Code development platform for open source projects from the European Union institutions

Skip to content
Snippets Groups Projects
Unverified Commit d5ba67a6 authored by Gilmar Lima's avatar Gilmar Lima Committed by GitHub
Browse files

Merge pull request #76 from openeuropa/OEL-1026

OEL-1026:  [oe_whitelabel] Style the event content type
parents c6124426 e088891b
No related branches found
No related tags found
No related merge requests found
Showing
with 629 additions and 2 deletions
......@@ -9,6 +9,7 @@
"php": ">=7.4",
"cweagans/composer-patches": "^1.7",
"drupal/core": "^8.9 || ^9.2",
"drupal/twig_field_value": "^2.0",
"openeuropa/oe_bootstrap_theme": "0.1.202202072010"
},
"require-dev": {
......@@ -31,10 +32,10 @@
"openeuropa/oe_authentication": "^1.4",
"openeuropa/oe_corporate_blocks": "^4.4",
"openeuropa/oe_multilingual": "^1.9",
"openeuropa/oe_starter_content": "1.x-dev",
"openeuropa/task-runner-drupal-project-symlink": "^1.0",
"phpspec/prophecy-phpunit": "^1 || ^2",
"openeuropa/oe_contact_forms": "~1.1"
"openeuropa/oe_contact_forms": "~1.1",
"openeuropa/oe_starter_content": "1.x-dev"
},
"scripts": {
"post-install-cmd": "./vendor/bin/run drupal:site-setup",
......
# OpenEuropa Whitelabel Event
\ No newline at end of file
langcode: en
status: true
dependencies: { }
id: oe_whitelabel_event_date
label: 'OE Whitelabel Event date'
locked: false
pattern: 'd F Y'
langcode: en
status: true
dependencies:
config:
- core.entity_view_mode.node.full
- field.field.node.oe_event.body
- field.field.node.oe_event.oe_documents
- field.field.node.oe_event.oe_event_dates
- field.field.node.oe_event.oe_featured_media
- field.field.node.oe_event.oe_location
- field.field.node.oe_event.oe_summary
- node.type.oe_event
module:
- address
- datetime_range
- text
- user
id: node.oe_event.full
targetEntityType: node
bundle: oe_event
mode: full
content:
body:
type: text_default
weight: 1
region: content
label: above
settings: { }
third_party_settings: { }
links:
weight: 7
region: content
settings: { }
third_party_settings: { }
oe_documents:
type: entity_reference_entity_view
weight: 6
region: content
label: above
settings:
link: true
view_mode: default
third_party_settings: { }
oe_event_dates:
type: daterange_default
label: inline
settings:
timezone_override: ''
format_type: oe_whitelabel_event_date
separator: to
third_party_settings: { }
weight: 4
region: content
oe_featured_media:
type: entity_reference_entity_view
weight: 3
region: content
label: hidden
settings:
link: true
view_mode: default
third_party_settings: { }
oe_location:
type: address_default
label: inline
settings: { }
third_party_settings: { }
weight: 5
region: content
oe_summary:
type: text_default
label: hidden
settings: { }
third_party_settings: { }
weight: 2
region: content
hidden: { }
langcode: en
status: true
dependencies:
config:
- core.entity_view_mode.node.teaser
- field.field.node.oe_event.body
- field.field.node.oe_event.oe_documents
- field.field.node.oe_event.oe_event_dates
- field.field.node.oe_event.oe_featured_media
- field.field.node.oe_event.oe_location
- field.field.node.oe_event.oe_summary
- node.type.oe_event
module:
- address
- datetime_range
- text
- user
id: node.oe_event.teaser
targetEntityType: node
bundle: oe_event
mode: teaser
content:
oe_event_dates:
type: daterange_default
label: hidden
settings:
timezone_override: ''
format_type: oe_whitelabel_event_date
separator: to
third_party_settings: { }
weight: 4
region: content
oe_location:
type: address_default
label: hidden
settings: { }
third_party_settings: { }
weight: 5
region: content
oe_summary:
type: text_default
label: hidden
settings: { }
third_party_settings: { }
weight: 2
region: content
hidden:
body: true
links: true
oe_documents: true
oe_featured_media: true
name: OpenEuropa Whitelabel Event
type: module
description: Adds additional functionality to the Event module
package: OpenEuropa Whitelabel Theme
core_version_requirement: ^8.9 || ^9.2
dependencies:
- drupal:twig_field_value
- oe_whitelabel:oe_whitelabel_helper
- oe_starter_content:oe_starter_content_event
config_devel:
install:
- core.entity_view_display.node.oe_event.full
- core.entity_view_display.node.oe_event.teaser
- core.date_format.oe_whitelabel_event_date
<?php
/**
* @file
* OE Whitelabel theme Event.
*/
declare(strict_types = 1);
use Drupal\Core\Cache\CacheableMetadata;
use Drupal\media\MediaInterface;
use Drupal\media\Plugin\media\Source\Image;
use Drupal\media_avportal\Plugin\media\Source\MediaAvPortalPhotoSource;
use Drupal\oe_bootstrap_theme\ValueObject\ImageValueObject;
use Drupal\Component\Utility\Html;
/**
* Implements template_preprocess_node() for the Event node type.
*/
function oe_whitelabel_event_preprocess_node__oe_event(&$variables) {
if ($variables['view_mode'] !== 'full' && $variables['view_mode'] !== 'teaser') {
return;
}
_oe_whitelabel_event_preprocess_featured_media($variables);
_oe_whitelabel_event_preprocess_inpage_nav($variables);
}
/**
* Helper function to preprocess the Featured media field.
*
* @param array $variables
* Render array variables.
*/
function _oe_whitelabel_event_preprocess_featured_media(array &$variables): void {
/** @var \Drupal\node\NodeInterface $node */
$node = $variables['node'];
// Bail out if there is no media present.
if ($node->get('oe_featured_media')->isEmpty()) {
return;
}
/** @var \Drupal\media\Entity\Media $media */
$media = $node->get('oe_featured_media')->entity;
if (!$media instanceof MediaInterface) {
// The media entity is not available anymore, bail out.
return;
}
// Retrieve the correct media translation.
/** @var \Drupal\media\Entity\Media $media */
$media = \Drupal::service('entity.repository')->getTranslationFromContext($media, $node->language()->getId());
// Caches are handled by the formatter usually. Since we are not rendering
// the original render arrays, we need to propagate our caches to the
// template.
$cacheability = CacheableMetadata::createFromRenderArray($variables);
$cacheability->addCacheableDependency($media);
// Run access checks on the media entity.
$access = $media->access('view', $variables['user'], TRUE);
$cacheability->addCacheableDependency($access);
if (!$access->isAllowed()) {
$cacheability->applyTo($variables);
return;
}
// Get the media source.
$source = $media->getSource();
$is_image = $source instanceof MediaAvPortalPhotoSource || $source instanceof Image;
// If it's not an image bail out.
if (!$is_image) {
$cacheability->applyTo($variables);
return;
}
$thumbnail = $media->get('thumbnail')->first();
$variables['image'] = ImageValueObject::fromImageItem($thumbnail);
if ($variables['view_mode'] == 'teaser') {
$variables['image'] = ['#markup' => $variables['image']->getSource()];
}
$cacheability->applyTo($variables);
}
/**
* Helper function to preprocess the inpage navigation pattern fields.
*
* @param array $variables
* Render array variables.
*/
function _oe_whitelabel_event_preprocess_inpage_nav(array &$variables): void {
/** @var \Drupal\node\NodeInterface $node */
$node = $variables['node'];
if ($node->get('body')->isEmpty() && $node->get('oe_documents')->isEmpty()) {
return;
}
$variables['inpage_navigation_links'] = [];
$fields = ['oe_documents', 'body'];
foreach ($variables['content'] as &$item) {
if (!array_key_exists('#field_name', $item)) {
continue;
}
if (!in_array($item['#field_name'], $fields)) {
continue;
}
$unique_id = Html::getUniqueId('oe-content--' . $item['#field_name']);
$item['#attributes'] = ['id' => $unique_id];
$variables['inpage_navigation_links'][] = [
'path' => '#' . $unique_id,
'label' => $node->{$item['#field_name']}->getFieldDefinition()->getLabel(),
];
}
}
{#
/**
* @file
* Default template for a field.
*/
#}
{%
set classes = [
bundle|clean_class ~ '__' ~ field_name_clean|clean_class,
label_display == 'inline' ? 'd-flex',
]
%}
{%
set title_classes = [
'field__label',
'fw-bold',
label_display == 'visually_hidden' ? 'visually-hidden',
]
%}
{% if label_hidden %}
{% if multiple %}
<div{{ attributes.addClass(classes) }}>
{% for item in items %}
<div{{ item.attributes.addClass('field__item') }}>{{ item.content }}</div>
{% endfor %}
</div>
{% else %}
{% for item in items %}
<div{{ attributes.addClass(classes) }}>{{ item.content }}</div>
{% endfor %}
{% endif %}
{% else %}
<div{{ attributes.addClass(classes) }}>
<h3{{ title_attributes.addClass(title_classes) }}>
{{ label }}{% if label_display == 'inline' %}<span class="me-1">:</span>{% endif %}
</h3>
{% if multiple %}
<div class="field__items">
{% endif %}
{% for item in items %}
<div{{ item.attributes.addClass('field__item') }}>{{ item.content }}</div>
{% endfor %}
{% if multiple %}
</div>
{% endif %}
</div>
{% endif %}
{#
/**
* @file
* Default template for a field.
*/
#}
{%
set classes = [
bundle|clean_class ~ '__' ~ field_name_clean|clean_class,
label_display == 'inline' ? 'd-flex',
]
%}
{%
set title_classes = [
'field__label',
'fw-bold',
label_display == 'visually_hidden' ? 'visually-hidden',
]
%}
{% if label_hidden %}
{% if multiple %}
<div{{ attributes.addClass(classes) }}>
{% for item in items %}
<div{{ item.attributes.addClass('field__item') }}>{{ item.content }}</div>
{% endfor %}
</div>
{% else %}
{% for item in items %}
<div{{ attributes.addClass(classes) }}>{{ item.content }}</div>
{% endfor %}
{% endif %}
{% else %}
<div{{ attributes.addClass(classes) }}>
<h3{{ title_attributes.addClass(title_classes) }}>
{{ label }}{% if label_display == 'inline' %}<span class="me-1">:</span>{% endif %}
</h3>
{% if multiple %}
<div class="field__items">
{% endif %}
{% for item in items %}
<div{{ item.attributes.addClass('field__item') }}>{{ item.content }}</div>
{% endfor %}
{% if multiple %}
</div>
{% endif %}
</div>
{% endif %}
{#
/**
* @file
* Event full display.
*/
#}
{% set description_items = [] %}
{% if content.oe_event_dates|field_value is not empty %}
{% set _event_dates %}
{{ content.oe_event_dates|field_value|safe_join(', ') }}
{% endset %}
{% set description_items = description_items|merge([
{
term:[{
'label': content.oe_event_dates|field_label,
'icon': 'calendar-event',
}],
definition: _event_dates,
}
]) %}
{% endif %}
{% if content.oe_location|field_value is not empty %}
{% set _event_location %}
{{ content.oe_location|field_value|safe_join(', ') }}
{% endset %}
{% set description_items = description_items|merge([
{
term:[{
'label': content.oe_location|field_label,
'icon': 'geo-alt-fill',
}],
definition: _event_location,
}
]) %}
{% endif %}
{# Set inpage navigation links and content #}
{% set inpage_navigation_fields %}
{{ pattern('description_list', {
items: description_items,
orientation: 'horizontal',
attributes: create_attribute().addClass(['mt-3', 'mb-4']),
}) }}
{{ content.body }}
{{ content.oe_documents }}
{% endset %}
<article{{attributes}}>
{{ pattern('content_banner', {
background: 'gray',
title: label,
content: content.oe_summary,
image: image,
attributes: create_attribute().addClass(['ps-0']),
}) }}
<div class="mt-md-4-75 mt-4">
{{ pattern('inpage_navigation', {
title: 'Page content',
links: inpage_navigation_links,
content: inpage_navigation_fields,
full_layout: true,
}) }}
</div>
</article>
{#
/**
* @file
* Search result template.
*/
#}
{% set _title %}
<a class="text-underline-hover" href="{{ url }}">{{ label }}</a>
{% endset %}
{% set _content %}
<span class="text-muted text-nowrap me-4-5">{{ content.oe_event_dates }}</span>
{% endset %}
<article{{attributes}}>
{{ pattern('card', {
variant: 'search',
title: _title,
text: content.oe_summary,
image: image,
content: _content
}) }}
......@@ -23,6 +23,8 @@ drupal:
- "./vendor/bin/drush en oe_whitelabel_contact_forms -y"
- "./vendor/bin/drush en oe_whitelabel_helper -y"
- "./vendor/bin/drush en oe_whitelabel_search -y"
- "./vendor/bin/drush en oe_whitelabel_news -y"
- "./vendor/bin/drush en oe_whitelabel_event -y"
- "./vendor/bin/drush en toolbar -y"
- "./vendor/bin/drush theme:enable oe_whitelabel -y"
- "./vendor/bin/drush theme:enable seven -y"
......
<?php
declare(strict_types = 1);
namespace Drupal\Tests\oe_whitelabel\Functional;
use Symfony\Component\DomCrawler\Crawler;
use Drupal\Tests\media\Traits\MediaTypeCreationTrait;
use Drupal\media\Entity\Media;
use Drupal\file\Entity\File;
use Drupal\Tests\TestFileCreationTrait;
/**
* Tests that the Event content type renders correctly.
*/
class ContentEventRenderTest extends WhitelabelBrowserTestBase {
use MediaTypeCreationTrait;
use TestFileCreationTrait;
/**
* {@inheritdoc}
*/
public static $modules = [
'oe_whitelabel_event',
];
/**
* A node to be rendered in diferent display views.
*
* @var \Drupal\node\NodeInterface
*/
protected $node;
/**
* {@inheritdoc}
*/
protected function setUp(): void {
parent::setUp();
// Create a sample media entity to be embedded.
File::create([
'uri' => $this->getTestFiles('image')[0]->uri,
])->save();
$media_image = Media::create([
'bundle' => 'image',
'name' => 'Starter Image test',
'oe_media_image' => [
[
'target_id' => 1,
'alt' => 'Starter Image test alt',
'title' => 'Starter Image test title',
],
],
]);
$media_image->save();
// Create a sample document media entity to be embedded.
File::create([
'uri' => $this->getTestFiles('text')[0]->uri,
])->save();
$media_document = Media::create([
'bundle' => 'document',
'name' => 'Event document test',
'oe_media_file_type' => 'local',
'oe_media_file' => [
[
'target_id' => 2,
'alt' => 'Event document alt',
'title' => 'Event document title',
],
],
]);
$media_document->save();
/** @var \Drupal\node\Entity\Node $node */
$node = \Drupal::entityTypeManager()
->getStorage('node')
->create([
'type' => 'oe_event',
'title' => 'Test event node',
'oe_summary' => 'http://www.example.org is a web page',
'body' => 'Event body',
'oe_event_dates' => [
'value' => '2022-02-09T20:00:00',
'end_value' => '2022-02-09T22:00:00',
],
'uid' => 1,
'status' => 1,
]);
$node->set('oe_documents', [$media_document]);
$node->set('oe_featured_media', [$media_image]);
$node->save();
$this->node = $node;
}
/**
* Tests that the Event page renders correctly in full display.
*/
public function testEventRenderingFull(): void {
// Build node full view.
$builder = \Drupal::entityTypeManager()->getViewBuilder('node');
$build = $builder->view($this->node, 'full');
$render = $this->container->get('renderer')->renderRoot($build);
$crawler = new Crawler((string) $render);
// Assert content banner title.
$content_banner = $crawler->filter('.bcl-content-banner');
$this->assertEquals(
'Test event node',
trim($content_banner->filter('.card-title')->text())
);
// Assert content banner image.
$image = $content_banner->filter('img');
$this->assertCount(1, $image);
$this->assertCount(1, $image->filter('.card-img-top'));
$this->assertStringContainsString(
'image-test.png',
trim($image->attr('src'))
);
$this->assertEquals('Starter Image test alt',
$image->attr('alt')
);
// Assert content banner summary.
$this->assertEquals(
'http://www.example.org is a web page',
trim($content_banner->filter('.oe-event__oe-summary')->text())
);
// Assert inpage-navigation.
$this->assertEquals(
'Page content',
trim($crawler->filter('nav.bcl-inpage-navigation > h5')->text())
);
// Assert inpage-navigation.
$inpage_links = $crawler->filter('nav.bcl-inpage-navigation > ul');
$this->assertCount(2, $inpage_links->filter('li'));
$this->assertEquals(
'Content',
trim($inpage_links->filter('li:nth-of-type(1)')->text())
);
$this->assertEquals(
'Documents',
trim($inpage_links->filter('li:nth-of-type(2)')->text())
);
}
/**
* Tests that the Event page renders correctly in teaser display.
*/
public function testEventRenderingTeaser(): void {
// Build node teaser view.
$builder = \Drupal::entityTypeManager()->getViewBuilder('node');
$build = $builder->view($this->node, 'teaser');
$render = $this->container->get('renderer')->renderRoot($build);
$crawler = new Crawler((string) $render);
// Assert content banner title.
$this->assertEquals(
'Test event node',
trim($crawler->filter('h5.card-title')->text())
);
// Assert content banner image.
$image = $crawler->filter('img');
$this->assertCount(1, $image);
$this->assertCount(1, $image->filter('.card-img-top'));
$this->assertStringContainsString(
'image-test.png',
trim($image->attr('src'))
);
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment