aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnton Tananaev <anton@traccar.org>2022-09-04 16:08:25 -0700
committerAnton Tananaev <anton@traccar.org>2022-09-04 16:08:25 -0700
commit842fd239a101e8c8ecbdb7da7a6efbfc83d3ad00 (patch)
tree0f18e28f4a468aa1e0fbd519399c5ad822004e81
parent47ffffb6f90bfd9a8aaae1fd696d588c175c94a6 (diff)
downloadtrackermap-web-842fd239a101e8c8ecbdb7da7a6efbfc83d3ad00.tar.gz
trackermap-web-842fd239a101e8c8ecbdb7da7a6efbfc83d3ad00.tar.bz2
trackermap-web-842fd239a101e8c8ecbdb7da7a6efbfc83d3ad00.zip
Add event report map (fix #1022)
-rw-r--r--modern/src/reports/EventReportPage.js137
1 files changed, 93 insertions, 44 deletions
diff --git a/modern/src/reports/EventReportPage.js b/modern/src/reports/EventReportPage.js
index 91c280da..623f26bd 100644
--- a/modern/src/reports/EventReportPage.js
+++ b/modern/src/reports/EventReportPage.js
@@ -1,7 +1,9 @@
import React, { useState } from 'react';
import {
- FormControl, InputLabel, Select, MenuItem, Table, TableHead, TableRow, TableCell, TableBody, Link,
+ FormControl, InputLabel, Select, MenuItem, Table, TableHead, TableRow, TableCell, TableBody, Link, IconButton,
} from '@mui/material';
+import GpsFixedIcon from '@mui/icons-material/GpsFixed';
+import LocationSearchingIcon from '@mui/icons-material/LocationSearching';
import { useSelector } from 'react-redux';
import { formatSpeed, formatTime } from '../common/util/formatter';
import ReportFilter from './components/ReportFilter';
@@ -15,6 +17,10 @@ import { useCatch, useEffectAsync } from '../reactHelper';
import useReportStyles from './common/useReportStyles';
import TableShimmer from '../common/components/TableShimmer';
import { useAttributePreference } from '../common/util/preferences';
+import MapView from '../map/core/MapView';
+import MapGeofence from '../map/MapGeofence';
+import MapPositions from '../map/MapPositions';
+import MapCamera from '../map/MapCamera';
const columnsArray = [
['eventTime', 'positionFixTime'],
@@ -40,6 +46,24 @@ const EventReportPage = () => {
const [eventTypes, setEventTypes] = useState(['allEvents']);
const [items, setItems] = useState([]);
const [loading, setLoading] = useState(false);
+ const [selectedItem, setSelectedItem] = useState(null);
+ const [position, setPosition] = useState(null);
+
+ useEffectAsync(async () => {
+ if (selectedItem) {
+ const response = await fetch(`/api/positions?id=${selectedItem.positionId}`);
+ if (response.ok) {
+ const positions = await response.json();
+ if (positions.length > 0) {
+ setPosition(positions[0]);
+ }
+ } else {
+ throw Error(await response.text());
+ }
+ } else {
+ setPosition(null);
+ }
+ }, [selectedItem]);
useEffectAsync(async () => {
const response = await fetch('/api/notifications/types');
@@ -114,51 +138,76 @@ const EventReportPage = () => {
return (
<PageLayout menu={<ReportsMenu />} breadcrumbs={['reportTitle', 'reportEvents']}>
- <div className={classes.header}>
- <ReportFilter handleSubmit={handleSubmit}>
- <div className={classes.filterItem}>
- <FormControl fullWidth>
- <InputLabel>{t('reportEventTypes')}</InputLabel>
- <Select
- label={t('reportEventTypes')}
- value={eventTypes}
- onChange={(event, child) => {
- let values = event.target.value;
- const clicked = child.props.value;
- if (values.includes('allEvents') && values.length > 1) {
- values = [clicked];
- }
- setEventTypes(values);
- }}
- multiple
- >
- {allEventTypes.map(([key, string]) => (
- <MenuItem key={key} value={key}>{t(string)}</MenuItem>
- ))}
- </Select>
- </FormControl>
+ <div className={classes.container}>
+ {selectedItem && (
+ <div className={classes.containerMap}>
+ <MapView>
+ <MapGeofence />
+ {position && <MapPositions positions={[position]} />}
+ </MapView>
+ {position && <MapCamera latitude={position.latitude} longitude={position.longitude} />}
+ </div>
+ )}
+ <div className={classes.containerMain}>
+ <div className={classes.header}>
+ <ReportFilter handleSubmit={handleSubmit}>
+ <div className={classes.filterItem}>
+ <FormControl fullWidth>
+ <InputLabel>{t('reportEventTypes')}</InputLabel>
+ <Select
+ label={t('reportEventTypes')}
+ value={eventTypes}
+ onChange={(event, child) => {
+ let values = event.target.value;
+ const clicked = child.props.value;
+ if (values.includes('allEvents') && values.length > 1) {
+ values = [clicked];
+ }
+ setEventTypes(values);
+ }}
+ multiple
+ >
+ {allEventTypes.map(([key, string]) => (
+ <MenuItem key={key} value={key}>{t(string)}</MenuItem>
+ ))}
+ </Select>
+ </FormControl>
+ </div>
+ <ColumnSelect columns={columns} setColumns={setColumns} columnsArray={columnsArray} />
+ </ReportFilter>
</div>
- <ColumnSelect columns={columns} setColumns={setColumns} columnsArray={columnsArray} />
- </ReportFilter>
+ <Table>
+ <TableHead>
+ <TableRow>
+ <TableCell className={classes.columnAction} />
+ {columns.map((key) => (<TableCell key={key}>{t(columnsMap.get(key))}</TableCell>))}
+ </TableRow>
+ </TableHead>
+ <TableBody>
+ {!loading ? items.map((item) => (
+ <TableRow key={item.id}>
+ <TableCell className={classes.columnAction} padding="none">
+ {item.positionId ? 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}>
+ {formatValue(item, key)}
+ </TableCell>
+ ))}
+ </TableRow>
+ )) : (<TableShimmer columns={columns.length + 1} />)}
+ </TableBody>
+ </Table>
+ </div>
</div>
- <Table>
- <TableHead>
- <TableRow>
- {columns.map((key) => (<TableCell key={key}>{t(columnsMap.get(key))}</TableCell>))}
- </TableRow>
- </TableHead>
- <TableBody>
- {!loading ? items.map((item) => (
- <TableRow key={item.id}>
- {columns.map((key) => (
- <TableCell key={key}>
- {formatValue(item, key)}
- </TableCell>
- ))}
- </TableRow>
- )) : (<TableShimmer columns={columns.length} />)}
- </TableBody>
- </Table>
</PageLayout>
);
};