@eeacms/volto-eea-map 0.1.1 → 0.1.4
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 +37 -0
- package/cypress.config.js +36 -0
- package/package.json +10 -3
- package/src/components/Blocks/EEAMap/Edit.jsx +12 -5
- package/src/components/Blocks/EEAMap/Schema.js +26 -6
- package/src/components/Blocks/EEAMap/View.jsx +7 -4
- package/src/components/Blocks/EEAMap/components/Webmap.jsx +22 -4
- package/src/components/Blocks/EEAMap/components/widgets/ExtraViews.jsx +20 -10
- package/src/components/Blocks/EEAMap/components/widgets/LayerSelectWidget.jsx +72 -16
- package/src/components/Blocks/EEAMap/components/widgets/LegendWidget.jsx +62 -19
- package/src/components/Blocks/EEAMap/components/widgets/MapEditorWidget.jsx +13 -4
- package/src/components/Blocks/EEAMap/components/widgets/ObjectTypesWidget.jsx +2 -2
- package/src/components/Blocks/EEAMap/components/widgets/panelsSchema.js +88 -103
- package/cypress.json +0 -17
- package/src/components/Blocks/EEAMap/components/TextView.jsx +0 -7
package/CHANGELOG.md
CHANGED
|
@@ -4,8 +4,45 @@ 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
|
+
#### [0.1.4](https://github.com/eea/volto-eea-map/compare/0.1.3...0.1.4)
|
|
8
|
+
|
|
9
|
+
- Configure Privacy protection screenshot data [`49097c0`](https://github.com/eea/volto-eea-map/commit/49097c0b7aa8657e626d5a49dd0eed84f5e71e78)
|
|
10
|
+
- Expandable Legend [`6edda2f`](https://github.com/eea/volto-eea-map/commit/6edda2fafd8a2a61f3f1f10c47a9ca5bb35a0355)
|
|
11
|
+
- Catch for no data [`7cef4e6`](https://github.com/eea/volto-eea-map/commit/7cef4e641650ede23e37ca9116130db1ef0a18db)
|
|
12
|
+
|
|
13
|
+
#### [0.1.3](https://github.com/eea/volto-eea-map/compare/0.1.2...0.1.3)
|
|
14
|
+
|
|
15
|
+
> 2 August 2022
|
|
16
|
+
|
|
17
|
+
- Center map on first layer [`#3`](https://github.com/eea/volto-eea-map/pull/3)
|
|
18
|
+
- Icons & download/viewer change [`321f538`](https://github.com/eea/volto-eea-map/commit/321f538e9582f9a12db3f64beb26588616e867e2)
|
|
19
|
+
- Inline inputs actions & styles [`1f4787e`](https://github.com/eea/volto-eea-map/commit/1f4787e3b3f0dc1328ff23cca2459db816188e3a)
|
|
20
|
+
- more updates for cy10 [`4d5c6a1`](https://github.com/eea/volto-eea-map/commit/4d5c6a1925413b44acc70b5ad3753378830dba2d)
|
|
21
|
+
- updates for cy10 [`30e0293`](https://github.com/eea/volto-eea-map/commit/30e0293ed79cad3cf3f62bcacd3c14a5627543bd)
|
|
22
|
+
- upgrade to cypress 10 [`fe9ca3e`](https://github.com/eea/volto-eea-map/commit/fe9ca3e6a98dd02c6b774f931fe73f18712e0e7b)
|
|
23
|
+
- padding & menu dimension [`da27ccd`](https://github.com/eea/volto-eea-map/commit/da27ccd2b0b42fb5c325a76bdde63e92216b1c93)
|
|
24
|
+
- general tab settings move to block schema [`075baed`](https://github.com/eea/volto-eea-map/commit/075baed1629964b40d355c8612498e02a16eedfc)
|
|
25
|
+
- enable conditional editor schema [`801f3c1`](https://github.com/eea/volto-eea-map/commit/801f3c1999b9b7373d1093d3835d62df8bd2fbca)
|
|
26
|
+
- run cypress on latest alpha [`0935ace`](https://github.com/eea/volto-eea-map/commit/0935aceedb0963b770aa9579c2c21a4f543513c3)
|
|
27
|
+
- Clear schema [`4b22f0a`](https://github.com/eea/volto-eea-map/commit/4b22f0aee58cca2bbcd2a8bee9864a01d65e7738)
|
|
28
|
+
- Center on extent control [`9e8b13d`](https://github.com/eea/volto-eea-map/commit/9e8b13dfd5bbfa5eb2419c54444a15fefa384de4)
|
|
29
|
+
- Clear consoles [`798bc2f`](https://github.com/eea/volto-eea-map/commit/798bc2fbf6f77ffadcedcf1e4666b315bc71ea6c)
|
|
30
|
+
|
|
31
|
+
#### [0.1.2](https://github.com/eea/volto-eea-map/compare/0.1.1...0.1.2)
|
|
32
|
+
|
|
33
|
+
> 29 July 2022
|
|
34
|
+
|
|
35
|
+
- Develop [`#2`](https://github.com/eea/volto-eea-map/pull/2)
|
|
36
|
+
- Legend only selected layer [`3474d79`](https://github.com/eea/volto-eea-map/commit/3474d7989321f656397c292bddc289f8f6329a8e)
|
|
37
|
+
- Query layer by existing fields [`52363f5`](https://github.com/eea/volto-eea-map/commit/52363f57a9ab4e49c7418e883bdf0c5bb30c1734)
|
|
38
|
+
- Cleanup [`d4e07b2`](https://github.com/eea/volto-eea-map/commit/d4e07b2fb89a5a27f5e4411047cb43e1c8add769)
|
|
39
|
+
- Description is slate [`86c983e`](https://github.com/eea/volto-eea-map/commit/86c983e7a4841ed07826c9015b70dbe931e9081a)
|
|
40
|
+
|
|
7
41
|
#### [0.1.1](https://github.com/eea/volto-eea-map/compare/0.1.0...0.1.1)
|
|
8
42
|
|
|
43
|
+
> 26 July 2022
|
|
44
|
+
|
|
45
|
+
- Repo structure update [`#1`](https://github.com/eea/volto-eea-map/pull/1)
|
|
9
46
|
- Lint [`d31819d`](https://github.com/eea/volto-eea-map/commit/d31819d98338fbc013dfd4506466e7c20b04aad5)
|
|
10
47
|
- Remove object pick widget [`40c7bcd`](https://github.com/eea/volto-eea-map/commit/40c7bcd2305bbab1c21919a0ae82af3eb628b09d)
|
|
11
48
|
- Add group layer [`74fd1af`](https://github.com/eea/volto-eea-map/commit/74fd1af2bce6347ce4a80758947e05b7c4a6d516)
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
const { defineConfig } = require('cypress');
|
|
2
|
+
|
|
3
|
+
module.exports = defineConfig({
|
|
4
|
+
viewportWidth: 1280,
|
|
5
|
+
defaultCommandTimeout: 8888,
|
|
6
|
+
chromeWebSecurity: false,
|
|
7
|
+
reporter: 'junit',
|
|
8
|
+
video: true,
|
|
9
|
+
|
|
10
|
+
retries: {
|
|
11
|
+
runMode: 8,
|
|
12
|
+
openMode: 0,
|
|
13
|
+
},
|
|
14
|
+
|
|
15
|
+
reporterOptions: {
|
|
16
|
+
mochaFile: 'cypress/reports/cypress-[hash].xml',
|
|
17
|
+
jenkinsMode: true,
|
|
18
|
+
toConsole: true,
|
|
19
|
+
},
|
|
20
|
+
|
|
21
|
+
e2e: {
|
|
22
|
+
// We've imported your old cypress plugins here.
|
|
23
|
+
// You may want to clean this up later by importing these.
|
|
24
|
+
// setupNodeEvents(on, config) {
|
|
25
|
+
// return require('./cypress/plugins/index.js')(on, config);
|
|
26
|
+
// },
|
|
27
|
+
baseUrl: 'http://localhost:3000',
|
|
28
|
+
},
|
|
29
|
+
|
|
30
|
+
component: {
|
|
31
|
+
devServer: {
|
|
32
|
+
framework: 'react',
|
|
33
|
+
bundler: 'webpack',
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@eeacms/volto-eea-map",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
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",
|
|
@@ -16,13 +16,20 @@
|
|
|
16
16
|
"type": "git",
|
|
17
17
|
"url": "git@github.com:eea/volto-eea-map.git"
|
|
18
18
|
},
|
|
19
|
+
"addons": [
|
|
20
|
+
"@eeacms/volto-embed",
|
|
21
|
+
"volto-slate"
|
|
22
|
+
],
|
|
19
23
|
"dependencies": {
|
|
24
|
+
"@eeacms/volto-embed": "^2.0.1",
|
|
25
|
+
"@plone/scripts": "*",
|
|
20
26
|
"esri-loader": "3.5.0",
|
|
21
|
-
"
|
|
27
|
+
"volto-slate": "*"
|
|
22
28
|
},
|
|
23
29
|
"devDependencies": {
|
|
24
30
|
"@cypress/code-coverage": "^3.9.5",
|
|
25
|
-
"babel-plugin-transform-class-properties": "^6.24.1"
|
|
31
|
+
"babel-plugin-transform-class-properties": "^6.24.1",
|
|
32
|
+
"cypress": "10.3.1"
|
|
26
33
|
},
|
|
27
34
|
"scripts": {
|
|
28
35
|
"release": "release-it",
|
|
@@ -5,6 +5,10 @@ import { Schema } from './Schema';
|
|
|
5
5
|
import Webmap from './components/Webmap';
|
|
6
6
|
import './styles/map.css';
|
|
7
7
|
import ExtraViews from './components/widgets/ExtraViews';
|
|
8
|
+
import {
|
|
9
|
+
PrivacyProtection,
|
|
10
|
+
addPrivacyProtectionToSchema,
|
|
11
|
+
} from '@eeacms/volto-embed';
|
|
8
12
|
|
|
9
13
|
const Edit = (props) => {
|
|
10
14
|
const { block, data, onChangeBlock, selected } = props;
|
|
@@ -12,15 +16,18 @@ const Edit = (props) => {
|
|
|
12
16
|
|
|
13
17
|
const { map_data = {}, height } = data;
|
|
14
18
|
if (__SERVER__) return '';
|
|
19
|
+
|
|
15
20
|
return (
|
|
16
|
-
|
|
17
|
-
<
|
|
18
|
-
|
|
21
|
+
<div>
|
|
22
|
+
<PrivacyProtection data={data} {...props}>
|
|
23
|
+
<Webmap data={map_data} height={height} />
|
|
24
|
+
<ExtraViews data={data} />
|
|
25
|
+
</PrivacyProtection>
|
|
19
26
|
<SidebarPortal selected={selected}>
|
|
20
27
|
<BlockDataForm
|
|
21
28
|
block={block}
|
|
22
29
|
title={schema.title}
|
|
23
|
-
schema={schema}
|
|
30
|
+
schema={addPrivacyProtectionToSchema(schema)}
|
|
24
31
|
onChangeField={(id, value) => {
|
|
25
32
|
onChangeBlock(block, {
|
|
26
33
|
...data,
|
|
@@ -30,7 +37,7 @@ const Edit = (props) => {
|
|
|
30
37
|
formData={data}
|
|
31
38
|
/>
|
|
32
39
|
</SidebarPortal>
|
|
33
|
-
|
|
40
|
+
</div>
|
|
34
41
|
);
|
|
35
42
|
};
|
|
36
43
|
|
|
@@ -5,7 +5,15 @@ export const Schema = () => {
|
|
|
5
5
|
{
|
|
6
6
|
id: 'default',
|
|
7
7
|
title: 'Default',
|
|
8
|
-
fields: [
|
|
8
|
+
fields: [
|
|
9
|
+
'description',
|
|
10
|
+
'height',
|
|
11
|
+
'map_data',
|
|
12
|
+
'show_sources',
|
|
13
|
+
'show_legend',
|
|
14
|
+
'show_download',
|
|
15
|
+
'show_viewer',
|
|
16
|
+
],
|
|
9
17
|
},
|
|
10
18
|
],
|
|
11
19
|
properties: {
|
|
@@ -13,19 +21,31 @@ export const Schema = () => {
|
|
|
13
21
|
title: 'Height',
|
|
14
22
|
type: 'number',
|
|
15
23
|
},
|
|
16
|
-
show_description: {
|
|
17
|
-
title: 'Show description',
|
|
18
|
-
type: 'boolean',
|
|
19
|
-
},
|
|
20
24
|
description: {
|
|
21
25
|
title: 'Description',
|
|
22
|
-
|
|
26
|
+
widget: 'slate',
|
|
23
27
|
},
|
|
24
28
|
map_data: {
|
|
25
29
|
title: 'Edit map',
|
|
26
30
|
description: 'Open the map customization interface',
|
|
27
31
|
widget: 'map_edit_widget',
|
|
28
32
|
},
|
|
33
|
+
show_sources: {
|
|
34
|
+
title: 'Show sources',
|
|
35
|
+
type: 'boolean',
|
|
36
|
+
},
|
|
37
|
+
show_legend: {
|
|
38
|
+
title: 'Show legend',
|
|
39
|
+
type: 'boolean',
|
|
40
|
+
},
|
|
41
|
+
show_download: {
|
|
42
|
+
title: 'Show download',
|
|
43
|
+
type: 'boolean',
|
|
44
|
+
},
|
|
45
|
+
show_viewer: {
|
|
46
|
+
title: 'Show web viewer',
|
|
47
|
+
type: 'boolean',
|
|
48
|
+
},
|
|
29
49
|
},
|
|
30
50
|
required: [],
|
|
31
51
|
};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import Webmap from './components/Webmap';
|
|
3
3
|
import ExtraViews from './components/widgets/ExtraViews';
|
|
4
|
+
import { PrivacyProtection } from '@eeacms/volto-embed';
|
|
4
5
|
|
|
5
6
|
const View = (props) => {
|
|
6
7
|
const { data } = props || {};
|
|
@@ -10,10 +11,12 @@ const View = (props) => {
|
|
|
10
11
|
if (__SERVER__) return '';
|
|
11
12
|
|
|
12
13
|
return (
|
|
13
|
-
|
|
14
|
-
<
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
<div>
|
|
15
|
+
<PrivacyProtection data={data} {...props}>
|
|
16
|
+
<Webmap data={map_data} />
|
|
17
|
+
<ExtraViews data={data} />
|
|
18
|
+
</PrivacyProtection>
|
|
19
|
+
</div>
|
|
17
20
|
);
|
|
18
21
|
};
|
|
19
22
|
|
|
@@ -36,6 +36,7 @@ const Webmap = (props) => {
|
|
|
36
36
|
const options = {
|
|
37
37
|
css: true,
|
|
38
38
|
};
|
|
39
|
+
|
|
39
40
|
const mapRef = React.useRef();
|
|
40
41
|
const [modules, setModules] = React.useState({});
|
|
41
42
|
const modules_loaded = React.useRef(false);
|
|
@@ -88,12 +89,10 @@ const Webmap = (props) => {
|
|
|
88
89
|
map_layers.length > 0 &&
|
|
89
90
|
map_layers
|
|
90
91
|
.filter(({ map_service_url, layer }) => map_service_url && layer)
|
|
91
|
-
.map(({ map_service_url, layer }) => {
|
|
92
|
+
.map(({ map_service_url, layer, query = '' }) => {
|
|
92
93
|
const url = `${map_service_url}/${layer}`;
|
|
93
94
|
|
|
94
95
|
let mapLayer;
|
|
95
|
-
|
|
96
|
-
//TODO: add more layers and error catch for unrecognized layer
|
|
97
96
|
switch (layer.type) {
|
|
98
97
|
case 'Raster Layer':
|
|
99
98
|
mapLayer = new MapImageLayer({
|
|
@@ -101,7 +100,10 @@ const Webmap = (props) => {
|
|
|
101
100
|
});
|
|
102
101
|
break;
|
|
103
102
|
case 'Feature Layer':
|
|
104
|
-
mapLayer = new FeatureLayer({
|
|
103
|
+
mapLayer = new FeatureLayer({
|
|
104
|
+
url,
|
|
105
|
+
definitionExpression: query,
|
|
106
|
+
});
|
|
105
107
|
break;
|
|
106
108
|
case 'Group Layer':
|
|
107
109
|
mapLayer = new GroupLayer({ url });
|
|
@@ -116,6 +118,7 @@ const Webmap = (props) => {
|
|
|
116
118
|
basemap: base_layer || 'hybrid',
|
|
117
119
|
layers,
|
|
118
120
|
});
|
|
121
|
+
|
|
119
122
|
const view = new MapView({
|
|
120
123
|
container: mapRef.current,
|
|
121
124
|
map,
|
|
@@ -126,6 +129,21 @@ const Webmap = (props) => {
|
|
|
126
129
|
},
|
|
127
130
|
});
|
|
128
131
|
|
|
132
|
+
if (layers && layers[0] && zoom && zoom.centerOnExtent) {
|
|
133
|
+
view.whenLayerView(layers[0]).then(function (layerView) {
|
|
134
|
+
layerView.watch('updating', function (val) {
|
|
135
|
+
// view.goTo(response.extent);
|
|
136
|
+
|
|
137
|
+
if (!val && layerView) {
|
|
138
|
+
layerView.queryExtent().then(function (response) {
|
|
139
|
+
///go to the extent of all the graphics in the layer view
|
|
140
|
+
if (response.extent) view.goTo(response.extent);
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
});
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
|
|
129
147
|
if (zoom?.show_zoom) {
|
|
130
148
|
const zoomPosition = zoom && zoom.position ? zoom.position : 'top-right';
|
|
131
149
|
const zoomWidget = new Zoom({
|
|
@@ -2,35 +2,41 @@ import React from 'react';
|
|
|
2
2
|
import { Button } from 'semantic-ui-react';
|
|
3
3
|
import { Icon } from '@plone/volto/components';
|
|
4
4
|
|
|
5
|
-
import TextView from '../TextView';
|
|
6
5
|
import LegendWidget from './LegendWidget';
|
|
6
|
+
import { serializeNodes } from 'volto-slate/editor/render';
|
|
7
7
|
|
|
8
8
|
import worldSVG from '@plone/volto/icons/world.svg';
|
|
9
9
|
import downloadSVG from '@plone/volto/icons/download.svg';
|
|
10
10
|
|
|
11
11
|
const ExtraViews = ({ data }) => {
|
|
12
|
-
const {
|
|
13
|
-
|
|
12
|
+
const {
|
|
13
|
+
map_data = {},
|
|
14
|
+
description,
|
|
15
|
+
show_legend,
|
|
16
|
+
show_download,
|
|
17
|
+
show_viewer,
|
|
18
|
+
} = data;
|
|
19
|
+
|
|
14
20
|
return (
|
|
15
21
|
<>
|
|
16
|
-
{
|
|
17
|
-
{show_description && description && <TextView text={description} />}
|
|
18
|
-
{(general.show_download || general.show_viewer) && (
|
|
22
|
+
{map_data.layers?.map_layers[0] && (show_download || show_viewer) && (
|
|
19
23
|
<div
|
|
20
24
|
style={{ display: 'flex', justifyContent: 'end', margin: '10px 0' }}
|
|
21
25
|
>
|
|
22
|
-
{
|
|
26
|
+
{show_download && (
|
|
23
27
|
<a
|
|
24
28
|
target="_blank"
|
|
25
29
|
rel="noreferrer"
|
|
26
30
|
href={`${map_data.layers.map_layers[0].map_layer.map_service_url}?f=lyr&v=9.3`}
|
|
27
31
|
>
|
|
28
32
|
<Button size="tiny">
|
|
29
|
-
<
|
|
33
|
+
<Button.Content>
|
|
34
|
+
<Icon name={downloadSVG} title="Download" size="25px" />
|
|
35
|
+
</Button.Content>
|
|
30
36
|
</Button>
|
|
31
37
|
</a>
|
|
32
38
|
)}
|
|
33
|
-
{
|
|
39
|
+
{show_viewer && (
|
|
34
40
|
<a
|
|
35
41
|
target="_blank"
|
|
36
42
|
rel="noreferrer"
|
|
@@ -40,12 +46,16 @@ const ExtraViews = ({ data }) => {
|
|
|
40
46
|
}
|
|
41
47
|
>
|
|
42
48
|
<Button size="tiny">
|
|
43
|
-
<
|
|
49
|
+
<Button.Content>
|
|
50
|
+
<Icon name={worldSVG} title="View map" size="25px" />
|
|
51
|
+
</Button.Content>
|
|
44
52
|
</Button>
|
|
45
53
|
</a>
|
|
46
54
|
)}
|
|
47
55
|
</div>
|
|
48
56
|
)}
|
|
57
|
+
{show_legend && <LegendWidget data={map_data} />}
|
|
58
|
+
{description && serializeNodes(description)}
|
|
49
59
|
</>
|
|
50
60
|
);
|
|
51
61
|
};
|
|
@@ -4,13 +4,21 @@ import { Input, Select, Button, Grid } from 'semantic-ui-react';
|
|
|
4
4
|
|
|
5
5
|
import checkSVG from '@plone/volto/icons/check.svg';
|
|
6
6
|
import closeSVG from '@plone/volto/icons/clear.svg';
|
|
7
|
+
import aheadSVG from '@plone/volto/icons/ahead.svg';
|
|
7
8
|
|
|
8
9
|
import { fetchArcgisData } from '../../utils';
|
|
9
10
|
|
|
10
11
|
const LayerSelectWidget = (props) => {
|
|
11
12
|
const { onChange, value = {}, id } = props;
|
|
12
13
|
|
|
13
|
-
const {
|
|
14
|
+
const {
|
|
15
|
+
available_layers,
|
|
16
|
+
map_data,
|
|
17
|
+
map_service_url,
|
|
18
|
+
layer,
|
|
19
|
+
fields = [],
|
|
20
|
+
query = '',
|
|
21
|
+
} = value;
|
|
14
22
|
|
|
15
23
|
const [mapData, setMapData] = React.useState(map_data);
|
|
16
24
|
const [checkColor, setCheckColor] = React.useState('');
|
|
@@ -20,6 +28,7 @@ const LayerSelectWidget = (props) => {
|
|
|
20
28
|
const [availableLayers, setAvailableLayers] = React.useState(
|
|
21
29
|
available_layers,
|
|
22
30
|
);
|
|
31
|
+
const [layerQuery, setLayerQuery] = React.useState(query);
|
|
23
32
|
|
|
24
33
|
const handleServiceUrlCheck = async () => {
|
|
25
34
|
// fetch url, save it, populate layers options
|
|
@@ -36,6 +45,7 @@ const LayerSelectWidget = (props) => {
|
|
|
36
45
|
);
|
|
37
46
|
}
|
|
38
47
|
onChange(id, {
|
|
48
|
+
...value,
|
|
39
49
|
layer: selectedLayer,
|
|
40
50
|
map_service_url: serviceUrl,
|
|
41
51
|
available_layers: availableLayers,
|
|
@@ -47,13 +57,32 @@ const LayerSelectWidget = (props) => {
|
|
|
47
57
|
}
|
|
48
58
|
};
|
|
49
59
|
|
|
50
|
-
const
|
|
60
|
+
const handleLayerFetch = async (service_url, id) => {
|
|
61
|
+
try {
|
|
62
|
+
let fullLayer = await fetchArcgisData(`${service_url}/${id}`);
|
|
63
|
+
return fullLayer;
|
|
64
|
+
} catch (e) {}
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
const handleSelectLayer = async (layer) => {
|
|
68
|
+
const fullLayer = await handleLayerFetch(serviceUrl, layer.id);
|
|
51
69
|
setSelectedLayer(layer);
|
|
52
70
|
onChange(id, {
|
|
71
|
+
...value,
|
|
53
72
|
layer,
|
|
73
|
+
fields: fullLayer.fields,
|
|
54
74
|
map_service_url: serviceUrl,
|
|
55
75
|
available_layers: availableLayers,
|
|
56
76
|
map_data: mapData,
|
|
77
|
+
query: '',
|
|
78
|
+
});
|
|
79
|
+
setLayerQuery('');
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
const handleQueryLayer = () => {
|
|
83
|
+
onChange(id, {
|
|
84
|
+
...value,
|
|
85
|
+
query: layerQuery,
|
|
57
86
|
});
|
|
58
87
|
};
|
|
59
88
|
|
|
@@ -69,30 +98,26 @@ const LayerSelectWidget = (props) => {
|
|
|
69
98
|
<Input
|
|
70
99
|
type="text"
|
|
71
100
|
onChange={(e, { value }) => setServiceUrl(value)}
|
|
72
|
-
style={{ width: '
|
|
101
|
+
style={{ width: '70%' }}
|
|
73
102
|
value={serviceUrl}
|
|
74
|
-
|
|
75
|
-
|
|
103
|
+
action
|
|
104
|
+
actionPosition="right"
|
|
105
|
+
>
|
|
106
|
+
<input />
|
|
76
107
|
<Button
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
alignItems: 'center',
|
|
81
|
-
}}
|
|
108
|
+
type="submit"
|
|
109
|
+
size="tiny"
|
|
110
|
+
compact
|
|
82
111
|
color={checkColor}
|
|
83
112
|
onClick={handleServiceUrlCheck}
|
|
84
113
|
>
|
|
85
|
-
<p style={{ fontSize: '14px', margin: '0', marginRight: '5px' }}>
|
|
86
|
-
Check Url
|
|
87
|
-
</p>
|
|
88
114
|
<Icon
|
|
89
115
|
name={serviceUrlError ? closeSVG : checkSVG}
|
|
90
|
-
style={{ marginLeft: '5px' }}
|
|
91
116
|
title="Check Url"
|
|
92
117
|
size="17px"
|
|
93
118
|
/>
|
|
94
119
|
</Button>
|
|
95
|
-
</
|
|
120
|
+
</Input>
|
|
96
121
|
</Grid.Row>
|
|
97
122
|
<h4>Layer</h4>
|
|
98
123
|
<Grid.Row>
|
|
@@ -104,7 +129,38 @@ const LayerSelectWidget = (props) => {
|
|
|
104
129
|
value={selectedLayer}
|
|
105
130
|
/>
|
|
106
131
|
</Grid.Row>
|
|
107
|
-
<
|
|
132
|
+
<h4>Query Layer</h4>
|
|
133
|
+
<Grid.Row stretched>
|
|
134
|
+
<Input
|
|
135
|
+
type="text"
|
|
136
|
+
onChange={(e, { value }) => setLayerQuery(value)}
|
|
137
|
+
style={{ width: '70%' }}
|
|
138
|
+
value={layerQuery}
|
|
139
|
+
action
|
|
140
|
+
actionPosition="right"
|
|
141
|
+
>
|
|
142
|
+
<input />
|
|
143
|
+
<Button
|
|
144
|
+
type="submit"
|
|
145
|
+
size="tiny"
|
|
146
|
+
compact
|
|
147
|
+
color={'green'}
|
|
148
|
+
onClick={handleQueryLayer}
|
|
149
|
+
>
|
|
150
|
+
<Icon name={aheadSVG} title="Check Url" size="17px" />
|
|
151
|
+
</Button>
|
|
152
|
+
</Input>
|
|
153
|
+
</Grid.Row>
|
|
154
|
+
<Grid.Row>
|
|
155
|
+
<p style={{ fontSize: '12px', fontWeight: 'bold' }}>
|
|
156
|
+
Available Fields:
|
|
157
|
+
</p>
|
|
158
|
+
</Grid.Row>
|
|
159
|
+
{fields &&
|
|
160
|
+
fields.length > 0 &&
|
|
161
|
+
fields.map((field, id) => (
|
|
162
|
+
<p style={{ fontSize: '12px' }}>{field.alias}</p>
|
|
163
|
+
))}
|
|
108
164
|
</Grid>
|
|
109
165
|
</div>
|
|
110
166
|
);
|
|
@@ -1,19 +1,50 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { Grid } from 'semantic-ui-react';
|
|
3
3
|
import { fetchArcgisData } from '../../utils';
|
|
4
|
+
import { Icon } from '@plone/volto/components';
|
|
5
|
+
|
|
6
|
+
import rightKeySVG from '@plone/volto/icons/right-key.svg';
|
|
7
|
+
import downKeySVG from '@plone/volto/icons/down-key.svg';
|
|
8
|
+
|
|
9
|
+
const LayerLegend = ({ data, name }) => {
|
|
10
|
+
const [expand, setExpand] = React.useState(true);
|
|
4
11
|
|
|
5
|
-
const LayerLegend = ({ data }) => {
|
|
6
12
|
return (
|
|
7
13
|
<div style={{ display: 'flex', flexDirection: 'column' }}>
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
}
|
|
14
|
+
<h5
|
|
15
|
+
role="presentation"
|
|
16
|
+
onClick={() => setExpand(!expand)}
|
|
17
|
+
style={{
|
|
18
|
+
marginTop: '10px',
|
|
19
|
+
marginBottom: '5px',
|
|
20
|
+
cursor: 'pointer',
|
|
21
|
+
display: 'flex',
|
|
22
|
+
}}
|
|
23
|
+
>
|
|
24
|
+
<Icon
|
|
25
|
+
name={expand ? downKeySVG : rightKeySVG}
|
|
26
|
+
title={expand ? 'Collapse' : 'Expand'}
|
|
27
|
+
size="17px"
|
|
28
|
+
/>
|
|
29
|
+
{name}
|
|
30
|
+
</h5>
|
|
31
|
+
<div style={{ display: 'flex', flexDirection: 'column' }}>
|
|
32
|
+
{expand &&
|
|
33
|
+
data.length > 0 &&
|
|
34
|
+
data.map((item, i) => {
|
|
35
|
+
return (
|
|
36
|
+
<span key={i} style={{ display: 'flex', alignItems: 'center' }}>
|
|
37
|
+
<img
|
|
38
|
+
alt="alt"
|
|
39
|
+
src={`data:image/png;base64,${item.imageData}`}
|
|
40
|
+
/>
|
|
41
|
+
<span style={{ fontSize: '13px', marginLeft: '5px' }}>
|
|
42
|
+
{item.label}
|
|
43
|
+
</span>
|
|
44
|
+
</span>
|
|
45
|
+
);
|
|
46
|
+
})}
|
|
47
|
+
</div>
|
|
17
48
|
</div>
|
|
18
49
|
);
|
|
19
50
|
};
|
|
@@ -27,15 +58,21 @@ const LegendWidget = (props) => {
|
|
|
27
58
|
const activeLayer = map_layers.length > 0 ? map_layers[0]?.map_layer : '';
|
|
28
59
|
const fetchLegend = async (url) => {
|
|
29
60
|
let legendData = await fetchArcgisData(url);
|
|
30
|
-
const { layers = [] } = legendData;
|
|
31
61
|
|
|
32
|
-
|
|
62
|
+
//TODO: configure this for multiple layers
|
|
63
|
+
const { layers = [] } = legendData;
|
|
64
|
+
const selectedLayerLedend = layers.filter(
|
|
65
|
+
(l, i) => l.layerId === activeLayer.layer.id,
|
|
66
|
+
);
|
|
67
|
+
setLegendLayers(selectedLayerLedend);
|
|
33
68
|
};
|
|
34
69
|
|
|
35
70
|
React.useEffect(() => {
|
|
36
|
-
|
|
71
|
+
if (activeLayer) {
|
|
72
|
+
fetchLegend(`${activeLayer.map_service_url}/legend`);
|
|
73
|
+
}
|
|
74
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
37
75
|
}, [data, activeLayer.map_service_url]);
|
|
38
|
-
|
|
39
76
|
return (
|
|
40
77
|
<>
|
|
41
78
|
<div style={{ margin: '10px 0' }}>
|
|
@@ -43,13 +80,19 @@ const LegendWidget = (props) => {
|
|
|
43
80
|
<Grid.Row>
|
|
44
81
|
<Grid.Column>
|
|
45
82
|
<h3>Legend:</h3>
|
|
83
|
+
{!activeLayer && (
|
|
84
|
+
<p>
|
|
85
|
+
No layer found for legend. Please add a map layer from editor.
|
|
86
|
+
</p>
|
|
87
|
+
)}
|
|
46
88
|
{legendLayers.length > 0 &&
|
|
47
|
-
legendLayers.map((layer,
|
|
89
|
+
legendLayers.map((layer, i) => {
|
|
48
90
|
return (
|
|
49
|
-
<
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
91
|
+
<LayerLegend
|
|
92
|
+
key={i}
|
|
93
|
+
name={layer?.layerName}
|
|
94
|
+
data={layer?.legend}
|
|
95
|
+
/>
|
|
53
96
|
);
|
|
54
97
|
})}
|
|
55
98
|
</Grid.Column>
|
|
@@ -3,7 +3,7 @@ import { Modal, Button, Grid } from 'semantic-ui-react';
|
|
|
3
3
|
import Webmap from '../Webmap';
|
|
4
4
|
import { FormFieldWrapper, InlineForm } from '@plone/volto/components';
|
|
5
5
|
|
|
6
|
-
import
|
|
6
|
+
import PanelsSchema from './panelsSchema';
|
|
7
7
|
|
|
8
8
|
const MapEditorWidget = (props) => {
|
|
9
9
|
const [open, setOpen] = React.useState(false);
|
|
@@ -11,9 +11,16 @@ const MapEditorWidget = (props) => {
|
|
|
11
11
|
const [intValue, setIntValue] = React.useState(value);
|
|
12
12
|
|
|
13
13
|
const dataForm = { map_data: intValue };
|
|
14
|
-
|
|
15
14
|
const handleApplyChanges = () => {
|
|
16
15
|
onChange(id, intValue);
|
|
16
|
+
|
|
17
|
+
//set map data for screenshot
|
|
18
|
+
if (intValue.layers?.map_layers[0].map_layer?.map_service_url) {
|
|
19
|
+
onChange(
|
|
20
|
+
'url',
|
|
21
|
+
`${intValue.layers?.map_layers[0].map_layer?.map_service_url}?f=jsapi`,
|
|
22
|
+
);
|
|
23
|
+
}
|
|
17
24
|
setOpen(false);
|
|
18
25
|
};
|
|
19
26
|
|
|
@@ -26,6 +33,8 @@ const MapEditorWidget = (props) => {
|
|
|
26
33
|
setIntValue(fieldVal);
|
|
27
34
|
};
|
|
28
35
|
|
|
36
|
+
let schema = PanelsSchema({ data: dataForm });
|
|
37
|
+
|
|
29
38
|
return (
|
|
30
39
|
<FormFieldWrapper {...props}>
|
|
31
40
|
<Modal
|
|
@@ -46,8 +55,8 @@ const MapEditorWidget = (props) => {
|
|
|
46
55
|
<Grid.Column width={4}>
|
|
47
56
|
<InlineForm
|
|
48
57
|
block={block}
|
|
49
|
-
title={
|
|
50
|
-
schema={
|
|
58
|
+
title={schema.title}
|
|
59
|
+
schema={schema}
|
|
51
60
|
onChangeField={(id, value) => {
|
|
52
61
|
handleChangeField(id, value);
|
|
53
62
|
}}
|
|
@@ -24,7 +24,7 @@ export const ObjectTypesWidget = (props) => {
|
|
|
24
24
|
),
|
|
25
25
|
render: () => {
|
|
26
26
|
return (
|
|
27
|
-
<Tab.Pane>
|
|
27
|
+
<Tab.Pane style={{ padding: '0' }}>
|
|
28
28
|
<ObjectWidget
|
|
29
29
|
schema={schema}
|
|
30
30
|
id={id}
|
|
@@ -45,7 +45,7 @@ export const ObjectTypesWidget = (props) => {
|
|
|
45
45
|
menu={{ fluid: true, vertical: true, tabular: true }}
|
|
46
46
|
panes={schemas.map(createTab)}
|
|
47
47
|
activeIndex={activeTab}
|
|
48
|
-
grid={{ paneWidth:
|
|
48
|
+
grid={{ paneWidth: 9, tabWidth: 3 }}
|
|
49
49
|
/>
|
|
50
50
|
);
|
|
51
51
|
};
|
|
@@ -55,6 +55,7 @@ const MapLayersSchema = {
|
|
|
55
55
|
},
|
|
56
56
|
required: [],
|
|
57
57
|
};
|
|
58
|
+
|
|
58
59
|
const PrintSchema = {
|
|
59
60
|
title: 'Print',
|
|
60
61
|
fieldsets: [
|
|
@@ -81,110 +82,94 @@ const PrintSchema = {
|
|
|
81
82
|
required: [],
|
|
82
83
|
};
|
|
83
84
|
|
|
84
|
-
const ZoomSchema = {
|
|
85
|
-
|
|
86
|
-
fieldsets: [
|
|
87
|
-
{
|
|
88
|
-
id: 'default',
|
|
89
|
-
title: 'Zoom',
|
|
90
|
-
fields: ['show_zoom', 'position', 'zoom_level', 'long', 'lat'],
|
|
91
|
-
},
|
|
92
|
-
],
|
|
93
|
-
properties: {
|
|
94
|
-
show_zoom: {
|
|
95
|
-
title: 'Show zoom',
|
|
96
|
-
type: 'boolean',
|
|
97
|
-
},
|
|
98
|
-
position: {
|
|
99
|
-
title: 'Zoom position',
|
|
100
|
-
choices: ['bottom-right', 'bottom-left', 'top-right', 'top-left'].map(
|
|
101
|
-
(n) => {
|
|
102
|
-
return [n, n];
|
|
103
|
-
},
|
|
104
|
-
),
|
|
105
|
-
},
|
|
106
|
-
zoom_level: {
|
|
107
|
-
title: 'Zoom level',
|
|
108
|
-
type: 'number',
|
|
109
|
-
},
|
|
110
|
-
long: {
|
|
111
|
-
title: 'Longitude',
|
|
112
|
-
type: 'number',
|
|
113
|
-
},
|
|
114
|
-
lat: {
|
|
115
|
-
title: 'Latitude',
|
|
116
|
-
type: 'number',
|
|
117
|
-
},
|
|
118
|
-
},
|
|
119
|
-
required: [],
|
|
120
|
-
};
|
|
85
|
+
const ZoomSchema = ({ data = {} }) => {
|
|
86
|
+
const centerOnExtent = data?.map_data?.zoom?.centerOnExtent;
|
|
121
87
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
88
|
+
return {
|
|
89
|
+
title: 'Zoom',
|
|
90
|
+
fieldsets: [
|
|
91
|
+
{
|
|
92
|
+
id: 'default',
|
|
93
|
+
title: 'Zoom',
|
|
94
|
+
fields: [
|
|
95
|
+
'show_zoom',
|
|
96
|
+
'centerOnExtent',
|
|
97
|
+
'position',
|
|
98
|
+
...(!centerOnExtent ? ['zoom_level', 'long', 'lat'] : []),
|
|
99
|
+
],
|
|
100
|
+
},
|
|
101
|
+
],
|
|
102
|
+
properties: {
|
|
103
|
+
show_zoom: {
|
|
104
|
+
title: 'Show zoom',
|
|
105
|
+
type: 'boolean',
|
|
106
|
+
},
|
|
107
|
+
centerOnExtent: {
|
|
108
|
+
title: 'Center on extent',
|
|
109
|
+
type: 'boolean',
|
|
110
|
+
description: 'This will override latitude/longitude/zoom level',
|
|
111
|
+
},
|
|
112
|
+
position: {
|
|
113
|
+
title: 'Zoom position',
|
|
114
|
+
choices: ['bottom-right', 'bottom-left', 'top-right', 'top-left'].map(
|
|
115
|
+
(n) => {
|
|
116
|
+
return [n, n];
|
|
117
|
+
},
|
|
118
|
+
),
|
|
119
|
+
},
|
|
120
|
+
zoom_level: {
|
|
121
|
+
title: 'Zoom level',
|
|
122
|
+
type: 'number',
|
|
123
|
+
},
|
|
124
|
+
long: {
|
|
125
|
+
title: 'Longitude',
|
|
126
|
+
type: 'number',
|
|
127
|
+
},
|
|
128
|
+
lat: {
|
|
129
|
+
title: 'Latitude',
|
|
130
|
+
type: 'number',
|
|
131
|
+
},
|
|
132
|
+
},
|
|
133
|
+
required: [],
|
|
134
|
+
};
|
|
150
135
|
};
|
|
151
136
|
|
|
152
|
-
export
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
},
|
|
188
|
-
|
|
189
|
-
|
|
137
|
+
export default ({ data = {} }) => {
|
|
138
|
+
const zoomSchema = ZoomSchema({ data });
|
|
139
|
+
|
|
140
|
+
return {
|
|
141
|
+
title: 'Map Editor',
|
|
142
|
+
fieldsets: [
|
|
143
|
+
{
|
|
144
|
+
id: 'default',
|
|
145
|
+
title: 'Map Editor Sections',
|
|
146
|
+
fields: ['map_data'],
|
|
147
|
+
},
|
|
148
|
+
],
|
|
149
|
+
properties: {
|
|
150
|
+
map_data: {
|
|
151
|
+
title: 'Panels',
|
|
152
|
+
widget: 'object_types_widget',
|
|
153
|
+
schemas: [
|
|
154
|
+
{
|
|
155
|
+
id: 'base',
|
|
156
|
+
schema: BaseLayerSchema,
|
|
157
|
+
},
|
|
158
|
+
{
|
|
159
|
+
id: 'layers',
|
|
160
|
+
schema: MapLayersSchema,
|
|
161
|
+
},
|
|
162
|
+
{
|
|
163
|
+
id: 'print',
|
|
164
|
+
schema: PrintSchema,
|
|
165
|
+
},
|
|
166
|
+
{
|
|
167
|
+
id: 'zoom',
|
|
168
|
+
schema: zoomSchema,
|
|
169
|
+
},
|
|
170
|
+
],
|
|
171
|
+
},
|
|
172
|
+
},
|
|
173
|
+
required: [],
|
|
174
|
+
};
|
|
190
175
|
};
|
package/cypress.json
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"baseUrl": "http://localhost:3000",
|
|
3
|
-
"viewportWidth": 1280,
|
|
4
|
-
"defaultCommandTimeout": 8888,
|
|
5
|
-
"chromeWebSecurity": false,
|
|
6
|
-
"reporter": "junit",
|
|
7
|
-
"video": true,
|
|
8
|
-
"retries": {
|
|
9
|
-
"runMode": 8,
|
|
10
|
-
"openMode": 0
|
|
11
|
-
},
|
|
12
|
-
"reporterOptions": {
|
|
13
|
-
"mochaFile": "cypress/reports/cypress-[hash].xml",
|
|
14
|
-
"jenkinsMode": true,
|
|
15
|
-
"toConsole": true
|
|
16
|
-
}
|
|
17
|
-
}
|