diff options
-rw-r--r-- | modern/.eslintrc.js | 6 | ||||
-rw-r--r-- | modern/src/other/ReplayPage.js | 2 | ||||
-rw-r--r-- | modern/src/reports/ChartReportPage.js | 6 | ||||
-rw-r--r-- | modern/src/reports/EventReportPage.js | 6 | ||||
-rw-r--r-- | modern/src/reports/StatisticsPage.js | 2 | ||||
-rw-r--r-- | modern/src/reports/StopReportPage.js | 6 | ||||
-rw-r--r-- | modern/src/reports/SummaryReportPage.js | 18 | ||||
-rw-r--r-- | modern/src/reports/TripReportPage.js | 6 | ||||
-rw-r--r-- | modern/src/reports/components/ReportFilter.js | 53 |
9 files changed, 68 insertions, 37 deletions
diff --git a/modern/.eslintrc.js b/modern/.eslintrc.js index 6cef63d8..df0dcd15 100644 --- a/modern/.eslintrc.js +++ b/modern/.eslintrc.js @@ -16,6 +16,12 @@ module.exports = { 'no-nested-ternary': [0], 'operator-linebreak': [0], 'import/no-unresolved': [0], + 'object-curly-newline': [1, { + ObjectExpression: { minProperties: 8, multiline: true, consistent: true }, + ObjectPattern: { minProperties: 8, multiline: true, consistent: true }, + ImportDeclaration: { minProperties: 4, multiline: true, consistent: true }, + ExportDeclaration: { minProperties: 4, multiline: true, consistent: true }, + }], 'react/jsx-filename-extension': [1, { extensions: ['.js'] }], 'react/function-component-definition': [1, { namedComponents: 'arrow-function', unnamedComponents: 'arrow-function' }], 'react/prop-types': [0], diff --git a/modern/src/other/ReplayPage.js b/modern/src/other/ReplayPage.js index 4893dda9..fb6e00a5 100644 --- a/modern/src/other/ReplayPage.js +++ b/modern/src/other/ReplayPage.js @@ -123,7 +123,7 @@ const ReplayPage = () => { } }, [index, positions]); - const handleSubmit = useCatch(async (deviceId, from, to, _, headers) => { + const handleSubmit = useCatch(async ({ deviceId, from, to, headers }) => { setSelectedDeviceId(deviceId); const query = new URLSearchParams({ deviceId, from, to }); const response = await fetch(`/api/positions?${query.toString()}`, { headers }); diff --git a/modern/src/reports/ChartReportPage.js b/modern/src/reports/ChartReportPage.js index ce50819b..ceb2361b 100644 --- a/modern/src/reports/ChartReportPage.js +++ b/modern/src/reports/ChartReportPage.js @@ -34,10 +34,8 @@ const ChartReportPage = () => { const maxValue = Math.max(...values); const valueRange = maxValue - minValue; - const handleSubmit = useCatch(async (deviceId, from, to, mail, headers) => { - const query = new URLSearchParams({ - deviceId, from, to, mail, - }); + const handleSubmit = useCatch(async ({ deviceId, from, to, mail, headers }) => { + 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(); diff --git a/modern/src/reports/EventReportPage.js b/modern/src/reports/EventReportPage.js index 447adaef..61b55fcc 100644 --- a/modern/src/reports/EventReportPage.js +++ b/modern/src/reports/EventReportPage.js @@ -54,10 +54,8 @@ const EventReportPage = () => { const [eventTypes, setEventTypes] = useState(['allEvents']); const [items, setItems] = useState([]); - const handleSubmit = useCatch(async (deviceId, from, to, mail, headers) => { - const query = new URLSearchParams({ - deviceId, from, to, mail, - }); + const handleSubmit = useCatch(async ({ deviceId, from, to, mail, headers }) => { + 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) { diff --git a/modern/src/reports/StatisticsPage.js b/modern/src/reports/StatisticsPage.js index 5da5b44e..41b8925d 100644 --- a/modern/src/reports/StatisticsPage.js +++ b/modern/src/reports/StatisticsPage.js @@ -33,7 +33,7 @@ const StatisticsPage = () => { const [columns, setColumns] = usePersistedState('statisticsColumns', ['captureTime', 'activeUsers', 'activeDevices', 'messagesStored']); const [items, setItems] = useState([]); - const handleSubmit = useCatch(async (_, from, to) => { + const handleSubmit = useCatch(async ({ from, to }) => { const query = new URLSearchParams({ from, to }); const response = await fetch(`/api/statistics?${query.toString()}`, { Accept: 'application/json' }); if (response.ok) { diff --git a/modern/src/reports/StopReportPage.js b/modern/src/reports/StopReportPage.js index d44e2046..00c8a41b 100644 --- a/modern/src/reports/StopReportPage.js +++ b/modern/src/reports/StopReportPage.js @@ -43,10 +43,8 @@ const StopReportPage = () => { const [items, setItems] = useState([]); const [selectedItem, setSelectedItem] = useState(null); - const handleSubmit = useCatch(async (deviceId, from, to, mail, headers) => { - const query = new URLSearchParams({ - deviceId, from, to, mail, - }); + const handleSubmit = useCatch(async ({ deviceId, from, to, mail, headers }) => { + 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'); diff --git a/modern/src/reports/SummaryReportPage.js b/modern/src/reports/SummaryReportPage.js index a66d1c61..ca18b828 100644 --- a/modern/src/reports/SummaryReportPage.js +++ b/modern/src/reports/SummaryReportPage.js @@ -1,4 +1,5 @@ import React, { useState } from 'react'; +import { useSelector } from 'react-redux'; import { FormControl, InputLabel, Select, MenuItem, Table, TableHead, TableRow, TableBody, TableCell, } from '@mui/material'; @@ -16,6 +17,7 @@ import { useCatch } from '../reactHelper'; import useReportStyles from './common/useReportStyles'; const columnsArray = [ + ['deviceId', 'sharedDevice'], ['startTime', 'reportStartDate'], ['distance', 'sharedDistance'], ['startOdometer', 'reportStartOdometer'], @@ -31,18 +33,20 @@ const SummaryReportPage = () => { const classes = useReportStyles(); const t = useTranslation(); + const devices = useSelector((state) => state.devices.items); + const distanceUnit = useAttributePreference('distanceUnit'); const speedUnit = useAttributePreference('speedUnit'); const volumeUnit = useAttributePreference('volumeUnit'); - const [columns, setColumns] = usePersistedState('summaryColumns', ['startTime', 'startOdometer', 'distance', 'averageSpeed']); + const [columns, setColumns] = usePersistedState('summaryColumns', ['deviceId', 'startTime', 'distance', 'averageSpeed']); const [daily, setDaily] = useState(false); const [items, setItems] = useState([]); - const handleSubmit = useCatch(async (deviceId, from, to, mail, headers) => { - const query = new URLSearchParams({ - deviceId, from, to, daily, mail, - }); + const handleSubmit = useCatch(async ({ deviceIds, groupIds, from, to, mail, headers }) => { + const query = new URLSearchParams({ from, to, daily, mail }); + deviceIds.forEach((deviceId) => query.append('deviceId', deviceId)); + groupIds.forEach((groupId) => query.append('groupId', groupId)); const response = await fetch(`/api/reports/summary?${query.toString()}`, { headers }); if (response.ok) { const contentType = response.headers.get('content-type'); @@ -60,6 +64,8 @@ const SummaryReportPage = () => { const formatValue = (item, key) => { switch (key) { + case 'deviceId': + return devices[item[key]].name; case 'startTime': return item[key] ? formatDate(item[key], 'YYYY-MM-DD') : null; case 'startOdometer': @@ -81,7 +87,7 @@ const SummaryReportPage = () => { return ( <PageLayout menu={<ReportsMenu />} breadcrumbs={['reportTitle', 'reportSummary']}> <div className={classes.header}> - <ReportFilter handleSubmit={handleSubmit}> + <ReportFilter handleSubmit={handleSubmit} multiDevice> <div className={classes.filterItem}> <FormControl fullWidth> <InputLabel>{t('sharedType')}</InputLabel> diff --git a/modern/src/reports/TripReportPage.js b/modern/src/reports/TripReportPage.js index 47f91ee3..28ec8cc9 100644 --- a/modern/src/reports/TripReportPage.js +++ b/modern/src/reports/TripReportPage.js @@ -68,10 +68,8 @@ const TripReportPage = () => { } }, [selectedItem]); - const handleSubmit = useCatch(async (deviceId, from, to, mail, headers) => { - const query = new URLSearchParams({ - deviceId, from, to, mail, - }); + const handleSubmit = useCatch(async ({ deviceId, from, to, mail, headers }) => { + 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'); diff --git a/modern/src/reports/components/ReportFilter.js b/modern/src/reports/components/ReportFilter.js index 29d53dd0..100dab90 100644 --- a/modern/src/reports/components/ReportFilter.js +++ b/modern/src/reports/components/ReportFilter.js @@ -7,20 +7,23 @@ import moment from 'moment'; import { useTranslation } from '../../common/components/LocalizationProvider'; import useReportStyles from '../common/useReportStyles'; -const ReportFilter = ({ - children, handleSubmit, showOnly, ignoreDevice, -}) => { +const ReportFilter = ({ children, handleSubmit, showOnly, ignoreDevice, multiDevice }) => { const classes = useReportStyles(); const t = useTranslation(); const devices = useSelector((state) => state.devices.items); + const groups = useSelector((state) => state.groups.items); const selectedDeviceId = useSelector((state) => state.devices.selectedId); const [deviceId, setDeviceId] = useState(selectedDeviceId); + const [deviceIds, setDeviceIds] = useState(selectedDeviceId ? [selectedDeviceId] : []); + const [groupIds, setGroupIds] = useState([]); const [period, setPeriod] = useState('today'); const [from, setFrom] = useState(moment().subtract(1, 'hour')); const [to, setTo] = useState(moment()); + const disabled = !ignoreDevice && !deviceId && !deviceIds.length && !groupIds.length; + const handleClick = (mail, json) => { let selectedFrom; let selectedTo; @@ -56,13 +59,15 @@ const ReportFilter = ({ } const accept = json ? 'application/json' : 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'; - handleSubmit( + handleSubmit({ deviceId, - selectedFrom.toISOString(), - selectedTo.toISOString(), + deviceIds, + groupIds, + from: selectedFrom.toISOString(), + to: selectedTo.toISOString(), mail, - { Accept: accept }, - ); + headers: { Accept: accept }, + }); }; return ( @@ -70,8 +75,13 @@ const ReportFilter = ({ {!ignoreDevice && ( <div className={classes.filterItem}> <FormControl fullWidth> - <InputLabel>{t('reportDevice')}</InputLabel> - <Select label={t('reportDevice')} value={deviceId || ''} onChange={(e) => setDeviceId(e.target.value)}> + <InputLabel>{t(multiDevice ? 'deviceTitle' : 'reportDevice')}</InputLabel> + <Select + label={t(multiDevice ? 'deviceTitle' : 'reportDevice')} + value={multiDevice ? deviceIds : deviceId || ''} + onChange={(e) => (multiDevice ? setDeviceIds(e.target.value) : setDeviceId(e.target.value))} + multiple={multiDevice} + > {Object.values(devices).map((device) => ( <MenuItem key={device.id} value={device.id}>{device.name}</MenuItem> ))} @@ -79,6 +89,23 @@ const ReportFilter = ({ </FormControl> </div> )} + {multiDevice && ( + <div className={classes.filterItem}> + <FormControl fullWidth> + <InputLabel>{t('settingsGroups')}</InputLabel> + <Select + label={t('settingsGroups')} + value={groupIds} + onChange={(e) => setGroupIds(e.target.value)} + multiple + > + {Object.values(groups).map((group) => ( + <MenuItem key={group.id} value={group.id}>{group.name}</MenuItem> + ))} + </Select> + </FormControl> + </div> + )} <div className={classes.filterItem}> <FormControl fullWidth> <InputLabel>{t('reportPeriod')}</InputLabel> @@ -122,7 +149,7 @@ const ReportFilter = ({ variant="outlined" color="secondary" className={classes.filterButton} - disabled={!ignoreDevice && !deviceId} + disabled={disabled} > {t('reportShow')} </Button> @@ -132,7 +159,7 @@ const ReportFilter = ({ variant="outlined" color="secondary" className={classes.filterButton} - disabled={!ignoreDevice && !deviceId} + disabled={disabled} > {t('reportExport')} </Button> @@ -143,7 +170,7 @@ const ReportFilter = ({ variant="outlined" color="secondary" className={classes.filterButton} - disabled={!ignoreDevice && !deviceId} + disabled={disabled} > <Typography variant="button" noWrap>{t('reportEmail')}</Typography> </Button> |