From c8a2b56710ae52d93812d44e49e65aec690695c3 Mon Sep 17 00:00:00 2001 From: Sergii Pavlenko Date: Tue, 11 Jan 2022 16:29:43 +0200 Subject: [PATCH 1/8] EWPP-1822: Add disclosing information mechanism regarding livestream information. --- .../js/event_livestream.js | 25 ++++++ .../oe_theme_content_event.libraries.yml | 6 ++ .../oe_theme_content_event.module | 2 + .../Display/LivestreamExtraField.php | 26 ++++-- .../Display/OnlineDescriptionExtraField.php | 90 ++++++++++++++++--- ...e-theme-content-event-livestream.html.twig | 13 ++- ...content-event-online-description.html.twig | 8 +- sass/components/_global.scss | 4 + 8 files changed, 150 insertions(+), 24 deletions(-) create mode 100644 modules/oe_theme_content_event/js/event_livestream.js create mode 100644 modules/oe_theme_content_event/oe_theme_content_event.libraries.yml diff --git a/modules/oe_theme_content_event/js/event_livestream.js b/modules/oe_theme_content_event/js/event_livestream.js new file mode 100644 index 000000000..957a03961 --- /dev/null +++ b/modules/oe_theme_content_event/js/event_livestream.js @@ -0,0 +1,25 @@ +/** + * @file + * Attaches behaviors for Event Livestreams. + */ +(function (Drupal, drupalSettings) { + /** + * Shows link when livestream is active. + * + * @type {Drupal~behavior} + * + * @prop {Drupal~behaviorAttach} attach + * Attaches the Livestream behaviors. + */ + Drupal.behaviors.liveStreamDiscloser = { + attach: function attach(context) { + setTimeout(function () { + Array.prototype.forEach.call(document.querySelectorAll('[data-livestream-element]'), function (element) { + element.classList.remove('hidden'); + element.classList.remove('ecl-link--hidden'); + }); + }, drupalSettings.livestream_starttime_timestamp-Date.now()) + + }, + }; +})(Drupal, drupalSettings); diff --git a/modules/oe_theme_content_event/oe_theme_content_event.libraries.yml b/modules/oe_theme_content_event/oe_theme_content_event.libraries.yml new file mode 100644 index 000000000..27096bb4b --- /dev/null +++ b/modules/oe_theme_content_event/oe_theme_content_event.libraries.yml @@ -0,0 +1,6 @@ +livestream_link_disclosure: + js: + js/event_livestream.js: {} + dependencies: + - core/drupal + - core/jquery diff --git a/modules/oe_theme_content_event/oe_theme_content_event.module b/modules/oe_theme_content_event/oe_theme_content_event.module index 848c622be..695a34627 100644 --- a/modules/oe_theme_content_event/oe_theme_content_event.module +++ b/modules/oe_theme_content_event/oe_theme_content_event.module @@ -48,6 +48,7 @@ function oe_theme_content_event_theme() { ], 'oe_theme_content_event_online_description' => [ 'variables' => [ + 'hidden' => FALSE, 'label' => '', 'url' => '', 'description' => '', @@ -58,6 +59,7 @@ function oe_theme_content_event_theme() { 'label' => '', 'url' => '', 'date' => '', + 'hide_link' => FALSE, ], ], 'oe_theme_content_event_status_message' => [ diff --git a/modules/oe_theme_content_event/src/Plugin/ExtraField/Display/LivestreamExtraField.php b/modules/oe_theme_content_event/src/Plugin/ExtraField/Display/LivestreamExtraField.php index 5a7f9eb93..9f2b9e296 100644 --- a/modules/oe_theme_content_event/src/Plugin/ExtraField/Display/LivestreamExtraField.php +++ b/modules/oe_theme_content_event/src/Plugin/ExtraField/Display/LivestreamExtraField.php @@ -98,7 +98,18 @@ public function viewElements(ContentEntityInterface $entity) { // If the livestream didn't start yet, we cache it by its start date and // render the date only. if ($event->isOnlinePeriodYetToCome($this->requestDateTime)) { - $this->applyHourTag($build, $event->getOnlineStartDate()); + $this->applyMidnightTag($build, $event->getOnlineStartDate()); + $current_date = $this->dateFormatter->format($this->requestDateTime->getTimestamp(), 'custom', 'Ymd'); + $start_day = $this->dateFormatter->format($event->getOnlineStartDate()->getTimestamp(), 'custom', 'Ymd'); + if ($current_date === $start_day) { + $build['#hide_link'] = TRUE; + $build['#attached'] = [ + 'library' => 'oe_theme_content_event/livestream_link_disclosure', + 'drupalSettings' => [ + 'livestream_starttime_timestamp' => $event->getOnlineStartDate()->getTimestamp() * 1000, + ], + ]; + } } $build['#date'] = $this->t('Starts on @date', [ '@date' => $this->dateFormatter->format($event->getOnlineStartDate()->getTimestamp(), 'oe_event_long_date_hour'), @@ -107,14 +118,15 @@ public function viewElements(ContentEntityInterface $entity) { if ($event->isOnlinePeriodActive($this->requestDateTime)) { // Cache it by its end date. $this->applyHourTag($build, $event->getOnlineEndDate()); - $link = $entity->get('oe_event_online_link')->first(); - $value = $link->getValue(); - $build += [ - '#url' => $link->getUrl(), - '#label' => $value['title'], - ]; } + $link = $entity->get('oe_event_online_link')->first(); + $value = $link->getValue(); + $build += [ + '#url' => $link->getUrl(), + '#label' => $value['title'], + ]; + return $build; } diff --git a/modules/oe_theme_content_event/src/Plugin/ExtraField/Display/OnlineDescriptionExtraField.php b/modules/oe_theme_content_event/src/Plugin/ExtraField/Display/OnlineDescriptionExtraField.php index 488d978e8..e32f2825b 100644 --- a/modules/oe_theme_content_event/src/Plugin/ExtraField/Display/OnlineDescriptionExtraField.php +++ b/modules/oe_theme_content_event/src/Plugin/ExtraField/Display/OnlineDescriptionExtraField.php @@ -4,8 +4,13 @@ namespace Drupal\oe_theme_content_event\Plugin\ExtraField\Display; +use Drupal\Component\Datetime\TimeInterface; +use Drupal\Core\Datetime\DateFormatterInterface; use Drupal\Core\Entity\ContentEntityInterface; +use Drupal\Core\Entity\EntityTypeManagerInterface; use Drupal\oe_content_event\EventNodeWrapper; +use Drupal\oe_time_caching\Cache\TimeBasedCacheTagGeneratorInterface; +use Symfony\Component\DependencyInjection\ContainerInterface; /** * Extra field displaying online description on events. @@ -21,6 +26,51 @@ */ class OnlineDescriptionExtraField extends DateAwareExtraFieldBase { + /** + * Date formatter service. + * + * @var \Drupal\Core\Datetime\DateFormatterInterface + */ + protected $dateFormatter; + + /** + * RegistrationButtonExtraField constructor. + * + * @param array $configuration + * A configuration array containing information about the plugin instance. + * @param string $plugin_id + * The plugin_id for the plugin instance. + * @param mixed $plugin_definition + * The plugin implementation definition. + * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager + * The entity type manager. + * @param \Drupal\Component\Datetime\TimeInterface $time + * The time service. + * @param \Drupal\oe_time_caching\Cache\TimeBasedCacheTagGeneratorInterface $cache_tag_generator + * Time based cache tag generator service. + * @param \Drupal\Core\Datetime\DateFormatterInterface $date_formatter + * The date formatter. + */ + public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityTypeManagerInterface $entity_type_manager, TimeInterface $time, TimeBasedCacheTagGeneratorInterface $cache_tag_generator, DateFormatterInterface $date_formatter) { + parent::__construct($configuration, $plugin_id, $plugin_definition, $entity_type_manager, $time, $cache_tag_generator); + $this->dateFormatter = $date_formatter; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { + return new static( + $configuration, + $plugin_id, + $plugin_definition, + $container->get('entity_type.manager'), + $container->get('datetime.time'), + $container->get('oe_time_caching.time_based_cache_tag_generator'), + $container->get('date.formatter') + ); + } + /** * {@inheritdoc} */ @@ -42,25 +92,39 @@ public function viewElements(ContentEntityInterface $entity) { // If the livestream didn't start yet, we cache it by its start date. if ($event->isOnlinePeriodYetToCome($this->requestDateTime)) { - $this->applyHourTag($build, $event->getOnlineStartDate()); - $this->isEmpty = TRUE; - return $build; + $this->applyMidnightTag($build, $event->getOnlineStartDate()); + $current_date = $this->dateFormatter->format($this->requestDateTime->getTimestamp(), 'custom', 'Ymd'); + $start_day = $this->dateFormatter->format($event->getOnlineStartDate()->getTimestamp(), 'custom', 'Ymd'); + // Do not send field value to browser if it is not yet day online + // livestreaming should be started. + if ($current_date !== $start_day) { + $this->isEmpty = TRUE; + return $build; + } + // But anyway keep information hidden from users till the time + // of online streaming has started. + $build['#hidden'] = TRUE; + $build['#attached'] = [ + 'library' => 'oe_theme_content_event/livestream_link_disclosure', + 'drupalSettings' => [ + 'livestream_starttime_timestamp' => $event->getOnlineStartDate()->getTimestamp() * 1000, + ], + ]; } if ($event->isOnlinePeriodActive($this->requestDateTime)) { // Cache it by the livestream end date. $this->applyHourTag($build, $event->getOnlineEndDate()); - $view_builder = $this->entityTypeManager->getViewBuilder('node'); - $build['#description'] = $view_builder->viewField($entity->get('oe_event_online_description'), [ - 'label' => 'hidden', - ]); - - /** @var \Drupal\link\Plugin\Field\FieldType\LinkItem $link */ - $link = $entity->get('oe_event_online_link')->first(); - $value = $link->getValue(); - $build['#url'] = $link->getUrl(); - $build['#label'] = $value['title']; } + $view_builder = $this->entityTypeManager->getViewBuilder('node'); + $build['#description'] = $view_builder->viewField($entity->get('oe_event_online_description'), [ + 'label' => 'hidden', + ]); + /** @var \Drupal\link\Plugin\Field\FieldType\LinkItem $link */ + $link = $entity->get('oe_event_online_link')->first(); + $value = $link->getValue(); + $build['#url'] = $link->getUrl(); + $build['#label'] = $value['title']; return $build; } diff --git a/modules/oe_theme_content_event/templates/oe-theme-content-event-livestream.html.twig b/modules/oe_theme_content_event/templates/oe-theme-content-event-livestream.html.twig index af16e46d4..270f15a81 100644 --- a/modules/oe_theme_content_event/templates/oe-theme-content-event-livestream.html.twig +++ b/modules/oe_theme_content_event/templates/oe-theme-content-event-livestream.html.twig @@ -8,6 +8,11 @@
{{ date }}
{% endif %} {% if label is not empty %} + {# + Use custom 'ecl-link--hidden' class in case we need to hide the link. + Usage of 'hidden' attribute is restricted by priorities of CSS rule. + Built-in classes of 'link' component have higher priority and override display rules. + #} {% include '@ecl-twig/link' with { link: { type: 'standalone', @@ -19,6 +24,12 @@ name: 'livestreaming', size: 's', path: ecl_icon_path - } + }, + extra_attributes: [ + { + name: 'data-livestream-element' + }, + ], + extra_classes: hide_link ? 'ecl-link--hidden', } %} {% endif %} diff --git a/modules/oe_theme_content_event/templates/oe-theme-content-event-online-description.html.twig b/modules/oe_theme_content_event/templates/oe-theme-content-event-online-description.html.twig index feccfbe4f..afcb5d982 100644 --- a/modules/oe_theme_content_event/templates/oe-theme-content-event-online-description.html.twig +++ b/modules/oe_theme_content_event/templates/oe-theme-content-event-online-description.html.twig @@ -5,7 +5,9 @@ */ #} {% if description is not empty %} -

{{ 'Livestream'|t }}

- {{ description }} - {{ label }} + {% endif %} diff --git a/sass/components/_global.scss b/sass/components/_global.scss index 0e12c1da3..e194bd1c7 100644 --- a/sass/components/_global.scss +++ b/sass/components/_global.scss @@ -29,3 +29,7 @@ a { .ecl-u-shadow-none { box-shadow: none!important; } + +.ecl-link--hidden { + display: none; +} From 8c12731fc416e9224979d071170e1fe1255a260a Mon Sep 17 00:00:00 2001 From: Sergii Pavlenko Date: Tue, 11 Jan 2022 16:31:52 +0200 Subject: [PATCH 2/8] EWPP-1822: Add FunctionalJavascript test. --- .../LivestreamDisplayDisclosingTest.php | 140 ++++++++++++++++++ 1 file changed, 140 insertions(+) create mode 100644 modules/oe_theme_content_event/tests/src/FunctionalJavascript/LivestreamDisplayDisclosingTest.php diff --git a/modules/oe_theme_content_event/tests/src/FunctionalJavascript/LivestreamDisplayDisclosingTest.php b/modules/oe_theme_content_event/tests/src/FunctionalJavascript/LivestreamDisplayDisclosingTest.php new file mode 100644 index 000000000..743a95af1 --- /dev/null +++ b/modules/oe_theme_content_event/tests/src/FunctionalJavascript/LivestreamDisplayDisclosingTest.php @@ -0,0 +1,140 @@ +container->get('theme_installer')->install(['oe_theme']); + $this->config('system.theme')->set('default', 'oe_theme')->save(); + $this->container->set('theme.registry', NULL); + + // Rebuild the ui_pattern definitions to collect the ones provided by + // oe_theme itself. + \Drupal::service('plugin.manager.ui_patterns')->clearCachedDefinitions(); + + FilterFormat::create([ + 'format' => 'full_html', + 'name' => 'Full HTML', + ])->save(); + } + + /** + * Tests that Event livestreaming link will be visible exactly on time. + */ + public function testContentWithoutInPageNav(): void { + $static_time = new DrupalDateTime('now', DateTimeItemInterface::STORAGE_TIMEZONE); + $start_date = (clone $static_time)->modify('+10 days'); + // Create an Event node with required fields only. + /** @var \Drupal\node\Entity\Node $node */ + $node = $this->container->get('entity_type.manager') + ->getStorage('node') + ->create([ + 'type' => 'oe_event', + 'title' => 'Test event node', + 'oe_event_type' => 'http://publications.europa.eu/resource/authority/public-event-type/COMPETITION_AWARD_CEREMONY', + 'oe_teaser' => 'Event teaser', + 'oe_subject' => 'http://data.europa.eu/uxp/1000', + 'oe_event_status' => 'as_planned', + 'oe_event_dates' => [ + 'value' => $start_date->format(DateTimeItemInterface::DATETIME_STORAGE_FORMAT), + 'end_value' => $start_date->format(DateTimeItemInterface::DATETIME_STORAGE_FORMAT), + ], + 'oe_event_online_dates' => [ + 'value' => $start_date->format(DateTimeItemInterface::DATETIME_STORAGE_FORMAT), + 'end_value' => $start_date->format(DateTimeItemInterface::DATETIME_STORAGE_FORMAT), + ], + 'oe_event_languages' => [ + ['target_id' => 'http://publications.europa.eu/resource/authority/language/EST'], + ['target_id' => 'http://publications.europa.eu/resource/authority/language/FRA'], + ], + 'oe_author' => 'http://publications.europa.eu/resource/authority/corporate-body/ACJHR', + 'oe_content_content_owner' => 'http://publications.europa.eu/resource/authority/corporate-body/COMMU', + 'uid' => 0, + 'status' => 1, + ]); + $node->save(); + $this->drupalGet($node->toUrl()); + $livetime_elements = $this->getSession()->getPage()->findAll('css', '[data-livestream-element]'); + $this->assertCount(0, $livetime_elements); + $livestream_js = $this->xpath("//script[contains(@src, 'js/event_livestream.js')]"); + $this->assertCount(0, $livestream_js); + + // Set livestream start date in 4 hours later. + $start_date = (clone $static_time)->modify('+4 hours'); + $node->set('oe_event_online_type', 'livestream'); + $node->set('oe_event_online_link', [ + 'uri' => 'http://www.example.com/online_link', + 'title' => 'Link to online event', + ]); + $node->set('oe_event_online_description', 'Online event description'); + $node->set('oe_event_online_dates', [ + 'value' => $start_date->format(DateTimeItemInterface::DATETIME_STORAGE_FORMAT), + 'end_value' => $start_date->format(DateTimeItemInterface::DATETIME_STORAGE_FORMAT), + ]); + $node->save(); + $this->drupalGet($node->toUrl()); + $livestream_js = $this->xpath("//script[contains(@src, 'js/event_livestream.js')]"); + $this->assertCount(1, $livestream_js); + $livetime_elements = $this->getSession()->getPage()->findAll('css', '[data-livestream-element]'); + $this->assertCount(2, $livetime_elements); + foreach ($livetime_elements as $livetime_element) { + $this->assertFalse($livetime_element->isVisible()); + } + + // Set livestream start date in 20 seconds later. + $start_date = (clone $static_time)->modify('+20 seconds'); + $node->set('oe_event_online_dates', [ + 'value' => $start_date->format(DateTimeItemInterface::DATETIME_STORAGE_FORMAT), + 'end_value' => $start_date->format(DateTimeItemInterface::DATETIME_STORAGE_FORMAT), + ]); + $node->save(); + $this->drupalGet($node->toUrl()); + $livestream_js = $this->xpath("//script[contains(@src, 'js/event_livestream.js')]"); + $this->assertCount(1, $livestream_js); + $livetime_elements = $this->getSession()->getPage()->findAll('css', '[data-livestream-element]'); + $this->assertCount(2, $livetime_elements); + $this->getSession()->wait(20000); + foreach ($livetime_elements as $livetime_element) { + $this->assertTrue($livetime_element->isVisible()); + } + } + +} From 67d44e46a33723e7d4b9d3f8f3ac06472ae232c9 Mon Sep 17 00:00:00 2001 From: Sergii Pavlenko Date: Tue, 11 Jan 2022 17:09:27 +0200 Subject: [PATCH 3/8] EWPP-1822: Update functional tests. --- tests/src/Functional/ContentEventRenderTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/src/Functional/ContentEventRenderTest.php b/tests/src/Functional/ContentEventRenderTest.php index 2cdae4b49..0a4272113 100644 --- a/tests/src/Functional/ContentEventRenderTest.php +++ b/tests/src/Functional/ContentEventRenderTest.php @@ -407,7 +407,7 @@ public function testEventRendering(): void { 'body' => "Friday 28 February 2020, 01:00\n - Monday 9 March 2020, 01:00", ], [ 'label' => 'Livestream', - 'body' => 'Starts on Wednesday 18 March 2020, 01:00', + 'body' => 'Starts on Wednesday 18 March 2020, 01:00Link to online event', ], [ 'label' => 'Who should attend', 'body' => 'Types of audiences that this event targets', From 68c7e47072d2d227fb927f2a9485a2d1b552136d Mon Sep 17 00:00:00 2001 From: Sergii Pavlenko Date: Tue, 11 Jan 2022 18:08:11 +0200 Subject: [PATCH 4/8] EWPP-1822: Adjust caching of extrafields. --- modules/oe_theme_content_event/js/event_livestream.js | 2 +- .../src/Plugin/ExtraField/Display/LivestreamExtraField.php | 2 +- .../Plugin/ExtraField/Display/OnlineDescriptionExtraField.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/oe_theme_content_event/js/event_livestream.js b/modules/oe_theme_content_event/js/event_livestream.js index 957a03961..a33842526 100644 --- a/modules/oe_theme_content_event/js/event_livestream.js +++ b/modules/oe_theme_content_event/js/event_livestream.js @@ -4,7 +4,7 @@ */ (function (Drupal, drupalSettings) { /** - * Shows link when livestream is active. + * Shows related description and link when livestream is active. * * @type {Drupal~behavior} * diff --git a/modules/oe_theme_content_event/src/Plugin/ExtraField/Display/LivestreamExtraField.php b/modules/oe_theme_content_event/src/Plugin/ExtraField/Display/LivestreamExtraField.php index 9f2b9e296..faa971d92 100644 --- a/modules/oe_theme_content_event/src/Plugin/ExtraField/Display/LivestreamExtraField.php +++ b/modules/oe_theme_content_event/src/Plugin/ExtraField/Display/LivestreamExtraField.php @@ -98,7 +98,7 @@ public function viewElements(ContentEntityInterface $entity) { // If the livestream didn't start yet, we cache it by its start date and // render the date only. if ($event->isOnlinePeriodYetToCome($this->requestDateTime)) { - $this->applyMidnightTag($build, $event->getOnlineStartDate()); + $this->applyHourTag($build, $event->getOnlineStartDate()); $current_date = $this->dateFormatter->format($this->requestDateTime->getTimestamp(), 'custom', 'Ymd'); $start_day = $this->dateFormatter->format($event->getOnlineStartDate()->getTimestamp(), 'custom', 'Ymd'); if ($current_date === $start_day) { diff --git a/modules/oe_theme_content_event/src/Plugin/ExtraField/Display/OnlineDescriptionExtraField.php b/modules/oe_theme_content_event/src/Plugin/ExtraField/Display/OnlineDescriptionExtraField.php index e32f2825b..49db4ad94 100644 --- a/modules/oe_theme_content_event/src/Plugin/ExtraField/Display/OnlineDescriptionExtraField.php +++ b/modules/oe_theme_content_event/src/Plugin/ExtraField/Display/OnlineDescriptionExtraField.php @@ -92,7 +92,7 @@ public function viewElements(ContentEntityInterface $entity) { // If the livestream didn't start yet, we cache it by its start date. if ($event->isOnlinePeriodYetToCome($this->requestDateTime)) { - $this->applyMidnightTag($build, $event->getOnlineStartDate()); + $this->applyHourTag($build, $event->getOnlineStartDate()); $current_date = $this->dateFormatter->format($this->requestDateTime->getTimestamp(), 'custom', 'Ymd'); $start_day = $this->dateFormatter->format($event->getOnlineStartDate()->getTimestamp(), 'custom', 'Ymd'); // Do not send field value to browser if it is not yet day online From 975d7e85439d372800a46183c0e5c41b40e57f2a Mon Sep 17 00:00:00 2001 From: Sergii Pavlenko Date: Thu, 13 Jan 2022 17:42:42 +0200 Subject: [PATCH 5/8] EWPP-1822: Improve test coverage and add minor fixes. --- .../Display/OnlineDescriptionExtraField.php | 2 +- ...content-event-online-description.html.twig | 2 +- .../LivestreamDisplayDisclosingTest.php | 46 ++++++++++++++++--- 3 files changed, 41 insertions(+), 9 deletions(-) diff --git a/modules/oe_theme_content_event/src/Plugin/ExtraField/Display/OnlineDescriptionExtraField.php b/modules/oe_theme_content_event/src/Plugin/ExtraField/Display/OnlineDescriptionExtraField.php index 49db4ad94..84d5a229f 100644 --- a/modules/oe_theme_content_event/src/Plugin/ExtraField/Display/OnlineDescriptionExtraField.php +++ b/modules/oe_theme_content_event/src/Plugin/ExtraField/Display/OnlineDescriptionExtraField.php @@ -34,7 +34,7 @@ class OnlineDescriptionExtraField extends DateAwareExtraFieldBase { protected $dateFormatter; /** - * RegistrationButtonExtraField constructor. + * OnlineDescriptionExtraField constructor. * * @param array $configuration * A configuration array containing information about the plugin instance. diff --git a/modules/oe_theme_content_event/templates/oe-theme-content-event-online-description.html.twig b/modules/oe_theme_content_event/templates/oe-theme-content-event-online-description.html.twig index afcb5d982..1d8c9fd08 100644 --- a/modules/oe_theme_content_event/templates/oe-theme-content-event-online-description.html.twig +++ b/modules/oe_theme_content_event/templates/oe-theme-content-event-online-description.html.twig @@ -5,7 +5,7 @@ */ #} {% if description is not empty %} -