@eeacms/volto-eea-map 0.1.13 → 0.1.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +38 -0
- package/package.json +3 -2
- package/src/actionTypes.js +1 -0
- package/src/actions.js +1 -1
- package/src/components/Blocks/EEAMap/Edit.jsx +1 -1
- package/src/components/Blocks/EEAMap/Schema.js +3 -5
- package/src/components/Blocks/EEAMap/View.jsx +3 -2
- package/src/components/Blocks/EmbedEEAMap/Edit.jsx +7 -6
- package/src/components/Blocks/EmbedEEAMap/Schema.js +13 -7
- package/src/components/Blocks/EmbedEEAMap/View.jsx +54 -46
- package/src/components/ExtraViews.jsx +85 -0
- package/src/components/{Blocks/EEAMap/components/Webmap.jsx → Webmap.jsx} +33 -31
- package/src/components/index.js +6 -6
- package/src/components/visualization/VisualizationEditorWidget.jsx +121 -0
- package/src/components/{Blocks/EEAMap/components/widgets → visualization}/VisualizationView.jsx +0 -0
- package/src/components/{Blocks/EEAMap/components/widgets → visualization}/panelsSchema.js +0 -1
- package/src/components/widgets/DataQueryWidget.jsx +50 -0
- package/src/components/{Blocks/EEAMap/components/widgets → widgets}/LayerSelectWidget.jsx +102 -46
- package/src/components/{Blocks/EEAMap/components/widgets/LayersPanel.jsx → widgets/LayersPanelWidget.jsx} +2 -2
- package/src/components/{Blocks/EEAMap/components/widgets → widgets}/LegendWidget.jsx +43 -31
- package/src/components/{Blocks/EEAMap/components/widgets → widgets}/MapEditorWidget.jsx +1 -0
- package/src/components/{Blocks/EEAMap/components/widgets → widgets}/ObjectTypesWidget.jsx +1 -2
- package/src/components/widgets/panelsSchema.js +151 -0
- package/src/constants.js +29 -1
- package/src/index.js +41 -41
- package/src/middlewares/index.js +1 -1
- package/src/reducers/map_visualizations.js +1 -1
- package/src/static/code-line.svg +1 -0
- package/src/{components/Blocks/EEAMap/styles → styles}/map.css +66 -5
- package/src/{components/Blocks/EEAMap/utils.js → utils.js} +18 -2
- package/src/components/Blocks/EEAMap/components/widgets/DataQueryWidget.jsx +0 -46
- package/src/components/Blocks/EEAMap/components/widgets/ExtraViews.jsx +0 -86
- package/src/components/Blocks/EEAMap/components/widgets/VisualizationEditorWidget.jsx +0 -94
- package/src/components/Blocks/EEAMap/constants.js +0 -29
- package/src/components/Blocks/EmbedEEAMap/styles/map.css +0 -22
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Modal, Button, Grid } from 'semantic-ui-react';
|
|
3
|
+
|
|
4
|
+
import { FormFieldWrapper, InlineForm } from '@plone/volto/components';
|
|
5
|
+
|
|
6
|
+
import PanelsSchema from './panelsSchema';
|
|
7
|
+
import Webmap from '../Webmap';
|
|
8
|
+
|
|
9
|
+
const VisualizationEditorWidget = (props) => {
|
|
10
|
+
const [open, setOpen] = React.useState(false);
|
|
11
|
+
const { onChange = {}, id } = props;
|
|
12
|
+
const block = React.useMemo(() => props.block, [props.block]);
|
|
13
|
+
const value = React.useMemo(() => props.value, [props.value]);
|
|
14
|
+
|
|
15
|
+
const [intValue, setIntValue] = React.useState(value);
|
|
16
|
+
|
|
17
|
+
const dataForm = { map_data: intValue };
|
|
18
|
+
const handleApplyChanges = () => {
|
|
19
|
+
onChange(id, intValue);
|
|
20
|
+
setOpen(false);
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
const handleClose = () => {
|
|
24
|
+
setIntValue(value);
|
|
25
|
+
setOpen(false);
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
const handleChangeField = (val) => {
|
|
29
|
+
setIntValue(val);
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
let schema = PanelsSchema({ data: dataForm });
|
|
33
|
+
|
|
34
|
+
React.useEffect(() => {
|
|
35
|
+
if (!intValue?.general) {
|
|
36
|
+
setIntValue({
|
|
37
|
+
...intValue,
|
|
38
|
+
general: {
|
|
39
|
+
print_position: 'top-right',
|
|
40
|
+
zoom_position: 'top-right',
|
|
41
|
+
centerOnExtent: true,
|
|
42
|
+
},
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
if (!intValue?.base) {
|
|
46
|
+
setIntValue({
|
|
47
|
+
...intValue,
|
|
48
|
+
base: {
|
|
49
|
+
base_layer: 'gray-vector',
|
|
50
|
+
},
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
54
|
+
}, [intValue]);
|
|
55
|
+
|
|
56
|
+
return (
|
|
57
|
+
<FormFieldWrapper {...props}>
|
|
58
|
+
<div className="wrapper">
|
|
59
|
+
<Button
|
|
60
|
+
floated="right"
|
|
61
|
+
size="tiny"
|
|
62
|
+
onClick={(e) => {
|
|
63
|
+
e.preventDefault();
|
|
64
|
+
e.stopPropagation();
|
|
65
|
+
setOpen(true);
|
|
66
|
+
}}
|
|
67
|
+
>
|
|
68
|
+
Open Map Editor
|
|
69
|
+
</Button>
|
|
70
|
+
</div>
|
|
71
|
+
|
|
72
|
+
{open && (
|
|
73
|
+
<Modal
|
|
74
|
+
id="map-editor-modal"
|
|
75
|
+
style={{ width: '95% !important' }}
|
|
76
|
+
open={true}
|
|
77
|
+
>
|
|
78
|
+
<Modal.Content scrolling>
|
|
79
|
+
<Grid stackable reversed="mobile vertically tablet vertically">
|
|
80
|
+
<Grid.Column
|
|
81
|
+
mobile={12}
|
|
82
|
+
tablet={12}
|
|
83
|
+
computer={5}
|
|
84
|
+
className="map-editor-column"
|
|
85
|
+
>
|
|
86
|
+
<InlineForm
|
|
87
|
+
block={block}
|
|
88
|
+
schema={schema}
|
|
89
|
+
onChangeField={(id, value) => {
|
|
90
|
+
handleChangeField(value);
|
|
91
|
+
}}
|
|
92
|
+
formData={dataForm}
|
|
93
|
+
/>
|
|
94
|
+
</Grid.Column>
|
|
95
|
+
<Grid.Column mobile={12} tablet={12} computer={7}>
|
|
96
|
+
<div className="webmap-container">
|
|
97
|
+
<Webmap data={intValue} editMode={true} />
|
|
98
|
+
</div>
|
|
99
|
+
</Grid.Column>
|
|
100
|
+
</Grid>
|
|
101
|
+
</Modal.Content>
|
|
102
|
+
<Modal.Actions>
|
|
103
|
+
<Grid>
|
|
104
|
+
<Grid.Row>
|
|
105
|
+
<div className="map-edit-actions-container">
|
|
106
|
+
<Button onClick={handleClose}>Close</Button>
|
|
107
|
+
<Button color="green" onClick={handleApplyChanges}>
|
|
108
|
+
Apply changes
|
|
109
|
+
</Button>
|
|
110
|
+
</div>
|
|
111
|
+
</Grid.Row>
|
|
112
|
+
</Grid>
|
|
113
|
+
</Modal.Actions>
|
|
114
|
+
</Modal>
|
|
115
|
+
)}
|
|
116
|
+
<Webmap data={value} editMode={true} />
|
|
117
|
+
</FormFieldWrapper>
|
|
118
|
+
);
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
export default VisualizationEditorWidget;
|
package/src/components/{Blocks/EEAMap/components/widgets → visualization}/VisualizationView.jsx
RENAMED
|
File without changes
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { FormFieldWrapper, Field } from '@plone/volto/components';
|
|
3
|
+
import { Accordion, Segment } from 'semantic-ui-react';
|
|
4
|
+
|
|
5
|
+
const DataQueryWidget = (props) => {
|
|
6
|
+
const { value, onChange, id } = props;
|
|
7
|
+
|
|
8
|
+
const onChangeAlias = (fieldId, fieldValue) => {
|
|
9
|
+
let altValue = value;
|
|
10
|
+
value[fieldId] = { ...value[fieldId], alias: fieldValue };
|
|
11
|
+
onChange(id, altValue);
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
return (
|
|
15
|
+
<div>
|
|
16
|
+
<FormFieldWrapper {...props} noForInFieldLabel></FormFieldWrapper>
|
|
17
|
+
<div className="data-query-widget-field">
|
|
18
|
+
{value && value.length > 0 ? (
|
|
19
|
+
value.map((param, i) => (
|
|
20
|
+
<Accordion
|
|
21
|
+
key={i}
|
|
22
|
+
fluid
|
|
23
|
+
styled
|
|
24
|
+
style={{ border: '1px solid lightgray', marginBottom: '15px' }}
|
|
25
|
+
>
|
|
26
|
+
<Accordion.Content active={true}>
|
|
27
|
+
<Segment>
|
|
28
|
+
<p className="data-param-title">
|
|
29
|
+
<strong>{param.i}:</strong> {param.v.join(', ')}
|
|
30
|
+
</p>
|
|
31
|
+
<Field
|
|
32
|
+
id={i}
|
|
33
|
+
title="Map to"
|
|
34
|
+
type="string"
|
|
35
|
+
onChange={onChangeAlias}
|
|
36
|
+
value={param?.alias}
|
|
37
|
+
/>
|
|
38
|
+
</Segment>
|
|
39
|
+
</Accordion.Content>
|
|
40
|
+
</Accordion>
|
|
41
|
+
))
|
|
42
|
+
) : (
|
|
43
|
+
<p style={{ textAlign: 'center' }}>No parameters set</p>
|
|
44
|
+
)}
|
|
45
|
+
</div>
|
|
46
|
+
</div>
|
|
47
|
+
);
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
export default DataQueryWidget;
|
|
@@ -4,6 +4,8 @@ import { Input, Select, Button, Grid } from 'semantic-ui-react';
|
|
|
4
4
|
import { QueryBuilder } from 'react-querybuilder';
|
|
5
5
|
import 'react-querybuilder/dist/query-builder.css';
|
|
6
6
|
|
|
7
|
+
import RichTextWidget from 'volto-slate/widgets/RichTextWidget';
|
|
8
|
+
|
|
7
9
|
import { connect } from 'react-redux';
|
|
8
10
|
import { compose } from 'redux';
|
|
9
11
|
|
|
@@ -14,7 +16,7 @@ import closeSVG from '@plone/volto/icons/clear.svg';
|
|
|
14
16
|
import aheadSVG from '@plone/volto/icons/ahead.svg';
|
|
15
17
|
import resetSVG from '@plone/volto/icons/reset.svg';
|
|
16
18
|
|
|
17
|
-
import {
|
|
19
|
+
import { fetchArcGISData } from '../../utils';
|
|
18
20
|
|
|
19
21
|
const LayerSelectWidget = (props) => {
|
|
20
22
|
const { onChange, id, data_query } = props;
|
|
@@ -28,6 +30,7 @@ const LayerSelectWidget = (props) => {
|
|
|
28
30
|
layer,
|
|
29
31
|
fields = [],
|
|
30
32
|
query = '',
|
|
33
|
+
description = '',
|
|
31
34
|
} = value;
|
|
32
35
|
|
|
33
36
|
const [mapData, setMapData] = React.useState(map_data);
|
|
@@ -35,6 +38,7 @@ const LayerSelectWidget = (props) => {
|
|
|
35
38
|
const [serviceUrlError, setServiceUrlError] = React.useState('');
|
|
36
39
|
const [serviceUrl, setServiceUrl] = React.useState(map_service_url);
|
|
37
40
|
const [selectedLayer, setSelectedLayer] = React.useState(layer);
|
|
41
|
+
|
|
38
42
|
const [availableLayers, setAvailableLayers] = React.useState(
|
|
39
43
|
available_layers,
|
|
40
44
|
);
|
|
@@ -44,7 +48,7 @@ const LayerSelectWidget = (props) => {
|
|
|
44
48
|
const handleServiceUrlCheck = async () => {
|
|
45
49
|
// fetch url, save it, populate layers options
|
|
46
50
|
try {
|
|
47
|
-
let mapData = await
|
|
51
|
+
let mapData = await fetchArcGISData(serviceUrl);
|
|
48
52
|
setCheckColor('green');
|
|
49
53
|
setMapData(mapData);
|
|
50
54
|
setServiceUrlError('');
|
|
@@ -61,6 +65,7 @@ const LayerSelectWidget = (props) => {
|
|
|
61
65
|
map_service_url: serviceUrl,
|
|
62
66
|
available_layers: availableLayers,
|
|
63
67
|
map_data: mapData,
|
|
68
|
+
description,
|
|
64
69
|
});
|
|
65
70
|
} catch (e) {
|
|
66
71
|
setCheckColor('youtube');
|
|
@@ -119,7 +124,7 @@ const LayerSelectWidget = (props) => {
|
|
|
119
124
|
|
|
120
125
|
const handleLayerFetch = async (service_url, id) => {
|
|
121
126
|
try {
|
|
122
|
-
let fullLayer = await
|
|
127
|
+
let fullLayer = await fetchArcGISData(`${service_url}/${id}`);
|
|
123
128
|
return fullLayer;
|
|
124
129
|
} catch (e) {}
|
|
125
130
|
};
|
|
@@ -148,13 +153,24 @@ const LayerSelectWidget = (props) => {
|
|
|
148
153
|
}
|
|
149
154
|
};
|
|
150
155
|
|
|
156
|
+
const handleChangeDescription = (val) => {
|
|
157
|
+
if (val) {
|
|
158
|
+
onChange(id, {
|
|
159
|
+
...value,
|
|
160
|
+
description: val,
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
};
|
|
164
|
+
|
|
151
165
|
const handleChangeServiceUrl = (value) => {
|
|
152
166
|
setServiceUrlError('');
|
|
153
167
|
setCheckColor('');
|
|
154
|
-
setServiceUrl(value);
|
|
155
168
|
setAvailableLayers('');
|
|
156
169
|
setBuiltQuery('');
|
|
157
170
|
setSelectedLayer('');
|
|
171
|
+
setMapData('');
|
|
172
|
+
|
|
173
|
+
setServiceUrl(value);
|
|
158
174
|
};
|
|
159
175
|
|
|
160
176
|
const handleReset = () => {
|
|
@@ -164,8 +180,8 @@ const LayerSelectWidget = (props) => {
|
|
|
164
180
|
setAvailableLayers(available_layers);
|
|
165
181
|
setBuiltQuery('');
|
|
166
182
|
setSelectedLayer(layer);
|
|
183
|
+
setMapData(map_data);
|
|
167
184
|
};
|
|
168
|
-
|
|
169
185
|
return (
|
|
170
186
|
<div
|
|
171
187
|
style={{
|
|
@@ -173,52 +189,71 @@ const LayerSelectWidget = (props) => {
|
|
|
173
189
|
}}
|
|
174
190
|
>
|
|
175
191
|
<Grid>
|
|
176
|
-
<
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
onChange={(e, { value }) => handleChangeServiceUrl(value)}
|
|
183
|
-
style={{ width: '100%' }}
|
|
184
|
-
error={serviceUrlError}
|
|
185
|
-
value={serviceUrl}
|
|
186
|
-
></Input>
|
|
192
|
+
<div className="spaced-row">
|
|
193
|
+
<Grid.Row stretched>
|
|
194
|
+
<h5 style={{ padding: '0', margin: '15px 0px 5px 0px' }}>
|
|
195
|
+
Service URL
|
|
196
|
+
</h5>
|
|
197
|
+
</Grid.Row>
|
|
187
198
|
|
|
188
|
-
<span style={{ fontSize: '12px', color: 'darkred' }}>
|
|
189
|
-
{serviceUrlError.error}
|
|
190
|
-
</span>
|
|
191
|
-
</Grid.Row>
|
|
192
|
-
{serviceUrl && (
|
|
193
199
|
<Grid.Row>
|
|
194
|
-
|
|
200
|
+
<Input
|
|
201
|
+
type="text"
|
|
202
|
+
onChange={(e, { value }) => handleChangeServiceUrl(value)}
|
|
203
|
+
style={{ width: '100%' }}
|
|
204
|
+
error={serviceUrlError}
|
|
205
|
+
value={serviceUrl}
|
|
206
|
+
></Input>
|
|
207
|
+
|
|
208
|
+
<span style={{ fontSize: '12px', color: 'darkred' }}>
|
|
209
|
+
{serviceUrlError.error}
|
|
210
|
+
</span>
|
|
211
|
+
</Grid.Row>
|
|
212
|
+
{serviceUrl && (
|
|
213
|
+
<Grid.Row style={{ display: 'flex' }}>
|
|
214
|
+
{serviceUrl !== map_service_url && (
|
|
215
|
+
<Button
|
|
216
|
+
size="small"
|
|
217
|
+
compact
|
|
218
|
+
className="layer-reset-button"
|
|
219
|
+
onClick={handleReset}
|
|
220
|
+
>
|
|
221
|
+
<Icon name={resetSVG} title="Reset" size="20px" />
|
|
222
|
+
</Button>
|
|
223
|
+
)}
|
|
195
224
|
<Button
|
|
196
225
|
size="small"
|
|
226
|
+
color={checkColor}
|
|
197
227
|
compact
|
|
198
|
-
className="layer-
|
|
199
|
-
onClick={
|
|
228
|
+
className="layer-check-button"
|
|
229
|
+
onClick={handleServiceUrlCheck}
|
|
200
230
|
>
|
|
201
|
-
<Icon
|
|
231
|
+
<Icon
|
|
232
|
+
name={serviceUrlError ? closeSVG : checkSVG}
|
|
233
|
+
title="Submit"
|
|
234
|
+
size="20px"
|
|
235
|
+
/>
|
|
202
236
|
</Button>
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
/>
|
|
216
|
-
</Button>
|
|
217
|
-
</Grid.Row>
|
|
237
|
+
</Grid.Row>
|
|
238
|
+
)}
|
|
239
|
+
</div>
|
|
240
|
+
{mapData && mapData.mapName && (
|
|
241
|
+
<div className="spaced-row">
|
|
242
|
+
<Grid.Row>
|
|
243
|
+
<h5 style={{ padding: '0', margin: '15px 0px 5px 0px' }}>
|
|
244
|
+
Map name:
|
|
245
|
+
</h5>
|
|
246
|
+
<p>{mapData.mapName}</p>
|
|
247
|
+
</Grid.Row>
|
|
248
|
+
</div>
|
|
218
249
|
)}
|
|
219
250
|
{availableLayers && availableLayers.length > 0 && (
|
|
220
|
-
|
|
221
|
-
<
|
|
251
|
+
<div className="spaced-row">
|
|
252
|
+
<Grid.Row>
|
|
253
|
+
<h5 style={{ padding: '0', margin: '15px 0px 5px 0px' }}>
|
|
254
|
+
Layer
|
|
255
|
+
</h5>
|
|
256
|
+
</Grid.Row>
|
|
222
257
|
<Grid.Row>
|
|
223
258
|
<Select
|
|
224
259
|
onChange={(e, { value }) => handleSelectLayer(value)}
|
|
@@ -228,10 +263,31 @@ const LayerSelectWidget = (props) => {
|
|
|
228
263
|
value={selectedLayer}
|
|
229
264
|
/>
|
|
230
265
|
</Grid.Row>
|
|
231
|
-
|
|
266
|
+
</div>
|
|
267
|
+
)}
|
|
268
|
+
{availableLayers && availableLayers.length > 0 && (
|
|
269
|
+
<div className="spaced-row">
|
|
270
|
+
<Grid.Row stretched>
|
|
271
|
+
<h5 style={{ padding: '0', margin: '15px 0px 5px 0px' }}>
|
|
272
|
+
Description
|
|
273
|
+
</h5>
|
|
274
|
+
</Grid.Row>
|
|
275
|
+
<Grid.Row stretched>
|
|
276
|
+
<div className="map-layer-description-field">
|
|
277
|
+
<RichTextWidget
|
|
278
|
+
title="description"
|
|
279
|
+
onChange={(name, value) => {
|
|
280
|
+
handleChangeDescription(value);
|
|
281
|
+
}}
|
|
282
|
+
value={value.description}
|
|
283
|
+
placeholder="Set Description"
|
|
284
|
+
/>
|
|
285
|
+
</div>
|
|
286
|
+
</Grid.Row>
|
|
287
|
+
</div>
|
|
232
288
|
)}
|
|
233
289
|
{availableLayers && fields && fields.length > 0 && (
|
|
234
|
-
|
|
290
|
+
<div className="spaced-row">
|
|
235
291
|
<h5 style={{ padding: '0', margin: '15px 0px 5px 0px' }}>
|
|
236
292
|
Query Layer
|
|
237
293
|
</h5>
|
|
@@ -246,7 +302,7 @@ const LayerSelectWidget = (props) => {
|
|
|
246
302
|
/>
|
|
247
303
|
</Grid.Row>
|
|
248
304
|
{builtQuery && (
|
|
249
|
-
<Grid.Row>
|
|
305
|
+
<Grid.Row style={{ display: 'flex' }}>
|
|
250
306
|
<Button
|
|
251
307
|
type="submit"
|
|
252
308
|
size="tiny"
|
|
@@ -275,7 +331,7 @@ const LayerSelectWidget = (props) => {
|
|
|
275
331
|
<strong>{field.alias}</strong> ({field.type})
|
|
276
332
|
</p>
|
|
277
333
|
))}
|
|
278
|
-
|
|
334
|
+
</div>
|
|
279
335
|
)}
|
|
280
336
|
</Grid>
|
|
281
337
|
</div>
|
|
@@ -2,7 +2,7 @@ import React from 'react';
|
|
|
2
2
|
import { Button } from 'semantic-ui-react';
|
|
3
3
|
import LayerSelectWidget from './LayerSelectWidget';
|
|
4
4
|
|
|
5
|
-
const
|
|
5
|
+
const LayersPanelWidget = ({ data, onChange, block }) => {
|
|
6
6
|
const map_layers = React.useMemo(() => data.map_layers || [], [
|
|
7
7
|
data.map_layers,
|
|
8
8
|
]);
|
|
@@ -55,4 +55,4 @@ const LayersPanel = ({ data, onChange, block }) => {
|
|
|
55
55
|
);
|
|
56
56
|
};
|
|
57
57
|
|
|
58
|
-
export default
|
|
58
|
+
export default LayersPanelWidget;
|
|
@@ -1,19 +1,20 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { Grid } from 'semantic-ui-react';
|
|
3
|
-
import {
|
|
3
|
+
import { fetchArcGISData, setLegendColumns } from '../../utils';
|
|
4
4
|
import { Icon } from '@plone/volto/components';
|
|
5
|
+
import { serializeNodes } from 'volto-slate/editor/render';
|
|
5
6
|
|
|
6
7
|
import rightKeySVG from '@plone/volto/icons/right-key.svg';
|
|
7
8
|
import downKeySVG from '@plone/volto/icons/down-key.svg';
|
|
9
|
+
import { withDeviceSize } from '../../hocs';
|
|
8
10
|
|
|
9
11
|
const LayerLegend = ({ data }) => {
|
|
10
|
-
const [expand, setExpand] = React.useState(true);
|
|
11
12
|
const [legendRows, setLegendRows] = React.useState([]);
|
|
12
13
|
|
|
13
14
|
const { id, name } = data.layer || {};
|
|
14
15
|
|
|
15
16
|
const fetchLegend = async (url, activeLayerID) => {
|
|
16
|
-
let legendData = await
|
|
17
|
+
let legendData = await fetchArcGISData(url);
|
|
17
18
|
|
|
18
19
|
const { layers = [] } = legendData;
|
|
19
20
|
const selectedLayer = layers.filter((l, i) => l.layerId === activeLayerID);
|
|
@@ -27,27 +28,18 @@ const LayerLegend = ({ data }) => {
|
|
|
27
28
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
28
29
|
}, [id, data.map_service_url]);
|
|
29
30
|
return (
|
|
30
|
-
<
|
|
31
|
+
<Grid.Column>
|
|
31
32
|
<h5
|
|
32
|
-
role="presentation"
|
|
33
|
-
onClick={() => setExpand(!expand)}
|
|
34
33
|
style={{
|
|
35
34
|
marginTop: '15px',
|
|
36
35
|
marginBottom: '5px',
|
|
37
|
-
cursor: 'pointer',
|
|
38
|
-
display: 'flex',
|
|
39
36
|
}}
|
|
40
37
|
>
|
|
41
|
-
<Icon
|
|
42
|
-
name={expand ? downKeySVG : rightKeySVG}
|
|
43
|
-
title={expand ? 'Collapse' : 'Expand'}
|
|
44
|
-
size="17px"
|
|
45
|
-
/>
|
|
46
38
|
{name}
|
|
47
39
|
</h5>
|
|
40
|
+
{data.description && serializeNodes(data.description)}
|
|
48
41
|
<div style={{ display: 'flex', flexDirection: 'column' }}>
|
|
49
|
-
{
|
|
50
|
-
legendRows.length > 0 &&
|
|
42
|
+
{legendRows.length > 0 &&
|
|
51
43
|
legendRows.map((item, i) => {
|
|
52
44
|
return (
|
|
53
45
|
<span key={i} style={{ display: 'flex', alignItems: 'center' }}>
|
|
@@ -62,39 +54,59 @@ const LayerLegend = ({ data }) => {
|
|
|
62
54
|
);
|
|
63
55
|
})}
|
|
64
56
|
</div>
|
|
65
|
-
</
|
|
57
|
+
</Grid.Column>
|
|
66
58
|
);
|
|
67
59
|
};
|
|
68
60
|
|
|
69
61
|
const LegendWidget = (props) => {
|
|
70
62
|
const data = React.useMemo(() => props.data, [props.data]);
|
|
63
|
+
const { device = '' } = props;
|
|
64
|
+
|
|
65
|
+
const [expand, setExpand] = React.useState(true);
|
|
66
|
+
|
|
71
67
|
const { layers = {} } = data;
|
|
72
|
-
const
|
|
68
|
+
const map_layers =
|
|
69
|
+
layers &&
|
|
70
|
+
layers.map_layers &&
|
|
71
|
+
layers.map_layers.length > 0 &&
|
|
72
|
+
layers.map_layers.length > 3
|
|
73
|
+
? layers?.map_layers.slice(0, 3)
|
|
74
|
+
: layers?.map_layers;
|
|
73
75
|
|
|
76
|
+
const legendColumns =
|
|
77
|
+
map_layers && setLegendColumns(map_layers.length, device);
|
|
74
78
|
return (
|
|
75
79
|
<>
|
|
76
|
-
<div
|
|
77
|
-
<
|
|
78
|
-
<
|
|
79
|
-
<
|
|
80
|
-
|
|
81
|
-
{
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
80
|
+
<div className="legend-container">
|
|
81
|
+
<button className="legend-action" onClick={() => setExpand(!expand)}>
|
|
82
|
+
<h4 role="presentation" className="legend-title">
|
|
83
|
+
<Icon
|
|
84
|
+
name={expand ? downKeySVG : rightKeySVG}
|
|
85
|
+
title={expand ? 'Collapse' : 'Expand'}
|
|
86
|
+
size="17px"
|
|
87
|
+
/>
|
|
88
|
+
Legend:
|
|
89
|
+
</h4>
|
|
90
|
+
</button>
|
|
91
|
+
<Grid columns={legendColumns}>
|
|
92
|
+
{(!map_layers || map_layers.length === 0) && (
|
|
93
|
+
<p>
|
|
94
|
+
No layer found for legend. Please add a map layer from editor.
|
|
95
|
+
</p>
|
|
96
|
+
)}
|
|
97
|
+
{expand && (
|
|
98
|
+
<Grid.Row divided>
|
|
87
99
|
{map_layers &&
|
|
88
100
|
map_layers.length > 0 &&
|
|
89
101
|
map_layers.map((l, i) => (
|
|
90
102
|
<LayerLegend key={i} data={l.map_layer} />
|
|
91
103
|
))}
|
|
92
|
-
</Grid.
|
|
93
|
-
|
|
104
|
+
</Grid.Row>
|
|
105
|
+
)}
|
|
94
106
|
</Grid>
|
|
95
107
|
</div>
|
|
96
108
|
</>
|
|
97
109
|
);
|
|
98
110
|
};
|
|
99
111
|
|
|
100
|
-
export default React.memo(LegendWidget);
|
|
112
|
+
export default withDeviceSize(React.memo(LegendWidget));
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { Menu, Tab } from 'semantic-ui-react';
|
|
3
3
|
import { ObjectWidget } from '@plone/volto/components';
|
|
4
|
-
import { withDeviceSize } from '
|
|
4
|
+
import { withDeviceSize } from '../../hocs';
|
|
5
5
|
|
|
6
6
|
export const ObjectTypesWidget = (props) => {
|
|
7
7
|
const {
|
|
@@ -20,7 +20,6 @@ export const ObjectTypesWidget = (props) => {
|
|
|
20
20
|
const [activeTab, setActiveTab] = React.useState(
|
|
21
21
|
defaultActiveTab > -1 ? defaultActiveTab : 0,
|
|
22
22
|
);
|
|
23
|
-
|
|
24
23
|
const createTab = ({ schema, id, icon }, index) => {
|
|
25
24
|
return {
|
|
26
25
|
menuItem: () => (
|