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 488833a..1664e07 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 0000000..ac3134f --- /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 b312881..6d17c06 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 c295b27..152347a 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 7714f22..44397ff 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 0000000..e05fb2b --- /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 90b0d94..b272b29 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 0000000..a1b07e3 --- /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 0000000..9b237e7 --- /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 0000000..e65dc51 --- /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 0000000..169b512 --- /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); + } + +}