@eeacms/volto-cca-policy 1.0.7 → 1.0.8
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 +42 -1
- package/package.json +1 -1
- package/src/components/manage/Widgets/VisualizationsWidget.jsx +151 -0
- package/src/components/manage/Widgets/visualizations.less +60 -0
- package/src/components/theme/Views/DatabaseItemView.jsx +65 -22
- package/src/components/theme/Views/DatabaseItemView.test.jsx +98 -38
- package/src/index.js +2 -0
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,16 @@ 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.8](https://github.com/eea/volto-cca-policy/compare/1.0.7...1.0.8) - 17 August 2026
|
|
8
|
+
|
|
9
|
+
#### :house: Internal changes
|
|
10
|
+
|
|
11
|
+
- style: Automated code fix [eea-jenkins - [`c06e6eb`](https://github.com/eea/volto-cca-policy/commit/c06e6ebc41cbe2bb80a9c8472d57fd361fe09dab)]
|
|
12
|
+
|
|
13
|
+
#### :hammer_and_wrench: Others
|
|
14
|
+
|
|
15
|
+
- Refs #307245 - Add test for visualizations. [GhitaB - [`15d7a0b`](https://github.com/eea/volto-cca-policy/commit/15d7a0bc514e6ac09bbec19303e42ceb120647dc)]
|
|
16
|
+
- Refs #307245 - Allow indicators to support multiple visualizations. [GhitaB - [`b7a0b7f`](https://github.com/eea/volto-cca-policy/commit/b7a0b7fe9db40a9d9a1847eb71a95a8f2245dd5e)]
|
|
7
17
|
### [1.0.7](https://github.com/eea/volto-cca-policy/compare/1.0.6...1.0.7) - 14 August 2026
|
|
8
18
|
|
|
9
19
|
#### :rocket: Dependency updates
|
|
@@ -233,8 +243,39 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
|
|
|
233
243
|
#### :hammer_and_wrench: Others
|
|
234
244
|
|
|
235
245
|
- test: pin Chromium version 149 to work with Cypress [valentinab25 - [`659ec82`](https://github.com/eea/volto-cca-policy/commit/659ec823dd71fe592a3a7accda22effbe1fb07bc)]
|
|
236
|
-
## [1.0.0](https://github.com/eea/volto-cca-policy/compare/1.0.0-alpha.
|
|
246
|
+
## [1.0.0](https://github.com/eea/volto-cca-policy/compare/1.0.0-alpha.18...1.0.0) - 12 June 2026
|
|
247
|
+
|
|
248
|
+
### [1.0.0-alpha.18](https://github.com/eea/volto-cca-policy/compare/1.0.0-alpha.17...1.0.0-alpha.18) - 13 August 2026
|
|
249
|
+
|
|
250
|
+
#### :rocket: Dependency updates
|
|
251
|
+
|
|
252
|
+
- Release @eeacms/volto-globalsearch@4.1.1 [EEA Jenkins - [`f34f23c`](https://github.com/eea/volto-cca-policy/commit/f34f23c587f32930acd4316d43f2f64fd9338764)]
|
|
253
|
+
- Release @eeacms/volto-globalsearch@4.1.0 [EEA Jenkins - [`5d7ddd2`](https://github.com/eea/volto-cca-policy/commit/5d7ddd2cf7a371007a569d185690d655c2c4b2d2)]
|
|
254
|
+
|
|
255
|
+
#### :bug: Bug Fixes
|
|
256
|
+
|
|
257
|
+
- fix: update import [kreafox - [`5e98924`](https://github.com/eea/volto-cca-policy/commit/5e9892488dd84e2e280d29905f4471af4f5403be)]
|
|
258
|
+
- fix: imports in GovernanceTab [kreafox - [`c1eb09f`](https://github.com/eea/volto-cca-policy/commit/c1eb09fd59e730fa15c71fd73f625f9811fd98fa)]
|
|
259
|
+
- fix: improve geochars parsing, and enhance capitalizeFirstLetter function [kreafox - [`370deb6`](https://github.com/eea/volto-cca-policy/commit/370deb6395872c4229c0747077f845f8d8375336)]
|
|
237
260
|
|
|
261
|
+
#### :nail_care: Enhancements
|
|
262
|
+
|
|
263
|
+
- refactor: remove unused export of euCountryNamesEnergy from helpers [kreafox - [`5c40276`](https://github.com/eea/volto-cca-policy/commit/5c40276f491e4b3a24de8ebe29e8fdc0d0d2fe57)]
|
|
264
|
+
- refactor: change exported components to default exports in ImageWidget, countryMap, and queryUtils [kreafox - [`43ce27c`](https://github.com/eea/volto-cca-policy/commit/43ce27c9af8f036e34d5ccefe185fa138fa6f823)]
|
|
265
|
+
- refactor: replace clientOnly HOC with withClientOnly and reorganize helper imports [kreafox - [`5e326f3`](https://github.com/eea/volto-cca-policy/commit/5e326f378af2ba784e7f8b4499a28500a04031b5)]
|
|
266
|
+
- refactor: reorganize content sections, views, and widgets [kreafox - [`4ff70ec`](https://github.com/eea/volto-cca-policy/commit/4ff70ec1a763071ace8292eeac6d2f0d692580cb)]
|
|
267
|
+
- refactor: shared content view components into reusable theme modules [kreafox - [`e0f1906`](https://github.com/eea/volto-cca-policy/commit/e0f190606acc8ab74dfad147f751451d1e8f38eb)]
|
|
268
|
+
|
|
269
|
+
#### :house: Internal changes
|
|
270
|
+
|
|
271
|
+
- style: Automated code fix [eea-jenkins - [`c06e6eb`](https://github.com/eea/volto-cca-policy/commit/c06e6ebc41cbe2bb80a9c8472d57fd361fe09dab)]
|
|
272
|
+
|
|
273
|
+
#### :hammer_and_wrench: Others
|
|
274
|
+
|
|
275
|
+
- Refs #307245 - Allow indicators to support multiple visualizations. [GhitaB - [`b7a0b7f`](https://github.com/eea/volto-cca-policy/commit/b7a0b7fe9db40a9d9a1847eb71a95a8f2245dd5e)]
|
|
276
|
+
- test: increase coverage for ImageWidget [kreafox - [`5fd74bf`](https://github.com/eea/volto-cca-policy/commit/5fd74bfe00db49e4977a64871de3144a7247415d)]
|
|
277
|
+
- core: update locales [kreafox - [`f1ba2dd`](https://github.com/eea/volto-cca-policy/commit/f1ba2dd01269d42da4cdeb948951b65857a05e3d)]
|
|
278
|
+
- core: update locales [kreafox - [`122817e`](https://github.com/eea/volto-cca-policy/commit/122817ea9f6f0084fe8cb697ccfaffb8a9fe833d)]
|
|
238
279
|
### [1.0.0-alpha.17](https://github.com/eea/volto-cca-policy/compare/1.0.0-alpha.16...1.0.0-alpha.17) - 4 August 2026
|
|
239
280
|
|
|
240
281
|
#### :rocket: New Features
|
package/package.json
CHANGED
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import PropTypes from 'prop-types';
|
|
3
|
+
import { Button, Checkbox, Form, Input, TextArea } from 'semantic-ui-react';
|
|
4
|
+
import FormFieldWrapper from '@plone/volto/components/manage/Widgets/FormFieldWrapper';
|
|
5
|
+
|
|
6
|
+
import './visualizations.less';
|
|
7
|
+
|
|
8
|
+
const emptyVisualization = {
|
|
9
|
+
title: '',
|
|
10
|
+
embed_code: '',
|
|
11
|
+
height: '',
|
|
12
|
+
full_width: false,
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
const normalizeVisualizations = (value) =>
|
|
16
|
+
Array.isArray(value)
|
|
17
|
+
? value.map((item) => ({ ...emptyVisualization, ...(item || {}) }))
|
|
18
|
+
: [];
|
|
19
|
+
|
|
20
|
+
const VisualizationsWidget = (props) => {
|
|
21
|
+
const { id, value, onChange, isDisabled } = props;
|
|
22
|
+
const visualizations = normalizeVisualizations(value);
|
|
23
|
+
|
|
24
|
+
const updateVisualizations = (nextValue) => {
|
|
25
|
+
onChange(id, nextValue);
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
const updateItem = (index, field, fieldValue) => {
|
|
29
|
+
updateVisualizations(
|
|
30
|
+
visualizations.map((item, itemIndex) =>
|
|
31
|
+
itemIndex === index ? { ...item, [field]: fieldValue } : item,
|
|
32
|
+
),
|
|
33
|
+
);
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
const addItem = () => {
|
|
37
|
+
updateVisualizations([...visualizations, { ...emptyVisualization }]);
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
const deleteItem = (index) => {
|
|
41
|
+
updateVisualizations(
|
|
42
|
+
visualizations.filter((_, itemIndex) => itemIndex !== index),
|
|
43
|
+
);
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
return (
|
|
47
|
+
<FormFieldWrapper {...props}>
|
|
48
|
+
<div className="visualizations-widget">
|
|
49
|
+
{visualizations.map((item, index) => (
|
|
50
|
+
<div
|
|
51
|
+
className="visualizations-widget-item"
|
|
52
|
+
key={`visualization-${index}`}
|
|
53
|
+
>
|
|
54
|
+
<div className="visualizations-widget-item-header">
|
|
55
|
+
<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>
|
|
66
|
+
</div>
|
|
67
|
+
|
|
68
|
+
<Form.Field>
|
|
69
|
+
<label htmlFor={`${id}-${index}-title`}>Title</label>
|
|
70
|
+
<Input
|
|
71
|
+
id={`${id}-${index}-title`}
|
|
72
|
+
value={item.title || ''}
|
|
73
|
+
disabled={isDisabled}
|
|
74
|
+
onChange={(event) =>
|
|
75
|
+
updateItem(index, 'title', event.target.value)
|
|
76
|
+
}
|
|
77
|
+
/>
|
|
78
|
+
</Form.Field>
|
|
79
|
+
|
|
80
|
+
<Form.Field>
|
|
81
|
+
<label htmlFor={`${id}-${index}-embed-code`}>
|
|
82
|
+
Embed code or URL
|
|
83
|
+
</label>
|
|
84
|
+
<TextArea
|
|
85
|
+
id={`${id}-${index}-embed-code`}
|
|
86
|
+
value={item.embed_code || ''}
|
|
87
|
+
disabled={isDisabled}
|
|
88
|
+
rows={5}
|
|
89
|
+
onChange={(event) =>
|
|
90
|
+
updateItem(index, 'embed_code', event.target.value)
|
|
91
|
+
}
|
|
92
|
+
/>
|
|
93
|
+
</Form.Field>
|
|
94
|
+
|
|
95
|
+
<Form.Group widths="equal">
|
|
96
|
+
<Form.Field className="visualizations-widget-height">
|
|
97
|
+
<label htmlFor={`${id}-${index}-height`}>Height</label>
|
|
98
|
+
<Input
|
|
99
|
+
id={`${id}-${index}-height`}
|
|
100
|
+
value={item.height || ''}
|
|
101
|
+
disabled={isDisabled}
|
|
102
|
+
placeholder="800"
|
|
103
|
+
onChange={(event) =>
|
|
104
|
+
updateItem(index, 'height', event.target.value)
|
|
105
|
+
}
|
|
106
|
+
/>
|
|
107
|
+
</Form.Field>
|
|
108
|
+
|
|
109
|
+
<Form.Field className="visualizations-widget-layout">
|
|
110
|
+
<label>Layout</label>
|
|
111
|
+
<Checkbox
|
|
112
|
+
label="Full width"
|
|
113
|
+
checked={!!item.full_width}
|
|
114
|
+
disabled={isDisabled}
|
|
115
|
+
onChange={(_, data) =>
|
|
116
|
+
updateItem(index, 'full_width', data.checked)
|
|
117
|
+
}
|
|
118
|
+
/>
|
|
119
|
+
</Form.Field>
|
|
120
|
+
</Form.Group>
|
|
121
|
+
</div>
|
|
122
|
+
))}
|
|
123
|
+
|
|
124
|
+
<Button
|
|
125
|
+
type="button"
|
|
126
|
+
basic
|
|
127
|
+
compact
|
|
128
|
+
primary
|
|
129
|
+
disabled={isDisabled}
|
|
130
|
+
onClick={addItem}
|
|
131
|
+
>
|
|
132
|
+
Add visualization
|
|
133
|
+
</Button>
|
|
134
|
+
</div>
|
|
135
|
+
</FormFieldWrapper>
|
|
136
|
+
);
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
VisualizationsWidget.propTypes = {
|
|
140
|
+
id: PropTypes.string.isRequired,
|
|
141
|
+
value: PropTypes.arrayOf(PropTypes.object),
|
|
142
|
+
onChange: PropTypes.func.isRequired,
|
|
143
|
+
isDisabled: PropTypes.bool,
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
VisualizationsWidget.defaultProps = {
|
|
147
|
+
value: [],
|
|
148
|
+
isDisabled: false,
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
export default VisualizationsWidget;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
.visualizations-widget {
|
|
2
|
+
max-width: 760px;
|
|
3
|
+
|
|
4
|
+
.visualizations-widget-item {
|
|
5
|
+
padding: 1.25rem;
|
|
6
|
+
border: 1px solid #d8d8d8;
|
|
7
|
+
margin-bottom: 1rem;
|
|
8
|
+
background: #fff;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
.visualizations-widget-item-header {
|
|
12
|
+
display: flex;
|
|
13
|
+
align-items: center;
|
|
14
|
+
justify-content: space-between;
|
|
15
|
+
padding-bottom: 0.75rem;
|
|
16
|
+
border-bottom: 1px solid #e6e6e6;
|
|
17
|
+
margin-bottom: 1rem;
|
|
18
|
+
gap: 1rem;
|
|
19
|
+
|
|
20
|
+
h4 {
|
|
21
|
+
margin: 0;
|
|
22
|
+
color: #1f405c;
|
|
23
|
+
font-size: 1rem;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
.field {
|
|
28
|
+
margin-bottom: 1rem;
|
|
29
|
+
|
|
30
|
+
> label {
|
|
31
|
+
display: block;
|
|
32
|
+
margin-bottom: 0.35rem;
|
|
33
|
+
color: #1f405c;
|
|
34
|
+
font-weight: 700;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.ui.input,
|
|
39
|
+
textarea {
|
|
40
|
+
width: 100%;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
textarea {
|
|
44
|
+
min-height: 8rem;
|
|
45
|
+
resize: vertical;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
.fields {
|
|
49
|
+
align-items: flex-end;
|
|
50
|
+
margin-bottom: 0;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
.visualizations-widget-height {
|
|
54
|
+
max-width: 180px;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
.visualizations-widget-layout {
|
|
58
|
+
padding-bottom: 0.55rem;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
@@ -32,12 +32,16 @@ import {
|
|
|
32
32
|
|
|
33
33
|
const SHARE_EEA = ['https://cmshare.eea.eu', 'shareit.eea.europa.eu'];
|
|
34
34
|
|
|
35
|
-
const
|
|
36
|
-
|
|
35
|
+
const getVisualizationEmbedCode = (visualization) =>
|
|
36
|
+
visualization?.embed_code || visualization?.map_graphs || '';
|
|
37
37
|
|
|
38
|
+
const MaybeFlourishVisualization = ({ visualization }) => {
|
|
39
|
+
const embedCode = getVisualizationEmbedCode(visualization);
|
|
38
40
|
// https://helpcenter.flourish.studio/hc/en-us/articles/8761537208463-How-to-embed-Flourish-charts-in-your-CMS
|
|
39
|
-
const flourishPath = getDataSrcFromEmbedCode(
|
|
41
|
+
const flourishPath = getDataSrcFromEmbedCode(embedCode);
|
|
40
42
|
const flourishUrl = buildFlourishUrl(flourishPath);
|
|
43
|
+
const height = visualization?.height || '980';
|
|
44
|
+
const title = visualization?.title || 'Interactive or visual content';
|
|
41
45
|
|
|
42
46
|
return !!flourishPath ? (
|
|
43
47
|
<PrivacyProtection
|
|
@@ -47,10 +51,10 @@ const MaybeFlourishVisualization = ({ content }) => {
|
|
|
47
51
|
}}
|
|
48
52
|
>
|
|
49
53
|
<iframe
|
|
50
|
-
height=
|
|
54
|
+
height={height}
|
|
51
55
|
width="100%"
|
|
52
56
|
src={flourishUrl}
|
|
53
|
-
title=
|
|
57
|
+
title={title}
|
|
54
58
|
className="flourish-embed-iframe"
|
|
55
59
|
sandbox="allow-same-origin allow-forms allow-scripts allow-downloads allow-popups allow-popups-to-escape-sandbox allow-top-navigation-by-user-activation"
|
|
56
60
|
></iframe>
|
|
@@ -73,10 +77,11 @@ function getFirstIframeSrc(htmlString) {
|
|
|
73
77
|
}
|
|
74
78
|
}
|
|
75
79
|
|
|
76
|
-
const MaybeIframeVisualization = ({
|
|
77
|
-
const
|
|
78
|
-
const url = getFirstIframeSrc(
|
|
79
|
-
const height =
|
|
80
|
+
const MaybeIframeVisualization = ({ visualization }) => {
|
|
81
|
+
const embedCode = getVisualizationEmbedCode(visualization);
|
|
82
|
+
const url = getFirstIframeSrc(embedCode);
|
|
83
|
+
const height = visualization?.height || 800;
|
|
84
|
+
const title = visualization?.title || 'Interactive or visual content';
|
|
80
85
|
const [isClient, setIsClient] = React.useState();
|
|
81
86
|
|
|
82
87
|
React.useEffect(() => setIsClient(true), []);
|
|
@@ -94,7 +99,7 @@ const MaybeIframeVisualization = ({ content }) => {
|
|
|
94
99
|
height={height}
|
|
95
100
|
width="100%"
|
|
96
101
|
src={url}
|
|
97
|
-
title=
|
|
102
|
+
title={title}
|
|
98
103
|
className="flourish-embed-iframe"
|
|
99
104
|
sandbox="allow-same-origin allow-forms allow-scripts allow-downloads allow-popups allow-popups-to-escape-sandbox allow-top-navigation-by-user-activation"
|
|
100
105
|
></iframe>
|
|
@@ -102,6 +107,43 @@ const MaybeIframeVisualization = ({ content }) => {
|
|
|
102
107
|
);
|
|
103
108
|
};
|
|
104
109
|
|
|
110
|
+
const Visualization = ({ visualization }) => (
|
|
111
|
+
<>
|
|
112
|
+
{visualization?.title && <h2>{visualization.title}</h2>}
|
|
113
|
+
<MaybeFlourishVisualization visualization={visualization} />
|
|
114
|
+
<MaybeIframeVisualization visualization={visualization} />
|
|
115
|
+
</>
|
|
116
|
+
);
|
|
117
|
+
|
|
118
|
+
const Visualizations = ({ visualizations }) => (
|
|
119
|
+
<>
|
|
120
|
+
{visualizations.map((visualization, index) => (
|
|
121
|
+
<Visualization
|
|
122
|
+
key={`visualization-${index}`}
|
|
123
|
+
visualization={visualization}
|
|
124
|
+
/>
|
|
125
|
+
))}
|
|
126
|
+
</>
|
|
127
|
+
);
|
|
128
|
+
|
|
129
|
+
const getVisualizations = (content) => {
|
|
130
|
+
const visualizations = Array.isArray(content?.visualizations)
|
|
131
|
+
? content.visualizations.filter((item) => item?.embed_code)
|
|
132
|
+
: [];
|
|
133
|
+
|
|
134
|
+
return content?.map_graphs
|
|
135
|
+
? [
|
|
136
|
+
...visualizations,
|
|
137
|
+
{
|
|
138
|
+
title: '',
|
|
139
|
+
embed_code: content.map_graphs,
|
|
140
|
+
height: content.map_graphs_height,
|
|
141
|
+
full_width: content.map_graphs_full_width,
|
|
142
|
+
},
|
|
143
|
+
]
|
|
144
|
+
: visualizations;
|
|
145
|
+
};
|
|
146
|
+
|
|
105
147
|
const BottomInfo = (props) => {
|
|
106
148
|
const { content } = props;
|
|
107
149
|
const { organisational_websites, organisational_contact_information } =
|
|
@@ -157,9 +199,14 @@ const DatabaseItemView = (props) => {
|
|
|
157
199
|
} = content;
|
|
158
200
|
const item_title = acronym ? title + ' (' + acronym + ')' : title;
|
|
159
201
|
const subtitle = CONTENT_TYPE_LABELS[type] ?? '';
|
|
160
|
-
const
|
|
161
|
-
const
|
|
162
|
-
|
|
202
|
+
const visualizations = getVisualizations(content);
|
|
203
|
+
const columnVisualizations = visualizations.filter(
|
|
204
|
+
(visualization) => !visualization.full_width,
|
|
205
|
+
);
|
|
206
|
+
const fullWidthVisualizations = visualizations.filter(
|
|
207
|
+
(visualization) => visualization.full_width,
|
|
208
|
+
);
|
|
209
|
+
const hasFullWidthVisualizations = !!fullWidthVisualizations.length;
|
|
163
210
|
|
|
164
211
|
const is_cmshare_video = SHARE_EEA.some((domain) =>
|
|
165
212
|
content?.embed_url?.includes(domain),
|
|
@@ -252,14 +299,11 @@ const DatabaseItemView = (props) => {
|
|
|
252
299
|
</>
|
|
253
300
|
)}
|
|
254
301
|
|
|
255
|
-
{
|
|
256
|
-
|
|
257
|
-
<MaybeFlourishVisualization {...props} />
|
|
258
|
-
<MaybeIframeVisualization {...props} />
|
|
259
|
-
</>
|
|
302
|
+
{!!columnVisualizations.length && (
|
|
303
|
+
<Visualizations visualizations={columnVisualizations} />
|
|
260
304
|
)}
|
|
261
305
|
|
|
262
|
-
{!
|
|
306
|
+
{!hasFullWidthVisualizations && <BottomInfo {...props} />}
|
|
263
307
|
</Grid.Column>
|
|
264
308
|
|
|
265
309
|
<Grid.Column
|
|
@@ -273,12 +317,11 @@ const DatabaseItemView = (props) => {
|
|
|
273
317
|
</Grid.Column>
|
|
274
318
|
</Grid.Row>
|
|
275
319
|
|
|
276
|
-
{
|
|
320
|
+
{hasFullWidthVisualizations && (
|
|
277
321
|
<>
|
|
278
322
|
<Grid.Row>
|
|
279
323
|
<Grid.Column mobile={12} tablet={12} computer={12}>
|
|
280
|
-
<
|
|
281
|
-
<MaybeIframeVisualization {...props} />
|
|
324
|
+
<Visualizations visualizations={fullWidthVisualizations} />
|
|
282
325
|
</Grid.Column>
|
|
283
326
|
</Grid.Row>
|
|
284
327
|
<Grid.Row>
|
|
@@ -17,6 +17,58 @@ config.blocks = {
|
|
|
17
17
|
|
|
18
18
|
const mockStore = configureStore();
|
|
19
19
|
|
|
20
|
+
const baseContent = {
|
|
21
|
+
title: 'My DatabaseItemView',
|
|
22
|
+
long_description: {
|
|
23
|
+
'content-type': null,
|
|
24
|
+
data: '<p>Nam commodo suscipit quam. Praesent egestas neque eu enim. Quisque rutrum.</p>',
|
|
25
|
+
encoding: 'utf-8',
|
|
26
|
+
},
|
|
27
|
+
publication_date: '2022-06-24',
|
|
28
|
+
geochars:
|
|
29
|
+
'{\r\n "geoElements":{"element":"GLOBAL",\r\n "macrotrans":null,"biotrans":null,"countries":[],\r\n "subnational":[],"city":""}}',
|
|
30
|
+
keywords: ['keyword 1', 'keyword 2'],
|
|
31
|
+
websites: ['https://example.org/'],
|
|
32
|
+
contributions: [
|
|
33
|
+
{
|
|
34
|
+
title: 'Contributor 1',
|
|
35
|
+
url: '/contributor-1',
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
title: 'Contributor 2',
|
|
39
|
+
url: '/contributor-2',
|
|
40
|
+
},
|
|
41
|
+
],
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
const visualizationEmbedCode =
|
|
45
|
+
'<div class="flourish-embed" data-src="visualisation/12345"></div>';
|
|
46
|
+
|
|
47
|
+
const renderDatabaseItemView = (content = baseContent) => {
|
|
48
|
+
const store = mockStore({
|
|
49
|
+
userSession: { token: '1234' },
|
|
50
|
+
intl: {
|
|
51
|
+
locale: 'en',
|
|
52
|
+
messages: {},
|
|
53
|
+
},
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
return renderer.create(
|
|
57
|
+
<Provider store={store}>
|
|
58
|
+
<MemoryRouter>
|
|
59
|
+
<DatabaseItemView content={content} />
|
|
60
|
+
</MemoryRouter>
|
|
61
|
+
</Provider>,
|
|
62
|
+
);
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
const findColumnByClassName = (component, className) =>
|
|
66
|
+
component.root.findAll(
|
|
67
|
+
(node) =>
|
|
68
|
+
typeof node.props.className === 'string' &&
|
|
69
|
+
node.props.className.includes(className),
|
|
70
|
+
)[0];
|
|
71
|
+
|
|
20
72
|
jest.mock('semantic-ui-react', () => ({
|
|
21
73
|
...jest.requireActual('semantic-ui-react'),
|
|
22
74
|
}));
|
|
@@ -29,46 +81,54 @@ jest.mock('@eeacms/volto-embed', () => {
|
|
|
29
81
|
|
|
30
82
|
describe('DatabaseItemView', () => {
|
|
31
83
|
it('should render the component', () => {
|
|
32
|
-
const
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
'{\r\n "geoElements":{"element":"GLOBAL",\r\n "macrotrans":null,"biotrans":null,"countries":[],\r\n "subnational":[],"city":""}}',
|
|
42
|
-
keywords: ['keyword 1', 'keyword 2'],
|
|
43
|
-
websites: ['https://example.org/'],
|
|
44
|
-
contributions: [
|
|
45
|
-
{
|
|
46
|
-
title: 'Contributor 1',
|
|
47
|
-
url: '/contributor-1',
|
|
48
|
-
},
|
|
49
|
-
{
|
|
50
|
-
title: 'Contributor 2',
|
|
51
|
-
url: '/contributor-2',
|
|
52
|
-
},
|
|
53
|
-
],
|
|
54
|
-
};
|
|
55
|
-
|
|
56
|
-
const store = mockStore({
|
|
57
|
-
userSession: { token: '1234' },
|
|
58
|
-
intl: {
|
|
59
|
-
locale: 'en',
|
|
60
|
-
messages: {},
|
|
61
|
-
},
|
|
84
|
+
const component = renderDatabaseItemView();
|
|
85
|
+
const json = component.toJSON();
|
|
86
|
+
expect(json).toMatchSnapshot();
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
it('renders the visualizations field in the left column by default', () => {
|
|
90
|
+
const component = renderDatabaseItemView({
|
|
91
|
+
...baseContent,
|
|
92
|
+
map_graphs: visualizationEmbedCode,
|
|
62
93
|
});
|
|
94
|
+
const colLeft = findColumnByClassName(component, 'col-left');
|
|
95
|
+
const fullWidthColumns = component.root.findAll(
|
|
96
|
+
(node) => node.props.computer === 12,
|
|
97
|
+
);
|
|
63
98
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
<DatabaseItemView content={content} />
|
|
68
|
-
</MemoryRouter>
|
|
69
|
-
</Provider>,
|
|
99
|
+
expect(colLeft.findAllByType('iframe')).toHaveLength(1);
|
|
100
|
+
expect(component.root.findByType('iframe').props.src).toBe(
|
|
101
|
+
'https://flo.uri.sh/visualisation/12345/embed',
|
|
70
102
|
);
|
|
71
|
-
|
|
72
|
-
|
|
103
|
+
expect(fullWidthColumns).toHaveLength(0);
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
it('renders the visualizations field full width when enabled', () => {
|
|
107
|
+
const component = renderDatabaseItemView({
|
|
108
|
+
...baseContent,
|
|
109
|
+
map_graphs: visualizationEmbedCode,
|
|
110
|
+
map_graphs_full_width: true,
|
|
111
|
+
});
|
|
112
|
+
const colLeft = findColumnByClassName(component, 'col-left');
|
|
113
|
+
const fullWidthColumn = component.root.findAll(
|
|
114
|
+
(node) => node.props.computer === 12,
|
|
115
|
+
)[0];
|
|
116
|
+
|
|
117
|
+
expect(colLeft.findAllByType('iframe')).toHaveLength(0);
|
|
118
|
+
expect(fullWidthColumn.findAllByType('iframe')).toHaveLength(1);
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
it('does not render a visualization when the visualizations field is empty', () => {
|
|
122
|
+
const component = renderDatabaseItemView({
|
|
123
|
+
...baseContent,
|
|
124
|
+
map_graphs: '',
|
|
125
|
+
map_graphs_full_width: true,
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
expect(component.root.findAllByType('iframe')).toHaveLength(0);
|
|
129
|
+
const fullWidthColumns = component.root.findAll(
|
|
130
|
+
(node) => node.props.computer === 12,
|
|
131
|
+
);
|
|
132
|
+
expect(fullWidthColumns).toHaveLength(0);
|
|
73
133
|
});
|
|
74
134
|
});
|
package/src/index.js
CHANGED
|
@@ -48,6 +48,7 @@ import {
|
|
|
48
48
|
|
|
49
49
|
import GeocharsWidget from './components/manage/Widgets/GeocharsWidget';
|
|
50
50
|
import PromotionalImageWidget from './components/manage/Widgets/PromotionalImageWidget';
|
|
51
|
+
import VisualizationsWidget from './components/manage/Widgets/VisualizationsWidget';
|
|
51
52
|
import HealthHorizontalCardItem from './components/Search/Result/HealthHorizontalCardItem';
|
|
52
53
|
import ClusterHorizontalCardItem from './components/Search/Result/ClusterHorizontalCardItem';
|
|
53
54
|
import NavigatorCatalogueCardItem from './components/Search/NavigatorCatalogue/NavigatorCatalogueCardItem';
|
|
@@ -443,6 +444,7 @@ const applyConfig = (config) => {
|
|
|
443
444
|
config.widgets.id.geochars = GeocharsWidget;
|
|
444
445
|
config.widgets.id.geolocation = GeolocationWidget;
|
|
445
446
|
config.widgets.id.promotional_image = PromotionalImageWidget;
|
|
447
|
+
config.widgets.id.visualizations = VisualizationsWidget;
|
|
446
448
|
config.widgets.id.image = ImageWidget;
|
|
447
449
|
|
|
448
450
|
if (config.widgets.views?.widget) {
|