@fleetbase/fleetops-engine 0.6.69 → 0.6.71

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (324) hide show
  1. package/RELEASE.md +21 -14
  2. package/addon/components/admin/telematics-settings.hbs +143 -0
  3. package/addon/components/admin/telematics-settings.js +145 -0
  4. package/addon/components/fuel-integration/hub.hbs +1 -1
  5. package/addon/components/layout/fleet-ops-sidebar.js +37 -17
  6. package/addon/components/map/leaflet-live-map.hbs +4 -242
  7. package/addon/components/map/leaflet-live-map.js +2 -1
  8. package/addon/components/map/marker-card/driver.hbs +57 -0
  9. package/addon/components/map/marker-card/driver.js +3 -0
  10. package/addon/components/map/marker-card/vehicle.hbs +78 -0
  11. package/addon/components/map/marker-card/vehicle.js +3 -0
  12. package/addon/components/order/details/activity.hbs +8 -6
  13. package/addon/components/order/details/activity.js +9 -0
  14. package/addon/components/order/details.hbs +29 -0
  15. package/addon/components/order/details.js +26 -0
  16. package/addon/components/order/form/details.hbs +30 -4
  17. package/addon/components/order/form/details.js +46 -0
  18. package/addon/components/order/form/route.hbs +4 -2
  19. package/addon/components/order/form/route.js +11 -0
  20. package/addon/components/order/form.hbs +12 -0
  21. package/addon/components/order/form.js +21 -1
  22. package/addon/components/order/kanban.js +72 -0
  23. package/addon/components/order-config-manager/activity-flow.js +45 -10
  24. package/addon/components/order-config-manager/lifecycle.hbs +250 -0
  25. package/addon/components/order-config-manager/lifecycle.js +358 -0
  26. package/addon/components/order-config-manager.js +5 -1
  27. package/addon/components/telematic/hub.hbs +1 -1
  28. package/addon/components/widget/live-fleet.hbs +8 -40
  29. package/addon/controllers/analytics/reports/index.js +15 -1
  30. package/addon/controllers/connectivity/devices/index/details.js +1 -0
  31. package/addon/controllers/connectivity/devices/index.js +12 -2
  32. package/addon/controllers/connectivity/events/index.js +31 -1
  33. package/addon/controllers/connectivity/fuel-providers/index.js +6 -4
  34. package/addon/controllers/connectivity/sensors/index/details.js +1 -1
  35. package/addon/controllers/connectivity/sensors/index.js +41 -1
  36. package/addon/controllers/connectivity/telematics/index.js +4 -0
  37. package/addon/controllers/maintenance/equipment/index/details.js +2 -2
  38. package/addon/controllers/maintenance/equipment/index.js +36 -10
  39. package/addon/controllers/maintenance/inspection-forms/index.js +32 -12
  40. package/addon/controllers/maintenance/inspection-submissions/index/details.js +2 -1
  41. package/addon/controllers/maintenance/inspection-submissions/index.js +56 -10
  42. package/addon/controllers/maintenance/maintenances/index/details.js +2 -0
  43. package/addon/controllers/maintenance/maintenances/index.js +24 -1
  44. package/addon/controllers/maintenance/parts/index/details.js +2 -2
  45. package/addon/controllers/maintenance/parts/index.js +36 -9
  46. package/addon/controllers/maintenance/schedules/index.js +48 -6
  47. package/addon/controllers/maintenance/work-orders/index/details.js +3 -3
  48. package/addon/controllers/maintenance/work-orders/index.js +47 -9
  49. package/addon/controllers/management/contacts/customers.js +13 -0
  50. package/addon/controllers/management/contacts/index.js +47 -1
  51. package/addon/controllers/management/drivers/index/details.js +1 -0
  52. package/addon/controllers/management/drivers/index.js +36 -2
  53. package/addon/controllers/management/fleets/index/details.js +1 -0
  54. package/addon/controllers/management/fleets/index.js +43 -1
  55. package/addon/controllers/management/fuel-reports/index.js +26 -2
  56. package/addon/controllers/management/fuel-transactions/index.js +45 -7
  57. package/addon/controllers/management/issues/index/details.js +1 -0
  58. package/addon/controllers/management/issues/index.js +26 -2
  59. package/addon/controllers/management/places/index.js +40 -1
  60. package/addon/controllers/management/trailers/index/details.js +1 -0
  61. package/addon/controllers/management/trailers/index.js +50 -2
  62. package/addon/controllers/management/vehicles/index/details.js +1 -0
  63. package/addon/controllers/management/vehicles/index.js +37 -2
  64. package/addon/controllers/management/vendors/index.js +30 -2
  65. package/addon/controllers/operations/orders/index/details.js +61 -5
  66. package/addon/controllers/operations/orders/index.js +66 -4
  67. package/addon/controllers/operations/service-rates/index.js +18 -1
  68. package/addon/controllers/settings/index.js +13 -0
  69. package/addon/controllers/settings/telematics.js +113 -0
  70. package/addon/extension.js +70 -6
  71. package/addon/routes/analytics/index.js +14 -1
  72. package/addon/routes/analytics/reports/index/details.js +1 -1
  73. package/addon/routes/analytics/reports/index/edit.js +1 -1
  74. package/addon/routes/analytics/reports/index/new.js +14 -1
  75. package/addon/routes/analytics/reports.js +14 -1
  76. package/addon/routes/connectivity/devices/index/new.js +14 -1
  77. package/addon/routes/connectivity/devices.js +14 -1
  78. package/addon/routes/connectivity/events.js +14 -1
  79. package/addon/routes/connectivity/fuel-providers/details/transactions.js +12 -0
  80. package/addon/routes/connectivity/fuel-providers/details.js +9 -0
  81. package/addon/routes/connectivity/fuel-providers/edit.js +9 -0
  82. package/addon/routes/connectivity/fuel-providers/new.js +14 -1
  83. package/addon/routes/connectivity/fuel-providers.js +14 -1
  84. package/addon/routes/connectivity/sensors/index/new.js +14 -1
  85. package/addon/routes/connectivity/sensors.js +14 -1
  86. package/addon/routes/connectivity/telematics/new.js +14 -1
  87. package/addon/routes/connectivity/telematics.js +14 -1
  88. package/addon/routes/connectivity/tracking.js +14 -1
  89. package/addon/routes/maintenance/equipment/index/details.js +2 -2
  90. package/addon/routes/maintenance/equipment/index/edit.js +2 -2
  91. package/addon/routes/maintenance/equipment/index/new.js +14 -1
  92. package/addon/routes/maintenance/equipment.js +14 -1
  93. package/addon/routes/maintenance/index.js +14 -1
  94. package/addon/routes/maintenance/inspection-forms/index/details.js +10 -1
  95. package/addon/routes/maintenance/inspection-forms/index/edit.js +10 -1
  96. package/addon/routes/maintenance/inspection-forms/index/new.js +14 -1
  97. package/addon/routes/maintenance/inspection-forms.js +14 -1
  98. package/addon/routes/maintenance/inspection-submissions/index/details.js +10 -1
  99. package/addon/routes/maintenance/inspection-submissions/index/edit.js +10 -1
  100. package/addon/routes/maintenance/inspection-submissions/index/new.js +14 -1
  101. package/addon/routes/maintenance/inspection-submissions.js +14 -1
  102. package/addon/routes/maintenance/maintenances/index/details.js +2 -2
  103. package/addon/routes/maintenance/maintenances/index/edit.js +2 -2
  104. package/addon/routes/maintenance/maintenances/index/new.js +14 -1
  105. package/addon/routes/maintenance/maintenances.js +14 -1
  106. package/addon/routes/maintenance/parts/index/details.js +2 -2
  107. package/addon/routes/maintenance/parts/index/edit.js +2 -2
  108. package/addon/routes/maintenance/parts/index/new.js +14 -1
  109. package/addon/routes/maintenance/parts.js +14 -1
  110. package/addon/routes/maintenance/schedules/index/details.js +2 -2
  111. package/addon/routes/maintenance/schedules/index/edit.js +2 -2
  112. package/addon/routes/maintenance/schedules/index/new.js +15 -1
  113. package/addon/routes/maintenance/schedules.js +15 -1
  114. package/addon/routes/maintenance/work-orders/index/details.js +2 -2
  115. package/addon/routes/maintenance/work-orders/index/edit.js +2 -2
  116. package/addon/routes/maintenance/work-orders/index/new.js +14 -1
  117. package/addon/routes/maintenance/work-orders.js +14 -1
  118. package/addon/routes/management/fuel-transactions/index/details.js +9 -0
  119. package/addon/routes/management/fuel-transactions.js +14 -1
  120. package/addon/routes/management/index.js +13 -0
  121. package/addon/routes/management/trailers.js +16 -0
  122. package/addon/routes/management/vendors/integrated/details.js +14 -1
  123. package/addon/routes/management/vendors/integrated/edit.js +14 -1
  124. package/addon/routes/management/vendors/integrated/new.js +14 -1
  125. package/addon/routes/management/vendors/integrated.js +14 -1
  126. package/addon/routes/operations/orders/index/details.js +1 -0
  127. package/addon/routes/operations/orders.js +40 -1
  128. package/addon/routes/operations/routes/index/details.js +14 -1
  129. package/addon/routes/operations/routes/index/new.js +13 -0
  130. package/addon/routes/operations/routes.js +14 -1
  131. package/addon/routes/operations/service-rates/index/new.js +11 -0
  132. package/addon/routes/operations/service-rates.js +14 -1
  133. package/addon/routes/settings/avatars.js +14 -1
  134. package/addon/routes/settings/custom-fields.js +14 -1
  135. package/addon/routes/settings/map.js +14 -1
  136. package/addon/routes/settings/notifications.js +11 -0
  137. package/addon/routes/settings/orchestrator.js +1 -1
  138. package/addon/routes/settings/payments/index.js +1 -1
  139. package/addon/routes/settings/routing.js +14 -1
  140. package/addon/routes/settings/scheduling.js +14 -1
  141. package/addon/routes/settings/telematics.js +21 -0
  142. package/addon/routes/virtual.js +11 -0
  143. package/addon/routes.js +1 -0
  144. package/addon/services/contact-actions.js +1 -0
  145. package/addon/services/customer-actions.js +2 -1
  146. package/addon/services/device-actions.js +1 -0
  147. package/addon/services/device-event-actions.js +1 -0
  148. package/addon/services/driver-actions.js +4 -13
  149. package/addon/services/equipment-actions.js +1 -0
  150. package/addon/services/fleet-actions.js +1 -0
  151. package/addon/services/fuel-report-actions.js +1 -0
  152. package/addon/services/inspection-form-actions.js +1 -0
  153. package/addon/services/inspection-submission-actions.js +1 -0
  154. package/addon/services/integrated-vendor-actions.js +1 -0
  155. package/addon/services/issue-actions.js +1 -0
  156. package/addon/services/maintenance-actions.js +1 -0
  157. package/addon/services/maintenance-schedule-actions.js +2 -1
  158. package/addon/services/order-actions.js +7 -0
  159. package/addon/services/order-presentation.js +129 -0
  160. package/addon/services/part-actions.js +1 -0
  161. package/addon/services/place-actions.js +1 -0
  162. package/addon/services/sensor-actions.js +1 -0
  163. package/addon/services/service-area-actions.js +1 -0
  164. package/addon/services/service-rate-actions.js +1 -0
  165. package/addon/services/telematic-actions.js +1 -0
  166. package/addon/services/trailer-actions.js +4 -14
  167. package/addon/services/vehicle-actions.js +4 -13
  168. package/addon/services/vendor-actions.js +1 -0
  169. package/addon/services/work-order-actions.js +1 -0
  170. package/addon/services/zone-actions.js +1 -0
  171. package/addon/templates/analytics/reports/index/details.hbs +1 -0
  172. package/addon/templates/analytics/reports/index.hbs +1 -0
  173. package/addon/templates/connectivity/devices/index/details.hbs +1 -0
  174. package/addon/templates/connectivity/devices/index.hbs +1 -0
  175. package/addon/templates/connectivity/events/index.hbs +1 -0
  176. package/addon/templates/connectivity/sensors/index/details.hbs +1 -0
  177. package/addon/templates/connectivity/sensors/index.hbs +1 -0
  178. package/addon/templates/maintenance/equipment/index/details.hbs +1 -0
  179. package/addon/templates/maintenance/equipment/index.hbs +2 -0
  180. package/addon/templates/maintenance/inspection-forms/index/details.hbs +1 -0
  181. package/addon/templates/maintenance/inspection-forms/index.hbs +1 -0
  182. package/addon/templates/maintenance/inspection-submissions/index/details.hbs +1 -0
  183. package/addon/templates/maintenance/inspection-submissions/index.hbs +1 -0
  184. package/addon/templates/maintenance/maintenances/index/details.hbs +1 -0
  185. package/addon/templates/maintenance/maintenances/index.hbs +1 -0
  186. package/addon/templates/maintenance/parts/index/details.hbs +1 -0
  187. package/addon/templates/maintenance/parts/index.hbs +2 -0
  188. package/addon/templates/maintenance/schedules/index/details.hbs +1 -0
  189. package/addon/templates/maintenance/schedules/index.hbs +2 -0
  190. package/addon/templates/maintenance/work-orders/index/details.hbs +1 -0
  191. package/addon/templates/maintenance/work-orders/index.hbs +1 -0
  192. package/addon/templates/management/contacts/customers/details.hbs +1 -0
  193. package/addon/templates/management/contacts/customers.hbs +1 -0
  194. package/addon/templates/management/contacts/index/details.hbs +1 -0
  195. package/addon/templates/management/contacts/index.hbs +1 -0
  196. package/addon/templates/management/contacts.hbs +1 -0
  197. package/addon/templates/management/drivers/index/details.hbs +1 -0
  198. package/addon/templates/management/drivers/index.hbs +2 -0
  199. package/addon/templates/management/fleets/index/details.hbs +1 -0
  200. package/addon/templates/management/fleets/index.hbs +1 -0
  201. package/addon/templates/management/fuel-reports/index/details.hbs +1 -0
  202. package/addon/templates/management/fuel-reports/index.hbs +1 -0
  203. package/addon/templates/management/fuel-transactions/index.hbs +1 -0
  204. package/addon/templates/management/issues/index/details.hbs +1 -0
  205. package/addon/templates/management/issues/index.hbs +1 -0
  206. package/addon/templates/management/places/index/details.hbs +1 -0
  207. package/addon/templates/management/places/index.hbs +1 -0
  208. package/addon/templates/management/trailers/index/details.hbs +1 -0
  209. package/addon/templates/management/trailers/index.hbs +2 -0
  210. package/addon/templates/management/vehicles/index/details.hbs +1 -0
  211. package/addon/templates/management/vehicles/index.hbs +2 -0
  212. package/addon/templates/management/vendors/index/details.hbs +1 -0
  213. package/addon/templates/management/vendors/index.hbs +2 -0
  214. package/addon/templates/management/vendors/integrated.hbs +1 -0
  215. package/addon/templates/operations/orders/index/details.hbs +1 -0
  216. package/addon/templates/operations/orders/index.hbs +1 -0
  217. package/addon/templates/operations/service-rates/index/details.hbs +1 -0
  218. package/addon/templates/operations/service-rates/index.hbs +1 -0
  219. package/addon/templates/settings/telematics.hbs +70 -0
  220. package/addon/utils/normalize-order-config-flow.js +6 -1
  221. package/app/components/admin/telematics-settings.js +1 -0
  222. package/app/components/map/marker-card/driver.js +1 -0
  223. package/app/components/map/marker-card/vehicle.js +1 -0
  224. package/app/controllers/settings/telematics.js +1 -0
  225. package/app/routes/settings/telematics.js +1 -0
  226. package/app/services/order-presentation.js +1 -0
  227. package/app/templates/settings/telematics.js +1 -0
  228. package/composer.json +2 -2
  229. package/docs/AFAQY.md +1 -1
  230. package/docs/TELEMATICS_QUEUES.md +1 -1
  231. package/docs/TELEMETRY_ARCHITECTURE.md +72 -1
  232. package/extension.json +1 -1
  233. package/package.json +3 -3
  234. package/server/config/telemetry.php +12 -0
  235. package/server/migrations/2026_09_23_000001_add_retention_index_to_device_events.php +40 -0
  236. package/server/migrations/2026_09_23_000002_add_retention_index_to_positions.php +40 -0
  237. package/server/migrations/2026_09_23_000003_add_retention_index_to_telematic_sync_runs.php +40 -0
  238. package/server/src/Auth/Schemas/FleetOps.php +104 -5
  239. package/server/src/Console/Commands/DrainTelematicInbox.php +3 -13
  240. package/server/src/Console/Commands/ProcessOperationalAlerts.php +3 -3
  241. package/server/src/Console/Commands/PruneTelematicsData.php +318 -0
  242. package/server/src/Http/Controllers/Api/v1/OrchestrationController.php +9 -0
  243. package/server/src/Http/Controllers/FleetOpsController.php +21 -0
  244. package/server/src/Http/Controllers/Internal/v1/AnalyticsController.php +11 -0
  245. package/server/src/Http/Controllers/Internal/v1/ContactController.php +11 -0
  246. package/server/src/Http/Controllers/Internal/v1/CustomerController.php +14 -0
  247. package/server/src/Http/Controllers/Internal/v1/DeviceController.php +13 -0
  248. package/server/src/Http/Controllers/Internal/v1/DeviceEventController.php +11 -0
  249. package/server/src/Http/Controllers/Internal/v1/DriverController.php +22 -0
  250. package/server/src/Http/Controllers/Internal/v1/FuelProviderConnectionController.php +13 -0
  251. package/server/src/Http/Controllers/Internal/v1/FuelProviderTransactionController.php +15 -0
  252. package/server/src/Http/Controllers/Internal/v1/FuelReportController.php +9 -3
  253. package/server/src/Http/Controllers/Internal/v1/InspectionFormController.php +15 -0
  254. package/server/src/Http/Controllers/Internal/v1/LiveController.php +16 -0
  255. package/server/src/Http/Controllers/Internal/v1/MaintenanceController.php +15 -0
  256. package/server/src/Http/Controllers/Internal/v1/MaintenanceScheduleController.php +15 -0
  257. package/server/src/Http/Controllers/Internal/v1/ManifestController.php +15 -0
  258. package/server/src/Http/Controllers/Internal/v1/MetricsController.php +11 -0
  259. package/server/src/Http/Controllers/Internal/v1/NavigatorController.php +42 -1
  260. package/server/src/Http/Controllers/Internal/v1/OrchestrationController.php +12 -0
  261. package/server/src/Http/Controllers/Internal/v1/OrderController.php +56 -4
  262. package/server/src/Http/Controllers/Internal/v1/PaymentController.php +13 -0
  263. package/server/src/Http/Controllers/Internal/v1/RadarController.php +19 -0
  264. package/server/src/Http/Controllers/Internal/v1/ServiceAreaController.php +9 -3
  265. package/server/src/Http/Controllers/Internal/v1/SettingController.php +465 -14
  266. package/server/src/Http/Controllers/Internal/v1/TelematicController.php +21 -0
  267. package/server/src/Http/Controllers/Internal/v1/TrailerController.php +21 -0
  268. package/server/src/Http/Controllers/Internal/v1/VehicleController.php +21 -0
  269. package/server/src/Http/Controllers/Internal/v1/VendorController.php +17 -0
  270. package/server/src/Http/Controllers/Internal/v1/WorkOrderController.php +11 -0
  271. package/server/src/Jobs/DispatchTelematicsRetentionJobs.php +70 -0
  272. package/server/src/Jobs/PruneTelematicsDataJob.php +74 -0
  273. package/server/src/Listeners/NotifyDriverOnShiftChange.php +3 -3
  274. package/server/src/Mail/CustomerCredentialsMail.php +1 -1
  275. package/server/src/Models/Order.php +35 -3
  276. package/server/src/Models/OrderConfig.php +129 -0
  277. package/server/src/Models/TrackingNumber.php +8 -4
  278. package/server/src/Orchestration/Engines/VroomOrchestrationEngine.php +9 -1
  279. package/server/src/Providers/FleetOpsServiceProvider.php +3 -0
  280. package/server/src/Support/Analytics/LiveFleet.php +18 -2
  281. package/server/src/Support/Authorization.php +103 -0
  282. package/server/src/Support/Database/TableIndexes.php +66 -0
  283. package/server/src/Support/OrderTracker.php +2 -2
  284. package/server/src/Support/Reporting/FleetOpsReportSchema.php +476 -116
  285. package/server/src/Support/Telematics/Retention/RetentionPolicy.php +300 -0
  286. package/server/src/Support/Telematics/Retention/TelemetryActivity.php +40 -0
  287. package/server/src/Support/Telematics/TelematicService.php +12 -2
  288. package/server/src/Support/Telematics/Telemetry/Ingestor.php +4 -2
  289. package/server/src/Tracking/TrackingIntelligenceService.php +1 -1
  290. package/server/src/Tracking/TrackingOptions.php +2 -2
  291. package/server/src/Traits/AuthorizesMethods.php +37 -0
  292. package/server/src/routes.php +9 -1
  293. package/server/tests/AnalyticsRoutesTest.php +29 -2
  294. package/server/tests/Feature/Http/AfaqyRealtimeIngestionTest.php +16 -1
  295. package/server/tests/Feature/Http/Api/TelematicsRetentionIndexMigrationTest.php +115 -0
  296. package/server/tests/Feature/Http/Internal/OrderControllerActivityFlowsTest.php +72 -0
  297. package/server/tests/Feature/Http/Internal/OrderControllerCreateRecordTest.php +26 -0
  298. package/server/tests/Feature/Http/Internal/SettingControllerHelpersTest.php +71 -0
  299. package/server/tests/Feature/Http/Internal/TelematicsStorageDeadlinesTest.php +119 -0
  300. package/server/tests/InternalImportExportControllerContractsTest.php +5 -8
  301. package/server/tests/NavigatorControllerContractsTest.php +36 -4
  302. package/server/tests/NotificationAndMailContractsTest.php +31 -0
  303. package/server/tests/ObserverContractsTest.php +1 -1
  304. package/server/tests/OrchestratorConsumableApiTest.php +42 -0
  305. package/server/tests/OrderConfigLifecycleTest.php +120 -0
  306. package/server/tests/ProviderContractsTest.php +10 -0
  307. package/server/tests/ReportSchemaContractsTest.php +120 -6
  308. package/server/tests/SettingControllerContractsTest.php +429 -18
  309. package/server/tests/SmallControllerContractsTest.php +8 -5
  310. package/server/tests/Support/PruneTelematicsDataProbe.php +55 -0
  311. package/server/tests/Unit/Console/Commands/ProcessOperationalAlertsCommandTest.php +2 -2
  312. package/server/tests/Unit/Console/PruneTelematicsDataCommandTest.php +353 -0
  313. package/server/tests/Unit/Events/OrderDispatchFailedTest.php +2 -1
  314. package/server/tests/Unit/Jobs/DispatchTelematicsRetentionJobsTest.php +114 -0
  315. package/server/tests/Unit/Jobs/PruneTelematicsDataJobTest.php +60 -0
  316. package/server/tests/Unit/Orchestration/VroomEngineTransportAndSettingsTest.php +20 -0
  317. package/server/tests/Unit/Support/Analytics/LiveFleetTest.php +6 -0
  318. package/server/tests/Unit/Support/AuthorizationTest.php +142 -0
  319. package/server/tests/Unit/Support/MaintainableAndOperationalAlertsTest.php +12 -1
  320. package/server/tests/Unit/Support/MoreQuerySeamsTest.php +11 -2
  321. package/server/tests/Unit/Support/Telematics/Retention/RetentionPolicyTest.php +190 -0
  322. package/server/tests/Unit/Support/Telematics/Retention/TelemetryActivityTest.php +68 -0
  323. package/server/tests/Unit/Tracking/TrackingOptionsCompanySettingsTest.php +109 -0
  324. package/translations/en-us.yaml +108 -0
@@ -7,6 +7,7 @@ import relationValue from '../../../utils/relation-value';
7
7
 
8
8
  export default class OperationsOrdersIndexController extends Controller {
9
9
  @service orderActions;
10
+ @service orderPresentation;
10
11
  @service driverActions;
11
12
  @service vehicleActions;
12
13
  @service store;
@@ -18,7 +19,7 @@ export default class OperationsOrdersIndexController extends Controller {
18
19
  @service intl;
19
20
 
20
21
  /** query params */
21
- @tracked queryParams = [
22
+ @tracked queryParams = this.orderActions.queryParamsFor([
22
23
  'page',
23
24
  'limit',
24
25
  'sort',
@@ -46,7 +47,7 @@ export default class OperationsOrdersIndexController extends Controller {
46
47
  'drawerOpen',
47
48
  'drawerTab',
48
49
  'orderPanelOpen',
49
- ];
50
+ ]);
50
51
  @tracked page = 1;
51
52
  @tracked limit;
52
53
  @tracked sort = '-created_at';
@@ -77,28 +78,35 @@ export default class OperationsOrdersIndexController extends Controller {
77
78
  get actionButtons() {
78
79
  return [
79
80
  {
81
+ id: 'refresh',
80
82
  icon: 'refresh',
81
83
  onClick: this.orderActions.refresh,
82
84
  helpText: this.intl.t('common.refresh'),
83
85
  },
84
86
  {
87
+ id: 'create',
85
88
  text: this.intl.t('common.new'),
86
89
  type: 'primary',
87
90
  icon: 'plus',
88
91
  onClick: this.orderActions.transition.create,
92
+ permission: 'fleet-ops create order',
89
93
  },
90
94
  {
95
+ id: 'export',
91
96
  text: this.intl.t('common.export'),
92
97
  icon: 'long-arrow-up',
93
98
  iconClass: 'rotate-icon-45',
94
99
  wrapperClass: 'hidden md:flex',
95
100
  onClick: this.orderActions.export,
101
+ permission: 'fleet-ops export order',
96
102
  },
97
103
  {
104
+ id: 'import-orders',
98
105
  text: this.intl.t('common.import'),
99
106
  icon: 'file-import',
100
107
  wrapperClass: 'hidden md:flex',
101
108
  onClick: () => this.orderActions.importOrders({ onImportComplete: this.orderActions.refresh }),
109
+ permission: 'fleet-ops import order',
102
110
  },
103
111
  ];
104
112
  }
@@ -107,26 +115,34 @@ export default class OperationsOrdersIndexController extends Controller {
107
115
  get bulkActions() {
108
116
  return [
109
117
  {
118
+ id: 'bulk-cancel',
110
119
  label: this.intl.t('common.cancel-resource', { resource: this.intl.t('resource.orders') }),
111
120
  icon: 'ban',
112
121
  fn: this.orderActions.bulkCancel,
122
+ permission: 'fleet-ops cancel order',
113
123
  },
114
124
  {
125
+ id: 'bulk-delete',
115
126
  label: this.intl.t('common.delete-resource', { resource: this.intl.t('resource.orders') }),
116
127
  icon: 'trash',
117
128
  class: 'text-red-500',
118
129
  fn: this.orderActions.bulkDelete,
130
+ permission: 'fleet-ops delete order',
119
131
  },
120
132
  { separator: true },
121
133
  {
134
+ id: 'bulk-dispatch',
122
135
  label: this.intl.t('common.dispatch-orders'),
123
136
  icon: 'rocket',
124
137
  fn: this.orderActions.bulkDispatch,
138
+ permission: 'fleet-ops dispatch order',
125
139
  },
126
140
  {
141
+ id: 'bulk-assign-driver',
127
142
  label: this.intl.t('common.assign-drivers'),
128
143
  icon: 'user-plus',
129
144
  fn: this.orderActions.bulkAssignDriver,
145
+ permission: 'fleet-ops assign-driver-for order',
130
146
  },
131
147
  ];
132
148
  }
@@ -135,6 +151,7 @@ export default class OperationsOrdersIndexController extends Controller {
135
151
  get columns() {
136
152
  return [
137
153
  {
154
+ id: 'public-id',
138
155
  sticky: true,
139
156
  label: this.intl.t('column.id'),
140
157
  valuePath: 'public_id',
@@ -148,6 +165,7 @@ export default class OperationsOrdersIndexController extends Controller {
148
165
  filterComponent: 'filter/string',
149
166
  },
150
167
  {
168
+ id: 'payload-waypoints-length',
151
169
  label: this.intl.t('column.route-type'),
152
170
  valuePath: 'payload.waypoints.length',
153
171
  cellComponent: 'cell/order-route-type',
@@ -155,6 +173,7 @@ export default class OperationsOrdersIndexController extends Controller {
155
173
  resizable: true,
156
174
  },
157
175
  {
176
+ id: 'internal-id',
158
177
  label: this.intl.t('column.internal-id'),
159
178
  valuePath: 'internal_id',
160
179
  cellComponent: 'click-to-copy',
@@ -167,6 +186,7 @@ export default class OperationsOrdersIndexController extends Controller {
167
186
  filterComponentPlaceholder: this.intl.t('order.placeholders.filter-internal-id'),
168
187
  },
169
188
  {
189
+ id: 'payload-public-id',
170
190
  label: this.intl.t('column.payload'),
171
191
  valuePath: 'payload.public_id',
172
192
  cellComponent: 'cell/payload-identity',
@@ -179,6 +199,7 @@ export default class OperationsOrdersIndexController extends Controller {
179
199
  filterComponent: 'filter/string',
180
200
  },
181
201
  {
202
+ id: 'driver-assigned',
182
203
  label: this.intl.t('column.driver-assigned'),
183
204
  cellComponent: 'cell/driver-identity',
184
205
  valuePath: 'driver_assigned',
@@ -196,6 +217,7 @@ export default class OperationsOrdersIndexController extends Controller {
196
217
  model: 'driver',
197
218
  },
198
219
  {
220
+ id: 'pickup-name',
199
221
  label: this.intl.t('column.pickup'),
200
222
  valuePath: 'pickupName',
201
223
  cellComponent: 'cell/place-identity',
@@ -212,6 +234,7 @@ export default class OperationsOrdersIndexController extends Controller {
212
234
  model: 'place',
213
235
  },
214
236
  {
237
+ id: 'dropoff-name',
215
238
  label: this.intl.t('column.dropoff'),
216
239
  valuePath: 'dropoffName',
217
240
  cellComponent: 'cell/place-identity',
@@ -227,6 +250,7 @@ export default class OperationsOrdersIndexController extends Controller {
227
250
  model: 'place',
228
251
  },
229
252
  {
253
+ id: 'customer-name',
230
254
  label: this.intl.t('column.customer'),
231
255
  valuePath: 'customer.name',
232
256
  cellComponent: 'cell/customer-identity',
@@ -241,6 +265,7 @@ export default class OperationsOrdersIndexController extends Controller {
241
265
  model: 'customer',
242
266
  },
243
267
  {
268
+ id: 'vehicle-assigned-display-name',
244
269
  label: this.intl.t('column.vehicle-assigned'),
245
270
  cellComponent: 'cell/vehicle-identity',
246
271
  valuePath: 'vehicle_assigned.display_name',
@@ -264,6 +289,7 @@ export default class OperationsOrdersIndexController extends Controller {
264
289
  model: 'vehicle',
265
290
  },
266
291
  {
292
+ id: 'facilitator-name',
267
293
  label: this.intl.t('column.facilitator'),
268
294
  valuePath: 'facilitator.name',
269
295
  cellComponent: 'cell/facilitator-identity',
@@ -278,6 +304,7 @@ export default class OperationsOrdersIndexController extends Controller {
278
304
  model: 'vendor',
279
305
  },
280
306
  {
307
+ id: 'scheduled-at',
281
308
  label: this.intl.t('column.scheduled-at'),
282
309
  valuePath: 'scheduledAt',
283
310
  sortParam: 'scheduled_at',
@@ -288,6 +315,7 @@ export default class OperationsOrdersIndexController extends Controller {
288
315
  filterComponent: 'filter/date',
289
316
  },
290
317
  {
318
+ id: 'item-count',
291
319
  label: this.intl.t('column.items'),
292
320
  cellComponent: 'table/cell/base',
293
321
  valuePath: 'item_count',
@@ -295,6 +323,7 @@ export default class OperationsOrdersIndexController extends Controller {
295
323
  hidden: true,
296
324
  },
297
325
  {
326
+ id: 'transaction-amount',
298
327
  label: this.intl.t('column.transaction'),
299
328
  cellComponent: 'table/cell/currency',
300
329
  valuePath: 'transaction_amount',
@@ -303,6 +332,7 @@ export default class OperationsOrdersIndexController extends Controller {
303
332
  sortable: true,
304
333
  },
305
334
  {
335
+ id: 'tracking-number-tracking-number',
306
336
  label: this.intl.t('column.tracking'),
307
337
  valuePath: 'tracking_number.tracking_number',
308
338
  cellComponent: 'click-to-copy',
@@ -312,6 +342,7 @@ export default class OperationsOrdersIndexController extends Controller {
312
342
  filterComponent: 'filter/string',
313
343
  },
314
344
  {
345
+ id: 'type',
315
346
  label: this.intl.t('column.type'),
316
347
  valuePath: 'type',
317
348
  resizable: true,
@@ -323,6 +354,7 @@ export default class OperationsOrdersIndexController extends Controller {
323
354
  filterComponentPlaceholder: 'Filter by order config',
324
355
  },
325
356
  {
357
+ id: 'status',
326
358
  label: this.intl.t('column.status'),
327
359
  valuePath: 'status',
328
360
  cellComponent: 'table/cell/status',
@@ -333,6 +365,7 @@ export default class OperationsOrdersIndexController extends Controller {
333
365
  fetchUri: 'orders/statuses',
334
366
  },
335
367
  {
368
+ id: 'created-at',
336
369
  label: this.intl.t('column.created-at'),
337
370
  valuePath: 'createdAt',
338
371
  sortParam: 'created_at',
@@ -343,6 +376,7 @@ export default class OperationsOrdersIndexController extends Controller {
343
376
  filterComponent: 'filter/date',
344
377
  },
345
378
  {
379
+ id: 'updated-at',
346
380
  label: this.intl.t('column.updated-at'),
347
381
  valuePath: 'updatedAt',
348
382
  sortParam: 'updated_at',
@@ -354,6 +388,7 @@ export default class OperationsOrdersIndexController extends Controller {
354
388
  filterComponent: 'filter/date',
355
389
  },
356
390
  {
391
+ id: 'created-by-name',
357
392
  label: this.intl.t('column.created-by'),
358
393
  valuePath: 'created_by_name',
359
394
  cellComponent: 'table/cell/user-identity',
@@ -367,6 +402,7 @@ export default class OperationsOrdersIndexController extends Controller {
367
402
  model: 'user',
368
403
  },
369
404
  {
405
+ id: 'updated-by-name',
370
406
  label: this.intl.t('column.updated-by'),
371
407
  valuePath: 'updated_by_name',
372
408
  cellComponent: 'table/cell/user-identity',
@@ -390,6 +426,7 @@ export default class OperationsOrdersIndexController extends Controller {
390
426
  hidden: true,
391
427
  },
392
428
  {
429
+ id: 'row-actions',
393
430
  label: '',
394
431
  cellComponent: 'table/cell/dropdown',
395
432
  ddButtonText: false,
@@ -400,14 +437,16 @@ export default class OperationsOrdersIndexController extends Controller {
400
437
  wrapperClass: 'flex items-center justify-end mx-2',
401
438
  sticky: 'right',
402
439
  width: 60,
403
- actions: [
440
+ actions: this.withPresentationProfile([
404
441
  {
442
+ id: 'view',
405
443
  label: this.intl.t('common.view-resource', { resource: this.intl.t('resource.order') }),
406
444
  icon: 'eye',
407
445
  fn: this.orderActions.transition.view,
408
446
  permission: 'fleet-ops view order',
409
447
  },
410
448
  {
449
+ id: 'dispatch',
411
450
  label: this.intl.t('common.dispatch-order'),
412
451
  icon: 'paper-plane',
413
452
  fn: this.orderActions.dispatch,
@@ -415,6 +454,7 @@ export default class OperationsOrdersIndexController extends Controller {
415
454
  isVisible: (order) => order.canBeDispatched,
416
455
  },
417
456
  {
457
+ id: 'assign-driver',
418
458
  label: this.intl.t('common.assign-driver'),
419
459
  icon: 'edit',
420
460
  fn: this.orderActions.assignDriver,
@@ -422,6 +462,7 @@ export default class OperationsOrdersIndexController extends Controller {
422
462
  isVisible: (order) => !order.has_driver_assigned,
423
463
  },
424
464
  {
465
+ id: 'unassign-driver',
425
466
  label: this.intl.t('common.unassign-driver'),
426
467
  icon: 'edit',
427
468
  fn: this.orderActions.unassignDriver,
@@ -429,6 +470,7 @@ export default class OperationsOrdersIndexController extends Controller {
429
470
  isVisible: (order) => order.has_driver_assigned,
430
471
  },
431
472
  {
473
+ id: 'cancel',
432
474
  label: this.intl.t('common.cancel-resource', { resource: this.intl.t('resource.order') }),
433
475
  icon: 'ban',
434
476
  fn: this.orderActions.cancel,
@@ -438,12 +480,13 @@ export default class OperationsOrdersIndexController extends Controller {
438
480
  separator: true,
439
481
  },
440
482
  {
483
+ id: 'delete',
441
484
  label: this.intl.t('common.delete-resource', { resource: this.intl.t('resource.order') }),
442
485
  icon: 'trash',
443
486
  fn: this.orderActions.delete,
444
487
  permission: 'fleet-ops delete order',
445
488
  },
446
- ],
489
+ ]),
447
490
  sortable: false,
448
491
  filterable: false,
449
492
  resizable: false,
@@ -452,6 +495,25 @@ export default class OperationsOrdersIndexController extends Controller {
452
495
  ];
453
496
  }
454
497
 
498
+ /**
499
+ * Hides the row actions an order's presentation profile lists in `hidden.actions`, by id,
500
+ * the same way the details panel does.
501
+ */
502
+ withPresentationProfile(actions) {
503
+ return actions.map((item) => {
504
+ if (!item.id) {
505
+ return item;
506
+ }
507
+
508
+ const isVisible = item.isVisible;
509
+ const builtInVisible = (order, ...rest) => (typeof isVisible === 'function' ? isVisible(order, ...rest) : isVisible !== false);
510
+ return {
511
+ ...item,
512
+ isVisible: (order, ...rest) => !this.orderPresentation.isHidden(order, 'actions', item.id) && builtInVisible(order, ...rest),
513
+ };
514
+ });
515
+ }
516
+
455
517
  constructor() {
456
518
  super(...arguments);
457
519
  this.orderSocketEvents.startCompany();
@@ -10,7 +10,7 @@ export default class OperationsServiceRatesIndexController extends Controller {
10
10
  @service intl;
11
11
 
12
12
  /** query params */
13
- @tracked queryParams = ['page', 'query', 'limit', 'sort', 'zone', 'service_area'];
13
+ @tracked queryParams = this.serviceRateActions.queryParamsFor(['page', 'query', 'limit', 'sort', 'zone', 'service_area']);
14
14
  @tracked page = 1;
15
15
  @tracked limit;
16
16
  @tracked query;
@@ -20,22 +20,27 @@ export default class OperationsServiceRatesIndexController extends Controller {
20
20
  get actionButtons() {
21
21
  return [
22
22
  {
23
+ id: 'refresh',
23
24
  icon: 'refresh',
24
25
  onClick: this.serviceRateActions.refresh,
25
26
  helpText: this.intl.t('common.refresh'),
26
27
  },
27
28
  {
29
+ id: 'create',
28
30
  text: this.intl.t('common.new'),
29
31
  type: 'primary',
30
32
  icon: 'plus',
31
33
  onClick: this.serviceRateActions.transition.create,
34
+ permission: 'fleet-ops create service-rate',
32
35
  },
33
36
  {
37
+ id: 'export',
34
38
  text: this.intl.t('common.export'),
35
39
  icon: 'long-arrow-up',
36
40
  iconClass: 'rotate-icon-45',
37
41
  wrapperClass: 'hidden md:flex',
38
42
  onClick: this.serviceRateActions.export,
43
+ permission: 'fleet-ops export service-rate',
39
44
  },
40
45
  ];
41
46
  }
@@ -44,9 +49,11 @@ export default class OperationsServiceRatesIndexController extends Controller {
44
49
  get bulkActions() {
45
50
  return [
46
51
  {
52
+ id: 'bulk-delete',
47
53
  label: 'Delete selected...',
48
54
  class: 'text-red-500',
49
55
  fn: this.serviceRateActions.bulkDelete,
56
+ permission: 'fleet-ops delete service-rate',
50
57
  },
51
58
  ];
52
59
  }
@@ -55,6 +62,7 @@ export default class OperationsServiceRatesIndexController extends Controller {
55
62
  get columns() {
56
63
  return [
57
64
  {
65
+ id: 'public-id',
58
66
  sticky: true,
59
67
  label: this.intl.t('column.id'),
60
68
  valuePath: 'public_id',
@@ -67,6 +75,7 @@ export default class OperationsServiceRatesIndexController extends Controller {
67
75
  filterComponent: 'filter/string',
68
76
  },
69
77
  {
78
+ id: 'service-name',
70
79
  label: this.intl.t('column.service'),
71
80
  valuePath: 'service_name',
72
81
  cellComponent: 'table/cell/base',
@@ -75,6 +84,7 @@ export default class OperationsServiceRatesIndexController extends Controller {
75
84
  filterable: false,
76
85
  },
77
86
  {
87
+ id: 'service-area-name',
78
88
  label: this.intl.t('column.service-area'),
79
89
  valuePath: 'service_area.name',
80
90
  cellComponent: 'cell/service-area-identity',
@@ -90,6 +100,7 @@ export default class OperationsServiceRatesIndexController extends Controller {
90
100
  model: 'service-area',
91
101
  },
92
102
  {
103
+ id: 'zone-name',
93
104
  label: this.intl.t('column.zone'),
94
105
  valuePath: 'zone.name',
95
106
  cellComponent: 'cell/zone-identity',
@@ -104,6 +115,7 @@ export default class OperationsServiceRatesIndexController extends Controller {
104
115
  model: 'zone',
105
116
  },
106
117
  {
118
+ id: 'created-at',
107
119
  label: this.intl.t('column.created-at'),
108
120
  valuePath: 'createdAt',
109
121
  sortParam: 'created_at',
@@ -113,6 +125,7 @@ export default class OperationsServiceRatesIndexController extends Controller {
113
125
  filterComponent: 'filter/date',
114
126
  },
115
127
  {
128
+ id: 'updated-at',
116
129
  label: this.intl.t('column.updated-at'),
117
130
  valuePath: 'updatedAt',
118
131
  sortParam: 'updated_at',
@@ -123,6 +136,7 @@ export default class OperationsServiceRatesIndexController extends Controller {
123
136
  filterComponent: 'filter/date',
124
137
  },
125
138
  {
139
+ id: 'row-actions',
126
140
  label: '',
127
141
  cellComponent: 'table/cell/dropdown',
128
142
  ddButtonText: false,
@@ -134,18 +148,21 @@ export default class OperationsServiceRatesIndexController extends Controller {
134
148
  width: 60,
135
149
  actions: [
136
150
  {
151
+ id: 'view',
137
152
  label: this.intl.t('common.view-resource', { resource: this.intl.t('resource.service-rate') }),
138
153
  icon: 'eye',
139
154
  fn: this.serviceRateActions.transition.view,
140
155
  permission: 'fleet-ops view service-rate',
141
156
  },
142
157
  {
158
+ id: 'edit',
143
159
  label: this.intl.t('common.edit-resource', { resource: this.intl.t('resource.service-rate') }),
144
160
  icon: 'pencil',
145
161
  fn: this.serviceRateActions.transition.edit,
146
162
  permission: 'fleet-ops view service-rate',
147
163
  },
148
164
  {
165
+ id: 'delete',
149
166
  label: this.intl.t('common.delete-resource', { resource: this.intl.t('resource.service-rate') }),
150
167
  icon: 'trash',
151
168
  fn: this.serviceRateActions.delete,
@@ -28,6 +28,12 @@ export default class SettingsIndexController extends Controller {
28
28
  description: 'Keep commerce, metadata, and visual conventions aligned.',
29
29
  links: [
30
30
  { label: 'Payments', route: 'settings.payments', icon: 'cash-register', description: 'Payment setup for operational commerce workflows.' },
31
+ {
32
+ label: 'Telematics',
33
+ route: 'settings.telematics',
34
+ icon: 'satellite-dish',
35
+ description: 'Device event and position history preferences within the system retention policy.',
36
+ },
31
37
  { label: 'Custom Fields', route: 'settings.custom-fields', icon: 'pen-to-square', description: 'Operational metadata fields for Fleet-Ops records.' },
32
38
  { label: 'Avatars', route: 'settings.avatars', icon: 'icons', description: 'Visual assets for driver, vehicle, and map displays.' },
33
39
  ],
@@ -113,6 +119,13 @@ export default class SettingsIndexController extends Controller {
113
119
  title: 'Scheduling settings',
114
120
  description: 'Manage schedule templates and timing rules for planned work.',
115
121
  },
122
+ {
123
+ label: 'Telematics',
124
+ icon: 'satellite-dish',
125
+ slug: 'fleet-ops/settings/telematics',
126
+ title: 'Telematics Settings',
127
+ description: 'Choose how long your organization keeps device events and position history.',
128
+ },
116
129
  {
117
130
  label: 'Custom Fields',
118
131
  icon: 'pen-to-square',
@@ -0,0 +1,113 @@
1
+ import Controller from '@ember/controller';
2
+ import { tracked } from '@glimmer/tracking';
3
+ import { inject as service } from '@ember/service';
4
+ import { action } from '@ember/object';
5
+ import { task } from 'ember-concurrency';
6
+
7
+ /** Organization history preferences, subject to the system retention policy. */
8
+ export default class SettingsTelematicsController extends Controller {
9
+ @service fetch;
10
+ @service notifications;
11
+ @service intl;
12
+
13
+ @tracked eventRetentionDays = 30;
14
+ @tracked positionRetentionDays = 90;
15
+ @tracked useDefaultEventRetention = true;
16
+ @tracked useDefaultPositionRetention = true;
17
+ @tracked defaults = {};
18
+ @tracked policy = {};
19
+ @tracked settingsLoaded = false;
20
+
21
+ get eventRetentionMinimum() {
22
+ return this.policy.max_event_retention_days > 0 ? 1 : 0;
23
+ }
24
+
25
+ get eventRetentionMaximum() {
26
+ return this.policy.max_event_retention_days > 0 ? this.policy.max_event_retention_days : 3650;
27
+ }
28
+
29
+ get positionRetentionMinimum() {
30
+ return this.policy.max_position_retention_days > 0 ? 1 : 0;
31
+ }
32
+
33
+ get positionRetentionMaximum() {
34
+ return this.policy.max_position_retention_days > 0 ? this.policy.max_position_retention_days : 3650;
35
+ }
36
+
37
+ get eventRetentionPolicyHelp() {
38
+ return this.retentionPolicyHelp(this.policy.max_event_retention_days);
39
+ }
40
+
41
+ get positionRetentionPolicyHelp() {
42
+ return this.retentionPolicyHelp(this.policy.max_position_retention_days);
43
+ }
44
+
45
+ get settingsPayload() {
46
+ return {
47
+ event_retention_days: this.useDefaultEventRetention ? null : this.eventRetentionDays,
48
+ position_retention_days: this.useDefaultPositionRetention ? null : this.positionRetentionDays,
49
+ };
50
+ }
51
+
52
+ @task({ restartable: true }) *getSettings() {
53
+ this.settingsLoaded = false;
54
+
55
+ try {
56
+ const settings = yield this.fetch.get('fleet-ops/settings/telematics-settings');
57
+ this.applySettings(settings);
58
+ this.settingsLoaded = true;
59
+ } catch (error) {
60
+ this.notifications.serverError(error);
61
+ }
62
+ }
63
+
64
+ @task({ drop: true }) *saveSettings() {
65
+ if (!this.settingsLoaded) {
66
+ return;
67
+ }
68
+
69
+ try {
70
+ const settings = yield this.fetch.post('fleet-ops/settings/telematics-settings', this.settingsPayload);
71
+ this.applySettings(settings);
72
+ this.notifications.success(this.intl.t('settings.telematics.settings-saved'));
73
+ } catch (error) {
74
+ this.notifications.serverError(error);
75
+ }
76
+ }
77
+
78
+ @action setUseDefaultEventRetention(enabled) {
79
+ this.useDefaultEventRetention = enabled;
80
+ if (enabled) {
81
+ this.eventRetentionDays = this.defaults.event_retention_days ?? this.eventRetentionDays;
82
+ }
83
+ }
84
+
85
+ @action setUseDefaultPositionRetention(enabled) {
86
+ this.useDefaultPositionRetention = enabled;
87
+ if (enabled) {
88
+ this.positionRetentionDays = this.defaults.position_retention_days ?? this.positionRetentionDays;
89
+ }
90
+ }
91
+
92
+ applySettings(settings = {}) {
93
+ const has = (object, key) => Object.prototype.hasOwnProperty.call(object ?? {}, key);
94
+ const hasHistoryMetadata = ['event_retention_days', 'position_retention_days'].every(
95
+ (key) => has(settings?.preferences, key) && has(settings?.defaults, key) && has(settings?.policy, `max_${key}`)
96
+ );
97
+
98
+ if (!hasHistoryMetadata) {
99
+ throw new Error(this.intl.t('settings.telematics.settings-unavailable'));
100
+ }
101
+
102
+ this.eventRetentionDays = settings.event_retention_days ?? this.eventRetentionDays;
103
+ this.positionRetentionDays = settings.position_retention_days ?? this.positionRetentionDays;
104
+ this.useDefaultEventRetention = (settings.preferences?.event_retention_days ?? null) === null;
105
+ this.useDefaultPositionRetention = (settings.preferences?.position_retention_days ?? null) === null;
106
+ this.defaults = settings.defaults ?? this.defaults;
107
+ this.policy = settings.policy ?? this.policy;
108
+ }
109
+
110
+ retentionPolicyHelp(maximum) {
111
+ return maximum > 0 ? this.intl.t('settings.telematics.history-policy-maximum', { days: maximum }) : this.intl.t('settings.telematics.history-policy-unlimited');
112
+ }
113
+ }