@eeacms/volto-n2k 1.1.1 → 1.1.3

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 (23) hide show
  1. package/CHANGELOG.md +19 -2
  2. package/package.json +1 -1
  3. package/src/components/manage/Blocks/ExploreHabitats/View.jsx +71 -66
  4. package/src/components/manage/Blocks/HabitatsBanner/View.jsx +4 -1
  5. package/src/components/manage/Blocks/ImageText/Edit.jsx +1 -2
  6. package/src/components/manage/Blocks/SiteHabitatsList/Filters/HabitatsGroups.jsx +49 -0
  7. package/src/components/manage/Blocks/SiteHabitatsList/Filters/SortBy.jsx +52 -0
  8. package/src/components/manage/Blocks/SiteHabitatsList/Filters/View.jsx +201 -0
  9. package/src/components/manage/Blocks/SiteHabitatsList/Filters/index.js +4 -0
  10. package/src/components/manage/Blocks/SiteHabitatsList/View.jsx +214 -84
  11. package/src/components/manage/Blocks/SiteHabitatsList/style.less +256 -45
  12. package/src/components/manage/Blocks/SiteHabitatsList/utils.js +33 -0
  13. package/src/components/manage/Blocks/SiteHabitatsListOld/View.jsx +106 -0
  14. package/src/components/manage/Blocks/SiteHabitatsListOld/index.js +17 -0
  15. package/src/components/manage/Blocks/SiteHabitatsListOld/schema.js +19 -0
  16. package/src/components/manage/Blocks/SiteHabitatsListOld/style.less +70 -0
  17. package/src/components/manage/Blocks/SiteProtectedHabitats/View.jsx +11 -9
  18. package/src/components/manage/Blocks/SiteProtectedSpecies/View.jsx +11 -9
  19. package/src/components/manage/Blocks/SiteSpeciesList/Filters/SortBy.jsx +1 -1
  20. package/src/components/manage/Blocks/SiteSpeciesList/Filters/SpeciesGroups.jsx +10 -4
  21. package/src/components/manage/Blocks/SiteSpeciesList/Filters/View.jsx +1 -0
  22. package/src/components/manage/Blocks/SiteSpeciesList/style.less +30 -22
  23. package/src/components/manage/Blocks/SpeciesBanner/View.jsx +1 -0
package/CHANGELOG.md CHANGED
@@ -4,11 +4,28 @@ 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.1](https://github.com/eea/volto-n2k/compare/1.1.0...1.1.1) - 12 November 2024
7
+ ### [1.1.3](https://github.com/eea/volto-n2k/compare/1.1.2...1.1.3) - 9 January 2025
8
+
9
+ #### :house: Internal changes
10
+
11
+ - style: Automated code fix [eea-jenkins - [`5364109`](https://github.com/eea/volto-n2k/commit/536410947c52c860c6c51ddd73f3d829880cadbe)]
12
+ - style: Automated code fix [eea-jenkins - [`6c96546`](https://github.com/eea/volto-n2k/commit/6c965460c1d7cfd124981b68e8db64e204846a3d)]
8
13
 
9
14
  #### :hammer_and_wrench: Others
10
15
 
11
- - use the correct object_list widget [Miu Razvan - [`94de8ee`](https://github.com/eea/volto-n2k/commit/94de8ee0980388e395cf679fcdae2f4b0da3fbba)]
16
+ - fix sonarqube errors [Claudia Ifrim - [`bbd9b7a`](https://github.com/eea/volto-n2k/commit/bbd9b7a0fb6acf40c3edbf5e2a034b7df0e2048b)]
17
+ - comment filters for habitats, fix z-index for filters on species list [Claudia Ifrim - [`44533aa`](https://github.com/eea/volto-n2k/commit/44533aa781b3b374320071b7cab0adbad322ad5b)]
18
+ - fix ImageText editor [Miu Razvan - [`67e6611`](https://github.com/eea/volto-n2k/commit/67e66113d289d5b3984909aee94e6b343fcd69a9)]
19
+ - Make site habitats list work la species list [Miu Razvan - [`498e995`](https://github.com/eea/volto-n2k/commit/498e9955882bba9c2c549ab29dce5b988f36f489)]
20
+ ### [1.1.2](https://github.com/eea/volto-n2k/compare/1.1.1...1.1.2) - 11 December 2024
21
+
22
+ #### :hammer_and_wrench: Others
23
+
24
+ - don't run cypress [Miu Razvan - [`3ff98b8`](https://github.com/eea/volto-n2k/commit/3ff98b8b0da5b594e701c517c562df31f8bdaf82)]
25
+ - fix tests [Miu Razvan - [`0b2d0e0`](https://github.com/eea/volto-n2k/commit/0b2d0e0c5317bc6ac81da56d2bb225ae8d782085)]
26
+ - Fix habitats/species banner, ref #278618 [Miu Razvan - [`b73d5c7`](https://github.com/eea/volto-n2k/commit/b73d5c73ca3f6d77c0bf0058bed453d404015e03)]
27
+ ### [1.1.1](https://github.com/eea/volto-n2k/compare/1.1.0...1.1.1) - 13 November 2024
28
+
12
29
  ### [1.1.0](https://github.com/eea/volto-n2k/compare/1.0.35...1.1.0) - 7 November 2024
13
30
 
14
31
  #### :bug: Bug Fixes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eeacms/volto-n2k",
3
- "version": "1.1.1",
3
+ "version": "1.1.3",
4
4
  "description": "volto-n2k: Volto add-on",
5
5
  "main": "src/index.js",
6
6
  "author": "European Environment Agency: IDM2 A-Team",
@@ -104,77 +104,82 @@ const View = (props) => {
104
104
  /* eslint-disable-next-line */
105
105
  }, [JSON.stringify(activePageResults)]);
106
106
 
107
+ if (__SERVER__) return null;
108
+
107
109
  return (
108
- <div className="explore-habitats-wrapper full-width">
109
- <div className="explore-habitats">
110
- <Map
111
- view={{
112
- center: proj.fromLonLat([20, 50]),
113
- showFullExtent: true,
114
- zoom: 5,
115
- ...(options.extent ? { extent: options.extent } : {}),
116
- }}
117
- pixelRatio={1}
118
- >
119
- <Layers>
120
- <Layer.Tile source={tileWMSSources[0]} zIndex={0} />
121
- <Layer.Tile source={tileWMSSources[1]} zIndex={1} />
122
- <Layer.Vector
123
- source={vectorSource}
124
- title="highlightLayer"
125
- style={
126
- new style.Style({
127
- fill: new style.Fill({
128
- color: 'rgba(255,255,255,0.4)',
129
- }),
130
- stroke: new style.Stroke({
131
- color: '#00A390',
132
- // color: '#F8E473',
133
- width: 3,
134
- }),
135
- image: new style.Circle({
136
- radius: 5,
137
- fill: new style.Fill({ color: 'rgba(4, 167, 125,0.6)' }),
138
- // fill: new style.Fill({ color: 'rgba(248,228,115,0.6)' }),
110
+ __CLIENT__ && (
111
+ <div className="explore-habitats-wrapper full-width">
112
+ <div className="explore-habitats">
113
+ <Map
114
+ view={{
115
+ center: proj.fromLonLat([20, 50]),
116
+ showFullExtent: true,
117
+ zoom: 5,
118
+ ...(options.extent ? { extent: options.extent } : {}),
119
+ }}
120
+ pixelRatio={1}
121
+ >
122
+ <Layers>
123
+ <Layer.Tile source={tileWMSSources[0]} zIndex={0} />
124
+ <Layer.Tile source={tileWMSSources[1]} zIndex={1} />
125
+ <Layer.Vector
126
+ source={vectorSource}
127
+ title="highlightLayer"
128
+ style={
129
+ new style.Style({
130
+ fill: new style.Fill({
131
+ color: 'rgba(255,255,255,0.4)',
132
+ }),
139
133
  stroke: new style.Stroke({
140
- color: 'rgba(242, 180, 87, 1)',
141
- width: 2,
134
+ color: '#00A390',
135
+ // color: '#F8E473',
136
+ width: 3,
137
+ }),
138
+ image: new style.Circle({
139
+ radius: 5,
140
+ fill: new style.Fill({ color: 'rgba(4, 167, 125,0.6)' }),
141
+ // fill: new style.Fill({ color: 'rgba(248,228,115,0.6)' }),
142
+ stroke: new style.Stroke({
143
+ color: 'rgba(242, 180, 87, 1)',
144
+ width: 2,
145
+ }),
142
146
  }),
143
- }),
144
- })
145
- }
146
- zIndex={2}
147
+ })
148
+ }
149
+ zIndex={2}
150
+ />
151
+ </Layers>
152
+ <Controls attribution={true} zoom={false} />
153
+ <Interactions
154
+ doubleClickZoom={true}
155
+ dragAndDrop={false}
156
+ dragPan={true}
157
+ keyboardPan={true}
158
+ keyboardZoom={true}
159
+ mouseWheelZoom={true}
160
+ pointer={false}
161
+ select={false}
147
162
  />
148
- </Layers>
149
- <Controls attribution={true} zoom={false} />
150
- <Interactions
151
- doubleClickZoom={true}
152
- dragAndDrop={false}
153
- dragPan={true}
154
- keyboardPan={true}
155
- keyboardZoom={true}
156
- mouseWheelZoom={true}
157
- pointer={false}
158
- select={false}
159
- />
160
- </Map>
163
+ </Map>
164
+ </div>
165
+ <Container>
166
+ <Message className="map-info-notice" style={{ color: '#005248' }}>
167
+ <p>
168
+ The designations employed and the presentation of material on this
169
+ map do not imply the expression of any opinion whatsoever on the
170
+ part of the European Union concerning the legal status of any
171
+ country, territory, city or area or of its authorities, or
172
+ concerning the delimitation of its frontiers or boundaries.
173
+ </p>
174
+ <p>
175
+ <strong>Note:</strong> When you perform a search we will highlight
176
+ only the results available on the active page of the results
177
+ table.
178
+ </p>
179
+ </Message>
180
+ </Container>
161
181
  </div>
162
- <Container>
163
- <Message className="map-info-notice" style={{ color: '#005248' }}>
164
- <p>
165
- The designations employed and the presentation of material on this
166
- map do not imply the expression of any opinion whatsoever on the
167
- part of the European Union concerning the legal status of any
168
- country, territory, city or area or of its authorities, or
169
- concerning the delimitation of its frontiers or boundaries.
170
- </p>
171
- <p>
172
- <strong>Note:</strong> When you perform a search we will highlight
173
- only the results available on the active page of the results table.
174
- </p>
175
- </Message>
176
- </Container>
177
- </div>
182
+ )
178
183
  );
179
184
  };
180
185
 
@@ -11,6 +11,7 @@ import arrowLeft from '@eeacms/volto-n2k/icons/arrow-left.svg';
11
11
  import arrowRight from '@eeacms/volto-n2k/icons/arrow-right.svg';
12
12
 
13
13
  import './style.less';
14
+ import 'swiper/css';
14
15
 
15
16
  const SwiperLoader = loadable.lib(() => import('swiper'));
16
17
  const SwiperReactLoader = loadable.lib(() => import('swiper/react'));
@@ -114,7 +115,9 @@ const _View = (props) => {
114
115
  </>
115
116
  )}
116
117
  {!!attribution_copyright[activeSlide] && (
117
- <p>{attribution_copyright[activeSlide]}</p>
118
+ <p title={attribution_copyright[activeSlide]}>
119
+ {attribution_copyright[activeSlide]}
120
+ </p>
118
121
  )}
119
122
  </div>
120
123
  {__CLIENT__ && (
@@ -18,8 +18,7 @@ const Edit = (props) => {
18
18
  const { data = {}, selected = false } = props;
19
19
  const schema = getSchema();
20
20
  const value = { children: data.value || [], isVoid: Editor.isVoid };
21
- const valueUndefined =
22
- !value.children.length || Editor.string(value, []) === '';
21
+ const valueUndefined = !value.children.length;
23
22
 
24
23
  const handleKeyDown = (e, index, { disableEnter = false } = {}) => {
25
24
  if (e.key === 'Enter' && !e.shiftKey && !disableEnter) {
@@ -0,0 +1,49 @@
1
+ import React from 'react';
2
+ import { Container } from 'semantic-ui-react';
3
+ import cx from 'classnames';
4
+
5
+ const HabitatsGroups = (props) => {
6
+ const [habitatsGroups, setHabitatsGroups] = React.useState([]);
7
+ const {
8
+ provider_data = {},
9
+ activeHabitatsGroup = 'All',
10
+ setActiveHabitatsGroup = () => {},
11
+ } = props;
12
+
13
+ React.useEffect(() => {
14
+ setHabitatsGroups(
15
+ [
16
+ ...(provider_data.habitat_group?.length ? ['All'] : []),
17
+ ...new Set(provider_data.habitat_group || []),
18
+ ].sort((a, b) => {
19
+ if (a === 'All') return -1;
20
+ if (b === 'All') return 1;
21
+ return a.localeCompare(b);
22
+ }),
23
+ );
24
+ /* eslint-disable-next-line */
25
+ }, [JSON.stringify(provider_data)]);
26
+
27
+ return (
28
+ <div className="habitats-groups">
29
+ <Container>
30
+ {habitatsGroups.map((species) => (
31
+ <button
32
+ key={`group-filter-${species}`}
33
+ className={cx({
34
+ 'habitats-group': true,
35
+ active: activeHabitatsGroup === species,
36
+ })}
37
+ onClick={() => {
38
+ setActiveHabitatsGroup(species);
39
+ }}
40
+ >
41
+ {species}
42
+ </button>
43
+ ))}
44
+ </Container>
45
+ </div>
46
+ );
47
+ };
48
+
49
+ export default HabitatsGroups;
@@ -0,0 +1,52 @@
1
+ import React from 'react';
2
+ import { Dropdown } from 'semantic-ui-react';
3
+ import { Icon } from '@plone/volto/components';
4
+ import upSVG from '@plone/volto/icons/up.svg';
5
+ import downSVG from '@plone/volto/icons/down.svg';
6
+
7
+ const antonyms = {
8
+ ASC: 'DESC',
9
+ DESC: 'ASC',
10
+ };
11
+
12
+ const View = (props) => {
13
+ const { sortBy, setSortBy } = props;
14
+
15
+ const sortByOptions = [
16
+ { text: 'Name', value: 'scientific_name', key: 'scientific_name' },
17
+ ];
18
+
19
+ return (
20
+ <Dropdown aria-label="Sort habitats by" text="SORT BY" floating button>
21
+ <Dropdown.Menu>
22
+ {sortByOptions.map((option) => (
23
+ <Dropdown.Item
24
+ key={option.text}
25
+ active={sortBy === option.value}
26
+ onClick={(e, data) => {
27
+ const activePoperty = sortBy[0];
28
+ const activeOrder = sortBy[1];
29
+ const newOrder =
30
+ activePoperty === option.value ? antonyms[activeOrder] : 'ASC';
31
+ setSortBy([option.value, newOrder]);
32
+ }}
33
+ >
34
+ <p>
35
+ {option.text}
36
+ {sortBy[0] === option.value ? (
37
+ <Icon
38
+ name={sortBy[1] === 'ASC' ? upSVG : downSVG}
39
+ size="14px"
40
+ />
41
+ ) : (
42
+ ''
43
+ )}
44
+ </p>
45
+ </Dropdown.Item>
46
+ ))}
47
+ </Dropdown.Menu>
48
+ </Dropdown>
49
+ );
50
+ };
51
+
52
+ export default View;
@@ -0,0 +1,201 @@
1
+ import React from 'react';
2
+ import {
3
+ Container,
4
+ Dropdown,
5
+ Sidebar,
6
+ Checkbox,
7
+ Label,
8
+ } from 'semantic-ui-react';
9
+ import { Icon } from '@plone/volto/components';
10
+ // import filterSVG from '@plone/volto/icons/filter.svg';
11
+ import clearSVG from '@plone/volto/icons/clear.svg';
12
+
13
+ import HabitatsGroups from './HabitatsGroups';
14
+ import SortBy from './SortBy';
15
+
16
+ import { filtersLabels } from '../utils';
17
+
18
+ const SidebarFilter = (props) => {
19
+ const { activeFilters, filters, filter, index, setActiveFilters } = props;
20
+ return (
21
+ <div className="filter">
22
+ <div className="header">
23
+ <p className="title">
24
+ {filtersLabels[filter].getTitle().toUpperCase()}
25
+ {!index ? (
26
+ <button
27
+ className="reset-button"
28
+ onClick={() => {
29
+ setActiveFilters({});
30
+ }}
31
+ >
32
+ Reset
33
+ </button>
34
+ ) : (
35
+ ''
36
+ )}
37
+ </p>
38
+ </div>
39
+ {Object.keys(filters[filter]).map((field) => (
40
+ <div key={filtersLabels[filter][field]} className="checkbox-wrapper">
41
+ <Checkbox
42
+ name={filter}
43
+ label={filtersLabels[filter][field]}
44
+ checked={activeFilters[filter]?.includes(field) || false}
45
+ onClick={() => {
46
+ const newActiveFilters = { ...activeFilters };
47
+ if (newActiveFilters[filter]?.includes(field)) {
48
+ newActiveFilters[filter].splice(
49
+ newActiveFilters[filter].indexOf(field),
50
+ 1,
51
+ );
52
+ } else {
53
+ newActiveFilters[filter] = [
54
+ ...(activeFilters[filter] || []),
55
+ field,
56
+ ];
57
+ }
58
+ if (!newActiveFilters[filter].length) {
59
+ delete newActiveFilters[filter];
60
+ }
61
+ setActiveFilters(newActiveFilters);
62
+ }}
63
+ />
64
+ <p className="count">{filters[filter][field]}</p>
65
+ </div>
66
+ ))}
67
+ </div>
68
+ );
69
+ };
70
+
71
+ const View = (props) => {
72
+ const [visible, setVisible] = React.useState(false);
73
+ const [filters, setFilters] = React.useState({});
74
+ const {
75
+ provider_data,
76
+ activeFilters,
77
+ filteredHabitats,
78
+ pagination,
79
+ sortBy,
80
+ habitats,
81
+ setActiveFilters,
82
+ setPagination,
83
+ setSortBy,
84
+ } = props;
85
+ const itemsPerPageOptions = [
86
+ { key: '10', text: '10', value: 10 },
87
+ { key: '25', text: '25', value: 25 },
88
+ { key: '50', text: '50', value: 50 },
89
+ { key: '100', text: '100', value: 100 },
90
+ ];
91
+
92
+ const updateFilters = () => {
93
+ const newFilters = {};
94
+ Object.keys(filtersLabels).forEach((filter) => {
95
+ newFilters[filter] = {};
96
+ for (let key in filtersLabels[filter]) {
97
+ if (key !== 'getTitle') {
98
+ newFilters[filter][key] =
99
+ filteredHabitats.filter((habitats) => {
100
+ return !!habitats.filter((habitat) => habitat[filter] === key)
101
+ .length;
102
+ }).length || 'none';
103
+ }
104
+ }
105
+ });
106
+ setFilters(newFilters);
107
+ };
108
+
109
+ React.useEffect(() => {
110
+ if (provider_data && habitats.length) {
111
+ updateFilters();
112
+ }
113
+ /* eslint-disable-next-line */
114
+ }, [filteredHabitats]);
115
+
116
+ return (
117
+ <div className="habitats-filters">
118
+ <HabitatsGroups {...props} />
119
+ <Container>
120
+ <div className="active-filters">
121
+ {Object.keys(activeFilters).map((filter) =>
122
+ activeFilters[filter].map((field) => (
123
+ <Label
124
+ className="active-filter"
125
+ key={`active-filter-${field}`}
126
+ as="span"
127
+ >
128
+ {filtersLabels[filter][field]}
129
+ <Icon
130
+ name={clearSVG}
131
+ size="18px"
132
+ onClick={() => {
133
+ const newActiveFilters = { ...activeFilters };
134
+ if (newActiveFilters[filter]?.includes(field)) {
135
+ newActiveFilters[filter].splice(
136
+ newActiveFilters[filter].indexOf(field),
137
+ 1,
138
+ );
139
+ }
140
+ if (!newActiveFilters[filter].length) {
141
+ delete newActiveFilters[filter];
142
+ }
143
+ setActiveFilters(newActiveFilters);
144
+ }}
145
+ />
146
+ </Label>
147
+ )),
148
+ )}
149
+ </div>
150
+ <div className="toolbar">
151
+ <SortBy sortBy={sortBy} setSortBy={setSortBy} />
152
+ <Dropdown
153
+ aria-label="Set number of habitats per page"
154
+ placeholder="Items per page"
155
+ value={pagination.itemsPerPage}
156
+ floating
157
+ button
158
+ options={itemsPerPageOptions}
159
+ onChange={(e, data) => {
160
+ setPagination({ ...pagination, itemsPerPage: data.value });
161
+ }}
162
+ />
163
+ {/* <button aria-label="Set filters" onClick={() => setVisible(!visible)}>
164
+ <Icon name={filterSVG} size="24px" />
165
+ </button> */}
166
+ </div>
167
+ </Container>
168
+ <Sidebar
169
+ as="div"
170
+ className="z-full"
171
+ animation="overlay"
172
+ direction="right"
173
+ onHide={() => setVisible(false)}
174
+ vertical
175
+ visible={visible}
176
+ width="wide"
177
+ >
178
+ <div className="sidebar-header">
179
+ <p className="title">Filters</p>
180
+ <button className="clear-button" onClick={() => setVisible(false)}>
181
+ <Icon name={clearSVG} size="20px" color="#fff" />
182
+ </button>
183
+ </div>
184
+ <div className="filters">
185
+ {Object.keys(filters).map((filter, index) => (
186
+ <SidebarFilter
187
+ key={filter}
188
+ index={index}
189
+ activeFilters={activeFilters}
190
+ filters={filters}
191
+ filter={filter}
192
+ setActiveFilters={setActiveFilters}
193
+ />
194
+ ))}
195
+ </div>
196
+ </Sidebar>
197
+ </div>
198
+ );
199
+ };
200
+
201
+ export default View;
@@ -0,0 +1,4 @@
1
+ import HabitatsGroupsFilters from './HabitatsGroups';
2
+ import Filters from './View';
3
+
4
+ export { HabitatsGroupsFilters, Filters };