aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--modern/src/map/GeofenceEditMap.js63
-rw-r--r--modern/src/map/mapUtil.js12
-rw-r--r--modern/src/store/geofences.js4
3 files changed, 75 insertions, 4 deletions
diff --git a/modern/src/map/GeofenceEditMap.js b/modern/src/map/GeofenceEditMap.js
index 9487e97c..291cab75 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 ef6ff995..67ce345e 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 c5e58147..504b7d02 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);
},