@eeacms/volto-eea-website-theme 2.0.2 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -4,6 +4,11 @@ All notable changes to this project will be documented in this file. Dates are d
4
4
 
5
5
  Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
6
6
 
7
+ ### [2.1.0](https://github.com/eea/volto-eea-website-theme/compare/2.0.2...2.1.0) - 23 May 2024
8
+
9
+ #### :hammer_and_wrench: Others
10
+
11
+ - bump package version [David Ichim - [`3c0c2eb`](https://github.com/eea/volto-eea-website-theme/commit/3c0c2eb3a863e85451c68f6d56b3e704de260618)]
7
12
  ### [2.0.2](https://github.com/eea/volto-eea-website-theme/compare/2.0.1...2.0.2) - 20 May 2024
8
13
 
9
14
  ### [2.0.1](https://github.com/eea/volto-eea-website-theme/compare/2.0.0...2.0.1) - 15 May 2024
@@ -62,7 +67,6 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
62
67
 
63
68
  #### :hammer_and_wrench: Others
64
69
 
65
- - Add Sonarqube tag using insitu-frontend addons list [EEA Jenkins - [`adc6730`](https://github.com/eea/volto-eea-website-theme/commit/adc6730e21a37afb865b842182624401de6a29f5)]
66
70
  ### [1.33.1](https://github.com/eea/volto-eea-website-theme/compare/1.33.0...1.33.1) - 4 April 2024
67
71
 
68
72
  #### :bug: Bug Fixes
@@ -196,8 +200,6 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
196
200
 
197
201
  - bump version [Razvan - [`721e939`](https://github.com/eea/volto-eea-website-theme/commit/721e939d12e324b459ebfa78a2e656ee7142a3d6)]
198
202
  - merge master into this branch [Razvan - [`586c8f9`](https://github.com/eea/volto-eea-website-theme/commit/586c8f910bac55a043bd8dda60e9444bd2ae1663)]
199
- - Add Sonarqube tag using freshwater-frontend addons list [EEA Jenkins - [`fd90044`](https://github.com/eea/volto-eea-website-theme/commit/fd9004442a9d1d465f7601ecdefe3e23c61e6a9c)]
200
- - Add Sonarqube tag using insitu-frontend addons list [EEA Jenkins - [`4bc3dd3`](https://github.com/eea/volto-eea-website-theme/commit/4bc3dd3ae412a66befd04b5b80fab3716c929240)]
201
203
  - test: Update jest,Jenkinsfile,lint to volto-addons-template PR30 [valentinab25 - [`c4dbd28`](https://github.com/eea/volto-eea-website-theme/commit/c4dbd289358205bc2d849aab7edb11ccf3b89cee)]
202
204
  - fix tests [Razvan - [`042330b`](https://github.com/eea/volto-eea-website-theme/commit/042330bc97d32ffe7ba769b4f2453f71cffed706)]
203
205
  - remove RemoveSchema logic [Razvan - [`08d10f8`](https://github.com/eea/volto-eea-website-theme/commit/08d10f8bf6f75478260e4e4c66d7316ba87b907a)]
@@ -292,11 +294,6 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
292
294
  - test: Add real image to cypress test [Alin Voinea - [`4ff591a`](https://github.com/eea/volto-eea-website-theme/commit/4ff591ae3318c9588b4e2114582c0fa6cfdf31ae)]
293
295
  - test: Add cypress tests for Image block styling position and align [Alin Voinea - [`7341ef7`](https://github.com/eea/volto-eea-website-theme/commit/7341ef7b92714fc0cc3ab0c31c39033e7b3e19e7)]
294
296
  - Revert "change(tests): commented out rss test since title block config is missing" [Alin Voinea - [`fb61191`](https://github.com/eea/volto-eea-website-theme/commit/fb611918d6ca380b89b594f283dcf9f685a4b294)]
295
- - test: [JENKINS] Use java17 for sonarqube scanner [valentinab25 - [`6a3be30`](https://github.com/eea/volto-eea-website-theme/commit/6a3be3092589411af7808a235f76de5222fd3868)]
296
- - test: [JENKINS] Run cypress in started frontend container [valentinab25 - [`c3978f2`](https://github.com/eea/volto-eea-website-theme/commit/c3978f23375ef066e9fd6f6c2e34ba6c1c058f69)]
297
- - test: [JENKINS] Add cpu limit on cypress docker [valentinab25 - [`f672779`](https://github.com/eea/volto-eea-website-theme/commit/f672779e845bec9240ccc901e9f53ec80c5a1819)]
298
- - test: [JENKINS] Increase shm-size to cypress docker [valentinab25 - [`ae5d8e3`](https://github.com/eea/volto-eea-website-theme/commit/ae5d8e3f4e04dc2808d47ce2ee886e1b23b528da)]
299
- - test: [JENKINS] Improve cypress time [valentinab25 - [`170ff0c`](https://github.com/eea/volto-eea-website-theme/commit/170ff0c8e3b30e69479bdf1117e811fea94f1027)]
300
297
  ### [1.23.0](https://github.com/eea/volto-eea-website-theme/compare/1.22.1...1.23.0) - 2 November 2023
301
298
 
302
299
  #### :rocket: New Features
@@ -309,7 +306,6 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
309
306
 
310
307
  #### :house: Internal changes
311
308
 
312
- - chore: [JENKINS] Refactor automated testing [valentinab25 - [`f28fce3`](https://github.com/eea/volto-eea-website-theme/commit/f28fce3d1eb815f95fb9aa40de42b10b7e8e30c5)]
313
309
  - chore: husky, lint-staged use fixed versions [valentinab25 - [`6d15088`](https://github.com/eea/volto-eea-website-theme/commit/6d150886c5aeb2ca0b569270486e60f7cc274e2c)]
314
310
  - chore:volto 16 in tests, update docs, fix stylelint overrides [valentinab25 - [`20c0323`](https://github.com/eea/volto-eea-website-theme/commit/20c032380b33c0077c869a05136f93e2fb68e5d4)]
315
311
 
@@ -495,7 +491,6 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
495
491
 
496
492
  #### :house: Internal changes
497
493
 
498
- - chore: [JENKINS] Deprecate circularity website [valentinab25 - [`370dcbf`](https://github.com/eea/volto-eea-website-theme/commit/370dcbfbf1a8135ce7b1b3b271b004552a631837)]
499
494
 
500
495
  #### :hammer_and_wrench: Others
501
496
 
@@ -651,7 +646,6 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
651
646
 
652
647
  #### :hammer_and_wrench: Others
653
648
 
654
- - Add Sonarqube tag using eea-website-frontend addons list [EEA Jenkins - [`6c5e2f8`](https://github.com/eea/volto-eea-website-theme/commit/6c5e2f80456e2061d9e9c15fd0a0b91b9ac70568)]
655
649
  ### [1.9.1](https://github.com/eea/volto-eea-website-theme/compare/1.9.0...1.9.1) - 28 February 2023
656
650
 
657
651
  #### :bug: Bug Fixes
@@ -798,7 +792,6 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
798
792
 
799
793
  - For some reasons types is a string [Alin Voinea - [`3769a09`](https://github.com/eea/volto-eea-website-theme/commit/3769a0981181d5b633f3498daebbe96be8b4b833)]
800
794
  - Fix(redirect): o.filter - refs #157627 [Alin Voinea - [`deb23da`](https://github.com/eea/volto-eea-website-theme/commit/deb23da846444cc96539697fd798429ae0abe89e)]
801
- - Add Sonarqube tag using advisory-board-frontend addons list [EEA Jenkins - [`f1fffc5`](https://github.com/eea/volto-eea-website-theme/commit/f1fffc5db96725440863d545580b4e76cce4b796)]
802
795
  ### [1.5.0](https://github.com/eea/volto-eea-website-theme/compare/1.4.2...1.5.0) - 9 January 2023
803
796
 
804
797
  #### :hammer_and_wrench: Others
@@ -832,7 +825,6 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
832
825
 
833
826
  - Release 1.4.0 [Alin Voinea - [`bd42a0d`](https://github.com/eea/volto-eea-website-theme/commit/bd42a0d26e928cac5d99933194755da3db06b341)]
834
827
  - bump version to use as volto-eea-design-system [David Ichim - [`f4be047`](https://github.com/eea/volto-eea-website-theme/commit/f4be047328b46399b03b612d378b18aaf82e7dc1)]
835
- - Add Sonarqube tag using advisory-board-frontend addons list [EEA Jenkins - [`9b7cfef`](https://github.com/eea/volto-eea-website-theme/commit/9b7cfefb4d34fc1c948015e491feb370f9795bd8)]
836
828
  - test(Jenkins): Run tests and cypress with latest canary @plone/volto [Alin Voinea - [`df252a9`](https://github.com/eea/volto-eea-website-theme/commit/df252a9bfed0bb86cadf53c59dd1603b1e2cd822)]
837
829
  ### [1.3.2](https://github.com/eea/volto-eea-website-theme/compare/1.3.1...1.3.2) - 16 December 2022
838
830
 
@@ -842,7 +834,6 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
842
834
 
843
835
  #### :hammer_and_wrench: Others
844
836
 
845
- - Add Sonarqube tag using cca-frontend addons list [EEA Jenkins - [`a43c658`](https://github.com/eea/volto-eea-website-theme/commit/a43c658a7920c8df95e763b9a637f38ce77eba2c)]
846
837
  - Better razzle.config [Tiberiu Ichim - [`81dbf48`](https://github.com/eea/volto-eea-website-theme/commit/81dbf48815fb27facb4f82c9b764540fdf188b2e)]
847
838
  - Better razzle.config [Tiberiu Ichim - [`7bc9da2`](https://github.com/eea/volto-eea-website-theme/commit/7bc9da2cd837ab62a95cd29979cdd9b0055b7d67)]
848
839
  ### [1.3.1](https://github.com/eea/volto-eea-website-theme/compare/1.3.0...1.3.1) - 28 November 2022
@@ -853,7 +844,6 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
853
844
 
854
845
  #### :hammer_and_wrench: Others
855
846
 
856
- - yarn 3 [Alin Voinea - [`ea7a709`](https://github.com/eea/volto-eea-website-theme/commit/ea7a7094945312776e9b6f44e371178603e92139)]
857
847
  ### [1.3.0](https://github.com/eea/volto-eea-website-theme/compare/1.2.0...1.3.0) - 22 November 2022
858
848
 
859
849
  #### :rocket: New Features
@@ -894,7 +884,6 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
894
884
  - Add subsite class to body [Tiberiu Ichim - [`74d700f`](https://github.com/eea/volto-eea-website-theme/commit/74d700fbfd6249a8604762a7e4e49cce857db0f3)]
895
885
  - Add subsite info to header [Tiberiu Ichim - [`47daf8b`](https://github.com/eea/volto-eea-website-theme/commit/47daf8bb6374a1222040626b19d4154df7ba1b83)]
896
886
  - fix eslint [Miu Razvan - [`eb8d0a7`](https://github.com/eea/volto-eea-website-theme/commit/eb8d0a790bc70c0aae256c6ff35f63c4885f338e)]
897
- - Add Sonarqube tag using circularity-frontend addons list [EEA Jenkins - [`cc578a4`](https://github.com/eea/volto-eea-website-theme/commit/cc578a413b205a8e61e091fab3a88f94cedefc89)]
898
887
  ### [1.1.0](https://github.com/eea/volto-eea-website-theme/compare/1.0.0...1.1.0) - 28 October 2022
899
888
 
900
889
  #### :nail_care: Enhancements
@@ -942,7 +931,6 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
942
931
 
943
932
  #### :hammer_and_wrench: Others
944
933
 
945
- - Add Sonarqube tag using eea-website-frontend addons list [EEA Jenkins - [`33b56ac`](https://github.com/eea/volto-eea-website-theme/commit/33b56acb13fbaf0c5b79e8fc6e13c4b699c79c90)]
946
934
  ### [0.7.3](https://github.com/eea/volto-eea-website-theme/compare/0.7.2...0.7.3) - 22 September 2022
947
935
 
948
936
  #### :hammer_and_wrench: Others
@@ -1210,7 +1198,6 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
1210
1198
  - Header refactor, add custom logo #5 [ichim-david - [`4950235`](https://github.com/eea/volto-eea-website-theme/commit/49502358105437cfeac3b144e6d301cb59aa2346)]
1211
1199
  - Update footer.config with new publication card component [ichim-david - [`2e38e9a`](https://github.com/eea/volto-eea-website-theme/commit/2e38e9a417f835009d60c80d4eb4b30229f55e45)]
1212
1200
  - feature(breadcrumbs): implement eea-design-system breadcrumb as Volto component #32 #7 [ichim-david - [`181af41`](https://github.com/eea/volto-eea-website-theme/commit/181af4125ce2b9ddac56dab4723cb11c26633221)]
1213
- - Add Sonarqube tag using eea-website-frontend addons list [EEA Jenkins - [`da8ceb6`](https://github.com/eea/volto-eea-website-theme/commit/da8ceb68ea68bfbc9504e48ccd4d68277f11ab9a)]
1214
1201
  - use breadcrumbs from eea-design-system [nileshgulia1 - [`db2f9e9`](https://github.com/eea/volto-eea-website-theme/commit/db2f9e9a4327420a3cce9a9903cd88549b129eab)]
1215
1202
  - Update theme.config [ichim-david - [`8eca4f4`](https://github.com/eea/volto-eea-website-theme/commit/8eca4f40397a4aeca6d39029c92db78968d37064)]
1216
1203
  - Added keyContent component to theme.config [ichim-david - [`d86f202`](https://github.com/eea/volto-eea-website-theme/commit/d86f202d0274d839487a88b51cae9a0e899beb23)]
@@ -1252,5 +1239,4 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
1252
1239
 
1253
1240
  #### :hammer_and_wrench: Others
1254
1241
 
1255
- - yarn bootstrap [Alin Voinea - [`6995e9e`](https://github.com/eea/volto-eea-website-theme/commit/6995e9e091f21fdbbdffa8a44fc0e2c626f6d46a)]
1256
1242
  - Initial commit [Alin Voinea - [`6a9c03a`](https://github.com/eea/volto-eea-website-theme/commit/6a9c03a7cebe71ca87e82cf58c42904063e9d8d3)]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eeacms/volto-eea-website-theme",
3
- "version": "2.0.2",
3
+ "version": "2.1.0",
4
4
  "description": "@eeacms/volto-eea-website-theme: Volto add-on",
5
5
  "main": "src/index.js",
6
6
  "author": "European Environment Agency: IDM2 A-Team",
@@ -2,11 +2,11 @@ import React from 'react';
2
2
  import config from '@plone/volto/registry';
3
3
 
4
4
  const CustomCSS = (props) => {
5
+ const href = `${config.settings.apiPath}/voltoCustom.css`;
5
6
  return (
6
- <link
7
- rel={'stylesheet'}
8
- href={`${config.settings.apiPath}/voltoCustom.css`}
9
- />
7
+ <>
8
+ <link rel="stylesheet" href={href} />
9
+ </>
10
10
  );
11
11
  };
12
12
  export default CustomCSS;
@@ -18,12 +18,17 @@ describe('TopicsWidget Component', () => {
18
18
  },
19
19
  });
20
20
 
21
+ const tags = [
22
+ { title: 'Environment', token: '1' },
23
+ { title: 'Climate', token: '2' },
24
+ ];
25
+
21
26
  const { container } = render(
22
27
  <Provider store={store}>
23
28
  <Router history={history}>
24
29
  <TopicsWidget
25
- value={['Value1', 'Value2']}
26
- children={''}
30
+ value={tags}
31
+ children={(tagTitle) => <span>{tagTitle}</span>}
27
32
  className={'test'}
28
33
  />
29
34
  </Router>
@@ -313,6 +313,7 @@ class Edit extends Component {
313
313
  '@id': data.url,
314
314
  image_field: data.image_field,
315
315
  image_scales: data.image_scales,
316
+ data: data,
316
317
  }
317
318
  : undefined
318
319
  }
@@ -323,7 +324,9 @@ class Edit extends Component {
323
324
  ? // Backwards compat in the case that the block is storing the full server URL
324
325
  (() => {
325
326
  if (data.size === 'l')
326
- return `${flattenToAppURL(data.url)}/@@images/image`;
327
+ return `${flattenToAppURL(
328
+ data.url,
329
+ )}/@@images/image/large`;
327
330
  if (data.size === 'm')
328
331
  return `${flattenToAppURL(
329
332
  data.url,
@@ -332,7 +335,9 @@ class Edit extends Component {
332
335
  return `${flattenToAppURL(
333
336
  data.url,
334
337
  )}/@@images/image/mini`;
335
- return `${flattenToAppURL(data.url)}/@@images/image`;
338
+ return `${flattenToAppURL(
339
+ data.url,
340
+ )}/@@images/image/large`;
336
341
  })()
337
342
  : data.url
338
343
  }
@@ -76,6 +76,7 @@ export const View = (props) => {
76
76
  '@id': data.url,
77
77
  image_field: data.image_field,
78
78
  image_scales: data.image_scales,
79
+ data: data,
79
80
  }
80
81
  : undefined
81
82
  }
@@ -88,7 +89,7 @@ export const View = (props) => {
88
89
  if (data.size === 'l')
89
90
  return `${flattenToAppURL(
90
91
  data.url,
91
- )}/@@images/image`;
92
+ )}/@@images/image/large`;
92
93
  if (data.size === 'm')
93
94
  return `${flattenToAppURL(
94
95
  data.url,
@@ -99,7 +100,7 @@ export const View = (props) => {
99
100
  )}/@@images/image/mini`;
100
101
  return `${flattenToAppURL(
101
102
  data.url,
102
- )}/@@images/image`;
103
+ )}/@@images/image/large`;
103
104
  })()
104
105
  : data.url
105
106
  }
@@ -95,10 +95,12 @@ export function ImageSchema({ formData, intl }) {
95
95
  align: {
96
96
  title: intl.formatMessage(messages.Align),
97
97
  widget: 'align',
98
+ default: 'center',
98
99
  },
99
100
  size: {
100
101
  title: intl.formatMessage(messages.size),
101
102
  widget: 'image_size',
103
+ default: 'l',
102
104
  },
103
105
  href: {
104
106
  title: intl.formatMessage(messages.LinkTo),
@@ -9,16 +9,10 @@ import { connect, useDispatch, useSelector } from 'react-redux';
9
9
 
10
10
  import { withRouter } from 'react-router-dom';
11
11
  import { UniversalLink } from '@plone/volto/components';
12
- import {
13
- getBaseUrl,
14
- hasApiExpander,
15
- flattenToAppURL,
16
- } from '@plone/volto/helpers';
12
+ import { getBaseUrl, hasApiExpander } from '@plone/volto/helpers';
17
13
  import { getNavigation } from '@plone/volto/actions';
18
14
  import { Header, Logo } from '@eeacms/volto-eea-design-system/ui';
19
15
  import { usePrevious } from '@eeacms/volto-eea-design-system/helpers';
20
- import { find } from 'lodash';
21
- import globeIcon from '@eeacms/volto-eea-design-system/../theme/themes/eea/assets/images/Header/global-line.svg';
22
16
  import eeaFlag from '@eeacms/volto-eea-design-system/../theme/themes/eea/assets/images/Header/eea.png';
23
17
 
24
18
  import config from '@plone/volto/registry';
@@ -26,6 +20,9 @@ import { compose } from 'recompose';
26
20
  import { BodyClass } from '@plone/volto/helpers';
27
21
 
28
22
  import cx from 'classnames';
23
+ import loadable from '@loadable/component';
24
+
25
+ const LazyLanguageSwitcher = loadable(() => import('./LanguageSwitcher'));
29
26
 
30
27
  function removeTrailingSlash(path) {
31
28
  return path.replace(/\/+$/, '');
@@ -35,11 +32,6 @@ function removeTrailingSlash(path) {
35
32
  * EEA Specific Header component.
36
33
  */
37
34
  const EEAHeader = ({ pathname, token, items, history, subsite }) => {
38
- const currentLang = useSelector((state) => state.intl.locale);
39
- const translations = useSelector(
40
- (state) => state.content.data?.['@components']?.translations?.items,
41
- );
42
-
43
35
  const router_pathname = useSelector((state) => {
44
36
  return removeTrailingSlash(state.router?.location?.pathname) || '';
45
37
  });
@@ -61,31 +53,25 @@ const EEAHeader = ({ pathname, token, items, history, subsite }) => {
61
53
  const { eea } = config.settings;
62
54
  const headerOpts = eea.headerOpts || {};
63
55
  const headerSearchBox = eea.headerSearchBox || [];
64
- const { logo, logoWhite } = headerOpts || {};
56
+ const { logo, logoWhite } = headerOpts;
65
57
  const width = useSelector((state) => state.screen?.width);
66
58
  const dispatch = useDispatch();
67
59
  const previousToken = usePrevious(token);
68
- const [language, setLanguage] = React.useState(
69
- currentLang || eea.defaultLanguage,
70
- );
71
60
 
72
61
  React.useEffect(() => {
73
- const { settings } = config;
74
62
  const base_url = getBaseUrl(pathname);
63
+ const { settings } = config;
64
+
65
+ // Check if navigation data needs to be fetched based on the API expander availability
75
66
  if (!hasApiExpander('navigation', base_url)) {
76
67
  dispatch(getNavigation(base_url, settings.navDepth));
77
68
  }
78
- }, [pathname, dispatch]);
79
69
 
80
- React.useEffect(() => {
70
+ // Additional check for token changes
81
71
  if (token !== previousToken) {
82
- const { settings } = config;
83
- const base = getBaseUrl(pathname);
84
- if (!hasApiExpander('navigation', base)) {
85
- dispatch(getNavigation(base, settings.navDepth));
86
- }
72
+ dispatch(getNavigation(base_url, settings.navDepth));
87
73
  }
88
- }, [token, dispatch, pathname, previousToken]);
74
+ }, [pathname, token, dispatch, previousToken]);
89
75
 
90
76
  return (
91
77
  <Header menuItems={items}>
@@ -155,50 +141,7 @@ const EEAHeader = ({ pathname, token, items, history, subsite }) => {
155
141
  {config.settings.isMultilingual &&
156
142
  config.settings.supportedLanguages.length > 1 &&
157
143
  config.settings.hasLanguageDropdown && (
158
- <Header.TopDropdownMenu
159
- id="language-switcher"
160
- className="item"
161
- text={`${language.toUpperCase()}`}
162
- mobileText={`${language.toUpperCase()}`}
163
- icon={
164
- <Image
165
- src={globeIcon}
166
- alt="language dropdown globe icon"
167
- ></Image>
168
- }
169
- viewportWidth={width}
170
- >
171
- <ul
172
- className="wrapper language-list"
173
- role="listbox"
174
- aria-label="language switcher"
175
- >
176
- {eea.languages.map((item, index) => (
177
- <Dropdown.Item
178
- as="li"
179
- key={index}
180
- text={
181
- <span>
182
- {item.name}
183
- <span className="country-code">
184
- {item.code.toUpperCase()}
185
- </span>
186
- </span>
187
- }
188
- onClick={() => {
189
- const translation = find(translations, {
190
- language: item.code,
191
- });
192
- const to = translation
193
- ? flattenToAppURL(translation['@id'])
194
- : `/${item.code}`;
195
- setLanguage(item.code);
196
- history.push(to);
197
- }}
198
- ></Dropdown.Item>
199
- ))}
200
- </ul>
201
- </Header.TopDropdownMenu>
144
+ <LazyLanguageSwitcher width={width} history={history} />
202
145
  )}
203
146
  </Header.TopHeader>
204
147
  <Header.Main
@@ -1,19 +1,33 @@
1
1
  import React from 'react';
2
- import renderer from 'react-test-renderer';
3
- import { render, fireEvent } from '@testing-library/react';
2
+ import { render, fireEvent, getByText } from '@testing-library/react';
3
+ import '@testing-library/jest-dom/extend-expect';
4
4
  import configureStore from 'redux-mock-store';
5
5
  import { Router } from 'react-router-dom';
6
6
  import { createMemoryHistory } from 'history';
7
7
  import { Provider } from 'react-intl-redux';
8
8
  import config from '@plone/volto/registry';
9
-
9
+ import { waitFor } from '@testing-library/react';
10
10
  import Header from './Header';
11
11
 
12
12
  const mockStore = configureStore();
13
13
  let history = createMemoryHistory();
14
14
 
15
+ const item = {
16
+ '@id': 'en',
17
+ description: 'Description of item',
18
+ items: [],
19
+ review_state: 'published',
20
+ title: 'Test english article',
21
+ };
22
+
23
+ jest.mock('@plone/volto/helpers/Loadable/Loadable');
24
+ beforeAll(
25
+ async () =>
26
+ await require('@plone/volto/helpers/Loadable/Loadable').__setLoadables(),
27
+ );
28
+
15
29
  describe('Header', () => {
16
- it('renders a header component', () => {
30
+ it('renders a header component with homepage_inverse_view layout', () => {
17
31
  const store = mockStore({
18
32
  userSession: { token: null },
19
33
  intl: {
@@ -21,7 +35,7 @@ describe('Header', () => {
21
35
  messages: {},
22
36
  },
23
37
  navigation: {
24
- items: ['en'],
38
+ items: [item],
25
39
  },
26
40
  content: {
27
41
  data: {
@@ -38,22 +52,23 @@ describe('Header', () => {
38
52
  config.settings = {
39
53
  ...config.settings,
40
54
  eea: {
55
+ ...config.settings.eea,
41
56
  headerOpts: undefined,
57
+ logoTargetUrl: '/',
42
58
  },
43
59
  };
44
60
 
45
- const component = renderer.create(
61
+ const { container } = render(
46
62
  <Provider store={store}>
47
63
  <Router history={history}>
48
64
  <Header pathname="/home" />
49
65
  </Router>
50
66
  </Provider>,
51
67
  );
52
- const json = component.toJSON();
53
- expect(json).toMatchSnapshot();
68
+ expect(container).toMatchSnapshot();
54
69
  });
55
70
 
56
- it('renders a header component', () => {
71
+ it('renders a header component with homepage_view layout and translations', async () => {
57
72
  const store = mockStore({
58
73
  userSession: { token: null },
59
74
  intl: {
@@ -61,47 +76,7 @@ describe('Header', () => {
61
76
  messages: {},
62
77
  },
63
78
  navigation: {
64
- items: ['en'],
65
- },
66
- content: {
67
- data: {
68
- layout: 'homepage_inverse_view',
69
- },
70
- },
71
- router: {
72
- location: {
73
- pathname: '/home/',
74
- },
75
- },
76
- });
77
-
78
- config.settings = {
79
- ...config.settings,
80
- eea: {
81
- headerOpts: {},
82
- },
83
- };
84
-
85
- const component = renderer.create(
86
- <Provider store={store}>
87
- <Router history={history}>
88
- <Header pathname="/blog" />
89
- </Router>
90
- </Provider>,
91
- );
92
- const json = component.toJSON();
93
- expect(json).toMatchSnapshot();
94
- });
95
-
96
- it('renders a header component', () => {
97
- const store = mockStore({
98
- userSession: { token: null },
99
- intl: {
100
- locale: undefined,
101
- messages: {},
102
- },
103
- navigation: {
104
- items: ['en'],
79
+ items: [item],
105
80
  },
106
81
  content: {
107
82
  data: {
@@ -123,6 +98,7 @@ describe('Header', () => {
123
98
  config.settings = {
124
99
  ...config.settings,
125
100
  eea: {
101
+ ...config.settings.eea,
126
102
  headerOpts: {
127
103
  partnerLinks: {
128
104
  links: [{ href: '/link1', title: 'link 1' }],
@@ -145,6 +121,9 @@ describe('Header', () => {
145
121
  );
146
122
 
147
123
  fireEvent.click(container.querySelector('.content'));
124
+ await waitFor(() => {
125
+ expect(container.querySelector('.country-code')).not.toBeNull();
126
+ });
148
127
  fireEvent.keyDown(container.querySelector('.content'), { keyCode: 37 });
149
128
  fireEvent.keyDown(container.querySelector('.content a'), { keyCode: 37 });
150
129
  fireEvent.keyDown(container.querySelector('a[href="/link1"]'), {
@@ -152,7 +131,7 @@ describe('Header', () => {
152
131
  });
153
132
  fireEvent.click(container.querySelector('.country-code'));
154
133
 
155
- // expect(getByText('da')).toBeInTheDocument();
134
+ expect(getByText(container, 'RO')).toBeInTheDocument();
156
135
 
157
136
  rerender(
158
137
  <Provider store={{ ...store, userSession: { token: '1234' } }}>
@@ -163,15 +142,15 @@ describe('Header', () => {
163
142
  );
164
143
  });
165
144
 
166
- it('renders a header component', () => {
145
+ it('renders a header component with a subsite', async () => {
167
146
  const store = mockStore({
168
147
  userSession: { token: null },
169
148
  intl: {
170
- locale: undefined,
149
+ locale: 'en',
171
150
  messages: {},
172
151
  },
173
152
  navigation: {
174
- items: ['en'],
153
+ items: [item],
175
154
  },
176
155
  content: {
177
156
  data: {
@@ -179,6 +158,7 @@ describe('Header', () => {
179
158
  '@components': {
180
159
  subsite: {
181
160
  '@type': 'Subsite',
161
+ '@id': 'http://localhost:8080/Plone/subsite',
182
162
  title: 'Home Page',
183
163
  subsite_logo: {
184
164
  scales: {
@@ -205,6 +185,7 @@ describe('Header', () => {
205
185
  config.settings = {
206
186
  ...config.settings,
207
187
  eea: {
188
+ ...config.settings.eea,
208
189
  headerOpts: {
209
190
  partnerLinks: {
210
191
  links: [{ href: '/link1', title: 'link 1' }],
@@ -227,6 +208,9 @@ describe('Header', () => {
227
208
  );
228
209
 
229
210
  fireEvent.click(container.querySelector('.content'));
211
+ await waitFor(() => {
212
+ expect(container.querySelector('.country-code')).not.toBeNull();
213
+ });
230
214
  fireEvent.keyDown(container.querySelector('.content'), { keyCode: 37 });
231
215
  fireEvent.keyDown(container.querySelector('.content a'), { keyCode: 37 });
232
216
  fireEvent.keyDown(container.querySelector('a[href="/link1"]'), {
@@ -234,7 +218,7 @@ describe('Header', () => {
234
218
  });
235
219
  fireEvent.click(container.querySelector('.country-code'));
236
220
 
237
- // expect(getByText('da')).toBeInTheDocument();
221
+ expect(getByText(container, 'RO')).toBeInTheDocument();
238
222
 
239
223
  rerender(
240
224
  <Provider store={{ ...store, userSession: { token: '1234' } }}>
@@ -245,17 +229,17 @@ describe('Header', () => {
245
229
  );
246
230
  });
247
231
 
248
- it('renders a header component', () => {
232
+ it('renders a header component with a subsite and two children', async () => {
249
233
  const store = mockStore({
250
234
  userSession: { token: null },
251
235
  intl: {
252
- locale: undefined,
236
+ locale: 'en',
253
237
  messages: {},
254
238
  },
255
239
  navigation: {
256
240
  items: [
257
241
  { url: '/test1', title: 'test 1', nav_title: 'Test 1', items: [] },
258
- { url: undefined, title: 'test 2', items: [] },
242
+ { url: '/test2', title: 'test 2', items: [] },
259
243
  ],
260
244
  },
261
245
  content: {
@@ -264,6 +248,7 @@ describe('Header', () => {
264
248
  '@components': {
265
249
  subsite: {
266
250
  '@type': 'Subsite',
251
+ '@id': 'http://localhost:8080/Plone/subsite',
267
252
  title: 'Home Page',
268
253
  subsite_logo: undefined,
269
254
  },
@@ -283,6 +268,7 @@ describe('Header', () => {
283
268
  config.settings = {
284
269
  ...config.settings,
285
270
  eea: {
271
+ ...config.settings.eea,
286
272
  headerOpts: {
287
273
  partnerLinks: {
288
274
  links: [{ href: '/link1', title: 'link 1' }],
@@ -305,6 +291,9 @@ describe('Header', () => {
305
291
  );
306
292
 
307
293
  fireEvent.click(container.querySelector('.content'));
294
+ await waitFor(() => {
295
+ expect(container.querySelector('.country-code')).not.toBeNull();
296
+ });
308
297
  fireEvent.keyDown(container.querySelector('.content'), { keyCode: 37 });
309
298
  fireEvent.keyDown(container.querySelector('.content a'), { keyCode: 37 });
310
299
  fireEvent.keyDown(container.querySelector('a[href="/link1"]'), {
@@ -313,7 +302,7 @@ describe('Header', () => {
313
302
  fireEvent.click(container.querySelector('.country-code'));
314
303
  fireEvent.click(container.querySelector('a[href="/test1"]'));
315
304
 
316
- // expect(getByText('da')).toBeInTheDocument();
305
+ expect(getByText(container, 'RO')).toBeInTheDocument();
317
306
 
318
307
  rerender(
319
308
  <Provider store={{ ...store, userSession: { token: '1234' } }}>
@@ -0,0 +1,71 @@
1
+ import React from 'react';
2
+ import { useSelector } from 'react-redux';
3
+ import { Dropdown, Image } from 'semantic-ui-react';
4
+ import { flattenToAppURL } from '@plone/volto/helpers';
5
+ import { find } from 'lodash';
6
+ import globeIcon from '@eeacms/volto-eea-design-system/../theme/themes/eea/assets/images/Header/global-line.svg';
7
+ import config from '@plone/volto/registry';
8
+ import { Header } from '@eeacms/volto-eea-design-system/ui';
9
+
10
+ /**
11
+ * LanguageSwitcher component.
12
+ * Provides a dropdown menu for language selection, changing the application's
13
+ * language and navigating to the corresponding translated URL.
14
+ *
15
+ * @param {Object} props - The component props.
16
+ * @param {number} props.width - The viewport width to adjust the dropdown display.
17
+ * @param {Object} props.history - The history object from React Router for navigation.
18
+ */
19
+ const LanguageSwitcher = ({ width, history }) => {
20
+ const currentLang = useSelector((state) => state.intl.locale);
21
+ const translations = useSelector(
22
+ (state) => state.content.data?.['@components']?.translations?.items,
23
+ );
24
+ const { eea } = config.settings;
25
+
26
+ const [language, setLanguage] = React.useState(
27
+ currentLang || eea.defaultLanguage,
28
+ );
29
+
30
+ return (
31
+ <Header.TopDropdownMenu
32
+ id="language-switcher"
33
+ className="item"
34
+ text={`${language.toUpperCase()}`}
35
+ mobileText={`${language.toUpperCase()}`}
36
+ icon={<Image src={globeIcon} alt="language dropdown globe icon"></Image>}
37
+ viewportWidth={width}
38
+ >
39
+ <ul
40
+ className="wrapper language-list"
41
+ role="listbox"
42
+ aria-label="language switcher"
43
+ >
44
+ {eea.languages.map((item, index) => (
45
+ <Dropdown.Item
46
+ as="li"
47
+ key={index}
48
+ text={
49
+ <span>
50
+ {item.name}
51
+ <span className="country-code">{item.code.toUpperCase()}</span>
52
+ </span>
53
+ }
54
+ onClick={() => {
55
+ const translation = find(translations, {
56
+ language: item.code,
57
+ });
58
+ const to = translation
59
+ ? flattenToAppURL(translation['@id'])
60
+ : `/${item.code}`;
61
+ setLanguage(item.code);
62
+ history.push(to);
63
+ }}
64
+ ></Dropdown.Item>
65
+ ))}
66
+ </ul>
67
+ </Header.TopDropdownMenu>
68
+ );
69
+ };
70
+
71
+ export default LanguageSwitcher;
@@ -0,0 +1,119 @@
1
+ import PropTypes from 'prop-types';
2
+ import cx from 'classnames';
3
+ import { flattenToAppURL, flattenScales } from '@plone/volto/helpers';
4
+
5
+ /**
6
+ * Determines the image scale name based on the provided data.
7
+ *
8
+ * @param {object} data - The data object containing the image size information.
9
+ * @param {string} [data.size] - The size of the image, can be 'l', 'm', or 's'.
10
+ * @returns {string} The name of the image scale, either 'large', 'preview', or 'mini'.
11
+ */
12
+ const imageScaleName = (data) => {
13
+ if (!data) return 'large';
14
+ if (data.size === 'l') return 'large';
15
+ if (data.size === 'm') return 'preview';
16
+ if (data.size === 's') return 'mini';
17
+ return 'large';
18
+ };
19
+
20
+ /**
21
+ * Image component
22
+ * @param {object} item - Context item that has the image field (can also be a catalog brain or summary)
23
+ * @param {string} imageField - Key of the image field inside the item, or inside the image_scales object of the item if it is a catalog brain or summary
24
+ * @param {string} src - URL of the image to be used if the item field is not available
25
+ * @param {string} alt - Alternative text for the image
26
+ * @param {boolean} loading - (default: eager) set to `lazy` to lazy load the image
27
+ * @param {boolean} responsive - (default: false) set to `true` to add the `responsive` class to the image
28
+ * @param {string} className - Additional classes to add to the image
29
+ */
30
+ export default function Image({
31
+ item,
32
+ imageField,
33
+ src,
34
+ alt = '',
35
+ loading = 'eager',
36
+ responsive = false,
37
+ className = '',
38
+ ...imageProps
39
+ }) {
40
+ if (!item && !src) return null;
41
+
42
+ // TypeScript hints for editor autocomplete :)
43
+ /** @type {React.ImgHTMLAttributes<HTMLImageElement>} */
44
+ const attrs = {};
45
+
46
+ if (!item && src) {
47
+ attrs.src = src;
48
+ attrs.className = cx(className, { responsive });
49
+ } else {
50
+ const isFromRealObject = !item.image_scales;
51
+ const imageFieldWithDefault = imageField || item.image_field || 'image';
52
+
53
+ const image = isFromRealObject
54
+ ? flattenScales(item['@id'], item[imageFieldWithDefault])
55
+ : flattenScales(
56
+ item['@id'],
57
+ item.image_scales[imageFieldWithDefault]?.[0],
58
+ );
59
+
60
+ if (!image) return null;
61
+
62
+ const isSvg = image['content-type'] === 'image/svg+xml';
63
+ // In case `base_path` is present (`preview_image_link`) use it as base path
64
+ const basePath = image.base_path || item['@id'];
65
+ const relativeBasePath = flattenToAppURL(basePath);
66
+ const selectedScale = imageScaleName(item.data);
67
+
68
+ attrs.src = `${relativeBasePath}/${image.download}`;
69
+ attrs.width = image.width;
70
+ attrs.height = image.height;
71
+ attrs.className = cx(className, { responsive });
72
+
73
+ if (!isSvg && image.scales && Object.keys(image.scales).length > 0) {
74
+ const filteredScales = [
75
+ 'mini',
76
+ 'preview',
77
+ 'large',
78
+ item.data?.align === 'full' ? 'huge' : undefined,
79
+ ]
80
+ .map((key) => image.scales[key])
81
+ .filter(Boolean);
82
+ const imageScale = image.scales[selectedScale];
83
+ if (imageScale) {
84
+ // set default image size, width and height to the selected scale
85
+ attrs.width = imageScale.width;
86
+ attrs.height = imageScale.height;
87
+ attrs.src = `${relativeBasePath}/${imageScale.download}`;
88
+ }
89
+
90
+ attrs.srcSet = filteredScales
91
+ .map((scale) => `${relativeBasePath}/${scale.download} ${scale.width}w`)
92
+ .join(', ');
93
+ }
94
+ }
95
+
96
+ if (loading === 'lazy') {
97
+ attrs.loading = 'lazy';
98
+ attrs.decoding = 'async';
99
+ } else {
100
+ attrs.fetchpriority = 'high';
101
+ }
102
+
103
+ return <img {...attrs} alt={alt} {...imageProps} />;
104
+ }
105
+
106
+ Image.propTypes = {
107
+ item: PropTypes.shape({
108
+ '@id': PropTypes.string,
109
+ image_field: PropTypes.string,
110
+ image_scales: PropTypes.object,
111
+ image: PropTypes.object,
112
+ }),
113
+ imageField: PropTypes.string,
114
+ src: PropTypes.string,
115
+ alt: PropTypes.string.isRequired,
116
+ loading: PropTypes.string,
117
+ responsive: PropTypes.bool,
118
+ className: PropTypes.string,
119
+ };
@@ -0,0 +1,3 @@
1
+ Customized Image component to restrict the image scales passed to srcset.
2
+ Right now we could select the small size and yet on FHD displays the image served
3
+ would be the huge scale.
package/src/index.js CHANGED
@@ -194,6 +194,18 @@ const applyConfig = (config) => {
194
194
  if (config.blocks.blocksConfig.image) {
195
195
  config.blocks.blocksConfig.image.schemaEnhancer =
196
196
  addStylingFieldsetSchemaEnhancerImagePosition;
197
+ config.blocks.blocksConfig.image.getSizes = function (data) {
198
+ if (data.size === 'm' || data.size === 's') return undefined;
199
+
200
+ if (data.align === 'left' || data.align === 'right') {
201
+ if (data.size === 'l') return '400px';
202
+ if (data.size === 'm') return '200px';
203
+ if (data.size === 's') return '200px';
204
+ }
205
+ if (data.size === 'l') {
206
+ return '(max-width: 600px) 400px, (max-width: 1440px) 800px, 100vw';
207
+ }
208
+ };
197
209
  }
198
210
 
199
211
  // Set Languages in nextcloud-video-block