@fleetbase/fleetops-engine 0.6.68 → 0.6.70

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 (294) hide show
  1. package/RELEASE.md +44 -9
  2. package/addon/components/admin/telematics-settings.hbs +143 -0
  3. package/addon/components/admin/telematics-settings.js +145 -0
  4. package/addon/components/contact/form.hbs +13 -2
  5. package/addon/components/customer/details.hbs +17 -17
  6. package/addon/components/customer/form.hbs +13 -2
  7. package/addon/components/customer/form.js +0 -56
  8. package/addon/components/driver/details.hbs +13 -19
  9. package/addon/components/driver/form.hbs +20 -35
  10. package/addon/components/driver/form.js +0 -58
  11. package/addon/components/fuel-integration/hub.hbs +1 -1
  12. package/addon/components/layout/fleet-ops-sidebar.js +37 -17
  13. package/addon/components/map/leaflet-live-map.hbs +4 -242
  14. package/addon/components/map/leaflet-live-map.js +2 -1
  15. package/addon/components/map/marker-card/driver.hbs +57 -0
  16. package/addon/components/map/marker-card/driver.js +3 -0
  17. package/addon/components/map/marker-card/vehicle.hbs +78 -0
  18. package/addon/components/map/marker-card/vehicle.js +3 -0
  19. package/addon/components/modals/driver-form.hbs +2 -2
  20. package/addon/components/modals/reset-profile-credentials.hbs +23 -0
  21. package/addon/components/modals/reset-profile-credentials.js +70 -0
  22. package/addon/components/profile-identity-hint.hbs +13 -0
  23. package/addon/components/profile-identity-hint.js +49 -0
  24. package/addon/components/telematic/hub.hbs +1 -1
  25. package/addon/components/widget/live-fleet.hbs +8 -40
  26. package/addon/controllers/analytics/reports/index.js +5 -0
  27. package/addon/controllers/connectivity/devices/index.js +4 -0
  28. package/addon/controllers/connectivity/fuel-providers/index.js +6 -4
  29. package/addon/controllers/connectivity/sensors/index.js +4 -0
  30. package/addon/controllers/connectivity/telematics/index.js +4 -0
  31. package/addon/controllers/maintenance/equipment/index.js +11 -4
  32. package/addon/controllers/maintenance/inspection-forms/index.js +2 -2
  33. package/addon/controllers/maintenance/inspection-submissions/index.js +8 -2
  34. package/addon/controllers/maintenance/maintenances/index.js +4 -0
  35. package/addon/controllers/maintenance/parts/index.js +11 -4
  36. package/addon/controllers/maintenance/schedules/index.js +17 -4
  37. package/addon/controllers/maintenance/work-orders/index.js +11 -4
  38. package/addon/controllers/management/contacts/index.js +4 -0
  39. package/addon/controllers/management/drivers/index.js +8 -0
  40. package/addon/controllers/management/fleets/index.js +4 -0
  41. package/addon/controllers/management/fuel-reports/index.js +4 -0
  42. package/addon/controllers/management/fuel-transactions/index.js +9 -7
  43. package/addon/controllers/management/issues/index.js +4 -0
  44. package/addon/controllers/management/places/index.js +4 -0
  45. package/addon/controllers/management/vehicles/index.js +4 -0
  46. package/addon/controllers/management/vendors/index.js +4 -0
  47. package/addon/controllers/operations/orders/index/details.js +30 -1
  48. package/addon/controllers/operations/orders/index.js +7 -0
  49. package/addon/controllers/operations/service-rates/index.js +3 -0
  50. package/addon/controllers/settings/index.js +13 -0
  51. package/addon/controllers/settings/telematics.js +113 -0
  52. package/addon/extension.js +42 -8
  53. package/addon/routes/analytics/index.js +14 -1
  54. package/addon/routes/analytics/reports/index/details.js +1 -1
  55. package/addon/routes/analytics/reports/index/edit.js +1 -1
  56. package/addon/routes/analytics/reports/index/new.js +14 -1
  57. package/addon/routes/analytics/reports.js +14 -1
  58. package/addon/routes/connectivity/devices/index/new.js +14 -1
  59. package/addon/routes/connectivity/devices.js +14 -1
  60. package/addon/routes/connectivity/events.js +14 -1
  61. package/addon/routes/connectivity/fuel-providers/details/transactions.js +12 -0
  62. package/addon/routes/connectivity/fuel-providers/details.js +9 -0
  63. package/addon/routes/connectivity/fuel-providers/edit.js +9 -0
  64. package/addon/routes/connectivity/fuel-providers/new.js +14 -1
  65. package/addon/routes/connectivity/fuel-providers.js +14 -1
  66. package/addon/routes/connectivity/sensors/index/new.js +14 -1
  67. package/addon/routes/connectivity/sensors.js +14 -1
  68. package/addon/routes/connectivity/telematics/new.js +14 -1
  69. package/addon/routes/connectivity/telematics.js +14 -1
  70. package/addon/routes/connectivity/tracking.js +14 -1
  71. package/addon/routes/maintenance/equipment/index/details.js +2 -2
  72. package/addon/routes/maintenance/equipment/index/edit.js +2 -2
  73. package/addon/routes/maintenance/equipment/index/new.js +14 -1
  74. package/addon/routes/maintenance/equipment.js +14 -1
  75. package/addon/routes/maintenance/index.js +14 -1
  76. package/addon/routes/maintenance/inspection-forms/index/details.js +10 -1
  77. package/addon/routes/maintenance/inspection-forms/index/edit.js +10 -1
  78. package/addon/routes/maintenance/inspection-forms/index/new.js +14 -1
  79. package/addon/routes/maintenance/inspection-forms.js +14 -1
  80. package/addon/routes/maintenance/inspection-submissions/index/details.js +10 -1
  81. package/addon/routes/maintenance/inspection-submissions/index/edit.js +10 -1
  82. package/addon/routes/maintenance/inspection-submissions/index/new.js +14 -1
  83. package/addon/routes/maintenance/inspection-submissions.js +14 -1
  84. package/addon/routes/maintenance/maintenances/index/details.js +2 -2
  85. package/addon/routes/maintenance/maintenances/index/edit.js +2 -2
  86. package/addon/routes/maintenance/maintenances/index/new.js +14 -1
  87. package/addon/routes/maintenance/maintenances.js +14 -1
  88. package/addon/routes/maintenance/parts/index/details.js +2 -2
  89. package/addon/routes/maintenance/parts/index/edit.js +2 -2
  90. package/addon/routes/maintenance/parts/index/new.js +14 -1
  91. package/addon/routes/maintenance/parts.js +14 -1
  92. package/addon/routes/maintenance/schedules/index/details.js +2 -2
  93. package/addon/routes/maintenance/schedules/index/edit.js +2 -2
  94. package/addon/routes/maintenance/schedules/index/new.js +15 -1
  95. package/addon/routes/maintenance/schedules.js +15 -1
  96. package/addon/routes/maintenance/work-orders/index/details.js +2 -2
  97. package/addon/routes/maintenance/work-orders/index/edit.js +2 -2
  98. package/addon/routes/maintenance/work-orders/index/new.js +14 -1
  99. package/addon/routes/maintenance/work-orders.js +14 -1
  100. package/addon/routes/management/fuel-transactions/index/details.js +9 -0
  101. package/addon/routes/management/fuel-transactions.js +14 -1
  102. package/addon/routes/management/index.js +13 -0
  103. package/addon/routes/management/trailers.js +16 -0
  104. package/addon/routes/management/vendors/integrated/details.js +14 -1
  105. package/addon/routes/management/vendors/integrated/edit.js +14 -1
  106. package/addon/routes/management/vendors/integrated/new.js +14 -1
  107. package/addon/routes/management/vendors/integrated.js +14 -1
  108. package/addon/routes/operations/orders.js +40 -1
  109. package/addon/routes/operations/routes/index/details.js +14 -1
  110. package/addon/routes/operations/routes/index/new.js +13 -0
  111. package/addon/routes/operations/routes.js +14 -1
  112. package/addon/routes/operations/service-rates/index/new.js +11 -0
  113. package/addon/routes/operations/service-rates.js +14 -1
  114. package/addon/routes/settings/avatars.js +14 -1
  115. package/addon/routes/settings/custom-fields.js +14 -1
  116. package/addon/routes/settings/map.js +14 -1
  117. package/addon/routes/settings/notifications.js +11 -0
  118. package/addon/routes/settings/orchestrator.js +1 -1
  119. package/addon/routes/settings/payments/index.js +1 -1
  120. package/addon/routes/settings/routing.js +14 -1
  121. package/addon/routes/settings/scheduling.js +14 -1
  122. package/addon/routes/settings/telematics.js +21 -0
  123. package/addon/routes/virtual.js +11 -0
  124. package/addon/routes.js +1 -0
  125. package/addon/services/contact-actions.js +50 -89
  126. package/addon/services/driver-actions.js +98 -0
  127. package/addon/templates/settings/telematics.hbs +70 -0
  128. package/addon/utils/profile-login-actions.js +172 -0
  129. package/app/components/admin/telematics-settings.js +1 -0
  130. package/app/components/{modals/reset-customer-credentials.js → map/marker-card/driver.js} +1 -1
  131. package/app/components/map/marker-card/vehicle.js +1 -0
  132. package/app/components/modals/reset-profile-credentials.js +1 -0
  133. package/app/components/profile-identity-hint.js +1 -0
  134. package/app/controllers/settings/telematics.js +1 -0
  135. package/app/routes/settings/telematics.js +1 -0
  136. package/app/templates/settings/telematics.js +1 -0
  137. package/composer.json +2 -2
  138. package/docs/AFAQY.md +1 -1
  139. package/docs/TELEMATICS_QUEUES.md +1 -1
  140. package/docs/TELEMETRY_ARCHITECTURE.md +72 -1
  141. package/extension.json +1 -1
  142. package/package.json +3 -3
  143. package/scripts/pest-bootstrap.php +12 -0
  144. package/server/config/telemetry.php +12 -0
  145. package/server/migrations/2026_09_21_000001_convert_profile_only_users_to_managed_accounts.php +132 -0
  146. package/server/migrations/2026_09_23_000001_add_retention_index_to_device_events.php +40 -0
  147. package/server/migrations/2026_09_23_000002_add_retention_index_to_positions.php +40 -0
  148. package/server/migrations/2026_09_23_000003_add_retention_index_to_telematic_sync_runs.php +40 -0
  149. package/server/resources/views/mail/driver-credentials.blade.php +21 -0
  150. package/server/src/Auth/Schemas/FleetOps.php +104 -5
  151. package/server/src/Console/Commands/DrainTelematicInbox.php +3 -13
  152. package/server/src/Console/Commands/FixCustomerCompanies.php +1 -1
  153. package/server/src/Console/Commands/FixDriverCompanies.php +1 -1
  154. package/server/src/Console/Commands/ProcessOperationalAlerts.php +3 -3
  155. package/server/src/Console/Commands/PruneTelematicsData.php +318 -0
  156. package/server/src/Exceptions/ProfileIdentityConflictException.php +34 -0
  157. package/server/src/Http/Controllers/Api/v1/CustomerController.php +14 -0
  158. package/server/src/Http/Controllers/Api/v1/DriverController.php +56 -39
  159. package/server/src/Http/Controllers/Api/v1/OrchestrationController.php +9 -0
  160. package/server/src/Http/Controllers/FleetOpsController.php +21 -0
  161. package/server/src/Http/Controllers/Internal/v1/AnalyticsController.php +11 -0
  162. package/server/src/Http/Controllers/Internal/v1/ContactController.php +16 -17
  163. package/server/src/Http/Controllers/Internal/v1/CustomerController.php +54 -4
  164. package/server/src/Http/Controllers/Internal/v1/DeviceController.php +13 -0
  165. package/server/src/Http/Controllers/Internal/v1/DeviceEventController.php +11 -0
  166. package/server/src/Http/Controllers/Internal/v1/DriverController.php +204 -162
  167. package/server/src/Http/Controllers/Internal/v1/FleetOpsLookupController.php +47 -0
  168. package/server/src/Http/Controllers/Internal/v1/FuelProviderConnectionController.php +13 -0
  169. package/server/src/Http/Controllers/Internal/v1/FuelProviderTransactionController.php +15 -0
  170. package/server/src/Http/Controllers/Internal/v1/FuelReportController.php +9 -3
  171. package/server/src/Http/Controllers/Internal/v1/InspectionFormController.php +15 -0
  172. package/server/src/Http/Controllers/Internal/v1/LiveController.php +16 -0
  173. package/server/src/Http/Controllers/Internal/v1/MaintenanceController.php +15 -0
  174. package/server/src/Http/Controllers/Internal/v1/MaintenanceScheduleController.php +15 -0
  175. package/server/src/Http/Controllers/Internal/v1/ManifestController.php +15 -0
  176. package/server/src/Http/Controllers/Internal/v1/MetricsController.php +11 -0
  177. package/server/src/Http/Controllers/Internal/v1/NavigatorController.php +42 -1
  178. package/server/src/Http/Controllers/Internal/v1/OrchestrationController.php +12 -0
  179. package/server/src/Http/Controllers/Internal/v1/OrderController.php +178 -27
  180. package/server/src/Http/Controllers/Internal/v1/PaymentController.php +13 -0
  181. package/server/src/Http/Controllers/Internal/v1/RadarController.php +19 -0
  182. package/server/src/Http/Controllers/Internal/v1/ServiceAreaController.php +9 -3
  183. package/server/src/Http/Controllers/Internal/v1/SettingController.php +465 -14
  184. package/server/src/Http/Controllers/Internal/v1/TelematicController.php +21 -0
  185. package/server/src/Http/Controllers/Internal/v1/TrailerController.php +21 -0
  186. package/server/src/Http/Controllers/Internal/v1/VehicleController.php +21 -0
  187. package/server/src/Http/Controllers/Internal/v1/VendorController.php +17 -0
  188. package/server/src/Http/Controllers/Internal/v1/WorkOrderController.php +11 -0
  189. package/server/src/Http/Requests/CreateDriverRequest.php +6 -2
  190. package/server/src/Http/Requests/Internal/CreateDriverRequest.php +9 -18
  191. package/server/src/Http/Resources/v1/Contact.php +3 -0
  192. package/server/src/Http/Resources/v1/Driver.php +3 -0
  193. package/server/src/Jobs/DispatchTelematicsRetentionJobs.php +70 -0
  194. package/server/src/Jobs/PruneTelematicsDataJob.php +74 -0
  195. package/server/src/Listeners/NotifyDriverOnShiftChange.php +3 -3
  196. package/server/src/Mail/CustomerCredentialsMail.php +1 -1
  197. package/server/src/Mail/DriverCredentialsMail.php +55 -0
  198. package/server/src/Models/Contact.php +55 -90
  199. package/server/src/Models/Sensor.php +3 -5
  200. package/server/src/Observers/ContactObserver.php +2 -22
  201. package/server/src/Observers/DriverObserver.php +5 -6
  202. package/server/src/Orchestration/Engines/VroomOrchestrationEngine.php +9 -1
  203. package/server/src/Providers/FleetOpsServiceProvider.php +18 -0
  204. package/server/src/Support/Ai/Capabilities/AbstractFleetOpsAICapability.php +62 -5
  205. package/server/src/Support/Ai/Capabilities/AssetStatusCapability.php +24 -5
  206. package/server/src/Support/Ai/Capabilities/CreateOrderPreviewCapability.php +6 -2
  207. package/server/src/Support/Ai/Capabilities/OrderInsightsCapability.php +40 -7
  208. package/server/src/Support/Ai/Capabilities/SearchResourcesCapability.php +86 -24
  209. package/server/src/Support/Ai/FleetOpsAiConsoleCommands.php +122 -0
  210. package/server/src/Support/Ai/Tools/CreateOrderTool.php +86 -0
  211. package/server/src/Support/Ai/Tools/ImportOrdersTool.php +53 -0
  212. package/server/src/Support/Ai/Tools/OptimizeOrderRouteTool.php +70 -0
  213. package/server/src/Support/Ai/Tools/SearchResourcesTool.php +73 -0
  214. package/server/src/Support/Analytics/LiveFleet.php +18 -2
  215. package/server/src/Support/Authorization.php +103 -0
  216. package/server/src/Support/Database/TableIndexes.php +66 -0
  217. package/server/src/Support/OrderTracker.php +2 -2
  218. package/server/src/Support/ProfileAccountManager.php +405 -0
  219. package/server/src/Support/Reporting/FleetOpsReportSchema.php +476 -116
  220. package/server/src/Support/Telematics/Retention/RetentionPolicy.php +300 -0
  221. package/server/src/Support/Telematics/Retention/TelemetryActivity.php +40 -0
  222. package/server/src/Support/Telematics/TelematicService.php +12 -2
  223. package/server/src/Support/Telematics/Telemetry/Ingestor.php +4 -2
  224. package/server/src/Tracking/TrackingIntelligenceService.php +1 -1
  225. package/server/src/Tracking/TrackingOptions.php +2 -2
  226. package/server/src/Traits/AuthorizesMethods.php +37 -0
  227. package/server/src/routes.php +14 -1
  228. package/server/tests/AiOperationalQueryCapabilityTest.php +1 -0
  229. package/server/tests/AnalyticsRoutesTest.php +29 -2
  230. package/server/tests/ApiCustomerControllerContractsTest.php +21 -0
  231. package/server/tests/ApiDriverControllerContractsTest.php +102 -20
  232. package/server/tests/CommandContractsTest.php +4 -4
  233. package/server/tests/ControllerHelperContractsTest.php +3 -11
  234. package/server/tests/Feature/Http/AfaqyRealtimeIngestionTest.php +21 -1
  235. package/server/tests/Feature/Http/Api/DriverControllerAuthFlowsTest.php +36 -0
  236. package/server/tests/Feature/Http/Api/DriverControllerSessionHelpersTest.php +19 -6
  237. package/server/tests/Feature/Http/Api/ProfileOnlyUserConversionMigrationTest.php +201 -0
  238. package/server/tests/Feature/Http/Api/TelematicsRetentionIndexMigrationTest.php +115 -0
  239. package/server/tests/Feature/Http/Internal/ContactControllerEndpointsTest.php +6 -4
  240. package/server/tests/Feature/Http/Internal/CustomerControllerCredentialsTest.php +6 -2
  241. package/server/tests/Feature/Http/Internal/DriverControllerContractsTest.php +23 -0
  242. package/server/tests/Feature/Http/Internal/DriverControllerCreateRecordTest.php +42 -17
  243. package/server/tests/Feature/Http/Internal/DriverControllerExistingUserAdoptionTest.php +168 -277
  244. package/server/tests/Feature/Http/Internal/DriverControllerLoginManagementTest.php +716 -0
  245. package/server/tests/Feature/Http/Internal/OrderControllerContractsTest.php +10 -3
  246. package/server/tests/Feature/Http/Internal/OrderControllerImportFromFilesTest.php +18 -0
  247. package/server/tests/Feature/Http/Internal/OrderControllerTenantScopingTest.php +411 -0
  248. package/server/tests/Feature/Http/Internal/OrderControllerUpstreamNotFoundTest.php +8 -20
  249. package/server/tests/Feature/Http/Internal/SettingControllerHelpersTest.php +71 -0
  250. package/server/tests/Feature/Http/Internal/TelematicsStorageDeadlinesTest.php +119 -0
  251. package/server/tests/InternalCustomerControllerContractsTest.php +32 -1
  252. package/server/tests/InternalImportExportControllerContractsTest.php +5 -8
  253. package/server/tests/ModelAccessorContractsTest.php +82 -20
  254. package/server/tests/NavigatorControllerContractsTest.php +36 -4
  255. package/server/tests/NotificationAndMailContractsTest.php +31 -0
  256. package/server/tests/ObserverContractsTest.php +28 -3
  257. package/server/tests/OrchestratorConsumableApiTest.php +42 -0
  258. package/server/tests/ProviderContractsTest.php +10 -0
  259. package/server/tests/ReportSchemaContractsTest.php +120 -6
  260. package/server/tests/RequestContractsTest.php +19 -11
  261. package/server/tests/SettingControllerContractsTest.php +429 -18
  262. package/server/tests/SmallControllerContractsTest.php +8 -5
  263. package/server/tests/Support/PruneTelematicsDataProbe.php +55 -0
  264. package/server/tests/SupportJobAndAiCoverageTest.php +3 -3
  265. package/server/tests/TelematicControllerContractsTest.php +22 -4
  266. package/server/tests/Unit/Console/Commands/ProcessOperationalAlertsCommandTest.php +2 -2
  267. package/server/tests/Unit/Console/PruneTelematicsDataCommandTest.php +353 -0
  268. package/server/tests/Unit/Jobs/DispatchTelematicsRetentionJobsTest.php +114 -0
  269. package/server/tests/Unit/Jobs/PruneTelematicsDataJobTest.php +60 -0
  270. package/server/tests/Unit/Models/ContactCustomerUserTest.php +90 -14
  271. package/server/tests/Unit/Models/ContactTest.php +48 -5
  272. package/server/tests/Unit/Models/SensorTest.php +2 -2
  273. package/server/tests/Unit/Models/SmallModelSurfacesTest.php +31 -32
  274. package/server/tests/Unit/Observers/ObserverListenerSeamsTest.php +7 -2
  275. package/server/tests/Unit/Orchestration/VroomEngineTransportAndSettingsTest.php +20 -0
  276. package/server/tests/Unit/Providers/FleetOpsAiRegistrationTest.php +15 -2
  277. package/server/tests/Unit/Support/Ai/AssetStatusCapabilityQueriesTest.php +42 -0
  278. package/server/tests/Unit/Support/Ai/Capabilities/OrderInsightsCapabilityTest.php +19 -1
  279. package/server/tests/Unit/Support/Ai/Capabilities/SearchResourcesCapabilityTest.php +85 -1
  280. package/server/tests/Unit/Support/Ai/FleetOpsAiConsoleCommandsTest.php +31 -0
  281. package/server/tests/Unit/Support/Ai/Tools/FleetOpsAiToolsTest.php +246 -0
  282. package/server/tests/Unit/Support/AiCapabilityPermissionsTest.php +3 -3
  283. package/server/tests/Unit/Support/Analytics/LiveFleetTest.php +6 -0
  284. package/server/tests/Unit/Support/AuthorizationTest.php +142 -0
  285. package/server/tests/Unit/Support/MaintainableAndOperationalAlertsTest.php +12 -1
  286. package/server/tests/Unit/Support/MoreQuerySeamsTest.php +11 -2
  287. package/server/tests/Unit/Support/ProfileAccountManagerTest.php +643 -0
  288. package/server/tests/Unit/Support/Telematics/Retention/RetentionPolicyTest.php +190 -0
  289. package/server/tests/Unit/Support/Telematics/Retention/TelemetryActivityTest.php +68 -0
  290. package/server/tests/Unit/Tracking/TrackingOptionsCompanySettingsTest.php +109 -0
  291. package/translations/en-us.yaml +85 -2
  292. package/translations/uk-ua.yaml +3475 -0
  293. package/addon/components/modals/reset-customer-credentials.hbs +0 -18
  294. package/addon/components/modals/reset-customer-credentials.js +0 -55
@@ -1,3 +1,16 @@
1
1
  import Route from '@ember/routing/route';
2
+ import { inject as service } from '@ember/service';
2
3
 
3
- export default class OperationsRoutesIndexDetailsRoute extends Route {}
4
+ export default class OperationsRoutesIndexDetailsRoute extends Route {
5
+ @service notifications;
6
+ @service hostRouter;
7
+ @service abilities;
8
+ @service intl;
9
+
10
+ beforeModel() {
11
+ if (this.abilities.cannot('fleet-ops view route')) {
12
+ this.notifications.warning(this.intl.t('common.unauthorized-access'));
13
+ return this.hostRouter.transitionTo('console.fleet-ops.operations.routes.index');
14
+ }
15
+ }
16
+ }
@@ -1,6 +1,19 @@
1
1
  import Route from '@ember/routing/route';
2
+ import { inject as service } from '@ember/service';
2
3
 
3
4
  export default class OperationsRoutesIndexNewRoute extends Route {
5
+ @service notifications;
6
+ @service hostRouter;
7
+ @service abilities;
8
+ @service intl;
9
+
10
+ beforeModel() {
11
+ if (this.abilities.cannot('fleet-ops create route')) {
12
+ this.notifications.warning(this.intl.t('common.unauthorized-access'));
13
+ return this.hostRouter.transitionTo('console.fleet-ops.operations.routes.index');
14
+ }
15
+ }
16
+
4
17
  queryParams = {
5
18
  selectedOrders: {
6
19
  refreshModel: false,
@@ -1,3 +1,16 @@
1
1
  import Route from '@ember/routing/route';
2
+ import { inject as service } from '@ember/service';
2
3
 
3
- export default class OperationsRoutesRoute extends Route {}
4
+ export default class OperationsRoutesRoute extends Route {
5
+ @service notifications;
6
+ @service hostRouter;
7
+ @service abilities;
8
+ @service intl;
9
+
10
+ beforeModel() {
11
+ if (this.abilities.cannot('fleet-ops list route')) {
12
+ this.notifications.warning(this.intl.t('common.unauthorized-access'));
13
+ return this.hostRouter.transitionTo('console.fleet-ops');
14
+ }
15
+ }
16
+ }
@@ -3,6 +3,17 @@ import { inject as service } from '@ember/service';
3
3
 
4
4
  export default class OperationsServiceRatesIndexNewRoute extends Route {
5
5
  @service store;
6
+ @service notifications;
7
+ @service hostRouter;
8
+ @service abilities;
9
+ @service intl;
10
+
11
+ beforeModel() {
12
+ if (this.abilities.cannot('fleet-ops create service-rate')) {
13
+ this.notifications.warning(this.intl.t('common.unauthorized-access'));
14
+ return this.hostRouter.transitionTo('console.fleet-ops.operations.service-rates.index');
15
+ }
16
+ }
6
17
 
7
18
  async setupController(controller) {
8
19
  super.setupController(...arguments);
@@ -1,3 +1,16 @@
1
1
  import Route from '@ember/routing/route';
2
+ import { inject as service } from '@ember/service';
2
3
 
3
- export default class OperationsServiceRatesRoute extends Route {}
4
+ export default class OperationsServiceRatesRoute extends Route {
5
+ @service notifications;
6
+ @service hostRouter;
7
+ @service abilities;
8
+ @service intl;
9
+
10
+ beforeModel() {
11
+ if (this.abilities.cannot('fleet-ops list service-rate')) {
12
+ this.notifications.warning(this.intl.t('common.unauthorized-access'));
13
+ return this.hostRouter.transitionTo('console.fleet-ops');
14
+ }
15
+ }
16
+ }
@@ -1,3 +1,16 @@
1
1
  import Route from '@ember/routing/route';
2
+ import { inject as service } from '@ember/service';
2
3
 
3
- export default class SettingsAvatarsRoute extends Route {}
4
+ export default class SettingsAvatarsRoute extends Route {
5
+ @service notifications;
6
+ @service hostRouter;
7
+ @service abilities;
8
+ @service intl;
9
+
10
+ beforeModel() {
11
+ if (this.abilities.cannot('fleet-ops list avatar')) {
12
+ this.notifications.warning(this.intl.t('common.unauthorized-access'));
13
+ return this.hostRouter.transitionTo('console.fleet-ops');
14
+ }
15
+ }
16
+ }
@@ -1,3 +1,16 @@
1
1
  import Route from '@ember/routing/route';
2
+ import { inject as service } from '@ember/service';
2
3
 
3
- export default class SettingsCustomFieldsRoute extends Route {}
4
+ export default class SettingsCustomFieldsRoute extends Route {
5
+ @service notifications;
6
+ @service hostRouter;
7
+ @service abilities;
8
+ @service intl;
9
+
10
+ beforeModel() {
11
+ if (this.abilities.cannot('fleet-ops list custom-field')) {
12
+ this.notifications.warning(this.intl.t('common.unauthorized-access'));
13
+ return this.hostRouter.transitionTo('console.fleet-ops');
14
+ }
15
+ }
16
+ }
@@ -1,3 +1,16 @@
1
1
  import Route from '@ember/routing/route';
2
+ import { inject as service } from '@ember/service';
2
3
 
3
- export default class SettingsMapRoute extends Route {}
4
+ export default class SettingsMapRoute extends Route {
5
+ @service notifications;
6
+ @service hostRouter;
7
+ @service abilities;
8
+ @service intl;
9
+
10
+ beforeModel() {
11
+ if (this.abilities.cannot('fleet-ops view map-settings')) {
12
+ this.notifications.warning(this.intl.t('common.unauthorized-access'));
13
+ return this.hostRouter.transitionTo('console.fleet-ops');
14
+ }
15
+ }
16
+ }
@@ -4,6 +4,17 @@ import { hash } from 'rsvp';
4
4
 
5
5
  export default class SettingsNotificationsRoute extends Route {
6
6
  @service fetch;
7
+ @service notifications;
8
+ @service hostRouter;
9
+ @service abilities;
10
+ @service intl;
11
+
12
+ beforeModel() {
13
+ if (this.abilities.cannot('fleet-ops view notification-settings')) {
14
+ this.notifications.warning(this.intl.t('common.unauthorized-access'));
15
+ return this.hostRouter.transitionTo('console.fleet-ops');
16
+ }
17
+ }
7
18
 
8
19
  model() {
9
20
  return hash({
@@ -14,7 +14,7 @@ export default class SettingsOrchestratorRoute extends Route {
14
14
  @service hostRouter;
15
15
 
16
16
  beforeModel() {
17
- if (this.abilities.cannot('fleet-ops list order')) {
17
+ if (this.abilities.cannot('fleet-ops view routing-settings')) {
18
18
  this.notifications.warning(this.intl.t('common.unauthorized-access'));
19
19
  return this.hostRouter.transitionTo('console.fleet-ops');
20
20
  }
@@ -16,7 +16,7 @@ export default class SettingsPaymentsIndexRoute extends Route {
16
16
  };
17
17
 
18
18
  beforeModel() {
19
- if (this.abilities.cannot('fleet-ops list purchase-rate')) {
19
+ if (this.abilities.cannot('fleet-ops view payments')) {
20
20
  this.notifications.warning(this.intl.t('common.unauthorized-access'));
21
21
  return this.hostRouter.transitionTo('console.fleet-ops');
22
22
  }
@@ -1,3 +1,16 @@
1
1
  import Route from '@ember/routing/route';
2
+ import { inject as service } from '@ember/service';
2
3
 
3
- export default class SettingsRoutingRoute extends Route {}
4
+ export default class SettingsRoutingRoute extends Route {
5
+ @service notifications;
6
+ @service hostRouter;
7
+ @service abilities;
8
+ @service intl;
9
+
10
+ beforeModel() {
11
+ if (this.abilities.cannot('fleet-ops view routing-settings')) {
12
+ this.notifications.warning(this.intl.t('common.unauthorized-access'));
13
+ return this.hostRouter.transitionTo('console.fleet-ops');
14
+ }
15
+ }
16
+ }
@@ -1,3 +1,16 @@
1
1
  import Route from '@ember/routing/route';
2
+ import { inject as service } from '@ember/service';
2
3
 
3
- export default class SettingsSchedulingRoute extends Route {}
4
+ export default class SettingsSchedulingRoute extends Route {
5
+ @service notifications;
6
+ @service hostRouter;
7
+ @service abilities;
8
+ @service intl;
9
+
10
+ beforeModel() {
11
+ if (this.abilities.cannot('fleet-ops view scheduling-settings')) {
12
+ this.notifications.warning(this.intl.t('common.unauthorized-access'));
13
+ return this.hostRouter.transitionTo('console.fleet-ops');
14
+ }
15
+ }
16
+ }
@@ -0,0 +1,21 @@
1
+ import Route from '@ember/routing/route';
2
+ import { inject as service } from '@ember/service';
3
+
4
+ export default class SettingsTelematicsRoute extends Route {
5
+ @service notifications;
6
+ @service hostRouter;
7
+ @service abilities;
8
+ @service intl;
9
+
10
+ beforeModel() {
11
+ if (this.abilities.cannot('fleet-ops view telematics-settings')) {
12
+ this.notifications.warning(this.intl.t('common.unauthorized-access'));
13
+ return this.hostRouter.transitionTo('console.fleet-ops');
14
+ }
15
+ }
16
+
17
+ setupController(controller) {
18
+ super.setupController(...arguments);
19
+ controller.getSettings.perform();
20
+ }
21
+ }
@@ -4,6 +4,10 @@ import { inject as service } from '@ember/service';
4
4
  export default class VirtualRoute extends Route {
5
5
  @service universe;
6
6
  @service('universe/menu-service') menuService;
7
+ @service notifications;
8
+ @service hostRouter;
9
+ @service abilities;
10
+ @service intl;
7
11
 
8
12
  queryParams = {
9
13
  view: {
@@ -15,4 +19,11 @@ export default class VirtualRoute extends Route {
15
19
  const view = this.universe.getViewFromTransition(transition);
16
20
  return this.menuService.lookupMenuItem('engine:fleet-ops', slug, view, section);
17
21
  }
22
+
23
+ afterModel(menuItem) {
24
+ if (menuItem?.permission && this.abilities.cannot(menuItem.permission)) {
25
+ this.notifications.warning(this.intl.t('common.unauthorized-access'));
26
+ return this.hostRouter.transitionTo('console.fleet-ops');
27
+ }
28
+ }
18
29
  }
package/addon/routes.js CHANGED
@@ -323,6 +323,7 @@ export default buildRoutes(function () {
323
323
  this.route('map');
324
324
  this.route('orchestrator');
325
325
  this.route('scheduling');
326
+ this.route('telematics');
326
327
  this.route('payments', function () {
327
328
  this.route('index', { path: '/' });
328
329
  this.route('onboard');
@@ -1,9 +1,8 @@
1
1
  import ResourceActionService from '@fleetbase/ember-core/services/resource-action';
2
2
  import { inject as service } from '@ember/service';
3
- import { action, get } from '@ember/object';
3
+ import { action } from '@ember/object';
4
4
  import { PANEL_DEFAULTS, closePanelsThen, registeredPanelTabs } from '../utils/context-panel';
5
-
6
- const INTERNAL_NAMESPACE = 'int/v1';
5
+ import { confirmLoginAction, hasInactiveLogin, hasLinkedUser, hasManagedLogin, linkedUserStatus, updateProfileFromResponse } from '../utils/profile-login-actions';
7
6
 
8
7
  export default class ContactActionsService extends ResourceActionService {
9
8
  @service fetch;
@@ -124,17 +123,23 @@ export default class ContactActionsService extends ResourceActionService {
124
123
  }
125
124
 
126
125
  hasLinkedUser(contact) {
127
- const user = contact?.user;
128
- return Boolean(contact?.user_uuid || (user && (get(user, 'id') || get(user, 'uuid'))));
126
+ return hasLinkedUser(contact);
127
+ }
128
+
129
+ /**
130
+ * True when the contact has a login account managed from Fleet-Ops. A
131
+ * contact owned by a staff member is managed from IAM instead.
132
+ */
133
+ hasManagedLogin(contact) {
134
+ return hasManagedLogin(contact);
129
135
  }
130
136
 
131
137
  linkedUserStatus(contact) {
132
- const user = contact?.user;
133
- return (user ? (get(user, 'status') ?? get(user, 'session_status')) : null) ?? 'active';
138
+ return linkedUserStatus(contact);
134
139
  }
135
140
 
136
141
  hasInactiveLogin(contact) {
137
- return ['inactive', 'disabled', 'suspended'].includes(this.linkedUserStatus(contact));
142
+ return hasInactiveLogin(contact);
138
143
  }
139
144
 
140
145
  isCustomerPortalInstalled() {
@@ -156,7 +161,7 @@ export default class ContactActionsService extends ResourceActionService {
156
161
  }
157
162
 
158
163
  accountActionButton(contact, options = {}) {
159
- if (!this.hasLinkedUser(contact)) {
164
+ if (!this.hasManagedLogin(contact)) {
160
165
  return null;
161
166
  }
162
167
 
@@ -171,23 +176,23 @@ export default class ContactActionsService extends ResourceActionService {
171
176
  accountActionItems(contact, options = {}) {
172
177
  const actions = [
173
178
  {
174
- text: 'Reset Password',
179
+ text: this.intl.t('profile-account.actions.reset-password'),
175
180
  icon: 'key',
176
181
  fn: () => this.openResetPasswordModal(contact),
177
182
  },
178
183
  {
179
- text: 'Send Credentials',
184
+ text: this.intl.t('profile-account.actions.send-credentials'),
180
185
  icon: 'paper-plane',
181
186
  fn: () => this.confirmSendCredentials(contact),
182
187
  },
183
188
  this.hasInactiveLogin(contact)
184
189
  ? {
185
- text: 'Reactivate Login',
190
+ text: this.intl.t('profile-account.actions.reactivate-login'),
186
191
  icon: 'unlock',
187
192
  fn: () => this.confirmReactivatePortalLogin(contact),
188
193
  }
189
194
  : {
190
- text: 'Deactivate Login',
195
+ text: this.intl.t('profile-account.actions.deactivate-login'),
191
196
  icon: 'lock',
192
197
  fn: () => this.confirmDeactivatePortalLogin(contact),
193
198
  class: 'text-red-500 hover:text-red-600',
@@ -200,7 +205,7 @@ export default class ContactActionsService extends ResourceActionService {
200
205
  separator: true,
201
206
  },
202
207
  {
203
- text: 'Convert to Vendor',
208
+ text: this.intl.t('profile-account.actions.convert-to-vendor'),
204
209
  icon: 'building',
205
210
  fn: () => this.openConvertToVendorModal(contact, options),
206
211
  }
@@ -212,42 +217,42 @@ export default class ContactActionsService extends ResourceActionService {
212
217
 
213
218
  accountRowActionItems(options = {}) {
214
219
  const hasCustomerPortal = this.isCustomerPortalInstalled();
215
- const hasLinkedUser = (contact) => this.hasLinkedUser(contact);
220
+ const hasManagedLogin = (contact) => this.hasManagedLogin(contact);
216
221
 
217
222
  const actions = [
218
223
  {
219
- label: 'Reset Password',
224
+ label: this.intl.t('profile-account.actions.reset-password'),
220
225
  icon: 'key',
221
226
  fn: (contact) => this.openResetPasswordModal(contact),
222
- isVisible: hasLinkedUser,
227
+ isVisible: hasManagedLogin,
223
228
  },
224
229
  {
225
- label: 'Send Credentials',
230
+ label: this.intl.t('profile-account.actions.send-credentials'),
226
231
  icon: 'paper-plane',
227
232
  fn: (contact) => this.confirmSendCredentials(contact),
228
- isVisible: hasLinkedUser,
233
+ isVisible: hasManagedLogin,
229
234
  },
230
235
  {
231
- label: 'Deactivate Login',
236
+ label: this.intl.t('profile-account.actions.deactivate-login'),
232
237
  icon: 'lock',
233
238
  class: 'text-red-500 hover:text-red-600',
234
239
  fn: (contact) => this.confirmDeactivatePortalLogin(contact),
235
- isVisible: (contact) => hasLinkedUser(contact) && !this.hasInactiveLogin(contact),
240
+ isVisible: (contact) => hasManagedLogin(contact) && !this.hasInactiveLogin(contact),
236
241
  },
237
242
  {
238
- label: 'Reactivate Login',
243
+ label: this.intl.t('profile-account.actions.reactivate-login'),
239
244
  icon: 'unlock',
240
245
  fn: (contact) => this.confirmReactivatePortalLogin(contact),
241
- isVisible: (contact) => hasLinkedUser(contact) && this.hasInactiveLogin(contact),
246
+ isVisible: (contact) => hasManagedLogin(contact) && this.hasInactiveLogin(contact),
242
247
  },
243
248
  ];
244
249
 
245
250
  if (hasCustomerPortal) {
246
251
  actions.push({
247
- label: 'Convert to Vendor',
252
+ label: this.intl.t('profile-account.actions.convert-to-vendor'),
248
253
  icon: 'building',
249
254
  fn: (contact) => this.openConvertToVendorModal(contact, options),
250
- isVisible: hasLinkedUser,
255
+ isVisible: hasManagedLogin,
251
256
  });
252
257
  }
253
258
 
@@ -255,8 +260,10 @@ export default class ContactActionsService extends ResourceActionService {
255
260
  }
256
261
 
257
262
  openResetPasswordModal(contact) {
258
- this.modalsManager.show('modals/reset-customer-credentials', {
259
- customer: contact,
263
+ this.modalsManager.show('modals/reset-profile-credentials', {
264
+ profile: contact,
265
+ endpoint: 'customers/reset-credentials',
266
+ payload: (profile) => ({ customer: profile?.id }),
260
267
  });
261
268
  }
262
269
 
@@ -278,86 +285,40 @@ export default class ContactActionsService extends ResourceActionService {
278
285
 
279
286
  confirmSendCredentials(contact) {
280
287
  this.confirmLoginAction(contact, {
281
- title: 'Send Portal Credentials',
282
- body: 'Generate a new temporary password and email this contact their portal credentials.',
283
- acceptButtonText: 'Send Credentials',
288
+ title: this.intl.t('profile-account.prompts.send-portal-credentials-title'),
289
+ body: this.intl.t('profile-account.prompts.send-portal-credentials-body'),
290
+ acceptButtonText: this.intl.t('profile-account.actions.send-credentials'),
284
291
  endpoint: 'customers/send-credentials',
285
- successMessage: 'Portal credentials sent.',
292
+ successMessage: this.intl.t('profile-account.prompts.send-portal-credentials-success'),
286
293
  });
287
294
  }
288
295
 
289
296
  confirmDeactivatePortalLogin(contact) {
290
297
  this.confirmLoginAction(contact, {
291
- title: 'Deactivate Login',
292
- body: 'Deactivate portal access for this contact. Their profile and history will be preserved.',
293
- acceptButtonText: 'Deactivate Login',
298
+ title: this.intl.t('profile-account.actions.deactivate-login'),
299
+ body: this.intl.t('profile-account.prompts.deactivate-portal-login-body'),
300
+ acceptButtonText: this.intl.t('profile-account.actions.deactivate-login'),
294
301
  acceptButtonScheme: 'danger',
295
302
  endpoint: 'customers/deactivate-portal-login',
296
- successMessage: 'Portal login deactivated.',
303
+ successMessage: this.intl.t('profile-account.prompts.deactivate-portal-login-success'),
297
304
  });
298
305
  }
299
306
 
300
307
  confirmReactivatePortalLogin(contact) {
301
308
  this.confirmLoginAction(contact, {
302
- title: 'Reactivate Login',
303
- body: 'Reactivate portal access for this contact.',
304
- acceptButtonText: 'Reactivate Login',
309
+ title: this.intl.t('profile-account.actions.reactivate-login'),
310
+ body: this.intl.t('profile-account.prompts.reactivate-portal-login-body'),
311
+ acceptButtonText: this.intl.t('profile-account.actions.reactivate-login'),
305
312
  endpoint: 'customers/reactivate-portal-login',
306
- successMessage: 'Portal login reactivated.',
313
+ successMessage: this.intl.t('profile-account.prompts.reactivate-portal-login-success'),
307
314
  });
308
315
  }
309
316
 
310
- confirmLoginAction(contact, { title, body, acceptButtonText, acceptButtonScheme, endpoint, successMessage }) {
311
- this.modalsManager.confirm({
312
- title,
313
- body,
314
- acceptButtonText,
315
- acceptButtonScheme,
316
- confirm: async (modal) => {
317
- modal.startLoading();
318
-
319
- try {
320
- const response = await this.fetch.post(endpoint, { customer: contact?.id }, { namespace: INTERNAL_NAMESPACE });
321
- await this.updateContactFromResponse(contact, response);
322
- this.notifications.success(successMessage);
323
- modal.done();
324
- } catch (error) {
325
- this.notifications.serverError(error);
326
- modal.stopLoading();
327
- }
328
- },
329
- });
317
+ confirmLoginAction(contact, options = {}) {
318
+ return confirmLoginAction(this, contact, { payload: { customer: contact?.id }, ...options });
330
319
  }
331
320
 
332
- async updateContactFromResponse(contact, response) {
333
- const payload = response.customer ?? response.contact;
334
-
335
- if (!payload || typeof contact?.setProperties !== 'function') {
336
- return;
337
- }
338
-
339
- contact.setProperties(
340
- this.withoutIdentityFields({
341
- user_uuid: payload.user_uuid,
342
- })
343
- );
344
-
345
- if (payload.user) {
346
- const user = await contact.user;
347
-
348
- if (typeof user?.setProperties === 'function') {
349
- user.setProperties(this.withoutIdentityFields(payload.user));
350
- }
351
- }
352
- }
353
-
354
- withoutIdentityFields(payload = {}) {
355
- const attributes = { ...payload };
356
-
357
- delete attributes.id;
358
- delete attributes.uuid;
359
- delete attributes.public_id;
360
-
361
- return attributes;
321
+ updateContactFromResponse(contact, response) {
322
+ return updateProfileFromResponse(contact, response);
362
323
  }
363
324
  }
@@ -5,6 +5,7 @@ import { action } from '@ember/object';
5
5
  import { isArray } from '@ember/array';
6
6
  import { dasherize } from '@ember/string';
7
7
  import { PANEL_DEFAULTS, closePanelsThen } from '../utils/context-panel';
8
+ import { confirmLoginAction, hasInactiveLogin, hasManagedLogin } from '../utils/profile-login-actions';
8
9
 
9
10
  export default class DriverActionsService extends ResourceActionService {
10
11
  @service('universe/menu-service') menuService;
@@ -422,9 +423,106 @@ export default class DriverActionsService extends ResourceActionService {
422
423
  { separator: true },
423
424
  { text: this.intl.t('driver.actions.locate-driver'), icon: 'location-dot', fn: () => this.locate(driver), permission: 'fleet-ops view driver' },
424
425
  { text: this.intl.t('driver.actions.create-issue'), icon: 'triangle-exclamation', fn: () => this.createIssue(driver), permission: 'fleet-ops create issue' },
426
+ ...this.accountMenuItems(driver),
425
427
  ];
426
428
  }
427
429
 
430
+ /**
431
+ * The login account section of a driver's actions menu. Only offered when
432
+ * the driver has a login managed from Fleet-Ops; a staff-linked driver's
433
+ * login is managed from IAM.
434
+ */
435
+ accountMenuItems(driver) {
436
+ if (!hasManagedLogin(driver)) {
437
+ return [];
438
+ }
439
+
440
+ const items = this.accountRowActionItems()
441
+ .filter(({ isVisible }) => isVisible(driver))
442
+ // eslint-disable-next-line no-unused-vars
443
+ .map(({ label, fn, isVisible, ...item }) => ({ ...item, text: label, fn: () => fn(driver) }));
444
+
445
+ return [{ separator: true }, ...items];
446
+ }
447
+
448
+ /**
449
+ * Login account actions for the drivers table row menu.
450
+ */
451
+ accountRowActionItems() {
452
+ const permission = 'fleet-ops update driver';
453
+
454
+ return [
455
+ {
456
+ label: this.intl.t('profile-account.actions.reset-password'),
457
+ icon: 'key',
458
+ fn: (driver) => this.resetCredentials(driver),
459
+ permission,
460
+ isVisible: (driver) => hasManagedLogin(driver),
461
+ },
462
+ {
463
+ label: this.intl.t('profile-account.actions.send-credentials'),
464
+ icon: 'paper-plane',
465
+ fn: (driver) => this.sendCredentials(driver),
466
+ permission,
467
+ isVisible: (driver) => hasManagedLogin(driver),
468
+ },
469
+ {
470
+ label: this.intl.t('profile-account.actions.deactivate-login'),
471
+ icon: 'lock',
472
+ class: 'text-red-500 hover:text-red-600',
473
+ fn: (driver) => this.deactivateLogin(driver),
474
+ permission,
475
+ isVisible: (driver) => hasManagedLogin(driver) && !hasInactiveLogin(driver),
476
+ },
477
+ {
478
+ label: this.intl.t('profile-account.actions.reactivate-login'),
479
+ icon: 'unlock',
480
+ fn: (driver) => this.reactivateLogin(driver),
481
+ permission,
482
+ isVisible: (driver) => hasManagedLogin(driver) && hasInactiveLogin(driver),
483
+ },
484
+ ];
485
+ }
486
+
487
+ @action resetCredentials(driver, options = {}) {
488
+ return this.modalsManager.show('modals/reset-profile-credentials', {
489
+ profile: driver,
490
+ endpoint: `drivers/${driver.id}/reset-credentials`,
491
+ ...options,
492
+ });
493
+ }
494
+
495
+ @action sendCredentials(driver) {
496
+ return confirmLoginAction(this, driver, {
497
+ title: this.intl.t('profile-account.prompts.send-credentials-title'),
498
+ body: this.intl.t('profile-account.prompts.send-credentials-body', { name: driver.name }),
499
+ acceptButtonText: this.intl.t('profile-account.actions.send-credentials'),
500
+ endpoint: `drivers/${driver.id}/send-credentials`,
501
+ successMessage: this.intl.t('profile-account.prompts.send-credentials-success', { name: driver.name }),
502
+ });
503
+ }
504
+
505
+ @action deactivateLogin(driver) {
506
+ return confirmLoginAction(this, driver, {
507
+ title: this.intl.t('profile-account.actions.deactivate-login'),
508
+ body: this.intl.t('profile-account.prompts.deactivate-login-body', { name: driver.name }),
509
+ acceptButtonText: this.intl.t('profile-account.actions.deactivate-login'),
510
+ acceptButtonScheme: 'danger',
511
+ endpoint: `drivers/${driver.id}/deactivate-login`,
512
+ successMessage: this.intl.t('profile-account.prompts.deactivate-login-success', { name: driver.name }),
513
+ });
514
+ }
515
+
516
+ @action reactivateLogin(driver) {
517
+ return confirmLoginAction(this, driver, {
518
+ title: this.intl.t('profile-account.actions.reactivate-login'),
519
+ body: this.intl.t('profile-account.prompts.reactivate-login-body', { name: driver.name }),
520
+ acceptButtonText: this.intl.t('profile-account.actions.reactivate-login'),
521
+ endpoint: `drivers/${driver.id}/reactivate-login`,
522
+ successMessage: this.intl.t('profile-account.prompts.reactivate-login-success', { name: driver.name }),
523
+ });
524
+ }
525
+
428
526
  @action createIssue(driver) {
429
527
  return this.issueActions.modal.create({
430
528
  driver,