aboutsummaryrefslogtreecommitdiff
path: root/modern
diff options
context:
space:
mode:
authorAnton Tananaev <anton@traccar.org>2022-05-28 07:37:24 -0700
committerAnton Tananaev <anton@traccar.org>2022-05-28 07:37:24 -0700
commit47fdc633966a8f2baefb5424042de6be2ecd1ab6 (patch)
tree9817e5b02898636f146c4ed7c62aa8221310bb6f /modern
parentab26340ead6eba063734286a374101951d08688b (diff)
downloadtrackermap-web-47fdc633966a8f2baefb5424042de6be2ecd1ab6.tar.gz
trackermap-web-47fdc633966a8f2baefb5424042de6be2ecd1ab6.tar.bz2
trackermap-web-47fdc633966a8f2baefb5424042de6be2ecd1ab6.zip
Add map to stops report
Diffstat (limited to 'modern')
-rw-r--r--modern/src/main/MainPage.js8
-rw-r--r--modern/src/map/MapCamera.js18
-rw-r--r--modern/src/map/MapCurrentLocation.js2
-rw-r--r--modern/src/map/MapGeofenceEdit.js2
-rw-r--r--modern/src/map/MapPadding.js2
-rw-r--r--modern/src/map/MapPositions.js6
-rw-r--r--modern/src/map/MapRoutePath.js2
-rw-r--r--modern/src/map/core/MapView.js (renamed from modern/src/map/core/Map.js)4
-rw-r--r--modern/src/map/main/MapAccuracy.js2
-rw-r--r--modern/src/map/main/MapDefaultCamera.js2
-rw-r--r--modern/src/map/main/MapGeofence.js2
-rw-r--r--modern/src/map/main/MapLiveRoutes.js2
-rw-r--r--modern/src/map/main/MapSelectedDevice.js2
-rw-r--r--modern/src/map/main/PoiMap.js2
-rw-r--r--modern/src/other/EventPage.js6
-rw-r--r--modern/src/other/GeofencesPage.js6
-rw-r--r--modern/src/other/ReplayPage.js6
-rw-r--r--modern/src/reports/RouteReportPage.js6
-rw-r--r--modern/src/reports/StopReportPage.js80
19 files changed, 107 insertions, 53 deletions
diff --git a/modern/src/main/MainPage.js b/modern/src/main/MainPage.js
index b3b23aab..f9341eb6 100644
--- a/modern/src/main/MainPage.js
+++ b/modern/src/main/MainPage.js
@@ -15,7 +15,7 @@ import ListIcon from '@mui/icons-material/ViewList';
import { useDispatch, useSelector } from 'react-redux';
import DevicesList from './DevicesList';
-import Map from '../map/core/Map';
+import MapView from '../map/core/MapView';
import MapSelectedDevice from '../map/main/MapSelectedDevice';
import MapAccuracy from '../map/main/MapAccuracy';
import MapGeofence from '../map/main/MapGeofence';
@@ -149,15 +149,15 @@ const MainPage = () => {
return (
<div className={classes.root}>
- <Map>
+ <MapView>
<MapGeofence />
<MapAccuracy />
{mapLiveRoutes && <MapLiveRoutes />}
- <MapPositions positions={positions} onClick={onClick} />
+ <MapPositions positions={positions} onClick={onClick} showStatus />
<MapDefaultCamera />
<MapSelectedDevice />
<PoiMap />
- </Map>
+ </MapView>
<MapCurrentLocation />
{desktop && <MapPadding left={parseInt(theme.dimensions.drawerWidthDesktop, 10)} />}
<Button
diff --git a/modern/src/map/MapCamera.js b/modern/src/map/MapCamera.js
new file mode 100644
index 00000000..7ebf24fb
--- /dev/null
+++ b/modern/src/map/MapCamera.js
@@ -0,0 +1,18 @@
+import { useEffect } from 'react';
+
+import { map } from './core/MapView';
+
+const MapCamera = ({
+ latitude, longitude,
+}) => {
+ useEffect(() => {
+ map.jumpTo({
+ center: [longitude, latitude],
+ zoom: Math.max(map.getZoom(), 10),
+ });
+ }, [latitude, longitude]);
+
+ return null;
+};
+
+export default MapCamera;
diff --git a/modern/src/map/MapCurrentLocation.js b/modern/src/map/MapCurrentLocation.js
index 691c6be3..66fc46ec 100644
--- a/modern/src/map/MapCurrentLocation.js
+++ b/modern/src/map/MapCurrentLocation.js
@@ -1,6 +1,6 @@
import maplibregl from 'maplibre-gl';
import { useEffect } from 'react';
-import { map } from './core/Map';
+import { map } from './core/MapView';
const MapCurrentLocation = () => {
useEffect(() => {
diff --git a/modern/src/map/MapGeofenceEdit.js b/modern/src/map/MapGeofenceEdit.js
index 0b5062d8..42e51af7 100644
--- a/modern/src/map/MapGeofenceEdit.js
+++ b/modern/src/map/MapGeofenceEdit.js
@@ -6,7 +6,7 @@ import { useEffect } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { useNavigate } from 'react-router-dom';
-import { map } from './core/Map';
+import { map } from './core/MapView';
import { geofenceToFeature, geometryToArea } from './core/mapUtil';
import { errorsActions, geofencesActions } from '../store';
import { useCatchCallback } from '../reactHelper';
diff --git a/modern/src/map/MapPadding.js b/modern/src/map/MapPadding.js
index 1a4643a9..b1927a1f 100644
--- a/modern/src/map/MapPadding.js
+++ b/modern/src/map/MapPadding.js
@@ -1,6 +1,6 @@
import { useEffect } from 'react';
-import { map } from './core/Map';
+import { map } from './core/MapView';
const MapPadding = ({
top, right, bottom, left,
diff --git a/modern/src/map/MapPositions.js b/modern/src/map/MapPositions.js
index 170a6b11..4b53255a 100644
--- a/modern/src/map/MapPositions.js
+++ b/modern/src/map/MapPositions.js
@@ -1,11 +1,11 @@
import { useCallback, useEffect } from 'react';
import { useSelector } from 'react-redux';
-import { map } from './core/Map';
+import { map } from './core/MapView';
import { getStatusColor } from '../common/util/formatter';
import usePersistedState from '../common/util/usePersistedState';
-const MapPositions = ({ positions, onClick }) => {
+const MapPositions = ({ positions, onClick, showStatus }) => {
const id = 'positions';
const clusters = `${id}-clusters`;
@@ -20,7 +20,7 @@ const MapPositions = ({ positions, onClick }) => {
deviceId: position.deviceId,
name: device.name,
category: device.category || 'default',
- color: getStatusColor(device.status),
+ color: showStatus ? getStatusColor(device.status) : 'neutral',
};
};
diff --git a/modern/src/map/MapRoutePath.js b/modern/src/map/MapRoutePath.js
index d7cb484d..9703bf24 100644
--- a/modern/src/map/MapRoutePath.js
+++ b/modern/src/map/MapRoutePath.js
@@ -1,7 +1,7 @@
import maplibregl from 'maplibre-gl';
import { useEffect } from 'react';
import { useSelector } from 'react-redux';
-import { map } from './core/Map';
+import { map } from './core/MapView';
const MapRoutePath = ({ positions }) => {
const id = 'replay';
diff --git a/modern/src/map/core/Map.js b/modern/src/map/core/MapView.js
index 1e7fa76b..ba5a67d6 100644
--- a/modern/src/map/core/Map.js
+++ b/modern/src/map/core/MapView.js
@@ -75,7 +75,7 @@ const switcher = new SwitcherControl(
map.addControl(switcher);
-const Map = ({ children }) => {
+const MapView = ({ children }) => {
const containerEl = useRef(null);
const t = useTranslation();
@@ -131,4 +131,4 @@ const Map = ({ children }) => {
);
};
-export default Map;
+export default MapView;
diff --git a/modern/src/map/main/MapAccuracy.js b/modern/src/map/main/MapAccuracy.js
index 11ea64ed..089389bd 100644
--- a/modern/src/map/main/MapAccuracy.js
+++ b/modern/src/map/main/MapAccuracy.js
@@ -2,7 +2,7 @@ import { useEffect } from 'react';
import { useSelector } from 'react-redux';
import circle from '@turf/circle';
-import { map } from '../core/Map';
+import { map } from '../core/MapView';
const MapAccuracy = () => {
const id = 'accuracy';
diff --git a/modern/src/map/main/MapDefaultCamera.js b/modern/src/map/main/MapDefaultCamera.js
index 24296c2f..6ccf660e 100644
--- a/modern/src/map/main/MapDefaultCamera.js
+++ b/modern/src/map/main/MapDefaultCamera.js
@@ -2,7 +2,7 @@ import maplibregl from 'maplibre-gl';
import { useEffect, useState } from 'react';
import { useSelector } from 'react-redux';
import { usePreference } from '../../common/util/preferences';
-import { map } from '../core/Map';
+import { map } from '../core/MapView';
const MapDefaultCamera = () => {
const selectedDeviceId = useSelector((state) => state.devices.selectedId);
diff --git a/modern/src/map/main/MapGeofence.js b/modern/src/map/main/MapGeofence.js
index ee1bc884..71d5cb6e 100644
--- a/modern/src/map/main/MapGeofence.js
+++ b/modern/src/map/main/MapGeofence.js
@@ -1,7 +1,7 @@
import { useEffect } from 'react';
import { useSelector } from 'react-redux';
-import { map } from '../core/Map';
+import { map } from '../core/MapView';
import { geofenceToFeature } from '../core/mapUtil';
const MapGeofence = () => {
diff --git a/modern/src/map/main/MapLiveRoutes.js b/modern/src/map/main/MapLiveRoutes.js
index 139f7d65..09319cff 100644
--- a/modern/src/map/main/MapLiveRoutes.js
+++ b/modern/src/map/main/MapLiveRoutes.js
@@ -1,7 +1,7 @@
import { useEffect, useState } from 'react';
import { useSelector } from 'react-redux';
-import { map } from '../core/Map';
+import { map } from '../core/MapView';
import { usePrevious } from '../../reactHelper';
const MapLiveRoutes = () => {
diff --git a/modern/src/map/main/MapSelectedDevice.js b/modern/src/map/main/MapSelectedDevice.js
index ba3bc784..9d97dd75 100644
--- a/modern/src/map/main/MapSelectedDevice.js
+++ b/modern/src/map/main/MapSelectedDevice.js
@@ -2,7 +2,7 @@ import { useEffect } from 'react';
import { useSelector } from 'react-redux';
import dimensions from '../../common/theme/dimensions';
-import { map } from '../core/Map';
+import { map } from '../core/MapView';
import { usePrevious } from '../../reactHelper';
import usePersistedState from '../../common/util/usePersistedState';
diff --git a/modern/src/map/main/PoiMap.js b/modern/src/map/main/PoiMap.js
index 5874f356..3ca344c5 100644
--- a/modern/src/map/main/PoiMap.js
+++ b/modern/src/map/main/PoiMap.js
@@ -1,7 +1,7 @@
import { useEffect, useState } from 'react';
import { kml } from '@tmcw/togeojson';
-import { map } from '../core/Map';
+import { map } from '../core/MapView';
import { useEffectAsync } from '../../reactHelper';
import { usePreference } from '../../common/util/preferences';
diff --git a/modern/src/other/EventPage.js b/modern/src/other/EventPage.js
index cbe4a0fb..f84e1e5e 100644
--- a/modern/src/other/EventPage.js
+++ b/modern/src/other/EventPage.js
@@ -8,7 +8,7 @@ import ArrowBackIcon from '@mui/icons-material/ArrowBack';
import { useNavigate, useParams } from 'react-router-dom';
import { useEffectAsync } from '../reactHelper';
import { useTranslation } from '../common/components/LocalizationProvider';
-import Map from '../map/core/Map';
+import MapView from '../map/core/MapView';
import MapPositions from '../map/MapPositions';
const useStyles = makeStyles(() => ({
@@ -68,9 +68,9 @@ const EventPage = () => {
</Toolbar>
</AppBar>
<div className={classes.mapContainer}>
- <Map>
+ <MapView>
{position && <MapPositions positions={[position]} />}
- </Map>
+ </MapView>
</div>
</div>
);
diff --git a/modern/src/other/GeofencesPage.js b/modern/src/other/GeofencesPage.js
index 6706ec98..fce15a39 100644
--- a/modern/src/other/GeofencesPage.js
+++ b/modern/src/other/GeofencesPage.js
@@ -7,7 +7,7 @@ import { useTheme } from '@mui/material/styles';
import Drawer from '@mui/material/Drawer';
import ArrowBackIcon from '@mui/icons-material/ArrowBack';
import { useNavigate } from 'react-router-dom';
-import Map from '../map/core/Map';
+import MapView from '../map/core/MapView';
import MapCurrentLocation from '../map/MapCurrentLocation';
import MapGeofenceEdit from '../map/MapGeofenceEdit';
import GeofencesList from './GeofencesList';
@@ -77,10 +77,10 @@ const GeofencesPage = () => {
<GeofencesList />
</Drawer>
<div className={classes.mapContainer}>
- <Map>
+ <MapView>
<MapCurrentLocation />
<MapGeofenceEdit />
- </Map>
+ </MapView>
</div>
</div>
</div>
diff --git a/modern/src/other/ReplayPage.js b/modern/src/other/ReplayPage.js
index fcf01fc7..4893dda9 100644
--- a/modern/src/other/ReplayPage.js
+++ b/modern/src/other/ReplayPage.js
@@ -13,7 +13,7 @@ import FastForwardIcon from '@mui/icons-material/FastForward';
import FastRewindIcon from '@mui/icons-material/FastRewind';
import { useNavigate } from 'react-router-dom';
import { useSelector } from 'react-redux';
-import Map from '../map/core/Map';
+import MapView from '../map/core/MapView';
import MapRoutePath from '../map/MapRoutePath';
import MapPositions from '../map/MapPositions';
import { formatTime } from '../common/util/formatter';
@@ -143,12 +143,12 @@ const ReplayPage = () => {
return (
<div className={classes.root}>
- <Map>
+ <MapView>
<MapRoutePath positions={positions} />
{index < positions.length && (
<MapPositions positions={[positions[index]]} onClick={onClick} />
)}
- </Map>
+ </MapView>
<div className={classes.sidebar}>
<Paper elevation={3} square>
<Toolbar>
diff --git a/modern/src/reports/RouteReportPage.js b/modern/src/reports/RouteReportPage.js
index b29fb269..33bc9350 100644
--- a/modern/src/reports/RouteReportPage.js
+++ b/modern/src/reports/RouteReportPage.js
@@ -13,7 +13,7 @@ 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 MapView from '../map/core/MapView';
import MapRoutePath from '../map/MapRoutePath';
import MapPositions from '../map/MapPositions';
import useReportStyles from './common/useReportStyles';
@@ -52,10 +52,10 @@ const RouteReportPage = () => {
<div className={classes.container}>
{selectedItem && (
<div className={classes.containerMap}>
- <Map>
+ <MapView>
<MapRoutePath positions={items} />
<MapPositions positions={[selectedItem]} />
- </Map>
+ </MapView>
</div>
)}
<div className={classes.containerMain}>
diff --git a/modern/src/reports/StopReportPage.js b/modern/src/reports/StopReportPage.js
index d2823b06..d44e2046 100644
--- a/modern/src/reports/StopReportPage.js
+++ b/modern/src/reports/StopReportPage.js
@@ -1,7 +1,10 @@
import React, { useState } from 'react';
import {
+ IconButton,
Table, TableBody, TableCell, TableHead, TableRow,
} from '@mui/material';
+import GpsFixedIcon from '@mui/icons-material/GpsFixed';
+import LocationSearchingIcon from '@mui/icons-material/LocationSearching';
import {
formatDistance, formatHours, formatDate, formatVolume,
} from '../common/util/formatter';
@@ -14,6 +17,9 @@ import ColumnSelect from './components/ColumnSelect';
import usePersistedState from '../common/util/usePersistedState';
import { useCatch } from '../reactHelper';
import useReportStyles from './common/useReportStyles';
+import MapPositions from '../map/MapPositions';
+import MapView from '../map/core/MapView';
+import MapCamera from '../map/MapCamera';
const columnsArray = [
['startTime', 'reportStartTime'],
@@ -35,6 +41,7 @@ const StopReportPage = () => {
const [columns, setColumns] = usePersistedState('stopColumns', ['startTime', 'endTime', 'startOdometer', 'address']);
const [items, setItems] = useState([]);
+ const [selectedItem, setSelectedItem] = useState(null);
const handleSubmit = useCatch(async (deviceId, from, to, mail, headers) => {
const query = new URLSearchParams({
@@ -75,29 +82,58 @@ const StopReportPage = () => {
return (
<PageLayout menu={<ReportsMenu />} breadcrumbs={['reportTitle', 'reportStops']}>
- <div className={classes.header}>
- <ReportFilter handleSubmit={handleSubmit}>
- <ColumnSelect columns={columns} setColumns={setColumns} columnsArray={columnsArray} />
- </ReportFilter>
- </div>
- <Table>
- <TableHead>
- <TableRow>
- {columns.map((key) => (<TableCell key={key}>{t(columnsMap.get(key))}</TableCell>))}
- </TableRow>
- </TableHead>
- <TableBody>
- {items.map((item) => (
- <TableRow key={item.positionId}>
- {columns.map((key) => (
- <TableCell key={key}>
- {formatValue(item, key)}
- </TableCell>
+ <div className={classes.container}>
+ {selectedItem && (
+ <div className={classes.containerMap}>
+ <MapView>
+ <MapPositions positions={[{
+ deviceId: selectedItem.deviceId,
+ latitude: selectedItem.latitude,
+ longitude: selectedItem.longitude,
+ }]}
+ />
+ </MapView>
+ <MapCamera latitude={selectedItem.latitude} longitude={selectedItem.longitude} />
+ </div>
+ )}
+ <div className={classes.containerMain}>
+ <div className={classes.header}>
+ <ReportFilter handleSubmit={handleSubmit}>
+ <ColumnSelect columns={columns} setColumns={setColumns} columnsArray={columnsArray} />
+ </ReportFilter>
+ </div>
+ <Table>
+ <TableHead>
+ <TableRow>
+ <TableCell className={classes.columnAction} />
+ {columns.map((key) => (<TableCell key={key}>{t(columnsMap.get(key))}</TableCell>))}
+ </TableRow>
+ </TableHead>
+ <TableBody>
+ {items.map((item) => (
+ <TableRow key={item.positionId}>
+ <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}>
+ {formatValue(item, key)}
+ </TableCell>
+ ))}
+ </TableRow>
))}
- </TableRow>
- ))}
- </TableBody>
- </Table>
+ </TableBody>
+ </Table>
+ </div>
+ </div>
</PageLayout>
);
};