aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnton Tananaev <anton@traccar.org>2022-11-06 17:00:03 -0800
committerAnton Tananaev <anton@traccar.org>2022-11-06 17:00:03 -0800
commita9c8b1b6c513257a5fd69cf00992d4fec59d6069 (patch)
treeb2fa1bd33ae8766affb4ac1cfdba2dde5a9a54de
parent4d6d5eca8c6ee8c43340d18d323816885edeb9da (diff)
downloadtrackermap-web-a9c8b1b6c513257a5fd69cf00992d4fec59d6069.tar.gz
trackermap-web-a9c8b1b6c513257a5fd69cf00992d4fec59d6069.tar.bz2
trackermap-web-a9c8b1b6c513257a5fd69cf00992d4fec59d6069.zip
Respect 12 hour time
-rw-r--r--modern/src/common/components/PositionValue.js3
-rw-r--r--modern/src/common/util/formatter.js17
-rw-r--r--modern/src/main/EventsDrawer.js8
-rw-r--r--modern/src/map/MapPositions.js5
-rw-r--r--modern/src/other/ReplayPage.js5
-rw-r--r--modern/src/reports/ChartReportPage.js5
-rw-r--r--modern/src/reports/EventReportPage.js5
-rw-r--r--modern/src/reports/StatisticsPage.js5
-rw-r--r--modern/src/reports/StopReportPage.js5
-rw-r--r--modern/src/reports/SummaryReportPage.js5
-rw-r--r--modern/src/reports/TripReportPage.js5
-rw-r--r--modern/src/settings/CalendarPage.js10
-rw-r--r--modern/src/settings/UsersPage.js5
13 files changed, 60 insertions, 23 deletions
diff --git a/modern/src/common/components/PositionValue.js b/modern/src/common/components/PositionValue.js
index a851c886..27f793c6 100644
--- a/modern/src/common/components/PositionValue.js
+++ b/modern/src/common/components/PositionValue.js
@@ -24,13 +24,14 @@ const PositionValue = ({ position, property, attribute }) => {
const altitudeUnit = useAttributePreference('altitudeUnit');
const speedUnit = useAttributePreference('speedUnit');
const coordinateFormat = usePreference('coordinateFormat');
+ const hours12 = usePreference('twelveHourFormat');
const formatValue = () => {
switch (key) {
case 'fixTime':
case 'deviceTime':
case 'serverTime':
- return formatTime(value);
+ return formatTime(value, 'seconds', hours12);
case 'latitude':
return formatCoordinate('latitude', value, coordinateFormat);
case 'longitude':
diff --git a/modern/src/common/util/formatter.js b/modern/src/common/util/formatter.js
index 88398c68..56c02547 100644
--- a/modern/src/common/util/formatter.js
+++ b/modern/src/common/util/formatter.js
@@ -17,7 +17,22 @@ export const formatNumber = (value, precision = 1) => Number(value.toFixed(preci
export const formatPercentage = (value) => `${value}%`;
-export const formatTime = (value, format = 'YYYY-MM-DD HH:mm:ss') => (value ? moment(value).format(format) : '');
+export const formatTime = (value, format, hours12) => {
+ if (value) {
+ const m = moment(value);
+ switch (format) {
+ case 'date':
+ return m.format('YYYY-MM-DD');
+ case 'time':
+ return m.format(hours12 ? 'hh:mm:ss A' : 'HH:mm:ss');
+ case 'minutes':
+ return m.format(hours12 ? 'YYYY-MM-DD hh:mm A' : 'YYYY-MM-DD HH:mm');
+ default:
+ return m.format(hours12 ? 'YYYY-MM-DD hh:mm:ss A' : 'YYYY-MM-DD HH:mm:ss');
+ }
+ }
+ return '';
+};
export const formatStatus = (value, t) => t(prefixString('deviceStatus', value));
export const formatAlarm = (value, t) => (value ? t(prefixString('alarm', value)) : '');
diff --git a/modern/src/main/EventsDrawer.js b/modern/src/main/EventsDrawer.js
index 46664f87..67700fc4 100644
--- a/modern/src/main/EventsDrawer.js
+++ b/modern/src/main/EventsDrawer.js
@@ -9,6 +9,7 @@ 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: {
@@ -29,6 +30,8 @@ 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);
@@ -61,7 +64,10 @@ const EventsDrawer = ({ open, onClose }) => {
onClick={() => navigate(`/event/${event.id}`)}
disabled={!event.id}
>
- <ListItemText primary={`${devices[event.deviceId]?.name} • ${formatType(event)}`} secondary={formatTime(event.eventTime)} />
+ <ListItemText
+ primary={`${devices[event.deviceId]?.name} • ${formatType(event)}`}
+ secondary={formatTime(event.eventTime, 'seconds', hours12)}
+ />
<IconButton size="small" onClick={() => dispatch(eventsActions.delete(event))}>
<DeleteIcon fontSize="small" className={classes.negative} />
</IconButton>
diff --git a/modern/src/map/MapPositions.js b/modern/src/map/MapPositions.js
index e334800c..2f038ec6 100644
--- a/modern/src/map/MapPositions.js
+++ b/modern/src/map/MapPositions.js
@@ -4,7 +4,7 @@ import { map } from './core/MapView';
import { formatTime, getStatusColor } from '../common/util/formatter';
import { mapIconKey } from './core/preloadImages';
import { findFonts } from './core/mapUtil';
-import { useAttributePreference } from '../common/util/preferences';
+import { useAttributePreference, usePreference } from '../common/util/preferences';
const MapPositions = ({ positions, onClick, showStatus, selectedPosition, titleField }) => {
const id = useId();
@@ -15,6 +15,7 @@ const MapPositions = ({ positions, onClick, showStatus, selectedPosition, titleF
const iconScale = useAttributePreference('iconScale', 1);
const mapCluster = useAttributePreference('mapCluster', true);
+ const hours12 = usePreference('twelveHourFormat');
const createFeature = (devices, position, selectedPositionId) => {
const device = devices[position.deviceId];
@@ -22,7 +23,7 @@ const MapPositions = ({ positions, onClick, showStatus, selectedPosition, titleF
id: position.id,
deviceId: position.deviceId,
name: device.name,
- fixTime: formatTime(position.fixTime),
+ fixTime: formatTime(position.fixTime, 'seconds', hours12),
category: mapIconKey(device.category),
color: showStatus ? position.attributes.color || getStatusColor(device.status) : 'neutral',
rotation: position.course,
diff --git a/modern/src/other/ReplayPage.js b/modern/src/other/ReplayPage.js
index 8839138f..1050b976 100644
--- a/modern/src/other/ReplayPage.js
+++ b/modern/src/other/ReplayPage.js
@@ -25,6 +25,7 @@ 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: {
@@ -81,6 +82,8 @@ const ReplayPage = () => {
const navigate = useNavigate();
const timerRef = useRef();
+ const hours12 = usePreference('twelveHourFormat');
+
const defaultDeviceId = useSelector((state) => state.devices.selectedId);
const [positions, setPositions] = useState([]);
@@ -207,7 +210,7 @@ const ReplayPage = () => {
<IconButton onClick={() => setIndex((index) => index + 1)} disabled={playing || index >= positions.length - 1}>
<FastForwardIcon />
</IconButton>
- {formatTime(positions[index].fixTime)}
+ {formatTime(positions[index].fixTime, 'seconds', hours12)}
</div>
</>
) : (
diff --git a/modern/src/reports/ChartReportPage.js b/modern/src/reports/ChartReportPage.js
index 4605a5b9..3a4aeb4f 100644
--- a/modern/src/reports/ChartReportPage.js
+++ b/modern/src/reports/ChartReportPage.js
@@ -12,7 +12,7 @@ import PageLayout from '../common/components/PageLayout';
import ReportsMenu from './components/ReportsMenu';
import usePositionAttributes from '../common/attributes/usePositionAttributes';
import { useCatch } from '../reactHelper';
-import { useAttributePreference } from '../common/util/preferences';
+import { useAttributePreference, usePreference } from '../common/util/preferences';
import {
altitudeFromMeters, distanceFromMeters, speedFromKnots, volumeFromLiters,
} from '../common/util/converter';
@@ -28,6 +28,7 @@ const ChartReportPage = () => {
const altitudeUnit = useAttributePreference('altitudeUnit');
const speedUnit = useAttributePreference('speedUnit');
const volumeUnit = useAttributePreference('volumeUnit');
+ const hours12 = usePreference('twelveHourFormat');
const [items, setItems] = useState([]);
const [type, setType] = useState('speed');
@@ -47,7 +48,7 @@ const ChartReportPage = () => {
const formattedPositions = positions.map((position) => {
const data = { ...position, ...position.attributes };
const formatted = {};
- formatted.fixTime = formatTime(position.fixTime, 'HH:mm:ss');
+ formatted.fixTime = formatTime(position.fixTime, 'time', hours12);
Object.keys(data).forEach((key) => {
const value = data[key];
if (typeof value === 'number') {
diff --git a/modern/src/reports/EventReportPage.js b/modern/src/reports/EventReportPage.js
index ce1772e4..67bbd888 100644
--- a/modern/src/reports/EventReportPage.js
+++ b/modern/src/reports/EventReportPage.js
@@ -16,7 +16,7 @@ import ColumnSelect from './components/ColumnSelect';
import { useCatch, useEffectAsync } from '../reactHelper';
import useReportStyles from './common/useReportStyles';
import TableShimmer from '../common/components/TableShimmer';
-import { useAttributePreference } from '../common/util/preferences';
+import { useAttributePreference, usePreference } from '../common/util/preferences';
import MapView from '../map/core/MapView';
import MapGeofence from '../map/MapGeofence';
import MapPositions from '../map/MapPositions';
@@ -39,6 +39,7 @@ const EventReportPage = () => {
const geofences = useSelector((state) => state.geofences.items);
const speedUnit = useAttributePreference('speedUnit');
+ const hours12 = usePreference('twelveHourFormat');
const [allEventTypes, setAllEventTypes] = useState([['allEvents', 'eventAll']]);
@@ -105,7 +106,7 @@ const EventReportPage = () => {
const formatValue = (item, key) => {
switch (key) {
case 'eventTime':
- return formatTime(item[key]);
+ return formatTime(item[key], 'seconds', hours12);
case 'type':
return t(prefixString('event', item[key]));
case 'geofenceId':
diff --git a/modern/src/reports/StatisticsPage.js b/modern/src/reports/StatisticsPage.js
index 254a912d..7b3f2879 100644
--- a/modern/src/reports/StatisticsPage.js
+++ b/modern/src/reports/StatisticsPage.js
@@ -12,6 +12,7 @@ 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'],
@@ -31,6 +32,8 @@ 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);
@@ -68,7 +71,7 @@ const StatisticsPage = () => {
<TableRow key={item.id}>
{columns.map((key) => (
<TableCell key={key}>
- {key === 'captureTime' ? formatTime(item[key], 'YYYY-MM-DD') : item[key]}
+ {key === 'captureTime' ? formatTime(item[key], 'date', hours12) : item[key]}
</TableCell>
))}
</TableRow>
diff --git a/modern/src/reports/StopReportPage.js b/modern/src/reports/StopReportPage.js
index a322304e..ce790401 100644
--- a/modern/src/reports/StopReportPage.js
+++ b/modern/src/reports/StopReportPage.js
@@ -9,7 +9,7 @@ import {
formatDistance, formatHours, formatVolume, formatTime,
} from '../common/util/formatter';
import ReportFilter from './components/ReportFilter';
-import { useAttributePreference } from '../common/util/preferences';
+import { useAttributePreference, usePreference } from '../common/util/preferences';
import { useTranslation } from '../common/components/LocalizationProvider';
import PageLayout from '../common/components/PageLayout';
import ReportsMenu from './components/ReportsMenu';
@@ -41,6 +41,7 @@ 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([]);
@@ -77,7 +78,7 @@ const StopReportPage = () => {
switch (key) {
case 'startTime':
case 'endTime':
- return formatTime(item[key], 'YYYY-MM-DD HH:mm');
+ return formatTime(item[key], 'minutes', hours12);
case 'startOdometer':
return formatDistance(item[key], distanceUnit, t);
case 'duration':
diff --git a/modern/src/reports/SummaryReportPage.js b/modern/src/reports/SummaryReportPage.js
index f8216155..d66d58c6 100644
--- a/modern/src/reports/SummaryReportPage.js
+++ b/modern/src/reports/SummaryReportPage.js
@@ -7,7 +7,7 @@ import {
formatDistance, formatHours, formatSpeed, formatVolume, formatTime,
} from '../common/util/formatter';
import ReportFilter from './components/ReportFilter';
-import { useAttributePreference } from '../common/util/preferences';
+import { useAttributePreference, usePreference } from '../common/util/preferences';
import { useTranslation } from '../common/components/LocalizationProvider';
import PageLayout from '../common/components/PageLayout';
import ReportsMenu from './components/ReportsMenu';
@@ -38,6 +38,7 @@ 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);
@@ -77,7 +78,7 @@ const SummaryReportPage = () => {
case 'deviceId':
return devices[item[key]].name;
case 'startTime':
- return item[key] ? formatTime(item[key], 'YYYY-MM-DD') : null;
+ return formatTime(item[key], 'date', hours12);
case 'startOdometer':
case 'endOdometer':
case 'distance':
diff --git a/modern/src/reports/TripReportPage.js b/modern/src/reports/TripReportPage.js
index 63988850..ffe16241 100644
--- a/modern/src/reports/TripReportPage.js
+++ b/modern/src/reports/TripReportPage.js
@@ -8,7 +8,7 @@ import {
formatDistance, formatSpeed, formatHours, formatVolume, formatTime,
} from '../common/util/formatter';
import ReportFilter from './components/ReportFilter';
-import { useAttributePreference } from '../common/util/preferences';
+import { useAttributePreference, usePreference } from '../common/util/preferences';
import { useTranslation } from '../common/components/LocalizationProvider';
import PageLayout from '../common/components/PageLayout';
import ReportsMenu from './components/ReportsMenu';
@@ -47,6 +47,7 @@ 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([]);
@@ -119,7 +120,7 @@ const TripReportPage = () => {
switch (key) {
case 'startTime':
case 'endTime':
- return formatTime(item[key], 'YYYY-MM-DD HH:mm');
+ return formatTime(item[key], 'minutes', hours12);
case 'startOdometer':
case 'endOdometer':
case 'distance':
diff --git a/modern/src/settings/CalendarPage.js b/modern/src/settings/CalendarPage.js
index 81f0021d..17848484 100644
--- a/modern/src/settings/CalendarPage.js
+++ b/modern/src/settings/CalendarPage.js
@@ -13,7 +13,7 @@ import { useTranslation } from '../common/components/LocalizationProvider';
import SettingsMenu from './components/SettingsMenu';
import { prefixString } from '../common/util/stringUtils';
-const formatTime = (time) => {
+const formatCalendarTime = (time) => {
const tzid = Intl.DateTimeFormat().resolvedOptions().timeZone;
return `TZID=${tzid}:${time.locale('en').format('YYYYMMDDTHHmmss')}`;
};
@@ -47,8 +47,8 @@ const simpleCalendar = () => window.btoa([
'PRODID:-//Traccar//NONSGML Traccar//EN',
'BEGIN:VEVENT',
'UID:00000000-0000-0000-0000-000000000000',
- `DTSTART;${formatTime(moment())}`,
- `DTEND;${formatTime(moment().add(1, 'hours'))}`,
+ `DTSTART;${formatCalendarTime(moment())}`,
+ `DTEND;${formatCalendarTime(moment().add(1, 'hours'))}`,
'RRULE:FREQ=DAILY',
'SUMMARY:Event',
'END:VEVENT',
@@ -133,7 +133,7 @@ const CalendarPage = () => {
type="datetime-local"
value={moment(lines[5].slice(-15)).locale('en').format(moment.HTML5_FMT.DATETIME_LOCAL)}
onChange={(e) => {
- const time = formatTime(moment(e.target.value, moment.HTML5_FMT.DATETIME_LOCAL));
+ const time = formatCalendarTime(moment(e.target.value, moment.HTML5_FMT.DATETIME_LOCAL));
setItem({ ...item, data: updateCalendar(lines, 5, `DTSTART;${time}`) });
}}
/>
@@ -142,7 +142,7 @@ const CalendarPage = () => {
type="datetime-local"
value={moment(lines[6].slice(-15)).locale('en').format(moment.HTML5_FMT.DATETIME_LOCAL)}
onChange={(e) => {
- const time = formatTime(moment(e.target.value, moment.HTML5_FMT.DATETIME_LOCAL));
+ const time = formatCalendarTime(moment(e.target.value, moment.HTML5_FMT.DATETIME_LOCAL));
setItem({ ...item, data: updateCalendar(lines, 6, `DTEND;${time}`) });
}}
/>
diff --git a/modern/src/settings/UsersPage.js b/modern/src/settings/UsersPage.js
index bdebb1bb..6cb10d25 100644
--- a/modern/src/settings/UsersPage.js
+++ b/modern/src/settings/UsersPage.js
@@ -14,6 +14,7 @@ import CollectionActions from './components/CollectionActions';
import TableShimmer from '../common/components/TableShimmer';
import { useAdministrator } from '../common/util/permissions';
import SearchHeader, { filterByKeyword } from './components/SearchHeader';
+import { usePreference } from '../common/util/preferences';
const useStyles = makeStyles((theme) => ({
columnAction: {
@@ -28,6 +29,8 @@ const UsersPage = () => {
const admin = useAdministrator();
+ const hours12 = usePreference('twelveHourFormat');
+
const [timestamp, setTimestamp] = useState(Date.now());
const [items, setItems] = useState([]);
const [searchKeyword, setSearchKeyword] = useState('');
@@ -83,7 +86,7 @@ const UsersPage = () => {
<TableCell>{item.email}</TableCell>
<TableCell>{formatBoolean(item.administrator, t)}</TableCell>
<TableCell>{formatBoolean(item.disabled, t)}</TableCell>
- <TableCell>{formatTime(item.expirationTime, 'YYYY-MM-DD')}</TableCell>
+ <TableCell>{formatTime(item.expirationTime, 'date', hours12)}</TableCell>
<TableCell className={classes.columnAction} padding="none">
<CollectionActions
itemId={item.id}