@eeacms/volto-eea-map 4.1.0 → 5.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/package.json +5 -2
  3. package/src/Arcgis/Editor/Editor.jsx +130 -0
  4. package/src/Arcgis/Editor/EditorContext.jsx +2 -0
  5. package/src/Arcgis/Editor/Fold/Fold.jsx +56 -0
  6. package/src/Arcgis/Editor/Panels/Panel.jsx +8 -0
  7. package/src/Arcgis/Editor/Panels/SettingsGeneralPanel.jsx +217 -0
  8. package/src/Arcgis/Editor/Panels/SettingsLayersPanel.jsx +216 -0
  9. package/src/Arcgis/Editor/Panels/StructureBaseLayerPanel.jsx +60 -0
  10. package/src/Arcgis/Editor/Panels/StructureLayersPanel.jsx +394 -0
  11. package/src/Arcgis/Editor/Panels/StructureWidgetsPanel.jsx +181 -0
  12. package/src/Arcgis/Editor/Panels/index.js +6 -0
  13. package/src/Arcgis/Editor/SidebarGroup.jsx +62 -0
  14. package/src/Arcgis/Layer/Layer.jsx +247 -0
  15. package/src/Arcgis/Map/Map.jsx +287 -0
  16. package/src/Arcgis/Map/MapBuilder.jsx +111 -0
  17. package/src/Arcgis/Map/MapContext.jsx +3 -0
  18. package/src/Arcgis/Widget/Widget.jsx +170 -0
  19. package/src/Arcgis/helpers.js +140 -0
  20. package/src/Blocks/EmbedEEAMap/Edit.jsx +40 -0
  21. package/src/Blocks/EmbedEEAMap/View.jsx +122 -0
  22. package/src/Blocks/EmbedEEAMap/helpers.js +12 -0
  23. package/src/Blocks/EmbedEEAMap/schema.js +126 -0
  24. package/src/{components → Toolbar}/Share.jsx +1 -1
  25. package/src/{components/ExtraViews.jsx → Toolbar/Toolbar.jsx} +14 -16
  26. package/src/{components/visualization → Views}/VisualizationView.jsx +8 -9
  27. package/src/Widgets/ArcgisColorPickerWidget.jsx +95 -0
  28. package/src/Widgets/ArcgisRendererWidget/ArcgisRendererWidget.jsx +106 -0
  29. package/src/Widgets/ArcgisRendererWidget/RendererEditor/ClassBreaks.jsx +8 -0
  30. package/src/Widgets/ArcgisRendererWidget/RendererEditor/Dictionary.jsx +8 -0
  31. package/src/Widgets/ArcgisRendererWidget/RendererEditor/DotDensity.jsx +8 -0
  32. package/src/Widgets/ArcgisRendererWidget/RendererEditor/Heatmap.jsx +8 -0
  33. package/src/Widgets/ArcgisRendererWidget/RendererEditor/PieChart.jsx +8 -0
  34. package/src/Widgets/ArcgisRendererWidget/RendererEditor/Simple.jsx +109 -0
  35. package/src/Widgets/ArcgisRendererWidget/RendererEditor/UniqueValue.jsx +8 -0
  36. package/src/Widgets/ArcgisRendererWidget/RendererEditor/_Editor.jsx +29 -0
  37. package/src/Widgets/ArcgisRendererWidget/RendererEditor/_EditorModal.jsx +88 -0
  38. package/src/Widgets/ArcgisRendererWidget/RendererEditor/_defaults.js +30 -0
  39. package/src/Widgets/ArcgisSliderWidget.jsx +79 -0
  40. package/src/Widgets/ArcgisViewpointWidget.jsx +112 -0
  41. package/src/{components/visualization → Widgets}/VisualizationViewWidget.jsx +9 -10
  42. package/src/Widgets/VisualizationWidget.jsx +200 -0
  43. package/src/arcgis.js +48 -0
  44. package/src/constants.js +225 -7
  45. package/src/hocs/withArcgis.jsx +27 -0
  46. package/src/hooks/useChangedProps.jsx +24 -0
  47. package/src/hooks/useClass.jsx +17 -0
  48. package/src/hooks/useCopyToClipboard.jsx +25 -0
  49. package/src/index.js +16 -16
  50. package/src/jsoneditor.js +72 -0
  51. package/src/styles/editor.less +446 -0
  52. package/src/styles/map.less +3 -0
  53. package/src/components/Blocks/EmbedEEAMap/Edit.jsx +0 -161
  54. package/src/components/Blocks/EmbedEEAMap/Schema.js +0 -161
  55. package/src/components/Blocks/EmbedEEAMap/View.jsx +0 -79
  56. package/src/components/Blocks/EmbedEEAMap/helpers.js +0 -45
  57. package/src/components/LegendView.jsx +0 -150
  58. package/src/components/Webmap.jsx +0 -371
  59. package/src/components/index.js +0 -6
  60. package/src/components/visualization/VisualizationEditorWidget.jsx +0 -122
  61. package/src/components/visualization/panelsSchema.js +0 -229
  62. package/src/components/widgets/DataQueryWidget.jsx +0 -51
  63. package/src/components/widgets/LayerSelectWidget.jsx +0 -463
  64. package/src/components/widgets/LayersPanelWidget.jsx +0 -59
  65. package/src/components/widgets/SimpleColorPickerWidget.jsx +0 -121
  66. package/src/hocs/index.js +0 -3
  67. package/src/hocs/withDeviceSize.jsx +0 -45
  68. package/src/less/global.less +0 -253
  69. package/src/less/variables.less +0 -5
  70. package/src/utils.js +0 -151
  71. /package/src/{components → Toolbar}/FigureNote.jsx +0 -0
  72. /package/src/{components → Toolbar}/MoreInfoLink.jsx +0 -0
  73. /package/src/{components → Toolbar}/Sources.jsx +0 -0
package/CHANGELOG.md CHANGED
@@ -4,6 +4,35 @@ 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
+ ### [5.0.0](https://github.com/eea/volto-eea-map/compare/4.1.0...5.0.0) - 25 July 2024
8
+
9
+ #### :house: Internal changes
10
+
11
+ - style: Automated code fix [eea-jenkins - [`aadf771`](https://github.com/eea/volto-eea-map/commit/aadf771b40e0a190c29de42d99466d2e6ef440e7)]
12
+ - style: Automated code fix [eea-jenkins - [`edfae3b`](https://github.com/eea/volto-eea-map/commit/edfae3b8ab4cdef23ae23ed7ea008043601dd783)]
13
+ - style: Automated code fix [eea-jenkins - [`fd6c49f`](https://github.com/eea/volto-eea-map/commit/fd6c49f6d0d5081a230f9b4427844eace0321361)]
14
+ - style: Automated code fix [eea-jenkins - [`5bcee12`](https://github.com/eea/volto-eea-map/commit/5bcee12ab667ad89096baae214ade24fa1c98fd1)]
15
+ - style: Automated code fix [eea-jenkins - [`9bf0079`](https://github.com/eea/volto-eea-map/commit/9bf0079694c16fa20c857f896e303850cf67da43)]
16
+ - style: Automated code fix [eea-jenkins - [`3d9adb6`](https://github.com/eea/volto-eea-map/commit/3d9adb6cee7ff1c45ae88d816e7f17de4bbaba37)]
17
+ - style: Automated code fix [eea-jenkins - [`f310427`](https://github.com/eea/volto-eea-map/commit/f3104279ad719b16a149a357c0eab2f8b7fd8ef7)]
18
+ - style: Automated code fix [eea-jenkins - [`fcf5adf`](https://github.com/eea/volto-eea-map/commit/fcf5adf32a73d388d97597dd9c88c3da362f90b8)]
19
+
20
+ #### :hammer_and_wrench: Others
21
+
22
+ - remove uneeded logo [Miu Razvan - [`759a07b`](https://github.com/eea/volto-eea-map/commit/759a07b587b8298d88800346a230fd55304aadf9)]
23
+ - fix bugs [Miu Razvan - [`ccccc8a`](https://github.com/eea/volto-eea-map/commit/ccccc8a1fac321d3968ffdc0843ff87138748476)]
24
+ - fix infinite rerenders [Miu Razvan - [`8dbb501`](https://github.com/eea/volto-eea-map/commit/8dbb5016741f2518668cfe1d40abe1484b53bfc3)]
25
+ - lint fix [Miu Razvan - [`56c2138`](https://github.com/eea/volto-eea-map/commit/56c2138099d7425e21a566cb13fee814acdaea68)]
26
+ - merge origin/develop into revamp branch [Miu Razvan - [`01ea06c`](https://github.com/eea/volto-eea-map/commit/01ea06ccad2b337a28f4e5847116a41bdda749e3)]
27
+ - fix zoom to layer extent [Miu Razvan - [`28bc084`](https://github.com/eea/volto-eea-map/commit/28bc08456fbaa66938e8d0bf5f25ceaff753fae3)]
28
+ - finalize eea-map refactoring [Miu Razvan - [`3c6abf9`](https://github.com/eea/volto-eea-map/commit/3c6abf998e3fdca55b1e81a0553749ee90bfbcd6)]
29
+ - update [Miu Razvan - [`65205bc`](https://github.com/eea/volto-eea-map/commit/65205bc494f1d3c1b381ed6f9af01ed022e87c75)]
30
+ - Update [Miu Razvan - [`13468a3`](https://github.com/eea/volto-eea-map/commit/13468a3c6738e612115535813e64b0a6af4c97d7)]
31
+ - wip [Miu Razvan - [`901fcc3`](https://github.com/eea/volto-eea-map/commit/901fcc318c618c0307a64081002ab4a048be70a7)]
32
+ - Update [Miu Razvan - [`d70dcf2`](https://github.com/eea/volto-eea-map/commit/d70dcf293b1395741ccbc524fa19145c829f72a9)]
33
+ - Update [Miu Razvan - [`a35b941`](https://github.com/eea/volto-eea-map/commit/a35b941700d985c6f3b53247cb60ecc103c4f339)]
34
+ - Widget component + other [Miu Razvan - [`291f5ad`](https://github.com/eea/volto-eea-map/commit/291f5ad97945cacb1bc4c6d12d177f232b907184)]
35
+ - update [Miu Razvan - [`b073166`](https://github.com/eea/volto-eea-map/commit/b073166de8be0b709e5b2ec397ba9d768c8c2fc8)]
7
36
  ### [4.1.0](https://github.com/eea/volto-eea-map/compare/4.0.0...4.1.0) - 7 June 2024
8
37
 
9
38
  #### :hammer_and_wrench: Others
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eeacms/volto-eea-map",
3
- "version": "4.1.0",
3
+ "version": "5.0.0",
4
4
  "description": "@eeacms/volto-eea-map: Volto add-on",
5
5
  "main": "src/index.js",
6
6
  "author": "European Environment Agency: IDM2 A-Team",
@@ -21,16 +21,19 @@
21
21
  "@eeacms/volto-object-widget"
22
22
  ],
23
23
  "dependencies": {
24
+ "@arcgis/core": "4.29.10",
24
25
  "@eeacms/volto-embed": "*",
25
26
  "@eeacms/volto-object-widget": "*",
26
27
  "@plone/scripts": "*",
27
28
  "esri-loader": "3.6.0",
29
+ "jsoneditor": "10.1.0",
28
30
  "lodash": "4.17.21",
29
31
  "razzle-plugin-scss": "4.2.18",
30
32
  "react-color": "~2.19.3",
31
- "react-querybuilder": "4.2.3"
33
+ "react-querybuilder": "6.5.5"
32
34
  },
33
35
  "devDependencies": {
36
+ "@babel/preset-env": "7.24.6",
34
37
  "@cypress/code-coverage": "^3.10.0",
35
38
  "@plone/scripts": "*",
36
39
  "babel-plugin-transform-class-properties": "^6.24.1",
@@ -0,0 +1,130 @@
1
+ import { memo, useRef, useState, useMemo } from 'react';
2
+ import { isNil } from 'lodash';
3
+
4
+ import SidebarGroup from './SidebarGroup';
5
+
6
+ import _MapBuilder from '../Map/MapBuilder';
7
+
8
+ import {
9
+ StructureBaseLayerPanel,
10
+ StructureLayersPanel,
11
+ StructureWidgetsPanel,
12
+ SettingsGeneralPanel,
13
+ SettingsLayersPanel,
14
+ } from './Panels';
15
+
16
+ import EditorContext from './EditorContext';
17
+
18
+ import 'react-querybuilder/dist/query-builder.css';
19
+ import 'jsoneditor/dist/jsoneditor.min.css';
20
+
21
+ const MapBuilder = memo(_MapBuilder);
22
+
23
+ const panels = {
24
+ structure: [
25
+ {
26
+ title: 'Base layer',
27
+ Panel: StructureBaseLayerPanel,
28
+ },
29
+ {
30
+ title: 'Layers',
31
+ Panel: StructureLayersPanel,
32
+ },
33
+ {
34
+ title: 'Widgets',
35
+ Panel: StructureWidgetsPanel,
36
+ },
37
+ ],
38
+ settings: [
39
+ { title: 'General', Panel: SettingsGeneralPanel },
40
+ { title: 'Layers', Panel: SettingsLayersPanel },
41
+ ],
42
+ };
43
+
44
+ function useApi() {
45
+ const [data, setData] = useState({});
46
+ const [loading, setLoading] = useState({});
47
+ const [loaded, setLoaded] = useState({});
48
+ const [error, setError] = useState({});
49
+
50
+ const load = async (url, opts) => {
51
+ if (data[url]) return data[url];
52
+ let response, result;
53
+ setLoading((prev) => ({ ...prev, [url]: true }));
54
+ try {
55
+ response = await fetch(`${url}?f=json`, opts);
56
+ } catch {
57
+ response = { ok: false, statusText: 'Unexpected error' };
58
+ }
59
+ try {
60
+ result = await response.json();
61
+ } catch {
62
+ result = response.ok
63
+ ? {
64
+ code: 500,
65
+ message: 'Unexpected error',
66
+ }
67
+ : {
68
+ code: response.status,
69
+ message: response.statusText,
70
+ };
71
+ }
72
+
73
+ if (!response.ok || (!isNil(result.code) && result.code !== 200)) {
74
+ setData((prev) => ({ ...prev, [url]: null }));
75
+ setError((prev) => ({ ...prev, [url]: result }));
76
+ setLoading((prev) => ({ ...prev, [url]: false }));
77
+ setLoaded((prev) => ({ ...prev, [url]: false }));
78
+ return;
79
+ }
80
+ setData((prev) => ({ ...prev, [url]: result }));
81
+ setError((prev) => ({ ...prev, [url]: null }));
82
+ setLoading((prev) => ({ ...prev, [url]: false }));
83
+ setLoaded((prev) => ({ ...prev, [url]: true }));
84
+ };
85
+
86
+ return { data, loading, loaded, error, load };
87
+ }
88
+
89
+ export default function Editor({ value, properties, onChangeValue }) {
90
+ const $map = useRef(null);
91
+ const [active, setActive] = useState({
92
+ sidebar: 'structure',
93
+ panel: panels.structure[0],
94
+ });
95
+ const servicesApi = useApi();
96
+ const layersApi = useApi();
97
+
98
+ const Panel = useMemo(() => active.panel.Panel, [active]);
99
+
100
+ return (
101
+ <EditorContext.Provider value={{ servicesApi, layersApi }}>
102
+ <div className="arcgis-map__editor">
103
+ <div className="arcgis-map__controls">
104
+ <div className="arcgis-map__sidebar">
105
+ {Object.keys(panels).map((panel) => (
106
+ <SidebarGroup
107
+ key={panel}
108
+ title={panel}
109
+ items={panels[panel]}
110
+ active={active}
111
+ setActive={setActive}
112
+ />
113
+ ))}
114
+ </div>
115
+ <div className="arcgis-map__panel">
116
+ <Panel
117
+ $map={$map}
118
+ value={value}
119
+ properties={properties}
120
+ onChangeValue={onChangeValue}
121
+ />
122
+ </div>
123
+ </div>
124
+ <div className="arcgis-map__view">
125
+ <MapBuilder data={value} ref={$map} />
126
+ </div>
127
+ </div>
128
+ </EditorContext.Provider>
129
+ );
130
+ }
@@ -0,0 +1,2 @@
1
+ import { createContext } from 'react';
2
+ export default createContext(null);
@@ -0,0 +1,56 @@
1
+ import { useState } from 'react';
2
+ import cx from 'classnames';
3
+
4
+ import { Icon } from '@plone/volto/components';
5
+
6
+ import clearSVG from '@plone/volto/icons/clear.svg';
7
+ import upKeySVG from '@plone/volto/icons/up-key.svg';
8
+
9
+ export default function Fold({
10
+ children,
11
+ title,
12
+ icon,
13
+ foldable,
14
+ deletable,
15
+ onDelete,
16
+ }) {
17
+ const [fold, setFold] = useState(false);
18
+
19
+ const isfolded = foldable && fold;
20
+
21
+ return (
22
+ <div className={cx('fold', { fold__open: !isfolded, foldable })}>
23
+ <div
24
+ className="fold--top"
25
+ {...(foldable
26
+ ? {
27
+ role: 'button',
28
+ tabIndex: 0,
29
+ onClick: () => setFold(!fold),
30
+ onKeyDown: () => {},
31
+ }
32
+ : {})}
33
+ >
34
+ <div className="fold--top__content">
35
+ {foldable && (
36
+ <Icon name={upKeySVG} className="fold--top__fold" size="16px" />
37
+ )}
38
+ {!!icon && <Icon name={icon} size="16px" />}
39
+ {!!title && <div className="fold--top__title">{title}</div>}
40
+ </div>
41
+ {deletable && (
42
+ <Icon
43
+ name={clearSVG}
44
+ className="fold--top__delete"
45
+ size="16px"
46
+ onClick={(e) => {
47
+ onDelete(e);
48
+ e.stopPropagation();
49
+ }}
50
+ />
51
+ )}
52
+ </div>
53
+ {!isfolded && <div className="fold--content">{children}</div>}
54
+ </div>
55
+ );
56
+ }
@@ -0,0 +1,8 @@
1
+ export default function Panel({ header, content }) {
2
+ return (
3
+ <div className="panel">
4
+ {!!header && <div className="panel--header">{header}</div>}
5
+ {!!content && <div className="panel--content">{content}</div>}
6
+ </div>
7
+ );
8
+ }
@@ -0,0 +1,217 @@
1
+ import { toNumber } from 'lodash';
2
+ import { InlineForm } from '@plone/volto/components';
3
+ import Panel from './Panel';
4
+ import Fold from '../Fold/Fold';
5
+ import { getDefaultWidgets } from '@eeacms/volto-eea-map/constants';
6
+
7
+ const mapSchema = {
8
+ title: '',
9
+ fieldsets: [
10
+ {
11
+ id: 'default',
12
+ title: 'Default',
13
+ fields: ['dimension'],
14
+ },
15
+ ],
16
+ properties: {
17
+ dimension: {
18
+ title: 'Dimension',
19
+ choices: [
20
+ ['2d', '2D'],
21
+ ['3d', '3D'],
22
+ ],
23
+ },
24
+ },
25
+ required: [],
26
+ };
27
+
28
+ const getViewConstraintsSchema = ({ $map }) => {
29
+ return {
30
+ title: 'Map View',
31
+ fieldsets: [
32
+ {
33
+ id: 'default',
34
+ title: 'Default',
35
+ fields: ['initialExtent'],
36
+ },
37
+ {
38
+ id: 'constraints',
39
+ title: 'Constraints',
40
+ fields: [
41
+ 'minScale',
42
+ 'maxScale',
43
+ 'minZoom',
44
+ 'maxZoom',
45
+ 'rotationEnabled',
46
+ ],
47
+ },
48
+ ],
49
+ properties: {
50
+ initialExtent: {
51
+ title: 'Initial viewpoint',
52
+ widget: 'arcgis_viewpoint',
53
+ $map,
54
+ },
55
+ minScale: {
56
+ title: 'Min scale',
57
+ type: 'number',
58
+ minimum: 0,
59
+ },
60
+ maxScale: {
61
+ title: 'Max scale',
62
+ type: 'number',
63
+ minimum: 0,
64
+ },
65
+ minZoom: {
66
+ title: 'Min zoom',
67
+ type: 'number',
68
+ minimum: 0,
69
+ },
70
+ maxZoom: {
71
+ title: 'Max zoom',
72
+ type: 'number',
73
+ minimum: 0,
74
+ },
75
+ rotationEnabled: {
76
+ title: 'Rotation enabled',
77
+ type: 'boolean',
78
+ },
79
+ },
80
+ required: [],
81
+ };
82
+ };
83
+
84
+ export default function SettingsGeneralPanel({ $map, value, onChangeValue }) {
85
+ const viewConstraints = value.settings?.view?.constraints || {};
86
+ const dimension = value.settings?.map?.dimension || '2d';
87
+
88
+ return (
89
+ <Panel
90
+ content={
91
+ <>
92
+ <Fold
93
+ title={
94
+ <>
95
+ <a
96
+ href="https://developers.arcgis.com/javascript/latest/api-reference/esri-Map.html"
97
+ onClick={(e) => {
98
+ e.stopPropagation();
99
+ }}
100
+ style={{ color: '#fff' }}
101
+ target="_blank"
102
+ rel="noopener noreferrer"
103
+ >
104
+ Map
105
+ </a>
106
+ </>
107
+ }
108
+ foldable
109
+ >
110
+ <InlineForm
111
+ schema={mapSchema}
112
+ formData={{
113
+ ...(value.settings?.map || {}),
114
+ dimension: value.settings?.map?.dimension || '2d',
115
+ }}
116
+ onChangeField={(id, fieldValue) => {
117
+ let $fieldValue = fieldValue;
118
+
119
+ onChangeValue({
120
+ ...value,
121
+ ...(id === 'dimension'
122
+ ? {
123
+ widgets: getDefaultWidgets($fieldValue),
124
+ }
125
+ : {}),
126
+ settings: {
127
+ ...(value.settings || {}),
128
+ map: {
129
+ ...(value.settings?.map || {}),
130
+ [id]: $fieldValue,
131
+ },
132
+ },
133
+ });
134
+ }}
135
+ />
136
+ </Fold>
137
+ {dimension === '2d' && (
138
+ <Fold
139
+ title={
140
+ <>
141
+ <a
142
+ href="https://developers.arcgis.com/javascript/latest/api-reference/esri-views-MapView.html"
143
+ onClick={(e) => {
144
+ e.stopPropagation();
145
+ }}
146
+ style={{ color: '#fff' }}
147
+ target="_blank"
148
+ rel="noopener noreferrer"
149
+ >
150
+ View
151
+ </a>
152
+ </>
153
+ }
154
+ foldable
155
+ >
156
+ <InlineForm
157
+ schema={getViewConstraintsSchema({ $map })}
158
+ formData={{
159
+ initialExtent: {
160
+ longitude: value.settings?.view?.center?.[0],
161
+ latitude: value.settings?.view?.center?.[1],
162
+ zoom: value.settings?.view?.zoom,
163
+ },
164
+ ...viewConstraints,
165
+ }}
166
+ onChangeField={(id, fieldValue) => {
167
+ let $fieldValue = fieldValue;
168
+
169
+ if (
170
+ ['minScale', 'maxScale', 'minZoom', 'maxZoom'].includes(id)
171
+ ) {
172
+ $fieldValue = Math.max(toNumber(fieldValue) || 0, 0);
173
+ }
174
+
175
+ if (id === 'initialExtent') {
176
+ const center = [
177
+ $fieldValue.longitude || 0,
178
+ $fieldValue.latitude || 0,
179
+ ];
180
+ const zoom = $fieldValue.zoom;
181
+
182
+ onChangeValue({
183
+ ...value,
184
+ settings: {
185
+ ...(value.settings || {}),
186
+ view: {
187
+ ...(value.settings?.view || {}),
188
+ center,
189
+ zoom,
190
+ },
191
+ },
192
+ });
193
+ return;
194
+ }
195
+
196
+ onChangeValue({
197
+ ...value,
198
+ settings: {
199
+ ...(value.settings || {}),
200
+ view: {
201
+ ...(value.settings?.view || {}),
202
+ constraints: {
203
+ ...(value.settings?.view?.constraints || {}),
204
+ [id]: $fieldValue,
205
+ },
206
+ },
207
+ },
208
+ });
209
+ }}
210
+ />
211
+ </Fold>
212
+ )}
213
+ </>
214
+ }
215
+ />
216
+ );
217
+ }
@@ -0,0 +1,216 @@
1
+ import { useState, useEffect, useContext, useMemo } from 'react';
2
+ import { Segment, Dimmer, Loader } from 'semantic-ui-react';
3
+ import { isNil, toNumber } from 'lodash';
4
+ import { v4 as uuid } from 'uuid';
5
+ import { InlineForm } from '@plone/volto/components';
6
+ import {
7
+ debounce,
8
+ getLayers,
9
+ getLayerDefaults,
10
+ } from '@eeacms/volto-eea-map/Arcgis/helpers';
11
+ import { blendModes } from '@eeacms/volto-eea-map/constants';
12
+ import EditorContext from '@eeacms/volto-eea-map/Arcgis/Editor/EditorContext';
13
+ import Panel from './Panel';
14
+ import Fold from '../Fold/Fold';
15
+
16
+ function Layer({ $map, layer, layers, index, value, onChangeValue }) {
17
+ const uid = useState(uuid());
18
+ const [isReady, setIsReady] = useState(false);
19
+ const { layersApi } = useContext(EditorContext);
20
+
21
+ const layerPath = useMemo(
22
+ () =>
23
+ !isNil(layer.url) && !isNil(layer.id) ? `${layer.url}/${layer.id}` : null,
24
+ [layer.url, layer.id],
25
+ );
26
+
27
+ const $layer = useMemo(
28
+ () => ({
29
+ data: layersApi.data[layerPath],
30
+ error: layersApi.error[layerPath],
31
+ loading: layersApi.loading[layerPath],
32
+ loaded: layersApi.loaded[layerPath],
33
+ load: layersApi.load,
34
+ }),
35
+ [layersApi, layerPath],
36
+ );
37
+
38
+ const schema = useMemo(
39
+ () => ({
40
+ title: 'General',
41
+ fieldsets: [
42
+ {
43
+ id: 'default',
44
+ title: 'Default',
45
+ fields: ['blendMode', 'minScale', 'maxScale', 'opacity', 'renderer'],
46
+ },
47
+ ],
48
+ properties: {
49
+ blendMode: {
50
+ title: 'Blend mode',
51
+ choices: blendModes,
52
+ },
53
+ minScale: {
54
+ title: 'Min scale',
55
+ type: 'number',
56
+ minimum: 0,
57
+ },
58
+ maxScale: {
59
+ title: 'Max scale',
60
+ type: 'number',
61
+ minimum: 0,
62
+ },
63
+ opacity: {
64
+ title: 'Opacity',
65
+ widget: 'arcgis_slider',
66
+ },
67
+ renderer: {
68
+ title: 'Renderer',
69
+ widget: 'arcgis_renderer',
70
+ $map,
71
+ },
72
+ },
73
+ required: [],
74
+ }),
75
+ [$map],
76
+ );
77
+
78
+ useEffect(() => {
79
+ if (!$layer.loaded && !$layer.loading && !$layer.error && layerPath) {
80
+ debounce(
81
+ () => {
82
+ $layer.load(layerPath);
83
+ },
84
+ 300,
85
+ `fetch:${uid}:${layerPath}`,
86
+ );
87
+ }
88
+ }, [uid, $layer, layerPath]);
89
+
90
+ useEffect(() => {
91
+ if (!$layer.loaded || $layer.data.id !== layer.id) return;
92
+ const defaults = getLayerDefaults($layer.data);
93
+ if (JSON.stringify(defaults) !== JSON.stringify(layer.defaults)) {
94
+ onChangeValue({
95
+ ...value,
96
+ layers: layers.map((layer, i) => {
97
+ if (i !== index) return layer;
98
+ return {
99
+ ...layer,
100
+ defaults,
101
+ };
102
+ }),
103
+ });
104
+ }
105
+ setIsReady(true);
106
+ }, [index, layer, $layer, layers, value, onChangeValue]);
107
+
108
+ if (!isReady) return null;
109
+
110
+ return (
111
+ <>
112
+ <Dimmer active={$layer.loading}>
113
+ <Loader />
114
+ </Dimmer>
115
+
116
+ <InlineForm
117
+ schema={schema}
118
+ formData={{
119
+ ...(layer.defaults || {}),
120
+ ...layer,
121
+ }}
122
+ onChangeField={(id, fieldValue) => {
123
+ let $fieldValue = fieldValue;
124
+
125
+ if (
126
+ ['minScale', 'maxScale', 'minZoom', 'maxZoom', 'opacity'].includes(
127
+ id,
128
+ )
129
+ ) {
130
+ $fieldValue = Math.max(toNumber(fieldValue) || 0, 0);
131
+ }
132
+
133
+ onChangeValue({
134
+ ...value,
135
+ layers: layers.map((layer, i) => {
136
+ if (i !== index) return layer;
137
+ return {
138
+ ...layer,
139
+ [id]: $fieldValue,
140
+ };
141
+ }),
142
+ });
143
+ }}
144
+ />
145
+ {layer.defaults && (
146
+ <Segment attached style={{ textAlign: 'right' }}>
147
+ <button
148
+ className="btn-primary"
149
+ onClick={() => {
150
+ const defaults = { ...layer };
151
+ Object.keys(schema.properties).forEach((key) => {
152
+ if (key in layer.defaults) {
153
+ defaults[key] = layer.defaults[key];
154
+ }
155
+ });
156
+ onChangeValue({
157
+ ...value,
158
+ layers: layers.map((layer, i) => {
159
+ if (i !== index) return layer;
160
+ return defaults;
161
+ }),
162
+ });
163
+ }}
164
+ >
165
+ Defaults
166
+ </button>
167
+ </Segment>
168
+ )}
169
+ </>
170
+ );
171
+ }
172
+
173
+ export default function SettingsLayersPanel({
174
+ $map,
175
+ value,
176
+ properties,
177
+ onChangeValue,
178
+ }) {
179
+ const data_query = properties?.data_query;
180
+
181
+ const layers = useMemo(
182
+ () =>
183
+ getLayers(
184
+ { layers: value.layers, styles: value.styles, data_query },
185
+ false,
186
+ ),
187
+ [value.layers, value.styles, data_query],
188
+ );
189
+
190
+ return (
191
+ <Panel
192
+ content={
193
+ <>
194
+ {layers.map((layer, index) => (
195
+ <Fold
196
+ key={index}
197
+ title={`Layer ${index + 1}${
198
+ layer.name ? ` - ${layer.name}` : ''
199
+ }`}
200
+ foldable
201
+ >
202
+ <Layer
203
+ $map={$map}
204
+ layer={layer}
205
+ layers={layers}
206
+ index={index}
207
+ value={value}
208
+ onChangeValue={onChangeValue}
209
+ />
210
+ </Fold>
211
+ ))}
212
+ </>
213
+ }
214
+ />
215
+ );
216
+ }