aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDesmond Kyeremeh <elDekyfin@gmail.com>2021-07-11 23:39:30 +0000
committerDesmond Kyeremeh <elDekyfin@gmail.com>2021-07-11 23:39:30 +0000
commit004367fc1fd389b169821eb2d73266490f409999 (patch)
tree1b7e6f13c03326a957bdb78351853f429156b3ae
parent1b93de84e2bf6a6532bdb03e1ae75e47061a4dca (diff)
parent702e674ecce7de1a4f4318ef8f30c572264a4560 (diff)
downloadetbsa-traccar-web-004367fc1fd389b169821eb2d73266490f409999.tar.gz
etbsa-traccar-web-004367fc1fd389b169821eb2d73266490f409999.tar.bz2
etbsa-traccar-web-004367fc1fd389b169821eb2d73266490f409999.zip
Merge remote-tracking branch 'upstream/master' into group-config
-rw-r--r--.github/workflows/new.yml20
-rw-r--r--.github/workflows/old.yml (renamed from .github/workflows/node.js.yml)2
-rw-r--r--modern/.eslintrc.js19
-rw-r--r--modern/package.json12
-rw-r--r--modern/src/DevicePage.js2
-rw-r--r--modern/src/EditItemView.js14
-rw-r--r--modern/src/MainToolbar.js3
-rw-r--r--modern/src/PositionPage.js2
-rw-r--r--modern/src/RegisterDialog.js1
-rw-r--r--modern/src/SocketController.js4
-rw-r--r--modern/src/admin/ServerPage.js48
-rw-r--r--modern/src/admin/StatisticsPage.js9
-rw-r--r--modern/src/admin/UsersPage.js4
-rw-r--r--modern/src/attributes/EditAttributesView.js57
-rw-r--r--modern/src/common/deviceCategories.js2
-rw-r--r--modern/src/common/formatter.js12
-rw-r--r--modern/src/common/localization.js116
-rw-r--r--modern/src/form/LinkField.js18
-rw-r--r--modern/src/map/GeofenceEditMap.js4
-rw-r--r--modern/src/map/Map.js17
-rw-r--r--modern/src/map/switcher/switcher.js5
-rw-r--r--modern/src/reactHelper.js2
-rw-r--r--modern/src/reports/ReportLayout.js13
-rw-r--r--modern/src/serviceWorker.js38
-rw-r--r--modern/src/settings/ComputedAttributesPage.js10
-rw-r--r--modern/src/settings/DriversPage.js10
-rw-r--r--modern/src/settings/GroupsPage.js10
-rw-r--r--modern/src/settings/MaintenancePage.js4
-rw-r--r--modern/src/settings/MaintenancesPage.js10
-rw-r--r--modern/src/settings/NotificationsPage.js18
-rw-r--r--modern/src/setupProxy.js4
31 files changed, 225 insertions, 265 deletions
diff --git a/.github/workflows/new.yml b/.github/workflows/new.yml
new file mode 100644
index 0000000..5895610
--- /dev/null
+++ b/.github/workflows/new.yml
@@ -0,0 +1,20 @@
+name: New App Lint
+
+on:
+ push:
+ branches: [ master ]
+ pull_request:
+ branches: [ master ]
+
+jobs:
+ build:
+
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@v2
+ - uses: actions/setup-node@v1
+ - run: npm install
+ working-directory: modern
+ - run: npm run lint
+ working-directory: modern
diff --git a/.github/workflows/node.js.yml b/.github/workflows/old.yml
index a4ba2ea..2f9f39f 100644
--- a/.github/workflows/node.js.yml
+++ b/.github/workflows/old.yml
@@ -1,4 +1,4 @@
-name: Node.js CI
+name: Old App Lint
on:
push:
diff --git a/modern/.eslintrc.js b/modern/.eslintrc.js
index 4ee202f..d6380a8 100644
--- a/modern/.eslintrc.js
+++ b/modern/.eslintrc.js
@@ -1,3 +1,18 @@
module.exports = {
- "extends": "airbnb"
-}; \ No newline at end of file
+ extends: 'airbnb',
+ plugins: [
+ 'react',
+ ],
+ ignorePatterns: ['serviceWorker.js', 'localization.js', 'switcher.js'],
+ rules: {
+ 'max-len': [0],
+ 'no-shadow': [0],
+ 'no-return-assign': [0],
+ 'no-param-reassign': [0],
+ 'no-prototype-builtins': [0],
+ 'react/jsx-filename-extension': [1, { extensions: ['.js'] }],
+ 'react/prop-types': [0],
+ 'react/jsx-props-no-spreading': [0],
+ 'jsx-a11y/anchor-is-valid': [0],
+ },
+};
diff --git a/modern/package.json b/modern/package.json
index 6c74cbe..365d986 100644
--- a/modern/package.json
+++ b/modern/package.json
@@ -10,6 +10,7 @@
"@material-ui/icons": "^4.11.2",
"@material-ui/lab": "^4.0.0-alpha.58",
"@reduxjs/toolkit": "^1.6.0",
+ "@turf/circle": "^6.5.0",
"@turf/turf": "^6.4.0",
"canvas-tint-image": "^2.0.1",
"maplibre-gl": "^1.15.0",
@@ -31,7 +32,9 @@
"start": "craco start",
"build": "craco build",
"build_release": "PUBLIC_URL=/modern/ craco build",
- "test": "craco test"
+ "test": "craco test",
+ "lint": "eslint .",
+ "lint:fix": "eslint --fix --ext .js ."
},
"browserslist": {
"production": [
@@ -44,5 +47,12 @@
"last 1 firefox version",
"last 1 safari version"
]
+ },
+ "devDependencies": {
+ "eslint": "^6.8.0",
+ "eslint-config-airbnb": "^18.2.1",
+ "eslint-plugin-import": "^2.23.4",
+ "eslint-plugin-react": "^7.24.0",
+ "eslint-plugin-react-hooks": "^1.7.0"
}
}
diff --git a/modern/src/DevicePage.js b/modern/src/DevicePage.js
index a20ba22..699e97c 100644
--- a/modern/src/DevicePage.js
+++ b/modern/src/DevicePage.js
@@ -10,7 +10,7 @@ import EditItemView from './EditItemView';
import EditAttributesView from './attributes/EditAttributesView';
import deviceAttributes from './attributes/deviceAttributes';
import SelectField from './form/SelectField';
-import { deviceCategories } from './common/deviceCategories';
+import deviceCategories from './common/deviceCategories';
import LinkField from './form/LinkField';
import { prefixString } from './common/stringUtils';
diff --git a/modern/src/EditItemView.js b/modern/src/EditItemView.js
index a77f578..e067a39 100644
--- a/modern/src/EditItemView.js
+++ b/modern/src/EditItemView.js
@@ -63,20 +63,10 @@ const EditItemView = ({
{children}
<FormControl fullWidth margin="normal">
<div className={classes.buttons}>
- <Button
- type="button"
- color="primary"
- variant="outlined"
- onClick={() => history.goBack()}
- >
+ <Button type="button" color="primary" variant="outlined" onClick={() => history.goBack()}>
{t('sharedCancel')}
</Button>
- <Button
- type="button"
- color="primary"
- variant="contained"
- onClick={handleSave}
- >
+ <Button type="button" color="primary" variant="contained" onClick={handleSave}>
{t('sharedSave')}
</Button>
</div>
diff --git a/modern/src/MainToolbar.js b/modern/src/MainToolbar.js
index 9a72729..dacd668 100644
--- a/modern/src/MainToolbar.js
+++ b/modern/src/MainToolbar.js
@@ -10,8 +10,6 @@ import IconButton from '@material-ui/core/IconButton';
import MenuIcon from '@material-ui/icons/Menu';
import Drawer from '@material-ui/core/Drawer';
import List from '@material-ui/core/List';
-import ListSubheader from '@material-ui/core/ListSubheader';
-import Divider from '@material-ui/core/Divider';
import ListItem from '@material-ui/core/ListItem';
import ListItemIcon from '@material-ui/core/ListItemIcon';
import ListItemText from '@material-ui/core/ListItemText';
@@ -44,7 +42,6 @@ const MainToolbar = () => {
const [drawer, setDrawer] = useState(false);
const classes = useStyles();
const history = useHistory();
- const adminEnabled = useSelector(selectors.getIsAdmin);
const userId = useSelector(selectors.getUserId);
const openDrawer = () => {
diff --git a/modern/src/PositionPage.js b/modern/src/PositionPage.js
index f1766f6..ce4c4ac 100644
--- a/modern/src/PositionPage.js
+++ b/modern/src/PositionPage.js
@@ -44,7 +44,7 @@ const PositionPage = () => {
const attributesList = () => {
const combinedList = { ...item, ...item.attributes };
- return Object.entries(combinedList).filter(([_, value]) => typeof value !== 'object');
+ return Object.entries(combinedList).filter(([, value]) => typeof value !== 'object');
};
return (
diff --git a/modern/src/RegisterDialog.js b/modern/src/RegisterDialog.js
index c4b99f3..aafec66 100644
--- a/modern/src/RegisterDialog.js
+++ b/modern/src/RegisterDialog.js
@@ -88,6 +88,7 @@ const RegisterDialog = ({ showDialog, onResult }) => {
</Dialog>
);
}
+ return null;
};
export default RegisterDialog;
diff --git a/modern/src/SocketController.js b/modern/src/SocketController.js
index 901f506..ae82d13 100644
--- a/modern/src/SocketController.js
+++ b/modern/src/SocketController.js
@@ -7,10 +7,10 @@ import { useEffectAsync } from './reactHelper';
const displayNotifications = (events) => {
if ('Notification' in window) {
if (Notification.permission === 'granted') {
- for (const event of events) {
+ events.forEach((event) => {
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') {
diff --git a/modern/src/admin/ServerPage.js b/modern/src/admin/ServerPage.js
index 6d5b575..ec0034f 100644
--- a/modern/src/admin/ServerPage.js
+++ b/modern/src/admin/ServerPage.js
@@ -79,45 +79,19 @@ const ServerPage = () => {
</AccordionSummary>
<AccordionDetails className={classes.details}>
<FormControlLabel
- control={(
- <Checkbox
- checked={item.registration}
- onChange={(event) => setItem({ ...item, registration: event.target.checked })}
- />
- )}
+ control={<Checkbox checked={item.registration} onChange={(event) => setItem({ ...item, registration: event.target.checked })} />}
label={t('serverRegistration')}
/>
<FormControlLabel
- control={(
- <Checkbox
- checked={item.readonly}
- onChange={(event) => setItem({ ...item, readonly: event.target.checked })}
- />
- )}
+ control={<Checkbox checked={item.readonly} onChange={(event) => setItem({ ...item, readonly: event.target.checked })} />}
label={t('serverReadonly')}
/>
<FormControlLabel
- control={(
- <Checkbox
- checked={item.deviceReadonly}
- onChange={(event) => setItem({
- ...item,
- deviceReadonly: event.target.checked,
- })}
- />
- )}
+ control={<Checkbox checked={item.deviceReadonly} onChange={(event) => setItem({ ...item, deviceReadonly: event.target.checked })} />}
label={t('userDeviceReadonly')}
/>
<FormControlLabel
- control={(
- <Checkbox
- checked={item.limitCommands}
- onChange={(event) => setItem({
- ...item,
- limitCommands: event.target.checked,
- })}
- />
- )}
+ control={<Checkbox checked={item.limitCommands} onChange={(event) => setItem({ ...item, limitCommands: event.target.checked })} />}
label={t('userLimitCommands')}
/>
</AccordionDetails>
@@ -140,20 +114,10 @@ const ServerPage = () => {
)}
<FormControl fullWidth margin="normal">
<div className={classes.buttons}>
- <Button
- type="button"
- color="primary"
- variant="outlined"
- onClick={() => history.goBack()}
- >
+ <Button type="button" color="primary" variant="outlined" onClick={() => history.goBack()}>
{t('sharedCancel')}
</Button>
- <Button
- type="button"
- color="primary"
- variant="contained"
- onClick={handleSave}
- >
+ <Button type="button" color="primary" variant="contained" onClick={handleSave}>
{t('sharedSave')}
</Button>
</div>
diff --git a/modern/src/admin/StatisticsPage.js b/modern/src/admin/StatisticsPage.js
index 8a6e601..20974f4 100644
--- a/modern/src/admin/StatisticsPage.js
+++ b/modern/src/admin/StatisticsPage.js
@@ -106,14 +106,7 @@ const Filter = ({ setItems }) => {
fullWidth
/>
)}
- <Button
- variant="contained"
- color="primary"
- onClick={handleClick}
- fullWidth
- >
- {t('reportShow')}
- </Button>
+ <Button variant="contained" color="primary" onClick={handleClick} fullWidth>{t('reportShow')}</Button>
</>
);
};
diff --git a/modern/src/admin/UsersPage.js b/modern/src/admin/UsersPage.js
index 6afe099..9b51cdd 100644
--- a/modern/src/admin/UsersPage.js
+++ b/modern/src/admin/UsersPage.js
@@ -44,9 +44,7 @@ const UsersView = ({ updateTimestamp, onMenuClick }) => {
{items.map((item) => (
<TableRow key={item.id}>
<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>
diff --git a/modern/src/attributes/EditAttributesView.js b/modern/src/attributes/EditAttributesView.js
index 5ca7cad..e8d427b 100644
--- a/modern/src/attributes/EditAttributesView.js
+++ b/modern/src/attributes/EditAttributesView.js
@@ -23,10 +23,37 @@ const EditAttributesView = ({ attributes, setAttributes, definitions }) => {
const [addDialogShown, setAddDialogShown] = useState(false);
+ const updateAttribute = (key, value) => {
+ const updatedAttributes = { ...attributes };
+ updatedAttributes[key] = value;
+ setAttributes(updatedAttributes);
+ };
+
+ const deleteAttribute = (key) => {
+ const updatedAttributes = { ...attributes };
+ delete updatedAttributes[key];
+ setAttributes(updatedAttributes);
+ };
+
+ const getAttributeName = (key) => {
+ const definition = definitions[key];
+ return definition ? definition.name : key;
+ };
+
+ const getAttributeType = (value) => {
+ if (typeof value === 'number') {
+ return 'number';
+ }
+ if (typeof value === 'boolean') {
+ return 'boolean';
+ }
+ return 'string';
+ };
+
const convertToList = (attributes) => {
const booleanList = [];
const otherList = [];
- for (const key in attributes) {
+ Object.keys(attributes).forEach((key) => {
const value = attributes[key];
const type = getAttributeType(value);
if (type === 'boolean') {
@@ -34,7 +61,7 @@ const EditAttributesView = ({ attributes, setAttributes, definitions }) => {
} else {
otherList.push({ key, value, type });
}
- }
+ });
return otherList.concat(booleanList);
};
@@ -55,32 +82,6 @@ const EditAttributesView = ({ attributes, setAttributes, definitions }) => {
}
};
- const updateAttribute = (key, value) => {
- const updatedAttributes = { ...attributes };
- updatedAttributes[key] = value;
- setAttributes(updatedAttributes);
- };
-
- const deleteAttribute = (key) => {
- const updatedAttributes = { ...attributes };
- delete updatedAttributes[key];
- setAttributes(updatedAttributes);
- };
-
- const getAttributeName = (key) => {
- const definition = definitions[key];
- return definition ? definition.name : key;
- };
-
- const getAttributeType = (value) => {
- if (typeof value === 'number') {
- return 'number';
- } if (typeof value === 'boolean') {
- return 'boolean';
- }
- return 'string';
- };
-
return (
<>
{convertToList(attributes).map(({ key, value, type }) => {
diff --git a/modern/src/common/deviceCategories.js b/modern/src/common/deviceCategories.js
index 1eda190..f5d749a 100644
--- a/modern/src/common/deviceCategories.js
+++ b/modern/src/common/deviceCategories.js
@@ -1,4 +1,4 @@
-export const deviceCategories = [
+export default [
'default',
'animal',
'bicycle',
diff --git a/modern/src/common/formatter.js b/modern/src/common/formatter.js
index 7441d01..3c0341b 100644
--- a/modern/src/common/formatter.js
+++ b/modern/src/common/formatter.js
@@ -1,6 +1,12 @@
import moment from 'moment';
import t from './localization';
+export const formatBoolean = (value) => (value ? t('sharedYes') : t('sharedNo'));
+
+export const formatNumber = (value, precision = 1) => Number(value.toFixed(precision));
+
+export const formatDate = (value, format = 'YYYY-MM-DD HH:mm') => moment(value).format(format);
+
export const formatPosition = (value, key) => {
if (value != null && typeof value === 'object') {
value = value[key];
@@ -29,12 +35,6 @@ export const formatPosition = (value, key) => {
}
};
-export const formatBoolean = (value) => (value ? t('sharedYes') : t('sharedNo'));
-
-export const formatNumber = (value, precision = 1) => Number(value.toFixed(precision));
-
-export const formatDate = (value, format = 'YYYY-MM-DD HH:mm') => moment(value).format(format);
-
export const formatDistance = (value, unit) => {
switch (unit) {
case 'mi':
diff --git a/modern/src/common/localization.js b/modern/src/common/localization.js
index cb1420b..9e2123a 100644
--- a/modern/src/common/localization.js
+++ b/modern/src/common/localization.js
@@ -54,60 +54,60 @@ import zh from '../../../web/l10n/zh.json';
import zh_TW from '../../../web/l10n/zh_TW.json';
const supportedLanguages = {
- 'af': { data: af, name: 'Afrikaans' },
- 'ar': { data: ar, name: 'العربية' },
- 'az': { data: az, name: 'Azərbaycanca' },
- 'bg': { data: bg, name: 'Български' },
- 'bn': { data: bn, name: 'বাংলা' },
- 'cs': { data: cs, name: 'Čeština' },
- 'de': { data: de, name: 'Deutsch' },
- 'da': { data: da, name: 'Dansk' },
- 'el': { data: el, name: 'Ελληνικά' },
- 'en': { data: en, name: 'English' },
- 'es': { data: es, name: 'Español' },
- 'fa': { data: fa, name: 'فارسی' },
- 'fi': { data: fi, name: 'Suomi' },
- 'fr': { data: fr, name: 'Français' },
- 'he': { data: he, name: 'עברית' },
- 'hi': { data: hi, name: 'हिन्दी' },
- 'hr': { data: hr, name: 'Hrvatski' },
- 'hu': { data: hu, name: 'Magyar' },
- 'id': { data: id, name: 'Bahasa Indonesia' },
- 'it': { data: it, name: 'Italiano' },
- 'ja': { data: ja, name: '日本語' },
- 'ka': { data: ka, name: 'ქართული' },
- 'kk': { data: kk, name: 'Қазақша' },
- 'ko': { data: ko, name: '한국어' },
- 'km': { data: km, name: 'ភាសាខ្មែរ' },
- 'lo': { data: lo, name: 'ລາວ' },
- 'lt': { data: lt, name: 'Lietuvių' },
- 'lv': { data: lv, name: 'Latviešu' },
- 'ml': { data: ml, name: 'മലയാളം' },
- 'mn': { data: mn, name: 'Монгол хэл' },
- 'ms': { data: ms, name: 'بهاس ملايو' },
- 'nb': { data: nb, name: 'Norsk bokmål' },
- 'ne': { data: ne, name: 'नेपाली' },
- 'nl': { data: nl, name: 'Nederlands' },
- 'nn': { data: nn, name: 'Norsk nynorsk' },
- 'pl': { data: pl, name: 'Polski' },
- 'pt': { data: pt, name: 'Português' },
- 'pt_BR': { data: pt_BR, name: 'Português (Brasil)' },
- 'ro': { data: ro, name: 'Română' },
- 'ru': { data: ru, name: 'Русский' },
- 'si': { data: si, name: 'සිංහල' },
- 'sk': { data: sk, name: 'Slovenčina' },
- 'sl': { data: sl, name: 'Slovenščina' },
- 'sq': { data: sq, name: 'Shqipëria' },
- 'sr': { data: sr, name: 'Srpski' },
- 'sv': { data: sv, name: 'Svenska' },
- 'ta': { data: ta, name: 'தமிழ்' },
- 'th': { data: th, name: 'ไทย' },
- 'tr': { data: tr, name: 'Türkçe' },
- 'uk': { data: uk, name: 'Українська' },
- 'uz': { data: uz, name: 'Oʻzbekcha' },
- 'vi': { data: vi, name: 'Tiếng Việt' },
- 'zh': { data: zh, name: '中文' },
- 'zh_TW': { data: zh_TW, name: '中文 (Taiwan)' }
+ af: { data: af, name: 'Afrikaans' },
+ ar: { data: ar, name: 'العربية' },
+ az: { data: az, name: 'Azərbaycanca' },
+ bg: { data: bg, name: 'Български' },
+ bn: { data: bn, name: 'বাংলা' },
+ cs: { data: cs, name: 'Čeština' },
+ de: { data: de, name: 'Deutsch' },
+ da: { data: da, name: 'Dansk' },
+ el: { data: el, name: 'Ελληνικά' },
+ en: { data: en, name: 'English' },
+ es: { data: es, name: 'Español' },
+ fa: { data: fa, name: 'فارسی' },
+ fi: { data: fi, name: 'Suomi' },
+ fr: { data: fr, name: 'Français' },
+ he: { data: he, name: 'עברית' },
+ hi: { data: hi, name: 'हिन्दी' },
+ hr: { data: hr, name: 'Hrvatski' },
+ hu: { data: hu, name: 'Magyar' },
+ id: { data: id, name: 'Bahasa Indonesia' },
+ it: { data: it, name: 'Italiano' },
+ ja: { data: ja, name: '日本語' },
+ ka: { data: ka, name: 'ქართული' },
+ kk: { data: kk, name: 'Қазақша' },
+ ko: { data: ko, name: '한국어' },
+ km: { data: km, name: 'ភាសាខ្មែរ' },
+ lo: { data: lo, name: 'ລາວ' },
+ lt: { data: lt, name: 'Lietuvių' },
+ lv: { data: lv, name: 'Latviešu' },
+ ml: { data: ml, name: 'മലയാളം' },
+ mn: { data: mn, name: 'Монгол хэл' },
+ ms: { data: ms, name: 'بهاس ملايو' },
+ nb: { data: nb, name: 'Norsk bokmål' },
+ ne: { data: ne, name: 'नेपाली' },
+ nl: { data: nl, name: 'Nederlands' },
+ nn: { data: nn, name: 'Norsk nynorsk' },
+ pl: { data: pl, name: 'Polski' },
+ pt: { data: pt, name: 'Português' },
+ pt_BR: { data: pt_BR, name: 'Português (Brasil)' },
+ ro: { data: ro, name: 'Română' },
+ ru: { data: ru, name: 'Русский' },
+ si: { data: si, name: 'සිංහල' },
+ sk: { data: sk, name: 'Slovenčina' },
+ sl: { data: sl, name: 'Slovenščina' },
+ sq: { data: sq, name: 'Shqipëria' },
+ sr: { data: sr, name: 'Srpski' },
+ sv: { data: sv, name: 'Svenska' },
+ ta: { data: ta, name: 'தமிழ்' },
+ th: { data: th, name: 'ไทย' },
+ tr: { data: tr, name: 'Türkçe' },
+ uk: { data: uk, name: 'Українська' },
+ uz: { data: uz, name: 'Oʻzbekcha' },
+ vi: { data: vi, name: 'Tiếng Việt' },
+ zh: { data: zh, name: '中文' },
+ zh_TW: { data: zh_TW, name: '中文 (Taiwan)' },
};
const languages = window.navigator.languages !== undefined ? window.navigator.languages.slice() : [];
@@ -130,10 +130,6 @@ for (let i = 0; i < languages.length; i++) {
const selectedLanguage = supportedLanguages[language];
-export const findStringKeys = (predicate) => {
- return Object.keys(selectedLanguage.data).filter(predicate);
-}
+export const findStringKeys = (predicate) => Object.keys(selectedLanguage.data).filter(predicate);
-export default key => {
- return selectedLanguage.data[key];
-};
+export default (key) => selectedLanguage.data[key];
diff --git a/modern/src/form/LinkField.js b/modern/src/form/LinkField.js
index 26e1471..81467a1 100644
--- a/modern/src/form/LinkField.js
+++ b/modern/src/form/LinkField.js
@@ -44,20 +44,22 @@ const LinkField = ({
const onChange = async (event) => {
const oldValue = linked;
const newValue = event.target.value;
- for (const added of newValue.filter((it) => !oldValue.includes(it))) {
- await fetch('/api/permissions', {
+ const results = [];
+ newValue.filter((it) => !oldValue.includes(it)).forEach((added) => {
+ results.push(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))) {
- await fetch('/api/permissions', {
+ }));
+ });
+ oldValue.filter((it) => !newValue.includes(it)).forEach((removed) => {
+ results.push(fetch('/api/permissions', {
method: 'DELETE',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(createBody(removed)),
- });
- }
+ }));
+ });
+ await Promise.all(results);
setLinked(newValue);
};
diff --git a/modern/src/map/GeofenceEditMap.js b/modern/src/map/GeofenceEditMap.js
index f24fcb3..d639c19 100644
--- a/modern/src/map/GeofenceEditMap.js
+++ b/modern/src/map/GeofenceEditMap.js
@@ -94,9 +94,9 @@ const GeofenceEditMap = () => {
useEffect(() => {
draw.deleteAll();
- for (const geofence of geofences) {
+ geofences.forEach((geofence) => {
draw.add(geofenceToFeature(geofence));
- }
+ });
}, [geofences]);
return null;
diff --git a/modern/src/map/Map.js b/modern/src/map/Map.js
index 672bd26..7dd1c2a 100644
--- a/modern/src/map/Map.js
+++ b/modern/src/map/Map.js
@@ -5,7 +5,7 @@ import React, {
useRef, useLayoutEffect, useEffect, useState,
} from 'react';
import { SwitcherControl } from './switcher/switcher';
-import { deviceCategories } from '../common/deviceCategories';
+import deviceCategories from '../common/deviceCategories';
import { prepareIcon, loadImage } from './mapUtil';
import { styleCarto, styleMapbox, styleOsm } from './mapStyles';
import t from '../common/localization';
@@ -45,12 +45,15 @@ const initMap = async () => {
pixelRatio: window.devicePixelRatio,
});
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]), {
- pixelRatio: window.devicePixelRatio,
- });
- }
+ const results = [];
+ ['green', 'red', 'gray'].forEach((color) => {
+ results.push(loadImage(`images/icon/${category}.svg`).then((icon) => {
+ map.addImage(`${category}-${color}`, prepareIcon(background, icon, palette.common[color]), {
+ pixelRatio: window.devicePixelRatio,
+ });
+ }));
+ });
+ await Promise.all(results);
}));
updateReadyValue(true);
};
diff --git a/modern/src/map/switcher/switcher.js b/modern/src/map/switcher/switcher.js
index a755645..e9076aa 100644
--- a/modern/src/map/switcher/switcher.js
+++ b/modern/src/map/switcher/switcher.js
@@ -1,5 +1,4 @@
export class SwitcherControl {
-
constructor(styles, defaultStyle, beforeSwitch, afterSwitch) {
this.styles = styles;
this.defaultStyle = defaultStyle;
@@ -27,8 +26,8 @@ export class SwitcherControl {
styleElement.innerText = style.title;
styleElement.classList.add(style.title.replace(/[^a-z0-9-]/gi, '_'));
styleElement.dataset.uri = JSON.stringify(style.uri);
- styleElement.addEventListener('click', event => {
- const srcElement = event.srcElement;
+ styleElement.addEventListener('click', (event) => {
+ const { srcElement } = event;
if (srcElement.classList.contains('active')) {
return;
}
diff --git a/modern/src/reactHelper.js b/modern/src/reactHelper.js
index d8e9200..f3ef78d 100644
--- a/modern/src/reactHelper.js
+++ b/modern/src/reactHelper.js
@@ -11,5 +11,5 @@ export const usePrevious = (value) => {
export const useEffectAsync = (effect, deps) => {
useEffect(() => {
effect();
- }, deps); // eslint-disable-line react-hooks/exhaustive-deps
+ }, deps);
};
diff --git a/modern/src/reports/ReportLayout.js b/modern/src/reports/ReportLayout.js
index 92ffc0c..e8dda63 100644
--- a/modern/src/reports/ReportLayout.js
+++ b/modern/src/reports/ReportLayout.js
@@ -1,13 +1,7 @@
import React, { useState, useEffect } from 'react';
import { useHistory, useLocation } from 'react-router-dom';
import {
- Grid,
- Typography,
- Divider,
- Drawer,
- makeStyles,
- IconButton,
- Hidden,
+ Grid, Typography, Divider, Drawer, makeStyles, IconButton, Hidden,
} from '@material-ui/core';
import TimelineIcon from '@material-ui/icons/Timeline';
import PauseCircleFilledIcon from '@material-ui/icons/PauseCircleFilled';
@@ -45,6 +39,11 @@ const useStyles = makeStyles((theme) => ({
alignItems: 'center',
padding: theme.spacing(0, 1),
},
+ backArrowIconContainer: {
+ '&:hover': {
+ backgroundColor: 'transparent',
+ },
+ },
toolbar: {
[theme.breakpoints.down('md')]: {
...theme.mixins.toolbar,
diff --git a/modern/src/serviceWorker.js b/modern/src/serviceWorker.js
index f59f199..a034430 100644
--- a/modern/src/serviceWorker.js
+++ b/modern/src/serviceWorker.js
@@ -11,13 +11,13 @@
// opt-in, read https://bit.ly/CRA-PWA
const isLocalhost = Boolean(
- window.location.hostname === 'localhost' ||
+ window.location.hostname === 'localhost'
// [::1] is the IPv6 localhost address.
- window.location.hostname === '[::1]' ||
+ || window.location.hostname === '[::1]'
// 127.0.0.0/8 are considered localhost for IPv4.
- window.location.hostname.match(
- /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
- )
+ || window.location.hostname.match(
+ /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/,
+ ),
);
export function register(config) {
@@ -42,8 +42,8 @@ export function register(config) {
// service worker/PWA documentation.
navigator.serviceWorker.ready.then(() => {
console.log(
- 'This web app is being served cache-first by a service ' +
- 'worker. To learn more, visit https://bit.ly/CRA-PWA'
+ 'This web app is being served cache-first by a service '
+ + 'worker. To learn more, visit https://bit.ly/CRA-PWA',
);
});
} else {
@@ -57,7 +57,7 @@ export function register(config) {
function registerValidSW(swUrl, config) {
navigator.serviceWorker
.register(swUrl)
- .then(registration => {
+ .then((registration) => {
registration.onupdatefound = () => {
const installingWorker = registration.installing;
if (installingWorker == null) {
@@ -70,8 +70,8 @@ function registerValidSW(swUrl, config) {
// but the previous service worker will still serve the older
// content until all client tabs are closed.
console.log(
- 'New content is available and will be used when all ' +
- 'tabs for this page are closed. See https://bit.ly/CRA-PWA.'
+ 'New content is available and will be used when all '
+ + 'tabs for this page are closed. See https://bit.ly/CRA-PWA.',
);
// Execute callback
@@ -93,7 +93,7 @@ function registerValidSW(swUrl, config) {
};
};
})
- .catch(error => {
+ .catch((error) => {
console.error('Error during service worker registration:', error);
});
}
@@ -103,15 +103,15 @@ function checkValidServiceWorker(swUrl, config) {
fetch(swUrl, {
headers: { 'Service-Worker': 'script' },
})
- .then(response => {
+ .then((response) => {
// Ensure service worker exists, and that we really are getting a JS file.
const contentType = response.headers.get('content-type');
if (
- response.status === 404 ||
- (contentType != null && contentType.indexOf('javascript') === -1)
+ response.status === 404
+ || (contentType != null && contentType.indexOf('javascript') === -1)
) {
// No service worker found. Probably a different app. Reload the page.
- navigator.serviceWorker.ready.then(registration => {
+ navigator.serviceWorker.ready.then((registration) => {
registration.unregister().then(() => {
window.location.reload();
});
@@ -123,7 +123,7 @@ function checkValidServiceWorker(swUrl, config) {
})
.catch(() => {
console.log(
- 'No internet connection found. App is running in offline mode.'
+ 'No internet connection found. App is running in offline mode.',
);
});
}
@@ -131,11 +131,11 @@ function checkValidServiceWorker(swUrl, config) {
export function unregister() {
if ('serviceWorker' in navigator) {
navigator.serviceWorker.ready
- .then(registration => {
+ .then((registration) => {
registration.unregister();
})
- .catch(error => {
+ .catch((error) => {
console.error(error.message);
});
}
-} \ No newline at end of file
+}
diff --git a/modern/src/settings/ComputedAttributesPage.js b/modern/src/settings/ComputedAttributesPage.js
index fcf49d3..d376f23 100644
--- a/modern/src/settings/ComputedAttributesPage.js
+++ b/modern/src/settings/ComputedAttributesPage.js
@@ -46,7 +46,8 @@ const ComputedAttributeView = ({ updateTimestamp, onMenuClick }) => {
<TableBody>
{items.map((item) => (
<TableRow key={item.id}>
- {adminEnabled && (
+ {adminEnabled
+ && (
<TableCell className={classes.columnAction} padding="none">
<IconButton
onClick={(event) => onMenuClick(event.currentTarget, item.id)}
@@ -69,11 +70,8 @@ const ComputedAttributeView = ({ updateTimestamp, onMenuClick }) => {
const ComputedAttributesPage = () => (
<OptionsLayout>
- <EditCollectionView
- content={ComputedAttributeView}
- editPath="/settings/attribute"
- endpoint="attributes/computed"
- />
+
+ <EditCollectionView content={ComputedAttributeView} editPath="/settings/attribute" endpoint="attributes/computed" />
</OptionsLayout>
);
diff --git a/modern/src/settings/DriversPage.js b/modern/src/settings/DriversPage.js
index 57f69b6..03bf49c 100644
--- a/modern/src/settings/DriversPage.js
+++ b/modern/src/settings/DriversPage.js
@@ -41,9 +41,7 @@ const DriversView = ({ updateTimestamp, onMenuClick }) => {
{items.map((item) => (
<TableRow key={item.id}>
<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>
@@ -59,11 +57,7 @@ const DriversView = ({ updateTimestamp, onMenuClick }) => {
const DriversPage = () => (
<OptionsLayout>
- <EditCollectionView
- content={DriversView}
- editPath="/settings/driver"
- endpoint="drivers"
- />
+ <EditCollectionView content={DriversView} editPath="/settings/driver" endpoint="drivers" />
</OptionsLayout>
);
diff --git a/modern/src/settings/GroupsPage.js b/modern/src/settings/GroupsPage.js
index 3b1058e..ebebd40 100644
--- a/modern/src/settings/GroupsPage.js
+++ b/modern/src/settings/GroupsPage.js
@@ -40,9 +40,7 @@ const GroupsView = ({ updateTimestamp, onMenuClick }) => {
{items.map((item) => (
<TableRow key={item.id}>
<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>
@@ -57,11 +55,7 @@ const GroupsView = ({ updateTimestamp, onMenuClick }) => {
const GroupsPage = () => (
<OptionsLayout>
- <EditCollectionView
- content={GroupsView}
- editPath="/settings/group"
- endpoint="groups"
- />
+ <EditCollectionView content={GroupsView} editPath="/settings/group" endpoint="groups" />
</OptionsLayout>
);
diff --git a/modern/src/settings/MaintenancePage.js b/modern/src/settings/MaintenancePage.js
index 9d60937..89ebaa1 100644
--- a/modern/src/settings/MaintenancePage.js
+++ b/modern/src/settings/MaintenancePage.js
@@ -30,12 +30,12 @@ const MaintenancePage = () => {
const convertToList = (attributes) => {
const otherList = [];
- for (const key in attributes) {
+ Object.keys(attributes).forEach((key) => {
const value = attributes[key];
if (value.type === 'number') {
otherList.push({ key, name: value.name, type: value.type });
}
- }
+ });
return otherList;
};
diff --git a/modern/src/settings/MaintenancesPage.js b/modern/src/settings/MaintenancesPage.js
index b8e74d2..357d079 100644
--- a/modern/src/settings/MaintenancesPage.js
+++ b/modern/src/settings/MaintenancesPage.js
@@ -65,9 +65,7 @@ const MaintenancesView = ({ updateTimestamp, onMenuClick }) => {
{items.map((item) => (
<TableRow key={item.id}>
<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>
@@ -85,11 +83,7 @@ const MaintenancesView = ({ updateTimestamp, onMenuClick }) => {
const MaintenacesPage = () => (
<OptionsLayout>
- <EditCollectionView
- content={MaintenancesView}
- editPath="/settings/maintenance"
- endpoint="maintenance"
- />
+ <EditCollectionView content={MaintenancesView} editPath="/settings/maintenance" endpoint="maintenance" />
</OptionsLayout>
);
diff --git a/modern/src/settings/NotificationsPage.js b/modern/src/settings/NotificationsPage.js
index 079f88d..2f1ee8b 100644
--- a/modern/src/settings/NotificationsPage.js
+++ b/modern/src/settings/NotificationsPage.js
@@ -56,20 +56,14 @@ const NotificationsView = ({ updateTimestamp, onMenuClick }) => {
{items.map((item) => (
<TableRow key={item.id}>
<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>{t(prefixString('event', item.type))}</TableCell>
<TableCell>{formatBoolean(item.always)}</TableCell>
- <TableCell>
- {formatList('alarm', item.attributes.alarms)}
- </TableCell>
- <TableCell>
- {formatList('notificator', item.notificators)}
- </TableCell>
+ <TableCell>{formatList('alarm', item.attributes.alarms)}</TableCell>
+ <TableCell>{formatList('notificator', item.notificators)}</TableCell>
</TableRow>
))}
</TableBody>
@@ -80,11 +74,7 @@ const NotificationsView = ({ updateTimestamp, onMenuClick }) => {
const NotificationsPage = () => (
<OptionsLayout>
- <EditCollectionView
- content={NotificationsView}
- editPath="/settings/notification"
- endpoint="notifications"
- />
+ <EditCollectionView content={NotificationsView} editPath="/settings/notification" endpoint="notifications" />
</OptionsLayout>
);
diff --git a/modern/src/setupProxy.js b/modern/src/setupProxy.js
index e5ca76d..3ab7643 100644
--- a/modern/src/setupProxy.js
+++ b/modern/src/setupProxy.js
@@ -1,6 +1,8 @@
+/* eslint-disable import/no-extraneous-dependencies */
+
const proxy = require('http-proxy-middleware');
-module.exports = function (app) {
+export default (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}` }));
};