@eeacms/volto-eea-map 0.1.5 → 0.1.8

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 (29) hide show
  1. package/CHANGELOG.md +39 -0
  2. package/package.json +1 -1
  3. package/src/actions.js +12 -0
  4. package/src/components/Blocks/EEAMap/Edit.jsx +4 -13
  5. package/src/components/Blocks/EEAMap/Schema.js +13 -7
  6. package/src/components/Blocks/EEAMap/View.jsx +4 -6
  7. package/src/components/Blocks/EEAMap/components/Webmap.jsx +22 -15
  8. package/src/components/Blocks/EEAMap/components/widgets/ExtraViews.jsx +2 -2
  9. package/src/components/Blocks/EEAMap/components/widgets/LayerSelectWidget.jsx +111 -56
  10. package/src/components/Blocks/EEAMap/components/widgets/LegendWidget.jsx +2 -1
  11. package/src/components/Blocks/EEAMap/components/widgets/MapEditorWidget.jsx +28 -21
  12. package/src/components/Blocks/EEAMap/components/widgets/ObjectTypesWidget.jsx +11 -3
  13. package/src/components/Blocks/EEAMap/components/widgets/VisualizationEditorWidget.jsx +94 -0
  14. package/src/components/Blocks/EEAMap/components/widgets/VisualizationView.jsx +16 -0
  15. package/src/components/Blocks/EEAMap/components/widgets/panelsSchema.js +3 -11
  16. package/src/components/Blocks/EEAMap/styles/map.css +44 -0
  17. package/src/components/Blocks/EmbedEEAMap/Edit.jsx +34 -0
  18. package/src/components/Blocks/EmbedEEAMap/Schema.js +46 -0
  19. package/src/components/Blocks/EmbedEEAMap/View.jsx +48 -0
  20. package/src/components/Blocks/EmbedEEAMap/styles/map.css +22 -0
  21. package/src/components/index.js +4 -1
  22. package/src/constants.js +1 -0
  23. package/src/hocs/index.js +3 -0
  24. package/src/hocs/withDeviceSize.jsx +45 -0
  25. package/src/index.js +54 -1
  26. package/src/middlewares/index.js +14 -0
  27. package/src/middlewares/map_visualizations.js +1 -0
  28. package/src/reducers/index.js +3 -0
  29. package/src/reducers/map_visualizations.js +48 -0
package/CHANGELOG.md CHANGED
@@ -4,8 +4,47 @@ 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.8](https://github.com/eea/volto-eea-map/compare/0.1.7...0.1.8)
8
+
9
+ - remove title on map edit widget [`1d00707`](https://github.com/eea/volto-eea-map/commit/1d0070716a743ea7f26c5f877b723492319fcecd)
10
+ - update query by stored value [`c0f6ddd`](https://github.com/eea/volto-eea-map/commit/c0f6dddadaaf28de5b9914214acf735a166fae88)
11
+ - stylelint [`511845a`](https://github.com/eea/volto-eea-map/commit/511845a319137dfe4e1c0c9846ee5ccb7656b32b)
12
+ - visual candy [`2b24975`](https://github.com/eea/volto-eea-map/commit/2b249758f30133d8080793e892d0771e9b63dea5)
13
+ - responsive hoc only keep device size [`444f8b3`](https://github.com/eea/volto-eea-map/commit/444f8b3df2dd58a1f1e5bd6c6a90c1e9919696a1)
14
+ - responsive improvements on edit widget [`1dcdda0`](https://github.com/eea/volto-eea-map/commit/1dcdda077f5aaa8ddd256d2bec2f1018a15e066d)
15
+ - map is sticky [`64f3874`](https://github.com/eea/volto-eea-map/commit/64f3874648f0ede23502998e9165e86538e44728)
16
+ - simplified layer edit [`b64348c`](https://github.com/eea/volto-eea-map/commit/b64348c962647cdfc48d3328c5effb3b02b6217c)
17
+ - no consoles [`1387128`](https://github.com/eea/volto-eea-map/commit/1387128037abb314798326fa3c47b52a13d0415f)
18
+ - show if zoom/print position [`c4d7107`](https://github.com/eea/volto-eea-map/commit/c4d7107e874616c2246ec883d07eb59fad76b21e)
19
+ - lint fix [`cc497bd`](https://github.com/eea/volto-eea-map/commit/cc497bd8fe61d8867b74a8a16bc4868ccf088d55)
20
+ - fixes on webmap [`1c4506b`](https://github.com/eea/volto-eea-map/commit/1c4506b227d3a0ad0f919e3ff826700304b0620a)
21
+ - new embed eea map block to work with visualizations [`be4f2b0`](https://github.com/eea/volto-eea-map/commit/be4f2b00f92ea9dedc359e8c2620a9a31f4b5b6b)
22
+ - remove vis_url logic, will be moved in a new block [`13ebe94`](https://github.com/eea/volto-eea-map/commit/13ebe94c6c339fc827c019aab0a698aa431c5b78)
23
+ - Updates for map visualization [`895d463`](https://github.com/eea/volto-eea-map/commit/895d46313e9b65c6a5f420284fb9459296ed83f4)
24
+
25
+ #### [0.1.7](https://github.com/eea/volto-eea-map/compare/0.1.6...0.1.7)
26
+
27
+ > 9 August 2022
28
+
29
+ - Develop [`#7`](https://github.com/eea/volto-eea-map/pull/7)
30
+ - fix height coming through in view [`39d4d28`](https://github.com/eea/volto-eea-map/commit/39d4d287a4fe86890f5fad8d9050130b496dfe70)
31
+ - Connected visualization view-edit [`52a8e21`](https://github.com/eea/volto-eea-map/commit/52a8e2187cb2e3a7db660ae4b6b5610c88be5083)
32
+ - map_view is map_editor_widget, add view component for content-type [`dc227f9`](https://github.com/eea/volto-eea-map/commit/dc227f9bbb259b59739a3694dc69f0fcca661137)
33
+ - Add map visualization widget [`affd84c`](https://github.com/eea/volto-eea-map/commit/affd84ca8753214c07f2f0756a13f08f5cf0a048)
34
+
35
+ #### [0.1.6](https://github.com/eea/volto-eea-map/compare/0.1.5...0.1.6)
36
+
37
+ > 5 August 2022
38
+
39
+ - Develop [`#6`](https://github.com/eea/volto-eea-map/pull/6)
40
+ - Lint fix [`f5561d1`](https://github.com/eea/volto-eea-map/commit/f5561d1581201bd635b4e53e8a46decaf684438f)
41
+ - Map improvements [`c75d16c`](https://github.com/eea/volto-eea-map/commit/c75d16c265136d9f676e194540e613bb742fb51b)
42
+
7
43
  #### [0.1.5](https://github.com/eea/volto-eea-map/compare/0.1.4...0.1.5)
8
44
 
45
+ > 4 August 2022
46
+
47
+ - Develop [`#5`](https://github.com/eea/volto-eea-map/pull/5)
9
48
  - Center on extent only on map load [`b63f586`](https://github.com/eea/volto-eea-map/commit/b63f586e0df68faa755bb0d25e297530e36ef7c9)
10
49
  - Configure proxy for all map subdomains [`0f19030`](https://github.com/eea/volto-eea-map/commit/0f19030569e1f77b1ff7657669e876519712840f)
11
50
  - Prevent unnecessary rerenders of ma [`8752384`](https://github.com/eea/volto-eea-map/commit/8752384b3bbd7b564a25b3e4347c47692106f556)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eeacms/volto-eea-map",
3
- "version": "0.1.5",
3
+ "version": "0.1.8",
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",
package/src/actions.js ADDED
@@ -0,0 +1,12 @@
1
+ import { GET_MAP_VISUALIZATION } from './constants';
2
+
3
+ export function getVisualization(path) {
4
+ return {
5
+ type: GET_MAP_VISUALIZATION,
6
+ path,
7
+ request: {
8
+ op: 'get',
9
+ path: `${path}/@map-visualization`,
10
+ },
11
+ };
12
+ }
@@ -2,26 +2,17 @@ import React from 'react';
2
2
  import { SidebarPortal } from '@plone/volto/components';
3
3
  import BlockDataForm from '@plone/volto/components/manage/Form/BlockDataForm';
4
4
  import { Schema } from './Schema';
5
- import Webmap from './components/Webmap';
5
+ import View from './View';
6
+ import { addPrivacyProtectionToSchema } from '@eeacms/volto-embed';
6
7
  import './styles/map.css';
7
- import ExtraViews from './components/widgets/ExtraViews';
8
- import {
9
- PrivacyProtection,
10
- addPrivacyProtectionToSchema,
11
- } from '@eeacms/volto-embed';
12
8
 
13
9
  const Edit = (props) => {
14
- const { block, data, onChangeBlock, selected } = props;
10
+ const { block, data, onChangeBlock, selected, id } = props;
15
11
  const schema = React.useMemo(() => Schema(props), [props]);
16
12
 
17
- const { map_data = {}, height } = data;
18
- if (__SERVER__) return '';
19
13
  return (
20
14
  <div>
21
- <PrivacyProtection data={data} {...props}>
22
- <Webmap data={map_data} height={height} />
23
- <ExtraViews data={data} />
24
- </PrivacyProtection>
15
+ <View data={data} id={id} />
25
16
  <SidebarPortal selected={selected}>
26
17
  <BlockDataForm
27
18
  block={block}
@@ -1,4 +1,4 @@
1
- export const Schema = () => {
1
+ export const Schema = (props) => {
2
2
  return {
3
3
  title: 'EEA Map Block',
4
4
  fieldsets: [
@@ -6,10 +6,10 @@ export const Schema = () => {
6
6
  id: 'default',
7
7
  title: 'Default',
8
8
  fields: [
9
+ 'map_data',
10
+ //...(use_visualization ? ['vis_url'] : ['map_data']),
9
11
  'description',
10
12
  'height',
11
- 'map_data',
12
- 'show_sources',
13
13
  'show_legend',
14
14
  'show_download',
15
15
  'show_viewer',
@@ -17,6 +17,16 @@ export const Schema = () => {
17
17
  },
18
18
  ],
19
19
  properties: {
20
+ // use_visualization: {
21
+ // title: 'Use visualization',
22
+ // description:
23
+ // 'This setting will enable importing the map data from a visualization. If is enabled, editing the map manually will not be possible',
24
+ // type: 'boolean',
25
+ // },
26
+ // vis_url: {
27
+ // widget: 'object_by_path',
28
+ // title: 'Visualization',
29
+ // },
20
30
  height: {
21
31
  title: 'Height',
22
32
  type: 'number',
@@ -30,10 +40,6 @@ export const Schema = () => {
30
40
  description: 'Open the map customization interface',
31
41
  widget: 'map_edit_widget',
32
42
  },
33
- show_sources: {
34
- title: 'Show sources',
35
- type: 'boolean',
36
- },
37
43
  show_legend: {
38
44
  title: 'Show legend',
39
45
  type: 'boolean',
@@ -1,19 +1,17 @@
1
1
  import React from 'react';
2
+
2
3
  import Webmap from './components/Webmap';
3
4
  import ExtraViews from './components/widgets/ExtraViews';
4
5
  import { PrivacyProtection } from '@eeacms/volto-embed';
5
6
 
6
7
  const View = (props) => {
7
- const { data } = props || {};
8
-
9
- const { map_data = {} } = data;
10
-
11
- if (__SERVER__) return '';
8
+ const { data, id } = props || {};
9
+ const { map_data = {}, height = '' } = data;
12
10
 
13
11
  return (
14
12
  <div>
15
13
  <PrivacyProtection data={data} {...props}>
16
- <Webmap data={map_data} />
14
+ <Webmap data={map_data} height={height} id={id} />
17
15
  <ExtraViews data={data} />
18
16
  </PrivacyProtection>
19
17
  </div>
@@ -1,5 +1,6 @@
1
1
  /* eslint-disable */
2
2
  import React from 'react';
3
+ import { withDeviceSize } from '@eeacms/volto-eea-map/hocs';
3
4
  import { loadModules } from 'esri-loader';
4
5
 
5
6
  const MODULES = [
@@ -15,11 +16,12 @@ const MODULES = [
15
16
  ];
16
17
 
17
18
  const Webmap = (props) => {
18
- const { editMode, height } = props;
19
+ const { editMode, height, id } = props;
19
20
 
20
21
  const data = React.useMemo(() => props.data || {}, [props.data]);
22
+ const device = React.useMemo(() => props.device || {}, [props.device]);
21
23
 
22
- const { base = {}, layers = {}, id, legend = {}, general = {} } = data;
24
+ const { base = {}, layers = {}, legend = {}, general = {} } = data;
23
25
 
24
26
  const { base_layer = '' } = base;
25
27
 
@@ -68,6 +70,7 @@ const Webmap = (props) => {
68
70
  }
69
71
  }, [setModules, options]);
70
72
 
73
+ // eslint-disable-next-line no-unused-vars
71
74
  const esri = React.useMemo(() => {
72
75
  if (Object.keys(modules).length === 0) return {};
73
76
  const {
@@ -138,9 +141,10 @@ const Webmap = (props) => {
138
141
  });
139
142
  }
140
143
 
141
- if (general?.show_zoom) {
142
- const zoomPosition =
143
- general && general.zoom_position ? general.zoom_position : 'top-right';
144
+ const zoomPosition =
145
+ general && general.zoom_position ? general.zoom_position : '';
146
+
147
+ if (zoomPosition) {
144
148
  const zoomWidget = new Zoom({
145
149
  view: view,
146
150
  });
@@ -156,7 +160,7 @@ const Webmap = (props) => {
156
160
  const legendWidget = new Expand({
157
161
  content: new Legend({
158
162
  view: view,
159
- style: 'classic', // other styles include 'classic'
163
+ style: 'classic',
160
164
  }),
161
165
  view: view,
162
166
  expanded: false,
@@ -167,11 +171,10 @@ const Webmap = (props) => {
167
171
  view.ui.add(legendWidget, legendPosition);
168
172
  }
169
173
 
170
- if (general?.show_print) {
171
- const printPosition =
172
- general && general.print_position
173
- ? general.print_position
174
- : 'top-right';
174
+ const printPosition =
175
+ general && general.print_position ? general.print_position : '';
176
+
177
+ if (printPosition) {
175
178
  const printWidget = new Expand({
176
179
  content: new Print({
177
180
  view: view,
@@ -190,14 +193,18 @@ const Webmap = (props) => {
190
193
  });
191
194
  }
192
195
  return { view, map };
193
- }, [modules, base_layer, map_layers]);
196
+ }, [modules, base_layer, map_layers, general, legend]);
194
197
 
195
- const currentLayerView = esri.view?.layerViews?.items?.[0];
196
198
  return (
197
199
  <div>
198
200
  <div
199
201
  style={{
200
- height: height && !editMode ? `${height}px` : '500px',
202
+ height:
203
+ height && !editMode
204
+ ? `${height}px`
205
+ : device === 'tablet' || device === 'mobile'
206
+ ? '300px'
207
+ : '500px',
201
208
  }}
202
209
  ref={mapRef}
203
210
  className="esri-map"
@@ -206,4 +213,4 @@ const Webmap = (props) => {
206
213
  );
207
214
  };
208
215
 
209
- export default React.memo(Webmap);
216
+ export default withDeviceSize(React.memo(Webmap));
@@ -18,7 +18,7 @@ const ExtraViews = ({ data }) => {
18
18
  } = data;
19
19
 
20
20
  return (
21
- <>
21
+ <div className="extra-eea-map-content">
22
22
  {map_data.layers?.map_layers[0] && (show_download || show_viewer) && (
23
23
  <div
24
24
  style={{ display: 'flex', justifyContent: 'end', margin: '10px 0' }}
@@ -56,7 +56,7 @@ const ExtraViews = ({ data }) => {
56
56
  )}
57
57
  {show_legend && <LegendWidget data={map_data} />}
58
58
  {description && serializeNodes(description)}
59
- </>
59
+ </div>
60
60
  );
61
61
  };
62
62
 
@@ -5,6 +5,7 @@ import { Input, Select, Button, Grid } from 'semantic-ui-react';
5
5
  import checkSVG from '@plone/volto/icons/check.svg';
6
6
  import closeSVG from '@plone/volto/icons/clear.svg';
7
7
  import aheadSVG from '@plone/volto/icons/ahead.svg';
8
+ import resetSVG from '@plone/volto/icons/reset.svg';
8
9
 
9
10
  import { fetchArcgisData } from '../../utils';
10
11
 
@@ -88,6 +89,24 @@ const LayerSelectWidget = (props) => {
88
89
  });
89
90
  };
90
91
 
92
+ const handleChangeServiceUrl = (value) => {
93
+ setServiceUrlError('');
94
+ setCheckColor('');
95
+ setServiceUrl(value);
96
+ setAvailableLayers('');
97
+ setLayerQuery('');
98
+ setSelectedLayer('');
99
+ };
100
+
101
+ const handleReset = () => {
102
+ setServiceUrlError('');
103
+ setServiceUrl(map_service_url);
104
+ setCheckColor('');
105
+ setAvailableLayers(available_layers);
106
+ setLayerQuery(query);
107
+ setSelectedLayer(layer);
108
+ };
109
+
91
110
  return (
92
111
  <div
93
112
  style={{
@@ -95,74 +114,110 @@ const LayerSelectWidget = (props) => {
95
114
  }}
96
115
  >
97
116
  <Grid>
98
- <h4>Service URL</h4>
117
+ <h5 style={{ padding: '0', margin: '15px 0px 5px 0px' }}>
118
+ Service URL
119
+ </h5>
99
120
  <Grid.Row>
100
121
  <Input
101
122
  type="text"
102
- onChange={(e, { value }) => setServiceUrl(value)}
103
- style={{ width: '70%' }}
123
+ onChange={(e, { value }) => handleChangeServiceUrl(value)}
124
+ style={{ width: '100%' }}
125
+ error={serviceUrlError}
104
126
  value={serviceUrl}
105
- action
106
- actionPosition="right"
107
- >
108
- <input />
127
+ // action
128
+ // actionPosition="right"
129
+ ></Input>
130
+
131
+ <span style={{ fontSize: '12px', color: 'darkred' }}>
132
+ {serviceUrlError.error}
133
+ </span>
134
+ </Grid.Row>
135
+ {serviceUrl && (
136
+ <Grid.Row>
137
+ {serviceUrl !== map_service_url && (
138
+ <Button
139
+ size="small"
140
+ compact
141
+ className="layer-reset-button"
142
+ onClick={handleReset}
143
+ >
144
+ <Icon name={resetSVG} title="Reset" size="20px" />
145
+ </Button>
146
+ )}
109
147
  <Button
110
- type="submit"
111
- size="tiny"
112
- compact
148
+ size="small"
113
149
  color={checkColor}
150
+ compact
151
+ className="layer-check-button"
114
152
  onClick={handleServiceUrlCheck}
115
153
  >
116
154
  <Icon
117
155
  name={serviceUrlError ? closeSVG : checkSVG}
118
- title="Check Url"
119
- size="17px"
156
+ title="Submit"
157
+ size="20px"
120
158
  />
121
159
  </Button>
122
- </Input>
123
- </Grid.Row>
124
- <h4>Layer</h4>
125
- <Grid.Row>
126
- <Select
127
- onChange={(e, { value }) => handleSelectLayer(value)}
128
- options={availableLayers}
129
- style={{ width: '100%' }}
130
- placeholder="Select layer"
131
- value={selectedLayer}
132
- />
133
- </Grid.Row>
134
- <h4>Query Layer</h4>
135
- <Grid.Row stretched>
136
- <Input
137
- type="text"
138
- onChange={(e, { value }) => setLayerQuery(value)}
139
- style={{ width: '70%' }}
140
- value={layerQuery}
141
- action
142
- actionPosition="right"
143
- >
144
- <input />
145
- <Button
146
- type="submit"
147
- size="tiny"
148
- compact
149
- color={'green'}
150
- onClick={handleQueryLayer}
151
- >
152
- <Icon name={aheadSVG} title="Check Url" size="17px" />
153
- </Button>
154
- </Input>
155
- </Grid.Row>
156
- <Grid.Row>
157
- <p style={{ fontSize: '12px', fontWeight: 'bold' }}>
158
- Available Fields:
159
- </p>
160
- </Grid.Row>
161
- {fields &&
162
- fields.length > 0 &&
163
- fields.map((field, id) => (
164
- <p style={{ fontSize: '12px' }}>{field.alias}</p>
165
- ))}
160
+ </Grid.Row>
161
+ )}
162
+ {availableLayers && availableLayers.length > 0 && (
163
+ <>
164
+ <h5 style={{ padding: '0', margin: '15px 0px 5px 0px' }}>Layer</h5>
165
+ <Grid.Row>
166
+ <Select
167
+ onChange={(e, { value }) => handleSelectLayer(value)}
168
+ options={availableLayers}
169
+ style={{ width: '100%' }}
170
+ placeholder="Select layer"
171
+ value={selectedLayer}
172
+ />
173
+ </Grid.Row>
174
+ </>
175
+ )}
176
+ {availableLayers && fields && fields.length > 0 && (
177
+ <>
178
+ <h5 style={{ padding: '0', margin: '15px 0px 5px 0px' }}>
179
+ Query Layer
180
+ </h5>
181
+ <Grid.Row stretched>
182
+ <Input
183
+ type="text"
184
+ style={{ width: '100%' }}
185
+ onChange={(e, { value }) => setLayerQuery(value)}
186
+ value={layerQuery}
187
+ ></Input>
188
+ </Grid.Row>
189
+ {layerQuery && (
190
+ <Grid.Row>
191
+ <Button
192
+ type="submit"
193
+ size="tiny"
194
+ compact
195
+ className="layer-submit-button "
196
+ color={'green'}
197
+ onClick={handleQueryLayer}
198
+ >
199
+ <Icon name={aheadSVG} title="Check Url" size="20px" />
200
+ </Button>
201
+ </Grid.Row>
202
+ )}
203
+ <Grid.Row>
204
+ <p
205
+ style={{
206
+ fontSize: '13px',
207
+ fontWeight: 'bold',
208
+ color: 'darkgray',
209
+ }}
210
+ >
211
+ Available Fields:
212
+ </p>
213
+ </Grid.Row>
214
+ {fields.map((field, id) => (
215
+ <p style={{ fontSize: '12px', padding: '0 5px' }}>
216
+ {field.alias}
217
+ </p>
218
+ ))}
219
+ </>
220
+ )}
166
221
  </Grid>
167
222
  </div>
168
223
  );
@@ -50,12 +50,13 @@ const LayerLegend = ({ data, name }) => {
50
50
  };
51
51
 
52
52
  const LegendWidget = (props) => {
53
- const { data = {} } = props;
53
+ const data = React.useMemo(() => props.data, [props.data]);
54
54
  const { layers = {} } = data;
55
55
  const { map_layers = [] } = layers;
56
56
  const [legendLayers, setLegendLayers] = React.useState([]);
57
57
 
58
58
  const activeLayer = map_layers.length > 0 ? map_layers[0]?.map_layer : '';
59
+
59
60
  const fetchLegend = async (url) => {
60
61
  let legendData = await fetchArcgisData(url);
61
62
 
@@ -7,7 +7,10 @@ import PanelsSchema from './panelsSchema';
7
7
 
8
8
  const MapEditorWidget = (props) => {
9
9
  const [open, setOpen] = React.useState(false);
10
- const { onChange = {}, block = {}, value = {}, id } = props;
10
+ const { onChange = {}, id } = props;
11
+ const block = React.useMemo(() => props.block, [props.block]);
12
+ const value = React.useMemo(() => props.value, [props.value]);
13
+
11
14
  const [intValue, setIntValue] = React.useState(value);
12
15
 
13
16
  const dataForm = { map_data: intValue };
@@ -39,7 +42,7 @@ const MapEditorWidget = (props) => {
39
42
  <FormFieldWrapper {...props}>
40
43
  <Modal
41
44
  id="map-editor-modal"
42
- style={{ width: '95% !important' }}
45
+ className="map-editor-modal"
43
46
  onClose={handleClose}
44
47
  onOpen={() => setOpen(true)}
45
48
  open={open}
@@ -50,35 +53,39 @@ const MapEditorWidget = (props) => {
50
53
  }
51
54
  >
52
55
  <Modal.Content scrolling>
53
- <Grid>
54
- <Grid.Row>
55
- <Grid.Column width={4}>
56
- <InlineForm
57
- block={block}
58
- title={schema.title}
59
- schema={schema}
60
- onChangeField={(id, value) => {
61
- handleChangeField(id, value);
62
- }}
63
- formData={dataForm}
64
- />
65
- </Grid.Column>
66
- <Grid.Column width={8}>
56
+ <Grid stackable reversed="mobile vertically tablet vertically">
57
+ <Grid.Column
58
+ mobile={12}
59
+ tablet={12}
60
+ computer={5}
61
+ className="map-editor-column"
62
+ >
63
+ <InlineForm
64
+ block={block}
65
+ //title={schema.title}
66
+ schema={schema}
67
+ onChangeField={(id, value) => {
68
+ handleChangeField(id, value);
69
+ }}
70
+ formData={dataForm}
71
+ />
72
+ </Grid.Column>
73
+ <Grid.Column mobile={12} tablet={12} computer={7}>
74
+ <div className="webmap-container">
67
75
  <Webmap data={intValue} editMode={true} />
68
- </Grid.Column>
69
- </Grid.Row>
76
+ </div>
77
+ </Grid.Column>
70
78
  </Grid>
71
79
  </Modal.Content>
72
80
  <Modal.Actions>
73
81
  <Grid>
74
82
  <Grid.Row>
75
- <Grid.Column width={8}></Grid.Column>
76
- <Grid.Column width={4}>
83
+ <div className="map-edit-actions-container">
77
84
  <Button onClick={handleClose}>Close</Button>
78
85
  <Button color="green" onClick={handleApplyChanges}>
79
86
  Apply changes
80
87
  </Button>
81
- </Grid.Column>
88
+ </div>
82
89
  </Grid.Row>
83
90
  </Grid>
84
91
  </Modal.Actions>
@@ -1,9 +1,10 @@
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 '@eeacms/volto-eea-map/hocs';
4
5
 
5
6
  export const ObjectTypesWidget = (props) => {
6
- const { schemas, value = {}, onChange, errors = {}, id } = props;
7
+ const { schemas, value = {}, onChange, errors = {}, id, device } = props;
7
8
  const objectId = id;
8
9
 
9
10
  const defaultActiveTab = 0;
@@ -11,6 +12,7 @@ export const ObjectTypesWidget = (props) => {
11
12
  const [activeTab, setActiveTab] = React.useState(
12
13
  defaultActiveTab > -1 ? defaultActiveTab : 0,
13
14
  );
15
+
14
16
  const createTab = ({ schema, id, icon }, index) => {
15
17
  return {
16
18
  menuItem: () => (
@@ -42,7 +44,13 @@ export const ObjectTypesWidget = (props) => {
42
44
 
43
45
  return (
44
46
  <Tab
45
- menu={{ fluid: true, vertical: true, tabular: true }}
47
+ menu={{
48
+ vertical:
49
+ device === 'computer' || device === 'tablet' || device === 'mobile'
50
+ ? false
51
+ : true,
52
+ tabular: true,
53
+ }}
46
54
  panes={schemas.map(createTab)}
47
55
  activeIndex={activeTab}
48
56
  grid={{ paneWidth: 9, tabWidth: 3 }}
@@ -50,4 +58,4 @@ export const ObjectTypesWidget = (props) => {
50
58
  );
51
59
  };
52
60
 
53
- export default ObjectTypesWidget;
61
+ export default withDeviceSize(ObjectTypesWidget);
@@ -0,0 +1,94 @@
1
+ import React from 'react';
2
+ import { Modal, Button, Grid } from 'semantic-ui-react';
3
+ import Webmap from '../Webmap';
4
+ import { FormFieldWrapper, InlineForm } from '@plone/volto/components';
5
+ import { VisibilitySensor } from '@eeacms/volto-datablocks/components';
6
+
7
+ import PanelsSchema from './panelsSchema';
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 = (id, fieldVal) => {
29
+ setIntValue(fieldVal);
30
+ };
31
+
32
+ let schema = PanelsSchema({ data: dataForm });
33
+
34
+ return (
35
+ <FormFieldWrapper {...props}>
36
+ <Button
37
+ floated="right"
38
+ size="tiny"
39
+ onClick={(e) => {
40
+ e.preventDefault();
41
+ e.stopPropagation();
42
+ setOpen(true);
43
+ }}
44
+ >
45
+ Open Map Editor
46
+ </Button>
47
+ {open && (
48
+ <Modal
49
+ id="map-editor-modal"
50
+ style={{ width: '95% !important' }}
51
+ open={true}
52
+ >
53
+ <Modal.Content scrolling>
54
+ <Grid>
55
+ <Grid.Row>
56
+ <Grid.Column width={4}>
57
+ <InlineForm
58
+ block={block}
59
+ title={schema.title}
60
+ schema={schema}
61
+ onChangeField={(id, value) => {
62
+ handleChangeField(id, value);
63
+ }}
64
+ formData={dataForm}
65
+ />
66
+ </Grid.Column>
67
+ <Grid.Column width={8}>
68
+ <VisibilitySensor>
69
+ <Webmap data={intValue} editMode={true} />
70
+ </VisibilitySensor>
71
+ </Grid.Column>
72
+ </Grid.Row>
73
+ </Grid>
74
+ </Modal.Content>
75
+ <Modal.Actions>
76
+ <Grid>
77
+ <Grid.Row>
78
+ <Grid.Column width={8}></Grid.Column>
79
+ <Grid.Column width={4}>
80
+ <Button onClick={() => handleClose()}>Close</Button>
81
+ <Button color="green" onClick={() => handleApplyChanges()}>
82
+ Apply changes
83
+ </Button>
84
+ </Grid.Column>
85
+ </Grid.Row>
86
+ </Grid>
87
+ </Modal.Actions>
88
+ </Modal>
89
+ )}
90
+ </FormFieldWrapper>
91
+ );
92
+ };
93
+
94
+ export default VisualizationEditorWidget;
@@ -0,0 +1,16 @@
1
+ import React from 'react';
2
+ import Webmap from '../Webmap';
3
+
4
+ const VisualizationView = (props) => {
5
+ const { content = {} } = props;
6
+
7
+ const { map_visualization_data = {} } = content;
8
+
9
+ return (
10
+ <div>
11
+ <Webmap data={map_visualization_data} />
12
+ </div>
13
+ );
14
+ };
15
+
16
+ export default VisualizationView;
@@ -66,25 +66,20 @@ const GeneralSchema = ({ data = {} }) => {
66
66
  id: 'default',
67
67
  title: 'Zoom',
68
68
  fields: [
69
- 'show_print',
70
69
  'print_position',
71
- 'show_zoom',
72
- 'centerOnExtent',
73
70
  'zoom_position',
71
+ 'centerOnExtent',
74
72
  ...(!centerOnExtent ? ['zoom_level', 'long', 'lat'] : []),
75
73
  ],
76
74
  },
77
75
  ],
78
76
  properties: {
79
- show_zoom: {
80
- title: 'Show zoom',
81
- type: 'boolean',
82
- },
83
77
  centerOnExtent: {
84
78
  title: 'Center on extent',
85
79
  type: 'boolean',
86
80
  description:
87
81
  'This will override latitude/longitude/zoom level and will lock zoom/moving the map.',
82
+ default: true,
88
83
  },
89
84
  zoom_position: {
90
85
  title: 'Zoom position',
@@ -106,10 +101,7 @@ const GeneralSchema = ({ data = {} }) => {
106
101
  title: 'Latitude',
107
102
  type: 'number',
108
103
  },
109
- show_print: {
110
- title: 'Show print',
111
- type: 'boolean',
112
- },
104
+
113
105
  print_position: {
114
106
  title: 'Print position',
115
107
  choices: ['bottom-right', 'bottom-left', 'top-right', 'top-left'].map(
@@ -20,3 +20,47 @@
20
20
  display: flex;
21
21
  padding: 1rem 0;
22
22
  }
23
+
24
+ .map-editor-modal {
25
+ width: '95% !important';
26
+ }
27
+
28
+ .webmap-container {
29
+ position: sticky;
30
+ top: 10px;
31
+ }
32
+
33
+ .map-edit-actions-container {
34
+ padding: 5px 0;
35
+ margin-right: 10px;
36
+ margin-left: auto;
37
+ }
38
+
39
+ .layer-reset-button {
40
+ margin-top: 5px !important;
41
+ animation: fadeDown 0.2s ease-in;
42
+ }
43
+
44
+ .layer-check-button {
45
+ margin-top: 5px !important;
46
+ margin-left: auto !important;
47
+ animation: fadeDown 0.2s ease-in;
48
+ }
49
+
50
+ .layer-submit-button {
51
+ margin-top: 5px !important;
52
+ margin-left: auto !important;
53
+ animation: fadeDown 0.2s ease-in;
54
+ }
55
+
56
+ @keyframes fadeDown {
57
+ from {
58
+ opacity: 0;
59
+ transform: translate3d(0, -20%, 0);
60
+ }
61
+
62
+ to {
63
+ opacity: 1;
64
+ transform: translate3d(0, 0, 0);
65
+ }
66
+ }
@@ -0,0 +1,34 @@
1
+ import React from 'react';
2
+ import { SidebarPortal } from '@plone/volto/components';
3
+ import BlockDataForm from '@plone/volto/components/manage/Form/BlockDataForm';
4
+ import { Schema } from './Schema';
5
+ import View from './View';
6
+ import { addPrivacyProtectionToSchema } from '@eeacms/volto-embed';
7
+ import './styles/map.css';
8
+
9
+ const Edit = (props) => {
10
+ const { block, data, onChangeBlock, selected } = props;
11
+ const schema = React.useMemo(() => Schema(props), [props]);
12
+
13
+ return (
14
+ <div>
15
+ <View data={data} />
16
+ <SidebarPortal selected={selected}>
17
+ <BlockDataForm
18
+ block={block}
19
+ title={schema.title}
20
+ schema={addPrivacyProtectionToSchema(schema)}
21
+ onChangeField={(id, value) => {
22
+ onChangeBlock(block, {
23
+ ...data,
24
+ [id]: value,
25
+ });
26
+ }}
27
+ formData={data}
28
+ />
29
+ </SidebarPortal>
30
+ </div>
31
+ );
32
+ };
33
+
34
+ export default Edit;
@@ -0,0 +1,46 @@
1
+ export const Schema = (props) => {
2
+ return {
3
+ title: 'Embed EEA Map Block',
4
+ fieldsets: [
5
+ {
6
+ id: 'default',
7
+ title: 'Default',
8
+ fields: [
9
+ 'vis_url',
10
+ 'description',
11
+ 'height',
12
+ 'show_legend',
13
+ 'show_download',
14
+ 'show_viewer',
15
+ ],
16
+ },
17
+ ],
18
+ properties: {
19
+ vis_url: {
20
+ widget: 'object_by_path',
21
+ title: 'Visualization',
22
+ },
23
+ height: {
24
+ title: 'Height',
25
+ type: 'number',
26
+ },
27
+ description: {
28
+ title: 'Description',
29
+ widget: 'slate',
30
+ },
31
+ show_legend: {
32
+ title: 'Show legend',
33
+ type: 'boolean',
34
+ },
35
+ show_download: {
36
+ title: 'Show download',
37
+ type: 'boolean',
38
+ },
39
+ show_viewer: {
40
+ title: 'Show web viewer',
41
+ type: 'boolean',
42
+ },
43
+ },
44
+ required: [],
45
+ };
46
+ };
@@ -0,0 +1,48 @@
1
+ import React from 'react';
2
+
3
+ import { connect } from 'react-redux';
4
+ import { compose } from 'redux';
5
+
6
+ import { PrivacyProtection } from '@eeacms/volto-embed';
7
+ import Webmap from '../EEAMap/components/Webmap';
8
+ import ExtraViews from '../EEAMap/components/widgets/ExtraViews';
9
+ import { getVisualization } from '@eeacms/volto-eea-map/actions';
10
+
11
+ const View = (props) => {
12
+ const { data, map_visualization } = props || {};
13
+ const { height = '', vis_url = '' } = data;
14
+
15
+ React.useEffect(() => {
16
+ if (vis_url) {
17
+ props.getVisualization(vis_url);
18
+ }
19
+ // eslint-disable-next-line react-hooks/exhaustive-deps
20
+ }, [vis_url]);
21
+
22
+ return (
23
+ <div>
24
+ <PrivacyProtection data={data} {...props}>
25
+ {map_visualization && (
26
+ <div>
27
+ <Webmap data={map_visualization.data} height={height} />
28
+ <ExtraViews data={{ ...data, map_data: map_visualization.data }} />
29
+ </div>
30
+ )}
31
+ {!map_visualization && (
32
+ <p>No map view to show. Set visualization in block configuration.</p>
33
+ )}
34
+ </PrivacyProtection>
35
+ </div>
36
+ );
37
+ };
38
+
39
+ export default compose(
40
+ connect(
41
+ (state, props) => ({
42
+ map_visualization: state.map_visualizations.data[props.data.vis_url],
43
+ }),
44
+ {
45
+ getVisualization,
46
+ },
47
+ ),
48
+ )(View);
@@ -0,0 +1,22 @@
1
+ .map-edit-container {
2
+ display: flex;
3
+ }
4
+
5
+ .map-modal-trigger-button {
6
+ margin-bottom: 10px !important;
7
+ }
8
+
9
+ #map-editor-modal {
10
+ top: auto;
11
+ left: auto !important;
12
+ width: 95% !important;
13
+ }
14
+
15
+ #map-widget-toggle {
16
+ color: blue !important;
17
+ }
18
+
19
+ .map-text-view {
20
+ display: flex;
21
+ padding: 1rem 0;
22
+ }
@@ -1,4 +1,7 @@
1
1
  import EEAMapView from './Blocks/EEAMap/View';
2
2
  import EEAMapEdit from './Blocks/EEAMap/Edit';
3
3
 
4
- export { EEAMapEdit, EEAMapView };
4
+ import EmbedMapView from './Blocks/EmbedEEAMap/View';
5
+ import EmbedMapEdit from './Blocks/EmbedEEAMap/Edit';
6
+
7
+ export { EEAMapEdit, EEAMapView, EmbedMapView, EmbedMapEdit };
@@ -0,0 +1 @@
1
+ export const GET_MAP_VISUALIZATION = 'GET_MAP_VISUALIZATION';
@@ -0,0 +1,3 @@
1
+ import withDeviceSize from './withDeviceSize';
2
+
3
+ export { withDeviceSize };
@@ -0,0 +1,45 @@
1
+ import React from 'react';
2
+
3
+ export default function withDeviceSize(WrappedComponent) {
4
+ return (props) => {
5
+ const [device, setDevice] = React.useState(null);
6
+
7
+ const updateScreenSize = () => {
8
+ if (__CLIENT__) {
9
+ const screenWidth =
10
+ window.innerWidth ||
11
+ document.documentElement.clientWidth ||
12
+ document.body.clientWidth ||
13
+ 0;
14
+
15
+ setDevice(getDeviceConfig(screenWidth));
16
+ }
17
+ };
18
+
19
+ const getDeviceConfig = (width) => {
20
+ // semantic ui breakpoints
21
+ if (width < 320) {
22
+ return 'mobile';
23
+ } else if (width >= 320 && width < 768) {
24
+ return 'tablet';
25
+ } else if (width >= 768 && width < 992) {
26
+ return 'computer';
27
+ } else if (width >= 992 && width < 1280) {
28
+ return 'large';
29
+ } else if (width >= 1280) {
30
+ return 'widescreen';
31
+ }
32
+ };
33
+
34
+ React.useEffect(() => {
35
+ updateScreenSize();
36
+ window.addEventListener('resize', updateScreenSize);
37
+ return () => {
38
+ window.removeEventListener('resize', updateScreenSize);
39
+ };
40
+ /* eslint-disable-next-line */
41
+ }, []);
42
+
43
+ return <WrappedComponent {...props} device={device} />;
44
+ };
45
+ }
package/src/index.js CHANGED
@@ -1,8 +1,18 @@
1
- import { EEAMapEdit, EEAMapView } from '@eeacms/volto-eea-map/components';
1
+ import {
2
+ EEAMapEdit,
3
+ EEAMapView,
4
+ EmbedMapView,
5
+ EmbedMapEdit,
6
+ } from '@eeacms/volto-eea-map/components';
2
7
  import world from '@plone/volto/icons/world.svg';
3
8
  import LayerSelectWidget from './components/Blocks/EEAMap/components/widgets/LayerSelectWidget';
4
9
  import MapEditorWidget from './components/Blocks/EEAMap/components/widgets/MapEditorWidget';
5
10
  import ObjectTypesWidget from './components/Blocks/EEAMap/components/widgets/ObjectTypesWidget';
11
+ import VisualizationEditorWidget from './components/Blocks/EEAMap/components/widgets/VisualizationEditorWidget';
12
+ import VisualizationView from './components/Blocks/EEAMap/components/widgets/VisualizationView';
13
+
14
+ import { data_visualizations } from './middlewares';
15
+ import * as addonReducers from './reducers';
6
16
 
7
17
  export default (config) => {
8
18
  config.settings.allowed_cors_destinations = [
@@ -48,9 +58,52 @@ export default (config) => {
48
58
  ],
49
59
  };
50
60
 
61
+ config.blocks.blocksConfig.embed_eea_map_block = {
62
+ id: 'embed_eea_map_block', // The name (id) of the block
63
+ title: 'Embed EEA Map', // The display name of the block
64
+ icon: world, // The icon used in the block chooser
65
+ group: 'common', // The group (blocks can be grouped, displayed in the chooser)
66
+ view: EmbedMapView, // The view mode component
67
+ edit: EmbedMapEdit, // The edit mode component
68
+ sidebarTab: 1, // The sidebar tab you want to be selected when selecting the block
69
+ security: {
70
+ addPermission: [], // Future proof (not implemented yet) add user permission role(s)
71
+ view: [], // Future proof (not implemented yet) view user role(s)
72
+ },
73
+ variations: [
74
+ {
75
+ id: 'default',
76
+ title: 'EEA Map (default)',
77
+ isDefault: true,
78
+ view: EEAMapView,
79
+ },
80
+ {
81
+ id: 'extra',
82
+ title: 'Extra variation (expand if needed)',
83
+ isDefault: true,
84
+ view: EEAMapView,
85
+ },
86
+ ],
87
+ };
88
+
51
89
  config.widgets.widget.map_edit_widget = MapEditorWidget;
52
90
  config.widgets.widget.map_layers_widget = LayerSelectWidget;
53
91
  config.widgets.widget.object_types_widget = ObjectTypesWidget;
54
92
 
93
+ //map editor for the visualization(content-type)
94
+ config.widgets.id.map_visualization_data = VisualizationEditorWidget;
95
+ //map viewer for the visualization(content-type)
96
+ config.views.contentTypesViews.map_visualization = VisualizationView;
97
+
98
+ config.settings.storeExtenders = [
99
+ ...(config.settings.storeExtenders || []),
100
+ data_visualizations,
101
+ ];
102
+
103
+ config.addonReducers = {
104
+ ...config.addonReducers,
105
+ ...addonReducers,
106
+ };
107
+
55
108
  return config;
56
109
  };
@@ -0,0 +1,14 @@
1
+ import { GET_MAP_VISUALIZATION } from '@eeacms/volto-eea-map/constants';
2
+
3
+ export const data_visualizations = (middlewares) => [
4
+ (store) => (next) => (action) => {
5
+ if (action.type === GET_MAP_VISUALIZATION) {
6
+ store.dispatch({
7
+ type: `${GET_MAP_VISUALIZATION}_PENDING`,
8
+ path: action.path,
9
+ });
10
+ }
11
+ return next(action);
12
+ },
13
+ ...middlewares,
14
+ ];
@@ -0,0 +1 @@
1
+ export * from './map_visualizations';
@@ -0,0 +1,3 @@
1
+ import map_visualizations from './map_visualizations';
2
+
3
+ export { map_visualizations };
@@ -0,0 +1,48 @@
1
+ import { GET_MAP_VISUALIZATION } from '@eeacms/volto-eea-map/constants';
2
+
3
+ const initialState = {
4
+ data: {},
5
+ error: null,
6
+ loaded: false,
7
+ loading: false,
8
+ };
9
+
10
+ export default function data_providers(state = initialState, action = {}) {
11
+ const path = action.path
12
+ ? action.path.replace(`/@map-visualization`, '')
13
+ : undefined;
14
+
15
+ switch (action.type) {
16
+ case `${GET_MAP_VISUALIZATION}_PENDING`:
17
+ return {
18
+ ...state,
19
+ error: null,
20
+ loaded: false,
21
+ loading: true,
22
+ };
23
+
24
+ case `${GET_MAP_VISUALIZATION}_SUCCESS`:
25
+ return {
26
+ ...state,
27
+ error: null,
28
+ data: {
29
+ ...state.data,
30
+ [path]: action.result.map_visualization,
31
+ },
32
+ loaded: true,
33
+ loading: false,
34
+ };
35
+
36
+ case `${GET_MAP_VISUALIZATION}_FAIL`:
37
+ return {
38
+ ...state,
39
+ error: action.error,
40
+ data: { ...state.data },
41
+ loaded: false,
42
+ loading: false,
43
+ };
44
+
45
+ default:
46
+ return state;
47
+ }
48
+ }