From 2a1bc9710eb1005a8937dc7ec63c25975bb28f41 Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Fri, 27 Jan 2023 14:24:09 -0800 Subject: Scheduled reports page --- modern/src/CachingController.js | 13 +++- modern/src/Navigation.js | 4 +- modern/src/reports/ScheduledPage.js | 91 ++++++++++++++++++++++++++++ modern/src/reports/components/ReportsMenu.js | 30 +++++---- modern/src/resources/l10n/en.json | 1 + modern/src/store/calendars.js | 16 +++++ modern/src/store/index.js | 3 + 7 files changed, 143 insertions(+), 15 deletions(-) create mode 100644 modern/src/reports/ScheduledPage.js create mode 100644 modern/src/store/calendars.js (limited to 'modern') diff --git a/modern/src/CachingController.js b/modern/src/CachingController.js index 1c8fb43a..55a4e020 100644 --- a/modern/src/CachingController.js +++ b/modern/src/CachingController.js @@ -1,7 +1,7 @@ import { useDispatch, useSelector, connect } from 'react-redux'; import { - geofencesActions, groupsActions, driversActions, maintenancesActions, + geofencesActions, groupsActions, driversActions, maintenancesActions, calendarsActions, } from './store'; import { useEffectAsync } from './reactHelper'; @@ -53,6 +53,17 @@ const CachingController = () => { } }, [authenticated]); + useEffectAsync(async () => { + if (authenticated) { + const response = await fetch('/api/calendars'); + if (response.ok) { + dispatch(calendarsActions.update(await response.json())); + } else { + throw Error(await response.text()); + } + } + }, [authenticated]); + return null; }; diff --git a/modern/src/Navigation.js b/modern/src/Navigation.js index d08fc12b..1e3a37b2 100644 --- a/modern/src/Navigation.js +++ b/modern/src/Navigation.js @@ -48,6 +48,7 @@ import CommandSendPage from './settings/CommandSendPage'; import App from './App'; import ChangeServerPage from './other/ChangeServerPage'; import DevicesPage from './settings/DevicesPage'; +import ScheduledPage from './reports/ScheduledPage'; const Navigation = () => { const navigate = useNavigate(); @@ -141,10 +142,11 @@ const Navigation = () => { } /> } /> } /> - } /> } /> } /> } /> + } /> + } /> diff --git a/modern/src/reports/ScheduledPage.js b/modern/src/reports/ScheduledPage.js new file mode 100644 index 00000000..831588b0 --- /dev/null +++ b/modern/src/reports/ScheduledPage.js @@ -0,0 +1,91 @@ +import React, { useState } from 'react'; +import { useSelector } from 'react-redux'; +import { + Table, TableRow, TableCell, TableHead, TableBody, IconButton, +} from '@mui/material'; +import makeStyles from '@mui/styles/makeStyles'; +import DeleteIcon from '@mui/icons-material/Delete'; +import { useEffectAsync } from '../reactHelper'; +import { useTranslation } from '../common/components/LocalizationProvider'; +import PageLayout from '../common/components/PageLayout'; +import ReportsMenu from './components/ReportsMenu'; +import TableShimmer from '../common/components/TableShimmer'; + +const useStyles = makeStyles((theme) => ({ + columnAction: { + width: '1%', + paddingRight: theme.spacing(1), + }, +})); + +const ScheduledPage = () => { + const classes = useStyles(); + const t = useTranslation(); + + const calendars = useSelector((state) => state.calendars.items); + + const [items, setItems] = useState([]); + const [loading, setLoading] = useState(false); + + useEffectAsync(async () => { + setLoading(true); + try { + const response = await fetch('/api/reports'); + if (response.ok) { + setItems(await response.json()); + } else { + throw Error(await response.text()); + } + } finally { + setLoading(false); + } + }, []); + + const formatType = (type) => { + switch (type) { + case 'events': + return t('reportEvents'); + case 'route': + return t('reportRoute'); + case 'summary': + return t('reportSummary'); + case 'trips': + return t('reportTrips'); + case 'stops': + return t('reportStops'); + default: + return type; + } + }; + + return ( + } breadcrumbs={['settingsTitle', 'sharedDrivers']}> + + + + {t('sharedType')} + {t('sharedDescription')} + {t('sharedCalendar')} + + + + + {!loading ? items.map((item) => ( + + {formatType(item.type)} + {item.description} + {calendars[item.calendarId].name} + + {}}> + + + + + )) : ()} + +
+
+ ); +}; + +export default ScheduledPage; diff --git a/modern/src/reports/components/ReportsMenu.js b/modern/src/reports/components/ReportsMenu.js index 8fa7df2d..3616f828 100644 --- a/modern/src/reports/components/ReportsMenu.js +++ b/modern/src/reports/components/ReportsMenu.js @@ -10,6 +10,7 @@ import FormatListBulletedIcon from '@mui/icons-material/FormatListBulleted'; import TrendingUpIcon from '@mui/icons-material/TrendingUp'; import BarChartIcon from '@mui/icons-material/BarChart'; import RouteIcon from '@mui/icons-material/Route'; +import EventRepeatIcon from '@mui/icons-material/EventRepeat'; import { Link, useLocation } from 'react-router-dom'; import { useTranslation } from '../../common/components/LocalizationProvider'; import { useAdministrator } from '../../common/util/permissions'; @@ -74,19 +75,22 @@ const ReportsMenu = () => { icon={} /> - {admin && ( - <> - - - } - selected={location.pathname === '/reports/statistics'} - /> - - - )} + + + } + /> + {admin && ( + } + selected={location.pathname === '/reports/statistics'} + /> + )} + ); }; diff --git a/modern/src/resources/l10n/en.json b/modern/src/resources/l10n/en.json index f68f0083..d93ad5bf 100644 --- a/modern/src/resources/l10n/en.json +++ b/modern/src/resources/l10n/en.json @@ -220,6 +220,7 @@ "settingsAppVersion": "App Version", "settingsConnection": "Connection", "reportTitle": "Reports", + "reportScheduled": "Scheduled Reports", "reportDevice": "Device", "reportGroup": "Group", "reportFrom": "From", diff --git a/modern/src/store/calendars.js b/modern/src/store/calendars.js new file mode 100644 index 00000000..924288e6 --- /dev/null +++ b/modern/src/store/calendars.js @@ -0,0 +1,16 @@ +import { createSlice } from '@reduxjs/toolkit'; + +const { reducer, actions } = createSlice({ + name: 'calendars', + initialState: { + items: {}, + }, + reducers: { + update(state, action) { + action.payload.forEach((item) => state.items[item.id] = item); + }, + }, +}); + +export { actions as calendarsActions }; +export { reducer as calendarsReducer }; diff --git a/modern/src/store/index.js b/modern/src/store/index.js index 0cc32d38..ea685ff3 100644 --- a/modern/src/store/index.js +++ b/modern/src/store/index.js @@ -8,6 +8,7 @@ import { geofencesReducer as geofences } from './geofences'; import { groupsReducer as groups } from './groups'; import { driversReducer as drivers } from './drivers'; import { maintenancesReducer as maintenances } from './maintenances'; +import { calendarsReducer as calendars } from './calendars'; import { reportsReducer as reports } from './reports'; import throttleMiddleware from './throttleMiddleware'; @@ -20,6 +21,7 @@ const reducer = combineReducers({ groups, drivers, maintenances, + calendars, reports, }); @@ -31,6 +33,7 @@ export { geofencesActions } from './geofences'; export { groupsActions } from './groups'; export { driversActions } from './drivers'; export { maintenancesActions } from './maintenances'; +export { calendarsActions } from './calendars'; export { reportsActions } from './reports'; export default configureStore({ -- cgit v1.2.3