@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
@@ -16,7 +16,7 @@ export default class ManagementVehiclesIndexController extends Controller {
16
16
  @service appCache;
17
17
 
18
18
  /** query params */
19
- @tracked queryParams = [
19
+ @tracked queryParams = this.vehicleActions.queryParamsFor([
20
20
  'page',
21
21
  'limit',
22
22
  'sort',
@@ -38,7 +38,7 @@ export default class ManagementVehiclesIndexController extends Controller {
38
38
  'has_trailer',
39
39
  'has_driver',
40
40
  'has_device',
41
- ];
41
+ ]);
42
42
  @tracked query = null;
43
43
  @tracked page = 1;
44
44
  @tracked limit;
@@ -68,6 +68,7 @@ export default class ManagementVehiclesIndexController extends Controller {
68
68
  get actionButtons() {
69
69
  return [
70
70
  {
71
+ id: 'more',
71
72
  component: 'dropdown-button',
72
73
  icon: 'display',
73
74
  size: 'xs',
@@ -93,28 +94,35 @@ export default class ManagementVehiclesIndexController extends Controller {
93
94
  helpText: 'Change the layout',
94
95
  },
95
96
  {
97
+ id: 'refresh',
96
98
  icon: 'refresh',
97
99
  onClick: this.vehicleActions.refresh,
98
100
  helpText: this.intl.t('common.refresh'),
99
101
  },
100
102
  {
103
+ id: 'create',
101
104
  text: this.intl.t('common.new'),
102
105
  type: 'primary',
103
106
  icon: 'plus',
104
107
  onClick: this.vehicleActions.transition.create,
108
+ permission: 'fleet-ops create vehicle',
105
109
  },
106
110
  {
111
+ id: 'import',
107
112
  text: this.intl.t('common.import'),
108
113
  type: 'magic',
109
114
  icon: 'upload',
110
115
  onClick: this.vehicleActions.import,
116
+ permission: 'fleet-ops import vehicle',
111
117
  },
112
118
  {
119
+ id: 'export',
113
120
  text: this.intl.t('common.export'),
114
121
  icon: 'long-arrow-up',
115
122
  iconClass: 'rotate-icon-45',
116
123
  wrapperClass: 'hidden md:flex',
117
124
  onClick: this.vehicleActions.export,
125
+ permission: 'fleet-ops export vehicle',
118
126
  },
119
127
  ];
120
128
  }
@@ -125,9 +133,11 @@ export default class ManagementVehiclesIndexController extends Controller {
125
133
 
126
134
  return [
127
135
  {
136
+ id: 'bulk-delete',
128
137
  label: this.intl.t('common.delete-selected-count', { count: selected.length }),
129
138
  class: 'text-red-500',
130
139
  fn: this.vehicleActions.bulkDelete,
140
+ permission: 'fleet-ops delete vehicle',
131
141
  },
132
142
  ];
133
143
  }
@@ -147,6 +157,7 @@ export default class ManagementVehiclesIndexController extends Controller {
147
157
  get columns() {
148
158
  return [
149
159
  {
160
+ id: 'display-name',
150
161
  sticky: true,
151
162
  label: this.intl.t('column.name'),
152
163
  valuePath: 'displayName',
@@ -161,6 +172,7 @@ export default class ManagementVehiclesIndexController extends Controller {
161
172
  filterParam: 'name',
162
173
  },
163
174
  {
175
+ id: 'plate-number',
164
176
  label: this.intl.t('column.plate-number'),
165
177
  valuePath: 'plate_number',
166
178
  cellComponent: 'table/cell/base',
@@ -172,6 +184,7 @@ export default class ManagementVehiclesIndexController extends Controller {
172
184
  filterParam: 'plate_number',
173
185
  },
174
186
  {
187
+ id: 'internal-id',
175
188
  label: this.intl.t('column.internal-id'),
176
189
  valuePath: 'internal_id',
177
190
  cellComponent: 'table/cell/base',
@@ -184,6 +197,7 @@ export default class ManagementVehiclesIndexController extends Controller {
184
197
  filterParam: 'internal_id',
185
198
  },
186
199
  {
200
+ id: 'driver-name',
187
201
  label: this.intl.t('column.driver-assigned'),
188
202
  cellComponent: 'cell/driver-identity',
189
203
  permission: 'fleet-ops view driver',
@@ -199,6 +213,7 @@ export default class ManagementVehiclesIndexController extends Controller {
199
213
  model: 'driver',
200
214
  },
201
215
  {
216
+ id: 'trailers',
202
217
  label: this.intl.t('resource.trailers'),
203
218
  valuePath: 'trailers',
204
219
  cellComponent: 'cell/resource-list',
@@ -212,6 +227,7 @@ export default class ManagementVehiclesIndexController extends Controller {
212
227
  modelNamePath: 'displayName',
213
228
  },
214
229
  {
230
+ id: 'devices',
215
231
  label: this.intl.t('resource.devices'),
216
232
  valuePath: 'devices',
217
233
  cellComponent: 'cell/resource-list',
@@ -225,6 +241,7 @@ export default class ManagementVehiclesIndexController extends Controller {
225
241
  modelNamePath: 'displayName',
226
242
  },
227
243
  {
244
+ id: 'public-id',
228
245
  label: this.intl.t('column.id'),
229
246
  valuePath: 'public_id',
230
247
  cellComponent: 'click-to-copy',
@@ -234,6 +251,7 @@ export default class ManagementVehiclesIndexController extends Controller {
234
251
  filterComponent: 'filter/string',
235
252
  },
236
253
  {
254
+ id: 'make',
237
255
  label: this.intl.t('column.make'),
238
256
  valuePath: 'make',
239
257
  cellComponent: 'table/cell/base',
@@ -245,6 +263,7 @@ export default class ManagementVehiclesIndexController extends Controller {
245
263
  filterComponent: 'filter/string',
246
264
  },
247
265
  {
266
+ id: 'model',
248
267
  label: this.intl.t('column.model'),
249
268
  valuePath: 'model',
250
269
  cellComponent: 'table/cell/base',
@@ -256,6 +275,7 @@ export default class ManagementVehiclesIndexController extends Controller {
256
275
  filterComponent: 'filter/string',
257
276
  },
258
277
  {
278
+ id: 'year',
259
279
  label: this.intl.t('column.year'),
260
280
  valuePath: 'year',
261
281
  cellComponent: 'table/cell/base',
@@ -266,6 +286,7 @@ export default class ManagementVehiclesIndexController extends Controller {
266
286
  filterComponent: 'filter/string',
267
287
  },
268
288
  {
289
+ id: 'vendor-name',
269
290
  label: this.intl.t('column.vendor'),
270
291
  cellComponent: 'cell/vendor-identity',
271
292
  permission: 'fleet-ops view vendor',
@@ -283,6 +304,7 @@ export default class ManagementVehiclesIndexController extends Controller {
283
304
  model: 'vendor',
284
305
  },
285
306
  {
307
+ id: 'status',
286
308
  label: this.intl.t('column.status'),
287
309
  valuePath: 'status',
288
310
  cellComponent: 'table/cell/status',
@@ -293,6 +315,7 @@ export default class ManagementVehiclesIndexController extends Controller {
293
315
  filterFetchOptions: 'vehicles/statuses',
294
316
  },
295
317
  {
318
+ id: 'created-at',
296
319
  label: this.intl.t('column.created-at'),
297
320
  valuePath: 'createdAt',
298
321
  sortParam: 'created_at',
@@ -304,6 +327,7 @@ export default class ManagementVehiclesIndexController extends Controller {
304
327
  filterComponent: 'filter/date',
305
328
  },
306
329
  {
330
+ id: 'updated-at',
307
331
  label: this.intl.t('column.updated-at'),
308
332
  valuePath: 'updatedAt',
309
333
  sortParam: 'updated_at',
@@ -347,6 +371,7 @@ export default class ManagementVehiclesIndexController extends Controller {
347
371
  filterParam: 'has_device',
348
372
  },
349
373
  {
374
+ id: 'row-actions',
350
375
  label: '',
351
376
  cellComponent: 'table/cell/dropdown',
352
377
  ddButtonText: false,
@@ -359,26 +384,31 @@ export default class ManagementVehiclesIndexController extends Controller {
359
384
  width: 60,
360
385
  actions: [
361
386
  {
387
+ id: 'view',
362
388
  label: this.intl.t('common.view-resource', { resource: this.intl.t('resource.vehicle') }),
363
389
  fn: this.vehicleActions.transition.view,
364
390
  permission: 'fleet-ops view vehicle',
365
391
  },
366
392
  {
393
+ id: 'edit',
367
394
  label: this.intl.t('common.edit-resource', { resource: this.intl.t('resource.vehicle') }),
368
395
  fn: this.vehicleActions.transition.edit,
369
396
  permission: 'fleet-ops update vehicle',
370
397
  },
371
398
  {
399
+ id: 'locate',
372
400
  label: this.intl.t('vehicle.actions.locate-vehicle'),
373
401
  fn: this.vehicleActions.locate,
374
402
  permission: 'fleet-ops view vehicle',
375
403
  },
376
404
  {
405
+ id: 'attach-device',
377
406
  label: this.intl.t('vehicle.actions.attach-device'),
378
407
  fn: this.vehicleActions.attachDevice,
379
408
  permission: 'fleet-ops update vehicle',
380
409
  },
381
410
  {
411
+ id: 'unassign-orders',
382
412
  label: this.intl.t('vehicle.actions.unassign-orders'),
383
413
  fn: this.vehicleActions.unassignOrders,
384
414
  permission: 'fleet-ops update vehicle',
@@ -388,21 +418,25 @@ export default class ManagementVehiclesIndexController extends Controller {
388
418
  separator: true,
389
419
  },
390
420
  {
421
+ id: 'schedule-maintenance',
391
422
  label: this.intl.t('vehicle.actions.schedule-maintenance'),
392
423
  fn: this.vehicleActions.scheduleMaintenance,
393
424
  permission: 'fleet-ops create maintenance-schedule',
394
425
  },
395
426
  {
427
+ id: 'create-work-order',
396
428
  label: this.intl.t('vehicle.actions.create-work-order'),
397
429
  fn: this.vehicleActions.createWorkOrder,
398
430
  permission: 'fleet-ops create work-order',
399
431
  },
400
432
  {
433
+ id: 'log-maintenance',
401
434
  label: this.intl.t('vehicle.actions.log-maintenance'),
402
435
  fn: this.vehicleActions.logMaintenance,
403
436
  permission: 'fleet-ops create maintenance',
404
437
  },
405
438
  {
439
+ id: 'create-issue',
406
440
  label: this.intl.t('vehicle.actions.create-issue'),
407
441
  fn: this.createIssue,
408
442
  permission: 'fleet-ops create issue',
@@ -411,6 +445,7 @@ export default class ManagementVehiclesIndexController extends Controller {
411
445
  separator: true,
412
446
  },
413
447
  {
448
+ id: 'delete',
414
449
  label: this.intl.t('common.delete-resource', { resource: this.intl.t('resource.vehicle') }),
415
450
  fn: this.vehicleActions.delete,
416
451
  permission: 'fleet-ops delete vehicle',
@@ -13,7 +13,7 @@ export default class ManagementVendorsIndexController extends Controller {
13
13
  @service appCache;
14
14
 
15
15
  /** query params */
16
- @tracked queryParams = [
16
+ @tracked queryParams = this.vendorActions.queryParamsFor([
17
17
  'page',
18
18
  'limit',
19
19
  'sort',
@@ -30,7 +30,7 @@ export default class ManagementVendorsIndexController extends Controller {
30
30
  'country',
31
31
  'address',
32
32
  'website_url',
33
- ];
33
+ ]);
34
34
  @tracked page = 1;
35
35
  @tracked limit;
36
36
  @tracked sort = '-created_at';
@@ -55,16 +55,19 @@ export default class ManagementVendorsIndexController extends Controller {
55
55
  get actionButtons() {
56
56
  return [
57
57
  {
58
+ id: 'more',
58
59
  component: 'dropdown-button',
59
60
  icon: 'display',
60
61
  size: 'xs',
61
62
  items: [
62
63
  {
64
+ id: 'table-view',
63
65
  label: this.intl.t('common.table-view'),
64
66
  icon: 'table-list',
65
67
  onClick: () => this.setLayout('table'),
66
68
  },
67
69
  {
70
+ id: 'grid-view',
68
71
  label: this.intl.t('common.grid-view'),
69
72
  icon: 'grip',
70
73
  onClick: () => this.setLayout('grid'),
@@ -74,28 +77,35 @@ export default class ManagementVendorsIndexController extends Controller {
74
77
  helpText: this.intl.t('common.change-layout'),
75
78
  },
76
79
  {
80
+ id: 'refresh',
77
81
  icon: 'refresh',
78
82
  onClick: this.vendorActions.refresh,
79
83
  helpText: this.intl.t('common.refresh'),
80
84
  },
81
85
  {
86
+ id: 'create',
82
87
  text: this.intl.t('common.new'),
83
88
  type: 'primary',
84
89
  icon: 'plus',
85
90
  onClick: this.vendorActions.transition.create,
91
+ permission: 'fleet-ops create vendor',
86
92
  },
87
93
  {
94
+ id: 'import',
88
95
  text: this.intl.t('common.import'),
89
96
  type: 'magic',
90
97
  icon: 'upload',
91
98
  onClick: this.vendorActions.import,
99
+ permission: 'fleet-ops import vendor',
92
100
  },
93
101
  {
102
+ id: 'export',
94
103
  text: this.intl.t('common.export'),
95
104
  icon: 'long-arrow-up',
96
105
  iconClass: 'rotate-icon-45',
97
106
  wrapperClass: 'hidden md:flex',
98
107
  onClick: this.vendorActions.export,
108
+ permission: 'fleet-ops export vendor',
99
109
  },
100
110
  ];
101
111
  }
@@ -106,9 +116,11 @@ export default class ManagementVendorsIndexController extends Controller {
106
116
 
107
117
  return [
108
118
  {
119
+ id: 'bulk-delete',
109
120
  label: this.intl.t('common.delete-selected-count', { count: selected.length }),
110
121
  class: 'text-red-500',
111
122
  fn: this.vendorActions.bulkDelete,
123
+ permission: 'fleet-ops delete vendor',
112
124
  },
113
125
  ];
114
126
  }
@@ -117,6 +129,7 @@ export default class ManagementVendorsIndexController extends Controller {
117
129
  get columns() {
118
130
  return [
119
131
  {
132
+ id: 'name',
120
133
  sticky: true,
121
134
  label: this.intl.t('column.name'),
122
135
  valuePath: 'name',
@@ -130,6 +143,7 @@ export default class ManagementVendorsIndexController extends Controller {
130
143
  filterComponent: 'filter/string',
131
144
  },
132
145
  {
146
+ id: 'public-id',
133
147
  label: this.intl.t('column.id'),
134
148
  valuePath: 'public_id',
135
149
  cellComponent: 'click-to-copy',
@@ -139,6 +153,7 @@ export default class ManagementVendorsIndexController extends Controller {
139
153
  filterComponent: 'filter/string',
140
154
  },
141
155
  {
156
+ id: 'internal-id',
142
157
  label: this.intl.t('column.internal-id'),
143
158
  valuePath: 'internal_id',
144
159
  cellComponent: 'click-to-copy',
@@ -148,6 +163,7 @@ export default class ManagementVendorsIndexController extends Controller {
148
163
  filterComponent: 'filter/string',
149
164
  },
150
165
  {
166
+ id: 'email',
151
167
  label: this.intl.t('column.email'),
152
168
  valuePath: 'email',
153
169
  cellComponent: 'click-to-copy',
@@ -158,6 +174,7 @@ export default class ManagementVendorsIndexController extends Controller {
158
174
  filterComponent: 'filter/string',
159
175
  },
160
176
  {
177
+ id: 'website-url',
161
178
  label: this.intl.t('column.website-url'),
162
179
  valuePath: 'website_url',
163
180
  cellComponent: 'click-to-copy',
@@ -168,6 +185,7 @@ export default class ManagementVendorsIndexController extends Controller {
168
185
  filterComponent: 'filter/string',
169
186
  },
170
187
  {
188
+ id: 'phone',
171
189
  label: this.intl.t('column.phone'),
172
190
  valuePath: 'phone',
173
191
  cellComponent: 'click-to-copy',
@@ -178,6 +196,7 @@ export default class ManagementVendorsIndexController extends Controller {
178
196
  filterComponent: 'filter/string',
179
197
  },
180
198
  {
199
+ id: 'address',
181
200
  label: this.intl.t('column.address'),
182
201
  valuePath: 'address',
183
202
  cellComponent: 'cell/place-identity',
@@ -190,6 +209,7 @@ export default class ManagementVendorsIndexController extends Controller {
190
209
  filterComponent: 'filter/string',
191
210
  },
192
211
  {
212
+ id: 'pretty-type',
193
213
  label: this.intl.t('column.type'),
194
214
  valuePath: 'prettyType',
195
215
  humanize: true,
@@ -200,6 +220,7 @@ export default class ManagementVendorsIndexController extends Controller {
200
220
  filterComponent: 'filter/string',
201
221
  },
202
222
  {
223
+ id: 'country',
203
224
  label: this.intl.t('column.country'),
204
225
  valuePath: 'country',
205
226
  cellComponent: 'table/cell/base',
@@ -212,6 +233,7 @@ export default class ManagementVendorsIndexController extends Controller {
212
233
  filterParam: 'country',
213
234
  },
214
235
  {
236
+ id: 'created-at',
215
237
  label: this.intl.t('column.created-at'),
216
238
  valuePath: 'createdAt',
217
239
  sortParam: 'created_at',
@@ -221,6 +243,7 @@ export default class ManagementVendorsIndexController extends Controller {
221
243
  filterComponent: 'filter/date',
222
244
  },
223
245
  {
246
+ id: 'updated-at',
224
247
  label: this.intl.t('column.updated-at'),
225
248
  valuePath: 'updatedAt',
226
249
  sortParam: 'updated_at',
@@ -231,6 +254,7 @@ export default class ManagementVendorsIndexController extends Controller {
231
254
  filterComponent: 'filter/date',
232
255
  },
233
256
  {
257
+ id: 'status',
234
258
  label: this.intl.t('column.status'),
235
259
  valuePath: 'status',
236
260
  cellComponent: 'table/cell/status',
@@ -243,6 +267,7 @@ export default class ManagementVendorsIndexController extends Controller {
243
267
  filterOptions: fleetOpsOptions('vendorStatuses'),
244
268
  },
245
269
  {
270
+ id: 'row-actions',
246
271
  label: '',
247
272
  cellComponent: 'table/cell/dropdown',
248
273
  ddButtonText: false,
@@ -255,11 +280,13 @@ export default class ManagementVendorsIndexController extends Controller {
255
280
  width: 60,
256
281
  actions: [
257
282
  {
283
+ id: 'view',
258
284
  label: this.intl.t('common.view-resource', { resource: this.intl.t('resource.vendor') }),
259
285
  fn: this.vendorActions.transition.view,
260
286
  permission: 'fleet-ops view vendor',
261
287
  },
262
288
  {
289
+ id: 'edit',
263
290
  label: this.intl.t('common.edit-resource', { resource: this.intl.t('resource.vendor') }),
264
291
  fn: this.vendorActions.transition.edit,
265
292
  permission: 'fleet-ops update vendor',
@@ -268,6 +295,7 @@ export default class ManagementVendorsIndexController extends Controller {
268
295
  separator: true,
269
296
  },
270
297
  {
298
+ id: 'delete',
271
299
  label: this.intl.t('common.delete-resource', { resource: this.intl.t('resource.vendor') }),
272
300
  fn: this.vendorActions.delete,
273
301
  permission: 'fleet-ops delete vendor',
@@ -17,6 +17,8 @@ export default class OperationsOrdersIndexDetailsController extends Controller {
17
17
  @service hostRouter;
18
18
  @service universe;
19
19
  @service sidebar;
20
+ @service orderPresentation;
21
+ @service abilities;
20
22
  @tracked routingControl;
21
23
  @tracked routingCompleted = false;
22
24
  @tracked realtimeOrderPublicId = null;
@@ -83,45 +85,70 @@ export default class OperationsOrdersIndexDetailsController extends Controller {
83
85
  ];
84
86
  }
85
87
 
88
+ /** True when the order reached a terminal activity (default or configured lifecycle). */
89
+ get isClosed() {
90
+ const status = this.model.status;
91
+ const lifecycle = this.model.order_config?.meta?.lifecycle;
92
+ if (!lifecycle) {
93
+ return status === 'canceled';
94
+ }
95
+
96
+ // Matches OrderConfig::getTerminalActivityCodes(): `terminal` plus the configured completed and canceled codes.
97
+ const terminal = [...(Array.isArray(lifecycle.terminal) ? lifecycle.terminal : []), lifecycle.completed, lifecycle.canceled].filter(Boolean);
98
+ return status === 'canceled' || terminal.includes(status);
99
+ }
100
+
86
101
  get actionButtons() {
102
+ const isHidden = (id) => this.orderPresentation.isHidden(this.model, 'actions', id);
103
+
87
104
  return [
88
105
  {
89
106
  items: [
90
107
  {
108
+ id: 'edit-order-details',
91
109
  text: 'Edit details',
92
110
  icon: 'pencil',
93
- disabled: this.model.status === 'canceled',
111
+ disabled: this.isClosed,
112
+ permission: 'fleet-ops update order',
94
113
  fn: () => this.orderActions.editOrderDetails(this.model),
95
114
  },
96
115
  {
116
+ id: 'update-activity',
97
117
  text: 'Update activity',
98
118
  icon: 'signal',
99
- disabled: this.model.status === 'canceled',
119
+ disabled: this.isClosed,
120
+ permission: 'fleet-ops update order',
100
121
  fn: () =>
101
122
  this.orderActions.updateActivity(this.model, {
102
123
  onFinish: this.handleActivityModalFinish,
103
124
  }),
104
125
  },
105
126
  {
127
+ id: this.model.has_driver_assigned ? 'unassign-driver' : 'assign-driver',
106
128
  text: this.model.has_driver_assigned ? 'Unassign driver' : 'Assign driver',
107
129
  icon: this.model.has_driver_assigned ? 'user-xmark' : 'edit',
130
+ permission: 'fleet-ops assign-driver-for order',
108
131
  disabled: this.model.has_driver_assigned ? !this.model.hasActiveStatus || !this.model.driver_assigned : !this.model.hasActiveStatus,
109
132
  fn: () => (this.model.has_driver_assigned ? this.orderActions.unassignDriver(this.model) : this.orderActions.assignDriver(this.model)),
110
133
  },
111
134
  {
135
+ id: 'view-label',
112
136
  text: 'View order label',
113
137
  icon: 'file-invoice',
138
+ permission: 'fleet-ops view order',
114
139
  fn: () => this.orderActions.viewLabel(this.model),
115
140
  },
116
141
  {
117
142
  separator: true,
118
143
  },
119
144
  {
145
+ id: 'listen-to-socket-channel',
120
146
  text: 'Listen to socket channel',
121
147
  icon: 'headphones',
122
148
  fn: () => this.hostRouter.transitionTo('console.developers.sockets.view', `order.${this.model.public_id}`),
123
149
  },
124
150
  {
151
+ id: 'view-metadata',
125
152
  text: 'View metadata',
126
153
  icon: 'table',
127
154
  fn: () => this.orderActions.viewMetadata(this.model),
@@ -130,16 +157,20 @@ export default class OperationsOrdersIndexDetailsController extends Controller {
130
157
  separator: true,
131
158
  },
132
159
  {
160
+ id: 'cancel',
133
161
  text: 'Cancel order',
134
162
  icon: 'ban',
135
163
  class: 'text-danger',
136
- disabled: this.model.status === 'canceled',
164
+ disabled: this.isClosed,
165
+ permission: 'fleet-ops cancel order',
137
166
  fn: () => this.orderActions.cancel(this.model),
138
167
  },
139
168
  {
169
+ id: 'delete',
140
170
  text: 'Delete order',
141
171
  icon: 'trash',
142
172
  class: 'text-danger',
173
+ permission: 'fleet-ops delete order',
143
174
  fn: () =>
144
175
  this.orderActions.delete(this.model, {
145
176
  taskOptions: {
@@ -149,9 +180,34 @@ export default class OperationsOrdersIndexDetailsController extends Controller {
149
180
  },
150
181
  }),
151
182
  },
152
- ].filter(Boolean),
183
+ ]
184
+ .filter(Boolean)
185
+ .filter((item) => !item.id || !isHidden(item.id))
186
+ .filter((item, index, items) => !(item.separator && (index === 0 || items[index - 1]?.separator))),
153
187
  },
154
- ];
188
+ ].map((actionButton) => ({ ...actionButton, items: this.permittedMenuItems(actionButton.items) }));
189
+ }
190
+
191
+ /**
192
+ * The panel header dropdown renders `items` as-is and ignores `permission`, so items the
193
+ * user is not permitted to use are removed here, along with any separators left dangling.
194
+ */
195
+ permittedMenuItems(items = []) {
196
+ const permitted = items.filter((item) => !item.permission || this.abilities.can(item.permission));
197
+ const result = permitted.reduce((list, item) => {
198
+ if (item.separator && (list.length === 0 || list[list.length - 1].separator)) {
199
+ return list;
200
+ }
201
+
202
+ list.push(item);
203
+ return list;
204
+ }, []);
205
+
206
+ if (result.length && result[result.length - 1].separator) {
207
+ result.pop();
208
+ }
209
+
210
+ return result;
155
211
  }
156
212
 
157
213
  @action handleActivityModalFinish(options) {