@eeacms/volto-cca-policy 1.0.35 → 1.0.37
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 +68 -1
- package/locales/bg/LC_MESSAGES/volto.po +30 -9
- package/locales/cs/LC_MESSAGES/volto.po +30 -9
- package/locales/da/LC_MESSAGES/volto.po +30 -9
- package/locales/de/LC_MESSAGES/volto.po +30 -9
- package/locales/el/LC_MESSAGES/volto.po +30 -9
- package/locales/en/LC_MESSAGES/volto.po +30 -9
- package/locales/es/LC_MESSAGES/volto.po +30 -9
- package/locales/et/LC_MESSAGES/volto.po +30 -9
- package/locales/fi/LC_MESSAGES/volto.po +30 -9
- package/locales/fr/LC_MESSAGES/volto.po +30 -9
- package/locales/ga/LC_MESSAGES/volto.po +30 -9
- package/locales/hr/LC_MESSAGES/volto.po +30 -9
- package/locales/hu/LC_MESSAGES/volto.po +30 -9
- package/locales/is/LC_MESSAGES/volto.po +30 -9
- package/locales/it/LC_MESSAGES/volto.po +30 -9
- package/locales/lt/LC_MESSAGES/volto.po +30 -9
- package/locales/lv/LC_MESSAGES/volto.po +30 -9
- package/locales/mt/LC_MESSAGES/volto.po +30 -9
- package/locales/nl/LC_MESSAGES/volto.po +30 -9
- package/locales/nn/LC_MESSAGES/volto.po +30 -9
- package/locales/pl/LC_MESSAGES/volto.po +30 -9
- package/locales/pt/LC_MESSAGES/volto.po +30 -9
- package/locales/ro/LC_MESSAGES/volto.po +30 -9
- package/locales/sk/LC_MESSAGES/volto.po +30 -9
- package/locales/sl/LC_MESSAGES/volto.po +30 -9
- package/locales/sv/LC_MESSAGES/volto.po +30 -9
- package/locales/tr/LC_MESSAGES/volto.po +30 -9
- package/locales/volto.pot +22 -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/components/theme/Footer/Footer.jsx +137 -0
- package/src/customizations/volto/components/theme/App/App.jsx +1 -1
- package/src/index.js +4 -0
- package/src/messages.js +20 -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
|
@@ -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',
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Policy Footer component.
|
|
3
|
+
* @module components/theme/Footer/Footer
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import React from 'react';
|
|
7
|
+
import { useIntl } from 'react-intl';
|
|
8
|
+
import { useSelector, shallowEqual } from 'react-redux';
|
|
9
|
+
import { flattenToAppURL } from '@plone/volto/helpers/Url/Url';
|
|
10
|
+
import EEAFooter from '@eeacms/volto-eea-design-system/ui/Footer/Footer';
|
|
11
|
+
import config from '@plone/volto/registry';
|
|
12
|
+
import isArray from 'lodash/isArray';
|
|
13
|
+
import messages from '@eeacms/volto-cca-policy/messages';
|
|
14
|
+
|
|
15
|
+
const footerMessages = [
|
|
16
|
+
messages.sitemap,
|
|
17
|
+
messages.managedBy,
|
|
18
|
+
messages.exploreEnvironmentalInformationSystems,
|
|
19
|
+
messages.about,
|
|
20
|
+
messages.aboutUs,
|
|
21
|
+
messages.contact,
|
|
22
|
+
messages.contactUs,
|
|
23
|
+
messages.help,
|
|
24
|
+
messages.privacy,
|
|
25
|
+
messages.privacyStatement,
|
|
26
|
+
messages.accessibility,
|
|
27
|
+
messages.legalNotice,
|
|
28
|
+
messages.dashboard,
|
|
29
|
+
messages.login,
|
|
30
|
+
messages.cmsLogin,
|
|
31
|
+
].reduce((result, message) => ({ ...result, [message.id]: message }), {});
|
|
32
|
+
|
|
33
|
+
const Footer = () => {
|
|
34
|
+
const intl = useIntl();
|
|
35
|
+
const { eea } = config.settings;
|
|
36
|
+
const {
|
|
37
|
+
footerActions,
|
|
38
|
+
copyrightActions,
|
|
39
|
+
socialActions,
|
|
40
|
+
contactActions,
|
|
41
|
+
contactExtraActions,
|
|
42
|
+
} = useSelector(
|
|
43
|
+
(state) => ({
|
|
44
|
+
footerActions: state.actions?.actions?.footer_actions,
|
|
45
|
+
copyrightActions: state.actions?.actions?.copyright_actions,
|
|
46
|
+
socialActions: state.actions?.actions?.social_actions,
|
|
47
|
+
contactActions: state.actions?.actions?.contact_actions,
|
|
48
|
+
contactExtraActions: state.actions?.actions?.contact_extra_actions,
|
|
49
|
+
}),
|
|
50
|
+
shallowEqual,
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
const translate = (text) =>
|
|
54
|
+
footerMessages[text] ? intl.formatMessage(footerMessages[text]) : text;
|
|
55
|
+
|
|
56
|
+
// ZMI > portal_actions > footer_actions
|
|
57
|
+
const actions = isArray(footerActions)
|
|
58
|
+
? footerActions.map((action) => ({
|
|
59
|
+
title: translate(action.title),
|
|
60
|
+
url: flattenToAppURL(action.url),
|
|
61
|
+
}))
|
|
62
|
+
: eea.footerOpts.actions?.map((action) => ({
|
|
63
|
+
...action,
|
|
64
|
+
title: translate(action.title),
|
|
65
|
+
}));
|
|
66
|
+
|
|
67
|
+
// ZMI > portal_actions > copyright_actions
|
|
68
|
+
const copyright = isArray(copyrightActions)
|
|
69
|
+
? copyrightActions.map((action) => ({
|
|
70
|
+
title: translate(action.title),
|
|
71
|
+
site: translate(action.title),
|
|
72
|
+
url: flattenToAppURL(action.url),
|
|
73
|
+
}))
|
|
74
|
+
: eea.footerOpts.copyright?.map((action) => ({
|
|
75
|
+
...action,
|
|
76
|
+
title: translate(action.title),
|
|
77
|
+
site: translate(action.site),
|
|
78
|
+
}));
|
|
79
|
+
|
|
80
|
+
// ZMI > portal_actions > social_actions
|
|
81
|
+
const social = isArray(socialActions)
|
|
82
|
+
? socialActions.map((action) => ({
|
|
83
|
+
name: action.id,
|
|
84
|
+
icon: action.icon,
|
|
85
|
+
url: action.url,
|
|
86
|
+
}))
|
|
87
|
+
: eea.footerOpts.social;
|
|
88
|
+
|
|
89
|
+
// ZMI > portal_actions > contact_actions
|
|
90
|
+
const contacts = isArray(contactActions)
|
|
91
|
+
? contactActions.map((action, idx) => ({
|
|
92
|
+
text: translate(action.title),
|
|
93
|
+
icon: action.icon,
|
|
94
|
+
url: flattenToAppURL(action.url),
|
|
95
|
+
children:
|
|
96
|
+
idx === 0
|
|
97
|
+
? (contactExtraActions || []).map((child) => ({
|
|
98
|
+
text: translate(child.title),
|
|
99
|
+
icon: child.icon,
|
|
100
|
+
url: flattenToAppURL(child.url),
|
|
101
|
+
}))
|
|
102
|
+
: [],
|
|
103
|
+
}))
|
|
104
|
+
: eea.footerOpts.contacts?.map((contact) => ({
|
|
105
|
+
...contact,
|
|
106
|
+
text: translate(contact.text),
|
|
107
|
+
children: contact.children?.map((child) => ({
|
|
108
|
+
...child,
|
|
109
|
+
text: translate(child.text),
|
|
110
|
+
})),
|
|
111
|
+
}));
|
|
112
|
+
|
|
113
|
+
// Update options with actions from backend
|
|
114
|
+
const options = {
|
|
115
|
+
...eea.footerOpts,
|
|
116
|
+
social,
|
|
117
|
+
contacts,
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
return (
|
|
121
|
+
<EEAFooter>
|
|
122
|
+
<EEAFooter.Header>
|
|
123
|
+
{translate(eea.footerOpts.logosHeader)}
|
|
124
|
+
</EEAFooter.Header>
|
|
125
|
+
<EEAFooter.SubFooter {...options} />
|
|
126
|
+
<EEAFooter.Header>{translate(eea.footerOpts.header)}</EEAFooter.Header>
|
|
127
|
+
<EEAFooter.SitesButton
|
|
128
|
+
buttonName={translate(eea.footerOpts.buttonName)}
|
|
129
|
+
hrefButton={eea.footerOpts.hrefButton}
|
|
130
|
+
/>
|
|
131
|
+
<EEAFooter.Social {...options} />
|
|
132
|
+
<EEAFooter.Actions actions={actions} copyright={copyright} />
|
|
133
|
+
</EEAFooter>
|
|
134
|
+
);
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
export default Footer;
|
|
@@ -25,7 +25,7 @@ import { injectIntl } from 'react-intl';
|
|
|
25
25
|
import Error from '@plone/volto/error';
|
|
26
26
|
|
|
27
27
|
import Breadcrumbs from '@plone/volto/components/theme/Breadcrumbs/Breadcrumbs';
|
|
28
|
-
import Footer from '@
|
|
28
|
+
import Footer from '@eeacms/volto-cca-policy/components/theme/Footer/Footer';
|
|
29
29
|
import Header from '@plone/volto/components/theme/Header/Header';
|
|
30
30
|
import Icon from '@plone/volto/components/theme/Icon/Icon';
|
|
31
31
|
import OutdatedBrowser from '@plone/volto/components/theme/OutdatedBrowser/OutdatedBrowser';
|
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,
|
package/src/messages.js
CHANGED
|
@@ -21,6 +21,14 @@ const messages = defineMessages({
|
|
|
21
21
|
id: 'Managed by',
|
|
22
22
|
defaultMessage: 'Managed by',
|
|
23
23
|
},
|
|
24
|
+
exploreEnvironmentalInformationSystems: {
|
|
25
|
+
id: 'Explore our environmental information systems',
|
|
26
|
+
defaultMessage: 'Explore our environmental information systems',
|
|
27
|
+
},
|
|
28
|
+
about: {
|
|
29
|
+
id: 'About',
|
|
30
|
+
defaultMessage: 'About',
|
|
31
|
+
},
|
|
24
32
|
aboutUs: {
|
|
25
33
|
id: 'About us',
|
|
26
34
|
defaultMessage: 'About us',
|
|
@@ -29,6 +37,14 @@ const messages = defineMessages({
|
|
|
29
37
|
id: 'Contact us',
|
|
30
38
|
defaultMessage: 'Contact us',
|
|
31
39
|
},
|
|
40
|
+
contact: {
|
|
41
|
+
id: 'Contact',
|
|
42
|
+
defaultMessage: 'Contact',
|
|
43
|
+
},
|
|
44
|
+
privacy: {
|
|
45
|
+
id: 'Privacy',
|
|
46
|
+
defaultMessage: 'Privacy',
|
|
47
|
+
},
|
|
32
48
|
help: {
|
|
33
49
|
id: 'Help',
|
|
34
50
|
defaultMessage: 'Help',
|
|
@@ -53,6 +69,10 @@ const messages = defineMessages({
|
|
|
53
69
|
id: 'Login',
|
|
54
70
|
defaultMessage: 'Login',
|
|
55
71
|
},
|
|
72
|
+
cmsLogin: {
|
|
73
|
+
id: 'CMS Login',
|
|
74
|
+
defaultMessage: 'CMS Login',
|
|
75
|
+
},
|
|
56
76
|
phNews: {
|
|
57
77
|
id: 'News',
|
|
58
78
|
defaultMessage: 'News',
|
|
@@ -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;
|