From f418231b6b2f5e030a0d2dcc390c314602b1f740 Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Sat, 6 Apr 2024 09:22:10 -0700 Subject: Move modern to the top --- .../src/common/attributes/useCommandAttributes.js | 213 ------------ .../common/attributes/useCommonDeviceAttributes.js | 21 -- .../common/attributes/useCommonUserAttributes.js | 136 -------- .../src/common/attributes/useDeviceAttributes.js | 33 -- .../src/common/attributes/useGeofenceAttributes.js | 18 - modern/src/common/attributes/useGroupAttributes.js | 12 - .../src/common/attributes/usePositionAttributes.js | 380 --------------------- .../src/common/attributes/useServerAttributes.js | 62 ---- modern/src/common/attributes/useUserAttributes.js | 60 ---- modern/src/common/components/AddressValue.jsx | 37 -- modern/src/common/components/BottomMenu.jsx | 135 -------- modern/src/common/components/DriverValue.js | 9 - modern/src/common/components/ErrorHandler.jsx | 27 -- modern/src/common/components/GeofencesValue.js | 9 - modern/src/common/components/LinkField.jsx | 93 ----- .../src/common/components/LocalizationProvider.jsx | 187 ---------- modern/src/common/components/NativeInterface.js | 72 ---- modern/src/common/components/NavBar.jsx | 25 -- modern/src/common/components/PageLayout.jsx | 118 ------- modern/src/common/components/PositionValue.jsx | 133 -------- modern/src/common/components/RemoveDialog.jsx | 54 --- modern/src/common/components/SelectField.jsx | 77 ----- modern/src/common/components/SideNav.jsx | 33 -- modern/src/common/components/SplitButton.jsx | 48 --- modern/src/common/components/StatusCard.jsx | 288 ---------------- modern/src/common/components/TableShimmer.jsx | 17 - modern/src/common/theme/components.js | 40 --- modern/src/common/theme/dimensions.js | 14 - modern/src/common/theme/index.js | 11 - modern/src/common/theme/palette.js | 22 -- modern/src/common/util/converter.js | 107 ------ modern/src/common/util/deviceCategories.js | 24 -- modern/src/common/util/duration.js | 2 - modern/src/common/util/formatter.js | 143 -------- modern/src/common/util/permissions.js | 28 -- modern/src/common/util/preferences.js | 41 --- modern/src/common/util/stringUtils.js | 3 - modern/src/common/util/useFeatures.js | 44 --- modern/src/common/util/usePersistedState.js | 22 -- modern/src/common/util/useQuery.js | 7 - 40 files changed, 2805 deletions(-) delete mode 100644 modern/src/common/attributes/useCommandAttributes.js delete mode 100644 modern/src/common/attributes/useCommonDeviceAttributes.js delete mode 100644 modern/src/common/attributes/useCommonUserAttributes.js delete mode 100644 modern/src/common/attributes/useDeviceAttributes.js delete mode 100644 modern/src/common/attributes/useGeofenceAttributes.js delete mode 100644 modern/src/common/attributes/useGroupAttributes.js delete mode 100644 modern/src/common/attributes/usePositionAttributes.js delete mode 100644 modern/src/common/attributes/useServerAttributes.js delete mode 100644 modern/src/common/attributes/useUserAttributes.js delete mode 100644 modern/src/common/components/AddressValue.jsx delete mode 100644 modern/src/common/components/BottomMenu.jsx delete mode 100644 modern/src/common/components/DriverValue.js delete mode 100644 modern/src/common/components/ErrorHandler.jsx delete mode 100644 modern/src/common/components/GeofencesValue.js delete mode 100644 modern/src/common/components/LinkField.jsx delete mode 100644 modern/src/common/components/LocalizationProvider.jsx delete mode 100644 modern/src/common/components/NativeInterface.js delete mode 100644 modern/src/common/components/NavBar.jsx delete mode 100644 modern/src/common/components/PageLayout.jsx delete mode 100644 modern/src/common/components/PositionValue.jsx delete mode 100644 modern/src/common/components/RemoveDialog.jsx delete mode 100644 modern/src/common/components/SelectField.jsx delete mode 100644 modern/src/common/components/SideNav.jsx delete mode 100644 modern/src/common/components/SplitButton.jsx delete mode 100644 modern/src/common/components/StatusCard.jsx delete mode 100644 modern/src/common/components/TableShimmer.jsx delete mode 100644 modern/src/common/theme/components.js delete mode 100644 modern/src/common/theme/dimensions.js delete mode 100644 modern/src/common/theme/index.js delete mode 100644 modern/src/common/theme/palette.js delete mode 100644 modern/src/common/util/converter.js delete mode 100644 modern/src/common/util/deviceCategories.js delete mode 100644 modern/src/common/util/duration.js delete mode 100644 modern/src/common/util/formatter.js delete mode 100644 modern/src/common/util/permissions.js delete mode 100644 modern/src/common/util/preferences.js delete mode 100644 modern/src/common/util/stringUtils.js delete mode 100644 modern/src/common/util/useFeatures.js delete mode 100644 modern/src/common/util/usePersistedState.js delete mode 100644 modern/src/common/util/useQuery.js (limited to 'modern/src/common') diff --git a/modern/src/common/attributes/useCommandAttributes.js b/modern/src/common/attributes/useCommandAttributes.js deleted file mode 100644 index 189a0e2e..00000000 --- a/modern/src/common/attributes/useCommandAttributes.js +++ /dev/null @@ -1,213 +0,0 @@ -import { useMemo } from 'react'; - -export default (t) => useMemo(() => ({ - custom: [ - { - key: 'data', - name: t('commandData'), - type: 'string', - }, - ], - positionPeriodic: [ - { - key: 'frequency', - name: t('commandFrequency'), - type: 'number', - }, - ], - setTimezone: [ - { - key: 'timezone', - name: t('commandTimezone'), - type: 'string', - }, - ], - sendSms: [ - { - key: 'phone', - name: t('commandPhone'), - type: 'string', - }, - { - key: 'message', - name: t('commandMessage'), - type: 'string', - }, - ], - message: [ - { - key: 'message', - name: t('commandMessage'), - type: 'string', - }, - ], - sendUssd: [ - { - key: 'phone', - name: t('commandPhone'), - type: 'string', - }, - ], - sosNumber: [ - { - key: 'index', - name: t('commandIndex'), - type: 'number', - }, - { - key: 'phone', - name: t('commandPhone'), - type: 'string', - }, - ], - silenceTime: [ - { - key: 'data', - name: t('commandData'), - type: 'string', - }, - ], - setPhonebook: [ - { - key: 'data', - name: t('commandData'), - type: 'string', - }, - ], - voiceMessage: [ - { - key: 'data', - name: t('commandData'), - type: 'string', - }, - ], - outputControl: [ - { - key: 'index', - name: t('commandIndex'), - type: 'number', - }, - { - key: 'data', - name: t('commandData'), - type: 'string', - }, - ], - voiceMonitoring: [ - { - key: 'enable', - name: t('commandEnable'), - type: 'boolean', - }, - ], - setAgps: [ - { - key: 'enable', - name: t('commandEnable'), - type: 'boolean', - }, - ], - setIndicator: [ - { - key: 'data', - name: t('commandData'), - type: 'string', - }, - ], - configuration: [ - { - key: 'data', - name: t('commandData'), - type: 'string', - }, - ], - setConnection: [ - { - key: 'server', - name: t('commandServer'), - type: 'string', - }, - { - key: 'port', - name: t('commandPort'), - type: 'number', - }, - ], - setOdometer: [ - { - key: 'data', - name: t('commandData'), - type: 'string', - }, - ], - modePowerSaving: [ - { - key: 'enable', - name: t('commandEnable'), - type: 'boolean', - }, - ], - modeDeepSleep: [ - { - key: 'enable', - name: t('commandEnable'), - type: 'boolean', - }, - ], - alarmGeofence: [ - { - key: 'radius', - name: t('commandRadius'), - type: 'number', - }, - ], - alarmBattery: [ - { - key: 'enable', - name: t('commandEnable'), - type: 'boolean', - }, - ], - alarmSos: [ - { - key: 'enable', - name: t('commandEnable'), - type: 'boolean', - }, - ], - alarmRemove: [ - { - key: 'enable', - name: t('commandEnable'), - type: 'boolean', - }, - ], - alarmClock: [ - { - key: 'data', - name: t('commandData'), - type: 'string', - }, - ], - alarmSpeed: [ - { - key: 'data', - name: t('commandData'), - type: 'string', - }, - ], - alarmFall: [ - { - key: 'enable', - name: t('commandEnable'), - type: 'boolean', - }, - ], - alarmVibration: [ - { - key: 'data', - name: t('commandData'), - type: 'string', - }, - ], -}), [t]); diff --git a/modern/src/common/attributes/useCommonDeviceAttributes.js b/modern/src/common/attributes/useCommonDeviceAttributes.js deleted file mode 100644 index f9214818..00000000 --- a/modern/src/common/attributes/useCommonDeviceAttributes.js +++ /dev/null @@ -1,21 +0,0 @@ -import { useMemo } from 'react'; - -export default (t) => useMemo(() => ({ - speedLimit: { - name: t('attributeSpeedLimit'), - type: 'number', - subtype: 'speed', - }, - fuelDropThreshold: { - name: t('attributeFuelDropThreshold'), - type: 'number', - }, - fuelIncreaseThreshold: { - name: t('attributeFuelIncreaseThreshold'), - type: 'number', - }, - 'report.ignoreOdometer': { - name: t('attributeReportIgnoreOdometer'), - type: 'boolean', - }, -}), [t]); diff --git a/modern/src/common/attributes/useCommonUserAttributes.js b/modern/src/common/attributes/useCommonUserAttributes.js deleted file mode 100644 index 294ddea8..00000000 --- a/modern/src/common/attributes/useCommonUserAttributes.js +++ /dev/null @@ -1,136 +0,0 @@ -import { useMemo } from 'react'; - -export default (t) => useMemo(() => ({ - mapGeofences: { - name: t('attributeShowGeofences'), - type: 'boolean', - }, - mapLiveRoutes: { - name: t('mapLiveRoutes'), - type: 'string', - }, - mapDirection: { - name: t('mapDirection'), - type: 'string', - }, - mapFollow: { - name: t('deviceFollow'), - type: 'boolean', - }, - mapCluster: { - name: t('mapClustering'), - type: 'boolean', - }, - mapOnSelect: { - name: t('mapOnSelect'), - type: 'boolean', - }, - activeMapStyles: { - name: t('mapActive'), - type: 'string', - }, - devicePrimary: { - name: t('devicePrimaryInfo'), - type: 'string', - }, - deviceSecondary: { - name: t('deviceSecondaryInfo'), - type: 'string', - }, - soundEvents: { - name: t('eventsSoundEvents'), - type: 'string', - }, - soundAlarms: { - name: t('eventsSoundAlarms'), - type: 'string', - }, - positionItems: { - name: t('attributePopupInfo'), - type: 'string', - }, - locationIqKey: { - name: t('mapLocationIqKey'), - type: 'string', - }, - mapboxAccessToken: { - name: t('mapMapboxKey'), - type: 'string', - }, - mapTilerKey: { - name: t('mapMapTilerKey'), - type: 'string', - }, - bingMapsKey: { - name: t('mapBingKey'), - type: 'string', - }, - openWeatherKey: { - name: t('mapOpenWeatherKey'), - type: 'string', - }, - tomTomKey: { - name: t('mapTomTomKey'), - type: 'string', - }, - hereKey: { - name: t('mapHereKey'), - type: 'string', - }, - notificationTokens: { - name: t('attributeNotificationTokens'), - type: 'string', - }, - 'ui.disableSavedCommands': { - name: t('attributeUiDisableSavedCommands'), - type: 'boolean', - }, - 'ui.disableGroups': { - name: t('attributeUiDisableGroups'), - type: 'boolean', - }, - 'ui.disableAttributes': { - name: t('attributeUiDisableAttributes'), - type: 'boolean', - }, - 'ui.disableEvents': { - name: t('attributeUiDisableEvents'), - type: 'boolean', - }, - 'ui.disableVehicleFeatures': { - name: t('attributeUiDisableVehicleFeatures'), - type: 'boolean', - }, - 'ui.disableDrivers': { - name: t('attributeUiDisableDrivers'), - type: 'boolean', - }, - 'ui.disableComputedAttributes': { - name: t('attributeUiDisableComputedAttributes'), - type: 'boolean', - }, - 'ui.disableCalendars': { - name: t('attributeUiDisableCalendars'), - type: 'boolean', - }, - 'ui.disableMaintenance': { - name: t('attributeUiDisableMaintenance'), - type: 'boolean', - }, - 'web.liveRouteLength': { - name: t('attributeWebLiveRouteLength'), - type: 'number', - }, - 'web.selectZoom': { - name: t('attributeWebSelectZoom'), - type: 'number', - }, - 'web.maxZoom': { - name: t('attributeWebMaxZoom'), - type: 'number', - }, - iconScale: { - name: t('sharedIconScale'), - type: 'number', - }, -}), [t]); diff --git a/modern/src/common/attributes/useDeviceAttributes.js b/modern/src/common/attributes/useDeviceAttributes.js deleted file mode 100644 index eab9b8f6..00000000 --- a/modern/src/common/attributes/useDeviceAttributes.js +++ /dev/null @@ -1,33 +0,0 @@ -import { useMemo } from 'react'; - -export default (t) => useMemo(() => ({ - 'web.reportColor': { - name: t('attributeWebReportColor'), - type: 'string', - subtype: 'color', - }, - devicePassword: { - name: t('attributeDevicePassword'), - type: 'string', - }, - deviceImage: { - name: t('attributeDeviceImage'), - type: 'string', - }, - 'processing.copyAttributes': { - name: t('attributeProcessingCopyAttributes'), - type: 'string', - }, - 'decoder.timezone': { - name: t('sharedTimezone'), - type: 'string', - }, - deviceInactivityStart: { - name: t('attributeDeviceInactivityStart'), - type: 'number', - }, - deviceInactivityPeriod: { - name: t('attributeDeviceInactivityPeriod'), - type: 'number', - }, -}), [t]); diff --git a/modern/src/common/attributes/useGeofenceAttributes.js b/modern/src/common/attributes/useGeofenceAttributes.js deleted file mode 100644 index a5cd068b..00000000 --- a/modern/src/common/attributes/useGeofenceAttributes.js +++ /dev/null @@ -1,18 +0,0 @@ -import { useMemo } from 'react'; - -export default (t) => useMemo(() => ({ - color: { - name: t('attributeColor'), - type: 'string', - }, - speedLimit: { - name: t('attributeSpeedLimit'), - type: 'number', - subtype: 'speed', - }, - polylineDistance: { - name: t('attributePolylineDistance'), - type: 'number', - subtype: 'distance', - }, -}), [t]); diff --git a/modern/src/common/attributes/useGroupAttributes.js b/modern/src/common/attributes/useGroupAttributes.js deleted file mode 100644 index 53a299e1..00000000 --- a/modern/src/common/attributes/useGroupAttributes.js +++ /dev/null @@ -1,12 +0,0 @@ -import { useMemo } from 'react'; - -export default (t) => useMemo(() => ({ - 'processing.copyAttributes': { - name: t('attributeProcessingCopyAttributes'), - type: 'string', - }, - 'decoder.timezone': { - name: t('sharedTimezone'), - type: 'string', - }, -}), [t]); diff --git a/modern/src/common/attributes/usePositionAttributes.js b/modern/src/common/attributes/usePositionAttributes.js deleted file mode 100644 index 0b191ebc..00000000 --- a/modern/src/common/attributes/usePositionAttributes.js +++ /dev/null @@ -1,380 +0,0 @@ -import { useMemo } from 'react'; - -export default (t) => useMemo(() => ({ - id: { - name: t('deviceIdentifier'), - type: 'number', - property: true, - }, - latitude: { - name: t('positionLatitude'), - type: 'number', - property: true, - }, - longitude: { - name: t('positionLongitude'), - type: 'number', - property: true, - }, - speed: { - name: t('positionSpeed'), - type: 'number', - dataType: 'speed', - property: true, - }, - course: { - name: t('positionCourse'), - type: 'number', - property: true, - }, - altitude: { - name: t('positionAltitude'), - type: 'number', - property: true, - }, - accuracy: { - name: t('positionAccuracy'), - type: 'number', - dataType: 'distance', - property: true, - }, - valid: { - name: t('positionValid'), - type: 'boolean', - property: true, - }, - protocol: { - name: t('positionProtocol'), - type: 'string', - property: true, - }, - address: { - name: t('positionAddress'), - type: 'string', - property: true, - }, - deviceTime: { - name: t('positionDeviceTime'), - type: 'string', - property: true, - }, - fixTime: { - name: t('positionFixTime'), - type: 'string', - property: true, - }, - serverTime: { - name: t('positionServerTime'), - type: 'string', - property: true, - }, - geofenceIds: { - name: t('sharedGeofences'), - property: true, - }, - raw: { - name: t('positionRaw'), - type: 'string', - }, - index: { - name: t('positionIndex'), - type: 'number', - }, - hdop: { - name: t('positionHdop'), - type: 'number', - }, - vdop: { - name: t('positionVdop'), - type: 'number', - }, - pdop: { - name: t('positionPdop'), - type: 'number', - }, - sat: { - name: t('positionSat'), - type: 'number', - }, - satVisible: { - name: t('positionSatVisible'), - type: 'number', - }, - rssi: { - name: t('positionRssi'), - type: 'number', - }, - coolantTemp: { - name: t('positionCoolantTemp'), - type: 'number', - }, - gps: { - name: t('positionGps'), - type: 'number', - }, - roaming: { - name: t('positionRoaming'), - type: 'boolean', - }, - event: { - name: t('positionEvent'), - type: 'string', - }, - alarm: { - name: t('positionAlarm'), - type: 'string', - }, - status: { - name: t('positionStatus'), - type: 'string', - }, - odometer: { - name: t('positionOdometer'), - type: 'number', - dataType: 'distance', - }, - serviceOdometer: { - name: t('positionServiceOdometer'), - type: 'number', - dataType: 'distance', - }, - tripOdometer: { - name: t('positionTripOdometer'), - type: 'number', - dataType: 'distance', - }, - hours: { - name: t('positionHours'), - type: 'number', - dataType: 'hours', - }, - steps: { - name: t('positionSteps'), - type: 'number', - }, - heartRate: { - name: t('positionHeartRate'), - type: 'number', - }, - input: { - name: t('positionInput'), - type: 'number', - }, - in1: { - name: `${t('positionInput')} 1`, - type: 'boolean', - }, - in2: { - name: `${t('positionInput')} 2`, - type: 'boolean', - }, - in3: { - name: `${t('positionInput')} 3`, - type: 'boolean', - }, - in4: { - name: `${t('positionInput')} 4`, - type: 'boolean', - }, - output: { - name: t('positionOutput'), - type: 'number', - }, - out1: { - name: `${t('positionOutput')} 1`, - type: 'boolean', - }, - out2: { - name: `${t('positionOutput')} 2`, - type: 'boolean', - }, - out3: { - name: `${t('positionOutput')} 3`, - type: 'boolean', - }, - out4: { - name: `${t('positionOutput')} 4`, - type: 'boolean', - }, - power: { - name: t('positionPower'), - type: 'number', - dataType: 'voltage', - }, - battery: { - name: t('positionBattery'), - type: 'number', - dataType: 'voltage', - }, - batteryLevel: { - name: t('positionBatteryLevel'), - type: 'number', - dataType: 'percentage', - }, - fuel: { - name: t('positionFuel'), - type: 'number', - dataType: 'volume', - }, - fuelConsumption: { - name: t('positionFuelConsumption'), - type: 'number', - }, - versionFw: { - name: t('positionVersionFw'), - type: 'string', - }, - versionHw: { - name: t('positionVersionHw'), - type: 'string', - }, - type: { - name: t('sharedType'), - type: 'string', - }, - ignition: { - name: t('positionIgnition'), - type: 'boolean', - }, - flags: { - name: t('positionFlags'), - type: 'string', - }, - charge: { - name: t('positionCharge'), - type: 'boolean', - }, - ip: { - name: t('positionIp'), - type: 'string', - }, - archive: { - name: t('positionArchive'), - type: 'boolean', - }, - distance: { - name: t('positionDistance'), - type: 'number', - dataType: 'distance', - }, - totalDistance: { - name: t('deviceTotalDistance'), - type: 'number', - dataType: 'distance', - }, - rpm: { - name: t('positionRpm'), - type: 'number', - }, - vin: { - name: t('positionVin'), - type: 'string', - }, - approximate: { - name: t('positionApproximate'), - type: 'boolean', - }, - throttle: { - name: t('positionThrottle'), - type: 'number', - }, - motion: { - name: t('positionMotion'), - type: 'boolean', - }, - armed: { - name: t('positionArmed'), - type: 'boolean', - }, - geofence: { - name: t('sharedGeofence'), - type: 'string', - }, - acceleration: { - name: t('positionAcceleration'), - type: 'number', - }, - deviceTemp: { - name: t('positionDeviceTemp'), - type: 'number', - }, - temp1: { - name: `${t('positionTemp')} 1`, - type: 'number', - }, - temp2: { - name: `${t('positionTemp')} 2`, - type: 'number', - }, - temp3: { - name: `${t('positionTemp')} 3`, - type: 'number', - }, - temp4: { - name: `${t('positionTemp')} 4`, - type: 'number', - }, - operator: { - name: t('positionOperator'), - type: 'string', - }, - command: { - name: t('deviceCommand'), - type: 'string', - }, - blocked: { - name: t('positionBlocked'), - type: 'boolean', - }, - lock: { - name: t('alarmLock'), - type: 'boolean', - }, - dtcs: { - name: t('positionDtcs'), - type: 'string', - }, - obdSpeed: { - name: t('positionObdSpeed'), - type: 'number', - dataType: 'speed', - }, - obdOdometer: { - name: t('positionObdOdometer'), - type: 'number', - dataType: 'distance', - }, - result: { - name: t('eventCommandResult'), - type: 'string', - }, - driverUniqueId: { - name: t('sharedDriver'), - type: 'string', - }, - card: { - name: t('positionCard'), - type: 'string', - }, - drivingTime: { - name: t('positionDrivingTime'), - type: 'number', - dataType: 'hours', - }, - color: { - name: t('attributeColor'), - type: 'string', - }, - image: { - name: t('positionImage'), - type: 'string', - }, - video: { - name: t('positionVideo'), - type: 'string', - }, - audio: { - name: t('positionAudio'), - type: 'string', - }, -}), [t]); diff --git a/modern/src/common/attributes/useServerAttributes.js b/modern/src/common/attributes/useServerAttributes.js deleted file mode 100644 index 80ac3c7d..00000000 --- a/modern/src/common/attributes/useServerAttributes.js +++ /dev/null @@ -1,62 +0,0 @@ -import { useMemo } from 'react'; - -export default (t) => useMemo(() => ({ - support: { - name: t('settingsSupport'), - type: 'string', - }, - title: { - name: t('serverName'), - type: 'string', - }, - description: { - name: t('serverDescription'), - type: 'string', - }, - logo: { - name: t('serverLogo'), - type: 'string', - }, - logoInverted: { - name: t('serverLogoInverted'), - type: 'string', - }, - colorPrimary: { - name: t('serverColorPrimary'), - type: 'string', - subtype: 'color', - }, - colorSecondary: { - name: t('serverColorSecondary'), - type: 'string', - subtype: 'color', - }, - disableChange: { - name: t('serverChangeDisable'), - type: 'boolean', - }, - darkMode: { - name: t('settingsDarkMode'), - type: 'boolean', - }, - totpEnable: { - name: t('settingsTotpEnable'), - type: 'boolean', - }, - totpForce: { - name: t('settingsTotpForce'), - type: 'boolean', - }, - serviceWorkerUpdateInterval: { - name: t('settingsServiceWorkerUpdateInterval'), - type: 'number', - }, - 'ui.disableLoginLanguage': { - name: t('attributeUiDisableLoginLanguage'), - type: 'boolean', - }, - disableShare: { - name: t('serverDisableShare'), - type: 'boolean', - }, -}), [t]); diff --git a/modern/src/common/attributes/useUserAttributes.js b/modern/src/common/attributes/useUserAttributes.js deleted file mode 100644 index 81230884..00000000 --- a/modern/src/common/attributes/useUserAttributes.js +++ /dev/null @@ -1,60 +0,0 @@ -import { useMemo } from 'react'; - -export default (t) => useMemo(() => ({ - telegramChatId: { - name: t('attributeTelegramChatId'), - type: 'string', - }, - pushoverUserKey: { - name: t('attributePushoverUserKey'), - type: 'string', - }, - pushoverDeviceNames: { - name: t('attributePushoverDeviceNames'), - type: 'string', - }, - 'mail.smtp.host': { - name: t('attributeMailSmtpHost'), - type: 'string', - }, - 'mail.smtp.port': { - name: t('attributeMailSmtpPort'), - type: 'number', - }, - 'mail.smtp.starttls.enable': { - name: t('attributeMailSmtpStarttlsEnable'), - type: 'boolean', - }, - 'mail.smtp.starttls.required': { - name: t('attributeMailSmtpStarttlsRequired'), - type: 'boolean', - }, - 'mail.smtp.ssl.enable': { - name: t('attributeMailSmtpSslEnable'), - type: 'boolean', - }, - 'mail.smtp.ssl.trust': { - name: t('attributeMailSmtpSslTrust'), - type: 'string', - }, - 'mail.smtp.ssl.protocols': { - name: t('attributeMailSmtpSslProtocols'), - type: 'string', - }, - 'mail.smtp.from': { - name: t('attributeMailSmtpFrom'), - type: 'string', - }, - 'mail.smtp.auth': { - name: t('attributeMailSmtpAuth'), - type: 'boolean', - }, - 'mail.smtp.username': { - name: t('attributeMailSmtpUsername'), - type: 'string', - }, - 'mail.smtp.password': { - name: t('attributeMailSmtpPassword'), - type: 'string', - }, -}), [t]); diff --git a/modern/src/common/components/AddressValue.jsx b/modern/src/common/components/AddressValue.jsx deleted file mode 100644 index 827a71de..00000000 --- a/modern/src/common/components/AddressValue.jsx +++ /dev/null @@ -1,37 +0,0 @@ -import React, { useEffect, useState } from 'react'; -import { useSelector } from 'react-redux'; -import { Link } from '@mui/material'; -import { useTranslation } from './LocalizationProvider'; -import { useCatch } from '../../reactHelper'; - -const AddressValue = ({ latitude, longitude, originalAddress }) => { - const t = useTranslation(); - - const addressEnabled = useSelector((state) => state.session.server.geocoderEnabled); - - const [address, setAddress] = useState(); - - useEffect(() => { - setAddress(originalAddress); - }, [latitude, longitude, originalAddress]); - - const showAddress = useCatch(async () => { - const query = new URLSearchParams({ latitude, longitude }); - const response = await fetch(`/api/server/geocode?${query.toString()}`); - if (response.ok) { - setAddress(await response.text()); - } else { - throw Error(await response.text()); - } - }); - - if (address) { - return address; - } - if (addressEnabled) { - return ({t('sharedShowAddress')}); - } - return ''; -}; - -export default AddressValue; diff --git a/modern/src/common/components/BottomMenu.jsx b/modern/src/common/components/BottomMenu.jsx deleted file mode 100644 index 07fa2e11..00000000 --- a/modern/src/common/components/BottomMenu.jsx +++ /dev/null @@ -1,135 +0,0 @@ -import React, { useState } from 'react'; -import { useDispatch, useSelector } from 'react-redux'; -import { useNavigate, useLocation } from 'react-router-dom'; -import { - Paper, BottomNavigation, BottomNavigationAction, Menu, MenuItem, Typography, Badge, -} from '@mui/material'; - -import DescriptionIcon from '@mui/icons-material/Description'; -import SettingsIcon from '@mui/icons-material/Settings'; -import MapIcon from '@mui/icons-material/Map'; -import PersonIcon from '@mui/icons-material/Person'; -import ExitToAppIcon from '@mui/icons-material/ExitToApp'; - -import { sessionActions } from '../../store'; -import { useTranslation } from './LocalizationProvider'; -import { useRestriction } from '../util/permissions'; -import { nativePostMessage } from './NativeInterface'; - -const BottomMenu = () => { - const navigate = useNavigate(); - const location = useLocation(); - const dispatch = useDispatch(); - const t = useTranslation(); - - const readonly = useRestriction('readonly'); - const disableReports = useRestriction('disableReports'); - const user = useSelector((state) => state.session.user); - const socket = useSelector((state) => state.session.socket); - - const [anchorEl, setAnchorEl] = useState(null); - - const currentSelection = () => { - if (location.pathname === `/settings/user/${user.id}`) { - return 'account'; - } if (location.pathname.startsWith('/settings')) { - return 'settings'; - } if (location.pathname.startsWith('/reports')) { - return 'reports'; - } if (location.pathname === '/') { - return 'map'; - } - return null; - }; - - const handleAccount = () => { - setAnchorEl(null); - navigate(`/settings/user/${user.id}`); - }; - - const handleLogout = async () => { - setAnchorEl(null); - - const notificationToken = window.localStorage.getItem('notificationToken'); - if (notificationToken && !user.readonly) { - window.localStorage.removeItem('notificationToken'); - const tokens = user.attributes.notificationTokens?.split(',') || []; - if (tokens.includes(notificationToken)) { - const updatedUser = { - ...user, - attributes: { - ...user.attributes, - notificationTokens: tokens.length > 1 ? tokens.filter((it) => it !== notificationToken).join(',') : undefined, - }, - }; - await fetch(`/api/users/${user.id}`, { - method: 'PUT', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify(updatedUser), - }); - } - } - - await fetch('/api/session', { method: 'DELETE' }); - nativePostMessage('logout'); - navigate('/login'); - dispatch(sessionActions.updateUser(null)); - }; - - const handleSelection = (event, value) => { - switch (value) { - case 'map': - navigate('/'); - break; - case 'reports': - navigate('/reports/combined'); - break; - case 'settings': - navigate('/settings/preferences'); - break; - case 'account': - setAnchorEl(event.currentTarget); - break; - case 'logout': - handleLogout(); - break; - default: - break; - } - }; - - return ( - - - - - - )} - value="map" - /> - {!disableReports && ( - } value="reports" /> - )} - } value="settings" /> - {readonly ? ( - } value="logout" /> - ) : ( - } value="account" /> - )} - - setAnchorEl(null)}> - - {t('settingsUser')} - - - {t('loginLogout')} - - - - ); -}; - -export default BottomMenu; diff --git a/modern/src/common/components/DriverValue.js b/modern/src/common/components/DriverValue.js deleted file mode 100644 index 6148b418..00000000 --- a/modern/src/common/components/DriverValue.js +++ /dev/null @@ -1,9 +0,0 @@ -import { useSelector } from 'react-redux'; - -const DriverValue = ({ driverUniqueId }) => { - const driver = useSelector((state) => state.drivers.items[driverUniqueId]); - - return driver?.name || driverUniqueId; -}; - -export default DriverValue; diff --git a/modern/src/common/components/ErrorHandler.jsx b/modern/src/common/components/ErrorHandler.jsx deleted file mode 100644 index 5c9c26d9..00000000 --- a/modern/src/common/components/ErrorHandler.jsx +++ /dev/null @@ -1,27 +0,0 @@ -import { Snackbar, Alert } from '@mui/material'; -import React from 'react'; -import { useDispatch, useSelector } from 'react-redux'; -import { usePrevious } from '../../reactHelper'; -import { errorsActions } from '../../store'; - -const ErrorHandler = () => { - const dispatch = useDispatch(); - - const error = useSelector((state) => state.errors.errors.find(() => true)); - const previousError = usePrevious(error); - - return ( - - dispatch(errorsActions.pop())} - severity="error" - variant="filled" - > - {error || previousError} - - - ); -}; - -export default ErrorHandler; diff --git a/modern/src/common/components/GeofencesValue.js b/modern/src/common/components/GeofencesValue.js deleted file mode 100644 index 4808a8a2..00000000 --- a/modern/src/common/components/GeofencesValue.js +++ /dev/null @@ -1,9 +0,0 @@ -import { useSelector } from 'react-redux'; - -const GeofencesValue = ({ geofenceIds }) => { - const geofences = useSelector((state) => state.geofences.items); - - return geofenceIds.map((id) => geofences[id]?.name).join(', '); -}; - -export default GeofencesValue; diff --git a/modern/src/common/components/LinkField.jsx b/modern/src/common/components/LinkField.jsx deleted file mode 100644 index 08c6213a..00000000 --- a/modern/src/common/components/LinkField.jsx +++ /dev/null @@ -1,93 +0,0 @@ -import { Autocomplete, TextField } from '@mui/material'; -import React, { useState } from 'react'; -import { useEffectAsync } from '../../reactHelper'; - -const LinkField = ({ - label, - endpointAll, - endpointLinked, - baseId, - keyBase, - keyLink, - keyGetter = (item) => item.id, - titleGetter = (item) => item.name, -}) => { - const [active, setActive] = useState(false); - const [open, setOpen] = useState(false); - const [items, setItems] = useState(); - const [linked, setLinked] = useState(); - - useEffectAsync(async () => { - if (active) { - const response = await fetch(endpointAll); - if (response.ok) { - setItems(await response.json()); - } else { - throw Error(await response.text()); - } - } - }, [active]); - - useEffectAsync(async () => { - if (active) { - const response = await fetch(endpointLinked); - if (response.ok) { - setLinked(await response.json()); - } else { - throw Error(await response.text()); - } - } - }, [active]); - - const createBody = (linkId) => { - const body = {}; - body[keyBase] = baseId; - body[keyLink] = linkId; - return body; - }; - - const onChange = async (value) => { - const oldValue = linked.map((it) => keyGetter(it)); - const newValue = value.map((it) => keyGetter(it)); - if (!newValue.find((it) => it < 0)) { - 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)), - })); - }); - 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(value); - } - }; - - return ( - keyGetter(i1) === keyGetter(i2)} - options={items || []} - getOptionLabel={(item) => titleGetter(item)} - renderInput={(params) => } - value={(items && linked) || []} - onChange={(_, value) => onChange(value)} - open={open} - onOpen={() => { - setOpen(true); - setActive(true); - }} - onClose={() => setOpen(false)} - multiple - /> - ); -}; - -export default LinkField; diff --git a/modern/src/common/components/LocalizationProvider.jsx b/modern/src/common/components/LocalizationProvider.jsx deleted file mode 100644 index 4104c773..00000000 --- a/modern/src/common/components/LocalizationProvider.jsx +++ /dev/null @@ -1,187 +0,0 @@ -/* eslint-disable import/no-relative-packages */ -import React, { - createContext, useContext, useEffect, useMemo, -} from 'react'; -import dayjs from 'dayjs'; -import usePersistedState from '../util/usePersistedState'; - -import af from '../../resources/l10n/af.json'; import 'dayjs/locale/af'; -import ar from '../../resources/l10n/ar.json'; import 'dayjs/locale/ar'; -import az from '../../resources/l10n/az.json'; import 'dayjs/locale/az'; -import bg from '../../resources/l10n/bg.json'; import 'dayjs/locale/bg'; -import bn from '../../resources/l10n/bn.json'; import 'dayjs/locale/bn'; -import ca from '../../resources/l10n/ca.json'; import 'dayjs/locale/ca'; -import cs from '../../resources/l10n/cs.json'; import 'dayjs/locale/cs'; -import da from '../../resources/l10n/da.json'; import 'dayjs/locale/da'; -import de from '../../resources/l10n/de.json'; import 'dayjs/locale/de'; -import el from '../../resources/l10n/el.json'; import 'dayjs/locale/el'; -import en from '../../resources/l10n/en.json'; import 'dayjs/locale/en'; -import es from '../../resources/l10n/es.json'; import 'dayjs/locale/es'; -import fa from '../../resources/l10n/fa.json'; import 'dayjs/locale/fa'; -import fi from '../../resources/l10n/fi.json'; import 'dayjs/locale/fi'; -import fr from '../../resources/l10n/fr.json'; import 'dayjs/locale/fr'; -import gl from '../../resources/l10n/gl.json'; import 'dayjs/locale/gl'; -import he from '../../resources/l10n/he.json'; import 'dayjs/locale/he'; -import hi from '../../resources/l10n/hi.json'; import 'dayjs/locale/hi'; -import hr from '../../resources/l10n/hr.json'; import 'dayjs/locale/hr'; -import hu from '../../resources/l10n/hu.json'; import 'dayjs/locale/hu'; -import id from '../../resources/l10n/id.json'; import 'dayjs/locale/id'; -import it from '../../resources/l10n/it.json'; import 'dayjs/locale/it'; -import ja from '../../resources/l10n/ja.json'; import 'dayjs/locale/ja'; -import ka from '../../resources/l10n/ka.json'; import 'dayjs/locale/ka'; -import kk from '../../resources/l10n/kk.json'; import 'dayjs/locale/kk'; -import km from '../../resources/l10n/km.json'; import 'dayjs/locale/km'; -import ko from '../../resources/l10n/ko.json'; import 'dayjs/locale/ko'; -import lo from '../../resources/l10n/lo.json'; import 'dayjs/locale/lo'; -import lt from '../../resources/l10n/lt.json'; import 'dayjs/locale/lt'; -import lv from '../../resources/l10n/lv.json'; import 'dayjs/locale/lv'; -import mk from '../../resources/l10n/mk.json'; import 'dayjs/locale/mk'; -import ml from '../../resources/l10n/ml.json'; import 'dayjs/locale/ml'; -import mn from '../../resources/l10n/mn.json'; import 'dayjs/locale/mn'; -import ms from '../../resources/l10n/ms.json'; import 'dayjs/locale/ms'; -import nb from '../../resources/l10n/nb.json'; import 'dayjs/locale/nb'; -import ne from '../../resources/l10n/ne.json'; import 'dayjs/locale/ne'; -import nl from '../../resources/l10n/nl.json'; import 'dayjs/locale/nl'; -import nn from '../../resources/l10n/nn.json'; import 'dayjs/locale/nn'; -import pl from '../../resources/l10n/pl.json'; import 'dayjs/locale/pl'; -import pt from '../../resources/l10n/pt.json'; import 'dayjs/locale/pt'; -import ptBR from '../../resources/l10n/pt_BR.json'; import 'dayjs/locale/pt-br'; -import ro from '../../resources/l10n/ro.json'; import 'dayjs/locale/ro'; -import ru from '../../resources/l10n/ru.json'; import 'dayjs/locale/ru'; -import si from '../../resources/l10n/si.json'; import 'dayjs/locale/si'; -import sk from '../../resources/l10n/sk.json'; import 'dayjs/locale/sk'; -import sl from '../../resources/l10n/sl.json'; import 'dayjs/locale/sl'; -import sq from '../../resources/l10n/sq.json'; import 'dayjs/locale/sq'; -import sr from '../../resources/l10n/sr.json'; import 'dayjs/locale/sr'; -import sv from '../../resources/l10n/sv.json'; import 'dayjs/locale/sv'; -import ta from '../../resources/l10n/ta.json'; import 'dayjs/locale/ta'; -import th from '../../resources/l10n/th.json'; import 'dayjs/locale/th'; -import tr from '../../resources/l10n/tr.json'; import 'dayjs/locale/tr'; -import uk from '../../resources/l10n/uk.json'; import 'dayjs/locale/uk'; -import uz from '../../resources/l10n/uz.json'; import 'dayjs/locale/uz'; -import vi from '../../resources/l10n/vi.json'; import 'dayjs/locale/vi'; -import zh from '../../resources/l10n/zh.json'; import 'dayjs/locale/zh'; -import zhTW from '../../resources/l10n/zh_TW.json'; import 'dayjs/locale/zh-tw'; - -const languages = { - af: { data: af, country: 'ZA', name: 'Afrikaans' }, - ar: { data: ar, country: 'AE', name: 'العربية' }, - az: { data: az, country: 'AZ', name: 'Azərbaycanca' }, - bg: { data: bg, country: 'BG', name: 'Български' }, - bn: { data: bn, country: 'IN', name: 'বাংলা' }, - ca: { data: ca, country: 'ES', name: 'Català' }, - cs: { data: cs, country: 'CZ', name: 'Čeština' }, - de: { data: de, country: 'DE', name: 'Deutsch' }, - da: { data: da, country: 'DK', name: 'Dansk' }, - el: { data: el, country: 'GR', name: 'Ελληνικά' }, - en: { data: en, country: 'US', name: 'English' }, - es: { data: es, country: 'ES', name: 'Español' }, - fa: { data: fa, country: 'IR', name: 'فارسی' }, - fi: { data: fi, country: 'FI', name: 'Suomi' }, - fr: { data: fr, country: 'FR', name: 'Français' }, - gl: { data: gl, country: 'ES', name: 'Galego' }, - he: { data: he, country: 'IL', name: 'עברית' }, - hi: { data: hi, country: 'IN', name: 'हिन्दी' }, - hr: { data: hr, country: 'HR', name: 'Hrvatski' }, - hu: { data: hu, country: 'HU', name: 'Magyar' }, - id: { data: id, country: 'ID', name: 'Bahasa Indonesia' }, - it: { data: it, country: 'IT', name: 'Italiano' }, - ja: { data: ja, country: 'JP', name: '日本語' }, - ka: { data: ka, country: 'GE', name: 'ქართული' }, - kk: { data: kk, country: 'KZ', name: 'Қазақша' }, - ko: { data: ko, country: 'KR', name: '한국어' }, - km: { data: km, country: 'KH', name: 'ភាសាខ្មែរ' }, - lo: { data: lo, country: 'LA', name: 'ລາວ' }, - lt: { data: lt, country: 'LT', name: 'Lietuvių' }, - lv: { data: lv, country: 'LV', name: 'Latviešu' }, - mk: { data: mk, country: 'MK', name: 'Mакедонски' }, - ml: { data: ml, country: 'IN', name: 'മലയാളം' }, - mn: { data: mn, country: 'MN', name: 'Монгол хэл' }, - ms: { data: ms, country: 'MY', name: 'بهاس ملايو' }, - nb: { data: nb, country: 'NO', name: 'Norsk bokmål' }, - ne: { data: ne, country: 'NP', name: 'नेपाली' }, - nl: { data: nl, country: 'NL', name: 'Nederlands' }, - nn: { data: nn, country: 'NO', name: 'Norsk nynorsk' }, - pl: { data: pl, country: 'PL', name: 'Polski' }, - pt: { data: pt, country: 'PT', name: 'Português' }, - ptBR: { data: ptBR, country: 'BR', name: 'Português (Brasil)' }, - ro: { data: ro, country: 'RO', name: 'Română' }, - ru: { data: ru, country: 'RU', name: 'Русский' }, - si: { data: si, country: 'LK', name: 'සිංහල' }, - sk: { data: sk, country: 'SK', name: 'Slovenčina' }, - sl: { data: sl, country: 'SI', name: 'Slovenščina' }, - sq: { data: sq, country: 'AL', name: 'Shqipëria' }, - sr: { data: sr, country: 'RS', name: 'Srpski' }, - sv: { data: sv, country: 'SE', name: 'Svenska' }, - ta: { data: ta, country: 'IN', name: 'தமிழ்' }, - th: { data: th, country: 'TH', name: 'ไทย' }, - tr: { data: tr, country: 'TR', name: 'Türkçe' }, - uk: { data: uk, country: 'UA', name: 'Українська' }, - uz: { data: uz, country: 'UZ', name: 'Oʻzbekcha' }, - vi: { data: vi, country: 'VN', name: 'Tiếng Việt' }, - zh: { data: zh, country: 'CN', name: '中文' }, - zhTW: { data: zhTW, country: 'TW', name: '中文 (Taiwan)' }, -}; - -const getDefaultLanguage = () => { - const browserLanguages = window.navigator.languages ? window.navigator.languages.slice() : []; - const browserLanguage = window.navigator.userLanguage || window.navigator.language; - browserLanguages.push(browserLanguage); - browserLanguages.push(browserLanguage.substring(0, 2)); - - for (let i = 0; i < browserLanguages.length; i += 1) { - let language = browserLanguages[i].replace('-', ''); - if (language in languages) { - return language; - } - if (language.length > 2) { - language = language.substring(0, 2); - if (language in languages) { - return language; - } - } - } - return 'en'; -}; - -const LocalizationContext = createContext({ - languages, - language: 'en', - setLanguage: () => {}, -}); - -export const LocalizationProvider = ({ children }) => { - const [language, setLanguage] = usePersistedState('language', getDefaultLanguage()); - - const value = useMemo(() => ({ languages, language, setLanguage }), [languages, language, setLanguage]); - - useEffect(() => { - let selected; - if (language.length > 2) { - selected = `${language.slice(0, 2)}-${language.slice(-2).toLowerCase()}`; - } else { - selected = language; - } - dayjs.locale(selected); - }, [language]); - - return ( - - {children} - - ); -}; - -export const useLocalization = () => useContext(LocalizationContext); - -export const useTranslation = () => { - const context = useContext(LocalizationContext); - const { data } = context.languages[context.language]; - return useMemo(() => (key) => data[key], [data]); -}; - -export const useTranslationKeys = (predicate) => { - const context = useContext(LocalizationContext); - const { data } = context.languages[context.language]; - return Object.keys(data).filter(predicate); -}; diff --git a/modern/src/common/components/NativeInterface.js b/modern/src/common/components/NativeInterface.js deleted file mode 100644 index b088de0e..00000000 --- a/modern/src/common/components/NativeInterface.js +++ /dev/null @@ -1,72 +0,0 @@ -import { useEffect, useState } from 'react'; -import { useDispatch, useSelector } from 'react-redux'; -import { useEffectAsync } from '../../reactHelper'; -import { sessionActions } from '../../store'; - -export const nativeEnvironment = window.appInterface || (window.webkit && window.webkit.messageHandlers.appInterface); - -export const nativePostMessage = (message) => { - if (window.webkit && window.webkit.messageHandlers.appInterface) { - window.webkit.messageHandlers.appInterface.postMessage(message); - } - if (window.appInterface) { - window.appInterface.postMessage(message); - } -}; - -export const handleLoginTokenListeners = new Set(); -window.handleLoginToken = (token) => { - handleLoginTokenListeners.forEach((listener) => listener(token)); -}; - -const updateNotificationTokenListeners = new Set(); -window.updateNotificationToken = (token) => { - updateNotificationTokenListeners.forEach((listener) => listener(token)); -}; - -const NativeInterface = () => { - const dispatch = useDispatch(); - - const user = useSelector((state) => state.session.user); - const [notificationToken, setNotificationToken] = useState(null); - - useEffect(() => { - const listener = (token) => setNotificationToken(token); - updateNotificationTokenListeners.add(listener); - return () => updateNotificationTokenListeners.delete(listener); - }, [setNotificationToken]); - - useEffectAsync(async () => { - if (user && !user.readonly && notificationToken) { - window.localStorage.setItem('notificationToken', notificationToken); - setNotificationToken(null); - - const tokens = user.attributes.notificationTokens?.split(',') || []; - if (!tokens.includes(notificationToken)) { - const updatedUser = { - ...user, - attributes: { - ...user.attributes, - notificationTokens: [...tokens.slice(-2), notificationToken].join(','), - }, - }; - - const response = await fetch(`/api/users/${user.id}`, { - method: 'PUT', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify(updatedUser), - }); - - if (response.ok) { - dispatch(sessionActions.updateUser(await response.json())); - } else { - throw Error(await response.text()); - } - } - } - }, [user, notificationToken, setNotificationToken]); - - return null; -}; - -export default NativeInterface; diff --git a/modern/src/common/components/NavBar.jsx b/modern/src/common/components/NavBar.jsx deleted file mode 100644 index a53960fd..00000000 --- a/modern/src/common/components/NavBar.jsx +++ /dev/null @@ -1,25 +0,0 @@ -import React from 'react'; -import { - AppBar, Toolbar, Typography, IconButton, -} from '@mui/material'; -import MenuIcon from '@mui/icons-material/Menu'; - -const Navbar = ({ setOpenDrawer, title }) => ( - - - setOpenDrawer(true)} - > - - - - {title} - - - -); - -export default Navbar; diff --git a/modern/src/common/components/PageLayout.jsx b/modern/src/common/components/PageLayout.jsx deleted file mode 100644 index e81c9754..00000000 --- a/modern/src/common/components/PageLayout.jsx +++ /dev/null @@ -1,118 +0,0 @@ -import React, { useState } from 'react'; -import { - AppBar, - Breadcrumbs, - Divider, - Drawer, - IconButton, - Toolbar, - Typography, - useMediaQuery, - useTheme, -} from '@mui/material'; -import makeStyles from '@mui/styles/makeStyles'; -import ArrowBackIcon from '@mui/icons-material/ArrowBack'; -import MenuIcon from '@mui/icons-material/Menu'; -import { useNavigate } from 'react-router-dom'; -import { useTranslation } from './LocalizationProvider'; - -const useStyles = makeStyles((theme) => ({ - desktopRoot: { - height: '100%', - display: 'flex', - }, - mobileRoot: { - height: '100%', - display: 'flex', - flexDirection: 'column', - }, - desktopDrawer: { - width: theme.dimensions.drawerWidthDesktop, - }, - mobileDrawer: { - width: theme.dimensions.drawerWidthTablet, - }, - mobileToolbar: { - zIndex: 1, - }, - content: { - flexGrow: 1, - alignItems: 'stretch', - display: 'flex', - flexDirection: 'column', - overflowY: 'auto', - }, -})); - -const PageTitle = ({ breadcrumbs }) => { - const theme = useTheme(); - const t = useTranslation(); - - const desktop = useMediaQuery(theme.breakpoints.up('md')); - - if (desktop) { - return ( - {t(breadcrumbs[0])} - ); - } - return ( - - {breadcrumbs.slice(0, -1).map((breadcrumb) => ( - {t(breadcrumb)} - ))} - {t(breadcrumbs[breadcrumbs.length - 1])} - - ); -}; - -const PageLayout = ({ menu, breadcrumbs, children }) => { - const classes = useStyles(); - const theme = useTheme(); - const navigate = useNavigate(); - - const desktop = useMediaQuery(theme.breakpoints.up('md')); - - const [openDrawer, setOpenDrawer] = useState(false); - - return desktop ? ( -
- - - navigate('/')}> - - - - - - {menu} - -
{children}
-
- ) : ( -
- setOpenDrawer(false)} - classes={{ paper: classes.mobileDrawer }} - > - {menu} - - - - setOpenDrawer(true)}> - - - - - -
{children}
-
- ); -}; - -export default PageLayout; diff --git a/modern/src/common/components/PositionValue.jsx b/modern/src/common/components/PositionValue.jsx deleted file mode 100644 index b1f8f656..00000000 --- a/modern/src/common/components/PositionValue.jsx +++ /dev/null @@ -1,133 +0,0 @@ -import React from 'react'; -import { useSelector } from 'react-redux'; -import { Link } from '@mui/material'; -import { Link as RouterLink } from 'react-router-dom'; -import { - formatAlarm, - formatAltitude, - formatBoolean, - formatCoordinate, - formatCourse, - formatDistance, - formatNumber, - formatNumericHours, - formatPercentage, - formatSpeed, - formatTime, - formatTemperature, - formatVoltage, - formatVolume, - formatConsumption, -} from '../util/formatter'; -import { speedToKnots } from '../util/converter'; -import { useAttributePreference, usePreference } from '../util/preferences'; -import { useTranslation } from './LocalizationProvider'; -import { useAdministrator } from '../util/permissions'; -import AddressValue from './AddressValue'; -import GeofencesValue from './GeofencesValue'; -import DriverValue from './DriverValue'; - -const PositionValue = ({ position, property, attribute }) => { - const t = useTranslation(); - - const admin = useAdministrator(); - - const device = useSelector((state) => state.devices.items[position.deviceId]); - - const key = property || attribute; - const value = property ? position[property] : position.attributes[attribute]; - - const distanceUnit = useAttributePreference('distanceUnit'); - const altitudeUnit = useAttributePreference('altitudeUnit'); - 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); - case 'latitude': - return formatCoordinate('latitude', value, coordinateFormat); - case 'longitude': - return formatCoordinate('longitude', value, coordinateFormat); - case 'speed': - return value != null ? formatSpeed(value, speedUnit, t) : ''; - case 'obdSpeed': - return value != null ? formatSpeed(speedToKnots(value, 'kmh'), speedUnit, t) : ''; - case 'course': - return formatCourse(value); - case 'altitude': - return formatAltitude(value, altitudeUnit, t); - case 'power': - case 'battery': - return formatVoltage(value, t); - case 'batteryLevel': - return value != null ? formatPercentage(value, t) : ''; - case 'volume': - return value != null ? formatVolume(value, volumeUnit, t) : ''; - case 'fuelConsumption': - return value != null ? formatConsumption(value, t) : ''; - case 'coolantTemp': - return formatTemperature(value); - case 'alarm': - return formatAlarm(value, t); - case 'odometer': - case 'serviceOdometer': - case 'tripOdometer': - case 'obdOdometer': - case 'distance': - case 'totalDistance': - return value != null ? formatDistance(value, distanceUnit, t) : ''; - case 'hours': - return value != null ? formatNumericHours(value, t) : ''; - default: - if (typeof value === 'number') { - return formatNumber(value); - } if (typeof value === 'boolean') { - return formatBoolean(value, t); - } - return value || ''; - } - }; - - switch (key) { - case 'image': - case 'video': - case 'audio': - return {value}; - case 'totalDistance': - case 'hours': - return ( - <> - {formatValue(value)} -    - {admin && ⚙} - - ); - case 'address': - return ; - case 'network': - if (value) { - return {t('sharedInfoTitle')}; - } - return ''; - case 'geofenceIds': - if (value) { - return ; - } - return ''; - case 'driverUniqueId': - if (value) { - return ; - } - return ''; - default: - return formatValue(value); - } -}; - -export default PositionValue; diff --git a/modern/src/common/components/RemoveDialog.jsx b/modern/src/common/components/RemoveDialog.jsx deleted file mode 100644 index 0f4254a8..00000000 --- a/modern/src/common/components/RemoveDialog.jsx +++ /dev/null @@ -1,54 +0,0 @@ -import React from 'react'; -import Button from '@mui/material/Button'; -import { Snackbar } from '@mui/material'; -import makeStyles from '@mui/styles/makeStyles'; -import { useTranslation } from './LocalizationProvider'; -import { useCatch } from '../../reactHelper'; -import { snackBarDurationLongMs } from '../util/duration'; - -const useStyles = makeStyles((theme) => ({ - root: { - [theme.breakpoints.down('md')]: { - bottom: `calc(${theme.dimensions.bottomBarHeight}px + ${theme.spacing(1)})`, - }, - }, - button: { - height: 'auto', - marginTop: 0, - marginBottom: 0, - color: theme.palette.error.main, - }, -})); - -const RemoveDialog = ({ - open, endpoint, itemId, onResult, -}) => { - const classes = useStyles(); - const t = useTranslation(); - - const handleRemove = useCatch(async () => { - const response = await fetch(`/api/${endpoint}/${itemId}`, { method: 'DELETE' }); - if (response.ok) { - onResult(true); - } else { - throw Error(await response.text()); - } - }); - - return ( - onResult(false)} - message={t('sharedRemoveConfirm')} - action={( - - )} - /> - ); -}; - -export default RemoveDialog; diff --git a/modern/src/common/components/SelectField.jsx b/modern/src/common/components/SelectField.jsx deleted file mode 100644 index db8c30b0..00000000 --- a/modern/src/common/components/SelectField.jsx +++ /dev/null @@ -1,77 +0,0 @@ -import { - FormControl, InputLabel, MenuItem, Select, Autocomplete, TextField, -} from '@mui/material'; -import React, { useState } from 'react'; -import { useEffectAsync } from '../../reactHelper'; - -const SelectField = ({ - label, - fullWidth, - multiple, - value = null, - emptyValue = null, - emptyTitle = '', - onChange, - endpoint, - data, - keyGetter = (item) => item.id, - titleGetter = (item) => item.name, -}) => { - const [items, setItems] = useState(data); - - const getOptionLabel = (option) => { - if (typeof option !== 'object') { - option = items.find((obj) => keyGetter(obj) === option); - } - return option ? titleGetter(option) : emptyTitle; - }; - - useEffectAsync(async () => { - if (endpoint) { - const response = await fetch(endpoint); - if (response.ok) { - setItems(await response.json()); - } else { - throw Error(await response.text()); - } - } - }, []); - - if (items) { - return ( - - {multiple ? ( - <> - {label} - - - ) : ( - ( - {titleGetter(option)} - )} - isOptionEqualToValue={(option, value) => keyGetter(option) === value} - value={value} - onChange={(_, value) => onChange({ target: { value: value ? keyGetter(value) : emptyValue } })} - renderInput={(params) => } - /> - )} - - ); - } - return null; -}; - -export default SelectField; diff --git a/modern/src/common/components/SideNav.jsx b/modern/src/common/components/SideNav.jsx deleted file mode 100644 index 97968bd1..00000000 --- a/modern/src/common/components/SideNav.jsx +++ /dev/null @@ -1,33 +0,0 @@ -import React, { Fragment } from 'react'; -import { - List, ListItemText, ListItemIcon, Divider, ListSubheader, ListItemButton, -} from '@mui/material'; -import { Link, useLocation } from 'react-router-dom'; - -const SideNav = ({ routes }) => { - const location = useLocation(); - - return ( - - {routes.map((route) => (route.subheader ? ( - - - {route.subheader} - - ) : ( - - {route.icon} - - - )))} - - ); -}; - -export default SideNav; diff --git a/modern/src/common/components/SplitButton.jsx b/modern/src/common/components/SplitButton.jsx deleted file mode 100644 index 84876f15..00000000 --- a/modern/src/common/components/SplitButton.jsx +++ /dev/null @@ -1,48 +0,0 @@ -import React, { useRef, useState } from 'react'; -import { - Button, ButtonGroup, Menu, MenuItem, Typography, -} from '@mui/material'; -import ArrowDropDownIcon from '@mui/icons-material/ArrowDropDown'; - -const SplitButton = ({ - fullWidth, variant, color, disabled, onClick, options, selected, setSelected, -}) => { - const anchorRef = useRef(); - const [menuAnchorEl, setMenuAnchorEl] = useState(null); - - return ( - <> - - - - - setMenuAnchorEl(null)} - anchorOrigin={{ - vertical: 'bottom', - horizontal: 'right', - }} - > - {Object.entries(options).map(([key, value]) => ( - { - setSelected(key); - setMenuAnchorEl(null); - }} - > - {value} - - ))} - - - ); -}; - -export default SplitButton; diff --git a/modern/src/common/components/StatusCard.jsx b/modern/src/common/components/StatusCard.jsx deleted file mode 100644 index a63d0f80..00000000 --- a/modern/src/common/components/StatusCard.jsx +++ /dev/null @@ -1,288 +0,0 @@ -import React, { useState } from 'react'; -import { useDispatch, useSelector } from 'react-redux'; -import { useNavigate } from 'react-router-dom'; -import Draggable from 'react-draggable'; -import { - Card, - CardContent, - Typography, - CardActions, - IconButton, - Table, - TableBody, - TableRow, - TableCell, - Menu, - MenuItem, - CardMedia, -} from '@mui/material'; -import makeStyles from '@mui/styles/makeStyles'; -import CloseIcon from '@mui/icons-material/Close'; -import ReplayIcon from '@mui/icons-material/Replay'; -import PublishIcon from '@mui/icons-material/Publish'; -import EditIcon from '@mui/icons-material/Edit'; -import DeleteIcon from '@mui/icons-material/Delete'; -import PendingIcon from '@mui/icons-material/Pending'; - -import { useTranslation } from './LocalizationProvider'; -import RemoveDialog from './RemoveDialog'; -import PositionValue from './PositionValue'; -import { useDeviceReadonly } from '../util/permissions'; -import usePositionAttributes from '../attributes/usePositionAttributes'; -import { devicesActions } from '../../store'; -import { useCatch, useCatchCallback } from '../../reactHelper'; -import { useAttributePreference } from '../util/preferences'; - -const useStyles = makeStyles((theme) => ({ - card: { - pointerEvents: 'auto', - width: theme.dimensions.popupMaxWidth, - }, - media: { - height: theme.dimensions.popupImageHeight, - display: 'flex', - justifyContent: 'flex-end', - alignItems: 'flex-start', - }, - mediaButton: { - color: theme.palette.primary.contrastText, - mixBlendMode: 'difference', - }, - header: { - display: 'flex', - justifyContent: 'space-between', - alignItems: 'center', - padding: theme.spacing(1, 1, 0, 2), - }, - content: { - paddingTop: theme.spacing(1), - paddingBottom: theme.spacing(1), - maxHeight: theme.dimensions.cardContentMaxHeight, - overflow: 'auto', - }, - delete: { - color: theme.palette.error.main, - }, - icon: { - width: '25px', - height: '25px', - filter: 'brightness(0) invert(1)', - }, - table: { - '& .MuiTableCell-sizeSmall': { - paddingLeft: 0, - paddingRight: 0, - }, - }, - cell: { - borderBottom: 'none', - }, - actions: { - justifyContent: 'space-between', - }, - root: ({ desktopPadding }) => ({ - pointerEvents: 'none', - position: 'fixed', - zIndex: 5, - left: '50%', - [theme.breakpoints.up('md')]: { - left: `calc(50% + ${desktopPadding} / 2)`, - bottom: theme.spacing(3), - }, - [theme.breakpoints.down('md')]: { - left: '50%', - bottom: `calc(${theme.spacing(3)} + ${theme.dimensions.bottomBarHeight}px)`, - }, - transform: 'translateX(-50%)', - }), -})); - -const StatusRow = ({ name, content }) => { - const classes = useStyles(); - - return ( - - - {name} - - - {content} - - - ); -}; - -const StatusCard = ({ deviceId, position, onClose, disableActions, desktopPadding = 0 }) => { - const classes = useStyles({ desktopPadding }); - const navigate = useNavigate(); - const dispatch = useDispatch(); - const t = useTranslation(); - - const deviceReadonly = useDeviceReadonly(); - - const shareDisabled = useSelector((state) => state.session.server.attributes.disableShare); - const user = useSelector((state) => state.session.user); - const device = useSelector((state) => state.devices.items[deviceId]); - - const deviceImage = device?.attributes?.deviceImage; - - const positionAttributes = usePositionAttributes(t); - const positionItems = useAttributePreference('positionItems', 'speed,address,totalDistance,course'); - - const [anchorEl, setAnchorEl] = useState(null); - - const [removing, setRemoving] = useState(false); - - const handleRemove = useCatch(async (removed) => { - if (removed) { - const response = await fetch('/api/devices'); - if (response.ok) { - dispatch(devicesActions.refresh(await response.json())); - } else { - throw Error(await response.text()); - } - } - setRemoving(false); - }); - - const handleGeofence = useCatchCallback(async () => { - const newItem = { - name: t('sharedGeofence'), - area: `CIRCLE (${position.latitude} ${position.longitude}, 50)`, - }; - const response = await fetch('/api/geofences', { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify(newItem), - }); - if (response.ok) { - const item = await response.json(); - const permissionResponse = await fetch('/api/permissions', { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ deviceId: position.deviceId, geofenceId: item.id }), - }); - if (!permissionResponse.ok) { - throw Error(await permissionResponse.text()); - } - navigate(`/settings/geofence/${item.id}`); - } else { - throw Error(await response.text()); - } - }, [navigate, position]); - - return ( - <> -
- {device && ( - - - {deviceImage ? ( - - - - - - ) : ( -
- - {device.name} - - - - -
- )} - {position && ( - - - - {positionItems.split(',').filter((key) => position.hasOwnProperty(key) || position.attributes.hasOwnProperty(key)).map((key) => ( - - )} - /> - ))} - -
-
- )} - - setAnchorEl(e.currentTarget)} - disabled={!position} - > - - - navigate('/replay')} - disabled={disableActions || !position} - > - - - navigate(`/settings/device/${deviceId}/command`)} - disabled={disableActions} - > - - - navigate(`/settings/device/${deviceId}`)} - disabled={disableActions || deviceReadonly} - > - - - setRemoving(true)} - disabled={disableActions || deviceReadonly} - className={classes.delete} - > - - - -
-
- )} -
- {position && ( - setAnchorEl(null)}> - navigate(`/position/${position.id}`)}>{t('sharedShowDetails')} - {t('sharedCreateGeofence')} - {t('linkGoogleMaps')} - {t('linkAppleMaps')} - {t('linkStreetView')} - {!shareDisabled && !user.temporary && navigate(`/settings/device/${deviceId}/share`)}>{t('deviceShare')}} - - )} - handleRemove(removed)} - /> - - ); -}; - -export default StatusCard; diff --git a/modern/src/common/components/TableShimmer.jsx b/modern/src/common/components/TableShimmer.jsx deleted file mode 100644 index 08a984a4..00000000 --- a/modern/src/common/components/TableShimmer.jsx +++ /dev/null @@ -1,17 +0,0 @@ -import React from 'react'; -import { Skeleton, TableCell, TableRow } from '@mui/material'; - -const TableShimmer = ({ columns, startAction, endAction }) => [...Array(3)].map((_, i) => ( - - {[...Array(columns)].map((_, j) => { - const action = (startAction && j === 0) || (endAction && j === columns - 1); - return ( - - {!action && } - - ); - })} - -)); - -export default TableShimmer; diff --git a/modern/src/common/theme/components.js b/modern/src/common/theme/components.js deleted file mode 100644 index 56a2ac75..00000000 --- a/modern/src/common/theme/components.js +++ /dev/null @@ -1,40 +0,0 @@ -export default { - MuiUseMediaQuery: { - defaultProps: { - noSsr: true, - }, - }, - MuiOutlinedInput: { - styleOverrides: { - root: ({ theme }) => ({ - backgroundColor: theme.palette.background.default, - }), - }, - }, - MuiButton: { - styleOverrides: { - sizeMedium: { - height: '40px', - }, - }, - }, - MuiFormControl: { - defaultProps: { - size: 'small', - }, - }, - MuiSnackbar: { - defaultProps: { - anchorOrigin: { - vertical: 'bottom', - horizontal: 'center', - }, - }, - }, - MuiTooltip: { - defaultProps: { - enterDelay: 500, - enterNextDelay: 500, - }, - }, -}; diff --git a/modern/src/common/theme/dimensions.js b/modern/src/common/theme/dimensions.js deleted file mode 100644 index 4930803a..00000000 --- a/modern/src/common/theme/dimensions.js +++ /dev/null @@ -1,14 +0,0 @@ -export default { - sidebarWidth: '28%', - sidebarWidthTablet: '52px', - drawerWidthDesktop: '360px', - drawerWidthTablet: '320px', - drawerHeightPhone: '250px', - filterFormWidth: '160px', - eventsDrawerWidth: '320px', - bottomBarHeight: 56, - popupMapOffset: 300, - popupMaxWidth: 288, - popupImageHeight: 144, - cardContentMaxHeight: '40vh', -}; diff --git a/modern/src/common/theme/index.js b/modern/src/common/theme/index.js deleted file mode 100644 index e8ce698b..00000000 --- a/modern/src/common/theme/index.js +++ /dev/null @@ -1,11 +0,0 @@ -import { useMemo } from 'react'; -import { createTheme } from '@mui/material/styles'; -import palette from './palette'; -import dimensions from './dimensions'; -import components from './components'; - -export default (server, darkMode) => useMemo(() => createTheme({ - palette: palette(server, darkMode), - dimensions, - components, -}), [server, darkMode]); diff --git a/modern/src/common/theme/palette.js b/modern/src/common/theme/palette.js deleted file mode 100644 index f32ed93e..00000000 --- a/modern/src/common/theme/palette.js +++ /dev/null @@ -1,22 +0,0 @@ -import { grey, green, indigo } from '@mui/material/colors'; - -const validatedColor = (color) => (/^#([0-9A-Fa-f]{3}){1,2}$/.test(color) ? color : null); - -export default (server, darkMode) => ({ - mode: darkMode ? 'dark' : 'light', - background: { - default: darkMode ? grey[900] : grey[50], - }, - primary: { - main: validatedColor(server?.attributes?.colorPrimary) || (darkMode ? indigo[200] : indigo[900]), - }, - secondary: { - main: validatedColor(server?.attributes?.colorSecondary) || (darkMode ? green[200] : green[800]), - }, - neutral: { - main: grey[500], - }, - geometry: { - main: '#3bb2d0', - }, -}); diff --git a/modern/src/common/util/converter.js b/modern/src/common/util/converter.js deleted file mode 100644 index cb21566b..00000000 --- a/modern/src/common/util/converter.js +++ /dev/null @@ -1,107 +0,0 @@ -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 altitudeConverter = (unit) => { - switch (unit) { - case 'ft': - return 3.28084; - case 'm': - default: - return 1; - } -}; - -export const altitudeUnitString = (unit, t) => { - switch (unit) { - case 'ft': - return t('sharedFeet'); - case 'm': - default: - return t('sharedMeters'); - } -}; - -export const altitudeFromMeters = (value, unit) => value * altitudeConverter(unit); - -export const altitudeToMeters = (value, unit) => value / altitudeConverter(unit); - -const volumeConverter = (unit) => { - switch (unit) { - case 'impGal': - return 4.546; - case 'usGal': - return 3.785; - case 'ltr': - default: - return 1; - } -}; - -export const volumeUnitString = (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 deleted file mode 100644 index a991e505..00000000 --- a/modern/src/common/util/deviceCategories.js +++ /dev/null @@ -1,24 +0,0 @@ -export default [ - 'default', - 'animal', - 'bicycle', - 'boat', - 'bus', - 'car', - 'camper', - '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 deleted file mode 100644 index aae74868..00000000 --- a/modern/src/common/util/duration.js +++ /dev/null @@ -1,2 +0,0 @@ -export const snackBarDurationShortMs = 1500; -export const snackBarDurationLongMs = 2750; diff --git a/modern/src/common/util/formatter.js b/modern/src/common/util/formatter.js deleted file mode 100644 index 7b7fc96d..00000000 --- a/modern/src/common/util/formatter.js +++ /dev/null @@ -1,143 +0,0 @@ -import dayjs from 'dayjs'; -import duration from 'dayjs/plugin/duration'; -import relativeTime from 'dayjs/plugin/relativeTime'; - -import { - altitudeFromMeters, - altitudeUnitString, - distanceFromMeters, - distanceUnitString, - speedFromKnots, - speedUnitString, - volumeFromLiters, - volumeUnitString, -} from './converter'; -import { prefixString } from './stringUtils'; - -dayjs.extend(duration); -dayjs.extend(relativeTime); - -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 formatTemperature = (value) => `${value}°C`; - -export const formatVoltage = (value, t) => `${value} ${t('sharedVoltAbbreviation')}`; - -export const formatConsumption = (value, t) => `${value} ${t('sharedLiterPerHourAbbreviation')}`; - -export const formatTime = (value, format, hours12) => { - if (value) { - const d = dayjs(value); - switch (format) { - case 'date': - return d.format('YYYY-MM-DD'); - case 'time': - return d.format(hours12 ? 'hh:mm:ss A' : 'HH:mm:ss'); - case 'minutes': - return d.format(hours12 ? 'YYYY-MM-DD hh:mm A' : 'YYYY-MM-DD HH:mm'); - default: - return d.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)) : ''); - -export const formatCourse = (value) => { - const courseValues = ['\u2191', '\u2197', '\u2192', '\u2198', '\u2193', '\u2199', '\u2190', '\u2196']; - let normalizedValue = (value + 45 / 2) % 360; - if (normalizedValue < 0) { - normalizedValue += 360; - } - return courseValues[Math.floor(normalizedValue / 45)]; -}; - -export const formatDistance = (value, unit, t) => `${distanceFromMeters(value, unit).toFixed(2)} ${distanceUnitString(unit, t)}`; - -export const formatAltitude = (value, unit, t) => `${altitudeFromMeters(value, unit).toFixed(2)} ${altitudeUnitString(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 formatNumericHours = (value, t) => { - const hours = Math.floor(value / 3600000); - const minutes = Math.floor((value % 3600000) / 60000); - return `${hours} ${t('sharedHourAbbreviation')} ${minutes} ${t('sharedMinuteAbbreviation')}`; -}; - -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 'success'; - case 'offline': - return 'error'; - case 'unknown': - default: - return 'neutral'; - } -}; - -export const getBatteryStatus = (batteryLevel) => { - if (batteryLevel >= 70) { - return 'success'; - } - if (batteryLevel > 30) { - return 'warning'; - } - return 'error'; -}; - -export const formatNotificationTitle = (t, notification, includeId) => { - let title = t(prefixString('event', notification.type)); - if (notification.type === 'alarm') { - const alarmString = notification.attributes.alarms; - if (alarmString) { - const alarms = alarmString.split(','); - if (alarms.length > 1) { - title += ` (${alarms.length})`; - } else { - title += ` ${formatAlarm(alarms[0], t)}`; - } - } - } - if (includeId) { - title += ` [${notification.id}]`; - } - return title; -}; diff --git a/modern/src/common/util/permissions.js b/modern/src/common/util/permissions.js deleted file mode 100644 index 8a63b5a1..00000000 --- a/modern/src/common/util/permissions.js +++ /dev/null @@ -1,28 +0,0 @@ -import { useSelector } from 'react-redux'; - -export const useAdministrator = () => useSelector((state) => { - const admin = state.session.user.administrator; - return admin; -}); - -export const useManager = () => useSelector((state) => { - const admin = state.session.user.administrator; - const manager = (state.session.user.userLimit || 0) !== 0; - return admin || manager; -}); - -export const useDeviceReadonly = () => useSelector((state) => { - const admin = state.session.user.administrator; - const serverReadonly = state.session.server.readonly; - const userReadonly = state.session.user.readonly; - const serverDeviceReadonly = state.session.server.deviceReadonly; - const userDeviceReadonly = state.session.user.deviceReadonly; - return !admin && (serverReadonly || userReadonly || serverDeviceReadonly || userDeviceReadonly); -}); - -export const useRestriction = (key) => useSelector((state) => { - const admin = state.session.user.administrator; - const serverValue = state.session.server[key]; - const userValue = state.session.user[key]; - return !admin && (serverValue || userValue); -}); diff --git a/modern/src/common/util/preferences.js b/modern/src/common/util/preferences.js deleted file mode 100644 index 229b6f17..00000000 --- a/modern/src/common/util/preferences.js +++ /dev/null @@ -1,41 +0,0 @@ -import { useSelector } from 'react-redux'; - -const containsProperty = (object, key) => object.hasOwnProperty(key) && object[key] !== null; - -export const usePreference = (key, defaultValue) => useSelector((state) => { - if (state.session.server.forceSettings) { - if (containsProperty(state.session.server, key)) { - return state.session.server[key]; - } - if (containsProperty(state.session.user, key)) { - return state.session.user[key]; - } - return defaultValue; - } - if (containsProperty(state.session.user, key)) { - return state.session.user[key]; - } - if (containsProperty(state.session.server, key)) { - return state.session.server[key]; - } - return defaultValue; -}); - -export const useAttributePreference = (key, defaultValue) => useSelector((state) => { - if (state.session.server.forceSettings) { - if (containsProperty(state.session.server.attributes, key)) { - return state.session.server.attributes[key]; - } - if (containsProperty(state.session.user.attributes, key)) { - return state.session.user.attributes[key]; - } - return defaultValue; - } - if (containsProperty(state.session.user.attributes, key)) { - return state.session.user.attributes[key]; - } - if (containsProperty(state.session.server.attributes, key)) { - return state.session.server.attributes[key]; - } - return defaultValue; -}); diff --git a/modern/src/common/util/stringUtils.js b/modern/src/common/util/stringUtils.js deleted file mode 100644 index fc997fe0..00000000 --- a/modern/src/common/util/stringUtils.js +++ /dev/null @@ -1,3 +0,0 @@ -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/useFeatures.js b/modern/src/common/util/useFeatures.js deleted file mode 100644 index 30361589..00000000 --- a/modern/src/common/util/useFeatures.js +++ /dev/null @@ -1,44 +0,0 @@ -import { createSelector } from '@reduxjs/toolkit'; -import { useSelector } from 'react-redux'; - -const get = (server, user, key) => { - if (server && user) { - if (user.administrator) { - return false; - } - if (server.forceSettings) { - return server.attributes[key] || user.attributes[key] || false; - } - return user.attributes[key] || server.attributes[key] || false; - } - return false; -}; - -const featureSelector = createSelector( - (state) => state.session.server, - (state) => state.session.user, - (server, user) => { - const disableSavedCommands = get(server, user, 'ui.disableSavedCommands'); - const disableAttributes = get(server, user, 'ui.disableAttributes'); - const disableVehicleFeatures = get(server, user, 'ui.disableVehicleFeatures'); - const disableDrivers = disableVehicleFeatures || get(server, user, 'ui.disableDrivers'); - const disableMaintenance = disableVehicleFeatures || get(server, user, 'ui.disableMaintenance'); - const disableGroups = get(server, user, 'ui.disableGroups'); - const disableEvents = get(server, user, 'ui.disableEvents'); - const disableComputedAttributes = get(server, user, 'ui.disableComputedAttributes'); - const disableCalendars = get(server, user, 'ui.disableCalendars'); - - return { - disableSavedCommands, - disableAttributes, - disableDrivers, - disableMaintenance, - disableGroups, - disableEvents, - disableComputedAttributes, - disableCalendars, - }; - }, -); - -export default () => useSelector(featureSelector); diff --git a/modern/src/common/util/usePersistedState.js b/modern/src/common/util/usePersistedState.js deleted file mode 100644 index 70a652ad..00000000 --- a/modern/src/common/util/usePersistedState.js +++ /dev/null @@ -1,22 +0,0 @@ -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(() => { - if (value !== defaultValue) { - savePersistedState(key, value); - } else { - window.localStorage.removeItem(key); - } - }, [key, value]); - - return [value, setValue]; -}; diff --git a/modern/src/common/util/useQuery.js b/modern/src/common/util/useQuery.js deleted file mode 100644 index f246df7c..00000000 --- a/modern/src/common/util/useQuery.js +++ /dev/null @@ -1,7 +0,0 @@ -import { useMemo } from 'react'; -import { useLocation } from 'react-router-dom'; - -export default () => { - const { search } = useLocation(); - return useMemo(() => new URLSearchParams(search), [search]); -}; -- cgit v1.2.3