@eeacms/volto-cca-policy 1.0.27 → 1.0.29
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 +157 -1
- package/locales/bg/LC_MESSAGES/volto.po +10 -0
- package/locales/cs/LC_MESSAGES/volto.po +10 -0
- package/locales/da/LC_MESSAGES/volto.po +10 -0
- package/locales/de/LC_MESSAGES/volto.po +10 -0
- package/locales/el/LC_MESSAGES/volto.po +10 -0
- package/locales/en/LC_MESSAGES/volto.po +10 -0
- package/locales/es/LC_MESSAGES/volto.po +10 -0
- package/locales/et/LC_MESSAGES/volto.po +10 -0
- package/locales/fi/LC_MESSAGES/volto.po +10 -0
- package/locales/fr/LC_MESSAGES/volto.po +10 -0
- package/locales/ga/LC_MESSAGES/volto.po +10 -0
- package/locales/hr/LC_MESSAGES/volto.po +10 -0
- package/locales/hu/LC_MESSAGES/volto.po +10 -0
- package/locales/is/LC_MESSAGES/volto.po +10 -0
- package/locales/it/LC_MESSAGES/volto.po +10 -0
- package/locales/lt/LC_MESSAGES/volto.po +10 -0
- package/locales/lv/LC_MESSAGES/volto.po +10 -0
- package/locales/mt/LC_MESSAGES/volto.po +10 -0
- package/locales/nl/LC_MESSAGES/volto.po +10 -0
- package/locales/nn/LC_MESSAGES/volto.po +10 -0
- package/locales/pl/LC_MESSAGES/volto.po +10 -0
- package/locales/pt/LC_MESSAGES/volto.po +10 -0
- package/locales/ro/LC_MESSAGES/volto.po +10 -0
- package/locales/sk/LC_MESSAGES/volto.po +10 -0
- package/locales/sl/LC_MESSAGES/volto.po +10 -0
- package/locales/sv/LC_MESSAGES/volto.po +10 -0
- package/locales/tr/LC_MESSAGES/volto.po +10 -0
- package/locales/volto.pot +11 -1
- package/package.json +1 -1
- package/src/components/Search/NavigatorCatalogue/NavigatorCatalogueContentView.jsx +26 -1
- package/src/components/Search/NavigatorCatalogue/NavigatorGeographicCoverageFacet.jsx +252 -0
- package/src/components/Search/NavigatorCatalogue/NavigatorGeographicCoverageFacet.test.jsx +122 -0
- package/src/index.js +5 -0
- package/src/search/navigator_catalogue/facets.js +30 -1
- package/theme/globals/navigator.less +59 -0
|
@@ -1738,7 +1738,17 @@ msgstr ""
|
|
|
1738
1738
|
msgid "{count, plural, =0 {No tools available} one {# tool available} other {# tools available}}"
|
|
1739
1739
|
msgstr ""
|
|
1740
1740
|
|
|
1741
|
+
#. Default: "{count, plural, one {tool in the catalogue} other {tools in the catalogue}}"
|
|
1742
|
+
#: components/Search/NavigatorCatalogue/NavigatorCatalogueContentView
|
|
1743
|
+
msgid "{count, plural, one {tool in the catalogue} other {tools in the catalogue}}"
|
|
1744
|
+
msgstr ""
|
|
1745
|
+
|
|
1741
1746
|
#. Default: "{count, plural, one {tool matches} other {tools match}}"
|
|
1742
1747
|
#: components/Search/NavigatorGuide/NavigatorGuideContentView
|
|
1743
1748
|
msgid "{count, plural, one {tool matches} other {tools match}}"
|
|
1744
1749
|
msgstr ""
|
|
1750
|
+
|
|
1751
|
+
#. Default: "{count, plural, one {tool matches} other {tools match}} \"{searchTerm}\""
|
|
1752
|
+
#: components/Search/NavigatorCatalogue/NavigatorCatalogueContentView
|
|
1753
|
+
msgid "{count, plural, one {tool matches} other {tools match}} \"{searchTerm}\""
|
|
1754
|
+
msgstr ""
|
|
@@ -1738,7 +1738,17 @@ msgstr ""
|
|
|
1738
1738
|
msgid "{count, plural, =0 {No tools available} one {# tool available} other {# tools available}}"
|
|
1739
1739
|
msgstr ""
|
|
1740
1740
|
|
|
1741
|
+
#. Default: "{count, plural, one {tool in the catalogue} other {tools in the catalogue}}"
|
|
1742
|
+
#: components/Search/NavigatorCatalogue/NavigatorCatalogueContentView
|
|
1743
|
+
msgid "{count, plural, one {tool in the catalogue} other {tools in the catalogue}}"
|
|
1744
|
+
msgstr ""
|
|
1745
|
+
|
|
1741
1746
|
#. Default: "{count, plural, one {tool matches} other {tools match}}"
|
|
1742
1747
|
#: components/Search/NavigatorGuide/NavigatorGuideContentView
|
|
1743
1748
|
msgid "{count, plural, one {tool matches} other {tools match}}"
|
|
1744
1749
|
msgstr ""
|
|
1750
|
+
|
|
1751
|
+
#. Default: "{count, plural, one {tool matches} other {tools match}} \"{searchTerm}\""
|
|
1752
|
+
#: components/Search/NavigatorCatalogue/NavigatorCatalogueContentView
|
|
1753
|
+
msgid "{count, plural, one {tool matches} other {tools match}} \"{searchTerm}\""
|
|
1754
|
+
msgstr ""
|
|
@@ -1738,7 +1738,17 @@ msgstr ""
|
|
|
1738
1738
|
msgid "{count, plural, =0 {No tools available} one {# tool available} other {# tools available}}"
|
|
1739
1739
|
msgstr ""
|
|
1740
1740
|
|
|
1741
|
+
#. Default: "{count, plural, one {tool in the catalogue} other {tools in the catalogue}}"
|
|
1742
|
+
#: components/Search/NavigatorCatalogue/NavigatorCatalogueContentView
|
|
1743
|
+
msgid "{count, plural, one {tool in the catalogue} other {tools in the catalogue}}"
|
|
1744
|
+
msgstr ""
|
|
1745
|
+
|
|
1741
1746
|
#. Default: "{count, plural, one {tool matches} other {tools match}}"
|
|
1742
1747
|
#: components/Search/NavigatorGuide/NavigatorGuideContentView
|
|
1743
1748
|
msgid "{count, plural, one {tool matches} other {tools match}}"
|
|
1744
1749
|
msgstr ""
|
|
1750
|
+
|
|
1751
|
+
#. Default: "{count, plural, one {tool matches} other {tools match}} \"{searchTerm}\""
|
|
1752
|
+
#: components/Search/NavigatorCatalogue/NavigatorCatalogueContentView
|
|
1753
|
+
msgid "{count, plural, one {tool matches} other {tools match}} \"{searchTerm}\""
|
|
1754
|
+
msgstr ""
|
|
@@ -1738,7 +1738,17 @@ msgstr ""
|
|
|
1738
1738
|
msgid "{count, plural, =0 {No tools available} one {# tool available} other {# tools available}}"
|
|
1739
1739
|
msgstr ""
|
|
1740
1740
|
|
|
1741
|
+
#. Default: "{count, plural, one {tool in the catalogue} other {tools in the catalogue}}"
|
|
1742
|
+
#: components/Search/NavigatorCatalogue/NavigatorCatalogueContentView
|
|
1743
|
+
msgid "{count, plural, one {tool in the catalogue} other {tools in the catalogue}}"
|
|
1744
|
+
msgstr ""
|
|
1745
|
+
|
|
1741
1746
|
#. Default: "{count, plural, one {tool matches} other {tools match}}"
|
|
1742
1747
|
#: components/Search/NavigatorGuide/NavigatorGuideContentView
|
|
1743
1748
|
msgid "{count, plural, one {tool matches} other {tools match}}"
|
|
1744
1749
|
msgstr ""
|
|
1750
|
+
|
|
1751
|
+
#. Default: "{count, plural, one {tool matches} other {tools match}} \"{searchTerm}\""
|
|
1752
|
+
#: components/Search/NavigatorCatalogue/NavigatorCatalogueContentView
|
|
1753
|
+
msgid "{count, plural, one {tool matches} other {tools match}} \"{searchTerm}\""
|
|
1754
|
+
msgstr ""
|
|
@@ -1738,7 +1738,17 @@ msgstr ""
|
|
|
1738
1738
|
msgid "{count, plural, =0 {No tools available} one {# tool available} other {# tools available}}"
|
|
1739
1739
|
msgstr ""
|
|
1740
1740
|
|
|
1741
|
+
#. Default: "{count, plural, one {tool in the catalogue} other {tools in the catalogue}}"
|
|
1742
|
+
#: components/Search/NavigatorCatalogue/NavigatorCatalogueContentView
|
|
1743
|
+
msgid "{count, plural, one {tool in the catalogue} other {tools in the catalogue}}"
|
|
1744
|
+
msgstr ""
|
|
1745
|
+
|
|
1741
1746
|
#. Default: "{count, plural, one {tool matches} other {tools match}}"
|
|
1742
1747
|
#: components/Search/NavigatorGuide/NavigatorGuideContentView
|
|
1743
1748
|
msgid "{count, plural, one {tool matches} other {tools match}}"
|
|
1744
1749
|
msgstr ""
|
|
1750
|
+
|
|
1751
|
+
#. Default: "{count, plural, one {tool matches} other {tools match}} \"{searchTerm}\""
|
|
1752
|
+
#: components/Search/NavigatorCatalogue/NavigatorCatalogueContentView
|
|
1753
|
+
msgid "{count, plural, one {tool matches} other {tools match}} \"{searchTerm}\""
|
|
1754
|
+
msgstr ""
|
package/locales/volto.pot
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
msgid ""
|
|
2
2
|
msgstr ""
|
|
3
3
|
"Project-Id-Version: Plone\n"
|
|
4
|
-
"POT-Creation-Date: 2026-09-
|
|
4
|
+
"POT-Creation-Date: 2026-09-22T11:58:59.754Z\n"
|
|
5
5
|
"Last-Translator: Plone i18n <plone-i18n@lists.sourceforge.net>\n"
|
|
6
6
|
"Language-Team: Plone i18n <plone-i18n@lists.sourceforge.net>\n"
|
|
7
7
|
"Content-Type: text/plain; charset=utf-8\n"
|
|
@@ -1740,7 +1740,17 @@ msgstr ""
|
|
|
1740
1740
|
msgid "{count, plural, =0 {No tools available} one {# tool available} other {# tools available}}"
|
|
1741
1741
|
msgstr ""
|
|
1742
1742
|
|
|
1743
|
+
#. Default: "{count, plural, one {tool in the catalogue} other {tools in the catalogue}}"
|
|
1744
|
+
#: components/Search/NavigatorCatalogue/NavigatorCatalogueContentView
|
|
1745
|
+
msgid "{count, plural, one {tool in the catalogue} other {tools in the catalogue}}"
|
|
1746
|
+
msgstr ""
|
|
1747
|
+
|
|
1743
1748
|
#. Default: "{count, plural, one {tool matches} other {tools match}}"
|
|
1744
1749
|
#: components/Search/NavigatorGuide/NavigatorGuideContentView
|
|
1745
1750
|
msgid "{count, plural, one {tool matches} other {tools match}}"
|
|
1746
1751
|
msgstr ""
|
|
1752
|
+
|
|
1753
|
+
#. Default: "{count, plural, one {tool matches} other {tools match}} \"{searchTerm}\""
|
|
1754
|
+
#: components/Search/NavigatorCatalogue/NavigatorCatalogueContentView
|
|
1755
|
+
msgid "{count, plural, one {tool matches} other {tools match}} \"{searchTerm}\""
|
|
1756
|
+
msgstr ""
|
package/package.json
CHANGED
|
@@ -55,6 +55,16 @@ const messages = defineMessages({
|
|
|
55
55
|
id: 'Active filters are always shown in edit mode',
|
|
56
56
|
defaultMessage: 'Active filters are always shown in edit mode',
|
|
57
57
|
},
|
|
58
|
+
toolsCount: {
|
|
59
|
+
id: '{count, plural, one {tool in the catalogue} other {tools in the catalogue}}',
|
|
60
|
+
defaultMessage:
|
|
61
|
+
'{count, plural, one {tool in the catalogue} other {tools in the catalogue}}',
|
|
62
|
+
},
|
|
63
|
+
toolsMatchSearch: {
|
|
64
|
+
id: '{count, plural, one {tool matches} other {tools match}} "{searchTerm}"',
|
|
65
|
+
defaultMessage:
|
|
66
|
+
'{count, plural, one {tool matches} other {tools match}} "{searchTerm}"',
|
|
67
|
+
},
|
|
58
68
|
});
|
|
59
69
|
|
|
60
70
|
const NavigatorCatalogueContentView = (props) => {
|
|
@@ -90,7 +100,7 @@ const NavigatorCatalogueContentView = (props) => {
|
|
|
90
100
|
const layoutMode =
|
|
91
101
|
activeNavigatorViewId === 'listing' ? 'fixed' : 'fullwidth';
|
|
92
102
|
|
|
93
|
-
const { wasSearched } = searchContext;
|
|
103
|
+
const { searchTerm, totalResults, wasSearched } = searchContext;
|
|
94
104
|
|
|
95
105
|
const loadingAtom = loadingFamily(appConfig.appName);
|
|
96
106
|
const isLoading = useAtomValue(loadingAtom);
|
|
@@ -117,6 +127,21 @@ const NavigatorCatalogueContentView = (props) => {
|
|
|
117
127
|
{showClusters && <SectionTabs />}
|
|
118
128
|
|
|
119
129
|
<div className={`results-layout ${layoutMode}`}>
|
|
130
|
+
{children.length > 0 && (
|
|
131
|
+
<div className="navigator-catalogue-result-count">
|
|
132
|
+
<span className="navigator-catalogue-result-count-value">
|
|
133
|
+
{totalResults || 0}
|
|
134
|
+
</span>{' '}
|
|
135
|
+
{intl.formatMessage(
|
|
136
|
+
searchTerm ? messages.toolsMatchSearch : messages.toolsCount,
|
|
137
|
+
{
|
|
138
|
+
count: totalResults || 0,
|
|
139
|
+
searchTerm,
|
|
140
|
+
},
|
|
141
|
+
)}
|
|
142
|
+
</div>
|
|
143
|
+
)}
|
|
144
|
+
|
|
120
145
|
<div className="navigator-catalogue-above-results">
|
|
121
146
|
<Menu pointing secondary className="navigator-view-tabs">
|
|
122
147
|
{navigatorResultViews.map((view) => (
|
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Button, Card, Icon } from 'semantic-ui-react';
|
|
3
|
+
import { defineMessages, useIntl } from 'react-intl';
|
|
4
|
+
import { Term } from '@eeacms/search/components';
|
|
5
|
+
import { useSearchContext } from '@eeacms/search/lib/hocs';
|
|
6
|
+
import { markSelectedFacetValuesFromFilters } from '@eeacms/search/lib/search/helpers';
|
|
7
|
+
|
|
8
|
+
export const CHARACTERISATION_FIELD = 'cca_geographic_characterisation.keyword';
|
|
9
|
+
export const TRANSNATIONAL_REGION_FIELD =
|
|
10
|
+
'cca_geographic_transnational_region.keyword';
|
|
11
|
+
export const COUNTRIES_FIELD = 'cca_geographic_countries.keyword';
|
|
12
|
+
|
|
13
|
+
const messages = defineMessages({
|
|
14
|
+
transnationalRegions: {
|
|
15
|
+
id: 'Macro-Transnational region',
|
|
16
|
+
defaultMessage: 'Macro-Transnational region',
|
|
17
|
+
},
|
|
18
|
+
countries: { id: 'Countries', defaultMessage: 'Countries' },
|
|
19
|
+
noOptionsAvailable: {
|
|
20
|
+
id: 'No options available',
|
|
21
|
+
defaultMessage: 'No options available',
|
|
22
|
+
},
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
const valueAsText = (value) =>
|
|
26
|
+
value && typeof value === 'object' && value.name
|
|
27
|
+
? value.name
|
|
28
|
+
: String(value ?? '');
|
|
29
|
+
|
|
30
|
+
export const getFacetOptions = (facets, filters, field) => {
|
|
31
|
+
const facetValue = facets?.[field];
|
|
32
|
+
const facet = Array.isArray(facetValue) ? facetValue[0] : facetValue;
|
|
33
|
+
|
|
34
|
+
return facet?.data
|
|
35
|
+
? markSelectedFacetValuesFromFilters(facet, filters || [], field, 'any')
|
|
36
|
+
.data
|
|
37
|
+
: [];
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
const FacetOption = ({ field, option, onChange }) => {
|
|
41
|
+
const intl = useIntl();
|
|
42
|
+
const value = valueAsText(option.value);
|
|
43
|
+
const inputId = `navigator-geographic-${field}-${value}`.replace(
|
|
44
|
+
/[^a-zA-Z0-9_-]/g,
|
|
45
|
+
'-',
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
return (
|
|
49
|
+
<label htmlFor={inputId} className="sui-multi-checkbox-facet__option-label">
|
|
50
|
+
<span className="sui-multi-checkbox-facet__option-input-wrapper">
|
|
51
|
+
<input
|
|
52
|
+
id={inputId}
|
|
53
|
+
type="checkbox"
|
|
54
|
+
aria-label={value}
|
|
55
|
+
className="sui-multi-checkbox-facet__checkbox"
|
|
56
|
+
checked={Boolean(option.selected)}
|
|
57
|
+
onChange={() => onChange(option)}
|
|
58
|
+
/>
|
|
59
|
+
<span className="checkmark" />
|
|
60
|
+
<span className="sui-multi-checkbox-facet__input-text">
|
|
61
|
+
<Term
|
|
62
|
+
term={intl.formatMessage({
|
|
63
|
+
id: value || 'no-id',
|
|
64
|
+
defaultMessage: value,
|
|
65
|
+
})}
|
|
66
|
+
field={field}
|
|
67
|
+
/>
|
|
68
|
+
</span>
|
|
69
|
+
</span>
|
|
70
|
+
<span className="sui-multi-checkbox-facet__option-count">
|
|
71
|
+
({Number(option.count || 0).toLocaleString('en')})
|
|
72
|
+
</span>
|
|
73
|
+
</label>
|
|
74
|
+
);
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
const ExpandableFacetGroup = ({
|
|
78
|
+
field,
|
|
79
|
+
id,
|
|
80
|
+
label,
|
|
81
|
+
options,
|
|
82
|
+
emptyMessage,
|
|
83
|
+
onChange,
|
|
84
|
+
}) => {
|
|
85
|
+
const hasSelection = options.some(({ selected }) => selected);
|
|
86
|
+
const [isOpen, setIsOpen] = React.useState(hasSelection);
|
|
87
|
+
|
|
88
|
+
React.useEffect(() => {
|
|
89
|
+
if (hasSelection) setIsOpen(true);
|
|
90
|
+
}, [hasSelection]);
|
|
91
|
+
|
|
92
|
+
return (
|
|
93
|
+
<div className="navigator-geographic-facet-group">
|
|
94
|
+
<button
|
|
95
|
+
type="button"
|
|
96
|
+
className={`navigator-geographic-facet-group-toggle${
|
|
97
|
+
isOpen ? ' active' : ''
|
|
98
|
+
}`}
|
|
99
|
+
aria-expanded={isOpen}
|
|
100
|
+
aria-controls={id}
|
|
101
|
+
onClick={() => setIsOpen((current) => !current)}
|
|
102
|
+
>
|
|
103
|
+
<span>{label}</span>
|
|
104
|
+
<Icon name={isOpen ? 'chevron up' : 'chevron down'} />
|
|
105
|
+
</button>
|
|
106
|
+
{isOpen &&
|
|
107
|
+
(options.length > 0 ? (
|
|
108
|
+
<div id={id} className="sui-multi-checkbox-facet">
|
|
109
|
+
{options.map((option) => (
|
|
110
|
+
<FacetOption
|
|
111
|
+
key={valueAsText(option.value)}
|
|
112
|
+
field={field}
|
|
113
|
+
option={option}
|
|
114
|
+
onChange={onChange}
|
|
115
|
+
/>
|
|
116
|
+
))}
|
|
117
|
+
</div>
|
|
118
|
+
) : (
|
|
119
|
+
<div id={id} className="navigator-geographic-facet-empty">
|
|
120
|
+
{emptyMessage}.
|
|
121
|
+
</div>
|
|
122
|
+
))}
|
|
123
|
+
</div>
|
|
124
|
+
);
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
const NavigatorActiveFilters = ({ filters, onRemove }) => {
|
|
128
|
+
const intl = useIntl();
|
|
129
|
+
const geographicFields = [
|
|
130
|
+
CHARACTERISATION_FIELD,
|
|
131
|
+
TRANSNATIONAL_REGION_FIELD,
|
|
132
|
+
COUNTRIES_FIELD,
|
|
133
|
+
];
|
|
134
|
+
const activeFilters = filters.filter(
|
|
135
|
+
({ field, values }) =>
|
|
136
|
+
geographicFields.includes(field) && values?.length > 0,
|
|
137
|
+
);
|
|
138
|
+
|
|
139
|
+
if (!activeFilters.length) return null;
|
|
140
|
+
|
|
141
|
+
return (
|
|
142
|
+
<div className="active-filters">
|
|
143
|
+
<h5>Active filters:</h5>
|
|
144
|
+
<div className="facets-wrapper">
|
|
145
|
+
{activeFilters.flatMap(({ field, values, type }) =>
|
|
146
|
+
values.map((value, index) => (
|
|
147
|
+
<Card key={`${field}-${index}`} className="term active-term">
|
|
148
|
+
<Card.Content>
|
|
149
|
+
<Card.Header className="card-header">
|
|
150
|
+
<Term
|
|
151
|
+
term={intl.formatMessage({
|
|
152
|
+
id: value,
|
|
153
|
+
defaultMessage: value,
|
|
154
|
+
})}
|
|
155
|
+
field={field}
|
|
156
|
+
/>
|
|
157
|
+
<Button
|
|
158
|
+
className="clear-filters"
|
|
159
|
+
onClick={() => onRemove(field, value, type)}
|
|
160
|
+
onKeyDown={(event) => {
|
|
161
|
+
if (event.key === 'Enter') {
|
|
162
|
+
onRemove(field, value, type);
|
|
163
|
+
}
|
|
164
|
+
}}
|
|
165
|
+
>
|
|
166
|
+
<Icon name="close" role="button" />
|
|
167
|
+
</Button>
|
|
168
|
+
</Card.Header>
|
|
169
|
+
</Card.Content>
|
|
170
|
+
</Card>
|
|
171
|
+
)),
|
|
172
|
+
)}
|
|
173
|
+
</div>
|
|
174
|
+
<Button
|
|
175
|
+
size="mini"
|
|
176
|
+
className="clear-btn"
|
|
177
|
+
content="Clear all"
|
|
178
|
+
onClick={() =>
|
|
179
|
+
activeFilters.forEach(({ field, values, type }) =>
|
|
180
|
+
values.forEach((value) => onRemove(field, value, type)),
|
|
181
|
+
)
|
|
182
|
+
}
|
|
183
|
+
/>
|
|
184
|
+
</div>
|
|
185
|
+
);
|
|
186
|
+
};
|
|
187
|
+
|
|
188
|
+
const NavigatorGeographicCoverageFacet = ({
|
|
189
|
+
className = '',
|
|
190
|
+
onRemove,
|
|
191
|
+
onSelect,
|
|
192
|
+
options = [],
|
|
193
|
+
}) => {
|
|
194
|
+
const intl = useIntl();
|
|
195
|
+
const { addFilter, facets, filters = [], removeFilter } = useSearchContext();
|
|
196
|
+
const transnationalOptions = getFacetOptions(
|
|
197
|
+
facets,
|
|
198
|
+
filters,
|
|
199
|
+
TRANSNATIONAL_REGION_FIELD,
|
|
200
|
+
);
|
|
201
|
+
const countryOptions = getFacetOptions(facets, filters, COUNTRIES_FIELD);
|
|
202
|
+
|
|
203
|
+
const updateChildFilter = (field, option) =>
|
|
204
|
+
option.selected
|
|
205
|
+
? removeFilter(field, option.value, 'any')
|
|
206
|
+
: addFilter(field, option.value, 'any');
|
|
207
|
+
|
|
208
|
+
return (
|
|
209
|
+
<fieldset
|
|
210
|
+
className={`sui-facet searchlib-multiterm-facet navigator-geographic-facet ${className}`}
|
|
211
|
+
>
|
|
212
|
+
<div className="sui-multi-checkbox-facet navigator-geographic-facet-direct-options">
|
|
213
|
+
{options.map((option) => (
|
|
214
|
+
<FacetOption
|
|
215
|
+
key={valueAsText(option.value)}
|
|
216
|
+
field={CHARACTERISATION_FIELD}
|
|
217
|
+
option={option}
|
|
218
|
+
onChange={(selectedOption) =>
|
|
219
|
+
selectedOption.selected
|
|
220
|
+
? onRemove(selectedOption.value)
|
|
221
|
+
: onSelect(selectedOption.value)
|
|
222
|
+
}
|
|
223
|
+
/>
|
|
224
|
+
))}
|
|
225
|
+
</div>
|
|
226
|
+
<ExpandableFacetGroup
|
|
227
|
+
field={TRANSNATIONAL_REGION_FIELD}
|
|
228
|
+
id="navigator-geographic-transnational-regions"
|
|
229
|
+
label={intl.formatMessage(messages.transnationalRegions)}
|
|
230
|
+
emptyMessage={intl.formatMessage(messages.noOptionsAvailable)}
|
|
231
|
+
options={transnationalOptions}
|
|
232
|
+
onChange={(option) =>
|
|
233
|
+
updateChildFilter(TRANSNATIONAL_REGION_FIELD, option)
|
|
234
|
+
}
|
|
235
|
+
/>
|
|
236
|
+
<ExpandableFacetGroup
|
|
237
|
+
field={COUNTRIES_FIELD}
|
|
238
|
+
id="navigator-geographic-countries"
|
|
239
|
+
label={intl.formatMessage(messages.countries)}
|
|
240
|
+
emptyMessage={intl.formatMessage(messages.noOptionsAvailable)}
|
|
241
|
+
options={countryOptions}
|
|
242
|
+
onChange={(option) => updateChildFilter(COUNTRIES_FIELD, option)}
|
|
243
|
+
/>
|
|
244
|
+
<NavigatorActiveFilters
|
|
245
|
+
filters={filters}
|
|
246
|
+
onRemove={(field, value, type) => removeFilter(field, value, type)}
|
|
247
|
+
/>
|
|
248
|
+
</fieldset>
|
|
249
|
+
);
|
|
250
|
+
};
|
|
251
|
+
|
|
252
|
+
export default NavigatorGeographicCoverageFacet;
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import '@testing-library/jest-dom';
|
|
3
|
+
import { fireEvent, render, screen } from '@testing-library/react';
|
|
4
|
+
import { IntlProvider } from 'react-intl';
|
|
5
|
+
import { useSearchContext } from '@eeacms/search/lib/hocs';
|
|
6
|
+
import NavigatorGeographicCoverageFacet, {
|
|
7
|
+
COUNTRIES_FIELD,
|
|
8
|
+
TRANSNATIONAL_REGION_FIELD,
|
|
9
|
+
} from './NavigatorGeographicCoverageFacet';
|
|
10
|
+
|
|
11
|
+
jest.mock('@eeacms/search/components', () => ({
|
|
12
|
+
Term: ({ term }) => <>{term}</>,
|
|
13
|
+
}));
|
|
14
|
+
jest.mock('@eeacms/search/lib/hocs', () => ({
|
|
15
|
+
useSearchContext: jest.fn(),
|
|
16
|
+
}));
|
|
17
|
+
|
|
18
|
+
const renderFacet = ({
|
|
19
|
+
filters = [],
|
|
20
|
+
onRemove = jest.fn(),
|
|
21
|
+
onSelect = jest.fn(),
|
|
22
|
+
} = {}) => {
|
|
23
|
+
const addFilter = jest.fn();
|
|
24
|
+
const removeFilter = jest.fn();
|
|
25
|
+
|
|
26
|
+
useSearchContext.mockReturnValue({
|
|
27
|
+
addFilter,
|
|
28
|
+
removeFilter,
|
|
29
|
+
filters,
|
|
30
|
+
facets: {
|
|
31
|
+
[TRANSNATIONAL_REGION_FIELD]: [
|
|
32
|
+
{
|
|
33
|
+
data: [
|
|
34
|
+
{ value: 'Alpine Space', count: 3 },
|
|
35
|
+
{ value: 'Outermost regions', count: 2 },
|
|
36
|
+
],
|
|
37
|
+
},
|
|
38
|
+
],
|
|
39
|
+
[COUNTRIES_FIELD]: [
|
|
40
|
+
{
|
|
41
|
+
data: [
|
|
42
|
+
{ value: 'Germany', count: 4 },
|
|
43
|
+
{ value: 'Spain', count: 2 },
|
|
44
|
+
],
|
|
45
|
+
},
|
|
46
|
+
],
|
|
47
|
+
},
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
render(
|
|
51
|
+
<IntlProvider locale="en">
|
|
52
|
+
<NavigatorGeographicCoverageFacet
|
|
53
|
+
onRemove={onRemove}
|
|
54
|
+
onSelect={onSelect}
|
|
55
|
+
options={[
|
|
56
|
+
{ value: 'Global', count: 5, selected: false },
|
|
57
|
+
{ value: 'Europe', count: 8, selected: false },
|
|
58
|
+
{
|
|
59
|
+
value: 'Macro-Transnational region',
|
|
60
|
+
count: 4,
|
|
61
|
+
selected: false,
|
|
62
|
+
},
|
|
63
|
+
{ value: 'Countries', count: 6, selected: false },
|
|
64
|
+
]}
|
|
65
|
+
/>
|
|
66
|
+
</IntlProvider>,
|
|
67
|
+
);
|
|
68
|
+
|
|
69
|
+
return { addFilter, onRemove, onSelect, removeFilter };
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
describe('NavigatorGeographicCoverageFacet', () => {
|
|
73
|
+
beforeEach(() => {
|
|
74
|
+
jest.clearAllMocks();
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
it('shows Globe and Europe as direct options and filters by the raw value', () => {
|
|
78
|
+
const { onSelect } = renderFacet();
|
|
79
|
+
|
|
80
|
+
expect(screen.getByText('Global')).toBeInTheDocument();
|
|
81
|
+
expect(screen.getByText('Europe')).toBeInTheDocument();
|
|
82
|
+
|
|
83
|
+
fireEvent.click(screen.getByLabelText('Global'));
|
|
84
|
+
|
|
85
|
+
expect(onSelect).toHaveBeenCalledWith('Global');
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
it('expands and filters Macro-Transnational region values', () => {
|
|
89
|
+
const { addFilter } = renderFacet();
|
|
90
|
+
|
|
91
|
+
fireEvent.click(
|
|
92
|
+
screen.getByRole('button', { name: 'Macro-Transnational region' }),
|
|
93
|
+
);
|
|
94
|
+
fireEvent.click(screen.getByLabelText('Outermost regions'));
|
|
95
|
+
|
|
96
|
+
expect(addFilter).toHaveBeenCalledWith(
|
|
97
|
+
TRANSNATIONAL_REGION_FIELD,
|
|
98
|
+
'Outermost regions',
|
|
99
|
+
'any',
|
|
100
|
+
);
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
it('opens Countries when it contains an active selection and removes it', () => {
|
|
104
|
+
const { removeFilter } = renderFacet({
|
|
105
|
+
filters: [
|
|
106
|
+
{
|
|
107
|
+
field: COUNTRIES_FIELD,
|
|
108
|
+
values: ['Germany'],
|
|
109
|
+
type: 'any',
|
|
110
|
+
},
|
|
111
|
+
],
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
fireEvent.click(screen.getByLabelText('Germany'));
|
|
115
|
+
|
|
116
|
+
expect(removeFilter).toHaveBeenCalledWith(
|
|
117
|
+
COUNTRIES_FIELD,
|
|
118
|
+
'Germany',
|
|
119
|
+
'any',
|
|
120
|
+
);
|
|
121
|
+
});
|
|
122
|
+
});
|
package/src/index.js
CHANGED
|
@@ -54,6 +54,7 @@ import ClusterHorizontalCardItem from './components/Search/Result/ClusterHorizon
|
|
|
54
54
|
import NavigatorCatalogueCardItem from './components/Search/NavigatorCatalogue/NavigatorCatalogueCardItem';
|
|
55
55
|
import NavigatorCatalogueMapView from './components/Search/NavigatorCatalogue/NavigatorCatalogueMapView';
|
|
56
56
|
import NavigatorCatalogueContentView from './components/Search/NavigatorCatalogue/NavigatorCatalogueContentView';
|
|
57
|
+
import NavigatorGeographicCoverageFacet from './components/Search/NavigatorCatalogue/NavigatorGeographicCoverageFacet';
|
|
57
58
|
import NavigatorGuideLayout from './components/Search/NavigatorGuide/NavigatorGuideLayout';
|
|
58
59
|
import NavigatorGuideContentView from './components/Search/NavigatorGuide/NavigatorGuideContentView';
|
|
59
60
|
|
|
@@ -434,6 +435,10 @@ const applyConfig = (config) => {
|
|
|
434
435
|
config.settings.searchlib.resolve.NavigatorCatalogueContentView = {
|
|
435
436
|
component: NavigatorCatalogueContentView,
|
|
436
437
|
};
|
|
438
|
+
config.settings.searchlib.resolve.NavigatorGeographicCoverageFacet = {
|
|
439
|
+
...config.settings.searchlib.resolve.MultiTermFacet,
|
|
440
|
+
component: NavigatorGeographicCoverageFacet,
|
|
441
|
+
};
|
|
437
442
|
config.settings.searchlib.resolve.NavigatorGuideLayout = {
|
|
438
443
|
component: NavigatorGuideLayout,
|
|
439
444
|
};
|
|
@@ -7,6 +7,14 @@ import {
|
|
|
7
7
|
} from './../common';
|
|
8
8
|
|
|
9
9
|
const messages = defineMessages({
|
|
10
|
+
geographicCoverage: {
|
|
11
|
+
id: 'Geographic coverage',
|
|
12
|
+
defaultMessage: 'Geographic coverage',
|
|
13
|
+
},
|
|
14
|
+
macroTransnationalRegion: {
|
|
15
|
+
id: 'Macro-Transnational region',
|
|
16
|
+
defaultMessage: 'Macro-Transnational region',
|
|
17
|
+
},
|
|
10
18
|
climateHazards: {
|
|
11
19
|
id: 'Climate hazards',
|
|
12
20
|
defaultMessage: 'Climate hazards',
|
|
@@ -59,7 +67,28 @@ const facets = [
|
|
|
59
67
|
label: messages.implementationLevel,
|
|
60
68
|
alwaysVisible: false,
|
|
61
69
|
}),
|
|
62
|
-
|
|
70
|
+
multiTermFacet({
|
|
71
|
+
field: 'cca_geographic_characterisation.keyword',
|
|
72
|
+
factory: 'NavigatorGeographicCoverageFacet',
|
|
73
|
+
isFilterable: false,
|
|
74
|
+
isMulti: true,
|
|
75
|
+
label: messages.geographicCoverage,
|
|
76
|
+
hideActiveFilters: true,
|
|
77
|
+
alwaysVisible: true,
|
|
78
|
+
}),
|
|
79
|
+
multiTermFacet({
|
|
80
|
+
field: 'cca_geographic_transnational_region.keyword',
|
|
81
|
+
isFilterable: false,
|
|
82
|
+
isFilter: true,
|
|
83
|
+
isMulti: true,
|
|
84
|
+
label: messages.macroTransnationalRegion,
|
|
85
|
+
showInFacetsList: true,
|
|
86
|
+
}),
|
|
87
|
+
{
|
|
88
|
+
...geographic_countries,
|
|
89
|
+
isFilter: true,
|
|
90
|
+
showInFacetsList: true,
|
|
91
|
+
},
|
|
63
92
|
multiTermFacet({
|
|
64
93
|
field: 'cca_adaptation_support_cycle_step.keyword',
|
|
65
94
|
isFilterable: false,
|
|
@@ -107,6 +107,65 @@
|
|
|
107
107
|
}
|
|
108
108
|
}
|
|
109
109
|
|
|
110
|
+
.navigator-catalogue-result-count {
|
|
111
|
+
margin-bottom: 1em;
|
|
112
|
+
font-weight: 700;
|
|
113
|
+
font-size: 1.5rem;
|
|
114
|
+
|
|
115
|
+
.navigator-catalogue-result-count-value {
|
|
116
|
+
color: @primaryColor;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
.navigator-geographic-facet {
|
|
121
|
+
min-width: 18rem;
|
|
122
|
+
|
|
123
|
+
.navigator-geographic-facet-group {
|
|
124
|
+
border-top: 1px solid @navigatorBorderColor;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
.navigator-geographic-facet-group-toggle {
|
|
128
|
+
display: flex;
|
|
129
|
+
width: 100%;
|
|
130
|
+
align-items: center;
|
|
131
|
+
justify-content: space-between;
|
|
132
|
+
padding: 0.65em 0.5em;
|
|
133
|
+
border: 0;
|
|
134
|
+
background: transparent;
|
|
135
|
+
color: inherit;
|
|
136
|
+
cursor: pointer;
|
|
137
|
+
font-family: inherit;
|
|
138
|
+
font-size: 14px;
|
|
139
|
+
font-weight: 500;
|
|
140
|
+
text-align: left;
|
|
141
|
+
|
|
142
|
+
&.active {
|
|
143
|
+
background: @navigatorCriteriaBackgroundColor;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
i.icon {
|
|
147
|
+
width: auto;
|
|
148
|
+
height: auto;
|
|
149
|
+
margin: 0 0 0 1rem;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
#navigator-geographic-countries {
|
|
154
|
+
column-count: 2;
|
|
155
|
+
column-gap: 1rem;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
.sui-multi-checkbox-facet
|
|
159
|
+
.sui-multi-checkbox-facet__option-label:first-child {
|
|
160
|
+
margin-top: 0;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
.navigator-geographic-facet-empty {
|
|
165
|
+
padding: 0.8em 0.5em;
|
|
166
|
+
font-size: 14px;
|
|
167
|
+
}
|
|
168
|
+
|
|
110
169
|
.catalogue-compare-panel {
|
|
111
170
|
position: fixed;
|
|
112
171
|
z-index: 1000;
|