@eeacms/volto-globalsearch 0.1.0
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/.coverage.babel.config.js +9 -0
- package/.eslintignore +1 -0
- package/.project.eslintrc.js +46 -0
- package/.release-it.json +17 -0
- package/CHANGELOG.md +26 -0
- package/DEVELOP.md +52 -0
- package/LICENSE.md +9 -0
- package/README.md +106 -0
- package/RELEASE.md +74 -0
- package/babel.config.js +17 -0
- package/bootstrap +41 -0
- package/cypress.json +17 -0
- package/jest-addon.config.js +36 -0
- package/locales/volto.pot +0 -0
- package/package.json +47 -0
- package/src/components/LogoImage.jsx +16 -0
- package/src/components/MasonryLandingPage.jsx +277 -0
- package/src/components/WebsiteFilterListComponent.jsx +14 -0
- package/src/components/img/content-types-bg.png +0 -0
- package/src/components/img/countries-bg.png +0 -0
- package/src/components/img/organisations-bg.png +0 -0
- package/src/components/img/search-album-slideshow-bg.png +0 -0
- package/src/components/img/topics-bg.png +0 -0
- package/src/config/clusters.js +172 -0
- package/src/config/download.js +20 -0
- package/src/config/facets.js +298 -0
- package/src/config/filters.js +15 -0
- package/src/config/global-search-config.js +118 -0
- package/src/config/index.js +92 -0
- package/src/config/json/contentTypeNormalize.json +56 -0
- package/src/config/json/objectProvidesWhitelist.json +56 -0
- package/src/config/json/placesBlacklist.json +268 -0
- package/src/config/json/spatialWhitelist.json +264 -0
- package/src/config/json/topicsBlacklist.json +1 -0
- package/src/config/json/typesWhitelist.json +49 -0
- package/src/config/query.js +44 -0
- package/src/config/views.js +157 -0
- package/src/config/vocabulary.js +59 -0
- package/src/index.js +13 -0
- package/src/static/bise-logo.png +0 -0
- package/src/static/climate-adapt-logo.png +0 -0
- package/src/static/eea-logo.png +0 -0
- package/src/static/eionet-logo.png +0 -0
- package/src/static/energy-logo.png +0 -0
- package/src/static/etc-atni.png +0 -0
- package/src/static/etc-bd.jpg +0 -0
- package/src/static/etc-cca.jpeg +0 -0
- package/src/static/etc-cme.png +0 -0
- package/src/static/etc-icm.jpg +0 -0
- package/src/static/etc-uls.png +0 -0
- package/src/static/etc-wmge.png +0 -0
- package/src/static/forest-logo.png +0 -0
- package/src/static/ias-logo.png +0 -0
- package/src/static/industry-logo.png +0 -0
- package/src/static/water-logo.png +0 -0
- package/src/static/website-logo.png +0 -0
- package/src/static/wise-logo.png +0 -0
- package/src/styles/masonry-landing-page.less +145 -0
- package/src/styles/tiles-landing-page.less +0 -0
- package/src/utils.js +250 -0
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import Masonry from 'react-masonry-component';
|
|
3
|
+
|
|
4
|
+
import { runRequest } from '@eeacms/search';
|
|
5
|
+
|
|
6
|
+
import objectProvidesWhitelist from '../config/json/objectProvidesWhitelist.json';
|
|
7
|
+
import spatialWhitelist from '../config/json/spatialWhitelist.json';
|
|
8
|
+
|
|
9
|
+
import { getTodayWithTime } from '../utils';
|
|
10
|
+
|
|
11
|
+
import '../styles/masonry-landing-page.less';
|
|
12
|
+
|
|
13
|
+
const RES_REQUEST = {
|
|
14
|
+
// es_query_metadata: {
|
|
15
|
+
// query_type: 'landing page documents',
|
|
16
|
+
// },
|
|
17
|
+
query: {
|
|
18
|
+
function_score: {
|
|
19
|
+
query: {
|
|
20
|
+
bool: {
|
|
21
|
+
must: [
|
|
22
|
+
{
|
|
23
|
+
match_all: {},
|
|
24
|
+
},
|
|
25
|
+
],
|
|
26
|
+
filter: [
|
|
27
|
+
{
|
|
28
|
+
term: {
|
|
29
|
+
hasWorkflowState: 'published',
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
constant_score: {
|
|
34
|
+
filter: {
|
|
35
|
+
bool: {
|
|
36
|
+
should: [
|
|
37
|
+
{
|
|
38
|
+
bool: {
|
|
39
|
+
must_not: {
|
|
40
|
+
exists: {
|
|
41
|
+
field: 'issued',
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
range: {
|
|
48
|
+
'issued.date': {
|
|
49
|
+
lte: getTodayWithTime(),
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
],
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
constant_score: {
|
|
60
|
+
filter: {
|
|
61
|
+
bool: {
|
|
62
|
+
should: [
|
|
63
|
+
{
|
|
64
|
+
bool: {
|
|
65
|
+
must_not: {
|
|
66
|
+
exists: {
|
|
67
|
+
field: 'expires',
|
|
68
|
+
},
|
|
69
|
+
},
|
|
70
|
+
},
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
range: {
|
|
74
|
+
expires: {
|
|
75
|
+
gte: getTodayWithTime(),
|
|
76
|
+
},
|
|
77
|
+
},
|
|
78
|
+
},
|
|
79
|
+
],
|
|
80
|
+
},
|
|
81
|
+
},
|
|
82
|
+
},
|
|
83
|
+
},
|
|
84
|
+
],
|
|
85
|
+
},
|
|
86
|
+
},
|
|
87
|
+
},
|
|
88
|
+
},
|
|
89
|
+
sort: [
|
|
90
|
+
{
|
|
91
|
+
'issued.index': {
|
|
92
|
+
order: 'desc',
|
|
93
|
+
},
|
|
94
|
+
},
|
|
95
|
+
],
|
|
96
|
+
size: 3,
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
const AGGS_REQUEST = {
|
|
100
|
+
// es_query_metadata: {
|
|
101
|
+
// query_type: 'landing page',
|
|
102
|
+
// },
|
|
103
|
+
query: {
|
|
104
|
+
bool: {
|
|
105
|
+
must: [
|
|
106
|
+
{
|
|
107
|
+
match_all: {},
|
|
108
|
+
},
|
|
109
|
+
],
|
|
110
|
+
},
|
|
111
|
+
},
|
|
112
|
+
|
|
113
|
+
aggs: {
|
|
114
|
+
languages: {
|
|
115
|
+
terms: {
|
|
116
|
+
field: 'language',
|
|
117
|
+
size: 1000000,
|
|
118
|
+
},
|
|
119
|
+
},
|
|
120
|
+
topics: {
|
|
121
|
+
terms: {
|
|
122
|
+
field: 'topic',
|
|
123
|
+
size: 1000000,
|
|
124
|
+
},
|
|
125
|
+
},
|
|
126
|
+
organisations: {
|
|
127
|
+
terms: {
|
|
128
|
+
field: 'organisation',
|
|
129
|
+
size: 1000000,
|
|
130
|
+
},
|
|
131
|
+
},
|
|
132
|
+
content_types: {
|
|
133
|
+
terms: {
|
|
134
|
+
field: 'objectProvides',
|
|
135
|
+
size: 1000000,
|
|
136
|
+
},
|
|
137
|
+
},
|
|
138
|
+
countries: {
|
|
139
|
+
terms: {
|
|
140
|
+
field: 'spatial',
|
|
141
|
+
size: 1000000,
|
|
142
|
+
},
|
|
143
|
+
},
|
|
144
|
+
max_timecoverage: {
|
|
145
|
+
max: {
|
|
146
|
+
script:
|
|
147
|
+
"def vals = doc['time_coverage']; if (vals.length == 0){return 2000} else {def ret = [];for (val in vals){def tmp_val = val.substring(0,4);ret.add(tmp_val.toLowerCase() == tmp_val.toUpperCase() ? Integer.parseInt(tmp_val) : 2000);}return ret;}",
|
|
148
|
+
},
|
|
149
|
+
},
|
|
150
|
+
min_timecoverage: {
|
|
151
|
+
min: {
|
|
152
|
+
script:
|
|
153
|
+
"def vals = doc['time_coverage']; if (vals.length == 0){return 2000} else {def ret = [];for (val in vals){def tmp_val = val.substring(0,4);ret.add(tmp_val.toLowerCase() == tmp_val.toUpperCase() ? Integer.parseInt(tmp_val) : 2000);}return ret;}",
|
|
154
|
+
},
|
|
155
|
+
},
|
|
156
|
+
},
|
|
157
|
+
size: 0,
|
|
158
|
+
track_total_hits: true,
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
const LandingPage = (props) => {
|
|
162
|
+
const { appConfig } = props;
|
|
163
|
+
const [landingDataAggs, setLandingDataAggs] = React.useState();
|
|
164
|
+
const [landingDataRes, setLandingDataRes] = React.useState();
|
|
165
|
+
const alreadyRequested = React.useRef(false);
|
|
166
|
+
|
|
167
|
+
React.useEffect(() => {
|
|
168
|
+
async function fetchDataAggs() {
|
|
169
|
+
if (!alreadyRequested.current) {
|
|
170
|
+
const resp = await runRequest(AGGS_REQUEST, appConfig);
|
|
171
|
+
setLandingDataAggs(resp.body);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// console.log('request config: ', RES_REQUEST);
|
|
176
|
+
async function fetchDataRes() {
|
|
177
|
+
if (!alreadyRequested.current) {
|
|
178
|
+
const resp = await runRequest(RES_REQUEST, appConfig);
|
|
179
|
+
setLandingDataRes(resp.body);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
Promise.all([fetchDataAggs(), fetchDataRes()]).then(() => {
|
|
184
|
+
alreadyRequested.current = true;
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
return () => {
|
|
188
|
+
alreadyRequested.current = true;
|
|
189
|
+
};
|
|
190
|
+
}, [appConfig]);
|
|
191
|
+
|
|
192
|
+
// console.log(landingDataAggs, landingDataRes);
|
|
193
|
+
if (landingDataAggs?.hits && landingDataRes?.hits) {
|
|
194
|
+
const total = landingDataAggs.hits?.total?.value;
|
|
195
|
+
const min_time_coverage =
|
|
196
|
+
landingDataAggs.aggregations.min_timecoverage.value;
|
|
197
|
+
const max_time_coverage =
|
|
198
|
+
landingDataAggs.aggregations.max_timecoverage.value;
|
|
199
|
+
const organisations =
|
|
200
|
+
landingDataAggs.aggregations.organisations.buckets.length;
|
|
201
|
+
const topics = landingDataAggs.aggregations.topics.buckets.length;
|
|
202
|
+
const languages = landingDataAggs.aggregations.languages.buckets.length;
|
|
203
|
+
const content_types = landingDataAggs.aggregations.content_types.buckets.filter(
|
|
204
|
+
(bucket) => objectProvidesWhitelist.indexOf(bucket.key) !== -1,
|
|
205
|
+
).length;
|
|
206
|
+
const countries = landingDataAggs.aggregations.countries.buckets.filter(
|
|
207
|
+
(bucket) => spatialWhitelist.indexOf(bucket.key) !== -1,
|
|
208
|
+
).length;
|
|
209
|
+
const elements = landingDataRes.hits.hits;
|
|
210
|
+
|
|
211
|
+
return (
|
|
212
|
+
<div className="landing-page">
|
|
213
|
+
<Masonry options={{ horizontalOrder: true }}>
|
|
214
|
+
<div className="tile available_content">
|
|
215
|
+
<h2>
|
|
216
|
+
Instantly search over 20 years of environmental knowledge by EEA
|
|
217
|
+
</h2>
|
|
218
|
+
<h3>Documents</h3>
|
|
219
|
+
<span>{total}</span>
|
|
220
|
+
<h3>Languages</h3>
|
|
221
|
+
<span>{languages}</span>
|
|
222
|
+
</div>
|
|
223
|
+
|
|
224
|
+
<div className="tile picture"></div>
|
|
225
|
+
|
|
226
|
+
<div className="tile topics">
|
|
227
|
+
<h2>Topics</h2>
|
|
228
|
+
<span>{topics}</span>
|
|
229
|
+
</div>
|
|
230
|
+
|
|
231
|
+
<div className="tile time_coverage">
|
|
232
|
+
<h2>Time coverage</h2>
|
|
233
|
+
<p>
|
|
234
|
+
<span className="label">from</span>
|
|
235
|
+
<span className="value">{min_time_coverage}</span>
|
|
236
|
+
</p>
|
|
237
|
+
<p>
|
|
238
|
+
<span className="label">to</span>
|
|
239
|
+
<span className="value">{max_time_coverage}</span>
|
|
240
|
+
</p>
|
|
241
|
+
</div>
|
|
242
|
+
<div className="tile organisations">
|
|
243
|
+
<h2>Organisations</h2>
|
|
244
|
+
<span>{organisations}</span>
|
|
245
|
+
</div>
|
|
246
|
+
|
|
247
|
+
<div className="tile content_types">
|
|
248
|
+
<h2>Content Types</h2>
|
|
249
|
+
<span>{content_types}</span>
|
|
250
|
+
</div>
|
|
251
|
+
<div className="tile countries">
|
|
252
|
+
<h2>Countries</h2>
|
|
253
|
+
<span>{countries}</span>
|
|
254
|
+
</div>
|
|
255
|
+
<div className="tile latest">
|
|
256
|
+
<h2>Recently added</h2>
|
|
257
|
+
<ul>
|
|
258
|
+
{elements.map((element, i) => {
|
|
259
|
+
const { about, title, issued } = element._source;
|
|
260
|
+
return (
|
|
261
|
+
<li key={i}>
|
|
262
|
+
<a href={about}>{title}</a>
|
|
263
|
+
<span>Published on </span>
|
|
264
|
+
<span>{issued}</span>
|
|
265
|
+
</li>
|
|
266
|
+
);
|
|
267
|
+
})}
|
|
268
|
+
</ul>
|
|
269
|
+
</div>
|
|
270
|
+
</Masonry>
|
|
271
|
+
</div>
|
|
272
|
+
);
|
|
273
|
+
} else {
|
|
274
|
+
return '';
|
|
275
|
+
}
|
|
276
|
+
};
|
|
277
|
+
export default LandingPage;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
// import React from 'react';
|
|
2
|
+
// import { Icon } from '@eeacms/search';
|
|
3
|
+
//
|
|
4
|
+
// const WebsiteFilterListComponent = (props) => {
|
|
5
|
+
// const { value } = props;
|
|
6
|
+
// return (
|
|
7
|
+
// <span>
|
|
8
|
+
// <Icon family="Sources" type={value} className="facet-option-icon" />
|
|
9
|
+
// {value}
|
|
10
|
+
// </span>
|
|
11
|
+
// );
|
|
12
|
+
// };
|
|
13
|
+
//
|
|
14
|
+
// export default WebsiteFilterListComponent;
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import { get_cluster_icons_dict, get_cluster_icons } from '../utils';
|
|
2
|
+
|
|
3
|
+
export const clusters = {
|
|
4
|
+
name: 'op_cluster',
|
|
5
|
+
field: 'objectProvides',
|
|
6
|
+
clusters: [
|
|
7
|
+
{
|
|
8
|
+
name: 'News',
|
|
9
|
+
icon: { name: 'bullhorn' },
|
|
10
|
+
values: ['News', 'Article'],
|
|
11
|
+
defaultResultView: 'horizontalCard',
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
name: 'Publications',
|
|
15
|
+
icon: { name: 'book' },
|
|
16
|
+
values: [
|
|
17
|
+
'Report',
|
|
18
|
+
'Indicator',
|
|
19
|
+
'Briefing',
|
|
20
|
+
'Topic page',
|
|
21
|
+
'Country fact sheet',
|
|
22
|
+
],
|
|
23
|
+
defaultResultView: 'horizontalCard',
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
name: 'Maps and charts',
|
|
27
|
+
icon: { name: 'chart area' },
|
|
28
|
+
values: [
|
|
29
|
+
'Figure (chart/map)',
|
|
30
|
+
'Chart (interactive)',
|
|
31
|
+
'Infographic',
|
|
32
|
+
'Dashboard',
|
|
33
|
+
'Map (interactive)',
|
|
34
|
+
],
|
|
35
|
+
defaultResultView: 'card',
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
name: 'Data',
|
|
39
|
+
icon: { name: 'database' },
|
|
40
|
+
values: ['External data reference', 'Data set'],
|
|
41
|
+
defaultResultView: 'horizontalCard',
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
name: 'Others',
|
|
45
|
+
icon: { name: 'copy outline' },
|
|
46
|
+
values: [
|
|
47
|
+
'Webpage',
|
|
48
|
+
'Organisation',
|
|
49
|
+
'FAQ',
|
|
50
|
+
'Video',
|
|
51
|
+
'Contract opportunity',
|
|
52
|
+
'Glossary term',
|
|
53
|
+
'Collection',
|
|
54
|
+
'File',
|
|
55
|
+
'Adaptation option',
|
|
56
|
+
'Guidance',
|
|
57
|
+
'Research and knowledge project',
|
|
58
|
+
'Information portal',
|
|
59
|
+
'Tool',
|
|
60
|
+
'Case study',
|
|
61
|
+
], // this will be transformed in "single type clusters".
|
|
62
|
+
defaultResultView: 'horizontalCard',
|
|
63
|
+
},
|
|
64
|
+
],
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
// Add "Others", a menu with subgroups.
|
|
68
|
+
|
|
69
|
+
export const clusterIcons = get_cluster_icons(clusters);
|
|
70
|
+
|
|
71
|
+
export default {
|
|
72
|
+
icons: {
|
|
73
|
+
'Content types': get_cluster_icons_dict(clusters),
|
|
74
|
+
Sources: {
|
|
75
|
+
fallback: {
|
|
76
|
+
url: require('../static/website-logo.png'),
|
|
77
|
+
},
|
|
78
|
+
eea: {
|
|
79
|
+
url: require('../static/eea-logo.png'),
|
|
80
|
+
},
|
|
81
|
+
ias: {
|
|
82
|
+
url: require('../static/ias-logo.png'),
|
|
83
|
+
},
|
|
84
|
+
bise: {
|
|
85
|
+
url: require('../static/bise-logo.png'),
|
|
86
|
+
},
|
|
87
|
+
'wise-marine': {
|
|
88
|
+
url: require('../static/wise-logo.png'),
|
|
89
|
+
},
|
|
90
|
+
energy: {
|
|
91
|
+
url: require('../static/energy-logo.png'),
|
|
92
|
+
},
|
|
93
|
+
'wise-freshwater': {
|
|
94
|
+
url: require('../static/water-logo.png'),
|
|
95
|
+
},
|
|
96
|
+
fise: {
|
|
97
|
+
url: require('../static/forest-logo.png'),
|
|
98
|
+
},
|
|
99
|
+
industry: {
|
|
100
|
+
url: require('../static/industry-logo.png'),
|
|
101
|
+
},
|
|
102
|
+
cca: {
|
|
103
|
+
url: require('../static/climate-adapt-logo.png'),
|
|
104
|
+
},
|
|
105
|
+
etc: {
|
|
106
|
+
url: require('../static/eionet-logo.png'),
|
|
107
|
+
},
|
|
108
|
+
'etc-atni': {
|
|
109
|
+
url: require('../static/etc-atni.png'),
|
|
110
|
+
},
|
|
111
|
+
|
|
112
|
+
'etc-bd': {
|
|
113
|
+
url: require('../static/etc-bd.jpg'),
|
|
114
|
+
},
|
|
115
|
+
|
|
116
|
+
'etc-cca': {
|
|
117
|
+
url: require('../static/etc-cca.jpeg'),
|
|
118
|
+
},
|
|
119
|
+
|
|
120
|
+
'etc-cme': {
|
|
121
|
+
url: require('../static/etc-cme.png'),
|
|
122
|
+
},
|
|
123
|
+
|
|
124
|
+
'etc-icm': {
|
|
125
|
+
url: require('../static/etc-icm.jpg'),
|
|
126
|
+
},
|
|
127
|
+
|
|
128
|
+
'etc-uls': {
|
|
129
|
+
url: require('../static/etc-uls.png'),
|
|
130
|
+
},
|
|
131
|
+
|
|
132
|
+
'etc-wmge': {
|
|
133
|
+
url: require('../static/etc-wmge.png'),
|
|
134
|
+
},
|
|
135
|
+
},
|
|
136
|
+
Countries: {
|
|
137
|
+
fallback: {
|
|
138
|
+
country: 'placeholder',
|
|
139
|
+
},
|
|
140
|
+
},
|
|
141
|
+
},
|
|
142
|
+
|
|
143
|
+
contentSectionsParams: {
|
|
144
|
+
// This enables the content as section tabs
|
|
145
|
+
enable: true,
|
|
146
|
+
sectionFacetsField: 'op_cluster',
|
|
147
|
+
sections: clusters.clusters,
|
|
148
|
+
clusterMapping: Object.assign(
|
|
149
|
+
{},
|
|
150
|
+
...clusters.clusters.map(({ name, values }) =>
|
|
151
|
+
Object.assign({}, ...values.map((v) => ({ [v]: name }))),
|
|
152
|
+
),
|
|
153
|
+
),
|
|
154
|
+
},
|
|
155
|
+
};
|
|
156
|
+
|
|
157
|
+
export function typesForClustersOptionsFilter(options, filters) {
|
|
158
|
+
// Only display content types that belong to the currently selected cluster
|
|
159
|
+
const clusterMap = Object.assign(
|
|
160
|
+
{},
|
|
161
|
+
...clusters.clusters.map(({ name, values }) =>
|
|
162
|
+
Object.assign({}, ...values.map((v) => ({ [v]: name }))),
|
|
163
|
+
),
|
|
164
|
+
);
|
|
165
|
+
|
|
166
|
+
const clusterFilter = filters?.find((f) => f.field === 'op_cluster');
|
|
167
|
+
const activeCluster = clusterFilter?.values?.[0];
|
|
168
|
+
|
|
169
|
+
return activeCluster
|
|
170
|
+
? options.filter((f) => clusterMap[f.value] === activeCluster)
|
|
171
|
+
: options;
|
|
172
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
download_fields: [
|
|
3
|
+
{
|
|
4
|
+
field: 'about',
|
|
5
|
+
name: 'About',
|
|
6
|
+
},
|
|
7
|
+
{
|
|
8
|
+
field: 'description',
|
|
9
|
+
name: 'Description',
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
field: 'subject',
|
|
13
|
+
name: 'Subject',
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
field: 'issued',
|
|
17
|
+
name: 'Issued',
|
|
18
|
+
},
|
|
19
|
+
],
|
|
20
|
+
};
|