diff options
author | Anton Tananaev <anton@traccar.org> | 2022-05-01 20:29:10 -0700 |
---|---|---|
committer | Anton Tananaev <anton@traccar.org> | 2022-05-01 20:29:10 -0700 |
commit | d3bd766cbc81f51c9b13b82d0ca92ae819561ea8 (patch) | |
tree | 7f76d29ead2628b0d3c67ae8e0715b9666b30136 | |
parent | d01f563d3909582acbcfd4fe20fa271ee224aba3 (diff) | |
download | trackermap-web-d3bd766cbc81f51c9b13b82d0ca92ae819561ea8.tar.gz trackermap-web-d3bd766cbc81f51c9b13b82d0ca92ae819561ea8.tar.bz2 trackermap-web-d3bd766cbc81f51c9b13b82d0ca92ae819561ea8.zip |
Global mobile bottom menu
-rw-r--r-- | modern/src/App.js | 97 | ||||
-rw-r--r-- | modern/src/MainPage.js | 19 | ||||
-rw-r--r-- | modern/src/StartPage.js | 2 | ||||
-rw-r--r-- | modern/src/components/BottomMenu.js | 51 |
4 files changed, 106 insertions, 63 deletions
diff --git a/modern/src/App.js b/modern/src/App.js index 57e44621..a4b66ea1 100644 --- a/modern/src/App.js +++ b/modern/src/App.js @@ -3,7 +3,7 @@ import { ThemeProvider } from '@material-ui/core/styles'; import { Switch, Route, useHistory } from 'react-router-dom'; import CssBaseline from '@material-ui/core/CssBaseline'; import { useDispatch, useSelector } from 'react-redux'; -import { LinearProgress } from '@material-ui/core'; +import { makeStyles, LinearProgress, useMediaQuery } from '@material-ui/core'; import MainPage from './MainPage'; import RouteReportPage from './reports/RouteReportPage'; import ServerPage from './admin/ServerPage'; @@ -48,10 +48,28 @@ import { useEffectAsync } from './reactHelper'; import { devicesActions } from './store'; import EventPage from './EventPage'; import PreferencesPage from './settings/PreferencesPage'; +import BottomMenu from './components/BottomMenu'; + +const useStyles = makeStyles((theme) => ({ + root: { + display: 'flex', + flexDirection: 'column', + height: '100%', + }, + page: { + flexGrow: 1, + }, + menu: { + zIndex: 1, + }, +})); const App = () => { const history = useHistory(); const dispatch = useDispatch(); + const classes = useStyles(); + + const desktop = useMediaQuery(theme.breakpoints.up('lg')); const initialized = useSelector((state) => !!state.session.server && !!state.session.user); const [redirectsHandled, setRedirectsHandled] = useState(false); @@ -93,40 +111,49 @@ const App = () => { <Route exact path="/reset-password" component={ResetPasswordForm} /> <Route> {!initialized ? (<LinearProgress />) : ( - <Switch> - <Route exact path="/" component={MainPage} /> - <Route exact path="/replay" component={ReplayPage} /> - <Route exact path="/position/:id?" component={PositionPage} /> - <Route exact path="/event/:id?" component={EventPage} /> - <Route exact path="/user/:id?" component={UserPage} /> - <Route exact path="/device/:id?" component={DevicePage} /> - <Route exact path="/geofence/:id?" component={GeofencePage} /> - <Route exact path="/geofences" component={GeofencesPage} /> - <Route exact path="/settings/preferences" component={PreferencesPage} /> - <Route exact path="/settings/notifications" component={NotificationsPage} /> - <Route exact path="/settings/notification/:id?" component={NotificationPage} /> - <Route exact path="/settings/groups" component={GroupsPage} /> - <Route exact path="/settings/group/:id?" component={GroupPage} /> - <Route exact path="/settings/drivers" component={DriversPage} /> - <Route exact path="/settings/driver/:id?" component={DriverPage} /> - <Route exact path="/settings/calendars" component={CalendarsPage} /> - <Route exact path="/settings/calendar/:id?" component={CalendarPage} /> - <Route exact path="/settings/attributes" component={ComputedAttributesPage} /> - <Route exact path="/settings/attribute/:id?" component={ComputedAttributePage} /> - <Route exact path="/settings/maintenances" component={MaintenancesPage} /> - <Route exact path="/settings/maintenance/:id?" component={MaintenancePage} /> - <Route exact path="/settings/commands" component={CommandsPage} /> - <Route exact path="/settings/command/:id?" component={CommandPage} /> - <Route exact path="/admin/server" component={ServerPage} /> - <Route exact path="/admin/users" component={UsersPage} /> - <Route exact path="/admin/statistics" component={StatisticsPage} /> - <Route exact path="/reports/route" component={RouteReportPage} /> - <Route exact path="/reports/event" component={EventReportPage} /> - <Route exact path="/reports/trip" component={TripReportPage} /> - <Route exact path="/reports/stop" component={StopReportPage} /> - <Route exact path="/reports/summary" component={SummaryReportPage} /> - <Route exact path="/reports/chart" component={ChartReportPage} /> - </Switch> + <div className={classes.root}> + <div className={classes.page}> + <Switch> + <Route exact path="/" component={MainPage} /> + <Route exact path="/replay" component={ReplayPage} /> + <Route exact path="/position/:id?" component={PositionPage} /> + <Route exact path="/event/:id?" component={EventPage} /> + <Route exact path="/user/:id?" component={UserPage} /> + <Route exact path="/device/:id?" component={DevicePage} /> + <Route exact path="/geofence/:id?" component={GeofencePage} /> + <Route exact path="/geofences" component={GeofencesPage} /> + <Route exact path="/settings/preferences" component={PreferencesPage} /> + <Route exact path="/settings/notifications" component={NotificationsPage} /> + <Route exact path="/settings/notification/:id?" component={NotificationPage} /> + <Route exact path="/settings/groups" component={GroupsPage} /> + <Route exact path="/settings/group/:id?" component={GroupPage} /> + <Route exact path="/settings/drivers" component={DriversPage} /> + <Route exact path="/settings/driver/:id?" component={DriverPage} /> + <Route exact path="/settings/calendars" component={CalendarsPage} /> + <Route exact path="/settings/calendar/:id?" component={CalendarPage} /> + <Route exact path="/settings/attributes" component={ComputedAttributesPage} /> + <Route exact path="/settings/attribute/:id?" component={ComputedAttributePage} /> + <Route exact path="/settings/maintenances" component={MaintenancesPage} /> + <Route exact path="/settings/maintenance/:id?" component={MaintenancePage} /> + <Route exact path="/settings/commands" component={CommandsPage} /> + <Route exact path="/settings/command/:id?" component={CommandPage} /> + <Route exact path="/admin/server" component={ServerPage} /> + <Route exact path="/admin/users" component={UsersPage} /> + <Route exact path="/admin/statistics" component={StatisticsPage} /> + <Route exact path="/reports/route" component={RouteReportPage} /> + <Route exact path="/reports/event" component={EventReportPage} /> + <Route exact path="/reports/trip" component={TripReportPage} /> + <Route exact path="/reports/stop" component={StopReportPage} /> + <Route exact path="/reports/summary" component={SummaryReportPage} /> + <Route exact path="/reports/chart" component={ChartReportPage} /> + </Switch> + </div> + {!desktop && ( + <div className={classes.menu}> + <BottomMenu /> + </div> + )} + </div> )} </Route> </Switch> diff --git a/modern/src/MainPage.js b/modern/src/MainPage.js index 0f6db95a..75af9666 100644 --- a/modern/src/MainPage.js +++ b/modern/src/MainPage.js @@ -28,7 +28,7 @@ import { devicesActions } from './store'; const useStyles = makeStyles((theme) => ({ root: { - height: '100vh', + height: '100%', }, sidebar: { display: 'flex', @@ -53,9 +53,6 @@ const useStyles = makeStyles((theme) => ({ transform: 'translateX(-100vw)', }, }, - paper: { - zIndex: 1, - }, toolbar: { display: 'flex', padding: theme.spacing(0, 1), @@ -101,6 +98,12 @@ const useStyles = makeStyles((theme) => ({ backgroundColor: 'white', }, }, + bottomMenu: { + position: 'fixed', + left: theme.spacing(1.5), + bottom: theme.spacing(1.5), + width: theme.dimensions.drawerWidthDesktop, + }, })); const MainPage = () => { @@ -147,7 +150,7 @@ const MainPage = () => { <div className={classes.sidebarToggleText}>{t('deviceTitle')}</div> </Button> <Paper square elevation={3} className={`${classes.sidebar} ${collapsed && classes.sidebarCollapsed}`}> - <Paper className={classes.paper} square elevation={3}> + <Paper square elevation={3}> <Toolbar className={classes.toolbar} disableGutters> {isTablet && ( <IconButton onClick={handleClose}> @@ -178,7 +181,11 @@ const MainPage = () => { <DevicesList filter={searchKeyword} /> </div> </Paper> - <BottomMenu /> + {!isPhone && !isTablet && ( + <div className={classes.bottomMenu}> + <BottomMenu /> + </div> + )} {selectedDeviceId && ( <div className={classes.statusCard}> <StatusCard diff --git a/modern/src/StartPage.js b/modern/src/StartPage.js index fcfaccca..1e672c2b 100644 --- a/modern/src/StartPage.js +++ b/modern/src/StartPage.js @@ -59,7 +59,7 @@ const StartPage = ({ children }) => { <svg height="64" width="240"> <use xlinkHref="/logo.svg#img" /> </svg> - )} + )} </div> <Paper className={classes.paper}> <form className={classes.form}> diff --git a/modern/src/components/BottomMenu.js b/modern/src/components/BottomMenu.js index c43cfb96..672c969a 100644 --- a/modern/src/components/BottomMenu.js +++ b/modern/src/components/BottomMenu.js @@ -1,8 +1,8 @@ import React, { useState } from 'react'; import { useDispatch, useSelector } from 'react-redux'; -import { useHistory } from 'react-router-dom'; +import { useHistory, useLocation } from 'react-router-dom'; import { - makeStyles, Paper, BottomNavigation, BottomNavigationAction, Menu, MenuItem, Typography, + Paper, BottomNavigation, BottomNavigationAction, Menu, MenuItem, Typography, } from '@material-ui/core'; import DescriptionIcon from '@material-ui/icons/Description'; @@ -13,23 +13,9 @@ import PersonIcon from '@material-ui/icons/Person'; import { sessionActions } from '../store'; import { useTranslation } from '../LocalizationProvider'; -const useStyles = makeStyles((theme) => ({ - container: { - bottom: theme.spacing(0), - left: '0px', - width: '100%', - position: 'fixed', - [theme.breakpoints.up('lg')]: { - left: theme.spacing(1.5), - bottom: theme.spacing(1.5), - width: theme.dimensions.drawerWidthDesktop, - }, - }, -})); - const BottomMenu = () => { - const classes = useStyles(); const history = useHistory(); + const location = useLocation(); const dispatch = useDispatch(); const t = useTranslation(); @@ -37,8 +23,25 @@ const BottomMenu = () => { const [anchorEl, setAnchorEl] = useState(null); - const handleSelection = async (event, value) => { + const currentSelection = () => { + if (location.pathname.startsWith('/user')) { + return 3; + } else if (location.pathname.startsWith('/settings')) { + return 2; + } else if (location.pathname.startsWith('/reports')) { + return 1; + } else if (location.pathname === '/') { + return 0; + } else { + return null; + } + } + + const handleSelection = (event, value) => { switch (value) { + case 0: + history.push('/'); + break; case 1: history.push('/reports/route'); break; @@ -53,22 +56,28 @@ const BottomMenu = () => { } }; + const handleAccount = () => { + setAnchorEl(null); + history.push(`/user/${userId}`); + }; + const handleLogout = async () => { + setAnchorEl(null); await fetch('/api/session', { method: 'DELETE' }); history.push('/login'); dispatch(sessionActions.updateUser(null)); }; return ( - <Paper square elevation={3} className={classes.container}> - <BottomNavigation value={0} onChange={handleSelection} showLabels> + <Paper square elevation={3}> + <BottomNavigation value={currentSelection()} onChange={handleSelection} showLabels> <BottomNavigationAction label={t('mapTitle')} icon={<MapIcon />} /> <BottomNavigationAction label={t('reportTitle')} icon={<DescriptionIcon />} /> <BottomNavigationAction label={t('settingsTitle')} icon={<SettingsIcon />} /> <BottomNavigationAction label={t('settingsUser')} icon={<PersonIcon />} /> </BottomNavigation> <Menu anchorEl={anchorEl} keepMounted open={Boolean(anchorEl)} onClose={() => setAnchorEl(null)}> - <MenuItem onClick={() => history.push(`/user/${userId}`)}> + <MenuItem onClick={handleAccount}> <Typography color="textPrimary">{t('settingsUser')}</Typography> </MenuItem> <MenuItem onClick={handleLogout}> |