aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnton Tananaev <anton.tananaev@gmail.com>2020-12-13 10:13:57 -0800
committerGitHub <noreply@github.com>2020-12-13 10:13:57 -0800
commitfca5aa3cdb5d335dca14115722cacae1b724fe4f (patch)
tree542416ca2e13ff811b818d2343e2b487fda97b86
parenta4c2f0477dcda2662a3fd268f77a7549dead6e67 (diff)
parentf8bb2fb5dfd801b7c49a3a3b66042e94dc7640dc (diff)
downloadetbsa-traccar-web-fca5aa3cdb5d335dca14115722cacae1b724fe4f.tar.gz
etbsa-traccar-web-fca5aa3cdb5d335dca14115722cacae1b724fe4f.tar.bz2
etbsa-traccar-web-fca5aa3cdb5d335dca14115722cacae1b724fe4f.zip
Merge pull request #797 from mail2bishnoi/chart-report
Implementing chart report initial structure
-rw-r--r--modern/package.json1
-rw-r--r--modern/src/App.js2
-rw-r--r--modern/src/MainToolbar.js2
-rw-r--r--modern/src/common/converter.js13
-rw-r--r--modern/src/reports/ChartReportPage.js72
-rw-r--r--modern/src/reports/EventReportPage.js4
-rw-r--r--modern/src/reports/Graph.js35
-rw-r--r--modern/src/reports/ReportLayoutPage.js4
-rw-r--r--modern/src/reports/RouteReportPage.js4
-rw-r--r--modern/src/reports/StopReportPage.js4
-rw-r--r--modern/src/reports/SummaryReportPage.js4
-rw-r--r--modern/src/reports/TripReportPage.js4
12 files changed, 136 insertions, 13 deletions
diff --git a/modern/package.json b/modern/package.json
index e5438b5..2c30c9f 100644
--- a/modern/package.json
+++ b/modern/package.json
@@ -20,6 +20,7 @@
"react-redux": "^7.2.1",
"react-router-dom": "^5.2.0",
"react-scripts": "^3.4.3",
+ "recharts": "^1.8.5",
"redux": "^4.0.5",
"typeface-roboto": "0.0.75",
"wellknown": "^0.5.0"
diff --git a/modern/src/App.js b/modern/src/App.js
index 8a308c1..83fd931 100644
--- a/modern/src/App.js
+++ b/modern/src/App.js
@@ -21,6 +21,7 @@ import { LinearProgress } from '@material-ui/core';
import TripReportPage from './reports/TripReportPage';
import StopReportPage from './reports/StopReportPage';
import SummaryReportPage from './reports/SummaryReportPage';
+import ChartReportPage from './reports/ChartReportPage';
const App = () => {
const initialized = useSelector(state => !!state.session.server && !!state.session.user);
@@ -50,6 +51,7 @@ const App = () => {
<Route exact path='/reports/trip' component={TripReportPage} />
<Route exact path='/reports/stop' component={StopReportPage} />
<Route exact path='/reports/summary' component={SummaryReportPage} />
+ <Route exact path='/reports/chart' component={ChartReportPage} />
</Switch>
)}
</Route>
diff --git a/modern/src/MainToolbar.js b/modern/src/MainToolbar.js
index 5b94b14..930e66a 100644
--- a/modern/src/MainToolbar.js
+++ b/modern/src/MainToolbar.js
@@ -141,7 +141,7 @@ const MainToolbar = () => {
</ListItemIcon>
<ListItemText primary={t('reportSummary')} />
</ListItem>
- <ListItem button disabled>
+ <ListItem button onClick={() => history.push('/reports/chart')}>
<ListItemIcon>
<TrendingUpIcon />
</ListItemIcon>
diff --git a/modern/src/common/converter.js b/modern/src/common/converter.js
new file mode 100644
index 0000000..e48b076
--- /dev/null
+++ b/modern/src/common/converter.js
@@ -0,0 +1,13 @@
+export const speedConverter = (value, unit) => {
+ let factor;
+ switch (unit) {
+ case 'kmh':
+ factor = 1.852;
+ case 'mph':
+ factor = 1.15078;
+ case 'kn':
+ default:
+ factor = 1;
+ }
+ return (value * factor).toFixed(2);
+};
diff --git a/modern/src/reports/ChartReportPage.js b/modern/src/reports/ChartReportPage.js
new file mode 100644
index 0000000..543c8a9
--- /dev/null
+++ b/modern/src/reports/ChartReportPage.js
@@ -0,0 +1,72 @@
+import React, { useState } from 'react';
+import { FormControl, InputLabel, Select, MenuItem } from '@material-ui/core';
+import ReportLayoutPage from './ReportLayoutPage';
+import ReportFilter from './ReportFilter';
+import Graph from './Graph';
+import { useAttributePreference } from '../common/preferences';
+import { formatDate } from '../common/formatter';
+import { speedConverter } from '../common/converter';
+import t from '../common/localization';
+
+const Filter = ({ children, setItems }) => {
+
+ const speedUnit = useAttributePreference('speedUnit');
+
+ const handleSubmit = async (deviceId, from, to, mail, headers) => {
+ const query = new URLSearchParams({ deviceId, from, to, mail });
+ const response = await fetch(`/api/reports/route?${query.toString()}`, { headers });
+ if (response.ok) {
+ const positions = await response.json();
+ let formattedPositions = positions.map(position => {
+ return {
+ speed: Number(speedConverter(position.speed, speedUnit)),
+ altitude: position.altitude,
+ accuracy: position.accuracy,
+ fixTime: formatDate(position.fixTime)
+ }
+ });
+ setItems(formattedPositions);
+ }
+ }
+ return (
+ <>
+ <ReportFilter handleSubmit={handleSubmit} showOnly />
+ {children}
+ </>
+ )
+}
+
+const ChartType = ({ type, setType }) => {
+
+ return (
+ <FormControl variant="filled" margin="normal" fullWidth>
+ <InputLabel>{t('reportChartType')}</InputLabel>
+ <Select value={type} onChange={e => setType(e.target.value)}>
+ <MenuItem value="speed">{t('positionSpeed')}</MenuItem>
+ <MenuItem value="accuracy">{t('positionAccuracy')}</MenuItem>
+ <MenuItem value="altitude">{t('positionAltitude')}</MenuItem>
+ </Select>
+ </FormControl>
+ )
+}
+
+
+const ChartReportPage = () => {
+
+ const [items, setItems] = useState([]);
+ const [type, setType] = useState('speed');
+
+ return (
+ <>
+ <ReportLayoutPage filter={
+ <Filter setItems={setItems}>
+ <ChartType type={type} setType={setType} />
+ </Filter>
+ }>
+ <Graph items={items} type={type} />
+ </ReportLayoutPage>
+ </>
+ )
+}
+
+export default ChartReportPage;
diff --git a/modern/src/reports/EventReportPage.js b/modern/src/reports/EventReportPage.js
index 13e081e..054181d 100644
--- a/modern/src/reports/EventReportPage.js
+++ b/modern/src/reports/EventReportPage.js
@@ -6,7 +6,7 @@ import { formatPosition } from '../common/formatter';
import ReportFilter from './ReportFilter';
import ReportLayoutPage from './ReportLayoutPage';
-const ReportFilterForm = ({ setItems }) => {
+const Filter = ({ setItems }) => {
const [eventTypes, setEventTypes] = useState(['allEvents']);
@@ -60,7 +60,7 @@ const EventReportPage = () => {
const [items, setItems] = useState([]);
return (
- <ReportLayoutPage reportFilterForm={ReportFilterForm} setItems={setItems}>
+ <ReportLayoutPage filter={<Filter setItems={setItems} />}>
<TableContainer component={Paper}>
<Table>
<TableHead>
diff --git a/modern/src/reports/Graph.js b/modern/src/reports/Graph.js
new file mode 100644
index 0000000..af54e10
--- /dev/null
+++ b/modern/src/reports/Graph.js
@@ -0,0 +1,35 @@
+import React from 'react';
+import { Box, Paper } from '@material-ui/core';
+import {LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, Legend, ResponsiveContainer } from 'recharts';
+
+const CustomizedAxisTick = ({ x, y, payload }) =>{
+ const parts = payload.value.split(' ');
+ return (
+ <g transform={`translate(${x},${y})`}>
+ <text x={0} y={0} dy={16} textAnchor="end" fill="#666" transform="rotate(-35)">{parts[0]}</text>
+ <text x={0} y={16} dy={16} textAnchor="end" fill="#666" transform="rotate(-35)">{parts[1]}</text>
+ </g>
+ );
+}
+
+const Graph = ({ type, items }) => {
+
+ return (
+ <Paper>
+ <Box height={400}>
+ <ResponsiveContainer>
+ <LineChart data={items}>
+ <XAxis dataKey="fixTime" tick={<CustomizedAxisTick/>} height={60} />
+ <YAxis />
+ <CartesianGrid strokeDasharray="3 3" />
+ <Tooltip />
+ <Legend />
+ <Line type="natural" dataKey={type} />
+ </LineChart>
+ </ResponsiveContainer>
+ </Box>
+ </Paper>
+ );
+}
+
+export default Graph;
diff --git a/modern/src/reports/ReportLayoutPage.js b/modern/src/reports/ReportLayoutPage.js
index ddc7325..d6fac05 100644
--- a/modern/src/reports/ReportLayoutPage.js
+++ b/modern/src/reports/ReportLayoutPage.js
@@ -18,7 +18,7 @@ const useStyles = makeStyles(theme => ({
},
}));
-const ReportLayoutPage = ({ reportFilterForm:ReportFilterForm, setItems, children }) => {
+const ReportLayoutPage = ({ children, filter }) => {
const classes = useStyles();
return (
<div className={classes.root}>
@@ -27,7 +27,7 @@ const ReportLayoutPage = ({ reportFilterForm:ReportFilterForm, setItems, childre
<Grid container spacing={2}>
<Grid item xs={12} md={3} lg={2}>
<Paper className={classes.form}>
- <ReportFilterForm setItems={ setItems } />
+ {filter}
</Paper>
</Grid>
<Grid item xs={12} md={9} lg={10}>
diff --git a/modern/src/reports/RouteReportPage.js b/modern/src/reports/RouteReportPage.js
index 43d310b..f2b0361 100644
--- a/modern/src/reports/RouteReportPage.js
+++ b/modern/src/reports/RouteReportPage.js
@@ -5,7 +5,7 @@ import { formatPosition } from '../common/formatter';
import ReportFilter from './ReportFilter';
import ReportLayoutPage from './ReportLayoutPage';
-const ReportFilterForm = ({ setItems }) => {
+const Filter = ({ setItems }) => {
const handleSubmit = async (deviceId, from, to, mail, headers) => {
const query = new URLSearchParams({ deviceId, from, to, mail });
@@ -30,7 +30,7 @@ const RouteReportPage = () => {
const [items, setItems] = useState([]);
return (
- <ReportLayoutPage reportFilterForm={ReportFilterForm} setItems={setItems}>
+ <ReportLayoutPage filter={<Filter setItems={setItems} />}>
<TableContainer component={Paper}>
<Table>
<TableHead>
diff --git a/modern/src/reports/StopReportPage.js b/modern/src/reports/StopReportPage.js
index 77d3dfa..d06997e 100644
--- a/modern/src/reports/StopReportPage.js
+++ b/modern/src/reports/StopReportPage.js
@@ -6,7 +6,7 @@ import ReportFilter from './ReportFilter';
import ReportLayoutPage from './ReportLayoutPage';
import { useAttributePreference } from '../common/preferences';
-const ReportFilterForm = ({ setItems }) => {
+const Filter = ({ setItems }) => {
const handleSubmit = async (deviceId, from, to, mail, headers) => {
const query = new URLSearchParams({ deviceId, from, to, mail });
@@ -32,7 +32,7 @@ const StopReportPage = () => {
const [items, setItems] = useState([]);
return (
- <ReportLayoutPage reportFilterForm={ReportFilterForm} setItems={setItems}>
+ <ReportLayoutPage filter={<Filter setItems={setItems} />}>
<TableContainer component={Paper}>
<Table>
<TableHead>
diff --git a/modern/src/reports/SummaryReportPage.js b/modern/src/reports/SummaryReportPage.js
index dcd3323..5cfd857 100644
--- a/modern/src/reports/SummaryReportPage.js
+++ b/modern/src/reports/SummaryReportPage.js
@@ -6,7 +6,7 @@ import ReportFilter from './ReportFilter';
import ReportLayoutPage from './ReportLayoutPage';
import { useAttributePreference } from '../common/preferences';
-const ReportFilterForm = ({ setItems }) => {
+const Filter = ({ setItems }) => {
const [daily, setDaily] = useState(false);
@@ -41,7 +41,7 @@ const SummaryReportPage = () => {
const [items, setItems] = useState([]);
return (
- <ReportLayoutPage reportFilterForm={ReportFilterForm} setItems={setItems}>
+ <ReportLayoutPage filter={<Filter setItems={setItems} />}>
<TableContainer component={Paper}>
<Table>
<TableHead>
diff --git a/modern/src/reports/TripReportPage.js b/modern/src/reports/TripReportPage.js
index 10f1c46..c1ba664 100644
--- a/modern/src/reports/TripReportPage.js
+++ b/modern/src/reports/TripReportPage.js
@@ -6,7 +6,7 @@ import ReportFilter from './ReportFilter';
import ReportLayoutPage from './ReportLayoutPage';
import { useAttributePreference } from '../common/preferences';
-const ReportFilterForm = ({ setItems }) => {
+const Filter = ({ setItems }) => {
const handleSubmit = async (deviceId, from, to, mail, headers) => {
const query = new URLSearchParams({ deviceId, from, to, mail });
@@ -33,7 +33,7 @@ const TripReportPage = () => {
const [items, setItems] = useState([]);
return (
- <ReportLayoutPage reportFilterForm={ReportFilterForm} setItems={setItems}>
+ <ReportLayoutPage filter={<Filter setItems={setItems} />}>
<TableContainer component={Paper}>
<Table>
<TableHead>