diff options
-rw-r--r-- | modern/src/MainPage.js | 4 | ||||
-rw-r--r-- | modern/src/map/CurrentPositionsMap.js | 11 | ||||
-rw-r--r-- | modern/src/map/PositionsMap.js | 33 | ||||
-rw-r--r-- | modern/src/reports/ReplayPage.js | 30 |
4 files changed, 57 insertions, 21 deletions
diff --git a/modern/src/MainPage.js b/modern/src/MainPage.js index 58bf83aa..a5a80618 100644 --- a/modern/src/MainPage.js +++ b/modern/src/MainPage.js @@ -5,10 +5,10 @@ import ContainerDimensions from 'react-container-dimensions'; import DevicesList from './DevicesList'; import MainToolbar from './MainToolbar'; import Map from './map/Map'; -import PositionsMap from './map/PositionsMap'; import SelectedDeviceMap from './map/SelectedDeviceMap'; import AccuracyMap from './map/AccuracyMap'; import GeofenceMap from './map/GeofenceMap'; +import CurrentPositionsMap from './map/CurrentPositionsMap'; const useStyles = makeStyles(theme => ({ root: { @@ -57,7 +57,7 @@ const MainPage = ({ width }) => { <Map> <GeofenceMap /> <AccuracyMap /> - <PositionsMap /> + <CurrentPositionsMap /> <SelectedDeviceMap /> </Map> </ContainerDimensions> diff --git a/modern/src/map/CurrentPositionsMap.js b/modern/src/map/CurrentPositionsMap.js new file mode 100644 index 00000000..0bfe4fcd --- /dev/null +++ b/modern/src/map/CurrentPositionsMap.js @@ -0,0 +1,11 @@ +import React, { } from 'react'; +import { useSelector } from 'react-redux'; + +import PositionsMap from './PositionsMap'; + +const CurrentPositionsMap = () => { + const positions = useSelector(state => Object.values(state.positions.items)); + return (<PositionsMap positions={positions} />); +} + +export default CurrentPositionsMap; diff --git a/modern/src/map/PositionsMap.js b/modern/src/map/PositionsMap.js index 0ad9a69d..fa7b431a 100644 --- a/modern/src/map/PositionsMap.js +++ b/modern/src/map/PositionsMap.js @@ -8,13 +8,14 @@ import store from '../store'; import { useHistory } from 'react-router-dom'; import StatusView from './StatusView'; -const PositionsMap = () => { +const PositionsMap = ({ positions }) => { const id = 'positions'; const history = useHistory(); + const devices = useSelector(state => state.devices.items); - const createFeature = (state, position) => { - const device = state.devices.items[position.deviceId] || null; + const createFeature = (devices, position) => { + const device = devices[position.deviceId] || null; return { deviceId: position.deviceId, name: device ? device.name : '', @@ -22,18 +23,6 @@ const PositionsMap = () => { } }; - const positions = useSelector(state => ({ - type: 'FeatureCollection', - features: Object.values(state.positions.items).map(position => ({ - type: 'Feature', - geometry: { - type: 'Point', - coordinates: [position.longitude, position.latitude] - }, - properties: createFeature(state, position), - })), - })); - const onMouseEnter = () => map.getCanvas().style.cursor = 'pointer'; const onMouseLeave = () => map.getCanvas().style.cursor = ''; @@ -106,8 +95,18 @@ const PositionsMap = () => { }, [onClickCallback]); useEffect(() => { - map.getSource(id).setData(positions); - }, [positions]); + map.getSource(id).setData({ + type: 'FeatureCollection', + features: positions.map(position => ({ + type: 'Feature', + geometry: { + type: 'Point', + coordinates: [position.longitude, position.latitude], + }, + properties: createFeature(devices, position), + })) + }); + }, [devices, positions]); return null; } diff --git a/modern/src/reports/ReplayPage.js b/modern/src/reports/ReplayPage.js index bdc9edb4..2afa1a2f 100644 --- a/modern/src/reports/ReplayPage.js +++ b/modern/src/reports/ReplayPage.js @@ -1,11 +1,13 @@ import React, { useState } from 'react'; -import { Accordion, AccordionDetails, AccordionSummary, Button, Container, FormControl, makeStyles, Paper, Slider, Typography } from '@material-ui/core'; +import { Accordion, AccordionDetails, AccordionSummary, Button, Container, FormControl, makeStyles, Paper, Slider, Tooltip, Typography } from '@material-ui/core'; import ExpandMoreIcon from '@material-ui/icons/ExpandMore'; import MainToolbar from '../MainToolbar'; import Map from '../map/Map'; import t from '../common/localization'; import FilterForm from './FilterForm'; import ReplayPathMap from '../map/ReplayPathMap'; +import PositionsMap from '../map/PositionsMap'; +import { formatPosition } from '../common/formatter'; const useStyles = makeStyles(theme => ({ root: { @@ -29,6 +31,14 @@ const useStyles = makeStyles(theme => ({ }, })); +const TimeLabel = ({ children, open, value }) => { + return ( + <Tooltip open={open} enterTouchDelay={0} placement="top" title={value}> + {children} + </Tooltip> + ); +}; + const ReplayPage = () => { const classes = useStyles(); @@ -40,6 +50,8 @@ const ReplayPage = () => { const [positions, setPositions] = useState([]); + const [index, setIndex] = useState(0); + const handleShow = async () => { const query = new URLSearchParams({ deviceId, @@ -48,6 +60,7 @@ const ReplayPage = () => { }); const response = await fetch(`/api/positions?${query.toString()}`, { headers: { 'Accept': 'application/json' } }); if (response.ok) { + setIndex(0); setPositions(await response.json()); setExpanded(false); } @@ -58,10 +71,23 @@ const ReplayPage = () => { <MainToolbar /> <Map> <ReplayPathMap positions={positions} /> + {index < positions.length && + <PositionsMap positions={[positions[index]]} /> + } </Map> <Container maxWidth="sm" className={classes.controlPanel}> <Paper className={classes.controlContent}> - <Slider defaultValue={30} /> + <Slider + disabled={!positions.length} + max={positions.length - 1} + step={null} + marks={positions.map((_, index) => ({ value: index }))} + value={index} + onChange={(_, index) => setIndex(index)} + valueLabelDisplay="auto" + valueLabelFormat={i => i < positions.length ? formatPosition(positions[i], 'fixTime') : ''} + ValueLabelComponent={TimeLabel} + /> </Paper> <div> <Accordion expanded={expanded} onChange={() => setExpanded(!expanded)}> |