aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnton Tananaev <anton@traccar.org>2022-08-01 09:08:48 -0700
committerAnton Tananaev <anton@traccar.org>2022-08-01 09:08:48 -0700
commit027f56866f4584debdef22792f0b9f1d7a545faf (patch)
tree7fe236975d3b3d8bf4eda8f41548c58cf51ede00
parent04385204c0ee230f73615224955b2b8b7a7d9c73 (diff)
downloadtrackermap-web-027f56866f4584debdef22792f0b9f1d7a545faf.tar.gz
trackermap-web-027f56866f4584debdef22792f0b9f1d7a545faf.tar.bz2
trackermap-web-027f56866f4584debdef22792f0b9f1d7a545faf.zip
Quick geofence creation
-rw-r--r--modern/src/main/StatusCard.js29
-rw-r--r--modern/src/settings/GeofencePage.js12
-rw-r--r--web/l10n/en.json1
3 files changed, 38 insertions, 4 deletions
diff --git a/modern/src/main/StatusCard.js b/modern/src/main/StatusCard.js
index 1e7b241b..373b02ab 100644
--- a/modern/src/main/StatusCard.js
+++ b/modern/src/main/StatusCard.js
@@ -30,7 +30,7 @@ import { useDeviceReadonly, useRestriction } from '../common/util/permissions';
import usePersistedState from '../common/util/usePersistedState';
import usePositionAttributes from '../common/attributes/usePositionAttributes';
import { devicesActions } from '../store';
-import { useCatch } from '../reactHelper';
+import { useCatch, useCatchCallback } from '../reactHelper';
const useStyles = makeStyles((theme) => ({
card: {
@@ -126,6 +126,32 @@ const StatusCard = ({ deviceId, onClose }) => {
setRemoving(false);
});
+ const handleGeofence = useCatchCallback(async () => {
+ const newItem = {
+ name: '',
+ area: `CIRCLE (${position.latitude} ${position.longitude}, 50)`,
+ };
+ 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();
+ const permissionResponse = await fetch('/api/permissions', {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify({ deviceId: position.deviceId, geofenceId: item.id }),
+ });
+ if (!permissionResponse.ok) {
+ throw Error(await permissionResponse.text());
+ }
+ navigate(`/settings/geofence/${item.id}`);
+ } else {
+ throw Error(await response.text());
+ }
+ }, [navigate]);
+
return (
<>
{device && (
@@ -209,6 +235,7 @@ const StatusCard = ({ deviceId, onClose }) => {
{position && (
<Menu anchorEl={anchorEl} open={Boolean(anchorEl)} onClose={() => setAnchorEl(null)}>
<MenuItem onClick={() => navigate(`/position/${position.id}`)}><Typography color="secondary">{t('sharedShowDetails')}</Typography></MenuItem>
+ <MenuItem onClick={handleGeofence}>{t('sharedCreateGeofence')}</MenuItem>
<MenuItem component="a" target="_blank" href={`https://www.google.com/maps/search/?api=1&query=${position.latitude}%2C${position.longitude}`}>{t('linkGoogleMaps')}</MenuItem>
<MenuItem component="a" target="_blank" href={`http://maps.apple.com/?ll=${position.latitude},${position.longitude}`}>{t('linkAppleMaps')}</MenuItem>
<MenuItem component="a" target="_blank" href={`https://www.google.com/maps/@?api=1&map_action=pano&viewpoint=${position.latitude}%2C${position.longitude}&heading=${position.course}`}>{t('linkStreetView')}</MenuItem>
diff --git a/modern/src/settings/GeofencePage.js b/modern/src/settings/GeofencePage.js
index 3bebea30..b6c516a1 100644
--- a/modern/src/settings/GeofencePage.js
+++ b/modern/src/settings/GeofencePage.js
@@ -1,8 +1,7 @@
import React, { useState } from 'react';
-import TextField from '@mui/material/TextField';
-
+import { useDispatch } from 'react-redux';
import {
- Accordion, AccordionSummary, AccordionDetails, Typography,
+ Accordion, AccordionSummary, AccordionDetails, Typography, TextField,
} from '@mui/material';
import makeStyles from '@mui/styles/makeStyles';
import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
@@ -12,6 +11,7 @@ import { useTranslation } from '../common/components/LocalizationProvider';
import useGeofenceAttributes from '../common/attributes/useGeofenceAttributes';
import SettingsMenu from './components/SettingsMenu';
import SelectField from '../common/components/SelectField';
+import { geofencesActions } from '../store';
const useStyles = makeStyles((theme) => ({
details: {
@@ -24,12 +24,17 @@ const useStyles = makeStyles((theme) => ({
const GeofencePage = () => {
const classes = useStyles();
+ const dispatch = useDispatch();
const t = useTranslation();
const geofenceAttributes = useGeofenceAttributes(t);
const [item, setItem] = useState();
+ const onItemSaved = (result) => {
+ dispatch(geofencesActions.update([result]));
+ };
+
const validate = () => item && item.name;
return (
@@ -38,6 +43,7 @@ const GeofencePage = () => {
item={item}
setItem={setItem}
validate={validate}
+ onItemSaved={onItemSaved}
menu={<SettingsMenu />}
breadcrumbs={['settingsTitle', 'sharedGeofence']}
>
diff --git a/web/l10n/en.json b/web/l10n/en.json
index 2549a081..3a7be25d 100644
--- a/web/l10n/en.json
+++ b/web/l10n/en.json
@@ -33,6 +33,7 @@
"sharedSearch": "Search",
"sharedGeofence": "Geofence",
"sharedGeofences": "Geofences",
+ "sharedCreateGeofence": "Create Geofence",
"sharedNotifications": "Notifications",
"sharedNotification": "Notification",
"sharedAttributes": "Attributes",