diff --git a/src/components/Map/Map.stories.jsx b/src/components/Map/Map.stories.jsx index 76b75272d..c69372051 100644 --- a/src/components/Map/Map.stories.jsx +++ b/src/components/Map/Map.stories.jsx @@ -16,7 +16,14 @@ export default { component: LeafletMap, decorators: [withMapLayout, ConfigDecorator], 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, diff --git a/src/components/Map/index.jsx b/src/components/Map/index.jsx index 77883cd8f..c2c34726c 100644 --- a/src/components/Map/index.jsx +++ b/src/components/Map/index.jsx @@ -1,8 +1,12 @@ +import * as Leaflet from 'leaflet'; +import 'leaflet-draw/dist/leaflet.draw.css'; import {GeoSearchControl} from 'leaflet-geosearch'; +import 'leaflet/dist/leaflet.css'; import PropTypes from 'prop-types'; -import React, {useContext, useEffect} from 'react'; +import React, {useContext, useEffect, useRef} from 'react'; import {defineMessages, useIntl} from 'react-intl'; -import {MapContainer, TileLayer, useMap} from 'react-leaflet'; +import {FeatureGroup, MapContainer, TileLayer, useMap} from 'react-leaflet'; +import {EditControl} from 'react-leaflet-draw'; import {useGeolocation} from 'react-use'; import {ConfigContext} from 'Context'; @@ -60,20 +64,39 @@ const useDefaultCoordinates = () => { }; const LeaftletMap = ({ - markerCoordinates, - onMarkerSet, + geoJsonFeature, + onGeoJsonFeatureSet, defaultCenter = DEFAULT_LAT_LNG, defaultZoomLevel = DEFAULT_ZOOM, disabled = false, tileLayerUrl = TILE_LAYER_RD.url, }) => { + const featureGroupRef = useRef(); const intl = useIntl(); const defaultCoordinates = useDefaultCoordinates(); - const coordinates = markerCoordinates || defaultCoordinates; + const coordinates = defaultCoordinates; const modifiers = disabled ? ['disabled'] : []; const className = getBEMClassName('leaflet-map', modifiers); + const onFeatureCreate = event => { + // Remove the old layers and add the new one. + // This limits the amount of features to 1 + const newLayer = event.layer; + featureGroupRef.current?.clearLayers(); + featureGroupRef.current?.addLayer(newLayer); + + onGeoJsonFeatureSet(featureGroupRef.current?.toGeoJSON()); + }; + + useEffect(() => { + if (!featureGroupRef.current) { + return; + } + featureGroupRef.current?.clearLayers(); + Leaflet.geoJSON(geoJsonFeature).addTo(featureGroupRef.current); + }, [geoJsonFeature, featureGroupRef.current]); + return ( <> + + + {coordinates ? ( <> ) : null} console.log('TODO')} options={{ showMarker: false, showPopup: false, @@ -115,16 +156,34 @@ const LeaftletMap = ({ /> {/*{disabled ? : }*/} - {markerCoordinates && markerCoordinates.length && ( - - )} + {/*{markerCoordinates && markerCoordinates.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, disabled: PropTypes.bool, tileLayerUrl: PropTypes.string, }; diff --git a/src/formio/components/Map.jsx b/src/formio/components/Map.jsx index dc81cac93..f31a57b10 100644 --- a/src/formio/components/Map.jsx +++ b/src/formio/components/Map.jsx @@ -91,7 +91,7 @@ export default class Map extends Field { super.destroy(); } - onMarkerSet(newLatLng) { + onGeoJsonSet(newLatLng) { this.setValue(newLatLng, {modified: true}); } @@ -100,7 +100,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; @@ -111,8 +111,8 @@ export default class Map extends Field {