From 17fab62eb9b8e810de7a4ba9484c3a74e59e4fdd Mon Sep 17 00:00:00 2001 From: Desmond Kyeremeh Date: Thu, 1 Jul 2021 02:50:29 +0000 Subject: fixed: login screen sidebar not shrinking on tablet --- modern/src/StartPage.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'modern/src') diff --git a/modern/src/StartPage.js b/modern/src/StartPage.js index 0a08617..53f8c35 100644 --- a/modern/src/StartPage.js +++ b/modern/src/StartPage.js @@ -16,7 +16,7 @@ const useStyles = makeStyles(theme => ({ paddingBottom: theme.spacing(5), width: theme.dimensions.sidebarWidth, [theme.breakpoints.down('md')]: { - width: theme.dimensions.tabletSidebarWidth, + width: theme.dimensions.sidebarWidthTablet, }, [theme.breakpoints.down('xs')]: { width: '0px', -- cgit v1.2.3 From ca5d34826de5596e91d1b3f6421e6399b617d204 Mon Sep 17 00:00:00 2001 From: Desmond Kyeremeh Date: Thu, 1 Jul 2021 02:59:01 +0000 Subject: Report filter: Always show buttons on the right side --- modern/src/reports/ReportFilter.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'modern/src') diff --git a/modern/src/reports/ReportFilter.js b/modern/src/reports/ReportFilter.js index b9817d5..868b866 100644 --- a/modern/src/reports/ReportFilter.js +++ b/modern/src/reports/ReportFilter.js @@ -56,7 +56,7 @@ const ReportFilter = ({ children, handleSubmit, showOnly }) => { } return ( - + {t('reportDevice')} -- cgit v1.2.3 From 36d05b64fbcd52760e023af227748b2efd74d21f Mon Sep 17 00:00:00 2001 From: Desmond Kyeremeh Date: Thu, 1 Jul 2021 13:53:44 +0000 Subject: Abstract ReportSidebar into SideNav component --- modern/src/components/SideNav.js | 41 ++++++++++++++++++++++++++ modern/src/components/reports/ReportSidebar.js | 29 ------------------ 2 files changed, 41 insertions(+), 29 deletions(-) create mode 100644 modern/src/components/SideNav.js delete mode 100644 modern/src/components/reports/ReportSidebar.js (limited to 'modern/src') diff --git a/modern/src/components/SideNav.js b/modern/src/components/SideNav.js new file mode 100644 index 0000000..669c79a --- /dev/null +++ b/modern/src/components/SideNav.js @@ -0,0 +1,41 @@ +import React from 'react'; +import { + List, + ListItem, + ListItemText, + ListItemIcon, + Divider, + ListSubheader +} from '@material-ui/core'; +import { Link, useLocation } from 'react-router-dom'; + +const SideNav = ({ routes }) => { + const location = useLocation(); + + return ( + + {routes.map((route, index) => + route.subheader ? ( + <> + + {route.subheader} + + ) : ( + + {route.icon} + + + ) + )} + + ); +}; + +export default SideNav; diff --git a/modern/src/components/reports/ReportSidebar.js b/modern/src/components/reports/ReportSidebar.js deleted file mode 100644 index 90e20c0..0000000 --- a/modern/src/components/reports/ReportSidebar.js +++ /dev/null @@ -1,29 +0,0 @@ -import React from 'react'; -import { List, ListItem, ListItemText, ListItemIcon } from '@material-ui/core'; -import { Link, useLocation } from 'react-router-dom'; - -const ReportSidebar = ({ routes }) => { - - const location = useLocation(); - - return ( - - {routes.map((route, index) => ( - - - {route.icon} - - - - ))} - - ) -} - -export default ReportSidebar; -- cgit v1.2.3 From 69d7c4feead09434914fdad109eb02e12c15cb89 Mon Sep 17 00:00:00 2001 From: Desmond Kyeremeh Date: Thu, 1 Jul 2021 13:54:49 +0000 Subject: Abstract ReportNavBar into NavBar --- modern/src/components/NavBar.js | 23 +++++++++++++++++++++++ modern/src/components/reports/ReportNavbar.js | 26 -------------------------- 2 files changed, 23 insertions(+), 26 deletions(-) create mode 100644 modern/src/components/NavBar.js delete mode 100644 modern/src/components/reports/ReportNavbar.js (limited to 'modern/src') diff --git a/modern/src/components/NavBar.js b/modern/src/components/NavBar.js new file mode 100644 index 0000000..68e38bf --- /dev/null +++ b/modern/src/components/NavBar.js @@ -0,0 +1,23 @@ +import React from 'react'; +import { AppBar, Toolbar, Typography, IconButton } from '@material-ui/core'; +import MenuIcon from '@material-ui/icons/Menu'; + +const Navbar = ({ setOpenDrawer, title }) => ( + + + setOpenDrawer(true)} + > + + + + {title} + + + +); + +export default Navbar; diff --git a/modern/src/components/reports/ReportNavbar.js b/modern/src/components/reports/ReportNavbar.js deleted file mode 100644 index ac01fad..0000000 --- a/modern/src/components/reports/ReportNavbar.js +++ /dev/null @@ -1,26 +0,0 @@ -import React from 'react'; -import { AppBar, Toolbar, Typography, IconButton } from '@material-ui/core'; -import MenuIcon from '@material-ui/icons/Menu'; -import t from '../../common/localization'; - -const ReportNavbar = ({ setOpenDrawer, reportTitle }) => { - - return ( - - - setOpenDrawer(true)}> - - - - {t('reportTitle')} {` / ${reportTitle}`} - - - - ) -} - -export default ReportNavbar; -- cgit v1.2.3 From 8b1c7bb055ceeb4d3e95d7ab3b8fbe7aa1f8dfa7 Mon Sep 17 00:00:00 2001 From: Desmond Kyeremeh Date: Thu, 1 Jul 2021 13:55:52 +0000 Subject: Moved some selectors into separate file --- modern/src/MainToolbar.js | 75 ++++++++++++++++++++++++++++------------------- modern/src/selectors.js | 3 ++ 2 files changed, 48 insertions(+), 30 deletions(-) create mode 100644 modern/src/selectors.js (limited to 'modern/src') diff --git a/modern/src/MainToolbar.js b/modern/src/MainToolbar.js index 064507f..c11ca96 100644 --- a/modern/src/MainToolbar.js +++ b/modern/src/MainToolbar.js @@ -28,21 +28,22 @@ 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'; +import * as selectors from './selectors' const useStyles = makeStyles(theme => ({ flex: { flexGrow: 1 }, appBar: { - zIndex: theme.zIndex.drawer + 1, + zIndex: theme.zIndex.drawer + 1 }, list: { width: 250 }, menuButton: { marginLeft: -12, - marginRight: 20, - }, + marginRight: 20 + } })); const MainToolbar = () => { @@ -50,11 +51,15 @@ const MainToolbar = () => { const [drawer, setDrawer] = useState(false); const classes = useStyles(); const history = useHistory(); - const adminEnabled = useSelector(state => state.session.user && state.session.user.administrator); - const userId = useSelector(state => state.session.user && state.session.user.id); + const adminEnabled = useSelector(selectors.getIsAdmin); + const userId = useSelector(selectors.getUserId); - const openDrawer = () => { setDrawer(true) } - const closeDrawer = () => { setDrawer(false) } + const openDrawer = () => { + setDrawer(true); + }; + const closeDrawer = () => { + setDrawer(false); + }; const handleLogout = async () => { const response = await fetch('/api/session', { method: 'DELETE' }); @@ -62,7 +67,7 @@ const MainToolbar = () => { dispatch(sessionActions.updateUser(null)); history.push('/login'); } - } + }; return ( <> @@ -71,13 +76,16 @@ const MainToolbar = () => { + onClick={openDrawer} + > Traccar - + @@ -86,7 +94,8 @@ const MainToolbar = () => { className={classes.list} role="button" onClick={closeDrawer} - onKeyDown={closeDrawer}> + onKeyDown={closeDrawer} + > history.push('/')}> @@ -105,16 +114,15 @@ const MainToolbar = () => { - + - - {t('settingsTitle')} - - }> - history.push(`/user/${userId}`)}> + {t('settingsTitle')}}> + history.push(`/user/${userId}`)} + > @@ -126,7 +134,10 @@ const MainToolbar = () => { - history.push('/settings/notifications')}> + history.push('/settings/notifications')} + > @@ -144,13 +155,19 @@ const MainToolbar = () => { - history.push('/settings/attributes')}> + history.push('/settings/attributes')} + > - history.push('/settings/maintenances')}> + history.push('/settings/maintenances')} + > @@ -160,12 +177,7 @@ const MainToolbar = () => { {adminEnabled && ( <> - - {t('userAdmin')} - - }> + {t('userAdmin')}}> history.push('/admin/server')}> @@ -178,7 +190,10 @@ const MainToolbar = () => { - history.push('/admin/statistics')}> + history.push('/admin/statistics')} + > @@ -191,6 +206,6 @@ const MainToolbar = () => { ); -} +}; export default MainToolbar; diff --git a/modern/src/selectors.js b/modern/src/selectors.js new file mode 100644 index 0000000..f0b08f5 --- /dev/null +++ b/modern/src/selectors.js @@ -0,0 +1,3 @@ +export const getIsAdmin = state => state.session.user?.administrator; + +export const getUserId = state => state.session.user?.id; -- cgit v1.2.3 From 7e495f2d557ca738460c1031302929ae075f0399 Mon Sep 17 00:00:00 2001 From: Desmond Kyeremeh Date: Thu, 1 Jul 2021 14:01:14 +0000 Subject: Renamed ReportLayoutPage to ReportLayout --- modern/src/admin/StatisticsPage.js | 6 +- modern/src/reports/ChartReportPage.js | 6 +- modern/src/reports/EventReportPage.js | 6 +- modern/src/reports/ReportLayout.js | 144 ++++++++++++++++++++++++++++++++ modern/src/reports/ReportLayoutPage.js | 124 --------------------------- modern/src/reports/RouteReportPage.js | 6 +- modern/src/reports/StopReportPage.js | 6 +- modern/src/reports/SummaryReportPage.js | 6 +- modern/src/reports/TripReportPage.js | 6 +- 9 files changed, 165 insertions(+), 145 deletions(-) create mode 100644 modern/src/reports/ReportLayout.js delete mode 100644 modern/src/reports/ReportLayoutPage.js (limited to 'modern/src') diff --git a/modern/src/admin/StatisticsPage.js b/modern/src/admin/StatisticsPage.js index 1e440a4..0137a1f 100644 --- a/modern/src/admin/StatisticsPage.js +++ b/modern/src/admin/StatisticsPage.js @@ -3,7 +3,7 @@ import React, { useState } from 'react'; import { FormControl, InputLabel,Select, MenuItem, TextField, Button, TableContainer, Table, TableRow, TableCell, TableHead, TableBody, Paper } from '@material-ui/core'; import t from '../common/localization'; import { formatDate } from '../common/formatter'; -import ReportLayoutPage from '../reports/ReportLayoutPage'; +import ReportLayout from '../reports/ReportLayout'; import moment from 'moment'; const Filter = ({ setItems }) => { @@ -96,7 +96,7 @@ const StatisticsPage = () => { const [items, setItems] = useState([]); return ( - }> + }> @@ -131,7 +131,7 @@ const StatisticsPage = () => {
-
+ ); } diff --git a/modern/src/reports/ChartReportPage.js b/modern/src/reports/ChartReportPage.js index 0a5c8e1..8eeedc4 100644 --- a/modern/src/reports/ChartReportPage.js +++ b/modern/src/reports/ChartReportPage.js @@ -1,6 +1,6 @@ import React, { useState } from 'react'; import { Grid, FormControl, InputLabel, Select, MenuItem } from '@material-ui/core'; -import ReportLayoutPage from './ReportLayoutPage'; +import ReportLayout from './ReportLayout'; import ReportFilter from './ReportFilter'; import Graph from './Graph'; import { useAttributePreference } from '../common/preferences'; @@ -61,13 +61,13 @@ const ChartReportPage = () => { const [type, setType] = useState('speed'); return ( - }> - + ) } diff --git a/modern/src/reports/EventReportPage.js b/modern/src/reports/EventReportPage.js index 6d80860..b938dc8 100644 --- a/modern/src/reports/EventReportPage.js +++ b/modern/src/reports/EventReportPage.js @@ -5,7 +5,7 @@ import { useTheme } from "@material-ui/core/styles"; import { useSelector } from 'react-redux'; import { formatDate } from '../common/formatter'; import ReportFilter from './ReportFilter'; -import ReportLayoutPage from './ReportLayoutPage'; +import ReportLayout from './ReportLayout'; import { prefixString } from '../common/stringUtils'; import t from '../common/localization'; @@ -99,13 +99,13 @@ const EventReportPage = () => { }]; return ( - }> + }> - + ); } diff --git a/modern/src/reports/ReportLayout.js b/modern/src/reports/ReportLayout.js new file mode 100644 index 0000000..5b54335 --- /dev/null +++ b/modern/src/reports/ReportLayout.js @@ -0,0 +1,144 @@ +import React, { useState, useEffect } from 'react'; +import { useHistory, useLocation } from 'react-router-dom'; +import { + Grid, + Typography, + Divider, + Drawer, + makeStyles, + IconButton, + Hidden +} from '@material-ui/core'; +import TimelineIcon from '@material-ui/icons/Timeline'; +import PauseCircleFilledIcon from '@material-ui/icons/PauseCircleFilled'; +import PlayCircleFilledIcon from '@material-ui/icons/PlayCircleFilled'; +import NotificationsActiveIcon from '@material-ui/icons/NotificationsActive'; +import FormatListBulletedIcon from '@material-ui/icons/FormatListBulleted'; +import TrendingUpIcon from '@material-ui/icons/TrendingUp'; +import ArrowBackIcon from '@material-ui/icons/ArrowBack'; + +import SideNav from '../components/SideNav'; +import NavBar from '../components/NavBar'; +import t from '../common/localization'; + +const useStyles = makeStyles(theme => ({ + root: { + display: 'flex', + height: '100%' + }, + drawerContainer: { + width: theme.dimensions.drawerWidthDesktop + }, + drawer: { + width: theme.dimensions.drawerWidthDesktop, + [theme.breakpoints.down('md')]: { + width: theme.dimensions.drawerWidthTablet + } + }, + content: { + flex: 1, + padding: theme.spacing(5, 3, 3, 3) + }, + drawerHeader: { + ...theme.mixins.toolbar, + display: 'flex', + alignItems: 'center', + padding: theme.spacing(0, 1) + }, + toolbar: { + [theme.breakpoints.down('md')]: { + ...theme.mixins.toolbar + } + } +})); + +const routes = [ + { name: t('reportRoute'), href: '/reports/route', icon: }, + { + name: t('reportEvents'), + href: '/reports/event', + icon: + }, + { + name: t('reportTrips'), + href: '/reports/trip', + icon: + }, + { + name: t('reportStops'), + href: '/reports/stop', + icon: + }, + { + name: t('reportSummary'), + href: '/reports/summary', + icon: + }, + { name: t('reportChart'), href: '/reports/chart', icon: } +]; + +const ReportLayout = ({ children, filter }) => { + const classes = useStyles(); + const history = useHistory(); + const location = useLocation(); + const [openDrawer, setOpenDrawer] = useState(false); + const [reportTitle, setReportTitle] = useState(); + + useEffect(() => { + routes.forEach(route => { + switch (location.pathname) { + case `${route.href}`: + setReportTitle(route.name); + break; + default: + break; + } + }); + }, [location]); + + const pageTitle = `${t('reportTitle')} / ${reportTitle}`; + + return ( +
+ + + setOpenDrawer(!openDrawer)} + classes={{ paper: classes.drawer }} + > + + + + + +
+ history.push('/')} + > + + + + {t('reportTitle')} + +
+ + +
+
+
+
+ + {filter} + {children} + +
+
+ ); +}; + +export default ReportLayout; diff --git a/modern/src/reports/ReportLayoutPage.js b/modern/src/reports/ReportLayoutPage.js deleted file mode 100644 index 6bab67c..0000000 --- a/modern/src/reports/ReportLayoutPage.js +++ /dev/null @@ -1,124 +0,0 @@ -import React, { useState, useEffect } from 'react'; -import { useHistory, useLocation } from 'react-router-dom'; -import { Grid, Typography, Divider, Drawer, makeStyles, IconButton, Hidden } from '@material-ui/core'; -import TimelineIcon from '@material-ui/icons/Timeline'; -import PauseCircleFilledIcon from '@material-ui/icons/PauseCircleFilled'; -import PlayCircleFilledIcon from '@material-ui/icons/PlayCircleFilled'; -import NotificationsActiveIcon from '@material-ui/icons/NotificationsActive'; -import FormatListBulletedIcon from '@material-ui/icons/FormatListBulleted'; -import TrendingUpIcon from '@material-ui/icons/TrendingUp'; -import ArrowBackIcon from '@material-ui/icons/ArrowBack'; - -import ReportSidebar from '../components/reports/ReportSidebar' -import ReportNavbar from '../components/reports/ReportNavbar' -import t from '../common/localization'; - -const useStyles = makeStyles(theme => ({ - root: { - display: 'flex', - height: '100%', - }, - drawerContainer: { - width: theme.dimensions.drawerWidthDesktop, - }, - drawer: { - width: theme.dimensions.drawerWidthDesktop, - [theme.breakpoints.down("md")]: { - width: theme.dimensions.drawerWidthTablet, - } - }, - content: { - flex: 1, - padding: theme.spacing(5, 3, 3, 3), - }, - drawerHeader: { - ...theme.mixins.toolbar, - display: 'flex', - alignItems: 'center', - padding: theme.spacing(0, 1), - }, - backArrowIconContainer: { - '&:hover': { - backgroundColor:"transparent" - } - }, - toolbar: { - [theme.breakpoints.down("md")]: { - ...theme.mixins.toolbar, - } - }, -})); - -const routes = [ - { name: t('reportRoute'), href: '/reports/route', icon: }, - { name: t('reportEvents'), href: '/reports/event', icon: }, - { name: t('reportTrips'), href: '/reports/trip', icon: }, - { name: t('reportStops'), href: '/reports/stop', icon: }, - { name: t('reportSummary'), href: '/reports/summary', icon: }, - { name: t('reportChart'), href: '/reports/chart', icon: }, -]; - -const ReportLayoutPage = ({ children, filter, }) => { - const classes = useStyles(); - const history = useHistory(); - const location = useLocation(); - const [openDrawer, setOpenDrawer] = useState(false); - const [reportTitle, setReportTitle] = useState(); - - useEffect(() => { - routes.forEach(route => { - switch (location.pathname) { - case `${route.href}`: - setReportTitle(route.name); - break; - default: - break; - } - }); - }, [location]); - - return ( -
- - - setOpenDrawer(!openDrawer)} - classes={{paper: classes.drawer}}> - - - - -
- -
- history.push('/')} - className={classes.backArrowIconContainer} - disableRipple> - - - - {t('reportTitle')} - -
- - -
-
-
-
-
- - {filter} - {children} - -
-
- ); -} - -export default ReportLayoutPage; diff --git a/modern/src/reports/RouteReportPage.js b/modern/src/reports/RouteReportPage.js index 04b513e..c09d4f5 100644 --- a/modern/src/reports/RouteReportPage.js +++ b/modern/src/reports/RouteReportPage.js @@ -4,7 +4,7 @@ import { DataGrid } from '@material-ui/data-grid'; import { useTheme } from "@material-ui/core/styles"; import { formatDistance, formatSpeed, formatBoolean, formatDate, formatCoordinate } from '../common/formatter'; import ReportFilter from './ReportFilter'; -import ReportLayoutPage from './ReportLayoutPage'; +import ReportLayout from './ReportLayout'; import { useAttributePreference, usePreference } from '../common/preferences'; import t from '../common/localization'; @@ -83,7 +83,7 @@ const RouteReportPage = () => { const [items, setItems] = useState([]); return ( - }> + }> { hideFooter autoHeight /> - + ); }; diff --git a/modern/src/reports/StopReportPage.js b/modern/src/reports/StopReportPage.js index 6953c46..57f5956 100644 --- a/modern/src/reports/StopReportPage.js +++ b/modern/src/reports/StopReportPage.js @@ -3,7 +3,7 @@ import { DataGrid } from '@material-ui/data-grid'; import { useTheme } from "@material-ui/core/styles"; import { formatDistance, formatHours, formatDate, formatVolume } from '../common/formatter'; import ReportFilter from './ReportFilter'; -import ReportLayoutPage from './ReportLayoutPage'; +import ReportLayout from './ReportLayout'; import { useAttributePreference } from '../common/preferences'; import t from '../common/localization'; @@ -82,14 +82,14 @@ const StopReportPage = () => { }] return ( - }> + }> Math.random()} /> - + ); }; diff --git a/modern/src/reports/SummaryReportPage.js b/modern/src/reports/SummaryReportPage.js index e3819a5..53e697d 100644 --- a/modern/src/reports/SummaryReportPage.js +++ b/modern/src/reports/SummaryReportPage.js @@ -4,7 +4,7 @@ import { Grid, FormControlLabel, Checkbox } from '@material-ui/core'; import { useTheme } from "@material-ui/core/styles"; import { formatDistance, formatHours, formatDate, formatSpeed, formatVolume } from '../common/formatter'; import ReportFilter from './ReportFilter'; -import ReportLayoutPage from './ReportLayoutPage'; +import ReportLayout from './ReportLayout'; import { useAttributePreference } from '../common/preferences'; import t from '../common/localization'; @@ -100,14 +100,14 @@ const SummaryReportPage = () => { }] return ( - }> + }> Math.random()} /> - + ); } diff --git a/modern/src/reports/TripReportPage.js b/modern/src/reports/TripReportPage.js index 5f414f4..e8c9129 100644 --- a/modern/src/reports/TripReportPage.js +++ b/modern/src/reports/TripReportPage.js @@ -3,7 +3,7 @@ import { DataGrid } from '@material-ui/data-grid'; import { useTheme } from "@material-ui/core/styles"; import { formatDistance, formatSpeed, formatHours, formatDate, formatVolume } from '../common/formatter'; import ReportFilter from './ReportFilter'; -import ReportLayoutPage from './ReportLayoutPage'; +import ReportLayout from './ReportLayout'; import { useAttributePreference } from '../common/preferences'; import t from '../common/localization'; @@ -113,14 +113,14 @@ const TripReportPage = () => { }] return ( - }> + }> Math.random()} /> - + ); } -- cgit v1.2.3 From 70fd67f635fbcd75ceab50934419999cdb71e78e Mon Sep 17 00:00:00 2001 From: Desmond Kyeremeh Date: Thu, 1 Jul 2021 14:01:44 +0000 Subject: Options layout --- modern/src/settings/OptionsLayout/index.js | 100 +++++++++++++++++++++++++ modern/src/settings/OptionsLayout/useRoutes.js | 71 ++++++++++++++++++ 2 files changed, 171 insertions(+) create mode 100644 modern/src/settings/OptionsLayout/index.js create mode 100644 modern/src/settings/OptionsLayout/useRoutes.js (limited to 'modern/src') diff --git a/modern/src/settings/OptionsLayout/index.js b/modern/src/settings/OptionsLayout/index.js new file mode 100644 index 0000000..a3a89f8 --- /dev/null +++ b/modern/src/settings/OptionsLayout/index.js @@ -0,0 +1,100 @@ +import React, { useState, useEffect } from 'react'; +import { useHistory, useLocation } from 'react-router-dom'; +import { + Typography, + Divider, + Drawer, + makeStyles, + IconButton, + Hidden +} from '@material-ui/core'; + +import ArrowBackIcon from '@material-ui/icons/ArrowBack'; + +import SideNav from '../../components/SideNav'; +import NavBar from '../../components/NavBar'; +import t from '../../common/localization'; +import useRoutes from './useRoutes'; + +const useStyles = makeStyles(theme => ({ + root: { + display: 'flex', + height: '100%' + }, + drawerContainer: { + width: theme.dimensions.drawerWidthDesktop + }, + drawer: { + width: theme.dimensions.drawerWidthDesktop, + [theme.breakpoints.down('md')]: { + width: theme.dimensions.drawerWidthTablet + } + }, + content: { + flex: 1, + padding: theme.spacing(5, 3, 3, 3) + }, + drawerHeader: { + ...theme.mixins.toolbar, + display: 'flex', + alignItems: 'center', + padding: theme.spacing(0, 1) + }, + toolbar: { + [theme.breakpoints.down('md')]: { + ...theme.mixins.toolbar + } + } +})); + +const OptionsLayout = ({ children }) => { + const classes = useStyles(); + const history = useHistory(); + const location = useLocation(); + const [openDrawer, setOpenDrawer] = useState(false); + const [OptionsTitle, setOptionsTitle] = useState(); + const routes = useRoutes(); + + useEffect(() => { + routes.find(route => route.href === location.pathname); + setOptionsTitle(route.name); + }, [location]); + + return ( +
+ + + setOpenDrawer(!openDrawer)} + classes={{ paper: classes.drawer }} + > + + + + + + +
+ history.push('/')}> + + + + {t('settingsTitle')} + +
+ + +
+
+ +
{children}
+
+ ); +}; + +export default OptionsLayout; diff --git a/modern/src/settings/OptionsLayout/useRoutes.js b/modern/src/settings/OptionsLayout/useRoutes.js new file mode 100644 index 0000000..e53e8fd --- /dev/null +++ b/modern/src/settings/OptionsLayout/useRoutes.js @@ -0,0 +1,71 @@ +import React, { useMemo } from 'react'; +import { useSelector } from 'react-redux'; +import CreateIcon from '@material-ui/icons/Create'; +import NotificationsIcon from '@material-ui/icons/Notifications'; +import FolderIcon from '@material-ui/icons/Folder'; +import PersonIcon from '@material-ui/icons/Person'; +import StorageIcon from '@material-ui/icons/Storage'; +import BuildIcon from '@material-ui/icons/Build'; +import PeopleIcon from '@material-ui/icons/People'; +import BarChartIcon from '@material-ui/icons/BarChart'; +import { getIsAdmin } from '../../selectors'; +import t from '../../common/localization'; + +const adminRoutes = [ + { subheader: t('userAdmin') }, + { + name: t('settingsServer'), + href: '/admin/server', + icon: + }, + { + name: t('settingsUsers'), + href: '/admin/users', + icon: + }, + { + name: t('statisticsTitle'), + href: '/admin/statistics', + icon: + } +]; + +const mainRoutes = [ + { + name: t('sharedGeofences'), + href: '/geofences', + icon: + }, + { + name: t('sharedNotifications'), + href: '/settings/notifications', + icon: + }, + { + name: t('settingsGroups'), + href: '/settings/groups', + icon: + }, + { + name: t('sharedDrivers'), + href: '/settings/drivers', + icon: + }, + { + name: t('sharedComputedAttributes'), + href: '/settings/attributes', + icon: + }, + { + name: t('sharedMaintenance'), + href: '/settings/maintenances', + icon: + } +]; + +export default () => { + const isAdmin = useSelector(getIsAdmin); + return useMemo(() => [...mainRoutes, ...(isAdmin ? adminRoutes : [])], [ + isAdmin + ]); +}; -- cgit v1.2.3 From e5b727e1bc85e6c38a15c8917aae57a70533da46 Mon Sep 17 00:00:00 2001 From: Desmond Kyeremeh Date: Thu, 1 Jul 2021 14:03:37 +0000 Subject: Apply OptionsLayout to settings pages --- modern/src/settings/ComputedAttributesPage.js | 34 +++++++++++++++++---------- modern/src/settings/DriversPage.js | 26 ++++++++++++-------- modern/src/settings/GroupsPage.js | 26 ++++++++++++-------- modern/src/settings/MaintenancesPage.js | 26 ++++++++++++-------- modern/src/settings/NotificationsPage.js | 32 ++++++++++++++++--------- 5 files changed, 90 insertions(+), 54 deletions(-) (limited to 'modern/src') diff --git a/modern/src/settings/ComputedAttributesPage.js b/modern/src/settings/ComputedAttributesPage.js index 1a6feab..49c35d6 100644 --- a/modern/src/settings/ComputedAttributesPage.js +++ b/modern/src/settings/ComputedAttributesPage.js @@ -6,19 +6,22 @@ import { useSelector } from 'react-redux'; import t from '../common/localization'; import { useEffectAsync } from '../reactHelper'; import EditCollectionView from '../EditCollectionView'; +import OptionsLayout from './OptionsLayout'; const useStyles = makeStyles(theme => ({ columnAction: { width: theme.spacing(1), - padding: theme.spacing(0, 1), - }, + padding: theme.spacing(0, 1) + } })); const ComputedAttributeView = ({ updateTimestamp, onMenuClick }) => { const classes = useStyles(); const [items, setItems] = useState([]); - const adminEnabled = useSelector(state => state.session.user && state.session.user.administrator); + const adminEnabled = useSelector( + state => state.session.user && state.session.user.administrator + ); useEffectAsync(async () => { const response = await fetch('/api/attributes/computed'); @@ -40,15 +43,17 @@ const ComputedAttributeView = ({ updateTimestamp, onMenuClick }) => { - {items.map((item) => ( + {items.map(item => ( - {adminEnabled && + {adminEnabled && ( - onMenuClick(event.currentTarget, item.id)}> + onMenuClick(event.currentTarget, item.id)} + > - } + )} {item.description} {item.attribute} {item.expression} @@ -59,15 +64,18 @@ const ComputedAttributeView = ({ updateTimestamp, onMenuClick }) => { ); -} +}; const ComputedAttributesPage = () => { return ( - <> - - - + + + ); -} +}; export default ComputedAttributesPage; diff --git a/modern/src/settings/DriversPage.js b/modern/src/settings/DriversPage.js index 957e225..13cb1c6 100644 --- a/modern/src/settings/DriversPage.js +++ b/modern/src/settings/DriversPage.js @@ -5,12 +5,13 @@ import MoreVertIcon from '@material-ui/icons/MoreVert'; import t from '../common/localization'; import { useEffectAsync } from '../reactHelper'; import EditCollectionView from '../EditCollectionView'; +import OptionsLayout from './OptionsLayout'; const useStyles = makeStyles(theme => ({ columnAction: { width: theme.spacing(1), - padding: theme.spacing(0, 1), - }, + padding: theme.spacing(0, 1) + } })); const DriversView = ({ updateTimestamp, onMenuClick }) => { @@ -36,10 +37,12 @@ const DriversView = ({ updateTimestamp, onMenuClick }) => { - {items.map((item) => ( + {items.map(item => ( - onMenuClick(event.currentTarget, item.id)}> + onMenuClick(event.currentTarget, item.id)} + > @@ -51,15 +54,18 @@ const DriversView = ({ updateTimestamp, onMenuClick }) => { ); -} +}; const DriversPage = () => { return ( - <> - - - + + + ); -} +}; export default DriversPage; diff --git a/modern/src/settings/GroupsPage.js b/modern/src/settings/GroupsPage.js index e274062..2de6241 100644 --- a/modern/src/settings/GroupsPage.js +++ b/modern/src/settings/GroupsPage.js @@ -5,12 +5,13 @@ import MoreVertIcon from '@material-ui/icons/MoreVert'; import t from '../common/localization'; import { useEffectAsync } from '../reactHelper'; import EditCollectionView from '../EditCollectionView'; +import OptionsLayout from './OptionsLayout'; const useStyles = makeStyles(theme => ({ columnAction: { width: theme.spacing(1), - padding: theme.spacing(0, 1), - }, + padding: theme.spacing(0, 1) + } })); const GroupsView = ({ updateTimestamp, onMenuClick }) => { @@ -35,10 +36,12 @@ const GroupsView = ({ updateTimestamp, onMenuClick }) => { - {items.map((item) => ( + {items.map(item => ( - onMenuClick(event.currentTarget, item.id)}> + onMenuClick(event.currentTarget, item.id)} + > @@ -49,15 +52,18 @@ const GroupsView = ({ updateTimestamp, onMenuClick }) => { ); -} +}; const GroupsPage = () => { return ( - <> - - - + + + ); -} +}; export default GroupsPage; diff --git a/modern/src/settings/MaintenancesPage.js b/modern/src/settings/MaintenancesPage.js index 7ba4bd2..3fd0b39 100644 --- a/modern/src/settings/MaintenancesPage.js +++ b/modern/src/settings/MaintenancesPage.js @@ -9,12 +9,13 @@ import EditCollectionView from '../EditCollectionView'; import positionAttributes from '../attributes/positionAttributes'; import { formatDistance, formatSpeed } from '../common/formatter'; import { useAttributePreference } from '../common/preferences'; +import OptionsLayout from './OptionsLayout'; const useStyles = makeStyles(theme => ({ columnAction: { width: theme.spacing(1), - padding: theme.spacing(0, 1), - }, + padding: theme.spacing(0, 1) + } })); const MaintenancesView = ({ updateTimestamp, onMenuClick }) => { @@ -45,7 +46,7 @@ const MaintenancesView = ({ updateTimestamp, onMenuClick }) => { } return value; - } + }; return ( @@ -63,7 +64,9 @@ const MaintenancesView = ({ updateTimestamp, onMenuClick }) => { {items.map(item => ( - onMenuClick(event.currentTarget, item.id)}> + onMenuClick(event.currentTarget, item.id)} + > @@ -77,15 +80,18 @@ const MaintenancesView = ({ updateTimestamp, onMenuClick }) => { ); -} +}; const MaintenacesPage = () => { return ( - <> - - - + + + ); -} +}; export default MaintenacesPage; diff --git a/modern/src/settings/NotificationsPage.js b/modern/src/settings/NotificationsPage.js index 15da0de..3756e96 100644 --- a/modern/src/settings/NotificationsPage.js +++ b/modern/src/settings/NotificationsPage.js @@ -7,12 +7,13 @@ import { useEffectAsync } from '../reactHelper'; import EditCollectionView from '../EditCollectionView'; import { prefixString } from '../common/stringUtils'; import { formatBoolean } from '../common/formatter'; +import OptionsLayout from './OptionsLayout'; const useStyles = makeStyles(theme => ({ columnAction: { width: theme.spacing(1), - padding: theme.spacing(0, 1), - }, + padding: theme.spacing(0, 1) + } })); const NotificationsView = ({ updateTimestamp, onMenuClick }) => { @@ -54,29 +55,38 @@ const NotificationsView = ({ updateTimestamp, onMenuClick }) => { {items.map(item => ( - onMenuClick(event.currentTarget, item.id)}> + onMenuClick(event.currentTarget, item.id)} + > {t(prefixString('event', item.type))} {formatBoolean(item.always)} - {formatList('alarm', item.attributes.alarms)} - {formatList('notificator', item.notificators)} + + {formatList('alarm', item.attributes.alarms)} + + + {formatList('notificator', item.notificators)} + ))} ); -} +}; const NotificationsPage = () => { return ( - <> - - - + + + ); -} +}; export default NotificationsPage; -- cgit v1.2.3 From a154c692e08f340f3a81e024fb8e9f1d3a56cf52 Mon Sep 17 00:00:00 2001 From: Desmond Kyeremeh Date: Thu, 1 Jul 2021 14:21:08 +0000 Subject: Used OptionsLayout for admin pages --- modern/src/admin/ServerPage.js | 111 +++++++++++++++++++++++++++---------- modern/src/admin/StatisticsPage.js | 76 +++++++++++++++++-------- modern/src/admin/UsersPage.js | 26 +++++---- 3 files changed, 150 insertions(+), 63 deletions(-) (limited to 'modern/src') diff --git a/modern/src/admin/ServerPage.js b/modern/src/admin/ServerPage.js index 43664e5..c33a631 100644 --- a/modern/src/admin/ServerPage.js +++ b/modern/src/admin/ServerPage.js @@ -6,26 +6,26 @@ import { Accordion, AccordionSummary, AccordionDetails, makeStyles, Typography, import ExpandMoreIcon from '@material-ui/icons/ExpandMore'; import { useHistory } from 'react-router-dom'; import { useDispatch, useSelector } from 'react-redux'; -import MainToolbar from '../MainToolbar'; import { sessionActions } from '../store'; import EditAttributesView from '../attributes/EditAttributesView'; import deviceAttributes from '../attributes/deviceAttributes'; import userAttributes from '../attributes/userAttributes'; +import OptionsLayout from '../settings/OptionsLayout'; const useStyles = makeStyles(theme => ({ container: { - marginTop: theme.spacing(2), + marginTop: theme.spacing(2) }, buttons: { display: 'flex', justifyContent: 'space-evenly', '& > *': { - flexBasis: '33%', - }, + flexBasis: '33%' + } }, details: { - flexDirection: 'column', - }, + flexDirection: 'column' + } })); const ServerPage = () => { @@ -34,13 +34,14 @@ const ServerPage = () => { const classes = useStyles(); const item = useSelector(state => state.session.server); - const setItem = (updatedItem) => dispatch(sessionActions.updateServer(updatedItem)); + const setItem = updatedItem => + dispatch(sessionActions.updateServer(updatedItem)); const handleSave = async () => { const response = await fetch('/api/server', { method: 'PUT', headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify(item), + body: JSON.stringify(item) }); if (response.ok) { @@ -49,10 +50,9 @@ const ServerPage = () => { }; return ( - <> - - - {item && + + + {item && ( <> }> @@ -64,9 +64,12 @@ const ServerPage = () => { setItem({...item, announcement: event.target.value})} + onChange={event => + setItem({ ...item, announcement: event.target.value }) + } label={t('serverAnnouncement')} - variant="filled" /> + variant="filled" + /> @@ -77,17 +80,55 @@ const ServerPage = () => { setItem({...item, registration: event.target.checked})} />} - label={t('serverRegistration')} /> + control={ + + setItem({ ...item, registration: event.target.checked }) + } + /> + } + label={t('serverRegistration')} + /> setItem({...item, readonly: event.target.checked})} />} - label={t('serverReadonly')} /> + control={ + + setItem({ ...item, readonly: event.target.checked }) + } + /> + } + label={t('serverReadonly')} + /> setItem({...item, deviceReadonly: event.target.checked})} />} - label={t('userDeviceReadonly')} /> + control={ + + setItem({ + ...item, + deviceReadonly: event.target.checked + }) + } + /> + } + label={t('userDeviceReadonly')} + /> setItem({...item, limitCommands: event.target.checked})} />} - label={t('userLimitCommands')} /> + control={ + + setItem({ + ...item, + limitCommands: event.target.checked + }) + } + /> + } + label={t('userLimitCommands')} + /> @@ -99,26 +140,36 @@ const ServerPage = () => { setItem({...item, attributes})} - definitions={{...userAttributes, ...deviceAttributes}} + setAttributes={attributes => setItem({ ...item, attributes })} + definitions={{ ...userAttributes, ...deviceAttributes }} /> - } - + )} +
- -
- +
); -} +}; export default ServerPage; diff --git a/modern/src/admin/StatisticsPage.js b/modern/src/admin/StatisticsPage.js index 0137a1f..b1504c8 100644 --- a/modern/src/admin/StatisticsPage.js +++ b/modern/src/admin/StatisticsPage.js @@ -3,8 +3,8 @@ import React, { useState } from 'react'; import { FormControl, InputLabel,Select, MenuItem, TextField, Button, TableContainer, Table, TableRow, TableCell, TableHead, TableBody, Paper } from '@material-ui/core'; import t from '../common/localization'; import { formatDate } from '../common/formatter'; -import ReportLayout from '../reports/ReportLayout'; import moment from 'moment'; +import OptionsLayout from '../settings/OptionsLayout'; const Filter = ({ setItems }) => { const [period, setPeriod] = useState('today'); @@ -20,24 +20,36 @@ const Filter = ({ setItems }) => { selectedTo = moment().endOf('day'); break; case 'yesterday': - selectedFrom = moment().subtract(1, 'day').startOf('day'); - selectedTo = moment().subtract(1, 'day').endOf('day'); + selectedFrom = moment() + .subtract(1, 'day') + .startOf('day'); + selectedTo = moment() + .subtract(1, 'day') + .endOf('day'); break; case 'thisWeek': selectedFrom = moment().startOf('week'); selectedTo = moment().endOf('week'); break; case 'previousWeek': - selectedFrom = moment().subtract(1, 'week').startOf('week'); - selectedTo = moment().subtract(1, 'week').endOf('week'); + selectedFrom = moment() + .subtract(1, 'week') + .startOf('week'); + selectedTo = moment() + .subtract(1, 'week') + .endOf('week'); break; case 'thisMonth': selectedFrom = moment().startOf('month'); selectedTo = moment().endOf('month'); break; case 'previousMonth': - selectedFrom = moment().subtract(1, 'month').startOf('month'); - selectedTo = moment().subtract(1, 'month').endOf('month'); + selectedFrom = moment() + .subtract(1, 'month') + .startOf('month'); + selectedTo = moment() + .subtract(1, 'month') + .endOf('month'); break; default: selectedFrom = from; @@ -45,18 +57,23 @@ const Filter = ({ setItems }) => { break; } - const query = new URLSearchParams({ from: selectedFrom.toISOString(), to: selectedTo.toISOString() }); - const response = await fetch(`/api/statistics?${query.toString()}`, { Accept: 'application/json' }); + const query = new URLSearchParams({ + from: selectedFrom.toISOString(), + to: selectedTo.toISOString() + }); + const response = await fetch(`/api/statistics?${query.toString()}`, { + Accept: 'application/json' + }); if (response.ok) { setItems(await response.json()); } - } + }; return ( <> {t('reportPeriod')} - setPeriod(e.target.value)}> {t('reportToday')} {t('reportYesterday')} {t('reportThisWeek')} @@ -73,8 +90,11 @@ const Filter = ({ setItems }) => { label={t('reportFrom')} type="datetime-local" value={from.format(moment.HTML5_FMT.DATETIME_LOCAL)} - onChange={e => setFrom(moment(e.target.value, moment.HTML5_FMT.DATETIME_LOCAL))} - fullWidth /> + onChange={e => + setFrom(moment(e.target.value, moment.HTML5_FMT.DATETIME_LOCAL)) + } + fullWidth + /> )} {period === 'custom' && ( { label={t('reportTo')} type="datetime-local" value={to.format(moment.HTML5_FMT.DATETIME_LOCAL)} - onChange={e => setTo(moment(e.target.value, moment.HTML5_FMT.DATETIME_LOCAL))} - fullWidth /> + onChange={e => + setTo(moment(e.target.value, moment.HTML5_FMT.DATETIME_LOCAL)) + } + fullWidth + /> )} - + - ) -} + ); +}; const StatisticsPage = () => { - const [items, setItems] = useState([]); return ( - }> + + @@ -114,7 +144,7 @@ const StatisticsPage = () => { - {items.map((item) => ( + {items.map(item => ( {formatDate(item.captureTime)} {item.activeUsers} @@ -131,8 +161,8 @@ const StatisticsPage = () => {
-
+ ); -} +}; export default StatisticsPage; diff --git a/modern/src/admin/UsersPage.js b/modern/src/admin/UsersPage.js index 630bea4..aed675c 100644 --- a/modern/src/admin/UsersPage.js +++ b/modern/src/admin/UsersPage.js @@ -6,12 +6,13 @@ import t from '../common/localization'; import { useEffectAsync } from '../reactHelper'; import EditCollectionView from '../EditCollectionView'; import { formatBoolean } from '../common/formatter'; +import OptionsLayout from '../settings/OptionsLayout'; const useStyles = makeStyles(theme => ({ columnAction: { width: theme.spacing(1), - padding: theme.spacing(0, 1), - }, + padding: theme.spacing(0, 1) + } })); const UsersView = ({ updateTimestamp, onMenuClick }) => { @@ -39,10 +40,12 @@ const UsersView = ({ updateTimestamp, onMenuClick }) => { - {items.map((item) => ( + {items.map(item => ( - onMenuClick(event.currentTarget, item.id)}> + onMenuClick(event.currentTarget, item.id)} + > @@ -56,15 +59,18 @@ const UsersView = ({ updateTimestamp, onMenuClick }) => { ); -} +}; const UsersPage = () => { return ( - <> - - - + + + ); -} +}; export default UsersPage; -- cgit v1.2.3 From a2722a1263e809b4f83100dbecc992cdeacf13ea Mon Sep 17 00:00:00 2001 From: Desmond Kyeremeh Date: Thu, 1 Jul 2021 14:21:56 +0000 Subject: Show option title for mobile navbar --- modern/src/settings/OptionsLayout/index.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'modern/src') diff --git a/modern/src/settings/OptionsLayout/index.js b/modern/src/settings/OptionsLayout/index.js index a3a89f8..c56ebc3 100644 --- a/modern/src/settings/OptionsLayout/index.js +++ b/modern/src/settings/OptionsLayout/index.js @@ -52,18 +52,20 @@ const OptionsLayout = ({ children }) => { const history = useHistory(); const location = useLocation(); const [openDrawer, setOpenDrawer] = useState(false); - const [OptionsTitle, setOptionsTitle] = useState(); + const [optionTitle, setOptionTitle] = useState(); const routes = useRoutes(); useEffect(() => { - routes.find(route => route.href === location.pathname); - setOptionsTitle(route.name); + const activeRoute = routes.find(route => route.href === location.pathname); + setOptionTitle(activeRoute.name); }, [location]); + const title = `Options / ${optionTitle}`; + return (
- + Date: Thu, 1 Jul 2021 14:22:05 +0000 Subject: Minor fixes --- modern/src/reports/ReportFilter.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'modern/src') diff --git a/modern/src/reports/ReportFilter.js b/modern/src/reports/ReportFilter.js index 868b866..516891e 100644 --- a/modern/src/reports/ReportFilter.js +++ b/modern/src/reports/ReportFilter.js @@ -1,5 +1,5 @@ import React, { useState } from 'react'; -import { FormControl, InputLabel, Select, MenuItem, Button, TextField, Grid, Typography, makeStyles } from '@material-ui/core'; +import { FormControl, InputLabel, Select, MenuItem, Button, TextField, Grid, Typography} from '@material-ui/core'; import { useSelector } from 'react-redux'; import moment from 'moment'; import t from '../common/localization'; -- cgit v1.2.3 From bf26504a27dbfc87c0280cb4909d85f4d5ecae7a Mon Sep 17 00:00:00 2001 From: Desmond Kyeremeh Date: Thu, 1 Jul 2021 14:23:55 +0000 Subject: Removed unused vars --- modern/src/admin/UsersPage.js | 1 - modern/src/settings/ComputedAttributesPage.js | 1 - modern/src/settings/DriversPage.js | 1 - modern/src/settings/GroupsPage.js | 1 - modern/src/settings/MaintenancesPage.js | 1 - modern/src/settings/NotificationsPage.js | 1 - modern/src/settings/OptionsLayout/index.js | 2 +- 7 files changed, 1 insertion(+), 7 deletions(-) (limited to 'modern/src') diff --git a/modern/src/admin/UsersPage.js b/modern/src/admin/UsersPage.js index aed675c..ceaab6a 100644 --- a/modern/src/admin/UsersPage.js +++ b/modern/src/admin/UsersPage.js @@ -1,5 +1,4 @@ import React, { useState } from 'react'; -import MainToolbar from '../MainToolbar'; import { TableContainer, Table, TableRow, TableCell, TableHead, TableBody, makeStyles, IconButton } from '@material-ui/core'; import MoreVertIcon from '@material-ui/icons/MoreVert'; import t from '../common/localization'; diff --git a/modern/src/settings/ComputedAttributesPage.js b/modern/src/settings/ComputedAttributesPage.js index 49c35d6..d747598 100644 --- a/modern/src/settings/ComputedAttributesPage.js +++ b/modern/src/settings/ComputedAttributesPage.js @@ -1,5 +1,4 @@ import React, { useState } from 'react'; -import MainToolbar from '../MainToolbar'; import { TableContainer, Table, TableRow, TableCell, TableHead, TableBody, makeStyles, IconButton } from '@material-ui/core'; import MoreVertIcon from '@material-ui/icons/MoreVert'; import { useSelector } from 'react-redux'; diff --git a/modern/src/settings/DriversPage.js b/modern/src/settings/DriversPage.js index 13cb1c6..d5427b2 100644 --- a/modern/src/settings/DriversPage.js +++ b/modern/src/settings/DriversPage.js @@ -1,5 +1,4 @@ import React, { useState } from 'react'; -import MainToolbar from '../MainToolbar'; import { TableContainer, Table, TableRow, TableCell, TableHead, TableBody, makeStyles, IconButton } from '@material-ui/core'; import MoreVertIcon from '@material-ui/icons/MoreVert'; import t from '../common/localization'; diff --git a/modern/src/settings/GroupsPage.js b/modern/src/settings/GroupsPage.js index 2de6241..2fc65c1 100644 --- a/modern/src/settings/GroupsPage.js +++ b/modern/src/settings/GroupsPage.js @@ -1,5 +1,4 @@ import React, { useState } from 'react'; -import MainToolbar from '../MainToolbar'; import { TableContainer, Table, TableRow, TableCell, TableHead, TableBody, makeStyles, IconButton } from '@material-ui/core'; import MoreVertIcon from '@material-ui/icons/MoreVert'; import t from '../common/localization'; diff --git a/modern/src/settings/MaintenancesPage.js b/modern/src/settings/MaintenancesPage.js index 3fd0b39..d713eaa 100644 --- a/modern/src/settings/MaintenancesPage.js +++ b/modern/src/settings/MaintenancesPage.js @@ -1,5 +1,4 @@ import React, { useState } from 'react'; -import MainToolbar from '../MainToolbar'; import { TableContainer, Table, TableRow, TableCell, TableHead, TableBody, makeStyles, IconButton } from '@material-ui/core'; import MoreVertIcon from '@material-ui/icons/MoreVert'; import t from '../common/localization'; diff --git a/modern/src/settings/NotificationsPage.js b/modern/src/settings/NotificationsPage.js index 3756e96..5707f89 100644 --- a/modern/src/settings/NotificationsPage.js +++ b/modern/src/settings/NotificationsPage.js @@ -1,5 +1,4 @@ import React, { useState } from 'react'; -import MainToolbar from '../MainToolbar'; import { TableContainer, Table, TableRow, TableCell, TableHead, TableBody, makeStyles, IconButton } from '@material-ui/core'; import MoreVertIcon from '@material-ui/icons/MoreVert'; import t from '../common/localization'; diff --git a/modern/src/settings/OptionsLayout/index.js b/modern/src/settings/OptionsLayout/index.js index c56ebc3..f6f1e4b 100644 --- a/modern/src/settings/OptionsLayout/index.js +++ b/modern/src/settings/OptionsLayout/index.js @@ -58,7 +58,7 @@ const OptionsLayout = ({ children }) => { useEffect(() => { const activeRoute = routes.find(route => route.href === location.pathname); setOptionTitle(activeRoute.name); - }, [location]); + }, [location, routes]); const title = `Options / ${optionTitle}`; -- cgit v1.2.3 From ca6f62e322ece99cb944ad341ebc4de9aa82c82d Mon Sep 17 00:00:00 2001 From: Desmond Kyeremeh Date: Fri, 2 Jul 2021 15:15:33 +0000 Subject: Used options layout for EditItemView --- modern/src/EditItemView.js | 37 +++++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 14 deletions(-) (limited to 'modern/src') diff --git a/modern/src/EditItemView.js b/modern/src/EditItemView.js index 16fbbae..bab56c7 100644 --- a/modern/src/EditItemView.js +++ b/modern/src/EditItemView.js @@ -1,5 +1,4 @@ import React from 'react'; -import MainToolbar from './MainToolbar'; import { useHistory, useParams } from 'react-router-dom'; import { makeStyles } from '@material-ui/core/styles'; import Container from '@material-ui/core/Container'; @@ -8,18 +7,19 @@ import FormControl from '@material-ui/core/FormControl'; import t from './common/localization'; import { useEffectAsync } from './reactHelper'; +import OptionsLayout from './settings/OptionsLayout'; const useStyles = makeStyles(theme => ({ container: { - marginTop: theme.spacing(2), + marginTop: theme.spacing(2) }, buttons: { display: 'flex', justifyContent: 'space-evenly', '& > *': { - flexBasis: '33%', - }, - }, + flexBasis: '33%' + } + } })); const EditItemView = ({ children, endpoint, item, setItem }) => { @@ -47,7 +47,7 @@ const EditItemView = ({ children, endpoint, item, setItem }) => { const response = await fetch(url, { method: !id ? 'POST' : 'PUT', headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify(item), + body: JSON.stringify(item) }); if (response.ok) { @@ -56,23 +56,32 @@ const EditItemView = ({ children, endpoint, item, setItem }) => { }; return ( - <> - - + + {children} - +
- -
- +
); -} +}; export default EditItemView; -- cgit v1.2.3 From 7704d0f907c1567888a7d908a4641edfec0e68f4 Mon Sep 17 00:00:00 2001 From: Desmond Kyeremeh Date: Fri, 2 Jul 2021 15:15:59 +0000 Subject: Updated geofencespage --- modern/src/GeofencesPage.js | 40 +++++++++++++++++++++++++++++----------- 1 file changed, 29 insertions(+), 11 deletions(-) (limited to 'modern/src') diff --git a/modern/src/GeofencesPage.js b/modern/src/GeofencesPage.js index 389ac99..c66637d 100644 --- a/modern/src/GeofencesPage.js +++ b/modern/src/GeofencesPage.js @@ -2,17 +2,20 @@ 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'; +import ArrowBackIcon from '@material-ui/icons/ArrowBack'; + +import t from './common/localization'; + const useStyles = makeStyles(theme => ({ root: { height: '100%', display: 'flex', - flexDirection: 'column', + flexDirection: 'column' }, content: { flexGrow: 1, @@ -20,21 +23,27 @@ const useStyles = makeStyles(theme => ({ display: 'flex', flexDirection: 'row', [theme.breakpoints.down('xs')]: { - flexDirection: 'column-reverse', + flexDirection: 'column-reverse' } }, drawerPaper: { position: 'relative', [theme.breakpoints.up('sm')]: { - width: 350, + width: 350 }, [theme.breakpoints.down('xs')]: { - height: 250, + height: 250 } }, - mapContainer: { - flexGrow: 1, + drawerHeader: { + ...theme.mixins.toolbar, + display: 'flex', + alignItems: 'center', + padding: theme.spacing(0, 1) }, + mapContainer: { + flexGrow: 1 + } })); const GeofencesPage = ({ width }) => { @@ -42,12 +51,21 @@ const GeofencesPage = ({ width }) => { return (
-
+ variant="permanent" + classes={{ paper: classes.drawerPaper }} + > +
+ + + + + {t('sharedGeofences')} + +
+
@@ -61,6 +79,6 @@ const GeofencesPage = ({ width }) => {
); -} +}; export default withWidth()(GeofencesPage); -- cgit v1.2.3 From 191ec6d655edd4f77ba40f3a42ae277ea769cc0a Mon Sep 17 00:00:00 2001 From: Desmond Kyeremeh Date: Fri, 2 Jul 2021 15:17:35 +0000 Subject: SideNav: updated url matching algorithm --- modern/src/components/SideNav.js | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) (limited to 'modern/src') diff --git a/modern/src/components/SideNav.js b/modern/src/components/SideNav.js index 669c79a..8bd43ac 100644 --- a/modern/src/components/SideNav.js +++ b/modern/src/components/SideNav.js @@ -1,12 +1,5 @@ import React from 'react'; -import { - List, - ListItem, - ListItemText, - ListItemIcon, - Divider, - ListSubheader -} from '@material-ui/core'; +import { List, ListItem, ListItemText, ListItemIcon, Divider, ListSubheader } from '@material-ui/core'; import { Link, useLocation } from 'react-router-dom'; const SideNav = ({ routes }) => { @@ -27,7 +20,7 @@ const SideNav = ({ routes }) => { key={route.href || route.subheader} button to={route.href} - selected={route.href === location.pathname} + selected={location.pathname.match(route.match || route.href)} > {route.icon} -- cgit v1.2.3 From 52f565bcb5e14b77757676013d1328ead92e13fa Mon Sep 17 00:00:00 2001 From: Desmond Kyeremeh Date: Fri, 2 Jul 2021 15:18:00 +0000 Subject: Account Route --- modern/src/settings/OptionsLayout/index.js | 7 +++---- modern/src/settings/OptionsLayout/useRoutes.js | 17 ++++++++++++++++- 2 files changed, 19 insertions(+), 5 deletions(-) (limited to 'modern/src') diff --git a/modern/src/settings/OptionsLayout/index.js b/modern/src/settings/OptionsLayout/index.js index f6f1e4b..4bcb380 100644 --- a/modern/src/settings/OptionsLayout/index.js +++ b/modern/src/settings/OptionsLayout/index.js @@ -1,5 +1,5 @@ import React, { useState, useEffect } from 'react'; -import { useHistory, useLocation } from 'react-router-dom'; +import { useLocation } from 'react-router-dom'; import { Typography, Divider, @@ -49,14 +49,13 @@ const useStyles = makeStyles(theme => ({ const OptionsLayout = ({ children }) => { const classes = useStyles(); - const history = useHistory(); const location = useLocation(); const [openDrawer, setOpenDrawer] = useState(false); const [optionTitle, setOptionTitle] = useState(); const routes = useRoutes(); useEffect(() => { - const activeRoute = routes.find(route => route.href === location.pathname); + const activeRoute = routes.find(route => location.pathname.match(route.match)); setOptionTitle(activeRoute.name); }, [location, routes]); @@ -82,7 +81,7 @@ const OptionsLayout = ({ children }) => { classes={{ root: classes.drawerContainer, paper: classes.drawer }} >
- history.push('/')}> + diff --git a/modern/src/settings/OptionsLayout/useRoutes.js b/modern/src/settings/OptionsLayout/useRoutes.js index e53e8fd..6796a56 100644 --- a/modern/src/settings/OptionsLayout/useRoutes.js +++ b/modern/src/settings/OptionsLayout/useRoutes.js @@ -8,9 +8,14 @@ import StorageIcon from '@material-ui/icons/Storage'; import BuildIcon from '@material-ui/icons/Build'; import PeopleIcon from '@material-ui/icons/People'; import BarChartIcon from '@material-ui/icons/BarChart'; -import { getIsAdmin } from '../../selectors'; +import { getIsAdmin, getUserId } from '../../selectors'; import t from '../../common/localization'; +const accountRoute = { + name: t('settingsUser'), + icon: +}; + const adminRoutes = [ { subheader: t('userAdmin') }, { @@ -31,32 +36,39 @@ const adminRoutes = [ ]; const mainRoutes = [ + accountRoute, { + match: 'geofence', name: t('sharedGeofences'), href: '/geofences', icon: }, { + match: 'notification', name: t('sharedNotifications'), href: '/settings/notifications', icon: }, { + match: 'group', name: t('settingsGroups'), href: '/settings/groups', icon: }, { + match: 'driver', name: t('sharedDrivers'), href: '/settings/drivers', icon: }, { + match: 'attribute', name: t('sharedComputedAttributes'), href: '/settings/attributes', icon: }, { + match: 'maintenance', name: t('sharedMaintenance'), href: '/settings/maintenances', icon: @@ -65,6 +77,9 @@ const mainRoutes = [ export default () => { const isAdmin = useSelector(getIsAdmin); + const userId = useSelector(getUserId); + accountRoute.match = accountRoute.href = `/user/${userId}`; + return useMemo(() => [...mainRoutes, ...(isAdmin ? adminRoutes : [])], [ isAdmin ]); -- cgit v1.2.3 From a474d75a7cbb65f25fe6332df70b4fbc8dcb7707 Mon Sep 17 00:00:00 2001 From: Desmond Kyeremeh Date: Fri, 2 Jul 2021 15:21:33 +0000 Subject: Fixed linting --- modern/src/GeofencesPage.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'modern/src') diff --git a/modern/src/GeofencesPage.js b/modern/src/GeofencesPage.js index c66637d..59b8459 100644 --- a/modern/src/GeofencesPage.js +++ b/modern/src/GeofencesPage.js @@ -1,5 +1,5 @@ import React from 'react'; -import { isWidthUp, makeStyles, withWidth } from '@material-ui/core'; +import { Divider, isWidthUp, makeStyles, withWidth, Typography, IconButton } from '@material-ui/core'; import Drawer from '@material-ui/core/Drawer'; import ContainerDimensions from 'react-container-dimensions'; import Map from './map/Map'; -- cgit v1.2.3 From 529e51405db4a086a8eae8e63602f46c3e67fab4 Mon Sep 17 00:00:00 2001 From: Desmond Kyeremeh Date: Fri, 2 Jul 2021 15:53:52 +0000 Subject: Minor fixes --- modern/src/MainToolbar.js | 89 +----------------------------- modern/src/settings/OptionsLayout/index.js | 5 +- 2 files changed, 7 insertions(+), 87 deletions(-) (limited to 'modern/src') diff --git a/modern/src/MainToolbar.js b/modern/src/MainToolbar.js index c11ca96..311f024 100644 --- a/modern/src/MainToolbar.js +++ b/modern/src/MainToolbar.js @@ -17,18 +17,11 @@ import ListItem from '@material-ui/core/ListItem'; import ListItemIcon from '@material-ui/core/ListItemIcon'; import ListItemText from '@material-ui/core/ListItemText'; import MapIcon from '@material-ui/icons/Map'; -import BarChartIcon from '@material-ui/icons/BarChart'; -import PeopleIcon from '@material-ui/icons/People'; -import StorageIcon from '@material-ui/icons/Storage'; 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'; -import * as selectors from './selectors' +import * as selectors from './selectors'; const useStyles = makeStyles(theme => ({ flex: { @@ -115,93 +108,17 @@ const MainToolbar = () => { - - - {t('settingsTitle')}}> history.push(`/user/${userId}`)} + onClick={() => history.push(`/settings/notifications`)} > - - - history.push('/geofences')}> - - - - - - history.push('/settings/notifications')} - > - - - - - - history.push('/settings/groups')}> - - - - - - history.push('/settings/drivers')}> - - - - - - history.push('/settings/attributes')} - > - - - - - - history.push('/settings/maintenances')} - > - - - - + - {adminEnabled && ( - <> - - {t('userAdmin')}}> - history.push('/admin/server')}> - - - - - - history.push('/admin/users')}> - - - - - - history.push('/admin/statistics')} - > - - - - - - - - )}
diff --git a/modern/src/settings/OptionsLayout/index.js b/modern/src/settings/OptionsLayout/index.js index 4bcb380..37b6355 100644 --- a/modern/src/settings/OptionsLayout/index.js +++ b/modern/src/settings/OptionsLayout/index.js @@ -32,7 +32,10 @@ const useStyles = makeStyles(theme => ({ }, content: { flex: 1, - padding: theme.spacing(5, 3, 3, 3) + padding: theme.spacing(5, 3, 3, 3), + [theme.breakpoints.down('md')]:{ + paddingTop: theme.spacing(10) + } }, drawerHeader: { ...theme.mixins.toolbar, -- cgit v1.2.3 From 2a0705f1c26befa75703238462930847b18895e1 Mon Sep 17 00:00:00 2001 From: Desmond Kyeremeh Date: Fri, 2 Jul 2021 17:07:17 +0000 Subject: show admin title in mobile appbar --- modern/src/settings/OptionsLayout/index.js | 8 +++++--- modern/src/settings/OptionsLayout/useRoutes.js | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) (limited to 'modern/src') diff --git a/modern/src/settings/OptionsLayout/index.js b/modern/src/settings/OptionsLayout/index.js index 37b6355..61a94cf 100644 --- a/modern/src/settings/OptionsLayout/index.js +++ b/modern/src/settings/OptionsLayout/index.js @@ -33,7 +33,7 @@ const useStyles = makeStyles(theme => ({ content: { flex: 1, padding: theme.spacing(5, 3, 3, 3), - [theme.breakpoints.down('md')]:{ + [theme.breakpoints.down('md')]: { paddingTop: theme.spacing(10) } }, @@ -58,8 +58,10 @@ const OptionsLayout = ({ children }) => { const routes = useRoutes(); useEffect(() => { - const activeRoute = routes.find(route => location.pathname.match(route.match)); - setOptionTitle(activeRoute.name); + const activeRoute = routes.find( + route => route.href && location.pathname.match(route.match || route.href) + ); + setOptionTitle(activeRoute?.name); }, [location, routes]); const title = `Options / ${optionTitle}`; diff --git a/modern/src/settings/OptionsLayout/useRoutes.js b/modern/src/settings/OptionsLayout/useRoutes.js index 6796a56..901719f 100644 --- a/modern/src/settings/OptionsLayout/useRoutes.js +++ b/modern/src/settings/OptionsLayout/useRoutes.js @@ -78,7 +78,7 @@ const mainRoutes = [ export default () => { const isAdmin = useSelector(getIsAdmin); const userId = useSelector(getUserId); - accountRoute.match = accountRoute.href = `/user/${userId}`; + accountRoute.href = `/user/${userId}`; return useMemo(() => [...mainRoutes, ...(isAdmin ? adminRoutes : [])], [ isAdmin -- cgit v1.2.3 From 1b93de84e2bf6a6532bdb03e1ae75e47061a4dca Mon Sep 17 00:00:00 2001 From: Desmond Kyeremeh Date: Sun, 11 Jul 2021 22:14:39 +0000 Subject: Fixed linting --- modern/craco.config.js | 8 +- modern/src/App.js | 68 ++++++++-------- modern/src/CachingController.js | 22 ++--- modern/src/DevicePage.js | 95 +++++++++++++--------- modern/src/DevicesList.js | 15 ++-- modern/src/EditCollectionView.js | 27 +++--- modern/src/EditItemView.js | 16 ++-- modern/src/GeofencePage.js | 22 +++-- modern/src/GeofencesList.js | 12 ++- modern/src/GeofencesPage.js | 27 +++--- modern/src/Logo.js | 47 +++++------ modern/src/MainPage.js | 11 +-- modern/src/MainToolbar.js | 16 ++-- modern/src/PositionPage.js | 29 +++---- modern/src/RegisterDialog.js | 61 +++++++------- modern/src/RemoveDialog.js | 9 +- modern/src/SocketController.js | 26 +++--- modern/src/StartPage.js | 19 +++-- modern/src/UserPage.js | 47 ++++++----- modern/src/admin/ServerPage.js | 77 ++++++++---------- modern/src/admin/StatisticsPage.js | 27 +++--- modern/src/admin/UsersPage.js | 82 +++++++++---------- modern/src/attributes/AddAttributeDialog.js | 36 ++++---- modern/src/attributes/EditAttributesView.js | 83 +++++++++---------- modern/src/attributes/deviceAttributes.js | 4 +- modern/src/attributes/geofenceAttributes.js | 4 +- modern/src/attributes/positionAttributes.js | 10 +-- modern/src/attributes/userAttributes.js | 12 +-- modern/src/common/converter.js | 24 ++---- modern/src/common/formatter.js | 48 +++++------ modern/src/common/preferences.js | 30 +++---- modern/src/common/stringUtils.js | 8 +- modern/src/components/NavBar.js | 4 +- modern/src/components/SideNav.js | 42 +++++----- modern/src/components/registration/LoginForm.js | 71 ++++++++-------- modern/src/components/registration/RegisterForm.js | 82 ++++++++++--------- .../components/registration/ResetPasswordForm.js | 13 ++- modern/src/form/LinkField.js | 30 +++---- modern/src/form/SelectField.js | 23 +++--- modern/src/index.js | 4 +- modern/src/map/AccuracyMap.js | 36 ++++---- modern/src/map/CurrentLocationMap.js | 2 +- modern/src/map/CurrentPositionsMap.js | 6 +- modern/src/map/GeofenceEditMap.js | 32 ++++---- modern/src/map/GeofenceMap.js | 56 ++++++------- modern/src/map/Map.js | 16 ++-- modern/src/map/PositionsMap.js | 71 ++++++++-------- modern/src/map/ReplayPathMap.js | 28 ++++--- modern/src/map/SelectedDeviceMap.js | 4 +- modern/src/map/StatusView.js | 65 ++++++++++++--- modern/src/map/mapStyles.js | 42 +++++----- modern/src/map/mapUtil.js | 57 ++++++------- modern/src/reactHelper.js | 3 +- modern/src/reports/ChartReportPage.js | 69 ++++++++-------- modern/src/reports/EventReportPage.js | 39 +++++---- modern/src/reports/Graph.js | 37 ++++----- modern/src/reports/ReplayPage.js | 36 ++++---- modern/src/reports/ReportFilter.js | 85 +++++++++++-------- modern/src/reports/ReportLayout.js | 34 ++++---- modern/src/reports/RouteReportPage.js | 24 +++--- modern/src/reports/StopReportPage.js | 33 ++++---- modern/src/reports/SummaryReportPage.js | 38 +++++---- modern/src/reports/TripReportPage.js | 33 ++++---- modern/src/settings/ComputedAttributePage.js | 60 ++++++++------ modern/src/settings/ComputedAttributesPage.js | 80 +++++++++--------- modern/src/settings/DriverPage.js | 27 +++--- modern/src/settings/DriversPage.js | 74 ++++++++--------- modern/src/settings/GroupPage.js | 27 +++--- modern/src/settings/GroupsPage.js | 70 ++++++++-------- modern/src/settings/MaintenancePage.js | 90 ++++++++++---------- modern/src/settings/MaintenancesPage.js | 84 +++++++++---------- modern/src/settings/NotificationPage.js | 56 +++++++------ modern/src/settings/NotificationsPage.js | 80 +++++++++--------- modern/src/settings/OptionsLayout/useRoutes.js | 26 +++--- modern/src/setupProxy.js | 4 +- modern/src/store/devices.js | 8 +- modern/src/store/drivers.js | 4 +- modern/src/store/geofences.js | 6 +- modern/src/store/groups.js | 4 +- modern/src/store/maintenances.js | 4 +- modern/src/store/positions.js | 4 +- modern/src/theme/dimensions.js | 2 +- modern/src/theme/index.js | 2 +- modern/src/theme/overrides.js | 50 ++++++------ 84 files changed, 1506 insertions(+), 1393 deletions(-) (limited to 'modern/src') diff --git a/modern/craco.config.js b/modern/craco.config.js index 3e5d98e..32971f2 100644 --- a/modern/craco.config.js +++ b/modern/craco.config.js @@ -1,12 +1,12 @@ module.exports = { webpack: { - configure: webpackConfig => { + configure: (webpackConfig) => { const scopePluginIndex = webpackConfig.resolve.plugins.findIndex( - ({ constructor }) => constructor && constructor.name === 'ModuleScopePlugin' + ({ constructor }) => constructor && constructor.name === 'ModuleScopePlugin', ); webpackConfig.resolve.plugins.splice(scopePluginIndex, 1); return webpackConfig; - } - } + }, + }, }; diff --git a/modern/src/App.js b/modern/src/App.js index b76995e..ac7cdb2 100644 --- a/modern/src/App.js +++ b/modern/src/App.js @@ -1,7 +1,9 @@ import React from 'react'; import { ThemeProvider } from '@material-ui/core/styles'; -import { Switch, Route } from 'react-router-dom' +import { Switch, Route } from 'react-router-dom'; import CssBaseline from '@material-ui/core/CssBaseline'; +import { useSelector } from 'react-redux'; +import { LinearProgress } from '@material-ui/core'; import MainPage from './MainPage'; import RouteReportPage from './reports/RouteReportPage'; import ServerPage from './admin/ServerPage'; @@ -16,8 +18,6 @@ import GroupPage from './settings/GroupPage'; import PositionPage from './PositionPage'; import EventReportPage from './reports/EventReportPage'; import ReplayPage from './reports/ReplayPage'; -import { useSelector } from 'react-redux'; -import { LinearProgress } from '@material-ui/core'; import TripReportPage from './reports/TripReportPage'; import StopReportPage from './reports/StopReportPage'; import SummaryReportPage from './reports/SummaryReportPage'; @@ -40,7 +40,7 @@ import GeofencesPage from './GeofencesPage'; import GeofencePage from './GeofencePage'; const App = () => { - const initialized = useSelector(state => !!state.session.server && !!state.session.user); + const initialized = useSelector((state) => !!state.session.server && !!state.session.user); return ( @@ -48,44 +48,44 @@ const App = () => { - - - + + + {!initialized ? () : ( - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + )} ); -} +}; export default App; diff --git a/modern/src/CachingController.js b/modern/src/CachingController.js index 3f808de..d6e2006 100644 --- a/modern/src/CachingController.js +++ b/modern/src/CachingController.js @@ -1,10 +1,12 @@ -import { useDispatch, useSelector } from 'react-redux'; -import { connect } from 'react-redux'; -import { geofencesActions, groupsActions, driversActions, maintenancesActions } from './store'; +import { useDispatch, useSelector, connect } from 'react-redux'; + +import { + geofencesActions, groupsActions, driversActions, maintenancesActions, +} from './store'; import { useEffectAsync } from './reactHelper'; const CachingController = () => { - const authenticated = useSelector(state => !!state.session.user); + const authenticated = useSelector((state) => !!state.session.user); const dispatch = useDispatch(); useEffectAsync(async () => { @@ -23,8 +25,8 @@ const CachingController = () => { dispatch(groupsActions.update(await response.json())); } } - }, [authenticated]); - + }, [authenticated]); + useEffectAsync(async () => { if (authenticated) { const response = await fetch('/api/drivers'); @@ -33,7 +35,7 @@ const CachingController = () => { } } }, [authenticated]); - + useEffectAsync(async () => { if (authenticated) { const response = await fetch('/api/maintenance'); @@ -41,9 +43,9 @@ const CachingController = () => { dispatch(maintenancesActions.update(await response.json())); } } - }, [authenticated]); - + }, [authenticated]); + return null; -} +}; export default connect()(CachingController); diff --git a/modern/src/DevicePage.js b/modern/src/DevicePage.js index ed5a6cb..a20ba22 100644 --- a/modern/src/DevicePage.js +++ b/modern/src/DevicePage.js @@ -1,10 +1,12 @@ import React, { useState } from 'react'; import TextField from '@material-ui/core/TextField'; +import { + Accordion, AccordionSummary, AccordionDetails, makeStyles, Typography, FormControlLabel, Checkbox, +} from '@material-ui/core'; +import ExpandMoreIcon from '@material-ui/icons/ExpandMore'; import t from './common/localization'; import EditItemView from './EditItemView'; -import { Accordion, AccordionSummary, AccordionDetails, makeStyles, Typography, FormControlLabel, Checkbox } from '@material-ui/core'; -import ExpandMoreIcon from '@material-ui/icons/ExpandMore'; import EditAttributesView from './attributes/EditAttributesView'; import deviceAttributes from './attributes/deviceAttributes'; import SelectField from './form/SelectField'; @@ -25,7 +27,8 @@ const DevicePage = () => { return ( - {item && + {item + && ( <> }> @@ -37,15 +40,17 @@ const DevicePage = () => { setItem({...item, name: event.target.value})} + onChange={(event) => setItem({ ...item, name: event.target.value })} label={t('sharedName')} - variant="filled" /> + variant="filled" + /> setItem({...item, uniqueId: event.target.value})} + onChange={(event) => setItem({ ...item, uniqueId: event.target.value })} label={t('deviceIdentifier')} - variant="filled" /> + variant="filled" + /> @@ -58,42 +63,48 @@ const DevicePage = () => { setItem({...item, groupId: Number(event.target.value)})} + onChange={(event) => setItem({ ...item, groupId: Number(event.target.value) })} endpoint="/api/groups" label={t('groupParent')} - variant="filled" /> + variant="filled" + /> setItem({...item, phone: event.target.value})} + onChange={(event) => setItem({ ...item, phone: event.target.value })} label={t('sharedPhone')} - variant="filled" /> + variant="filled" + /> setItem({...item, model: event.target.value})} + onChange={(event) => setItem({ ...item, model: event.target.value })} label={t('deviceModel')} - variant="filled" /> + variant="filled" + /> setItem({...item, contact: event.target.value})} + onChange={(event) => setItem({ ...item, contact: event.target.value })} label={t('deviceContact')} - variant="filled" /> + variant="filled" + /> setItem({...item, category: event.target.value})} - data={deviceCategories.map(category => ({ + onChange={(event) => setItem({ ...item, category: event.target.value })} + data={deviceCategories.map((category) => ({ id: category, - name: t(`category${category.replace(/^\w/, c => c.toUpperCase())}`) + name: t(`category${category.replace(/^\w/, (c) => c.toUpperCase())}`), }))} label={t('deviceCategory')} - variant="filled" /> + variant="filled" + /> setItem({...item, disabled: event.target.checked})} />} - label={t('sharedDisabled')} /> + control={ setItem({ ...item, disabled: event.target.checked })} />} + label={t('sharedDisabled')} + /> @@ -105,12 +116,13 @@ const DevicePage = () => { setItem({...item, attributes})} + setAttributes={(attributes) => setItem({ ...item, attributes })} definitions={deviceAttributes} - /> + /> - {item.id && + {item.id + && ( }> @@ -121,57 +133,62 @@ const DevicePage = () => { + variant="filled" + /> t(prefixString('event', it.type))} + titleGetter={(it) => t(prefixString('event', it.type))} label={t('sharedNotifications')} - variant="filled" /> + variant="filled" + /> + variant="filled" + /> it.description} + titleGetter={(it) => it.description} label={t('sharedComputedAttributes')} - variant="filled" /> + variant="filled" + /> + variant="filled" + /> - } + )} - } + )} ); -} +}; export default DevicePage; diff --git a/modern/src/DevicesList.js b/modern/src/DevicesList.js index f66d717..85b936c 100644 --- a/modern/src/DevicesList.js +++ b/modern/src/DevicesList.js @@ -34,7 +34,7 @@ const DeviceRow = ({ data, index, style }) => { const { items, onMenuClick } = data; const item = items[index]; - + return (
@@ -61,7 +61,7 @@ const DeviceView = ({ updateTimestamp, onMenuClick }) => { const classes = useStyles(); const dispatch = useDispatch(); - const items = useSelector(state => Object.values(state.devices.items)); + const items = useSelector((state) => Object.values(state.devices.items)); useEffectAsync(async () => { const response = await fetch('/api/devices'); @@ -79,7 +79,8 @@ const DeviceView = ({ updateTimestamp, onMenuClick }) => { height={height} itemCount={items.length} itemData={{ items, onMenuClick }} - itemSize={72 + 1} > + itemSize={72 + 1} + > {DeviceRow} @@ -88,10 +89,8 @@ const DeviceView = ({ updateTimestamp, onMenuClick }) => { ); }; -const DevicesList = () => { - return ( - - ); -}; +const DevicesList = () => ( + +); export default DevicesList; diff --git a/modern/src/EditCollectionView.js b/modern/src/EditCollectionView.js index 572a1d1..7d5e4b2 100644 --- a/modern/src/EditCollectionView.js +++ b/modern/src/EditCollectionView.js @@ -10,7 +10,7 @@ import { useSelector } from 'react-redux'; import t from './common/localization'; import RemoveDialog from './RemoveDialog'; -const useStyles = makeStyles(theme => ({ +const useStyles = makeStyles((theme) => ({ fab: { position: 'absolute', bottom: theme.spacing(2), @@ -18,7 +18,9 @@ const useStyles = makeStyles(theme => ({ }, })); -const EditCollectionView = ({ content, editPath, endpoint, disableAdd }) => { +const EditCollectionView = ({ + content, editPath, endpoint, disableAdd, +}) => { const classes = useStyles(); const history = useHistory(); @@ -26,47 +28,48 @@ const EditCollectionView = ({ content, editPath, endpoint, disableAdd }) => { const [selectedAnchorEl, setSelectedAnchorEl] = useState(null); const [removeDialogShown, setRemoveDialogShown] = useState(false); const [updateTimestamp, setUpdateTimestamp] = useState(Date.now()); - const adminEnabled = useSelector(state => state.session.user && state.session.user.administrator); + const adminEnabled = useSelector((state) => state.session.user && state.session.user.administrator); const menuShow = (anchorId, itemId) => { setSelectedAnchorEl(anchorId); setSelectedId(itemId); - } + }; const menuHide = () => { setSelectedAnchorEl(null); - } + }; const handleAdd = () => { history.push(editPath); menuHide(); - } + }; const handleEdit = () => { history.push(`${editPath}/${selectedId}`); menuHide(); - } + }; const handleRemove = () => { setRemoveDialogShown(true); menuHide(); - } + }; const handleRemoveResult = () => { setRemoveDialogShown(false); setUpdateTimestamp(Date.now()); - } + }; const Content = content; return ( <> - {adminEnabled && !disableAdd && + {adminEnabled && !disableAdd + && ( - } + )} {t('sharedEdit')} {t('sharedRemove')} @@ -74,6 +77,6 @@ const EditCollectionView = ({ content, editPath, endpoint, disableAdd }) => { ); -} +}; export default EditCollectionView; diff --git a/modern/src/EditItemView.js b/modern/src/EditItemView.js index bab56c7..a77f578 100644 --- a/modern/src/EditItemView.js +++ b/modern/src/EditItemView.js @@ -9,20 +9,22 @@ import t from './common/localization'; import { useEffectAsync } from './reactHelper'; import OptionsLayout from './settings/OptionsLayout'; -const useStyles = makeStyles(theme => ({ +const useStyles = makeStyles((theme) => ({ container: { - marginTop: theme.spacing(2) + marginTop: theme.spacing(2), }, buttons: { display: 'flex', justifyContent: 'space-evenly', '& > *': { - flexBasis: '33%' - } - } + flexBasis: '33%', + }, + }, })); -const EditItemView = ({ children, endpoint, item, setItem }) => { +const EditItemView = ({ + children, endpoint, item, setItem, +}) => { const history = useHistory(); const classes = useStyles(); const { id } = useParams(); @@ -47,7 +49,7 @@ const EditItemView = ({ children, endpoint, item, setItem }) => { const response = await fetch(url, { method: !id ? 'POST' : 'PUT', headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify(item) + body: JSON.stringify(item), }); if (response.ok) { diff --git a/modern/src/GeofencePage.js b/modern/src/GeofencePage.js index 6c5db9b..06456fc 100644 --- a/modern/src/GeofencePage.js +++ b/modern/src/GeofencePage.js @@ -1,10 +1,12 @@ import React, { useState } from 'react'; import TextField from '@material-ui/core/TextField'; +import { + Accordion, AccordionSummary, AccordionDetails, makeStyles, Typography, +} from '@material-ui/core'; +import ExpandMoreIcon from '@material-ui/icons/ExpandMore'; 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'; @@ -21,7 +23,8 @@ const GeofencePage = () => { return ( - {item && + {item + && ( <> }> @@ -33,9 +36,10 @@ const GeofencePage = () => { setItem({...item, name: event.target.value})} + onChange={(event) => setItem({ ...item, name: event.target.value })} label={t('sharedName')} - variant="filled" /> + variant="filled" + /> @@ -47,15 +51,15 @@ const GeofencePage = () => { setItem({...item, attributes})} + setAttributes={(attributes) => setItem({ ...item, attributes })} definitions={geofenceAttributes} - /> + /> - } + )} ); -} +}; export default GeofencePage; diff --git a/modern/src/GeofencesList.js b/modern/src/GeofencesList.js index 2988bef..572ac5b 100644 --- a/modern/src/GeofencesList.js +++ b/modern/src/GeofencesList.js @@ -28,7 +28,7 @@ const GeofenceView = ({ onMenuClick }) => { const classes = useStyles(); const dispatch = useDispatch(); - const items = useSelector(state => Object.values(state.geofences.items)); + const items = useSelector((state) => Object.values(state.geofences.items)); return ( @@ -47,12 +47,10 @@ const GeofenceView = ({ onMenuClick }) => { ))} ); -} +}; -const GeofencesList = () => { - return ( - - ); -} +const GeofencesList = () => ( + +); export default GeofencesList; diff --git a/modern/src/GeofencesPage.js b/modern/src/GeofencesPage.js index 59b8459..71219c1 100644 --- a/modern/src/GeofencesPage.js +++ b/modern/src/GeofencesPage.js @@ -1,21 +1,22 @@ import React from 'react'; -import { Divider, isWidthUp, makeStyles, withWidth, Typography, IconButton } from '@material-ui/core'; +import { + Divider, isWidthUp, makeStyles, withWidth, Typography, IconButton, +} from '@material-ui/core'; import Drawer from '@material-ui/core/Drawer'; import ContainerDimensions from 'react-container-dimensions'; +import ArrowBackIcon from '@material-ui/icons/ArrowBack'; import Map from './map/Map'; import CurrentLocationMap from './map/CurrentLocationMap'; import GeofenceEditMap from './map/GeofenceEditMap'; import GeofencesList from './GeofencesList'; -import ArrowBackIcon from '@material-ui/icons/ArrowBack'; - import t from './common/localization'; -const useStyles = makeStyles(theme => ({ +const useStyles = makeStyles((theme) => ({ root: { height: '100%', display: 'flex', - flexDirection: 'column' + flexDirection: 'column', }, content: { flexGrow: 1, @@ -23,27 +24,27 @@ const useStyles = makeStyles(theme => ({ display: 'flex', flexDirection: 'row', [theme.breakpoints.down('xs')]: { - flexDirection: 'column-reverse' - } + flexDirection: 'column-reverse', + }, }, drawerPaper: { position: 'relative', [theme.breakpoints.up('sm')]: { - width: 350 + width: 350, }, [theme.breakpoints.down('xs')]: { - height: 250 - } + height: 250, + }, }, drawerHeader: { ...theme.mixins.toolbar, display: 'flex', alignItems: 'center', - padding: theme.spacing(0, 1) + padding: theme.spacing(0, 1), }, mapContainer: { - flexGrow: 1 - } + flexGrow: 1, + }, })); const GeofencesPage = ({ width }) => { diff --git a/modern/src/Logo.js b/modern/src/Logo.js index bea14d8..1fb1ac8 100644 --- a/modern/src/Logo.js +++ b/modern/src/Logo.js @@ -1,31 +1,28 @@ import React from 'react'; -const Logo = ({ fill }) => { - - return ( - - - - - - - - - - +const Logo = ({ fill }) => ( + + + + + + + + + + - - - - - - - - + + + + + + + - - - ) -} + + + +); export default Logo; diff --git a/modern/src/MainPage.js b/modern/src/MainPage.js index 8d0b18d..88608df 100644 --- a/modern/src/MainPage.js +++ b/modern/src/MainPage.js @@ -11,7 +11,7 @@ import GeofenceMap from './map/GeofenceMap'; import CurrentPositionsMap from './map/CurrentPositionsMap'; import CurrentLocationMap from './map/CurrentLocationMap'; -const useStyles = makeStyles(theme => ({ +const useStyles = makeStyles((theme) => ({ root: { height: '100%', display: 'flex', @@ -24,7 +24,7 @@ const useStyles = makeStyles(theme => ({ flexDirection: 'row', [theme.breakpoints.down('xs')]: { flexDirection: 'column-reverse', - } + }, }, drawerPaper: { position: 'relative', @@ -50,8 +50,9 @@ const MainPage = ({ width }) => {
+ variant="permanent" + classes={{ paper: classes.drawerPaper }} + >
@@ -68,6 +69,6 @@ const MainPage = ({ width }) => {
); -} +}; export default withWidth()(MainPage); diff --git a/modern/src/MainToolbar.js b/modern/src/MainToolbar.js index 311f024..9a72729 100644 --- a/modern/src/MainToolbar.js +++ b/modern/src/MainToolbar.js @@ -2,7 +2,6 @@ import React, { useState } from 'react'; import { useHistory } from 'react-router-dom'; import { makeStyles } from '@material-ui/core/styles'; import { useDispatch, useSelector } from 'react-redux'; -import { sessionActions } from './store'; import AppBar from '@material-ui/core/AppBar'; import Toolbar from '@material-ui/core/Toolbar'; import Typography from '@material-ui/core/Typography'; @@ -20,23 +19,24 @@ import MapIcon from '@material-ui/icons/Map'; import PersonIcon from '@material-ui/icons/Person'; import DescriptionIcon from '@material-ui/icons/Description'; import ReplayIcon from '@material-ui/icons/Replay'; +import { sessionActions } from './store'; import t from './common/localization'; import * as selectors from './selectors'; -const useStyles = makeStyles(theme => ({ +const useStyles = makeStyles((theme) => ({ flex: { - flexGrow: 1 + flexGrow: 1, }, appBar: { - zIndex: theme.zIndex.drawer + 1 + zIndex: theme.zIndex.drawer + 1, }, list: { - width: 250 + width: 250, }, menuButton: { marginLeft: -12, - marginRight: 20 - } + marginRight: 20, + }, })); const MainToolbar = () => { @@ -111,7 +111,7 @@ const MainToolbar = () => { history.push(`/settings/notifications`)} + onClick={() => history.push('/settings/notifications')} > diff --git a/modern/src/PositionPage.js b/modern/src/PositionPage.js index a91a7a1..f1766f6 100644 --- a/modern/src/PositionPage.js +++ b/modern/src/PositionPage.js @@ -1,14 +1,16 @@ import React, { Fragment, useState } from 'react'; -import t from './common/localization'; -import { makeStyles, Typography, ListItem, ListItemText, ListItemSecondaryAction, List, Container, Paper, Divider } from '@material-ui/core'; +import { + makeStyles, Typography, ListItem, ListItemText, ListItemSecondaryAction, List, Container, Paper, Divider, +} from '@material-ui/core'; import { useParams } from 'react-router-dom'; +import t from './common/localization'; import { useEffectAsync } from './reactHelper'; import MainToolbar from './MainToolbar'; import { formatPosition } from './common/formatter'; import { prefixString } from './common/stringUtils'; -const useStyles = makeStyles(theme => ({ +const useStyles = makeStyles((theme) => ({ root: { marginTop: theme.spacing(2), marginBottom: theme.spacing(2), @@ -26,7 +28,7 @@ const PositionPage = () => { if (id) { const response = await fetch(`/api/positions?id=${id}`, { headers: { - 'Accept': 'application/json' + Accept: 'application/json', }, }); if (response.ok) { @@ -38,28 +40,27 @@ const PositionPage = () => { } }, [id]); - const formatKey = (key) => { - return t(prefixString('position', key)) || `${t('sharedAttribute')} "${key}"`; - }; + const formatKey = (key) => t(prefixString('position', key)) || `${t('sharedAttribute')} "${key}"`; const attributesList = () => { - const combinedList = {...item, ...item.attributes}; + const combinedList = { ...item, ...item.attributes }; return Object.entries(combinedList).filter(([_, value]) => typeof value !== 'object'); - } + }; return ( <> - + - {item && + {item + && ( {attributesList().map(([key, value], index, list) => ( + /> {formatPosition(value, key)} @@ -70,11 +71,11 @@ const PositionPage = () => { ))} - } + )} ); -} +}; export default PositionPage; diff --git a/modern/src/RegisterDialog.js b/modern/src/RegisterDialog.js index c640c51..c4b99f3 100644 --- a/modern/src/RegisterDialog.js +++ b/modern/src/RegisterDialog.js @@ -1,4 +1,3 @@ -import t from './common/localization' import React, { useState } from 'react'; import Button from '@material-ui/core/Button'; import Dialog from '@material-ui/core/Dialog'; @@ -7,6 +6,7 @@ import DialogContent from '@material-ui/core/DialogContent'; import DialogContentText from '@material-ui/core/DialogContentText'; import TextField from '@material-ui/core/TextField'; import Snackbar from '@material-ui/core/Snackbar'; +import t from './common/localization'; const RegisterDialog = ({ showDialog, onResult }) => { const [name, setName] = useState(''); @@ -14,80 +14,79 @@ const RegisterDialog = ({ showDialog, onResult }) => { const [password, setPassword] = useState(''); const [snackbarOpen, setSnackbarOpen] = useState(false); - const submitDisabled = () => { - return !name || !/(.+)@(.+)\.(.{2,})/.test(email) || !password; - } + const submitDisabled = () => !name || !/(.+)@(.+)\.(.{2,})/.test(email) || !password; const handleRegister = async () => { const response = await fetch('/api/users', { method: 'POST', headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({name, email, password}) + body: JSON.stringify({ name, email, password }), }); if (response.ok) { showDialog = false; setSnackbarOpen(true); - } - } + } + }; if (snackbarOpen) { - return ( { onResult(true) }} - message={t('loginCreated')} /> + onClose={() => { onResult(true); }} + message={t('loginCreated')} + /> ); - - } else if (showDialog) { - + } if (showDialog) { return ( { onResult(false) }}> + open + onClose={() => { onResult(false); }} + > {t('loginRegister')} setName(event.target.value)} /> + onChange={(event) => setName(event.target.value)} + /> setEmail(event.target.value)} /> + autoComplete="email" + onChange={(event) => setEmail(event.target.value)} + /> setPassword(event.target.value)} /> + type="password" + autoComplete="current-password" + onChange={(event) => setPassword(event.target.value)} + /> - ) - + ); } }; diff --git a/modern/src/RemoveDialog.js b/modern/src/RemoveDialog.js index bbcfb22..8ff162c 100644 --- a/modern/src/RemoveDialog.js +++ b/modern/src/RemoveDialog.js @@ -1,12 +1,14 @@ -import t from './common/localization' import React from 'react'; import Button from '@material-ui/core/Button'; import Dialog from '@material-ui/core/Dialog'; import DialogActions from '@material-ui/core/DialogActions'; import DialogContent from '@material-ui/core/DialogContent'; import DialogContentText from '@material-ui/core/DialogContentText'; +import t from './common/localization'; -const RemoveDialog = ({ open, endpoint, itemId, onResult }) => { +const RemoveDialog = ({ + open, endpoint, itemId, onResult, +}) => { const handleRemove = async () => { const response = await fetch(`/api/${endpoint}/${itemId}`, { method: 'DELETE' }); if (response.ok) { @@ -17,7 +19,8 @@ const RemoveDialog = ({ open, endpoint, itemId, onResult }) => { return ( { onResult(false) }}> + onClose={() => { onResult(false); }} + > {t('sharedRemoveConfirm')} diff --git a/modern/src/SocketController.js b/modern/src/SocketController.js index cda693a..901f506 100644 --- a/modern/src/SocketController.js +++ b/modern/src/SocketController.js @@ -1,19 +1,19 @@ -import { useDispatch, useSelector } from 'react-redux'; -import { connect } from 'react-redux'; -import { positionsActions, devicesActions, sessionActions } from './store'; +import { useDispatch, useSelector, connect } from 'react-redux'; + import { useHistory } from 'react-router-dom'; +import { positionsActions, devicesActions, sessionActions } from './store'; import { useEffectAsync } from './reactHelper'; -const displayNotifications = events => { - if ("Notification" in window) { - if (Notification.permission === "granted") { +const displayNotifications = (events) => { + if ('Notification' in window) { + if (Notification.permission === 'granted') { for (const event of events) { const notification = new Notification(`Event: ${event.type}`); setTimeout(notification.close.bind(notification), 4 * 1000); } - } else if (Notification.permission !== "denied") { - Notification.requestPermission(permission => { - if (permission === "granted") { + } else if (Notification.permission !== 'denied') { + Notification.requestPermission((permission) => { + if (permission === 'granted') { displayNotifications(events); } }); @@ -24,11 +24,11 @@ const displayNotifications = events => { const SocketController = () => { const dispatch = useDispatch(); const history = useHistory(); - const authenticated = useSelector(state => !!state.session.user); + const authenticated = useSelector((state) => !!state.session.user); const connectSocket = () => { const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:'; - const socket = new WebSocket(protocol + '//' + window.location.host + '/api/socket'); + const socket = new WebSocket(`${protocol}//${window.location.host}/api/socket`); socket.onclose = () => { setTimeout(() => connectSocket(), 60 * 1000); @@ -46,7 +46,7 @@ const SocketController = () => { displayNotifications(data.events); } }; - } + }; useEffectAsync(async () => { const response = await fetch('/api/server'); @@ -73,6 +73,6 @@ const SocketController = () => { }, [authenticated]); return null; -} +}; export default connect()(SocketController); diff --git a/modern/src/StartPage.js b/modern/src/StartPage.js index 53f8c35..1472f50 100644 --- a/modern/src/StartPage.js +++ b/modern/src/StartPage.js @@ -2,7 +2,7 @@ import React from 'react'; import { useMediaQuery, makeStyles, Paper } from '@material-ui/core'; import { useTheme } from '@material-ui/core/styles'; -const useStyles = makeStyles(theme => ({ +const useStyles = makeStyles((theme) => ({ root: { display: 'flex', height: '100vh', @@ -23,20 +23,20 @@ const useStyles = makeStyles(theme => ({ }, }, paper: { - display:'flex', + display: 'flex', flexDirection: 'column', justifyContent: 'center', alignItems: 'center', flex: 1, boxShadow: '-2px 0px 16px rgba(0, 0, 0, 0.25)', [theme.breakpoints.up('lg')]: { - padding: theme.spacing(0, 25, 0, 0) + padding: theme.spacing(0, 25, 0, 0), }, }, form: { maxWidth: theme.spacing(52), padding: theme.spacing(5), - width: "100%", + width: '100%', }, })); @@ -47,11 +47,12 @@ const StartPage = ({ children }) => { return (
- {!useMediaQuery(theme.breakpoints.down('md')) && + {!useMediaQuery(theme.breakpoints.down('md')) + && ( - + - } + )}
@@ -59,7 +60,7 @@ const StartPage = ({ children }) => {
- ) -} + ); +}; export default StartPage; diff --git a/modern/src/UserPage.js b/modern/src/UserPage.js index dfe8b98..6afbdf7 100644 --- a/modern/src/UserPage.js +++ b/modern/src/UserPage.js @@ -1,11 +1,13 @@ import React, { useState } from 'react'; import TextField from '@material-ui/core/TextField'; +import { + Accordion, AccordionSummary, AccordionDetails, makeStyles, Typography, +} from '@material-ui/core'; +import ExpandMoreIcon from '@material-ui/icons/ExpandMore'; import t from './common/localization'; import userAttributes from './attributes/userAttributes'; 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 LinkField from './form/LinkField'; @@ -22,7 +24,8 @@ const UserPage = () => { return ( - {item && + {item + && ( <> }> @@ -34,21 +37,24 @@ const UserPage = () => { setItem({...item, name: event.target.value})} + onChange={(event) => setItem({ ...item, name: event.target.value })} label={t('sharedName')} - variant="filled" /> + variant="filled" + /> setItem({...item, email: event.target.value})} + onChange={(event) => setItem({ ...item, email: event.target.value })} label={t('userEmail')} - variant="filled" /> + variant="filled" + /> setItem({...item, password: event.target.value})} + onChange={(event) => setItem({ ...item, password: event.target.value })} label={t('userPassword')} - variant="filled" /> + variant="filled" + /> @@ -60,12 +66,13 @@ const UserPage = () => { setItem({...item, attributes})} + setAttributes={(attributes) => setItem({ ...item, attributes })} definitions={userAttributes} - /> + /> - {item.id && + {item.id + && ( }> @@ -76,28 +83,30 @@ const UserPage = () => { + variant="filled" + /> + variant="filled" + /> - } + )} - } + )} ); -} +}; export default UserPage; diff --git a/modern/src/admin/ServerPage.js b/modern/src/admin/ServerPage.js index c33a631..6d5b575 100644 --- a/modern/src/admin/ServerPage.js +++ b/modern/src/admin/ServerPage.js @@ -1,31 +1,33 @@ import React from 'react'; import TextField from '@material-ui/core/TextField'; -import t from '../common/localization'; -import { Accordion, AccordionSummary, AccordionDetails, makeStyles, Typography, Button, FormControl, Container, Checkbox, FormControlLabel } from '@material-ui/core'; +import { + Accordion, AccordionSummary, AccordionDetails, makeStyles, Typography, Button, FormControl, Container, Checkbox, FormControlLabel, +} from '@material-ui/core'; import ExpandMoreIcon from '@material-ui/icons/ExpandMore'; import { useHistory } from 'react-router-dom'; import { useDispatch, useSelector } from 'react-redux'; +import t from '../common/localization'; import { sessionActions } from '../store'; import EditAttributesView from '../attributes/EditAttributesView'; import deviceAttributes from '../attributes/deviceAttributes'; import userAttributes from '../attributes/userAttributes'; import OptionsLayout from '../settings/OptionsLayout'; -const useStyles = makeStyles(theme => ({ +const useStyles = makeStyles((theme) => ({ container: { - marginTop: theme.spacing(2) + marginTop: theme.spacing(2), }, buttons: { display: 'flex', justifyContent: 'space-evenly', '& > *': { - flexBasis: '33%' - } + flexBasis: '33%', + }, }, details: { - flexDirection: 'column' - } + flexDirection: 'column', + }, })); const ServerPage = () => { @@ -33,15 +35,14 @@ const ServerPage = () => { const dispatch = useDispatch(); const classes = useStyles(); - const item = useSelector(state => state.session.server); - const setItem = updatedItem => - dispatch(sessionActions.updateServer(updatedItem)); + const item = useSelector((state) => state.session.server); + const setItem = (updatedItem) => dispatch(sessionActions.updateServer(updatedItem)); const handleSave = async () => { const response = await fetch('/api/server', { method: 'PUT', headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify(item) + body: JSON.stringify(item), }); if (response.ok) { @@ -64,9 +65,7 @@ const ServerPage = () => { - setItem({ ...item, announcement: event.target.value }) - } + onChange={(event) => setItem({ ...item, announcement: event.target.value })} label={t('serverAnnouncement')} variant="filled" /> @@ -80,53 +79,45 @@ const ServerPage = () => { - setItem({ ...item, registration: event.target.checked }) - } + onChange={(event) => setItem({ ...item, registration: event.target.checked })} /> - } + )} label={t('serverRegistration')} /> - setItem({ ...item, readonly: event.target.checked }) - } + onChange={(event) => setItem({ ...item, readonly: event.target.checked })} /> - } + )} label={t('serverReadonly')} /> - setItem({ - ...item, - deviceReadonly: event.target.checked - }) - } + onChange={(event) => setItem({ + ...item, + deviceReadonly: event.target.checked, + })} /> - } + )} label={t('userDeviceReadonly')} /> - setItem({ - ...item, - limitCommands: event.target.checked - }) - } + onChange={(event) => setItem({ + ...item, + limitCommands: event.target.checked, + })} /> - } + )} label={t('userLimitCommands')} /> @@ -140,9 +131,9 @@ const ServerPage = () => { setItem({ ...item, attributes })} + setAttributes={(attributes) => setItem({ ...item, attributes })} definitions={{ ...userAttributes, ...deviceAttributes }} - /> + /> diff --git a/modern/src/admin/StatisticsPage.js b/modern/src/admin/StatisticsPage.js index b1504c8..8a6e601 100644 --- a/modern/src/admin/StatisticsPage.js +++ b/modern/src/admin/StatisticsPage.js @@ -1,9 +1,10 @@ - import React, { useState } from 'react'; -import { FormControl, InputLabel,Select, MenuItem, TextField, Button, TableContainer, Table, TableRow, TableCell, TableHead, TableBody, Paper } from '@material-ui/core'; +import { + FormControl, InputLabel, Select, MenuItem, TextField, Button, TableContainer, Table, TableRow, TableCell, TableHead, TableBody, Paper, +} from '@material-ui/core'; +import moment from 'moment'; import t from '../common/localization'; import { formatDate } from '../common/formatter'; -import moment from 'moment'; import OptionsLayout from '../settings/OptionsLayout'; const Filter = ({ setItems }) => { @@ -59,10 +60,10 @@ const Filter = ({ setItems }) => { const query = new URLSearchParams({ from: selectedFrom.toISOString(), - to: selectedTo.toISOString() + to: selectedTo.toISOString(), }); const response = await fetch(`/api/statistics?${query.toString()}`, { - Accept: 'application/json' + Accept: 'application/json', }); if (response.ok) { setItems(await response.json()); @@ -73,7 +74,7 @@ const Filter = ({ setItems }) => { <> {t('reportPeriod')} - setPeriod(e.target.value)}> {t('reportToday')} {t('reportYesterday')} {t('reportThisWeek')} @@ -90,9 +91,7 @@ const Filter = ({ setItems }) => { label={t('reportFrom')} type="datetime-local" value={from.format(moment.HTML5_FMT.DATETIME_LOCAL)} - onChange={e => - setFrom(moment(e.target.value, moment.HTML5_FMT.DATETIME_LOCAL)) - } + onChange={(e) => setFrom(moment(e.target.value, moment.HTML5_FMT.DATETIME_LOCAL))} fullWidth /> )} @@ -103,9 +102,7 @@ const Filter = ({ setItems }) => { label={t('reportTo')} type="datetime-local" value={to.format(moment.HTML5_FMT.DATETIME_LOCAL)} - onChange={e => - setTo(moment(e.target.value, moment.HTML5_FMT.DATETIME_LOCAL)) - } + onChange={(e) => setTo(moment(e.target.value, moment.HTML5_FMT.DATETIME_LOCAL))} fullWidth /> )} @@ -117,7 +114,7 @@ const Filter = ({ setItems }) => { > {t('reportShow')} - + ); }; @@ -144,7 +141,7 @@ const StatisticsPage = () => { - {items.map(item => ( + {items.map((item) => ( {formatDate(item.captureTime)} {item.activeUsers} @@ -155,7 +152,7 @@ const StatisticsPage = () => { {item.mailSent} {item.smsSent} {item.geocoderRequests} - {item.geolocationRequests} + {item.geolocationRequests} ))} diff --git a/modern/src/admin/UsersPage.js b/modern/src/admin/UsersPage.js index ceaab6a..6afe099 100644 --- a/modern/src/admin/UsersPage.js +++ b/modern/src/admin/UsersPage.js @@ -1,5 +1,7 @@ import React, { useState } from 'react'; -import { TableContainer, Table, TableRow, TableCell, TableHead, TableBody, makeStyles, IconButton } from '@material-ui/core'; +import { + TableContainer, Table, TableRow, TableCell, TableHead, TableBody, makeStyles, IconButton, +} from '@material-ui/core'; import MoreVertIcon from '@material-ui/icons/MoreVert'; import t from '../common/localization'; import { useEffectAsync } from '../reactHelper'; @@ -7,11 +9,11 @@ import EditCollectionView from '../EditCollectionView'; import { formatBoolean } from '../common/formatter'; import OptionsLayout from '../settings/OptionsLayout'; -const useStyles = makeStyles(theme => ({ +const useStyles = makeStyles((theme) => ({ columnAction: { width: theme.spacing(1), - padding: theme.spacing(0, 1) - } + padding: theme.spacing(0, 1), + }, })); const UsersView = ({ updateTimestamp, onMenuClick }) => { @@ -28,48 +30,46 @@ const UsersView = ({ updateTimestamp, onMenuClick }) => { return ( - - - - - {t('sharedName')} - {t('userEmail')} - {t('userAdmin')} - {t('sharedDisabled')} - - - - {items.map(item => ( - - +
+ + + + {t('sharedName')} + {t('userEmail')} + {t('userAdmin')} + {t('sharedDisabled')} + + + + {items.map((item) => ( + + onMenuClick(event.currentTarget, item.id)} + onClick={(event) => onMenuClick(event.currentTarget, item.id)} > - - - - {item.name} - {item.email} - {formatBoolean(item, 'administrator')} - {formatBoolean(item, 'disabled')} - - ))} - -
+ + + + {item.name} + {item.email} + {formatBoolean(item, 'administrator')} + {formatBoolean(item, 'disabled')} + + ))} + +
); }; -const UsersPage = () => { - return ( - - - - ); -}; +const UsersPage = () => ( + + + +); export default UsersPage; diff --git a/modern/src/attributes/AddAttributeDialog.js b/modern/src/attributes/AddAttributeDialog.js index ee4c48c..24c208a 100644 --- a/modern/src/attributes/AddAttributeDialog.js +++ b/modern/src/attributes/AddAttributeDialog.js @@ -1,12 +1,14 @@ import React, { useState } from 'react'; -import { Button, Dialog, DialogActions, DialogContent, FormControl, InputLabel, MenuItem, Select, TextField } from "@material-ui/core"; +import { + Button, Dialog, DialogActions, DialogContent, FormControl, InputLabel, MenuItem, Select, TextField, +} from '@material-ui/core'; -import t from '../common/localization'; import { Autocomplete, createFilterOptions } from '@material-ui/lab'; +import t from '../common/localization'; const AddAttributeDialog = ({ open, onResult, definitions }) => { const filter = createFilterOptions({ - stringify: option => option.name, + stringify: (option) => option.name, }); const options = Object.entries(definitions).map(([key, value]) => ({ @@ -39,10 +41,8 @@ const AddAttributeDialog = ({ open, onResult, definitions }) => { return filtered; }} options={options} - getOptionLabel={option => { - return option && typeof option === 'object' ? option.name : option; - }} - renderOption={option => option.name} + getOptionLabel={(option) => (option && typeof option === 'object' ? option.name : option)} + renderOption={(option) => option.name} freeSolo renderInput={(params) => ( @@ -52,14 +52,16 @@ const AddAttributeDialog = ({ open, onResult, definitions }) => { variant="filled" margin="normal" fullWidth - disabled={key in definitions}> + disabled={key in definitions} + > {t('sharedType')}
@@ -67,17 +69,19 @@ const AddAttributeDialog = ({ open, onResult, definitions }) => {
- ) -} + ); +}; export default AddAttributeDialog; diff --git a/modern/src/attributes/EditAttributesView.js b/modern/src/attributes/EditAttributesView.js index 619d857..5ca7cad 100644 --- a/modern/src/attributes/EditAttributesView.js +++ b/modern/src/attributes/EditAttributesView.js @@ -1,13 +1,14 @@ import React, { useState } from 'react'; -import t from '../common/localization'; - -import { Button, Checkbox, FilledInput, FormControl, FormControlLabel, Grid, IconButton, InputAdornment, InputLabel, makeStyles } from "@material-ui/core"; +import { + Button, Checkbox, FilledInput, FormControl, FormControlLabel, Grid, IconButton, InputAdornment, InputLabel, makeStyles, +} from '@material-ui/core'; import CloseIcon from '@material-ui/icons/Close'; import AddIcon from '@material-ui/icons/Add'; +import t from '../common/localization'; import AddAttributeDialog from './AddAttributeDialog'; -const useStyles = makeStyles(theme => ({ +const useStyles = makeStyles((theme) => ({ addButton: { marginTop: theme.spacing(2), marginBottom: theme.spacing(1), @@ -23,8 +24,8 @@ const EditAttributesView = ({ attributes, setAttributes, definitions }) => { const [addDialogShown, setAddDialogShown] = useState(false); const convertToList = (attributes) => { - let booleanList = []; - let otherList = []; + const booleanList = []; + const otherList = []; for (const key in attributes) { const value = attributes[key]; const type = getAttributeType(value); @@ -35,12 +36,12 @@ const EditAttributesView = ({ attributes, setAttributes, definitions }) => { } } return otherList.concat(booleanList); - } + }; const handleAddResult = (definition) => { setAddDialogShown(false); if (definition) { - switch(definition.type) { + switch (definition.type) { case 'number': updateAttribute(definition.key, 0); break; @@ -48,20 +49,20 @@ const EditAttributesView = ({ attributes, setAttributes, definitions }) => { updateAttribute(definition.key, false); break; default: - updateAttribute(definition.key, ""); + updateAttribute(definition.key, ''); break; } } - } + }; const updateAttribute = (key, value) => { - let updatedAttributes = {...attributes}; + const updatedAttributes = { ...attributes }; updatedAttributes[key] = value; setAttributes(updatedAttributes); }; const deleteAttribute = (key) => { - let updatedAttributes = {...attributes}; + const updatedAttributes = { ...attributes }; delete updatedAttributes[key]; setAttributes(updatedAttributes); }; @@ -74,11 +75,10 @@ const EditAttributesView = ({ attributes, setAttributes, definitions }) => { const getAttributeType = (value) => { if (typeof value === 'number') { return 'number'; - } else if (typeof value === 'boolean') { + } if (typeof value === 'boolean') { return 'boolean'; - } else { - return 'string'; } + return 'string'; }; return ( @@ -88,37 +88,37 @@ const EditAttributesView = ({ attributes, setAttributes, definitions }) => { return ( updateAttribute(key, e.target.checked)} - /> - } - label={getAttributeName(key)} /> + onChange={(e) => updateAttribute(key, e.target.checked)} + /> + )} + label={getAttributeName(key)} + /> deleteAttribute(key)}> ); - } else { - return ( - - {getAttributeName(key)} - updateAttribute(key, e.target.value)} - endAdornment={ - - deleteAttribute(key)}> - - - - } - /> - - ); } + return ( + + {getAttributeName(key)} + updateAttribute(key, e.target.value)} + endAdornment={( + + deleteAttribute(key)}> + + + + )} + /> + + ); })} + /> ); -} +}; export default EditAttributesView; diff --git a/modern/src/attributes/deviceAttributes.js b/modern/src/attributes/deviceAttributes.js index 891a225..26e3d92 100644 --- a/modern/src/attributes/deviceAttributes.js +++ b/modern/src/attributes/deviceAttributes.js @@ -1,7 +1,7 @@ -import t from '../common/localization' +import t from '../common/localization'; export default { - 'speedLimit': { + speedLimit: { name: t('attributeSpeedLimit'), type: 'string', }, diff --git a/modern/src/attributes/geofenceAttributes.js b/modern/src/attributes/geofenceAttributes.js index 4b9c9e6..59a8869 100644 --- a/modern/src/attributes/geofenceAttributes.js +++ b/modern/src/attributes/geofenceAttributes.js @@ -1,7 +1,7 @@ -import t from '../common/localization' +import t from '../common/localization'; export default { - 'speedLimit': { + speedLimit: { name: t('attributeSpeedLimit'), type: 'string', }, diff --git a/modern/src/attributes/positionAttributes.js b/modern/src/attributes/positionAttributes.js index b1efe3d..94f396a 100644 --- a/modern/src/attributes/positionAttributes.js +++ b/modern/src/attributes/positionAttributes.js @@ -1,19 +1,19 @@ -import t from '../common/localization' +import t from '../common/localization'; export default { - 'raw': { + raw: { name: t('positionRaw'), type: 'string', }, - 'index': { + index: { name: t('positionIndex'), type: 'number', }, - 'ignition': { + ignition: { name: t('positionIgnition'), type: 'boolean', }, - 'odometer': { + odometer: { name: t('positionOdometer'), type: 'number', dataType: 'distance', diff --git a/modern/src/attributes/userAttributes.js b/modern/src/attributes/userAttributes.js index bcec29f..6f842f9 100644 --- a/modern/src/attributes/userAttributes.js +++ b/modern/src/attributes/userAttributes.js @@ -1,7 +1,7 @@ -import t from '../common/localization' +import t from '../common/localization'; export default { - 'notificationTokens': { + notificationTokens: { name: t('attributeNotificationTokens'), type: 'string', }, @@ -49,19 +49,19 @@ export default { name: t('attributeUiHidePositionAttributes'), type: 'string', }, - 'distanceUnit': { + distanceUnit: { name: t('settingsDistanceUnit'), type: 'string', }, - 'speedUnit': { + speedUnit: { name: t('settingsSpeedUnit'), type: 'string', }, - 'volumeUnit': { + volumeUnit: { name: t('settingsVolumeUnit'), type: 'string', }, - 'timezone': { + timezone: { name: t('sharedTimezone'), type: 'string', }, diff --git a/modern/src/common/converter.js b/modern/src/common/converter.js index 9cdc623..d45db5d 100644 --- a/modern/src/common/converter.js +++ b/modern/src/common/converter.js @@ -1,4 +1,4 @@ -const speedConverter = unit => { +const speedConverter = (unit) => { switch (unit) { case 'kmh': return 1.852; @@ -10,7 +10,7 @@ const speedConverter = unit => { } }; -const distanceConverter = unit => { +const distanceConverter = (unit) => { switch (unit) { case 'mi': return 0.000621371; @@ -19,21 +19,13 @@ const distanceConverter = unit => { case 'km': default: return 0.001; - } -} + } +}; -export const speedFromKnots = (value, unit) => { - return value * speedConverter(unit); -} +export const speedFromKnots = (value, unit) => value * speedConverter(unit); -export const speedToKnots = (value, unit) => { - return value / speedConverter(unit); -} +export const speedToKnots = (value, unit) => value / speedConverter(unit); -export const distanceFromMeters = (value, unit) => { - return value * distanceConverter(unit); -} +export const distanceFromMeters = (value, unit) => value * distanceConverter(unit); -export const distanceToMeters = (value, unit) => { - return value / distanceConverter(unit); -} +export const distanceToMeters = (value, unit) => value / distanceConverter(unit); diff --git a/modern/src/common/formatter.js b/modern/src/common/formatter.js index 0d8ac4c..7441d01 100644 --- a/modern/src/common/formatter.js +++ b/modern/src/common/formatter.js @@ -1,5 +1,5 @@ import moment from 'moment'; -import t from '../common/localization'; +import t from './localization'; export const formatPosition = (value, key) => { if (value != null && typeof value === 'object') { @@ -18,29 +18,22 @@ export const formatPosition = (value, key) => { case 'course': return value.toFixed(1); case 'batteryLevel': - return value + '%'; + return `${value}%`; default: if (typeof value === 'number') { return formatNumber(value); - } else if (typeof value === 'boolean') { + } if (typeof value === 'boolean') { return formatBoolean(value); - } else { - return value; } + return value; } }; -export const formatBoolean = (value) => { - return value ? t('sharedYes') : t('sharedNo'); -}; +export const formatBoolean = (value) => (value ? t('sharedYes') : t('sharedNo')); -export const formatNumber = (value, precision = 1) => { - return Number(value.toFixed(precision)); -}; +export const formatNumber = (value, precision = 1) => Number(value.toFixed(precision)); -export const formatDate = (value, format = 'YYYY-MM-DD HH:mm') => { - return moment(value).format(format); -}; +export const formatDate = (value, format = 'YYYY-MM-DD HH:mm') => moment(value).format(format); export const formatDistance = (value, unit) => { switch (unit) { @@ -50,7 +43,7 @@ export const formatDistance = (value, unit) => { return `${(value * 0.000539957).toFixed(2)} ${t('sharedNmi')}`; case 'km': default: - return `${(value * 0.001).toFixed(2)} ${t('sharedKm')}`; + return `${(value * 0.001).toFixed(2)} ${t('sharedKm')}`; } }; @@ -62,8 +55,8 @@ export const formatSpeed = (value, unit) => { return `${(value * 1.15078).toFixed(2)} ${t('sharedMph')}`; case 'kn': default: - return `${(value * 1).toFixed(2)} ${t('sharedKn')}`; - } + return `${(value * 1).toFixed(2)} ${t('sharedKn')}`; + } }; export const formatVolume = (value, unit) => { @@ -74,16 +67,15 @@ export const formatVolume = (value, unit) => { return `${(value / 3.785).toFixed(2)} ${t('sharedGallonAbbreviation')}`; case 'ltr': default: - return `${(value / 1).toFixed(2)} ${t('sharedLiterAbbreviation')}`; - } -} - -export const formatHours = (value) => { - return moment.duration(value).humanize(); + return `${(value / 1).toFixed(2)} ${t('sharedLiterAbbreviation')}`; + } }; +export const formatHours = (value) => moment.duration(value).humanize(); + export const formatCoordinate = (key, value, unit) => { - var hemisphere, degrees, minutes, seconds; + let hemisphere; let degrees; let minutes; let + seconds; if (key === 'latitude') { hemisphere = value >= 0 ? 'N' : 'S'; } else { @@ -95,14 +87,14 @@ export const formatCoordinate = (key, value, unit) => { value = Math.abs(value); degrees = Math.floor(value); minutes = (value - degrees) * 60; - return degrees + '° ' + minutes.toFixed(6) + '\' ' + hemisphere; + return `${degrees}° ${minutes.toFixed(6)}' ${hemisphere}`; case 'dms': value = Math.abs(value); degrees = Math.floor(value); minutes = Math.floor((value - degrees) * 60); seconds = Math.round((value - degrees - minutes / 60) * 3600); - return degrees + '° ' + minutes + '\' ' + seconds + '" ' + hemisphere; + return `${degrees}° ${minutes}' ${seconds}" ${hemisphere}`; default: - return value.toFixed(6) + '°'; - } + return `${value.toFixed(6)}°`; + } }; diff --git a/modern/src/common/preferences.js b/modern/src/common/preferences.js index 24fe389..aba3c82 100644 --- a/modern/src/common/preferences.js +++ b/modern/src/common/preferences.js @@ -1,21 +1,15 @@ import { useSelector } from 'react-redux'; -export const usePreference = (key, defaultValue) => { - return useSelector(state => { - if (state.session.server.forceSettings) { - return state.session.server[key] || state.session.user[key] || defaultValue; - } else { - return state.session.user[key] || state.session.server[key] || defaultValue; - } - }); -}; +export const usePreference = (key, defaultValue) => useSelector((state) => { + if (state.session.server.forceSettings) { + return state.session.server[key] || state.session.user[key] || defaultValue; + } + return state.session.user[key] || state.session.server[key] || defaultValue; +}); -export const useAttributePreference = (key, defaultValue) => { - return useSelector(state => { - if (state.session.server.forceSettings) { - return state.session.server.attributes[key] || state.session.user.attributes[key] || defaultValue; - } else { - return state.session.user.attributes[key] || state.session.server.attributes[key] || defaultValue; - } - }); -}; +export const useAttributePreference = (key, defaultValue) => useSelector((state) => { + if (state.session.server.forceSettings) { + return state.session.server.attributes[key] || state.session.user.attributes[key] || defaultValue; + } + return state.session.user.attributes[key] || state.session.server.attributes[key] || defaultValue; +}); diff --git a/modern/src/common/stringUtils.js b/modern/src/common/stringUtils.js index 7bd68c8..fc997fe 100644 --- a/modern/src/common/stringUtils.js +++ b/modern/src/common/stringUtils.js @@ -1,7 +1,3 @@ -export const prefixString = (prefix, value) => { - return prefix + value.charAt(0).toUpperCase() + value.slice(1); -} +export const prefixString = (prefix, value) => prefix + value.charAt(0).toUpperCase() + value.slice(1); -export const unprefixString = (prefix, value) => { - return value.charAt(prefix.length).toLowerCase() + value.slice(prefix.length + 1); -} +export const unprefixString = (prefix, value) => value.charAt(prefix.length).toLowerCase() + value.slice(prefix.length + 1); diff --git a/modern/src/components/NavBar.js b/modern/src/components/NavBar.js index 68e38bf..93e79bb 100644 --- a/modern/src/components/NavBar.js +++ b/modern/src/components/NavBar.js @@ -1,5 +1,7 @@ import React from 'react'; -import { AppBar, Toolbar, Typography, IconButton } from '@material-ui/core'; +import { + AppBar, Toolbar, Typography, IconButton, +} from '@material-ui/core'; import MenuIcon from '@material-ui/icons/Menu'; const Navbar = ({ setOpenDrawer, title }) => ( diff --git a/modern/src/components/SideNav.js b/modern/src/components/SideNav.js index 8bd43ac..aa07808 100644 --- a/modern/src/components/SideNav.js +++ b/modern/src/components/SideNav.js @@ -1,5 +1,7 @@ import React from 'react'; -import { List, ListItem, ListItemText, ListItemIcon, Divider, ListSubheader } from '@material-ui/core'; +import { + List, ListItem, ListItemText, ListItemIcon, Divider, ListSubheader, +} from '@material-ui/core'; import { Link, useLocation } from 'react-router-dom'; const SideNav = ({ routes }) => { @@ -7,26 +9,24 @@ const SideNav = ({ routes }) => { return ( - {routes.map((route, index) => - route.subheader ? ( - <> - - {route.subheader} - - ) : ( - - {route.icon} - - - ) - )} + {routes.map((route, index) => (route.subheader ? ( + <> + + {route.subheader} + + ) : ( + + {route.icon} + + + )))} ); }; diff --git a/modern/src/components/registration/LoginForm.js b/modern/src/components/registration/LoginForm.js index 382b4fd..e083541 100644 --- a/modern/src/components/registration/LoginForm.js +++ b/modern/src/components/registration/LoginForm.js @@ -1,24 +1,25 @@ import React, { useState } from 'react'; -import { Grid, useMediaQuery, makeStyles, InputLabel, Select, MenuItem, FormControl, Button, TextField, Link } from '@material-ui/core'; +import { + Grid, useMediaQuery, makeStyles, InputLabel, Select, MenuItem, FormControl, Button, TextField, Link, +} from '@material-ui/core'; import { useTheme } from '@material-ui/core/styles'; import { useDispatch, useSelector } from 'react-redux'; import { useHistory } from 'react-router-dom'; import { sessionActions } from '../../store'; import t from '../../common/localization'; -import StartPage from './../../StartPage'; +import StartPage from '../../StartPage'; -const useStyles = makeStyles(theme => ({ +const useStyles = makeStyles((theme) => ({ logoContainer: { textAlign: 'center', color: theme.palette.primary.main, }, resetPassword: { cursor: 'pointer', - } + }, })); const LoginForm = () => { - const classes = useStyles(); const dispatch = useDispatch(); const history = useHistory(); @@ -27,16 +28,16 @@ const LoginForm = () => { const [failed, setFailed] = useState(false); const [email, setEmail] = useState(''); const [password, setPassword] = useState(''); - const registrationEnabled = useSelector(state => state.session.server ? state.session.server['registration'] : false); - const emailEnabled = useSelector(state => state.session.server ? state.session.server['emailEnabled'] : false); + const registrationEnabled = useSelector((state) => (state.session.server ? state.session.server.registration : false)); + const emailEnabled = useSelector((state) => (state.session.server ? state.session.server.emailEnabled : false)); const handleEmailChange = (event) => { setEmail(event.target.value); - } + }; const handlePasswordChange = (event) => { setPassword(event.target.value); - } + }; const handleLogin = async (event) => { event.preventDefault(); @@ -49,38 +50,40 @@ const LoginForm = () => { setFailed(true); setPassword(''); } - } + }; - const handleSpecialKey = e => { + const handleSpecialKey = (e) => { if (e.keyCode === 13 && email && password) { handleLogin(e); } - } + }; return ( - - {useMediaQuery(theme.breakpoints.down('md')) && + + {useMediaQuery(theme.breakpoints.down('md')) + && ( - + - } + )} + variant="filled" + /> { fullWidth error={failed} label={t('userPassword')} - name='password' + name="password" value={password} - type='password' - autoComplete='current-password' + type="password" + autoComplete="current-password" onChange={handlePasswordChange} onKeyUp={handleSpecialKey} - variant='filled' /> + variant="filled" + /> - @@ -122,14 +127,16 @@ const LoginForm = () => { - {emailEnabled && + {emailEnabled && ( + - history.push('/reset-password')} className={classes.resetPassword} underline="none">{t('loginReset')} + history.push('/reset-password')} className={classes.resetPassword} underline="none">{t('loginReset')} - } + + )} - ) -} + ); +}; export default LoginForm; diff --git a/modern/src/components/registration/RegisterForm.js b/modern/src/components/registration/RegisterForm.js index b2a8222..06f5355 100644 --- a/modern/src/components/registration/RegisterForm.js +++ b/modern/src/components/registration/RegisterForm.js @@ -1,27 +1,28 @@ import React, { useState } from 'react'; -import { Grid, Button, TextField, Typography, Link, makeStyles, Snackbar } from '@material-ui/core'; +import { + Grid, Button, TextField, Typography, Link, makeStyles, Snackbar, +} from '@material-ui/core'; import { useHistory } from 'react-router-dom'; import ArrowBackIcon from '@material-ui/icons/ArrowBack'; -import StartPage from './../../StartPage'; -import t from './../../common/localization'; +import StartPage from '../../StartPage'; +import t from '../../common/localization'; -const useStyles = makeStyles(theme => ({ +const useStyles = makeStyles((theme) => ({ register: { fontSize: theme.spacing(3), fontWeight: 500, marginLeft: theme.spacing(2), - textTransform: "uppercase" + textTransform: 'uppercase', }, link: { fontSize: theme.spacing(3), fontWeight: 500, marginTop: theme.spacing(0.5), - cursor: 'pointer' - } + cursor: 'pointer', + }, })); const RegisterForm = () => { - const classes = useStyles(); const history = useHistory(); @@ -30,21 +31,19 @@ const RegisterForm = () => { const [password, setPassword] = useState(''); const [snackbarOpen, setSnackbarOpen] = useState(false); - const submitDisabled = () => { - return !name || !/(.+)@(.+)\.(.{2,})/.test(email) || !password; - } + const submitDisabled = () => !name || !/(.+)@(.+)\.(.{2,})/.test(email) || !password; const handleRegister = async () => { const response = await fetch('/api/users', { method: 'POST', headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({name, email, password}) + body: JSON.stringify({ name, email, password }), }); if (response.ok) { setSnackbarOpen(true); - } - } + } + }; return ( @@ -53,18 +52,19 @@ const RegisterForm = () => { open={snackbarOpen} onClose={() => history.push('/login')} autoHideDuration={6000} - message={t('loginCreated')} /> - + message={t('loginCreated')} + /> + - + history.push('/login')}> - + {t('loginRegister')} @@ -74,50 +74,54 @@ const RegisterForm = () => { required fullWidth label={t('sharedName')} - name='name' + name="name" value={name || ''} - autoComplete='name' + autoComplete="name" autoFocus - onChange={event => setName(event.target.value)} - variant='filled' /> + onChange={(event) => setName(event.target.value)} + variant="filled" + /> setEmail(event.target.value)} - variant='filled' /> + autoComplete="email" + onChange={(event) => setEmail(event.target.value)} + variant="filled" + /> setPassword(event.target.value)} - variant='filled' /> + type="password" + autoComplete="current-password" + onChange={(event) => setPassword(event.target.value)} + variant="filled" + /> - ) -} + ); +}; export default RegisterForm; diff --git a/modern/src/components/registration/ResetPasswordForm.js b/modern/src/components/registration/ResetPasswordForm.js index c268f80..f4dd2e4 100644 --- a/modern/src/components/registration/ResetPasswordForm.js +++ b/modern/src/components/registration/ResetPasswordForm.js @@ -1,12 +1,9 @@ import React from 'react'; -const ResetPasswordForm = () => { - - return ( - <> -
Reset Password Comming Soon!!!
- - ) -} +const ResetPasswordForm = () => ( + <> +
Reset Password Comming Soon!!!
+ +); export default ResetPasswordForm; diff --git a/modern/src/form/LinkField.js b/modern/src/form/LinkField.js index b228fb3..26e1471 100644 --- a/modern/src/form/LinkField.js +++ b/modern/src/form/LinkField.js @@ -1,4 +1,6 @@ -import { FormControl, InputLabel, MenuItem, Select } from '@material-ui/core'; +import { + FormControl, InputLabel, MenuItem, Select, +} from '@material-ui/core'; import React, { useState } from 'react'; import { useEffectAsync } from '../reactHelper'; @@ -11,8 +13,8 @@ const LinkField = ({ baseId, keyBase, keyLink, - keyGetter = item => item.id, - titleGetter = item => item.name, + keyGetter = (item) => item.id, + titleGetter = (item) => item.name, }) => { const [items, setItems] = useState(); const [linked, setLinked] = useState(); @@ -28,28 +30,28 @@ const LinkField = ({ const response = await fetch(endpointLinked); if (response.ok) { const data = await response.json(); - setLinked(data.map(it => it.id)); + setLinked(data.map((it) => it.id)); } }, []); - const createBody = linkId => { + const createBody = (linkId) => { const body = {}; body[keyBase] = baseId; body[keyLink] = linkId; return body; - } + }; - const onChange = async event => { + const onChange = async (event) => { const oldValue = linked; const newValue = event.target.value; - for (const added of newValue.filter(it => !oldValue.includes(it))) { + for (const added of newValue.filter((it) => !oldValue.includes(it))) { await fetch('/api/permissions', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(createBody(added)), }); } - for (const removed of oldValue.filter(it => !newValue.includes(it))) { + for (const removed of oldValue.filter((it) => !newValue.includes(it))) { await fetch('/api/permissions', { method: 'DELETE', headers: { 'Content-Type': 'application/json' }, @@ -66,16 +68,16 @@ const LinkField = ({ ); - } else { - return null; } -} + return null; +}; export default LinkField; diff --git a/modern/src/form/SelectField.js b/modern/src/form/SelectField.js index b179c58..303d203 100644 --- a/modern/src/form/SelectField.js +++ b/modern/src/form/SelectField.js @@ -1,4 +1,6 @@ -import { FormControl, InputLabel, MenuItem, Select } from '@material-ui/core'; +import { + FormControl, InputLabel, MenuItem, Select, +} from '@material-ui/core'; import React, { useState } from 'react'; import { useEffectAsync } from '../reactHelper'; @@ -12,8 +14,8 @@ const SelectField = ({ onChange, endpoint, data, - keyGetter = item => item.id, - titleGetter = item => item.name, + keyGetter = (item) => item.id, + titleGetter = (item) => item.name, }) => { const [items, setItems] = useState(data); @@ -33,19 +35,18 @@ const SelectField = ({ ); - } else { - return null; } -} + return null; +}; export default SelectField; diff --git a/modern/src/index.js b/modern/src/index.js index 82ddef9..155bf62 100644 --- a/modern/src/index.js +++ b/modern/src/index.js @@ -1,7 +1,7 @@ -import 'typeface-roboto' +import 'typeface-roboto'; import React from 'react'; import ReactDOM from 'react-dom'; -import { HashRouter } from 'react-router-dom' +import { HashRouter } from 'react-router-dom'; import { Provider } from 'react-redux'; import App from './App'; diff --git a/modern/src/map/AccuracyMap.js b/modern/src/map/AccuracyMap.js index e81fc8f..4baa105 100644 --- a/modern/src/map/AccuracyMap.js +++ b/modern/src/map/AccuracyMap.js @@ -7,33 +7,31 @@ import { map } from './Map'; const AccuracyMap = () => { const id = 'accuracy'; - const positions = useSelector(state => ({ + const positions = useSelector((state) => ({ type: 'FeatureCollection', - features: Object.values(state.positions.items).filter(position => position.accuracy > 0).map(position => - circle([position.longitude, position.latitude], position.accuracy * 0.001) - ), + features: Object.values(state.positions.items).filter((position) => position.accuracy > 0).map((position) => circle([position.longitude, position.latitude], position.accuracy * 0.001)), })); useEffect(() => { map.addSource(id, { - 'type': 'geojson', - 'data': { + type: 'geojson', + data: { type: 'FeatureCollection', - features: [] - } + features: [], + }, }); map.addLayer({ - 'source': id, - 'id': id, - 'type': 'fill', - 'filter': [ - 'all', - ['==', '$type', 'Polygon'], + source: id, + id, + type: 'fill', + filter: [ + 'all', + ['==', '$type', 'Polygon'], ], - 'paint': { - 'fill-color':'#3bb2d0', - 'fill-outline-color':'#3bb2d0', - 'fill-opacity':0.25, + paint: { + 'fill-color': '#3bb2d0', + 'fill-outline-color': '#3bb2d0', + 'fill-opacity': 0.25, }, }); @@ -48,6 +46,6 @@ const AccuracyMap = () => { }, [positions]); return null; -} +}; export default AccuracyMap; diff --git a/modern/src/map/CurrentLocationMap.js b/modern/src/map/CurrentLocationMap.js index 06aaad0..69724ce 100644 --- a/modern/src/map/CurrentLocationMap.js +++ b/modern/src/map/CurrentLocationMap.js @@ -16,6 +16,6 @@ const CurrentLocationMap = () => { }, []); return null; -} +}; export default CurrentLocationMap; diff --git a/modern/src/map/CurrentPositionsMap.js b/modern/src/map/CurrentPositionsMap.js index 0bfe4fc..9e00774 100644 --- a/modern/src/map/CurrentPositionsMap.js +++ b/modern/src/map/CurrentPositionsMap.js @@ -1,11 +1,11 @@ -import React, { } from 'react'; +import React, { } from 'react'; import { useSelector } from 'react-redux'; import PositionsMap from './PositionsMap'; const CurrentPositionsMap = () => { - const positions = useSelector(state => Object.values(state.positions.items)); + const positions = useSelector((state) => Object.values(state.positions.items)); return (); -} +}; export default CurrentPositionsMap; diff --git a/modern/src/map/GeofenceEditMap.js b/modern/src/map/GeofenceEditMap.js index fe84338..f24fcb3 100644 --- a/modern/src/map/GeofenceEditMap.js +++ b/modern/src/map/GeofenceEditMap.js @@ -1,13 +1,13 @@ -import '@mapbox/mapbox-gl-draw/dist/mapbox-gl-draw.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 { useEffect } from 'react'; +import { useDispatch, useSelector } from 'react-redux'; +import { useHistory } from 'react-router-dom'; 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, @@ -17,15 +17,15 @@ const draw = new MapboxDraw({ }, userProperties: true, styles: [...theme, { - 'id': 'gl-draw-title', - 'type': 'symbol', - 'filter': ['all'], - 'layout': { + id: 'gl-draw-title', + type: 'symbol', + filter: ['all'], + layout: { 'text-field': '{user_name}', 'text-font': ['Roboto Regular'], 'text-size': 12, }, - 'paint': { + paint: { 'text-halo-color': 'white', 'text-halo-width': 1, }, @@ -36,25 +36,25 @@ const GeofenceEditMap = () => { const dispatch = useDispatch(); const history = useHistory(); - const geofences = useSelector(state => Object.values(state.geofences.items)); + 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'); - map.on('draw.create', async event => { + 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`, { + const response = await fetch('/api/geofences', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(newItem), @@ -65,7 +65,7 @@ const GeofenceEditMap = () => { } }); - map.on('draw.delete', async event => { + map.on('draw.delete', async (event) => { const feature = event.features[0]; const response = await fetch(`/api/geofences/${feature.id}`, { method: 'DELETE' }); if (response.ok) { @@ -73,9 +73,9 @@ const GeofenceEditMap = () => { } }); - map.on('draw.update', async event => { + map.on('draw.update', async (event) => { const feature = event.features[0]; - const item = geofences.find(i => i.id === feature.id); + 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}`, { @@ -100,6 +100,6 @@ const GeofenceEditMap = () => { }, [geofences]); return null; -} +}; export default GeofenceEditMap; diff --git a/modern/src/map/GeofenceMap.js b/modern/src/map/GeofenceMap.js index 8db175a..d00cbb1 100644 --- a/modern/src/map/GeofenceMap.js +++ b/modern/src/map/GeofenceMap.js @@ -7,49 +7,49 @@ import { geofenceToFeature } from './mapUtil'; const GeofenceMap = () => { const id = 'geofences'; - const geofences = useSelector(state => Object.values(state.geofences.items)); + const geofences = useSelector((state) => Object.values(state.geofences.items)); useEffect(() => { map.addSource(id, { - 'type': 'geojson', - 'data': { + type: 'geojson', + data: { type: 'FeatureCollection', - features: [] - } + features: [], + }, }); map.addLayer({ - 'source': id, - 'id': 'geofences-fill', - 'type': 'fill', - 'filter': [ - 'all', - ['==', '$type', 'Polygon'], + source: id, + id: 'geofences-fill', + type: 'fill', + filter: [ + 'all', + ['==', '$type', 'Polygon'], ], - 'paint': { - 'fill-color':'#3bb2d0', - 'fill-outline-color':'#3bb2d0', - 'fill-opacity':0.1, + paint: { + 'fill-color': '#3bb2d0', + 'fill-outline-color': '#3bb2d0', + 'fill-opacity': 0.1, }, }); map.addLayer({ - 'source': id, - 'id': 'geofences-line', - 'type': 'line', - 'paint': { - 'line-color': '#3bb2d0', - 'line-width': 2, + source: id, + id: 'geofences-line', + type: 'line', + paint: { + 'line-color': '#3bb2d0', + 'line-width': 2, }, }); map.addLayer({ - 'source': id, - 'id': 'geofences-title', - 'type': 'symbol', - 'layout': { + source: id, + id: 'geofences-title', + type: 'symbol', + layout: { 'text-field': '{name}', 'text-font': ['Roboto Regular'], 'text-size': 12, }, - 'paint': { + paint: { 'text-halo-color': 'white', 'text-halo-width': 1, }, @@ -66,11 +66,11 @@ const GeofenceMap = () => { useEffect(() => { map.getSource(id).setData({ type: 'FeatureCollection', - features: geofences.map(geofenceToFeature) + features: geofences.map(geofenceToFeature), }); }, [geofences]); return null; -} +}; export default GeofenceMap; diff --git a/modern/src/map/Map.js b/modern/src/map/Map.js index 46c59d2..672bd26 100644 --- a/modern/src/map/Map.js +++ b/modern/src/map/Map.js @@ -1,8 +1,10 @@ import 'maplibre-gl/dist/maplibre-gl.css'; import './switcher/switcher.css'; import maplibregl from 'maplibre-gl'; +import React, { + useRef, useLayoutEffect, useEffect, useState, +} from 'react'; import { SwitcherControl } from './switcher/switcher'; -import React, { useRef, useLayoutEffect, useEffect, useState } from 'react'; import { deviceCategories } from '../common/deviceCategories'; import { prepareIcon, loadImage } from './mapUtil'; import { styleCarto, styleMapbox, styleOsm } from './mapStyles'; @@ -22,18 +24,18 @@ export const map = new maplibregl.Map({ let ready = false; const readyListeners = new Set(); -const addReadyListener = listener => { +const addReadyListener = (listener) => { readyListeners.add(listener); listener(ready); }; -const removeReadyListener = listener => { +const removeReadyListener = (listener) => { readyListeners.delete(listener); }; -const updateReadyValue = value => { +const updateReadyValue = (value) => { ready = value; - readyListeners.forEach(listener => listener(value)); + readyListeners.forEach((listener) => listener(value)); }; const initMap = async () => { @@ -42,7 +44,7 @@ const initMap = async () => { map.addImage('background', await prepareIcon(background), { pixelRatio: window.devicePixelRatio, }); - await Promise.all(deviceCategories.map(async category => { + await Promise.all(deviceCategories.map(async (category) => { for (const color of ['green', 'red', 'gray']) { const icon = await loadImage(`images/icon/${category}.svg`); map.addImage(`${category}-${color}`, prepareIcon(background, icon, palette.common[color]), { @@ -93,7 +95,7 @@ const Map = ({ children }) => { }, [mapboxAccessToken]); useEffect(() => { - const listener = ready => setMapReady(ready); + const listener = (ready) => setMapReady(ready); addReadyListener(listener); return () => { removeReadyListener(listener); diff --git a/modern/src/map/PositionsMap.js b/modern/src/map/PositionsMap.js index 35d6d92..2de01d2 100644 --- a/modern/src/map/PositionsMap.js +++ b/modern/src/map/PositionsMap.js @@ -3,9 +3,9 @@ import ReactDOM from 'react-dom'; import maplibregl from 'maplibre-gl'; import { Provider, useSelector } from 'react-redux'; +import { useHistory } from 'react-router-dom'; import { map } from './Map'; import store from '../store'; -import { useHistory } from 'react-router-dom'; import StatusView from './StatusView'; const PositionsMap = ({ positions }) => { @@ -13,9 +13,9 @@ const PositionsMap = ({ positions }) => { const clusters = `${id}-clusters`; const history = useHistory(); - const devices = useSelector(state => state.devices.items); + const devices = useSelector((state) => state.devices.items); - const deviceColor = device => { + const deviceColor = (device) => { switch (device.status) { case 'online': return 'green'; @@ -33,15 +33,15 @@ const PositionsMap = ({ positions }) => { name: device.name, category: device.category || 'default', color: deviceColor(device), - } + }; }; const onMouseEnter = () => map.getCanvas().style.cursor = 'pointer'; const onMouseLeave = () => map.getCanvas().style.cursor = ''; - const onMarkerClick = useCallback(event => { + const onMarkerClick = useCallback((event) => { const feature = event.features[0]; - let coordinates = feature.geometry.coordinates.slice(); + const coordinates = feature.geometry.coordinates.slice(); while (Math.abs(event.lngLat.lng - coordinates[0]) > 180) { coordinates[0] += event.lngLat.lng > coordinates[0] ? 360 : -360; } @@ -49,50 +49,52 @@ const PositionsMap = ({ positions }) => { const placeholder = document.createElement('div'); ReactDOM.render( - history.push(`/position/${positionId}`)} /> + history.push(`/position/${positionId}`)} /> , - placeholder + placeholder, ); new maplibregl.Popup({ offset: 25, - anchor: 'top' + anchor: 'top', }) .setDOMContent(placeholder) .setLngLat(coordinates) .addTo(map); }, [history]); - const onClusterClick = event => { + const onClusterClick = (event) => { const features = map.queryRenderedFeatures(event.point, { layers: [clusters], }); const clusterId = features[0].properties.cluster_id; map.getSource(id).getClusterExpansionZoom(clusterId, (error, zoom) => { - if (!error) map.easeTo({ - center: features[0].geometry.coordinates, - zoom: zoom, - }); + if (!error) { + map.easeTo({ + center: features[0].geometry.coordinates, + zoom, + }); + } }); }; useEffect(() => { map.addSource(id, { - 'type': 'geojson', - 'data': { + type: 'geojson', + data: { type: 'FeatureCollection', features: [], }, - 'cluster': true, - 'clusterMaxZoom': 14, - 'clusterRadius': 50, + cluster: true, + clusterMaxZoom: 14, + clusterRadius: 50, }); map.addLayer({ - 'id': id, - 'type': 'symbol', - 'source': id, - 'filter': ['!', ['has', 'point_count']], - 'layout': { + id, + type: 'symbol', + source: id, + filter: ['!', ['has', 'point_count']], + layout: { 'icon-image': '{category}-{color}', 'icon-allow-overlap': true, 'text-field': '{name}', @@ -102,17 +104,17 @@ const PositionsMap = ({ positions }) => { 'text-font': ['Roboto Regular'], 'text-size': 12, }, - 'paint': { + paint: { 'text-halo-color': 'white', 'text-halo-width': 1, }, }); map.addLayer({ - 'id': clusters, - 'type': 'symbol', - 'source': id, - 'filter': ['has', 'point_count'], - 'layout': { + id: clusters, + type: 'symbol', + source: id, + filter: ['has', 'point_count'], + layout: { 'icon-image': 'background', 'text-field': '{point_count_abbreviated}', 'text-font': ['Roboto Regular'], @@ -120,7 +122,6 @@ const PositionsMap = ({ positions }) => { }, }); - map.on('mouseenter', id, onMouseEnter); map.on('mouseleave', id, onMouseLeave); map.on('mouseenter', clusters, onMouseEnter); @@ -129,7 +130,7 @@ const PositionsMap = ({ positions }) => { map.on('click', clusters, onClusterClick); return () => { - Array.from(map.getContainer().getElementsByClassName('maplibregl-popup')).forEach(el => el.remove()); + Array.from(map.getContainer().getElementsByClassName('maplibregl-popup')).forEach((el) => el.remove()); map.off('mouseenter', id, onMouseEnter); map.off('mouseleave', id, onMouseLeave); @@ -147,18 +148,18 @@ const PositionsMap = ({ positions }) => { useEffect(() => { map.getSource(id).setData({ type: 'FeatureCollection', - features: positions.filter(it => devices.hasOwnProperty(it.deviceId)).map(position => ({ + features: positions.filter((it) => devices.hasOwnProperty(it.deviceId)).map((position) => ({ type: 'Feature', geometry: { type: 'Point', coordinates: [position.longitude, position.latitude], }, properties: createFeature(devices, position), - })) + })), }); }, [devices, positions]); return null; -} +}; export default PositionsMap; diff --git a/modern/src/map/ReplayPathMap.js b/modern/src/map/ReplayPathMap.js index b40aa69..62b3f27 100644 --- a/modern/src/map/ReplayPathMap.js +++ b/modern/src/map/ReplayPathMap.js @@ -7,8 +7,8 @@ const ReplayPathMap = ({ positions }) => { useEffect(() => { map.addSource(id, { - 'type': 'geojson', - 'data': { + type: 'geojson', + data: { type: 'Feature', geometry: { type: 'LineString', @@ -17,16 +17,16 @@ const ReplayPathMap = ({ positions }) => { }, }); map.addLayer({ - 'source': id, - 'id': id, - 'type': 'line', - 'layout': { + source: id, + id, + type: 'line', + layout: { 'line-join': 'round', 'line-cap': 'round', }, - 'paint': { - 'line-color': '#333', - 'line-width': 5, + paint: { + 'line-color': '#333', + 'line-width': 5, }, }); @@ -37,23 +37,25 @@ const ReplayPathMap = ({ positions }) => { }, []); useEffect(() => { - const coordinates = positions.map(item => [item.longitude, item.latitude]); + const coordinates = positions.map((item) => [item.longitude, item.latitude]); map.getSource(id).setData({ type: 'Feature', geometry: { type: 'LineString', - coordinates: coordinates, + coordinates, }, }); if (coordinates.length) { const bounds = coordinates.reduce((bounds, item) => bounds.extend(item), new maplibregl.LngLatBounds(coordinates[0], coordinates[0])); map.fitBounds(bounds, { - padding: { top: 50, bottom: 250, left: 25, right: 25 }, + padding: { + top: 50, bottom: 250, left: 25, right: 25, + }, }); } }, [positions]); return null; -} +}; export default ReplayPathMap; diff --git a/modern/src/map/SelectedDeviceMap.js b/modern/src/map/SelectedDeviceMap.js index 655fca9..e6c5f58 100644 --- a/modern/src/map/SelectedDeviceMap.js +++ b/modern/src/map/SelectedDeviceMap.js @@ -4,7 +4,7 @@ import { useSelector } from 'react-redux'; import { map } from './Map'; const SelectedDeviceMap = () => { - const mapCenter = useSelector(state => { + const mapCenter = useSelector((state) => { if (state.devices.selectedId) { const position = state.positions.items[state.devices.selectedId] || null; if (position) { @@ -19,6 +19,6 @@ const SelectedDeviceMap = () => { }, [mapCenter]); return null; -} +}; export default SelectedDeviceMap; diff --git a/modern/src/map/StatusView.js b/modern/src/map/StatusView.js index ae049af..20e5b74 100644 --- a/modern/src/map/StatusView.js +++ b/modern/src/map/StatusView.js @@ -1,27 +1,68 @@ -import t from '../common/localization' import React from 'react'; import { useSelector } from 'react-redux'; +import t from '../common/localization'; import { formatPosition } from '../common/formatter'; const StatusView = ({ deviceId, onShowDetails }) => { - const device = useSelector(state => state.devices.items[deviceId]); - const position = useSelector(state => state.positions.items[deviceId]); + const device = useSelector((state) => state.devices.items[deviceId]); + const position = useSelector((state) => state.positions.items[deviceId]); - const handleClick = e => { + const handleClick = (e) => { e.preventDefault(); onShowDetails(position.id); }; return ( <> - {t('deviceStatus')}: {formatPosition(device.status, 'status')}
- {t('sharedLocation')}: {formatPosition(position, 'latitude')} {formatPosition(position, 'longitude')}
- {t('positionSpeed')}: {formatPosition(position.speed, 'speed')}
- {t('positionCourse')}: {formatPosition(position.course, 'course')}
- {t('positionDistance')}: {formatPosition(position.attributes.totalDistance, 'distance')}
- {position.attributes.batteryLevel && - <>{t('positionBattery')}: {formatPosition(position.attributes.batteryLevel, 'batteryLevel')}
- } + + {t('deviceStatus')} + : + + {' '} + {formatPosition(device.status, 'status')} +
+ + {t('sharedLocation')} + : + + {' '} + {formatPosition(position, 'latitude')} + {' '} + {formatPosition(position, 'longitude')} +
+ + {t('positionSpeed')} + : + + {' '} + {formatPosition(position.speed, 'speed')} +
+ + {t('positionCourse')} + : + + {' '} + {formatPosition(position.course, 'course')} +
+ + {t('positionDistance')} + : + + {' '} + {formatPosition(position.attributes.totalDistance, 'distance')} +
+ {position.attributes.batteryLevel + && ( + <> + + {t('positionBattery')} + : + + {' '} + {formatPosition(position.attributes.batteryLevel, 'batteryLevel')} +
+ + )} {t('sharedShowDetails')} ); diff --git a/modern/src/map/mapStyles.js b/modern/src/map/mapStyles.js index 00a8666..9650ead 100644 --- a/modern/src/map/mapStyles.js +++ b/modern/src/map/mapStyles.js @@ -4,7 +4,7 @@ export const styleCustom = (url, attribution) => ({ osm: { type: 'raster', tiles: [url], - attribution: attribution, + attribution, tileSize: 256, }, }, @@ -22,30 +22,30 @@ export const styleOsm = () => styleCustom( ); export const styleCarto = () => ({ - 'version': 8, - 'sources': { + version: 8, + sources: { 'raster-tiles': { - 'type': 'raster', - 'tiles': [ - 'https://a.basemaps.cartocdn.com/rastertiles/voyager/{z}/{x}/{y}@2x.png', - 'https://b.basemaps.cartocdn.com/rastertiles/voyager/{z}/{x}/{y}@2x.png', - 'https://c.basemaps.cartocdn.com/rastertiles/voyager/{z}/{x}/{y}@2x.png', - 'https://d.basemaps.cartocdn.com/rastertiles/voyager/{z}/{x}/{y}@2x.png' + type: 'raster', + tiles: [ + 'https://a.basemaps.cartocdn.com/rastertiles/voyager/{z}/{x}/{y}@2x.png', + 'https://b.basemaps.cartocdn.com/rastertiles/voyager/{z}/{x}/{y}@2x.png', + 'https://c.basemaps.cartocdn.com/rastertiles/voyager/{z}/{x}/{y}@2x.png', + 'https://d.basemaps.cartocdn.com/rastertiles/voyager/{z}/{x}/{y}@2x.png', ], - 'tileSize': 256, - 'attribution': '© OpenStreetMap contributors, © CARTO' - } + tileSize: 256, + attribution: '© OpenStreetMap contributors, © CARTO', + }, }, - 'glyphs': 'https://cdn.traccar.com/map/fonts/{fontstack}/{range}.pbf', - 'layers': [ + glyphs: 'https://cdn.traccar.com/map/fonts/{fontstack}/{range}.pbf', + layers: [ { - 'id': 'simple-tiles', - 'type': 'raster', - 'source': 'raster-tiles', - 'minzoom': 0, - 'maxzoom': 22, - } - ] + id: 'simple-tiles', + type: 'raster', + source: 'raster-tiles', + minzoom: 0, + maxzoom: 22, + }, + ], }); export const styleMapbox = (style) => `mapbox://styles/mapbox/${style}`; diff --git a/modern/src/map/mapUtil.js b/modern/src/map/mapUtil.js index 67ce345..e3c32f4 100644 --- a/modern/src/map/mapUtil.js +++ b/modern/src/map/mapUtil.js @@ -2,13 +2,11 @@ import { parse, stringify } from 'wellknown'; import canvasTintImage from 'canvas-tint-image'; import circle from '@turf/circle'; -export const loadImage = (url) => { - return new Promise(imageLoaded => { - const image = new Image(); - image.onload = () => imageLoaded(image); - image.src = url; - }); -}; +export const loadImage = (url) => new Promise((imageLoaded) => { + const image = new Image(); + image.onload = () => imageLoaded(image); + image.src = url; +}); export const prepareIcon = (background, icon, color) => { const pixelRatio = window.devicePixelRatio; @@ -32,44 +30,39 @@ export const prepareIcon = (background, icon, color) => { return context.getImageData(0, 0, canvas.width, canvas.height); }; -export const reverseCoordinates = it => { +export const reverseCoordinates = (it) => { if (!it) { return it; - } else if (Array.isArray(it)) { + } if (Array.isArray(it)) { if (it.length === 2 && !Number.isNaN(it[0]) && !Number.isNaN(it[1])) { return [it[1], it[0]]; - } else { - return it.map(it => reverseCoordinates(it)); - } - } else { - return { - ...it, - coordinates: reverseCoordinates(it.coordinates), } + return it.map((it) => reverseCoordinates(it)); } -} + return { + ...it, + coordinates: reverseCoordinates(it.coordinates), + }; +}; export const geofenceToFeature = (item) => { if (item.area.indexOf('CIRCLE') > -1) { - 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); + const coordinates = item.area.replace(/CIRCLE|\(|\)|,/g, ' ').trim().split(/ +/); + const options = { steps: 32, units: 'meters' }; + const polygon = circle([Number(coordinates[1]), Number(coordinates[0])], Number(coordinates[2]), options); return { id: item.id, type: 'Feature', geometry: polygon.geometry, - properties: { name: item.name } - }; - } else { - return { - id: item.id, - type: 'Feature', - geometry: reverseCoordinates(parse(item.area)), - properties: { name: item.name } + properties: { name: item.name }, }; } -} + return { + id: item.id, + type: 'Feature', + geometry: reverseCoordinates(parse(item.area)), + properties: { name: item.name }, + }; +}; -export const geometryToArea = (geometry) => { - return stringify(reverseCoordinates(geometry)); -} +export const geometryToArea = (geometry) => stringify(reverseCoordinates(geometry)); diff --git a/modern/src/reactHelper.js b/modern/src/reactHelper.js index b0eb016..d8e9200 100644 --- a/modern/src/reactHelper.js +++ b/modern/src/reactHelper.js @@ -1,7 +1,6 @@ - import { useRef, useEffect } from 'react'; -export const usePrevious = value => { +export const usePrevious = (value) => { const ref = useRef(); useEffect(() => { ref.current = value; diff --git a/modern/src/reports/ChartReportPage.js b/modern/src/reports/ChartReportPage.js index 8eeedc4..c55ed6d 100644 --- a/modern/src/reports/ChartReportPage.js +++ b/modern/src/reports/ChartReportPage.js @@ -1,5 +1,7 @@ import React, { useState } from 'react'; -import { Grid, FormControl, InputLabel, Select, MenuItem } from '@material-ui/core'; +import { + Grid, FormControl, InputLabel, Select, MenuItem, +} from '@material-ui/core'; import ReportLayout from './ReportLayout'; import ReportFilter from './ReportFilter'; import Graph from './Graph'; @@ -9,66 +11,61 @@ import { speedFromKnots } from '../common/converter'; import t from '../common/localization'; const Filter = ({ children, setItems }) => { - const speedUnit = useAttributePreference('speedUnit'); const handleSubmit = async (deviceId, from, to, mail, headers) => { - const query = new URLSearchParams({ deviceId, from, to, mail }); + const query = new URLSearchParams({ + deviceId, from, to, mail, + }); const response = await fetch(`/api/reports/route?${query.toString()}`, { headers }); if (response.ok) { const positions = await response.json(); - let formattedPositions = positions.map(position => { - return { - speed: Number(speedFromKnots(position.speed, speedUnit)), - altitude: position.altitude, - accuracy: position.accuracy, - fixTime: formatDate(position.fixTime) - } - }); + const formattedPositions = positions.map((position) => ({ + speed: Number(speedFromKnots(position.speed, speedUnit)), + altitude: position.altitude, + accuracy: position.accuracy, + fixTime: formatDate(position.fixTime), + })); setItems(formattedPositions); } - } + }; return ( <> {children} - ) -} - -const ChartType = ({ type, setType }) => { + ); +}; - return ( - - - - {t('reportChartType')} - - - +const ChartType = ({ type, setType }) => ( + + + + {t('reportChartType')} + + - ) -} - + +); const ChartReportPage = () => { - const [items, setItems] = useState([]); const [type, setType] = useState('speed'); return ( - - }> + )} + > - ) -} + ); +}; export default ChartReportPage; diff --git a/modern/src/reports/EventReportPage.js b/modern/src/reports/EventReportPage.js index b938dc8..b5c3dae 100644 --- a/modern/src/reports/EventReportPage.js +++ b/modern/src/reports/EventReportPage.js @@ -1,7 +1,9 @@ import React, { useState } from 'react'; import { DataGrid } from '@material-ui/data-grid'; -import { Grid, FormControl, InputLabel, Select, MenuItem } from '@material-ui/core'; -import { useTheme } from "@material-ui/core/styles"; +import { + Grid, FormControl, InputLabel, Select, MenuItem, +} from '@material-ui/core'; +import { useTheme } from '@material-ui/core/styles'; import { useSelector } from 'react-redux'; import { formatDate } from '../common/formatter'; import ReportFilter from './ReportFilter'; @@ -10,12 +12,13 @@ import { prefixString } from '../common/stringUtils'; import t from '../common/localization'; const Filter = ({ setItems }) => { - const [eventTypes, setEventTypes] = useState(['allEvents']); const handleSubmit = async (deviceId, from, to, mail, headers) => { - const query = new URLSearchParams({ deviceId, from, to, mail }); - eventTypes.forEach(it => query.append('type', it)); + const query = new URLSearchParams({ + deviceId, from, to, mail, + }); + eventTypes.forEach((it) => query.append('type', it)); const response = await fetch(`/api/reports/events?${query.toString()}`, { headers }); if (response.ok) { const contentType = response.headers.get('content-type'); @@ -34,7 +37,7 @@ const Filter = ({ setItems }) => { {t('reportEventTypes')} - setEventTypes(e.target.value)} multiple> {t('eventAll')} {t('eventDeviceOnline')} {t('eventDeviceUnknown')} @@ -58,21 +61,20 @@ const Filter = ({ setItems }) => { ); -} +}; const EventReportPage = () => { - const theme = useTheme(); - const geofences = useSelector(state => state.geofences.items); + const geofences = useSelector((state) => state.geofences.items); const [items, setItems] = useState([]); - const formatGeofence = value => { + const formatGeofence = (value) => { if (value > 0) { - const geofence = geofences[value]; - return geofence ? geofence.name : ''; + const geofence = geofences[value]; + return geofence ? geofence.name : ''; } return null; - } + }; const columns = [{ headerName: t('positionFixTime'), @@ -101,12 +103,13 @@ const EventReportPage = () => { return ( }> + rows={items} + columns={columns} + hideFooter + autoHeight + /> ); -} +}; export default EventReportPage; diff --git a/modern/src/reports/Graph.js b/modern/src/reports/Graph.js index 990eb5d..63d24ee 100644 --- a/modern/src/reports/Graph.js +++ b/modern/src/reports/Graph.js @@ -1,9 +1,11 @@ import React from 'react'; import { withWidth } from '@material-ui/core'; -import {LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, Legend, ResponsiveContainer } from 'recharts'; +import { + LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, Legend, ResponsiveContainer, +} from 'recharts'; -const CustomizedAxisTick = ({ x, y, payload }) =>{ - if(!payload.value) { +const CustomizedAxisTick = ({ x, y, payload }) => { + if (!payload.value) { return payload.value; } const parts = payload.value.split(' '); @@ -13,22 +15,19 @@ const CustomizedAxisTick = ({ x, y, payload }) =>{ {parts[1]} ); -} +}; -const Graph = ({ type, items }) => { - - return ( - - - } height={60} /> - - - - - - - - ); -} +const Graph = ({ type, items }) => ( + + + } height={60} /> + + + + + + + +); export default withWidth()(Graph); diff --git a/modern/src/reports/ReplayPage.js b/modern/src/reports/ReplayPage.js index dfa9999..12bbd35 100644 --- a/modern/src/reports/ReplayPage.js +++ b/modern/src/reports/ReplayPage.js @@ -1,5 +1,7 @@ import React, { useState } from 'react'; -import { Accordion, AccordionDetails, AccordionSummary, Container, makeStyles, Paper, Slider, Tooltip, Typography } from '@material-ui/core'; +import { + Accordion, AccordionDetails, AccordionSummary, Container, makeStyles, Paper, Slider, Tooltip, Typography, +} from '@material-ui/core'; import ExpandMoreIcon from '@material-ui/icons/ExpandMore'; import MainToolbar from '../MainToolbar'; import Map from '../map/Map'; @@ -9,7 +11,7 @@ import PositionsMap from '../map/PositionsMap'; import { formatPosition } from '../common/formatter'; import ReportFilter from './ReportFilter'; -const useStyles = makeStyles(theme => ({ +const useStyles = makeStyles((theme) => ({ root: { height: '100%', display: 'flex', @@ -31,13 +33,11 @@ const useStyles = makeStyles(theme => ({ }, })); -const TimeLabel = ({ children, open, value }) => { - return ( - - {children} - - ); -}; +const TimeLabel = ({ children, open, value }) => ( + + {children} + +); const ReplayPage = () => { const classes = useStyles(); @@ -61,12 +61,12 @@ const ReplayPage = () => { - {index < positions.length && - - } + {index < positions.length + && } - {!!positions.length && + {!!positions.length + && ( { value={index} onChange={(_, index) => setIndex(index)} valueLabelDisplay="auto" - valueLabelFormat={i => i < positions.length ? formatPosition(positions[i], 'fixTime') : ''} + valueLabelFormat={(i) => (i < positions.length ? formatPosition(positions[i], 'fixTime') : '')} ValueLabelComponent={TimeLabel} - /> + /> - } + )}
setExpanded(!expanded)}> }> - + {t('reportConfigure')} @@ -95,6 +95,6 @@ const ReplayPage = () => {
); -} +}; export default ReplayPage; diff --git a/modern/src/reports/ReportFilter.js b/modern/src/reports/ReportFilter.js index 524f7bb..dec8d01 100644 --- a/modern/src/reports/ReportFilter.js +++ b/modern/src/reports/ReportFilter.js @@ -1,11 +1,13 @@ import React, { useState } from 'react'; -import { FormControl, InputLabel, Select, MenuItem, Button, TextField, Grid, Typography } from '@material-ui/core'; +import { + FormControl, InputLabel, Select, MenuItem, Button, TextField, Grid, Typography, +} from '@material-ui/core'; import { useSelector } from 'react-redux'; import moment from 'moment'; import t from '../common/localization'; const ReportFilter = ({ children, handleSubmit, showOnly }) => { - const devices = useSelector(state => Object.values(state.devices.items)); + const devices = useSelector((state) => Object.values(state.devices.items)); const [deviceId, setDeviceId] = useState(); const [period, setPeriod] = useState('today'); const [from, setFrom] = useState(moment().subtract(1, 'hour')); @@ -51,9 +53,9 @@ const ReportFilter = ({ children, handleSubmit, showOnly }) => { selectedFrom.toISOString(), selectedTo.toISOString(), mail, - { Accept: accept } + { Accept: accept }, ); - } + }; return ( @@ -81,56 +83,69 @@ const ReportFilter = ({ children, handleSubmit, showOnly }) => { - {period === 'custom' && + {period === 'custom' && ( + setFrom(moment(e.target.value, moment.HTML5_FMT.DATETIME_LOCAL))} - fullWidth /> - } - {period === 'custom' && + onChange={(e) => setFrom(moment(e.target.value, moment.HTML5_FMT.DATETIME_LOCAL))} + fullWidth + /> + + )} + {period === 'custom' && ( + setTo(moment(e.target.value, moment.HTML5_FMT.DATETIME_LOCAL))} - fullWidth /> - } + onChange={(e) => setTo(moment(e.target.value, moment.HTML5_FMT.DATETIME_LOCAL))} + fullWidth + /> + + )} {children} - - {!showOnly && + {!showOnly + && ( - - } - {!showOnly && + + + )} + {!showOnly + && ( - - } + + + )} ); -} +}; export default ReportFilter; diff --git a/modern/src/reports/ReportLayout.js b/modern/src/reports/ReportLayout.js index 5b54335..92ffc0c 100644 --- a/modern/src/reports/ReportLayout.js +++ b/modern/src/reports/ReportLayout.js @@ -7,7 +7,7 @@ import { Drawer, makeStyles, IconButton, - Hidden + Hidden, } from '@material-ui/core'; import TimelineIcon from '@material-ui/icons/Timeline'; import PauseCircleFilledIcon from '@material-ui/icons/PauseCircleFilled'; @@ -21,35 +21,35 @@ import SideNav from '../components/SideNav'; import NavBar from '../components/NavBar'; import t from '../common/localization'; -const useStyles = makeStyles(theme => ({ +const useStyles = makeStyles((theme) => ({ root: { display: 'flex', - height: '100%' + height: '100%', }, drawerContainer: { - width: theme.dimensions.drawerWidthDesktop + width: theme.dimensions.drawerWidthDesktop, }, drawer: { width: theme.dimensions.drawerWidthDesktop, [theme.breakpoints.down('md')]: { - width: theme.dimensions.drawerWidthTablet - } + width: theme.dimensions.drawerWidthTablet, + }, }, content: { flex: 1, - padding: theme.spacing(5, 3, 3, 3) + padding: theme.spacing(5, 3, 3, 3), }, drawerHeader: { ...theme.mixins.toolbar, display: 'flex', alignItems: 'center', - padding: theme.spacing(0, 1) + padding: theme.spacing(0, 1), }, toolbar: { [theme.breakpoints.down('md')]: { - ...theme.mixins.toolbar - } - } + ...theme.mixins.toolbar, + }, + }, })); const routes = [ @@ -57,24 +57,24 @@ const routes = [ { name: t('reportEvents'), href: '/reports/event', - icon: + icon: , }, { name: t('reportTrips'), href: '/reports/trip', - icon: + icon: , }, { name: t('reportStops'), href: '/reports/stop', - icon: + icon: , }, { name: t('reportSummary'), href: '/reports/summary', - icon: + icon: , }, - { name: t('reportChart'), href: '/reports/chart', icon: } + { name: t('reportChart'), href: '/reports/chart', icon: }, ]; const ReportLayout = ({ children, filter }) => { @@ -85,7 +85,7 @@ const ReportLayout = ({ children, filter }) => { const [reportTitle, setReportTitle] = useState(); useEffect(() => { - routes.forEach(route => { + routes.forEach((route) => { switch (location.pathname) { case `${route.href}`: setReportTitle(route.name); diff --git a/modern/src/reports/RouteReportPage.js b/modern/src/reports/RouteReportPage.js index c09d4f5..fffcdcb 100644 --- a/modern/src/reports/RouteReportPage.js +++ b/modern/src/reports/RouteReportPage.js @@ -1,17 +1,20 @@ import React, { useState } from 'react'; import { Paper } from '@material-ui/core'; import { DataGrid } from '@material-ui/data-grid'; -import { useTheme } from "@material-ui/core/styles"; -import { formatDistance, formatSpeed, formatBoolean, formatDate, formatCoordinate } from '../common/formatter'; +import { useTheme } from '@material-ui/core/styles'; +import { + formatDistance, formatSpeed, formatBoolean, formatDate, formatCoordinate, +} from '../common/formatter'; import ReportFilter from './ReportFilter'; import ReportLayout from './ReportLayout'; import { useAttributePreference, usePreference } from '../common/preferences'; import t from '../common/localization'; const Filter = ({ setItems }) => { - const handleSubmit = async (deviceId, from, to, mail, headers) => { - const query = new URLSearchParams({ deviceId, from, to, mail }); + const query = new URLSearchParams({ + deviceId, from, to, mail, + }); const response = await fetch(`/api/reports/route?${query.toString()}`, { headers }); if (response.ok) { const contentType = response.headers.get('content-type'); @@ -23,7 +26,7 @@ const Filter = ({ setItems }) => { } } } - } + }; return ; }; @@ -78,7 +81,7 @@ const RouteReportPage = () => { width: theme.dimensions.columnWidthNumber, valueGetter: ({ row }) => row.attributes.totalDistance, valueFormatter: ({ value }) => formatDistance(value, distanceUnit), - }] + }]; const [items, setItems] = useState([]); @@ -86,10 +89,11 @@ const RouteReportPage = () => { }> + rows={items} + columns={columns} + hideFooter + autoHeight + /> ); diff --git a/modern/src/reports/StopReportPage.js b/modern/src/reports/StopReportPage.js index 57f5956..d2e7e7e 100644 --- a/modern/src/reports/StopReportPage.js +++ b/modern/src/reports/StopReportPage.js @@ -1,16 +1,19 @@ import React, { useState } from 'react'; import { DataGrid } from '@material-ui/data-grid'; -import { useTheme } from "@material-ui/core/styles"; -import { formatDistance, formatHours, formatDate, formatVolume } from '../common/formatter'; +import { useTheme } from '@material-ui/core/styles'; +import { + formatDistance, formatHours, formatDate, formatVolume, +} from '../common/formatter'; import ReportFilter from './ReportFilter'; import ReportLayout from './ReportLayout'; import { useAttributePreference } from '../common/preferences'; import t from '../common/localization'; const Filter = ({ setItems }) => { - const handleSubmit = async (deviceId, from, to, mail, headers) => { - const query = new URLSearchParams({ deviceId, from, to, mail }); + const query = new URLSearchParams({ + deviceId, from, to, mail, + }); const response = await fetch(`/api/reports/stops?${query.toString()}`, { headers }); if (response.ok) { const contentType = response.headers.get('content-type'); @@ -22,13 +25,12 @@ const Filter = ({ setItems }) => { } } } - } + }; return ; }; const StopReportPage = () => { - const theme = useTheme(); const distanceUnit = useAttributePreference('distanceUnit'); @@ -41,7 +43,7 @@ const StopReportPage = () => { field: 'startTime', type: 'dateTime', width: theme.dimensions.columnWidthDate, - valueFormatter: ({ value }) => formatDate(value), + valueFormatter: ({ value }) => formatDate(value), }, { headerName: t('positionOdometer'), field: 'startOdometer', @@ -53,7 +55,7 @@ const StopReportPage = () => { field: 'address', type: 'string', hide: true, - width: theme.dimensions.columnWidthString, + width: theme.dimensions.columnWidthString, }, { headerName: t('reportEndTime'), field: 'endTime', @@ -78,17 +80,18 @@ const StopReportPage = () => { type: 'number', width: theme.dimensions.columnWidthNumber, hide: true, - valueFormatter: ({ value }) => formatVolume(value, volumeUnit), - }] - + valueFormatter: ({ value }) => formatVolume(value, volumeUnit), + }]; + return ( }> Math.random()} /> + getRowId={() => Math.random()} + /> ); }; diff --git a/modern/src/reports/SummaryReportPage.js b/modern/src/reports/SummaryReportPage.js index 53e697d..4523e65 100644 --- a/modern/src/reports/SummaryReportPage.js +++ b/modern/src/reports/SummaryReportPage.js @@ -1,19 +1,22 @@ import React, { useState } from 'react'; import { DataGrid } from '@material-ui/data-grid'; import { Grid, FormControlLabel, Checkbox } from '@material-ui/core'; -import { useTheme } from "@material-ui/core/styles"; -import { formatDistance, formatHours, formatDate, formatSpeed, formatVolume } from '../common/formatter'; +import { useTheme } from '@material-ui/core/styles'; +import { + formatDistance, formatHours, formatDate, formatSpeed, formatVolume, +} from '../common/formatter'; import ReportFilter from './ReportFilter'; import ReportLayout from './ReportLayout'; import { useAttributePreference } from '../common/preferences'; import t from '../common/localization'; const Filter = ({ setItems }) => { - const [daily, setDaily] = useState(false); const handleSubmit = async (deviceId, from, to, mail, headers) => { - const query = new URLSearchParams({ deviceId, from, to, daily, mail }); + const query = new URLSearchParams({ + deviceId, from, to, daily, mail, + }); const response = await fetch(`/api/reports/summary?${query.toString()}`, { headers }); if (response.ok) { const contentType = response.headers.get('content-type'); @@ -25,21 +28,21 @@ const Filter = ({ setItems }) => { } } } - } + }; return ( setDaily(e.target.checked)} />} - label={t('reportDaily')} /> + control={ setDaily(e.target.checked)} />} + label={t('reportDaily')} + /> ); -} +}; const SummaryReportPage = () => { - const theme = useTheme(); const distanceUnit = useAttributePreference('distanceUnit'); @@ -96,19 +99,20 @@ const SummaryReportPage = () => { type: 'number', width: theme.dimensions.columnWidthNumber, hide: true, - valueFormatter: ({ value }) => formatVolume(value, volumeUnit), - }] - + valueFormatter: ({ value }) => formatVolume(value, volumeUnit), + }]; + return ( }> Math.random()} /> + getRowId={() => Math.random()} + /> ); -} +}; export default SummaryReportPage; diff --git a/modern/src/reports/TripReportPage.js b/modern/src/reports/TripReportPage.js index e8c9129..f611dde 100644 --- a/modern/src/reports/TripReportPage.js +++ b/modern/src/reports/TripReportPage.js @@ -1,16 +1,19 @@ import React, { useState } from 'react'; import { DataGrid } from '@material-ui/data-grid'; -import { useTheme } from "@material-ui/core/styles"; -import { formatDistance, formatSpeed, formatHours, formatDate, formatVolume } from '../common/formatter'; +import { useTheme } from '@material-ui/core/styles'; +import { + formatDistance, formatSpeed, formatHours, formatDate, formatVolume, +} from '../common/formatter'; import ReportFilter from './ReportFilter'; import ReportLayout from './ReportLayout'; import { useAttributePreference } from '../common/preferences'; import t from '../common/localization'; const Filter = ({ setItems }) => { - const handleSubmit = async (deviceId, from, to, mail, headers) => { - const query = new URLSearchParams({ deviceId, from, to, mail }); + const query = new URLSearchParams({ + deviceId, from, to, mail, + }); const response = await fetch(`/api/reports/trips?${query.toString()}`, { headers }); if (response.ok) { const contentType = response.headers.get('content-type'); @@ -22,15 +25,14 @@ const Filter = ({ setItems }) => { } } } - } + }; return ; -} +}; const TripReportPage = () => { - const theme = useTheme(); - + const distanceUnit = useAttributePreference('distanceUnit'); const speedUnit = useAttributePreference('speedUnit'); const volumeUnit = useAttributePreference('volumeUnit'); @@ -109,19 +111,20 @@ const TripReportPage = () => { field: 'driverName', type: 'string', width: theme.dimensions.columnWidthString, - hide: true - }] + hide: true, + }]; return ( }> Math.random()} /> + getRowId={() => Math.random()} + /> ); -} +}; export default TripReportPage; diff --git a/modern/src/settings/ComputedAttributePage.js b/modern/src/settings/ComputedAttributePage.js index 73759fa..fea613a 100644 --- a/modern/src/settings/ComputedAttributePage.js +++ b/modern/src/settings/ComputedAttributePage.js @@ -1,19 +1,19 @@ import React, { useState } from 'react'; -import { Accordion, AccordionSummary, AccordionDetails, makeStyles, Typography, FormControl, InputLabel, MenuItem, Select, TextField } from "@material-ui/core"; +import { + Accordion, AccordionSummary, AccordionDetails, makeStyles, Typography, FormControl, InputLabel, MenuItem, Select, TextField, +} from '@material-ui/core'; +import ExpandMoreIcon from '@material-ui/icons/ExpandMore'; import t from '../common/localization'; import EditItemView from '../EditItemView'; -import ExpandMoreIcon from '@material-ui/icons/ExpandMore'; import positionAttributes from '../attributes/positionAttributes'; - const useStyles = makeStyles(() => ({ details: { flexDirection: 'column', }, })); -const ComputedAttributePage =() => { - +const ComputedAttributePage = () => { const classes = useStyles(); const [item, setItem] = useState(); const [key, setKey] = useState(); @@ -24,20 +24,21 @@ const ComputedAttributePage =() => { type: value.type, })); - const handleChange = event => { + const handleChange = (event) => { const newValue = event.target.value; setKey(newValue); const positionAttribute = positionAttributes[newValue]; - if(positionAttribute && positionAttribute.type) { - setItem({...item, attribute: newValue, type: positionAttribute.type}); + if (positionAttribute && positionAttribute.type) { + setItem({ ...item, attribute: newValue, type: positionAttribute.type }); } else { - setItem({...item, attribute: newValue}); + setItem({ ...item, attribute: newValue }); } - } + }; return ( - {item && + {item + && ( }> @@ -48,46 +49,51 @@ const ComputedAttributePage =() => { setItem({...item, description: event.target.value})} + onChange={(event) => setItem({ ...item, description: event.target.value })} label={t('sharedDescription')} - variant="filled" /> + variant="filled" + /> {t('sharedAttribute')} - {options.map((option) => ( {option.name} ))} - + setItem({...item, expression: event.target.value})} + onChange={(event) => setItem({ ...item, expression: event.target.value })} label={t('sharedExpression')} multiline rows={4} - variant="filled" /> + variant="filled" + /> + disabled={key in positionAttributes} + > {t('sharedType')} - } + )} - ) -} + ); +}; export default ComputedAttributePage; diff --git a/modern/src/settings/ComputedAttributesPage.js b/modern/src/settings/ComputedAttributesPage.js index d747598..fcf49d3 100644 --- a/modern/src/settings/ComputedAttributesPage.js +++ b/modern/src/settings/ComputedAttributesPage.js @@ -1,5 +1,7 @@ import React, { useState } from 'react'; -import { TableContainer, Table, TableRow, TableCell, TableHead, TableBody, makeStyles, IconButton } from '@material-ui/core'; +import { + TableContainer, Table, TableRow, TableCell, TableHead, TableBody, makeStyles, IconButton, +} from '@material-ui/core'; import MoreVertIcon from '@material-ui/icons/MoreVert'; import { useSelector } from 'react-redux'; import t from '../common/localization'; @@ -7,11 +9,11 @@ import { useEffectAsync } from '../reactHelper'; import EditCollectionView from '../EditCollectionView'; import OptionsLayout from './OptionsLayout'; -const useStyles = makeStyles(theme => ({ +const useStyles = makeStyles((theme) => ({ columnAction: { width: theme.spacing(1), - padding: theme.spacing(0, 1) - } + padding: theme.spacing(0, 1), + }, })); const ComputedAttributeView = ({ updateTimestamp, onMenuClick }) => { @@ -19,7 +21,7 @@ const ComputedAttributeView = ({ updateTimestamp, onMenuClick }) => { const [items, setItems] = useState([]); const adminEnabled = useSelector( - state => state.session.user && state.session.user.administrator + (state) => state.session.user && state.session.user.administrator, ); useEffectAsync(async () => { @@ -31,50 +33,48 @@ const ComputedAttributeView = ({ updateTimestamp, onMenuClick }) => { return ( - - - - {adminEnabled && } - {t('sharedDescription')} - {t('sharedAttribute')} - {t('sharedExpression')} - {t('sharedType')} - - - - {items.map(item => ( - +
+ + + {adminEnabled && } + {t('sharedDescription')} + {t('sharedAttribute')} + {t('sharedExpression')} + {t('sharedType')} + + + + {items.map((item) => ( + {adminEnabled && ( - onMenuClick(event.currentTarget, item.id)} - > + onMenuClick(event.currentTarget, item.id)} + > )} - {item.description} - {item.attribute} - {item.expression} - {item.type} - - ))} - -
+ {item.description} + {item.attribute} + {item.expression} + {item.type} + + ))} + +
); }; -const ComputedAttributesPage = () => { - return ( - - - - ); -}; +const ComputedAttributesPage = () => ( + + + +); export default ComputedAttributesPage; diff --git a/modern/src/settings/DriverPage.js b/modern/src/settings/DriverPage.js index 86feab8..01400c5 100644 --- a/modern/src/settings/DriverPage.js +++ b/modern/src/settings/DriverPage.js @@ -1,9 +1,11 @@ import React, { useState } from 'react'; import TextField from '@material-ui/core/TextField'; +import { + Accordion, AccordionSummary, AccordionDetails, makeStyles, Typography, +} from '@material-ui/core'; +import ExpandMoreIcon from '@material-ui/icons/ExpandMore'; 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'; const useStyles = makeStyles(() => ({ @@ -19,7 +21,8 @@ const DriverPage = () => { return ( - {item && + {item + && ( <> }> @@ -31,15 +34,17 @@ const DriverPage = () => { setItem({...item, name: event.target.value})} + onChange={(event) => setItem({ ...item, name: event.target.value })} label={t('sharedName')} - variant="filled" /> + variant="filled" + /> setItem({...item, uniqueId: event.target.value})} + onChange={(event) => setItem({ ...item, uniqueId: event.target.value })} label={t('deviceIdentifier')} - variant="filled" /> + variant="filled" + /> @@ -51,15 +56,15 @@ const DriverPage = () => { setItem({...item, attributes})} + setAttributes={(attributes) => setItem({ ...item, attributes })} definitions={{}} - /> + /> - } + )} ); -} +}; export default DriverPage; diff --git a/modern/src/settings/DriversPage.js b/modern/src/settings/DriversPage.js index d5427b2..57f69b6 100644 --- a/modern/src/settings/DriversPage.js +++ b/modern/src/settings/DriversPage.js @@ -1,16 +1,18 @@ import React, { useState } from 'react'; -import { TableContainer, Table, TableRow, TableCell, TableHead, TableBody, makeStyles, IconButton } from '@material-ui/core'; +import { + TableContainer, Table, TableRow, TableCell, TableHead, TableBody, makeStyles, IconButton, +} from '@material-ui/core'; import MoreVertIcon from '@material-ui/icons/MoreVert'; import t from '../common/localization'; import { useEffectAsync } from '../reactHelper'; import EditCollectionView from '../EditCollectionView'; import OptionsLayout from './OptionsLayout'; -const useStyles = makeStyles(theme => ({ +const useStyles = makeStyles((theme) => ({ columnAction: { width: theme.spacing(1), - padding: theme.spacing(0, 1) - } + padding: theme.spacing(0, 1), + }, })); const DriversView = ({ updateTimestamp, onMenuClick }) => { @@ -27,44 +29,42 @@ const DriversView = ({ updateTimestamp, onMenuClick }) => { return ( - - - - - {t('sharedName')} - {t('deviceIdentifier')} - - - - {items.map(item => ( - - +
+ + + + {t('sharedName')} + {t('deviceIdentifier')} + + + + {items.map((item) => ( + + onMenuClick(event.currentTarget, item.id)} + onClick={(event) => onMenuClick(event.currentTarget, item.id)} > - - - - {item.name} - {item.uniqueId} - - ))} - -
+ + + + {item.name} + {item.uniqueId} + + ))} + +
); }; -const DriversPage = () => { - return ( - - - - ); -}; +const DriversPage = () => ( + + + +); export default DriversPage; diff --git a/modern/src/settings/GroupPage.js b/modern/src/settings/GroupPage.js index b9fa871..f9af0f8 100644 --- a/modern/src/settings/GroupPage.js +++ b/modern/src/settings/GroupPage.js @@ -1,10 +1,12 @@ import React, { useState } from 'react'; import TextField from '@material-ui/core/TextField'; +import { + Accordion, AccordionSummary, AccordionDetails, makeStyles, Typography, +} from '@material-ui/core'; +import ExpandMoreIcon from '@material-ui/icons/ExpandMore'; 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 deviceAttributes from '../attributes/deviceAttributes'; import SelectField from '../form/SelectField'; @@ -22,7 +24,8 @@ const GroupPage = () => { return ( - {item && + {item + && ( <> }> @@ -34,9 +37,10 @@ const GroupPage = () => { setItem({...item, name: event.target.value})} + onChange={(event) => setItem({ ...item, name: event.target.value })} label={t('sharedName')} - variant="filled" /> + variant="filled" + /> @@ -49,10 +53,11 @@ const GroupPage = () => { setItem({...item, groupId: Number(event.target.value)})} + onChange={(event) => setItem({ ...item, groupId: Number(event.target.value) })} endpoint="/api/groups" label={t('groupParent')} - variant="filled" /> + variant="filled" + /> @@ -64,15 +69,15 @@ const GroupPage = () => { setItem({...item, attributes})} + setAttributes={(attributes) => setItem({ ...item, attributes })} definitions={deviceAttributes} - /> + /> - } + )} ); -} +}; export default GroupPage; diff --git a/modern/src/settings/GroupsPage.js b/modern/src/settings/GroupsPage.js index 2fc65c1..3b1058e 100644 --- a/modern/src/settings/GroupsPage.js +++ b/modern/src/settings/GroupsPage.js @@ -1,16 +1,18 @@ import React, { useState } from 'react'; -import { TableContainer, Table, TableRow, TableCell, TableHead, TableBody, makeStyles, IconButton } from '@material-ui/core'; +import { + TableContainer, Table, TableRow, TableCell, TableHead, TableBody, makeStyles, IconButton, +} from '@material-ui/core'; import MoreVertIcon from '@material-ui/icons/MoreVert'; import t from '../common/localization'; import { useEffectAsync } from '../reactHelper'; import EditCollectionView from '../EditCollectionView'; import OptionsLayout from './OptionsLayout'; -const useStyles = makeStyles(theme => ({ +const useStyles = makeStyles((theme) => ({ columnAction: { width: theme.spacing(1), - padding: theme.spacing(0, 1) - } + padding: theme.spacing(0, 1), + }, })); const GroupsView = ({ updateTimestamp, onMenuClick }) => { @@ -27,42 +29,40 @@ const GroupsView = ({ updateTimestamp, onMenuClick }) => { return ( - - - - - {t('sharedName')} - - - - {items.map(item => ( - - +
+ + + + {t('sharedName')} + + + + {items.map((item) => ( + + onMenuClick(event.currentTarget, item.id)} + onClick={(event) => onMenuClick(event.currentTarget, item.id)} > - - - - {item.name} - - ))} - -
+ + + + {item.name} + + ))} + +
); }; -const GroupsPage = () => { - return ( - - - - ); -}; +const GroupsPage = () => ( + + + +); export default GroupsPage; diff --git a/modern/src/settings/MaintenancePage.js b/modern/src/settings/MaintenancePage.js index 3b4fde5..9d60937 100644 --- a/modern/src/settings/MaintenancePage.js +++ b/modern/src/settings/MaintenancePage.js @@ -1,14 +1,18 @@ import React, { useState } from 'react'; +import { + Accordion, AccordionSummary, AccordionDetails, makeStyles, Typography, TextField, FormControl, InputLabel, MenuItem, Select, +} from '@material-ui/core'; +import InputAdornment from '@material-ui/core/InputAdornment'; +import ExpandMoreIcon from '@material-ui/icons/ExpandMore'; import t from '../common/localization'; import { prefixString } from '../common/stringUtils'; import EditItemView from '../EditItemView'; -import { Accordion, AccordionSummary, AccordionDetails, makeStyles, Typography, TextField, FormControl, InputLabel, MenuItem, Select, } from '@material-ui/core'; -import InputAdornment from '@material-ui/core/InputAdornment'; -import ExpandMoreIcon from '@material-ui/icons/ExpandMore'; import EditAttributesView from '../attributes/EditAttributesView'; import positionAttributes from '../attributes/positionAttributes'; import { useAttributePreference } from '../common/preferences'; -import { speedFromKnots, speedToKnots, distanceFromMeters, distanceToMeters } from '../common/converter'; +import { + speedFromKnots, speedToKnots, distanceFromMeters, distanceToMeters, +} from '../common/converter'; const useStyles = makeStyles(() => ({ details: { @@ -17,46 +21,46 @@ const useStyles = makeStyles(() => ({ })); const MaintenancePage = () => { - const classes = useStyles(); const [item, setItem] = useState(); - const [labels, setLabels] = useState({start: '', period: ''}); + const [labels, setLabels] = useState({ start: '', period: '' }); const speedUnit = useAttributePreference('speedUnit'); const distanceUnit = useAttributePreference('distanceUnit'); const convertToList = (attributes) => { - let otherList = []; + const otherList = []; for (const key in attributes) { const value = attributes[key]; if (value.type === 'number') { - otherList.push({key, name: value.name, type: value.type}); + otherList.push({ key, name: value.name, type: value.type }); } } return otherList; - } + }; - const onMaintenanceTypeChange = event => { + const onMaintenanceTypeChange = (event) => { const newValue = event.target.value; - setItem({ ...item, type: newValue, start: 0, period: 0 }); + setItem({ + ...item, type: newValue, start: 0, period: 0, + }); const attribute = positionAttributes[newValue]; if (attribute && attribute.dataType) { switch (attribute.dataType) { case 'distance': - setLabels({ ...labels, start: t(prefixString('shared', distanceUnit)), period: t(prefixString('shared', distanceUnit))}); + setLabels({ ...labels, start: t(prefixString('shared', distanceUnit)), period: t(prefixString('shared', distanceUnit)) }); break; case 'speed': - setLabels({ ...labels, start: t(prefixString('shared', speedUnit)), period: t(prefixString('shared', speedUnit))}); + setLabels({ ...labels, start: t(prefixString('shared', speedUnit)), period: t(prefixString('shared', speedUnit)) }); break; default: break; } } - } - - const rawToValue = value => { + }; + const rawToValue = (value) => { const attribute = positionAttributes[item.type]; if (attribute && attribute.dataType) { switch (attribute.dataType) { @@ -69,10 +73,9 @@ const MaintenancePage = () => { } } return value; - } - - const valueToRaw = value => { + }; + const valueToRaw = (value) => { const attribute = positionAttributes[item.type]; if (attribute && attribute.dataType) { switch (attribute.dataType) { @@ -85,11 +88,12 @@ const MaintenancePage = () => { } } return value; - } + }; return ( - {item && + {item + && ( <> }> @@ -101,39 +105,43 @@ const MaintenancePage = () => { setItem({...item, name: event.target.value})} + onChange={(event) => setItem({ ...item, name: event.target.value })} label={t('sharedName')} - variant="filled" /> + variant="filled" + /> {t('sharedType')} - + {convertToList(positionAttributes).map(({ key, name }) => ( + {name} + ))} - + setItem({...item, start: valueToRaw(event.target.value)})} + onChange={(event) => setItem({ ...item, start: valueToRaw(event.target.value) })} label={t('maintenanceStart')} variant="filled" InputProps={{ - endAdornment: {labels.start}, - }} /> + endAdornment: {labels.start}, + }} + /> setItem({...item, period: valueToRaw(event.target.value)})} + onChange={(event) => setItem({ ...item, period: valueToRaw(event.target.value) })} label={t('maintenancePeriod')} variant="filled" InputProps={{ - endAdornment: {labels.period}, - }} /> + endAdornment: {labels.period}, + }} + /> @@ -145,15 +153,15 @@ const MaintenancePage = () => { setItem({...item, attributes})} + setAttributes={(attributes) => setItem({ ...item, attributes })} definitions={{}} - /> + /> - + - } + )} ); -} +}; export default MaintenancePage; diff --git a/modern/src/settings/MaintenancesPage.js b/modern/src/settings/MaintenancesPage.js index d713eaa..b8e74d2 100644 --- a/modern/src/settings/MaintenancesPage.js +++ b/modern/src/settings/MaintenancesPage.js @@ -1,5 +1,7 @@ import React, { useState } from 'react'; -import { TableContainer, Table, TableRow, TableCell, TableHead, TableBody, makeStyles, IconButton } from '@material-ui/core'; +import { + TableContainer, Table, TableRow, TableCell, TableHead, TableBody, makeStyles, IconButton, +} from '@material-ui/core'; import MoreVertIcon from '@material-ui/icons/MoreVert'; import t from '../common/localization'; import { useEffectAsync } from '../reactHelper'; @@ -10,11 +12,11 @@ import { formatDistance, formatSpeed } from '../common/formatter'; import { useAttributePreference } from '../common/preferences'; import OptionsLayout from './OptionsLayout'; -const useStyles = makeStyles(theme => ({ +const useStyles = makeStyles((theme) => ({ columnAction: { width: theme.spacing(1), - padding: theme.spacing(0, 1) - } + padding: theme.spacing(0, 1), + }, })); const MaintenancesView = ({ updateTimestamp, onMenuClick }) => { @@ -37,7 +39,7 @@ const MaintenancesView = ({ updateTimestamp, onMenuClick }) => { switch (attribute.dataType) { case 'speed': return formatSpeed(value, speedUnit); - case 'distance': + case 'distance': return formatDistance(value, distanceUnit); default: return value; @@ -49,48 +51,46 @@ const MaintenancesView = ({ updateTimestamp, onMenuClick }) => { return ( - - - - - {t('sharedName')} - {t('sharedType')} - {t('maintenanceStart')} - {t('maintenancePeriod')} - - - - {items.map(item => ( - - +
+ + + + {t('sharedName')} + {t('sharedType')} + {t('maintenanceStart')} + {t('maintenancePeriod')} + + + + {items.map((item) => ( + + onMenuClick(event.currentTarget, item.id)} + onClick={(event) => onMenuClick(event.currentTarget, item.id)} > - - - - {item.name} - {item.type} - {convertAttribute(item.type, item.start)} - {convertAttribute(item.type, item.period)} - - ))} - -
+ + + + {item.name} + {item.type} + {convertAttribute(item.type, item.start)} + {convertAttribute(item.type, item.period)} + + ))} + +
); }; -const MaintenacesPage = () => { - return ( - - - - ); -}; +const MaintenacesPage = () => ( + + + +); export default MaintenacesPage; diff --git a/modern/src/settings/NotificationPage.js b/modern/src/settings/NotificationPage.js index 33904e7..11c427f 100644 --- a/modern/src/settings/NotificationPage.js +++ b/modern/src/settings/NotificationPage.js @@ -1,9 +1,11 @@ import React, { useState } from 'react'; +import { + Accordion, AccordionSummary, AccordionDetails, makeStyles, Typography, FormControlLabel, Checkbox, +} from '@material-ui/core'; +import ExpandMoreIcon from '@material-ui/icons/ExpandMore'; import t, { findStringKeys } from '../common/localization'; import EditItemView from '../EditItemView'; -import { Accordion, AccordionSummary, AccordionDetails, makeStyles, Typography, FormControlLabel, Checkbox } from '@material-ui/core'; -import ExpandMoreIcon from '@material-ui/icons/ExpandMore'; import { prefixString, unprefixString } from '../common/stringUtils'; import SelectField from '../form/SelectField'; @@ -18,14 +20,15 @@ const NotificationPage = () => { const [item, setItem] = useState(); - const alarms = findStringKeys(it => it.startsWith('alarm')).map(it => ({ + const alarms = findStringKeys((it) => it.startsWith('alarm')).map((it) => ({ key: unprefixString('alarm', it), name: t(it), })); return ( - {item && + {item + && ( <> }> @@ -38,47 +41,52 @@ const NotificationPage = () => { margin="normal" value={item.type || 'alarm'} emptyValue={null} - onChange={e => setItem({...item, type: e.target.value})} + onChange={(e) => setItem({ ...item, type: e.target.value })} endpoint="/api/notifications/types" - keyGetter={it => it.type} - titleGetter={it => t(prefixString('event', it.type))} + keyGetter={(it) => it.type} + titleGetter={(it) => t(prefixString('event', it.type))} label={t('sharedType')} - variant="filled" /> + variant="filled" + /> setItem({...item, notificators: e.target.value.join()})} + onChange={(e) => setItem({ ...item, notificators: e.target.value.join() })} endpoint="/api/notifications/notificators" - keyGetter={it => it.type} - titleGetter={it => t(prefixString('notificator', it.type))} + keyGetter={(it) => it.type} + titleGetter={(it) => t(prefixString('notificator', it.type))} label={t('notificationNotificators')} - variant="filled" /> - {(!item.type || item.type === 'alarm') && + variant="filled" + /> + {(!item.type || item.type === 'alarm') + && ( setItem({...item, attributes: {...item.attributes, alarms: e.target.value.join()}})} + onChange={(e) => setItem({ ...item, attributes: { ...item.attributes, alarms: e.target.value.join() } })} data={alarms} - keyGetter={it => it.key} + keyGetter={(it) => it.key} label={t('sharedAlarms')} - variant="filled" /> - } + variant="filled" + /> + )} setItem({...item, always: event.target.checked})} - /> - } - label={t('notificationAlways')} /> + onChange={(event) => setItem({ ...item, always: event.target.checked })} + /> + )} + label={t('notificationAlways')} + /> - } + )} ); -} +}; export default NotificationPage; diff --git a/modern/src/settings/NotificationsPage.js b/modern/src/settings/NotificationsPage.js index 5707f89..079f88d 100644 --- a/modern/src/settings/NotificationsPage.js +++ b/modern/src/settings/NotificationsPage.js @@ -1,5 +1,7 @@ import React, { useState } from 'react'; -import { TableContainer, Table, TableRow, TableCell, TableHead, TableBody, makeStyles, IconButton } from '@material-ui/core'; +import { + TableContainer, Table, TableRow, TableCell, TableHead, TableBody, makeStyles, IconButton, +} from '@material-ui/core'; import MoreVertIcon from '@material-ui/icons/MoreVert'; import t from '../common/localization'; import { useEffectAsync } from '../reactHelper'; @@ -8,11 +10,11 @@ import { prefixString } from '../common/stringUtils'; import { formatBoolean } from '../common/formatter'; import OptionsLayout from './OptionsLayout'; -const useStyles = makeStyles(theme => ({ +const useStyles = makeStyles((theme) => ({ columnAction: { width: theme.spacing(1), - padding: theme.spacing(0, 1) - } + padding: theme.spacing(0, 1), + }, })); const NotificationsView = ({ updateTimestamp, onMenuClick }) => { @@ -32,7 +34,7 @@ const NotificationsView = ({ updateTimestamp, onMenuClick }) => { return value .split(/[, ]+/) .filter(Boolean) - .map(it => t(prefixString(prefix, it))) + .map((it) => t(prefixString(prefix, it))) .join(', '); } return ''; @@ -40,52 +42,50 @@ const NotificationsView = ({ updateTimestamp, onMenuClick }) => { return ( - - - - - {t('notificationType')} - {t('notificationAlways')} - {t('sharedAlarms')} - {t('notificationNotificators')} - - - - {items.map(item => ( - - +
+ + + + {t('notificationType')} + {t('notificationAlways')} + {t('sharedAlarms')} + {t('notificationNotificators')} + + + + {items.map((item) => ( + + onMenuClick(event.currentTarget, item.id)} + onClick={(event) => onMenuClick(event.currentTarget, item.id)} > - - - - {t(prefixString('event', item.type))} - {formatBoolean(item.always)} + + + + {t(prefixString('event', item.type))} + {formatBoolean(item.always)} {formatList('alarm', item.attributes.alarms)} {formatList('notificator', item.notificators)} - - ))} - -
+ + ))} + +
); }; -const NotificationsPage = () => { - return ( - - - - ); -}; +const NotificationsPage = () => ( + + + +); export default NotificationsPage; diff --git a/modern/src/settings/OptionsLayout/useRoutes.js b/modern/src/settings/OptionsLayout/useRoutes.js index 901719f..f2603dd 100644 --- a/modern/src/settings/OptionsLayout/useRoutes.js +++ b/modern/src/settings/OptionsLayout/useRoutes.js @@ -13,7 +13,7 @@ import t from '../../common/localization'; const accountRoute = { name: t('settingsUser'), - icon: + icon: , }; const adminRoutes = [ @@ -21,18 +21,18 @@ const adminRoutes = [ { name: t('settingsServer'), href: '/admin/server', - icon: + icon: , }, { name: t('settingsUsers'), href: '/admin/users', - icon: + icon: , }, { name: t('statisticsTitle'), href: '/admin/statistics', - icon: - } + icon: , + }, ]; const mainRoutes = [ @@ -41,38 +41,38 @@ const mainRoutes = [ match: 'geofence', name: t('sharedGeofences'), href: '/geofences', - icon: + icon: , }, { match: 'notification', name: t('sharedNotifications'), href: '/settings/notifications', - icon: + icon: , }, { match: 'group', name: t('settingsGroups'), href: '/settings/groups', - icon: + icon: , }, { match: 'driver', name: t('sharedDrivers'), href: '/settings/drivers', - icon: + icon: , }, { match: 'attribute', name: t('sharedComputedAttributes'), href: '/settings/attributes', - icon: + icon: , }, { match: 'maintenance', name: t('sharedMaintenance'), href: '/settings/maintenances', - icon: - } + icon: , + }, ]; export default () => { @@ -81,6 +81,6 @@ export default () => { accountRoute.href = `/user/${userId}`; return useMemo(() => [...mainRoutes, ...(isAdmin ? adminRoutes : [])], [ - isAdmin + isAdmin, ]); }; diff --git a/modern/src/setupProxy.js b/modern/src/setupProxy.js index c16655c..e5ca76d 100644 --- a/modern/src/setupProxy.js +++ b/modern/src/setupProxy.js @@ -1,6 +1,6 @@ const proxy = require('http-proxy-middleware'); module.exports = function (app) { - app.use(proxy('/api/socket', { target: 'ws://' + process.env.REACT_APP_URL_NAME, ws: true })); - app.use(proxy('/api', { target: 'http://' + process.env.REACT_APP_URL_NAME })); + app.use(proxy('/api/socket', { target: `ws://${process.env.REACT_APP_URL_NAME}`, ws: true })); + app.use(proxy('/api', { target: `http://${process.env.REACT_APP_URL_NAME}` })); }; diff --git a/modern/src/store/devices.js b/modern/src/store/devices.js index 66c1607..cca23cb 100644 --- a/modern/src/store/devices.js +++ b/modern/src/store/devices.js @@ -4,15 +4,15 @@ const { reducer, actions } = createSlice({ name: 'devices', initialState: { items: {}, - selectedId: null + selectedId: null, }, reducers: { refresh(state, action) { state.items = {}; - action.payload.forEach(item => state.items[item['id']] = item); + action.payload.forEach((item) => state.items[item.id] = item); }, update(state, action) { - action.payload.forEach(item => state.items[item['id']] = item); + action.payload.forEach((item) => state.items[item.id] = item); }, select(state, action) { state.selectedId = action.payload.id; @@ -20,7 +20,7 @@ const { reducer, actions } = createSlice({ remove(state, action) { delete state.items[action.payload]; }, - } + }, }); export { actions as devicesActions }; diff --git a/modern/src/store/drivers.js b/modern/src/store/drivers.js index 63522d7..38933d8 100644 --- a/modern/src/store/drivers.js +++ b/modern/src/store/drivers.js @@ -7,9 +7,9 @@ const { reducer, actions } = createSlice({ }, reducers: { update(state, action) { - action.payload.forEach(item => state.items[item['id']] = item); + action.payload.forEach((item) => state.items[item.id] = item); }, - } + }, }); export { actions as driversActions }; diff --git a/modern/src/store/geofences.js b/modern/src/store/geofences.js index 504b7d0..f2b7666 100644 --- a/modern/src/store/geofences.js +++ b/modern/src/store/geofences.js @@ -8,12 +8,12 @@ const { reducer, actions } = createSlice({ reducers: { refresh(state, action) { state.items = {}; - action.payload.forEach(item => state.items[item['id']] = item); + action.payload.forEach((item) => state.items[item.id] = item); }, update(state, action) { - action.payload.forEach(item => state.items[item['id']] = item); + action.payload.forEach((item) => state.items[item.id] = item); }, - } + }, }); export { actions as geofencesActions }; diff --git a/modern/src/store/groups.js b/modern/src/store/groups.js index 483323f..11fc5db 100644 --- a/modern/src/store/groups.js +++ b/modern/src/store/groups.js @@ -7,9 +7,9 @@ const { reducer, actions } = createSlice({ }, reducers: { update(state, action) { - action.payload.forEach(item => state.items[item['id']] = item); + action.payload.forEach((item) => state.items[item.id] = item); }, - } + }, }); export { actions as groupsActions }; diff --git a/modern/src/store/maintenances.js b/modern/src/store/maintenances.js index 0813f6b..08b2adb 100644 --- a/modern/src/store/maintenances.js +++ b/modern/src/store/maintenances.js @@ -7,9 +7,9 @@ const { reducer, actions } = createSlice({ }, reducers: { update(state, action) { - action.payload.forEach(item => state.items[item['id']] = item); + action.payload.forEach((item) => state.items[item.id] = item); }, - } + }, }); export { actions as maintenancesActions }; diff --git a/modern/src/store/positions.js b/modern/src/store/positions.js index 1df468c..8858298 100644 --- a/modern/src/store/positions.js +++ b/modern/src/store/positions.js @@ -7,9 +7,9 @@ const { reducer, actions } = createSlice({ }, reducers: { update(state, action) { - action.payload.forEach(item => state.items[item['deviceId']] = item); + action.payload.forEach((item) => state.items[item.deviceId] = item); }, - } + }, }); export { actions as positionsActions }; diff --git a/modern/src/theme/dimensions.js b/modern/src/theme/dimensions.js index a2403ab..fcdbaee 100644 --- a/modern/src/theme/dimensions.js +++ b/modern/src/theme/dimensions.js @@ -8,5 +8,5 @@ export default { columnWidthDate: 160, columnWidthNumber: 130, columnWidthString: 160, - columnWidthBoolean: 130 + columnWidthBoolean: 130, }; diff --git a/modern/src/theme/index.js b/modern/src/theme/index.js index 5a3b2a9..dc0a35b 100644 --- a/modern/src/theme/index.js +++ b/modern/src/theme/index.js @@ -6,7 +6,7 @@ import dimensions from './dimensions'; const theme = createMuiTheme({ palette, overrides, - dimensions + dimensions, }); export default theme; diff --git a/modern/src/theme/overrides.js b/modern/src/theme/overrides.js index cd6c5a5..a6d08cf 100644 --- a/modern/src/theme/overrides.js +++ b/modern/src/theme/overrides.js @@ -4,17 +4,17 @@ export default { MuiFormControl: { root: { marginTop: 5, - marginBottom: 5 - } + marginBottom: 5, + }, }, MuiInputLabel: { filled: { transform: 'translate(12px, 14px) scale(1)', - '&$shrink' :{ - transform: 'translate(12px, -14px) scale(0.72)' - } + '&$shrink': { + transform: 'translate(12px, -14px) scale(0.72)', + }, }, - }, + }, MuiFilledInput: { root: { height: dimensions.inputHeight, @@ -28,19 +28,19 @@ export default { boxSizing: 'border-box', '&:-webkit-autofill': { WebkitBoxShadow: '0 0 0 100px #eeeeee inset', - }, + }, }, underline: { - "&:before": { + '&:before': { borderBottom: 'none', }, - "&:after": { + '&:after': { borderBottom: 'none', }, - "&:hover:before": { + '&:hover:before': { borderBottom: 'none', - }, - } + }, + }, }, MuiButton: { root: { @@ -48,31 +48,31 @@ export default { marginTop: 5, marginBottom: 5, '&$disabled': { - opacity: .4, + opacity: 0.4, color: undefined, - } + }, }, contained: { '&$disabled': { - opacity: .4, + opacity: 0.4, color: undefined, - backgroundColor: undefined - } - } + backgroundColor: undefined, + }, + }, }, MuiFormHelperText: { root: { - marginBottom: -10 + marginBottom: -10, }, contained: { - marginLeft: 12 - } + marginLeft: 12, + }, }, MuiAutocomplete: { inputRoot: { '&.MuiFilledInput-root': { - paddingTop: 0 - } - } - } + paddingTop: 0, + }, + }, + }, }; -- cgit v1.2.3 From aba0f502a1a5e9a9467a06e1417ebb72c1e2ced2 Mon Sep 17 00:00:00 2001 From: Desmond Kyeremeh Date: Mon, 12 Jul 2021 03:05:49 +0000 Subject: Updated eslint --- modern/.eslintrc.js | 3 +++ modern/package.json | 2 +- modern/src/components/SideNav.js | 2 +- modern/src/selectors.js | 4 ++-- modern/src/settings/OptionsLayout/index.js | 26 +++++++++++++------------- 5 files changed, 20 insertions(+), 17 deletions(-) (limited to 'modern/src') diff --git a/modern/.eslintrc.js b/modern/.eslintrc.js index d6380a8..a4cf305 100644 --- a/modern/.eslintrc.js +++ b/modern/.eslintrc.js @@ -1,5 +1,8 @@ module.exports = { extends: 'airbnb', + parserOptions: { + ecmaVersion: 2020, + }, plugins: [ 'react', ], diff --git a/modern/package.json b/modern/package.json index 365d986..2ae229c 100644 --- a/modern/package.json +++ b/modern/package.json @@ -49,7 +49,7 @@ ] }, "devDependencies": { - "eslint": "^6.8.0", + "eslint": "^7.30.0", "eslint-config-airbnb": "^18.2.1", "eslint-plugin-import": "^2.23.4", "eslint-plugin-react": "^7.24.0", diff --git a/modern/src/components/SideNav.js b/modern/src/components/SideNav.js index aa07808..bcf8ecd 100644 --- a/modern/src/components/SideNav.js +++ b/modern/src/components/SideNav.js @@ -9,7 +9,7 @@ const SideNav = ({ routes }) => { return ( - {routes.map((route, index) => (route.subheader ? ( + {routes.map((route) => (route.subheader ? ( <> {route.subheader} diff --git a/modern/src/selectors.js b/modern/src/selectors.js index f0b08f5..44a0c54 100644 --- a/modern/src/selectors.js +++ b/modern/src/selectors.js @@ -1,3 +1,3 @@ -export const getIsAdmin = state => state.session.user?.administrator; +export const getIsAdmin = (state) => state.session.user?.administrator; -export const getUserId = state => state.session.user?.id; +export const getUserId = (state) => state.session.user?.id; diff --git a/modern/src/settings/OptionsLayout/index.js b/modern/src/settings/OptionsLayout/index.js index 61a94cf..1184465 100644 --- a/modern/src/settings/OptionsLayout/index.js +++ b/modern/src/settings/OptionsLayout/index.js @@ -6,7 +6,7 @@ import { Drawer, makeStyles, IconButton, - Hidden + Hidden, } from '@material-ui/core'; import ArrowBackIcon from '@material-ui/icons/ArrowBack'; @@ -16,38 +16,38 @@ import NavBar from '../../components/NavBar'; import t from '../../common/localization'; import useRoutes from './useRoutes'; -const useStyles = makeStyles(theme => ({ +const useStyles = makeStyles((theme) => ({ root: { display: 'flex', - height: '100%' + height: '100%', }, drawerContainer: { - width: theme.dimensions.drawerWidthDesktop + width: theme.dimensions.drawerWidthDesktop, }, drawer: { width: theme.dimensions.drawerWidthDesktop, [theme.breakpoints.down('md')]: { - width: theme.dimensions.drawerWidthTablet - } + width: theme.dimensions.drawerWidthTablet, + }, }, content: { flex: 1, padding: theme.spacing(5, 3, 3, 3), [theme.breakpoints.down('md')]: { - paddingTop: theme.spacing(10) - } + paddingTop: theme.spacing(10), + }, }, drawerHeader: { ...theme.mixins.toolbar, display: 'flex', alignItems: 'center', - padding: theme.spacing(0, 1) + padding: theme.spacing(0, 1), }, toolbar: { [theme.breakpoints.down('md')]: { - ...theme.mixins.toolbar - } - } + ...theme.mixins.toolbar, + }, + }, })); const OptionsLayout = ({ children }) => { @@ -59,7 +59,7 @@ const OptionsLayout = ({ children }) => { useEffect(() => { const activeRoute = routes.find( - route => route.href && location.pathname.match(route.match || route.href) + (route) => route.href && location.pathname.match(route.match || route.href), ); setOptionTitle(activeRoute?.name); }, [location, routes]); -- cgit v1.2.3 From a7e1b5f5fd772d37f9777fec097f28411f13562f Mon Sep 17 00:00:00 2001 From: Desmond Kyeremeh Date: Mon, 12 Jul 2021 03:12:10 +0000 Subject: moved selectors to common --- modern/src/MainToolbar.js | 2 +- modern/src/common/selectors.js | 3 +++ modern/src/selectors.js | 3 --- modern/src/settings/OptionsLayout/useRoutes.js | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) create mode 100644 modern/src/common/selectors.js delete mode 100644 modern/src/selectors.js (limited to 'modern/src') diff --git a/modern/src/MainToolbar.js b/modern/src/MainToolbar.js index dacd668..8b6c22c 100644 --- a/modern/src/MainToolbar.js +++ b/modern/src/MainToolbar.js @@ -19,7 +19,7 @@ import DescriptionIcon from '@material-ui/icons/Description'; import ReplayIcon from '@material-ui/icons/Replay'; import { sessionActions } from './store'; import t from './common/localization'; -import * as selectors from './selectors'; +import * as selectors from './common/selectors'; const useStyles = makeStyles((theme) => ({ flex: { diff --git a/modern/src/common/selectors.js b/modern/src/common/selectors.js new file mode 100644 index 0000000..44a0c54 --- /dev/null +++ b/modern/src/common/selectors.js @@ -0,0 +1,3 @@ +export const getIsAdmin = (state) => state.session.user?.administrator; + +export const getUserId = (state) => state.session.user?.id; diff --git a/modern/src/selectors.js b/modern/src/selectors.js deleted file mode 100644 index 44a0c54..0000000 --- a/modern/src/selectors.js +++ /dev/null @@ -1,3 +0,0 @@ -export const getIsAdmin = (state) => state.session.user?.administrator; - -export const getUserId = (state) => state.session.user?.id; diff --git a/modern/src/settings/OptionsLayout/useRoutes.js b/modern/src/settings/OptionsLayout/useRoutes.js index f2603dd..1832081 100644 --- a/modern/src/settings/OptionsLayout/useRoutes.js +++ b/modern/src/settings/OptionsLayout/useRoutes.js @@ -8,7 +8,7 @@ import StorageIcon from '@material-ui/icons/Storage'; import BuildIcon from '@material-ui/icons/Build'; import PeopleIcon from '@material-ui/icons/People'; import BarChartIcon from '@material-ui/icons/BarChart'; -import { getIsAdmin, getUserId } from '../../selectors'; +import { getIsAdmin, getUserId } from '../../common/selectors'; import t from '../../common/localization'; const accountRoute = { -- cgit v1.2.3 From f60983a4131862db0125844a651b994d2212022d Mon Sep 17 00:00:00 2001 From: Desmond Kyeremeh Date: Mon, 12 Jul 2021 03:30:34 +0000 Subject: Restored styling --- modern/src/MainToolbar.js | 12 +++------- modern/src/admin/StatisticsPage.js | 33 +++++++-------------------- modern/src/admin/UsersPage.js | 6 +---- modern/src/attributes/EditAttributesView.js | 3 +-- modern/src/settings/ComputedAttributesPage.js | 8 ++----- 5 files changed, 15 insertions(+), 47 deletions(-) (limited to 'modern/src') diff --git a/modern/src/MainToolbar.js b/modern/src/MainToolbar.js index 8b6c22c..59c2eca 100644 --- a/modern/src/MainToolbar.js +++ b/modern/src/MainToolbar.js @@ -44,12 +44,8 @@ const MainToolbar = () => { const history = useHistory(); const userId = useSelector(selectors.getUserId); - const openDrawer = () => { - setDrawer(true); - }; - const closeDrawer = () => { - setDrawer(false); - }; + const openDrawer = () => { setDrawer(true); }; + const closeDrawer = () => { setDrawer(false); }; const handleLogout = async () => { const response = await fetch('/api/session', { method: 'DELETE' }); @@ -73,9 +69,7 @@ const MainToolbar = () => { Traccar - + diff --git a/modern/src/admin/StatisticsPage.js b/modern/src/admin/StatisticsPage.js index 20974f4..1f32c3d 100644 --- a/modern/src/admin/StatisticsPage.js +++ b/modern/src/admin/StatisticsPage.js @@ -21,36 +21,24 @@ const Filter = ({ setItems }) => { selectedTo = moment().endOf('day'); break; case 'yesterday': - selectedFrom = moment() - .subtract(1, 'day') - .startOf('day'); - selectedTo = moment() - .subtract(1, 'day') - .endOf('day'); + selectedFrom = moment().subtract(1, 'day').startOf('day'); + selectedTo = moment().subtract(1, 'day').endOf('day'); break; case 'thisWeek': selectedFrom = moment().startOf('week'); selectedTo = moment().endOf('week'); break; case 'previousWeek': - selectedFrom = moment() - .subtract(1, 'week') - .startOf('week'); - selectedTo = moment() - .subtract(1, 'week') - .endOf('week'); + selectedFrom = moment().subtract(1, 'week').startOf('week'); + selectedTo = moment().subtract(1, 'week').endOf('week'); break; case 'thisMonth': selectedFrom = moment().startOf('month'); selectedTo = moment().endOf('month'); break; case 'previousMonth': - selectedFrom = moment() - .subtract(1, 'month') - .startOf('month'); - selectedTo = moment() - .subtract(1, 'month') - .endOf('month'); + selectedFrom = moment().subtract(1, 'month').startOf('month'); + selectedTo = moment().subtract(1, 'month').endOf('month'); break; default: selectedFrom = from; @@ -58,13 +46,8 @@ const Filter = ({ setItems }) => { break; } - const query = new URLSearchParams({ - from: selectedFrom.toISOString(), - to: selectedTo.toISOString(), - }); - const response = await fetch(`/api/statistics?${query.toString()}`, { - Accept: 'application/json', - }); + const query = new URLSearchParams({ from: selectedFrom.toISOString(), to: selectedTo.toISOString() }); + const response = await fetch(`/api/statistics?${query.toString()}`, { Accept: 'application/json' }); if (response.ok) { setItems(await response.json()); } diff --git a/modern/src/admin/UsersPage.js b/modern/src/admin/UsersPage.js index 9b51cdd..a8b3c84 100644 --- a/modern/src/admin/UsersPage.js +++ b/modern/src/admin/UsersPage.js @@ -62,11 +62,7 @@ const UsersView = ({ updateTimestamp, onMenuClick }) => { const UsersPage = () => ( - + ); diff --git a/modern/src/attributes/EditAttributesView.js b/modern/src/attributes/EditAttributesView.js index e8d427b..e38c02a 100644 --- a/modern/src/attributes/EditAttributesView.js +++ b/modern/src/attributes/EditAttributesView.js @@ -43,8 +43,7 @@ const EditAttributesView = ({ attributes, setAttributes, definitions }) => { const getAttributeType = (value) => { if (typeof value === 'number') { return 'number'; - } - if (typeof value === 'boolean') { + } if (typeof value === 'boolean') { return 'boolean'; } return 'string'; diff --git a/modern/src/settings/ComputedAttributesPage.js b/modern/src/settings/ComputedAttributesPage.js index d376f23..9f131d3 100644 --- a/modern/src/settings/ComputedAttributesPage.js +++ b/modern/src/settings/ComputedAttributesPage.js @@ -20,9 +20,7 @@ const ComputedAttributeView = ({ updateTimestamp, onMenuClick }) => { const classes = useStyles(); const [items, setItems] = useState([]); - const adminEnabled = useSelector( - (state) => state.session.user && state.session.user.administrator, - ); + const adminEnabled = useSelector((state) => state.session.user && state.session.user.administrator); useEffectAsync(async () => { const response = await fetch('/api/attributes/computed'); @@ -49,9 +47,7 @@ const ComputedAttributeView = ({ updateTimestamp, onMenuClick }) => { {adminEnabled && ( - onMenuClick(event.currentTarget, item.id)} - > + onMenuClick(event.currentTarget, item.id)}> -- cgit v1.2.3 From 3b3aaf4081dd3a5291d9f5ebbb190db482dea62c Mon Sep 17 00:00:00 2001 From: Desmond Kyeremeh Date: Mon, 12 Jul 2021 03:34:40 +0000 Subject: f --- modern/src/reports/ReportLayout.js | 24 ++++-------------------- 1 file changed, 4 insertions(+), 20 deletions(-) (limited to 'modern/src') diff --git a/modern/src/reports/ReportLayout.js b/modern/src/reports/ReportLayout.js index e8dda63..c231cd8 100644 --- a/modern/src/reports/ReportLayout.js +++ b/modern/src/reports/ReportLayout.js @@ -53,26 +53,10 @@ const useStyles = makeStyles((theme) => ({ const routes = [ { name: t('reportRoute'), href: '/reports/route', icon: }, - { - name: t('reportEvents'), - href: '/reports/event', - icon: , - }, - { - name: t('reportTrips'), - href: '/reports/trip', - icon: , - }, - { - name: t('reportStops'), - href: '/reports/stop', - icon: , - }, - { - name: t('reportSummary'), - href: '/reports/summary', - icon: , - }, + { name: t('reportEvents'), href: '/reports/event', icon: }, + { name: t('reportTrips'), href: '/reports/trip', icon: }, + { name: t('reportStops'), href: '/reports/stop', icon: }, + { name: t('reportSummary'), href: '/reports/summary', icon: }, { name: t('reportChart'), href: '/reports/chart', icon: }, ]; -- cgit v1.2.3 From ea4ec2d769866db3490514b429cd95d314d19141 Mon Sep 17 00:00:00 2001 From: Desmond Kyeremeh Date: Mon, 12 Jul 2021 22:40:11 +0000 Subject: Used localised setting string --- modern/src/settings/OptionsLayout/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'modern/src') diff --git a/modern/src/settings/OptionsLayout/index.js b/modern/src/settings/OptionsLayout/index.js index 1184465..4a42e58 100644 --- a/modern/src/settings/OptionsLayout/index.js +++ b/modern/src/settings/OptionsLayout/index.js @@ -64,7 +64,7 @@ const OptionsLayout = ({ children }) => { setOptionTitle(activeRoute?.name); }, [location, routes]); - const title = `Options / ${optionTitle}`; + const title = `${t('settingsTitle')} / ${optionTitle}`; return (
-- cgit v1.2.3 From 31026c731b6b30c8b4207fc2ab86edf3cca0acda Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Tue, 13 Jul 2021 20:31:28 -0700 Subject: Encode login form (fix #875) --- modern/src/components/registration/LoginForm.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'modern/src') diff --git a/modern/src/components/registration/LoginForm.js b/modern/src/components/registration/LoginForm.js index e083541..d8dc696 100644 --- a/modern/src/components/registration/LoginForm.js +++ b/modern/src/components/registration/LoginForm.js @@ -41,7 +41,10 @@ const LoginForm = () => { const handleLogin = async (event) => { event.preventDefault(); - const response = await fetch('/api/session', { method: 'POST', body: new URLSearchParams(`email=${email}&password=${password}`) }); + const response = await fetch('/api/session', { + method: 'POST', + body: new URLSearchParams(`email=${encodeURIComponent(email)}&password=${encodeURIComponent(password)}`) + }); if (response.ok) { const user = await response.json(); dispatch(sessionActions.updateUser(user)); -- cgit v1.2.3 From 909b1adda19e88d7e05cb207b81e51e2022a5358 Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Tue, 13 Jul 2021 20:34:31 -0700 Subject: Fix lint --- modern/src/components/registration/LoginForm.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'modern/src') diff --git a/modern/src/components/registration/LoginForm.js b/modern/src/components/registration/LoginForm.js index d8dc696..e6da05e 100644 --- a/modern/src/components/registration/LoginForm.js +++ b/modern/src/components/registration/LoginForm.js @@ -43,7 +43,7 @@ const LoginForm = () => { event.preventDefault(); const response = await fetch('/api/session', { method: 'POST', - body: new URLSearchParams(`email=${encodeURIComponent(email)}&password=${encodeURIComponent(password)}`) + body: new URLSearchParams(`email=${encodeURIComponent(email)}&password=${encodeURIComponent(password)}`), }); if (response.ok) { const user = await response.json(); -- cgit v1.2.3 From 2b8e12b24c2c1aea9f9f36f98061f8200e153eda Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Sun, 18 Jul 2021 21:35:12 -0700 Subject: Handle empty attributes --- modern/src/attributes/EditAttributesView.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'modern/src') diff --git a/modern/src/attributes/EditAttributesView.js b/modern/src/attributes/EditAttributesView.js index e38c02a..13ea9bd 100644 --- a/modern/src/attributes/EditAttributesView.js +++ b/modern/src/attributes/EditAttributesView.js @@ -52,7 +52,7 @@ const EditAttributesView = ({ attributes, setAttributes, definitions }) => { const convertToList = (attributes) => { const booleanList = []; const otherList = []; - Object.keys(attributes).forEach((key) => { + Object.keys(attributes || []).forEach((key) => { const value = attributes[key]; const type = getAttributeType(value); if (type === 'boolean') { -- cgit v1.2.3 From 4273ec353b001a2b3a926c6ef07b8db9dbab3299 Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Sun, 18 Jul 2021 22:14:08 -0700 Subject: Fix geofence edit controls --- modern/package.json | 1 + modern/public/styles.css | 4 ++++ modern/src/map/GeofenceEditMap.js | 1 + 3 files changed, 6 insertions(+) (limited to 'modern/src') diff --git a/modern/package.json b/modern/package.json index 2ae229c..6606649 100644 --- a/modern/package.json +++ b/modern/package.json @@ -13,6 +13,7 @@ "@turf/circle": "^6.5.0", "@turf/turf": "^6.4.0", "canvas-tint-image": "^2.0.1", + "mapbox-gl": "^1.13.1", "maplibre-gl": "^1.15.0", "moment": "^2.29.1", "react": "^17.0.2", diff --git a/modern/public/styles.css b/modern/public/styles.css index 7e9de65..e7aee86 100644 --- a/modern/public/styles.css +++ b/modern/public/styles.css @@ -6,3 +6,7 @@ canvas { .maplibregl-popup-content { padding: 10px !important; } + +.mapboxgl-ctrl { + margin: 10px; +} diff --git a/modern/src/map/GeofenceEditMap.js b/modern/src/map/GeofenceEditMap.js index d639c19..28e259b 100644 --- a/modern/src/map/GeofenceEditMap.js +++ b/modern/src/map/GeofenceEditMap.js @@ -1,3 +1,4 @@ +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'; -- cgit v1.2.3 From 928de80f2c3af58459cc31a75384d0a950e480cf Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Sun, 18 Jul 2021 22:18:04 -0700 Subject: Fix style --- modern/src/map/GeofenceEditMap.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'modern/src') diff --git a/modern/src/map/GeofenceEditMap.js b/modern/src/map/GeofenceEditMap.js index 28e259b..3d1822f 100644 --- a/modern/src/map/GeofenceEditMap.js +++ b/modern/src/map/GeofenceEditMap.js @@ -1,4 +1,4 @@ -import 'mapbox-gl/dist/mapbox-gl.css' +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'; -- cgit v1.2.3 From c7e5e57c3ae706ad6e503beb0c535eca8ba8df40 Mon Sep 17 00:00:00 2001 From: Desmond Kyeremeh Date: Tue, 20 Jul 2021 18:19:13 +0000 Subject: Main page updates --- modern/src/MainPage.js | 235 +++++++++++++++---------------------------------- 1 file changed, 73 insertions(+), 162 deletions(-) (limited to 'modern/src') diff --git a/modern/src/MainPage.js b/modern/src/MainPage.js index d5447e5..c411ec5 100644 --- a/modern/src/MainPage.js +++ b/modern/src/MainPage.js @@ -1,7 +1,7 @@ import React, { useState } from 'react'; import { useHistory } from 'react-router-dom'; import { - makeStyles, Paper, Toolbar, Grid, TextField, IconButton, Button, + makeStyles, Paper, Toolbar, TextField, IconButton, Button, } from '@material-ui/core'; import { useTheme } from '@material-ui/core/styles'; @@ -10,116 +10,77 @@ import AddIcon from '@material-ui/icons/Add'; import CloseIcon from '@material-ui/icons/Close'; import ArrowBackIcon from '@material-ui/icons/ArrowBack'; import ListIcon from '@material-ui/icons/List'; -import ReplayIcon from '@material-ui/icons/Replay'; -import DescriptionIcon from '@material-ui/icons/Description'; -import ShuffleIcon from '@material-ui/icons/Shuffle'; -import PersonIcon from '@material-ui/icons/Person'; import DevicesList from './DevicesList'; -import MainToolbar from './MainToolbar'; import Map from './map/Map'; import SelectedDeviceMap from './map/SelectedDeviceMap'; import AccuracyMap from './map/AccuracyMap'; import GeofenceMap from './map/GeofenceMap'; import CurrentPositionsMap from './map/CurrentPositionsMap'; import CurrentLocationMap from './map/CurrentLocationMap'; +import BottomNav from "./components/BottomNav" import t from './common/localization'; const useStyles = makeStyles((theme) => ({ root: { height: '100vh', - display: 'flex', - flexDirection: 'column', }, - drawerPaper: { - position: 'relative', - [theme.breakpoints.up('sm')]: { - width: 350, - }, - [theme.breakpoints.down('xs')]: { - height: 250, - }, - overflow: 'hidden', - }, - listContainer: { + sidebar: { + display: 'flex', + flexDirection: "column", position: 'absolute', - left: theme.spacing(1.5), - top: theme.spacing(10.5), + left: 0, + top: 0, + margin: theme.spacing(1.5), width: theme.dimensions.drawerWidthDesktop, + bottom: theme.spacing(9.5), zIndex: 1301, - height: '100%', - maxHeight: `calc(100vh - ${theme.spacing(20)}px)`, + transition: 'transform .5s ease', [theme.breakpoints.down('md')]: { - top: theme.spacing(7), - left: '0px', width: '100%', - maxHeight: `calc(100vh - ${theme.spacing(14)}px)`, + margin: 0, + backgroundColor: 'white', + }, + }, + sidebarCollapsed: { + transform: `translateX(-${theme.dimensions.drawerWidthDesktop})`, + marginLeft: 0, + [theme.breakpoints.down('md')]: { + transform: 'translateX(-100vw)', }, }, paper: { borderRadius: '0px', }, toolbar: { - paddingLeft: theme.spacing(2), - paddingRight: theme.spacing(2), + display: 'flex', + padding: theme.spacing(0, 1), + '& > *': { + margin: theme.spacing(0, 1), + } }, deviceList: { - height: '100%', - backgroundColor: 'transparent', - [theme.breakpoints.down('md')]: { - backgroundColor: 'white', - }, - }, - collapsed: { - transform: `translateX(-${360 + 16}px)`, - transition: 'transform .5s ease', - [theme.breakpoints.down('md')]: { - transform: 'translateX(-100vw)', - }, - }, - uncollapsed: { - transform: `translateX(${theme.spacing(1.5)})`, - transition: 'transform .5s ease', - [theme.breakpoints.down('md')]: { - transform: 'translateX(0)', - }, + flex: 1, + overflow: 'auto', + paddingTop: theme.spacing(1.5), }, - deviceButton: { + sidebarToggle: { position: 'absolute', - left: theme.spacing(1), - top: theme.spacing(10.5), + left: theme.spacing(1.5), + top: theme.spacing(3), borderRadius: '0px', [theme.breakpoints.down('md')]: { left: theme.spacing(0), top: theme.spacing(7), }, }, - deviceButtonBackground: { + sidebarToggleBg: { backgroundColor: 'white', color: '#777777', '&:hover': { backgroundColor: 'white', }, }, - bottomMenuContainer: { - position: 'absolute', - left: theme.spacing(1.5), - bottom: theme.spacing(1.5), - width: theme.dimensions.drawerWidthDesktop, - zIndex: 1301, - [theme.breakpoints.down('md')]: { - bottom: theme.spacing(0), - left: '0px', - width: '100%', - }, - }, - menuButton: { - display: 'flex', - flexDirection: 'column', - fontSize: '0.75rem', - fontWeight: 'normal', - color: '#222222', - }, })); const MainPage = () => { @@ -127,7 +88,7 @@ const MainPage = () => { const history = useHistory(); const theme = useTheme(); - const [deviceName, setDeviceName] = useState(); + const [deviceName, setDeviceName] = useState(''); const [collapsed, setCollapsed] = useState(false); const isTablet = useMediaQuery(theme.breakpoints.down('md')); @@ -139,7 +100,6 @@ const MainPage = () => { return (
- @@ -147,100 +107,51 @@ const MainPage = () => { - {collapsed - && ( - - )} -
- - - - - - {isTablet && ( - - - - - - )} - - setDeviceName(event.target.value)} - placeholder="Search Devices" - variant="filled" - /> - - - history.push('/device')}> - - - - {!isTablet && ( - - - - - - )} - - - - - -
- -
-
-
-
-
- + +
+ - - - - - {t('reportReplay')} - - - - - - {t('reportTitle')} - - - - - - Options - - - - - - {t('settingsUser')} - - - + {isTablet && ( + + + + )} + setDeviceName(event.target.value)} + placeholder="Search Devices" + variant="filled" + /> + history.push('/device')}> + + + {!isTablet && ( + + + + )} +
+ +
+ +
); }; -- cgit v1.2.3 From e058059d9297afaf9bed45e863c41979196dad1b Mon Sep 17 00:00:00 2001 From: Desmond Kyeremeh Date: Tue, 20 Jul 2021 21:33:41 +0000 Subject: Bottom Nav --- modern/src/components/BottomNav.js | 109 +++++++++++++++++++++++++++++++++++++ 1 file changed, 109 insertions(+) create mode 100644 modern/src/components/BottomNav.js (limited to 'modern/src') diff --git a/modern/src/components/BottomNav.js b/modern/src/components/BottomNav.js new file mode 100644 index 0000000..6aad1dd --- /dev/null +++ b/modern/src/components/BottomNav.js @@ -0,0 +1,109 @@ +import React from 'react'; +import { useDispatch } from 'react-redux'; +import { Link, useHistory } from 'react-router-dom'; +import { + makeStyles, Paper, Toolbar, IconButton, useMediaQuery, useTheme, +} from '@material-ui/core'; + +import ReplayIcon from '@material-ui/icons/Replay'; +import DescriptionIcon from '@material-ui/icons/Description'; +import ShuffleIcon from '@material-ui/icons/Shuffle'; +import MapIcon from '@material-ui/icons/Map'; +import LogoutIcon from '@material-ui/icons/ExitToApp'; + +import { sessionActions } from '../store'; +import t from '../common/localization'; + +const useStyles = makeStyles((theme) => ({ + container: { + bottom: theme.spacing(0), + left: '0px', + width: '100%', + position: 'fixed', + zIndex: 1301, + [theme.breakpoints.up('lg')]: { + left: theme.spacing(1.5), + bottom: theme.spacing(1.5), + width: theme.dimensions.drawerWidthDesktop, + }, + }, + paper: { + borderRadius: '0px', + }, + toolbar: { + padding: theme.spacing(0, 2), + display: 'flex', + justifyContent: 'space-around', + maxWidth: theme.dimensions.bottomNavMaxWidth, + margin: 'auto', + }, + navItem: { + display: 'flex', + flexDirection: 'column', + fontSize: '0.75rem', + fontWeight: 'normal', + }, +})); + +const BottomNav = ({ showOnDesktop }) => { + const classes = useStyles(); + const theme = useTheme(); + const history = useHistory(); + + const isDesktop = useMediaQuery(theme.breakpoints.up('lg')); + const dispatch = useDispatch(); + + const NavLink = ({ children, location }) => ( + + {children} + + ); + + const handleLogout = async () => { + const response = await fetch('/api/session', { method: 'DELETE' }); + if (response.ok) { + dispatch(sessionActions.updateUser(null)); + history.push('/login'); + } + }; + + if (isDesktop && !showOnDesktop) return null; + + return ( +
+ + + + {isDesktop ? ( + + + {t('reportReplay')} + + ) : ( + + + {t('mapTitle')} + + )} + + + + {t('reportTitle')} + + + + + {t('settingsTitle')} + + + + + {t('loginLogout')} + + + +
+ ); +}; + +export default BottomNav; -- cgit v1.2.3 From 9dcecc62460c27b037fe7e56416afe6172404ef0 Mon Sep 17 00:00:00 2001 From: Desmond Kyeremeh Date: Tue, 20 Jul 2021 21:33:52 +0000 Subject: Updated Main page --- modern/src/MainPage.js | 17 ++++++++--------- modern/src/theme/dimensions.js | 1 + 2 files changed, 9 insertions(+), 9 deletions(-) (limited to 'modern/src') diff --git a/modern/src/MainPage.js b/modern/src/MainPage.js index c411ec5..a53cec1 100644 --- a/modern/src/MainPage.js +++ b/modern/src/MainPage.js @@ -9,7 +9,7 @@ import useMediaQuery from '@material-ui/core/useMediaQuery'; import AddIcon from '@material-ui/icons/Add'; import CloseIcon from '@material-ui/icons/Close'; import ArrowBackIcon from '@material-ui/icons/ArrowBack'; -import ListIcon from '@material-ui/icons/List'; +import ListIcon from '@material-ui/icons/ViewList'; import DevicesList from './DevicesList'; import Map from './map/Map'; @@ -18,7 +18,7 @@ import AccuracyMap from './map/AccuracyMap'; import GeofenceMap from './map/GeofenceMap'; import CurrentPositionsMap from './map/CurrentPositionsMap'; import CurrentLocationMap from './map/CurrentLocationMap'; -import BottomNav from "./components/BottomNav" +import BottomNav from './components/BottomNav'; import t from './common/localization'; const useStyles = makeStyles((theme) => ({ @@ -27,13 +27,13 @@ const useStyles = makeStyles((theme) => ({ }, sidebar: { display: 'flex', - flexDirection: "column", + flexDirection: 'column', position: 'absolute', left: 0, top: 0, margin: theme.spacing(1.5), width: theme.dimensions.drawerWidthDesktop, - bottom: theme.spacing(9.5), + bottom: theme.spacing(8), zIndex: 1301, transition: 'transform .5s ease', [theme.breakpoints.down('md')]: { @@ -57,12 +57,12 @@ const useStyles = makeStyles((theme) => ({ padding: theme.spacing(0, 1), '& > *': { margin: theme.spacing(0, 1), - } + }, }, deviceList: { flex: 1, overflow: 'auto', - paddingTop: theme.spacing(1.5), + padding: theme.spacing(1.5, 0), }, sidebarToggle: { position: 'absolute', @@ -71,7 +71,6 @@ const useStyles = makeStyles((theme) => ({ borderRadius: '0px', [theme.breakpoints.down('md')]: { left: theme.spacing(0), - top: theme.spacing(7), }, }, sidebarToggleBg: { @@ -113,9 +112,9 @@ const MainPage = () => { classes={{ containedPrimary: classes.sidebarToggleBg }} className={classes.sidebarToggle} onClick={handleClose} - startIcon={} disableElevation > + {!isPhone ? t('deviceTitle') : ''}
@@ -150,7 +149,7 @@ const MainPage = () => {
- +
); diff --git a/modern/src/theme/dimensions.js b/modern/src/theme/dimensions.js index fcdbaee..b6edc5e 100644 --- a/modern/src/theme/dimensions.js +++ b/modern/src/theme/dimensions.js @@ -9,4 +9,5 @@ export default { columnWidthNumber: 130, columnWidthString: 160, columnWidthBoolean: 130, + bottomNavMaxWidth: '400px', }; -- cgit v1.2.3 From cc293e067842f9d88b56f143d5921790c91c4e37 Mon Sep 17 00:00:00 2001 From: Desmond Kyeremeh Date: Tue, 20 Jul 2021 21:54:15 +0000 Subject: callapse sidebar on tablets --- modern/src/MainPage.js | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'modern/src') diff --git a/modern/src/MainPage.js b/modern/src/MainPage.js index a53cec1..6f6b05c 100644 --- a/modern/src/MainPage.js +++ b/modern/src/MainPage.js @@ -1,4 +1,4 @@ -import React, { useState } from 'react'; +import React, { useState, useEffect } from 'react'; import { useHistory } from 'react-router-dom'; import { makeStyles, Paper, Toolbar, TextField, IconButton, Button, @@ -87,16 +87,21 @@ const MainPage = () => { const history = useHistory(); const theme = useTheme(); - const [deviceName, setDeviceName] = useState(''); - const [collapsed, setCollapsed] = useState(false); - const isTablet = useMediaQuery(theme.breakpoints.down('md')); const isPhone = useMediaQuery(theme.breakpoints.down('xs')); + const [deviceName, setDeviceName] = useState(''); + const [collapsed, setCollapsed] = useState(false); + const handleClose = () => { setCollapsed(!collapsed); }; + // Collapse sidebar for tablets and phones + useEffect(() => { + setCollapsed(isTablet); + }, [isTablet]); + return (
-- cgit v1.2.3 From f22c36eb475aa515c3991caff98605d67f1f18e0 Mon Sep 17 00:00:00 2001 From: Desmond Kyeremeh Date: Tue, 20 Jul 2021 22:30:36 +0000 Subject: Use ignition icon --- modern/public/images/icon/ignition.svg | 3 +++ modern/src/DevicesList.js | 15 ++++++++++----- modern/src/MainPage.js | 1 + 3 files changed, 14 insertions(+), 5 deletions(-) create mode 100644 modern/public/images/icon/ignition.svg (limited to 'modern/src') diff --git a/modern/public/images/icon/ignition.svg b/modern/public/images/icon/ignition.svg new file mode 100644 index 0000000..d731c92 --- /dev/null +++ b/modern/public/images/icon/ignition.svg @@ -0,0 +1,3 @@ + + + diff --git a/modern/src/DevicesList.js b/modern/src/DevicesList.js index b06f7f7..3ffd421 100644 --- a/modern/src/DevicesList.js +++ b/modern/src/DevicesList.js @@ -9,10 +9,11 @@ import ListItemAvatar from '@material-ui/core/ListItemAvatar'; import ListItemSecondaryAction from '@material-ui/core/ListItemSecondaryAction'; import Grid from '@material-ui/core/Grid'; import ListItemText from '@material-ui/core/ListItemText'; +import SvgIcon from '@material-ui/core/SvgIcon'; import { FixedSizeList } from 'react-window'; import AutoSizer from 'react-virtualized-auto-sizer'; import BatteryFullIcon from '@material-ui/icons/BatteryFull'; -import VpnKeyIcon from '@material-ui/icons/VpnKey'; +import { ReactComponent as IgnitionIcon } from '../public/images/icon/ignition.svg'; import { devicesActions } from './store'; import EditCollectionView from './EditCollectionView'; @@ -48,6 +49,9 @@ const useStyles = makeStyles((theme) => ({ gray: { color: theme.palette.common.gray, }, + indicators: { + lineHeight: 1, + }, })); const getStatusColor = (status) => { @@ -79,6 +83,7 @@ const DeviceRow = ({ data, index, style }) => { const { items } = data; const item = items[index]; const position = useSelector((state) => state.positions.items[item.id]); + const showIgnition = true;// position?.attributes.hasOwnProperty('ignition') && position.attributes.ignition return (
@@ -90,12 +95,12 @@ const DeviceRow = ({ data, index, style }) => { - + {position && ( - - {position.attributes.hasOwnProperty('ignition') && ( + + {showIgnition && ( - + )} {position.attributes.hasOwnProperty('batteryLevel') && ( diff --git a/modern/src/MainPage.js b/modern/src/MainPage.js index 6f6b05c..417cdb0 100644 --- a/modern/src/MainPage.js +++ b/modern/src/MainPage.js @@ -69,6 +69,7 @@ const useStyles = makeStyles((theme) => ({ left: theme.spacing(1.5), top: theme.spacing(3), borderRadius: '0px', + minWidth: 0, [theme.breakpoints.down('md')]: { left: theme.spacing(0), }, -- cgit v1.2.3 From b0c4891c4b2687e7a08f05e779c84847a0f4f46c Mon Sep 17 00:00:00 2001 From: Desmond Kyeremeh Date: Tue, 20 Jul 2021 22:44:27 +0000 Subject: showignition logic --- modern/src/DevicesList.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'modern/src') diff --git a/modern/src/DevicesList.js b/modern/src/DevicesList.js index 3ffd421..aa85630 100644 --- a/modern/src/DevicesList.js +++ b/modern/src/DevicesList.js @@ -83,7 +83,7 @@ const DeviceRow = ({ data, index, style }) => { const { items } = data; const item = items[index]; const position = useSelector((state) => state.positions.items[item.id]); - const showIgnition = true;// position?.attributes.hasOwnProperty('ignition') && position.attributes.ignition + const showIgnition = position?.attributes.hasOwnProperty('ignition') && position.attributes.ignition return (
-- cgit v1.2.3