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
This commit is contained in:
parent
b71f8cc7f8
commit
58d56220de
|
@ -4,6 +4,8 @@
|
|||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/web/modules/custom/custom/src" isTestSource="false" packagePrefix="Drupal\custom" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/web/modules/custom/custom/tests/src" isTestSource="true" packagePrefix="Drupal\Tests\custom" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/web/modules/custom/opd_talks/tests/src" isTestSource="true" packagePrefix="Drupal\Tests\opd_talks" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/web/modules/custom/opd_talks/src" isTestSource="false" packagePrefix="Drupal\opd_talks" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/asm89/stack-cors" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/behat/mink" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/behat/mink-browserkit-driver" />
|
||||
|
|
14
.idea/php-test-framework.xml
Normal file
14
.idea/php-test-framework.xml
Normal file
|
@ -0,0 +1,14 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="PhpTestFrameworkVersionCache">
|
||||
<tools_cache>
|
||||
<tool tool_name="PHPUnit">
|
||||
<cache>
|
||||
<versions>
|
||||
<info id="Local" version="7.5.20" />
|
||||
</versions>
|
||||
</cache>
|
||||
</tool>
|
||||
</tools_cache>
|
||||
</component>
|
||||
</project>
|
|
@ -142,4 +142,9 @@
|
|||
</include_path>
|
||||
</component>
|
||||
<component name="PhpProjectSharedConfiguration" php_language_level="7.4" />
|
||||
<component name="PhpUnit">
|
||||
<phpunit_settings>
|
||||
<PhpUnitSettings configuration_file_path="$PROJECT_DIR$/phpunit.xml.dist" custom_loader_path="$PROJECT_DIR$/vendor/autoload.php" phpunit_phar_path="" use_configuration_file="true" />
|
||||
</phpunit_settings>
|
||||
</component>
|
||||
</project>
|
|
@ -38,6 +38,7 @@ module:
|
|||
migrate_plus: 0
|
||||
migrate_tools: 0
|
||||
node: 0
|
||||
opd_talks: 0
|
||||
page_cache: 0
|
||||
path: 0
|
||||
path_alias: 0
|
||||
|
|
|
@ -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: { }
|
||||
|
|
|
@ -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: { }
|
|
@ -12,6 +12,8 @@ use Drupal\paragraphs\ParagraphInterface;
|
|||
|
||||
abstract class TalksTestBase extends EntityKernelTestBase {
|
||||
|
||||
protected $strictConfigSchema = FALSE;
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
|
|
5
web/modules/custom/opd_talks/opd_talks.info.yml
Normal file
5
web/modules/custom/opd_talks/opd_talks.info.yml
Normal file
|
@ -0,0 +1,5 @@
|
|||
name: Oliver Davies Talks
|
||||
description: Custom code for talks pages.
|
||||
type: module
|
||||
core_version_requirement: ^8 || ^9
|
||||
package: Custom
|
23
web/modules/custom/opd_talks/opd_talks.module
Normal file
23
web/modules/custom/opd_talks/opd_talks.module
Normal file
|
@ -0,0 +1,23 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Custom code for talks pages.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* Implements hook_views_data_alter().
|
||||
*/
|
||||
function opd_talks_views_data_alter(array &$data): void {
|
||||
$data['node_field_data']['event_sort'] = [
|
||||
'title' => t('Custom event sort'),
|
||||
'group' => t('Content'),
|
||||
'help' => t('Sort events by past/future, then distance from now.'),
|
||||
'sort' => [
|
||||
'field' => 'created',
|
||||
'id' => 'event_sort',
|
||||
]
|
||||
];
|
||||
}
|
40
web/modules/custom/opd_talks/src/Plugin/views/sort/Event.php
Normal file
40
web/modules/custom/opd_talks/src/Plugin/views/sort/Event.php
Normal file
|
@ -0,0 +1,40 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Drupal\opd_talks\Plugin\views\sort;
|
||||
|
||||
use Drupal\Core\Datetime\DrupalDateTime;
|
||||
use Drupal\datetime\DateTimeComputed;
|
||||
use Drupal\views\Plugin\views\sort\Date;
|
||||
use Drupal\views\Annotation\ViewsSort;
|
||||
|
||||
/**
|
||||
* @ViewsSort("event_sort")
|
||||
*/
|
||||
final class Event extends Date {
|
||||
|
||||
public function query() {
|
||||
$this->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"
|
||||
);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Drupal\Tests\opd_talks\Kernel;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Drupal\Tests\custom\Kernel\TalksTestBase;
|
||||
use Drupal\views\ResultRow;
|
||||
|
||||
final class TalksPageSortTest extends TalksTestBase {
|
||||
|
||||
public static $modules = [
|
||||
'views',
|
||||
'opd_talks',
|
||||
];
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function upcoming_talks_are_shown_first_followed_by_past_talks_and_ordered_by_distance() {
|
||||
$this->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);
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in a new issue