aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnton Tananaev <anton@traccar.org>2022-05-03 19:32:19 -0700
committerAnton Tananaev <anton@traccar.org>2022-05-03 19:32:19 -0700
commiteb52cc9ed238be6bbcb33a0f95d336b1ea404253 (patch)
treea33e47e6fd648b707d253f058ec45b6cb002f77b
parent02539d31ea7522fcfbbbcf4cf3fcd03e1961786f (diff)
downloadtrackermap-web-eb52cc9ed238be6bbcb33a0f95d336b1ea404253.tar.gz
trackermap-web-eb52cc9ed238be6bbcb33a0f95d336b1ea404253.tar.bz2
trackermap-web-eb52cc9ed238be6bbcb33a0f95d336b1ea404253.zip
Support accumulators reset
-rw-r--r--modern/src/App.js2
-rw-r--r--modern/src/components/PositionValue.js27
-rw-r--r--modern/src/settings/AccumulatorsPage.js114
3 files changed, 137 insertions, 6 deletions
diff --git a/modern/src/App.js b/modern/src/App.js
index 7a4af349..a64a8391 100644
--- a/modern/src/App.js
+++ b/modern/src/App.js
@@ -49,6 +49,7 @@ import { devicesActions } from './store';
import EventPage from './EventPage';
import PreferencesPage from './settings/PreferencesPage';
import BottomMenu from './components/BottomMenu';
+import AccumulatorsPage from './settings/AccumulatorsPage';
const useStyles = makeStyles(() => ({
root: {
@@ -123,6 +124,7 @@ const App = () => {
<Route exact path="/device/:id?" component={DevicePage} />
<Route exact path="/geofence/:id?" component={GeofencePage} />
<Route exact path="/geofences" component={GeofencesPage} />
+ <Route exact path="/settings/accumulators/:id?" component={AccumulatorsPage} />
<Route exact path="/settings/preferences" component={PreferencesPage} />
<Route exact path="/settings/notifications" component={NotificationsPage} />
<Route exact path="/settings/notification/:id?" component={NotificationPage} />
diff --git a/modern/src/components/PositionValue.js b/modern/src/components/PositionValue.js
index 4edfb416..fd331a7d 100644
--- a/modern/src/components/PositionValue.js
+++ b/modern/src/components/PositionValue.js
@@ -1,5 +1,7 @@
import React, { useEffect, useState } from 'react';
import { Link } from '@material-ui/core';
+import { Link as RouterLink } from 'react-router-dom';
+import { useSelector } from 'react-redux';
import {
formatAlarm, formatBoolean, formatCoordinate, formatCourse, formatDistance, formatNumber, formatPercentage, formatSpeed, formatTime,
} from '../common/formatter';
@@ -9,6 +11,8 @@ import { useTranslation } from '../LocalizationProvider';
const PositionValue = ({ position, property, attribute }) => {
const t = useTranslation();
+ const admin = useSelector((state) => state.session.user?.administrator);
+
const key = property || attribute;
const value = property ? position[property] : position.attributes[attribute];
@@ -65,13 +69,24 @@ const PositionValue = ({ position, property, attribute }) => {
}
};
- if (property === 'address') {
- if (address) {
- return (<>{address}</>);
- }
- return (<Link onClick={showAddress}>{t('sharedShowAddress')}</Link>);
+ switch (key) {
+ case 'totalDistance':
+ case 'hours':
+ return (
+ <>
+ {formatValue(value)}
+ &nbsp;&nbsp;
+ {admin && (<Link component={RouterLink} to={`/settings/accumulators/${position.deviceId}`}>&#9881;</Link>)}
+ </>
+ );
+ case 'address':
+ if (address) {
+ return (<>{address}</>);
+ }
+ return (<Link href="#" onClick={showAddress}>{t('sharedShowAddress')}</Link>);
+ default:
+ return (<>{formatValue(value)}</>);
}
- return (<>{formatValue(value)}</>);
};
export default PositionValue;
diff --git a/modern/src/settings/AccumulatorsPage.js b/modern/src/settings/AccumulatorsPage.js
new file mode 100644
index 00000000..f592445d
--- /dev/null
+++ b/modern/src/settings/AccumulatorsPage.js
@@ -0,0 +1,114 @@
+import React, { useEffect, useState } from 'react';
+import { useSelector } from 'react-redux';
+import { useHistory, useParams } from 'react-router-dom';
+import {
+ Accordion, AccordionSummary, AccordionDetails, makeStyles, Typography, Container, TextField, FormControl, Button,
+} from '@material-ui/core';
+import ExpandMoreIcon from '@material-ui/icons/ExpandMore';
+import { useTranslation } from '../LocalizationProvider';
+import OptionsLayout from './OptionsLayout';
+
+const useStyles = makeStyles((theme) => ({
+ container: {
+ marginTop: theme.spacing(2),
+ },
+ buttons: {
+ display: 'flex',
+ justifyContent: 'space-evenly',
+ '& > *': {
+ flexBasis: '33%',
+ },
+ },
+ details: {
+ flexDirection: 'column',
+ },
+}));
+
+const AccumulatorsPage = () => {
+ const history = useHistory();
+ const classes = useStyles();
+ const t = useTranslation();
+
+ const { id } = useParams();
+ const position = useSelector((state) => state.positions.items[id]);
+
+ const [item, setItem] = useState();
+
+ useEffect(() => {
+ if (position) {
+ setItem({
+ deviceId: parseInt(id, 10),
+ hours: position.attributes.hours || 0,
+ totalDistance: position.attributes.totalDistance || 0,
+ });
+ }
+ }, [id, position]);
+
+ const handleSave = async () => {
+ const response = await fetch(`/api/devices/${id}/accumulators`, {
+ method: 'PUT',
+ headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify(item),
+ });
+
+ if (response.ok) {
+ history.goBack();
+ }
+ };
+
+ return (
+ <OptionsLayout>
+ {item && (
+ <Container maxWidth="xs" className={classes.container}>
+ <Accordion defaultExpanded>
+ <AccordionSummary expandIcon={<ExpandMoreIcon />}>
+ <Typography variant="subtitle1">
+ {t('sharedRequired')}
+ </Typography>
+ </AccordionSummary>
+ <AccordionDetails className={classes.details}>
+ <TextField
+ margin="normal"
+ type="number"
+ value={item.hours}
+ onChange={(event) => setItem({ ...item, hours: Number(event.target.value) })}
+ label={t('positionHours')}
+ variant="filled"
+ />
+ <TextField
+ margin="normal"
+ type="number"
+ value={item.totalDistance}
+ onChange={(event) => setItem({ ...item, totalDistance: Number(event.target.value) })}
+ label={t('deviceTotalDistance')}
+ variant="filled"
+ />
+ </AccordionDetails>
+ </Accordion>
+ <FormControl fullWidth margin="normal">
+ <div className={classes.buttons}>
+ <Button
+ type="button"
+ color="primary"
+ variant="outlined"
+ onClick={() => history.goBack()}
+ >
+ {t('sharedCancel')}
+ </Button>
+ <Button
+ type="button"
+ color="primary"
+ variant="contained"
+ onClick={handleSave}
+ >
+ {t('sharedSave')}
+ </Button>
+ </div>
+ </FormControl>
+ </Container>
+ )}
+ </OptionsLayout>
+ );
+};
+
+export default AccumulatorsPage;