@eeacms/volto-cca-policy 1.0.12 → 1.0.14

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,14 @@ 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
+ ### [1.0.14](https://github.com/eea/volto-cca-policy/compare/1.0.13...1.0.14) - 1 September 2026
8
+
9
+ ### [1.0.13](https://github.com/eea/volto-cca-policy/compare/1.0.12...1.0.13) - 31 August 2026
10
+
11
+ #### :hammer_and_wrench: Others
12
+
13
+ - Refs #307245 - Visualizations: fix order in view mode. [GhitaB - [`bfbe754`](https://github.com/eea/volto-cca-policy/commit/bfbe7549af5a4f767c3d023b894b55b5eb81918e)]
14
+ - Refs #307245 - Visualizations: order and descriptions. [GhitaB - [`5fff846`](https://github.com/eea/volto-cca-policy/commit/5fff846b623250e89cbf2a844828f545c0f2f9f9)]
7
15
  ### [1.0.12](https://github.com/eea/volto-cca-policy/compare/1.0.11...1.0.12) - 24 August 2026
8
16
 
9
17
  #### :bug: Bug Fixes
@@ -301,8 +309,29 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
301
309
  #### :hammer_and_wrench: Others
302
310
 
303
311
  - test: pin Chromium version 149 to work with Cypress [valentinab25 - [`659ec82`](https://github.com/eea/volto-cca-policy/commit/659ec823dd71fe592a3a7accda22effbe1fb07bc)]
304
- ## [1.0.0](https://github.com/eea/volto-cca-policy/compare/1.0.0-alpha.24...1.0.0) - 12 June 2026
312
+ ## [1.0.0](https://github.com/eea/volto-cca-policy/compare/1.0.0-alpha.27...1.0.0) - 12 June 2026
313
+
314
+ ### [1.0.0-alpha.27](https://github.com/eea/volto-cca-policy/compare/1.0.0-alpha.26...1.0.0-alpha.27) - 31 August 2026
315
+
316
+ #### :hammer_and_wrench: Others
317
+
318
+ - Refs #307732 - Remove volto-banner override. [GhitaB - [`44250da`](https://github.com/eea/volto-cca-policy/commit/44250da7145a69be41f6a4f11c84ef7c4a62d5c9)]
319
+ ### [1.0.0-alpha.26](https://github.com/eea/volto-cca-policy/compare/1.0.0-alpha.25...1.0.0-alpha.26) - 28 August 2026
320
+
321
+ ### [1.0.0-alpha.25](https://github.com/eea/volto-cca-policy/compare/1.0.0-alpha.24...1.0.0-alpha.25) - 27 August 2026
322
+
323
+ #### :bug: Bug Fixes
324
+
325
+ - fix: disable unavailable navigator guide options [kreafox - [`4b114c2`](https://github.com/eea/volto-cca-policy/commit/4b114c2b0ea7a6a6528ae8ae378c2e671b640945)]
326
+
327
+ #### :nail_care: Enhancements
305
328
 
329
+ - change: add custom hook for guide facet options and add tests [kreafox - [`872eb9b`](https://github.com/eea/volto-cca-policy/commit/872eb9b35c41fc2094c605b113411448a8cef9a8)]
330
+
331
+ #### :hammer_and_wrench: Others
332
+
333
+ - Refs #307245 - Visualizations: order and descriptions. [GhitaB - [`5fff846`](https://github.com/eea/volto-cca-policy/commit/5fff846b623250e89cbf2a844828f545c0f2f9f9)]
334
+ - test: increase utility coverage [kreafox - [`d9c3db8`](https://github.com/eea/volto-cca-policy/commit/d9c3db8cc6fb91ead00f83b822f6fe48c26a70b1)]
306
335
  ### [1.0.0-alpha.24](https://github.com/eea/volto-cca-policy/compare/1.0.0-alpha.23...1.0.0-alpha.24) - 24 August 2026
307
336
 
308
337
  ### [1.0.0-alpha.23](https://github.com/eea/volto-cca-policy/compare/1.0.0-alpha.22...1.0.0-alpha.23) - 19 August 2026
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eeacms/volto-cca-policy",
3
- "version": "1.0.12",
3
+ "version": "1.0.14",
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",
@@ -7,6 +7,7 @@ import './visualizations.less';
7
7
 
8
8
  const emptyVisualization = {
9
9
  title: '',
10
+ description: '',
10
11
  embed_code: '',
11
12
  height: '',
12
13
  full_width: false,
@@ -43,6 +44,19 @@ const VisualizationsWidget = (props) => {
43
44
  );
44
45
  };
45
46
 
47
+ const moveItem = (index, direction) => {
48
+ const nextIndex = index + direction;
49
+
50
+ if (nextIndex < 0 || nextIndex >= visualizations.length) return;
51
+
52
+ const nextVisualizations = [...visualizations];
53
+ [nextVisualizations[index], nextVisualizations[nextIndex]] = [
54
+ nextVisualizations[nextIndex],
55
+ nextVisualizations[index],
56
+ ];
57
+ updateVisualizations(nextVisualizations);
58
+ };
59
+
46
60
  return (
47
61
  <FormFieldWrapper {...props}>
48
62
  <div className="visualizations-widget">
@@ -53,16 +67,30 @@ const VisualizationsWidget = (props) => {
53
67
  >
54
68
  <div className="visualizations-widget-item-header">
55
69
  <h4>Visualization {index + 1}</h4>
56
- <Button
57
- type="button"
58
- basic
59
- compact
60
- negative
61
- disabled={isDisabled}
62
- onClick={() => deleteItem(index)}
63
- >
64
- Delete
65
- </Button>
70
+ <Button.Group basic compact>
71
+ <Button
72
+ type="button"
73
+ disabled={isDisabled || index === 0}
74
+ onClick={() => moveItem(index, -1)}
75
+ >
76
+ Up
77
+ </Button>
78
+ <Button
79
+ type="button"
80
+ disabled={isDisabled || index === visualizations.length - 1}
81
+ onClick={() => moveItem(index, 1)}
82
+ >
83
+ Down
84
+ </Button>
85
+ <Button
86
+ type="button"
87
+ negative
88
+ disabled={isDisabled}
89
+ onClick={() => deleteItem(index)}
90
+ >
91
+ Delete
92
+ </Button>
93
+ </Button.Group>
66
94
  </div>
67
95
 
68
96
  <Form.Field>
@@ -77,6 +105,19 @@ const VisualizationsWidget = (props) => {
77
105
  />
78
106
  </Form.Field>
79
107
 
108
+ <Form.Field>
109
+ <label htmlFor={`${id}-${index}-description`}>Description</label>
110
+ <TextArea
111
+ id={`${id}-${index}-description`}
112
+ value={item.description || ''}
113
+ disabled={isDisabled}
114
+ rows={3}
115
+ onChange={(event) =>
116
+ updateItem(index, 'description', event.target.value)
117
+ }
118
+ />
119
+ </Form.Field>
120
+
80
121
  <Form.Field>
81
122
  <label htmlFor={`${id}-${index}-embed-code`}>
82
123
  Embed code or URL
@@ -22,6 +22,10 @@
22
22
  color: #1f405c;
23
23
  font-size: 1rem;
24
24
  }
25
+
26
+ .ui.buttons {
27
+ flex-shrink: 0;
28
+ }
25
29
  }
26
30
 
27
31
  .field {
@@ -107,6 +107,9 @@ const MaybeIframeVisualization = ({ visualization }) => {
107
107
  const Visualization = ({ visualization }) => (
108
108
  <>
109
109
  {visualization?.title && <h2>{visualization.title}</h2>}
110
+ {visualization?.description && (
111
+ <p className="visualization-description">{visualization.description}</p>
112
+ )}
110
113
  <MaybeFlourishVisualization visualization={visualization} />
111
114
  <MaybeIframeVisualization visualization={visualization} />
112
115
  </>
@@ -129,6 +132,20 @@ const getVisualizations = (content) => {
129
132
  : [];
130
133
  };
131
134
 
135
+ const groupVisualizations = (visualizations) =>
136
+ visualizations.reduce((groups, visualization) => {
137
+ const fullWidth = !!visualization.full_width;
138
+ const lastGroup = groups[groups.length - 1];
139
+
140
+ if (lastGroup && lastGroup.fullWidth === fullWidth) {
141
+ lastGroup.items.push(visualization);
142
+ } else {
143
+ groups.push({ fullWidth, items: [visualization] });
144
+ }
145
+
146
+ return groups;
147
+ }, []);
148
+
132
149
  const BottomInfo = (props) => {
133
150
  const { content } = props;
134
151
  const { organisational_websites, organisational_contact_information } =
@@ -185,13 +202,11 @@ const DatabaseItemView = (props) => {
185
202
  const item_title = acronym ? title + ' (' + acronym + ')' : title;
186
203
  const subtitle = CONTENT_TYPE_LABELS[type] ?? '';
187
204
  const visualizations = getVisualizations(content);
188
- const columnVisualizations = visualizations.filter(
189
- (visualization) => !visualization.full_width,
205
+ const visualizationGroups = groupVisualizations(visualizations);
206
+ const firstVisualizationGroup = visualizationGroups[0];
207
+ const hasFullWidthVisualizations = visualizationGroups.some(
208
+ (group) => group.fullWidth,
190
209
  );
191
- const fullWidthVisualizations = visualizations.filter(
192
- (visualization) => visualization.full_width,
193
- );
194
- const hasFullWidthVisualizations = !!fullWidthVisualizations.length;
195
210
 
196
211
  const is_cmshare_video = SHARE_EEA.some((domain) =>
197
212
  content?.embed_url?.includes(domain),
@@ -284,9 +299,12 @@ const DatabaseItemView = (props) => {
284
299
  </>
285
300
  )}
286
301
 
287
- {!!columnVisualizations.length && (
288
- <Visualizations visualizations={columnVisualizations} />
289
- )}
302
+ {firstVisualizationGroup &&
303
+ !firstVisualizationGroup.fullWidth && (
304
+ <Visualizations
305
+ visualizations={firstVisualizationGroup.items}
306
+ />
307
+ )}
290
308
 
291
309
  {!hasFullWidthVisualizations && <BottomInfo {...props} />}
292
310
  </Grid.Column>
@@ -304,11 +322,22 @@ const DatabaseItemView = (props) => {
304
322
 
305
323
  {hasFullWidthVisualizations && (
306
324
  <>
307
- <Grid.Row>
308
- <Grid.Column mobile={12} tablet={12} computer={12}>
309
- <Visualizations visualizations={fullWidthVisualizations} />
310
- </Grid.Column>
311
- </Grid.Row>
325
+ {visualizationGroups.map((group, index) => {
326
+ if (index === 0 && !group.fullWidth) return null;
327
+
328
+ return (
329
+ <Grid.Row key={`visualization-group-${index}`}>
330
+ <Grid.Column
331
+ mobile={12}
332
+ tablet={12}
333
+ computer={group.fullWidth ? 12 : 8}
334
+ className={group.fullWidth ? undefined : 'col-left'}
335
+ >
336
+ <Visualizations visualizations={group.items} />
337
+ </Grid.Column>
338
+ </Grid.Row>
339
+ );
340
+ })}
312
341
  <Grid.Row>
313
342
  <Grid.Column
314
343
  mobile={12}
@@ -46,6 +46,7 @@ const visualizationEmbedCode =
46
46
 
47
47
  const getVisualization = (overrides = {}) => ({
48
48
  title: '',
49
+ description: '',
49
50
  embed_code: visualizationEmbedCode,
50
51
  height: '',
51
52
  full_width: false,
@@ -125,6 +126,39 @@ describe('DatabaseItemView', () => {
125
126
  expect(fullWidthColumn.findAllByType('iframe')).toHaveLength(1);
126
127
  });
127
128
 
129
+ it('renders visualization descriptions', () => {
130
+ const component = renderDatabaseItemView({
131
+ ...baseContent,
132
+ visualizations: [
133
+ getVisualization({ description: 'Visualization summary text.' }),
134
+ ],
135
+ });
136
+
137
+ expect(
138
+ component.root.findByProps({
139
+ className: 'visualization-description',
140
+ }).children,
141
+ ).toEqual(['Visualization summary text.']);
142
+ });
143
+
144
+ it('preserves visualization order when full-width and column items are mixed', () => {
145
+ const component = renderDatabaseItemView({
146
+ ...baseContent,
147
+ visualizations: [
148
+ getVisualization({ title: 'First', full_width: true }),
149
+ getVisualization({ title: 'Second' }),
150
+ getVisualization({ title: 'Third', full_width: true }),
151
+ ],
152
+ });
153
+
154
+ const headings = component.root
155
+ .findAllByType('h2')
156
+ .map((heading) => heading.children.join(''))
157
+ .filter((title) => ['First', 'Second', 'Third'].includes(title));
158
+
159
+ expect(headings).toEqual(['First', 'Second', 'Third']);
160
+ });
161
+
128
162
  it('does not render a visualization when the visualizations field is empty', () => {
129
163
  const component = renderDatabaseItemView({
130
164
  ...baseContent,
@@ -1,5 +0,0 @@
1
- const StagingBanner = ({ banner, token, dispatch }) => {
2
- return null;
3
- };
4
-
5
- export default StagingBanner;
@@ -1,3 +0,0 @@
1
- export default function dummyConfig(config) {
2
- return config;
3
- }