@eeacms/volto-cca-policy 1.0.35 → 1.0.36
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 +46 -1
- package/package.json +1 -1
- package/src/components/Search/NavigatorCatalogue/NavigatorGeographicCoverageFacet.jsx +45 -21
- package/src/components/Search/NavigatorCatalogue/NavigatorGeographicCoverageFacet.test.jsx +89 -23
- package/src/components/theme/CompareTools/CompareToolsView.jsx +82 -8
- package/src/components/theme/CompareTools/CompareToolsView.test.jsx +10 -0
- package/src/index.js +4 -0
- package/src/search/navigator_catalogue/config.js +5 -1
- package/src/search/navigator_catalogue/facets.js +2 -1
- package/src/search/navigator_catalogue/geographicCoverage.js +47 -0
- package/src/search/navigator_catalogue/geographicCoverage.test.js +65 -0
- package/theme/globals/navigator.less +30 -0
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,17 @@ 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.36](https://github.com/eea/volto-cca-policy/compare/1.0.35...1.0.36) - 8 October 2026
|
|
8
|
+
|
|
9
|
+
#### :rocket: New Features
|
|
10
|
+
|
|
11
|
+
- feat(navigator): update geographic coverage functionality, add runtime mappings and facet value retrieval [kreafox - [`4787c3b`](https://github.com/eea/volto-cca-policy/commit/4787c3b890b69d46ee0806084983ac3c0f36fe43)]
|
|
12
|
+
- feat: add tooltips for usability and functionality criteria in CompareToolsView - refs #304612 [kreafox - [`d23175c`](https://github.com/eea/volto-cca-policy/commit/d23175c7e3e1df85e2c75deba6612be3dd94b88d)]
|
|
13
|
+
|
|
14
|
+
#### :nail_care: Enhancements
|
|
15
|
+
|
|
16
|
+
- refactor(navigator): clean up imports and test files [kreafox - [`4a79b41`](https://github.com/eea/volto-cca-policy/commit/4a79b414b713d387af0fcf7baefd699da747cdac)]
|
|
17
|
+
|
|
7
18
|
### [1.0.35](https://github.com/eea/volto-cca-policy/compare/1.0.34...1.0.35) - 6 October 2026
|
|
8
19
|
|
|
9
20
|
#### :bug: Bug Fixes
|
|
@@ -615,8 +626,42 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
|
|
|
615
626
|
#### :hammer_and_wrench: Others
|
|
616
627
|
|
|
617
628
|
- test: pin Chromium version 149 to work with Cypress [valentinab25 - [`659ec82`](https://github.com/eea/volto-cca-policy/commit/659ec823dd71fe592a3a7accda22effbe1fb07bc)]
|
|
618
|
-
## [1.0.0](https://github.com/eea/volto-cca-policy/compare/1.0.0-alpha.
|
|
629
|
+
## [1.0.0](https://github.com/eea/volto-cca-policy/compare/1.0.0-alpha.33...1.0.0) - 12 June 2026
|
|
630
|
+
|
|
631
|
+
### [1.0.0-alpha.33](https://github.com/eea/volto-cca-policy/compare/1.0.0-alpha.32...1.0.0-alpha.33) - 7 October 2026
|
|
632
|
+
|
|
633
|
+
### [1.0.0-alpha.32](https://github.com/eea/volto-cca-policy/compare/1.0.0-alpha.31...1.0.0-alpha.32) - 7 October 2026
|
|
634
|
+
|
|
635
|
+
#### :bug: Bug Fixes
|
|
636
|
+
|
|
637
|
+
- fix(test): add waitFor to image load assertions [kreafox - [`84eed2e`](https://github.com/eea/volto-cca-policy/commit/84eed2e15a911d9a8a4a1d20e7d29b3de261bb7d)]
|
|
638
|
+
|
|
639
|
+
#### :nail_care: Enhancements
|
|
619
640
|
|
|
641
|
+
- change(navigator): conditionally render result count based on selections [kreafox - [`0ed5449`](https://github.com/eea/volto-cca-policy/commit/0ed54490c16c9a5b4652fd1de47adbad8d2c8256)]
|
|
642
|
+
- change(NavigatorGuide): implement sorting for guide options - refs #304612 [kreafox - [`4ffcbff`](https://github.com/eea/volto-cca-policy/commit/4ffcbff4f98a2c95b1c88dfc0f662c2906678c13)]
|
|
643
|
+
- change(navigator): implement default sorting in guide me tools listing - refs #304612 [kreafox - [`a9f7fb3`](https://github.com/eea/volto-cca-policy/commit/a9f7fb31b276ed2c28d0fa24b800bebfd0ff5425)]
|
|
644
|
+
- change(CatalogueChatView): remove CompareToolsPanel and update tests - refs #309337 [kreafox - [`a5bb420`](https://github.com/eea/volto-cca-policy/commit/a5bb420e8a3229b1a04fd38f36ee87266bb0e59d)]
|
|
645
|
+
- change(locales): update translations [kreafox - [`4541062`](https://github.com/eea/volto-cca-policy/commit/45410626484ff0cc536447ff75895b662e3e9554)]
|
|
646
|
+
- change(navigator): update adaptation stage questions [kreafox - [`a1e3705`](https://github.com/eea/volto-cca-policy/commit/a1e3705f1004777ce72a1395f89149c9d8f8e539)]
|
|
647
|
+
- change(locales): add "Governance level" translations [kreafox - [`23ae204`](https://github.com/eea/volto-cca-policy/commit/23ae2046557203a55b2dd40b761ed99e84b78d80)]
|
|
648
|
+
- change(navigator): update implementation level messages to governance level [kreafox - [`f28a93e`](https://github.com/eea/volto-cca-policy/commit/f28a93e408ba24a81ac27229947de1b959a5c42b)]
|
|
649
|
+
|
|
650
|
+
#### :house: Internal changes
|
|
651
|
+
|
|
652
|
+
- style: Automated code fix [eea-jenkins - [`3a0597d`](https://github.com/eea/volto-cca-policy/commit/3a0597dd9358ba2c7f365bef9d3e4ffae36ee68b)]
|
|
653
|
+
- style: Automated code fix [eea-jenkins - [`d91a798`](https://github.com/eea/volto-cca-policy/commit/d91a798f30b29e4bc058cc44ebcc02f07ac216ab)]
|
|
654
|
+
|
|
655
|
+
#### :hammer_and_wrench: Others
|
|
656
|
+
|
|
657
|
+
- update SonarQube messages [iugin - [`cf21375`](https://github.com/eea/volto-cca-policy/commit/cf21375202f946f7adb2959db45cb0e991bfae68)]
|
|
658
|
+
- add mapstyle test [iugin - [`e80b843`](https://github.com/eea/volto-cca-policy/commit/e80b8438e6ff47cb73e43cc8927511e7b8979a8f)]
|
|
659
|
+
- remove test [iugin - [`dcd7fb2`](https://github.com/eea/volto-cca-policy/commit/dcd7fb2873101fd7c0e6612e0eb11012b18412a3)]
|
|
660
|
+
- Refs #296263 - add more tests [iugin - [`898d8e7`](https://github.com/eea/volto-cca-policy/commit/898d8e7878e49a7e777c749e1f88dc6c94ce416b)]
|
|
661
|
+
- Refs #296263 - update tests img alt [iugin - [`1f720a8`](https://github.com/eea/volto-cca-policy/commit/1f720a83b389cb1cb5dbed33c96418fc8def73d9)]
|
|
662
|
+
- Refs #296263 - add tests [iugin - [`c9012e0`](https://github.com/eea/volto-cca-policy/commit/c9012e0e7ca850acda608459e9b78c70f37e7ad4)]
|
|
663
|
+
- Refs #296263 - duplication country profile mapstyle [iugin - [`a6771e9`](https://github.com/eea/volto-cca-policy/commit/a6771e921bcdc6b9ce2f0f9f40413a2fefe78e84)]
|
|
664
|
+
- Refs #296263 - duplicate content [iugin - [`400b661`](https://github.com/eea/volto-cca-policy/commit/400b6618cc3fb50df44f9007253aeaba5e5d36b0)]
|
|
620
665
|
### [1.0.0-alpha.31](https://github.com/eea/volto-cca-policy/compare/1.0.0-alpha.30...1.0.0-alpha.31) - 2 October 2026
|
|
621
666
|
|
|
622
667
|
#### :rocket: New Features
|
package/package.json
CHANGED
|
@@ -4,11 +4,11 @@ import { defineMessages, useIntl } from 'react-intl';
|
|
|
4
4
|
import { Term } from '@eeacms/search/components';
|
|
5
5
|
import { useSearchContext } from '@eeacms/search/lib/hocs';
|
|
6
6
|
import { markSelectedFacetValuesFromFilters } from '@eeacms/search/lib/search/helpers';
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
7
|
+
import {
|
|
8
|
+
CHARACTERISATION_FIELD,
|
|
9
|
+
COUNTRIES_FIELD,
|
|
10
|
+
TRANSNATIONAL_REGION_FIELD,
|
|
11
|
+
} from '../../../search/navigator_catalogue/geographicCoverage';
|
|
12
12
|
|
|
13
13
|
const messages = defineMessages({
|
|
14
14
|
noOptionsAvailable: {
|
|
@@ -196,29 +196,53 @@ const NavigatorGeographicCoverageFacet = ({
|
|
|
196
196
|
TRANSNATIONAL_REGION_FIELD,
|
|
197
197
|
);
|
|
198
198
|
const countryOptions = getFacetOptions(facets, filters, COUNTRIES_FIELD);
|
|
199
|
+
const selectedDirectValues =
|
|
200
|
+
filters.find(({ field }) => field === CHARACTERISATION_FIELD)?.values || [];
|
|
201
|
+
|
|
202
|
+
const clearFilter = (field) => removeFilter(field, null, 'any');
|
|
203
|
+
|
|
204
|
+
const updateDirectFilter = (option) => {
|
|
205
|
+
if (option.selected) {
|
|
206
|
+
onRemove(option.value);
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
clearFilter(COUNTRIES_FIELD);
|
|
211
|
+
clearFilter(TRANSNATIONAL_REGION_FIELD);
|
|
212
|
+
onSelect(option.value);
|
|
213
|
+
};
|
|
199
214
|
|
|
200
|
-
const updateChildFilter = (field, option) =>
|
|
201
|
-
option.selected
|
|
202
|
-
|
|
203
|
-
|
|
215
|
+
const updateChildFilter = (field, option) => {
|
|
216
|
+
if (option.selected) {
|
|
217
|
+
removeFilter(field, option.value, 'any');
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
clearFilter(CHARACTERISATION_FIELD);
|
|
222
|
+
addFilter(field, option.value, 'any');
|
|
223
|
+
};
|
|
204
224
|
|
|
205
225
|
return (
|
|
206
226
|
<fieldset
|
|
207
227
|
className={`sui-facet searchlib-multiterm-facet navigator-geographic-facet ${className}`}
|
|
208
228
|
>
|
|
209
229
|
<div className="sui-multi-checkbox-facet navigator-geographic-facet-direct-options">
|
|
210
|
-
{options.map((option) =>
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
230
|
+
{options.map((option) => {
|
|
231
|
+
const directOption = {
|
|
232
|
+
...option,
|
|
233
|
+
selected:
|
|
234
|
+
option.selected || selectedDirectValues.includes(option.value),
|
|
235
|
+
};
|
|
236
|
+
|
|
237
|
+
return (
|
|
238
|
+
<FacetOption
|
|
239
|
+
key={valueAsText(option.value)}
|
|
240
|
+
field={CHARACTERISATION_FIELD}
|
|
241
|
+
option={directOption}
|
|
242
|
+
onChange={updateDirectFilter}
|
|
243
|
+
/>
|
|
244
|
+
);
|
|
245
|
+
})}
|
|
222
246
|
</div>
|
|
223
247
|
<ExpandableFacetGroup
|
|
224
248
|
field={COUNTRIES_FIELD}
|
|
@@ -3,10 +3,12 @@ import '@testing-library/jest-dom';
|
|
|
3
3
|
import { fireEvent, render, screen } from '@testing-library/react';
|
|
4
4
|
import { IntlProvider } from 'react-intl';
|
|
5
5
|
import { useSearchContext } from '@eeacms/search/lib/hocs';
|
|
6
|
-
import NavigatorGeographicCoverageFacet
|
|
6
|
+
import NavigatorGeographicCoverageFacet from './NavigatorGeographicCoverageFacet';
|
|
7
|
+
import {
|
|
8
|
+
CHARACTERISATION_FIELD,
|
|
7
9
|
COUNTRIES_FIELD,
|
|
8
10
|
TRANSNATIONAL_REGION_FIELD,
|
|
9
|
-
} from '
|
|
11
|
+
} from '../../../search/navigator_catalogue/geographicCoverage';
|
|
10
12
|
|
|
11
13
|
jest.mock('@eeacms/search/components', () => ({
|
|
12
14
|
Term: ({ term }) => <>{term}</>,
|
|
@@ -16,6 +18,7 @@ jest.mock('@eeacms/search/lib/hocs', () => ({
|
|
|
16
18
|
}));
|
|
17
19
|
|
|
18
20
|
const renderFacet = ({
|
|
21
|
+
detailedOptions = true,
|
|
19
22
|
filters = [],
|
|
20
23
|
onRemove = jest.fn(),
|
|
21
24
|
onSelect = jest.fn(),
|
|
@@ -30,18 +33,22 @@ const renderFacet = ({
|
|
|
30
33
|
facets: {
|
|
31
34
|
[TRANSNATIONAL_REGION_FIELD]: [
|
|
32
35
|
{
|
|
33
|
-
data:
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
36
|
+
data: detailedOptions
|
|
37
|
+
? [
|
|
38
|
+
{ value: 'Alpine Space', count: 3 },
|
|
39
|
+
{ value: 'Outermost regions', count: 2 },
|
|
40
|
+
]
|
|
41
|
+
: [],
|
|
37
42
|
},
|
|
38
43
|
],
|
|
39
44
|
[COUNTRIES_FIELD]: [
|
|
40
45
|
{
|
|
41
|
-
data:
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
46
|
+
data: detailedOptions
|
|
47
|
+
? [
|
|
48
|
+
{ value: 'Germany', count: 4 },
|
|
49
|
+
{ value: 'Spain', count: 2 },
|
|
50
|
+
]
|
|
51
|
+
: [],
|
|
45
52
|
},
|
|
46
53
|
],
|
|
47
54
|
},
|
|
@@ -58,14 +65,8 @@ const renderFacet = ({
|
|
|
58
65
|
defaultMessage: 'Transnational regions',
|
|
59
66
|
}}
|
|
60
67
|
options={[
|
|
61
|
-
{ value: 'Global', count: 5, selected: false },
|
|
62
68
|
{ value: 'Europe', count: 8, selected: false },
|
|
63
|
-
{
|
|
64
|
-
value: 'Macro-Transnational region',
|
|
65
|
-
count: 4,
|
|
66
|
-
selected: false,
|
|
67
|
-
},
|
|
68
|
-
{ value: 'Countries', count: 6, selected: false },
|
|
69
|
+
{ value: 'Global', count: 5, selected: false },
|
|
69
70
|
]}
|
|
70
71
|
/>
|
|
71
72
|
</IntlProvider>,
|
|
@@ -79,15 +80,37 @@ describe('NavigatorGeographicCoverageFacet', () => {
|
|
|
79
80
|
jest.clearAllMocks();
|
|
80
81
|
});
|
|
81
82
|
|
|
82
|
-
it('shows
|
|
83
|
-
|
|
83
|
+
it('shows Global and Europe as direct options', () => {
|
|
84
|
+
renderFacet();
|
|
85
|
+
|
|
86
|
+
expect(
|
|
87
|
+
screen
|
|
88
|
+
.getAllByRole('checkbox')
|
|
89
|
+
.slice(0, 2)
|
|
90
|
+
.map((option) => option.getAttribute('aria-label')),
|
|
91
|
+
).toEqual(['Europe', 'Global']);
|
|
92
|
+
});
|
|
84
93
|
|
|
85
|
-
|
|
86
|
-
|
|
94
|
+
it('clears detailed coverage before selecting a direct scope', () => {
|
|
95
|
+
const { onSelect, removeFilter } = renderFacet({
|
|
96
|
+
filters: [
|
|
97
|
+
{
|
|
98
|
+
field: COUNTRIES_FIELD,
|
|
99
|
+
values: ['Germany'],
|
|
100
|
+
type: 'any',
|
|
101
|
+
},
|
|
102
|
+
],
|
|
103
|
+
});
|
|
87
104
|
|
|
88
|
-
fireEvent.click(screen.getByLabelText('
|
|
105
|
+
fireEvent.click(screen.getByLabelText('Europe'));
|
|
89
106
|
|
|
90
|
-
expect(
|
|
107
|
+
expect(removeFilter).toHaveBeenCalledWith(COUNTRIES_FIELD, null, 'any');
|
|
108
|
+
expect(removeFilter).toHaveBeenCalledWith(
|
|
109
|
+
TRANSNATIONAL_REGION_FIELD,
|
|
110
|
+
null,
|
|
111
|
+
'any',
|
|
112
|
+
);
|
|
113
|
+
expect(onSelect).toHaveBeenCalledWith('Europe');
|
|
91
114
|
});
|
|
92
115
|
|
|
93
116
|
it('expands and filters Macro-Transnational region values', () => {
|
|
@@ -124,4 +147,47 @@ describe('NavigatorGeographicCoverageFacet', () => {
|
|
|
124
147
|
'any',
|
|
125
148
|
);
|
|
126
149
|
});
|
|
150
|
+
|
|
151
|
+
it('shows empty detailed coverage groups while Europe is selected', () => {
|
|
152
|
+
const { onRemove } = renderFacet({
|
|
153
|
+
detailedOptions: false,
|
|
154
|
+
filters: [
|
|
155
|
+
{
|
|
156
|
+
field: CHARACTERISATION_FIELD,
|
|
157
|
+
values: ['Europe'],
|
|
158
|
+
type: 'any',
|
|
159
|
+
},
|
|
160
|
+
],
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
expect(screen.getByLabelText('Europe')).toBeChecked();
|
|
164
|
+
fireEvent.click(screen.getByRole('button', { name: 'Countries' }));
|
|
165
|
+
fireEvent.click(
|
|
166
|
+
screen.getByRole('button', { name: 'Transnational regions' }),
|
|
167
|
+
);
|
|
168
|
+
|
|
169
|
+
expect(screen.getAllByText('No options available.')).toHaveLength(2);
|
|
170
|
+
|
|
171
|
+
fireEvent.click(screen.getByLabelText('Europe'));
|
|
172
|
+
|
|
173
|
+
expect(onRemove).toHaveBeenCalledWith('Europe');
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
it('keeps detailed coverage available when a country is selected', () => {
|
|
177
|
+
renderFacet({
|
|
178
|
+
filters: [
|
|
179
|
+
{
|
|
180
|
+
field: COUNTRIES_FIELD,
|
|
181
|
+
values: ['Germany'],
|
|
182
|
+
type: 'any',
|
|
183
|
+
},
|
|
184
|
+
],
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
expect(screen.getByRole('button', { name: 'Countries' })).toBeEnabled();
|
|
188
|
+
expect(screen.getByLabelText('Germany')).toBeEnabled();
|
|
189
|
+
expect(
|
|
190
|
+
screen.getByRole('button', { name: 'Transnational regions' }),
|
|
191
|
+
).toBeEnabled();
|
|
192
|
+
});
|
|
127
193
|
});
|
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
Icon,
|
|
8
8
|
Loader,
|
|
9
9
|
Message,
|
|
10
|
+
Popup,
|
|
10
11
|
Table,
|
|
11
12
|
Button,
|
|
12
13
|
} from 'semantic-ui-react';
|
|
@@ -84,10 +85,20 @@ const messages = defineMessages({
|
|
|
84
85
|
id: 'Usability',
|
|
85
86
|
defaultMessage: 'Usability',
|
|
86
87
|
},
|
|
88
|
+
usabilityTooltip: {
|
|
89
|
+
id: 'This indicates how easy the tool and its outputs are to understand and interpret, with low = high-level expertise needed, moderate = some prior technical/scientific knowledge needed, high = general user-friendly, minimal technical knowledge needed.',
|
|
90
|
+
defaultMessage:
|
|
91
|
+
'This indicates how easy the tool and its outputs are to understand and interpret, with low = high-level expertise needed, moderate = some prior technical/scientific knowledge needed, high = general user-friendly, minimal technical knowledge needed.',
|
|
92
|
+
},
|
|
87
93
|
functionality: {
|
|
88
94
|
id: 'Functionality',
|
|
89
95
|
defaultMessage: 'Functionality',
|
|
90
96
|
},
|
|
97
|
+
functionalityTooltip: {
|
|
98
|
+
id: 'Number of adaptation support cycle steps supported, from 1 to 6 steps.',
|
|
99
|
+
defaultMessage:
|
|
100
|
+
'Number of adaptation support cycle steps supported, from 1 to 6 steps.',
|
|
101
|
+
},
|
|
91
102
|
spatialScale: {
|
|
92
103
|
id: 'Spatial scale',
|
|
93
104
|
defaultMessage: 'Spatial scale',
|
|
@@ -231,6 +242,53 @@ const FunctionalityScore = ({ value }) => {
|
|
|
231
242
|
);
|
|
232
243
|
};
|
|
233
244
|
|
|
245
|
+
const UsabilityTooltipContent = ({ text }) => {
|
|
246
|
+
const parts = text.match(
|
|
247
|
+
/^(.* with) low = (.*), moderate = (.*), high = (.*)$/,
|
|
248
|
+
);
|
|
249
|
+
|
|
250
|
+
if (!parts) return text;
|
|
251
|
+
|
|
252
|
+
const [, introduction, low, moderate, high] = parts;
|
|
253
|
+
const levels = [
|
|
254
|
+
['low', low],
|
|
255
|
+
['moderate', moderate],
|
|
256
|
+
['high', high],
|
|
257
|
+
];
|
|
258
|
+
|
|
259
|
+
return (
|
|
260
|
+
<div className="usability-tooltip-content">
|
|
261
|
+
<div className="usability-tooltip-introduction">{introduction}:</div>
|
|
262
|
+
{levels.map(([level, description]) => (
|
|
263
|
+
<div className="usability-tooltip-level" key={level}>
|
|
264
|
+
<strong>{level}</strong>
|
|
265
|
+
<span>{` = ${description}`}</span>
|
|
266
|
+
</div>
|
|
267
|
+
))}
|
|
268
|
+
</div>
|
|
269
|
+
);
|
|
270
|
+
};
|
|
271
|
+
|
|
272
|
+
const CriterionLabel = ({ label, tooltip, tooltipContent }) => (
|
|
273
|
+
<div className="compare-criteria-title">
|
|
274
|
+
<span>{label}</span>
|
|
275
|
+
<Popup
|
|
276
|
+
className="compare-criteria-popup"
|
|
277
|
+
content={tooltipContent || tooltip}
|
|
278
|
+
position="top left"
|
|
279
|
+
trigger={
|
|
280
|
+
<button
|
|
281
|
+
type="button"
|
|
282
|
+
className="compare-criteria-tooltip"
|
|
283
|
+
aria-label={tooltip}
|
|
284
|
+
>
|
|
285
|
+
<Icon className="ri-information-line" aria-hidden="true" />
|
|
286
|
+
</button>
|
|
287
|
+
}
|
|
288
|
+
/>
|
|
289
|
+
</div>
|
|
290
|
+
);
|
|
291
|
+
|
|
234
292
|
const getCompareUids = (search) => {
|
|
235
293
|
const params = new URLSearchParams(search);
|
|
236
294
|
|
|
@@ -297,6 +355,7 @@ const CompareToolsView = () => {
|
|
|
297
355
|
const registry = config.settings.searchlib;
|
|
298
356
|
const landingPageURL = getNavigatorCataloguePageURL(currentLang);
|
|
299
357
|
const compareToolsTitle = intl.formatMessage(messages.compareTools);
|
|
358
|
+
const usabilityTooltip = intl.formatMessage(messages.usabilityTooltip);
|
|
300
359
|
const returnURL =
|
|
301
360
|
location.state?.returnURL ||
|
|
302
361
|
getReturnURL(location.search) ||
|
|
@@ -519,11 +578,19 @@ const CompareToolsView = () => {
|
|
|
519
578
|
|
|
520
579
|
<Table.Body>
|
|
521
580
|
<Table.Row>
|
|
522
|
-
<Table.Cell
|
|
581
|
+
<Table.Cell
|
|
582
|
+
as="th"
|
|
583
|
+
scope="row"
|
|
584
|
+
aria-label={intl.formatMessage(messages.usability)}
|
|
585
|
+
>
|
|
523
586
|
<div className="compare-criteria">
|
|
524
|
-
<
|
|
525
|
-
{intl.formatMessage(messages.usability)}
|
|
526
|
-
|
|
587
|
+
<CriterionLabel
|
|
588
|
+
label={intl.formatMessage(messages.usability)}
|
|
589
|
+
tooltip={usabilityTooltip}
|
|
590
|
+
tooltipContent={
|
|
591
|
+
<UsabilityTooltipContent text={usabilityTooltip} />
|
|
592
|
+
}
|
|
593
|
+
/>
|
|
527
594
|
</div>
|
|
528
595
|
</Table.Cell>
|
|
529
596
|
|
|
@@ -537,11 +604,18 @@ const CompareToolsView = () => {
|
|
|
537
604
|
</Table.Row>
|
|
538
605
|
|
|
539
606
|
<Table.Row>
|
|
540
|
-
<Table.Cell
|
|
607
|
+
<Table.Cell
|
|
608
|
+
as="th"
|
|
609
|
+
scope="row"
|
|
610
|
+
aria-label={intl.formatMessage(messages.functionality)}
|
|
611
|
+
>
|
|
541
612
|
<div className="compare-criteria">
|
|
542
|
-
<
|
|
543
|
-
{intl.formatMessage(messages.functionality)}
|
|
544
|
-
|
|
613
|
+
<CriterionLabel
|
|
614
|
+
label={intl.formatMessage(messages.functionality)}
|
|
615
|
+
tooltip={intl.formatMessage(
|
|
616
|
+
messages.functionalityTooltip,
|
|
617
|
+
)}
|
|
618
|
+
/>
|
|
545
619
|
</div>
|
|
546
620
|
</Table.Cell>
|
|
547
621
|
|
|
@@ -128,6 +128,16 @@ describe('CompareToolsView', () => {
|
|
|
128
128
|
expect(
|
|
129
129
|
screen.getByRole('rowheader', { name: 'Functionality' }),
|
|
130
130
|
).toHaveAttribute('scope', 'row');
|
|
131
|
+
expect(
|
|
132
|
+
screen.getByRole('button', {
|
|
133
|
+
name: 'This indicates how easy the tool and its outputs are to understand and interpret, with low = high-level expertise needed, moderate = some prior technical/scientific knowledge needed, high = general user-friendly, minimal technical knowledge needed.',
|
|
134
|
+
}),
|
|
135
|
+
).toBeInTheDocument();
|
|
136
|
+
expect(
|
|
137
|
+
screen.getByRole('button', {
|
|
138
|
+
name: 'Number of adaptation support cycle steps supported, from 1 to 6 steps.',
|
|
139
|
+
}),
|
|
140
|
+
).toBeInTheDocument();
|
|
131
141
|
expect(
|
|
132
142
|
screen.getByRole('button', {
|
|
133
143
|
name: 'Remove Tool one from comparison',
|
package/src/index.js
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
import { defineMessages, FormattedMessage } from 'react-intl';
|
|
4
4
|
import loadable from '@loadable/component';
|
|
5
5
|
import { compose } from 'redux';
|
|
6
|
+
import { buildTermFacetAggregationRequest } from '@eeacms/search/lib/search';
|
|
6
7
|
import Sitemap from '@plone/volto/components/theme/Sitemap/Sitemap';
|
|
7
8
|
import DefaultView from '@plone/volto/components/theme/View/DefaultView';
|
|
8
9
|
import SelectAutoCompleteWidget from '@plone/volto/components/manage/Widgets/SelectAutoComplete';
|
|
@@ -57,6 +58,7 @@ import NavigatorCatalogueContentView from './components/Search/NavigatorCatalogu
|
|
|
57
58
|
import NavigatorGeographicCoverageFacet from './components/Search/NavigatorCatalogue/NavigatorGeographicCoverageFacet';
|
|
58
59
|
import NavigatorGuideLayout from './components/Search/NavigatorGuide/NavigatorGuideLayout';
|
|
59
60
|
import NavigatorGuideContentView from './components/Search/NavigatorGuide/NavigatorGuideContentView';
|
|
61
|
+
import { getGeographicCoverageFacetValue } from './search/navigator_catalogue/geographicCoverage';
|
|
60
62
|
|
|
61
63
|
import { langRedirection } from './store/middleware';
|
|
62
64
|
|
|
@@ -437,7 +439,9 @@ const applyConfig = (config) => {
|
|
|
437
439
|
};
|
|
438
440
|
config.settings.searchlib.resolve.NavigatorGeographicCoverageFacet = {
|
|
439
441
|
...config.settings.searchlib.resolve.MultiTermFacet,
|
|
442
|
+
buildRequest: buildTermFacetAggregationRequest,
|
|
440
443
|
component: NavigatorGeographicCoverageFacet,
|
|
444
|
+
getValue: getGeographicCoverageFacetValue,
|
|
441
445
|
};
|
|
442
446
|
config.settings.searchlib.resolve.NavigatorGuideLayout = {
|
|
443
447
|
component: NavigatorGuideLayout,
|
|
@@ -4,6 +4,7 @@ import { getClientProxyAddress } from './../utils';
|
|
|
4
4
|
import { vocab } from './../vocabulary';
|
|
5
5
|
|
|
6
6
|
import facets from './facets';
|
|
7
|
+
import { geographicCoverageRuntimeMappings } from './geographicCoverage';
|
|
7
8
|
import views from './views';
|
|
8
9
|
|
|
9
10
|
const navigatorCatalogueConfig = {
|
|
@@ -46,7 +47,10 @@ export default function installNavigatorCatalogueSearch(config) {
|
|
|
46
47
|
index_name: 'data_searchui',
|
|
47
48
|
host: process.env.RAZZLE_ES_PROXY_ADDR || 'http://localhost:3000',
|
|
48
49
|
vocab,
|
|
49
|
-
runtime_mappings:
|
|
50
|
+
runtime_mappings: {
|
|
51
|
+
...build_runtime_mappings(clusters),
|
|
52
|
+
...geographicCoverageRuntimeMappings,
|
|
53
|
+
},
|
|
50
54
|
};
|
|
51
55
|
|
|
52
56
|
const { navigatorCatalogueSearch } = config.searchui;
|
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
geographic_countries,
|
|
6
6
|
language,
|
|
7
7
|
} from './../common';
|
|
8
|
+
import { CHARACTERISATION_FIELD } from './geographicCoverage';
|
|
8
9
|
|
|
9
10
|
const messages = defineMessages({
|
|
10
11
|
geographicCoverage: {
|
|
@@ -68,7 +69,7 @@ const facets = [
|
|
|
68
69
|
alwaysVisible: false,
|
|
69
70
|
}),
|
|
70
71
|
multiTermFacet({
|
|
71
|
-
field:
|
|
72
|
+
field: CHARACTERISATION_FIELD,
|
|
72
73
|
factory: 'NavigatorGeographicCoverageFacet',
|
|
73
74
|
isFilterable: false,
|
|
74
75
|
isMulti: true,
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
export const CHARACTERISATION_FIELD = 'cca_navigator_geographic_scope';
|
|
2
|
+
export const TRANSNATIONAL_REGION_FIELD =
|
|
3
|
+
'cca_geographic_transnational_region.keyword';
|
|
4
|
+
export const COUNTRIES_FIELD = 'cca_geographic_countries.keyword';
|
|
5
|
+
|
|
6
|
+
export const geographicCoverageRuntimeMappings = {
|
|
7
|
+
[CHARACTERISATION_FIELD]: {
|
|
8
|
+
type: 'keyword',
|
|
9
|
+
script: {
|
|
10
|
+
source: `
|
|
11
|
+
boolean hasCountries = doc.containsKey('cca_geographic_countries.keyword') && doc['cca_geographic_countries.keyword'].size() != 0;
|
|
12
|
+
boolean hasTransnational = doc.containsKey('cca_geographic_transnational_region.keyword') && doc['cca_geographic_transnational_region.keyword'].size() != 0;
|
|
13
|
+
boolean hasSubnational = doc.containsKey('cca_sub_nationals.keyword') && doc['cca_sub_nationals.keyword'].size() != 0;
|
|
14
|
+
boolean hasCity = doc.containsKey('cca_city.keyword') && doc['cca_city.keyword'].size() != 0;
|
|
15
|
+
|
|
16
|
+
if (!hasCountries && !hasTransnational && !hasSubnational && !hasCity) {
|
|
17
|
+
for (def value : doc['cca_geographic_characterisation.keyword']) {
|
|
18
|
+
emit(value);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
`,
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export const getGeographicCoverageFacetValue = ({
|
|
27
|
+
aggregations,
|
|
28
|
+
fieldName,
|
|
29
|
+
}) => {
|
|
30
|
+
const aggregation = aggregations?.[fieldName];
|
|
31
|
+
if (!aggregation) return undefined;
|
|
32
|
+
|
|
33
|
+
const counts = Object.fromEntries(
|
|
34
|
+
(aggregation.buckets || []).map(({ key, doc_count }) => [key, doc_count]),
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
return [
|
|
38
|
+
{
|
|
39
|
+
field: fieldName,
|
|
40
|
+
type: 'value',
|
|
41
|
+
data: ['Europe', 'Global'].map((value) => ({
|
|
42
|
+
value,
|
|
43
|
+
count: counts[value] || 0,
|
|
44
|
+
})),
|
|
45
|
+
},
|
|
46
|
+
];
|
|
47
|
+
};
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import {
|
|
2
|
+
CHARACTERISATION_FIELD,
|
|
3
|
+
geographicCoverageRuntimeMappings,
|
|
4
|
+
getGeographicCoverageFacetValue,
|
|
5
|
+
} from './geographicCoverage';
|
|
6
|
+
|
|
7
|
+
describe('geographic coverage runtime mapping', () => {
|
|
8
|
+
it('defines an exclusive keyword scope from all specific location fields', () => {
|
|
9
|
+
const mapping = geographicCoverageRuntimeMappings[CHARACTERISATION_FIELD];
|
|
10
|
+
|
|
11
|
+
expect(mapping.type).toBe('keyword');
|
|
12
|
+
expect(mapping.script.source).toContain(
|
|
13
|
+
"doc['cca_geographic_countries.keyword']",
|
|
14
|
+
);
|
|
15
|
+
expect(mapping.script.source).toContain(
|
|
16
|
+
"doc['cca_geographic_transnational_region.keyword']",
|
|
17
|
+
);
|
|
18
|
+
expect(mapping.script.source).toContain("doc['cca_sub_nationals.keyword']");
|
|
19
|
+
expect(mapping.script.source).toContain("doc['cca_city.keyword']");
|
|
20
|
+
expect(mapping.script.source).toContain(
|
|
21
|
+
"doc['cca_geographic_characterisation.keyword']",
|
|
22
|
+
);
|
|
23
|
+
});
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
describe('geographic coverage facet value', () => {
|
|
27
|
+
it('keeps the facet available with zero counts when its buckets are empty', () => {
|
|
28
|
+
expect(
|
|
29
|
+
getGeographicCoverageFacetValue({
|
|
30
|
+
aggregations: {
|
|
31
|
+
[CHARACTERISATION_FIELD]: { buckets: [] },
|
|
32
|
+
},
|
|
33
|
+
fieldName: CHARACTERISATION_FIELD,
|
|
34
|
+
}),
|
|
35
|
+
).toEqual([
|
|
36
|
+
{
|
|
37
|
+
field: CHARACTERISATION_FIELD,
|
|
38
|
+
type: 'value',
|
|
39
|
+
data: [
|
|
40
|
+
{ value: 'Europe', count: 0 },
|
|
41
|
+
{ value: 'Global', count: 0 },
|
|
42
|
+
],
|
|
43
|
+
},
|
|
44
|
+
]);
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it('returns Europe and Global alphabetically with their counts', () => {
|
|
48
|
+
expect(
|
|
49
|
+
getGeographicCoverageFacetValue({
|
|
50
|
+
aggregations: {
|
|
51
|
+
[CHARACTERISATION_FIELD]: {
|
|
52
|
+
buckets: [
|
|
53
|
+
{ key: 'Global', doc_count: 25 },
|
|
54
|
+
{ key: 'Europe', doc_count: 20 },
|
|
55
|
+
],
|
|
56
|
+
},
|
|
57
|
+
},
|
|
58
|
+
fieldName: CHARACTERISATION_FIELD,
|
|
59
|
+
})[0].data,
|
|
60
|
+
).toEqual([
|
|
61
|
+
{ value: 'Europe', count: 20 },
|
|
62
|
+
{ value: 'Global', count: 25 },
|
|
63
|
+
]);
|
|
64
|
+
});
|
|
65
|
+
});
|
|
@@ -354,6 +354,22 @@
|
|
|
354
354
|
margin-left: 0.5rem !important;
|
|
355
355
|
}
|
|
356
356
|
|
|
357
|
+
.ui.popup.compare-criteria-popup {
|
|
358
|
+
max-width: min(450px, calc(100vw - 2rem));
|
|
359
|
+
|
|
360
|
+
.usability-tooltip-introduction {
|
|
361
|
+
margin-bottom: 0.65rem;
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
.usability-tooltip-level {
|
|
365
|
+
strong {
|
|
366
|
+
font-weight: 700;
|
|
367
|
+
text-transform: capitalize;
|
|
368
|
+
color: @secondaryColor;
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
|
|
357
373
|
.navigator-catalogue-compare-view {
|
|
358
374
|
overflow-x: auto;
|
|
359
375
|
|
|
@@ -431,6 +447,20 @@
|
|
|
431
447
|
font-weight: 500;
|
|
432
448
|
}
|
|
433
449
|
|
|
450
|
+
.compare-criteria-tooltip {
|
|
451
|
+
padding: 0;
|
|
452
|
+
border: 0;
|
|
453
|
+
margin-left: 0.4rem;
|
|
454
|
+
background: transparent;
|
|
455
|
+
color: @primaryColor;
|
|
456
|
+
cursor: pointer;
|
|
457
|
+
line-height: 1;
|
|
458
|
+
|
|
459
|
+
i.icon {
|
|
460
|
+
margin: 0;
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
|
|
434
464
|
.usability-value,
|
|
435
465
|
.functionality-value {
|
|
436
466
|
color: @secondaryColor;
|