From 58d56220de7b6e7f9c144bc35164f5bbb502c605 Mon Sep 17 00:00:00 2001 From: Oliver Davies Date: Fri, 26 Jun 2020 01:49:47 +0100 Subject: [PATCH] Show upcoming talks in chronological order Update the ordering of the future talks on the talks page so that upcoming talks are shown in chronological order (soonest first), followed by past talks in reverse chronological order (most recent first). This still uses the `created` date for ordering, which is updated automatically on saving the node to match the furthest future talk, but I may want to move that into a custom node property at some point. Fixes #140 --- .idea/oliverdavies-uk.iml | 2 + .idea/php-test-framework.xml | 14 ++ .idea/php.xml | 5 + config/default/core.extension.yml | 1 + config/default/views.view.talks.yml | 14 +- .../config/install/views.view.talks.yml | 197 ++++++++++++++++++ .../custom/tests/src/Kernel/TalksTestBase.php | 2 + .../custom/opd_talks/opd_talks.info.yml | 5 + web/modules/custom/opd_talks/opd_talks.module | 23 ++ .../opd_talks/src/Plugin/views/sort/Event.php | 40 ++++ .../tests/src/Kernel/TalksPageSortTest.php | 35 ++++ 11 files changed, 331 insertions(+), 7 deletions(-) create mode 100644 .idea/php-test-framework.xml create mode 100644 web/modules/custom/custom/tests/modules/custom_test/config/install/views.view.talks.yml create mode 100644 web/modules/custom/opd_talks/opd_talks.info.yml create mode 100644 web/modules/custom/opd_talks/opd_talks.module create mode 100644 web/modules/custom/opd_talks/src/Plugin/views/sort/Event.php create mode 100644 web/modules/custom/opd_talks/tests/src/Kernel/TalksPageSortTest.php diff --git a/.idea/oliverdavies-uk.iml b/.idea/oliverdavies-uk.iml index 488833a45..1664e077d 100644 --- a/.idea/oliverdavies-uk.iml +++ b/.idea/oliverdavies-uk.iml @@ -4,6 +4,8 @@ + + diff --git a/.idea/php-test-framework.xml b/.idea/php-test-framework.xml new file mode 100644 index 000000000..ac3134f0f --- /dev/null +++ b/.idea/php-test-framework.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/php.xml b/.idea/php.xml index b31288151..6d17c0687 100644 --- a/.idea/php.xml +++ b/.idea/php.xml @@ -142,4 +142,9 @@ + + + + + \ No newline at end of file diff --git a/config/default/core.extension.yml b/config/default/core.extension.yml index c295b2733..152347a29 100644 --- a/config/default/core.extension.yml +++ b/config/default/core.extension.yml @@ -38,6 +38,7 @@ module: migrate_plus: 0 migrate_tools: 0 node: 0 + opd_talks: 0 page_cache: 0 path: 0 path_alias: 0 diff --git a/config/default/views.view.talks.yml b/config/default/views.view.talks.yml index 7714f2224..44397ff7e 100644 --- a/config/default/views.view.talks.yml +++ b/config/default/views.view.talks.yml @@ -8,6 +8,7 @@ dependencies: - system.menu.main module: - node + - opd_talks - user id: talks label: Talks @@ -141,21 +142,20 @@ display: operator_limit_selection: false operator_list: { } sorts: - created: - id: created + event_sort: + id: event_sort table: node_field_data - field: created - order: DESC - entity_type: node - entity_field: created - plugin_id: date + field: event_sort relationship: none group_type: group admin_label: '' + order: ASC exposed: false expose: label: '' granularity: second + entity_type: node + plugin_id: event_sort title: Talks header: { } footer: { } diff --git a/web/modules/custom/custom/tests/modules/custom_test/config/install/views.view.talks.yml b/web/modules/custom/custom/tests/modules/custom_test/config/install/views.view.talks.yml new file mode 100644 index 000000000..e05fb2b63 --- /dev/null +++ b/web/modules/custom/custom/tests/modules/custom_test/config/install/views.view.talks.yml @@ -0,0 +1,197 @@ +langcode: en +status: true +dependencies: + config: + - core.entity_view_mode.node.teaser + - node.type.talk + - system.menu.main + module: + - node + - opd_talks + - user +id: talks +label: Talks +module: views +description: '' +tag: '' +base_table: node_field_data +base_field: nid +display: + default: + display_plugin: default + id: default + display_title: Master + position: 0 + display_options: + access: + type: perm + options: + perm: 'access content' + cache: + type: tag + options: { } + query: + type: views_query + options: + disable_sql_rewrite: false + distinct: false + replica: false + query_comment: '' + query_tags: { } + 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 + pager: + type: none + options: + items_per_page: 0 + offset: 0 + style: + type: html_list + options: + row_class: '' + default_row_class: true + uses_fields: false + type: ul + wrapper_class: '' + class: space-y-8 + row: + type: 'entity:node' + options: + view_mode: teaser + fields: + title: + id: title + table: node_field_data + field: title + entity_type: node + entity_field: title + label: '' + alter: + alter_text: false + make_link: false + absolute: false + trim: false + word_boundary: false + ellipsis: false + strip_tags: false + html: false + hide_empty: false + empty_zero: false + settings: + link_to_entity: true + plugin_id: field + relationship: none + group_type: group + admin_label: '' + exclude: 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_alter_empty: true + click_sort_column: value + type: string + 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 + filters: + status: + value: '1' + table: node_field_data + field: status + plugin_id: boolean + entity_type: node + entity_field: status + id: status + expose: + operator: '' + operator_limit_selection: false + operator_list: { } + group: 1 + type: + id: type + table: node_field_data + field: type + value: + talk: talk + entity_type: node + entity_field: type + plugin_id: bundle + expose: + operator_limit_selection: false + operator_list: { } + sorts: + event_sort: + id: event_sort + table: node_field_data + field: event_sort + relationship: none + group_type: group + admin_label: '' + order: ASC + exposed: false + expose: + label: '' + granularity: second + entity_type: node + plugin_id: event_sort + title: Talks + header: { } + footer: { } + empty: { } + relationships: { } + arguments: { } + display_extenders: { } + cache_metadata: + max-age: -1 + contexts: + - 'languages:language_content' + - 'languages:language_interface' + - 'user.node_grants:view' + - user.permissions + tags: { } + page_1: + display_plugin: page + id: page_1 + display_title: Page + position: 1 + display_options: + display_extenders: { } + path: talks + menu: + type: normal + title: Talks + description: '' + expanded: false + parent: '' + weight: -48 + context: '0' + menu_name: main + cache_metadata: + max-age: -1 + contexts: + - 'languages:language_content' + - 'languages:language_interface' + - 'user.node_grants:view' + - user.permissions + tags: { } diff --git a/web/modules/custom/custom/tests/src/Kernel/TalksTestBase.php b/web/modules/custom/custom/tests/src/Kernel/TalksTestBase.php index 90b0d941c..b272b292f 100644 --- a/web/modules/custom/custom/tests/src/Kernel/TalksTestBase.php +++ b/web/modules/custom/custom/tests/src/Kernel/TalksTestBase.php @@ -12,6 +12,8 @@ use Drupal\paragraphs\ParagraphInterface; abstract class TalksTestBase extends EntityKernelTestBase { + protected $strictConfigSchema = FALSE; + /** * {@inheritDoc} */ diff --git a/web/modules/custom/opd_talks/opd_talks.info.yml b/web/modules/custom/opd_talks/opd_talks.info.yml new file mode 100644 index 000000000..a1b07e3c9 --- /dev/null +++ b/web/modules/custom/opd_talks/opd_talks.info.yml @@ -0,0 +1,5 @@ +name: Oliver Davies Talks +description: Custom code for talks pages. +type: module +core_version_requirement: ^8 || ^9 +package: Custom diff --git a/web/modules/custom/opd_talks/opd_talks.module b/web/modules/custom/opd_talks/opd_talks.module new file mode 100644 index 000000000..9b237e7e1 --- /dev/null +++ b/web/modules/custom/opd_talks/opd_talks.module @@ -0,0 +1,23 @@ + t('Custom event sort'), + 'group' => t('Content'), + 'help' => t('Sort events by past/future, then distance from now.'), + 'sort' => [ + 'field' => 'created', + 'id' => 'event_sort', + ] + ]; +} diff --git a/web/modules/custom/opd_talks/src/Plugin/views/sort/Event.php b/web/modules/custom/opd_talks/src/Plugin/views/sort/Event.php new file mode 100644 index 000000000..e65dc51ff --- /dev/null +++ b/web/modules/custom/opd_talks/src/Plugin/views/sort/Event.php @@ -0,0 +1,40 @@ +ensureMyTable(); + + $currentTime = time(); + $dateAlias = "$this->tableAlias.$this->realField"; + + // Is this event in the past? + $this->query->addOrderBy( + NULL, + sprintf("%d > %s", $currentTime, $dateAlias), + $this->options['order'], + "in_past" + ); + + // How far in the past/future is this event? + $this->query->addOrderBy( + NULL, + sprintf('ABS(%s - %d)', $dateAlias, $currentTime), + $this->options['order'], + "distance_from_now" + ); + } + +} diff --git a/web/modules/custom/opd_talks/tests/src/Kernel/TalksPageSortTest.php b/web/modules/custom/opd_talks/tests/src/Kernel/TalksPageSortTest.php new file mode 100644 index 000000000..169b5123b --- /dev/null +++ b/web/modules/custom/opd_talks/tests/src/Kernel/TalksPageSortTest.php @@ -0,0 +1,35 @@ +createTalk(['created' => Carbon::parse('+4 days')->getTimestamp()]); + $this->createTalk(['created' => Carbon::parse('-2 days')->getTimestamp()]); + $this->createTalk(['created' => Carbon::parse('+1 days')->getTimestamp()]); + $this->createTalk(['created' => Carbon::parse('-10 days')->getTimestamp()]); + + $talkIds = array_map( + fn(ResultRow $row) => (int) $row->_entity->id(), + views_get_view_result('talks') + ); + + $this->assertSame([3, 1, 2, 4], $talkIds); + } + +}