@eeacms/volto-cca-policy 1.0.7 → 1.0.9
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 +48 -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 +51 -23
- package/src/components/theme/Views/DatabaseItemView.test.jsx +104 -38
- package/src/index.js +2 -0
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,18 @@ 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.9](https://github.com/eea/volto-cca-policy/compare/1.0.8...1.0.9) - 18 August 2026
|
|
8
|
+
|
|
9
|
+
### [1.0.8](https://github.com/eea/volto-cca-policy/compare/1.0.7...1.0.8) - 17 August 2026
|
|
10
|
+
|
|
11
|
+
#### :house: Internal changes
|
|
12
|
+
|
|
13
|
+
- style: Automated code fix [eea-jenkins - [`c06e6eb`](https://github.com/eea/volto-cca-policy/commit/c06e6ebc41cbe2bb80a9c8472d57fd361fe09dab)]
|
|
14
|
+
|
|
15
|
+
#### :hammer_and_wrench: Others
|
|
16
|
+
|
|
17
|
+
- Refs #307245 - Add test for visualizations. [GhitaB - [`15d7a0b`](https://github.com/eea/volto-cca-policy/commit/15d7a0bc514e6ac09bbec19303e42ceb120647dc)]
|
|
18
|
+
- Refs #307245 - Allow indicators to support multiple visualizations. [GhitaB - [`b7a0b7f`](https://github.com/eea/volto-cca-policy/commit/b7a0b7fe9db40a9d9a1847eb71a95a8f2245dd5e)]
|
|
7
19
|
### [1.0.7](https://github.com/eea/volto-cca-policy/compare/1.0.6...1.0.7) - 14 August 2026
|
|
8
20
|
|
|
9
21
|
#### :rocket: Dependency updates
|
|
@@ -233,8 +245,43 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
|
|
|
233
245
|
#### :hammer_and_wrench: Others
|
|
234
246
|
|
|
235
247
|
- 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.
|
|
248
|
+
## [1.0.0](https://github.com/eea/volto-cca-policy/compare/1.0.0-alpha.20...1.0.0) - 12 June 2026
|
|
249
|
+
|
|
250
|
+
### [1.0.0-alpha.20](https://github.com/eea/volto-cca-policy/compare/1.0.0-alpha.19...1.0.0-alpha.20) - 18 August 2026
|
|
251
|
+
|
|
252
|
+
### [1.0.0-alpha.19](https://github.com/eea/volto-cca-policy/compare/1.0.0-alpha.18...1.0.0-alpha.19) - 18 August 2026
|
|
253
|
+
|
|
254
|
+
### [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
|
|
255
|
+
|
|
256
|
+
#### :rocket: Dependency updates
|
|
257
|
+
|
|
258
|
+
- Release @eeacms/volto-globalsearch@4.1.1 [EEA Jenkins - [`f34f23c`](https://github.com/eea/volto-cca-policy/commit/f34f23c587f32930acd4316d43f2f64fd9338764)]
|
|
259
|
+
- Release @eeacms/volto-globalsearch@4.1.0 [EEA Jenkins - [`5d7ddd2`](https://github.com/eea/volto-cca-policy/commit/5d7ddd2cf7a371007a569d185690d655c2c4b2d2)]
|
|
260
|
+
|
|
261
|
+
#### :bug: Bug Fixes
|
|
262
|
+
|
|
263
|
+
- fix: update import [kreafox - [`5e98924`](https://github.com/eea/volto-cca-policy/commit/5e9892488dd84e2e280d29905f4471af4f5403be)]
|
|
264
|
+
- fix: imports in GovernanceTab [kreafox - [`c1eb09f`](https://github.com/eea/volto-cca-policy/commit/c1eb09fd59e730fa15c71fd73f625f9811fd98fa)]
|
|
265
|
+
- fix: improve geochars parsing, and enhance capitalizeFirstLetter function [kreafox - [`370deb6`](https://github.com/eea/volto-cca-policy/commit/370deb6395872c4229c0747077f845f8d8375336)]
|
|
266
|
+
|
|
267
|
+
#### :nail_care: Enhancements
|
|
268
|
+
|
|
269
|
+
- refactor: remove unused export of euCountryNamesEnergy from helpers [kreafox - [`5c40276`](https://github.com/eea/volto-cca-policy/commit/5c40276f491e4b3a24de8ebe29e8fdc0d0d2fe57)]
|
|
270
|
+
- refactor: change exported components to default exports in ImageWidget, countryMap, and queryUtils [kreafox - [`43ce27c`](https://github.com/eea/volto-cca-policy/commit/43ce27c9af8f036e34d5ccefe185fa138fa6f823)]
|
|
271
|
+
- refactor: replace clientOnly HOC with withClientOnly and reorganize helper imports [kreafox - [`5e326f3`](https://github.com/eea/volto-cca-policy/commit/5e326f378af2ba784e7f8b4499a28500a04031b5)]
|
|
272
|
+
- refactor: reorganize content sections, views, and widgets [kreafox - [`4ff70ec`](https://github.com/eea/volto-cca-policy/commit/4ff70ec1a763071ace8292eeac6d2f0d692580cb)]
|
|
273
|
+
- refactor: shared content view components into reusable theme modules [kreafox - [`e0f1906`](https://github.com/eea/volto-cca-policy/commit/e0f190606acc8ab74dfad147f751451d1e8f38eb)]
|
|
274
|
+
|
|
275
|
+
#### :house: Internal changes
|
|
237
276
|
|
|
277
|
+
- style: Automated code fix [eea-jenkins - [`c06e6eb`](https://github.com/eea/volto-cca-policy/commit/c06e6ebc41cbe2bb80a9c8472d57fd361fe09dab)]
|
|
278
|
+
|
|
279
|
+
#### :hammer_and_wrench: Others
|
|
280
|
+
|
|
281
|
+
- Refs #307245 - Allow indicators to support multiple visualizations. [GhitaB - [`b7a0b7f`](https://github.com/eea/volto-cca-policy/commit/b7a0b7fe9db40a9d9a1847eb71a95a8f2245dd5e)]
|
|
282
|
+
- test: increase coverage for ImageWidget [kreafox - [`5fd74bf`](https://github.com/eea/volto-cca-policy/commit/5fd74bfe00db49e4977a64871de3144a7247415d)]
|
|
283
|
+
- core: update locales [kreafox - [`f1ba2dd`](https://github.com/eea/volto-cca-policy/commit/f1ba2dd01269d42da4cdeb948951b65857a05e3d)]
|
|
284
|
+
- core: update locales [kreafox - [`122817e`](https://github.com/eea/volto-cca-policy/commit/122817ea9f6f0084fe8cb697ccfaffb8a9fe833d)]
|
|
238
285
|
### [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
286
|
|
|
240
287
|
#### :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,13 @@ import {
|
|
|
32
32
|
|
|
33
33
|
const SHARE_EEA = ['https://cmshare.eea.eu', 'shareit.eea.europa.eu'];
|
|
34
34
|
|
|
35
|
-
const MaybeFlourishVisualization = ({
|
|
36
|
-
const
|
|
37
|
-
|
|
35
|
+
const MaybeFlourishVisualization = ({ visualization }) => {
|
|
36
|
+
const embedCode = visualization?.embed_code || '';
|
|
38
37
|
// https://helpcenter.flourish.studio/hc/en-us/articles/8761537208463-How-to-embed-Flourish-charts-in-your-CMS
|
|
39
|
-
const flourishPath = getDataSrcFromEmbedCode(
|
|
38
|
+
const flourishPath = getDataSrcFromEmbedCode(embedCode);
|
|
40
39
|
const flourishUrl = buildFlourishUrl(flourishPath);
|
|
40
|
+
const height = visualization?.height || '980';
|
|
41
|
+
const title = visualization?.title || 'Interactive or visual content';
|
|
41
42
|
|
|
42
43
|
return !!flourishPath ? (
|
|
43
44
|
<PrivacyProtection
|
|
@@ -47,10 +48,10 @@ const MaybeFlourishVisualization = ({ content }) => {
|
|
|
47
48
|
}}
|
|
48
49
|
>
|
|
49
50
|
<iframe
|
|
50
|
-
height=
|
|
51
|
+
height={height}
|
|
51
52
|
width="100%"
|
|
52
53
|
src={flourishUrl}
|
|
53
|
-
title=
|
|
54
|
+
title={title}
|
|
54
55
|
className="flourish-embed-iframe"
|
|
55
56
|
sandbox="allow-same-origin allow-forms allow-scripts allow-downloads allow-popups allow-popups-to-escape-sandbox allow-top-navigation-by-user-activation"
|
|
56
57
|
></iframe>
|
|
@@ -73,10 +74,11 @@ function getFirstIframeSrc(htmlString) {
|
|
|
73
74
|
}
|
|
74
75
|
}
|
|
75
76
|
|
|
76
|
-
const MaybeIframeVisualization = ({
|
|
77
|
-
const
|
|
78
|
-
const url = getFirstIframeSrc(
|
|
79
|
-
const height =
|
|
77
|
+
const MaybeIframeVisualization = ({ visualization }) => {
|
|
78
|
+
const embedCode = visualization?.embed_code || '';
|
|
79
|
+
const url = getFirstIframeSrc(embedCode);
|
|
80
|
+
const height = visualization?.height || 800;
|
|
81
|
+
const title = visualization?.title || 'Interactive or visual content';
|
|
80
82
|
const [isClient, setIsClient] = React.useState();
|
|
81
83
|
|
|
82
84
|
React.useEffect(() => setIsClient(true), []);
|
|
@@ -94,7 +96,7 @@ const MaybeIframeVisualization = ({ content }) => {
|
|
|
94
96
|
height={height}
|
|
95
97
|
width="100%"
|
|
96
98
|
src={url}
|
|
97
|
-
title=
|
|
99
|
+
title={title}
|
|
98
100
|
className="flourish-embed-iframe"
|
|
99
101
|
sandbox="allow-same-origin allow-forms allow-scripts allow-downloads allow-popups allow-popups-to-escape-sandbox allow-top-navigation-by-user-activation"
|
|
100
102
|
></iframe>
|
|
@@ -102,6 +104,31 @@ const MaybeIframeVisualization = ({ content }) => {
|
|
|
102
104
|
);
|
|
103
105
|
};
|
|
104
106
|
|
|
107
|
+
const Visualization = ({ visualization }) => (
|
|
108
|
+
<>
|
|
109
|
+
{visualization?.title && <h2>{visualization.title}</h2>}
|
|
110
|
+
<MaybeFlourishVisualization visualization={visualization} />
|
|
111
|
+
<MaybeIframeVisualization visualization={visualization} />
|
|
112
|
+
</>
|
|
113
|
+
);
|
|
114
|
+
|
|
115
|
+
const Visualizations = ({ visualizations }) => (
|
|
116
|
+
<>
|
|
117
|
+
{visualizations.map((visualization, index) => (
|
|
118
|
+
<Visualization
|
|
119
|
+
key={`visualization-${index}`}
|
|
120
|
+
visualization={visualization}
|
|
121
|
+
/>
|
|
122
|
+
))}
|
|
123
|
+
</>
|
|
124
|
+
);
|
|
125
|
+
|
|
126
|
+
const getVisualizations = (content) => {
|
|
127
|
+
return Array.isArray(content?.visualizations)
|
|
128
|
+
? content.visualizations.filter((item) => item?.embed_code)
|
|
129
|
+
: [];
|
|
130
|
+
};
|
|
131
|
+
|
|
105
132
|
const BottomInfo = (props) => {
|
|
106
133
|
const { content } = props;
|
|
107
134
|
const { organisational_websites, organisational_contact_information } =
|
|
@@ -157,9 +184,14 @@ const DatabaseItemView = (props) => {
|
|
|
157
184
|
} = content;
|
|
158
185
|
const item_title = acronym ? title + ' (' + acronym + ')' : title;
|
|
159
186
|
const subtitle = CONTENT_TYPE_LABELS[type] ?? '';
|
|
160
|
-
const
|
|
161
|
-
const
|
|
162
|
-
|
|
187
|
+
const visualizations = getVisualizations(content);
|
|
188
|
+
const columnVisualizations = visualizations.filter(
|
|
189
|
+
(visualization) => !visualization.full_width,
|
|
190
|
+
);
|
|
191
|
+
const fullWidthVisualizations = visualizations.filter(
|
|
192
|
+
(visualization) => visualization.full_width,
|
|
193
|
+
);
|
|
194
|
+
const hasFullWidthVisualizations = !!fullWidthVisualizations.length;
|
|
163
195
|
|
|
164
196
|
const is_cmshare_video = SHARE_EEA.some((domain) =>
|
|
165
197
|
content?.embed_url?.includes(domain),
|
|
@@ -252,14 +284,11 @@ const DatabaseItemView = (props) => {
|
|
|
252
284
|
</>
|
|
253
285
|
)}
|
|
254
286
|
|
|
255
|
-
{
|
|
256
|
-
|
|
257
|
-
<MaybeFlourishVisualization {...props} />
|
|
258
|
-
<MaybeIframeVisualization {...props} />
|
|
259
|
-
</>
|
|
287
|
+
{!!columnVisualizations.length && (
|
|
288
|
+
<Visualizations visualizations={columnVisualizations} />
|
|
260
289
|
)}
|
|
261
290
|
|
|
262
|
-
{!
|
|
291
|
+
{!hasFullWidthVisualizations && <BottomInfo {...props} />}
|
|
263
292
|
</Grid.Column>
|
|
264
293
|
|
|
265
294
|
<Grid.Column
|
|
@@ -273,12 +302,11 @@ const DatabaseItemView = (props) => {
|
|
|
273
302
|
</Grid.Column>
|
|
274
303
|
</Grid.Row>
|
|
275
304
|
|
|
276
|
-
{
|
|
305
|
+
{hasFullWidthVisualizations && (
|
|
277
306
|
<>
|
|
278
307
|
<Grid.Row>
|
|
279
308
|
<Grid.Column mobile={12} tablet={12} computer={12}>
|
|
280
|
-
<
|
|
281
|
-
<MaybeIframeVisualization {...props} />
|
|
309
|
+
<Visualizations visualizations={fullWidthVisualizations} />
|
|
282
310
|
</Grid.Column>
|
|
283
311
|
</Grid.Row>
|
|
284
312
|
<Grid.Row>
|
|
@@ -17,6 +17,66 @@ 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 getVisualization = (overrides = {}) => ({
|
|
48
|
+
title: '',
|
|
49
|
+
embed_code: visualizationEmbedCode,
|
|
50
|
+
height: '',
|
|
51
|
+
full_width: false,
|
|
52
|
+
...overrides,
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
const renderDatabaseItemView = (content = baseContent) => {
|
|
56
|
+
const store = mockStore({
|
|
57
|
+
userSession: { token: '1234' },
|
|
58
|
+
intl: {
|
|
59
|
+
locale: 'en',
|
|
60
|
+
messages: {},
|
|
61
|
+
},
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
return renderer.create(
|
|
65
|
+
<Provider store={store}>
|
|
66
|
+
<MemoryRouter>
|
|
67
|
+
<DatabaseItemView content={content} />
|
|
68
|
+
</MemoryRouter>
|
|
69
|
+
</Provider>,
|
|
70
|
+
);
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
const findColumnByClassName = (component, className) =>
|
|
74
|
+
component.root.findAll(
|
|
75
|
+
(node) =>
|
|
76
|
+
typeof node.props.className === 'string' &&
|
|
77
|
+
node.props.className.includes(className),
|
|
78
|
+
)[0];
|
|
79
|
+
|
|
20
80
|
jest.mock('semantic-ui-react', () => ({
|
|
21
81
|
...jest.requireActual('semantic-ui-react'),
|
|
22
82
|
}));
|
|
@@ -29,46 +89,52 @@ jest.mock('@eeacms/volto-embed', () => {
|
|
|
29
89
|
|
|
30
90
|
describe('DatabaseItemView', () => {
|
|
31
91
|
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
|
-
},
|
|
92
|
+
const component = renderDatabaseItemView();
|
|
93
|
+
const json = component.toJSON();
|
|
94
|
+
expect(json).toMatchSnapshot();
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
it('renders the visualizations field in the left column by default', () => {
|
|
98
|
+
const component = renderDatabaseItemView({
|
|
99
|
+
...baseContent,
|
|
100
|
+
visualizations: [getVisualization()],
|
|
62
101
|
});
|
|
102
|
+
const colLeft = findColumnByClassName(component, 'col-left');
|
|
103
|
+
const fullWidthColumns = component.root.findAll(
|
|
104
|
+
(node) => node.props.computer === 12,
|
|
105
|
+
);
|
|
63
106
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
<DatabaseItemView content={content} />
|
|
68
|
-
</MemoryRouter>
|
|
69
|
-
</Provider>,
|
|
107
|
+
expect(colLeft.findAllByType('iframe')).toHaveLength(1);
|
|
108
|
+
expect(component.root.findByType('iframe').props.src).toBe(
|
|
109
|
+
'https://flo.uri.sh/visualisation/12345/embed',
|
|
70
110
|
);
|
|
71
|
-
|
|
72
|
-
|
|
111
|
+
expect(fullWidthColumns).toHaveLength(0);
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
it('renders the visualizations field full width when enabled', () => {
|
|
115
|
+
const component = renderDatabaseItemView({
|
|
116
|
+
...baseContent,
|
|
117
|
+
visualizations: [getVisualization({ full_width: true })],
|
|
118
|
+
});
|
|
119
|
+
const colLeft = findColumnByClassName(component, 'col-left');
|
|
120
|
+
const fullWidthColumn = component.root.findAll(
|
|
121
|
+
(node) => node.props.computer === 12,
|
|
122
|
+
)[0];
|
|
123
|
+
|
|
124
|
+
expect(colLeft.findAllByType('iframe')).toHaveLength(0);
|
|
125
|
+
expect(fullWidthColumn.findAllByType('iframe')).toHaveLength(1);
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
it('does not render a visualization when the visualizations field is empty', () => {
|
|
129
|
+
const component = renderDatabaseItemView({
|
|
130
|
+
...baseContent,
|
|
131
|
+
visualizations: [],
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
expect(component.root.findAllByType('iframe')).toHaveLength(0);
|
|
135
|
+
const fullWidthColumns = component.root.findAll(
|
|
136
|
+
(node) => node.props.computer === 12,
|
|
137
|
+
);
|
|
138
|
+
expect(fullWidthColumns).toHaveLength(0);
|
|
73
139
|
});
|
|
74
140
|
});
|
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) {
|