1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
|
import 'mapbox-gl/dist/mapbox-gl.css';
import '@mapbox/mapbox-gl-draw/dist/mapbox-gl-draw.css';
import MapboxDraw from '@mapbox/mapbox-gl-draw';
import theme from '@mapbox/mapbox-gl-draw/src/lib/theme';
import { useCallback, useEffect } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { useHistory } from 'react-router-dom';
import { map } from './core/Map';
import { geofenceToFeature, geometryToArea } from './core/mapUtil';
import { geofencesActions } from '../store';
const draw = new MapboxDraw({
displayControlsDefault: false,
controls: {
polygon: true,
trash: true,
},
userProperties: true,
styles: [...theme, {
id: 'gl-draw-title',
type: 'symbol',
filter: ['all'],
layout: {
'text-field': '{user_name}',
'text-font': ['Roboto Regular'],
'text-size': 12,
},
paint: {
'text-halo-color': 'white',
'text-halo-width': 1,
},
}],
});
const GeofenceEditMap = () => {
const dispatch = useDispatch();
const history = useHistory();
const geofences = useSelector((state) => state.geofences.items);
const refreshGeofences = useCallback(async () => {
const response = await fetch('/api/geofences');
if (response.ok) {
dispatch(geofencesActions.refresh(await response.json()));
}
}, [dispatch]);
useEffect(() => {
refreshGeofences();
map.addControl(draw, 'top-left');
return () => map.removeControl(draw);
}, [refreshGeofences]);
useEffect(() => {
const listener = 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.create', listener);
return () => map.off('draw.create', listener);
}, [history]);
useEffect(() => {
const listener = async (event) => {
const feature = event.features[0];
const response = await fetch(`/api/geofences/${feature.id}`, { method: 'DELETE' });
if (response.ok) {
refreshGeofences();
}
};
map.on('draw.delete', listener);
return () => map.off('draw.delete', listener);
}, [refreshGeofences]);
useEffect(() => {
const listener = async (event) => {
const feature = event.features[0];
const item = Object.values(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();
}
}
};
map.on('draw.update', listener);
return () => map.off('draw.update', listener);
}, [geofences, refreshGeofences]);
useEffect(() => {
draw.deleteAll();
Object.values(geofences).forEach((geofence) => {
draw.add(geofenceToFeature(geofence));
});
}, [geofences]);
return null;
};
export default GeofenceEditMap;
|