Skip to content

Commit

Permalink
Add translation menu button to default navigation bar
Browse files Browse the repository at this point in the history
REDMINE-20592
  • Loading branch information
tf committed Feb 13, 2024
1 parent 1f8391c commit 1034877
Show file tree
Hide file tree
Showing 16 changed files with 223 additions and 28 deletions.
6 changes: 0 additions & 6 deletions entry_types/scrolled/config/locales/de.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1060,9 +1060,3 @@ de:
type_text: Text eingeben
type_title: Titel
url_placeholder: URL eingeben oder einfügen
public:
third_party_consent:
opt_in_prompt:
twitter: Ich bin damit einverstanden, dass Inhalte von Twitter angezeigt werden.
twitter:
default_title: Tweet
6 changes: 0 additions & 6 deletions entry_types/scrolled/config/locales/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -898,9 +898,3 @@ en:
type_text: Type some text
type_title: Title
url_placeholder: Type or paste URL
public:
third_party_consent:
opt_in_prompt:
twitter: I agree with being shown content from Twitter.
twitter:
default_title: Tweet
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import '@testing-library/jest-dom/extend-expect';

describe('MediaPlayerControls', () => {
useFakeTranslations({
'pageflow_scrolled.public.languages.en': 'English',
'pageflow_scrolled.public.languages.fr': 'French',
'pageflow_scrolled.public.text_track_modes.none': 'Off',
'pageflow_scrolled.public.text_track_modes.auto_off': 'Auto'
});
Expand All @@ -26,8 +26,8 @@ describe('MediaPlayerControls', () => {
parentFileModelType: 'Pageflow::AudioFile',
configuration: {
kind: 'subtitles',
srclang: 'en',
label: 'English'
srclang: 'fr',
label: 'French'
}
}]
};
Expand All @@ -51,9 +51,9 @@ describe('MediaPlayerControls', () => {
{seed}
);

fireEvent.click(getByRole('menuitemradio', {name: 'English'}));
fireEvent.click(getByRole('menuitemradio', {name: 'French'}));

expect(getByRole('menuitemradio', {name: 'English'})).toHaveAttribute('aria-checked', 'true');
expect(getByRole('menuitemradio', {name: 'French'})).toHaveAttribute('aria-checked', 'true');
});

it('supports turning text tracks off', () => {
Expand Down
17 changes: 11 additions & 6 deletions entry_types/scrolled/package/spec/frontend/useTextTracks-spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ describe('useTextTracks', () => {
const videoFile2CaptionsDePermaId = 4100;

const seed = {
entry: {locale: 'en'},
videoFiles: [
{id: videoFile1Id, permaId: videoFile1PermaId},
{id: videoFile2Id, permaId: videoFile2PermaId}
Expand Down Expand Up @@ -108,7 +109,7 @@ describe('useTextTracks', () => {
expect(result.current).toMatchObject({
activeFileId: videoFile1CaptionsDeId,
mode: 'user',
autoDisplayLabel: 'Auto (Off)'
autoDisplayLabel: 'Auto (English)'
});
});

Expand All @@ -122,7 +123,7 @@ describe('useTextTracks', () => {
expect(result.current).toMatchObject({
activeFileId: null,
mode: 'off',
autoDisplayLabel: 'Auto (Off)'
autoDisplayLabel: 'Auto (English)'
});
});

Expand Down Expand Up @@ -155,12 +156,16 @@ describe('useTextTracks', () => {
const {result} = renderHookInEntry(() => useTextTracks({
file: useFile({collectionName: 'videoFiles', permaId: videoFile1PermaId}),
captionsByDefault: true
}), {seed});
}), {
seed: {
...seed,
entry: {locale: 'fr'}
}
});

expect(result.current).toMatchObject({
activeFileId: videoFile1CaptionsDeId,
mode: 'auto',
autoDisplayLabel: 'Auto (Unknown)'
mode: 'auto'
});
});

Expand All @@ -170,8 +175,8 @@ describe('useTextTracks', () => {
captionsByDefault: true
}), {
seed: {
...seed,
entry: {locale: 'en'},
...seed
}
});

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import React from 'react';
import {TranslationsMenu} from 'widgets/defaultNavigation/TranslationsMenu';

import '@testing-library/jest-dom/extend-expect';
import {renderInEntry} from 'support';

describe('TranslationsMenu', () => {
it('marks current page in rendered list of translations', async () => {
const {getByRole} = renderInEntry(<TranslationsMenu />, {
seed: {
entry: {
id: 5,
},
entryTranslations: [
{
id: 5,
displayLocale: 'Deutsch',
url: '/entry-de'
},
{
id: 6,
displayLocale: 'English',
url: '/entry-en'
}
]
}
});

expect(getByRole('link', {name: 'English'})).toHaveAttribute('href', '/entry-en');
expect(getByRole('listitem', {current: 'page'})).toHaveTextContent('Deutsch');
});

it('includes shortend uppercased locale in button', async () => {
const {getByRole} = renderInEntry(<TranslationsMenu />, {
seed: {
entry: {
id: 5,
locale: 'de-ch'
},
entryTranslations: [
{
id: 5,
displayLocale: 'Deutsch',
url: '/entry-de'
},
{
id: 6,
displayLocale: 'English',
url: '/entry-en'
}
]
}
});

expect(getByRole('button')).toHaveTextContent(/^DE$/);
});

it('renders nothing if no translations are present', async () => {
const {container} = renderInEntry(<TranslationsMenu />, {
seed: {
entry: {
id: 5,
locale: 'de-ch'
},
entryTranslations: []
}
});

expect(container).toBeEmptyDOMElement();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import {useEntryStateConfig} from "./EntryStateProvider";

export function useEntryTranslations() {
const config = useEntryStateConfig();
return config.entryTranslations;
}
1 change: 1 addition & 0 deletions entry_types/scrolled/package/src/entryState/index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
export {useAdditionalSeedData} from './additionalSeedData';
export {useContentElementConsentVendor} from './consentVendors';
export {useShareProviders, useShareUrl} from './sharing';
export {useEntryTranslations} from './entryTranslations';
export {useEntryMetadata} from './metadata';
export {
useEntryStructure,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export function watchCollections(entry, {dispatch}) {
name: 'entries',
attributes: [
'locale',
{id: () => entry.id},
{permaId: () => entry.id}, // Make sure key attribute is present
{shareProviders: 'share_providers'},
{shareUrl: 'share_url'},
Expand Down
4 changes: 3 additions & 1 deletion entry_types/scrolled/package/src/frontend/ThemeIcon.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import share from './icons/share.svg';
import unmuted from './icons/unmuted.svg';
import gear from './icons/gear.svg';
import copyright from './icons/copyright.svg';
import world from './icons/world.svg';

import email from './icons/social/email.svg';
import facebook from './icons/social/facebook.svg';
Expand All @@ -27,6 +28,7 @@ const icons = {
unmuted,
gear,
copyright,
world,

email,
facebook,
Expand All @@ -46,7 +48,7 @@ const icons = {
* @param {string} props.name -
* Either: copyright, expand, gear, information, muted, share, unmuted,
* email, facebook, linkedIn, telegram, twitter, whatsApp,
* arrowLeft, arrowRight,
* arrowLeft, arrowRight, world
* @params {number} [props.width] - Image width.
* @params {number} [props.height] - Image height.
*/
Expand Down
3 changes: 3 additions & 0 deletions entry_types/scrolled/package/src/frontend/icons/world.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions entry_types/scrolled/package/src/frontend/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,9 @@ export {
useAdditionalSeedData,
useChapters,
useCredits,
useEntryMetadata,
useEntryStateDispatch,
useEntryTranslations,
useFile,
useFileRights,
useFileWithInlineRights,
Expand Down
10 changes: 7 additions & 3 deletions entry_types/scrolled/package/src/testHelpers/normalizeSeed.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,13 @@ export function normalizeSeed({
additionalSeedData,
consentVendors,
contentElementConsentVendors,
fileLicenses
fileLicenses,
entryTranslations
} = {}) {
const entries = entry ? [entry] : [{}];
const normalizedEntries = normalizeCollection(entries);
const normalizedEntries = normalizeCollection(entries, {
locale: 'en'
});

const normalizedContentElements = normalizeCollection(contentElements, {
typeName: 'textBlock',
Expand Down Expand Up @@ -87,7 +90,8 @@ export function normalizeSeed({
},
consentVendors: consentVendors || [],
contentElementConsentVendors: contentElementConsentVendors || {},
fileLicenses: fileLicenses || {}
fileLicenses: fileLicenses || {},
entryTranslations: entryTranslations || []
},
collections: {
entries: normalizedEntries,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {
import {HamburgerIcon} from './HamburgerIcon'
import {ChapterLink} from "./ChapterLink";
import {LegalInfoMenu} from "./LegalInfoMenu";
import {TranslationsMenu} from "./TranslationsMenu";
import {SharingMenu} from "./SharingMenu";
import {ToggleMuteButton} from './ToggleMuteButton';
import {Logo} from './Logo';
Expand Down Expand Up @@ -136,6 +137,7 @@ export function DefaultNavigation({configuration}) {

<div className={classNames(styles.contextIcons)}>
{!configuration.hideToggleMuteButton && <ToggleMuteButton />}
<TranslationsMenu />
{!theme.options.hideLegalInfoButton &&<LegalInfoMenu tooltipOffset={hideSharingButton ? -40 : 0} />}
{!hideSharingButton && <SharingMenu shareProviders={shareProviders} />}
</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import React from 'react';
import classNames from 'classnames';
import headerStyles from "./DefaultNavigation.module.css";
import styles from "./TranslationsMenu.module.css";

import {
ThemeIcon,
Tooltip,
useI18n,
useEntryMetadata,
useEntryTranslations
} from 'pageflow-scrolled/frontend';

export function TranslationsMenu({tooltipOffset = 0}) {
const {t} = useI18n();
const entry = useEntryMetadata();
const translations = useEntryTranslations();

if (translations.length < 2) {
return null;
}

const content = (
<div className={styles.tooltip}>
<ul className={styles.list}>
{translations.map(({id, url, displayLocale}) => {
if (entry.id === id) {
return (
<li key={id} aria-current="page">
<strong>{displayLocale}</strong>
</li>
);
}
else {
return (
<li key={id}>
<a target="_top" href={url}>{displayLocale}</a>
</li>
);
}
})}
</ul>
</div>
);

return (
<Tooltip horizontalOffset={tooltipOffset - 30}
arrowPos={120 - tooltipOffset}
content={content}>
<button className={classNames(headerStyles.contextIcon)}
aria-haspopup="true"
title={t('pageflow_scrolled.public.navigation.language')}>
<ThemeIcon name="world" />
<div className={styles.tag}>
<span>{entry.locale.substring(0, 2).toUpperCase()}</span>
</div>
</button>
</Tooltip>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
.tooltip {
margin: -5px 0;
}

.list {
list-style: none;
padding: 0;
margin: 0;
}

.list > li {
margin: 0;
border-top: solid 1px var(--default-navigation-separator-color);
}

.list > li:first-child {
border-top: none;
}

.list a,
.list strong {
display: block;
font-size: 16px;
font-weight: bold;
text-decoration: none;
line-height: 42px;
}

.list a {
color: var(--theme-widget-primary-color);
}

.list strong {
color: var(--theme-accent-color);
}

.tag {
position: absolute;
bottom: 10px;
right: 5px;
background: currentColor;
border-radius: 3px;
font-size: 11px;
padding: 2px;
font-weight: bold;
}

.tag > span {
color: #fff;
}
Loading

0 comments on commit 1034877

Please sign in to comment.