@eeacms/volto-n2k 1.1.2 → 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.
@@ -1,70 +1,281 @@
1
- .site-habitats-list {
2
- .icon {
3
- cursor: pointer;
4
- }
1
+ div#view .site-habitats-list .habitats-group-filter .ui.container > *,
2
+ div#view .site-habitats-list .habitats-filters .ui.container > *,
3
+ div#view .site-habitats-list .habitats-list .ui.container > * {
4
+ margin-bottom: 0;
5
+ }
5
6
 
6
- .habitat {
7
- padding: 1rem 2rem;
8
- border: 1px solid #e8e8e8;
9
- border-radius: 10px;
10
- margin-bottom: 1rem;
11
- background-color: #fff !important;
7
+ .site-habitats-list {
8
+ margin-top: -1em;
12
9
 
13
- .habitat-toolbar {
10
+ .habitats-filters {
11
+ .ui.container {
14
12
  display: flex;
15
- align-items: center;
16
13
  justify-content: space-between;
14
+
15
+ .active-filters {
16
+ .ui.label.active-filter {
17
+ display: inline-flex;
18
+ flex-flow: row;
19
+ align-items: center;
20
+ border: 1px solid #c5c5c5;
21
+ border-radius: 18px;
22
+ color: #000;
23
+ font-weight: 400;
24
+
25
+ svg.icon {
26
+ margin-right: 0;
27
+ margin-left: 0.5rem;
28
+ cursor: pointer;
29
+ }
30
+ }
31
+ }
32
+
33
+ .toolbar {
34
+ display: flex;
35
+ flex-flow: row;
36
+ justify-content: center;
37
+
38
+ .ui.button.dropdown,
39
+ button {
40
+ border: 1px solid #0000001f;
41
+ margin-bottom: 0;
42
+ background-color: #fff !important;
43
+ color: #000;
44
+ cursor: pointer;
45
+ }
46
+ }
47
+ }
48
+
49
+ .habitats-groups {
17
50
  margin-bottom: 1rem;
51
+ background-color: #00a390;
52
+ text-align: center;
53
+ white-space: nowrap;
54
+
55
+ button.habitats-group {
56
+ padding: 1rem;
57
+ border: none;
58
+ background-color: transparent;
59
+ color: #fff !important;
60
+ cursor: pointer;
61
+ font-size: 16px;
62
+ text-transform: uppercase;
63
+
64
+ &::after {
65
+ display: block;
66
+ width: calc(100% + 8px);
67
+ height: 3px;
68
+ margin-top: 2px;
69
+ background: transparent;
70
+ content: '';
71
+ transform: translateX(-4px);
72
+ }
18
73
 
19
- &.marginless {
20
- margin-bottom: 0;
74
+ &.active,
75
+ &:hover {
76
+ &::after {
77
+ background: #ffffff;
78
+ }
79
+ }
80
+ }
81
+
82
+ .ui.container {
83
+ display: block;
84
+ overflow-x: auto;
85
+ text-align: center;
21
86
  }
22
87
  }
23
88
 
24
- .habitat-name {
25
- display: flex;
26
- align-items: center;
27
-
28
- h3 {
29
- margin-right: 1rem;
30
- margin-bottom: 0;
31
- color: #013c60;
32
- font-weight: 400;
33
- line-height: 25px;
89
+ .ui.sidebar {
90
+ background-color: #fff !important;
91
+
92
+ &.right.visible {
93
+ z-index: 800;
94
+ box-shadow: 0px 0px 13px -5px #000000;
34
95
  }
35
96
 
36
- .count {
37
- width: 24px;
38
- height: 24px;
39
- border-radius: 6px;
40
- margin-bottom: 0;
97
+ .sidebar-header {
98
+ display: flex;
99
+ flex-flow: row;
100
+ align-items: center;
101
+ justify-content: space-between;
102
+ padding: 2rem 1rem;
41
103
  background-color: #00a390;
42
- color: #fff !important;
43
- font-weight: bold;
44
- line-height: 24px;
45
- text-align: center;
104
+
105
+ .title {
106
+ margin-bottom: 0;
107
+ color: #fff !important;
108
+ font-size: 20px;
109
+ font-weight: bold;
110
+ }
111
+
112
+ .clear-button {
113
+ border: none;
114
+ background-color: transparent;
115
+ cursor: pointer;
116
+ }
117
+ }
118
+
119
+ .filters {
120
+ padding: 2rem 0;
121
+
122
+ .filter {
123
+ padding: 0 1rem 1rem 1rem;
124
+ border-bottom: 2px solid #e0e0e0;
125
+ margin-bottom: 2rem;
126
+
127
+ .header {
128
+ padding: 0;
129
+ margin-bottom: 2rem;
130
+ background-color: transparent;
131
+
132
+ .title {
133
+ color: #000;
134
+ font-weight: 600;
135
+
136
+ .reset-button {
137
+ border: none;
138
+ margin-left: 1rem;
139
+ background-color: transparent;
140
+ color: #00a390;
141
+ cursor: pointer;
142
+
143
+ &:hover {
144
+ opacity: 0.8;
145
+ }
146
+ }
147
+ }
148
+ }
149
+
150
+ .checkbox-wrapper {
151
+ display: flex;
152
+ align-items: center;
153
+ justify-content: space-between;
154
+ margin-bottom: 1rem;
155
+
156
+ .count {
157
+ color: #636363;
158
+ }
159
+ }
160
+ }
46
161
  }
47
162
  }
163
+ }
48
164
 
49
- .habitat-item {
50
- .description {
51
- color: #013c60;
52
- font-size: 1.2rem;
53
- font-weight: 400;
165
+ .habitats-list {
166
+ .ui.grid.habitats {
167
+ margin-top: 0;
168
+ margin-right: 0;
169
+ margin-bottom: 0;
54
170
 
55
- &:hover {
56
- opacity: 0.9;
171
+ .row {
172
+ padding: 1rem 0;
173
+ }
174
+
175
+ .habitats-photo {
176
+ overflow: hidden;
177
+ padding-right: 0;
178
+
179
+ img {
180
+ width: 100%;
181
+ height: 100%;
182
+ border-bottom-left-radius: 10px;
183
+ border-top-left-radius: 10px;
184
+ object-fit: cover;
185
+
186
+ @media only screen and (max-width: 767px) {
187
+ border-bottom-left-radius: 0;
188
+ border-top-left-radius: 10px;
189
+ border-top-right-radius: 10px;
190
+ }
57
191
  }
58
192
  }
59
193
 
60
- .coverage {
61
- color: #8c8c8c;
194
+ .habitats-details {
195
+ display: flex;
196
+ flex-flow: column;
197
+ justify-content: space-between;
198
+ padding: 0;
199
+ background-color: #fff !important;
200
+ border-bottom-right-radius: 10px;
201
+ border-top-right-radius: 10px;
202
+
203
+ @media only screen and (max-width: 767px) {
204
+ margin-left: 0.625rem;
205
+ border-bottom-left-radius: 10px;
206
+ border-bottom-right-radius: 10;
207
+ border-top-left-radius: 0;
208
+ border-top-right-radius: 0;
209
+ }
210
+
211
+ .metadata {
212
+ padding: 0 2rem;
213
+ padding-top: 1rem;
214
+ margin-bottom: 1rem;
215
+
216
+ .name {
217
+ margin-bottom: 1rem;
218
+
219
+ a {
220
+ color: #013c60;
221
+ font-size: 25px;
222
+ font-weight: 400;
223
+ }
224
+
225
+ .code-2000 {
226
+ color: #0f8f22;
227
+ }
228
+ }
229
+
230
+ .habitat-data:not(:last-child) {
231
+ margin-bottom: 0.5rem;
232
+ }
233
+ }
234
+
235
+ .footer-metadata {
236
+ display: flex;
237
+ padding: 1rem 2rem;
238
+ border-top: 1px solid #e8e8e8;
239
+
240
+ p:not(.last-child) {
241
+ margin-right: 1rem;
242
+ }
243
+ }
244
+
245
+ .metadata,
246
+ .footer-metadata {
247
+ .blue {
248
+ color: #013c60;
249
+ }
250
+
251
+ .orange {
252
+ color: #ff9300;
253
+ }
254
+
255
+ .green {
256
+ color: #0f8f22;
257
+ }
258
+ }
62
259
  }
260
+ }
261
+
262
+ .ui.pagination.menu {
263
+ width: 100%;
264
+ justify-content: center;
265
+ background-color: transparent;
63
266
 
64
- p {
65
- margin-bottom: 0;
267
+ .item {
268
+ &.active {
269
+ color: #013c60;
270
+ font-weight: bold;
271
+ }
66
272
  }
67
- margin-bottom: 1rem;
273
+ }
274
+
275
+ .empty {
276
+ margin-top: 3rem;
277
+ margin-bottom: 3rem !important;
278
+ text-align: left;
68
279
  }
69
280
  }
70
281
  }
@@ -0,0 +1,33 @@
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',
20
+ },
21
+ };
22
+
23
+ export const getPopulationString = (min, max, prefix = '') => {
24
+ return `${prefix}Population: min: ${min || 'not reported'}, max: ${
25
+ max || 'not reported'
26
+ }`;
27
+ };
28
+
29
+ export const getLabelString = (label, key, prefix = '') => {
30
+ return `${prefix}${filtersLabels[label].getTitle()}: ${
31
+ filtersLabels[label]?.[key]?.toLowerCase() || key || 'not reported'
32
+ }`;
33
+ };
@@ -0,0 +1,106 @@
1
+ import React from 'react';
2
+ import findIndex from 'lodash/findIndex';
3
+ import { Icon } from '@plone/volto/components';
4
+ import { Link } from 'react-router-dom';
5
+ import cx from 'classnames';
6
+ import { getObjectByIndex } from '@eeacms/volto-n2k/helpers';
7
+ import downKeySVG from '@plone/volto/icons/down-key.svg';
8
+ import upKeySVG from '@plone/volto/icons/up-key.svg';
9
+ import './style.less';
10
+
11
+ const View = (props) => {
12
+ const [habitats, setHabitats] = React.useState({});
13
+ const [expandedHabitats, setExpandedHabitats] = React.useState([]);
14
+ const { provider_data = {}, placeholder = 'No results' } = props;
15
+
16
+ React.useEffect(() => {
17
+ const newHabitats = {};
18
+ if (provider_data?.habitat_group?.length) {
19
+ provider_data.habitat_group.forEach((habitat, index) => {
20
+ if (!newHabitats[habitat]) {
21
+ newHabitats[habitat] = [];
22
+ }
23
+ newHabitats[habitat].push(getObjectByIndex(provider_data, index));
24
+ });
25
+ }
26
+ setHabitats(newHabitats);
27
+ /* eslint-disable-next-line */
28
+ }, [JSON.stringify(provider_data)]);
29
+
30
+ return (
31
+ <div className="site-habitats-list">
32
+ {Object.keys(habitats)?.length ? (
33
+ Object.keys(habitats)
34
+ .sort((a, b) => a.localeCompare(b))
35
+ .map((habitat) => {
36
+ const expanded = expandedHabitats.includes(habitat);
37
+ return (
38
+ <div className="habitat" key={habitat}>
39
+ <div
40
+ className={cx({
41
+ 'habitat-toolbar': true,
42
+ marginless: !expanded,
43
+ })}
44
+ >
45
+ <div className="habitat-name">
46
+ <h3>{habitat}</h3>
47
+ <p className="count">{habitats[habitat].length}</p>
48
+ </div>
49
+ <Icon
50
+ name={expanded ? upKeySVG : downKeySVG}
51
+ onClick={(e) => {
52
+ const index = findIndex(
53
+ expandedHabitats,
54
+ (name) => name === habitat,
55
+ );
56
+ if (index === -1) {
57
+ setExpandedHabitats((prevExpandedHabitats) => [
58
+ ...prevExpandedHabitats,
59
+ habitat,
60
+ ]);
61
+ } else {
62
+ setExpandedHabitats((prevExpandedHabitats) => {
63
+ const newExpandedHabitats = [...prevExpandedHabitats];
64
+ newExpandedHabitats.splice(index, 1);
65
+ return newExpandedHabitats;
66
+ });
67
+ }
68
+ e.preventDefault();
69
+ e.stopPropagation();
70
+ }}
71
+ color="#8C8C8C"
72
+ size="32px"
73
+ />
74
+ </div>
75
+
76
+ {expanded
77
+ ? habitats[habitat].map((item, index) => (
78
+ <div
79
+ className="habitat-item"
80
+ key={`${habitat}-${index}-item`}
81
+ >
82
+ <Link
83
+ className="description"
84
+ to={`/habitats/${item.code_2000}`}
85
+ >
86
+ {item.habitat_description} ({item.code_2000})
87
+ </Link>
88
+ <p className="coverage">
89
+ {item.coverage_ha.toFixed(2)} ha (
90
+ {(item.coverage_ha / 100).toFixed(4)} km
91
+ <sup>2</sup>)
92
+ </p>
93
+ </div>
94
+ ))
95
+ : ''}
96
+ </div>
97
+ );
98
+ })
99
+ ) : (
100
+ <p>{placeholder}</p>
101
+ )}
102
+ </div>
103
+ );
104
+ };
105
+
106
+ export default View;
@@ -0,0 +1,17 @@
1
+ // import SiteHabitatsList from './View';
2
+ // import getSchema from './schema';
3
+
4
+ export default function applyConfig(config) {
5
+ // config.blocks.blocksConfig.custom_connected_block = {
6
+ // ...config.blocks.blocksConfig.custom_connected_block,
7
+ // blocks: {
8
+ // ...config.blocks.blocksConfig.custom_connected_block.blocks,
9
+ // site_habitats_list: {
10
+ // view: SiteHabitatsList,
11
+ // getSchema: getSchema,
12
+ // title: 'Site habitats list',
13
+ // },
14
+ // },
15
+ // };
16
+ return config;
17
+ }
@@ -0,0 +1,19 @@
1
+ const getSchema = (props) => {
2
+ return {
3
+ title: 'Site habitats list',
4
+
5
+ fieldsets: [
6
+ {
7
+ id: 'default',
8
+ title: 'Default',
9
+ fields: [],
10
+ },
11
+ ],
12
+
13
+ properties: {},
14
+
15
+ required: [],
16
+ };
17
+ };
18
+
19
+ export default getSchema;
@@ -0,0 +1,70 @@
1
+ .site-habitats-list {
2
+ .icon {
3
+ cursor: pointer;
4
+ }
5
+
6
+ .habitat {
7
+ padding: 1rem 2rem;
8
+ border: 1px solid #e8e8e8;
9
+ border-radius: 10px;
10
+ margin-bottom: 1rem;
11
+ background-color: #fff !important;
12
+
13
+ .habitat-toolbar {
14
+ display: flex;
15
+ align-items: center;
16
+ justify-content: space-between;
17
+ margin-bottom: 1rem;
18
+
19
+ &.marginless {
20
+ margin-bottom: 0;
21
+ }
22
+ }
23
+
24
+ .habitat-name {
25
+ display: flex;
26
+ align-items: center;
27
+
28
+ h3 {
29
+ margin-right: 1rem;
30
+ margin-bottom: 0;
31
+ color: #013c60;
32
+ font-weight: 400;
33
+ line-height: 25px;
34
+ }
35
+
36
+ .count {
37
+ width: 24px;
38
+ height: 24px;
39
+ border-radius: 6px;
40
+ margin-bottom: 0;
41
+ background-color: #00a390;
42
+ color: #fff !important;
43
+ font-weight: bold;
44
+ line-height: 24px;
45
+ text-align: center;
46
+ }
47
+ }
48
+
49
+ .habitat-item {
50
+ .description {
51
+ color: #013c60;
52
+ font-size: 1.2rem;
53
+ font-weight: 400;
54
+
55
+ &:hover {
56
+ opacity: 0.9;
57
+ }
58
+ }
59
+
60
+ .coverage {
61
+ color: #8c8c8c;
62
+ }
63
+
64
+ p {
65
+ margin-bottom: 0;
66
+ }
67
+ margin-bottom: 1rem;
68
+ }
69
+ }
70
+ }
@@ -27,16 +27,18 @@ const View = (props) => {
27
27
  <div className="habitats-container">
28
28
  <Container className="habitats-wrapper">
29
29
  <div className="habitats-wrapper">
30
- {Object.entries(habitats).map(([habitat, items], index) => (
31
- <div key={index} className="habitat-box">
32
- <div className="upper">
33
- <span>{items.length}</span>
30
+ {Object.keys(habitats)
31
+ .sort((a, b) => a.localeCompare(b))
32
+ .map((habitat, index) => (
33
+ <div key={index} className="habitat-box">
34
+ <div className="upper">
35
+ <span>{habitats[habitat].length}</span>
36
+ </div>
37
+ <div className="lower">
38
+ <span>{habitat}</span>
39
+ </div>
34
40
  </div>
35
- <div className="lower">
36
- <span>{habitat}</span>
37
- </div>
38
- </div>
39
- ))}
41
+ ))}
40
42
  </div>
41
43
  </Container>
42
44
  </div>
@@ -35,16 +35,18 @@ const View = (props) => {
35
35
  </Grid.Row>
36
36
  </Grid> */}
37
37
  <div className="species-wrapper">
38
- {Object.entries(data).map(([item, value], index) => (
39
- <div key={index} className="species-box">
40
- <div className="upper">
41
- <span>{value}</span>
42
- </div>
43
- <div className="lower">
44
- <span>{item}</span>
38
+ {Object.keys(data)
39
+ .sort((a, b) => a.localeCompare(b))
40
+ .map((species, index) => (
41
+ <div key={index} className="species-box">
42
+ <div className="upper">
43
+ <span>{data[species]}</span>
44
+ </div>
45
+ <div className="lower">
46
+ <span>{species}</span>
47
+ </div>
45
48
  </div>
46
- </div>
47
- ))}
49
+ ))}
48
50
  </div>
49
51
  </Container>
50
52
  </div>
@@ -13,7 +13,7 @@ const View = (props) => {
13
13
  const { sortBy, setSortBy } = props;
14
14
 
15
15
  const sortByOptions = [
16
- { text: 'Alphabetical', value: 'scientific_name', key: 'scientific_name' },
16
+ { text: 'Name', value: 'scientific_name', key: 'scientific_name' },
17
17
  ];
18
18
 
19
19
  return (
@@ -11,10 +11,16 @@ const SpeciesGroups = (props) => {
11
11
  } = props;
12
12
 
13
13
  React.useEffect(() => {
14
- setSpeciesGroups([
15
- ...(provider_data.species_group_name?.length ? ['All'] : []),
16
- ...new Set(provider_data.species_group_name || []),
17
- ]);
14
+ setSpeciesGroups(
15
+ [
16
+ ...(provider_data.species_group_name?.length ? ['All'] : []),
17
+ ...new Set(provider_data.species_group_name || []),
18
+ ].sort((a, b) => {
19
+ if (a === 'All') return -1;
20
+ if (b === 'All') return 1;
21
+ return a.localeCompare(b);
22
+ }),
23
+ );
18
24
  /* eslint-disable-next-line */
19
25
  }, [JSON.stringify(provider_data)]);
20
26
 
@@ -167,6 +167,7 @@ const View = (props) => {
167
167
  </Container>
168
168
  <Sidebar
169
169
  as="div"
170
+ className="z-full"
170
171
  animation="overlay"
171
172
  direction="right"
172
173
  onHide={() => setVisible(false)}