diff options
-rw-r--r-- | modern/src/map/GeofenceEditMap.js | 63 | ||||
-rw-r--r-- | modern/src/map/mapUtil.js | 12 | ||||
-rw-r--r-- | modern/src/store/geofences.js | 4 |
3 files changed, 75 insertions, 4 deletions
diff --git a/modern/src/map/GeofenceEditMap.js b/modern/src/map/GeofenceEditMap.js index 9487e97..291cab7 100644 --- a/modern/src/map/GeofenceEditMap.js +++ b/modern/src/map/GeofenceEditMap.js @@ -3,6 +3,10 @@ import MapboxDraw from '@mapbox/mapbox-gl-draw'; import { useEffect } from 'react'; import { map } from './Map'; +import { geofenceToFeature, geometryToArea } from './mapUtil'; +import { useDispatch, useSelector } from 'react-redux'; +import { geofencesActions } from '../store'; +import { useHistory } from 'react-router-dom'; const draw = new MapboxDraw({ displayControlsDefault: false, @@ -13,8 +17,67 @@ const draw = new MapboxDraw({ }); const GeofenceEditMap = () => { + const dispatch = useDispatch(); + const history = useHistory(); + + const geofences = useSelector(state => Object.values(state.geofences.items)); + + const refreshGeofences = async () => { + const response = await fetch('/api/geofences'); + if (response.ok) { + dispatch(geofencesActions.refresh(await response.json())); + } + } + useEffect(() => { + refreshGeofences(); + map.addControl(draw, 'top-left'); + + draw.deleteAll(); + for (const geofence of geofences) { + draw.add(geofenceToFeature(geofence)); + } + + map.on('draw.create', async event => { + const feature = event.features[0]; + const newItem = { name: '', area: geometryToArea(feature.geometry) }; + draw.delete(feature.id); + const response = await fetch(`/api/geofences`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(newItem), + }); + if (response.ok) { + const item = await response.json(); + history.push(`/geofence/${item.id}`); + } + }); + + map.on('draw.delete', async event => { + const feature = event.features[0]; + const response = await fetch(`/api/geofences/${feature.id}`, { method: 'DELETE' }); + if (response.ok) { + refreshGeofences(); + } + }); + + map.on('draw.update', async event => { + const feature = event.features[0]; + const item = geofences.find(i => i.id === feature.id); + if (item) { + const updatedItem = { ...item, area: geometryToArea(feature.geometry) }; + const response = await fetch(`/api/geofences/${feature.id}`, { + method: 'PUT', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(updatedItem), + }); + if (response.ok) { + refreshGeofences(); + } + } + }); + return () => map.removeControl(draw); }, []); diff --git a/modern/src/map/mapUtil.js b/modern/src/map/mapUtil.js index ef6ff99..67ce345 100644 --- a/modern/src/map/mapUtil.js +++ b/modern/src/map/mapUtil.js @@ -1,4 +1,4 @@ -import wellknown from 'wellknown'; +import { parse, stringify } from 'wellknown'; import canvasTintImage from 'canvas-tint-image'; import circle from '@turf/circle'; @@ -54,18 +54,22 @@ export const geofenceToFeature = (item) => { let coordinates = item.area.replace(/CIRCLE|\(|\)|,/g, " ").trim().split(/ +/); var options = { steps: 32, units: 'meters' }; let polygon = circle([Number(coordinates[1]), Number(coordinates[0])], Number(coordinates[2]), options); - return { + return { + id: item.id, type: 'Feature', geometry: polygon.geometry, properties: { name: item.name } }; } else { return { + id: item.id, type: 'Feature', - geometry: reverseCoordinates(wellknown(item.area)), + geometry: reverseCoordinates(parse(item.area)), properties: { name: item.name } }; } } - +export const geometryToArea = (geometry) => { + return stringify(reverseCoordinates(geometry)); +} diff --git a/modern/src/store/geofences.js b/modern/src/store/geofences.js index c5e5814..504b7d0 100644 --- a/modern/src/store/geofences.js +++ b/modern/src/store/geofences.js @@ -6,6 +6,10 @@ const { reducer, actions } = createSlice({ items: {}, }, reducers: { + refresh(state, action) { + state.items = {}; + action.payload.forEach(item => state.items[item['id']] = item); + }, update(state, action) { action.payload.forEach(item => state.items[item['id']] = item); }, |