@eeacms/volto-n2k 1.1.4 → 1.1.6

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.
Files changed (26) hide show
  1. package/CHANGELOG.md +43 -10
  2. package/package.json +1 -1
  3. package/src/components/manage/Blocks/CDDACountryProfileMap/View.jsx +3 -2
  4. package/src/components/manage/Blocks/CddaShape/View.jsx +3 -2
  5. package/src/components/manage/Blocks/ExploreHabitats/View.jsx +3 -2
  6. package/src/components/manage/Blocks/ExploreSites/View.jsx +3 -2
  7. package/src/components/manage/Blocks/ExploreSpecies/View.jsx +3 -2
  8. package/src/components/manage/Blocks/HabitatDistribution/View.jsx +3 -2
  9. package/src/components/manage/Blocks/HabitatProtectedSites/View.jsx +3 -2
  10. package/src/components/manage/Blocks/HabitatsBanner/View.jsx +60 -38
  11. package/src/components/manage/Blocks/N2KCountryProfileMap/View.jsx +3 -2
  12. package/src/components/manage/Blocks/SiteBanner/View.jsx +81 -47
  13. package/src/components/manage/Blocks/SiteHabitatsList/Filters/SortBy.jsx +2 -0
  14. package/src/components/manage/Blocks/SiteHabitatsList/Filters/View.jsx +21 -5
  15. package/src/components/manage/Blocks/SiteHabitatsList/View.jsx +37 -7
  16. package/src/components/manage/Blocks/SiteHabitatsList/style.less +3 -0
  17. package/src/components/manage/Blocks/SiteHabitatsList/utils.js +4 -18
  18. package/src/components/manage/Blocks/SiteProtectedHabitats/View.jsx +1 -1
  19. package/src/components/manage/Blocks/SiteProtectedSpecies/View.jsx +1 -1
  20. package/src/components/manage/Blocks/SiteShape/View.jsx +3 -2
  21. package/src/components/manage/Blocks/SiteSpeciesList/View.jsx +5 -0
  22. package/src/components/manage/Blocks/SiteSpeciesList/style.less +3 -0
  23. package/src/components/manage/Blocks/SpeciesBanner/View.jsx +43 -31
  24. package/src/components/manage/Blocks/SpeciesDistribution/View.jsx +3 -2
  25. package/src/components/manage/Blocks/SpeciesProtectedSites/View.jsx +73 -16
  26. package/src/components/manage/Blocks/SpeciesProtectedSites/index.js +10 -3
package/CHANGELOG.md CHANGED
@@ -4,11 +4,51 @@ All notable changes to this project will be documented in this file. Dates are d
4
4
 
5
5
  Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
6
6
 
7
- ### [1.1.4](https://github.com/eea/volto-n2k/compare/1.1.3...1.1.4) - 16 January 2025
7
+ ### [1.1.6](https://github.com/eea/volto-n2k/compare/1.1.5...1.1.6) - 23 June 2025
8
8
 
9
- #### :bug: Bug Fixes
9
+ #### :house: Internal changes
10
+
11
+ - style: Automated code fix [eea-jenkins - [`8231cbf`](https://github.com/eea/volto-n2k/commit/8231cbf9aada31924e4e79e1757d3ca4dbb6ed10)]
12
+ - style: Automated code fix [eea-jenkins - [`924b48f`](https://github.com/eea/volto-n2k/commit/924b48fc053bad993dbef1ca8d64a3847727299c)]
13
+ - style: Automated code fix [eea-jenkins - [`516d098`](https://github.com/eea/volto-n2k/commit/516d0986bbe882686878bb42d9a48eb062222c03)]
14
+ - style: Automated code fix [eea-jenkins - [`6836c3e`](https://github.com/eea/volto-n2k/commit/6836c3e0542f602286eee3321d1f190364f50fb9)]
15
+ - style: Automated code fix [eea-jenkins - [`a513b0e`](https://github.com/eea/volto-n2k/commit/a513b0ee92965caffffd8305f00e1e3c4ecb23cc)]
16
+ - style: Automated code fix [eea-jenkins - [`fcf78ea`](https://github.com/eea/volto-n2k/commit/fcf78eaa96ce7cfdcaa29db08e473f5217d43858)]
17
+ - style: Automated code fix [eea-jenkins - [`4d55dd4`](https://github.com/eea/volto-n2k/commit/4d55dd4199d130e841398b893f51ecb6e2a70487)]
18
+ - style: Automated code fix [eea-jenkins - [`f13d5b5`](https://github.com/eea/volto-n2k/commit/f13d5b5a64f6de9fe87999ae9e87d9e69d171581)]
19
+ - style: Automated code fix [eea-jenkins - [`cea8ba8`](https://github.com/eea/volto-n2k/commit/cea8ba8d6cfb74ced07f3d5cbbd1f74f9aeb28ea)]
20
+ - style: Automated code fix [eea-jenkins - [`73b990c`](https://github.com/eea/volto-n2k/commit/73b990ca03ab0cc97e000a1bda8b503a3463984f)]
21
+
22
+ #### :hammer_and_wrench: Others
23
+
24
+ - update site banner for natda [Claudia Ifrim - [`9a41070`](https://github.com/eea/volto-n2k/commit/9a410704364cafbdfe13bc3c159922f31a6b10c3)]
25
+ - show habitat priotity [Claudia Ifrim - [`205f0ed`](https://github.com/eea/volto-n2k/commit/205f0ed9b1a9c49c824e69f41104cbd5ab36768a)]
26
+ - fix lint [vladcalin-edw - [`ca7b199`](https://github.com/eea/volto-n2k/commit/ca7b1995315ea7d76ecf092e02672bd39e2b6067)]
27
+ - Fixed habitats filter and ui breaking [vladcalin-edw - [`a5e9024`](https://github.com/eea/volto-n2k/commit/a5e90240cf0b653e4f1daf7288b29ed33bd095f8)]
28
+ - fix warnings [Claudia Ifrim - [`87b03f2`](https://github.com/eea/volto-n2k/commit/87b03f2b7ef88814452063dd1f9af2b31f2bc04e)]
29
+ - fix sonar [vladcalin-edw - [`c054b68`](https://github.com/eea/volto-n2k/commit/c054b683522dfd3350eff1a302746dc6810596d2)]
30
+ - fix eslint errors [vladcalin-edw - [`78604e8`](https://github.com/eea/volto-n2k/commit/78604e8fdd7129726d2321c7a3cef04abedebb70)]
31
+ - restart jenkins [vladcalin-edw - [`f61974a`](https://github.com/eea/volto-n2k/commit/f61974a4bbbbfbf829d7867ff301da0492e629fd)]
32
+ - species banner avoiding rerenders [vladcalin-edw - [`82b25dc`](https://github.com/eea/volto-n2k/commit/82b25dcd51408fd5c8926cde71584d9dc4963649)]
33
+ - performance improvement [vladcalin-edw - [`a0db347`](https://github.com/eea/volto-n2k/commit/a0db3478e1abd70d65c615ce7ba5c82ccb57034e)]
34
+ - query layer 3 and layer 7 [Claudia Ifrim - [`64b2c7d`](https://github.com/eea/volto-n2k/commit/64b2c7de6ea82a376f0f9ae2128f98ab20d96def)]
35
+ - fix sonarqube [vladcalin-edw - [`b207555`](https://github.com/eea/volto-n2k/commit/b207555ee533cce97f4f4d2d22a7eb84240dd76f)]
36
+ - fix sonarqube [vladcalin-edw - [`8726d0f`](https://github.com/eea/volto-n2k/commit/8726d0fbed394b6b1dec6be99da8250b159c1be8)]
37
+ - fix lint issue [vladcalin-edw - [`7570ec3`](https://github.com/eea/volto-n2k/commit/7570ec3ee87c9d7e13f96bc0ec17edef48977d4e)]
38
+ - cleanup [vladcalin-edw - [`6dd7033`](https://github.com/eea/volto-n2k/commit/6dd7033385bd9db25107873d1c252a2d890493e5)]
39
+ - cleanup [vladcalin-edw - [`69f712b`](https://github.com/eea/volto-n2k/commit/69f712b733dc5a6a34c03c1c046fcd82c8ac49fd)]
40
+ - added priority filter, sort by coverage, sites [vladcalin-edw - [`340f3d4`](https://github.com/eea/volto-n2k/commit/340f3d4e7eda946d6b1254c19dad854611ab96c4)]
41
+ - changed label naming back to formatLabel [vladcalin-edw - [`4f93eeb`](https://github.com/eea/volto-n2k/commit/4f93eeba28545e28ee31a854da433099d7db5cf2)]
42
+ - habitats filtering with hardcoded values [vladcalin-edw - [`ccdda01`](https://github.com/eea/volto-n2k/commit/ccdda013a90d91a05d50c811bb52a1036e729362)]
43
+ - in progress [vladcalin-edw - [`f2669ec`](https://github.com/eea/volto-n2k/commit/f2669ec6c07237cc574f24a08511294cd3e8e4d7)]
44
+ ### [1.1.5](https://github.com/eea/volto-n2k/compare/1.1.4...1.1.5) - 18 February 2025
10
45
 
11
- - fix: remove number for priority habitat type [Claudia Ifrim - [`7d65e7d`](https://github.com/eea/volto-n2k/commit/7d65e7d95de554b0ea3dc34e960f59fb9b9d88e7)]
46
+ #### :hammer_and_wrench: Others
47
+
48
+ - Scroll to banner on page change [Miu Razvan - [`3195762`](https://github.com/eea/volto-n2k/commit/31957629fdb1addb596f86183251ac9b272b26b6)]
49
+ - fix font size + decimals [Claudia Ifrim - [`4beb02b`](https://github.com/eea/volto-n2k/commit/4beb02bd8bd69a6ef76510166e240b80190b9d12)]
50
+ - show number of caves [Claudia Ifrim - [`e3876b8`](https://github.com/eea/volto-n2k/commit/e3876b8624886c8055692c4324f258a90578170a)]
51
+ ### [1.1.4](https://github.com/eea/volto-n2k/compare/1.1.3...1.1.4) - 16 January 2025
12
52
 
13
53
  ### [1.1.3](https://github.com/eea/volto-n2k/compare/1.1.2...1.1.3) - 9 January 2025
14
54
 
@@ -66,7 +106,6 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
66
106
 
67
107
  #### :house: Internal changes
68
108
 
69
- - chore: [JENKINS] Refactor automated testing [valentinab25 - [`e4f9fc8`](https://github.com/eea/volto-n2k/commit/e4f9fc800b753b97cca7c685bc47dd48804276f0)]
70
109
  - chore: husky, lint-staged use fixed versions [valentinab25 - [`647d621`](https://github.com/eea/volto-n2k/commit/647d621d52400c50f5bc629b3ddc4f2121f14ffa)]
71
110
  - chore:volto 16 in tests, update docs, fix stylelint overrides [valentinab25 - [`60d94b6`](https://github.com/eea/volto-n2k/commit/60d94b61ff8826abc57af9616793a1a247f585b5)]
72
111
 
@@ -81,11 +120,6 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
81
120
  - try to use volto-spotlight theme in jenkins [Miu Razvan - [`ec0b952`](https://github.com/eea/volto-n2k/commit/ec0b9525b967f907922ae660bd9f520119cd80c1)]
82
121
  - remove waitForResourceToLoad [ana-oprea - [`eaded9b`](https://github.com/eea/volto-n2k/commit/eaded9b9ecd1ca2eb78aa8dd65838c063d95db85)]
83
122
  - update image size from 300 to 800 px [Claudia Ifrim - [`8d9270a`](https://github.com/eea/volto-n2k/commit/8d9270a09506278ceaea25e8a72abdf5b22fcc78)]
84
- - test: [JENKINS] Use java17 for sonarqube scanner [valentinab25 - [`350f8a6`](https://github.com/eea/volto-n2k/commit/350f8a6928aafbf168472b572f8041a79f71f577)]
85
- - test: [JENKINS] Run cypress in started frontend container [valentinab25 - [`99b3a84`](https://github.com/eea/volto-n2k/commit/99b3a84a266710fadf7d430117359b741cadede8)]
86
- - test: [JENKINS] Add cpu limit on cypress docker [valentinab25 - [`050ac98`](https://github.com/eea/volto-n2k/commit/050ac982ec39e9a1b4885b665cdc118fca7b1283)]
87
- - test: [JENKINS] Increase shm-size to cypress docker [valentinab25 - [`3546040`](https://github.com/eea/volto-n2k/commit/35460409817f496fc752ab34e37d6d33a069b2e9)]
88
- - test: [JENKINS] Improve cypress time [valentinab25 - [`06a4ab1`](https://github.com/eea/volto-n2k/commit/06a4ab151799b8cdf4a316dbcb0c323e0f568e30)]
89
123
  - test: EN locales, pre-commit fix, feature PRs checks Refs #257193 [valentinab25 - [`4850d6a`](https://github.com/eea/volto-n2k/commit/4850d6a65349fe49dbe9244c30592ae38c9aeaba)]
90
124
  - test: Update Makefile and docker-compose to align it with Jenkinsfile [valentinab25 - [`2c91856`](https://github.com/eea/volto-n2k/commit/2c9185688a2fe6b36e5eeb2963f6c8676e3c5628)]
91
125
  ### [1.0.33](https://github.com/eea/volto-n2k/compare/1.0.32...1.0.33) - 3 July 2023
@@ -342,7 +376,6 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
342
376
  - Update [razvanMiu - [`42ab50e`](https://github.com/eea/volto-n2k/commit/42ab50e6681a47251d15ac06b836c6f8c27157fa)]
343
377
  - Added bubble chart [razvanMiu - [`89fba5e`](https://github.com/eea/volto-n2k/commit/89fba5e5db41aa955ba2d0ed58c9f0042c461504)]
344
378
  - Group species by id_eunis in species list [razvanMiu - [`543c957`](https://github.com/eea/volto-n2k/commit/543c9573b53acd8eecc9afbb6ae7beeddba53966)]
345
- - Add Sonarqube tag using frontend addons list [EEA Jenkins - [`2ca3e4c`](https://github.com/eea/volto-n2k/commit/2ca3e4c092211f92339791d71db81f5b4ca2d562)]
346
379
  - update maps - species and habitats distribution maps [Claudia Ifrim - [`ad12eb1`](https://github.com/eea/volto-n2k/commit/ad12eb141907d6f28444f1eafc3f687735d2a68d)]
347
380
  - update format for common name and author [Claudia Ifrim - [`26b7a2f`](https://github.com/eea/volto-n2k/commit/26b7a2f3d20c7701b57fb24f39fc7dfeceec3ce8)]
348
381
  - update format for species name (common / scientific) [Claudia Ifrim - [`abdedcf`](https://github.com/eea/volto-n2k/commit/abdedcfe645665031dedf050fd2c5cdde8c14a50)]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eeacms/volto-n2k",
3
- "version": "1.1.4",
3
+ "version": "1.1.6",
4
4
  "description": "volto-n2k: Volto add-on",
5
5
  "main": "src/index.js",
6
6
  "author": "European Environment Agency: IDM2 A-Team",
@@ -3,7 +3,7 @@ import isArray from 'lodash/isArray';
3
3
  import isString from 'lodash/isString';
4
4
  import Map from '@eeacms/volto-openlayers-map/Map';
5
5
  import { Layers, Layer } from '@eeacms/volto-openlayers-map/Layers';
6
- import { openlayers } from '@eeacms/volto-openlayers-map';
6
+ import { withOpenLayers } from '@eeacms/volto-openlayers-map';
7
7
 
8
8
  // layer definitions
9
9
  const smallScaleLayerId = 1;
@@ -57,6 +57,7 @@ const dynamicLayerDefinition = `
57
57
  ]`;
58
58
 
59
59
  const View = (props) => {
60
+ const { ol: openlayers } = props;
60
61
  const [sources, setSources] = useState([]);
61
62
  const [tiles, setTiles] = useState([]);
62
63
  const [extent, setExtent] = useState(null);
@@ -200,4 +201,4 @@ const View = (props) => {
200
201
  );
201
202
  };
202
203
 
203
- export default View;
204
+ export default withOpenLayers(View);
@@ -4,11 +4,12 @@ import Map from '@eeacms/volto-openlayers-map/Map';
4
4
  import { Interactions } from '@eeacms/volto-openlayers-map/Interactions';
5
5
  import { Controls } from '@eeacms/volto-openlayers-map/Controls';
6
6
  import { Layers, Layer } from '@eeacms/volto-openlayers-map/Layers';
7
- import { openlayers } from '@eeacms/volto-openlayers-map';
7
+ import { withOpenLayers } from '@eeacms/volto-openlayers-map';
8
8
  import { getCddaShapeURL } from './index';
9
9
  import './style.less';
10
10
 
11
11
  const View = (props) => {
12
+ const { ol: openlayers } = props;
12
13
  const dataFetched = React.useRef();
13
14
  const [options, setOptions] = React.useState({});
14
15
  const [vectorSource, setVectorSource] = useState(null);
@@ -121,4 +122,4 @@ const View = (props) => {
121
122
  );
122
123
  };
123
124
 
124
- export default View;
125
+ export default withOpenLayers(View);
@@ -5,11 +5,12 @@ import Map from '@eeacms/volto-openlayers-map/Map';
5
5
  import { Interactions } from '@eeacms/volto-openlayers-map/Interactions';
6
6
  import { Controls } from '@eeacms/volto-openlayers-map/Controls';
7
7
  import { Layers, Layer } from '@eeacms/volto-openlayers-map/Layers';
8
- import { openlayers } from '@eeacms/volto-openlayers-map';
8
+ import { withOpenLayers } from '@eeacms/volto-openlayers-map';
9
9
  import { getActiveHabitatsURL } from './index';
10
10
  import './style.less';
11
11
 
12
12
  const View = (props) => {
13
+ const { ol: openlayers } = props;
13
14
  const [options, setOptions] = React.useState({});
14
15
  const [vectorSource, setVectorSource] = useState(null);
15
16
  const [tileWMSSources, setTileWMSSources] = useState([]);
@@ -185,4 +186,4 @@ const View = (props) => {
185
186
 
186
187
  export default connect((state) => ({
187
188
  search: state.table_search || {},
188
- }))(View);
189
+ }))(withOpenLayers(View));
@@ -5,11 +5,12 @@ import Map from '@eeacms/volto-openlayers-map/Map';
5
5
  import { Interactions } from '@eeacms/volto-openlayers-map/Interactions';
6
6
  import { Controls } from '@eeacms/volto-openlayers-map/Controls';
7
7
  import { Layers, Layer } from '@eeacms/volto-openlayers-map/Layers';
8
- import { openlayers } from '@eeacms/volto-openlayers-map';
8
+ import { withOpenLayers } from '@eeacms/volto-openlayers-map';
9
9
  import { getActiveSitesURL } from './index';
10
10
  import './style.less';
11
11
 
12
12
  const View = (props) => {
13
+ const { ol: openlayers } = props;
13
14
  const [options, setOptions] = React.useState({});
14
15
  const [vectorSource, setVectorSource] = useState(null);
15
16
  const [tileWMSSources, setTileWMSSources] = useState([]);
@@ -176,4 +177,4 @@ const View = (props) => {
176
177
 
177
178
  export default connect((state) => ({
178
179
  search: state.table_search || {},
179
- }))(View);
180
+ }))(withOpenLayers(View));
@@ -5,11 +5,12 @@ import Map from '@eeacms/volto-openlayers-map/Map';
5
5
  import { Interactions } from '@eeacms/volto-openlayers-map/Interactions';
6
6
  import { Controls } from '@eeacms/volto-openlayers-map/Controls';
7
7
  import { Layers, Layer } from '@eeacms/volto-openlayers-map/Layers';
8
- import { openlayers } from '@eeacms/volto-openlayers-map';
8
+ import { withOpenLayers } from '@eeacms/volto-openlayers-map';
9
9
  import { getActiveSpeciesURL } from './index';
10
10
  import './style.less';
11
11
 
12
12
  const View = (props) => {
13
+ const { ol: openlayers } = props;
13
14
  const [options, setOptions] = React.useState({});
14
15
  const [vectorSource, setVectorSource] = useState(null);
15
16
  const [tileWMSSources, setTileWMSSources] = useState([]);
@@ -179,4 +180,4 @@ const View = (props) => {
179
180
 
180
181
  export default connect((state) => ({
181
182
  search: state.table_search || {},
182
- }))(View);
183
+ }))(withOpenLayers(View));
@@ -4,11 +4,12 @@ import Map from '@eeacms/volto-openlayers-map/Map';
4
4
  import { Interactions } from '@eeacms/volto-openlayers-map/Interactions';
5
5
  import { Controls } from '@eeacms/volto-openlayers-map/Controls';
6
6
  import { Layers, Layer } from '@eeacms/volto-openlayers-map/Layers';
7
- import { openlayers } from '@eeacms/volto-openlayers-map';
7
+ import { withOpenLayers } from '@eeacms/volto-openlayers-map';
8
8
  import { getHabitatDistributionURL } from './index';
9
9
  import './style.less';
10
10
 
11
11
  const View = (props) => {
12
+ const { ol: openlayers } = props;
12
13
  const dataFetched = React.useRef();
13
14
  const [options, setOptions] = React.useState({});
14
15
  const [vectorSource, setVectorSource] = useState(null);
@@ -110,4 +111,4 @@ const View = (props) => {
110
111
  );
111
112
  };
112
113
 
113
- export default View;
114
+ export default withOpenLayers(View);
@@ -4,11 +4,12 @@ import Map from '@eeacms/volto-openlayers-map/Map';
4
4
  import { Interactions } from '@eeacms/volto-openlayers-map/Interactions';
5
5
  import { Controls } from '@eeacms/volto-openlayers-map/Controls';
6
6
  import { Layers, Layer } from '@eeacms/volto-openlayers-map/Layers';
7
- import { openlayers } from '@eeacms/volto-openlayers-map';
7
+ import { withOpenLayers } from '@eeacms/volto-openlayers-map';
8
8
  import { getHabitatProtectedSitesURL } from './index';
9
9
  import './style.less';
10
10
 
11
11
  const View = (props) => {
12
+ const { ol: openlayers } = props;
12
13
  const dataFetched = React.useRef();
13
14
  const [options, setOptions] = React.useState({});
14
15
  const [vectorSource, setVectorSource] = useState(null);
@@ -110,4 +111,4 @@ const View = (props) => {
110
111
  );
111
112
  };
112
113
 
113
- export default View;
114
+ export default withOpenLayers(View);
@@ -1,17 +1,17 @@
1
- import React, { useRef, useMemo, useState } from 'react';
2
- import { compose } from 'redux';
3
- import cx from 'classnames';
4
- import loadable from '@loadable/component';
5
- import { Icon } from '@plone/volto/components';
6
- import { flattenToAppURL } from '@plone/volto/helpers';
7
1
  import { VisibilitySensor } from '@eeacms/volto-datablocks/components';
8
2
  import { connectToMultipleProviders } from '@eeacms/volto-datablocks/hocs';
9
3
  import { replaceQueryParam } from '@eeacms/volto-n2k/helpers';
10
4
  import arrowLeft from '@eeacms/volto-n2k/icons/arrow-left.svg';
11
5
  import arrowRight from '@eeacms/volto-n2k/icons/arrow-right.svg';
6
+ import loadable from '@loadable/component';
7
+ import { Icon } from '@plone/volto/components';
8
+ import { flattenToAppURL } from '@plone/volto/helpers';
9
+ import cx from 'classnames';
10
+ import { useCallback, useMemo, useRef, useState } from 'react';
11
+ import { compose } from 'redux';
12
12
 
13
- import './style.less';
14
13
  import 'swiper/css';
14
+ import './style.less';
15
15
 
16
16
  const SwiperLoader = loadable.lib(() => import('swiper'));
17
17
  const SwiperReactLoader = loadable.lib(() => import('swiper/react'));
@@ -23,21 +23,34 @@ const getSource = (source) => {
23
23
  return parsedSource;
24
24
  };
25
25
 
26
- const _View = (props) => {
26
+ const ViewComponent = (props) => {
27
27
  const swiperEl = useRef();
28
28
  const previewEl = useRef();
29
29
  const [activeSlide, setActiveSlide] = useState(0);
30
- const habitat_provider = flattenToAppURL(props.data.habitat_provider);
31
- const habitat_pictures_provider = flattenToAppURL(
32
- props.data.habitat_pictures_provider,
30
+
31
+ const habitat_provider = useMemo(
32
+ () => flattenToAppURL(props.data.habitat_provider),
33
+ [props.data.habitat_provider],
34
+ );
35
+ const habitat_pictures_provider = useMemo(
36
+ () => flattenToAppURL(props.data.habitat_pictures_provider),
37
+ [props.data.habitat_pictures_provider],
38
+ );
39
+
40
+ const habitat = useMemo(
41
+ () => props.providers_data?.[habitat_provider] || {},
42
+ [props.providers_data, habitat_provider],
33
43
  );
34
- const habitat = props.providers_data?.[habitat_provider] || {};
35
44
  const habitat_pictures = useMemo(
36
45
  () => props.providers_data?.[habitat_pictures_provider] || {},
37
46
  [props.providers_data, habitat_pictures_provider],
38
47
  );
39
48
 
40
- const { code_2000 = [], scientific_name = [] } = habitat;
49
+ const {
50
+ code_2000 = [],
51
+ scientific_name = [],
52
+ habitat_prioriy = [],
53
+ } = habitat;
41
54
  const { attribution_copyright = [] } = habitat_pictures;
42
55
 
43
56
  const pictures = useMemo(
@@ -49,6 +62,28 @@ const _View = (props) => {
49
62
  [pictures],
50
63
  );
51
64
 
65
+ const handleSliderPrevious = useCallback(() => {
66
+ swiperEl.current.slidePrev();
67
+ if (previewEl.current?.[0]) {
68
+ previewEl.current[0].slidePrev();
69
+ }
70
+ if (previewEl.current?.[1]) {
71
+ previewEl.current[1].slidePrev();
72
+ }
73
+ setActiveSlide(swiperEl.current.realIndex);
74
+ }, []);
75
+
76
+ const handleSliderNext = useCallback(() => {
77
+ swiperEl.current.slideNext();
78
+ if (previewEl.current?.[0]) {
79
+ previewEl.current[0].slideNext();
80
+ }
81
+ if (previewEl.current?.[1]) {
82
+ previewEl.current[1].slideNext();
83
+ }
84
+ setActiveSlide(swiperEl.current.realIndex);
85
+ }, []);
86
+
52
87
  if (!habitat_provider && props.mode === 'edit') {
53
88
  return 'Habitat banner block, habitat provider undefined';
54
89
  }
@@ -64,6 +99,11 @@ const _View = (props) => {
64
99
  <p className="info">
65
100
  Habitats Directive Annex I code&nbsp;&nbsp;&nbsp;{code_2000[0]}
66
101
  </p>
102
+ {habitat_prioriy[0] && (
103
+ <p className="info" style={{ marginTop: '1rem' }}>
104
+ Priority habitat type
105
+ </p>
106
+ )}
67
107
  </div>
68
108
  {pictures_length > 0 && (
69
109
  <div className={cx('carousel one-slide')}>
@@ -74,16 +114,7 @@ const _View = (props) => {
74
114
  <>
75
115
  <button
76
116
  className="swiper-button image-swiper-button-prev"
77
- onClick={() => {
78
- swiperEl.current.slidePrev();
79
- if (previewEl.current?.[0]) {
80
- previewEl.current[0].slidePrev();
81
- }
82
- if (previewEl.current?.[1]) {
83
- previewEl.current[1].slidePrev();
84
- }
85
- setActiveSlide(swiperEl.current.realIndex);
86
- }}
117
+ onClick={handleSliderPrevious}
87
118
  >
88
119
  <Icon
89
120
  className="icon-left"
@@ -94,16 +125,7 @@ const _View = (props) => {
94
125
  </button>
95
126
  <button
96
127
  className="swiper-button image-swiper-button-next"
97
- onClick={() => {
98
- swiperEl.current.slideNext();
99
- if (previewEl.current?.[0]) {
100
- previewEl.current[0].slideNext();
101
- }
102
- if (previewEl.current?.[1]) {
103
- previewEl.current[1].slideNext();
104
- }
105
- setActiveSlide(swiperEl.current.realIndex);
106
- }}
128
+ onClick={handleSliderNext}
107
129
  >
108
130
  <Icon
109
131
  className="icon-right"
@@ -139,7 +161,7 @@ const _View = (props) => {
139
161
  }}
140
162
  >
141
163
  {pictures.map((source, index) => (
142
- <SwiperSlide>
164
+ <SwiperSlide key={source}>
143
165
  <img
144
166
  src={getSource(source)}
145
167
  alt={pictures[index]}
@@ -162,7 +184,7 @@ const _View = (props) => {
162
184
  );
163
185
  };
164
186
 
165
- const View = compose(
187
+ const ViewCompose = compose(
166
188
  connectToMultipleProviders((props) => ({
167
189
  providers: [
168
190
  {
@@ -171,12 +193,12 @@ const View = compose(
171
193
  { provider_url: props.data?.habitat_pictures_provider },
172
194
  ],
173
195
  })),
174
- )(_View);
196
+ )(ViewComponent);
175
197
 
176
- export default function $View(props) {
198
+ export default function View(props) {
177
199
  return (
178
200
  <VisibilitySensor Placeholder={() => <div>loading....&nbsp;</div>}>
179
- <View {...props} />
201
+ <ViewCompose {...props} />
180
202
  </VisibilitySensor>
181
203
  );
182
204
  }
@@ -3,7 +3,7 @@ import isArray from 'lodash/isArray';
3
3
  import isString from 'lodash/isString';
4
4
  import Map from '@eeacms/volto-openlayers-map/Map';
5
5
  import { Layers, Layer } from '@eeacms/volto-openlayers-map/Layers';
6
- import { openlayers } from '@eeacms/volto-openlayers-map';
6
+ import { withOpenLayers } from '@eeacms/volto-openlayers-map';
7
7
 
8
8
  let dynamicLayerDefinition = `
9
9
  [
@@ -43,6 +43,7 @@ let dynamicLayerDefinition = `
43
43
  ]`;
44
44
 
45
45
  const View = (props) => {
46
+ const { ol: openlayers } = props;
46
47
  const mapRef = useRef();
47
48
  const [sources, setSources] = useState([]);
48
49
  const [tiles, setTiles] = useState([]);
@@ -159,4 +160,4 @@ const View = (props) => {
159
160
  );
160
161
  };
161
162
 
162
- export default View;
163
+ export default withOpenLayers(View);
@@ -12,14 +12,15 @@ const View = (props) => {
12
12
  country_name,
13
13
  site_name,
14
14
  designation = [],
15
- cdda_designation_national_language = [],
15
+ iucn_category = [],
16
16
  site_type = [],
17
17
  site_code = [],
18
+ national_id = [],
18
19
  area_ha = [],
19
20
  year_stablished = [],
20
21
  number_protected_habitat_types = [],
21
22
  number_protected_species = [],
22
- major_ecosystem_type = [],
23
+ marine_area_percentage = [],
23
24
  } = provider_data;
24
25
 
25
26
  if (!site_code[0]) return '';
@@ -31,7 +32,9 @@ const View = (props) => {
31
32
  <h2 className="country-title">{site_name}</h2>
32
33
  <p className="site-name">{country_name}</p>
33
34
  {designation ? (
34
- <p className="site-designation">{designation}</p>
35
+ <p className="site-designation">
36
+ Designation type: {designation}
37
+ </p>
35
38
  ) : (
36
39
  ''
37
40
  )}
@@ -42,68 +45,99 @@ const View = (props) => {
42
45
  <>
43
46
  <div className="site-detail">
44
47
  <div className="upper">
45
- {cdda_designation_national_language[0] ? (
46
- <div>{cdda_designation_national_language}</div>
48
+ {site_code[0] ? <div>{site_code}</div> : <div>-</div>}
49
+ </div>
50
+ <div className="lower">NatDA Site Code</div>
51
+ </div>
52
+
53
+ <div className="site-detail">
54
+ <div className="upper">
55
+ {isNumber(area_ha[0]) ? (
56
+ <div>{area_ha} ha</div>
47
57
  ) : (
48
- <div>-</div>
58
+ <div>No data</div>
49
59
  )}
50
60
  </div>
51
- <div className="lower">Designation (National Language)</div>
61
+ <div className="lower">Reported area</div>
52
62
  </div>
53
63
 
54
64
  <div className="site-detail">
55
65
  <div className="upper">
56
- {designation[0] ? <div>{designation}</div> : <div>-</div>}
66
+ {year_stablished[0] ? (
67
+ <div>{year_stablished}</div>
68
+ ) : (
69
+ <div>-</div>
70
+ )}
57
71
  </div>
58
- <div className="lower">Designation (English)</div>
72
+ <div className="lower">Site established</div>
59
73
  </div>
60
- </>
61
- )}
62
74
 
63
- <div className="site-detail">
64
- <div className="upper">
65
- {site_code[0] ? <div>{site_code}</div> : <div>-</div>}
66
- </div>
67
- <div className="lower">Site code</div>
68
- </div>
69
-
70
- <div className="site-detail">
71
- <div className="upper">
72
- {isNumber(area_ha[0]) ? (
73
- <div>{area_ha} ha</div>
75
+ {national_id > 0 ? (
76
+ <div className="site-detail">
77
+ <div className="upper">
78
+ <div>{national_id}</div>
79
+ </div>
80
+ <div className="lower">National Site Code</div>
81
+ </div>
74
82
  ) : (
75
- <div>No data</div>
83
+ ''
76
84
  )}
77
- </div>
78
- <div className="lower">Reported area</div>
79
- </div>
80
85
 
81
- <div className="site-detail">
82
- <div className="upper">
83
- {year_stablished[0] ? (
84
- <div>{year_stablished}</div>
86
+ <div className="site-detail">
87
+ <div className="upper">
88
+ {iucn_category[0] ? (
89
+ <div>{iucn_category}</div>
90
+ ) : (
91
+ <div>Not Reported</div>
92
+ )}
93
+ </div>
94
+ <div className="lower">IUCN Management Category</div>
95
+ </div>
96
+
97
+ {marine_area_percentage > 0 ? (
98
+ <div className="site-detail">
99
+ <div className="upper">
100
+ <div>{marine_area_percentage} %</div>
101
+ </div>
102
+ <div className="lower">Marine Area</div>
103
+ </div>
85
104
  ) : (
86
- <div>-</div>
105
+ ''
87
106
  )}
88
- </div>
89
- <div className="lower">Site established</div>
90
- </div>
91
-
92
- {site_type[0] === 'CDDA' && (
93
- <div className="site-detail">
94
- <div className="upper">
95
- {major_ecosystem_type[0] ? (
96
- <div>{major_ecosystem_type}</div>
97
- ) : (
98
- <div>-</div>
99
- )}
100
- </div>
101
- <div className="lower">Ecosystem</div>
102
- </div>
107
+ </>
103
108
  )}
104
109
 
105
- {site_type[0] === 'Natura2000' && (
110
+ {['Natura2000', 'Emerald'].includes(site_type[0]) && (
106
111
  <>
112
+ <div className="site-detail">
113
+ <div className="upper">
114
+ {site_code[0] ? <div>{site_code}</div> : <div>-</div>}
115
+ </div>
116
+ <div className="lower">Site code</div>
117
+ </div>
118
+
119
+ <div className="site-detail">
120
+ <div className="upper">
121
+ {isNumber(area_ha[0]) ? (
122
+ <div>{area_ha} ha</div>
123
+ ) : (
124
+ <div>No data</div>
125
+ )}
126
+ </div>
127
+ <div className="lower">Reported area</div>
128
+ </div>
129
+
130
+ <div className="site-detail">
131
+ <div className="upper">
132
+ {year_stablished[0] ? (
133
+ <div>{year_stablished}</div>
134
+ ) : (
135
+ <div>-</div>
136
+ )}
137
+ </div>
138
+ <div className="lower">Site established</div>
139
+ </div>
140
+
107
141
  <div className="site-detail">
108
142
  <div className="upper">
109
143
  {isNumber(number_protected_habitat_types[0]) ? (
@@ -14,6 +14,8 @@ const View = (props) => {
14
14
 
15
15
  const sortByOptions = [
16
16
  { text: 'Name', value: 'scientific_name', key: 'scientific_name' },
17
+ { text: 'Coverage', value: 'coverage_ha', key: 'coverage_ha' },
18
+ { text: 'Sites', value: 'number_sites', key: 'number_sites' },
17
19
  ];
18
20
 
19
21
  return (
@@ -7,7 +7,7 @@ import {
7
7
  Label,
8
8
  } from 'semantic-ui-react';
9
9
  import { Icon } from '@plone/volto/components';
10
- // import filterSVG from '@plone/volto/icons/filter.svg';
10
+ import filterSVG from '@plone/volto/icons/filter.svg';
11
11
  import clearSVG from '@plone/volto/icons/clear.svg';
12
12
 
13
13
  import HabitatsGroups from './HabitatsGroups';
@@ -15,8 +15,10 @@ import SortBy from './SortBy';
15
15
 
16
16
  import { filtersLabels } from '../utils';
17
17
 
18
+ // TODO: Display the correct filters for habitats based on existing data
18
19
  const SidebarFilter = (props) => {
19
20
  const { activeFilters, filters, filter, index, setActiveFilters } = props;
21
+
20
22
  return (
21
23
  <div className="filter">
22
24
  <div className="header">
@@ -97,8 +99,22 @@ const View = (props) => {
97
99
  if (key !== 'getTitle') {
98
100
  newFilters[filter][key] =
99
101
  filteredHabitats.filter((habitats) => {
100
- return !!habitats.filter((habitat) => habitat[filter] === key)
101
- .length;
102
+ return !!habitats.filter((habitat) => {
103
+ if (
104
+ filtersLabels[filter][key] ===
105
+ filtersLabels.habitat_prioriy.wp
106
+ ) {
107
+ return habitat[filter] === 1;
108
+ }
109
+ if (
110
+ filtersLabels[filter][key] ===
111
+ filtersLabels.habitat_prioriy.np
112
+ ) {
113
+ return habitat[filter] === null;
114
+ }
115
+
116
+ return habitat[filter] === filtersLabels[filter][key];
117
+ }).length;
102
118
  }).length || 'none';
103
119
  }
104
120
  }
@@ -160,9 +176,9 @@ const View = (props) => {
160
176
  setPagination({ ...pagination, itemsPerPage: data.value });
161
177
  }}
162
178
  />
163
- {/* <button aria-label="Set filters" onClick={() => setVisible(!visible)}>
179
+ <button aria-label="Set filters" onClick={() => setVisible(!visible)}>
164
180
  <Icon name={filterSVG} size="24px" />
165
- </button> */}
181
+ </button>
166
182
  </div>
167
183
  </Container>
168
184
  <Sidebar
@@ -3,9 +3,9 @@ import { Link } from 'react-router-dom';
3
3
  import { Container, Pagination, Grid } from 'semantic-ui-react';
4
4
  import { getObjectByIndex, photoPlaceholders } from '@eeacms/volto-n2k/helpers';
5
5
  import { Filters } from './Filters';
6
- // import { getPopulationString, getLabelString } from './utils';
7
6
 
8
7
  import './style.less';
8
+ import { filtersLabels } from './utils';
9
9
 
10
10
  const getCurrentPageLength = (pagination, arr) => {
11
11
  const totalPages = Math.ceil(pagination.totalItems / pagination.itemsPerPage);
@@ -56,13 +56,36 @@ const View = (props) => {
56
56
 
57
57
  const filteredHabitats = habitats.filter((items, index) => {
58
58
  let itemsHaveFilter = true;
59
+
59
60
  Object.keys(activeFilters).forEach((filter) => {
60
61
  let habitatHasFilter = false;
61
- items.forEach((item) => {
62
- if (activeFilters[filter].includes(item[filter])) {
63
- habitatHasFilter = true;
62
+
63
+ activeFilters[filter].forEach((key) => {
64
+ if (filter in filtersLabels) {
65
+ if (
66
+ filtersLabels[filter][key] === filtersLabels.habitat_prioriy.wp
67
+ ) {
68
+ habitatHasFilter = items[0][filter] === 1;
69
+ return;
70
+ }
71
+ if (
72
+ filtersLabels[filter][key] === filtersLabels.habitat_prioriy.np
73
+ ) {
74
+ habitatHasFilter = items[0][filter] === null;
75
+ return;
76
+ }
77
+
78
+ if (filtersLabels[filter][key] === items[0][filter]) {
79
+ habitatHasFilter = true;
80
+ return;
81
+ }
64
82
  }
65
83
  });
84
+
85
+ if (activeFilters[filter].includes(items[0][filter])) {
86
+ habitatHasFilter = true;
87
+ }
88
+
66
89
  if (!habitatHasFilter) {
67
90
  itemsHaveFilter = false;
68
91
  }
@@ -188,10 +211,13 @@ const View = (props) => {
188
211
  style={{ fontSize: '1.2rem' }}
189
212
  key={`habitat-${index}-${habitat.code_2000}`}
190
213
  >
191
- Cover: {habitat.coverage_ha.toFixed(2)} ha (
192
- {(habitat.coverage_ha / 100).toFixed(4)} km²)
193
214
  {habitat.habitat_prioriy
194
- ? `; Priority habitat type`
215
+ ? `Priority habitat type; `
216
+ : ''}
217
+ Cover: {habitat.coverage_ha.toFixed(2)} ha (
218
+ {(habitat.coverage_ha / 100).toFixed(2)} km²)
219
+ {habitat.caves > 0
220
+ ? `; Number of caves: ${habitat.caves}`
195
221
  : ''}
196
222
  </p>
197
223
  ))}
@@ -220,6 +246,10 @@ const View = (props) => {
220
246
  )}
221
247
  onPageChange={(e, data) => {
222
248
  setPagination({ ...pagination, activePage: data.activePage });
249
+ const el = document.getElementById('habitats-banner');
250
+ el.scrollIntoView({
251
+ block: 'start',
252
+ });
223
253
  }}
224
254
  prevItem={null}
225
255
  nextItem={null}
@@ -10,9 +10,12 @@ div#view .site-habitats-list .habitats-list .ui.container > * {
10
10
  .habitats-filters {
11
11
  .ui.container {
12
12
  display: flex;
13
+ align-items: center;
13
14
  justify-content: space-between;
14
15
 
15
16
  .active-filters {
17
+ margin-top: 0;
18
+
16
19
  .ui.label.active-filter {
17
20
  display: inline-flex;
18
21
  flex-flow: row;
@@ -1,22 +1,8 @@
1
1
  export const filtersLabels = {
2
- population_type: {
3
- p: 'Permanent',
4
- r: 'Reproducing',
5
- c: 'Concentration',
6
- w: 'Wintering',
7
- getTitle: () => 'Population type',
8
- },
9
- counting_unit: {
10
- i: 'Individuals',
11
- p: 'Pairs',
12
- getTitle: () => 'Unit',
13
- },
14
- abundance_category: {
15
- C: 'Common',
16
- R: 'Rare',
17
- V: 'Very rare',
18
- P: 'Present',
19
- getTitle: () => 'Abundance',
2
+ habitat_prioriy: {
3
+ wp: 'With priority',
4
+ np: 'Without priority',
5
+ getTitle: () => 'Habitat priority',
20
6
  },
21
7
  };
22
8
 
@@ -23,7 +23,7 @@ const View = (props) => {
23
23
  }, [JSON.stringify(provider_data)]);
24
24
 
25
25
  return (
26
- <div className="habitats-banner full-width">
26
+ <div className="habitats-banner full-width" id="habitats-banner">
27
27
  <div className="habitats-container">
28
28
  <Container className="habitats-wrapper">
29
29
  <div className="habitats-wrapper">
@@ -11,7 +11,7 @@ const View = (props) => {
11
11
  }, {});
12
12
 
13
13
  return (
14
- <div className="species-banner full-width">
14
+ <div className="species-banner full-width" id="species-banner">
15
15
  <div className="species-container">
16
16
  <Container className="species-wrapper">
17
17
  {/* <Grid size="12">
@@ -4,11 +4,12 @@ import Map from '@eeacms/volto-openlayers-map/Map';
4
4
  import { Interactions } from '@eeacms/volto-openlayers-map/Interactions';
5
5
  import { Controls } from '@eeacms/volto-openlayers-map/Controls';
6
6
  import { Layers, Layer } from '@eeacms/volto-openlayers-map/Layers';
7
- import { openlayers } from '@eeacms/volto-openlayers-map';
7
+ import { withOpenLayers } from '@eeacms/volto-openlayers-map';
8
8
  import { getSiteShapeURL } from './index';
9
9
  import './style.less';
10
10
 
11
11
  const View = (props) => {
12
+ const { ol: openlayers } = props;
12
13
  const dataFetched = React.useRef();
13
14
  const [options, setOptions] = React.useState({});
14
15
  const [vectorSource, setVectorSource] = useState(null);
@@ -119,4 +120,4 @@ const View = (props) => {
119
120
  );
120
121
  };
121
122
 
122
- export default View;
123
+ export default withOpenLayers(View);
@@ -181,6 +181,7 @@ const View = (props) => {
181
181
  {filteredSpecies[index].map((specimen, index) => (
182
182
  <p
183
183
  className="specimen-data"
184
+ style={{ fontSize: '1.2rem' }}
184
185
  key={`specimen-${index}-${specimen.id_eunis}`}
185
186
  >
186
187
  {getLabelString(
@@ -233,6 +234,10 @@ const View = (props) => {
233
234
  )}
234
235
  onPageChange={(e, data) => {
235
236
  setPagination({ ...pagination, activePage: data.activePage });
237
+ const el = document.getElementById('species-banner');
238
+ el.scrollIntoView({
239
+ block: 'start',
240
+ });
236
241
  }}
237
242
  prevItem={null}
238
243
  nextItem={null}
@@ -10,9 +10,12 @@ div#view .site-species-list .species-list .ui.container > * {
10
10
  .species-filters {
11
11
  .ui.container {
12
12
  display: flex;
13
+ align-items: center;
13
14
  justify-content: space-between;
14
15
 
15
16
  .active-filters {
17
+ margin-top: 0;
18
+
16
19
  .ui.label.active-filter {
17
20
  display: inline-flex;
18
21
  flex-flow: row;
@@ -1,5 +1,5 @@
1
1
  /* eslint-disable react/jsx-no-target-blank */
2
- import React, { useRef, useMemo, useState } from 'react';
2
+ import React, { useRef, useMemo, useState, useCallback } from 'react';
3
3
  import { compose } from 'redux';
4
4
  import cx from 'classnames';
5
5
  import loadable from '@loadable/component';
@@ -24,15 +24,23 @@ const getSource = (source) => {
24
24
  return parsedSource;
25
25
  };
26
26
 
27
- const _View = (props) => {
27
+ const ViewComponent = (props) => {
28
28
  const swiperEl = useRef();
29
29
  const previewEl = useRef();
30
30
  const [activeSlide, setActiveSlide] = useState(0);
31
- const species_provider = flattenToAppURL(props.data.species_provider);
32
- const species_pictures_provider = flattenToAppURL(
33
- props.data.species_pictures_provider,
31
+ const species_provider = useMemo(
32
+ () => flattenToAppURL(props.data.species_provider),
33
+ [props.data.species_provider],
34
+ );
35
+ const species_pictures_provider = useMemo(
36
+ () => flattenToAppURL(props.data.species_pictures_provider),
37
+ [props.data.species_pictures_provider],
38
+ );
39
+
40
+ const species = useMemo(
41
+ () => props.providers_data?.[species_provider] || {},
42
+ [props.providers_data, species_provider],
34
43
  );
35
- const species = props.providers_data?.[species_provider] || {};
36
44
  const species_pictures = useMemo(
37
45
  () => props.providers_data?.[species_pictures_provider] || {},
38
46
  [props.providers_data, species_pictures_provider],
@@ -63,6 +71,28 @@ const _View = (props) => {
63
71
  [pictures],
64
72
  );
65
73
 
74
+ const handleSliderPrevious = useCallback(() => {
75
+ swiperEl.current.slidePrev();
76
+ if (previewEl.current?.[0]) {
77
+ previewEl.current[0].slidePrev();
78
+ }
79
+ if (previewEl.current?.[1]) {
80
+ previewEl.current[1].slidePrev();
81
+ }
82
+ setActiveSlide(swiperEl.current.realIndex);
83
+ }, []);
84
+
85
+ const handleSliderNext = useCallback(() => {
86
+ swiperEl.current.slideNext();
87
+ if (previewEl.current?.[0]) {
88
+ previewEl.current[0].slideNext();
89
+ }
90
+ if (previewEl.current?.[1]) {
91
+ previewEl.current[1].slideNext();
92
+ }
93
+ setActiveSlide(swiperEl.current.realIndex);
94
+ }, []);
95
+
66
96
  if (!species_provider && props.mode === 'edit') {
67
97
  return 'species banner block, species provider undefined';
68
98
  }
@@ -110,16 +140,7 @@ const _View = (props) => {
110
140
  <>
111
141
  <button
112
142
  className="swiper-button image-swiper-button-prev"
113
- onClick={() => {
114
- swiperEl.current.slidePrev();
115
- if (previewEl.current?.[0]) {
116
- previewEl.current[0].slidePrev();
117
- }
118
- if (previewEl.current?.[1]) {
119
- previewEl.current[1].slidePrev();
120
- }
121
- setActiveSlide(swiperEl.current.realIndex);
122
- }}
143
+ onClick={handleSliderPrevious}
123
144
  >
124
145
  <Icon
125
146
  className="icon-left"
@@ -130,16 +151,7 @@ const _View = (props) => {
130
151
  </button>
131
152
  <button
132
153
  className="swiper-button image-swiper-button-next"
133
- onClick={() => {
134
- swiperEl.current.slideNext();
135
- if (previewEl.current?.[0]) {
136
- previewEl.current[0].slideNext();
137
- }
138
- if (previewEl.current?.[1]) {
139
- previewEl.current[1].slideNext();
140
- }
141
- setActiveSlide(swiperEl.current.realIndex);
142
- }}
154
+ onClick={handleSliderNext}
143
155
  >
144
156
  <Icon
145
157
  className="icon-right"
@@ -176,7 +188,7 @@ const _View = (props) => {
176
188
  }}
177
189
  >
178
190
  {pictures.map((source, index) => (
179
- <SwiperSlide>
191
+ <SwiperSlide key={source}>
180
192
  <img
181
193
  src={getSource(source)}
182
194
  alt={pictures[index]}
@@ -198,7 +210,7 @@ const _View = (props) => {
198
210
  );
199
211
  };
200
212
 
201
- const View = compose(
213
+ const ViewCompose = compose(
202
214
  connectToMultipleProviders((props) => ({
203
215
  providers: [
204
216
  {
@@ -207,12 +219,12 @@ const View = compose(
207
219
  { provider_url: props.data?.species_pictures_provider },
208
220
  ],
209
221
  })),
210
- )(_View);
222
+ )(ViewComponent);
211
223
 
212
- export default function $View(props) {
224
+ export default function View(props) {
213
225
  return (
214
226
  <VisibilitySensor Placeholder={() => <div>loading....&nbsp;</div>}>
215
- <View {...props} />
227
+ <ViewCompose {...props} />
216
228
  </VisibilitySensor>
217
229
  );
218
230
  }
@@ -4,11 +4,12 @@ import Map from '@eeacms/volto-openlayers-map/Map';
4
4
  import { Interactions } from '@eeacms/volto-openlayers-map/Interactions';
5
5
  import { Controls } from '@eeacms/volto-openlayers-map/Controls';
6
6
  import { Layers, Layer } from '@eeacms/volto-openlayers-map/Layers';
7
- import { openlayers } from '@eeacms/volto-openlayers-map';
7
+ import { withOpenLayers } from '@eeacms/volto-openlayers-map';
8
8
  import { getSpeciesDistributionURL } from './index';
9
9
  import './style.less';
10
10
 
11
11
  const View = (props) => {
12
+ const { ol: openlayers } = props;
12
13
  const dataFetched = React.useRef();
13
14
  const [options, setOptions] = React.useState({});
14
15
  const [vectorSource, setVectorSource] = useState(null);
@@ -115,4 +116,4 @@ const View = (props) => {
115
116
  );
116
117
  };
117
118
 
118
- export default View;
119
+ export default withOpenLayers(View);
@@ -4,11 +4,14 @@ import Map from '@eeacms/volto-openlayers-map/Map';
4
4
  import { Interactions } from '@eeacms/volto-openlayers-map/Interactions';
5
5
  import { Controls } from '@eeacms/volto-openlayers-map/Controls';
6
6
  import { Layers, Layer } from '@eeacms/volto-openlayers-map/Layers';
7
- import { openlayers } from '@eeacms/volto-openlayers-map';
7
+ import { withOpenLayers } from '@eeacms/volto-openlayers-map';
8
8
  import { getSpeciesProtectedSitesURL } from './index';
9
9
  import './style.less';
10
10
 
11
+ const DEFAULT_LAYERS = [3, 7];
12
+
11
13
  const View = (props) => {
14
+ const { ol: openlayers } = props;
12
15
  const dataFetched = React.useRef();
13
16
  const [options, setOptions] = React.useState({});
14
17
  const [vectorSource, setVectorSource] = useState(null);
@@ -16,6 +19,7 @@ const View = (props) => {
16
19
  const { extent, format, proj, style, source } = openlayers;
17
20
  const provider_data = props.provider_data || {};
18
21
  const { code_2000 = [] } = provider_data;
22
+ const layers = DEFAULT_LAYERS;
19
23
 
20
24
  useEffect(() => {
21
25
  if (__SERVER__) return;
@@ -32,36 +36,89 @@ const View = (props) => {
32
36
  }),
33
37
  ]);
34
38
  /* eslint-disable-next-line */
35
- }, []);
39
+ }, [source]);
36
40
 
37
41
  useEffect(() => {
38
- if (__SERVER__ || !vectorSource || !code_2000[0] || dataFetched.current)
42
+ if (__SERVER__ || !vectorSource || !code_2000[0]) {
43
+ dataFetched.current = false;
39
44
  return;
45
+ }
40
46
 
41
47
  const esrijsonFormat = new format.EsriJSON();
42
- // Get species protected sites
43
- fetch(getSpeciesProtectedSitesURL(code_2000[0])).then(function (response) {
44
- if (response.status !== 200) return;
45
- response.json().then(function (data) {
48
+ const urls = getSpeciesProtectedSitesURL(code_2000[0], layers);
49
+
50
+ let isMounted = true;
51
+ dataFetched.current = false;
52
+
53
+ // Get species protected sites from all specified layers
54
+ Promise.all(
55
+ Object.values(urls).map((url) =>
56
+ fetch(url)
57
+ .then((response) => {
58
+ if (!isMounted) return { features: [] };
59
+ return response.status === 200 ? response.json() : { features: [] };
60
+ })
61
+ .catch(() => {
62
+ if (!isMounted) return { features: [] };
63
+ return { features: [] };
64
+ }),
65
+ ),
66
+ )
67
+ .then((results) => {
68
+ if (!isMounted) return;
69
+
70
+ const validResults = results.filter((r) => !r.error);
46
71
  dataFetched.current = true;
47
- if (data.features && data.features.length > 0) {
48
- const features = esrijsonFormat.readFeatures(data);
72
+
73
+ const allFeatures = validResults.reduce((acc, data) => {
74
+ return acc.concat(data.features || []);
75
+ }, []);
76
+
77
+ if (allFeatures.length > 0) {
78
+ // all features from all layers should have the same metadata
79
+ const metadataTemplate = validResults.find(
80
+ (r) => r.features && r.features.length > 0,
81
+ );
82
+
83
+ const features = esrijsonFormat.readFeatures({
84
+ ...metadataTemplate,
85
+ features: allFeatures,
86
+ });
87
+
49
88
  if (features.length > 0) {
50
89
  vectorSource.addFeatures(features);
51
90
  const vectorExtent = vectorSource.getExtent();
52
- let size = extent.getSize(vectorExtent);
53
- setOptions({
54
- ...options,
55
- extent: new extent.buffer(vectorExtent, size[0] * 0.1),
56
- });
91
+
92
+ if (!extent.isEmpty(vectorExtent)) {
93
+ let size = extent.getSize(vectorExtent);
94
+ setOptions({
95
+ ...options,
96
+ extent: new extent.buffer(vectorExtent, size[0] * 0.1),
97
+ });
98
+ }
57
99
  }
58
100
  }
101
+ })
102
+ .catch((error) => {
103
+ if (!isMounted) return;
104
+
105
+ dataFetched.current = false;
106
+
107
+ if (vectorSource) vectorSource.clear();
108
+ setOptions((currentOptions) => ({
109
+ ...currentOptions,
110
+ extent: undefined,
111
+ }));
59
112
  });
60
- });
113
+
114
+ return () => {
115
+ isMounted = false;
116
+ };
61
117
  /* eslint-disable-next-line */
62
118
  }, [vectorSource, code_2000?.[0]]);
63
119
 
64
120
  if (__SERVER__ || !vectorSource) return '';
121
+
65
122
  return (
66
123
  <div className="species-protected-sites-wrapper">
67
124
  <div className="species-protected-sites">
@@ -111,4 +168,4 @@ const View = (props) => {
111
168
  );
112
169
  };
113
170
 
114
- export default View;
171
+ export default withOpenLayers(View);
@@ -1,10 +1,17 @@
1
1
  import SpeciesProtectedSitesView from './View';
2
2
  import getSchema from './schema';
3
3
 
4
- export function getSpeciesProtectedSitesURL(code_2000) {
5
- return encodeURI(
6
- `https://bio.discomap.eea.europa.eu/arcgis/rest/services/ProtectedSites/EUNIS_Website_Dyna_WM/MapServer/7/query?f=json&where=SPECIESCODE LIKE '%${code_2000.toUpperCase()}%'&returnGeometry=true&spatialRel=esriSpatialRelIntersects&outFields=SPECIESCODE,SITECODE,HABITATCODE,OBJECTID&outSR=102100`,
4
+ export function getSpeciesProtectedSitesURL(code_2000, layers) {
5
+ const baseUrl =
6
+ 'https://bio.discomap.eea.europa.eu/arcgis/rest/services/ProtectedSites/EUNIS_Website_Dyna_WM/MapServer';
7
+ const queryParams = encodeURI(
8
+ `?f=json&where=SPECIESCODE LIKE '%${code_2000.toUpperCase()}%'&returnGeometry=true&spatialRel=esriSpatialRelIntersects&outFields=SPECIESCODE,SITECODE,HABITATCODE,OBJECTID&outSR=102100`,
7
9
  );
10
+
11
+ return layers.reduce((acc, layer) => {
12
+ acc[`layer${layer}`] = `${baseUrl}/${layer}/query${queryParams}`;
13
+ return acc;
14
+ }, {});
8
15
  }
9
16
 
10
17
  export default function applyConfig(config) {