diff --git a/package-lock.json b/package-lock.json
index 1d373d8be..b5308787c 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -28,6 +28,7 @@
"ibantools": "^3.3.0",
"immer": "^9.0.6",
"leaflet": "^1.9.4",
+ "leaflet-draw": "^1.0.4",
"leaflet-geosearch": "^3.8.0",
"leaflet-gesture-handling": "^1.2.2",
"microscope-sass": "^2.0.0",
@@ -36,6 +37,7 @@
"react-formio": "^4.3.0",
"react-intl": "^6.4.4",
"react-leaflet": "4.2.1",
+ "react-leaflet-draw": "^0.20.4",
"react-modal": "3.16.1",
"react-number-format": "5.2.2",
"react-router-dom": "^6.11.2",
@@ -19567,6 +19569,12 @@
"resolved": "https://registry.npmjs.org/leaflet/-/leaflet-1.9.4.tgz",
"integrity": "sha512-nxS1ynzJOmOlHp+iL3FyWqK89GtNL8U8rvlMOsQdTTssxZwCXh8N2NB3GDQOL+YR3XnWyZAxwQixURb+FA74PA=="
},
+ "node_modules/leaflet-draw": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/leaflet-draw/-/leaflet-draw-1.0.4.tgz",
+ "integrity": "sha512-rsQ6saQO5ST5Aj6XRFylr5zvarWgzWnrg46zQ1MEOEIHsppdC/8hnN8qMoFvACsPvTioAuysya/TVtog15tyAQ==",
+ "license": "MIT"
+ },
"node_modules/leaflet-geosearch": {
"version": "3.11.1",
"resolved": "https://registry.npmjs.org/leaflet-geosearch/-/leaflet-geosearch-3.11.1.tgz",
@@ -23377,6 +23385,23 @@
"react-dom": "^18.0.0"
}
},
+ "node_modules/react-leaflet-draw": {
+ "version": "0.20.4",
+ "resolved": "https://registry.npmjs.org/react-leaflet-draw/-/react-leaflet-draw-0.20.4.tgz",
+ "integrity": "sha512-u5JHdow2Z9G2AveyUEOTWHXhdhzXdEVQifkNfSaVbEn0gvD+2xW03TQN444zVqovDBvIrBcVWo1VajL4zgl6yg==",
+ "license": "ISC",
+ "dependencies": {
+ "fast-deep-equal": "^3.1.3",
+ "lodash-es": "^4.17.15"
+ },
+ "peerDependencies": {
+ "leaflet": "^1.8.0",
+ "leaflet-draw": "^1.0.4",
+ "prop-types": "^15.5.2",
+ "react": "^18.0.0",
+ "react-leaflet": "^4.0.0"
+ }
+ },
"node_modules/react-lifecycles-compat": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz",
diff --git a/package.json b/package.json
index cdba8c6f5..28969b34d 100644
--- a/package.json
+++ b/package.json
@@ -43,6 +43,7 @@
"ibantools": "^3.3.0",
"immer": "^9.0.6",
"leaflet": "^1.9.4",
+ "leaflet-draw": "^1.0.4",
"leaflet-geosearch": "^3.8.0",
"leaflet-gesture-handling": "^1.2.2",
"microscope-sass": "^2.0.0",
@@ -51,6 +52,7 @@
"react-formio": "^4.3.0",
"react-intl": "^6.4.4",
"react-leaflet": "4.2.1",
+ "react-leaflet-draw": "^0.20.4",
"react-modal": "3.16.1",
"react-number-format": "5.2.2",
"react-router-dom": "^6.11.2",
diff --git a/src/components/FormStepSummary/ComponentValueDisplay.jsx b/src/components/FormStepSummary/ComponentValueDisplay.jsx
index 2b491424c..8cddb82b4 100644
--- a/src/components/FormStepSummary/ComponentValueDisplay.jsx
+++ b/src/components/FormStepSummary/ComponentValueDisplay.jsx
@@ -189,7 +189,7 @@ const MapDisplay = ({component, value}) => {
return ;
}
- return ;
+ return ;
};
const CoSignDisplay = ({value}) => {
diff --git a/src/components/Map/Map.stories.jsx b/src/components/Map/Map.stories.jsx
index 76b75272d..b9d9f8029 100644
--- a/src/components/Map/Map.stories.jsx
+++ b/src/components/Map/Map.stories.jsx
@@ -1,4 +1,5 @@
-import {userEvent, within} from '@storybook/test';
+import {expect, fn, userEvent, waitFor, within} from '@storybook/test';
+import {useState} from 'react';
import {ConfigDecorator} from 'story-utils/decorators';
@@ -11,12 +12,33 @@ const withMapLayout = Story => (
);
+const StorybookLeafletMap = props => {
+ const [geoJson, setGeoJson] = useState(props?.geoJsonFeature);
+ const handleGeoJsonChange = args => {
+ if (props?.onGeoJsonFeatureSet) {
+ props?.onGeoJsonFeatureSet(args);
+ }
+ setGeoJson(args);
+ };
+ return (
+
+ );
+};
+
export default {
title: 'Private API / Map',
component: LeafletMap,
decorators: [withMapLayout, ConfigDecorator],
+ render: StorybookLeafletMap,
args: {
- markerCoordinates: [52.1326332, 5.291266],
+ geoJsonFeature: {
+ type: 'Feature',
+ properties: {},
+ geometry: {
+ type: 'Point',
+ coordinates: [5.291266, 52.1326332],
+ },
+ },
defaultCenter: [52.1326332, 5.291266],
defaultZoomLevel: 12,
disabled: false,
@@ -31,10 +53,17 @@ export default {
export const Map = {};
export const MapWithAddressSearch = {
- play: async ({canvasElement}) => {
+ args: {
+ onGeoJsonFeatureSet: fn(),
+ },
+ play: async ({canvasElement, args}) => {
const canvas = within(canvasElement);
- const button = await canvas.findByLabelText('Zoeken');
- await userEvent.click(button);
+
+ await waitFor(async () => {
+ const button = await canvas.findByLabelText('Zoeken');
+ await userEvent.click(button);
+ expect(await canvas.findByPlaceholderText('Zoek adres')).toBeVisible();
+ });
const searchField = await canvas.findByPlaceholderText('Zoek adres');
const searchBox = within(searchField.parentNode);
@@ -42,6 +71,18 @@ export const MapWithAddressSearch = {
const searchResult = await searchBox.findByText('Utrecht, Utrecht, Utrecht');
await userEvent.click(searchResult);
+ await waitFor(async () => {
+ // A marker is placed on the search result
+ expect(args.onGeoJsonFeatureSet).toBeCalledWith({
+ type: 'Feature',
+ properties: {},
+ geometry: {
+ type: 'Point',
+ // To make sure that this test doesn't magically fail, just expect any 2 values
+ coordinates: [expect.anything(), expect.anything()],
+ },
+ });
+ });
},
};
@@ -59,3 +100,49 @@ export const MapWithAerialPhotoBackground = {
'https://service.pdok.nl/hwh/luchtfotorgb/wmts/v1_0/Actueel_orthoHR/EPSG:28992/{z}/{x}/{y}.png',
},
};
+
+export const MapWithInteractions = {
+ args: {
+ interactions: {
+ polygon: true,
+ polyline: true,
+ marker: true,
+ },
+ onGeoJsonFeatureSet: fn(),
+ },
+ parameters: {
+ msw: {
+ handlers: [mockAddressSearchGet, mockLatLngSearchEmptyGet],
+ },
+ },
+ play: async ({canvasElement, step, args}) => {
+ const canvas = within(canvasElement);
+ const map = canvasElement.querySelector('.leaflet-pane.leaflet-map-pane');
+
+ await step('All interactions are available', async () => {
+ expect(await canvas.findByTitle('Draw a marker')).toBeVisible();
+ expect(await canvas.findByTitle('Draw a polygon')).toBeVisible();
+ expect(await canvas.findByTitle('Draw a polyline')).toBeVisible();
+ });
+
+ await step('Draw a marker', async () => {
+ const markerButton = await canvas.findByTitle('Draw a marker');
+ await userEvent.click(markerButton);
+
+ await userEvent.click(map, {x: 100, y: 100});
+
+ expect(await canvas.findByRole('button', {name: 'Marker'})).toBeVisible();
+ expect(args.onGeoJsonFeatureSet).toBeCalledWith({
+ type: 'Feature',
+ properties: {},
+ geometry: {
+ type: 'Point',
+ // Expect that the coordinates array contains 2 items.
+ // We cannot pin it to specific values, because they can differentiate.
+ // To make sure that this test doesn't magically fail, just expect any 2 values
+ coordinates: [expect.anything(), expect.anything()],
+ },
+ });
+ });
+ },
+};
diff --git a/src/components/Map/index.jsx b/src/components/Map/index.jsx
index 35adf77ae..fcc909b44 100644
--- a/src/components/Map/index.jsx
+++ b/src/components/Map/index.jsx
@@ -1,47 +1,30 @@
+import * as Leaflet from 'leaflet';
import {GeoSearchControl} from 'leaflet-geosearch';
-import isEqual from 'lodash/isEqual';
import PropTypes from 'prop-types';
-import {useCallback, useContext, useEffect} from 'react';
-import {defineMessages, useIntl} from 'react-intl';
-import {MapContainer, Marker, TileLayer, useMap, useMapEvent} from 'react-leaflet';
+import {useContext, useEffect, useRef} from 'react';
+import {useIntl} from 'react-intl';
+import {FeatureGroup, MapContainer, TileLayer, useMap} from 'react-leaflet';
+import {EditControl} from 'react-leaflet-draw';
import {useGeolocation} from 'react-use';
import {ConfigContext} from 'Context';
-import {CRS_RD, DEFAULT_LAT_LNG, DEFAULT_ZOOM, TILE_LAYER_RD} from 'map/constants';
+import {
+ CRS_RD,
+ DEFAULT_INTERACTIONS,
+ DEFAULT_LAT_LNG,
+ DEFAULT_ZOOM,
+ TILE_LAYER_RD,
+} from 'map/constants';
import {getBEMClassName} from 'utils';
import NearestAddress from './NearestAddress';
+import './map.scss';
import OpenFormsProvider from './provider';
-
-const searchControlMessages = defineMessages({
- buttonLabel: {
- description: "The leaflet map's search button areaLabel text.",
- defaultMessage: 'Map component search button',
- },
- searchLabel: {
- description: "The leaflet map's input fields placeholder message.",
- defaultMessage: 'Enter address, please',
- },
- notFound: {
- description: "The leaflet map's location not found message.",
- defaultMessage: 'Sorry, that address could not be found.',
- },
-});
-
-const leafletGestureHandlingText = defineMessages({
- touch: {
- description: 'Gesturehandeling phone touch message.',
- defaultMessage: 'Use two fingers to move the map',
- },
- scroll: {
- description: 'Gesturehandeling pc scroll message.',
- defaultMessage: 'Use ctrl + scroll to zoom the map',
- },
- scrollMac: {
- description: 'Gesturehandeling mac scroll message.',
- defaultMessage: 'Use \u2318 + scroll to zoom the map',
- },
-});
+import {
+ applyLeafletTranslations,
+ leafletGestureHandlingText,
+ searchControlMessages,
+} from './translations';
const useDefaultCoordinates = () => {
// FIXME: can't call hooks conditionally
@@ -60,27 +43,64 @@ const useDefaultCoordinates = () => {
return [latitude, longitude];
};
+const getCoordinates = geoJsonFeature => {
+ if (!geoJsonFeature) {
+ return null;
+ }
+
+ const center = Leaflet.geoJSON(geoJsonFeature).getBounds().getCenter();
+ return [center.lat, center.lng];
+};
+
const LeaftletMap = ({
- markerCoordinates,
- onMarkerSet,
+ geoJsonFeature,
+ onGeoJsonFeatureSet,
defaultCenter = DEFAULT_LAT_LNG,
defaultZoomLevel = DEFAULT_ZOOM,
disabled = false,
+ interactions = DEFAULT_INTERACTIONS,
tileLayerUrl = TILE_LAYER_RD.url,
}) => {
+ const featureGroupRef = useRef();
const intl = useIntl();
const defaultCoordinates = useDefaultCoordinates();
- const coordinates = markerCoordinates || defaultCoordinates;
-
- const onWrapperMarkerSet = coordinates => {
- const coordinatesChanged = !isEqual(markerCoordinates, coordinates);
- if (!coordinatesChanged) return;
- onMarkerSet(coordinates);
- };
+ const geoJsonCoordinates = getCoordinates(geoJsonFeature);
+ const coordinates = geoJsonCoordinates ?? defaultCoordinates;
const modifiers = disabled ? ['disabled'] : [];
const className = getBEMClassName('leaflet-map', modifiers);
+ applyLeafletTranslations(intl);
+
+ const onFeatureCreate = event => {
+ updateGeoJsonFeature(event.layer);
+ };
+
+ const onFeatureDelete = () => {
+ // The value `null` is needed to make sure that Formio actually updates the value.
+ // node_modules/formiojs/components/_classes/component/Component.js:2528
+ onGeoJsonFeatureSet(null);
+ };
+
+ const onSearchMarkerSet = event => {
+ updateGeoJsonFeature(event.marker);
+ };
+
+ const updateGeoJsonFeature = newFeatureLayer => {
+ if (featureGroupRef.current) {
+ const newFeatureLayerId = newFeatureLayer._leaflet_id;
+ const layers = featureGroupRef.current?.getLayers();
+ // Limit the amount of features to 1, by removing the previous layer
+ if (layers.length > 1) {
+ const oldLayerId = layers
+ .map(layer => layer._leaflet_id)
+ .filter(layerId => layerId !== newFeatureLayerId);
+ featureGroupRef.current?.removeLayer(oldLayerId[0]);
+ }
+ }
+ onGeoJsonFeatureSet(newFeatureLayer.toGeoJSON());
+ };
+
return (
<>
- {coordinates ? (
- <>
-
-
- >
- ) : null}
-
- {disabled ? : }
+
+ {!disabled && (
+
+ )}
+
+ {coordinates && }
+ {!disabled && (
+
+ )}
+ {disabled && }
- {markerCoordinates && markerCoordinates.length && (
-
+ {geoJsonCoordinates && geoJsonCoordinates.length && (
+
)}
>
);
};
LeaftletMap.propTypes = {
- markerCoordinates: PropTypes.arrayOf(PropTypes.number),
- onMarkerSet: PropTypes.func,
+ geoJsonFeature: PropTypes.shape({
+ type: PropTypes.oneOf(['Feature']).isRequired,
+ properties: PropTypes.object,
+ geometry: PropTypes.oneOfType([
+ PropTypes.shape({
+ type: PropTypes.oneOf(['Point']).isRequired,
+ coordinates: PropTypes.arrayOf(PropTypes.number).isRequired,
+ }),
+ PropTypes.shape({
+ type: PropTypes.oneOf(['LineString']).isRequired,
+ coordinates: PropTypes.arrayOf(PropTypes.arrayOf(PropTypes.number)).isRequired,
+ }),
+ PropTypes.shape({
+ type: PropTypes.oneOf(['Polygon']).isRequired,
+ coordinates: PropTypes.arrayOf(PropTypes.arrayOf(PropTypes.arrayOf(PropTypes.number)))
+ .isRequired,
+ }),
+ ]).isRequired,
+ }),
+ onGeoJsonFeatureSet: PropTypes.func,
+ interactions: PropTypes.shape({
+ polyline: PropTypes.bool,
+ polygon: PropTypes.bool,
+ marker: PropTypes.bool,
+ }),
disabled: PropTypes.bool,
tileLayerUrl: PropTypes.string,
};
@@ -172,15 +232,6 @@ const SearchControl = ({onMarkerSet, options}) => {
const buttonLabel = intl.formatMessage(searchControlMessages.buttonLabel);
- const setMarker = useCallback(
- result => {
- if (result.location) {
- onMarkerSet([result.location.y, result.location.x]);
- }
- },
- [onMarkerSet]
- );
-
useEffect(() => {
const provider = new OpenFormsProvider(baseUrl);
const searchControl = new GeoSearchControl({
@@ -199,15 +250,15 @@ const SearchControl = ({onMarkerSet, options}) => {
searchControl.button.setAttribute('aria-label', buttonLabel);
map.addControl(searchControl);
- map.on('geosearch/showlocation', setMarker);
+ map.on('geosearch/showlocation', onMarkerSet);
return () => {
- map.off('geosearch/showlocation', setMarker);
+ map.off('geosearch/showlocation', onMarkerSet);
map.removeControl(searchControl);
};
}, [
map,
- setMarker,
+ onMarkerSet,
baseUrl,
showMarker,
showPopup,
@@ -239,24 +290,6 @@ SearchControl.propTypes = {
}),
};
-const MarkerWrapper = ({position, onMarkerSet, ...props}) => {
- const shouldSetMarker = !!(position && position.length === 2);
-
- useEffect(() => {
- if (!shouldSetMarker) return;
- if (!onMarkerSet) return;
- onMarkerSet(position);
- });
-
- // only render a marker if we explicitly have a marker
- return shouldSetMarker ? : null;
-};
-
-MarkerWrapper.propTypes = {
- position: PropTypes.arrayOf(PropTypes.number),
- onMarkerSet: PropTypes.func,
-};
-
const DisabledMapControls = () => {
const map = useMap();
useEffect(() => {
@@ -271,16 +304,4 @@ const DisabledMapControls = () => {
return null;
};
-const CaptureClick = ({setMarker}) => {
- useMapEvent('click', event => {
- const newLatLng = [event.latlng.lat, event.latlng.lng];
- setMarker(newLatLng);
- });
- return null;
-};
-
-CaptureClick.propTypes = {
- setMarker: PropTypes.func.isRequired,
-};
-
export default LeaftletMap;
diff --git a/src/components/Map/map.scss b/src/components/Map/map.scss
new file mode 100644
index 000000000..d02b5593c
--- /dev/null
+++ b/src/components/Map/map.scss
@@ -0,0 +1,26 @@
+@import 'leaflet/dist/leaflet.css';
+@import 'leaflet-draw/dist/leaflet.draw.css';
+
+.leaflet-draw-actions {
+ margin-top: -1px;
+ border: 2px solid rgba(0, 0, 0, 0.2);
+ border-radius: 4px;
+
+ // Make sure all action bars are the same height
+ a,
+ &.leaflet-draw-actions-top a,
+ &.leaflet-draw-actions-bottom a {
+ height: 30px;
+ line-height: 30px;
+ }
+
+ a {
+ background-color: #fff;
+ border-color: #ccc;
+
+ &:hover,
+ &:focus {
+ background-color: #f4f4f4;
+ }
+ }
+}
diff --git a/src/components/Map/translations.js b/src/components/Map/translations.js
new file mode 100644
index 000000000..3aec19e8c
--- /dev/null
+++ b/src/components/Map/translations.js
@@ -0,0 +1,202 @@
+import * as Leaflet from 'leaflet';
+import {defineMessages} from 'react-intl';
+
+const searchControlMessages = defineMessages({
+ buttonLabel: {
+ description: "The leaflet map's search button areaLabel text.",
+ defaultMessage: 'Map component search button',
+ },
+ searchLabel: {
+ description: "The leaflet map's input fields placeholder message.",
+ defaultMessage: 'Enter address, please',
+ },
+ notFound: {
+ description: "The leaflet map's location not found message.",
+ defaultMessage: 'Sorry, that address could not be found.',
+ },
+});
+
+const leafletGestureHandlingText = defineMessages({
+ touch: {
+ description: 'Gesturehandeling phone touch message.',
+ defaultMessage: 'Use two fingers to move the map',
+ },
+ scroll: {
+ description: 'Gesturehandeling pc scroll message.',
+ defaultMessage: 'Use ctrl + scroll to zoom the map',
+ },
+ scrollMac: {
+ description: 'Gesturehandeling mac scroll message.',
+ defaultMessage: 'Use \u2318 + scroll to zoom the map',
+ },
+});
+
+const leafletEditToolbarMessages = defineMessages({
+ saveText: {
+ description: 'Edit toolbar save message.',
+ defaultMessage: 'Save',
+ },
+ saveTitle: {
+ description: 'Edit toolbar save tooltip.',
+ defaultMessage: 'Save changes',
+ },
+ cancelText: {
+ description: 'Edit toolbar cancel message.',
+ defaultMessage: 'Cancel',
+ },
+ cancelTitle: {
+ description: 'Edit toolbar cancel tooltip.',
+ defaultMessage: 'Cancel changes',
+ },
+ clearAllText: {
+ description: 'Edit toolbar clearAll message.',
+ defaultMessage: 'Remove all',
+ },
+ clearAllTitle: {
+ description: 'Edit toolbar clearAll tooltip.',
+ defaultMessage: 'Remove all shapes',
+ },
+ remove: {
+ description: 'Edit toolbar remove button tooltip.',
+ defaultMessage: 'Remove shapes',
+ },
+ removeDisabled: {
+ description: 'Edit toolbar remove button disabled tooltip.',
+ defaultMessage: 'No shapes to remove',
+ },
+});
+
+const leafletDrawToolbarMessages = defineMessages({
+ actionsText: {
+ description: 'Draw toolbar cancel button message.',
+ defaultMessage: 'Cancel',
+ },
+ actionsTitle: {
+ description: 'Draw toolbar cancel button tooltip.',
+ defaultMessage: 'Cancel drawing',
+ },
+ finishText: {
+ description: 'Draw toolbar finish button message.',
+ defaultMessage: 'Finish',
+ },
+ finishTitle: {
+ description: 'Draw toolbar finish button tooltip.',
+ defaultMessage: 'Finish drawing',
+ },
+ undoText: {
+ description: 'Draw toolbar undo button message.',
+ defaultMessage: 'Remove last point',
+ },
+ undoTitle: {
+ description: 'Draw toolbar undo button tooltip.',
+ defaultMessage: 'Remove last drawn point',
+ },
+ polyline: {
+ description: 'Draw toolbar polyline button tooltip.',
+ defaultMessage: 'Line',
+ },
+ polygon: {
+ description: 'Draw toolbar polygon button tooltip.',
+ defaultMessage: 'Shape (polygon)',
+ },
+ marker: {
+ description: 'Draw toolbar marker button tooltip.',
+ defaultMessage: 'Marker',
+ },
+});
+
+const leafletDrawHandlerMessages = defineMessages({
+ markerTooltipStart: {
+ description: 'Draw handler marker tooltip start.',
+ defaultMessage: 'Click map to place marker',
+ },
+ polylineTooltipStart: {
+ description: 'Draw handler polyline tooltip start.',
+ defaultMessage: 'Click to start drawing line',
+ },
+ polylineTooltipContinue: {
+ description: 'Draw handler polyline tooltip continue.',
+ defaultMessage: 'Click to continue drawing line',
+ },
+ polylineTooltipEnd: {
+ description: 'Draw handler polyline tooltip end.',
+ defaultMessage: 'Click last point to finish line',
+ },
+ polygonTooltipStart: {
+ description: 'Draw handler polygon tooltip start.',
+ defaultMessage: 'Click to start drawing shape',
+ },
+ polygonTooltipContinue: {
+ description: 'Draw handler polygon tooltip continue.',
+ defaultMessage: 'Click to continue drawing shape',
+ },
+ polygonTooltipEnd: {
+ description: 'Draw handler polygon tooltip end.',
+ defaultMessage: 'Click first point to finish shape',
+ },
+});
+
+const applyLeafletTranslations = intl => {
+ // We have to do the translations via Leaflet
+ // https://github.com/alex3165/react-leaflet-draw/issues/179
+ Leaflet.drawLocal.edit.toolbar = {
+ actions: {
+ save: {
+ text: intl.formatMessage(leafletEditToolbarMessages.saveText),
+ title: intl.formatMessage(leafletEditToolbarMessages.saveTitle),
+ },
+ cancel: {
+ text: intl.formatMessage(leafletEditToolbarMessages.cancelText),
+ title: intl.formatMessage(leafletEditToolbarMessages.cancelTitle),
+ },
+ clearAll: {
+ text: intl.formatMessage(leafletEditToolbarMessages.clearAllText),
+ title: intl.formatMessage(leafletEditToolbarMessages.clearAllTitle),
+ },
+ },
+ buttons: {
+ remove: intl.formatMessage(leafletEditToolbarMessages.remove),
+ removeDisabled: intl.formatMessage(leafletEditToolbarMessages.removeDisabled),
+ },
+ };
+ Leaflet.drawLocal.draw.toolbar = {
+ actions: {
+ text: intl.formatMessage(leafletDrawToolbarMessages.actionsText),
+ title: intl.formatMessage(leafletDrawToolbarMessages.actionsTitle),
+ },
+ finish: {
+ text: intl.formatMessage(leafletDrawToolbarMessages.finishText),
+ title: intl.formatMessage(leafletDrawToolbarMessages.finishTitle),
+ },
+ undo: {
+ text: intl.formatMessage(leafletDrawToolbarMessages.undoText),
+ title: intl.formatMessage(leafletDrawToolbarMessages.undoTitle),
+ },
+ buttons: {
+ polyline: intl.formatMessage(leafletDrawToolbarMessages.polyline),
+ polygon: intl.formatMessage(leafletDrawToolbarMessages.polygon),
+ marker: intl.formatMessage(leafletDrawToolbarMessages.marker),
+ },
+ };
+ Leaflet.drawLocal.draw.handlers.marker = {
+ tooltip: {
+ start: intl.formatMessage(leafletDrawHandlerMessages.markerTooltipStart),
+ },
+ };
+ Leaflet.drawLocal.draw.handlers.polyline = {
+ tooltip: {
+ start: intl.formatMessage(leafletDrawHandlerMessages.polylineTooltipStart),
+ cont: intl.formatMessage(leafletDrawHandlerMessages.polylineTooltipContinue),
+ end: intl.formatMessage(leafletDrawHandlerMessages.polylineTooltipEnd),
+ },
+ };
+ Leaflet.drawLocal.draw.handlers.polygon = {
+ tooltip: {
+ start: intl.formatMessage(leafletDrawHandlerMessages.polygonTooltipStart),
+ cont: intl.formatMessage(leafletDrawHandlerMessages.polygonTooltipContinue),
+ end: intl.formatMessage(leafletDrawHandlerMessages.polygonTooltipEnd),
+ },
+ };
+};
+
+export {searchControlMessages, leafletGestureHandlingText, applyLeafletTranslations};
diff --git a/src/formio/components/Map.jsx b/src/formio/components/Map.jsx
index 0e75ac9ff..f633972db 100644
--- a/src/formio/components/Map.jsx
+++ b/src/formio/components/Map.jsx
@@ -44,7 +44,7 @@ export default class Map extends Field {
}
get emptyValue() {
- return '';
+ return undefined;
}
/**
@@ -90,8 +90,8 @@ export default class Map extends Field {
super.destroy();
}
- onMarkerSet(newLatLng) {
- this.setValue(newLatLng, {modified: true});
+ onGeoJsonSet(newGeoJson) {
+ this.setValue(newGeoJson, {modified: true});
}
renderReact() {
@@ -99,7 +99,7 @@ export default class Map extends Field {
const {lat = defaultLat, lng = defaultLon} = this.component?.initialCenter || {};
const defaultCenter = [lat, lng];
- const markerCoordinates = this.getValue();
+ const geoJsonFeature = this.getValue();
const container = this.refs.mapContainer;
const zoom = this.component.defaultZoom;
@@ -110,10 +110,11 @@ export default class Map extends Field {
@@ -122,6 +123,11 @@ export default class Map extends Field {
}
setValue(value, flags = {}) {
+ if (value === null) {
+ // The `resetValue` flag is needed to allow the setting of `undefined` or `null` values.
+ // node_modules/formiojs/components/_classes/component/Component.js:2526
+ flags.resetValue = true;
+ }
const changed = super.setValue(value, flags);
// re-render if the value is set, which may be because of existing submission data
changed && this.renderReact();
diff --git a/src/i18n/compiled/en.json b/src/i18n/compiled/en.json
index 69d4d9e5d..a8d22545c 100644
--- a/src/i18n/compiled/en.json
+++ b/src/i18n/compiled/en.json
@@ -43,12 +43,30 @@
"value": "."
}
],
+ "+KBbXH": [
+ {
+ "type": 0,
+ "value": "Click to start drawing shape"
+ }
+ ],
+ "+W79Dr": [
+ {
+ "type": 0,
+ "value": "Click to continue drawing line"
+ }
+ ],
"+uwsgF": [
{
"type": 0,
"value": "Location and time"
}
],
+ "/yX9Xl": [
+ {
+ "type": 0,
+ "value": "Cancel drawing"
+ }
+ ],
"0j8tMq": [
{
"type": 0,
@@ -81,6 +99,12 @@
"value": "Something went wrong while presenting the login option. Please contact the municipality."
}
],
+ "2D6ubj": [
+ {
+ "type": 0,
+ "value": "Line"
+ }
+ ],
"2HHJrq": [
{
"type": 0,
@@ -117,6 +141,12 @@
"value": "Loading..."
}
],
+ "4ZOmtU": [
+ {
+ "type": 0,
+ "value": "Save changes"
+ }
+ ],
"4gPdgK": [
{
"type": 0,
@@ -129,6 +159,12 @@
"value": "Verify"
}
],
+ "4ui8R+": [
+ {
+ "type": 0,
+ "value": "Click last point to finish line"
+ }
+ ],
"5uh2hS": [
{
"type": 0,
@@ -155,6 +191,12 @@
"value": "Check and co-sign submission"
}
],
+ "62SBjV": [
+ {
+ "type": 0,
+ "value": "Shape (polygon)"
+ }
+ ],
"6GNK65": [
{
"type": 0,
@@ -449,6 +491,12 @@
"value": "provider"
}
],
+ "B/W1uC": [
+ {
+ "type": 0,
+ "value": "Remove shapes"
+ }
+ ],
"BL1Ehr": [
{
"type": 0,
@@ -479,6 +527,12 @@
"value": "This form is currently undergoing maintenance and can not be accessed at the moment."
}
],
+ "D6TdPW": [
+ {
+ "type": 0,
+ "value": "Click map to place marker"
+ }
+ ],
"DBTNgI": [
{
"type": 0,
@@ -665,6 +719,18 @@
"value": "Inloggen bij deze organisatie is niet gelukt. Probeert u het later nog een keer. Lukt het nog steeds niet? Log in bij Mijn DigiD. Zo controleert u of uw DigiD goed werkt. Mogelijk is er een storing bij de organisatie waar u inlogt."
}
],
+ "HY6Irs": [
+ {
+ "type": 0,
+ "value": "Cancel changes"
+ }
+ ],
+ "HgLr1F": [
+ {
+ "type": 0,
+ "value": "Cancel"
+ }
+ ],
"HhcSoc": [
{
"type": 0,
@@ -677,6 +743,12 @@
"value": "Invalid input."
}
],
+ "Hkq6NE": [
+ {
+ "type": 0,
+ "value": "Finish drawing"
+ }
+ ],
"I6ok5N": [
{
"type": 0,
@@ -973,6 +1045,12 @@
"value": "Payment"
}
],
+ "N2sZnS": [
+ {
+ "type": 0,
+ "value": "Save"
+ }
+ ],
"OnfuIr": [
{
"options": {
@@ -1005,6 +1083,12 @@
"value": "withAsterisk"
}
],
+ "Op4orj": [
+ {
+ "type": 0,
+ "value": "No shapes to remove"
+ }
+ ],
"P194bo": [
{
"type": 0,
@@ -1031,6 +1115,12 @@
"value": "Invalid input."
}
],
+ "Q6/Lj7": [
+ {
+ "type": 0,
+ "value": "Remove last drawn point"
+ }
+ ],
"QPdaOi": [
{
"type": 0,
@@ -1223,6 +1313,12 @@
"value": "."
}
],
+ "U5+FHP": [
+ {
+ "type": 0,
+ "value": "Cancel"
+ }
+ ],
"UyEKdQ": [
{
"type": 0,
@@ -1297,6 +1393,12 @@
"value": "."
}
],
+ "Y3jHZm": [
+ {
+ "type": 0,
+ "value": "Remove last point"
+ }
+ ],
"YcC4PD": [
{
"type": 0,
@@ -1423,6 +1525,12 @@
"value": "Contact details"
}
],
+ "bRtoG6": [
+ {
+ "type": 0,
+ "value": "Remove all"
+ }
+ ],
"bgfiRG": [
{
"type": 0,
@@ -1465,6 +1573,12 @@
"value": "Back to form start"
}
],
+ "dNGw+S": [
+ {
+ "type": 0,
+ "value": "Click to continue drawing shape"
+ }
+ ],
"eAmrdi": [
{
"type": 0,
@@ -1483,6 +1597,12 @@
"value": "Processing..."
}
],
+ "fJVa0u": [
+ {
+ "type": 0,
+ "value": "Marker"
+ }
+ ],
"fWjfVm": [
{
"type": 0,
@@ -2075,6 +2195,12 @@
"value": "Find address"
}
],
+ "sYb+eZ": [
+ {
+ "type": 0,
+ "value": "Remove all shapes"
+ }
+ ],
"senRv3": [
{
"type": 0,
@@ -2215,12 +2341,24 @@
"value": "Amount"
}
],
+ "vfKvuS": [
+ {
+ "type": 0,
+ "value": "Click first point to finish shape"
+ }
+ ],
"wwsWUp": [
{
"type": 0,
"value": "How do you rate this form?"
}
],
+ "xh+7Vv": [
+ {
+ "type": 0,
+ "value": "Finish"
+ }
+ ],
"y31iyC": [
{
"type": 0,
@@ -2247,6 +2385,12 @@
"value": "Return to main website"
}
],
+ "zpHAro": [
+ {
+ "type": 0,
+ "value": "Click to start drawing line"
+ }
+ ],
"zvoXSU": [
{
"type": 0,
diff --git a/src/i18n/compiled/nl.json b/src/i18n/compiled/nl.json
index a57a85100..d1524570a 100644
--- a/src/i18n/compiled/nl.json
+++ b/src/i18n/compiled/nl.json
@@ -43,12 +43,30 @@
"value": " actief."
}
],
+ "+KBbXH": [
+ {
+ "type": 0,
+ "value": "Klik om een veelhoek (polygoon) te tekenen"
+ }
+ ],
+ "+W79Dr": [
+ {
+ "type": 0,
+ "value": "Klik om verder te tekenen"
+ }
+ ],
"+uwsgF": [
{
"type": 0,
"value": "Afspraakdetails"
}
],
+ "/yX9Xl": [
+ {
+ "type": 0,
+ "value": "Tekeningen annuleren"
+ }
+ ],
"0j8tMq": [
{
"type": 0,
@@ -81,6 +99,12 @@
"value": "Er is iets fout gegaan bij het presenteren van de inlogopties. Neem alstublieft contact met ons op."
}
],
+ "2D6ubj": [
+ {
+ "type": 0,
+ "value": "Lijn"
+ }
+ ],
"2HHJrq": [
{
"type": 0,
@@ -117,6 +141,12 @@
"value": "Opties ophalen..."
}
],
+ "4ZOmtU": [
+ {
+ "type": 0,
+ "value": "Wijzigingen opslaan"
+ }
+ ],
"4gPdgK": [
{
"type": 0,
@@ -129,6 +159,12 @@
"value": "Bevestigen"
}
],
+ "4ui8R+": [
+ {
+ "type": 0,
+ "value": "Klik het laatste punt om de lijn te voltooien"
+ }
+ ],
"5uh2hS": [
{
"type": 0,
@@ -155,6 +191,12 @@
"value": "Controle en medeondertekenen inzending"
}
],
+ "62SBjV": [
+ {
+ "type": 0,
+ "value": "Veelhoek (polygoon)"
+ }
+ ],
"6GNK65": [
{
"type": 0,
@@ -449,6 +491,12 @@
"value": "provider"
}
],
+ "B/W1uC": [
+ {
+ "type": 0,
+ "value": "Verwijder vormen"
+ }
+ ],
"BL1Ehr": [
{
"type": 0,
@@ -479,6 +527,12 @@
"value": "Dit formulier is momenteel in onderhoud en daardoor tijdelijk niet beschikbaar."
}
],
+ "D6TdPW": [
+ {
+ "type": 0,
+ "value": "Klik op de kaart om een pin/punt te plaatsen"
+ }
+ ],
"DBTNgI": [
{
"type": 0,
@@ -665,6 +719,18 @@
"value": "Inloggen bij deze organisatie is niet gelukt. Probeert u het later nog een keer. Lukt het nog steeds niet? Log in bij Mijn DigiD. Zo controleert u of uw DigiD goed werkt. Mogelijk is er een storing bij de organisatie waar u inlogt."
}
],
+ "HY6Irs": [
+ {
+ "type": 0,
+ "value": "Wijzigingen annuleren"
+ }
+ ],
+ "HgLr1F": [
+ {
+ "type": 0,
+ "value": "Annuleer"
+ }
+ ],
"HhcSoc": [
{
"type": 0,
@@ -677,6 +743,12 @@
"value": "Ongeldige invoer."
}
],
+ "Hkq6NE": [
+ {
+ "type": 0,
+ "value": "Tekening voltooien"
+ }
+ ],
"I6ok5N": [
{
"type": 0,
@@ -973,6 +1045,12 @@
"value": "Betalen"
}
],
+ "N2sZnS": [
+ {
+ "type": 0,
+ "value": "Opslaan"
+ }
+ ],
"OnfuIr": [
{
"options": {
@@ -1005,6 +1083,12 @@
"value": "withAsterisk"
}
],
+ "Op4orj": [
+ {
+ "type": 0,
+ "value": "Geen vormen om te verwijderen"
+ }
+ ],
"P194bo": [
{
"type": 0,
@@ -1031,6 +1115,12 @@
"value": "Ongeldige invoer."
}
],
+ "Q6/Lj7": [
+ {
+ "type": 0,
+ "value": "Verwijder het laatst getekende punt"
+ }
+ ],
"QPdaOi": [
{
"type": 0,
@@ -1223,6 +1313,12 @@
"value": " lang zijn."
}
],
+ "U5+FHP": [
+ {
+ "type": 0,
+ "value": "Annuleer"
+ }
+ ],
"UyEKdQ": [
{
"type": 0,
@@ -1297,6 +1393,12 @@
"value": " zijn."
}
],
+ "Y3jHZm": [
+ {
+ "type": 0,
+ "value": "Verwijder laatste punt"
+ }
+ ],
"YcC4PD": [
{
"type": 0,
@@ -1427,6 +1529,12 @@
"value": "Je gegevens"
}
],
+ "bRtoG6": [
+ {
+ "type": 0,
+ "value": "Verwijder alles"
+ }
+ ],
"bgfiRG": [
{
"type": 0,
@@ -1469,6 +1577,12 @@
"value": "Terug naar begin"
}
],
+ "dNGw+S": [
+ {
+ "type": 0,
+ "value": "Klik om verder te tekenen"
+ }
+ ],
"eAmrdi": [
{
"type": 0,
@@ -1487,6 +1601,12 @@
"value": "Bezig..."
}
],
+ "fJVa0u": [
+ {
+ "type": 0,
+ "value": "Pin/punt"
+ }
+ ],
"fWjfVm": [
{
"type": 0,
@@ -2079,6 +2199,12 @@
"value": "Zoek adres"
}
],
+ "sYb+eZ": [
+ {
+ "type": 0,
+ "value": "Verwijder alle vormen van de kaart"
+ }
+ ],
"senRv3": [
{
"type": 0,
@@ -2219,12 +2345,24 @@
"value": "Aantal personen"
}
],
+ "vfKvuS": [
+ {
+ "type": 0,
+ "value": "Klik op het eerste punt, om de veelhoek te voltooien"
+ }
+ ],
"wwsWUp": [
{
"type": 0,
"value": "Wat vind je van dit formulier?"
}
],
+ "xh+7Vv": [
+ {
+ "type": 0,
+ "value": "Voltooi"
+ }
+ ],
"y31iyC": [
{
"type": 0,
@@ -2251,6 +2389,12 @@
"value": "Terug naar de website"
}
],
+ "zpHAro": [
+ {
+ "type": 0,
+ "value": "Klik om een lijk te tekenen"
+ }
+ ],
"zvoXSU": [
{
"type": 0,
diff --git a/src/i18n/messages/en.json b/src/i18n/messages/en.json
index 965f9c360..c075c5ed0 100644
--- a/src/i18n/messages/en.json
+++ b/src/i18n/messages/en.json
@@ -9,11 +9,26 @@
"description": "Form save modal body text",
"originalDefault": "Enter your email address to get an email to resume the form at a later date. This can be done on any device where you open the link. The link remains valid for {numberOfDays, plural, one {1 day} other {{numberOfDays} days}}."
},
+ "+KBbXH": {
+ "defaultMessage": "Click to start drawing shape",
+ "description": "Draw handler polygon tooltip start.",
+ "originalDefault": "Click to start drawing shape"
+ },
+ "+W79Dr": {
+ "defaultMessage": "Click to continue drawing line",
+ "description": "Draw handler polyline tooltip continue.",
+ "originalDefault": "Click to continue drawing line"
+ },
"+uwsgF": {
"defaultMessage": "Location and time",
"description": "Appointments navbar title for 'location and time' step",
"originalDefault": "Location and time"
},
+ "/yX9Xl": {
+ "defaultMessage": "Cancel drawing",
+ "description": "Draw toolbar cancel button tooltip.",
+ "originalDefault": "Cancel drawing"
+ },
"0j8tMq": {
"defaultMessage": "Log out",
"description": "Log out button text",
@@ -29,6 +44,11 @@
"description": "Co-sign auth option not available on form",
"originalDefault": "Something went wrong while presenting the login option. Please contact the municipality."
},
+ "2D6ubj": {
+ "defaultMessage": "Line",
+ "description": "Draw toolbar polyline button tooltip.",
+ "originalDefault": "Line"
+ },
"2HHJrq": {
"defaultMessage": "Invalid function arguments",
"description": "ZOD 'invalid_arguments' error message",
@@ -59,6 +79,11 @@
"description": "(Async) select options loading message",
"originalDefault": "Loading..."
},
+ "4ZOmtU": {
+ "defaultMessage": "Save changes",
+ "description": "Edit toolbar save tooltip.",
+ "originalDefault": "Save changes"
+ },
"4gPdgK": {
"defaultMessage": "Bad",
"description": "GovMetric rating text",
@@ -69,6 +94,11 @@
"description": "Email verification: verify code button text",
"originalDefault": "Verify"
},
+ "4ui8R+": {
+ "defaultMessage": "Click last point to finish line",
+ "description": "Draw handler polyline tooltip end.",
+ "originalDefault": "Click last point to finish line"
+ },
"5uh2hS": {
"defaultMessage": "Appointment cancellation failed",
"description": "Appointment cancellation error message",
@@ -84,6 +114,11 @@
"description": "Check overview and co-sign",
"originalDefault": "Check and co-sign submission"
},
+ "62SBjV": {
+ "defaultMessage": "Shape (polygon)",
+ "description": "Draw toolbar polygon button tooltip.",
+ "originalDefault": "Shape (polygon)"
+ },
"6GNK65": {
"defaultMessage": "There was an authentication and/or permission problem.",
"description": "Authentication error message",
@@ -214,6 +249,11 @@
"description": "Login button label",
"originalDefault": "Login with {provider}"
},
+ "B/W1uC": {
+ "defaultMessage": "Remove shapes",
+ "description": "Edit toolbar remove button tooltip.",
+ "originalDefault": "Remove shapes"
+ },
"BL1Ehr": {
"defaultMessage": "Invalid.",
"description": "ZOD 'invalid_string' error message, regex validation",
@@ -239,6 +279,11 @@
"description": "Maintenance mode message",
"originalDefault": "This form is currently undergoing maintenance and can not be accessed at the moment."
},
+ "D6TdPW": {
+ "defaultMessage": "Click map to place marker",
+ "description": "Draw handler marker tooltip start.",
+ "originalDefault": "Click map to place marker"
+ },
"DBTNgI": {
"defaultMessage": "d",
"description": "Placeholder for day part of a date",
@@ -364,6 +409,16 @@
"description": "DigiD error message. MUST BE THIS EXACT STRING!",
"originalDefault": "Inloggen bij deze organisatie is niet gelukt. Probeert u het later nog een keer. Lukt het nog steeds niet? Log in bij Mijn DigiD. Zo controleert u of uw DigiD goed werkt. Mogelijk is er een storing bij de organisatie waar u inlogt."
},
+ "HY6Irs": {
+ "defaultMessage": "Cancel changes",
+ "description": "Edit toolbar cancel tooltip.",
+ "originalDefault": "Cancel changes"
+ },
+ "HgLr1F": {
+ "defaultMessage": "Cancel",
+ "description": "Draw toolbar cancel button message.",
+ "originalDefault": "Cancel"
+ },
"HhcSoc": {
"defaultMessage": "Save and resume later",
"description": "Form save modal title",
@@ -374,6 +429,11 @@
"description": "ZOD 'too_big' error message, generic",
"originalDefault": "Invalid input."
},
+ "Hkq6NE": {
+ "defaultMessage": "Finish drawing",
+ "description": "Draw toolbar finish button tooltip.",
+ "originalDefault": "Finish drawing"
+ },
"I6ok5N": {
"defaultMessage": "Invalid {validation, select, email {email} url {url} datetime {date and time} ip {IP address} other {validation} }.",
"description": "ZOD 'invalid_string' error message, validation other than regex",
@@ -484,11 +544,21 @@
"description": "Payment page title",
"originalDefault": "Payment"
},
+ "N2sZnS": {
+ "defaultMessage": "Save",
+ "description": "Edit toolbar save message.",
+ "originalDefault": "Save"
+ },
"OnfuIr": {
"defaultMessage": "{withAsterisk, select, true {} other { (not required)}}",
"description": "Form field label, field not required",
"originalDefault": "{withAsterisk, select, true {} other { (not required)}}"
},
+ "Op4orj": {
+ "defaultMessage": "No shapes to remove",
+ "description": "Edit toolbar remove button disabled tooltip.",
+ "originalDefault": "No shapes to remove"
+ },
"P194bo": {
"defaultMessage": "Invalid input: must start with \"{startsWith}\".",
"description": "ZOD 'invalid_string' error message, with startsWith",
@@ -504,6 +574,11 @@
"description": "ZOD 'too_small' error message, generic",
"originalDefault": "Invalid input."
},
+ "Q6/Lj7": {
+ "defaultMessage": "Remove last drawn point",
+ "description": "Draw toolbar undo button tooltip.",
+ "originalDefault": "Remove last drawn point"
+ },
"QPdaOi": {
"defaultMessage": "No results found",
"description": "Select 'no options' message",
@@ -574,6 +649,11 @@
"description": "ZOD 'too_small' error message, for strings",
"originalDefault": "String must contain {exact, select, true {exactly} other {{inclusive, select, true {at least} other {more than}}} } {minimum, plural, one {{minimum} character} other {{minimum} characters}}."
},
+ "U5+FHP": {
+ "defaultMessage": "Cancel",
+ "description": "Edit toolbar cancel message.",
+ "originalDefault": "Cancel"
+ },
"UyEKdQ": {
"defaultMessage": "Product {number}/{total}",
"description": "Appointments: single product label/header",
@@ -619,6 +699,11 @@
"description": "ZOD 'too_big' error message, for dates",
"originalDefault": "Date must be smaller than or equal to {maximum}."
},
+ "Y3jHZm": {
+ "defaultMessage": "Remove last point",
+ "description": "Draw toolbar undo button message.",
+ "originalDefault": "Remove last point"
+ },
"YcC4PD": {
"defaultMessage": "Choose language",
"description": "Language selection heading",
@@ -669,6 +754,11 @@
"description": "Appointments: contact details step title",
"originalDefault": "Contact details"
},
+ "bRtoG6": {
+ "defaultMessage": "Remove all",
+ "description": "Edit toolbar clearAll message.",
+ "originalDefault": "Remove all"
+ },
"bgfiRG": {
"defaultMessage": "You've started the payment process.",
"description": "payment started status",
@@ -704,6 +794,11 @@
"description": "return to form start link after 403",
"originalDefault": "Back to form start"
},
+ "dNGw+S": {
+ "defaultMessage": "Click to continue drawing shape",
+ "description": "Draw handler polygon tooltip continue.",
+ "originalDefault": "Click to continue drawing shape"
+ },
"eAmrdi": {
"defaultMessage": "Loading...",
"description": "Loading content text",
@@ -719,6 +814,11 @@
"description": "Checking background processing status title",
"originalDefault": "Processing..."
},
+ "fJVa0u": {
+ "defaultMessage": "Marker",
+ "description": "Draw toolbar marker button tooltip.",
+ "originalDefault": "Marker"
+ },
"fWjfVm": {
"defaultMessage": "Please hold on while we're processing your submission.",
"description": "Checking background processing status body",
@@ -989,6 +1089,11 @@
"description": "The leaflet map's input fields placeholder message.",
"originalDefault": "Enter address, please"
},
+ "sYb+eZ": {
+ "defaultMessage": "Remove all shapes",
+ "description": "Edit toolbar clearAll tooltip.",
+ "originalDefault": "Remove all shapes"
+ },
"senRv3": {
"defaultMessage": "You're about to cancel your appointment on {date} at {time}. Please fill out your email address for verification purposes.",
"description": "Appointment cancellation body text",
@@ -1039,11 +1144,21 @@
"description": "Appointments: product amount field label",
"originalDefault": "Amount"
},
+ "vfKvuS": {
+ "defaultMessage": "Click first point to finish shape",
+ "description": "Draw handler polygon tooltip end.",
+ "originalDefault": "Click first point to finish shape"
+ },
"wwsWUp": {
"defaultMessage": "How do you rate this form?",
"description": "GovMetric snippet header",
"originalDefault": "How do you rate this form?"
},
+ "xh+7Vv": {
+ "defaultMessage": "Finish",
+ "description": "Draw toolbar finish button message.",
+ "originalDefault": "Finish"
+ },
"y31iyC": {
"defaultMessage": "Invalid literal value, expected {expected}.",
"description": "ZOD 'invalid_literal' error message",
@@ -1059,6 +1174,11 @@
"description": "Back to main website link title",
"originalDefault": "Return to main website"
},
+ "zpHAro": {
+ "defaultMessage": "Click to start drawing line",
+ "description": "Draw handler polyline tooltip start.",
+ "originalDefault": "Click to start drawing line"
+ },
"zvoXSU": {
"defaultMessage": "Nearest address: ",
"description": "Reverse geocoded address result display",
diff --git a/src/i18n/messages/nl.json b/src/i18n/messages/nl.json
index 4ef35f536..b2e835870 100644
--- a/src/i18n/messages/nl.json
+++ b/src/i18n/messages/nl.json
@@ -9,11 +9,26 @@
"description": "Form save modal body text",
"originalDefault": "Enter your email address to get an email to resume the form at a later date. This can be done on any device where you open the link. The link remains valid for {numberOfDays, plural, one {1 day} other {{numberOfDays} days}}."
},
+ "+KBbXH": {
+ "defaultMessage": "Klik om een veelhoek (polygoon) te tekenen",
+ "description": "Draw handler polygon tooltip start.",
+ "originalDefault": "Click to start drawing shape"
+ },
+ "+W79Dr": {
+ "defaultMessage": "Klik om verder te tekenen",
+ "description": "Draw handler polyline tooltip continue.",
+ "originalDefault": "Click to continue drawing line"
+ },
"+uwsgF": {
"defaultMessage": "Afspraakdetails",
"description": "Appointments navbar title for 'location and time' step",
"originalDefault": "Location and time"
},
+ "/yX9Xl": {
+ "defaultMessage": "Tekeningen annuleren",
+ "description": "Draw toolbar cancel button tooltip.",
+ "originalDefault": "Cancel drawing"
+ },
"0j8tMq": {
"defaultMessage": "Uitloggen",
"description": "Log out button text",
@@ -29,6 +44,11 @@
"description": "Co-sign auth option not available on form",
"originalDefault": "Something went wrong while presenting the login option. Please contact the municipality."
},
+ "2D6ubj": {
+ "defaultMessage": "Lijn",
+ "description": "Draw toolbar polyline button tooltip.",
+ "originalDefault": "Line"
+ },
"2HHJrq": {
"defaultMessage": "Ongeldige functie-argumenten",
"description": "ZOD 'invalid_arguments' error message",
@@ -59,6 +79,11 @@
"description": "(Async) select options loading message",
"originalDefault": "Loading..."
},
+ "4ZOmtU": {
+ "defaultMessage": "Wijzigingen opslaan",
+ "description": "Edit toolbar save tooltip.",
+ "originalDefault": "Save changes"
+ },
"4gPdgK": {
"defaultMessage": "Slecht",
"description": "GovMetric rating text",
@@ -69,6 +94,11 @@
"description": "Email verification: verify code button text",
"originalDefault": "Verify"
},
+ "4ui8R+": {
+ "defaultMessage": "Klik het laatste punt om de lijn te voltooien",
+ "description": "Draw handler polyline tooltip end.",
+ "originalDefault": "Click last point to finish line"
+ },
"5uh2hS": {
"defaultMessage": "Afspraak annuleren mislukt",
"description": "Appointment cancellation error message",
@@ -84,6 +114,11 @@
"description": "Check overview and co-sign",
"originalDefault": "Check and co-sign submission"
},
+ "62SBjV": {
+ "defaultMessage": "Veelhoek (polygoon)",
+ "description": "Draw toolbar polygon button tooltip.",
+ "originalDefault": "Shape (polygon)"
+ },
"6GNK65": {
"defaultMessage": "Je moet ingelogd zijn voor deze actie.",
"description": "Authentication error message",
@@ -216,6 +251,11 @@
"description": "Login button label",
"originalDefault": "Login with {provider}"
},
+ "B/W1uC": {
+ "defaultMessage": "Verwijder vormen",
+ "description": "Edit toolbar remove button tooltip.",
+ "originalDefault": "Remove shapes"
+ },
"BL1Ehr": {
"defaultMessage": "Ongeldig.",
"description": "ZOD 'invalid_string' error message, regex validation",
@@ -241,6 +281,11 @@
"description": "Maintenance mode message",
"originalDefault": "This form is currently undergoing maintenance and can not be accessed at the moment."
},
+ "D6TdPW": {
+ "defaultMessage": "Klik op de kaart om een pin/punt te plaatsen",
+ "description": "Draw handler marker tooltip start.",
+ "originalDefault": "Click map to place marker"
+ },
"DBTNgI": {
"defaultMessage": "d",
"description": "Placeholder for day part of a date",
@@ -369,6 +414,16 @@
"isTranslated": true,
"originalDefault": "Inloggen bij deze organisatie is niet gelukt. Probeert u het later nog een keer. Lukt het nog steeds niet? Log in bij Mijn DigiD. Zo controleert u of uw DigiD goed werkt. Mogelijk is er een storing bij de organisatie waar u inlogt."
},
+ "HY6Irs": {
+ "defaultMessage": "Wijzigingen annuleren",
+ "description": "Edit toolbar cancel tooltip.",
+ "originalDefault": "Cancel changes"
+ },
+ "HgLr1F": {
+ "defaultMessage": "Annuleer",
+ "description": "Draw toolbar cancel button message.",
+ "originalDefault": "Cancel"
+ },
"HhcSoc": {
"defaultMessage": "Opslaan en later verdergaan",
"description": "Form save modal title",
@@ -379,6 +434,11 @@
"description": "ZOD 'too_big' error message, generic",
"originalDefault": "Invalid input."
},
+ "Hkq6NE": {
+ "defaultMessage": "Tekening voltooien",
+ "description": "Draw toolbar finish button tooltip.",
+ "originalDefault": "Finish drawing"
+ },
"I6ok5N": {
"defaultMessage": "Ongeldig{validation, select, email { e-mailadres} url {e URL} datetime {e datumtijd} ip { IP address} other { validation} }.",
"description": "ZOD 'invalid_string' error message, validation other than regex",
@@ -491,11 +551,21 @@
"description": "Payment page title",
"originalDefault": "Payment"
},
+ "N2sZnS": {
+ "defaultMessage": "Opslaan",
+ "description": "Edit toolbar save message.",
+ "originalDefault": "Save"
+ },
"OnfuIr": {
"defaultMessage": "{withAsterisk, select, true {} other { (niet verplicht)}}",
"description": "Form field label, field not required",
"originalDefault": "{withAsterisk, select, true {} other { (not required)}}"
},
+ "Op4orj": {
+ "defaultMessage": "Geen vormen om te verwijderen",
+ "description": "Edit toolbar remove button disabled tooltip.",
+ "originalDefault": "No shapes to remove"
+ },
"P194bo": {
"defaultMessage": "De ingevoerde waarde moet beginnen met \"{startsWith}\".",
"description": "ZOD 'invalid_string' error message, with startsWith",
@@ -511,6 +581,11 @@
"description": "ZOD 'too_small' error message, generic",
"originalDefault": "Invalid input."
},
+ "Q6/Lj7": {
+ "defaultMessage": "Verwijder het laatst getekende punt",
+ "description": "Draw toolbar undo button tooltip.",
+ "originalDefault": "Remove last drawn point"
+ },
"QPdaOi": {
"defaultMessage": "Geen beschikbare keuzes",
"description": "Select 'no options' message",
@@ -581,6 +656,11 @@
"description": "ZOD 'too_small' error message, for strings",
"originalDefault": "String must contain {exact, select, true {exactly} other {{inclusive, select, true {at least} other {more than}}} } {minimum, plural, one {{minimum} character} other {{minimum} characters}}."
},
+ "U5+FHP": {
+ "defaultMessage": "Annuleer",
+ "description": "Edit toolbar cancel message.",
+ "originalDefault": "Cancel"
+ },
"UyEKdQ": {
"defaultMessage": "Product {number}/{total}",
"description": "Appointments: single product label/header",
@@ -627,6 +707,11 @@
"description": "ZOD 'too_big' error message, for dates",
"originalDefault": "Date must be smaller than or equal to {maximum}."
},
+ "Y3jHZm": {
+ "defaultMessage": "Verwijder laatste punt",
+ "description": "Draw toolbar undo button message.",
+ "originalDefault": "Remove last point"
+ },
"YcC4PD": {
"defaultMessage": "Taal kiezen",
"description": "Language selection heading",
@@ -678,6 +763,11 @@
"description": "Appointments: contact details step title",
"originalDefault": "Contact details"
},
+ "bRtoG6": {
+ "defaultMessage": "Verwijder alles",
+ "description": "Edit toolbar clearAll message.",
+ "originalDefault": "Remove all"
+ },
"bgfiRG": {
"defaultMessage": "Je hebt de betaling gestart.",
"description": "payment started status",
@@ -713,6 +803,11 @@
"description": "return to form start link after 403",
"originalDefault": "Back to form start"
},
+ "dNGw+S": {
+ "defaultMessage": "Klik om verder te tekenen",
+ "description": "Draw handler polygon tooltip continue.",
+ "originalDefault": "Click to continue drawing shape"
+ },
"eAmrdi": {
"defaultMessage": "Laden...",
"description": "Loading content text",
@@ -728,6 +823,11 @@
"description": "Checking background processing status title",
"originalDefault": "Processing..."
},
+ "fJVa0u": {
+ "defaultMessage": "Pin/punt",
+ "description": "Draw toolbar marker button tooltip.",
+ "originalDefault": "Marker"
+ },
"fWjfVm": {
"defaultMessage": "Een moment geduld alstublieft. De inzending wordt verwerkt.",
"description": "Checking background processing status body",
@@ -1001,6 +1101,11 @@
"description": "The leaflet map's input fields placeholder message.",
"originalDefault": "Enter address, please"
},
+ "sYb+eZ": {
+ "defaultMessage": "Verwijder alle vormen van de kaart",
+ "description": "Edit toolbar clearAll tooltip.",
+ "originalDefault": "Remove all shapes"
+ },
"senRv3": {
"defaultMessage": "Je staat op het punt je afspraak op {date} om {time} te annuleren. Vul je e-mailadres in ter controle.",
"description": "Appointment cancellation body text",
@@ -1051,11 +1156,21 @@
"description": "Appointments: product amount field label",
"originalDefault": "Amount"
},
+ "vfKvuS": {
+ "defaultMessage": "Klik op het eerste punt, om de veelhoek te voltooien",
+ "description": "Draw handler polygon tooltip end.",
+ "originalDefault": "Click first point to finish shape"
+ },
"wwsWUp": {
"defaultMessage": "Wat vind je van dit formulier?",
"description": "GovMetric snippet header",
"originalDefault": "How do you rate this form?"
},
+ "xh+7Vv": {
+ "defaultMessage": "Voltooi",
+ "description": "Draw toolbar finish button message.",
+ "originalDefault": "Finish"
+ },
"y31iyC": {
"defaultMessage": "Ongeldige letterlijke waarde, verwachtte {expected}.",
"description": "ZOD 'invalid_literal' error message",
@@ -1071,6 +1186,11 @@
"description": "Back to main website link title",
"originalDefault": "Return to main website"
},
+ "zpHAro": {
+ "defaultMessage": "Klik om een lijk te tekenen",
+ "description": "Draw handler polyline tooltip start.",
+ "originalDefault": "Click to start drawing line"
+ },
"zvoXSU": {
"defaultMessage": "Adres in de buurt: ",
"description": "Reverse geocoded address result display",
diff --git a/src/map/constants.js b/src/map/constants.js
index dd7cd2f6b..82ad32d79 100644
--- a/src/map/constants.js
+++ b/src/map/constants.js
@@ -6,5 +6,10 @@ import {CRS_RD, TILE_LAYER_RD} from '@open-formulieren/leaflet-tools';
// Roughly the center of the Netherlands
const DEFAULT_LAT_LNG = [52.1326332, 5.291266];
const DEFAULT_ZOOM = 13;
+const DEFAULT_INTERACTIONS = {
+ marker: true,
+ polygon: false,
+ polyline: false,
+};
-export {CRS_RD, DEFAULT_LAT_LNG, DEFAULT_ZOOM, TILE_LAYER_RD};
+export {CRS_RD, DEFAULT_LAT_LNG, DEFAULT_ZOOM, DEFAULT_INTERACTIONS, TILE_LAYER_RD};