diff options
-rw-r--r-- | modern/src/App.js | 2 | ||||
-rw-r--r-- | modern/src/MainMap.js | 5 | ||||
-rw-r--r-- | modern/src/PositionPage.js | 80 | ||||
-rw-r--r-- | modern/src/StatusView.js | 12 | ||||
-rw-r--r-- | modern/src/common/formatter.js | 4 | ||||
-rw-r--r-- | modern/src/settings/NotificationPage.js | 1 | ||||
-rw-r--r-- | web/l10n/en.json | 1 |
7 files changed, 99 insertions, 6 deletions
diff --git a/modern/src/App.js b/modern/src/App.js index b25d1ab..9dc963b 100644 --- a/modern/src/App.js +++ b/modern/src/App.js @@ -11,6 +11,7 @@ import UserPage from './UserPage'; import SocketController from './SocketController'; import NotificationsPage from './settings/NotificationsPage'; import NotificationPage from './settings/NotificationPage'; +import PositionPage from './PositionPage'; const App = () => { return ( @@ -20,6 +21,7 @@ const App = () => { <Switch> <Route exact path='/' component={MainPage} /> <Route exact path='/login' component={LoginPage} /> + <Route exact path='/position/:id?' component={PositionPage} /> <Route exact path='/user/:id?' component={UserPage} /> <Route exact path='/device/:id?' component={DevicePage} /> <Route exact path='/reports/route' component={RouteReportPage} /> diff --git a/modern/src/MainMap.js b/modern/src/MainMap.js index 5ba5098..b3fafb6 100644 --- a/modern/src/MainMap.js +++ b/modern/src/MainMap.js @@ -6,8 +6,11 @@ import mapboxgl from 'mapbox-gl'; import mapManager from './mapManager'; import store from './store'; import StatusView from './StatusView'; +import { useHistory } from 'react-router-dom'; const MainMap = () => { + const history = useHistory(); + const containerEl = useRef(null); const [mapReady, setMapReady] = useState(false); @@ -67,7 +70,7 @@ const MainMap = () => { const placeholder = document.createElement('div'); ReactDOM.render( <Provider store={store}> - <StatusView deviceId={feature.properties.deviceId} /> + <StatusView deviceId={feature.properties.deviceId} onShowDetails={positionId => history.push(`/position/${positionId}`)} /> </Provider>, placeholder); diff --git a/modern/src/PositionPage.js b/modern/src/PositionPage.js new file mode 100644 index 0000000..a91a7a1 --- /dev/null +++ b/modern/src/PositionPage.js @@ -0,0 +1,80 @@ +import React, { Fragment, useState } from 'react'; + +import t from './common/localization'; +import { makeStyles, Typography, ListItem, ListItemText, ListItemSecondaryAction, List, Container, Paper, Divider } from '@material-ui/core'; +import { useParams } from 'react-router-dom'; +import { useEffectAsync } from './reactHelper'; +import MainToolbar from './MainToolbar'; +import { formatPosition } from './common/formatter'; +import { prefixString } from './common/stringUtils'; + +const useStyles = makeStyles(theme => ({ + root: { + marginTop: theme.spacing(2), + marginBottom: theme.spacing(2), + }, +})); + +const PositionPage = () => { + const classes = useStyles(); + + const { id } = useParams(); + + const [item, setItem] = useState(); + + useEffectAsync(async () => { + if (id) { + const response = await fetch(`/api/positions?id=${id}`, { + headers: { + 'Accept': 'application/json' + }, + }); + if (response.ok) { + const items = await response.json(); + setItem(items[0]); + } + } else { + setItem({}); + } + }, [id]); + + const formatKey = (key) => { + return t(prefixString('position', key)) || `${t('sharedAttribute')} "${key}"`; + }; + + const attributesList = () => { + const combinedList = {...item, ...item.attributes}; + return Object.entries(combinedList).filter(([_, value]) => typeof value !== 'object'); + } + + return ( + <> + <MainToolbar /> + <Container maxWidth='sm' className={classes.root}> + <Paper> + {item && + <List> + {attributesList().map(([key, value], index, list) => ( + <Fragment key={key}> + <ListItem> + <ListItemText + primary={formatKey(key)} + /> + <ListItemSecondaryAction> + <Typography variant="body2"> + {formatPosition(value, key)} + </Typography> + </ListItemSecondaryAction> + </ListItem> + {index < list.length - 1 ? <Divider /> : null} + </Fragment> + ))} + </List> + } + </Paper> + </Container> + </> + ); +} + +export default PositionPage; diff --git a/modern/src/StatusView.js b/modern/src/StatusView.js index 61fd150..0713d47 100644 --- a/modern/src/StatusView.js +++ b/modern/src/StatusView.js @@ -3,9 +3,14 @@ import React from 'react'; import { useSelector } from 'react-redux'; import { formatPosition } from './common/formatter'; -const StatusView = (props) => { - const device = useSelector(state => state.devices.items[props.deviceId]); - const position = useSelector(state => state.positions.items[props.deviceId]); +const StatusView = ({ deviceId, onShowDetails }) => { + const device = useSelector(state => state.devices.items[deviceId]); + const position = useSelector(state => state.positions.items[deviceId]); + + const handleClick = e => { + e.preventDefault(); + onShowDetails(position.id); + }; return ( <> @@ -17,6 +22,7 @@ const StatusView = (props) => { {position.attributes.batteryLevel && <><b>{t('positionBattery')}:</b> {formatPosition(position.attributes.batteryLevel, 'batteryLevel')}<br /></> } + <a href="#" onClick={handleClick}>{t('sharedShowDetails')}</a> </> ); }; diff --git a/modern/src/common/formatter.js b/modern/src/common/formatter.js index 057041e..f04bb43 100644 --- a/modern/src/common/formatter.js +++ b/modern/src/common/formatter.js @@ -2,11 +2,13 @@ import moment from 'moment'; import t from '../common/localization'; export const formatPosition = (value, key) => { - if (value != null && typeof value == 'object') { + if (value != null && typeof value === 'object') { value = value[key]; } switch (key) { case 'fixTime': + case 'deviceTime': + case 'serverTime': return moment(value).format('LLL'); case 'latitude': case 'longitude': diff --git a/modern/src/settings/NotificationPage.js b/modern/src/settings/NotificationPage.js index 3e47650..5a772d0 100644 --- a/modern/src/settings/NotificationPage.js +++ b/modern/src/settings/NotificationPage.js @@ -1,5 +1,4 @@ import React, { useState } from 'react'; -import TextField from '@material-ui/core/TextField'; import t, { findStringKeys } from '../common/localization'; import EditItemView from '../EditItemView'; diff --git a/web/l10n/en.json b/web/l10n/en.json index 6e0c62f..139640b 100644 --- a/web/l10n/en.json +++ b/web/l10n/en.json @@ -75,6 +75,7 @@ "sharedSavedCommands": "Saved Commands", "sharedNew": "New…", "sharedShowAddress": "Show Address", + "sharedShowDetails": "More Details", "sharedDisabled": "Disabled", "sharedMaintenance": "Maintenance", "sharedDeviceAccumulators": "Accumulators", |