@eeacms/volto-eea-map 4.0.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.
- package/CHANGELOG.md +36 -1
- package/package.json +6 -3
- package/src/Arcgis/Editor/Editor.jsx +130 -0
- package/src/Arcgis/Editor/EditorContext.jsx +2 -0
- package/src/Arcgis/Editor/Fold/Fold.jsx +56 -0
- package/src/Arcgis/Editor/Panels/Panel.jsx +8 -0
- package/src/Arcgis/Editor/Panels/SettingsGeneralPanel.jsx +217 -0
- package/src/Arcgis/Editor/Panels/SettingsLayersPanel.jsx +216 -0
- package/src/Arcgis/Editor/Panels/StructureBaseLayerPanel.jsx +60 -0
- package/src/Arcgis/Editor/Panels/StructureLayersPanel.jsx +394 -0
- package/src/Arcgis/Editor/Panels/StructureWidgetsPanel.jsx +181 -0
- package/src/Arcgis/Editor/Panels/index.js +6 -0
- package/src/Arcgis/Editor/SidebarGroup.jsx +62 -0
- package/src/Arcgis/Layer/Layer.jsx +247 -0
- package/src/Arcgis/Map/Map.jsx +287 -0
- package/src/Arcgis/Map/MapBuilder.jsx +111 -0
- package/src/Arcgis/Map/MapContext.jsx +3 -0
- package/src/Arcgis/Widget/Widget.jsx +170 -0
- package/src/Arcgis/helpers.js +140 -0
- package/src/Blocks/EmbedEEAMap/Edit.jsx +40 -0
- package/src/Blocks/EmbedEEAMap/View.jsx +122 -0
- package/src/Blocks/EmbedEEAMap/helpers.js +12 -0
- package/src/Blocks/EmbedEEAMap/schema.js +126 -0
- package/src/{components → Toolbar}/Share.jsx +1 -1
- package/src/{components/ExtraViews.jsx → Toolbar/Toolbar.jsx} +14 -16
- package/src/{components/visualization → Views}/VisualizationView.jsx +8 -9
- package/src/Widgets/ArcgisColorPickerWidget.jsx +95 -0
- package/src/Widgets/ArcgisRendererWidget/ArcgisRendererWidget.jsx +106 -0
- package/src/Widgets/ArcgisRendererWidget/RendererEditor/ClassBreaks.jsx +8 -0
- package/src/Widgets/ArcgisRendererWidget/RendererEditor/Dictionary.jsx +8 -0
- package/src/Widgets/ArcgisRendererWidget/RendererEditor/DotDensity.jsx +8 -0
- package/src/Widgets/ArcgisRendererWidget/RendererEditor/Heatmap.jsx +8 -0
- package/src/Widgets/ArcgisRendererWidget/RendererEditor/PieChart.jsx +8 -0
- package/src/Widgets/ArcgisRendererWidget/RendererEditor/Simple.jsx +109 -0
- package/src/Widgets/ArcgisRendererWidget/RendererEditor/UniqueValue.jsx +8 -0
- package/src/Widgets/ArcgisRendererWidget/RendererEditor/_Editor.jsx +29 -0
- package/src/Widgets/ArcgisRendererWidget/RendererEditor/_EditorModal.jsx +88 -0
- package/src/Widgets/ArcgisRendererWidget/RendererEditor/_defaults.js +30 -0
- package/src/Widgets/ArcgisSliderWidget.jsx +79 -0
- package/src/Widgets/ArcgisViewpointWidget.jsx +112 -0
- package/src/{components/visualization → Widgets}/VisualizationViewWidget.jsx +9 -10
- package/src/Widgets/VisualizationWidget.jsx +200 -0
- package/src/arcgis.js +48 -0
- package/src/constants.js +225 -7
- package/src/hocs/withArcgis.jsx +27 -0
- package/src/hooks/useChangedProps.jsx +24 -0
- package/src/hooks/useClass.jsx +17 -0
- package/src/hooks/useCopyToClipboard.jsx +25 -0
- package/src/index.js +16 -16
- package/src/jsoneditor.js +72 -0
- package/src/styles/editor.less +446 -0
- package/src/styles/map.less +3 -0
- package/src/components/Blocks/EmbedEEAMap/Edit.jsx +0 -161
- package/src/components/Blocks/EmbedEEAMap/Schema.js +0 -161
- package/src/components/Blocks/EmbedEEAMap/View.jsx +0 -79
- package/src/components/Blocks/EmbedEEAMap/helpers.js +0 -45
- package/src/components/LegendView.jsx +0 -150
- package/src/components/Webmap.jsx +0 -365
- package/src/components/index.js +0 -6
- package/src/components/visualization/VisualizationEditorWidget.jsx +0 -122
- package/src/components/visualization/panelsSchema.js +0 -229
- package/src/components/widgets/DataQueryWidget.jsx +0 -51
- package/src/components/widgets/LayerSelectWidget.jsx +0 -456
- package/src/components/widgets/LayersPanelWidget.jsx +0 -59
- package/src/components/widgets/SimpleColorPickerWidget.jsx +0 -121
- package/src/hocs/index.js +0 -3
- package/src/hocs/withDeviceSize.jsx +0 -45
- package/src/less/global.less +0 -253
- package/src/less/variables.less +0 -5
- package/src/utils.js +0 -151
- /package/src/{components → Toolbar}/FigureNote.jsx +0 -0
- /package/src/{components → Toolbar}/MoreInfoLink.jsx +0 -0
- /package/src/{components → Toolbar}/Sources.jsx +0 -0
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import React, { useMemo } from 'react';
|
|
2
|
+
import { Message } from 'semantic-ui-react';
|
|
3
|
+
|
|
4
|
+
import { SidebarPortal } from '@plone/volto/components';
|
|
5
|
+
import { flattenToAppURL } from '@plone/volto/helpers';
|
|
6
|
+
import BlockDataForm from '@plone/volto/components/manage/Form/BlockDataForm';
|
|
7
|
+
|
|
8
|
+
import { schema } from './schema';
|
|
9
|
+
import View from './View';
|
|
10
|
+
|
|
11
|
+
const Edit = (props) => {
|
|
12
|
+
const { block, onChangeBlock, selected, data } = props;
|
|
13
|
+
|
|
14
|
+
const url = useMemo(() => flattenToAppURL(data.vis_url), [data.vis_url]);
|
|
15
|
+
|
|
16
|
+
return (
|
|
17
|
+
<>
|
|
18
|
+
{!url && (
|
|
19
|
+
<Message>Please select a "Map (simple)" from block editor.</Message>
|
|
20
|
+
)}
|
|
21
|
+
<View {...props} mode="edit" />
|
|
22
|
+
<SidebarPortal selected={selected}>
|
|
23
|
+
<BlockDataForm
|
|
24
|
+
block={block}
|
|
25
|
+
title={schema.title}
|
|
26
|
+
schema={schema}
|
|
27
|
+
onChangeField={(id, value) => {
|
|
28
|
+
onChangeBlock(block, {
|
|
29
|
+
...data,
|
|
30
|
+
[id]: value,
|
|
31
|
+
});
|
|
32
|
+
}}
|
|
33
|
+
formData={data}
|
|
34
|
+
/>
|
|
35
|
+
</SidebarPortal>
|
|
36
|
+
</>
|
|
37
|
+
);
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
export default Edit;
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import React, { useMemo, useEffect } from 'react';
|
|
2
|
+
import { v4 as uuid } from 'uuid';
|
|
3
|
+
import { connect } from 'react-redux';
|
|
4
|
+
import { compose } from 'redux';
|
|
5
|
+
import { flattenToAppURL } from '@plone/volto/helpers';
|
|
6
|
+
import { getContent } from '@plone/volto/actions';
|
|
7
|
+
import { PrivacyProtection } from '@eeacms/volto-embed';
|
|
8
|
+
import { getLayers } from '@eeacms/volto-eea-map/Arcgis/helpers';
|
|
9
|
+
import MapBuilder from '@eeacms/volto-eea-map/Arcgis/Map/MapBuilder';
|
|
10
|
+
import Toolbar from '@eeacms/volto-eea-map/Toolbar/Toolbar';
|
|
11
|
+
|
|
12
|
+
import { getMapData } from './helpers';
|
|
13
|
+
|
|
14
|
+
const View = (props) => {
|
|
15
|
+
const { id, mode, data, getContent, content } = props;
|
|
16
|
+
const {
|
|
17
|
+
vis_url,
|
|
18
|
+
data_query_params,
|
|
19
|
+
enable_queries,
|
|
20
|
+
show_note = true,
|
|
21
|
+
show_more_info = true,
|
|
22
|
+
show_share = true,
|
|
23
|
+
dataprotection = { enabled: true },
|
|
24
|
+
height = '',
|
|
25
|
+
} = data;
|
|
26
|
+
|
|
27
|
+
const url = useMemo(() => flattenToAppURL(vis_url), [vis_url]);
|
|
28
|
+
|
|
29
|
+
const mapData = useMemo(() => getMapData({ content, data }), [content, data]);
|
|
30
|
+
|
|
31
|
+
const mapServiceURL = useMemo(() => {
|
|
32
|
+
const url = getLayers(mapData)?.[0]?.url;
|
|
33
|
+
|
|
34
|
+
if (url) {
|
|
35
|
+
return `${url}?f=jsapi`;
|
|
36
|
+
}
|
|
37
|
+
return '';
|
|
38
|
+
}, [mapData]);
|
|
39
|
+
|
|
40
|
+
const definitionExpression = useMemo(
|
|
41
|
+
() =>
|
|
42
|
+
enable_queries
|
|
43
|
+
? {
|
|
44
|
+
id: uuid(),
|
|
45
|
+
combinator: 'and',
|
|
46
|
+
not: false,
|
|
47
|
+
rules: data_query_params
|
|
48
|
+
.map((query) => {
|
|
49
|
+
if (!query.alias || !query.i) {
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
return {
|
|
53
|
+
id: uuid(),
|
|
54
|
+
dataQuery: [query.i],
|
|
55
|
+
field: query.alias,
|
|
56
|
+
operator: '=',
|
|
57
|
+
value: '',
|
|
58
|
+
valueSource: 'value',
|
|
59
|
+
};
|
|
60
|
+
})
|
|
61
|
+
.filter((query) => {
|
|
62
|
+
return query?.field;
|
|
63
|
+
}),
|
|
64
|
+
}
|
|
65
|
+
: null,
|
|
66
|
+
[data_query_params, enable_queries],
|
|
67
|
+
);
|
|
68
|
+
|
|
69
|
+
useEffect(() => {
|
|
70
|
+
if (mode !== 'edit') return;
|
|
71
|
+
const mapPath = flattenToAppURL(mapData['@id'] || '');
|
|
72
|
+
if (!mapData?.error && url && url !== mapPath) {
|
|
73
|
+
getContent(url, null, id);
|
|
74
|
+
}
|
|
75
|
+
}, [id, mode, url, mapData, getContent]);
|
|
76
|
+
|
|
77
|
+
if (!mapData || !url) {
|
|
78
|
+
return null;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if (mapData?.error) {
|
|
82
|
+
return <p dangerouslySetInnerHTML={{ __html: mapData.error }} />;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
return (
|
|
86
|
+
<PrivacyProtection
|
|
87
|
+
{...props}
|
|
88
|
+
data={mapServiceURL ? { ...data, url: mapServiceURL } : data}
|
|
89
|
+
>
|
|
90
|
+
<div className="embed-map-visualization">
|
|
91
|
+
<MapBuilder
|
|
92
|
+
data={mapData}
|
|
93
|
+
properties={{ ...(props.properties || {}), definitionExpression }}
|
|
94
|
+
height={height}
|
|
95
|
+
/>
|
|
96
|
+
<Toolbar
|
|
97
|
+
style={{ marginTop: '1rem' }}
|
|
98
|
+
data={{
|
|
99
|
+
...data,
|
|
100
|
+
show_note,
|
|
101
|
+
show_sources: true,
|
|
102
|
+
show_more_info,
|
|
103
|
+
show_share,
|
|
104
|
+
dataprotection,
|
|
105
|
+
mapData,
|
|
106
|
+
}}
|
|
107
|
+
/>
|
|
108
|
+
</div>
|
|
109
|
+
</PrivacyProtection>
|
|
110
|
+
);
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
export default compose(
|
|
114
|
+
connect(
|
|
115
|
+
(state, props) => {
|
|
116
|
+
return {
|
|
117
|
+
content: state.content.subrequests?.[props.id]?.data,
|
|
118
|
+
};
|
|
119
|
+
},
|
|
120
|
+
{ getContent },
|
|
121
|
+
),
|
|
122
|
+
)(View);
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { pickMetadata } from '@eeacms/volto-embed/helpers';
|
|
2
|
+
|
|
3
|
+
function getMapData({ content = {}, data }) {
|
|
4
|
+
const map_visualization_data =
|
|
5
|
+
content?.map_visualization_data || data?.map_visualization_data || {};
|
|
6
|
+
return {
|
|
7
|
+
...pickMetadata(content),
|
|
8
|
+
...map_visualization_data,
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export { getMapData };
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
const protectionSchema = {
|
|
2
|
+
title: 'Data Protection',
|
|
3
|
+
|
|
4
|
+
fieldsets: [
|
|
5
|
+
{
|
|
6
|
+
id: 'default',
|
|
7
|
+
title: 'Default',
|
|
8
|
+
fields: [
|
|
9
|
+
'privacy_statement',
|
|
10
|
+
'privacy_cookie_key',
|
|
11
|
+
'enabled',
|
|
12
|
+
'background_image',
|
|
13
|
+
],
|
|
14
|
+
},
|
|
15
|
+
],
|
|
16
|
+
|
|
17
|
+
properties: {
|
|
18
|
+
privacy_statement: {
|
|
19
|
+
title: 'Privacy statement',
|
|
20
|
+
description: 'Defined in template. Change only if necessary',
|
|
21
|
+
widget: 'slate_richtext',
|
|
22
|
+
className: 'slate-Widget',
|
|
23
|
+
defaultValue: [
|
|
24
|
+
{
|
|
25
|
+
children: [
|
|
26
|
+
{
|
|
27
|
+
text: 'This map is hosted by a third party, Environmental Systems Research Institute. By showing the external content you accept the terms and conditions of ',
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
type: 'a',
|
|
31
|
+
url: 'https://www.esri.com',
|
|
32
|
+
children: [
|
|
33
|
+
{
|
|
34
|
+
text: 'esri.com',
|
|
35
|
+
},
|
|
36
|
+
],
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
text: '. This includes their cookie policies, which we have no control over.',
|
|
40
|
+
},
|
|
41
|
+
],
|
|
42
|
+
},
|
|
43
|
+
],
|
|
44
|
+
},
|
|
45
|
+
privacy_cookie_key: {
|
|
46
|
+
title: 'Privacy cookie key',
|
|
47
|
+
description: 'Use default for Esri maps, otherwise change',
|
|
48
|
+
defaultValue: 'esri-maps',
|
|
49
|
+
},
|
|
50
|
+
enabled: {
|
|
51
|
+
title: 'Data protection disclaimer enabled',
|
|
52
|
+
description: 'Enable/disable the privacy protection',
|
|
53
|
+
type: 'boolean',
|
|
54
|
+
},
|
|
55
|
+
background_image: {
|
|
56
|
+
title: 'Static map preview image',
|
|
57
|
+
widget: 'file',
|
|
58
|
+
required: true,
|
|
59
|
+
},
|
|
60
|
+
},
|
|
61
|
+
|
|
62
|
+
required: ['background_image'],
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
export const schema = {
|
|
66
|
+
title: 'Embed Map layers (ArcGis)',
|
|
67
|
+
fieldsets: [
|
|
68
|
+
{
|
|
69
|
+
id: 'default',
|
|
70
|
+
title: 'Default',
|
|
71
|
+
fields: ['vis_url', 'description', 'height'],
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
id: 'toolbar',
|
|
75
|
+
title: 'Toolbar',
|
|
76
|
+
fields: ['show_note', 'show_more_info', 'show_share'],
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
fields: ['dataprotection'],
|
|
80
|
+
title: 'Data Protection',
|
|
81
|
+
},
|
|
82
|
+
],
|
|
83
|
+
properties: {
|
|
84
|
+
vis_url: {
|
|
85
|
+
widget: 'internal_url',
|
|
86
|
+
title: 'Visualization',
|
|
87
|
+
},
|
|
88
|
+
height: {
|
|
89
|
+
title: 'Height',
|
|
90
|
+
description:
|
|
91
|
+
'Map block height in px. Default is 500px. Change only if necessary',
|
|
92
|
+
type: 'number',
|
|
93
|
+
},
|
|
94
|
+
description: {
|
|
95
|
+
title: 'Description',
|
|
96
|
+
widget: 'slate',
|
|
97
|
+
},
|
|
98
|
+
show_note: {
|
|
99
|
+
title: 'Show note',
|
|
100
|
+
type: 'boolean',
|
|
101
|
+
defaultValue: true,
|
|
102
|
+
},
|
|
103
|
+
show_sources: {
|
|
104
|
+
title: 'Show sources',
|
|
105
|
+
description: 'Will show sources set in this page Data provenance',
|
|
106
|
+
type: 'boolean',
|
|
107
|
+
defaultValue: true,
|
|
108
|
+
},
|
|
109
|
+
show_more_info: {
|
|
110
|
+
title: 'Show more info',
|
|
111
|
+
type: 'boolean',
|
|
112
|
+
defaultValue: true,
|
|
113
|
+
},
|
|
114
|
+
show_share: {
|
|
115
|
+
title: 'Show share button',
|
|
116
|
+
type: 'boolean',
|
|
117
|
+
defaultValue: true,
|
|
118
|
+
},
|
|
119
|
+
dataprotection: {
|
|
120
|
+
widget: 'object',
|
|
121
|
+
schema: protectionSchema,
|
|
122
|
+
default: { enabled: true },
|
|
123
|
+
},
|
|
124
|
+
},
|
|
125
|
+
required: [],
|
|
126
|
+
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { Popup, Input, Button } from 'semantic-ui-react';
|
|
3
|
-
import
|
|
3
|
+
import useCopyToClipboard from '@eeacms/volto-eea-map/hooks/useCopyToClipboard';
|
|
4
4
|
import cx from 'classnames';
|
|
5
5
|
|
|
6
6
|
const Share = ({ contentTypeLink = '' }) => {
|
|
@@ -8,29 +8,26 @@ import {
|
|
|
8
8
|
MoreInfo,
|
|
9
9
|
Share,
|
|
10
10
|
} from '@eeacms/volto-embed/Toolbar';
|
|
11
|
-
import LegendView from '@eeacms/volto-eea-map/components/LegendView';
|
|
12
11
|
|
|
13
12
|
import '@eeacms/volto-embed/Toolbar/styles.less';
|
|
14
13
|
|
|
15
|
-
const
|
|
16
|
-
const
|
|
14
|
+
const Toolbar = ({ data, screen, style }) => {
|
|
15
|
+
const el = useRef();
|
|
17
16
|
const [mobile, setMobile] = useState(false);
|
|
18
17
|
const {
|
|
19
|
-
|
|
18
|
+
mapData = {},
|
|
20
19
|
description,
|
|
21
|
-
show_legend,
|
|
22
|
-
show_viewer,
|
|
23
20
|
show_note = true,
|
|
24
21
|
show_sources = true,
|
|
25
22
|
show_more_info = true,
|
|
26
23
|
show_share = true,
|
|
27
24
|
} = data;
|
|
28
25
|
|
|
29
|
-
const { data_provenance = {}, figure_note = [] } =
|
|
26
|
+
const { data_provenance = {}, figure_note = [] } = mapData;
|
|
30
27
|
|
|
31
28
|
useEffect(() => {
|
|
32
|
-
if (
|
|
33
|
-
const toolbarParentWidth =
|
|
29
|
+
if (el.current) {
|
|
30
|
+
const toolbarParentWidth = el.current.parentElement.offsetWidth;
|
|
34
31
|
|
|
35
32
|
if (toolbarParentWidth < 600 && !mobile) {
|
|
36
33
|
setMobile(true);
|
|
@@ -42,17 +39,18 @@ const ExtraViews = ({ data, screen }) => {
|
|
|
42
39
|
|
|
43
40
|
return (
|
|
44
41
|
<>
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
42
|
+
<div
|
|
43
|
+
className={cx('visualization-toolbar', { mobile })}
|
|
44
|
+
style={style}
|
|
45
|
+
ref={el}
|
|
46
|
+
>
|
|
49
47
|
<div className="left-col">
|
|
50
48
|
{show_note && <FigureNote notes={figure_note || []} />}
|
|
51
49
|
{show_sources && <Sources sources={data_provenance?.data} />}
|
|
52
|
-
{show_more_info && <MoreInfo href={
|
|
50
|
+
{show_more_info && <MoreInfo href={mapData['@id']} />}
|
|
53
51
|
</div>
|
|
54
52
|
<div className="right-col">
|
|
55
|
-
{show_share && <Share href={
|
|
53
|
+
{show_share && <Share href={mapData['@id']} />}
|
|
56
54
|
</div>
|
|
57
55
|
</div>
|
|
58
56
|
{description && serializeNodes(description)}
|
|
@@ -62,4 +60,4 @@ const ExtraViews = ({ data, screen }) => {
|
|
|
62
60
|
|
|
63
61
|
export default connect((state) => ({
|
|
64
62
|
screen: state.screen,
|
|
65
|
-
}))(
|
|
63
|
+
}))(Toolbar);
|
|
@@ -2,13 +2,13 @@ import React from 'react';
|
|
|
2
2
|
import { hasBlocksData } from '@plone/volto/helpers';
|
|
3
3
|
import RenderBlocks from '@plone/volto/components/theme/View/RenderBlocks';
|
|
4
4
|
import { pickMetadata } from '@eeacms/volto-embed/helpers';
|
|
5
|
-
import
|
|
6
|
-
import
|
|
5
|
+
import MapBuilder from '@eeacms/volto-eea-map/Arcgis/Map/MapBuilder';
|
|
6
|
+
import Toolbar from '../Toolbar/Toolbar';
|
|
7
7
|
|
|
8
8
|
const VisualizationView = (props) => {
|
|
9
9
|
const content = props && props.content ? props.content : {};
|
|
10
10
|
|
|
11
|
-
const
|
|
11
|
+
const mapData =
|
|
12
12
|
content && content.map_visualization_data
|
|
13
13
|
? content.map_visualization_data
|
|
14
14
|
: {};
|
|
@@ -19,17 +19,16 @@ const VisualizationView = (props) => {
|
|
|
19
19
|
<RenderBlocks {...props} />
|
|
20
20
|
) : (
|
|
21
21
|
<>
|
|
22
|
-
<
|
|
23
|
-
<
|
|
22
|
+
<MapBuilder data={mapData} />
|
|
23
|
+
<Toolbar
|
|
24
|
+
style={{ marginTop: '1rem' }}
|
|
24
25
|
data={{
|
|
25
|
-
show_viewer: true,
|
|
26
|
-
show_legend: true,
|
|
27
26
|
show_note: false,
|
|
28
27
|
show_sources: false,
|
|
29
28
|
show_more_info: false,
|
|
30
29
|
show_share: true,
|
|
31
|
-
|
|
32
|
-
...
|
|
30
|
+
mapData: {
|
|
31
|
+
...mapData,
|
|
33
32
|
...pickMetadata(content),
|
|
34
33
|
},
|
|
35
34
|
}}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { useEffect, useState, useRef } from 'react';
|
|
2
|
+
import { FormFieldWrapper, Icon } from '@plone/volto/components';
|
|
3
|
+
import { Button } from 'semantic-ui-react';
|
|
4
|
+
import loadable from '@loadable/component';
|
|
5
|
+
import clearSVG from '@plone/volto/icons/clear.svg';
|
|
6
|
+
|
|
7
|
+
const ReactColor = loadable.lib(() => import('react-color'));
|
|
8
|
+
|
|
9
|
+
function colorToRGBA(color) {
|
|
10
|
+
const r = color.r;
|
|
11
|
+
const g = color.g;
|
|
12
|
+
const b = color.b;
|
|
13
|
+
const a = color.a;
|
|
14
|
+
return `rgba(${r}, ${g}, ${b}, ${a})`;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export default function ArcgisColorPickerWidget(props) {
|
|
18
|
+
const el = useRef(null);
|
|
19
|
+
const colorPickerEl = useRef(null);
|
|
20
|
+
const { $map, id, value, onChange, available_colors } = props;
|
|
21
|
+
const [showColorPicker, setShowColorPicker] = useState(false);
|
|
22
|
+
|
|
23
|
+
const color = new $map.current.modules.AgColor(value);
|
|
24
|
+
|
|
25
|
+
function onClickOutside(e) {
|
|
26
|
+
if (el.current && !el.current.contains(e.target)) {
|
|
27
|
+
setShowColorPicker(false);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
useEffect(() => {
|
|
32
|
+
window.addEventListener('click', onClickOutside);
|
|
33
|
+
|
|
34
|
+
return () => {
|
|
35
|
+
window.removeEventListener('click', onClickOutside);
|
|
36
|
+
};
|
|
37
|
+
}, []);
|
|
38
|
+
|
|
39
|
+
return (
|
|
40
|
+
<FormFieldWrapper {...props}>
|
|
41
|
+
<div ref={el} style={{ display: 'flex', alignItems: 'center' }}>
|
|
42
|
+
<Button
|
|
43
|
+
style={{
|
|
44
|
+
margin: 0,
|
|
45
|
+
backgroundColor: colorToRGBA(color),
|
|
46
|
+
}}
|
|
47
|
+
onClick={() =>
|
|
48
|
+
setShowColorPicker((showColorPicker) => !showColorPicker)
|
|
49
|
+
}
|
|
50
|
+
size="small"
|
|
51
|
+
fluid
|
|
52
|
+
title="Show color picker"
|
|
53
|
+
/>
|
|
54
|
+
<Button
|
|
55
|
+
compact
|
|
56
|
+
style={{ margin: 0, padding: '8px' }}
|
|
57
|
+
onClick={() => onChange(id, null)}
|
|
58
|
+
>
|
|
59
|
+
<Icon name={clearSVG} size="18px" color="red" style={{ margin: 0 }} />
|
|
60
|
+
</Button>
|
|
61
|
+
{showColorPicker && (
|
|
62
|
+
<div
|
|
63
|
+
ref={colorPickerEl}
|
|
64
|
+
style={{
|
|
65
|
+
position: 'absolute',
|
|
66
|
+
bottom: '100%',
|
|
67
|
+
left: '50%',
|
|
68
|
+
transform: 'translateX(-50%)',
|
|
69
|
+
}}
|
|
70
|
+
>
|
|
71
|
+
<ReactColor>
|
|
72
|
+
{({ SketchPicker }) => {
|
|
73
|
+
return (
|
|
74
|
+
<SketchPicker
|
|
75
|
+
width="180px"
|
|
76
|
+
style={{
|
|
77
|
+
borderBottomLeftRadius: 0,
|
|
78
|
+
borderBottomRightRadius: 0,
|
|
79
|
+
}}
|
|
80
|
+
colors={available_colors}
|
|
81
|
+
color={color}
|
|
82
|
+
onChangeComplete={(color) => {
|
|
83
|
+
const { r, g, b, a } = color.rgb;
|
|
84
|
+
onChange(id, [r, g, b, a]);
|
|
85
|
+
}}
|
|
86
|
+
/>
|
|
87
|
+
);
|
|
88
|
+
}}
|
|
89
|
+
</ReactColor>
|
|
90
|
+
</div>
|
|
91
|
+
)}
|
|
92
|
+
</div>
|
|
93
|
+
</FormFieldWrapper>
|
|
94
|
+
);
|
|
95
|
+
}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { useState } from 'react';
|
|
2
|
+
import { compose } from 'redux';
|
|
3
|
+
import { injectIntl } from 'react-intl';
|
|
4
|
+
import { FormFieldWrapper, Icon } from '@plone/volto/components';
|
|
5
|
+
import { injectLazyLibs } from '@plone/volto/helpers/Loadable/Loadable';
|
|
6
|
+
import {
|
|
7
|
+
customSelectStyles,
|
|
8
|
+
DropdownIndicator,
|
|
9
|
+
ClearIndicator,
|
|
10
|
+
Option,
|
|
11
|
+
selectTheme,
|
|
12
|
+
MultiValueContainer,
|
|
13
|
+
} from '@plone/volto/components/manage/Widgets/SelectStyling';
|
|
14
|
+
import { normalizeValue } from '@plone/volto/components/manage/Widgets/SelectUtils';
|
|
15
|
+
import {
|
|
16
|
+
rendererTypes,
|
|
17
|
+
renderersMapping,
|
|
18
|
+
} from '@eeacms/volto-eea-map/constants';
|
|
19
|
+
import RendererEditor from './RendererEditor/_Editor';
|
|
20
|
+
import RendererEditorModal from './RendererEditor/_EditorModal';
|
|
21
|
+
import { simpleFillSymbol } from './RendererEditor/_defaults';
|
|
22
|
+
|
|
23
|
+
import editSVG from '@plone/volto/icons/editing.svg';
|
|
24
|
+
|
|
25
|
+
function ArcgisRendererWidget(props) {
|
|
26
|
+
const [open, setOpen] = useState(false);
|
|
27
|
+
const { value, id, intl, onChange } = props;
|
|
28
|
+
const $type = renderersMapping[value?.type] || value?.type;
|
|
29
|
+
const type = normalizeValue(rendererTypes, $type, intl);
|
|
30
|
+
|
|
31
|
+
const Select = props.reactSelect.default;
|
|
32
|
+
|
|
33
|
+
return (
|
|
34
|
+
<>
|
|
35
|
+
<FormFieldWrapper
|
|
36
|
+
{...props}
|
|
37
|
+
title={
|
|
38
|
+
<button
|
|
39
|
+
className="btn-primary"
|
|
40
|
+
style={{ fontSize: 'var(--font-size-small)' }}
|
|
41
|
+
onClick={() => {
|
|
42
|
+
setOpen(true);
|
|
43
|
+
}}
|
|
44
|
+
>
|
|
45
|
+
<Icon name={editSVG} size="20px" />
|
|
46
|
+
Renderer
|
|
47
|
+
</button>
|
|
48
|
+
}
|
|
49
|
+
>
|
|
50
|
+
<Select
|
|
51
|
+
id={`field-${id}`}
|
|
52
|
+
name={id}
|
|
53
|
+
menuShouldScrollIntoView={false}
|
|
54
|
+
isDisabled={false}
|
|
55
|
+
isSearchable={true}
|
|
56
|
+
className="react-select-container"
|
|
57
|
+
classNamePrefix="react-select"
|
|
58
|
+
isMulti={false}
|
|
59
|
+
options={rendererTypes}
|
|
60
|
+
styles={customSelectStyles}
|
|
61
|
+
theme={selectTheme}
|
|
62
|
+
components={{
|
|
63
|
+
MultiValueContainer,
|
|
64
|
+
DropdownIndicator,
|
|
65
|
+
ClearIndicator,
|
|
66
|
+
Option: props.customOptionStyling || Option,
|
|
67
|
+
}}
|
|
68
|
+
value={type}
|
|
69
|
+
placeholder="Select a renderer type..."
|
|
70
|
+
onChange={(selectedOption) => {
|
|
71
|
+
return onChange(id, {
|
|
72
|
+
autocast: true,
|
|
73
|
+
type:
|
|
74
|
+
selectedOption && selectedOption.value !== 'no-value'
|
|
75
|
+
? selectedOption.value
|
|
76
|
+
: undefined,
|
|
77
|
+
...(selectedOption.value === 'simple'
|
|
78
|
+
? { symbol: simpleFillSymbol }
|
|
79
|
+
: {}),
|
|
80
|
+
});
|
|
81
|
+
}}
|
|
82
|
+
/>
|
|
83
|
+
</FormFieldWrapper>
|
|
84
|
+
<div className="arcgis-renderer-editor">
|
|
85
|
+
<RendererEditor {...props} type={$type} />
|
|
86
|
+
{open && (
|
|
87
|
+
<RendererEditorModal
|
|
88
|
+
value={value}
|
|
89
|
+
onChange={(newValue) => {
|
|
90
|
+
onChange(id, newValue);
|
|
91
|
+
}}
|
|
92
|
+
onClose={() => {
|
|
93
|
+
setOpen(false);
|
|
94
|
+
}}
|
|
95
|
+
/>
|
|
96
|
+
)}
|
|
97
|
+
</div>
|
|
98
|
+
</>
|
|
99
|
+
);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export const ArcgisRendererWidgetComponent = injectIntl(ArcgisRendererWidget);
|
|
103
|
+
|
|
104
|
+
export default compose(injectLazyLibs(['reactSelect']))(
|
|
105
|
+
ArcgisRendererWidgetComponent,
|
|
106
|
+
);
|