Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

UHF-11329 Visual regression and chart refactor #1175

Merged
merged 25 commits into from
Feb 6, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
c70bfaf
UHF-11329: Added the embedded content cookie compliance functionality…
khalima Feb 5, 2025
b7c62e3
UHF-11329: Skip the HDBT cookie banner element when testing scenarios.
khalima Feb 5, 2025
2f6a522
UHF-11329: Use allow attribute if available.
khalima Feb 5, 2025
8b81fbd
UHF-11329: Removed customised styles for the helfi_chart specific coo…
khalima Feb 5, 2025
2ba5924
UHF-11329: Removed obsolete templates.
khalima Feb 5, 2025
a611b86
UHF-11329: Added wrapper for the chart component.
khalima Feb 5, 2025
93a2330
UHF-11329: Added a template for the helfi chart media type.
khalima Feb 5, 2025
fae450f
UHF-11329: Added dist.
khalima Feb 5, 2025
8baaae5
UHF-11329: Merge branch 'main' of https://github.com/City-of-Helsinki…
khalima Feb 5, 2025
e953f04
UHF-11329: Reverted the label hack.
khalima Feb 5, 2025
f5b4c49
UHF-11329: Added possibility to change the cookie consent groups base…
khalima Feb 5, 2025
59d383e
UHF-11329: Added dist.
khalima Feb 5, 2025
8ba7686
UHF-11329: Styled the cookie compliance block background to be dark g…
teroelonen Feb 5, 2025
55972cd
UHF-11329: Add space to selector for journey planner
teroelonen Feb 5, 2025
d994d57
UHF-11329: Fix unique map skip link functionality on the embedded-con…
teroelonen Feb 5, 2025
bfa8b2d
UHF-11329: Merge branch 'UHF-11329' of https://github.com/City-of-Hel…
teroelonen Feb 5, 2025
4299c56
UHF-11329: Added translations for skip links; see embedded-content-co…
khalima Feb 6, 2025
1f7e4b1
UHF-11329: Defined skip links for chart and remote video. Unified the…
khalima Feb 6, 2025
0abb5be
UHF-11329: Fixed skip link text color.
khalima Feb 6, 2025
b138c39
UHF-11329: Refactored the skip links.
khalima Feb 6, 2025
b200a90
UHF-11329: Added dist.
khalima Feb 6, 2025
43d9a52
UHF-11329: Bump up the version.
khalima Feb 6, 2025
0e0686b
UHF-11329: Removed package.json and replaced it with version file.
khalima Feb 6, 2025
fb597cd
UHF-11329: Removed obsolete translations.
khalima Feb 6, 2025
1b691d4
UHF-11329: Fix chart title skip-links when the paragraph has title set
teroelonen Feb 6, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 2 additions & 6 deletions .github/workflows/visual.yml
Original file line number Diff line number Diff line change
Expand Up @@ -90,9 +90,7 @@ jobs:
# Install the site from existing dump if the cache restoration was successful.
- name: Install Drupal from existing dump
working-directory: ${{ env.DRUPAL_ROOT }}
if: |
!contains(github.event.pull_request.labels.*.name, 'install-drupal-from-scratch') &&
steps.drupal-cache.outputs.cache-hit == 'true'
if: steps.drupal-cache.outputs.cache-hit == 'true'
run: |
docker compose exec app bash -c "mysql --user=drupal --password=drupal --database=drupal --host=db --port=3306 -A < /app/public/sites/default/files/latest.sql"
docker compose exec app bash -c "drush updb -y && drush cr"
Expand All @@ -102,9 +100,7 @@ jobs:
# installation process and install Drupal using that dump from now on.
- name: Install Drupal from scratch
working-directory: ${{ env.DRUPAL_ROOT }}
if: |
contains(github.event.pull_request.labels.*.name, 'install-drupal-from-scratch') ||
steps.drupal-cache.outputs.cache-hit != 'true'
if: steps.drupal-cache.outputs.cache-hit != 'true'
run: |
docker compose exec app bash -c "drush si minimal -y"
docker compose exec app bash -c "drush en redis -y"
Expand Down
2 changes: 1 addition & 1 deletion backstop/backstop_dynamic_config.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ function getConfig(hostname, protocol, type) {
'.breadcrumb__container',
'.block--react-and-share',
'.footer',
'.sliding-popup-bottom',
'.hds-cc--banner',
'iframe',
];

Expand Down
34 changes: 4 additions & 30 deletions backstop/onBefore.js
Original file line number Diff line number Diff line change
@@ -1,32 +1,6 @@
module.exports = async (page, scenario, vp, isReference, browserContext, config) => {
module.exports = async (page) => {
// Simulate the "prefers-reduced-motion: reduce" media query,
// which is a user setting that reduces animations and transitions.
// It will provide less distorted test images.
await page.emulateMedia({ reducedMotion: 'reduce' });

const { hostname } = config;

browserContext.addCookies([
{
'name': 'cookie-agreed-version',
'value': '1.1.0',
'domain': hostname,
'path': '/',
'httpOnly': false,
'secure': false
},
{
'name': 'cookie-agreed',
'value': '2',
'domain': hostname,
'path': '/',
'httpOnly': false,
'secure': false
},
{
'name': 'cookie-agreed-categories',
'value': '%5B%22essential%22%2C%22preference%22%2C%22statistics%22%2C%22marketing%22%2C%22chat%22%5D',
'domain': hostname,
'path': '/',
'httpOnly': false,
'secure': false
}
]);
};
2 changes: 1 addition & 1 deletion dist/css/styles.min.css

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/js/embedded-content-cookie-compliance.min.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion hdbt.libraries.yml
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ hdbt-icons:
dist/css/hdbt-icons.css: {}

embedded-content-cookie-compliance:
version: 1.0
version: 1.1
js:
dist/js/embedded-content-cookie-compliance.min.js: {
minified: true
Expand Down
190 changes: 125 additions & 65 deletions src/js/embedded-content-cookie-compliance.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,75 +4,135 @@
*/
// eslint-disable-next-line func-names
(function ($, Drupal, drupalSettings) {

// Check whether the given cookie categories have been accepted.
const categoriesAgreed = (categories) => {
// Set default categories if none exists.
if (!categories) {
categories = ['preferences', 'statistics'];
}
return Drupal.cookieConsent.getConsentStatus(categories);
};

const loadEmbeddedContent = () => {
if (
Drupal.cookieConsent.getConsentStatus(['preferences', 'statistics']) &&
drupalSettings.embedded_media_attributes
) {
// eslint-disable-next-line no-restricted-syntax
for (const [id, attributes] of Object.entries(drupalSettings.embedded_media_attributes)) {
const iframeElement = document.createElement('iframe');
iframeElement.classList.add('media-oembed-content');
iframeElement.src = attributes.src;
iframeElement.title = attributes.title;
if (attributes.height) {
iframeElement.height = attributes.height;
}
if (attributes.width) {
iframeElement.width = attributes.width;
Object.entries(drupalSettings?.embedded_media_attributes || {})
.forEach(([id, attributes]) => {
if (!categoriesAgreed(attributes?.cookieConsentGroups)) {
return;
}

const skipLinkBefore = document.createElement('a');
skipLinkBefore.classList.add('focusable', 'skip-link');
skipLinkBefore.href = `#${attributes.skipLinkAfterId}`;
skipLinkBefore.id = attributes.skipLinkBeforeId;

const skipLinkAfter = document.createElement('a');
skipLinkAfter.classList.add('focusable', 'skip-link');
skipLinkAfter.href = `#${attributes.skipLinkBeforeId}`;
skipLinkAfter.id = attributes.skipLinkAfterId;

const containerElement = document.createElement('div');
containerElement.appendChild(iframeElement);

if (attributes.type === 'video') {
containerElement.classList.add('responsive-video-container');
$(`.embedded-content-cookie-compliance.media-${id}`)
.empty()
.append(containerElement)
.removeClass(`media-${id}`);
} else if (attributes.type === 'map') {
const $mapContainer = $(`.embedded-content-cookie-compliance.media-${id}`);

// Extract the map name from the wrapping component element.
const mediaContainers = $(`.embedded-content-cookie-compliance.media-${id}`);

// Each of the media type is grouped to their own
// mediaContainers so we need to iterate through them.
mediaContainers.each(function processMediaContainer(index) {
const mediaContainer = $(this);

const iframeElement = document.createElement('iframe');
iframeElement.classList.add('media-oembed-content');
iframeElement.src = attributes.src;
iframeElement.title = attributes.title;

if (attributes.allow) {
iframeElement.allow = attributes.allow;
}

if (attributes.height) {
iframeElement.height = attributes.height;
}
if (attributes.width) {
iframeElement.width = attributes.width;
}

const containerElement = document.createElement('div');
containerElement.appendChild(iframeElement);

// Extract the media name from the wrapping component title or in
// case of video, from the remote video - video title.
// Fallback to empty if no title is set.
const mapName = $mapContainer.parent().prevAll('h2').first().text().trim() || '';

containerElement.classList.add('responsive-map-container');
skipLinkAfter.classList.add('skip-link--map--after');
skipLinkBefore.classList.add('skip-link--map--before');

// Adjust the skip link text based on whether mapName is found.
skipLinkAfter.text = mapName
? Drupal.t('Continue above the @map map', { '@map': mapName }, { context: 'Skip link after the map for the map paragraph' })
: Drupal.t('Continue above the map', {}, { context: 'Skip link after the map for the map paragraph' });

skipLinkBefore.text = mapName
? Drupal.t('Continue below the @map map', { '@map': mapName }, { context: 'Skip link before the map for the map paragraph' })
: Drupal.t('Continue below the map', {}, { context: 'Skip link before the map for the map paragraph' });

$mapContainer.replaceWith(skipLinkBefore, containerElement, skipLinkAfter);
} else if (attributes.type === 'journey_planner') {
containerElement.classList.add('journey-planner-container');
skipLinkAfter.classList.add('skip-link--planner--after');
skipLinkBefore.classList.add('skip-link--planner--before');
skipLinkAfter.text = Drupal.t('Continue above the journey planner', {}, { context: 'Skip link after the journey planner for the journey planner paragraph' });
skipLinkBefore.text = Drupal.t('Continue below the journey planner', {}, { context: 'Skip link before the journey planner for the journey planner paragraph' });
$(`.embedded-content-cookie-compliance.media-${id}`)
.replaceWith(skipLinkBefore, containerElement, skipLinkAfter);
}
}
}
let mediaName = '';
switch (attributes.type) {
case 'video':
mediaName = mediaContainer.parent().siblings('.remote-video__video-title').text().trim() || '';
break;
default:
mediaName = mediaContainer.closest(`.component__content.${attributes.type}`).siblings('.component__title').text().trim() || '';
break;
}

// Initialize skip links elements.
const skipLinkBefore = document.createElement('a');
const skipLinkAfter = document.createElement('a');

// Construct skip links if their IDs are set.
if (attributes.skipLinkBeforeId && attributes.skipLinkAfterId) {
skipLinkBefore.classList.add('focusable', 'skip-link');
skipLinkBefore.href = `#${attributes.skipLinkAfterId}-${index}`;
skipLinkBefore.id = `${attributes.skipLinkBeforeId}-${index}`;

skipLinkAfter.classList.add('focusable', 'skip-link');
skipLinkAfter.href = `#${attributes.skipLinkBeforeId}-${index}`;
skipLinkAfter.id = `${attributes.skipLinkAfterId}-${index}`;
}

switch (attributes.type) {
case 'video':
containerElement.classList.add(`responsive-${attributes.type}-container`);
skipLinkAfter.classList.add('skip-link--video--after');
skipLinkBefore.classList.add('skip-link--video--before');

// Adjust the skip link text based on whether the mediaName is found.
skipLinkAfter.text = Drupal.t('Continue above the @video video', { '@video': mediaName }, { context: 'Skip links' });
skipLinkBefore.text = Drupal.t('Continue below the @video video', { '@video': mediaName }, { context: 'Skip links' });
mediaContainer.replaceWith(skipLinkBefore, containerElement, skipLinkAfter);
break;

case 'chart':
containerElement.classList.add(`responsive-${attributes.type}-container`);
skipLinkAfter.classList.add('skip-link--chart--after');
skipLinkBefore.classList.add('skip-link--chart--before');

// Adjust the skip link text based on whether the mediaName is found.
skipLinkAfter.text = mediaName
? Drupal.t('Continue above the @chart chart', { '@chart': mediaName }, { context: 'Skip links' })
: Drupal.t('Continue above the chart', {}, { context: 'Skip links' });
skipLinkBefore.text = mediaName
? Drupal.t('Continue below the @chart chart', { '@chart': mediaName }, { context: 'Skip links' })
: Drupal.t('Continue below the chart', {}, { context: 'Skip links' });

mediaContainer.replaceWith(skipLinkBefore, containerElement, skipLinkAfter);
break;

case 'journey_planner':
containerElement.classList.add('journey-planner-container');
skipLinkAfter.classList.add('skip-link--planner--after');
skipLinkBefore.classList.add('skip-link--planner--before');
skipLinkAfter.text = Drupal.t('Continue above the journey planner', {}, { context: 'Skip links' });
skipLinkBefore.text = Drupal.t('Continue below the journey planner', {}, { context: 'Skip links' });
mediaContainer.replaceWith(skipLinkBefore, containerElement, skipLinkAfter);
break;

case 'map':
containerElement.classList.add('responsive-map-container');
skipLinkAfter.classList.add('skip-link--map--after');
skipLinkBefore.classList.add('skip-link--map--before');

// Adjust the skip link text based on whether the mediaName is found.
skipLinkAfter.text = mediaName
? Drupal.t('Continue above the @map map', { '@map': mediaName }, { context: 'Skip links' })
: Drupal.t('Continue above the map', {}, { context: 'Skip links' });
skipLinkBefore.text = mediaName
? Drupal.t('Continue below the @map map', { '@map': mediaName }, { context: 'Skip links' })
: Drupal.t('Continue below the map', {}, { context: 'Skip links' });

mediaContainer.replaceWith(skipLinkBefore, containerElement, skipLinkAfter);
break;

default:
break;
}
});
});
};

// Remove noscript element.
Expand Down
9 changes: 6 additions & 3 deletions src/scss/06_components/pages/_cookie-compliance.scss
Original file line number Diff line number Diff line change
Expand Up @@ -78,14 +78,14 @@
}

.embedded-content-cookie-compliance,
.react-and-share-cookie-compliance,
.helfi-charts-cookie-compliance {
.react-and-share-cookie-compliance {
align-content: center;
align-items: center;
display: flex;
justify-content: center;

.map &,
.chart &,
.remote-video & {
aspect-ratio: 16 / 9; // Best guess for content size
}
Expand Down Expand Up @@ -147,8 +147,11 @@
background-color: $color-black-10;
}

// Elements that are not presented on gray background should have the default
// light shade of gray.
.react-and-share-cookie-compliance,
.helfi-charts-cookie-compliance {
.component--chart .embedded-content-cookie-compliance,
.component--journey-planner .embedded-content-cookie-compliance {
background-color: $color-black-5;
}

Expand Down
25 changes: 14 additions & 11 deletions src/scss/06_components/paragraphs/_chart.scss
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
.helfi-charts-content iframe {
aspect-ratio: 16 / 9;
border: 0;
height: auto;
width: 100%;
}
.chart__container {
position: relative;

.helfi-charts-noscript {
background: $color-silver;
padding: $spacing;
.responsive-chart-container {
aspect-ratio: 16 / 9;
background-color: $color-black-5; // Add color to show a "placeholder" while the video is loading.
overflow: hidden;

p:first-child {
margin-top: 0;
iframe {
border: 0;
height: 100%;
left: 0;
position: absolute;
top: 0;
width: 100%;
}
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/scss/06_components/paragraphs/_remote-video.scss
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
}

.component--remote-video,
.component--remote-video a:not(.hds-button, [data-hds-component='button']:not([class*='hds-button'])) {
.component--remote-video a:not(.hds-button, [data-hds-component='button']:not([class*='hds-button']), .skip-link) {
color: $color-black;
}

Expand Down
1 change: 1 addition & 0 deletions src/scss/xx_external/hds-core/VERSION.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
hds-core - version: 4.1.0
Loading
Loading