aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnton Tananaev <anton@traccar.org>2022-05-27 09:24:32 -0700
committerAnton Tananaev <anton@traccar.org>2022-05-27 09:24:32 -0700
commit2d371784bd8a1fbefa0b489c3a4a2a1c04eaf7c9 (patch)
tree2bf82f58b641098faf6c52a5538fa0f23b264e67
parent5f1de2f30ffcc80c75a4a3256340a56d822dc1fa (diff)
downloadtrackermap-web-2d371784bd8a1fbefa0b489c3a4a2a1c04eaf7c9.tar.gz
trackermap-web-2d371784bd8a1fbefa0b489c3a4a2a1c04eaf7c9.tar.bz2
trackermap-web-2d371784bd8a1fbefa0b489c3a4a2a1c04eaf7c9.zip
Add route report map (fix #942)
-rw-r--r--modern/src/reports/RouteReportPage.js110
1 files changed, 78 insertions, 32 deletions
diff --git a/modern/src/reports/RouteReportPage.js b/modern/src/reports/RouteReportPage.js
index c88da633..152d0ead 100644
--- a/modern/src/reports/RouteReportPage.js
+++ b/modern/src/reports/RouteReportPage.js
@@ -1,8 +1,10 @@
import React, { useState } from 'react';
import {
- Table, TableBody, TableCell, TableHead, TableRow,
+ IconButton, Table, TableBody, TableCell, TableHead, TableRow,
} from '@mui/material';
import { makeStyles } from '@mui/styles';
+import GpsFixedIcon from '@mui/icons-material/GpsFixed';
+import LocationSearchingIcon from '@mui/icons-material/LocationSearching';
import ReportFilter from './components/ReportFilter';
import { useTranslation } from '../common/components/LocalizationProvider';
import PageLayout from '../common/components/PageLayout';
@@ -12,8 +14,23 @@ import PositionValue from '../common/components/PositionValue';
import ColumnSelect from './components/ColumnSelect';
import usePositionAttributes from '../common/attributes/usePositionAttributes';
import { useCatch } from '../reactHelper';
+import Map from '../map/core/Map';
+import MapRoutePath from '../map/MapRoutePath';
+import MapPositions from '../map/MapPositions';
-const useStyles = makeStyles(() => ({
+const useStyles = makeStyles((theme) => ({
+ container: {
+ height: '100%',
+ display: 'flex',
+ flexDirection: 'column',
+ },
+ containerMap: {
+ flexBasis: '40%',
+ flexShrink: 0,
+ },
+ containerMain: {
+ overflow: 'auto',
+ },
header: {
position: 'sticky',
left: 0,
@@ -21,6 +38,10 @@ const useStyles = makeStyles(() => ({
flexDirection: 'column',
alignItems: 'stretch',
},
+ columnAction: {
+ width: '1%',
+ paddingLeft: theme.spacing(1),
+ },
}));
const RouteReportPage = () => {
@@ -31,6 +52,7 @@ const RouteReportPage = () => {
const [columns, setColumns] = usePersistedState('routeColumns', ['fixTime', 'latitude', 'longitude', 'speed', 'address']);
const [items, setItems] = useState([]);
+ const [selectedItem, setSelectedItem] = useState(null);
const handleSubmit = useCatch(async (deviceId, from, to, mail, headers) => {
const query = new URLSearchParams({
@@ -53,37 +75,61 @@ const RouteReportPage = () => {
return (
<PageLayout menu={<ReportsMenu />} breadcrumbs={['reportTitle', 'reportRoute']}>
- <div className={classes.header}>
- <ReportFilter handleSubmit={handleSubmit}>
- <ColumnSelect
- columns={columns}
- setColumns={setColumns}
- columnsObject={positionAttributes}
- />
- </ReportFilter>
- </div>
- <Table>
- <TableHead>
- <TableRow>
- {columns.map((key) => (<TableCell key={key}>{positionAttributes[key].name}</TableCell>))}
- </TableRow>
- </TableHead>
- <TableBody>
- {items.map((item) => (
- <TableRow key={item.id}>
- {columns.map((key) => (
- <TableCell key={key}>
- <PositionValue
- position={item}
- property={item.hasOwnProperty(key) ? key : null}
- attribute={item.hasOwnProperty(key) ? null : key}
- />
- </TableCell>
+ <div className={classes.container}>
+ {selectedItem && (
+ <div className={classes.containerMap}>
+ <Map>
+ <MapRoutePath positions={items} />
+ <MapPositions positions={[selectedItem]} />
+ </Map>
+ </div>
+ )}
+ <div className={classes.containerMain}>
+ <div className={classes.header}>
+ <ReportFilter handleSubmit={handleSubmit}>
+ <ColumnSelect
+ columns={columns}
+ setColumns={setColumns}
+ columnsObject={positionAttributes}
+ />
+ </ReportFilter>
+ </div>
+ <Table>
+ <TableHead>
+ <TableRow>
+ <TableCell className={classes.columnAction} />
+ {columns.map((key) => (<TableCell key={key}>{positionAttributes[key].name}</TableCell>))}
+ </TableRow>
+ </TableHead>
+ <TableBody>
+ {items.map((item) => (
+ <TableRow key={item.id}>
+ <TableCell className={classes.columnAction} padding="none">
+ {selectedItem === item ? (
+ <IconButton size="small" onClick={() => setSelectedItem(null)}>
+ <GpsFixedIcon fontSize="small" />
+ </IconButton>
+ ) : (
+ <IconButton size="small" onClick={() => setSelectedItem(item)}>
+ <LocationSearchingIcon fontSize="small" />
+ </IconButton>
+ )}
+ </TableCell>
+ {columns.map((key) => (
+ <TableCell key={key}>
+ <PositionValue
+ position={item}
+ property={item.hasOwnProperty(key) ? key : null}
+ attribute={item.hasOwnProperty(key) ? null : key}
+ />
+ </TableCell>
+ ))}
+ </TableRow>
))}
- </TableRow>
- ))}
- </TableBody>
- </Table>
+ </TableBody>
+ </Table>
+ </div>
+ </div>
</PageLayout>
);
};