aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAnton Tananaev <anton@traccar.org>2024-05-09 07:24:14 -0700
committerAnton Tananaev <anton@traccar.org>2024-05-09 07:24:14 -0700
commitc4754d0befac1a0bfb85f56419dade8378b98b32 (patch)
treec71409e6e312848df9a537acf5870bddb2e81c9b /src
parentf6d15a1a445a1abd18d89a803b8617957c6970b6 (diff)
downloadtrackermap-web-c4754d0befac1a0bfb85f56419dade8378b98b32.tar.gz
trackermap-web-c4754d0befac1a0bfb85f56419dade8378b98b32.tar.bz2
trackermap-web-c4754d0befac1a0bfb85f56419dade8378b98b32.zip
Automatic locale time formatting
Diffstat (limited to 'src')
-rw-r--r--src/common/components/PositionValue.jsx3
-rw-r--r--src/common/util/formatter.js12
-rw-r--r--src/main/EventsDrawer.jsx5
-rw-r--r--src/map/MapPositions.js5
-rw-r--r--src/other/ReplayPage.jsx5
-rw-r--r--src/reports/ChartReportPage.jsx7
-rw-r--r--src/reports/CombinedReportPage.jsx5
-rw-r--r--src/reports/EventReportPage.jsx5
-rw-r--r--src/reports/StatisticsPage.jsx5
-rw-r--r--src/reports/StopReportPage.jsx5
-rw-r--r--src/reports/SummaryReportPage.jsx5
-rw-r--r--src/reports/TripReportPage.jsx5
-rw-r--r--src/settings/DevicesPage.jsx5
-rw-r--r--src/settings/ServerPage.jsx4
-rw-r--r--src/settings/UserPage.jsx6
-rw-r--r--src/settings/UsersPage.jsx5
16 files changed, 27 insertions, 60 deletions
diff --git a/src/common/components/PositionValue.jsx b/src/common/components/PositionValue.jsx
index b1f8f656..cedf47c9 100644
--- a/src/common/components/PositionValue.jsx
+++ b/src/common/components/PositionValue.jsx
@@ -42,14 +42,13 @@ const PositionValue = ({ position, property, attribute }) => {
const speedUnit = useAttributePreference('speedUnit');
const volumeUnit = useAttributePreference('volumeUnit');
const coordinateFormat = usePreference('coordinateFormat');
- const hours12 = usePreference('twelveHourFormat');
const formatValue = () => {
switch (key) {
case 'fixTime':
case 'deviceTime':
case 'serverTime':
- return formatTime(value, 'seconds', hours12);
+ return formatTime(value, 'seconds');
case 'latitude':
return formatCoordinate('latitude', value, coordinateFormat);
case 'longitude':
diff --git a/src/common/util/formatter.js b/src/common/util/formatter.js
index 0463df2b..b10d737a 100644
--- a/src/common/util/formatter.js
+++ b/src/common/util/formatter.js
@@ -1,6 +1,7 @@
import dayjs from 'dayjs';
import duration from 'dayjs/plugin/duration';
import relativeTime from 'dayjs/plugin/relativeTime';
+import localizedFormat from 'dayjs/plugin/localizedFormat';
import {
altitudeFromMeters,
@@ -16,6 +17,7 @@ import { prefixString } from './stringUtils';
dayjs.extend(duration);
dayjs.extend(relativeTime);
+dayjs.extend(localizedFormat);
export const formatBoolean = (value, t) => (value ? t('sharedYes') : t('sharedNo'));
@@ -29,18 +31,18 @@ export const formatVoltage = (value, t) => `${value.toFixed(2)} ${t('sharedVoltA
export const formatConsumption = (value, t) => `${value.toFixed(2)} ${t('sharedLiterPerHourAbbreviation')}`;
-export const formatTime = (value, format, hours12) => {
+export const formatTime = (value, format) => {
if (value) {
const d = dayjs(value);
switch (format) {
case 'date':
- return d.format('YYYY-MM-DD');
+ return d.format('L');
case 'time':
- return d.format(hours12 ? 'hh:mm:ss A' : 'HH:mm:ss');
+ return d.format('LTS');
case 'minutes':
- return d.format(hours12 ? 'YYYY-MM-DD hh:mm A' : 'YYYY-MM-DD HH:mm');
+ return d.format('L LT');
default:
- return d.format(hours12 ? 'YYYY-MM-DD hh:mm:ss A' : 'YYYY-MM-DD HH:mm:ss');
+ return d.format('L LTS');
}
}
return '';
diff --git a/src/main/EventsDrawer.jsx b/src/main/EventsDrawer.jsx
index f9602e95..57a95eb2 100644
--- a/src/main/EventsDrawer.jsx
+++ b/src/main/EventsDrawer.jsx
@@ -9,7 +9,6 @@ import DeleteIcon from '@mui/icons-material/Delete';
import { formatNotificationTitle, formatTime } from '../common/util/formatter';
import { useTranslation } from '../common/components/LocalizationProvider';
import { eventsActions } from '../store';
-import { usePreference } from '../common/util/preferences';
const useStyles = makeStyles((theme) => ({
drawer: {
@@ -30,8 +29,6 @@ const EventsDrawer = ({ open, onClose }) => {
const dispatch = useDispatch();
const t = useTranslation();
- const hours12 = usePreference('twelveHourFormat');
-
const devices = useSelector((state) => state.devices.items);
const events = useSelector((state) => state.events.items);
@@ -66,7 +63,7 @@ const EventsDrawer = ({ open, onClose }) => {
>
<ListItemText
primary={`${devices[event.deviceId]?.name} • ${formatType(event)}`}
- secondary={formatTime(event.eventTime, 'seconds', hours12)}
+ secondary={formatTime(event.eventTime, 'seconds')}
/>
<IconButton size="small" onClick={() => dispatch(eventsActions.delete(event))}>
<DeleteIcon fontSize="small" className={classes.delete} />
diff --git a/src/map/MapPositions.js b/src/map/MapPositions.js
index 08bc6b83..d1b16299 100644
--- a/src/map/MapPositions.js
+++ b/src/map/MapPositions.js
@@ -5,7 +5,7 @@ import { useTheme } from '@mui/styles';
import { map } from './core/MapView';
import { formatTime, getStatusColor } from '../common/util/formatter';
import { mapIconKey } from './core/preloadImages';
-import { useAttributePreference, usePreference } from '../common/util/preferences';
+import { useAttributePreference } from '../common/util/preferences';
import { useCatchCallback } from '../reactHelper';
const MapPositions = ({ positions, onClick, showStatus, selectedPosition, titleField }) => {
@@ -21,7 +21,6 @@ const MapPositions = ({ positions, onClick, showStatus, selectedPosition, titleF
const selectedDeviceId = useSelector((state) => state.devices.selectedId);
const mapCluster = useAttributePreference('mapCluster', true);
- const hours12 = usePreference('twelveHourFormat');
const directionType = useAttributePreference('mapDirection', 'selected');
const createFeature = (devices, position, selectedPositionId) => {
@@ -42,7 +41,7 @@ const MapPositions = ({ positions, onClick, showStatus, selectedPosition, titleF
id: position.id,
deviceId: position.deviceId,
name: device.name,
- fixTime: formatTime(position.fixTime, 'seconds', hours12),
+ fixTime: formatTime(position.fixTime, 'seconds'),
category: mapIconKey(device.category),
color: showStatus ? position.attributes.color || getStatusColor(device.status) : 'neutral',
rotation: position.course,
diff --git a/src/other/ReplayPage.jsx b/src/other/ReplayPage.jsx
index 1050b976..1425c495 100644
--- a/src/other/ReplayPage.jsx
+++ b/src/other/ReplayPage.jsx
@@ -25,7 +25,6 @@ import { useCatch } from '../reactHelper';
import MapCamera from '../map/MapCamera';
import MapGeofence from '../map/MapGeofence';
import StatusCard from '../common/components/StatusCard';
-import { usePreference } from '../common/util/preferences';
const useStyles = makeStyles((theme) => ({
root: {
@@ -82,8 +81,6 @@ const ReplayPage = () => {
const navigate = useNavigate();
const timerRef = useRef();
- const hours12 = usePreference('twelveHourFormat');
-
const defaultDeviceId = useSelector((state) => state.devices.selectedId);
const [positions, setPositions] = useState([]);
@@ -210,7 +207,7 @@ const ReplayPage = () => {
<IconButton onClick={() => setIndex((index) => index + 1)} disabled={playing || index >= positions.length - 1}>
<FastForwardIcon />
</IconButton>
- {formatTime(positions[index].fixTime, 'seconds', hours12)}
+ {formatTime(positions[index].fixTime, 'seconds')}
</div>
</>
) : (
diff --git a/src/reports/ChartReportPage.jsx b/src/reports/ChartReportPage.jsx
index 6175e1d8..8a3d01b8 100644
--- a/src/reports/ChartReportPage.jsx
+++ b/src/reports/ChartReportPage.jsx
@@ -13,7 +13,7 @@ import PageLayout from '../common/components/PageLayout';
import ReportsMenu from './components/ReportsMenu';
import usePositionAttributes from '../common/attributes/usePositionAttributes';
import { useCatch } from '../reactHelper';
-import { useAttributePreference, usePreference } from '../common/util/preferences';
+import { useAttributePreference } from '../common/util/preferences';
import {
altitudeFromMeters, distanceFromMeters, speedFromKnots, volumeFromLiters,
} from '../common/util/converter';
@@ -29,7 +29,6 @@ const ChartReportPage = () => {
const altitudeUnit = useAttributePreference('altitudeUnit');
const speedUnit = useAttributePreference('speedUnit');
const volumeUnit = useAttributePreference('volumeUnit');
- const hours12 = usePreference('twelveHourFormat');
const [items, setItems] = useState([]);
const [types, setTypes] = useState(['speed']);
@@ -126,7 +125,7 @@ const ChartReportPage = () => {
<XAxis
dataKey="fixTime"
type="number"
- tickFormatter={(value) => formatTime(value, 'time', hours12)}
+ tickFormatter={(value) => formatTime(value, 'time')}
domain={['dataMin', 'dataMax']}
scale="time"
/>
@@ -138,7 +137,7 @@ const ChartReportPage = () => {
<CartesianGrid strokeDasharray="3 3" />
<Tooltip
formatter={(value, key) => [value, positionAttributes[key]?.name || key]}
- labelFormatter={(value) => formatTime(value, 'seconds', hours12)}
+ labelFormatter={(value) => formatTime(value, 'seconds')}
/>
<Line type="monotone" dataKey={type} />
</LineChart>
diff --git a/src/reports/CombinedReportPage.jsx b/src/reports/CombinedReportPage.jsx
index a5000839..ab472dfa 100644
--- a/src/reports/CombinedReportPage.jsx
+++ b/src/reports/CombinedReportPage.jsx
@@ -15,7 +15,6 @@ import TableShimmer from '../common/components/TableShimmer';
import MapCamera from '../map/MapCamera';
import MapGeofence from '../map/MapGeofence';
import { formatTime } from '../common/util/formatter';
-import { usePreference } from '../common/util/preferences';
import { prefixString } from '../common/util/stringUtils';
import MapMarkers from '../map/MapMarkers';
@@ -25,8 +24,6 @@ const CombinedReportPage = () => {
const devices = useSelector((state) => state.devices.items);
- const hours12 = usePreference('twelveHourFormat');
-
const [items, setItems] = useState([]);
const [loading, setLoading] = useState(false);
@@ -90,7 +87,7 @@ const CombinedReportPage = () => {
{!loading ? items.flatMap((item) => item.events.map((event, index) => (
<TableRow key={event.id}>
<TableCell>{index ? '' : devices[item.deviceId].name}</TableCell>
- <TableCell>{formatTime(event.eventTime, 'seconds', hours12)}</TableCell>
+ <TableCell>{formatTime(event.eventTime, 'seconds')}</TableCell>
<TableCell>{t(prefixString('event', event.type))}</TableCell>
</TableRow>
))) : (<TableShimmer columns={3} />)}
diff --git a/src/reports/EventReportPage.jsx b/src/reports/EventReportPage.jsx
index 5dd97741..55c1452c 100644
--- a/src/reports/EventReportPage.jsx
+++ b/src/reports/EventReportPage.jsx
@@ -17,7 +17,7 @@ import ColumnSelect from './components/ColumnSelect';
import { useCatch, useEffectAsync } from '../reactHelper';
import useReportStyles from './common/useReportStyles';
import TableShimmer from '../common/components/TableShimmer';
-import { useAttributePreference, usePreference } from '../common/util/preferences';
+import { useAttributePreference } from '../common/util/preferences';
import MapView from '../map/core/MapView';
import MapGeofence from '../map/MapGeofence';
import MapPositions from '../map/MapPositions';
@@ -42,7 +42,6 @@ const EventReportPage = () => {
const geofences = useSelector((state) => state.geofences.items);
const speedUnit = useAttributePreference('speedUnit');
- const hours12 = usePreference('twelveHourFormat');
const [allEventTypes, setAllEventTypes] = useState([['allEvents', 'eventAll']]);
@@ -123,7 +122,7 @@ const EventReportPage = () => {
const value = item[key];
switch (key) {
case 'eventTime':
- return formatTime(value, 'seconds', hours12);
+ return formatTime(value, 'seconds');
case 'type':
return t(prefixString('event', value));
case 'geofenceId':
diff --git a/src/reports/StatisticsPage.jsx b/src/reports/StatisticsPage.jsx
index 7b3f2879..3d5dcf8c 100644
--- a/src/reports/StatisticsPage.jsx
+++ b/src/reports/StatisticsPage.jsx
@@ -12,7 +12,6 @@ import ColumnSelect from './components/ColumnSelect';
import { useCatch } from '../reactHelper';
import useReportStyles from './common/useReportStyles';
import TableShimmer from '../common/components/TableShimmer';
-import { usePreference } from '../common/util/preferences';
const columnsArray = [
['captureTime', 'statisticsCaptureTime'],
@@ -32,8 +31,6 @@ const StatisticsPage = () => {
const classes = useReportStyles();
const t = useTranslation();
- const hours12 = usePreference('twelveHourFormat');
-
const [columns, setColumns] = usePersistedState('statisticsColumns', ['captureTime', 'activeUsers', 'activeDevices', 'messagesStored']);
const [items, setItems] = useState([]);
const [loading, setLoading] = useState(false);
@@ -71,7 +68,7 @@ const StatisticsPage = () => {
<TableRow key={item.id}>
{columns.map((key) => (
<TableCell key={key}>
- {key === 'captureTime' ? formatTime(item[key], 'date', hours12) : item[key]}
+ {key === 'captureTime' ? formatTime(item[key], 'date') : item[key]}
</TableCell>
))}
</TableRow>
diff --git a/src/reports/StopReportPage.jsx b/src/reports/StopReportPage.jsx
index 13a42cd4..c26351cd 100644
--- a/src/reports/StopReportPage.jsx
+++ b/src/reports/StopReportPage.jsx
@@ -10,7 +10,7 @@ import {
formatDistance, formatVolume, formatTime, formatNumericHours,
} from '../common/util/formatter';
import ReportFilter from './components/ReportFilter';
-import { useAttributePreference, usePreference } from '../common/util/preferences';
+import { useAttributePreference } from '../common/util/preferences';
import { useTranslation } from '../common/components/LocalizationProvider';
import PageLayout from '../common/components/PageLayout';
import ReportsMenu from './components/ReportsMenu';
@@ -44,7 +44,6 @@ const StopReportPage = () => {
const distanceUnit = useAttributePreference('distanceUnit');
const volumeUnit = useAttributePreference('volumeUnit');
- const hours12 = usePreference('twelveHourFormat');
const [columns, setColumns] = usePersistedState('stopColumns', ['startTime', 'endTime', 'startOdometer', 'address']);
const [items, setItems] = useState([]);
@@ -92,7 +91,7 @@ const StopReportPage = () => {
switch (key) {
case 'startTime':
case 'endTime':
- return formatTime(value, 'minutes', hours12);
+ return formatTime(value, 'minutes');
case 'startOdometer':
return formatDistance(value, distanceUnit, t);
case 'duration':
diff --git a/src/reports/SummaryReportPage.jsx b/src/reports/SummaryReportPage.jsx
index 4172514c..4d3d8b30 100644
--- a/src/reports/SummaryReportPage.jsx
+++ b/src/reports/SummaryReportPage.jsx
@@ -8,7 +8,7 @@ import {
formatDistance, formatSpeed, formatVolume, formatTime, formatNumericHours,
} from '../common/util/formatter';
import ReportFilter from './components/ReportFilter';
-import { useAttributePreference, usePreference } from '../common/util/preferences';
+import { useAttributePreference } from '../common/util/preferences';
import { useTranslation } from '../common/components/LocalizationProvider';
import PageLayout from '../common/components/PageLayout';
import ReportsMenu from './components/ReportsMenu';
@@ -41,7 +41,6 @@ const SummaryReportPage = () => {
const distanceUnit = useAttributePreference('distanceUnit');
const speedUnit = useAttributePreference('speedUnit');
const volumeUnit = useAttributePreference('volumeUnit');
- const hours12 = usePreference('twelveHourFormat');
const [columns, setColumns] = usePersistedState('summaryColumns', ['startTime', 'distance', 'averageSpeed']);
const [daily, setDaily] = useState(false);
@@ -93,7 +92,7 @@ const SummaryReportPage = () => {
case 'deviceId':
return devices[value].name;
case 'startTime':
- return formatTime(value, 'date', hours12);
+ return formatTime(value, 'date');
case 'startOdometer':
case 'endOdometer':
case 'distance':
diff --git a/src/reports/TripReportPage.jsx b/src/reports/TripReportPage.jsx
index 29bf33e5..67eca586 100644
--- a/src/reports/TripReportPage.jsx
+++ b/src/reports/TripReportPage.jsx
@@ -9,7 +9,7 @@ import {
formatDistance, formatSpeed, formatVolume, formatTime, formatNumericHours,
} from '../common/util/formatter';
import ReportFilter from './components/ReportFilter';
-import { useAttributePreference, usePreference } from '../common/util/preferences';
+import { useAttributePreference } from '../common/util/preferences';
import { useTranslation } from '../common/components/LocalizationProvider';
import PageLayout from '../common/components/PageLayout';
import ReportsMenu from './components/ReportsMenu';
@@ -50,7 +50,6 @@ const TripReportPage = () => {
const distanceUnit = useAttributePreference('distanceUnit');
const speedUnit = useAttributePreference('speedUnit');
const volumeUnit = useAttributePreference('volumeUnit');
- const hours12 = usePreference('twelveHourFormat');
const [columns, setColumns] = usePersistedState('tripColumns', ['startTime', 'endTime', 'distance', 'averageSpeed']);
const [items, setItems] = useState([]);
@@ -134,7 +133,7 @@ const TripReportPage = () => {
switch (key) {
case 'startTime':
case 'endTime':
- return formatTime(value, 'minutes', hours12);
+ return formatTime(value, 'minutes');
case 'startOdometer':
case 'endOdometer':
case 'distance':
diff --git a/src/settings/DevicesPage.jsx b/src/settings/DevicesPage.jsx
index c0da0ba7..831736e4 100644
--- a/src/settings/DevicesPage.jsx
+++ b/src/settings/DevicesPage.jsx
@@ -13,7 +13,6 @@ import CollectionFab from './components/CollectionFab';
import CollectionActions from './components/CollectionActions';
import TableShimmer from '../common/components/TableShimmer';
import SearchHeader, { filterByKeyword } from './components/SearchHeader';
-import { usePreference } from '../common/util/preferences';
import { formatTime } from '../common/util/formatter';
import { useDeviceReadonly } from '../common/util/permissions';
import useSettingsStyles from './common/useSettingsStyles';
@@ -25,8 +24,6 @@ const DevicesPage = () => {
const groups = useSelector((state) => state.groups.items);
- const hours12 = usePreference('twelveHourFormat');
-
const deviceReadonly = useDeviceReadonly();
const [timestamp, setTimestamp] = useState(Date.now());
@@ -84,7 +81,7 @@ const DevicesPage = () => {
<TableCell>{item.phone}</TableCell>
<TableCell>{item.model}</TableCell>
<TableCell>{item.contact}</TableCell>
- <TableCell>{formatTime(item.expirationTime, 'date', hours12)}</TableCell>
+ <TableCell>{formatTime(item.expirationTime, 'date')}</TableCell>
<TableCell className={classes.columnAction} padding="none">
<CollectionActions
itemId={item.id}
diff --git a/src/settings/ServerPage.jsx b/src/settings/ServerPage.jsx
index 0ac76334..26258733 100644
--- a/src/settings/ServerPage.jsx
+++ b/src/settings/ServerPage.jsx
@@ -191,10 +191,6 @@ const ServerPage = () => {
/>
<FormGroup>
<FormControlLabel
- control={<Checkbox checked={item.twelveHourFormat} onChange={(event) => setItem({ ...item, twelveHourFormat: event.target.checked })} />}
- label={t('settingsTwelveHourFormat')}
- />
- <FormControlLabel
control={<Checkbox checked={item.forceSettings} onChange={(event) => setItem({ ...item, forceSettings: event.target.checked })} />}
label={t('serverForceSettings')}
/>
diff --git a/src/settings/UserPage.jsx b/src/settings/UserPage.jsx
index 6748dd31..03a016c1 100644
--- a/src/settings/UserPage.jsx
+++ b/src/settings/UserPage.jsx
@@ -270,12 +270,6 @@ const UserPage = () => {
onChange={(e) => setItem({ ...item, poiLayer: e.target.value })}
label={t('mapPoiLayer')}
/>
- <FormGroup>
- <FormControlLabel
- control={<Checkbox checked={item.twelveHourFormat} onChange={(e) => setItem({ ...item, twelveHourFormat: e.target.checked })} />}
- label={t('settingsTwelveHourFormat')}
- />
- </FormGroup>
</AccordionDetails>
</Accordion>
<Accordion>
diff --git a/src/settings/UsersPage.jsx b/src/settings/UsersPage.jsx
index 2941965b..030f6a18 100644
--- a/src/settings/UsersPage.jsx
+++ b/src/settings/UsersPage.jsx
@@ -15,7 +15,6 @@ import CollectionActions from './components/CollectionActions';
import TableShimmer from '../common/components/TableShimmer';
import { useManager } from '../common/util/permissions';
import SearchHeader, { filterByKeyword } from './components/SearchHeader';
-import { usePreference } from '../common/util/preferences';
import useSettingsStyles from './common/useSettingsStyles';
const UsersPage = () => {
@@ -25,8 +24,6 @@ const UsersPage = () => {
const manager = useManager();
- const hours12 = usePreference('twelveHourFormat');
-
const [timestamp, setTimestamp] = useState(Date.now());
const [items, setItems] = useState([]);
const [searchKeyword, setSearchKeyword] = useState('');
@@ -91,7 +88,7 @@ const UsersPage = () => {
<TableCell>{item.email}</TableCell>
<TableCell>{formatBoolean(item.administrator, t)}</TableCell>
<TableCell>{formatBoolean(item.disabled, t)}</TableCell>
- <TableCell>{formatTime(item.expirationTime, 'date', hours12)}</TableCell>
+ <TableCell>{formatTime(item.expirationTime, 'date')}</TableCell>
<TableCell className={classes.columnAction} padding="none">
<CollectionActions
itemId={item.id}