Add podcast listing page
This commit is contained in:
parent
203056d54a
commit
fc1beaf3fb
10 changed files with 414 additions and 2 deletions
|
@ -48,6 +48,7 @@ module:
|
|||
metatag_twitter_cards: 0
|
||||
node: 0
|
||||
opd_daily_emails: 0
|
||||
opd_podcast: 0
|
||||
options: 0
|
||||
page_cache: 0
|
||||
path: 0
|
||||
|
|
|
@ -14,4 +14,4 @@ description: null
|
|||
help: null
|
||||
new_revision: true
|
||||
preview_mode: 1
|
||||
display_submitted: false
|
||||
display_submitted: true
|
||||
|
|
204
config/sync/views.view.podcast_episodes.yml
Normal file
204
config/sync/views.view.podcast_episodes.yml
Normal file
|
@ -0,0 +1,204 @@
|
|||
uuid: 18036b67-1a46-4b88-a11c-64253e3e2ada
|
||||
langcode: en
|
||||
status: true
|
||||
dependencies:
|
||||
config:
|
||||
- core.entity_view_mode.node.teaser
|
||||
- node.type.podcast_episode
|
||||
module:
|
||||
- node
|
||||
- user
|
||||
id: podcast_episodes
|
||||
label: 'Podcast episodes'
|
||||
module: views
|
||||
description: ''
|
||||
tag: ''
|
||||
base_table: node_field_data
|
||||
base_field: nid
|
||||
display:
|
||||
default:
|
||||
id: default
|
||||
display_title: Default
|
||||
display_plugin: default
|
||||
position: 0
|
||||
display_options:
|
||||
title: 'The Beyond Blocks Podcast'
|
||||
fields:
|
||||
title:
|
||||
id: title
|
||||
table: node_field_data
|
||||
field: title
|
||||
relationship: none
|
||||
group_type: group
|
||||
admin_label: ''
|
||||
entity_type: node
|
||||
entity_field: title
|
||||
plugin_id: field
|
||||
label: ''
|
||||
exclude: false
|
||||
alter:
|
||||
alter_text: false
|
||||
make_link: false
|
||||
absolute: false
|
||||
word_boundary: false
|
||||
ellipsis: false
|
||||
strip_tags: false
|
||||
trim: false
|
||||
html: false
|
||||
element_type: ''
|
||||
element_class: ''
|
||||
element_label_type: ''
|
||||
element_label_class: ''
|
||||
element_label_colon: true
|
||||
element_wrapper_type: ''
|
||||
element_wrapper_class: ''
|
||||
element_default_classes: true
|
||||
empty: ''
|
||||
hide_empty: false
|
||||
empty_zero: false
|
||||
hide_alter_empty: true
|
||||
click_sort_column: value
|
||||
type: string
|
||||
settings:
|
||||
link_to_entity: true
|
||||
group_column: value
|
||||
group_columns: { }
|
||||
group_rows: true
|
||||
delta_limit: 0
|
||||
delta_offset: 0
|
||||
delta_reversed: false
|
||||
delta_first_last: false
|
||||
multi_type: separator
|
||||
separator: ', '
|
||||
field_api_classes: false
|
||||
pager:
|
||||
type: mini
|
||||
options:
|
||||
offset: 0
|
||||
pagination_heading_level: h4
|
||||
items_per_page: 10
|
||||
total_pages: null
|
||||
id: 0
|
||||
tags:
|
||||
next: ››
|
||||
previous: ‹‹
|
||||
expose:
|
||||
items_per_page: false
|
||||
items_per_page_label: 'Items per page'
|
||||
items_per_page_options: '5, 10, 25, 50'
|
||||
items_per_page_options_all: false
|
||||
items_per_page_options_all_label: '- All -'
|
||||
offset: false
|
||||
offset_label: Offset
|
||||
exposed_form:
|
||||
type: basic
|
||||
options:
|
||||
submit_button: Apply
|
||||
reset_button: false
|
||||
reset_button_label: Reset
|
||||
exposed_sorts_label: 'Sort by'
|
||||
expose_sort_order: true
|
||||
sort_asc_label: Asc
|
||||
sort_desc_label: Desc
|
||||
access:
|
||||
type: perm
|
||||
options:
|
||||
perm: 'access content'
|
||||
cache:
|
||||
type: tag
|
||||
options: { }
|
||||
empty: { }
|
||||
sorts:
|
||||
field_episode_number_value:
|
||||
id: field_episode_number_value
|
||||
table: node__field_episode_number
|
||||
field: field_episode_number_value
|
||||
relationship: none
|
||||
group_type: group
|
||||
admin_label: ''
|
||||
plugin_id: standard
|
||||
order: DESC
|
||||
expose:
|
||||
label: ''
|
||||
field_identifier: ''
|
||||
exposed: false
|
||||
arguments: { }
|
||||
filters:
|
||||
status:
|
||||
id: status
|
||||
table: node_field_data
|
||||
field: status
|
||||
entity_type: node
|
||||
entity_field: status
|
||||
plugin_id: boolean
|
||||
value: '1'
|
||||
group: 1
|
||||
expose:
|
||||
operator: ''
|
||||
type:
|
||||
id: type
|
||||
table: node_field_data
|
||||
field: type
|
||||
entity_type: node
|
||||
entity_field: type
|
||||
plugin_id: bundle
|
||||
value:
|
||||
podcast_episode: podcast_episode
|
||||
style:
|
||||
type: default
|
||||
row:
|
||||
type: 'entity:node'
|
||||
options:
|
||||
relationship: none
|
||||
view_mode: teaser
|
||||
query:
|
||||
type: views_query
|
||||
options:
|
||||
query_comment: ''
|
||||
disable_sql_rewrite: false
|
||||
distinct: false
|
||||
replica: false
|
||||
query_tags: { }
|
||||
relationships: { }
|
||||
header:
|
||||
area:
|
||||
id: area
|
||||
table: views
|
||||
field: area
|
||||
relationship: none
|
||||
group_type: group
|
||||
admin_label: ''
|
||||
plugin_id: text
|
||||
empty: false
|
||||
content:
|
||||
value: "<p>A podcast about Drupal, PHP, open-source, and related software development topics.\r\nGuests include people like <a href=\"/podcast/1-retrofit\">Matt Glaman</a>, <a href=\"/podcast/8-eirik-morland-violinist\">Eirik Morland</a>, <a href=\"/podcast/9-tim-lehnen\">Tim Lehnen</a>, <a href=\"/podcast/13-ryan-szrama-centarro\">Ryan Szrama</a>, <a href=\"/podcast/19-sam-mortenson\">Sam Mortenson</a> and <a href=\"/podcast/25-jess-archer-drush-laravel-prompts\">Jess Archer</a>.</p>"
|
||||
format: basic_html
|
||||
tokenize: false
|
||||
footer: { }
|
||||
display_extenders: { }
|
||||
cache_metadata:
|
||||
max-age: -1
|
||||
contexts:
|
||||
- 'languages:language_content'
|
||||
- 'languages:language_interface'
|
||||
- url.query_args
|
||||
- 'user.node_grants:view'
|
||||
- user.permissions
|
||||
tags: { }
|
||||
page_1:
|
||||
id: page_1
|
||||
display_title: Page
|
||||
display_plugin: page
|
||||
position: 1
|
||||
display_options:
|
||||
display_extenders: { }
|
||||
path: podcast
|
||||
cache_metadata:
|
||||
max-age: -1
|
||||
contexts:
|
||||
- 'languages:language_content'
|
||||
- 'languages:language_interface'
|
||||
- url.query_args
|
||||
- 'user.node_grants:view'
|
||||
- user.permissions
|
||||
tags: { }
|
5
modules/opd_podcast/opd_podcast.info.yml
Normal file
5
modules/opd_podcast/opd_podcast.info.yml
Normal file
|
@ -0,0 +1,5 @@
|
|||
name: Podcast
|
||||
description: Custom functionality for podcasts.
|
||||
core_version_requirement: ^11
|
||||
type: module
|
||||
package: Custom
|
21
modules/opd_podcast/opd_podcast.module
Normal file
21
modules/opd_podcast/opd_podcast.module
Normal file
|
@ -0,0 +1,21 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use Drupal\node\NodeInterface;
|
||||
|
||||
function opd_podcast_node_links_alter(array &$links, NodeInterface $entity, array &$context): void {
|
||||
if ($entity->bundle() !== 'podcast_episode') {
|
||||
return;
|
||||
}
|
||||
|
||||
$links['node']['#links']['node-readmore']['title'] = t('Listen now<span class="visually-hidden"> to @title</span> →');
|
||||
|
||||
$links['node']['#links']['node-readmore']['attributes']['class'] = [
|
||||
'p-0',
|
||||
];
|
||||
|
||||
$links['#attributes']['class'][] = 'list-none';
|
||||
$links['#attributes']['class'][] = 'm-0';
|
||||
$links['#attributes']['class'][] = 'p-0';
|
||||
}
|
|
@ -1620,6 +1620,11 @@ select {
|
|||
margin-bottom: 0px;
|
||||
}
|
||||
|
||||
.my-2 {
|
||||
margin-top: 0.5rem;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.my-4 {
|
||||
margin-top: 1rem;
|
||||
margin-bottom: 1rem;
|
||||
|
@ -1913,6 +1918,12 @@ select {
|
|||
margin-left: calc(1.5rem * calc(1 - var(--tw-space-x-reverse)));
|
||||
}
|
||||
|
||||
.space-y-6 > :not([hidden]) ~ :not([hidden]) {
|
||||
--tw-space-y-reverse: 0;
|
||||
margin-top: calc(1.5rem * calc(1 - var(--tw-space-y-reverse)));
|
||||
margin-bottom: calc(1.5rem * var(--tw-space-y-reverse));
|
||||
}
|
||||
|
||||
.space-y-10 > :not([hidden]) ~ :not([hidden]) {
|
||||
--tw-space-y-reverse: 0;
|
||||
margin-top: calc(2.5rem * calc(1 - var(--tw-space-y-reverse)));
|
||||
|
@ -2909,4 +2920,3 @@ select {
|
|||
border-color: rgb(168 162 158 / var(--tw-border-opacity));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
3
themes/opdavies/css/overrides.css
Normal file
3
themes/opdavies/css/overrides.css
Normal file
|
@ -0,0 +1,3 @@
|
|||
ul.links.inline > li {
|
||||
padding: 0;
|
||||
}
|
|
@ -2,3 +2,4 @@ global-styling:
|
|||
css:
|
||||
base:
|
||||
build/tailwind.css: {}
|
||||
css/overrides.css: {}
|
||||
|
|
|
@ -0,0 +1,89 @@
|
|||
{#
|
||||
/**
|
||||
* @file
|
||||
* Default theme implementation to display a node.
|
||||
*
|
||||
* Available variables:
|
||||
* - node: The node entity with limited access to object properties and methods.
|
||||
* Only method names starting with "get", "has", or "is" and a few common
|
||||
* methods such as "id", "label", and "bundle" are available. For example:
|
||||
* - node.getCreatedTime() will return the node creation timestamp.
|
||||
* - node.hasField('field_example') returns TRUE if the node bundle includes
|
||||
* field_example. (This does not indicate the presence of a value in this
|
||||
* field.)
|
||||
* - node.isPublished() will return whether the node is published or not.
|
||||
* Calling other methods, such as node.delete(), will result in an exception.
|
||||
* See \Drupal\node\Entity\Node for a full list of public properties and
|
||||
* methods for the node object.
|
||||
* - label: (optional) The title of the node.
|
||||
* - content: All node items. Use {{ content }} to print them all,
|
||||
* or print a subset such as {{ content.field_example }}. Use
|
||||
* {{ content|without('field_example') }} to temporarily suppress the printing
|
||||
* of a given child element.
|
||||
* - author_picture: The node author user entity, rendered using the "compact"
|
||||
* view mode.
|
||||
* - date: (optional) Themed creation date field.
|
||||
* - author_name: (optional) Themed author name field.
|
||||
* - url: Direct URL of the current node.
|
||||
* - display_submitted: Whether submission information should be displayed.
|
||||
* - attributes: HTML attributes for the containing element.
|
||||
* The attributes.class element may contain one or more of the following
|
||||
* classes:
|
||||
* - node: The current template type (also known as a "theming hook").
|
||||
* - node--type-[type]: The current node type. For example, if the node is an
|
||||
* "Article" it would result in "node--type-article". Note that the machine
|
||||
* name will often be in a short form of the human readable label.
|
||||
* - node--view-mode-[view_mode]: The View Mode of the node; for example, a
|
||||
* teaser would result in: "node--view-mode-teaser", and
|
||||
* full: "node--view-mode-full".
|
||||
* The following are controlled through the node publishing options.
|
||||
* - node--promoted: Appears on nodes promoted to the front page.
|
||||
* - node--sticky: Appears on nodes ordered above other non-sticky nodes in
|
||||
* teaser listings.
|
||||
* - node--unpublished: Appears on unpublished nodes visible only to site
|
||||
* admins.
|
||||
* - title_attributes: Same as attributes, except applied to the main title
|
||||
* tag that appears in the template.
|
||||
* - content_attributes: Same as attributes, except applied to the main
|
||||
* content tag that appears in the template.
|
||||
* - author_attributes: Same as attributes, except applied to the author of
|
||||
* the node tag that appears in the template.
|
||||
* - title_prefix: Additional output populated by modules, intended to be
|
||||
* displayed in front of the main title tag that appears in the template.
|
||||
* - title_suffix: Additional output populated by modules, intended to be
|
||||
* displayed after the main title tag that appears in the template.
|
||||
* - view_mode: View mode; for example, "teaser" or "full".
|
||||
* - page: Flag for the full page state. Will be true if view_mode is 'full'.
|
||||
*
|
||||
* @see template_preprocess_node()
|
||||
*
|
||||
* @ingroup themeable
|
||||
*/
|
||||
#}
|
||||
<article{{ attributes }}>
|
||||
{{ title_prefix }}
|
||||
{% if label and not page %}
|
||||
<h2{{ title_attributes.addClass('font-bold text-xl') }}>
|
||||
<a href="{{ url }}" rel="bookmark">{{ label }}</a>
|
||||
</h2>
|
||||
{% endif %}
|
||||
{{ title_suffix }}
|
||||
|
||||
<div class="prose prose-p:text-black prose-a:font-light prose-a:text-blue-primary prose-p:text-lg prose-blockquote:border-blue-primary dark:marker:text-white prose-li:my-1 prose-li:text-lg prose-figcaption:text-white prose-li:text-black marker:text-black dark:prose-p:text-white dark:prose-invert dark:prose-a:text-blue-400 dark:prose-blockquote:border-blue-400 dark:prose-li:text-white hover:prose-a:no-underline prose-h2:text-xl prose-code:font-normal prose-h2:mb-4 prose-ul:my-3 dark:prose-hr:border-grey-400 prose-code:before:content-[''] prose-code:after:content-['']">
|
||||
{% if display_submitted %}
|
||||
<div class="my-2 text-base">
|
||||
{% set created = node.getCreatedTime() %}
|
||||
|
||||
<time datetime="{{ created|format_date('html_date') }}">{{ created|format_date('short') }}</time>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div{{ content_attributes.addClass('mt-2') }}>
|
||||
{{ content|without('links') }}
|
||||
|
||||
<div class="mt-4">
|
||||
{{ content.links }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
|
@ -0,0 +1,78 @@
|
|||
{#
|
||||
/**
|
||||
* @file
|
||||
* Default theme implementation for main view template.
|
||||
*
|
||||
* Available variables:
|
||||
* - attributes: Remaining HTML attributes for the element.
|
||||
* - css_name: A CSS-safe version of the view name.
|
||||
* - css_class: The user-specified classes names, if any.
|
||||
* - header: The optional header.
|
||||
* - footer: The optional footer.
|
||||
* - rows: The results of the view query, if any.
|
||||
* - empty: The content to display if there are no rows.
|
||||
* - pager: The optional pager next/prev links to display.
|
||||
* - exposed: Exposed widget form/info to display.
|
||||
* - feed_icons: Optional feed icons to display.
|
||||
* - more: An optional link to the next page of results.
|
||||
* - title: Title of the view, only used when displaying in the admin preview.
|
||||
* - title_prefix: Additional output populated by modules, intended to be
|
||||
* displayed in front of the view title.
|
||||
* - title_suffix: Additional output populated by modules, intended to be
|
||||
* displayed after the view title.
|
||||
* - attachment_before: An optional attachment view to be displayed before the
|
||||
* view content.
|
||||
* - attachment_after: An optional attachment view to be displayed after the
|
||||
* view content.
|
||||
* - dom_id: Unique id for every view being printed to give unique class for
|
||||
* JavaScript.
|
||||
*
|
||||
* @see template_preprocess_views_view()
|
||||
*
|
||||
* @ingroup themeable
|
||||
*/
|
||||
#}
|
||||
{%
|
||||
set classes = [
|
||||
dom_id ? 'js-view-dom-id-' ~ dom_id,
|
||||
]
|
||||
%}
|
||||
<div{{ attributes.addClass(classes) }}>
|
||||
{{ title_prefix }}
|
||||
{{ title }}
|
||||
{{ title_suffix }}
|
||||
|
||||
<div>
|
||||
{% if header %}
|
||||
<header class="prose prose-p:text-black prose-a:font-light prose-a:text-blue-primary prose-p:text-lg prose-blockquote:border-blue-primary dark:marker:text-white prose-li:my-1 prose-li:text-lg prose-figcaption:text-white prose-li:text-black marker:text-black dark:prose-p:text-white dark:prose-invert dark:prose-a:text-blue-400 dark:prose-blockquote:border-blue-400 dark:prose-li:text-white hover:prose-a:no-underline prose-h2:text-xl prose-code:font-normal prose-h2:mb-4 prose-ul:my-3 dark:prose-hr:border-grey-400 prose-code:before:content-[''] prose-code:after:content-['']">
|
||||
{{ header }}
|
||||
</header>
|
||||
{% endif %}
|
||||
|
||||
{{ exposed }}
|
||||
{{ attachment_before }}
|
||||
|
||||
{% if rows -%}
|
||||
<div class="mt-10">
|
||||
<div class="space-y-8">
|
||||
{{ rows }}
|
||||
</div>
|
||||
</div>
|
||||
{% elseif empty -%}
|
||||
{{ empty }}
|
||||
{% endif %}
|
||||
|
||||
{{ pager }}
|
||||
</div>
|
||||
|
||||
{{ attachment_after }}
|
||||
{{ more }}
|
||||
|
||||
{% if footer %}
|
||||
<footer>
|
||||
{{ footer }}
|
||||
</footer>
|
||||
{% endif %}
|
||||
|
||||
{{ feed_icons }}
|
||||
</div>
|
Loading…
Add table
Add a link
Reference in a new issue