From 26916278758cd5e4abb16aa31e31099e066ea8d5 Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Sun, 27 Jun 2021 11:08:26 -0700 Subject: Add geofences screen --- modern/src/App.js | 4 ++ modern/src/EditCollectionView.js | 4 +- modern/src/GeofencePage.js | 61 ++++++++++++++++++++++++++ modern/src/GeofencesList.js | 58 +++++++++++++++++++++++++ modern/src/GeofencesPage.js | 66 +++++++++++++++++++++++++++++ modern/src/MainToolbar.js | 7 +++ modern/src/attributes/geofenceAttributes.js | 8 ++++ modern/src/map/GeofenceMap.js | 13 ++---- 8 files changed, 209 insertions(+), 12 deletions(-) create mode 100644 modern/src/GeofencePage.js create mode 100644 modern/src/GeofencesList.js create mode 100644 modern/src/GeofencesPage.js create mode 100644 modern/src/attributes/geofenceAttributes.js diff --git a/modern/src/App.js b/modern/src/App.js index 3641339e..b76995ea 100644 --- a/modern/src/App.js +++ b/modern/src/App.js @@ -36,6 +36,8 @@ import RegisterForm from './components/registration/RegisterForm'; import ResetPasswordForm from './components/registration/ResetPasswordForm'; import theme from './theme'; +import GeofencesPage from './GeofencesPage'; +import GeofencePage from './GeofencePage'; const App = () => { const initialized = useSelector(state => !!state.session.server && !!state.session.user); @@ -57,6 +59,8 @@ const App = () => { + + diff --git a/modern/src/EditCollectionView.js b/modern/src/EditCollectionView.js index d3d0af17..572a1d19 100644 --- a/modern/src/EditCollectionView.js +++ b/modern/src/EditCollectionView.js @@ -18,7 +18,7 @@ const useStyles = makeStyles(theme => ({ }, })); -const EditCollectionView = ({ content, editPath, endpoint }) => { +const EditCollectionView = ({ content, editPath, endpoint, disableAdd }) => { const classes = useStyles(); const history = useHistory(); @@ -62,7 +62,7 @@ const EditCollectionView = ({ content, editPath, endpoint }) => { return ( <> - {adminEnabled && + {adminEnabled && !disableAdd && diff --git a/modern/src/GeofencePage.js b/modern/src/GeofencePage.js new file mode 100644 index 00000000..6c5db9bb --- /dev/null +++ b/modern/src/GeofencePage.js @@ -0,0 +1,61 @@ +import React, { useState } from 'react'; +import TextField from '@material-ui/core/TextField'; + +import t from './common/localization'; +import EditItemView from './EditItemView'; +import { Accordion, AccordionSummary, AccordionDetails, makeStyles, Typography } from '@material-ui/core'; +import ExpandMoreIcon from '@material-ui/icons/ExpandMore'; +import EditAttributesView from './attributes/EditAttributesView'; +import geofenceAttributes from './attributes/geofenceAttributes'; + +const useStyles = makeStyles(() => ({ + details: { + flexDirection: 'column', + }, +})); + +const GeofencePage = () => { + const classes = useStyles(); + + const [item, setItem] = useState(); + + return ( + + {item && + <> + + }> + + {t('sharedRequired')} + + + + setItem({...item, name: event.target.value})} + label={t('sharedName')} + variant="filled" /> + + + + }> + + {t('sharedAttributes')} + + + + setItem({...item, attributes})} + definitions={geofenceAttributes} + /> + + + + } + + ); +} + +export default GeofencePage; diff --git a/modern/src/GeofencesList.js b/modern/src/GeofencesList.js new file mode 100644 index 00000000..2988bef1 --- /dev/null +++ b/modern/src/GeofencesList.js @@ -0,0 +1,58 @@ +import React, { Fragment } from 'react'; +import { useDispatch, useSelector } from 'react-redux'; +import { makeStyles } from '@material-ui/core/styles'; +import Divider from '@material-ui/core/Divider'; +import IconButton from '@material-ui/core/IconButton'; +import List from '@material-ui/core/List'; +import ListItem from '@material-ui/core/ListItem'; +import ListItemSecondaryAction from '@material-ui/core/ListItemSecondaryAction'; +import ListItemText from '@material-ui/core/ListItemText'; +import MoreVertIcon from '@material-ui/icons/MoreVert'; + +import { devicesActions } from './store'; +import EditCollectionView from './EditCollectionView'; + +const useStyles = makeStyles(() => ({ + list: { + maxHeight: '100%', + overflow: 'auto', + }, + icon: { + width: '25px', + height: '25px', + filter: 'brightness(0) invert(1)', + }, +})); + +const GeofenceView = ({ onMenuClick }) => { + const classes = useStyles(); + const dispatch = useDispatch(); + + const items = useSelector(state => Object.values(state.geofences.items)); + + return ( + + {items.map((item, index, list) => ( + + dispatch(devicesActions.select(item))}> + + + onMenuClick(event.currentTarget, item.id)}> + + + + + {index < list.length - 1 ? : null} + + ))} + + ); +} + +const GeofencesList = () => { + return ( + + ); +} + +export default GeofencesList; diff --git a/modern/src/GeofencesPage.js b/modern/src/GeofencesPage.js new file mode 100644 index 00000000..389ac998 --- /dev/null +++ b/modern/src/GeofencesPage.js @@ -0,0 +1,66 @@ +import React from 'react'; +import { isWidthUp, makeStyles, withWidth } from '@material-ui/core'; +import Drawer from '@material-ui/core/Drawer'; +import ContainerDimensions from 'react-container-dimensions'; +import MainToolbar from './MainToolbar'; +import Map from './map/Map'; +import CurrentLocationMap from './map/CurrentLocationMap'; +import GeofenceEditMap from './map/GeofenceEditMap'; +import GeofencesList from './GeofencesList'; + +const useStyles = makeStyles(theme => ({ + root: { + height: '100%', + display: 'flex', + flexDirection: 'column', + }, + content: { + flexGrow: 1, + overflow: 'hidden', + display: 'flex', + flexDirection: 'row', + [theme.breakpoints.down('xs')]: { + flexDirection: 'column-reverse', + } + }, + drawerPaper: { + position: 'relative', + [theme.breakpoints.up('sm')]: { + width: 350, + }, + [theme.breakpoints.down('xs')]: { + height: 250, + } + }, + mapContainer: { + flexGrow: 1, + }, +})); + +const GeofencesPage = ({ width }) => { + const classes = useStyles(); + + return ( +
+ +
+ + + +
+ + + + + + +
+
+
+ ); +} + +export default withWidth()(GeofencesPage); diff --git a/modern/src/MainToolbar.js b/modern/src/MainToolbar.js index 63d8efec..064507fb 100644 --- a/modern/src/MainToolbar.js +++ b/modern/src/MainToolbar.js @@ -24,6 +24,7 @@ import PersonIcon from '@material-ui/icons/Person'; import NotificationsIcon from '@material-ui/icons/Notifications'; import DescriptionIcon from '@material-ui/icons/Description'; import FolderIcon from '@material-ui/icons/Folder'; +import CreateIcon from '@material-ui/icons/Create'; import ReplayIcon from '@material-ui/icons/Replay'; import BuildIcon from '@material-ui/icons/Build'; import t from './common/localization'; @@ -119,6 +120,12 @@ const MainToolbar = () => { + history.push('/geofences')}> + + + + + history.push('/settings/notifications')}> diff --git a/modern/src/attributes/geofenceAttributes.js b/modern/src/attributes/geofenceAttributes.js new file mode 100644 index 00000000..4b9c9e63 --- /dev/null +++ b/modern/src/attributes/geofenceAttributes.js @@ -0,0 +1,8 @@ +import t from '../common/localization' + +export default { + 'speedLimit': { + name: t('attributeSpeedLimit'), + type: 'string', + }, +}; diff --git a/modern/src/map/GeofenceMap.js b/modern/src/map/GeofenceMap.js index c98a8c16..8db175a2 100644 --- a/modern/src/map/GeofenceMap.js +++ b/modern/src/map/GeofenceMap.js @@ -1,20 +1,13 @@ -import { useEffect, useState } from 'react'; +import { useEffect } from 'react'; +import { useSelector } from 'react-redux'; import { map } from './Map'; -import { useEffectAsync } from '../reactHelper'; import { geofenceToFeature } from './mapUtil'; const GeofenceMap = () => { const id = 'geofences'; - const [geofences, setGeofences] = useState([]); - - useEffectAsync(async () => { - const response = await fetch('/api/geofences'); - if (response.ok) { - setGeofences(await response.json()); - } - }, []); + const geofences = useSelector(state => Object.values(state.geofences.items)); useEffect(() => { map.addSource(id, { -- cgit v1.2.3