diff options
author | Anton Tananaev <anton.tananaev@gmail.com> | 2020-09-28 20:43:47 -0700 |
---|---|---|
committer | Anton Tananaev <anton.tananaev@gmail.com> | 2020-09-28 20:43:47 -0700 |
commit | 94e8c40f52b239562aded5e70e334ddbb2eea23b (patch) | |
tree | bd5d8b9425a08ac055f0617818e6e54930c4d557 /modern/src | |
parent | 9d72339c8365da80154f635dc8184b135a53bab0 (diff) | |
download | trackermap-web-94e8c40f52b239562aded5e70e334ddbb2eea23b.tar.gz trackermap-web-94e8c40f52b239562aded5e70e334ddbb2eea23b.tar.bz2 trackermap-web-94e8c40f52b239562aded5e70e334ddbb2eea23b.zip |
Page for all attributes
Diffstat (limited to 'modern/src')
-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 |
6 files changed, 98 insertions, 6 deletions
diff --git a/modern/src/App.js b/modern/src/App.js index b25d1aba..9dc963b6 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 5ba50982..b3fafb6a 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 00000000..a91a7a15 --- /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 61fd1504..0713d47e 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 057041e2..f04bb434 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 3e47650b..5a772d0c 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'; |