@eeacms/volto-cca-policy 0.3.64 → 0.3.66

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.
Files changed (45) hide show
  1. package/CHANGELOG.md +83 -0
  2. package/locales/bg/LC_MESSAGES/volto.po +31 -39
  3. package/locales/cs/LC_MESSAGES/volto.po +31 -39
  4. package/locales/da/LC_MESSAGES/volto.po +31 -39
  5. package/locales/de/LC_MESSAGES/volto.po +31 -39
  6. package/locales/el/LC_MESSAGES/volto.po +31 -39
  7. package/locales/en/LC_MESSAGES/volto.po +31 -38
  8. package/locales/es/LC_MESSAGES/volto.po +31 -39
  9. package/locales/et/LC_MESSAGES/volto.po +31 -39
  10. package/locales/fi/LC_MESSAGES/volto.po +31 -39
  11. package/locales/fr/LC_MESSAGES/volto.po +31 -39
  12. package/locales/ga/LC_MESSAGES/volto.po +31 -39
  13. package/locales/hr/LC_MESSAGES/volto.po +31 -39
  14. package/locales/hu/LC_MESSAGES/volto.po +31 -39
  15. package/locales/is/LC_MESSAGES/volto.po +31 -39
  16. package/locales/it/LC_MESSAGES/volto.po +31 -39
  17. package/locales/lt/LC_MESSAGES/volto.po +31 -39
  18. package/locales/lv/LC_MESSAGES/volto.po +31 -39
  19. package/locales/mt/LC_MESSAGES/volto.po +31 -39
  20. package/locales/nl/LC_MESSAGES/volto.po +31 -39
  21. package/locales/nn/LC_MESSAGES/volto.po +31 -39
  22. package/locales/pl/LC_MESSAGES/volto.po +31 -39
  23. package/locales/pt/LC_MESSAGES/volto.po +31 -39
  24. package/locales/ro/LC_MESSAGES/volto.po +31 -39
  25. package/locales/sk/LC_MESSAGES/volto.po +31 -39
  26. package/locales/sl/LC_MESSAGES/volto.po +31 -39
  27. package/locales/sv/LC_MESSAGES/volto.po +31 -39
  28. package/locales/tr/LC_MESSAGES/volto.po +309 -351
  29. package/locales/volto.pot +22 -39
  30. package/package.json +2 -2
  31. package/src/components/manage/Blocks/CaseStudyExplorer/CaseStudyMap.test.jsx +6 -6
  32. package/src/components/manage/Blocks/CaseStudyExplorer/FeatureDisplay.test.jsx +2 -2
  33. package/src/components/theme/Header/Header.jsx +49 -28
  34. package/src/components/theme/Header/LanguageSwitch.jsx +41 -68
  35. package/src/components/theme/ImageGallery/ImageGallery.jsx +2 -2
  36. package/src/components/theme/ImageGallery/ImageGallery.test.jsx +38 -0
  37. package/src/components/theme/MissionSignatoryProfile/TabSections/PlanningTab.test.jsx +3 -2
  38. package/src/components/theme/PortalMessage/PortalMessage.jsx +6 -4
  39. package/src/components/theme/PortalMessage/PortalMessage.test.jsx +24 -0
  40. package/src/components/theme/Widgets/PromotionalImageWidget.jsx +35 -13
  41. package/src/components/theme/Widgets/PromotionalImageWidget.test.jsx +1 -1
  42. package/src/customizations/volto/components/theme/View/DefaultView.jsx +5 -1
  43. package/src/index.js +3 -3
  44. package/src/utils.js +11 -6
  45. package/theme/extras/header.overrides +14 -0
package/locales/volto.pot CHANGED
@@ -1,7 +1,7 @@
1
1
  msgid ""
2
2
  msgstr ""
3
3
  "Project-Id-Version: Plone\n"
4
- "POT-Creation-Date: 2025-04-22T09:13:00.209Z\n"
4
+ "POT-Creation-Date: 2025-07-14T08:07:37.202Z\n"
5
5
  "Last-Translator: Plone i18n <plone-i18n@lists.sourceforge.net>\n"
6
6
  "Language-Team: Plone i18n <plone-i18n@lists.sourceforge.net>\n"
7
7
  "Content-Type: text/plain; charset=utf-8\n"
@@ -20,8 +20,6 @@ msgstr ""
20
20
 
21
21
  #. Default: "Adaptation Approaches"
22
22
  #: search/cca/facets
23
- #: search/facets
24
- #: search/fise/facets
25
23
  #: search/health_observatory/facets-health
26
24
  #: search/mission_all/facets-all
27
25
  #: search/mission_projects/facets-projects
@@ -46,8 +44,6 @@ msgstr ""
46
44
  #. Default: "Adaptation Sectors"
47
45
  #: search/cca/facets
48
46
  #: search/common
49
- #: search/facets
50
- #: search/fise/facets
51
47
  msgid "Adaptation Sectors"
52
48
  msgstr ""
53
49
 
@@ -88,11 +84,6 @@ msgstr ""
88
84
  msgid "Background information"
89
85
  msgstr ""
90
86
 
91
- #. Default: "Belgium"
92
- #: helpers/Constants
93
- msgid "Belgium"
94
- msgstr ""
95
-
96
87
  #. Default: "Biogeographical regions:"
97
88
  #: helpers/ContentMetadata
98
89
  msgid "Biogeographical regions:"
@@ -114,7 +105,7 @@ msgid "Case Study illustrations"
114
105
  msgstr ""
115
106
 
116
107
  #. Default: "Case studies related to this option:"
117
- #: components/theme/Views/AdaptationOptionView
108
+ #: helpers/ContentMetadata
118
109
  msgid "Case studies related to this option:"
119
110
  msgstr ""
120
111
 
@@ -151,8 +142,6 @@ msgstr ""
151
142
  #. Default: "Climate Impacts"
152
143
  #: search/cca/facets
153
144
  #: search/common
154
- #: search/facets
155
- #: search/fise/facets
156
145
  msgid "Climate Impacts"
157
146
  msgstr ""
158
147
 
@@ -306,11 +295,6 @@ msgstr ""
306
295
  msgid "For more search options"
307
296
  msgstr ""
308
297
 
309
- #. Default: "France"
310
- #: helpers/Constants
311
- msgid "France"
312
- msgstr ""
313
-
314
298
  #. Default: "Fullscreen"
315
299
  #: components/theme/Views/C3SIndicatorView
316
300
  msgid "Fullscreen"
@@ -318,8 +302,6 @@ msgstr ""
318
302
 
319
303
  #. Default: "Funding Programme"
320
304
  #: search/cca/facets
321
- #: search/facets
322
- #: search/fise/facets
323
305
  #: search/mission_projects/facets-projects
324
306
  #: search/mission_stories/facets-stories
325
307
  msgid "Funding Programme"
@@ -365,11 +347,6 @@ msgstr ""
365
347
  msgid "Hazard Type"
366
348
  msgstr ""
367
349
 
368
- #. Default: "Health Impacts"
369
- #: search/health_observatory/config-health
370
- msgid "Health Impacts"
371
- msgstr ""
372
-
373
350
  #. Default: "Health impact:"
374
351
  #: helpers/ContentMetadata
375
352
  msgid "Health impact:"
@@ -433,8 +410,6 @@ msgstr ""
433
410
 
434
411
  #. Default: "Item from third parties"
435
412
  #: search/cca/facets
436
- #: search/facets
437
- #: search/fise/facets
438
413
  msgid "Item from third parties"
439
414
  msgstr ""
440
415
 
@@ -446,8 +421,6 @@ msgstr ""
446
421
  #. Default: "Key Type Measure"
447
422
  #: components/manage/Blocks/FilterAceContent/FilterAceContentView
448
423
  #: search/cca/facets
449
- #: search/facets
450
- #: search/fise/facets
451
424
  msgid "Key Type Measure"
452
425
  msgstr ""
453
426
 
@@ -521,6 +494,11 @@ msgstr ""
521
494
  msgid "Lead"
522
495
  msgstr ""
523
496
 
497
+ #. Default: "Learn more"
498
+ #: components/manage/Blocks/Listing/EventAccordionListingView
499
+ msgid "Learn more"
500
+ msgstr ""
501
+
524
502
  #. Default: "Legal aspects"
525
503
  #: components/theme/Views/AdaptationOptionView
526
504
  #: components/theme/Views/CaseStudyView
@@ -578,6 +556,11 @@ msgstr ""
578
556
  msgid "No results"
579
557
  msgstr ""
580
558
 
559
+ #. Default: "Non-EU Languages"
560
+ #: components/theme/Header/LanguageSwitch
561
+ msgid "Non-EU Languages"
562
+ msgstr ""
563
+
581
564
  #. Default: "Objectives of the adaptation measure"
582
565
  #: components/theme/Views/CaseStudyView
583
566
  msgid "Objectives of the adaptation measure"
@@ -594,7 +577,6 @@ msgid "Observatory contributions"
594
577
  msgstr ""
595
578
 
596
579
  #. Default: "Observatory partner"
597
- #: search/health_observatory/config-health
598
580
  #: search/health_observatory/facets-health
599
581
  msgid "Observatory partner"
600
582
  msgstr ""
@@ -729,8 +711,6 @@ msgstr ""
729
711
 
730
712
  #. Default: "Section"
731
713
  #: search/cca/facets
732
- #: search/facets
733
- #: search/fise/facets
734
714
  msgid "Section"
735
715
  msgstr ""
736
716
 
@@ -841,6 +821,11 @@ msgstr ""
841
821
  msgid "The date refers to the moment in which the item has been prepared or updated by contributing experts to be submitted for the publication in Climate ADAPT"
842
822
  msgstr ""
843
823
 
824
+ #. Default: "This object has been archived because its content is outdated. You can still access it as legacy."
825
+ #: components/theme/PortalMessage/PortalMessage
826
+ msgid "This object has been archived because its content is outdated. You can still access it as legacy."
827
+ msgstr ""
828
+
844
829
  #. Default: "Topics:"
845
830
  #: components/Result/ClusterHorizontalCardItem
846
831
  #: components/Result/HealthHorizontalCardItem
@@ -849,8 +834,6 @@ msgstr ""
849
834
 
850
835
  #. Default: "Transnational regions"
851
836
  #: search/cca/facets
852
- #: search/facets
853
- #: search/fise/facets
854
837
  msgid "Transnational regions"
855
838
  msgstr ""
856
839
 
@@ -860,11 +843,6 @@ msgstr ""
860
843
  msgid "Type of item"
861
844
  msgstr ""
862
845
 
863
- #. Default: "Types"
864
- #: search/health_observatory/config-health
865
- msgid "Types"
866
- msgstr ""
867
-
868
846
  #. Default: "Updating notes"
869
847
  #: components/theme/Views/CaseStudyView
870
848
  msgid "Updating notes"
@@ -915,3 +893,8 @@ msgstr ""
915
893
  #: helpers/Utils
916
894
  msgid "Where"
917
895
  msgstr ""
896
+
897
+ #. Default: "Officially reported governmental information is only available in English"
898
+ #: components/manage/Blocks/CountryProfileDetail/View
899
+ msgid "officiallyInEnglish"
900
+ msgstr ""
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eeacms/volto-cca-policy",
3
- "version": "0.3.64",
3
+ "version": "0.3.66",
4
4
  "description": "@eeacms/volto-cca-policy: Volto add-on",
5
5
  "main": "src/index.js",
6
6
  "author": "European Environment Agency: IDM2 A-Team",
@@ -35,7 +35,7 @@
35
35
  "@eeacms/volto-globalsearch": "2.1.2",
36
36
  "@eeacms/volto-hero-block": "^7.1.0",
37
37
  "@eeacms/volto-openlayers-map": "1.0.1",
38
- "@eeacms/volto-searchlib": "2.0.16",
38
+ "@eeacms/volto-searchlib": "2.1.0",
39
39
  "@eeacms/volto-slate-label": "^0.6.0",
40
40
  "@eeacms/volto-tabs-block": "^7.5.1",
41
41
  "@elastic/search-ui": "1.21.2",
@@ -83,11 +83,11 @@ describe('CaseStudyMap', () => {
83
83
  portal_type: 'casestudy',
84
84
  description:
85
85
  '<p>The Sand Motor is a mega-nourishment implemented in the Delfland Coast.</p>',
86
- url: 'http://website.com',
86
+ url: 'https://website.com',
87
87
  adaptation_options_links:
88
- "<a href='http://website.com'>Beach and shoreface nourishment</a>",
88
+ "<a href='https://website.com'>Beach and shoreface nourishment</a>",
89
89
  elements_str: 'Nature-based solutions',
90
- image: 'http://website.com/preview',
90
+ image: 'https://website.com/preview',
91
91
  origin_adaptecca: 20,
92
92
  adaptation_options: 'Dune construction',
93
93
  },
@@ -107,11 +107,11 @@ describe('CaseStudyMap', () => {
107
107
  portal_type: 'casestudy',
108
108
  description:
109
109
  '<p>The Sand Motor is a mega-nourishment implemented in the Delfland Coast.</p>',
110
- url: 'http://website.com',
110
+ url: 'https://website.com',
111
111
  adaptation_options_links:
112
- "<a href='http://website.com'>Beach and shoreface nourishment</a>",
112
+ "<a href='https://website.com'>Beach and shoreface nourishment</a>",
113
113
  elements_str: 'Nature-based solutions',
114
- image: 'http://website.com/preview',
114
+ image: 'https://website.com/preview',
115
115
  origin_adaptecca: 20,
116
116
  adaptation_options: 'Dune construction',
117
117
  },
@@ -12,8 +12,8 @@ describe('FeatureDisplay', () => {
12
12
  it('should render the component', () => {
13
13
  const feature = {
14
14
  title: 'Case study',
15
- url: 'http://example.com',
16
- image: 'http://example.com/image.jpg',
15
+ url: 'https://example.com',
16
+ image: 'https://example.com/image.jpg',
17
17
  impacts: 'Impact A, Impact B',
18
18
  adaptation_options_links: '',
19
19
  };
@@ -5,7 +5,7 @@
5
5
 
6
6
  import React from 'react';
7
7
  import { compose } from 'recompose';
8
- import { withRouter } from 'react-router-dom';
8
+ import { withRouter, Link } from 'react-router-dom';
9
9
  import { Dropdown, Image } from 'semantic-ui-react';
10
10
  import { connect, useDispatch, useSelector } from 'react-redux';
11
11
  import { UniversalLink } from '@plone/volto/components';
@@ -26,7 +26,10 @@ import cx from 'classnames';
26
26
  import eeaFlag from '@eeacms/volto-eea-design-system/../theme/themes/eea/assets/images/Header/eea.png';
27
27
 
28
28
  function removeTrailingSlash(path) {
29
- return path.replace(/\/+$/, '');
29
+ while (path.endsWith('/')) {
30
+ path = path.slice(0, -1);
31
+ }
32
+ return path;
30
33
  }
31
34
 
32
35
  /**
@@ -62,6 +65,7 @@ const DirectLinkLogo = ({
62
65
  */
63
66
  const EEAHeader = (props) => {
64
67
  const { pathname, token, items, subsite } = props;
68
+ const currentLang = useSelector((state) => state.intl.locale);
65
69
  const router_pathname = useSelector((state) => {
66
70
  return removeTrailingSlash(state.router?.location?.pathname) || '';
67
71
  });
@@ -153,32 +157,50 @@ const EEAHeader = (props) => {
153
157
  </Header.TopDropdownMenu>
154
158
  </Header.TopItem>
155
159
 
156
- {!!headerOpts.partnerLinks && (
157
- <Header.TopItem>
158
- <Header.TopDropdownMenu
159
- id="theme-sites"
160
- text={headerOpts.partnerLinks.title}
161
- viewportWidth={width}
162
- >
163
- <div className="wrapper">
164
- {headerOpts.partnerLinks.links.map((item, index) => (
165
- <Dropdown.Item key={index}>
166
- <a
167
- href={item.href}
168
- className="site"
169
- target="_blank"
170
- onKeyDown={(evt) => evt.stopPropagation()}
171
- >
172
- {item.title}
173
- </a>
174
- </Dropdown.Item>
175
- ))}
176
- </div>
177
- </Header.TopDropdownMenu>
178
- </Header.TopItem>
179
- )}
160
+ <div className="top-header-right-items">
161
+ <div className="item">
162
+ <div className="divider text">
163
+ <Link
164
+ to={
165
+ pathname.includes('/observatory')
166
+ ? `/${currentLang}/observatory/sitemap`
167
+ : pathname.includes('/mission')
168
+ ? `/${currentLang}/mission/sitemap`
169
+ : `/${currentLang}/sitemap`
170
+ }
171
+ >
172
+ Sitemap
173
+ </Link>
174
+ </div>
175
+ </div>
176
+
177
+ {!!headerOpts.partnerLinks && (
178
+ <Header.TopItem>
179
+ <Header.TopDropdownMenu
180
+ id="theme-sites"
181
+ text={headerOpts.partnerLinks.title}
182
+ viewportWidth={width}
183
+ >
184
+ <div className="wrapper">
185
+ {headerOpts.partnerLinks.links.map((item, index) => (
186
+ <Dropdown.Item key={index}>
187
+ <a
188
+ href={item.href}
189
+ className="site"
190
+ target="_blank"
191
+ onKeyDown={(evt) => evt.stopPropagation()}
192
+ >
193
+ {item.title}
194
+ </a>
195
+ </Dropdown.Item>
196
+ ))}
197
+ </div>
198
+ </Header.TopDropdownMenu>
199
+ </Header.TopItem>
200
+ )}
180
201
 
181
- {config.settings.isMultilingual && <LanguageSwitch {...props} />}
202
+ {config.settings.isMultilingual && <LanguageSwitch {...props} />}
203
+ </div>
182
204
  </Header.TopHeader>
183
205
  <Header.Main
184
206
  pathname={pathname}
@@ -229,7 +251,6 @@ const EEAHeader = (props) => {
229
251
  href={item.url || '/'}
230
252
  title={item.title}
231
253
  onClick={(e) => {
232
- // debugger;
233
254
  onClick(e, item);
234
255
  }}
235
256
  >
@@ -20,8 +20,8 @@ export default function LanguageSwitch({ history }) {
20
20
  );
21
21
  const [, setSelectedLanguage] = useAtom(selectedLanguageAtom);
22
22
  const width = useSelector((state) => state.screen?.width);
23
-
24
23
  const currentLang = useSelector((state) => state.intl.locale);
24
+
25
25
  const [language, setLanguage] = React.useState(
26
26
  currentLang || eea.defaultLanguage,
27
27
  );
@@ -45,7 +45,43 @@ export default function LanguageSwitch({ history }) {
45
45
  });
46
46
  };
47
47
 
48
- // .filter((item) => eea.non_eu_langs.indexOf(item.code) !== -1)
48
+ const renderLanguageItems = (languages) =>
49
+ languages.map((item, index) => {
50
+ const translated = (translations || []).some(
51
+ (obj) => obj.language === item.code,
52
+ );
53
+ const active = item.code === currentLang;
54
+ const disabled = !translated && !active;
55
+
56
+ return (
57
+ <Dropdown.Item
58
+ className={cx({
59
+ disabled: disabled,
60
+ active: active,
61
+ })}
62
+ as="li"
63
+ key={index}
64
+ text={
65
+ <span>
66
+ <span className="country-code">{item.code.toUpperCase()}</span>{' '}
67
+ {item.name}
68
+ </span>
69
+ }
70
+ onClick={(e) =>
71
+ disabled || active ? e.preventDefault() : handlePageRedirect(item)
72
+ }
73
+ />
74
+ );
75
+ });
76
+
77
+ const euLanguages = eea.languages.filter(
78
+ (item) => eea.non_eu_langs.indexOf(item.code) === -1,
79
+ );
80
+
81
+ const nonEuLanguages = eea.languages.filter(
82
+ (item) => eea.non_eu_langs.indexOf(item.code) !== -1,
83
+ );
84
+
49
85
  return (
50
86
  <Header.TopDropdownMenu
51
87
  id="language-switcher"
@@ -56,7 +92,7 @@ export default function LanguageSwitch({ history }) {
56
92
  }
57
93
  text={`${language.toUpperCase()}`}
58
94
  mobileText={`${language.toUpperCase()}`}
59
- icon={<Image src={globeIcon} alt="language dropdown globe icon"></Image>}
95
+ icon={<Image src={globeIcon} alt="language dropdown globe icon" />}
60
96
  viewportWidth={width}
61
97
  >
62
98
  <ul
@@ -64,39 +100,8 @@ export default function LanguageSwitch({ history }) {
64
100
  role="listbox"
65
101
  aria-label="language switcher"
66
102
  >
67
- {eea.languages
68
- .filter((item) => eea.non_eu_langs.indexOf(item.code) === -1)
69
- .map((item, index) => {
70
- const translated = (translations || []).some(
71
- (obj) => obj.language === item.code,
72
- );
73
- const active = item.code === currentLang;
74
- const disabled = !translated && !active;
103
+ {renderLanguageItems(euLanguages)}
75
104
 
76
- return (
77
- <Dropdown.Item
78
- className={cx({
79
- disabled: disabled,
80
- active: active,
81
- })}
82
- as="li"
83
- key={index}
84
- text={
85
- <span>
86
- <span className="country-code">
87
- {item.code.toUpperCase()}
88
- </span>{' '}
89
- {item.name}
90
- </span>
91
- }
92
- onClick={(e) =>
93
- disabled || active
94
- ? e.preventDefault()
95
- : handlePageRedirect(item)
96
- }
97
- ></Dropdown.Item>
98
- );
99
- })}
100
105
  <strong className="noneu-langs-label">
101
106
  <FormattedMessage
102
107
  id="Non-EU Languages"
@@ -104,39 +109,7 @@ export default function LanguageSwitch({ history }) {
104
109
  />
105
110
  </strong>
106
111
 
107
- {eea.languages
108
- .filter((item) => eea.non_eu_langs.indexOf(item.code) !== -1)
109
- .map((item, index) => {
110
- const translated = (translations || []).some(
111
- (obj) => obj.language === item.code,
112
- );
113
- const active = item.code === currentLang;
114
- const disabled = !translated && !active;
115
-
116
- return (
117
- <Dropdown.Item
118
- className={cx({
119
- disabled: disabled,
120
- active: active,
121
- })}
122
- as="li"
123
- key={index}
124
- text={
125
- <span>
126
- <span className="country-code">
127
- {item.code.toUpperCase()}
128
- </span>{' '}
129
- {item.name}
130
- </span>
131
- }
132
- onClick={(e) =>
133
- disabled || active
134
- ? e.preventDefault()
135
- : handlePageRedirect(item)
136
- }
137
- ></Dropdown.Item>
138
- );
139
- })}
112
+ {renderLanguageItems(nonEuLanguages)}
140
113
  </ul>
141
114
  </Header.TopDropdownMenu>
142
115
  );
@@ -89,10 +89,10 @@ const ImageGallery = (props) => {
89
89
  <Slider {...carouselSettings} ref={sliderRef}>
90
90
  {items.map((item, i) => {
91
91
  return image.rights ? (
92
- <div>
92
+ <div key={i}>
93
93
  <div className="image-slide">
94
94
  <div className="image-rights">@ {image.rights}</div>
95
- <Image key={i} src={item.url} alt={item?.title} />
95
+ <Image src={item.url} alt={item?.title} />
96
96
  </div>
97
97
  </div>
98
98
  ) : (
@@ -0,0 +1,38 @@
1
+ import '@testing-library/jest-dom';
2
+ import { render, screen, fireEvent } from '@testing-library/react';
3
+ import ImageGallery from './ImageGallery';
4
+
5
+ jest.mock('react-slick', () => (props) => <div>React Slick Gallery</div>);
6
+
7
+ const mockItems = [
8
+ {
9
+ url: 'https://example.com/image1.jpg',
10
+ title: 'Image One',
11
+ description: 'First image description',
12
+ rights: 'Author One',
13
+ },
14
+ {
15
+ url: 'https://example.com/image2.jpg',
16
+ title: 'Image Two',
17
+ description: 'Second image description',
18
+ rights: 'Author Two',
19
+ },
20
+ ];
21
+
22
+ describe('ImageGallery', () => {
23
+ it('renders preview image and opens modal on click', () => {
24
+ render(<ImageGallery items={mockItems} />);
25
+
26
+ const previewImage = screen.getByRole('img', { name: /Image One/i });
27
+ expect(previewImage).toBeInTheDocument();
28
+
29
+ expect(
30
+ screen.queryByText('First image description'),
31
+ ).not.toBeInTheDocument();
32
+
33
+ fireEvent.click(previewImage);
34
+
35
+ expect(screen.getByText('Image One')).toBeInTheDocument();
36
+ expect(screen.getByText('First image description')).toBeInTheDocument();
37
+ });
38
+ });
@@ -60,9 +60,10 @@ describe('PlanningTab', () => {
60
60
  Approval_Year: '2023',
61
61
  End_Year_Of_Plan_Label: 'End Year:',
62
62
  End_Year: '2030',
63
- Name_Of_Plan_And_Hyperlink: 'http://example.com; https://plan-link.com',
63
+ Name_Of_Plan_And_Hyperlink:
64
+ 'https://example.com; https://plan-link.com',
64
65
  Further_Information_Link_Text: 'More Info',
65
- Attachment: 'http://attachment.com',
66
+ Attachment: 'https://attachment.com',
66
67
  Explore_Plan_Link_Text: 'Explore Plan',
67
68
  Sectors: ['Agriculture'],
68
69
  },
@@ -1,7 +1,7 @@
1
+ import { FormattedMessage } from 'react-intl';
1
2
  import { Message, Icon } from 'semantic-ui-react';
2
3
 
3
- const PortalMessage = (props) => {
4
- const { content } = props;
4
+ const PortalMessage = ({ content }) => {
5
5
  const { review_state } = content;
6
6
  const isArchivedContent = review_state === 'archived';
7
7
 
@@ -9,8 +9,10 @@ const PortalMessage = (props) => {
9
9
  <Message info icon>
10
10
  <Icon name="info" />
11
11
  <Message.Content>
12
- This object has been archived because its content is outdated. You can
13
- still access it as legacy.
12
+ <FormattedMessage
13
+ id="This object has been archived because its content is outdated. You can still access it as legacy."
14
+ defaultMessage="This object has been archived because its content is outdated. You can still access it as legacy."
15
+ />
14
16
  </Message.Content>
15
17
  </Message>
16
18
  ) : null;
@@ -0,0 +1,24 @@
1
+ import { render } from '@testing-library/react';
2
+ import PortalMessage from './PortalMessage';
3
+ import { IntlProvider } from 'react-intl';
4
+ import '@testing-library/jest-dom';
5
+
6
+ const renderWithIntl = (ui) =>
7
+ render(<IntlProvider locale="en">{ui}</IntlProvider>);
8
+
9
+ describe('PortalMessage', () => {
10
+ it('renders the message component when content is archived', () => {
11
+ const content = { review_state: 'archived' };
12
+ const { container } = renderWithIntl(<PortalMessage content={content} />);
13
+
14
+ const messageEl = container.querySelector('.ui.message');
15
+ expect(messageEl).toBeInTheDocument();
16
+ });
17
+
18
+ it('renders nothing when content is not archived', () => {
19
+ const content = { review_state: 'published' };
20
+ const { container } = renderWithIntl(<PortalMessage content={content} />);
21
+
22
+ expect(container).toBeEmptyDOMElement();
23
+ });
24
+ });