Skip to content

Commit

Permalink
Merge branch 'traccar:master' into route_turbo_color_ramp
Browse files Browse the repository at this point in the history
  • Loading branch information
Kalabint authored Sep 26, 2024
2 parents e9e325d + 9463e50 commit 3a5228d
Show file tree
Hide file tree
Showing 101 changed files with 4,661 additions and 2,929 deletions.
11 changes: 10 additions & 1 deletion index.html
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,19 @@
<link rel="manifest" href="/manifest.webmanifest" />
<link rel="stylesheet" href="/styles.css">
<title>${title}</title>
<style>
.loader {
position: fixed; top: calc(50% - 25px); left: calc(50% - 25px);
width: 50px; aspect-ratio: 1; box-sizing: content-box; animation: ll 1s infinite linear;
border-radius: 50%; border: 8px solid lightgray; border-right-color: black;
}
@keyframes ll {to{transform: rotate(1turn)}}
</style>
</head>
<body>
<noscript>Enable JavaScript to use <a href="https://www.traccar.org/">Traccar GPS Tracking System</a>.</noscript>
<div id="root" class="root"></div>
<script type="module" src="/src/index.jsx"></script>
<div class="loader"></div>
<script type="module" src="/src/index.jsx" onerror="alert('Loading error.')"></script>
</body>
</html>
6,507 changes: 3,970 additions & 2,537 deletions package-lock.json

Large diffs are not rendered by default.

47 changes: 23 additions & 24 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,45 +1,44 @@
{
"name": "traccar",
"version": "6.2.0",
"version": "6.5.0",
"type": "module",
"private": true,
"dependencies": {
"@emotion/cache": "^11.11.0",
"@emotion/react": "^11.11.4",
"@emotion/styled": "^11.11.5",
"@fontsource/roboto": "^5.0.13",
"@emotion/cache": "^11.13.1",
"@emotion/react": "^11.13.3",
"@emotion/styled": "^11.13.0",
"@mapbox/mapbox-gl-draw": "^1.4.3",
"@mapbox/mapbox-gl-rtl-text": "^0.2.3",
"@maplibre/maplibre-gl-geocoder": "^1.5.0",
"@mui/icons-material": "^5.15.19",
"@mui/lab": "^5.0.0-alpha.170",
"@mui/material": "^5.15.19",
"@mui/styles": "^5.15.19",
"@reduxjs/toolkit": "^2.2.5",
"@maplibre/maplibre-gl-geocoder": "^1.7.0",
"@mui/icons-material": "^5.16.7",
"@mui/lab": "^5.0.0-alpha.173",
"@mui/material": "^5.16.7",
"@mui/styles": "^5.16.7",
"@reduxjs/toolkit": "^2.2.7",
"@tmcw/togeojson": "^5.8.1",
"@turf/circle": "^6.5.0",
"@turf/turf": "^6.5.0",
"@vitejs/plugin-react": "^4.3.0",
"dayjs": "^1.11.11",
"@turf/circle": "^7.1.0",
"@turf/turf": "^7.1.0",
"@vitejs/plugin-react": "^4.3.1",
"dayjs": "^1.11.13",
"events": "^3.3.0",
"mapbox-gl": "^1.13.3",
"maplibre-gl": "^4.3.2",
"maplibre-gl": "^4.7.0",
"maplibre-google-maps": "^1.1.0",
"react": "^18.3.1",
"react-country-flag": "3.1.0",
"react-dom": "^18.3.1",
"react-draggable": "^4.4.6",
"react-mui-dropzone": "^4.0.7",
"react-redux": "^9.1.2",
"react-router-dom": "^6.23.1",
"react-router-dom": "^6.26.2",
"react-virtualized-auto-sizer": "^1.0.24",
"react-window": "^1.8.10",
"recharts": "^2.12.7",
"redux": "^5.0.1",
"stylis": "^4.3.2",
"stylis": "^4.3.4",
"stylis-plugin-rtl": "^2.1.1",
"vite": "^5.2.12",
"vite-plugin-pwa": "^0.20.0",
"vite": "^5.4.6",
"vite-plugin-pwa": "^0.20.5",
"vite-plugin-svgr": "^4.2.0",
"wellknown": "^0.5.0"
},
Expand All @@ -62,12 +61,12 @@
]
},
"devDependencies": {
"@vite-pwa/assets-generator": "^0.2.4",
"@vite-pwa/assets-generator": "^0.2.6",
"eslint": "^8.57.0",
"eslint-config-airbnb": "^19.0.4",
"eslint-plugin-import": "^2.29.1",
"eslint-plugin-jsx-a11y": "^6.8.0",
"eslint-plugin-react": "^7.34.2",
"eslint-plugin-import": "^2.30.0",
"eslint-plugin-jsx-a11y": "^6.10.0",
"eslint-plugin-react": "^7.36.1",
"eslint-plugin-react-hooks": "^4.6.2"
}
}
5 changes: 3 additions & 2 deletions src/App.jsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from 'react';
import { Outlet, useNavigate } from 'react-router-dom';
import { useDispatch, useSelector } from 'react-redux';
import { LinearProgress, useMediaQuery, useTheme } from '@mui/material';
import { useMediaQuery, useTheme } from '@mui/material';
import makeStyles from '@mui/styles/makeStyles';
import BottomMenu from './common/components/BottomMenu';
import SocketController from './SocketController';
Expand All @@ -10,6 +10,7 @@ import { useCatch, useEffectAsync } from './reactHelper';
import { sessionActions } from './store';
import UpdateController from './UpdateController';
import TermsDialog from './common/components/TermsDialog';
import Loader from './common/components/Loader';

const useStyles = makeStyles(() => ({
page: {
Expand Down Expand Up @@ -61,7 +62,7 @@ const App = () => {
}, [user]);

if (user == null) {
return (<LinearProgress />);
return (<Loader />);
}
if (termsUrl && !user.attributes.termsAccepted) {
return (<TermsDialog open onCancel={() => navigate('/login')} onAccept={() => acceptTerms()} />);
Expand Down
4 changes: 2 additions & 2 deletions src/Navigation.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import {
Route, Routes, useLocation, useNavigate,
} from 'react-router-dom';
import { useDispatch } from 'react-redux';
import { LinearProgress } from '@mui/material';
import MainPage from './main/MainPage';
import CombinedReportPage from './reports/CombinedReportPage';
import RouteReportPage from './reports/RouteReportPage';
Expand Down Expand Up @@ -58,6 +57,7 @@ import LogsPage from './reports/LogsPage';
import SharePage from './settings/SharePage';
import AnnouncementPage from './settings/AnnouncementPage';
import EmulatorPage from './other/EmulatorPage';
import Loader from './common/components/Loader';

const Navigation = () => {
const navigate = useNavigate();
Expand Down Expand Up @@ -94,7 +94,7 @@ const Navigation = () => {
}, [query]);

if (!redirectsHandled) {
return (<LinearProgress />);
return (<Loader />);
}
return (
<Routes>
Expand Down
8 changes: 5 additions & 3 deletions src/ServerProvider.jsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import React, { useState } from 'react';
import { Alert, IconButton, LinearProgress } from '@mui/material';
import { Alert, IconButton } from '@mui/material';
import ReplayIcon from '@mui/icons-material/Replay';
import { useDispatch, useSelector } from 'react-redux';
import { useEffectAsync } from './reactHelper';
import { sessionActions } from './store';
import Loader from './common/components/Loader';

const ServerProvider = ({
children,
Expand All @@ -20,7 +21,8 @@ const ServerProvider = ({
if (response.ok) {
dispatch(sessionActions.updateServer(await response.json()));
} else {
throw Error(await response.text());
const message = await response.text();
throw Error(message || response.statusText);
}
} catch (error) {
setError(error.message);
Expand All @@ -43,7 +45,7 @@ const ServerProvider = ({
);
}
if (!initialized) {
return (<LinearProgress />);
return (<Loader />);
}
return children;
};
Expand Down
8 changes: 8 additions & 0 deletions src/common/attributes/useCommonDeviceAttributes.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,12 @@ export default (t) => useMemo(() => ({
name: t('attributeReportIgnoreOdometer'),
type: 'boolean',
},
deviceInactivityStart: {
name: t('attributeDeviceInactivityStart'),
type: 'number',
},
deviceInactivityPeriod: {
name: t('attributeDeviceInactivityPeriod'),
type: 'number',
},
}), [t]);
8 changes: 8 additions & 0 deletions src/common/attributes/useCommonUserAttributes.js
Original file line number Diff line number Diff line change
Expand Up @@ -137,4 +137,12 @@ export default (t) => useMemo(() => ({
name: t('sharedIconScale'),
type: 'number',
},
navigationAppLink: {
name: t('attributeNavigationAppLink'),
type: 'string',
},
navigationAppTitle: {
name: t('attributeNavigationAppTitle'),
type: 'string',
},
}), [t]);
8 changes: 0 additions & 8 deletions src/common/attributes/useDeviceAttributes.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,4 @@ export default (t) => useMemo(() => ({
name: t('sharedTimezone'),
type: 'string',
},
deviceInactivityStart: {
name: t('attributeDeviceInactivityStart'),
type: 'number',
},
deviceInactivityPeriod: {
name: t('attributeDeviceInactivityPeriod'),
type: 'number',
},
}), [t]);
12 changes: 12 additions & 0 deletions src/common/components/Loader.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { useEffect } from 'react';

const Loader = () => {
useEffect(() => {
const loader = document.querySelector('.loader');
loader.style.display = '';
return () => loader.style.display = 'none';
}, []);
return null;
};

export default Loader;
3 changes: 1 addition & 2 deletions src/common/components/RemoveDialog.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ const useStyles = makeStyles((theme) => ({
height: 'auto',
marginTop: 0,
marginBottom: 0,
color: theme.palette.error.main,
},
}));

Expand All @@ -43,7 +42,7 @@ const RemoveDialog = ({
onClose={() => onResult(false)}
message={t('sharedRemoveConfirm')}
action={(
<Button size="small" className={classes.button} onClick={handleRemove}>
<Button size="small" className={classes.button} color="error" onClick={handleRemove}>
{t('sharedRemove')}
</Button>
)}
Expand Down
9 changes: 5 additions & 4 deletions src/common/components/StatusCard.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,6 @@ const useStyles = makeStyles((theme) => ({
maxHeight: theme.dimensions.cardContentMaxHeight,
overflow: 'auto',
},
delete: {
color: theme.palette.error.main,
},
icon: {
width: '25px',
height: '25px',
Expand Down Expand Up @@ -129,6 +126,9 @@ const StatusCard = ({ deviceId, position, onClose, disableActions, desktopPaddin
const positionAttributes = usePositionAttributes(t);
const positionItems = useAttributePreference('positionItems', 'fixTime,address,speed,totalDistance');

const navigationAppLink = useAttributePreference('navigationAppLink');
const navigationAppTitle = useAttributePreference('navigationAppTitle');

const [anchorEl, setAnchorEl] = useState(null);

const [removing, setRemoving] = useState(false);
Expand Down Expand Up @@ -254,9 +254,9 @@ const StatusCard = ({ deviceId, position, onClose, disableActions, desktopPaddin
<EditIcon />
</IconButton>
<IconButton
color="error"
onClick={() => setRemoving(true)}
disabled={disableActions || deviceReadonly}
className={classes.delete}
>
<DeleteIcon />
</IconButton>
Expand All @@ -272,6 +272,7 @@ const StatusCard = ({ deviceId, position, onClose, disableActions, desktopPaddin
<MenuItem component="a" target="_blank" href={`https://www.google.com/maps/search/?api=1&query=${position.latitude}%2C${position.longitude}`}>{t('linkGoogleMaps')}</MenuItem>
<MenuItem component="a" target="_blank" href={`http://maps.apple.com/?ll=${position.latitude},${position.longitude}`}>{t('linkAppleMaps')}</MenuItem>
<MenuItem component="a" target="_blank" href={`https://www.google.com/maps/@?api=1&map_action=pano&viewpoint=${position.latitude}%2C${position.longitude}&heading=${position.course}`}>{t('linkStreetView')}</MenuItem>
{navigationAppTitle && <MenuItem component="a" target="_blank" href={navigationAppLink.replace('{latitude}', position.latitude).replace('{longitude}', position.longitude)}>{navigationAppTitle}</MenuItem>}
{!shareDisabled && !user.temporary && <MenuItem onClick={() => navigate(`/settings/device/${deviceId}/share`)}>{t('deviceShare')}</MenuItem>}
</Menu>
)}
Expand Down
3 changes: 3 additions & 0 deletions src/common/theme/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ import dimensions from './dimensions';
import components from './components';

export default (server, darkMode, direction) => useMemo(() => createTheme({
typography: {
fontFamily: 'Roboto,Segoe UI,Helvetica Neue,Arial,sans-serif',
},
palette: palette(server, darkMode),
direction,
dimensions,
Expand Down
26 changes: 20 additions & 6 deletions src/common/util/formatter.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,23 +33,34 @@ export const formatConsumption = (value, t) => `${value.toFixed(2)} ${t('sharedL

export const formatTime = (value, format) => {
if (value) {
const d = dayjs(value);
const d = dayjs(value).toDate();
const dateConfig = { year: 'numeric', month: '2-digit', day: '2-digit' };
const minuteConfig = { hour: '2-digit', minute: '2-digit' };
const secondConfig = { ...minuteConfig, second: '2-digit' };
switch (format) {
case 'date':
return d.format('L');
return d.toLocaleDateString(undefined, dateConfig);
case 'time':
return d.format('LTS');
return d.toLocaleTimeString(undefined, secondConfig);
case 'minutes':
return d.format('L LT');
return d.toLocaleString(undefined, { ...dateConfig, ...minuteConfig });
default:
return d.format('L LTS');
return d.toLocaleString(undefined, { ...dateConfig, ...secondConfig });
}
}
return '';
};

export const formatStatus = (value, t) => t(prefixString('deviceStatus', value));
export const formatAlarm = (value, t) => (value ? t(prefixString('alarm', value)) : '');

export const formatAlarm = (value, t) => {
if (value) {
return value.split(',')
.map((alarm) => t(prefixString('alarm', alarm)))
.join(', ');
}
return '';
};

export const formatCourse = (value) => {
const courseValues = ['\u2191', '\u2197', '\u2192', '\u2198', '\u2193', '\u2199', '\u2190', '\u2196'];
Expand Down Expand Up @@ -126,6 +137,9 @@ export const getBatteryStatus = (batteryLevel) => {
};

export const formatNotificationTitle = (t, notification, includeId) => {
if (notification.description) {
return notification.description;
}
let title = t(prefixString('event', notification.type));
if (notification.type === 'alarm') {
const alarmString = notification.attributes.alarms;
Expand Down
4 changes: 0 additions & 4 deletions src/index.jsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
import '@fontsource/roboto/300.css';
import '@fontsource/roboto/400.css';
import '@fontsource/roboto/500.css';
import '@fontsource/roboto/700.css';
import React from 'react';
import { createRoot } from 'react-dom/client';
import { BrowserRouter } from 'react-router-dom';
Expand Down
5 changes: 3 additions & 2 deletions src/login/LoginPage.jsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React, { useEffect, useState } from 'react';
import dayjs from 'dayjs';
import {
useMediaQuery, Select, MenuItem, FormControl, Button, TextField, Link, Snackbar, IconButton, Tooltip, LinearProgress, Box,
useMediaQuery, Select, MenuItem, FormControl, Button, TextField, Link, Snackbar, IconButton, Tooltip, Box,
} from '@mui/material';
import ReactCountryFlag from 'react-country-flag';
import makeStyles from '@mui/styles/makeStyles';
Expand All @@ -17,6 +17,7 @@ import usePersistedState from '../common/util/usePersistedState';
import { handleLoginTokenListeners, nativeEnvironment, nativePostMessage } from '../common/components/NativeInterface';
import LogoImage from './LogoImage';
import { useCatch } from '../reactHelper';
import Loader from '../common/components/Loader';

const useStyles = makeStyles((theme) => ({
options: {
Expand Down Expand Up @@ -143,7 +144,7 @@ const LoginPage = () => {

if (openIdForced) {
handleOpenIdLogin();
return (<LinearProgress />);
return (<Loader />);
}

return (
Expand Down
2 changes: 1 addition & 1 deletion src/main/MainMap.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ const MainMap = ({ filteredPositions, selectedPosition, onEventsClick }) => {
<MapNotification enabled={eventsAvailable} onClick={onEventsClick} />
)}
{desktop && (
<MapPadding left={parseInt(theme.dimensions.drawerWidthDesktop, 10)} />
<MapPadding left={parseInt(theme.dimensions.drawerWidthDesktop, 10) + parseInt(theme.spacing(1.5), 10)} />
)}
</>
);
Expand Down
Loading

0 comments on commit 3a5228d

Please sign in to comment.