@eeacms/volto-cca-policy 0.2.69 → 0.2.71
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 +33 -0
- package/package.json +2 -2
- package/src/components/Result/ClusterHorizontalCardItem.jsx +136 -0
- package/src/components/manage/Blocks/C3SIndicatorsGlossaryBlock/C3SIndicatorsGlossaryBlockView.test.jsx +34 -0
- package/src/components/manage/Blocks/C3SIndicatorsListingBlock/C3SIndicatorsListingBlockView.test.jsx +43 -0
- package/src/components/manage/Blocks/CaseStudyExplorer/CaseStudyExplorerEdit.test.jsx +89 -0
- package/src/components/manage/Blocks/CaseStudyExplorer/CaseStudyExplorerView.test.jsx +93 -0
- package/src/components/manage/Blocks/CaseStudyExplorer/CaseStudyMap.jsx +13 -79
- package/src/components/manage/Blocks/CaseStudyExplorer/CaseStudyMap.test.jsx +131 -0
- package/src/components/manage/Blocks/CaseStudyExplorer/FeatureDisplay.jsx +5 -1
- package/src/components/manage/Blocks/CaseStudyExplorer/FeatureDisplay.test.jsx +59 -0
- package/src/components/manage/Blocks/CaseStudyExplorer/FeatureInteraction.jsx +132 -53
- package/src/components/manage/Blocks/CaseStudyExplorer/styles.less +4 -0
- package/src/components/manage/Blocks/CaseStudyExplorer/useInteractiveStyles.jsx +189 -0
- package/src/components/manage/Blocks/MKHMap/InfoOverlay.jsx +20 -8
- package/src/components/manage/Blocks/MKHMap/View.jsx +1 -1
- package/src/components/theme/ImageGallery/styles.less +1 -1
- package/src/index.js +4 -1
- package/src/search/config.js +79 -26
- package/src/search/facets.js +12 -1
- package/src/search/views.js +15 -0
- package/src/components/manage/Blocks/CaseStudyExplorer/InfoOverlay.jsx +0 -80
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,39 @@ 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
|
+
### [0.2.71](https://github.com/eea/volto-cca-policy/compare/0.2.70...0.2.71) - 9 October 2024
|
|
8
|
+
|
|
9
|
+
#### :hammer_and_wrench: Others
|
|
10
|
+
|
|
11
|
+
- core: update volto-datablocks version - refs #277718 [kreafox - [`a1dc7c7`](https://github.com/eea/volto-cca-policy/commit/a1dc7c768fe400406854cbc496545034748bad37)]
|
|
12
|
+
### [0.2.70](https://github.com/eea/volto-cca-policy/compare/0.2.69...0.2.70) - 7 October 2024
|
|
13
|
+
|
|
14
|
+
#### :hammer_and_wrench: Others
|
|
15
|
+
|
|
16
|
+
- test: increase code coverage [kreafox - [`caa04c2`](https://github.com/eea/volto-cca-policy/commit/caa04c2cf23879d937d19f49fb9be38289a96f4a)]
|
|
17
|
+
- Refs #272477 - add more test [Tripon Eugen - [`65cafca`](https://github.com/eea/volto-cca-policy/commit/65cafca45e03ec27bb9aae3b346bc50a0ed00c20)]
|
|
18
|
+
- Refs #272477 - test update [Tripon Eugen - [`7c99ffc`](https://github.com/eea/volto-cca-policy/commit/7c99ffc6013ebd9a0625acce762f7069648037c7)]
|
|
19
|
+
- Refs #272477 - test [Tripon Eugen - [`c60ab3e`](https://github.com/eea/volto-cca-policy/commit/c60ab3e7e07b0f9493386f74a1c6f3658aef74cf)]
|
|
20
|
+
- Refs #Q272477 - test [Tripon Eugen - [`8a67efa`](https://github.com/eea/volto-cca-policy/commit/8a67efacc1e38801f4d30de28002eae7ef45b61b)]
|
|
21
|
+
- test: increase code coverage [kreafox - [`82e5828`](https://github.com/eea/volto-cca-policy/commit/82e5828d44f7c848fccab13d2e224eb4239b15c3)]
|
|
22
|
+
- Don't need background [Tiberiu Ichim - [`233be07`](https://github.com/eea/volto-cca-policy/commit/233be07bc6208bb37d76678688799a0934be4a78)]
|
|
23
|
+
- Port InfoOverlay from casestudymap [Tiberiu Ichim - [`96f61d7`](https://github.com/eea/volto-cca-policy/commit/96f61d7af9d09d76c74714921d7f8b6b7b277137)]
|
|
24
|
+
- Open link in new window [Tiberiu Ichim - [`3b94048`](https://github.com/eea/volto-cca-policy/commit/3b94048b4d5c23b5faa97bd5d8ae3a01d146a215)]
|
|
25
|
+
- Add test [Tiberiu Ichim - [`31b3a80`](https://github.com/eea/volto-cca-policy/commit/31b3a8053388cdcdd0b4b2d7fc90ea0e39aaf18f)]
|
|
26
|
+
- Remove unused file [Tiberiu Ichim - [`915dbf4`](https://github.com/eea/volto-cca-policy/commit/915dbf4e06cd46fbea5b36d8f7f31e72f3610f27)]
|
|
27
|
+
- Remove console.log [Tiberiu Ichim - [`9cf77d8`](https://github.com/eea/volto-cca-policy/commit/9cf77d8cc5999cf52ce231e1179dfd54538d0b4d)]
|
|
28
|
+
- Remove console.log [Tiberiu Ichim - [`04949b7`](https://github.com/eea/volto-cca-policy/commit/04949b70ee741aa54aacccd2eebe8c529b0367f1)]
|
|
29
|
+
- WIP [Tiberiu Ichim - [`101d459`](https://github.com/eea/volto-cca-policy/commit/101d459ad818f274f8e74fd77e8847e6c6c09384)]
|
|
30
|
+
- WIP [Tiberiu Ichim - [`9f18518`](https://github.com/eea/volto-cca-policy/commit/9f18518021a3750626bdff9e3f6f78344c5b8e9a)]
|
|
31
|
+
- WIP [Tiberiu Ichim - [`2cb4ecb`](https://github.com/eea/volto-cca-policy/commit/2cb4ecb052f3ba951b317a8830ecbb09c7d388b6)]
|
|
32
|
+
- eslint [Tripon Eugen - [`e1f3bb2`](https://github.com/eea/volto-cca-policy/commit/e1f3bb252c6e3e615f63cb7747324c569b832b11)]
|
|
33
|
+
- Refs #272477 - view horizontal card eslint [Tripon Eugen - [`da0df68`](https://github.com/eea/volto-cca-policy/commit/da0df6829296b33d483c3880a7c39ecdf803caee)]
|
|
34
|
+
- Refs #272477 - view horizontal card cluster [Tripon Eugen - [`d9fbd97`](https://github.com/eea/volto-cca-policy/commit/d9fbd97e3a9566ef6a9da62f283dd8639d7d00f0)]
|
|
35
|
+
- Better style [Tiberiu Ichim - [`d05b49b`](https://github.com/eea/volto-cca-policy/commit/d05b49b762e9970fa51fe811322a81aacc75570f)]
|
|
36
|
+
- Zoom to map center [Tiberiu Ichim - [`1b55019`](https://github.com/eea/volto-cca-policy/commit/1b5501940733e451d4870b0b2b29963e5f7ff655)]
|
|
37
|
+
- add cluster [Tripon Eugen - [`8e25736`](https://github.com/eea/volto-cca-policy/commit/8e257363f173d6b09f0548ad0ec6a03ff47f1f13)]
|
|
38
|
+
- checkpoint [Tiberiu Ichim - [`49595c1`](https://github.com/eea/volto-cca-policy/commit/49595c11d1eaf74924d1eed48f0d20594dbdcd1f)]
|
|
39
|
+
- Refs #273188 - openDB link move to item title [Tripon Eugen - [`b4d66d6`](https://github.com/eea/volto-cca-policy/commit/b4d66d6874958659474057e7a1df5c28067b870a)]
|
|
7
40
|
### [0.2.69](https://github.com/eea/volto-cca-policy/compare/0.2.68...0.2.69) - 26 September 2024
|
|
8
41
|
|
|
9
42
|
#### :bug: Bug Fixes
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@eeacms/volto-cca-policy",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.71",
|
|
4
4
|
"description": "@eeacms/volto-cca-policy: Volto add-on",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"author": "European Environment Agency: IDM2 A-Team",
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
],
|
|
29
29
|
"dependencies": {
|
|
30
30
|
"@eeacms/volto-block-style": "github:eea/volto-block-style#6.x.x",
|
|
31
|
-
"@eeacms/volto-datablocks": "^7.2.
|
|
31
|
+
"@eeacms/volto-datablocks": "^7.2.5",
|
|
32
32
|
"@eeacms/volto-eea-design-system": "*",
|
|
33
33
|
"@eeacms/volto-eea-website-theme": "^1.33.2",
|
|
34
34
|
"@eeacms/volto-embed": "^9.1.1",
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
// Original: https://github.com/eea/volto-searchlib/blob/master/searchlib/components/Result/HorizontalCardItem.jsx
|
|
2
|
+
// We need custom href for results.
|
|
3
|
+
import React from 'react';
|
|
4
|
+
import { Label } from 'semantic-ui-react';
|
|
5
|
+
import {
|
|
6
|
+
SegmentedBreadcrumb,
|
|
7
|
+
StringList,
|
|
8
|
+
DateTime,
|
|
9
|
+
} from '@eeacms/search/components';
|
|
10
|
+
import { useAppConfig } from '@eeacms/search/lib/hocs';
|
|
11
|
+
|
|
12
|
+
import ExternalLink from '@eeacms/search/components/Result/ExternalLink';
|
|
13
|
+
import ResultContext from '@eeacms/search/components/Result/ResultContext';
|
|
14
|
+
import ContentClusters from '@eeacms/search/components/Result/ContentClusters';
|
|
15
|
+
|
|
16
|
+
const healthURL = (href, is_observatory) => {
|
|
17
|
+
if (is_observatory) {
|
|
18
|
+
return href.replace(/\/metadata\//, '/observatory/++aq++metadata/');
|
|
19
|
+
}
|
|
20
|
+
return href;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
const healthBreadcrumb = (href, is_observatory) => {
|
|
24
|
+
// It's only cosmetic. We don't want to show ++aq...
|
|
25
|
+
if (is_observatory) {
|
|
26
|
+
return href.replace(/\/metadata\//, '/observatory/');
|
|
27
|
+
}
|
|
28
|
+
return href;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
const ExtraContent = (props) => {
|
|
32
|
+
const { result, is_mission, is_observatory } = props;
|
|
33
|
+
let title = 'Climate-ADAPT';
|
|
34
|
+
if (is_mission) {
|
|
35
|
+
title = 'Mission Portal';
|
|
36
|
+
}
|
|
37
|
+
if (is_observatory) {
|
|
38
|
+
title = 'Health Observatory';
|
|
39
|
+
}
|
|
40
|
+
return (
|
|
41
|
+
<div>
|
|
42
|
+
<div className="result-bottom">
|
|
43
|
+
<div className="result-info">
|
|
44
|
+
{/* <span className="result-info-title">Published: </span> */}
|
|
45
|
+
<DateTime format="DATE_MED" value={result.issued} />
|
|
46
|
+
</div>
|
|
47
|
+
<div className="result-info">
|
|
48
|
+
<span className="result-info-title">Topics: </span>
|
|
49
|
+
<StringList value={result.tags} />
|
|
50
|
+
</div>
|
|
51
|
+
</div>
|
|
52
|
+
<div>
|
|
53
|
+
<div className="result-info result-source">
|
|
54
|
+
<span className="result-info-title">Source: </span>
|
|
55
|
+
<ExternalLink href={healthURL(result.href, is_observatory)}>
|
|
56
|
+
<strong title={result.source} className="source">
|
|
57
|
+
{title}
|
|
58
|
+
{/* {firstWords(
|
|
59
|
+
getTermDisplayValue({
|
|
60
|
+
vocab,
|
|
61
|
+
field: 'cluster_name',
|
|
62
|
+
term: result.source,
|
|
63
|
+
}),
|
|
64
|
+
8,
|
|
65
|
+
)} */}
|
|
66
|
+
</strong>
|
|
67
|
+
<SegmentedBreadcrumb
|
|
68
|
+
href={healthBreadcrumb(result.href, is_observatory)}
|
|
69
|
+
short={true}
|
|
70
|
+
maxChars={40}
|
|
71
|
+
/>
|
|
72
|
+
</ExternalLink>
|
|
73
|
+
</div>
|
|
74
|
+
</div>
|
|
75
|
+
</div>
|
|
76
|
+
);
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
const ClusterHorizontalCardItem = (props) => {
|
|
80
|
+
const { result } = props;
|
|
81
|
+
const { registry } = useAppConfig();
|
|
82
|
+
const clusters = result.clusterInfo;
|
|
83
|
+
|
|
84
|
+
const UniversalCard = registry.resolve['UniversalCard'].component;
|
|
85
|
+
|
|
86
|
+
let is_mission = false;
|
|
87
|
+
let is_observatory = false;
|
|
88
|
+
if (
|
|
89
|
+
result.cca_include_in_mission.raw === 'true' ||
|
|
90
|
+
result.href.includes('climate-adapt.eea.europa.eu/en/mission')
|
|
91
|
+
) {
|
|
92
|
+
is_mission = true;
|
|
93
|
+
}
|
|
94
|
+
if (result.cca_include_in_search_observatory.raw === 'true') {
|
|
95
|
+
is_observatory = true;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const item = {
|
|
99
|
+
'@id': result.href,
|
|
100
|
+
title: (
|
|
101
|
+
<>
|
|
102
|
+
<ExternalLink
|
|
103
|
+
href={healthURL(result.href, is_observatory)}
|
|
104
|
+
title={result.title}
|
|
105
|
+
>
|
|
106
|
+
{result.title}
|
|
107
|
+
{result.isNew && <Label className="new-item">New</Label>}
|
|
108
|
+
{result.isExpired && (
|
|
109
|
+
<Label className="archived-item">Archived</Label>
|
|
110
|
+
)}
|
|
111
|
+
</ExternalLink>
|
|
112
|
+
</>
|
|
113
|
+
),
|
|
114
|
+
meta: <ContentClusters clusters={clusters} item={result} />,
|
|
115
|
+
description: props.children ? props.children : <ResultContext {...props} />,
|
|
116
|
+
preview_image_url: result.hasImage ? result.thumbUrl : undefined,
|
|
117
|
+
extra: (
|
|
118
|
+
<ExtraContent
|
|
119
|
+
result={result}
|
|
120
|
+
is_mission={is_mission}
|
|
121
|
+
is_observatory={is_observatory}
|
|
122
|
+
/>
|
|
123
|
+
),
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
const itemModel = {
|
|
127
|
+
hasImage: result.hasImage,
|
|
128
|
+
hasDescription: true,
|
|
129
|
+
imageOnRightSide: true,
|
|
130
|
+
'@type': 'searchItem',
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
return <UniversalCard item={item} itemModel={itemModel} />;
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
export default ClusterHorizontalCardItem;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { MemoryRouter } from 'react-router-dom';
|
|
3
|
+
import configureStore from 'redux-mock-store';
|
|
4
|
+
import { render } from '@testing-library/react';
|
|
5
|
+
import '@testing-library/jest-dom/extend-expect';
|
|
6
|
+
import { Provider } from 'react-intl-redux';
|
|
7
|
+
import C3SIndicatorsGlossaryBlockView from './C3SIndicatorsGlossaryBlockView';
|
|
8
|
+
|
|
9
|
+
const mockStore = configureStore();
|
|
10
|
+
|
|
11
|
+
describe('C3SIndicatorsGlossaryBlockView', () => {
|
|
12
|
+
it('should render the component', () => {
|
|
13
|
+
const data = {
|
|
14
|
+
mode: 'test',
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
const store = mockStore({
|
|
18
|
+
userSession: { token: '1234' },
|
|
19
|
+
intl: {
|
|
20
|
+
locale: 'en',
|
|
21
|
+
messages: {},
|
|
22
|
+
},
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
const { container } = render(
|
|
26
|
+
<Provider store={store}>
|
|
27
|
+
<MemoryRouter>
|
|
28
|
+
<C3SIndicatorsGlossaryBlockView {...data} />
|
|
29
|
+
</MemoryRouter>
|
|
30
|
+
</Provider>,
|
|
31
|
+
);
|
|
32
|
+
expect(container).toBeTruthy();
|
|
33
|
+
});
|
|
34
|
+
});
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { MemoryRouter } from 'react-router-dom';
|
|
3
|
+
import configureStore from 'redux-mock-store';
|
|
4
|
+
import { render } from '@testing-library/react';
|
|
5
|
+
import '@testing-library/jest-dom/extend-expect';
|
|
6
|
+
import { Provider } from 'react-intl-redux';
|
|
7
|
+
import C3SIndicatorsListingBlockView from './C3SIndicatorsListingBlockView';
|
|
8
|
+
|
|
9
|
+
const mockStore = configureStore();
|
|
10
|
+
|
|
11
|
+
describe('C3SIndicatorsListingBlockView', () => {
|
|
12
|
+
it('should render the component', () => {
|
|
13
|
+
const data = {
|
|
14
|
+
metadata: {
|
|
15
|
+
'@components': {
|
|
16
|
+
c3s_indicators_listing: {
|
|
17
|
+
items: [
|
|
18
|
+
{ url: 'https://www.europa.eu', title: 'Europa' },
|
|
19
|
+
{ url: 'https://www.copernicus.eu/en', title: 'Copernicus' },
|
|
20
|
+
],
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
const store = mockStore({
|
|
27
|
+
userSession: { token: '1234' },
|
|
28
|
+
intl: {
|
|
29
|
+
locale: 'en',
|
|
30
|
+
messages: {},
|
|
31
|
+
},
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
const { container } = render(
|
|
35
|
+
<Provider store={store}>
|
|
36
|
+
<MemoryRouter>
|
|
37
|
+
<C3SIndicatorsListingBlockView {...data} />
|
|
38
|
+
</MemoryRouter>
|
|
39
|
+
</Provider>,
|
|
40
|
+
);
|
|
41
|
+
expect(container).toBeTruthy();
|
|
42
|
+
});
|
|
43
|
+
});
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { MemoryRouter } from 'react-router-dom';
|
|
3
|
+
import configureStore from 'redux-mock-store';
|
|
4
|
+
import { render } from '@testing-library/react';
|
|
5
|
+
import '@testing-library/jest-dom/extend-expect';
|
|
6
|
+
import { Provider } from 'react-intl-redux';
|
|
7
|
+
import CaseStudyExplorerEdit from './CaseStudyExplorerEdit';
|
|
8
|
+
import { useCases } from './hooks';
|
|
9
|
+
import * as utils from './utils';
|
|
10
|
+
|
|
11
|
+
const mockStore = configureStore();
|
|
12
|
+
|
|
13
|
+
jest.mock('./CaseStudyExplorerView', () => (props) => (
|
|
14
|
+
<div>Mock Case Study Explorer View {JSON.stringify(props)}</div>
|
|
15
|
+
));
|
|
16
|
+
jest.mock('./CaseStudyMap', () => () => <div>Mock Case Study Map</div>);
|
|
17
|
+
jest.mock('./CaseStudyFilters', () => () => <div>Mock Case Study Filters</div>);
|
|
18
|
+
|
|
19
|
+
jest.mock('./hooks', () => ({
|
|
20
|
+
useCases: jest.fn(),
|
|
21
|
+
}));
|
|
22
|
+
|
|
23
|
+
jest.mock('./utils', () => ({
|
|
24
|
+
filterCases: jest.fn(),
|
|
25
|
+
getFilters: jest.fn(),
|
|
26
|
+
}));
|
|
27
|
+
|
|
28
|
+
const store = mockStore({
|
|
29
|
+
userSession: { token: '1234' },
|
|
30
|
+
intl: {
|
|
31
|
+
locale: 'en',
|
|
32
|
+
messages: {},
|
|
33
|
+
},
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
describe('CaseStudyExplorerEdit', () => {
|
|
37
|
+
const mockCasesData = {
|
|
38
|
+
features: [
|
|
39
|
+
{
|
|
40
|
+
properties: {
|
|
41
|
+
title: 'Case Study 1',
|
|
42
|
+
image: 'image1.jpg',
|
|
43
|
+
sectors_str: 'Sector1',
|
|
44
|
+
impacts_str: 'Impact1',
|
|
45
|
+
adaptation_options_links: 'link1',
|
|
46
|
+
url: 'https://example.com/case-study-1',
|
|
47
|
+
origin_adaptecca: 20,
|
|
48
|
+
sectors: '1,2',
|
|
49
|
+
impacts: '1',
|
|
50
|
+
elements: '1',
|
|
51
|
+
},
|
|
52
|
+
geometry: {
|
|
53
|
+
coordinates: [-123.3656, 48.4284],
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
],
|
|
57
|
+
filters: {
|
|
58
|
+
measures: [],
|
|
59
|
+
},
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
beforeEach(() => {
|
|
63
|
+
useCases.mockReturnValue(mockCasesData);
|
|
64
|
+
|
|
65
|
+
utils.getFilters.mockReturnValue({
|
|
66
|
+
impacts: { 1: 'Impact 1' },
|
|
67
|
+
sectors: { 1: 'Sector 1' },
|
|
68
|
+
elements: { 1: 'Element 1' },
|
|
69
|
+
measures: {},
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
utils.filterCases.mockImplementation((cases, activeFilters) => {
|
|
73
|
+
return activeFilters.sectors.length ? cases : [];
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
it('renders the CaseStudyExplorerEdit component', () => {
|
|
78
|
+
const { getByText } = render(
|
|
79
|
+
<Provider store={store}>
|
|
80
|
+
<MemoryRouter>
|
|
81
|
+
<CaseStudyExplorerEdit />
|
|
82
|
+
</MemoryRouter>
|
|
83
|
+
</Provider>,
|
|
84
|
+
);
|
|
85
|
+
|
|
86
|
+
expect(getByText(/Mock Case Study Explorer View/i)).toBeInTheDocument();
|
|
87
|
+
expect(getByText(/"mode":"edit"/i)).toBeInTheDocument(); // Check for the mode prop
|
|
88
|
+
});
|
|
89
|
+
});
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { MemoryRouter } from 'react-router-dom';
|
|
3
|
+
import configureStore from 'redux-mock-store';
|
|
4
|
+
import { render } from '@testing-library/react';
|
|
5
|
+
import '@testing-library/jest-dom/extend-expect';
|
|
6
|
+
import { Provider } from 'react-intl-redux';
|
|
7
|
+
import CaseStudyExplorerView from './CaseStudyExplorerView';
|
|
8
|
+
import { useCases } from './hooks';
|
|
9
|
+
import * as utils from './utils';
|
|
10
|
+
|
|
11
|
+
const mockStore = configureStore();
|
|
12
|
+
|
|
13
|
+
jest.mock('./CaseStudyMap', () => () => <div>Mock Case Study Map</div>);
|
|
14
|
+
jest.mock('./CaseStudyFilters', () => () => <div>Mock Case Study Filters</div>);
|
|
15
|
+
|
|
16
|
+
jest.mock('./hooks', () => ({
|
|
17
|
+
useCases: jest.fn(),
|
|
18
|
+
}));
|
|
19
|
+
|
|
20
|
+
jest.mock('./utils', () => ({
|
|
21
|
+
filterCases: jest.fn(),
|
|
22
|
+
getFilters: jest.fn(),
|
|
23
|
+
}));
|
|
24
|
+
|
|
25
|
+
jest.mock('@plone/volto/helpers', () => ({
|
|
26
|
+
addAppURL: jest.fn((url) => url),
|
|
27
|
+
}));
|
|
28
|
+
|
|
29
|
+
const store = mockStore({
|
|
30
|
+
userSession: { token: '1234' },
|
|
31
|
+
intl: {
|
|
32
|
+
locale: 'en',
|
|
33
|
+
messages: {},
|
|
34
|
+
},
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
// Define the __SERVER__ variable for testing
|
|
38
|
+
global.__SERVER__ = false; // Set it to false to avoid server-side return
|
|
39
|
+
|
|
40
|
+
describe('CaseStudyExplorerView', () => {
|
|
41
|
+
const mockCasesData = {
|
|
42
|
+
features: [
|
|
43
|
+
{
|
|
44
|
+
properties: {
|
|
45
|
+
title: 'Case Study 1',
|
|
46
|
+
image: 'image1.jpg',
|
|
47
|
+
sectors_str: 'Sector1',
|
|
48
|
+
impacts_str: 'Impact1',
|
|
49
|
+
adaptation_options_links: 'link1',
|
|
50
|
+
url: 'https://example.com/case-study-1',
|
|
51
|
+
origin_adaptecca: 20,
|
|
52
|
+
sectors: '1,2',
|
|
53
|
+
impacts: '1',
|
|
54
|
+
elements: '1',
|
|
55
|
+
},
|
|
56
|
+
geometry: {
|
|
57
|
+
coordinates: [-123.3656, 48.4284],
|
|
58
|
+
},
|
|
59
|
+
},
|
|
60
|
+
],
|
|
61
|
+
filters: {
|
|
62
|
+
measures: [],
|
|
63
|
+
},
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
beforeEach(() => {
|
|
67
|
+
useCases.mockReturnValue(mockCasesData);
|
|
68
|
+
utils.filterCases.mockImplementation((cases, filters) => cases);
|
|
69
|
+
utils.getFilters.mockReturnValue({
|
|
70
|
+
impacts: { 1: 'Impact 1' },
|
|
71
|
+
sectors: { 1: 'Sector 1' },
|
|
72
|
+
elements: { 1: 'Element 1' },
|
|
73
|
+
measures: {},
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
afterEach(() => {
|
|
78
|
+
jest.clearAllMocks();
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
it('renders the CaseStudyExplorerView with case studies', () => {
|
|
82
|
+
const { getByText } = render(
|
|
83
|
+
<Provider store={store}>
|
|
84
|
+
<MemoryRouter>
|
|
85
|
+
<CaseStudyExplorerView />
|
|
86
|
+
</MemoryRouter>
|
|
87
|
+
</Provider>,
|
|
88
|
+
);
|
|
89
|
+
|
|
90
|
+
expect(getByText('Mock Case Study Map')).toBeInTheDocument();
|
|
91
|
+
expect(getByText('Mock Case Study Filters')).toBeInTheDocument();
|
|
92
|
+
});
|
|
93
|
+
});
|
|
@@ -3,7 +3,6 @@ import React from 'react';
|
|
|
3
3
|
import { Map, Layer, Layers } from '@eeacms/volto-openlayers-map/api';
|
|
4
4
|
import { openlayers as ol } from '@eeacms/volto-openlayers-map';
|
|
5
5
|
|
|
6
|
-
import InfoOverlay from './InfoOverlay';
|
|
7
6
|
import FeatureInteraction from './FeatureInteraction';
|
|
8
7
|
|
|
9
8
|
import { getFeatures } from './utils';
|
|
@@ -12,7 +11,7 @@ export default function CaseStudyMap(props) {
|
|
|
12
11
|
const { items, activeItems } = props;
|
|
13
12
|
const [selectedCase, onSelectedCase] = React.useState();
|
|
14
13
|
|
|
15
|
-
const features = getFeatures(items);
|
|
14
|
+
const features = React.useMemo(() => getFeatures(items), [items]);
|
|
16
15
|
|
|
17
16
|
const [tileWMSSources] = React.useState([
|
|
18
17
|
new ol.source.TileWMS({
|
|
@@ -26,97 +25,32 @@ export default function CaseStudyMap(props) {
|
|
|
26
25
|
transition: 0,
|
|
27
26
|
}),
|
|
28
27
|
]);
|
|
29
|
-
const [pointsSource] = React.useState(
|
|
30
|
-
new ol.source.Vector({
|
|
31
|
-
features,
|
|
32
|
-
}),
|
|
33
|
-
);
|
|
34
28
|
|
|
35
|
-
const
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
29
|
+
const mapCenter = React.useMemo(
|
|
30
|
+
() => ({
|
|
31
|
+
center: ol.proj.fromLonLat([20, 50]),
|
|
32
|
+
showFullExtent: true,
|
|
33
|
+
zoom: 4,
|
|
39
34
|
}),
|
|
35
|
+
[],
|
|
40
36
|
);
|
|
41
37
|
|
|
42
|
-
React.useEffect(() => {
|
|
43
|
-
if (activeItems) {
|
|
44
|
-
pointsSource.clear();
|
|
45
|
-
pointsSource.addFeatures(getFeatures(activeItems));
|
|
46
|
-
}
|
|
47
|
-
}, [activeItems, pointsSource]);
|
|
48
|
-
|
|
49
38
|
return features.length > 0 ? (
|
|
50
39
|
<Map
|
|
51
|
-
view={
|
|
52
|
-
center: ol.proj.fromLonLat([20, 50]),
|
|
53
|
-
showFullExtent: true,
|
|
54
|
-
zoom: 4,
|
|
55
|
-
}}
|
|
40
|
+
view={mapCenter}
|
|
56
41
|
pixelRatio={1}
|
|
57
42
|
controls={ol.control.defaults({ attribution: false })}
|
|
58
43
|
>
|
|
59
44
|
<Layers>
|
|
60
|
-
<
|
|
61
|
-
selectedFeature={selectedCase}
|
|
45
|
+
<FeatureInteraction
|
|
62
46
|
onFeatureSelect={onSelectedCase}
|
|
63
|
-
|
|
64
|
-
|
|
47
|
+
selectedFeature={selectedCase}
|
|
48
|
+
mapCenter={mapCenter}
|
|
49
|
+
features={features}
|
|
50
|
+
activeItems={activeItems}
|
|
65
51
|
/>
|
|
66
|
-
<FeatureInteraction onFeatureSelect={onSelectedCase} />
|
|
67
52
|
<Layer.Tile source={tileWMSSources[0]} zIndex={0} />
|
|
68
|
-
<Layer.Vector style={clusterStyle} source={clusterSource} zIndex={1} />
|
|
69
53
|
</Layers>
|
|
70
54
|
</Map>
|
|
71
55
|
) : null;
|
|
72
56
|
}
|
|
73
|
-
|
|
74
|
-
const _cached = {};
|
|
75
|
-
|
|
76
|
-
function getStyle(size, haveAdaptecca) {
|
|
77
|
-
let style = _cached[size + '_' + haveAdaptecca];
|
|
78
|
-
|
|
79
|
-
if (!style) {
|
|
80
|
-
style =
|
|
81
|
-
size === 1
|
|
82
|
-
? new ol.style.Style({
|
|
83
|
-
image: new ol.style.Circle({
|
|
84
|
-
radius: 5,
|
|
85
|
-
stroke: new ol.style.Stroke({
|
|
86
|
-
color: '#fff',
|
|
87
|
-
}),
|
|
88
|
-
fill: new ol.style.Fill({
|
|
89
|
-
color: haveAdaptecca ? '#00ffff' : '#005c96',
|
|
90
|
-
}),
|
|
91
|
-
}),
|
|
92
|
-
})
|
|
93
|
-
: new ol.style.Style({
|
|
94
|
-
image: new ol.style.Circle({
|
|
95
|
-
radius: 10 + Math.min(Math.floor(size / 3), 10),
|
|
96
|
-
stroke: new ol.style.Stroke({
|
|
97
|
-
color: '#fff',
|
|
98
|
-
}),
|
|
99
|
-
fill: new ol.style.Fill({
|
|
100
|
-
color: haveAdaptecca ? '#318CE7' : '#005c96',
|
|
101
|
-
}),
|
|
102
|
-
}),
|
|
103
|
-
text: new ol.style.Text({
|
|
104
|
-
text: size.toString(),
|
|
105
|
-
fill: new ol.style.Fill({
|
|
106
|
-
color: '#fff',
|
|
107
|
-
}),
|
|
108
|
-
}),
|
|
109
|
-
});
|
|
110
|
-
_cached[size + '_' + haveAdaptecca] = style;
|
|
111
|
-
}
|
|
112
|
-
return style;
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
function clusterStyle(feature) {
|
|
116
|
-
const size = feature.get('features').length;
|
|
117
|
-
const cases = feature
|
|
118
|
-
.get('features')
|
|
119
|
-
.filter((_case) => _case['values_']['origin_adaptecca'] < 20);
|
|
120
|
-
|
|
121
|
-
return getStyle(size, cases.length > 0 ? 1 : 0);
|
|
122
|
-
}
|