diff options
author | Anton Tananaev <anton@traccar.org> | 2022-09-04 16:08:25 -0700 |
---|---|---|
committer | Anton Tananaev <anton@traccar.org> | 2022-09-04 16:08:25 -0700 |
commit | 842fd239a101e8c8ecbdb7da7a6efbfc83d3ad00 (patch) | |
tree | 0f18e28f4a468aa1e0fbd519399c5ad822004e81 /modern/src | |
parent | 47ffffb6f90bfd9a8aaae1fd696d588c175c94a6 (diff) | |
download | trackermap-web-842fd239a101e8c8ecbdb7da7a6efbfc83d3ad00.tar.gz trackermap-web-842fd239a101e8c8ecbdb7da7a6efbfc83d3ad00.tar.bz2 trackermap-web-842fd239a101e8c8ecbdb7da7a6efbfc83d3ad00.zip |
Add event report map (fix #1022)
Diffstat (limited to 'modern/src')
-rw-r--r-- | modern/src/reports/EventReportPage.js | 137 |
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> ); }; |