diff options
author | Anton Tananaev <anton@traccar.org> | 2022-05-08 11:48:09 -0700 |
---|---|---|
committer | Anton Tananaev <anton@traccar.org> | 2022-05-08 11:48:09 -0700 |
commit | 2352071211b61c10fa5bf5736baaff7809d18bf0 (patch) | |
tree | 743e4adc1cc35fb3585b912daaa8719ae5757f60 /modern/src/common/util | |
parent | 044733ff543156d76437daae8edb66850d785ac9 (diff) | |
download | trackermap-web-2352071211b61c10fa5bf5736baaff7809d18bf0.tar.gz trackermap-web-2352071211b61c10fa5bf5736baaff7809d18bf0.tar.bz2 trackermap-web-2352071211b61c10fa5bf5736baaff7809d18bf0.zip |
Organize common code
Diffstat (limited to 'modern/src/common/util')
-rw-r--r-- | modern/src/common/util/converter.js | 83 | ||||
-rw-r--r-- | modern/src/common/util/deviceCategories.js | 23 | ||||
-rw-r--r-- | modern/src/common/util/duration.js | 2 | ||||
-rw-r--r-- | modern/src/common/util/formatter.js | 81 | ||||
-rw-r--r-- | modern/src/common/util/permissions.js | 11 | ||||
-rw-r--r-- | modern/src/common/util/preferences.js | 15 | ||||
-rw-r--r-- | modern/src/common/util/stringUtils.js | 3 | ||||
-rw-r--r-- | modern/src/common/util/usePersistedState.js | 18 | ||||
-rw-r--r-- | modern/src/common/util/useQuery.js | 7 |
9 files changed, 243 insertions, 0 deletions
diff --git a/modern/src/common/util/converter.js b/modern/src/common/util/converter.js new file mode 100644 index 00000000..61e2dfe6 --- /dev/null +++ b/modern/src/common/util/converter.js @@ -0,0 +1,83 @@ +const speedConverter = (unit) => { + switch (unit) { + case 'kmh': + return 1.852; + case 'mph': + return 1.15078; + case 'kn': + default: + return 1; + } +}; + +export const speedUnitString = (unit, t) => { + switch (unit) { + case 'kmh': + return t('sharedKmh'); + case 'mph': + return t('sharedMph'); + case 'kn': + default: + return t('sharedKn'); + } +}; + +export const speedFromKnots = (value, unit) => value * speedConverter(unit); + +export const speedToKnots = (value, unit) => value / speedConverter(unit); + +const distanceConverter = (unit) => { + switch (unit) { + case 'mi': + return 0.000621371; + case 'nmi': + return 0.000539957; + case 'km': + default: + return 0.001; + } +}; + +export const distanceUnitString = (unit, t) => { + switch (unit) { + case 'mi': + return t('sharedMi'); + case 'nmi': + return t('sharedNmi'); + case 'km': + default: + return t('sharedKm'); + } +}; + +export const distanceFromMeters = (value, unit) => value * distanceConverter(unit); + +export const distanceToMeters = (value, unit) => value / distanceConverter(unit); + +const volumeConverter = (unit) => { + switch (unit) { + case 'impGal': + return 4.546; + case 'usGal': + return 3.785; + case 'ltr': + default: + return 1; + } +}; + +export const volumeUnitString = (value, unit, t) => { + switch (unit) { + case 'impGal': + return t('sharedGallonAbbreviation'); + case 'usGal': + return t('sharedGallonAbbreviation'); + case 'ltr': + default: + return t('sharedLiterAbbreviation'); + } +}; + +export const volumeFromLiters = (value, unit) => value / volumeConverter(unit); + +export const volumeToLiters = (value, unit) => value * volumeConverter(unit); diff --git a/modern/src/common/util/deviceCategories.js b/modern/src/common/util/deviceCategories.js new file mode 100644 index 00000000..f5d749aa --- /dev/null +++ b/modern/src/common/util/deviceCategories.js @@ -0,0 +1,23 @@ +export default [ + 'default', + 'animal', + 'bicycle', + 'boat', + 'bus', + 'car', + 'crane', + 'helicopter', + 'motorcycle', + 'offroad', + 'person', + 'pickup', + 'plane', + 'ship', + 'tractor', + 'train', + 'tram', + 'trolleybus', + 'truck', + 'van', + 'scooter', +]; diff --git a/modern/src/common/util/duration.js b/modern/src/common/util/duration.js new file mode 100644 index 00000000..aae74868 --- /dev/null +++ b/modern/src/common/util/duration.js @@ -0,0 +1,2 @@ +export const snackBarDurationShortMs = 1500; +export const snackBarDurationLongMs = 2750; diff --git a/modern/src/common/util/formatter.js b/modern/src/common/util/formatter.js new file mode 100644 index 00000000..08e29bc4 --- /dev/null +++ b/modern/src/common/util/formatter.js @@ -0,0 +1,81 @@ +import moment from 'moment'; +import { + distanceFromMeters, distanceUnitString, speedFromKnots, speedUnitString, volumeFromLiters, volumeUnitString, +} from './converter'; +import { prefixString } from './stringUtils'; + +export const formatBoolean = (value, t) => (value ? t('sharedYes') : t('sharedNo')); + +export const formatNumber = (value, precision = 1) => Number(value.toFixed(precision)); + +export const formatPercentage = (value) => `${value}%`; + +export const formatDate = (value, format = 'YYYY-MM-DD HH:mm') => moment(value).format(format); +export const formatTime = (value, format = 'YYYY-MM-DD HH:mm:ss') => moment(value).format(format); + +export const formatStatus = (value, t) => t(prefixString('deviceStatus', value)); +export const formatAlarm = (value, t) => t(prefixString('alarm', value)); + +export const formatCourse = (value) => { + const courseValues = ['N', 'NE', 'E', 'SE', 'S', 'SW', 'W', 'NW']; + return courseValues[Math.floor(value / 45)]; +}; + +export const formatDistance = (value, unit, t) => `${distanceFromMeters(value, unit).toFixed(2)} ${distanceUnitString(unit, t)}`; + +export const formatSpeed = (value, unit, t) => `${speedFromKnots(value, unit).toFixed(2)} ${speedUnitString(unit, t)}`; + +export const formatVolume = (value, unit, t) => `${volumeFromLiters(value, unit).toFixed(2)} ${volumeUnitString(unit, t)}`; + +export const formatHours = (value) => moment.duration(value).humanize(); + +export const formatCoordinate = (key, value, unit) => { + let hemisphere; + let degrees; + let minutes; + let seconds; + + if (key === 'latitude') { + hemisphere = value >= 0 ? 'N' : 'S'; + } else { + hemisphere = value >= 0 ? 'E' : 'W'; + } + + switch (unit) { + case 'ddm': + value = Math.abs(value); + degrees = Math.floor(value); + minutes = (value - degrees) * 60; + 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}`; + default: + return `${value.toFixed(6)}°`; + } +}; + +export const getStatusColor = (status) => { + switch (status) { + case 'online': + return 'positive'; + case 'offline': + return 'negative'; + case 'unknown': + default: + return 'neutral'; + } +}; + +export const getBatteryStatus = (batteryLevel) => { + if (batteryLevel >= 70) { + return 'positive'; + } + if (batteryLevel > 30) { + return 'medium'; + } + return 'negative'; +}; diff --git a/modern/src/common/util/permissions.js b/modern/src/common/util/permissions.js new file mode 100644 index 00000000..72ca0b08 --- /dev/null +++ b/modern/src/common/util/permissions.js @@ -0,0 +1,11 @@ +import { useSelector } from 'react-redux'; + +export const useAdministrator = () => useSelector((state) => state.session.user?.administrator); + +export const useReadonly = () => useSelector((state) => state.session.server?.readonly || state.session.user?.readonly); + +export const useDeviceReadonly = () => useSelector((state) => state.session.server?.readonly || state.session.user?.readonly + || state.session.server?.deviceReadonly || state.session.user?.deviceReadonly); + +export const useEditable = () => useSelector((state) => state.session.user?.administrator + || (!state.session.server?.readonly && !state.session.user?.readonly)); diff --git a/modern/src/common/util/preferences.js b/modern/src/common/util/preferences.js new file mode 100644 index 00000000..aba3c82c --- /dev/null +++ b/modern/src/common/util/preferences.js @@ -0,0 +1,15 @@ +import { useSelector } from 'react-redux'; + +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) => 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/util/stringUtils.js b/modern/src/common/util/stringUtils.js new file mode 100644 index 00000000..fc997fe0 --- /dev/null +++ b/modern/src/common/util/stringUtils.js @@ -0,0 +1,3 @@ +export const prefixString = (prefix, value) => prefix + value.charAt(0).toUpperCase() + value.slice(1); + +export const unprefixString = (prefix, value) => value.charAt(prefix.length).toLowerCase() + value.slice(prefix.length + 1); diff --git a/modern/src/common/util/usePersistedState.js b/modern/src/common/util/usePersistedState.js new file mode 100644 index 00000000..8bc4401f --- /dev/null +++ b/modern/src/common/util/usePersistedState.js @@ -0,0 +1,18 @@ +import { useEffect, useState } from 'react'; + +export const savePersistedState = (key, value) => { + window.localStorage.setItem(key, JSON.stringify(value)); +}; + +export default (key, defaultValue) => { + const [value, setValue] = useState(() => { + const stickyValue = window.localStorage.getItem(key); + return stickyValue ? JSON.parse(stickyValue) : defaultValue; + }); + + useEffect(() => { + savePersistedState(key, value); + }, [key, value]); + + return [value, setValue]; +}; diff --git a/modern/src/common/util/useQuery.js b/modern/src/common/util/useQuery.js new file mode 100644 index 00000000..f246df7c --- /dev/null +++ b/modern/src/common/util/useQuery.js @@ -0,0 +1,7 @@ +import { useMemo } from 'react'; +import { useLocation } from 'react-router-dom'; + +export default () => { + const { search } = useLocation(); + return useMemo(() => new URLSearchParams(search), [search]); +}; |