aboutsummaryrefslogtreecommitdiff
path: root/modern/src
diff options
context:
space:
mode:
Diffstat (limited to 'modern/src')
-rw-r--r--modern/src/App.js68
-rw-r--r--modern/src/CachingController.js22
-rw-r--r--modern/src/DevicePage.js95
-rw-r--r--modern/src/DevicesList.js15
-rw-r--r--modern/src/EditCollectionView.js27
-rw-r--r--modern/src/EditItemView.js16
-rw-r--r--modern/src/GeofencePage.js22
-rw-r--r--modern/src/GeofencesList.js12
-rw-r--r--modern/src/GeofencesPage.js27
-rw-r--r--modern/src/Logo.js47
-rw-r--r--modern/src/MainPage.js11
-rw-r--r--modern/src/MainToolbar.js16
-rw-r--r--modern/src/PositionPage.js29
-rw-r--r--modern/src/RegisterDialog.js61
-rw-r--r--modern/src/RemoveDialog.js9
-rw-r--r--modern/src/SocketController.js26
-rw-r--r--modern/src/StartPage.js19
-rw-r--r--modern/src/UserPage.js47
-rw-r--r--modern/src/admin/ServerPage.js77
-rw-r--r--modern/src/admin/StatisticsPage.js27
-rw-r--r--modern/src/admin/UsersPage.js82
-rw-r--r--modern/src/attributes/AddAttributeDialog.js36
-rw-r--r--modern/src/attributes/EditAttributesView.js83
-rw-r--r--modern/src/attributes/deviceAttributes.js4
-rw-r--r--modern/src/attributes/geofenceAttributes.js4
-rw-r--r--modern/src/attributes/positionAttributes.js10
-rw-r--r--modern/src/attributes/userAttributes.js12
-rw-r--r--modern/src/common/converter.js24
-rw-r--r--modern/src/common/formatter.js48
-rw-r--r--modern/src/common/preferences.js30
-rw-r--r--modern/src/common/stringUtils.js8
-rw-r--r--modern/src/components/NavBar.js4
-rw-r--r--modern/src/components/SideNav.js42
-rw-r--r--modern/src/components/registration/LoginForm.js71
-rw-r--r--modern/src/components/registration/RegisterForm.js82
-rw-r--r--modern/src/components/registration/ResetPasswordForm.js13
-rw-r--r--modern/src/form/LinkField.js30
-rw-r--r--modern/src/form/SelectField.js23
-rw-r--r--modern/src/index.js4
-rw-r--r--modern/src/map/AccuracyMap.js36
-rw-r--r--modern/src/map/CurrentLocationMap.js2
-rw-r--r--modern/src/map/CurrentPositionsMap.js6
-rw-r--r--modern/src/map/GeofenceEditMap.js32
-rw-r--r--modern/src/map/GeofenceMap.js56
-rw-r--r--modern/src/map/Map.js16
-rw-r--r--modern/src/map/PositionsMap.js71
-rw-r--r--modern/src/map/ReplayPathMap.js28
-rw-r--r--modern/src/map/SelectedDeviceMap.js4
-rw-r--r--modern/src/map/StatusView.js65
-rw-r--r--modern/src/map/mapStyles.js42
-rw-r--r--modern/src/map/mapUtil.js57
-rw-r--r--modern/src/reactHelper.js3
-rw-r--r--modern/src/reports/ChartReportPage.js69
-rw-r--r--modern/src/reports/EventReportPage.js39
-rw-r--r--modern/src/reports/Graph.js37
-rw-r--r--modern/src/reports/ReplayPage.js36
-rw-r--r--modern/src/reports/ReportFilter.js85
-rw-r--r--modern/src/reports/ReportLayout.js34
-rw-r--r--modern/src/reports/RouteReportPage.js24
-rw-r--r--modern/src/reports/StopReportPage.js33
-rw-r--r--modern/src/reports/SummaryReportPage.js38
-rw-r--r--modern/src/reports/TripReportPage.js33
-rw-r--r--modern/src/settings/ComputedAttributePage.js60
-rw-r--r--modern/src/settings/ComputedAttributesPage.js80
-rw-r--r--modern/src/settings/DriverPage.js27
-rw-r--r--modern/src/settings/DriversPage.js74
-rw-r--r--modern/src/settings/GroupPage.js27
-rw-r--r--modern/src/settings/GroupsPage.js70
-rw-r--r--modern/src/settings/MaintenancePage.js90
-rw-r--r--modern/src/settings/MaintenancesPage.js84
-rw-r--r--modern/src/settings/NotificationPage.js56
-rw-r--r--modern/src/settings/NotificationsPage.js80
-rw-r--r--modern/src/settings/OptionsLayout/useRoutes.js26
-rw-r--r--modern/src/setupProxy.js4
-rw-r--r--modern/src/store/devices.js8
-rw-r--r--modern/src/store/drivers.js4
-rw-r--r--modern/src/store/geofences.js6
-rw-r--r--modern/src/store/groups.js4
-rw-r--r--modern/src/store/maintenances.js4
-rw-r--r--modern/src/store/positions.js4
-rw-r--r--modern/src/theme/dimensions.js2
-rw-r--r--modern/src/theme/index.js2
-rw-r--r--modern/src/theme/overrides.js50
83 files changed, 1502 insertions, 1389 deletions
diff --git a/modern/src/App.js b/modern/src/App.js
index b76995e..ac7cdb2 100644
--- a/modern/src/App.js
+++ b/modern/src/App.js
@@ -1,7 +1,9 @@
import React from 'react';
import { ThemeProvider } from '@material-ui/core/styles';
-import { Switch, Route } from 'react-router-dom'
+import { Switch, Route } from 'react-router-dom';
import CssBaseline from '@material-ui/core/CssBaseline';
+import { useSelector } from 'react-redux';
+import { LinearProgress } from '@material-ui/core';
import MainPage from './MainPage';
import RouteReportPage from './reports/RouteReportPage';
import ServerPage from './admin/ServerPage';
@@ -16,8 +18,6 @@ import GroupPage from './settings/GroupPage';
import PositionPage from './PositionPage';
import EventReportPage from './reports/EventReportPage';
import ReplayPage from './reports/ReplayPage';
-import { useSelector } from 'react-redux';
-import { LinearProgress } from '@material-ui/core';
import TripReportPage from './reports/TripReportPage';
import StopReportPage from './reports/StopReportPage';
import SummaryReportPage from './reports/SummaryReportPage';
@@ -40,7 +40,7 @@ import GeofencesPage from './GeofencesPage';
import GeofencePage from './GeofencePage';
const App = () => {
- const initialized = useSelector(state => !!state.session.server && !!state.session.user);
+ const initialized = useSelector((state) => !!state.session.server && !!state.session.user);
return (
<ThemeProvider theme={theme}>
@@ -48,44 +48,44 @@ const App = () => {
<SocketController />
<CachingController />
<Switch>
- <Route exact path='/login' component={LoginForm} />
- <Route exact path='/register' component={RegisterForm} />
- <Route exact path='/reset-password' component={ResetPasswordForm} />
+ <Route exact path="/login" component={LoginForm} />
+ <Route exact path="/register" component={RegisterForm} />
+ <Route exact path="/reset-password" component={ResetPasswordForm} />
<Route>
{!initialized ? (<LinearProgress />) : (
<Switch>
- <Route exact path='/' component={MainPage} />
- <Route exact path='/replay' component={ReplayPage} />
- <Route exact path='/position/:id?' component={PositionPage} />
- <Route exact path='/user/:id?' component={UserPage} />
- <Route exact path='/device/:id?' component={DevicePage} />
- <Route exact path='/geofence/:id?' component={GeofencePage} />
- <Route exact path='/geofences' component={GeofencesPage} />
- <Route exact path='/settings/notifications' component={NotificationsPage} />
- <Route exact path='/settings/notification/:id?' component={NotificationPage} />
- <Route exact path='/settings/groups' component={GroupsPage} />
- <Route exact path='/settings/group/:id?' component={GroupPage} />
- <Route exact path='/settings/drivers' component={DriversPage} />
- <Route exact path='/settings/driver/:id?' component={DriverPage} />
- <Route exact path='/settings/attributes' component={ComputedAttributesPage} />
- <Route exact path='/settings/attribute/:id?' component={ComputedAttributePage} />
- <Route exact path='/settings/maintenances' component={MaintenancesPage} />
- <Route exact path='/settings/maintenance/:id?' component={MaintenancePage} />
- <Route exact path='/admin/server' component={ServerPage} />
- <Route exact path='/admin/users' component={UsersPage} />
- <Route exact path='/admin/statistics' component={StatisticsPage} />
- <Route exact path='/reports/route' component={RouteReportPage} />
- <Route exact path='/reports/event' component={EventReportPage} />
- <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} />
+ <Route exact path="/" component={MainPage} />
+ <Route exact path="/replay" component={ReplayPage} />
+ <Route exact path="/position/:id?" component={PositionPage} />
+ <Route exact path="/user/:id?" component={UserPage} />
+ <Route exact path="/device/:id?" component={DevicePage} />
+ <Route exact path="/geofence/:id?" component={GeofencePage} />
+ <Route exact path="/geofences" component={GeofencesPage} />
+ <Route exact path="/settings/notifications" component={NotificationsPage} />
+ <Route exact path="/settings/notification/:id?" component={NotificationPage} />
+ <Route exact path="/settings/groups" component={GroupsPage} />
+ <Route exact path="/settings/group/:id?" component={GroupPage} />
+ <Route exact path="/settings/drivers" component={DriversPage} />
+ <Route exact path="/settings/driver/:id?" component={DriverPage} />
+ <Route exact path="/settings/attributes" component={ComputedAttributesPage} />
+ <Route exact path="/settings/attribute/:id?" component={ComputedAttributePage} />
+ <Route exact path="/settings/maintenances" component={MaintenancesPage} />
+ <Route exact path="/settings/maintenance/:id?" component={MaintenancePage} />
+ <Route exact path="/admin/server" component={ServerPage} />
+ <Route exact path="/admin/users" component={UsersPage} />
+ <Route exact path="/admin/statistics" component={StatisticsPage} />
+ <Route exact path="/reports/route" component={RouteReportPage} />
+ <Route exact path="/reports/event" component={EventReportPage} />
+ <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>
</Switch>
</ThemeProvider>
);
-}
+};
export default App;
diff --git a/modern/src/CachingController.js b/modern/src/CachingController.js
index 3f808de..d6e2006 100644
--- a/modern/src/CachingController.js
+++ b/modern/src/CachingController.js
@@ -1,10 +1,12 @@
-import { useDispatch, useSelector } from 'react-redux';
-import { connect } from 'react-redux';
-import { geofencesActions, groupsActions, driversActions, maintenancesActions } from './store';
+import { useDispatch, useSelector, connect } from 'react-redux';
+
+import {
+ geofencesActions, groupsActions, driversActions, maintenancesActions,
+} from './store';
import { useEffectAsync } from './reactHelper';
const CachingController = () => {
- const authenticated = useSelector(state => !!state.session.user);
+ const authenticated = useSelector((state) => !!state.session.user);
const dispatch = useDispatch();
useEffectAsync(async () => {
@@ -23,8 +25,8 @@ const CachingController = () => {
dispatch(groupsActions.update(await response.json()));
}
}
- }, [authenticated]);
-
+ }, [authenticated]);
+
useEffectAsync(async () => {
if (authenticated) {
const response = await fetch('/api/drivers');
@@ -33,7 +35,7 @@ const CachingController = () => {
}
}
}, [authenticated]);
-
+
useEffectAsync(async () => {
if (authenticated) {
const response = await fetch('/api/maintenance');
@@ -41,9 +43,9 @@ const CachingController = () => {
dispatch(maintenancesActions.update(await response.json()));
}
}
- }, [authenticated]);
-
+ }, [authenticated]);
+
return null;
-}
+};
export default connect()(CachingController);
diff --git a/modern/src/DevicePage.js b/modern/src/DevicePage.js
index ed5a6cb..a20ba22 100644
--- a/modern/src/DevicePage.js
+++ b/modern/src/DevicePage.js
@@ -1,10 +1,12 @@
import React, { useState } from 'react';
import TextField from '@material-ui/core/TextField';
+import {
+ Accordion, AccordionSummary, AccordionDetails, makeStyles, Typography, FormControlLabel, Checkbox,
+} from '@material-ui/core';
+import ExpandMoreIcon from '@material-ui/icons/ExpandMore';
import t from './common/localization';
import EditItemView from './EditItemView';
-import { Accordion, AccordionSummary, AccordionDetails, makeStyles, Typography, FormControlLabel, Checkbox } from '@material-ui/core';
-import ExpandMoreIcon from '@material-ui/icons/ExpandMore';
import EditAttributesView from './attributes/EditAttributesView';
import deviceAttributes from './attributes/deviceAttributes';
import SelectField from './form/SelectField';
@@ -25,7 +27,8 @@ const DevicePage = () => {
return (
<EditItemView endpoint="devices" item={item} setItem={setItem}>
- {item &&
+ {item
+ && (
<>
<Accordion defaultExpanded>
<AccordionSummary expandIcon={<ExpandMoreIcon />}>
@@ -37,15 +40,17 @@ const DevicePage = () => {
<TextField
margin="normal"
value={item.name || ''}
- onChange={event => setItem({...item, name: event.target.value})}
+ onChange={(event) => setItem({ ...item, name: event.target.value })}
label={t('sharedName')}
- variant="filled" />
+ variant="filled"
+ />
<TextField
margin="normal"
value={item.uniqueId || ''}
- onChange={event => setItem({...item, uniqueId: event.target.value})}
+ onChange={(event) => setItem({ ...item, uniqueId: event.target.value })}
label={t('deviceIdentifier')}
- variant="filled" />
+ variant="filled"
+ />
</AccordionDetails>
</Accordion>
<Accordion>
@@ -58,42 +63,48 @@ const DevicePage = () => {
<SelectField
margin="normal"
value={item.groupId || 0}
- onChange={event => setItem({...item, groupId: Number(event.target.value)})}
+ onChange={(event) => setItem({ ...item, groupId: Number(event.target.value) })}
endpoint="/api/groups"
label={t('groupParent')}
- variant="filled" />
+ variant="filled"
+ />
<TextField
margin="normal"
value={item.phone || ''}
- onChange={event => setItem({...item, phone: event.target.value})}
+ onChange={(event) => setItem({ ...item, phone: event.target.value })}
label={t('sharedPhone')}
- variant="filled" />
+ variant="filled"
+ />
<TextField
margin="normal"
value={item.model || ''}
- onChange={event => setItem({...item, model: event.target.value})}
+ onChange={(event) => setItem({ ...item, model: event.target.value })}
label={t('deviceModel')}
- variant="filled" />
+ variant="filled"
+ />
<TextField
margin="normal"
value={item.contact || ''}
- onChange={event => setItem({...item, contact: event.target.value})}
+ onChange={(event) => setItem({ ...item, contact: event.target.value })}
label={t('deviceContact')}
- variant="filled" />
+ variant="filled"
+ />
<SelectField
margin="normal"
value={item.category || 'default'}
emptyValue={null}
- onChange={event => setItem({...item, category: event.target.value})}
- data={deviceCategories.map(category => ({
+ onChange={(event) => setItem({ ...item, category: event.target.value })}
+ data={deviceCategories.map((category) => ({
id: category,
- name: t(`category${category.replace(/^\w/, c => c.toUpperCase())}`)
+ name: t(`category${category.replace(/^\w/, (c) => c.toUpperCase())}`),
}))}
label={t('deviceCategory')}
- variant="filled" />
+ variant="filled"
+ />
<FormControlLabel
- control={<Checkbox checked={item.disabled} onChange={event => setItem({...item, disabled: event.target.checked})} />}
- label={t('sharedDisabled')} />
+ control={<Checkbox checked={item.disabled} onChange={(event) => setItem({ ...item, disabled: event.target.checked })} />}
+ label={t('sharedDisabled')}
+ />
</AccordionDetails>
</Accordion>
<Accordion>
@@ -105,12 +116,13 @@ const DevicePage = () => {
<AccordionDetails className={classes.details}>
<EditAttributesView
attributes={item.attributes}
- setAttributes={attributes => setItem({...item, attributes})}
+ setAttributes={(attributes) => setItem({ ...item, attributes })}
definitions={deviceAttributes}
- />
+ />
</AccordionDetails>
</Accordion>
- {item.id &&
+ {item.id
+ && (
<Accordion>
<AccordionSummary expandIcon={<ExpandMoreIcon />}>
<Typography variant="subtitle1">
@@ -121,57 +133,62 @@ const DevicePage = () => {
<LinkField
margin="normal"
endpointAll="/api/geofences"
- endpointLinked={"/api/geofences?deviceId=" + item.id}
+ endpointLinked={`/api/geofences?deviceId=${item.id}`}
baseId={item.id}
keyBase="deviceId"
keyLink="geofenceId"
label={t('sharedGeofences')}
- variant="filled" />
+ variant="filled"
+ />
<LinkField
margin="normal"
endpointAll="/api/notifications"
- endpointLinked={"/api/notifications?deviceId=" + item.id}
+ endpointLinked={`/api/notifications?deviceId=${item.id}`}
baseId={item.id}
keyBase="deviceId"
keyLink="notificationId"
- titleGetter={it => t(prefixString('event', it.type))}
+ titleGetter={(it) => t(prefixString('event', it.type))}
label={t('sharedNotifications')}
- variant="filled" />
+ variant="filled"
+ />
<LinkField
margin="normal"
endpointAll="/api/drivers"
- endpointLinked={"/api/drivers?deviceId=" + item.id}
+ endpointLinked={`/api/drivers?deviceId=${item.id}`}
baseId={item.id}
keyBase="deviceId"
keyLink="driverId"
label={t('sharedDrivers')}
- variant="filled" />
+ variant="filled"
+ />
<LinkField
margin="normal"
endpointAll="/api/attributes/computed"
- endpointLinked={"/api/attributes/computed?deviceId=" + item.id}
+ endpointLinked={`/api/attributes/computed?deviceId=${item.id}`}
baseId={item.id}
keyBase="deviceId"
keyLink="attributeId"
- titleGetter={it => it.description}
+ titleGetter={(it) => it.description}
label={t('sharedComputedAttributes')}
- variant="filled" />
+ variant="filled"
+ />
<LinkField
margin="normal"
endpointAll="/api/maintenance"
- endpointLinked={"/api/maintenance?deviceId=" + item.id}
+ endpointLinked={`/api/maintenance?deviceId=${item.id}`}
baseId={item.id}
keyBase="deviceId"
keyLink="maintenanceId"
label={t('sharedMaintenance')}
- variant="filled" />
+ variant="filled"
+ />
</AccordionDetails>
</Accordion>
- }
+ )}
</>
- }
+ )}
</EditItemView>
);
-}
+};
export default DevicePage;
diff --git a/modern/src/DevicesList.js b/modern/src/DevicesList.js
index f66d717..85b936c 100644
--- a/modern/src/DevicesList.js
+++ b/modern/src/DevicesList.js
@@ -34,7 +34,7 @@ const DeviceRow = ({ data, index, style }) => {
const { items, onMenuClick } = data;
const item = items[index];
-
+
return (
<div style={style}>
<Fragment key={index}>
@@ -61,7 +61,7 @@ const DeviceView = ({ updateTimestamp, onMenuClick }) => {
const classes = useStyles();
const dispatch = useDispatch();
- const items = useSelector(state => Object.values(state.devices.items));
+ const items = useSelector((state) => Object.values(state.devices.items));
useEffectAsync(async () => {
const response = await fetch('/api/devices');
@@ -79,7 +79,8 @@ const DeviceView = ({ updateTimestamp, onMenuClick }) => {
height={height}
itemCount={items.length}
itemData={{ items, onMenuClick }}
- itemSize={72 + 1} >
+ itemSize={72 + 1}
+ >
{DeviceRow}
</FixedSizeList>
</List>
@@ -88,10 +89,8 @@ const DeviceView = ({ updateTimestamp, onMenuClick }) => {
);
};
-const DevicesList = () => {
- return (
- <EditCollectionView content={DeviceView} editPath="/device" endpoint="devices" />
- );
-};
+const DevicesList = () => (
+ <EditCollectionView content={DeviceView} editPath="/device" endpoint="devices" />
+);
export default DevicesList;
diff --git a/modern/src/EditCollectionView.js b/modern/src/EditCollectionView.js
index 572a1d1..7d5e4b2 100644
--- a/modern/src/EditCollectionView.js
+++ b/modern/src/EditCollectionView.js
@@ -10,7 +10,7 @@ import { useSelector } from 'react-redux';
import t from './common/localization';
import RemoveDialog from './RemoveDialog';
-const useStyles = makeStyles(theme => ({
+const useStyles = makeStyles((theme) => ({
fab: {
position: 'absolute',
bottom: theme.spacing(2),
@@ -18,7 +18,9 @@ const useStyles = makeStyles(theme => ({
},
}));
-const EditCollectionView = ({ content, editPath, endpoint, disableAdd }) => {
+const EditCollectionView = ({
+ content, editPath, endpoint, disableAdd,
+}) => {
const classes = useStyles();
const history = useHistory();
@@ -26,47 +28,48 @@ const EditCollectionView = ({ content, editPath, endpoint, disableAdd }) => {
const [selectedAnchorEl, setSelectedAnchorEl] = useState(null);
const [removeDialogShown, setRemoveDialogShown] = useState(false);
const [updateTimestamp, setUpdateTimestamp] = useState(Date.now());
- const adminEnabled = useSelector(state => state.session.user && state.session.user.administrator);
+ const adminEnabled = useSelector((state) => state.session.user && state.session.user.administrator);
const menuShow = (anchorId, itemId) => {
setSelectedAnchorEl(anchorId);
setSelectedId(itemId);
- }
+ };
const menuHide = () => {
setSelectedAnchorEl(null);
- }
+ };
const handleAdd = () => {
history.push(editPath);
menuHide();
- }
+ };
const handleEdit = () => {
history.push(`${editPath}/${selectedId}`);
menuHide();
- }
+ };
const handleRemove = () => {
setRemoveDialogShown(true);
menuHide();
- }
+ };
const handleRemoveResult = () => {
setRemoveDialogShown(false);
setUpdateTimestamp(Date.now());
- }
+ };
const Content = content;
return (
<>
<Content updateTimestamp={updateTimestamp} onMenuClick={menuShow} />
- {adminEnabled && !disableAdd &&
+ {adminEnabled && !disableAdd
+ && (
<Fab size="medium" color="primary" className={classes.fab} onClick={handleAdd}>
<AddIcon />
</Fab>
- }
+ )}
<Menu open={!!selectedAnchorEl} anchorEl={selectedAnchorEl} onClose={menuHide}>
<MenuItem onClick={handleEdit}>{t('sharedEdit')}</MenuItem>
<MenuItem onClick={handleRemove}>{t('sharedRemove')}</MenuItem>
@@ -74,6 +77,6 @@ const EditCollectionView = ({ content, editPath, endpoint, disableAdd }) => {
<RemoveDialog open={removeDialogShown} endpoint={endpoint} itemId={selectedId} onResult={handleRemoveResult} />
</>
);
-}
+};
export default EditCollectionView;
diff --git a/modern/src/EditItemView.js b/modern/src/EditItemView.js
index bab56c7..a77f578 100644
--- a/modern/src/EditItemView.js
+++ b/modern/src/EditItemView.js
@@ -9,20 +9,22 @@ import t from './common/localization';
import { useEffectAsync } from './reactHelper';
import OptionsLayout from './settings/OptionsLayout';
-const useStyles = makeStyles(theme => ({
+const useStyles = makeStyles((theme) => ({
container: {
- marginTop: theme.spacing(2)
+ marginTop: theme.spacing(2),
},
buttons: {
display: 'flex',
justifyContent: 'space-evenly',
'& > *': {
- flexBasis: '33%'
- }
- }
+ flexBasis: '33%',
+ },
+ },
}));
-const EditItemView = ({ children, endpoint, item, setItem }) => {
+const EditItemView = ({
+ children, endpoint, item, setItem,
+}) => {
const history = useHistory();
const classes = useStyles();
const { id } = useParams();
@@ -47,7 +49,7 @@ const EditItemView = ({ children, endpoint, item, setItem }) => {
const response = await fetch(url, {
method: !id ? 'POST' : 'PUT',
headers: { 'Content-Type': 'application/json' },
- body: JSON.stringify(item)
+ body: JSON.stringify(item),
});
if (response.ok) {
diff --git a/modern/src/GeofencePage.js b/modern/src/GeofencePage.js
index 6c5db9b..06456fc 100644
--- a/modern/src/GeofencePage.js
+++ b/modern/src/GeofencePage.js
@@ -1,10 +1,12 @@
import React, { useState } from 'react';
import TextField from '@material-ui/core/TextField';
+import {
+ Accordion, AccordionSummary, AccordionDetails, makeStyles, Typography,
+} from '@material-ui/core';
+import ExpandMoreIcon from '@material-ui/icons/ExpandMore';
import t from './common/localization';
import EditItemView from './EditItemView';
-import { Accordion, AccordionSummary, AccordionDetails, makeStyles, Typography } from '@material-ui/core';
-import ExpandMoreIcon from '@material-ui/icons/ExpandMore';
import EditAttributesView from './attributes/EditAttributesView';
import geofenceAttributes from './attributes/geofenceAttributes';
@@ -21,7 +23,8 @@ const GeofencePage = () => {
return (
<EditItemView endpoint="geofences" item={item} setItem={setItem}>
- {item &&
+ {item
+ && (
<>
<Accordion defaultExpanded>
<AccordionSummary expandIcon={<ExpandMoreIcon />}>
@@ -33,9 +36,10 @@ const GeofencePage = () => {
<TextField
margin="normal"
value={item.name || ''}
- onChange={event => setItem({...item, name: event.target.value})}
+ onChange={(event) => setItem({ ...item, name: event.target.value })}
label={t('sharedName')}
- variant="filled" />
+ variant="filled"
+ />
</AccordionDetails>
</Accordion>
<Accordion>
@@ -47,15 +51,15 @@ const GeofencePage = () => {
<AccordionDetails className={classes.details}>
<EditAttributesView
attributes={item.attributes}
- setAttributes={attributes => setItem({...item, attributes})}
+ setAttributes={(attributes) => setItem({ ...item, attributes })}
definitions={geofenceAttributes}
- />
+ />
</AccordionDetails>
</Accordion>
</>
- }
+ )}
</EditItemView>
);
-}
+};
export default GeofencePage;
diff --git a/modern/src/GeofencesList.js b/modern/src/GeofencesList.js
index 2988bef..572ac5b 100644
--- a/modern/src/GeofencesList.js
+++ b/modern/src/GeofencesList.js
@@ -28,7 +28,7 @@ const GeofenceView = ({ onMenuClick }) => {
const classes = useStyles();
const dispatch = useDispatch();
- const items = useSelector(state => Object.values(state.geofences.items));
+ const items = useSelector((state) => Object.values(state.geofences.items));
return (
<List className={classes.list}>
@@ -47,12 +47,10 @@ const GeofenceView = ({ onMenuClick }) => {
))}
</List>
);
-}
+};
-const GeofencesList = () => {
- return (
- <EditCollectionView content={GeofenceView} editPath="/geofence" endpoint="geofences" disableAdd />
- );
-}
+const GeofencesList = () => (
+ <EditCollectionView content={GeofenceView} editPath="/geofence" endpoint="geofences" disableAdd />
+);
export default GeofencesList;
diff --git a/modern/src/GeofencesPage.js b/modern/src/GeofencesPage.js
index 59b8459..71219c1 100644
--- a/modern/src/GeofencesPage.js
+++ b/modern/src/GeofencesPage.js
@@ -1,21 +1,22 @@
import React from 'react';
-import { Divider, isWidthUp, makeStyles, withWidth, Typography, IconButton } from '@material-ui/core';
+import {
+ Divider, isWidthUp, makeStyles, withWidth, Typography, IconButton,
+} from '@material-ui/core';
import Drawer from '@material-ui/core/Drawer';
import ContainerDimensions from 'react-container-dimensions';
+import ArrowBackIcon from '@material-ui/icons/ArrowBack';
import Map from './map/Map';
import CurrentLocationMap from './map/CurrentLocationMap';
import GeofenceEditMap from './map/GeofenceEditMap';
import GeofencesList from './GeofencesList';
-import ArrowBackIcon from '@material-ui/icons/ArrowBack';
-
import t from './common/localization';
-const useStyles = makeStyles(theme => ({
+const useStyles = makeStyles((theme) => ({
root: {
height: '100%',
display: 'flex',
- flexDirection: 'column'
+ flexDirection: 'column',
},
content: {
flexGrow: 1,
@@ -23,27 +24,27 @@ const useStyles = makeStyles(theme => ({
display: 'flex',
flexDirection: 'row',
[theme.breakpoints.down('xs')]: {
- flexDirection: 'column-reverse'
- }
+ flexDirection: 'column-reverse',
+ },
},
drawerPaper: {
position: 'relative',
[theme.breakpoints.up('sm')]: {
- width: 350
+ width: 350,
},
[theme.breakpoints.down('xs')]: {
- height: 250
- }
+ height: 250,
+ },
},
drawerHeader: {
...theme.mixins.toolbar,
display: 'flex',
alignItems: 'center',
- padding: theme.spacing(0, 1)
+ padding: theme.spacing(0, 1),
},
mapContainer: {
- flexGrow: 1
- }
+ flexGrow: 1,
+ },
}));
const GeofencesPage = ({ width }) => {
diff --git a/modern/src/Logo.js b/modern/src/Logo.js
index bea14d8..1fb1ac8 100644
--- a/modern/src/Logo.js
+++ b/modern/src/Logo.js
@@ -1,31 +1,28 @@
import React from 'react';
-const Logo = ({ fill }) => {
-
- return (
- <svg xmlns='http://www.w3.org/2000/svg' height="64" viewBox="0 0 240 64" width="240" version="1.1">
- <g id="layer1">
- <rect id="rect3778" height="64" width="236.1" y="0" x="0" fill="none"/>
- <ellipse id="path3038" rx="28.995" ry="28.995" transform="rotate(-30)" cy="43.713" cx="11.713" stroke-width="10.699" fill="#fff"/>
- <g fill= {fill}>
- <circle id="path2993" strokeWidth="1.3262" transform="rotate(-30)" cy="43.713" cx="9.4364" r="2.2765"/>
- <path id="path3004" d="m37.012 24.177-2.8428 3.6128c0.66345 0.52205 1.3255 1.1576 1.7734 1.9333 0.4479 0.77578 0.66726 1.6669 0.78764 2.5025l4.5502-0.65558c-0.193-1.42-0.633-2.804-1.394-4.123s-1.74-2.391-2.874-3.27z" strokeWidth="1.0095"/>
- <path id="path3014" d="m42.504 16.9-2.8428 3.6128c1.607 1.2355 3.0914 2.7935 4.1679 4.6581s1.6835 3.9291 1.95 5.9386l4.5502-0.65558c-0.33967-2.5954-1.1669-5.1513-2.5573-7.5594-1.3903-2.4081-3.1901-4.4025-5.268-5.9944z" strokeWidth="1.0095"/>
- <path id="path3036" d="m2.607 52.819a9.1058 9.1058 0 0 1 -7.8859 -4.5529 9.1058 9.1058 0 0 1 0 -9.1058 9.1058 9.1058 0 0 1 7.8859 -4.5529l-2e-7 9.1058z" transform="rotate(-30)" strokeWidth="3.6204"/>
- <path id="path3038-8" d="m17.502 6.8895c-13.868 8.0065-18.619 25.74-10.612 39.608 8.006 13.868 25.739 18.619 39.608 10.613 13.868-8.007 18.619-25.74 10.613-39.609-8.007-13.868-25.74-18.619-39.609-10.612zm1.706 2.9541c12.237-7.0648 27.884-2.8722 34.948 9.3644 7.065 12.237 2.873 27.884-9.364 34.948-12.237 7.065-27.884 2.873-34.948-9.364-7.0652-12.237-2.8726-27.884 9.364-34.948z" strokeWidth="1.0095"/>
+const Logo = ({ fill }) => (
+ <svg xmlns="http://www.w3.org/2000/svg" height="64" viewBox="0 0 240 64" width="240" version="1.1">
+ <g id="layer1">
+ <rect id="rect3778" height="64" width="236.1" y="0" x="0" fill="none" />
+ <ellipse id="path3038" rx="28.995" ry="28.995" transform="rotate(-30)" cy="43.713" cx="11.713" strokeWidth="10.699" fill="#fff" />
+ <g fill={fill}>
+ <circle id="path2993" strokeWidth="1.3262" transform="rotate(-30)" cy="43.713" cx="9.4364" r="2.2765" />
+ <path id="path3004" d="m37.012 24.177-2.8428 3.6128c0.66345 0.52205 1.3255 1.1576 1.7734 1.9333 0.4479 0.77578 0.66726 1.6669 0.78764 2.5025l4.5502-0.65558c-0.193-1.42-0.633-2.804-1.394-4.123s-1.74-2.391-2.874-3.27z" strokeWidth="1.0095" />
+ <path id="path3014" d="m42.504 16.9-2.8428 3.6128c1.607 1.2355 3.0914 2.7935 4.1679 4.6581s1.6835 3.9291 1.95 5.9386l4.5502-0.65558c-0.33967-2.5954-1.1669-5.1513-2.5573-7.5594-1.3903-2.4081-3.1901-4.4025-5.268-5.9944z" strokeWidth="1.0095" />
+ <path id="path3036" d="m2.607 52.819a9.1058 9.1058 0 0 1 -7.8859 -4.5529 9.1058 9.1058 0 0 1 0 -9.1058 9.1058 9.1058 0 0 1 7.8859 -4.5529l-2e-7 9.1058z" transform="rotate(-30)" strokeWidth="3.6204" />
+ <path id="path3038-8" d="m17.502 6.8895c-13.868 8.0065-18.619 25.74-10.612 39.608 8.006 13.868 25.739 18.619 39.608 10.613 13.868-8.007 18.619-25.74 10.613-39.609-8.007-13.868-25.74-18.619-39.609-10.612zm1.706 2.9541c12.237-7.0648 27.884-2.8722 34.948 9.3644 7.065 12.237 2.873 27.884-9.364 34.948-12.237 7.065-27.884 2.873-34.948-9.364-7.0652-12.237-2.8726-27.884 9.364-34.948z" strokeWidth="1.0095" />
<g id="text3003" ariaLabel="Traccar">
- <path id="path4172" d="m89.719 48.671h-3.915v-30.192h-10.663v-3.4775h25.241v3.4775h-10.663v30.192z"/>
- <path id="path4174" d="m116.36 22.969q1.6812 0 3.0169 0.27636l-0.52968 3.5466q-1.566-0.34544-2.7636-0.34544-3.063 0-5.2508 2.4872-2.1648 2.4872-2.1648 6.195v13.541h-3.8229v-25.241h3.1551l0.43756 4.675h0.18424q1.4048-2.4642 3.3854-3.7999t4.3526-1.3357z"/>
- <path id="path4176" d="m139.62 48.671-0.75998-3.5926h-0.18424q-1.8884 2.3721-3.7769 3.2242-1.8654 0.82907-4.675 0.82907-3.7538 0-5.8956-1.9345-2.1187-1.9345-2.1187-5.5041 0-7.6459 12.229-8.0143l4.2835-0.13818v-1.566q0-2.9708-1.2897-4.3756-1.2666-1.4278-4.0763-1.4278-3.1551 0-7.1392 1.9345l-1.1745-2.9248q1.8654-1.0133 4.0762-1.589 2.2339-0.57574 4.4678-0.57574 4.5138 0 6.6786 2.0036 2.1878 2.0036 2.1878 6.4253v17.226h-2.8326zm-8.6361-2.6945q3.5696 0 5.5962-1.9575 2.0496-1.9575 2.0496-5.4811v-2.2799l-3.8229 0.16121q-4.5599 0.16121-6.5865 1.4278-2.0036 1.2436-2.0036 3.892 0 2.0727 1.2436 3.1551 1.2666 1.0824 3.5236 1.0824z"/>
- <path id="path4178" d="m160.44 49.131q-5.4811 0-8.498-3.3623-2.9939-3.3854-2.9939-9.5573 0-6.3332 3.0399-9.7876 3.063-3.4545 8.7052-3.4545 1.8194 0 3.6387 0.3915t2.8557 0.92119l-1.1745 3.2472q-1.2666-0.50665-2.7636-0.82907-1.4969-0.34544-2.6484-0.34544-7.6919 0-7.6919 9.8106 0 4.652 1.8654 7.1392 1.8884 2.4872 5.5732 2.4872 3.1551 0 6.4713-1.3588v3.3854q-2.5333 1.3127-6.3792 1.3127z"/>
- <path id="path4180" d="m182.92 49.131q-5.4811 0-8.498-3.3623-2.9939-3.3854-2.9939-9.5573 0-6.3332 3.0399-9.7876 3.063-3.4545 8.7052-3.4545 1.8193 0 3.6387 0.3915t2.8557 0.92119l-1.1745 3.2472q-1.2666-0.50665-2.7636-0.82907-1.4969-0.34544-2.6484-0.34544-7.6919 0-7.6919 9.8106 0 4.652 1.8654 7.1392 1.8884 2.4872 5.5732 2.4872 3.1551 0 6.4714-1.3588v3.3854q-2.5333 1.3127-6.3792 1.3127z"/>
- <path id="path4182" d="m210.83 48.671-0.75998-3.5926h-0.18424q-1.8884 2.3721-3.7769 3.2242-1.8654 0.82907-4.675 0.82907-3.7538 0-5.8956-1.9345-2.1187-1.9345-2.1187-5.5041 0-7.6459 12.229-8.0143l4.2835-0.13818v-1.566q0-2.9708-1.2897-4.3756-1.2666-1.4278-4.0762-1.4278-3.1551 0-7.1392 1.9345l-1.1745-2.9248q1.8654-1.0133 4.0762-1.589 2.2339-0.57574 4.4678-0.57574 4.5138 0 6.6786 2.0036 2.1878 2.0036 2.1878 6.4253v17.226h-2.8326zm-8.6361-2.6945q3.5696 0 5.5962-1.9575 2.0496-1.9575 2.0496-5.4811v-2.2799l-3.8229 0.16121q-4.5599 0.16121-6.5865 1.4278-2.0036 1.2436-2.0036 3.892 0 2.0727 1.2436 3.1551 1.2666 1.0824 3.5235 1.0824z"/>
- <path id="path4184" d="m233.08 22.969q1.6812 0 3.0169 0.27636l-0.52968 3.5466q-1.566-0.34544-2.7636-0.34544-3.0629 0-5.2508 2.4872-2.1648 2.4872-2.1648 6.195v13.541h-3.8229v-25.241h3.1551l0.43757 4.675h0.18423q1.4048-2.4642 3.3854-3.7999t4.3526-1.3357z"/>
- </g>
+ <path id="path4172" d="m89.719 48.671h-3.915v-30.192h-10.663v-3.4775h25.241v3.4775h-10.663v30.192z" />
+ <path id="path4174" d="m116.36 22.969q1.6812 0 3.0169 0.27636l-0.52968 3.5466q-1.566-0.34544-2.7636-0.34544-3.063 0-5.2508 2.4872-2.1648 2.4872-2.1648 6.195v13.541h-3.8229v-25.241h3.1551l0.43756 4.675h0.18424q1.4048-2.4642 3.3854-3.7999t4.3526-1.3357z" />
+ <path id="path4176" d="m139.62 48.671-0.75998-3.5926h-0.18424q-1.8884 2.3721-3.7769 3.2242-1.8654 0.82907-4.675 0.82907-3.7538 0-5.8956-1.9345-2.1187-1.9345-2.1187-5.5041 0-7.6459 12.229-8.0143l4.2835-0.13818v-1.566q0-2.9708-1.2897-4.3756-1.2666-1.4278-4.0763-1.4278-3.1551 0-7.1392 1.9345l-1.1745-2.9248q1.8654-1.0133 4.0762-1.589 2.2339-0.57574 4.4678-0.57574 4.5138 0 6.6786 2.0036 2.1878 2.0036 2.1878 6.4253v17.226h-2.8326zm-8.6361-2.6945q3.5696 0 5.5962-1.9575 2.0496-1.9575 2.0496-5.4811v-2.2799l-3.8229 0.16121q-4.5599 0.16121-6.5865 1.4278-2.0036 1.2436-2.0036 3.892 0 2.0727 1.2436 3.1551 1.2666 1.0824 3.5236 1.0824z" />
+ <path id="path4178" d="m160.44 49.131q-5.4811 0-8.498-3.3623-2.9939-3.3854-2.9939-9.5573 0-6.3332 3.0399-9.7876 3.063-3.4545 8.7052-3.4545 1.8194 0 3.6387 0.3915t2.8557 0.92119l-1.1745 3.2472q-1.2666-0.50665-2.7636-0.82907-1.4969-0.34544-2.6484-0.34544-7.6919 0-7.6919 9.8106 0 4.652 1.8654 7.1392 1.8884 2.4872 5.5732 2.4872 3.1551 0 6.4713-1.3588v3.3854q-2.5333 1.3127-6.3792 1.3127z" />
+ <path id="path4180" d="m182.92 49.131q-5.4811 0-8.498-3.3623-2.9939-3.3854-2.9939-9.5573 0-6.3332 3.0399-9.7876 3.063-3.4545 8.7052-3.4545 1.8193 0 3.6387 0.3915t2.8557 0.92119l-1.1745 3.2472q-1.2666-0.50665-2.7636-0.82907-1.4969-0.34544-2.6484-0.34544-7.6919 0-7.6919 9.8106 0 4.652 1.8654 7.1392 1.8884 2.4872 5.5732 2.4872 3.1551 0 6.4714-1.3588v3.3854q-2.5333 1.3127-6.3792 1.3127z" />
+ <path id="path4182" d="m210.83 48.671-0.75998-3.5926h-0.18424q-1.8884 2.3721-3.7769 3.2242-1.8654 0.82907-4.675 0.82907-3.7538 0-5.8956-1.9345-2.1187-1.9345-2.1187-5.5041 0-7.6459 12.229-8.0143l4.2835-0.13818v-1.566q0-2.9708-1.2897-4.3756-1.2666-1.4278-4.0762-1.4278-3.1551 0-7.1392 1.9345l-1.1745-2.9248q1.8654-1.0133 4.0762-1.589 2.2339-0.57574 4.4678-0.57574 4.5138 0 6.6786 2.0036 2.1878 2.0036 2.1878 6.4253v17.226h-2.8326zm-8.6361-2.6945q3.5696 0 5.5962-1.9575 2.0496-1.9575 2.0496-5.4811v-2.2799l-3.8229 0.16121q-4.5599 0.16121-6.5865 1.4278-2.0036 1.2436-2.0036 3.892 0 2.0727 1.2436 3.1551 1.2666 1.0824 3.5235 1.0824z" />
+ <path id="path4184" d="m233.08 22.969q1.6812 0 3.0169 0.27636l-0.52968 3.5466q-1.566-0.34544-2.7636-0.34544-3.0629 0-5.2508 2.4872-2.1648 2.4872-2.1648 6.195v13.541h-3.8229v-25.241h3.1551l0.43757 4.675h0.18423q1.4048-2.4642 3.3854-3.7999t4.3526-1.3357z" />
</g>
- </g>
- </svg>
- )
-}
+ </g>
+ </g>
+ </svg>
+);
export default Logo;
diff --git a/modern/src/MainPage.js b/modern/src/MainPage.js
index 8d0b18d..88608df 100644
--- a/modern/src/MainPage.js
+++ b/modern/src/MainPage.js
@@ -11,7 +11,7 @@ import GeofenceMap from './map/GeofenceMap';
import CurrentPositionsMap from './map/CurrentPositionsMap';
import CurrentLocationMap from './map/CurrentLocationMap';
-const useStyles = makeStyles(theme => ({
+const useStyles = makeStyles((theme) => ({
root: {
height: '100%',
display: 'flex',
@@ -24,7 +24,7 @@ const useStyles = makeStyles(theme => ({
flexDirection: 'row',
[theme.breakpoints.down('xs')]: {
flexDirection: 'column-reverse',
- }
+ },
},
drawerPaper: {
position: 'relative',
@@ -50,8 +50,9 @@ const MainPage = ({ width }) => {
<div className={classes.content}>
<Drawer
anchor={isWidthUp('sm', width) ? 'left' : 'bottom'}
- variant='permanent'
- classes={{ paper: classes.drawerPaper }}>
+ variant="permanent"
+ classes={{ paper: classes.drawerPaper }}
+ >
<DevicesList />
</Drawer>
<div className={classes.mapContainer}>
@@ -68,6 +69,6 @@ const MainPage = ({ width }) => {
</div>
</div>
);
-}
+};
export default withWidth()(MainPage);
diff --git a/modern/src/MainToolbar.js b/modern/src/MainToolbar.js
index 311f024..9a72729 100644
--- a/modern/src/MainToolbar.js
+++ b/modern/src/MainToolbar.js
@@ -2,7 +2,6 @@ import React, { useState } from 'react';
import { useHistory } from 'react-router-dom';
import { makeStyles } from '@material-ui/core/styles';
import { useDispatch, useSelector } from 'react-redux';
-import { sessionActions } from './store';
import AppBar from '@material-ui/core/AppBar';
import Toolbar from '@material-ui/core/Toolbar';
import Typography from '@material-ui/core/Typography';
@@ -20,23 +19,24 @@ import MapIcon from '@material-ui/icons/Map';
import PersonIcon from '@material-ui/icons/Person';
import DescriptionIcon from '@material-ui/icons/Description';
import ReplayIcon from '@material-ui/icons/Replay';
+import { sessionActions } from './store';
import t from './common/localization';
import * as selectors from './selectors';
-const useStyles = makeStyles(theme => ({
+const useStyles = makeStyles((theme) => ({
flex: {
- flexGrow: 1
+ flexGrow: 1,
},
appBar: {
- zIndex: theme.zIndex.drawer + 1
+ zIndex: theme.zIndex.drawer + 1,
},
list: {
- width: 250
+ width: 250,
},
menuButton: {
marginLeft: -12,
- marginRight: 20
- }
+ marginRight: 20,
+ },
}));
const MainToolbar = () => {
@@ -111,7 +111,7 @@ const MainToolbar = () => {
<ListItem
button
disabled={!userId}
- onClick={() => history.push(`/settings/notifications`)}
+ onClick={() => history.push('/settings/notifications')}
>
<ListItemIcon>
<PersonIcon />
diff --git a/modern/src/PositionPage.js b/modern/src/PositionPage.js
index a91a7a1..f1766f6 100644
--- a/modern/src/PositionPage.js
+++ b/modern/src/PositionPage.js
@@ -1,14 +1,16 @@
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 {
+ makeStyles, Typography, ListItem, ListItemText, ListItemSecondaryAction, List, Container, Paper, Divider,
+} from '@material-ui/core';
import { useParams } from 'react-router-dom';
+import t from './common/localization';
import { useEffectAsync } from './reactHelper';
import MainToolbar from './MainToolbar';
import { formatPosition } from './common/formatter';
import { prefixString } from './common/stringUtils';
-const useStyles = makeStyles(theme => ({
+const useStyles = makeStyles((theme) => ({
root: {
marginTop: theme.spacing(2),
marginBottom: theme.spacing(2),
@@ -26,7 +28,7 @@ const PositionPage = () => {
if (id) {
const response = await fetch(`/api/positions?id=${id}`, {
headers: {
- 'Accept': 'application/json'
+ Accept: 'application/json',
},
});
if (response.ok) {
@@ -38,28 +40,27 @@ const PositionPage = () => {
}
}, [id]);
- const formatKey = (key) => {
- return t(prefixString('position', key)) || `${t('sharedAttribute')} "${key}"`;
- };
+ const formatKey = (key) => t(prefixString('position', key)) || `${t('sharedAttribute')} "${key}"`;
const attributesList = () => {
- const combinedList = {...item, ...item.attributes};
+ const combinedList = { ...item, ...item.attributes };
return Object.entries(combinedList).filter(([_, value]) => typeof value !== 'object');
- }
+ };
return (
<>
<MainToolbar />
- <Container maxWidth='sm' className={classes.root}>
+ <Container maxWidth="sm" className={classes.root}>
<Paper>
- {item &&
+ {item
+ && (
<List>
{attributesList().map(([key, value], index, list) => (
<Fragment key={key}>
<ListItem>
<ListItemText
primary={formatKey(key)}
- />
+ />
<ListItemSecondaryAction>
<Typography variant="body2">
{formatPosition(value, key)}
@@ -70,11 +71,11 @@ const PositionPage = () => {
</Fragment>
))}
</List>
- }
+ )}
</Paper>
</Container>
</>
);
-}
+};
export default PositionPage;
diff --git a/modern/src/RegisterDialog.js b/modern/src/RegisterDialog.js
index c640c51..c4b99f3 100644
--- a/modern/src/RegisterDialog.js
+++ b/modern/src/RegisterDialog.js
@@ -1,4 +1,3 @@
-import t from './common/localization'
import React, { useState } from 'react';
import Button from '@material-ui/core/Button';
import Dialog from '@material-ui/core/Dialog';
@@ -7,6 +6,7 @@ import DialogContent from '@material-ui/core/DialogContent';
import DialogContentText from '@material-ui/core/DialogContentText';
import TextField from '@material-ui/core/TextField';
import Snackbar from '@material-ui/core/Snackbar';
+import t from './common/localization';
const RegisterDialog = ({ showDialog, onResult }) => {
const [name, setName] = useState('');
@@ -14,80 +14,79 @@ const RegisterDialog = ({ showDialog, onResult }) => {
const [password, setPassword] = useState('');
const [snackbarOpen, setSnackbarOpen] = useState(false);
- const submitDisabled = () => {
- return !name || !/(.+)@(.+)\.(.{2,})/.test(email) || !password;
- }
+ const submitDisabled = () => !name || !/(.+)@(.+)\.(.{2,})/.test(email) || !password;
const handleRegister = async () => {
const response = await fetch('/api/users', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
- body: JSON.stringify({name, email, password})
+ body: JSON.stringify({ name, email, password }),
});
if (response.ok) {
showDialog = false;
setSnackbarOpen(true);
- }
- }
+ }
+ };
if (snackbarOpen) {
-
return (
<Snackbar
anchorOrigin={{ vertical: 'bottom', horizontal: 'center' }}
open={snackbarOpen}
autoHideDuration={6000}
- onClose={() => { onResult(true) }}
- message={t('loginCreated')} />
+ onClose={() => { onResult(true); }}
+ message={t('loginCreated')}
+ />
);
-
- } else if (showDialog) {
-
+ } if (showDialog) {
return (
<Dialog
- open={true}
- onClose={() => { onResult(false) }}>
+ open
+ onClose={() => { onResult(false); }}
+ >
<DialogContent>
<DialogContentText>{t('loginRegister')}</DialogContentText>
<TextField
- margin='normal'
+ margin="normal"
required
fullWidth
label={t('sharedName')}
- name='name'
+ name="name"
value={name || ''}
- autoComplete='name'
+ autoComplete="name"
autoFocus
- onChange={event => setName(event.target.value)} />
+ onChange={(event) => setName(event.target.value)}
+ />
<TextField
- margin='normal'
+ margin="normal"
required
fullWidth
- type='email'
+ type="email"
label={t('userEmail')}
- name='email'
+ name="email"
value={email || ''}
- autoComplete='email'
- onChange={event => setEmail(event.target.value)} />
+ autoComplete="email"
+ onChange={(event) => setEmail(event.target.value)}
+ />
<TextField
- margin='normal'
+ margin="normal"
required
fullWidth
label={t('userPassword')}
- name='password'
+ name="password"
value={password || ''}
- type='password'
- autoComplete='current-password'
- onChange={event => setPassword(event.target.value)} />
+ type="password"
+ autoComplete="current-password"
+ onChange={(event) => setPassword(event.target.value)}
+ />
</DialogContent>
<DialogActions>
<Button color="primary" onClick={handleRegister} disabled={submitDisabled()}>{t('loginRegister')}</Button>
<Button autoFocus onClick={() => onResult(false)}>{t('sharedCancel')}</Button>
</DialogActions>
</Dialog>
- )
-
+ );
}
};
diff --git a/modern/src/RemoveDialog.js b/modern/src/RemoveDialog.js
index bbcfb22..8ff162c 100644
--- a/modern/src/RemoveDialog.js
+++ b/modern/src/RemoveDialog.js
@@ -1,12 +1,14 @@
-import t from './common/localization'
import React from 'react';
import Button from '@material-ui/core/Button';
import Dialog from '@material-ui/core/Dialog';
import DialogActions from '@material-ui/core/DialogActions';
import DialogContent from '@material-ui/core/DialogContent';
import DialogContentText from '@material-ui/core/DialogContentText';
+import t from './common/localization';
-const RemoveDialog = ({ open, endpoint, itemId, onResult }) => {
+const RemoveDialog = ({
+ open, endpoint, itemId, onResult,
+}) => {
const handleRemove = async () => {
const response = await fetch(`/api/${endpoint}/${itemId}`, { method: 'DELETE' });
if (response.ok) {
@@ -17,7 +19,8 @@ const RemoveDialog = ({ open, endpoint, itemId, onResult }) => {
return (
<Dialog
open={open}
- onClose={() => { onResult(false) }}>
+ onClose={() => { onResult(false); }}
+ >
<DialogContent>
<DialogContentText>{t('sharedRemoveConfirm')}</DialogContentText>
</DialogContent>
diff --git a/modern/src/SocketController.js b/modern/src/SocketController.js
index cda693a..901f506 100644
--- a/modern/src/SocketController.js
+++ b/modern/src/SocketController.js
@@ -1,19 +1,19 @@
-import { useDispatch, useSelector } from 'react-redux';
-import { connect } from 'react-redux';
-import { positionsActions, devicesActions, sessionActions } from './store';
+import { useDispatch, useSelector, connect } from 'react-redux';
+
import { useHistory } from 'react-router-dom';
+import { positionsActions, devicesActions, sessionActions } from './store';
import { useEffectAsync } from './reactHelper';
-const displayNotifications = events => {
- if ("Notification" in window) {
- if (Notification.permission === "granted") {
+const displayNotifications = (events) => {
+ if ('Notification' in window) {
+ if (Notification.permission === 'granted') {
for (const event of events) {
const notification = new Notification(`Event: ${event.type}`);
setTimeout(notification.close.bind(notification), 4 * 1000);
}
- } else if (Notification.permission !== "denied") {
- Notification.requestPermission(permission => {
- if (permission === "granted") {
+ } else if (Notification.permission !== 'denied') {
+ Notification.requestPermission((permission) => {
+ if (permission === 'granted') {
displayNotifications(events);
}
});
@@ -24,11 +24,11 @@ const displayNotifications = events => {
const SocketController = () => {
const dispatch = useDispatch();
const history = useHistory();
- const authenticated = useSelector(state => !!state.session.user);
+ const authenticated = useSelector((state) => !!state.session.user);
const connectSocket = () => {
const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
- const socket = new WebSocket(protocol + '//' + window.location.host + '/api/socket');
+ const socket = new WebSocket(`${protocol}//${window.location.host}/api/socket`);
socket.onclose = () => {
setTimeout(() => connectSocket(), 60 * 1000);
@@ -46,7 +46,7 @@ const SocketController = () => {
displayNotifications(data.events);
}
};
- }
+ };
useEffectAsync(async () => {
const response = await fetch('/api/server');
@@ -73,6 +73,6 @@ const SocketController = () => {
}, [authenticated]);
return null;
-}
+};
export default connect()(SocketController);
diff --git a/modern/src/StartPage.js b/modern/src/StartPage.js
index 53f8c35..1472f50 100644
--- a/modern/src/StartPage.js
+++ b/modern/src/StartPage.js
@@ -2,7 +2,7 @@ import React from 'react';
import { useMediaQuery, makeStyles, Paper } from '@material-ui/core';
import { useTheme } from '@material-ui/core/styles';
-const useStyles = makeStyles(theme => ({
+const useStyles = makeStyles((theme) => ({
root: {
display: 'flex',
height: '100vh',
@@ -23,20 +23,20 @@ const useStyles = makeStyles(theme => ({
},
},
paper: {
- display:'flex',
+ display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
alignItems: 'center',
flex: 1,
boxShadow: '-2px 0px 16px rgba(0, 0, 0, 0.25)',
[theme.breakpoints.up('lg')]: {
- padding: theme.spacing(0, 25, 0, 0)
+ padding: theme.spacing(0, 25, 0, 0),
},
},
form: {
maxWidth: theme.spacing(52),
padding: theme.spacing(5),
- width: "100%",
+ width: '100%',
},
}));
@@ -47,11 +47,12 @@ const StartPage = ({ children }) => {
return (
<main className={classes.root}>
<div className={classes.sidebar}>
- {!useMediaQuery(theme.breakpoints.down('md')) &&
+ {!useMediaQuery(theme.breakpoints.down('md'))
+ && (
<svg height="64" width="240">
- <use xlinkHref="/logo.svg#img"></use>
+ <use xlinkHref="/logo.svg#img" />
</svg>
- }
+ )}
</div>
<Paper className={classes.paper}>
<form className={classes.form}>
@@ -59,7 +60,7 @@ const StartPage = ({ children }) => {
</form>
</Paper>
</main>
- )
-}
+ );
+};
export default StartPage;
diff --git a/modern/src/UserPage.js b/modern/src/UserPage.js
index dfe8b98..6afbdf7 100644
--- a/modern/src/UserPage.js
+++ b/modern/src/UserPage.js
@@ -1,11 +1,13 @@
import React, { useState } from 'react';
import TextField from '@material-ui/core/TextField';
+import {
+ Accordion, AccordionSummary, AccordionDetails, makeStyles, Typography,
+} from '@material-ui/core';
+import ExpandMoreIcon from '@material-ui/icons/ExpandMore';
import t from './common/localization';
import userAttributes from './attributes/userAttributes';
import EditItemView from './EditItemView';
-import { Accordion, AccordionSummary, AccordionDetails, makeStyles, Typography } from '@material-ui/core';
-import ExpandMoreIcon from '@material-ui/icons/ExpandMore';
import EditAttributesView from './attributes/EditAttributesView';
import LinkField from './form/LinkField';
@@ -22,7 +24,8 @@ const UserPage = () => {
return (
<EditItemView endpoint="users" item={item} setItem={setItem}>
- {item &&
+ {item
+ && (
<>
<Accordion defaultExpanded>
<AccordionSummary expandIcon={<ExpandMoreIcon />}>
@@ -34,21 +37,24 @@ const UserPage = () => {
<TextField
margin="normal"
value={item.name || ''}
- onChange={event => setItem({...item, name: event.target.value})}
+ onChange={(event) => setItem({ ...item, name: event.target.value })}
label={t('sharedName')}
- variant="filled" />
+ variant="filled"
+ />
<TextField
margin="normal"
value={item.email || ''}
- onChange={event => setItem({...item, email: event.target.value})}
+ onChange={(event) => setItem({ ...item, email: event.target.value })}
label={t('userEmail')}
- variant="filled" />
+ variant="filled"
+ />
<TextField
margin="normal"
type="password"
- onChange={event => setItem({...item, password: event.target.value})}
+ onChange={(event) => setItem({ ...item, password: event.target.value })}
label={t('userPassword')}
- variant="filled" />
+ variant="filled"
+ />
</AccordionDetails>
</Accordion>
<Accordion>
@@ -60,12 +66,13 @@ const UserPage = () => {
<AccordionDetails className={classes.details}>
<EditAttributesView
attributes={item.attributes}
- setAttributes={attributes => setItem({...item, attributes})}
+ setAttributes={(attributes) => setItem({ ...item, attributes })}
definitions={userAttributes}
- />
+ />
</AccordionDetails>
</Accordion>
- {item.id &&
+ {item.id
+ && (
<Accordion>
<AccordionSummary expandIcon={<ExpandMoreIcon />}>
<Typography variant="subtitle1">
@@ -76,28 +83,30 @@ const UserPage = () => {
<LinkField
margin="normal"
endpointAll="/api/devices?all=true"
- endpointLinked={"/api/devices?userId=" + item.id}
+ endpointLinked={`/api/devices?userId=${item.id}`}
baseId={item.id}
keyBase="userId"
keyLink="deviceId"
label={t('deviceTitle')}
- variant="filled" />
+ variant="filled"
+ />
<LinkField
margin="normal"
endpointAll="/api/groups?all=true"
- endpointLinked={"/api/groups?userId=" + item.id}
+ endpointLinked={`/api/groups?userId=${item.id}`}
baseId={item.id}
keyBase="userId"
keyLink="groupId"
label={t('settingsGroups')}
- variant="filled" />
+ variant="filled"
+ />
</AccordionDetails>
</Accordion>
- }
+ )}
</>
- }
+ )}
</EditItemView>
);
-}
+};
export default UserPage;
diff --git a/modern/src/admin/ServerPage.js b/modern/src/admin/ServerPage.js
index c33a631..6d5b575 100644
--- a/modern/src/admin/ServerPage.js
+++ b/modern/src/admin/ServerPage.js
@@ -1,31 +1,33 @@
import React from 'react';
import TextField from '@material-ui/core/TextField';
-import t from '../common/localization';
-import { Accordion, AccordionSummary, AccordionDetails, makeStyles, Typography, Button, FormControl, Container, Checkbox, FormControlLabel } from '@material-ui/core';
+import {
+ Accordion, AccordionSummary, AccordionDetails, makeStyles, Typography, Button, FormControl, Container, Checkbox, FormControlLabel,
+} from '@material-ui/core';
import ExpandMoreIcon from '@material-ui/icons/ExpandMore';
import { useHistory } from 'react-router-dom';
import { useDispatch, useSelector } from 'react-redux';
+import t from '../common/localization';
import { sessionActions } from '../store';
import EditAttributesView from '../attributes/EditAttributesView';
import deviceAttributes from '../attributes/deviceAttributes';
import userAttributes from '../attributes/userAttributes';
import OptionsLayout from '../settings/OptionsLayout';
-const useStyles = makeStyles(theme => ({
+const useStyles = makeStyles((theme) => ({
container: {
- marginTop: theme.spacing(2)
+ marginTop: theme.spacing(2),
},
buttons: {
display: 'flex',
justifyContent: 'space-evenly',
'& > *': {
- flexBasis: '33%'
- }
+ flexBasis: '33%',
+ },
},
details: {
- flexDirection: 'column'
- }
+ flexDirection: 'column',
+ },
}));
const ServerPage = () => {
@@ -33,15 +35,14 @@ const ServerPage = () => {
const dispatch = useDispatch();
const classes = useStyles();
- const item = useSelector(state => state.session.server);
- const setItem = updatedItem =>
- dispatch(sessionActions.updateServer(updatedItem));
+ const item = useSelector((state) => state.session.server);
+ const setItem = (updatedItem) => dispatch(sessionActions.updateServer(updatedItem));
const handleSave = async () => {
const response = await fetch('/api/server', {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
- body: JSON.stringify(item)
+ body: JSON.stringify(item),
});
if (response.ok) {
@@ -64,9 +65,7 @@ const ServerPage = () => {
<TextField
margin="normal"
value={item.announcement || ''}
- onChange={event =>
- setItem({ ...item, announcement: event.target.value })
- }
+ onChange={(event) => setItem({ ...item, announcement: event.target.value })}
label={t('serverAnnouncement')}
variant="filled"
/>
@@ -80,53 +79,45 @@ const ServerPage = () => {
</AccordionSummary>
<AccordionDetails className={classes.details}>
<FormControlLabel
- control={
+ control={(
<Checkbox
checked={item.registration}
- onChange={event =>
- setItem({ ...item, registration: event.target.checked })
- }
+ onChange={(event) => setItem({ ...item, registration: event.target.checked })}
/>
- }
+ )}
label={t('serverRegistration')}
/>
<FormControlLabel
- control={
+ control={(
<Checkbox
checked={item.readonly}
- onChange={event =>
- setItem({ ...item, readonly: event.target.checked })
- }
+ onChange={(event) => setItem({ ...item, readonly: event.target.checked })}
/>
- }
+ )}
label={t('serverReadonly')}
/>
<FormControlLabel
- control={
+ control={(
<Checkbox
checked={item.deviceReadonly}
- onChange={event =>
- setItem({
- ...item,
- deviceReadonly: event.target.checked
- })
- }
+ onChange={(event) => setItem({
+ ...item,
+ deviceReadonly: event.target.checked,
+ })}
/>
- }
+ )}
label={t('userDeviceReadonly')}
/>
<FormControlLabel
- control={
+ control={(
<Checkbox
checked={item.limitCommands}
- onChange={event =>
- setItem({
- ...item,
- limitCommands: event.target.checked
- })
- }
+ onChange={(event) => setItem({
+ ...item,
+ limitCommands: event.target.checked,
+ })}
/>
- }
+ )}
label={t('userLimitCommands')}
/>
</AccordionDetails>
@@ -140,9 +131,9 @@ const ServerPage = () => {
<AccordionDetails className={classes.details}>
<EditAttributesView
attributes={item.attributes}
- setAttributes={attributes => setItem({ ...item, attributes })}
+ setAttributes={(attributes) => setItem({ ...item, attributes })}
definitions={{ ...userAttributes, ...deviceAttributes }}
- />
+ />
</AccordionDetails>
</Accordion>
</>
diff --git a/modern/src/admin/StatisticsPage.js b/modern/src/admin/StatisticsPage.js
index b1504c8..8a6e601 100644
--- a/modern/src/admin/StatisticsPage.js
+++ b/modern/src/admin/StatisticsPage.js
@@ -1,9 +1,10 @@
-
import React, { useState } from 'react';
-import { FormControl, InputLabel,Select, MenuItem, TextField, Button, TableContainer, Table, TableRow, TableCell, TableHead, TableBody, Paper } from '@material-ui/core';
+import {
+ FormControl, InputLabel, Select, MenuItem, TextField, Button, TableContainer, Table, TableRow, TableCell, TableHead, TableBody, Paper,
+} from '@material-ui/core';
+import moment from 'moment';
import t from '../common/localization';
import { formatDate } from '../common/formatter';
-import moment from 'moment';
import OptionsLayout from '../settings/OptionsLayout';
const Filter = ({ setItems }) => {
@@ -59,10 +60,10 @@ const Filter = ({ setItems }) => {
const query = new URLSearchParams({
from: selectedFrom.toISOString(),
- to: selectedTo.toISOString()
+ to: selectedTo.toISOString(),
});
const response = await fetch(`/api/statistics?${query.toString()}`, {
- Accept: 'application/json'
+ Accept: 'application/json',
});
if (response.ok) {
setItems(await response.json());
@@ -73,7 +74,7 @@ const Filter = ({ setItems }) => {
<>
<FormControl variant="filled" margin="normal" fullWidth>
<InputLabel>{t('reportPeriod')}</InputLabel>
- <Select value={period} onChange={e => setPeriod(e.target.value)}>
+ <Select value={period} onChange={(e) => setPeriod(e.target.value)}>
<MenuItem value="today">{t('reportToday')}</MenuItem>
<MenuItem value="yesterday">{t('reportYesterday')}</MenuItem>
<MenuItem value="thisWeek">{t('reportThisWeek')}</MenuItem>
@@ -90,9 +91,7 @@ const Filter = ({ setItems }) => {
label={t('reportFrom')}
type="datetime-local"
value={from.format(moment.HTML5_FMT.DATETIME_LOCAL)}
- onChange={e =>
- setFrom(moment(e.target.value, moment.HTML5_FMT.DATETIME_LOCAL))
- }
+ onChange={(e) => setFrom(moment(e.target.value, moment.HTML5_FMT.DATETIME_LOCAL))}
fullWidth
/>
)}
@@ -103,9 +102,7 @@ const Filter = ({ setItems }) => {
label={t('reportTo')}
type="datetime-local"
value={to.format(moment.HTML5_FMT.DATETIME_LOCAL)}
- onChange={e =>
- setTo(moment(e.target.value, moment.HTML5_FMT.DATETIME_LOCAL))
- }
+ onChange={(e) => setTo(moment(e.target.value, moment.HTML5_FMT.DATETIME_LOCAL))}
fullWidth
/>
)}
@@ -117,7 +114,7 @@ const Filter = ({ setItems }) => {
>
{t('reportShow')}
</Button>
- </>
+ </>
);
};
@@ -144,7 +141,7 @@ const StatisticsPage = () => {
</TableRow>
</TableHead>
<TableBody>
- {items.map(item => (
+ {items.map((item) => (
<TableRow key={item.id}>
<TableCell>{formatDate(item.captureTime)}</TableCell>
<TableCell>{item.activeUsers}</TableCell>
@@ -155,7 +152,7 @@ const StatisticsPage = () => {
<TableCell>{item.mailSent}</TableCell>
<TableCell>{item.smsSent}</TableCell>
<TableCell>{item.geocoderRequests}</TableCell>
- <TableCell>{item.geolocationRequests}</TableCell>
+ <TableCell>{item.geolocationRequests}</TableCell>
</TableRow>
))}
</TableBody>
diff --git a/modern/src/admin/UsersPage.js b/modern/src/admin/UsersPage.js
index ceaab6a..6afe099 100644
--- a/modern/src/admin/UsersPage.js
+++ b/modern/src/admin/UsersPage.js
@@ -1,5 +1,7 @@
import React, { useState } from 'react';
-import { TableContainer, Table, TableRow, TableCell, TableHead, TableBody, makeStyles, IconButton } from '@material-ui/core';
+import {
+ TableContainer, Table, TableRow, TableCell, TableHead, TableBody, makeStyles, IconButton,
+} from '@material-ui/core';
import MoreVertIcon from '@material-ui/icons/MoreVert';
import t from '../common/localization';
import { useEffectAsync } from '../reactHelper';
@@ -7,11 +9,11 @@ import EditCollectionView from '../EditCollectionView';
import { formatBoolean } from '../common/formatter';
import OptionsLayout from '../settings/OptionsLayout';
-const useStyles = makeStyles(theme => ({
+const useStyles = makeStyles((theme) => ({
columnAction: {
width: theme.spacing(1),
- padding: theme.spacing(0, 1)
- }
+ padding: theme.spacing(0, 1),
+ },
}));
const UsersView = ({ updateTimestamp, onMenuClick }) => {
@@ -28,48 +30,46 @@ const UsersView = ({ updateTimestamp, onMenuClick }) => {
return (
<TableContainer>
- <Table>
- <TableHead>
- <TableRow>
- <TableCell className={classes.columnAction} />
- <TableCell>{t('sharedName')}</TableCell>
- <TableCell>{t('userEmail')}</TableCell>
- <TableCell>{t('userAdmin')}</TableCell>
- <TableCell>{t('sharedDisabled')}</TableCell>
- </TableRow>
- </TableHead>
- <TableBody>
- {items.map(item => (
- <TableRow key={item.id}>
- <TableCell className={classes.columnAction} padding="none">
+ <Table>
+ <TableHead>
+ <TableRow>
+ <TableCell className={classes.columnAction} />
+ <TableCell>{t('sharedName')}</TableCell>
+ <TableCell>{t('userEmail')}</TableCell>
+ <TableCell>{t('userAdmin')}</TableCell>
+ <TableCell>{t('sharedDisabled')}</TableCell>
+ </TableRow>
+ </TableHead>
+ <TableBody>
+ {items.map((item) => (
+ <TableRow key={item.id}>
+ <TableCell className={classes.columnAction} padding="none">
<IconButton
- onClick={event => onMenuClick(event.currentTarget, item.id)}
+ onClick={(event) => onMenuClick(event.currentTarget, item.id)}
>
- <MoreVertIcon />
- </IconButton>
- </TableCell>
- <TableCell>{item.name}</TableCell>
- <TableCell>{item.email}</TableCell>
- <TableCell>{formatBoolean(item, 'administrator')}</TableCell>
- <TableCell>{formatBoolean(item, 'disabled')}</TableCell>
- </TableRow>
- ))}
- </TableBody>
- </Table>
+ <MoreVertIcon />
+ </IconButton>
+ </TableCell>
+ <TableCell>{item.name}</TableCell>
+ <TableCell>{item.email}</TableCell>
+ <TableCell>{formatBoolean(item, 'administrator')}</TableCell>
+ <TableCell>{formatBoolean(item, 'disabled')}</TableCell>
+ </TableRow>
+ ))}
+ </TableBody>
+ </Table>
</TableContainer>
);
};
-const UsersPage = () => {
- return (
- <OptionsLayout>
- <EditCollectionView
- content={UsersView}
- editPath="/user"
- endpoint="users"
- />
- </OptionsLayout>
- );
-};
+const UsersPage = () => (
+ <OptionsLayout>
+ <EditCollectionView
+ content={UsersView}
+ editPath="/user"
+ endpoint="users"
+ />
+ </OptionsLayout>
+);
export default UsersPage;
diff --git a/modern/src/attributes/AddAttributeDialog.js b/modern/src/attributes/AddAttributeDialog.js
index ee4c48c..24c208a 100644
--- a/modern/src/attributes/AddAttributeDialog.js
+++ b/modern/src/attributes/AddAttributeDialog.js
@@ -1,12 +1,14 @@
import React, { useState } from 'react';
-import { Button, Dialog, DialogActions, DialogContent, FormControl, InputLabel, MenuItem, Select, TextField } from "@material-ui/core";
+import {
+ Button, Dialog, DialogActions, DialogContent, FormControl, InputLabel, MenuItem, Select, TextField,
+} from '@material-ui/core';
-import t from '../common/localization';
import { Autocomplete, createFilterOptions } from '@material-ui/lab';
+import t from '../common/localization';
const AddAttributeDialog = ({ open, onResult, definitions }) => {
const filter = createFilterOptions({
- stringify: option => option.name,
+ stringify: (option) => option.name,
});
const options = Object.entries(definitions).map(([key, value]) => ({
@@ -39,10 +41,8 @@ const AddAttributeDialog = ({ open, onResult, definitions }) => {
return filtered;
}}
options={options}
- getOptionLabel={option => {
- return option && typeof option === 'object' ? option.name : option;
- }}
- renderOption={option => option.name}
+ getOptionLabel={(option) => (option && typeof option === 'object' ? option.name : option)}
+ renderOption={(option) => option.name}
freeSolo
renderInput={(params) => (
<TextField {...params} label={t('sharedAttribute')} variant="filled" margin="normal" />
@@ -52,14 +52,16 @@ const AddAttributeDialog = ({ open, onResult, definitions }) => {
variant="filled"
margin="normal"
fullWidth
- disabled={key in definitions}>
+ disabled={key in definitions}
+ >
<InputLabel>{t('sharedType')}</InputLabel>
<Select
value={type}
- onChange={e => setType(e.target.value)}>
- <MenuItem value={'string'}>{t('sharedTypeString')}</MenuItem>
- <MenuItem value={'number'}>{t('sharedTypeNumber')}</MenuItem>
- <MenuItem value={'boolean'}>{t('sharedTypeBoolean')}</MenuItem>
+ onChange={(e) => setType(e.target.value)}
+ >
+ <MenuItem value="string">{t('sharedTypeString')}</MenuItem>
+ <MenuItem value="number">{t('sharedTypeNumber')}</MenuItem>
+ <MenuItem value="boolean">{t('sharedTypeBoolean')}</MenuItem>
</Select>
</FormControl>
</DialogContent>
@@ -67,17 +69,19 @@ const AddAttributeDialog = ({ open, onResult, definitions }) => {
<Button
color="primary"
disabled={!key}
- onClick={() => onResult({ key, type })}>
+ onClick={() => onResult({ key, type })}
+ >
{t('sharedAdd')}
</Button>
<Button
autoFocus
- onClick={() => onResult(null)}>
+ onClick={() => onResult(null)}
+ >
{t('sharedCancel')}
</Button>
</DialogActions>
</Dialog>
- )
-}
+ );
+};
export default AddAttributeDialog;
diff --git a/modern/src/attributes/EditAttributesView.js b/modern/src/attributes/EditAttributesView.js
index 619d857..5ca7cad 100644
--- a/modern/src/attributes/EditAttributesView.js
+++ b/modern/src/attributes/EditAttributesView.js
@@ -1,13 +1,14 @@
import React, { useState } from 'react';
-import t from '../common/localization';
-
-import { Button, Checkbox, FilledInput, FormControl, FormControlLabel, Grid, IconButton, InputAdornment, InputLabel, makeStyles } from "@material-ui/core";
+import {
+ Button, Checkbox, FilledInput, FormControl, FormControlLabel, Grid, IconButton, InputAdornment, InputLabel, makeStyles,
+} from '@material-ui/core';
import CloseIcon from '@material-ui/icons/Close';
import AddIcon from '@material-ui/icons/Add';
+import t from '../common/localization';
import AddAttributeDialog from './AddAttributeDialog';
-const useStyles = makeStyles(theme => ({
+const useStyles = makeStyles((theme) => ({
addButton: {
marginTop: theme.spacing(2),
marginBottom: theme.spacing(1),
@@ -23,8 +24,8 @@ const EditAttributesView = ({ attributes, setAttributes, definitions }) => {
const [addDialogShown, setAddDialogShown] = useState(false);
const convertToList = (attributes) => {
- let booleanList = [];
- let otherList = [];
+ const booleanList = [];
+ const otherList = [];
for (const key in attributes) {
const value = attributes[key];
const type = getAttributeType(value);
@@ -35,12 +36,12 @@ const EditAttributesView = ({ attributes, setAttributes, definitions }) => {
}
}
return otherList.concat(booleanList);
- }
+ };
const handleAddResult = (definition) => {
setAddDialogShown(false);
if (definition) {
- switch(definition.type) {
+ switch (definition.type) {
case 'number':
updateAttribute(definition.key, 0);
break;
@@ -48,20 +49,20 @@ const EditAttributesView = ({ attributes, setAttributes, definitions }) => {
updateAttribute(definition.key, false);
break;
default:
- updateAttribute(definition.key, "");
+ updateAttribute(definition.key, '');
break;
}
}
- }
+ };
const updateAttribute = (key, value) => {
- let updatedAttributes = {...attributes};
+ const updatedAttributes = { ...attributes };
updatedAttributes[key] = value;
setAttributes(updatedAttributes);
};
const deleteAttribute = (key) => {
- let updatedAttributes = {...attributes};
+ const updatedAttributes = { ...attributes };
delete updatedAttributes[key];
setAttributes(updatedAttributes);
};
@@ -74,11 +75,10 @@ const EditAttributesView = ({ attributes, setAttributes, definitions }) => {
const getAttributeType = (value) => {
if (typeof value === 'number') {
return 'number';
- } else if (typeof value === 'boolean') {
+ } if (typeof value === 'boolean') {
return 'boolean';
- } else {
- return 'string';
}
+ return 'string';
};
return (
@@ -88,37 +88,37 @@ const EditAttributesView = ({ attributes, setAttributes, definitions }) => {
return (
<Grid container direction="row" justify="space-between">
<FormControlLabel
- control={
+ control={(
<Checkbox
checked={value}
- onChange={e => updateAttribute(key, e.target.checked)}
- />
- }
- label={getAttributeName(key)} />
+ onChange={(e) => updateAttribute(key, e.target.checked)}
+ />
+ )}
+ label={getAttributeName(key)}
+ />
<IconButton className={classes.removeButton} onClick={() => deleteAttribute(key)}>
<CloseIcon />
</IconButton>
</Grid>
);
- } else {
- return (
- <FormControl variant="filled" margin="normal" key={key}>
- <InputLabel>{getAttributeName(key)}</InputLabel>
- <FilledInput
- type={type === 'number' ? 'number' : 'text'}
- value={value || ''}
- onChange={e => updateAttribute(key, e.target.value)}
- endAdornment={
- <InputAdornment position="end">
- <IconButton onClick={() => deleteAttribute(key)}>
- <CloseIcon />
- </IconButton>
- </InputAdornment>
- }
- />
- </FormControl>
- );
}
+ return (
+ <FormControl variant="filled" margin="normal" key={key}>
+ <InputLabel>{getAttributeName(key)}</InputLabel>
+ <FilledInput
+ type={type === 'number' ? 'number' : 'text'}
+ value={value || ''}
+ onChange={(e) => updateAttribute(key, e.target.value)}
+ endAdornment={(
+ <InputAdornment position="end">
+ <IconButton onClick={() => deleteAttribute(key)}>
+ <CloseIcon />
+ </IconButton>
+ </InputAdornment>
+ )}
+ />
+ </FormControl>
+ );
})}
<Button
size="large"
@@ -126,16 +126,17 @@ const EditAttributesView = ({ attributes, setAttributes, definitions }) => {
color="primary"
onClick={() => setAddDialogShown(true)}
startIcon={<AddIcon />}
- className={classes.addButton}>
+ className={classes.addButton}
+ >
{t('sharedAdd')}
</Button>
<AddAttributeDialog
open={addDialogShown}
onResult={handleAddResult}
definitions={definitions}
- />
+ />
</>
);
-}
+};
export default EditAttributesView;
diff --git a/modern/src/attributes/deviceAttributes.js b/modern/src/attributes/deviceAttributes.js
index 891a225..26e3d92 100644
--- a/modern/src/attributes/deviceAttributes.js
+++ b/modern/src/attributes/deviceAttributes.js
@@ -1,7 +1,7 @@
-import t from '../common/localization'
+import t from '../common/localization';
export default {
- 'speedLimit': {
+ speedLimit: {
name: t('attributeSpeedLimit'),
type: 'string',
},
diff --git a/modern/src/attributes/geofenceAttributes.js b/modern/src/attributes/geofenceAttributes.js
index 4b9c9e6..59a8869 100644
--- a/modern/src/attributes/geofenceAttributes.js
+++ b/modern/src/attributes/geofenceAttributes.js
@@ -1,7 +1,7 @@
-import t from '../common/localization'
+import t from '../common/localization';
export default {
- 'speedLimit': {
+ speedLimit: {
name: t('attributeSpeedLimit'),
type: 'string',
},
diff --git a/modern/src/attributes/positionAttributes.js b/modern/src/attributes/positionAttributes.js
index b1efe3d..94f396a 100644
--- a/modern/src/attributes/positionAttributes.js
+++ b/modern/src/attributes/positionAttributes.js
@@ -1,19 +1,19 @@
-import t from '../common/localization'
+import t from '../common/localization';
export default {
- 'raw': {
+ raw: {
name: t('positionRaw'),
type: 'string',
},
- 'index': {
+ index: {
name: t('positionIndex'),
type: 'number',
},
- 'ignition': {
+ ignition: {
name: t('positionIgnition'),
type: 'boolean',
},
- 'odometer': {
+ odometer: {
name: t('positionOdometer'),
type: 'number',
dataType: 'distance',
diff --git a/modern/src/attributes/userAttributes.js b/modern/src/attributes/userAttributes.js
index bcec29f..6f842f9 100644
--- a/modern/src/attributes/userAttributes.js
+++ b/modern/src/attributes/userAttributes.js
@@ -1,7 +1,7 @@
-import t from '../common/localization'
+import t from '../common/localization';
export default {
- 'notificationTokens': {
+ notificationTokens: {
name: t('attributeNotificationTokens'),
type: 'string',
},
@@ -49,19 +49,19 @@ export default {
name: t('attributeUiHidePositionAttributes'),
type: 'string',
},
- 'distanceUnit': {
+ distanceUnit: {
name: t('settingsDistanceUnit'),
type: 'string',
},
- 'speedUnit': {
+ speedUnit: {
name: t('settingsSpeedUnit'),
type: 'string',
},
- 'volumeUnit': {
+ volumeUnit: {
name: t('settingsVolumeUnit'),
type: 'string',
},
- 'timezone': {
+ timezone: {
name: t('sharedTimezone'),
type: 'string',
},
diff --git a/modern/src/common/converter.js b/modern/src/common/converter.js
index 9cdc623..d45db5d 100644
--- a/modern/src/common/converter.js
+++ b/modern/src/common/converter.js
@@ -1,4 +1,4 @@
-const speedConverter = unit => {
+const speedConverter = (unit) => {
switch (unit) {
case 'kmh':
return 1.852;
@@ -10,7 +10,7 @@ const speedConverter = unit => {
}
};
-const distanceConverter = unit => {
+const distanceConverter = (unit) => {
switch (unit) {
case 'mi':
return 0.000621371;
@@ -19,21 +19,13 @@ const distanceConverter = unit => {
case 'km':
default:
return 0.001;
- }
-}
+ }
+};
-export const speedFromKnots = (value, unit) => {
- return value * speedConverter(unit);
-}
+export const speedFromKnots = (value, unit) => value * speedConverter(unit);
-export const speedToKnots = (value, unit) => {
- return value / speedConverter(unit);
-}
+export const speedToKnots = (value, unit) => value / speedConverter(unit);
-export const distanceFromMeters = (value, unit) => {
- return value * distanceConverter(unit);
-}
+export const distanceFromMeters = (value, unit) => value * distanceConverter(unit);
-export const distanceToMeters = (value, unit) => {
- return value / distanceConverter(unit);
-}
+export const distanceToMeters = (value, unit) => value / distanceConverter(unit);
diff --git a/modern/src/common/formatter.js b/modern/src/common/formatter.js
index 0d8ac4c..7441d01 100644
--- a/modern/src/common/formatter.js
+++ b/modern/src/common/formatter.js
@@ -1,5 +1,5 @@
import moment from 'moment';
-import t from '../common/localization';
+import t from './localization';
export const formatPosition = (value, key) => {
if (value != null && typeof value === 'object') {
@@ -18,29 +18,22 @@ export const formatPosition = (value, key) => {
case 'course':
return value.toFixed(1);
case 'batteryLevel':
- return value + '%';
+ return `${value}%`;
default:
if (typeof value === 'number') {
return formatNumber(value);
- } else if (typeof value === 'boolean') {
+ } if (typeof value === 'boolean') {
return formatBoolean(value);
- } else {
- return value;
}
+ return value;
}
};
-export const formatBoolean = (value) => {
- return value ? t('sharedYes') : t('sharedNo');
-};
+export const formatBoolean = (value) => (value ? t('sharedYes') : t('sharedNo'));
-export const formatNumber = (value, precision = 1) => {
- return Number(value.toFixed(precision));
-};
+export const formatNumber = (value, precision = 1) => Number(value.toFixed(precision));
-export const formatDate = (value, format = 'YYYY-MM-DD HH:mm') => {
- return moment(value).format(format);
-};
+export const formatDate = (value, format = 'YYYY-MM-DD HH:mm') => moment(value).format(format);
export const formatDistance = (value, unit) => {
switch (unit) {
@@ -50,7 +43,7 @@ export const formatDistance = (value, unit) => {
return `${(value * 0.000539957).toFixed(2)} ${t('sharedNmi')}`;
case 'km':
default:
- return `${(value * 0.001).toFixed(2)} ${t('sharedKm')}`;
+ return `${(value * 0.001).toFixed(2)} ${t('sharedKm')}`;
}
};
@@ -62,8 +55,8 @@ export const formatSpeed = (value, unit) => {
return `${(value * 1.15078).toFixed(2)} ${t('sharedMph')}`;
case 'kn':
default:
- return `${(value * 1).toFixed(2)} ${t('sharedKn')}`;
- }
+ return `${(value * 1).toFixed(2)} ${t('sharedKn')}`;
+ }
};
export const formatVolume = (value, unit) => {
@@ -74,16 +67,15 @@ export const formatVolume = (value, unit) => {
return `${(value / 3.785).toFixed(2)} ${t('sharedGallonAbbreviation')}`;
case 'ltr':
default:
- return `${(value / 1).toFixed(2)} ${t('sharedLiterAbbreviation')}`;
- }
-}
-
-export const formatHours = (value) => {
- return moment.duration(value).humanize();
+ return `${(value / 1).toFixed(2)} ${t('sharedLiterAbbreviation')}`;
+ }
};
+export const formatHours = (value) => moment.duration(value).humanize();
+
export const formatCoordinate = (key, value, unit) => {
- var hemisphere, degrees, minutes, seconds;
+ let hemisphere; let degrees; let minutes; let
+ seconds;
if (key === 'latitude') {
hemisphere = value >= 0 ? 'N' : 'S';
} else {
@@ -95,14 +87,14 @@ export const formatCoordinate = (key, value, unit) => {
value = Math.abs(value);
degrees = Math.floor(value);
minutes = (value - degrees) * 60;
- return degrees + 'Ā° ' + minutes.toFixed(6) + '\' ' + hemisphere;
+ return `${degrees}Ā° ${minutes.toFixed(6)}' ${hemisphere}`;
case 'dms':
value = Math.abs(value);
degrees = Math.floor(value);
minutes = Math.floor((value - degrees) * 60);
seconds = Math.round((value - degrees - minutes / 60) * 3600);
- return degrees + 'Ā° ' + minutes + '\' ' + seconds + '" ' + hemisphere;
+ return `${degrees}Ā° ${minutes}' ${seconds}" ${hemisphere}`;
default:
- return value.toFixed(6) + 'Ā°';
- }
+ return `${value.toFixed(6)}Ā°`;
+ }
};
diff --git a/modern/src/common/preferences.js b/modern/src/common/preferences.js
index 24fe389..aba3c82 100644
--- a/modern/src/common/preferences.js
+++ b/modern/src/common/preferences.js
@@ -1,21 +1,15 @@
import { useSelector } from 'react-redux';
-export const usePreference = (key, defaultValue) => {
- return useSelector(state => {
- if (state.session.server.forceSettings) {
- return state.session.server[key] || state.session.user[key] || defaultValue;
- } else {
- return state.session.user[key] || state.session.server[key] || defaultValue;
- }
- });
-};
+export const usePreference = (key, defaultValue) => useSelector((state) => {
+ if (state.session.server.forceSettings) {
+ return state.session.server[key] || state.session.user[key] || defaultValue;
+ }
+ return state.session.user[key] || state.session.server[key] || defaultValue;
+});
-export const useAttributePreference = (key, defaultValue) => {
- return useSelector(state => {
- if (state.session.server.forceSettings) {
- return state.session.server.attributes[key] || state.session.user.attributes[key] || defaultValue;
- } else {
- return state.session.user.attributes[key] || state.session.server.attributes[key] || defaultValue;
- }
- });
-};
+export const useAttributePreference = (key, defaultValue) => useSelector((state) => {
+ if (state.session.server.forceSettings) {
+ return state.session.server.attributes[key] || state.session.user.attributes[key] || defaultValue;
+ }
+ return state.session.user.attributes[key] || state.session.server.attributes[key] || defaultValue;
+});
diff --git a/modern/src/common/stringUtils.js b/modern/src/common/stringUtils.js
index 7bd68c8..fc997fe 100644
--- a/modern/src/common/stringUtils.js
+++ b/modern/src/common/stringUtils.js
@@ -1,7 +1,3 @@
-export const prefixString = (prefix, value) => {
- return prefix + value.charAt(0).toUpperCase() + value.slice(1);
-}
+export const prefixString = (prefix, value) => prefix + value.charAt(0).toUpperCase() + value.slice(1);
-export const unprefixString = (prefix, value) => {
- return value.charAt(prefix.length).toLowerCase() + value.slice(prefix.length + 1);
-}
+export const unprefixString = (prefix, value) => value.charAt(prefix.length).toLowerCase() + value.slice(prefix.length + 1);
diff --git a/modern/src/components/NavBar.js b/modern/src/components/NavBar.js
index 68e38bf..93e79bb 100644
--- a/modern/src/components/NavBar.js
+++ b/modern/src/components/NavBar.js
@@ -1,5 +1,7 @@
import React from 'react';
-import { AppBar, Toolbar, Typography, IconButton } from '@material-ui/core';
+import {
+ AppBar, Toolbar, Typography, IconButton,
+} from '@material-ui/core';
import MenuIcon from '@material-ui/icons/Menu';
const Navbar = ({ setOpenDrawer, title }) => (
diff --git a/modern/src/components/SideNav.js b/modern/src/components/SideNav.js
index 8bd43ac..aa07808 100644
--- a/modern/src/components/SideNav.js
+++ b/modern/src/components/SideNav.js
@@ -1,5 +1,7 @@
import React from 'react';
-import { List, ListItem, ListItemText, ListItemIcon, Divider, ListSubheader } from '@material-ui/core';
+import {
+ List, ListItem, ListItemText, ListItemIcon, Divider, ListSubheader,
+} from '@material-ui/core';
import { Link, useLocation } from 'react-router-dom';
const SideNav = ({ routes }) => {
@@ -7,26 +9,24 @@ const SideNav = ({ routes }) => {
return (
<List disablePadding style={{ paddingTop: '16px' }}>
- {routes.map((route, index) =>
- route.subheader ? (
- <>
- <Divider />
- <ListSubheader>{route.subheader}</ListSubheader>
- </>
- ) : (
- <ListItem
- disableRipple
- component={Link}
- key={route.href || route.subheader}
- button
- to={route.href}
- selected={location.pathname.match(route.match || route.href)}
- >
- <ListItemIcon>{route.icon}</ListItemIcon>
- <ListItemText primary={route.name} />
- </ListItem>
- )
- )}
+ {routes.map((route, index) => (route.subheader ? (
+ <>
+ <Divider />
+ <ListSubheader>{route.subheader}</ListSubheader>
+ </>
+ ) : (
+ <ListItem
+ disableRipple
+ component={Link}
+ key={route.href || route.subheader}
+ button
+ to={route.href}
+ selected={location.pathname.match(route.match || route.href)}
+ >
+ <ListItemIcon>{route.icon}</ListItemIcon>
+ <ListItemText primary={route.name} />
+ </ListItem>
+ )))}
</List>
);
};
diff --git a/modern/src/components/registration/LoginForm.js b/modern/src/components/registration/LoginForm.js
index 382b4fd..e083541 100644
--- a/modern/src/components/registration/LoginForm.js
+++ b/modern/src/components/registration/LoginForm.js
@@ -1,24 +1,25 @@
import React, { useState } from 'react';
-import { Grid, useMediaQuery, makeStyles, InputLabel, Select, MenuItem, FormControl, Button, TextField, Link } from '@material-ui/core';
+import {
+ Grid, useMediaQuery, makeStyles, InputLabel, Select, MenuItem, FormControl, Button, TextField, Link,
+} from '@material-ui/core';
import { useTheme } from '@material-ui/core/styles';
import { useDispatch, useSelector } from 'react-redux';
import { useHistory } from 'react-router-dom';
import { sessionActions } from '../../store';
import t from '../../common/localization';
-import StartPage from './../../StartPage';
+import StartPage from '../../StartPage';
-const useStyles = makeStyles(theme => ({
+const useStyles = makeStyles((theme) => ({
logoContainer: {
textAlign: 'center',
color: theme.palette.primary.main,
},
resetPassword: {
cursor: 'pointer',
- }
+ },
}));
const LoginForm = () => {
-
const classes = useStyles();
const dispatch = useDispatch();
const history = useHistory();
@@ -27,16 +28,16 @@ const LoginForm = () => {
const [failed, setFailed] = useState(false);
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
- const registrationEnabled = useSelector(state => state.session.server ? state.session.server['registration'] : false);
- const emailEnabled = useSelector(state => state.session.server ? state.session.server['emailEnabled'] : false);
+ const registrationEnabled = useSelector((state) => (state.session.server ? state.session.server.registration : false));
+ const emailEnabled = useSelector((state) => (state.session.server ? state.session.server.emailEnabled : false));
const handleEmailChange = (event) => {
setEmail(event.target.value);
- }
+ };
const handlePasswordChange = (event) => {
setPassword(event.target.value);
- }
+ };
const handleLogin = async (event) => {
event.preventDefault();
@@ -49,38 +50,40 @@ const LoginForm = () => {
setFailed(true);
setPassword('');
}
- }
+ };
- const handleSpecialKey = e => {
+ const handleSpecialKey = (e) => {
if (e.keyCode === 13 && email && password) {
handleLogin(e);
}
- }
+ };
return (
<StartPage>
- <Grid container direction='column' spacing={2}>
- {useMediaQuery(theme.breakpoints.down('md')) &&
+ <Grid container direction="column" spacing={2}>
+ {useMediaQuery(theme.breakpoints.down('md'))
+ && (
<Grid item className={classes.logoContainer}>
<svg height="64" width="240">
- <use xlinkHref="/logo.svg#img"></use>
+ <use xlinkHref="/logo.svg#img" />
</svg>
</Grid>
- }
+ )}
<Grid item>
<TextField
required
fullWidth
error={failed}
label={t('userEmail')}
- name='email'
+ name="email"
value={email}
- autoComplete='email'
+ autoComplete="email"
autoFocus
onChange={handleEmailChange}
onKeyUp={handleSpecialKey}
helperText={failed && 'Invalid username or password'}
- variant='filled' />
+ variant="filled"
+ />
</Grid>
<Grid item>
<TextField
@@ -88,22 +91,24 @@ const LoginForm = () => {
fullWidth
error={failed}
label={t('userPassword')}
- name='password'
+ name="password"
value={password}
- type='password'
- autoComplete='current-password'
+ type="password"
+ autoComplete="current-password"
onChange={handlePasswordChange}
onKeyUp={handleSpecialKey}
- variant='filled' />
+ variant="filled"
+ />
</Grid>
<Grid item>
- <Button
+ <Button
onClick={handleLogin}
onKeyUp={handleSpecialKey}
- variant='contained'
- color='secondary'
+ variant="contained"
+ color="secondary"
disabled={!email || !password}
- fullWidth>
+ fullWidth
+ >
{t('loginLogin')}
</Button>
</Grid>
@@ -122,14 +127,16 @@ const LoginForm = () => {
</FormControl>
</Grid>
</Grid>
- {emailEnabled && <Grid item container justify="flex-end">
+ {emailEnabled && (
+ <Grid item container justify="flex-end">
<Grid item>
- <Link onClick={() => history.push('/reset-password')} className={classes.resetPassword} underline="none">{t('loginReset')}</Link>
+ <Link onClick={() => history.push('/reset-password')} className={classes.resetPassword} underline="none">{t('loginReset')}</Link>
</Grid>
- </Grid>}
+ </Grid>
+ )}
</Grid>
</StartPage>
- )
-}
+ );
+};
export default LoginForm;
diff --git a/modern/src/components/registration/RegisterForm.js b/modern/src/components/registration/RegisterForm.js
index b2a8222..06f5355 100644
--- a/modern/src/components/registration/RegisterForm.js
+++ b/modern/src/components/registration/RegisterForm.js
@@ -1,27 +1,28 @@
import React, { useState } from 'react';
-import { Grid, Button, TextField, Typography, Link, makeStyles, Snackbar } from '@material-ui/core';
+import {
+ Grid, Button, TextField, Typography, Link, makeStyles, Snackbar,
+} from '@material-ui/core';
import { useHistory } from 'react-router-dom';
import ArrowBackIcon from '@material-ui/icons/ArrowBack';
-import StartPage from './../../StartPage';
-import t from './../../common/localization';
+import StartPage from '../../StartPage';
+import t from '../../common/localization';
-const useStyles = makeStyles(theme => ({
+const useStyles = makeStyles((theme) => ({
register: {
fontSize: theme.spacing(3),
fontWeight: 500,
marginLeft: theme.spacing(2),
- textTransform: "uppercase"
+ textTransform: 'uppercase',
},
link: {
fontSize: theme.spacing(3),
fontWeight: 500,
marginTop: theme.spacing(0.5),
- cursor: 'pointer'
- }
+ cursor: 'pointer',
+ },
}));
const RegisterForm = () => {
-
const classes = useStyles();
const history = useHistory();
@@ -30,21 +31,19 @@ const RegisterForm = () => {
const [password, setPassword] = useState('');
const [snackbarOpen, setSnackbarOpen] = useState(false);
- const submitDisabled = () => {
- return !name || !/(.+)@(.+)\.(.{2,})/.test(email) || !password;
- }
+ const submitDisabled = () => !name || !/(.+)@(.+)\.(.{2,})/.test(email) || !password;
const handleRegister = async () => {
const response = await fetch('/api/users', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
- body: JSON.stringify({name, email, password})
+ body: JSON.stringify({ name, email, password }),
});
if (response.ok) {
setSnackbarOpen(true);
- }
- }
+ }
+ };
return (
<StartPage>
@@ -53,18 +52,19 @@ const RegisterForm = () => {
open={snackbarOpen}
onClose={() => history.push('/login')}
autoHideDuration={6000}
- message={t('loginCreated')} />
- <Grid container direction='column' spacing={2}>
+ message={t('loginCreated')}
+ />
+ <Grid container direction="column" spacing={2}>
<Grid container item>
<Grid item>
- <Typography className={classes.link} color='primary'>
+ <Typography className={classes.link} color="primary">
<Link onClick={() => history.push('/login')}>
<ArrowBackIcon />
</Link>
</Typography>
</Grid>
<Grid item xs>
- <Typography className={classes.register} color='primary'>
+ <Typography className={classes.register} color="primary">
{t('loginRegister')}
</Typography>
</Grid>
@@ -74,50 +74,54 @@ const RegisterForm = () => {
required
fullWidth
label={t('sharedName')}
- name='name'
+ name="name"
value={name || ''}
- autoComplete='name'
+ autoComplete="name"
autoFocus
- onChange={event => setName(event.target.value)}
- variant='filled' />
+ onChange={(event) => setName(event.target.value)}
+ variant="filled"
+ />
</Grid>
<Grid item>
<TextField
required
fullWidth
- type='email'
+ type="email"
label={t('userEmail')}
- name='email'
+ name="email"
value={email || ''}
- autoComplete='email'
- onChange={event => setEmail(event.target.value)}
- variant='filled' />
+ autoComplete="email"
+ onChange={(event) => setEmail(event.target.value)}
+ variant="filled"
+ />
</Grid>
<Grid item>
<TextField
required
fullWidth
label={t('userPassword')}
- name='password'
+ name="password"
value={password || ''}
- type='password'
- autoComplete='current-password'
- onChange={event => setPassword(event.target.value)}
- variant='filled' />
+ type="password"
+ autoComplete="current-password"
+ onChange={(event) => setPassword(event.target.value)}
+ variant="filled"
+ />
</Grid>
<Grid item>
<Button
- variant='contained'
- color="secondary"
- onClick={handleRegister}
+ variant="contained"
+ color="secondary"
+ onClick={handleRegister}
disabled={submitDisabled()}
- fullWidth>
- {t('loginRegister')}
+ fullWidth
+ >
+ {t('loginRegister')}
</Button>
</Grid>
</Grid>
</StartPage>
- )
-}
+ );
+};
export default RegisterForm;
diff --git a/modern/src/components/registration/ResetPasswordForm.js b/modern/src/components/registration/ResetPasswordForm.js
index c268f80..f4dd2e4 100644
--- a/modern/src/components/registration/ResetPasswordForm.js
+++ b/modern/src/components/registration/ResetPasswordForm.js
@@ -1,12 +1,9 @@
import React from 'react';
-const ResetPasswordForm = () => {
-
- return (
- <>
- <div>Reset Password Comming Soon!!!</div>
- </>
- )
-}
+const ResetPasswordForm = () => (
+ <>
+ <div>Reset Password Comming Soon!!!</div>
+ </>
+);
export default ResetPasswordForm;
diff --git a/modern/src/form/LinkField.js b/modern/src/form/LinkField.js
index b228fb3..26e1471 100644
--- a/modern/src/form/LinkField.js
+++ b/modern/src/form/LinkField.js
@@ -1,4 +1,6 @@
-import { FormControl, InputLabel, MenuItem, Select } from '@material-ui/core';
+import {
+ FormControl, InputLabel, MenuItem, Select,
+} from '@material-ui/core';
import React, { useState } from 'react';
import { useEffectAsync } from '../reactHelper';
@@ -11,8 +13,8 @@ const LinkField = ({
baseId,
keyBase,
keyLink,
- keyGetter = item => item.id,
- titleGetter = item => item.name,
+ keyGetter = (item) => item.id,
+ titleGetter = (item) => item.name,
}) => {
const [items, setItems] = useState();
const [linked, setLinked] = useState();
@@ -28,28 +30,28 @@ const LinkField = ({
const response = await fetch(endpointLinked);
if (response.ok) {
const data = await response.json();
- setLinked(data.map(it => it.id));
+ setLinked(data.map((it) => it.id));
}
}, []);
- const createBody = linkId => {
+ const createBody = (linkId) => {
const body = {};
body[keyBase] = baseId;
body[keyLink] = linkId;
return body;
- }
+ };
- const onChange = async event => {
+ const onChange = async (event) => {
const oldValue = linked;
const newValue = event.target.value;
- for (const added of newValue.filter(it => !oldValue.includes(it))) {
+ for (const added of newValue.filter((it) => !oldValue.includes(it))) {
await fetch('/api/permissions', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(createBody(added)),
});
}
- for (const removed of oldValue.filter(it => !newValue.includes(it))) {
+ for (const removed of oldValue.filter((it) => !newValue.includes(it))) {
await fetch('/api/permissions', {
method: 'DELETE',
headers: { 'Content-Type': 'application/json' },
@@ -66,16 +68,16 @@ const LinkField = ({
<Select
multiple
value={linked}
- onChange={onChange}>
- {items.map(item => (
+ onChange={onChange}
+ >
+ {items.map((item) => (
<MenuItem key={keyGetter(item)} value={keyGetter(item)}>{titleGetter(item)}</MenuItem>
))}
</Select>
</FormControl>
);
- } else {
- return null;
}
-}
+ return null;
+};
export default LinkField;
diff --git a/modern/src/form/SelectField.js b/modern/src/form/SelectField.js
index b179c58..303d203 100644
--- a/modern/src/form/SelectField.js
+++ b/modern/src/form/SelectField.js
@@ -1,4 +1,6 @@
-import { FormControl, InputLabel, MenuItem, Select } from '@material-ui/core';
+import {
+ FormControl, InputLabel, MenuItem, Select,
+} from '@material-ui/core';
import React, { useState } from 'react';
import { useEffectAsync } from '../reactHelper';
@@ -12,8 +14,8 @@ const SelectField = ({
onChange,
endpoint,
data,
- keyGetter = item => item.id,
- titleGetter = item => item.name,
+ keyGetter = (item) => item.id,
+ titleGetter = (item) => item.name,
}) => {
const [items, setItems] = useState(data);
@@ -33,19 +35,18 @@ const SelectField = ({
<Select
multiple={multiple}
value={value}
- onChange={onChange}>
- {!multiple && emptyValue !== null &&
- <MenuItem value={emptyValue}>&nbsp;</MenuItem>
- }
- {items.map(item => (
+ onChange={onChange}
+ >
+ {!multiple && emptyValue !== null
+ && <MenuItem value={emptyValue}>&nbsp;</MenuItem>}
+ {items.map((item) => (
<MenuItem key={keyGetter(item)} value={keyGetter(item)}>{titleGetter(item)}</MenuItem>
))}
</Select>
</FormControl>
);
- } else {
- return null;
}
-}
+ return null;
+};
export default SelectField;
diff --git a/modern/src/index.js b/modern/src/index.js
index 82ddef9..155bf62 100644
--- a/modern/src/index.js
+++ b/modern/src/index.js
@@ -1,7 +1,7 @@
-import 'typeface-roboto'
+import 'typeface-roboto';
import React from 'react';
import ReactDOM from 'react-dom';
-import { HashRouter } from 'react-router-dom'
+import { HashRouter } from 'react-router-dom';
import { Provider } from 'react-redux';
import App from './App';
diff --git a/modern/src/map/AccuracyMap.js b/modern/src/map/AccuracyMap.js
index e81fc8f..4baa105 100644
--- a/modern/src/map/AccuracyMap.js
+++ b/modern/src/map/AccuracyMap.js
@@ -7,33 +7,31 @@ import { map } from './Map';
const AccuracyMap = () => {
const id = 'accuracy';
- const positions = useSelector(state => ({
+ const positions = useSelector((state) => ({
type: 'FeatureCollection',
- features: Object.values(state.positions.items).filter(position => position.accuracy > 0).map(position =>
- circle([position.longitude, position.latitude], position.accuracy * 0.001)
- ),
+ features: Object.values(state.positions.items).filter((position) => position.accuracy > 0).map((position) => circle([position.longitude, position.latitude], position.accuracy * 0.001)),
}));
useEffect(() => {
map.addSource(id, {
- 'type': 'geojson',
- 'data': {
+ type: 'geojson',
+ data: {
type: 'FeatureCollection',
- features: []
- }
+ features: [],
+ },
});
map.addLayer({
- 'source': id,
- 'id': id,
- 'type': 'fill',
- 'filter': [
- 'all',
- ['==', '$type', 'Polygon'],
+ source: id,
+ id,
+ type: 'fill',
+ filter: [
+ 'all',
+ ['==', '$type', 'Polygon'],
],
- 'paint': {
- 'fill-color':'#3bb2d0',
- 'fill-outline-color':'#3bb2d0',
- 'fill-opacity':0.25,
+ paint: {
+ 'fill-color': '#3bb2d0',
+ 'fill-outline-color': '#3bb2d0',
+ 'fill-opacity': 0.25,
},
});
@@ -48,6 +46,6 @@ const AccuracyMap = () => {
}, [positions]);
return null;
-}
+};
export default AccuracyMap;
diff --git a/modern/src/map/CurrentLocationMap.js b/modern/src/map/CurrentLocationMap.js
index 06aaad0..69724ce 100644
--- a/modern/src/map/CurrentLocationMap.js
+++ b/modern/src/map/CurrentLocationMap.js
@@ -16,6 +16,6 @@ const CurrentLocationMap = () => {
}, []);
return null;
-}
+};
export default CurrentLocationMap;
diff --git a/modern/src/map/CurrentPositionsMap.js b/modern/src/map/CurrentPositionsMap.js
index 0bfe4fc..9e00774 100644
--- a/modern/src/map/CurrentPositionsMap.js
+++ b/modern/src/map/CurrentPositionsMap.js
@@ -1,11 +1,11 @@
-import React, { } from 'react';
+import React, { } from 'react';
import { useSelector } from 'react-redux';
import PositionsMap from './PositionsMap';
const CurrentPositionsMap = () => {
- const positions = useSelector(state => Object.values(state.positions.items));
+ const positions = useSelector((state) => Object.values(state.positions.items));
return (<PositionsMap positions={positions} />);
-}
+};
export default CurrentPositionsMap;
diff --git a/modern/src/map/GeofenceEditMap.js b/modern/src/map/GeofenceEditMap.js
index fe84338..f24fcb3 100644
--- a/modern/src/map/GeofenceEditMap.js
+++ b/modern/src/map/GeofenceEditMap.js
@@ -1,13 +1,13 @@
-import '@mapbox/mapbox-gl-draw/dist/mapbox-gl-draw.css'
+import '@mapbox/mapbox-gl-draw/dist/mapbox-gl-draw.css';
import MapboxDraw from '@mapbox/mapbox-gl-draw';
import theme from '@mapbox/mapbox-gl-draw/src/lib/theme';
import { useEffect } from 'react';
+import { useDispatch, useSelector } from 'react-redux';
+import { useHistory } from 'react-router-dom';
import { map } from './Map';
import { geofenceToFeature, geometryToArea } from './mapUtil';
-import { useDispatch, useSelector } from 'react-redux';
import { geofencesActions } from '../store';
-import { useHistory } from 'react-router-dom';
const draw = new MapboxDraw({
displayControlsDefault: false,
@@ -17,15 +17,15 @@ const draw = new MapboxDraw({
},
userProperties: true,
styles: [...theme, {
- 'id': 'gl-draw-title',
- 'type': 'symbol',
- 'filter': ['all'],
- 'layout': {
+ id: 'gl-draw-title',
+ type: 'symbol',
+ filter: ['all'],
+ layout: {
'text-field': '{user_name}',
'text-font': ['Roboto Regular'],
'text-size': 12,
},
- 'paint': {
+ paint: {
'text-halo-color': 'white',
'text-halo-width': 1,
},
@@ -36,25 +36,25 @@ const GeofenceEditMap = () => {
const dispatch = useDispatch();
const history = useHistory();
- const geofences = useSelector(state => Object.values(state.geofences.items));
+ const geofences = useSelector((state) => Object.values(state.geofences.items));
const refreshGeofences = async () => {
const response = await fetch('/api/geofences');
if (response.ok) {
dispatch(geofencesActions.refresh(await response.json()));
}
- }
+ };
useEffect(() => {
refreshGeofences();
map.addControl(draw, 'top-left');
- map.on('draw.create', async event => {
+ map.on('draw.create', async (event) => {
const feature = event.features[0];
const newItem = { name: '', area: geometryToArea(feature.geometry) };
draw.delete(feature.id);
- const response = await fetch(`/api/geofences`, {
+ const response = await fetch('/api/geofences', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(newItem),
@@ -65,7 +65,7 @@ const GeofenceEditMap = () => {
}
});
- map.on('draw.delete', async event => {
+ map.on('draw.delete', async (event) => {
const feature = event.features[0];
const response = await fetch(`/api/geofences/${feature.id}`, { method: 'DELETE' });
if (response.ok) {
@@ -73,9 +73,9 @@ const GeofenceEditMap = () => {
}
});
- map.on('draw.update', async event => {
+ map.on('draw.update', async (event) => {
const feature = event.features[0];
- const item = geofences.find(i => i.id === feature.id);
+ const item = geofences.find((i) => i.id === feature.id);
if (item) {
const updatedItem = { ...item, area: geometryToArea(feature.geometry) };
const response = await fetch(`/api/geofences/${feature.id}`, {
@@ -100,6 +100,6 @@ const GeofenceEditMap = () => {
}, [geofences]);
return null;
-}
+};
export default GeofenceEditMap;
diff --git a/modern/src/map/GeofenceMap.js b/modern/src/map/GeofenceMap.js
index 8db175a..d00cbb1 100644
--- a/modern/src/map/GeofenceMap.js
+++ b/modern/src/map/GeofenceMap.js
@@ -7,49 +7,49 @@ import { geofenceToFeature } from './mapUtil';
const GeofenceMap = () => {
const id = 'geofences';
- const geofences = useSelector(state => Object.values(state.geofences.items));
+ const geofences = useSelector((state) => Object.values(state.geofences.items));
useEffect(() => {
map.addSource(id, {
- 'type': 'geojson',
- 'data': {
+ type: 'geojson',
+ data: {
type: 'FeatureCollection',
- features: []
- }
+ features: [],
+ },
});
map.addLayer({
- 'source': id,
- 'id': 'geofences-fill',
- 'type': 'fill',
- 'filter': [
- 'all',
- ['==', '$type', 'Polygon'],
+ source: id,
+ id: 'geofences-fill',
+ type: 'fill',
+ filter: [
+ 'all',
+ ['==', '$type', 'Polygon'],
],
- 'paint': {
- 'fill-color':'#3bb2d0',
- 'fill-outline-color':'#3bb2d0',
- 'fill-opacity':0.1,
+ paint: {
+ 'fill-color': '#3bb2d0',
+ 'fill-outline-color': '#3bb2d0',
+ 'fill-opacity': 0.1,
},
});
map.addLayer({
- 'source': id,
- 'id': 'geofences-line',
- 'type': 'line',
- 'paint': {
- 'line-color': '#3bb2d0',
- 'line-width': 2,
+ source: id,
+ id: 'geofences-line',
+ type: 'line',
+ paint: {
+ 'line-color': '#3bb2d0',
+ 'line-width': 2,
},
});
map.addLayer({
- 'source': id,
- 'id': 'geofences-title',
- 'type': 'symbol',
- 'layout': {
+ source: id,
+ id: 'geofences-title',
+ type: 'symbol',
+ layout: {
'text-field': '{name}',
'text-font': ['Roboto Regular'],
'text-size': 12,
},
- 'paint': {
+ paint: {
'text-halo-color': 'white',
'text-halo-width': 1,
},
@@ -66,11 +66,11 @@ const GeofenceMap = () => {
useEffect(() => {
map.getSource(id).setData({
type: 'FeatureCollection',
- features: geofences.map(geofenceToFeature)
+ features: geofences.map(geofenceToFeature),
});
}, [geofences]);
return null;
-}
+};
export default GeofenceMap;
diff --git a/modern/src/map/Map.js b/modern/src/map/Map.js
index 46c59d2..672bd26 100644
--- a/modern/src/map/Map.js
+++ b/modern/src/map/Map.js
@@ -1,8 +1,10 @@
import 'maplibre-gl/dist/maplibre-gl.css';
import './switcher/switcher.css';
import maplibregl from 'maplibre-gl';
+import React, {
+ useRef, useLayoutEffect, useEffect, useState,
+} from 'react';
import { SwitcherControl } from './switcher/switcher';
-import React, { useRef, useLayoutEffect, useEffect, useState } from 'react';
import { deviceCategories } from '../common/deviceCategories';
import { prepareIcon, loadImage } from './mapUtil';
import { styleCarto, styleMapbox, styleOsm } from './mapStyles';
@@ -22,18 +24,18 @@ export const map = new maplibregl.Map({
let ready = false;
const readyListeners = new Set();
-const addReadyListener = listener => {
+const addReadyListener = (listener) => {
readyListeners.add(listener);
listener(ready);
};
-const removeReadyListener = listener => {
+const removeReadyListener = (listener) => {
readyListeners.delete(listener);
};
-const updateReadyValue = value => {
+const updateReadyValue = (value) => {
ready = value;
- readyListeners.forEach(listener => listener(value));
+ readyListeners.forEach((listener) => listener(value));
};
const initMap = async () => {
@@ -42,7 +44,7 @@ const initMap = async () => {
map.addImage('background', await prepareIcon(background), {
pixelRatio: window.devicePixelRatio,
});
- await Promise.all(deviceCategories.map(async category => {
+ await Promise.all(deviceCategories.map(async (category) => {
for (const color of ['green', 'red', 'gray']) {
const icon = await loadImage(`images/icon/${category}.svg`);
map.addImage(`${category}-${color}`, prepareIcon(background, icon, palette.common[color]), {
@@ -93,7 +95,7 @@ const Map = ({ children }) => {
}, [mapboxAccessToken]);
useEffect(() => {
- const listener = ready => setMapReady(ready);
+ const listener = (ready) => setMapReady(ready);
addReadyListener(listener);
return () => {
removeReadyListener(listener);
diff --git a/modern/src/map/PositionsMap.js b/modern/src/map/PositionsMap.js
index 35d6d92..2de01d2 100644
--- a/modern/src/map/PositionsMap.js
+++ b/modern/src/map/PositionsMap.js
@@ -3,9 +3,9 @@ import ReactDOM from 'react-dom';
import maplibregl from 'maplibre-gl';
import { Provider, useSelector } from 'react-redux';
+import { useHistory } from 'react-router-dom';
import { map } from './Map';
import store from '../store';
-import { useHistory } from 'react-router-dom';
import StatusView from './StatusView';
const PositionsMap = ({ positions }) => {
@@ -13,9 +13,9 @@ const PositionsMap = ({ positions }) => {
const clusters = `${id}-clusters`;
const history = useHistory();
- const devices = useSelector(state => state.devices.items);
+ const devices = useSelector((state) => state.devices.items);
- const deviceColor = device => {
+ const deviceColor = (device) => {
switch (device.status) {
case 'online':
return 'green';
@@ -33,15 +33,15 @@ const PositionsMap = ({ positions }) => {
name: device.name,
category: device.category || 'default',
color: deviceColor(device),
- }
+ };
};
const onMouseEnter = () => map.getCanvas().style.cursor = 'pointer';
const onMouseLeave = () => map.getCanvas().style.cursor = '';
- const onMarkerClick = useCallback(event => {
+ const onMarkerClick = useCallback((event) => {
const feature = event.features[0];
- let coordinates = feature.geometry.coordinates.slice();
+ const coordinates = feature.geometry.coordinates.slice();
while (Math.abs(event.lngLat.lng - coordinates[0]) > 180) {
coordinates[0] += event.lngLat.lng > coordinates[0] ? 360 : -360;
}
@@ -49,50 +49,52 @@ const PositionsMap = ({ positions }) => {
const placeholder = document.createElement('div');
ReactDOM.render(
<Provider store={store}>
- <StatusView deviceId={feature.properties.deviceId} onShowDetails={positionId => history.push(`/position/${positionId}`)} />
+ <StatusView deviceId={feature.properties.deviceId} onShowDetails={(positionId) => history.push(`/position/${positionId}`)} />
</Provider>,
- placeholder
+ placeholder,
);
new maplibregl.Popup({
offset: 25,
- anchor: 'top'
+ anchor: 'top',
})
.setDOMContent(placeholder)
.setLngLat(coordinates)
.addTo(map);
}, [history]);
- const onClusterClick = event => {
+ const onClusterClick = (event) => {
const features = map.queryRenderedFeatures(event.point, {
layers: [clusters],
});
const clusterId = features[0].properties.cluster_id;
map.getSource(id).getClusterExpansionZoom(clusterId, (error, zoom) => {
- if (!error) map.easeTo({
- center: features[0].geometry.coordinates,
- zoom: zoom,
- });
+ if (!error) {
+ map.easeTo({
+ center: features[0].geometry.coordinates,
+ zoom,
+ });
+ }
});
};
useEffect(() => {
map.addSource(id, {
- 'type': 'geojson',
- 'data': {
+ type: 'geojson',
+ data: {
type: 'FeatureCollection',
features: [],
},
- 'cluster': true,
- 'clusterMaxZoom': 14,
- 'clusterRadius': 50,
+ cluster: true,
+ clusterMaxZoom: 14,
+ clusterRadius: 50,
});
map.addLayer({
- 'id': id,
- 'type': 'symbol',
- 'source': id,
- 'filter': ['!', ['has', 'point_count']],
- 'layout': {
+ id,
+ type: 'symbol',
+ source: id,
+ filter: ['!', ['has', 'point_count']],
+ layout: {
'icon-image': '{category}-{color}',
'icon-allow-overlap': true,
'text-field': '{name}',
@@ -102,17 +104,17 @@ const PositionsMap = ({ positions }) => {
'text-font': ['Roboto Regular'],
'text-size': 12,
},
- 'paint': {
+ paint: {
'text-halo-color': 'white',
'text-halo-width': 1,
},
});
map.addLayer({
- 'id': clusters,
- 'type': 'symbol',
- 'source': id,
- 'filter': ['has', 'point_count'],
- 'layout': {
+ id: clusters,
+ type: 'symbol',
+ source: id,
+ filter: ['has', 'point_count'],
+ layout: {
'icon-image': 'background',
'text-field': '{point_count_abbreviated}',
'text-font': ['Roboto Regular'],
@@ -120,7 +122,6 @@ const PositionsMap = ({ positions }) => {
},
});
-
map.on('mouseenter', id, onMouseEnter);
map.on('mouseleave', id, onMouseLeave);
map.on('mouseenter', clusters, onMouseEnter);
@@ -129,7 +130,7 @@ const PositionsMap = ({ positions }) => {
map.on('click', clusters, onClusterClick);
return () => {
- Array.from(map.getContainer().getElementsByClassName('maplibregl-popup')).forEach(el => el.remove());
+ Array.from(map.getContainer().getElementsByClassName('maplibregl-popup')).forEach((el) => el.remove());
map.off('mouseenter', id, onMouseEnter);
map.off('mouseleave', id, onMouseLeave);
@@ -147,18 +148,18 @@ const PositionsMap = ({ positions }) => {
useEffect(() => {
map.getSource(id).setData({
type: 'FeatureCollection',
- features: positions.filter(it => devices.hasOwnProperty(it.deviceId)).map(position => ({
+ features: positions.filter((it) => devices.hasOwnProperty(it.deviceId)).map((position) => ({
type: 'Feature',
geometry: {
type: 'Point',
coordinates: [position.longitude, position.latitude],
},
properties: createFeature(devices, position),
- }))
+ })),
});
}, [devices, positions]);
return null;
-}
+};
export default PositionsMap;
diff --git a/modern/src/map/ReplayPathMap.js b/modern/src/map/ReplayPathMap.js
index b40aa69..62b3f27 100644
--- a/modern/src/map/ReplayPathMap.js
+++ b/modern/src/map/ReplayPathMap.js
@@ -7,8 +7,8 @@ const ReplayPathMap = ({ positions }) => {
useEffect(() => {
map.addSource(id, {
- 'type': 'geojson',
- 'data': {
+ type: 'geojson',
+ data: {
type: 'Feature',
geometry: {
type: 'LineString',
@@ -17,16 +17,16 @@ const ReplayPathMap = ({ positions }) => {
},
});
map.addLayer({
- 'source': id,
- 'id': id,
- 'type': 'line',
- 'layout': {
+ source: id,
+ id,
+ type: 'line',
+ layout: {
'line-join': 'round',
'line-cap': 'round',
},
- 'paint': {
- 'line-color': '#333',
- 'line-width': 5,
+ paint: {
+ 'line-color': '#333',
+ 'line-width': 5,
},
});
@@ -37,23 +37,25 @@ const ReplayPathMap = ({ positions }) => {
}, []);
useEffect(() => {
- const coordinates = positions.map(item => [item.longitude, item.latitude]);
+ const coordinates = positions.map((item) => [item.longitude, item.latitude]);
map.getSource(id).setData({
type: 'Feature',
geometry: {
type: 'LineString',
- coordinates: coordinates,
+ coordinates,
},
});
if (coordinates.length) {
const bounds = coordinates.reduce((bounds, item) => bounds.extend(item), new maplibregl.LngLatBounds(coordinates[0], coordinates[0]));
map.fitBounds(bounds, {
- padding: { top: 50, bottom: 250, left: 25, right: 25 },
+ padding: {
+ top: 50, bottom: 250, left: 25, right: 25,
+ },
});
}
}, [positions]);
return null;
-}
+};
export default ReplayPathMap;
diff --git a/modern/src/map/SelectedDeviceMap.js b/modern/src/map/SelectedDeviceMap.js
index 655fca9..e6c5f58 100644
--- a/modern/src/map/SelectedDeviceMap.js
+++ b/modern/src/map/SelectedDeviceMap.js
@@ -4,7 +4,7 @@ import { useSelector } from 'react-redux';
import { map } from './Map';
const SelectedDeviceMap = () => {
- const mapCenter = useSelector(state => {
+ const mapCenter = useSelector((state) => {
if (state.devices.selectedId) {
const position = state.positions.items[state.devices.selectedId] || null;
if (position) {
@@ -19,6 +19,6 @@ const SelectedDeviceMap = () => {
}, [mapCenter]);
return null;
-}
+};
export default SelectedDeviceMap;
diff --git a/modern/src/map/StatusView.js b/modern/src/map/StatusView.js
index ae049af..20e5b74 100644
--- a/modern/src/map/StatusView.js
+++ b/modern/src/map/StatusView.js
@@ -1,27 +1,68 @@
-import t from '../common/localization'
import React from 'react';
import { useSelector } from 'react-redux';
+import t from '../common/localization';
import { formatPosition } from '../common/formatter';
const StatusView = ({ deviceId, onShowDetails }) => {
- const device = useSelector(state => state.devices.items[deviceId]);
- const position = useSelector(state => state.positions.items[deviceId]);
+ const device = useSelector((state) => state.devices.items[deviceId]);
+ const position = useSelector((state) => state.positions.items[deviceId]);
- const handleClick = e => {
+ const handleClick = (e) => {
e.preventDefault();
onShowDetails(position.id);
};
return (
<>
- <b>{t('deviceStatus')}:</b> {formatPosition(device.status, 'status')}<br />
- <b>{t('sharedLocation')}:</b> {formatPosition(position, 'latitude')} {formatPosition(position, 'longitude')}<br />
- <b>{t('positionSpeed')}:</b> {formatPosition(position.speed, 'speed')}<br />
- <b>{t('positionCourse')}:</b> {formatPosition(position.course, 'course')}<br />
- <b>{t('positionDistance')}:</b> {formatPosition(position.attributes.totalDistance, 'distance')}<br />
- {position.attributes.batteryLevel &&
- <><b>{t('positionBattery')}:</b> {formatPosition(position.attributes.batteryLevel, 'batteryLevel')}<br /></>
- }
+ <b>
+ {t('deviceStatus')}
+ :
+ </b>
+ {' '}
+ {formatPosition(device.status, 'status')}
+ <br />
+ <b>
+ {t('sharedLocation')}
+ :
+ </b>
+ {' '}
+ {formatPosition(position, 'latitude')}
+ {' '}
+ {formatPosition(position, 'longitude')}
+ <br />
+ <b>
+ {t('positionSpeed')}
+ :
+ </b>
+ {' '}
+ {formatPosition(position.speed, 'speed')}
+ <br />
+ <b>
+ {t('positionCourse')}
+ :
+ </b>
+ {' '}
+ {formatPosition(position.course, 'course')}
+ <br />
+ <b>
+ {t('positionDistance')}
+ :
+ </b>
+ {' '}
+ {formatPosition(position.attributes.totalDistance, 'distance')}
+ <br />
+ {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/map/mapStyles.js b/modern/src/map/mapStyles.js
index 00a8666..9650ead 100644
--- a/modern/src/map/mapStyles.js
+++ b/modern/src/map/mapStyles.js
@@ -4,7 +4,7 @@ export const styleCustom = (url, attribution) => ({
osm: {
type: 'raster',
tiles: [url],
- attribution: attribution,
+ attribution,
tileSize: 256,
},
},
@@ -22,30 +22,30 @@ export const styleOsm = () => styleCustom(
);
export const styleCarto = () => ({
- 'version': 8,
- 'sources': {
+ version: 8,
+ sources: {
'raster-tiles': {
- 'type': 'raster',
- 'tiles': [
- 'https://a.basemaps.cartocdn.com/rastertiles/voyager/{z}/{x}/{y}@2x.png',
- 'https://b.basemaps.cartocdn.com/rastertiles/voyager/{z}/{x}/{y}@2x.png',
- 'https://c.basemaps.cartocdn.com/rastertiles/voyager/{z}/{x}/{y}@2x.png',
- 'https://d.basemaps.cartocdn.com/rastertiles/voyager/{z}/{x}/{y}@2x.png'
+ type: 'raster',
+ tiles: [
+ 'https://a.basemaps.cartocdn.com/rastertiles/voyager/{z}/{x}/{y}@2x.png',
+ 'https://b.basemaps.cartocdn.com/rastertiles/voyager/{z}/{x}/{y}@2x.png',
+ 'https://c.basemaps.cartocdn.com/rastertiles/voyager/{z}/{x}/{y}@2x.png',
+ 'https://d.basemaps.cartocdn.com/rastertiles/voyager/{z}/{x}/{y}@2x.png',
],
- 'tileSize': 256,
- 'attribution': 'Ā© <a target="_top" rel="noopener" href="http://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors, Ā© <a target="_top" rel="noopener" href="https://carto.com/attribution">CARTO</a>'
- }
+ tileSize: 256,
+ attribution: 'Ā© <a target="_top" rel="noopener" href="http://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors, Ā© <a target="_top" rel="noopener" href="https://carto.com/attribution">CARTO</a>',
+ },
},
- 'glyphs': 'https://cdn.traccar.com/map/fonts/{fontstack}/{range}.pbf',
- 'layers': [
+ glyphs: 'https://cdn.traccar.com/map/fonts/{fontstack}/{range}.pbf',
+ layers: [
{
- 'id': 'simple-tiles',
- 'type': 'raster',
- 'source': 'raster-tiles',
- 'minzoom': 0,
- 'maxzoom': 22,
- }
- ]
+ id: 'simple-tiles',
+ type: 'raster',
+ source: 'raster-tiles',
+ minzoom: 0,
+ maxzoom: 22,
+ },
+ ],
});
export const styleMapbox = (style) => `mapbox://styles/mapbox/${style}`;
diff --git a/modern/src/map/mapUtil.js b/modern/src/map/mapUtil.js
index 67ce345..e3c32f4 100644
--- a/modern/src/map/mapUtil.js
+++ b/modern/src/map/mapUtil.js
@@ -2,13 +2,11 @@ import { parse, stringify } from 'wellknown';
import canvasTintImage from 'canvas-tint-image';
import circle from '@turf/circle';
-export const loadImage = (url) => {
- return new Promise(imageLoaded => {
- const image = new Image();
- image.onload = () => imageLoaded(image);
- image.src = url;
- });
-};
+export const loadImage = (url) => new Promise((imageLoaded) => {
+ const image = new Image();
+ image.onload = () => imageLoaded(image);
+ image.src = url;
+});
export const prepareIcon = (background, icon, color) => {
const pixelRatio = window.devicePixelRatio;
@@ -32,44 +30,39 @@ export const prepareIcon = (background, icon, color) => {
return context.getImageData(0, 0, canvas.width, canvas.height);
};
-export const reverseCoordinates = it => {
+export const reverseCoordinates = (it) => {
if (!it) {
return it;
- } else if (Array.isArray(it)) {
+ } if (Array.isArray(it)) {
if (it.length === 2 && !Number.isNaN(it[0]) && !Number.isNaN(it[1])) {
return [it[1], it[0]];
- } else {
- return it.map(it => reverseCoordinates(it));
- }
- } else {
- return {
- ...it,
- coordinates: reverseCoordinates(it.coordinates),
}
+ return it.map((it) => reverseCoordinates(it));
}
-}
+ return {
+ ...it,
+ coordinates: reverseCoordinates(it.coordinates),
+ };
+};
export const geofenceToFeature = (item) => {
if (item.area.indexOf('CIRCLE') > -1) {
- let coordinates = item.area.replace(/CIRCLE|\(|\)|,/g, " ").trim().split(/ +/);
- var options = { steps: 32, units: 'meters' };
- let polygon = circle([Number(coordinates[1]), Number(coordinates[0])], Number(coordinates[2]), options);
+ const coordinates = item.area.replace(/CIRCLE|\(|\)|,/g, ' ').trim().split(/ +/);
+ const options = { steps: 32, units: 'meters' };
+ const polygon = circle([Number(coordinates[1]), Number(coordinates[0])], Number(coordinates[2]), options);
return {
id: item.id,
type: 'Feature',
geometry: polygon.geometry,
- properties: { name: item.name }
- };
- } else {
- return {
- id: item.id,
- type: 'Feature',
- geometry: reverseCoordinates(parse(item.area)),
- properties: { name: item.name }
+ properties: { name: item.name },
};
}
-}
+ return {
+ id: item.id,
+ type: 'Feature',
+ geometry: reverseCoordinates(parse(item.area)),
+ properties: { name: item.name },
+ };
+};
-export const geometryToArea = (geometry) => {
- return stringify(reverseCoordinates(geometry));
-}
+export const geometryToArea = (geometry) => stringify(reverseCoordinates(geometry));
diff --git a/modern/src/reactHelper.js b/modern/src/reactHelper.js
index b0eb016..d8e9200 100644
--- a/modern/src/reactHelper.js
+++ b/modern/src/reactHelper.js
@@ -1,7 +1,6 @@
-
import { useRef, useEffect } from 'react';
-export const usePrevious = value => {
+export const usePrevious = (value) => {
const ref = useRef();
useEffect(() => {
ref.current = value;
diff --git a/modern/src/reports/ChartReportPage.js b/modern/src/reports/ChartReportPage.js
index 8eeedc4..c55ed6d 100644
--- a/modern/src/reports/ChartReportPage.js
+++ b/modern/src/reports/ChartReportPage.js
@@ -1,5 +1,7 @@
import React, { useState } from 'react';
-import { Grid, FormControl, InputLabel, Select, MenuItem } from '@material-ui/core';
+import {
+ Grid, FormControl, InputLabel, Select, MenuItem,
+} from '@material-ui/core';
import ReportLayout from './ReportLayout';
import ReportFilter from './ReportFilter';
import Graph from './Graph';
@@ -9,66 +11,61 @@ import { speedFromKnots } 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 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(speedFromKnots(position.speed, speedUnit)),
- altitude: position.altitude,
- accuracy: position.accuracy,
- fixTime: formatDate(position.fixTime)
- }
- });
+ const formattedPositions = positions.map((position) => ({
+ speed: Number(speedFromKnots(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 (
- <Grid container spacing={3}>
- <Grid item xs={12} sm={6}>
- <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>
- </Grid>
+const ChartType = ({ type, setType }) => (
+ <Grid container spacing={3}>
+ <Grid item xs={12} sm={6}>
+ <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>
</Grid>
- )
-}
-
+ </Grid>
+);
const ChartReportPage = () => {
-
const [items, setItems] = useState([]);
const [type, setType] = useState('speed');
return (
- <ReportLayout filter={
+ <ReportLayout filter={(
<Filter setItems={setItems}>
<ChartType type={type} setType={setType} />
</Filter>
- }>
+ )}
+ >
<Graph items={items} type={type} />
</ReportLayout>
- )
-}
+ );
+};
export default ChartReportPage;
diff --git a/modern/src/reports/EventReportPage.js b/modern/src/reports/EventReportPage.js
index b938dc8..b5c3dae 100644
--- a/modern/src/reports/EventReportPage.js
+++ b/modern/src/reports/EventReportPage.js
@@ -1,7 +1,9 @@
import React, { useState } from 'react';
import { DataGrid } from '@material-ui/data-grid';
-import { Grid, FormControl, InputLabel, Select, MenuItem } from '@material-ui/core';
-import { useTheme } from "@material-ui/core/styles";
+import {
+ Grid, FormControl, InputLabel, Select, MenuItem,
+} from '@material-ui/core';
+import { useTheme } from '@material-ui/core/styles';
import { useSelector } from 'react-redux';
import { formatDate } from '../common/formatter';
import ReportFilter from './ReportFilter';
@@ -10,12 +12,13 @@ import { prefixString } from '../common/stringUtils';
import t from '../common/localization';
const Filter = ({ setItems }) => {
-
const [eventTypes, setEventTypes] = useState(['allEvents']);
const handleSubmit = async (deviceId, from, to, mail, headers) => {
- const query = new URLSearchParams({ deviceId, from, to, mail });
- eventTypes.forEach(it => query.append('type', it));
+ const query = new URLSearchParams({
+ deviceId, from, to, mail,
+ });
+ eventTypes.forEach((it) => query.append('type', it));
const response = await fetch(`/api/reports/events?${query.toString()}`, { headers });
if (response.ok) {
const contentType = response.headers.get('content-type');
@@ -34,7 +37,7 @@ const Filter = ({ setItems }) => {
<Grid item xs={12} sm={6}>
<FormControl variant="filled" fullWidth>
<InputLabel>{t('reportEventTypes')}</InputLabel>
- <Select value={eventTypes} onChange={e => setEventTypes(e.target.value)} multiple>
+ <Select value={eventTypes} onChange={(e) => setEventTypes(e.target.value)} multiple>
<MenuItem value="allEvents">{t('eventAll')}</MenuItem>
<MenuItem value="deviceOnline">{t('eventDeviceOnline')}</MenuItem>
<MenuItem value="deviceUnknown">{t('eventDeviceUnknown')}</MenuItem>
@@ -58,21 +61,20 @@ const Filter = ({ setItems }) => {
</Grid>
</ReportFilter>
);
-}
+};
const EventReportPage = () => {
-
const theme = useTheme();
- const geofences = useSelector(state => state.geofences.items);
+ const geofences = useSelector((state) => state.geofences.items);
const [items, setItems] = useState([]);
- const formatGeofence = value => {
+ const formatGeofence = (value) => {
if (value > 0) {
- const geofence = geofences[value];
- return geofence ? geofence.name : '';
+ const geofence = geofences[value];
+ return geofence ? geofence.name : '';
}
return null;
- }
+ };
const columns = [{
headerName: t('positionFixTime'),
@@ -101,12 +103,13 @@ const EventReportPage = () => {
return (
<ReportLayout filter={<Filter setItems={setItems} />}>
<DataGrid
- rows={items}
- columns={columns}
- hideFooter
- autoHeight />
+ rows={items}
+ columns={columns}
+ hideFooter
+ autoHeight
+ />
</ReportLayout>
);
-}
+};
export default EventReportPage;
diff --git a/modern/src/reports/Graph.js b/modern/src/reports/Graph.js
index 990eb5d..63d24ee 100644
--- a/modern/src/reports/Graph.js
+++ b/modern/src/reports/Graph.js
@@ -1,9 +1,11 @@
import React from 'react';
import { withWidth } from '@material-ui/core';
-import {LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, Legend, ResponsiveContainer } from 'recharts';
+import {
+ LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, Legend, ResponsiveContainer,
+} from 'recharts';
-const CustomizedAxisTick = ({ x, y, payload }) =>{
- if(!payload.value) {
+const CustomizedAxisTick = ({ x, y, payload }) => {
+ if (!payload.value) {
return payload.value;
}
const parts = payload.value.split(' ');
@@ -13,22 +15,19 @@ const CustomizedAxisTick = ({ x, y, payload }) =>{
<text x={0} y={16} dy={16} textAnchor="end" fill="#666" transform="rotate(-35)">{parts[1]}</text>
</g>
);
-}
+};
-const Graph = ({ type, items }) => {
-
- return (
- <ResponsiveContainer height={400} width="100%" debounce={1}>
- <LineChart data={items}>
- <XAxis dataKey="fixTime" tick={<CustomizedAxisTick/>} height={60} />
- <YAxis />
- <CartesianGrid strokeDasharray="3 3" />
- <Tooltip />
- <Legend />
- <Line type="natural" dataKey={type} />
- </LineChart>
- </ResponsiveContainer>
- );
-}
+const Graph = ({ type, items }) => (
+ <ResponsiveContainer height={400} width="100%" debounce={1}>
+ <LineChart data={items}>
+ <XAxis dataKey="fixTime" tick={<CustomizedAxisTick />} height={60} />
+ <YAxis />
+ <CartesianGrid strokeDasharray="3 3" />
+ <Tooltip />
+ <Legend />
+ <Line type="natural" dataKey={type} />
+ </LineChart>
+ </ResponsiveContainer>
+);
export default withWidth()(Graph);
diff --git a/modern/src/reports/ReplayPage.js b/modern/src/reports/ReplayPage.js
index dfa9999..12bbd35 100644
--- a/modern/src/reports/ReplayPage.js
+++ b/modern/src/reports/ReplayPage.js
@@ -1,5 +1,7 @@
import React, { useState } from 'react';
-import { Accordion, AccordionDetails, AccordionSummary, Container, makeStyles, Paper, Slider, Tooltip, Typography } from '@material-ui/core';
+import {
+ Accordion, AccordionDetails, AccordionSummary, Container, 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';
@@ -9,7 +11,7 @@ import PositionsMap from '../map/PositionsMap';
import { formatPosition } from '../common/formatter';
import ReportFilter from './ReportFilter';
-const useStyles = makeStyles(theme => ({
+const useStyles = makeStyles((theme) => ({
root: {
height: '100%',
display: 'flex',
@@ -31,13 +33,11 @@ const useStyles = makeStyles(theme => ({
},
}));
-const TimeLabel = ({ children, open, value }) => {
- return (
- <Tooltip open={open} enterTouchDelay={0} placement="top" title={value}>
- {children}
- </Tooltip>
- );
-};
+const TimeLabel = ({ children, open, value }) => (
+ <Tooltip open={open} enterTouchDelay={0} placement="top" title={value}>
+ {children}
+ </Tooltip>
+);
const ReplayPage = () => {
const classes = useStyles();
@@ -61,12 +61,12 @@ const ReplayPage = () => {
<MainToolbar />
<Map>
<ReplayPathMap positions={positions} />
- {index < positions.length &&
- <PositionsMap positions={[positions[index]]} />
- }
+ {index < positions.length
+ && <PositionsMap positions={[positions[index]]} />}
</Map>
<Container maxWidth="sm" className={classes.controlPanel}>
- {!!positions.length &&
+ {!!positions.length
+ && (
<Paper className={classes.controlContent}>
<Slider
max={positions.length - 1}
@@ -75,15 +75,15 @@ const ReplayPage = () => {
value={index}
onChange={(_, index) => setIndex(index)}
valueLabelDisplay="auto"
- valueLabelFormat={i => i < positions.length ? formatPosition(positions[i], 'fixTime') : ''}
+ valueLabelFormat={(i) => (i < positions.length ? formatPosition(positions[i], 'fixTime') : '')}
ValueLabelComponent={TimeLabel}
- />
+ />
</Paper>
- }
+ )}
<div>
<Accordion expanded={expanded} onChange={() => setExpanded(!expanded)}>
<AccordionSummary expandIcon={<ExpandMoreIcon />}>
- <Typography align='center'>
+ <Typography align="center">
{t('reportConfigure')}
</Typography>
</AccordionSummary>
@@ -95,6 +95,6 @@ const ReplayPage = () => {
</Container>
</div>
);
-}
+};
export default ReplayPage;
diff --git a/modern/src/reports/ReportFilter.js b/modern/src/reports/ReportFilter.js
index 524f7bb..dec8d01 100644
--- a/modern/src/reports/ReportFilter.js
+++ b/modern/src/reports/ReportFilter.js
@@ -1,11 +1,13 @@
import React, { useState } from 'react';
-import { FormControl, InputLabel, Select, MenuItem, Button, TextField, Grid, Typography } from '@material-ui/core';
+import {
+ FormControl, InputLabel, Select, MenuItem, Button, TextField, Grid, Typography,
+} from '@material-ui/core';
import { useSelector } from 'react-redux';
import moment from 'moment';
import t from '../common/localization';
const ReportFilter = ({ children, handleSubmit, showOnly }) => {
- const devices = useSelector(state => Object.values(state.devices.items));
+ const devices = useSelector((state) => Object.values(state.devices.items));
const [deviceId, setDeviceId] = useState();
const [period, setPeriod] = useState('today');
const [from, setFrom] = useState(moment().subtract(1, 'hour'));
@@ -51,9 +53,9 @@ const ReportFilter = ({ children, handleSubmit, showOnly }) => {
selectedFrom.toISOString(),
selectedTo.toISOString(),
mail,
- { Accept: accept }
+ { Accept: accept },
);
- }
+ };
return (
<Grid container spacing={2} justify="flex-end">
@@ -81,56 +83,69 @@ const ReportFilter = ({ children, handleSubmit, showOnly }) => {
</Select>
</FormControl>
</Grid>
- {period === 'custom' && <Grid item xs={12} sm={3}>
+ {period === 'custom' && (
+ <Grid item xs={12} sm={3}>
<TextField
variant="filled"
label={t('reportFrom')}
type="datetime-local"
value={from.format(moment.HTML5_FMT.DATETIME_LOCAL)}
- onChange={e => setFrom(moment(e.target.value, moment.HTML5_FMT.DATETIME_LOCAL))}
- fullWidth />
- </Grid>}
- {period === 'custom' && <Grid item xs={12} sm={3}>
+ onChange={(e) => setFrom(moment(e.target.value, moment.HTML5_FMT.DATETIME_LOCAL))}
+ fullWidth
+ />
+ </Grid>
+ )}
+ {period === 'custom' && (
+ <Grid item xs={12} sm={3}>
<TextField
variant="filled"
label={t('reportTo')}
type="datetime-local"
value={to.format(moment.HTML5_FMT.DATETIME_LOCAL)}
- onChange={e => setTo(moment(e.target.value, moment.HTML5_FMT.DATETIME_LOCAL))}
- fullWidth />
- </Grid>}
+ onChange={(e) => setTo(moment(e.target.value, moment.HTML5_FMT.DATETIME_LOCAL))}
+ fullWidth
+ />
+ </Grid>
+ )}
{children}
<Grid item xs={!showOnly ? 4 : 12} sm={!showOnly ? 2 : 6}>
- <Button
+ <Button
onClick={() => handleClick(false, true)}
- variant='outlined'
- color='secondary'
- fullWidth>
+ variant="outlined"
+ color="secondary"
+ fullWidth
+ >
{t('reportShow')}
</Button>
</Grid>
- {!showOnly &&
+ {!showOnly
+ && (
<Grid item xs={4} sm={2}>
- <Button
- onClick={() => handleClick(false, false)}
- variant='outlined'
- color='secondary'
- fullWidth>
- {t('reportExport')}
- </Button>
- </Grid>}
- {!showOnly &&
+ <Button
+ onClick={() => handleClick(false, false)}
+ variant="outlined"
+ color="secondary"
+ fullWidth
+ >
+ {t('reportExport')}
+ </Button>
+ </Grid>
+ )}
+ {!showOnly
+ && (
<Grid item xs={4} sm={2}>
- <Button
- onClick={() => handleClick(true, false)}
- variant='outlined'
- color='secondary'
- fullWidth>
- <Typography variant="button" noWrap>{t('reportEmail')}</Typography>
- </Button>
- </Grid>}
+ <Button
+ onClick={() => handleClick(true, false)}
+ variant="outlined"
+ color="secondary"
+ fullWidth
+ >
+ <Typography variant="button" noWrap>{t('reportEmail')}</Typography>
+ </Button>
+ </Grid>
+ )}
</Grid>
);
-}
+};
export default ReportFilter;
diff --git a/modern/src/reports/ReportLayout.js b/modern/src/reports/ReportLayout.js
index 5b54335..92ffc0c 100644
--- a/modern/src/reports/ReportLayout.js
+++ b/modern/src/reports/ReportLayout.js
@@ -7,7 +7,7 @@ import {
Drawer,
makeStyles,
IconButton,
- Hidden
+ Hidden,
} from '@material-ui/core';
import TimelineIcon from '@material-ui/icons/Timeline';
import PauseCircleFilledIcon from '@material-ui/icons/PauseCircleFilled';
@@ -21,35 +21,35 @@ import SideNav from '../components/SideNav';
import NavBar from '../components/NavBar';
import t from '../common/localization';
-const useStyles = makeStyles(theme => ({
+const useStyles = makeStyles((theme) => ({
root: {
display: 'flex',
- height: '100%'
+ height: '100%',
},
drawerContainer: {
- width: theme.dimensions.drawerWidthDesktop
+ width: theme.dimensions.drawerWidthDesktop,
},
drawer: {
width: theme.dimensions.drawerWidthDesktop,
[theme.breakpoints.down('md')]: {
- width: theme.dimensions.drawerWidthTablet
- }
+ width: theme.dimensions.drawerWidthTablet,
+ },
},
content: {
flex: 1,
- padding: theme.spacing(5, 3, 3, 3)
+ padding: theme.spacing(5, 3, 3, 3),
},
drawerHeader: {
...theme.mixins.toolbar,
display: 'flex',
alignItems: 'center',
- padding: theme.spacing(0, 1)
+ padding: theme.spacing(0, 1),
},
toolbar: {
[theme.breakpoints.down('md')]: {
- ...theme.mixins.toolbar
- }
- }
+ ...theme.mixins.toolbar,
+ },
+ },
}));
const routes = [
@@ -57,24 +57,24 @@ const routes = [
{
name: t('reportEvents'),
href: '/reports/event',
- icon: <NotificationsActiveIcon />
+ icon: <NotificationsActiveIcon />,
},
{
name: t('reportTrips'),
href: '/reports/trip',
- icon: <PlayCircleFilledIcon />
+ icon: <PlayCircleFilledIcon />,
},
{
name: t('reportStops'),
href: '/reports/stop',
- icon: <PauseCircleFilledIcon />
+ icon: <PauseCircleFilledIcon />,
},
{
name: t('reportSummary'),
href: '/reports/summary',
- icon: <FormatListBulletedIcon />
+ icon: <FormatListBulletedIcon />,
},
- { name: t('reportChart'), href: '/reports/chart', icon: <TrendingUpIcon /> }
+ { name: t('reportChart'), href: '/reports/chart', icon: <TrendingUpIcon /> },
];
const ReportLayout = ({ children, filter }) => {
@@ -85,7 +85,7 @@ const ReportLayout = ({ children, filter }) => {
const [reportTitle, setReportTitle] = useState();
useEffect(() => {
- routes.forEach(route => {
+ routes.forEach((route) => {
switch (location.pathname) {
case `${route.href}`:
setReportTitle(route.name);
diff --git a/modern/src/reports/RouteReportPage.js b/modern/src/reports/RouteReportPage.js
index c09d4f5..fffcdcb 100644
--- a/modern/src/reports/RouteReportPage.js
+++ b/modern/src/reports/RouteReportPage.js
@@ -1,17 +1,20 @@
import React, { useState } from 'react';
import { Paper } from '@material-ui/core';
import { DataGrid } from '@material-ui/data-grid';
-import { useTheme } from "@material-ui/core/styles";
-import { formatDistance, formatSpeed, formatBoolean, formatDate, formatCoordinate } from '../common/formatter';
+import { useTheme } from '@material-ui/core/styles';
+import {
+ formatDistance, formatSpeed, formatBoolean, formatDate, formatCoordinate,
+} from '../common/formatter';
import ReportFilter from './ReportFilter';
import ReportLayout from './ReportLayout';
import { useAttributePreference, usePreference } from '../common/preferences';
import t from '../common/localization';
const Filter = ({ setItems }) => {
-
const handleSubmit = async (deviceId, from, to, mail, headers) => {
- const query = new URLSearchParams({ deviceId, from, to, mail });
+ const query = new URLSearchParams({
+ deviceId, from, to, mail,
+ });
const response = await fetch(`/api/reports/route?${query.toString()}`, { headers });
if (response.ok) {
const contentType = response.headers.get('content-type');
@@ -23,7 +26,7 @@ const Filter = ({ setItems }) => {
}
}
}
- }
+ };
return <ReportFilter handleSubmit={handleSubmit} />;
};
@@ -78,7 +81,7 @@ const RouteReportPage = () => {
width: theme.dimensions.columnWidthNumber,
valueGetter: ({ row }) => row.attributes.totalDistance,
valueFormatter: ({ value }) => formatDistance(value, distanceUnit),
- }]
+ }];
const [items, setItems] = useState([]);
@@ -86,10 +89,11 @@ const RouteReportPage = () => {
<ReportLayout filter={<Filter setItems={setItems} />}>
<Paper>
<DataGrid
- rows={items}
- columns={columns}
- hideFooter
- autoHeight />
+ rows={items}
+ columns={columns}
+ hideFooter
+ autoHeight
+ />
</Paper>
</ReportLayout>
);
diff --git a/modern/src/reports/StopReportPage.js b/modern/src/reports/StopReportPage.js
index 57f5956..d2e7e7e 100644
--- a/modern/src/reports/StopReportPage.js
+++ b/modern/src/reports/StopReportPage.js
@@ -1,16 +1,19 @@
import React, { useState } from 'react';
import { DataGrid } from '@material-ui/data-grid';
-import { useTheme } from "@material-ui/core/styles";
-import { formatDistance, formatHours, formatDate, formatVolume } from '../common/formatter';
+import { useTheme } from '@material-ui/core/styles';
+import {
+ formatDistance, formatHours, formatDate, formatVolume,
+} from '../common/formatter';
import ReportFilter from './ReportFilter';
import ReportLayout from './ReportLayout';
import { useAttributePreference } from '../common/preferences';
import t from '../common/localization';
const Filter = ({ setItems }) => {
-
const handleSubmit = async (deviceId, from, to, mail, headers) => {
- const query = new URLSearchParams({ deviceId, from, to, mail });
+ const query = new URLSearchParams({
+ deviceId, from, to, mail,
+ });
const response = await fetch(`/api/reports/stops?${query.toString()}`, { headers });
if (response.ok) {
const contentType = response.headers.get('content-type');
@@ -22,13 +25,12 @@ const Filter = ({ setItems }) => {
}
}
}
- }
+ };
return <ReportFilter handleSubmit={handleSubmit} />;
};
const StopReportPage = () => {
-
const theme = useTheme();
const distanceUnit = useAttributePreference('distanceUnit');
@@ -41,7 +43,7 @@ const StopReportPage = () => {
field: 'startTime',
type: 'dateTime',
width: theme.dimensions.columnWidthDate,
- valueFormatter: ({ value }) => formatDate(value),
+ valueFormatter: ({ value }) => formatDate(value),
}, {
headerName: t('positionOdometer'),
field: 'startOdometer',
@@ -53,7 +55,7 @@ const StopReportPage = () => {
field: 'address',
type: 'string',
hide: true,
- width: theme.dimensions.columnWidthString,
+ width: theme.dimensions.columnWidthString,
}, {
headerName: t('reportEndTime'),
field: 'endTime',
@@ -78,17 +80,18 @@ const StopReportPage = () => {
type: 'number',
width: theme.dimensions.columnWidthNumber,
hide: true,
- valueFormatter: ({ value }) => formatVolume(value, volumeUnit),
- }]
-
+ valueFormatter: ({ value }) => formatVolume(value, volumeUnit),
+ }];
+
return (
<ReportLayout filter={<Filter setItems={setItems} />}>
<DataGrid
- rows={items}
- columns={columns}
- hideFooter
+ rows={items}
+ columns={columns}
+ hideFooter
autoHeight
- getRowId={() => Math.random()} />
+ getRowId={() => Math.random()}
+ />
</ReportLayout>
);
};
diff --git a/modern/src/reports/SummaryReportPage.js b/modern/src/reports/SummaryReportPage.js
index 53e697d..4523e65 100644
--- a/modern/src/reports/SummaryReportPage.js
+++ b/modern/src/reports/SummaryReportPage.js
@@ -1,19 +1,22 @@
import React, { useState } from 'react';
import { DataGrid } from '@material-ui/data-grid';
import { Grid, FormControlLabel, Checkbox } from '@material-ui/core';
-import { useTheme } from "@material-ui/core/styles";
-import { formatDistance, formatHours, formatDate, formatSpeed, formatVolume } from '../common/formatter';
+import { useTheme } from '@material-ui/core/styles';
+import {
+ formatDistance, formatHours, formatDate, formatSpeed, formatVolume,
+} from '../common/formatter';
import ReportFilter from './ReportFilter';
import ReportLayout from './ReportLayout';
import { useAttributePreference } from '../common/preferences';
import t from '../common/localization';
const Filter = ({ setItems }) => {
-
const [daily, setDaily] = useState(false);
const handleSubmit = async (deviceId, from, to, mail, headers) => {
- const query = new URLSearchParams({ deviceId, from, to, daily, mail });
+ const query = new URLSearchParams({
+ deviceId, from, to, daily, mail,
+ });
const response = await fetch(`/api/reports/summary?${query.toString()}`, { headers });
if (response.ok) {
const contentType = response.headers.get('content-type');
@@ -25,21 +28,21 @@ const Filter = ({ setItems }) => {
}
}
}
- }
+ };
return (
<ReportFilter handleSubmit={handleSubmit}>
<Grid item xs={12} sm={6}>
<FormControlLabel
- control={<Checkbox checked={daily} onChange={e => setDaily(e.target.checked)} />}
- label={t('reportDaily')} />
+ control={<Checkbox checked={daily} onChange={(e) => setDaily(e.target.checked)} />}
+ label={t('reportDaily')}
+ />
</Grid>
</ReportFilter>
);
-}
+};
const SummaryReportPage = () => {
-
const theme = useTheme();
const distanceUnit = useAttributePreference('distanceUnit');
@@ -96,19 +99,20 @@ const SummaryReportPage = () => {
type: 'number',
width: theme.dimensions.columnWidthNumber,
hide: true,
- valueFormatter: ({ value }) => formatVolume(value, volumeUnit),
- }]
-
+ valueFormatter: ({ value }) => formatVolume(value, volumeUnit),
+ }];
+
return (
<ReportLayout filter={<Filter setItems={setItems} />}>
<DataGrid
- rows={items}
- columns={columns}
- hideFooter
+ rows={items}
+ columns={columns}
+ hideFooter
autoHeight
- getRowId={() => Math.random()} />
+ getRowId={() => Math.random()}
+ />
</ReportLayout>
);
-}
+};
export default SummaryReportPage;
diff --git a/modern/src/reports/TripReportPage.js b/modern/src/reports/TripReportPage.js
index e8c9129..f611dde 100644
--- a/modern/src/reports/TripReportPage.js
+++ b/modern/src/reports/TripReportPage.js
@@ -1,16 +1,19 @@
import React, { useState } from 'react';
import { DataGrid } from '@material-ui/data-grid';
-import { useTheme } from "@material-ui/core/styles";
-import { formatDistance, formatSpeed, formatHours, formatDate, formatVolume } from '../common/formatter';
+import { useTheme } from '@material-ui/core/styles';
+import {
+ formatDistance, formatSpeed, formatHours, formatDate, formatVolume,
+} from '../common/formatter';
import ReportFilter from './ReportFilter';
import ReportLayout from './ReportLayout';
import { useAttributePreference } from '../common/preferences';
import t from '../common/localization';
const Filter = ({ setItems }) => {
-
const handleSubmit = async (deviceId, from, to, mail, headers) => {
- const query = new URLSearchParams({ deviceId, from, to, mail });
+ const query = new URLSearchParams({
+ deviceId, from, to, mail,
+ });
const response = await fetch(`/api/reports/trips?${query.toString()}`, { headers });
if (response.ok) {
const contentType = response.headers.get('content-type');
@@ -22,15 +25,14 @@ const Filter = ({ setItems }) => {
}
}
}
- }
+ };
return <ReportFilter handleSubmit={handleSubmit} />;
-}
+};
const TripReportPage = () => {
-
const theme = useTheme();
-
+
const distanceUnit = useAttributePreference('distanceUnit');
const speedUnit = useAttributePreference('speedUnit');
const volumeUnit = useAttributePreference('volumeUnit');
@@ -109,19 +111,20 @@ const TripReportPage = () => {
field: 'driverName',
type: 'string',
width: theme.dimensions.columnWidthString,
- hide: true
- }]
+ hide: true,
+ }];
return (
<ReportLayout filter={<Filter setItems={setItems} />}>
<DataGrid
- rows={items}
- columns={columns}
- hideFooter
+ rows={items}
+ columns={columns}
+ hideFooter
autoHeight
- getRowId={() => Math.random()} />
+ getRowId={() => Math.random()}
+ />
</ReportLayout>
);
-}
+};
export default TripReportPage;
diff --git a/modern/src/settings/ComputedAttributePage.js b/modern/src/settings/ComputedAttributePage.js
index 73759fa..fea613a 100644
--- a/modern/src/settings/ComputedAttributePage.js
+++ b/modern/src/settings/ComputedAttributePage.js
@@ -1,19 +1,19 @@
import React, { useState } from 'react';
-import { Accordion, AccordionSummary, AccordionDetails, makeStyles, Typography, FormControl, InputLabel, MenuItem, Select, TextField } from "@material-ui/core";
+import {
+ Accordion, AccordionSummary, AccordionDetails, makeStyles, Typography, FormControl, InputLabel, MenuItem, Select, TextField,
+} from '@material-ui/core';
+import ExpandMoreIcon from '@material-ui/icons/ExpandMore';
import t from '../common/localization';
import EditItemView from '../EditItemView';
-import ExpandMoreIcon from '@material-ui/icons/ExpandMore';
import positionAttributes from '../attributes/positionAttributes';
-
const useStyles = makeStyles(() => ({
details: {
flexDirection: 'column',
},
}));
-const ComputedAttributePage =() => {
-
+const ComputedAttributePage = () => {
const classes = useStyles();
const [item, setItem] = useState();
const [key, setKey] = useState();
@@ -24,20 +24,21 @@ const ComputedAttributePage =() => {
type: value.type,
}));
- const handleChange = event => {
+ const handleChange = (event) => {
const newValue = event.target.value;
setKey(newValue);
const positionAttribute = positionAttributes[newValue];
- if(positionAttribute && positionAttribute.type) {
- setItem({...item, attribute: newValue, type: positionAttribute.type});
+ if (positionAttribute && positionAttribute.type) {
+ setItem({ ...item, attribute: newValue, type: positionAttribute.type });
} else {
- setItem({...item, attribute: newValue});
+ setItem({ ...item, attribute: newValue });
}
- }
+ };
return (
<EditItemView endpoint="/attributes/computed" item={item} setItem={setItem}>
- {item &&
+ {item
+ && (
<Accordion defaultExpanded>
<AccordionSummary expandIcon={<ExpandMoreIcon />}>
<Typography variant="subtitle1">
@@ -48,46 +49,51 @@ const ComputedAttributePage =() => {
<TextField
margin="normal"
value={item.description || ''}
- onChange={event => setItem({...item, description: event.target.value})}
+ onChange={(event) => setItem({ ...item, description: event.target.value })}
label={t('sharedDescription')}
- variant="filled" />
+ variant="filled"
+ />
<FormControl variant="filled" margin="normal" fullWidth>
<InputLabel>{t('sharedAttribute')}</InputLabel>
- <Select
- value={item.attribute || ''}
- onChange={handleChange}>
+ <Select
+ value={item.attribute || ''}
+ onChange={handleChange}
+ >
{options.map((option) => (
<MenuItem key={option.key} value={option.key}>{option.name}</MenuItem>
))}
</Select>
- </FormControl>
+ </FormControl>
<TextField
margin="normal"
value={item.expression || ''}
- onChange={event => setItem({...item, expression: event.target.value})}
+ onChange={(event) => setItem({ ...item, expression: event.target.value })}
label={t('sharedExpression')}
multiline
rows={4}
- variant="filled" />
+ variant="filled"
+ />
<FormControl
variant="filled"
margin="normal"
fullWidth
- disabled={key in positionAttributes}>
+ disabled={key in positionAttributes}
+ >
<InputLabel>{t('sharedType')}</InputLabel>
<Select
value={item.type || ''}
- onChange={event => setItem({...item, type: event.target.value})}>
- <MenuItem value={'string'}>{t('sharedTypeString')}</MenuItem>
- <MenuItem value={'number'}>{t('sharedTypeNumber')}</MenuItem>
- <MenuItem value={'boolean'}>{t('sharedTypeBoolean')}</MenuItem>
+ onChange={(event) => setItem({ ...item, type: event.target.value })}
+ >
+ <MenuItem value="string">{t('sharedTypeString')}</MenuItem>
+ <MenuItem value="number">{t('sharedTypeNumber')}</MenuItem>
+ <MenuItem value="boolean">{t('sharedTypeBoolean')}</MenuItem>
</Select>
</FormControl>
</AccordionDetails>
</Accordion>
- }
+ )}
</EditItemView>
- )
-}
+ );
+};
export default ComputedAttributePage;
diff --git a/modern/src/settings/ComputedAttributesPage.js b/modern/src/settings/ComputedAttributesPage.js
index d747598..fcf49d3 100644
--- a/modern/src/settings/ComputedAttributesPage.js
+++ b/modern/src/settings/ComputedAttributesPage.js
@@ -1,5 +1,7 @@
import React, { useState } from 'react';
-import { TableContainer, Table, TableRow, TableCell, TableHead, TableBody, makeStyles, IconButton } from '@material-ui/core';
+import {
+ TableContainer, Table, TableRow, TableCell, TableHead, TableBody, makeStyles, IconButton,
+} from '@material-ui/core';
import MoreVertIcon from '@material-ui/icons/MoreVert';
import { useSelector } from 'react-redux';
import t from '../common/localization';
@@ -7,11 +9,11 @@ import { useEffectAsync } from '../reactHelper';
import EditCollectionView from '../EditCollectionView';
import OptionsLayout from './OptionsLayout';
-const useStyles = makeStyles(theme => ({
+const useStyles = makeStyles((theme) => ({
columnAction: {
width: theme.spacing(1),
- padding: theme.spacing(0, 1)
- }
+ padding: theme.spacing(0, 1),
+ },
}));
const ComputedAttributeView = ({ updateTimestamp, onMenuClick }) => {
@@ -19,7 +21,7 @@ const ComputedAttributeView = ({ updateTimestamp, onMenuClick }) => {
const [items, setItems] = useState([]);
const adminEnabled = useSelector(
- state => state.session.user && state.session.user.administrator
+ (state) => state.session.user && state.session.user.administrator,
);
useEffectAsync(async () => {
@@ -31,50 +33,48 @@ const ComputedAttributeView = ({ updateTimestamp, onMenuClick }) => {
return (
<TableContainer>
- <Table>
- <TableHead>
- <TableRow>
- {adminEnabled && <TableCell className={classes.columnAction} />}
- <TableCell>{t('sharedDescription')}</TableCell>
- <TableCell>{t('sharedAttribute')}</TableCell>
- <TableCell>{t('sharedExpression')}</TableCell>
- <TableCell>{t('sharedType')}</TableCell>
- </TableRow>
- </TableHead>
- <TableBody>
- {items.map(item => (
- <TableRow key={item.id}>
+ <Table>
+ <TableHead>
+ <TableRow>
+ {adminEnabled && <TableCell className={classes.columnAction} />}
+ <TableCell>{t('sharedDescription')}</TableCell>
+ <TableCell>{t('sharedAttribute')}</TableCell>
+ <TableCell>{t('sharedExpression')}</TableCell>
+ <TableCell>{t('sharedType')}</TableCell>
+ </TableRow>
+ </TableHead>
+ <TableBody>
+ {items.map((item) => (
+ <TableRow key={item.id}>
{adminEnabled && (
<TableCell className={classes.columnAction} padding="none">
- <IconButton
- onClick={event => onMenuClick(event.currentTarget, item.id)}
- >
+ <IconButton
+ onClick={(event) => onMenuClick(event.currentTarget, item.id)}
+ >
<MoreVertIcon />
</IconButton>
</TableCell>
)}
- <TableCell>{item.description}</TableCell>
- <TableCell>{item.attribute}</TableCell>
- <TableCell>{item.expression}</TableCell>
- <TableCell>{item.type}</TableCell>
- </TableRow>
- ))}
- </TableBody>
- </Table>
+ <TableCell>{item.description}</TableCell>
+ <TableCell>{item.attribute}</TableCell>
+ <TableCell>{item.expression}</TableCell>
+ <TableCell>{item.type}</TableCell>
+ </TableRow>
+ ))}
+ </TableBody>
+ </Table>
</TableContainer>
);
};
-const ComputedAttributesPage = () => {
- return (
- <OptionsLayout>
- <EditCollectionView
- content={ComputedAttributeView}
- editPath="/settings/attribute"
- endpoint="attributes/computed"
- />
- </OptionsLayout>
- );
-};
+const ComputedAttributesPage = () => (
+ <OptionsLayout>
+ <EditCollectionView
+ content={ComputedAttributeView}
+ editPath="/settings/attribute"
+ endpoint="attributes/computed"
+ />
+ </OptionsLayout>
+);
export default ComputedAttributesPage;
diff --git a/modern/src/settings/DriverPage.js b/modern/src/settings/DriverPage.js
index 86feab8..01400c5 100644
--- a/modern/src/settings/DriverPage.js
+++ b/modern/src/settings/DriverPage.js
@@ -1,9 +1,11 @@
import React, { useState } from 'react';
import TextField from '@material-ui/core/TextField';
+import {
+ Accordion, AccordionSummary, AccordionDetails, makeStyles, Typography,
+} from '@material-ui/core';
+import ExpandMoreIcon from '@material-ui/icons/ExpandMore';
import t from '../common/localization';
import EditItemView from '../EditItemView';
-import { Accordion, AccordionSummary, AccordionDetails, makeStyles, Typography } from '@material-ui/core';
-import ExpandMoreIcon from '@material-ui/icons/ExpandMore';
import EditAttributesView from '../attributes/EditAttributesView';
const useStyles = makeStyles(() => ({
@@ -19,7 +21,8 @@ const DriverPage = () => {
return (
<EditItemView endpoint="drivers" item={item} setItem={setItem}>
- {item &&
+ {item
+ && (
<>
<Accordion defaultExpanded>
<AccordionSummary expandIcon={<ExpandMoreIcon />}>
@@ -31,15 +34,17 @@ const DriverPage = () => {
<TextField
margin="normal"
value={item.name || ''}
- onChange={event => setItem({...item, name: event.target.value})}
+ onChange={(event) => setItem({ ...item, name: event.target.value })}
label={t('sharedName')}
- variant="filled" />
+ variant="filled"
+ />
<TextField
margin="normal"
value={item.uniqueId || ''}
- onChange={event => setItem({...item, uniqueId: event.target.value})}
+ onChange={(event) => setItem({ ...item, uniqueId: event.target.value })}
label={t('deviceIdentifier')}
- variant="filled" />
+ variant="filled"
+ />
</AccordionDetails>
</Accordion>
<Accordion>
@@ -51,15 +56,15 @@ const DriverPage = () => {
<AccordionDetails className={classes.details}>
<EditAttributesView
attributes={item.attributes}
- setAttributes={attributes => setItem({...item, attributes})}
+ setAttributes={(attributes) => setItem({ ...item, attributes })}
definitions={{}}
- />
+ />
</AccordionDetails>
</Accordion>
</>
- }
+ )}
</EditItemView>
);
-}
+};
export default DriverPage;
diff --git a/modern/src/settings/DriversPage.js b/modern/src/settings/DriversPage.js
index d5427b2..57f69b6 100644
--- a/modern/src/settings/DriversPage.js
+++ b/modern/src/settings/DriversPage.js
@@ -1,16 +1,18 @@
import React, { useState } from 'react';
-import { TableContainer, Table, TableRow, TableCell, TableHead, TableBody, makeStyles, IconButton } from '@material-ui/core';
+import {
+ TableContainer, Table, TableRow, TableCell, TableHead, TableBody, makeStyles, IconButton,
+} from '@material-ui/core';
import MoreVertIcon from '@material-ui/icons/MoreVert';
import t from '../common/localization';
import { useEffectAsync } from '../reactHelper';
import EditCollectionView from '../EditCollectionView';
import OptionsLayout from './OptionsLayout';
-const useStyles = makeStyles(theme => ({
+const useStyles = makeStyles((theme) => ({
columnAction: {
width: theme.spacing(1),
- padding: theme.spacing(0, 1)
- }
+ padding: theme.spacing(0, 1),
+ },
}));
const DriversView = ({ updateTimestamp, onMenuClick }) => {
@@ -27,44 +29,42 @@ const DriversView = ({ updateTimestamp, onMenuClick }) => {
return (
<TableContainer>
- <Table>
- <TableHead>
- <TableRow>
- <TableCell className={classes.columnAction} />
- <TableCell>{t('sharedName')}</TableCell>
- <TableCell>{t('deviceIdentifier')}</TableCell>
- </TableRow>
- </TableHead>
- <TableBody>
- {items.map(item => (
- <TableRow key={item.id}>
- <TableCell className={classes.columnAction} padding="none">
+ <Table>
+ <TableHead>
+ <TableRow>
+ <TableCell className={classes.columnAction} />
+ <TableCell>{t('sharedName')}</TableCell>
+ <TableCell>{t('deviceIdentifier')}</TableCell>
+ </TableRow>
+ </TableHead>
+ <TableBody>
+ {items.map((item) => (
+ <TableRow key={item.id}>
+ <TableCell className={classes.columnAction} padding="none">
<IconButton
- onClick={event => onMenuClick(event.currentTarget, item.id)}
+ onClick={(event) => onMenuClick(event.currentTarget, item.id)}
>
- <MoreVertIcon />
- </IconButton>
- </TableCell>
- <TableCell>{item.name}</TableCell>
- <TableCell>{item.uniqueId}</TableCell>
- </TableRow>
- ))}
- </TableBody>
- </Table>
+ <MoreVertIcon />
+ </IconButton>
+ </TableCell>
+ <TableCell>{item.name}</TableCell>
+ <TableCell>{item.uniqueId}</TableCell>
+ </TableRow>
+ ))}
+ </TableBody>
+ </Table>
</TableContainer>
);
};
-const DriversPage = () => {
- return (
- <OptionsLayout>
- <EditCollectionView
- content={DriversView}
- editPath="/settings/driver"
- endpoint="drivers"
- />
- </OptionsLayout>
- );
-};
+const DriversPage = () => (
+ <OptionsLayout>
+ <EditCollectionView
+ content={DriversView}
+ editPath="/settings/driver"
+ endpoint="drivers"
+ />
+ </OptionsLayout>
+);
export default DriversPage;
diff --git a/modern/src/settings/GroupPage.js b/modern/src/settings/GroupPage.js
index b9fa871..f9af0f8 100644
--- a/modern/src/settings/GroupPage.js
+++ b/modern/src/settings/GroupPage.js
@@ -1,10 +1,12 @@
import React, { useState } from 'react';
import TextField from '@material-ui/core/TextField';
+import {
+ Accordion, AccordionSummary, AccordionDetails, makeStyles, Typography,
+} from '@material-ui/core';
+import ExpandMoreIcon from '@material-ui/icons/ExpandMore';
import t from '../common/localization';
import EditItemView from '../EditItemView';
-import { Accordion, AccordionSummary, AccordionDetails, makeStyles, Typography } from '@material-ui/core';
-import ExpandMoreIcon from '@material-ui/icons/ExpandMore';
import EditAttributesView from '../attributes/EditAttributesView';
import deviceAttributes from '../attributes/deviceAttributes';
import SelectField from '../form/SelectField';
@@ -22,7 +24,8 @@ const GroupPage = () => {
return (
<EditItemView endpoint="groups" item={item} setItem={setItem}>
- {item &&
+ {item
+ && (
<>
<Accordion defaultExpanded>
<AccordionSummary expandIcon={<ExpandMoreIcon />}>
@@ -34,9 +37,10 @@ const GroupPage = () => {
<TextField
margin="normal"
value={item.name || ''}
- onChange={event => setItem({...item, name: event.target.value})}
+ onChange={(event) => setItem({ ...item, name: event.target.value })}
label={t('sharedName')}
- variant="filled" />
+ variant="filled"
+ />
</AccordionDetails>
</Accordion>
<Accordion>
@@ -49,10 +53,11 @@ const GroupPage = () => {
<SelectField
margin="normal"
value={item.groupId || 0}
- onChange={event => setItem({...item, groupId: Number(event.target.value)})}
+ onChange={(event) => setItem({ ...item, groupId: Number(event.target.value) })}
endpoint="/api/groups"
label={t('groupParent')}
- variant="filled" />
+ variant="filled"
+ />
</AccordionDetails>
</Accordion>
<Accordion>
@@ -64,15 +69,15 @@ const GroupPage = () => {
<AccordionDetails className={classes.details}>
<EditAttributesView
attributes={item.attributes}
- setAttributes={attributes => setItem({...item, attributes})}
+ setAttributes={(attributes) => setItem({ ...item, attributes })}
definitions={deviceAttributes}
- />
+ />
</AccordionDetails>
</Accordion>
</>
- }
+ )}
</EditItemView>
);
-}
+};
export default GroupPage;
diff --git a/modern/src/settings/GroupsPage.js b/modern/src/settings/GroupsPage.js
index 2fc65c1..3b1058e 100644
--- a/modern/src/settings/GroupsPage.js
+++ b/modern/src/settings/GroupsPage.js
@@ -1,16 +1,18 @@
import React, { useState } from 'react';
-import { TableContainer, Table, TableRow, TableCell, TableHead, TableBody, makeStyles, IconButton } from '@material-ui/core';
+import {
+ TableContainer, Table, TableRow, TableCell, TableHead, TableBody, makeStyles, IconButton,
+} from '@material-ui/core';
import MoreVertIcon from '@material-ui/icons/MoreVert';
import t from '../common/localization';
import { useEffectAsync } from '../reactHelper';
import EditCollectionView from '../EditCollectionView';
import OptionsLayout from './OptionsLayout';
-const useStyles = makeStyles(theme => ({
+const useStyles = makeStyles((theme) => ({
columnAction: {
width: theme.spacing(1),
- padding: theme.spacing(0, 1)
- }
+ padding: theme.spacing(0, 1),
+ },
}));
const GroupsView = ({ updateTimestamp, onMenuClick }) => {
@@ -27,42 +29,40 @@ const GroupsView = ({ updateTimestamp, onMenuClick }) => {
return (
<TableContainer>
- <Table>
- <TableHead>
- <TableRow>
- <TableCell className={classes.columnAction} />
- <TableCell>{t('sharedName')}</TableCell>
- </TableRow>
- </TableHead>
- <TableBody>
- {items.map(item => (
- <TableRow key={item.id}>
- <TableCell className={classes.columnAction} padding="none">
+ <Table>
+ <TableHead>
+ <TableRow>
+ <TableCell className={classes.columnAction} />
+ <TableCell>{t('sharedName')}</TableCell>
+ </TableRow>
+ </TableHead>
+ <TableBody>
+ {items.map((item) => (
+ <TableRow key={item.id}>
+ <TableCell className={classes.columnAction} padding="none">
<IconButton
- onClick={event => onMenuClick(event.currentTarget, item.id)}
+ onClick={(event) => onMenuClick(event.currentTarget, item.id)}
>
- <MoreVertIcon />
- </IconButton>
- </TableCell>
- <TableCell>{item.name}</TableCell>
- </TableRow>
- ))}
- </TableBody>
- </Table>
+ <MoreVertIcon />
+ </IconButton>
+ </TableCell>
+ <TableCell>{item.name}</TableCell>
+ </TableRow>
+ ))}
+ </TableBody>
+ </Table>
</TableContainer>
);
};
-const GroupsPage = () => {
- return (
- <OptionsLayout>
- <EditCollectionView
- content={GroupsView}
- editPath="/settings/group"
- endpoint="groups"
- />
- </OptionsLayout>
- );
-};
+const GroupsPage = () => (
+ <OptionsLayout>
+ <EditCollectionView
+ content={GroupsView}
+ editPath="/settings/group"
+ endpoint="groups"
+ />
+ </OptionsLayout>
+);
export default GroupsPage;
diff --git a/modern/src/settings/MaintenancePage.js b/modern/src/settings/MaintenancePage.js
index 3b4fde5..9d60937 100644
--- a/modern/src/settings/MaintenancePage.js
+++ b/modern/src/settings/MaintenancePage.js
@@ -1,14 +1,18 @@
import React, { useState } from 'react';
+import {
+ Accordion, AccordionSummary, AccordionDetails, makeStyles, Typography, TextField, FormControl, InputLabel, MenuItem, Select,
+} from '@material-ui/core';
+import InputAdornment from '@material-ui/core/InputAdornment';
+import ExpandMoreIcon from '@material-ui/icons/ExpandMore';
import t from '../common/localization';
import { prefixString } from '../common/stringUtils';
import EditItemView from '../EditItemView';
-import { Accordion, AccordionSummary, AccordionDetails, makeStyles, Typography, TextField, FormControl, InputLabel, MenuItem, Select, } from '@material-ui/core';
-import InputAdornment from '@material-ui/core/InputAdornment';
-import ExpandMoreIcon from '@material-ui/icons/ExpandMore';
import EditAttributesView from '../attributes/EditAttributesView';
import positionAttributes from '../attributes/positionAttributes';
import { useAttributePreference } from '../common/preferences';
-import { speedFromKnots, speedToKnots, distanceFromMeters, distanceToMeters } from '../common/converter';
+import {
+ speedFromKnots, speedToKnots, distanceFromMeters, distanceToMeters,
+} from '../common/converter';
const useStyles = makeStyles(() => ({
details: {
@@ -17,46 +21,46 @@ const useStyles = makeStyles(() => ({
}));
const MaintenancePage = () => {
-
const classes = useStyles();
const [item, setItem] = useState();
- const [labels, setLabels] = useState({start: '', period: ''});
+ const [labels, setLabels] = useState({ start: '', period: '' });
const speedUnit = useAttributePreference('speedUnit');
const distanceUnit = useAttributePreference('distanceUnit');
const convertToList = (attributes) => {
- let otherList = [];
+ const otherList = [];
for (const key in attributes) {
const value = attributes[key];
if (value.type === 'number') {
- otherList.push({key, name: value.name, type: value.type});
+ otherList.push({ key, name: value.name, type: value.type });
}
}
return otherList;
- }
+ };
- const onMaintenanceTypeChange = event => {
+ const onMaintenanceTypeChange = (event) => {
const newValue = event.target.value;
- setItem({ ...item, type: newValue, start: 0, period: 0 });
+ setItem({
+ ...item, type: newValue, start: 0, period: 0,
+ });
const attribute = positionAttributes[newValue];
if (attribute && attribute.dataType) {
switch (attribute.dataType) {
case 'distance':
- setLabels({ ...labels, start: t(prefixString('shared', distanceUnit)), period: t(prefixString('shared', distanceUnit))});
+ setLabels({ ...labels, start: t(prefixString('shared', distanceUnit)), period: t(prefixString('shared', distanceUnit)) });
break;
case 'speed':
- setLabels({ ...labels, start: t(prefixString('shared', speedUnit)), period: t(prefixString('shared', speedUnit))});
+ setLabels({ ...labels, start: t(prefixString('shared', speedUnit)), period: t(prefixString('shared', speedUnit)) });
break;
default:
break;
}
}
- }
-
- const rawToValue = value => {
+ };
+ const rawToValue = (value) => {
const attribute = positionAttributes[item.type];
if (attribute && attribute.dataType) {
switch (attribute.dataType) {
@@ -69,10 +73,9 @@ const MaintenancePage = () => {
}
}
return value;
- }
-
- const valueToRaw = value => {
+ };
+ const valueToRaw = (value) => {
const attribute = positionAttributes[item.type];
if (attribute && attribute.dataType) {
switch (attribute.dataType) {
@@ -85,11 +88,12 @@ const MaintenancePage = () => {
}
}
return value;
- }
+ };
return (
<EditItemView endpoint="maintenance" item={item} setItem={setItem}>
- {item &&
+ {item
+ && (
<>
<Accordion defaultExpanded>
<AccordionSummary expandIcon={<ExpandMoreIcon />}>
@@ -101,39 +105,43 @@ const MaintenancePage = () => {
<TextField
margin="normal"
value={item.name || ''}
- onChange={event => setItem({...item, name: event.target.value})}
+ onChange={(event) => setItem({ ...item, name: event.target.value })}
label={t('sharedName')}
- variant="filled" />
+ variant="filled"
+ />
<FormControl variant="filled" margin="normal" fullWidth>
<InputLabel>{t('sharedType')}</InputLabel>
- <Select
- value={item.type || ''}
- onChange={onMaintenanceTypeChange}>
- {convertToList(positionAttributes).map(({ key, name })=>(
- <MenuItem key={key} value={key}>{name}</MenuItem>
- ))}
+ <Select
+ value={item.type || ''}
+ onChange={onMaintenanceTypeChange}
+ >
+ {convertToList(positionAttributes).map(({ key, name }) => (
+ <MenuItem key={key} value={key}>{name}</MenuItem>
+ ))}
</Select>
- </FormControl>
+ </FormControl>
<TextField
margin="normal"
type="number"
value={rawToValue(item.start) || ''}
- onChange={event => setItem({...item, start: valueToRaw(event.target.value)})}
+ onChange={(event) => setItem({ ...item, start: valueToRaw(event.target.value) })}
label={t('maintenanceStart')}
variant="filled"
InputProps={{
- endAdornment: <InputAdornment position="start">{labels.start}</InputAdornment>,
- }} />
+ endAdornment: <InputAdornment position="start">{labels.start}</InputAdornment>,
+ }}
+ />
<TextField
margin="normal"
type="number"
value={rawToValue(item.period) || ''}
- onChange={event => setItem({...item, period: valueToRaw(event.target.value)})}
+ onChange={(event) => setItem({ ...item, period: valueToRaw(event.target.value) })}
label={t('maintenancePeriod')}
variant="filled"
InputProps={{
- endAdornment: <InputAdornment position="start">{labels.period}</InputAdornment>,
- }} />
+ endAdornment: <InputAdornment position="start">{labels.period}</InputAdornment>,
+ }}
+ />
</AccordionDetails>
</Accordion>
<Accordion>
@@ -145,15 +153,15 @@ const MaintenancePage = () => {
<AccordionDetails className={classes.details}>
<EditAttributesView
attributes={item.attributes}
- setAttributes={attributes => setItem({...item, attributes})}
+ setAttributes={(attributes) => setItem({ ...item, attributes })}
definitions={{}}
- />
+ />
</AccordionDetails>
- </Accordion>
+ </Accordion>
</>
- }
+ )}
</EditItemView>
);
-}
+};
export default MaintenancePage;
diff --git a/modern/src/settings/MaintenancesPage.js b/modern/src/settings/MaintenancesPage.js
index d713eaa..b8e74d2 100644
--- a/modern/src/settings/MaintenancesPage.js
+++ b/modern/src/settings/MaintenancesPage.js
@@ -1,5 +1,7 @@
import React, { useState } from 'react';
-import { TableContainer, Table, TableRow, TableCell, TableHead, TableBody, makeStyles, IconButton } from '@material-ui/core';
+import {
+ TableContainer, Table, TableRow, TableCell, TableHead, TableBody, makeStyles, IconButton,
+} from '@material-ui/core';
import MoreVertIcon from '@material-ui/icons/MoreVert';
import t from '../common/localization';
import { useEffectAsync } from '../reactHelper';
@@ -10,11 +12,11 @@ import { formatDistance, formatSpeed } from '../common/formatter';
import { useAttributePreference } from '../common/preferences';
import OptionsLayout from './OptionsLayout';
-const useStyles = makeStyles(theme => ({
+const useStyles = makeStyles((theme) => ({
columnAction: {
width: theme.spacing(1),
- padding: theme.spacing(0, 1)
- }
+ padding: theme.spacing(0, 1),
+ },
}));
const MaintenancesView = ({ updateTimestamp, onMenuClick }) => {
@@ -37,7 +39,7 @@ const MaintenancesView = ({ updateTimestamp, onMenuClick }) => {
switch (attribute.dataType) {
case 'speed':
return formatSpeed(value, speedUnit);
- case 'distance':
+ case 'distance':
return formatDistance(value, distanceUnit);
default:
return value;
@@ -49,48 +51,46 @@ const MaintenancesView = ({ updateTimestamp, onMenuClick }) => {
return (
<TableContainer>
- <Table>
- <TableHead>
- <TableRow>
- <TableCell className={classes.columnAction} />
- <TableCell>{t('sharedName')}</TableCell>
- <TableCell>{t('sharedType')}</TableCell>
- <TableCell>{t('maintenanceStart')}</TableCell>
- <TableCell>{t('maintenancePeriod')}</TableCell>
- </TableRow>
- </TableHead>
- <TableBody>
- {items.map(item => (
- <TableRow key={item.id}>
- <TableCell className={classes.columnAction} padding="none">
+ <Table>
+ <TableHead>
+ <TableRow>
+ <TableCell className={classes.columnAction} />
+ <TableCell>{t('sharedName')}</TableCell>
+ <TableCell>{t('sharedType')}</TableCell>
+ <TableCell>{t('maintenanceStart')}</TableCell>
+ <TableCell>{t('maintenancePeriod')}</TableCell>
+ </TableRow>
+ </TableHead>
+ <TableBody>
+ {items.map((item) => (
+ <TableRow key={item.id}>
+ <TableCell className={classes.columnAction} padding="none">
<IconButton
- onClick={event => onMenuClick(event.currentTarget, item.id)}
+ onClick={(event) => onMenuClick(event.currentTarget, item.id)}
>
- <MoreVertIcon />
- </IconButton>
- </TableCell>
- <TableCell>{item.name}</TableCell>
- <TableCell>{item.type}</TableCell>
- <TableCell>{convertAttribute(item.type, item.start)}</TableCell>
- <TableCell>{convertAttribute(item.type, item.period)}</TableCell>
- </TableRow>
- ))}
- </TableBody>
- </Table>
+ <MoreVertIcon />
+ </IconButton>
+ </TableCell>
+ <TableCell>{item.name}</TableCell>
+ <TableCell>{item.type}</TableCell>
+ <TableCell>{convertAttribute(item.type, item.start)}</TableCell>
+ <TableCell>{convertAttribute(item.type, item.period)}</TableCell>
+ </TableRow>
+ ))}
+ </TableBody>
+ </Table>
</TableContainer>
);
};
-const MaintenacesPage = () => {
- return (
- <OptionsLayout>
- <EditCollectionView
- content={MaintenancesView}
- editPath="/settings/maintenance"
- endpoint="maintenance"
- />
- </OptionsLayout>
- );
-};
+const MaintenacesPage = () => (
+ <OptionsLayout>
+ <EditCollectionView
+ content={MaintenancesView}
+ editPath="/settings/maintenance"
+ endpoint="maintenance"
+ />
+ </OptionsLayout>
+);
export default MaintenacesPage;
diff --git a/modern/src/settings/NotificationPage.js b/modern/src/settings/NotificationPage.js
index 33904e7..11c427f 100644
--- a/modern/src/settings/NotificationPage.js
+++ b/modern/src/settings/NotificationPage.js
@@ -1,9 +1,11 @@
import React, { useState } from 'react';
+import {
+ Accordion, AccordionSummary, AccordionDetails, makeStyles, Typography, FormControlLabel, Checkbox,
+} from '@material-ui/core';
+import ExpandMoreIcon from '@material-ui/icons/ExpandMore';
import t, { findStringKeys } from '../common/localization';
import EditItemView from '../EditItemView';
-import { Accordion, AccordionSummary, AccordionDetails, makeStyles, Typography, FormControlLabel, Checkbox } from '@material-ui/core';
-import ExpandMoreIcon from '@material-ui/icons/ExpandMore';
import { prefixString, unprefixString } from '../common/stringUtils';
import SelectField from '../form/SelectField';
@@ -18,14 +20,15 @@ const NotificationPage = () => {
const [item, setItem] = useState();
- const alarms = findStringKeys(it => it.startsWith('alarm')).map(it => ({
+ const alarms = findStringKeys((it) => it.startsWith('alarm')).map((it) => ({
key: unprefixString('alarm', it),
name: t(it),
}));
return (
<EditItemView endpoint="notifications" item={item} setItem={setItem}>
- {item &&
+ {item
+ && (
<>
<Accordion defaultExpanded>
<AccordionSummary expandIcon={<ExpandMoreIcon />}>
@@ -38,47 +41,52 @@ const NotificationPage = () => {
margin="normal"
value={item.type || 'alarm'}
emptyValue={null}
- onChange={e => setItem({...item, type: e.target.value})}
+ onChange={(e) => setItem({ ...item, type: e.target.value })}
endpoint="/api/notifications/types"
- keyGetter={it => it.type}
- titleGetter={it => t(prefixString('event', it.type))}
+ keyGetter={(it) => it.type}
+ titleGetter={(it) => t(prefixString('event', it.type))}
label={t('sharedType')}
- variant="filled" />
+ variant="filled"
+ />
<SelectField
multiple
margin="normal"
value={item.notificators ? item.notificators.split(/[, ]+/) : []}
- onChange={e => setItem({...item, notificators: e.target.value.join()})}
+ onChange={(e) => setItem({ ...item, notificators: e.target.value.join() })}
endpoint="/api/notifications/notificators"
- keyGetter={it => it.type}
- titleGetter={it => t(prefixString('notificator', it.type))}
+ keyGetter={(it) => it.type}
+ titleGetter={(it) => t(prefixString('notificator', it.type))}
label={t('notificationNotificators')}
- variant="filled" />
- {(!item.type || item.type === 'alarm') &&
+ variant="filled"
+ />
+ {(!item.type || item.type === 'alarm')
+ && (
<SelectField
multiple
margin="normal"
value={item.attributes && item.attributes.alarms ? item.attributes.alarms.split(/[, ]+/) : []}
- onChange={e => setItem({...item, attributes: {...item.attributes, alarms: e.target.value.join()}})}
+ onChange={(e) => setItem({ ...item, attributes: { ...item.attributes, alarms: e.target.value.join() } })}
data={alarms}
- keyGetter={it => it.key}
+ keyGetter={(it) => it.key}
label={t('sharedAlarms')}
- variant="filled" />
- }
+ variant="filled"
+ />
+ )}
<FormControlLabel
- control={
+ control={(
<Checkbox
checked={item.always}
- onChange={event => setItem({...item, always: event.target.checked})}
- />
- }
- label={t('notificationAlways')} />
+ onChange={(event) => setItem({ ...item, always: event.target.checked })}
+ />
+ )}
+ label={t('notificationAlways')}
+ />
</AccordionDetails>
</Accordion>
</>
- }
+ )}
</EditItemView>
);
-}
+};
export default NotificationPage;
diff --git a/modern/src/settings/NotificationsPage.js b/modern/src/settings/NotificationsPage.js
index 5707f89..079f88d 100644
--- a/modern/src/settings/NotificationsPage.js
+++ b/modern/src/settings/NotificationsPage.js
@@ -1,5 +1,7 @@
import React, { useState } from 'react';
-import { TableContainer, Table, TableRow, TableCell, TableHead, TableBody, makeStyles, IconButton } from '@material-ui/core';
+import {
+ TableContainer, Table, TableRow, TableCell, TableHead, TableBody, makeStyles, IconButton,
+} from '@material-ui/core';
import MoreVertIcon from '@material-ui/icons/MoreVert';
import t from '../common/localization';
import { useEffectAsync } from '../reactHelper';
@@ -8,11 +10,11 @@ import { prefixString } from '../common/stringUtils';
import { formatBoolean } from '../common/formatter';
import OptionsLayout from './OptionsLayout';
-const useStyles = makeStyles(theme => ({
+const useStyles = makeStyles((theme) => ({
columnAction: {
width: theme.spacing(1),
- padding: theme.spacing(0, 1)
- }
+ padding: theme.spacing(0, 1),
+ },
}));
const NotificationsView = ({ updateTimestamp, onMenuClick }) => {
@@ -32,7 +34,7 @@ const NotificationsView = ({ updateTimestamp, onMenuClick }) => {
return value
.split(/[, ]+/)
.filter(Boolean)
- .map(it => t(prefixString(prefix, it)))
+ .map((it) => t(prefixString(prefix, it)))
.join(', ');
}
return '';
@@ -40,52 +42,50 @@ const NotificationsView = ({ updateTimestamp, onMenuClick }) => {
return (
<TableContainer>
- <Table>
- <TableHead>
- <TableRow>
- <TableCell className={classes.columnAction} />
- <TableCell>{t('notificationType')}</TableCell>
- <TableCell>{t('notificationAlways')}</TableCell>
- <TableCell>{t('sharedAlarms')}</TableCell>
- <TableCell>{t('notificationNotificators')}</TableCell>
- </TableRow>
- </TableHead>
- <TableBody>
- {items.map(item => (
- <TableRow key={item.id}>
- <TableCell className={classes.columnAction} padding="none">
+ <Table>
+ <TableHead>
+ <TableRow>
+ <TableCell className={classes.columnAction} />
+ <TableCell>{t('notificationType')}</TableCell>
+ <TableCell>{t('notificationAlways')}</TableCell>
+ <TableCell>{t('sharedAlarms')}</TableCell>
+ <TableCell>{t('notificationNotificators')}</TableCell>
+ </TableRow>
+ </TableHead>
+ <TableBody>
+ {items.map((item) => (
+ <TableRow key={item.id}>
+ <TableCell className={classes.columnAction} padding="none">
<IconButton
- onClick={event => onMenuClick(event.currentTarget, item.id)}
+ onClick={(event) => onMenuClick(event.currentTarget, item.id)}
>
- <MoreVertIcon />
- </IconButton>
- </TableCell>
- <TableCell>{t(prefixString('event', item.type))}</TableCell>
- <TableCell>{formatBoolean(item.always)}</TableCell>
+ <MoreVertIcon />
+ </IconButton>
+ </TableCell>
+ <TableCell>{t(prefixString('event', item.type))}</TableCell>
+ <TableCell>{formatBoolean(item.always)}</TableCell>
<TableCell>
{formatList('alarm', item.attributes.alarms)}
</TableCell>
<TableCell>
{formatList('notificator', item.notificators)}
</TableCell>
- </TableRow>
- ))}
- </TableBody>
- </Table>
+ </TableRow>
+ ))}
+ </TableBody>
+ </Table>
</TableContainer>
);
};
-const NotificationsPage = () => {
- return (
- <OptionsLayout>
- <EditCollectionView
- content={NotificationsView}
- editPath="/settings/notification"
- endpoint="notifications"
- />
- </OptionsLayout>
- );
-};
+const NotificationsPage = () => (
+ <OptionsLayout>
+ <EditCollectionView
+ content={NotificationsView}
+ editPath="/settings/notification"
+ endpoint="notifications"
+ />
+ </OptionsLayout>
+);
export default NotificationsPage;
diff --git a/modern/src/settings/OptionsLayout/useRoutes.js b/modern/src/settings/OptionsLayout/useRoutes.js
index 901719f..f2603dd 100644
--- a/modern/src/settings/OptionsLayout/useRoutes.js
+++ b/modern/src/settings/OptionsLayout/useRoutes.js
@@ -13,7 +13,7 @@ import t from '../../common/localization';
const accountRoute = {
name: t('settingsUser'),
- icon: <PersonIcon />
+ icon: <PersonIcon />,
};
const adminRoutes = [
@@ -21,18 +21,18 @@ const adminRoutes = [
{
name: t('settingsServer'),
href: '/admin/server',
- icon: <StorageIcon />
+ icon: <StorageIcon />,
},
{
name: t('settingsUsers'),
href: '/admin/users',
- icon: <PeopleIcon />
+ icon: <PeopleIcon />,
},
{
name: t('statisticsTitle'),
href: '/admin/statistics',
- icon: <BarChartIcon />
- }
+ icon: <BarChartIcon />,
+ },
];
const mainRoutes = [
@@ -41,38 +41,38 @@ const mainRoutes = [
match: 'geofence',
name: t('sharedGeofences'),
href: '/geofences',
- icon: <CreateIcon />
+ icon: <CreateIcon />,
},
{
match: 'notification',
name: t('sharedNotifications'),
href: '/settings/notifications',
- icon: <NotificationsIcon />
+ icon: <NotificationsIcon />,
},
{
match: 'group',
name: t('settingsGroups'),
href: '/settings/groups',
- icon: <FolderIcon />
+ icon: <FolderIcon />,
},
{
match: 'driver',
name: t('sharedDrivers'),
href: '/settings/drivers',
- icon: <PersonIcon />
+ icon: <PersonIcon />,
},
{
match: 'attribute',
name: t('sharedComputedAttributes'),
href: '/settings/attributes',
- icon: <StorageIcon />
+ icon: <StorageIcon />,
},
{
match: 'maintenance',
name: t('sharedMaintenance'),
href: '/settings/maintenances',
- icon: <BuildIcon />
- }
+ icon: <BuildIcon />,
+ },
];
export default () => {
@@ -81,6 +81,6 @@ export default () => {
accountRoute.href = `/user/${userId}`;
return useMemo(() => [...mainRoutes, ...(isAdmin ? adminRoutes : [])], [
- isAdmin
+ isAdmin,
]);
};
diff --git a/modern/src/setupProxy.js b/modern/src/setupProxy.js
index c16655c..e5ca76d 100644
--- a/modern/src/setupProxy.js
+++ b/modern/src/setupProxy.js
@@ -1,6 +1,6 @@
const proxy = require('http-proxy-middleware');
module.exports = function (app) {
- app.use(proxy('/api/socket', { target: 'ws://' + process.env.REACT_APP_URL_NAME, ws: true }));
- app.use(proxy('/api', { target: 'http://' + process.env.REACT_APP_URL_NAME }));
+ app.use(proxy('/api/socket', { target: `ws://${process.env.REACT_APP_URL_NAME}`, ws: true }));
+ app.use(proxy('/api', { target: `http://${process.env.REACT_APP_URL_NAME}` }));
};
diff --git a/modern/src/store/devices.js b/modern/src/store/devices.js
index 66c1607..cca23cb 100644
--- a/modern/src/store/devices.js
+++ b/modern/src/store/devices.js
@@ -4,15 +4,15 @@ const { reducer, actions } = createSlice({
name: 'devices',
initialState: {
items: {},
- selectedId: null
+ selectedId: null,
},
reducers: {
refresh(state, action) {
state.items = {};
- action.payload.forEach(item => state.items[item['id']] = item);
+ action.payload.forEach((item) => state.items[item.id] = item);
},
update(state, action) {
- action.payload.forEach(item => state.items[item['id']] = item);
+ action.payload.forEach((item) => state.items[item.id] = item);
},
select(state, action) {
state.selectedId = action.payload.id;
@@ -20,7 +20,7 @@ const { reducer, actions } = createSlice({
remove(state, action) {
delete state.items[action.payload];
},
- }
+ },
});
export { actions as devicesActions };
diff --git a/modern/src/store/drivers.js b/modern/src/store/drivers.js
index 63522d7..38933d8 100644
--- a/modern/src/store/drivers.js
+++ b/modern/src/store/drivers.js
@@ -7,9 +7,9 @@ const { reducer, actions } = createSlice({
},
reducers: {
update(state, action) {
- action.payload.forEach(item => state.items[item['id']] = item);
+ action.payload.forEach((item) => state.items[item.id] = item);
},
- }
+ },
});
export { actions as driversActions };
diff --git a/modern/src/store/geofences.js b/modern/src/store/geofences.js
index 504b7d0..f2b7666 100644
--- a/modern/src/store/geofences.js
+++ b/modern/src/store/geofences.js
@@ -8,12 +8,12 @@ const { reducer, actions } = createSlice({
reducers: {
refresh(state, action) {
state.items = {};
- action.payload.forEach(item => state.items[item['id']] = item);
+ action.payload.forEach((item) => state.items[item.id] = item);
},
update(state, action) {
- action.payload.forEach(item => state.items[item['id']] = item);
+ action.payload.forEach((item) => state.items[item.id] = item);
},
- }
+ },
});
export { actions as geofencesActions };
diff --git a/modern/src/store/groups.js b/modern/src/store/groups.js
index 483323f..11fc5db 100644
--- a/modern/src/store/groups.js
+++ b/modern/src/store/groups.js
@@ -7,9 +7,9 @@ const { reducer, actions } = createSlice({
},
reducers: {
update(state, action) {
- action.payload.forEach(item => state.items[item['id']] = item);
+ action.payload.forEach((item) => state.items[item.id] = item);
},
- }
+ },
});
export { actions as groupsActions };
diff --git a/modern/src/store/maintenances.js b/modern/src/store/maintenances.js
index 0813f6b..08b2adb 100644
--- a/modern/src/store/maintenances.js
+++ b/modern/src/store/maintenances.js
@@ -7,9 +7,9 @@ const { reducer, actions } = createSlice({
},
reducers: {
update(state, action) {
- action.payload.forEach(item => state.items[item['id']] = item);
+ action.payload.forEach((item) => state.items[item.id] = item);
},
- }
+ },
});
export { actions as maintenancesActions };
diff --git a/modern/src/store/positions.js b/modern/src/store/positions.js
index 1df468c..8858298 100644
--- a/modern/src/store/positions.js
+++ b/modern/src/store/positions.js
@@ -7,9 +7,9 @@ const { reducer, actions } = createSlice({
},
reducers: {
update(state, action) {
- action.payload.forEach(item => state.items[item['deviceId']] = item);
+ action.payload.forEach((item) => state.items[item.deviceId] = item);
},
- }
+ },
});
export { actions as positionsActions };
diff --git a/modern/src/theme/dimensions.js b/modern/src/theme/dimensions.js
index a2403ab..fcdbaee 100644
--- a/modern/src/theme/dimensions.js
+++ b/modern/src/theme/dimensions.js
@@ -8,5 +8,5 @@ export default {
columnWidthDate: 160,
columnWidthNumber: 130,
columnWidthString: 160,
- columnWidthBoolean: 130
+ columnWidthBoolean: 130,
};
diff --git a/modern/src/theme/index.js b/modern/src/theme/index.js
index 5a3b2a9..dc0a35b 100644
--- a/modern/src/theme/index.js
+++ b/modern/src/theme/index.js
@@ -6,7 +6,7 @@ import dimensions from './dimensions';
const theme = createMuiTheme({
palette,
overrides,
- dimensions
+ dimensions,
});
export default theme;
diff --git a/modern/src/theme/overrides.js b/modern/src/theme/overrides.js
index cd6c5a5..a6d08cf 100644
--- a/modern/src/theme/overrides.js
+++ b/modern/src/theme/overrides.js
@@ -4,17 +4,17 @@ export default {
MuiFormControl: {
root: {
marginTop: 5,
- marginBottom: 5
- }
+ marginBottom: 5,
+ },
},
MuiInputLabel: {
filled: {
transform: 'translate(12px, 14px) scale(1)',
- '&$shrink' :{
- transform: 'translate(12px, -14px) scale(0.72)'
- }
+ '&$shrink': {
+ transform: 'translate(12px, -14px) scale(0.72)',
+ },
},
- },
+ },
MuiFilledInput: {
root: {
height: dimensions.inputHeight,
@@ -28,19 +28,19 @@ export default {
boxSizing: 'border-box',
'&:-webkit-autofill': {
WebkitBoxShadow: '0 0 0 100px #eeeeee inset',
- },
+ },
},
underline: {
- "&:before": {
+ '&:before': {
borderBottom: 'none',
},
- "&:after": {
+ '&:after': {
borderBottom: 'none',
},
- "&:hover:before": {
+ '&:hover:before': {
borderBottom: 'none',
- },
- }
+ },
+ },
},
MuiButton: {
root: {
@@ -48,31 +48,31 @@ export default {
marginTop: 5,
marginBottom: 5,
'&$disabled': {
- opacity: .4,
+ opacity: 0.4,
color: undefined,
- }
+ },
},
contained: {
'&$disabled': {
- opacity: .4,
+ opacity: 0.4,
color: undefined,
- backgroundColor: undefined
- }
- }
+ backgroundColor: undefined,
+ },
+ },
},
MuiFormHelperText: {
root: {
- marginBottom: -10
+ marginBottom: -10,
},
contained: {
- marginLeft: 12
- }
+ marginLeft: 12,
+ },
},
MuiAutocomplete: {
inputRoot: {
'&.MuiFilledInput-root': {
- paddingTop: 0
- }
- }
- }
+ paddingTop: 0,
+ },
+ },
+ },
};