diff --git a/src/components/Map/Map.stories.jsx b/src/components/Map/Map.stories.jsx index c69372051..d1b5cde9a 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, within} from '@storybook/test'; +import {useState} from 'react'; import {ConfigDecorator} from 'story-utils/decorators'; @@ -11,10 +12,24 @@ 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: { geoJsonFeature: { type: 'Feature', @@ -66,3 +81,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: { + geoJsonFeature: undefined, + interactions: { + circle: true, + 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 circle')).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', + coordinates: [4.839249, 52.387153], + }, + }); + }); + }, +}; diff --git a/src/components/Map/index.jsx b/src/components/Map/index.jsx index c2c34726c..594a2b179 100644 --- a/src/components/Map/index.jsx +++ b/src/components/Map/index.jsx @@ -10,7 +10,13 @@ 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'; @@ -69,6 +75,7 @@ const LeaftletMap = ({ defaultCenter = DEFAULT_LAT_LNG, defaultZoomLevel = DEFAULT_ZOOM, disabled = false, + interactions = DEFAULT_INTERACTIONS, tileLayerUrl = TILE_LAYER_RD.url, }) => { const featureGroupRef = useRef(); @@ -127,10 +134,10 @@ const LeaftletMap = ({ }} draw={{ rectangle: false, - circle: true, - polyline: true, - polygon: true, - marker: true, + circle: !!interactions?.circle, + polyline: !!interactions?.polyline, + polygon: !!interactions?.polygon, + marker: !!interactions?.marker, circlemarker: false, }} /> @@ -184,6 +191,12 @@ LeaftletMap.propTypes = { ]).isRequired, }), onGeoJsonFeatureSet: PropTypes.func, + interactions: PropTypes.shape({ + circle: PropTypes.bool, + polyline: PropTypes.bool, + polygon: PropTypes.bool, + marker: PropTypes.bool, + }), disabled: PropTypes.bool, tileLayerUrl: PropTypes.string, }; diff --git a/src/formio/components/Map.jsx b/src/formio/components/Map.jsx index f31a57b10..28ac93a92 100644 --- a/src/formio/components/Map.jsx +++ b/src/formio/components/Map.jsx @@ -115,6 +115,7 @@ export default class Map extends Field { onGeoJsonFeatureSet={this.onGeoJsonSet.bind(this)} defaultCenter={defaultCenter} defaultZoomLevel={zoom || DEFAULT_ZOOM} + interactions={this.component?.interactions} tileLayerUrl={this.component.tileLayerUrl} /> diff --git a/src/map/constants.js b/src/map/constants.js index dd7cd2f6b..d86bbb60f 100644 --- a/src/map/constants.js +++ b/src/map/constants.js @@ -6,5 +6,11 @@ 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, + circle: 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};