aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnton Tananaev <anton@traccar.org>2022-08-02 07:50:08 -0700
committerAnton Tananaev <anton@traccar.org>2022-08-02 07:50:08 -0700
commit0d9573c2145a6e2df3d43ef4e192529654bc65de (patch)
tree55394bbf7fdad784331cc7781454e791ccf8172b
parentf57d9020d5031744e3e0e19ac8178cc8f7010f03 (diff)
downloadtrackermap-web-0d9573c2145a6e2df3d43ef4e192529654bc65de.tar.gz
trackermap-web-0d9573c2145a6e2df3d43ef4e192529654bc65de.tar.bz2
trackermap-web-0d9573c2145a6e2df3d43ef4e192529654bc65de.zip
Multi device route (fix #998)
-rw-r--r--modern/src/reports/RouteReportPage.js16
-rw-r--r--modern/src/reports/SummaryReportPage.js7
-rw-r--r--modern/src/reports/components/ReportFilter.js4
3 files changed, 18 insertions, 9 deletions
diff --git a/modern/src/reports/RouteReportPage.js b/modern/src/reports/RouteReportPage.js
index fb05f1b1..d60b241c 100644
--- a/modern/src/reports/RouteReportPage.js
+++ b/modern/src/reports/RouteReportPage.js
@@ -1,4 +1,5 @@
import React, { useState } from 'react';
+import { useSelector } from 'react-redux';
import {
IconButton, Table, TableBody, TableCell, TableHead, TableRow,
} from '@mui/material';
@@ -26,13 +27,16 @@ const RouteReportPage = () => {
const positionAttributes = usePositionAttributes(t);
+ const devices = useSelector((state) => state.devices.items);
+
const [columns, setColumns] = usePersistedState('routeColumns', ['fixTime', 'latitude', 'longitude', 'speed', 'address']);
const [items, setItems] = useState([]);
const [loading, setLoading] = useState(false);
const [selectedItem, setSelectedItem] = useState(null);
- const handleSubmit = useCatch(async ({ deviceId, from, to, type }) => {
- const query = new URLSearchParams({ deviceId, from, to });
+ const handleSubmit = useCatch(async ({ deviceIds, from, to, type }) => {
+ const query = new URLSearchParams({ from, to });
+ deviceIds.forEach((deviceId) => query.append('deviceId', deviceId));
if (type === 'export') {
window.location.assign(`/api/reports/route/xlsx?${query.toString()}`);
} else if (type === 'mail') {
@@ -63,7 +67,9 @@ const RouteReportPage = () => {
{selectedItem && (
<div className={classes.containerMap}>
<MapView>
- <MapRoutePath positions={items} />
+ {[...new Set(items.map((it) => it.deviceId))].map((deviceId) => (
+ <MapRoutePath key={deviceId} positions={items.filter((position) => position.deviceId === deviceId)} />
+ ))}
<MapPositions positions={[selectedItem]} />
</MapView>
<MapCamera positions={items} />
@@ -71,7 +77,7 @@ const RouteReportPage = () => {
)}
<div className={classes.containerMain}>
<div className={classes.header}>
- <ReportFilter handleSubmit={handleSubmit}>
+ <ReportFilter handleSubmit={handleSubmit} multiDevice>
<ColumnSelect
columns={columns}
setColumns={setColumns}
@@ -83,6 +89,7 @@ const RouteReportPage = () => {
<TableHead>
<TableRow>
<TableCell className={classes.columnAction} />
+ <TableCell>{t('sharedDevice')}</TableCell>
{columns.map((key) => (<TableCell key={key}>{positionAttributes[key].name}</TableCell>))}
</TableRow>
</TableHead>
@@ -100,6 +107,7 @@ const RouteReportPage = () => {
</IconButton>
)}
</TableCell>
+ <TableCell>{devices[item.deviceId].name}</TableCell>
{columns.map((key) => (
<TableCell key={key}>
<PositionValue
diff --git a/modern/src/reports/SummaryReportPage.js b/modern/src/reports/SummaryReportPage.js
index b8ec9283..77c42cba 100644
--- a/modern/src/reports/SummaryReportPage.js
+++ b/modern/src/reports/SummaryReportPage.js
@@ -18,7 +18,6 @@ import useReportStyles from './common/useReportStyles';
import TableShimmer from '../common/components/TableShimmer';
const columnsArray = [
- ['deviceId', 'sharedDevice'],
['startTime', 'reportStartDate'],
['distance', 'sharedDistance'],
['startOdometer', 'reportStartOdometer'],
@@ -40,7 +39,7 @@ const SummaryReportPage = () => {
const speedUnit = useAttributePreference('speedUnit');
const volumeUnit = useAttributePreference('volumeUnit');
- const [columns, setColumns] = usePersistedState('summaryColumns', ['deviceId', 'startTime', 'distance', 'averageSpeed']);
+ const [columns, setColumns] = usePersistedState('summaryColumns', ['startTime', 'distance', 'averageSpeed']);
const [daily, setDaily] = useState(false);
const [items, setItems] = useState([]);
const [loading, setLoading] = useState(false);
@@ -98,7 +97,7 @@ const SummaryReportPage = () => {
return (
<PageLayout menu={<ReportsMenu />} breadcrumbs={['reportTitle', 'reportSummary']}>
<div className={classes.header}>
- <ReportFilter handleSubmit={handleSubmit} multiDevice>
+ <ReportFilter handleSubmit={handleSubmit} multiDevice includeGroups>
<div className={classes.filterItem}>
<FormControl fullWidth>
<InputLabel>{t('sharedType')}</InputLabel>
@@ -114,12 +113,14 @@ const SummaryReportPage = () => {
<Table>
<TableHead>
<TableRow>
+ <TableCell>{t('sharedDevice')}</TableCell>
{columns.map((key) => (<TableCell key={key}>{t(columnsMap.get(key))}</TableCell>))}
</TableRow>
</TableHead>
<TableBody>
{!loading ? items.map((item) => (
<TableRow key={(`${item.deviceId}_${Date.parse(item.startTime)}`)}>
+ <TableCell>{devices[item.deviceId].name}</TableCell>
{columns.map((key) => (
<TableCell key={key}>
{formatValue(item, key)}
diff --git a/modern/src/reports/components/ReportFilter.js b/modern/src/reports/components/ReportFilter.js
index 816fde8d..d223b086 100644
--- a/modern/src/reports/components/ReportFilter.js
+++ b/modern/src/reports/components/ReportFilter.js
@@ -7,7 +7,7 @@ import moment from 'moment';
import { useTranslation } from '../../common/components/LocalizationProvider';
import useReportStyles from '../common/useReportStyles';
-const ReportFilter = ({ children, handleSubmit, showOnly, ignoreDevice, multiDevice }) => {
+const ReportFilter = ({ children, handleSubmit, showOnly, ignoreDevice, multiDevice, includeGroups }) => {
const classes = useReportStyles();
const t = useTranslation();
@@ -87,7 +87,7 @@ const ReportFilter = ({ children, handleSubmit, showOnly, ignoreDevice, multiDev
</FormControl>
</div>
)}
- {multiDevice && (
+ {includeGroups && (
<div className={classes.filterItem}>
<FormControl fullWidth>
<InputLabel>{t('settingsGroups')}</InputLabel>