@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.
- package/RELEASE.md +21 -14
- package/addon/components/admin/telematics-settings.hbs +143 -0
- package/addon/components/admin/telematics-settings.js +145 -0
- package/addon/components/fuel-integration/hub.hbs +1 -1
- package/addon/components/layout/fleet-ops-sidebar.js +37 -17
- package/addon/components/map/leaflet-live-map.hbs +4 -242
- package/addon/components/map/leaflet-live-map.js +2 -1
- package/addon/components/map/marker-card/driver.hbs +57 -0
- package/addon/components/map/marker-card/driver.js +3 -0
- package/addon/components/map/marker-card/vehicle.hbs +78 -0
- package/addon/components/map/marker-card/vehicle.js +3 -0
- package/addon/components/order/details/activity.hbs +8 -6
- package/addon/components/order/details/activity.js +9 -0
- package/addon/components/order/details.hbs +29 -0
- package/addon/components/order/details.js +26 -0
- package/addon/components/order/form/details.hbs +30 -4
- package/addon/components/order/form/details.js +46 -0
- package/addon/components/order/form/route.hbs +4 -2
- package/addon/components/order/form/route.js +11 -0
- package/addon/components/order/form.hbs +12 -0
- package/addon/components/order/form.js +21 -1
- package/addon/components/order/kanban.js +72 -0
- package/addon/components/order-config-manager/activity-flow.js +45 -10
- package/addon/components/order-config-manager/lifecycle.hbs +250 -0
- package/addon/components/order-config-manager/lifecycle.js +358 -0
- package/addon/components/order-config-manager.js +5 -1
- package/addon/components/telematic/hub.hbs +1 -1
- package/addon/components/widget/live-fleet.hbs +8 -40
- package/addon/controllers/analytics/reports/index.js +15 -1
- package/addon/controllers/connectivity/devices/index/details.js +1 -0
- package/addon/controllers/connectivity/devices/index.js +12 -2
- package/addon/controllers/connectivity/events/index.js +31 -1
- package/addon/controllers/connectivity/fuel-providers/index.js +6 -4
- package/addon/controllers/connectivity/sensors/index/details.js +1 -1
- package/addon/controllers/connectivity/sensors/index.js +41 -1
- package/addon/controllers/connectivity/telematics/index.js +4 -0
- package/addon/controllers/maintenance/equipment/index/details.js +2 -2
- package/addon/controllers/maintenance/equipment/index.js +36 -10
- package/addon/controllers/maintenance/inspection-forms/index.js +32 -12
- package/addon/controllers/maintenance/inspection-submissions/index/details.js +2 -1
- package/addon/controllers/maintenance/inspection-submissions/index.js +56 -10
- package/addon/controllers/maintenance/maintenances/index/details.js +2 -0
- package/addon/controllers/maintenance/maintenances/index.js +24 -1
- package/addon/controllers/maintenance/parts/index/details.js +2 -2
- package/addon/controllers/maintenance/parts/index.js +36 -9
- package/addon/controllers/maintenance/schedules/index.js +48 -6
- package/addon/controllers/maintenance/work-orders/index/details.js +3 -3
- package/addon/controllers/maintenance/work-orders/index.js +47 -9
- package/addon/controllers/management/contacts/customers.js +13 -0
- package/addon/controllers/management/contacts/index.js +47 -1
- package/addon/controllers/management/drivers/index/details.js +1 -0
- package/addon/controllers/management/drivers/index.js +36 -2
- package/addon/controllers/management/fleets/index/details.js +1 -0
- package/addon/controllers/management/fleets/index.js +43 -1
- package/addon/controllers/management/fuel-reports/index.js +26 -2
- package/addon/controllers/management/fuel-transactions/index.js +45 -7
- package/addon/controllers/management/issues/index/details.js +1 -0
- package/addon/controllers/management/issues/index.js +26 -2
- package/addon/controllers/management/places/index.js +40 -1
- package/addon/controllers/management/trailers/index/details.js +1 -0
- package/addon/controllers/management/trailers/index.js +50 -2
- package/addon/controllers/management/vehicles/index/details.js +1 -0
- package/addon/controllers/management/vehicles/index.js +37 -2
- package/addon/controllers/management/vendors/index.js +30 -2
- package/addon/controllers/operations/orders/index/details.js +61 -5
- package/addon/controllers/operations/orders/index.js +66 -4
- package/addon/controllers/operations/service-rates/index.js +18 -1
- package/addon/controllers/settings/index.js +13 -0
- package/addon/controllers/settings/telematics.js +113 -0
- package/addon/extension.js +70 -6
- package/addon/routes/analytics/index.js +14 -1
- package/addon/routes/analytics/reports/index/details.js +1 -1
- package/addon/routes/analytics/reports/index/edit.js +1 -1
- package/addon/routes/analytics/reports/index/new.js +14 -1
- package/addon/routes/analytics/reports.js +14 -1
- package/addon/routes/connectivity/devices/index/new.js +14 -1
- package/addon/routes/connectivity/devices.js +14 -1
- package/addon/routes/connectivity/events.js +14 -1
- package/addon/routes/connectivity/fuel-providers/details/transactions.js +12 -0
- package/addon/routes/connectivity/fuel-providers/details.js +9 -0
- package/addon/routes/connectivity/fuel-providers/edit.js +9 -0
- package/addon/routes/connectivity/fuel-providers/new.js +14 -1
- package/addon/routes/connectivity/fuel-providers.js +14 -1
- package/addon/routes/connectivity/sensors/index/new.js +14 -1
- package/addon/routes/connectivity/sensors.js +14 -1
- package/addon/routes/connectivity/telematics/new.js +14 -1
- package/addon/routes/connectivity/telematics.js +14 -1
- package/addon/routes/connectivity/tracking.js +14 -1
- package/addon/routes/maintenance/equipment/index/details.js +2 -2
- package/addon/routes/maintenance/equipment/index/edit.js +2 -2
- package/addon/routes/maintenance/equipment/index/new.js +14 -1
- package/addon/routes/maintenance/equipment.js +14 -1
- package/addon/routes/maintenance/index.js +14 -1
- package/addon/routes/maintenance/inspection-forms/index/details.js +10 -1
- package/addon/routes/maintenance/inspection-forms/index/edit.js +10 -1
- package/addon/routes/maintenance/inspection-forms/index/new.js +14 -1
- package/addon/routes/maintenance/inspection-forms.js +14 -1
- package/addon/routes/maintenance/inspection-submissions/index/details.js +10 -1
- package/addon/routes/maintenance/inspection-submissions/index/edit.js +10 -1
- package/addon/routes/maintenance/inspection-submissions/index/new.js +14 -1
- package/addon/routes/maintenance/inspection-submissions.js +14 -1
- package/addon/routes/maintenance/maintenances/index/details.js +2 -2
- package/addon/routes/maintenance/maintenances/index/edit.js +2 -2
- package/addon/routes/maintenance/maintenances/index/new.js +14 -1
- package/addon/routes/maintenance/maintenances.js +14 -1
- package/addon/routes/maintenance/parts/index/details.js +2 -2
- package/addon/routes/maintenance/parts/index/edit.js +2 -2
- package/addon/routes/maintenance/parts/index/new.js +14 -1
- package/addon/routes/maintenance/parts.js +14 -1
- package/addon/routes/maintenance/schedules/index/details.js +2 -2
- package/addon/routes/maintenance/schedules/index/edit.js +2 -2
- package/addon/routes/maintenance/schedules/index/new.js +15 -1
- package/addon/routes/maintenance/schedules.js +15 -1
- package/addon/routes/maintenance/work-orders/index/details.js +2 -2
- package/addon/routes/maintenance/work-orders/index/edit.js +2 -2
- package/addon/routes/maintenance/work-orders/index/new.js +14 -1
- package/addon/routes/maintenance/work-orders.js +14 -1
- package/addon/routes/management/fuel-transactions/index/details.js +9 -0
- package/addon/routes/management/fuel-transactions.js +14 -1
- package/addon/routes/management/index.js +13 -0
- package/addon/routes/management/trailers.js +16 -0
- package/addon/routes/management/vendors/integrated/details.js +14 -1
- package/addon/routes/management/vendors/integrated/edit.js +14 -1
- package/addon/routes/management/vendors/integrated/new.js +14 -1
- package/addon/routes/management/vendors/integrated.js +14 -1
- package/addon/routes/operations/orders/index/details.js +1 -0
- package/addon/routes/operations/orders.js +40 -1
- package/addon/routes/operations/routes/index/details.js +14 -1
- package/addon/routes/operations/routes/index/new.js +13 -0
- package/addon/routes/operations/routes.js +14 -1
- package/addon/routes/operations/service-rates/index/new.js +11 -0
- package/addon/routes/operations/service-rates.js +14 -1
- package/addon/routes/settings/avatars.js +14 -1
- package/addon/routes/settings/custom-fields.js +14 -1
- package/addon/routes/settings/map.js +14 -1
- package/addon/routes/settings/notifications.js +11 -0
- package/addon/routes/settings/orchestrator.js +1 -1
- package/addon/routes/settings/payments/index.js +1 -1
- package/addon/routes/settings/routing.js +14 -1
- package/addon/routes/settings/scheduling.js +14 -1
- package/addon/routes/settings/telematics.js +21 -0
- package/addon/routes/virtual.js +11 -0
- package/addon/routes.js +1 -0
- package/addon/services/contact-actions.js +1 -0
- package/addon/services/customer-actions.js +2 -1
- package/addon/services/device-actions.js +1 -0
- package/addon/services/device-event-actions.js +1 -0
- package/addon/services/driver-actions.js +4 -13
- package/addon/services/equipment-actions.js +1 -0
- package/addon/services/fleet-actions.js +1 -0
- package/addon/services/fuel-report-actions.js +1 -0
- package/addon/services/inspection-form-actions.js +1 -0
- package/addon/services/inspection-submission-actions.js +1 -0
- package/addon/services/integrated-vendor-actions.js +1 -0
- package/addon/services/issue-actions.js +1 -0
- package/addon/services/maintenance-actions.js +1 -0
- package/addon/services/maintenance-schedule-actions.js +2 -1
- package/addon/services/order-actions.js +7 -0
- package/addon/services/order-presentation.js +129 -0
- package/addon/services/part-actions.js +1 -0
- package/addon/services/place-actions.js +1 -0
- package/addon/services/sensor-actions.js +1 -0
- package/addon/services/service-area-actions.js +1 -0
- package/addon/services/service-rate-actions.js +1 -0
- package/addon/services/telematic-actions.js +1 -0
- package/addon/services/trailer-actions.js +4 -14
- package/addon/services/vehicle-actions.js +4 -13
- package/addon/services/vendor-actions.js +1 -0
- package/addon/services/work-order-actions.js +1 -0
- package/addon/services/zone-actions.js +1 -0
- package/addon/templates/analytics/reports/index/details.hbs +1 -0
- package/addon/templates/analytics/reports/index.hbs +1 -0
- package/addon/templates/connectivity/devices/index/details.hbs +1 -0
- package/addon/templates/connectivity/devices/index.hbs +1 -0
- package/addon/templates/connectivity/events/index.hbs +1 -0
- package/addon/templates/connectivity/sensors/index/details.hbs +1 -0
- package/addon/templates/connectivity/sensors/index.hbs +1 -0
- package/addon/templates/maintenance/equipment/index/details.hbs +1 -0
- package/addon/templates/maintenance/equipment/index.hbs +2 -0
- package/addon/templates/maintenance/inspection-forms/index/details.hbs +1 -0
- package/addon/templates/maintenance/inspection-forms/index.hbs +1 -0
- package/addon/templates/maintenance/inspection-submissions/index/details.hbs +1 -0
- package/addon/templates/maintenance/inspection-submissions/index.hbs +1 -0
- package/addon/templates/maintenance/maintenances/index/details.hbs +1 -0
- package/addon/templates/maintenance/maintenances/index.hbs +1 -0
- package/addon/templates/maintenance/parts/index/details.hbs +1 -0
- package/addon/templates/maintenance/parts/index.hbs +2 -0
- package/addon/templates/maintenance/schedules/index/details.hbs +1 -0
- package/addon/templates/maintenance/schedules/index.hbs +2 -0
- package/addon/templates/maintenance/work-orders/index/details.hbs +1 -0
- package/addon/templates/maintenance/work-orders/index.hbs +1 -0
- package/addon/templates/management/contacts/customers/details.hbs +1 -0
- package/addon/templates/management/contacts/customers.hbs +1 -0
- package/addon/templates/management/contacts/index/details.hbs +1 -0
- package/addon/templates/management/contacts/index.hbs +1 -0
- package/addon/templates/management/contacts.hbs +1 -0
- package/addon/templates/management/drivers/index/details.hbs +1 -0
- package/addon/templates/management/drivers/index.hbs +2 -0
- package/addon/templates/management/fleets/index/details.hbs +1 -0
- package/addon/templates/management/fleets/index.hbs +1 -0
- package/addon/templates/management/fuel-reports/index/details.hbs +1 -0
- package/addon/templates/management/fuel-reports/index.hbs +1 -0
- package/addon/templates/management/fuel-transactions/index.hbs +1 -0
- package/addon/templates/management/issues/index/details.hbs +1 -0
- package/addon/templates/management/issues/index.hbs +1 -0
- package/addon/templates/management/places/index/details.hbs +1 -0
- package/addon/templates/management/places/index.hbs +1 -0
- package/addon/templates/management/trailers/index/details.hbs +1 -0
- package/addon/templates/management/trailers/index.hbs +2 -0
- package/addon/templates/management/vehicles/index/details.hbs +1 -0
- package/addon/templates/management/vehicles/index.hbs +2 -0
- package/addon/templates/management/vendors/index/details.hbs +1 -0
- package/addon/templates/management/vendors/index.hbs +2 -0
- package/addon/templates/management/vendors/integrated.hbs +1 -0
- package/addon/templates/operations/orders/index/details.hbs +1 -0
- package/addon/templates/operations/orders/index.hbs +1 -0
- package/addon/templates/operations/service-rates/index/details.hbs +1 -0
- package/addon/templates/operations/service-rates/index.hbs +1 -0
- package/addon/templates/settings/telematics.hbs +70 -0
- package/addon/utils/normalize-order-config-flow.js +6 -1
- package/app/components/admin/telematics-settings.js +1 -0
- package/app/components/map/marker-card/driver.js +1 -0
- package/app/components/map/marker-card/vehicle.js +1 -0
- package/app/controllers/settings/telematics.js +1 -0
- package/app/routes/settings/telematics.js +1 -0
- package/app/services/order-presentation.js +1 -0
- package/app/templates/settings/telematics.js +1 -0
- package/composer.json +2 -2
- package/docs/AFAQY.md +1 -1
- package/docs/TELEMATICS_QUEUES.md +1 -1
- package/docs/TELEMETRY_ARCHITECTURE.md +72 -1
- package/extension.json +1 -1
- package/package.json +3 -3
- package/server/config/telemetry.php +12 -0
- package/server/migrations/2026_09_23_000001_add_retention_index_to_device_events.php +40 -0
- package/server/migrations/2026_09_23_000002_add_retention_index_to_positions.php +40 -0
- package/server/migrations/2026_09_23_000003_add_retention_index_to_telematic_sync_runs.php +40 -0
- package/server/src/Auth/Schemas/FleetOps.php +104 -5
- package/server/src/Console/Commands/DrainTelematicInbox.php +3 -13
- package/server/src/Console/Commands/ProcessOperationalAlerts.php +3 -3
- package/server/src/Console/Commands/PruneTelematicsData.php +318 -0
- package/server/src/Http/Controllers/Api/v1/OrchestrationController.php +9 -0
- package/server/src/Http/Controllers/FleetOpsController.php +21 -0
- package/server/src/Http/Controllers/Internal/v1/AnalyticsController.php +11 -0
- package/server/src/Http/Controllers/Internal/v1/ContactController.php +11 -0
- package/server/src/Http/Controllers/Internal/v1/CustomerController.php +14 -0
- package/server/src/Http/Controllers/Internal/v1/DeviceController.php +13 -0
- package/server/src/Http/Controllers/Internal/v1/DeviceEventController.php +11 -0
- package/server/src/Http/Controllers/Internal/v1/DriverController.php +22 -0
- package/server/src/Http/Controllers/Internal/v1/FuelProviderConnectionController.php +13 -0
- package/server/src/Http/Controllers/Internal/v1/FuelProviderTransactionController.php +15 -0
- package/server/src/Http/Controllers/Internal/v1/FuelReportController.php +9 -3
- package/server/src/Http/Controllers/Internal/v1/InspectionFormController.php +15 -0
- package/server/src/Http/Controllers/Internal/v1/LiveController.php +16 -0
- package/server/src/Http/Controllers/Internal/v1/MaintenanceController.php +15 -0
- package/server/src/Http/Controllers/Internal/v1/MaintenanceScheduleController.php +15 -0
- package/server/src/Http/Controllers/Internal/v1/ManifestController.php +15 -0
- package/server/src/Http/Controllers/Internal/v1/MetricsController.php +11 -0
- package/server/src/Http/Controllers/Internal/v1/NavigatorController.php +42 -1
- package/server/src/Http/Controllers/Internal/v1/OrchestrationController.php +12 -0
- package/server/src/Http/Controllers/Internal/v1/OrderController.php +56 -4
- package/server/src/Http/Controllers/Internal/v1/PaymentController.php +13 -0
- package/server/src/Http/Controllers/Internal/v1/RadarController.php +19 -0
- package/server/src/Http/Controllers/Internal/v1/ServiceAreaController.php +9 -3
- package/server/src/Http/Controllers/Internal/v1/SettingController.php +465 -14
- package/server/src/Http/Controllers/Internal/v1/TelematicController.php +21 -0
- package/server/src/Http/Controllers/Internal/v1/TrailerController.php +21 -0
- package/server/src/Http/Controllers/Internal/v1/VehicleController.php +21 -0
- package/server/src/Http/Controllers/Internal/v1/VendorController.php +17 -0
- package/server/src/Http/Controllers/Internal/v1/WorkOrderController.php +11 -0
- package/server/src/Jobs/DispatchTelematicsRetentionJobs.php +70 -0
- package/server/src/Jobs/PruneTelematicsDataJob.php +74 -0
- package/server/src/Listeners/NotifyDriverOnShiftChange.php +3 -3
- package/server/src/Mail/CustomerCredentialsMail.php +1 -1
- package/server/src/Models/Order.php +35 -3
- package/server/src/Models/OrderConfig.php +129 -0
- package/server/src/Models/TrackingNumber.php +8 -4
- package/server/src/Orchestration/Engines/VroomOrchestrationEngine.php +9 -1
- package/server/src/Providers/FleetOpsServiceProvider.php +3 -0
- package/server/src/Support/Analytics/LiveFleet.php +18 -2
- package/server/src/Support/Authorization.php +103 -0
- package/server/src/Support/Database/TableIndexes.php +66 -0
- package/server/src/Support/OrderTracker.php +2 -2
- package/server/src/Support/Reporting/FleetOpsReportSchema.php +476 -116
- package/server/src/Support/Telematics/Retention/RetentionPolicy.php +300 -0
- package/server/src/Support/Telematics/Retention/TelemetryActivity.php +40 -0
- package/server/src/Support/Telematics/TelematicService.php +12 -2
- package/server/src/Support/Telematics/Telemetry/Ingestor.php +4 -2
- package/server/src/Tracking/TrackingIntelligenceService.php +1 -1
- package/server/src/Tracking/TrackingOptions.php +2 -2
- package/server/src/Traits/AuthorizesMethods.php +37 -0
- package/server/src/routes.php +9 -1
- package/server/tests/AnalyticsRoutesTest.php +29 -2
- package/server/tests/Feature/Http/AfaqyRealtimeIngestionTest.php +16 -1
- package/server/tests/Feature/Http/Api/TelematicsRetentionIndexMigrationTest.php +115 -0
- package/server/tests/Feature/Http/Internal/OrderControllerActivityFlowsTest.php +72 -0
- package/server/tests/Feature/Http/Internal/OrderControllerCreateRecordTest.php +26 -0
- package/server/tests/Feature/Http/Internal/SettingControllerHelpersTest.php +71 -0
- package/server/tests/Feature/Http/Internal/TelematicsStorageDeadlinesTest.php +119 -0
- package/server/tests/InternalImportExportControllerContractsTest.php +5 -8
- package/server/tests/NavigatorControllerContractsTest.php +36 -4
- package/server/tests/NotificationAndMailContractsTest.php +31 -0
- package/server/tests/ObserverContractsTest.php +1 -1
- package/server/tests/OrchestratorConsumableApiTest.php +42 -0
- package/server/tests/OrderConfigLifecycleTest.php +120 -0
- package/server/tests/ProviderContractsTest.php +10 -0
- package/server/tests/ReportSchemaContractsTest.php +120 -6
- package/server/tests/SettingControllerContractsTest.php +429 -18
- package/server/tests/SmallControllerContractsTest.php +8 -5
- package/server/tests/Support/PruneTelematicsDataProbe.php +55 -0
- package/server/tests/Unit/Console/Commands/ProcessOperationalAlertsCommandTest.php +2 -2
- package/server/tests/Unit/Console/PruneTelematicsDataCommandTest.php +353 -0
- package/server/tests/Unit/Events/OrderDispatchFailedTest.php +2 -1
- package/server/tests/Unit/Jobs/DispatchTelematicsRetentionJobsTest.php +114 -0
- package/server/tests/Unit/Jobs/PruneTelematicsDataJobTest.php +60 -0
- package/server/tests/Unit/Orchestration/VroomEngineTransportAndSettingsTest.php +20 -0
- package/server/tests/Unit/Support/Analytics/LiveFleetTest.php +6 -0
- package/server/tests/Unit/Support/AuthorizationTest.php +142 -0
- package/server/tests/Unit/Support/MaintainableAndOperationalAlertsTest.php +12 -1
- package/server/tests/Unit/Support/MoreQuerySeamsTest.php +11 -2
- package/server/tests/Unit/Support/Telematics/Retention/RetentionPolicyTest.php +190 -0
- package/server/tests/Unit/Support/Telematics/Retention/TelemetryActivityTest.php +68 -0
- package/server/tests/Unit/Tracking/TrackingOptionsCompanySettingsTest.php +109 -0
- package/translations/en-us.yaml +108 -0
package/RELEASE.md
CHANGED
|
@@ -1,25 +1,32 @@
|
|
|
1
|
-
> v0.6.
|
|
1
|
+
> v0.6.71 ~ "Extensible tables and panels, configured order lifecycles and order presentation profiles"
|
|
2
2
|
|
|
3
3
|
---
|
|
4
|
-
##
|
|
5
|
-
- **Fleet-Ops works with Fleetbase AI tool calling.** Creating orders from the AI prompt works again with the tool-calling assistant, and the assistant can also propose an optimized waypoint sequence for an order and explain what an order or resource import needs. Every change is a preview card the user confirms.
|
|
6
|
-
- **Fleet-Ops console actions.** The assistant can offer to open Fleet-Ops pages and dialogs, such as **Operations › Orders** and **New Order**, as confirmation cards.
|
|
7
|
-
- **Resource search for the assistant.** A `fleetops_search` tool finds orders, vehicles, drivers, work orders, maintenances, devices, sensors and telematics records by id, name, plate, VIN, email or phone.
|
|
4
|
+
## Highlights
|
|
8
5
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
-
|
|
6
|
+
- **Resource view registries.** Extensions can add the following through `fleet-ops:<resource>:table:<slot>` and `fleet-ops:<resource>:details:<slot>`:
|
|
7
|
+
- columns, row actions, bulk actions and toolbar buttons on every top-level Fleet-Ops table;
|
|
8
|
+
- header buttons and "…" menu items on its details panels and side panels.
|
|
12
9
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
-
|
|
16
|
-
-
|
|
10
|
+
Built-in items carry stable ids, so registered items can be placed before or after them.
|
|
11
|
+
- **Configured order lifecycles.** An order config can define its own lifecycle in `meta.lifecycle`: `initial`, `completed`, `canceled` and `terminal` activities, `dispatch: false` and `strict_transitions`. The internal API starts orders at the initial activity, refuses to dispatch when dispatch is off, accepts only the flow's transitions when strict, and cancels to the configured activity. Configs without a lifecycle behave as before.
|
|
12
|
+
- **Lifecycle tab** in Order Configuration, to view and edit a config's lifecycle.
|
|
13
|
+
- **The board** shows a configured lifecycle's activities as its columns.
|
|
14
|
+
- **The activity flow editor** roots at the configured initial activity, and handles flows with cycles.
|
|
15
|
+
- **Order presentation profiles.** An extension can give its order type its own order form sections, extra and hidden fields, details view sections and hidden actions, registered in `fleet-ops:order-presentation`. **Edit details** opens the profiled form. Other order types are unchanged.
|
|
16
|
+
- **The Order Configuration manager lists every config**, including configs created while the console is open.
|
|
17
|
+
- **An order's activity timeline follows status changes made on the server.**
|
|
18
|
+
- **Fix: the Activity Flow crashed on a flow with a cycle.**
|
|
19
|
+
- **Fix: order details now load the assigned vehicle with the order.**
|
|
20
|
+
- **Fix: the order form failed when its custom fields couldn't load.**
|
|
21
|
+
- **Fix: registered details tabs.** Opening a driver, vehicle or trailer side panel removed the route from tabs other extensions had registered, which broke them in the full details view. Side panels also left out the tabs they could render.
|
|
22
|
+
- **Fix: the sensor details view showed the tabs registered for places.**
|
|
17
23
|
|
|
18
24
|
---
|
|
19
|
-
##
|
|
20
|
-
-
|
|
25
|
+
## Upgrading
|
|
26
|
+
Needs fleetbase/ember-core v0.3.25 and fleetbase/ember-ui v0.4.5.
|
|
21
27
|
|
|
22
28
|
---
|
|
23
29
|
## Need help?
|
|
24
30
|
- [GitHub Discussions](https://github.com/fleetbase/fleetbase/discussions)
|
|
25
31
|
- [Discord](https://discord.gg/HnTqQ6zAVn)
|
|
32
|
+
---
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
<div class="space-y-6">
|
|
2
|
+
<InfoBlock @type="info" @icon="circle-info" class="mb-4">
|
|
3
|
+
Configure telematics retention policy and activity logging for all organizations. Organizations can choose device event and position history retention within these limits from Fleet-Ops › Settings › Telematics.
|
|
4
|
+
A maximum takes precedence over organization preferences, inherited defaults and requests to keep history forever. Reducing a maximum can delete existing history at the next cleanup.
|
|
5
|
+
</InfoBlock>
|
|
6
|
+
|
|
7
|
+
<ContentPanel @title="System Device Events Retention Policy" @open={{true}} @wrapperClass="bordered-classic">
|
|
8
|
+
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
|
9
|
+
<InputGroup @name="Default Device Event Retention (days)" @helpText="Retention for organizations that inherit the system default. 0 keeps history forever, subject to the maximum below.">
|
|
10
|
+
<Input @type="number" @value={{this.eventRetentionDays}} min="0" max="3650" class="form-input w-full" />
|
|
11
|
+
</InputGroup>
|
|
12
|
+
<InputGroup @name="Maximum Device Event Retention (days)" @helpText="The longest any organization can keep device events. 0 sets no maximum and allows organizations to keep history forever.">
|
|
13
|
+
<Input @type="number" @value={{this.maxEventRetentionDays}} min="0" max="3650" class="form-input w-full" />
|
|
14
|
+
</InputGroup>
|
|
15
|
+
</div>
|
|
16
|
+
</ContentPanel>
|
|
17
|
+
|
|
18
|
+
<ContentPanel @title="System Position History Retention Policy" @open={{true}} @wrapperClass="bordered-classic">
|
|
19
|
+
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
|
20
|
+
<InputGroup @name="Default Position History Retention (days)" @helpText="Retention for organizations that inherit the system default. 0 keeps history forever, subject to the maximum below.">
|
|
21
|
+
<Input @type="number" @value={{this.positionRetentionDays}} min="0" max="3650" class="form-input w-full" />
|
|
22
|
+
</InputGroup>
|
|
23
|
+
<InputGroup @name="Maximum Position History Retention (days)" @helpText="The longest any organization can keep vehicle and trailer positions. 0 sets no maximum and allows organizations to keep history forever.">
|
|
24
|
+
<Input @type="number" @value={{this.maxPositionRetentionDays}} min="0" max="3650" class="form-input w-full" />
|
|
25
|
+
</InputGroup>
|
|
26
|
+
</div>
|
|
27
|
+
</ContentPanel>
|
|
28
|
+
|
|
29
|
+
<ContentPanel @title="System Device Event Raw Payload Retention" @open={{true}} @wrapperClass="bordered-classic">
|
|
30
|
+
<InputGroup @name="Device Event Raw Payload Retention (days)" @helpText="Remove raw provider payloads from retained device events across all organizations after this many days. 0 disables compaction. This does not change how long the event history itself is kept.">
|
|
31
|
+
<Input @type="number" @value={{this.eventCompactAfterDays}} min="0" max="3650" class="form-input w-full" />
|
|
32
|
+
</InputGroup>
|
|
33
|
+
</ContentPanel>
|
|
34
|
+
|
|
35
|
+
<ContentPanel @title="System Delivery Inbox and Sync Run Retention Policy" @open={{true}} @wrapperClass="bordered-classic">
|
|
36
|
+
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
|
37
|
+
<InputGroup @name="Processed Delivery Retention (hours)" @helpText="Delete processed delivery envelopes across all organizations after this many hours. 0 keeps them forever.">
|
|
38
|
+
<Input @type="number" @value={{this.processedRetentionHours}} min="0" max="720" class="form-input w-full" />
|
|
39
|
+
</InputGroup>
|
|
40
|
+
<InputGroup @name="Quarantined Delivery Retention (days)" @helpText="Delete quarantined delivery envelopes across all organizations after this many days. 0 keeps them forever.">
|
|
41
|
+
<Input @type="number" @value={{this.quarantineRetentionDays}} min="0" max="365" class="form-input w-full" />
|
|
42
|
+
</InputGroup>
|
|
43
|
+
<InputGroup @name="Sync Run Diagnostics Retention (days)" @helpText="Delete finished sync run diagnostics across all organizations after this many days. 0 keeps them forever.">
|
|
44
|
+
<Input @type="number" @value={{this.syncRunRetentionDays}} min="0" max="365" class="form-input w-full" />
|
|
45
|
+
</InputGroup>
|
|
46
|
+
</div>
|
|
47
|
+
</ContentPanel>
|
|
48
|
+
|
|
49
|
+
<ContentPanel @title="System Telemetry Activity Logging" @open={{true}} @wrapperClass="bordered-classic">
|
|
50
|
+
<Toggle
|
|
51
|
+
@label="Log Telemetry Activity"
|
|
52
|
+
@helpText="Write telemetry-driven device, event and vehicle saves to the activity log for all organizations. Every poll can add several activity rows per device."
|
|
53
|
+
@isToggled={{this.logTelemetryActivity}}
|
|
54
|
+
@onToggle={{fn (mut this.logTelemetryActivity)}}
|
|
55
|
+
/>
|
|
56
|
+
</ContentPanel>
|
|
57
|
+
|
|
58
|
+
<div class="flex justify-end">
|
|
59
|
+
<Button
|
|
60
|
+
@type="primary"
|
|
61
|
+
@size="sm"
|
|
62
|
+
@icon="save"
|
|
63
|
+
@text="Save System Policy"
|
|
64
|
+
@onClick={{perform this.saveSettings}}
|
|
65
|
+
@disabled={{or this.saveSettings.isRunning this.loadSettings.isRunning (not this.settingsLoaded)}}
|
|
66
|
+
@isLoading={{or this.saveSettings.isRunning this.loadSettings.isRunning}}
|
|
67
|
+
/>
|
|
68
|
+
</div>
|
|
69
|
+
|
|
70
|
+
<ContentPanel @title={{t "settings.telematics.storage-usage"}} @open={{true}} @wrapperClass="bordered-classic">
|
|
71
|
+
<p class="mb-3 text-sm text-gray-600 dark:text-gray-300">
|
|
72
|
+
Storage usage includes telematics data across all organizations. Cleanup applies system-wide, using the saved system policy and each organization's history preferences within that policy.
|
|
73
|
+
</p>
|
|
74
|
+
<div class="flex items-center justify-end gap-2 mb-3">
|
|
75
|
+
<Button
|
|
76
|
+
@size="xs"
|
|
77
|
+
@icon="rotate"
|
|
78
|
+
@text={{t "settings.telematics.refresh"}}
|
|
79
|
+
@onClick={{perform this.loadUsage}}
|
|
80
|
+
@disabled={{this.loadUsage.isRunning}}
|
|
81
|
+
@isLoading={{this.loadUsage.isRunning}}
|
|
82
|
+
/>
|
|
83
|
+
<Button
|
|
84
|
+
@type="danger"
|
|
85
|
+
@size="xs"
|
|
86
|
+
@icon="broom"
|
|
87
|
+
@text={{t "settings.telematics.run-cleanup"}}
|
|
88
|
+
@onClick={{this.confirmRunCleanup}}
|
|
89
|
+
@disabled={{or this.runCleanup.isRunning this.loadSettings.isRunning this.saveSettings.isRunning (not this.settingsLoaded)}}
|
|
90
|
+
@isLoading={{this.runCleanup.isRunning}}
|
|
91
|
+
/>
|
|
92
|
+
</div>
|
|
93
|
+
{{#if this.usageRows.length}}
|
|
94
|
+
<div class="overflow-x-auto">
|
|
95
|
+
<table class="w-full text-sm">
|
|
96
|
+
<thead>
|
|
97
|
+
<tr class="text-left text-xs uppercase text-gray-500 dark:text-gray-400">
|
|
98
|
+
<th class="py-2 pr-3">{{t "settings.telematics.table"}}</th>
|
|
99
|
+
<th class="py-2 pr-3 text-right">{{t "settings.telematics.rows"}}</th>
|
|
100
|
+
<th class="py-2 pr-3 text-right">{{t "settings.telematics.estimated-size"}}</th>
|
|
101
|
+
<th class="py-2 pl-6 text-right whitespace-nowrap">{{t "settings.telematics.oldest"}}</th>
|
|
102
|
+
</tr>
|
|
103
|
+
</thead>
|
|
104
|
+
<tbody class="divide-y divide-gray-100 dark:divide-gray-700">
|
|
105
|
+
{{#each this.usageRows as |row|}}
|
|
106
|
+
<tr class="text-gray-800 dark:text-gray-100">
|
|
107
|
+
<td class="py-2 pr-3">
|
|
108
|
+
<div class="font-medium">{{row.label}}</div>
|
|
109
|
+
{{#if row.raw_payload_rows}}
|
|
110
|
+
<div class="text-xs text-gray-500 dark:text-gray-400">
|
|
111
|
+
{{t "settings.telematics.raw-payload-rows" count=(format-number row.raw_payload_rows) compactable=(format-number row.compactable_rows)}}
|
|
112
|
+
</div>
|
|
113
|
+
{{/if}}
|
|
114
|
+
</td>
|
|
115
|
+
<td class="py-2 pr-3 text-right">
|
|
116
|
+
{{#if (eq row.rows null)}}
|
|
117
|
+
{{t "settings.telematics.not-available"}}
|
|
118
|
+
{{else if row.rows_estimated}}
|
|
119
|
+
{{t "settings.telematics.estimated-rows" count=(format-number row.rows)}}
|
|
120
|
+
{{else}}
|
|
121
|
+
{{format-number row.rows}}
|
|
122
|
+
{{/if}}
|
|
123
|
+
</td>
|
|
124
|
+
<td class="py-2 pr-3 text-right">{{#if (or row.estimated_bytes (eq row.estimated_bytes 0))}}{{format-bytes row.estimated_bytes}}{{else}}{{t "settings.telematics.not-available"}}{{/if}}</td>
|
|
125
|
+
<td class="py-2 pl-6 text-right text-xs whitespace-nowrap">{{#if row.oldest}}{{row.oldest}}{{else}}{{t "settings.telematics.not-available"}}{{/if}}</td>
|
|
126
|
+
</tr>
|
|
127
|
+
{{/each}}
|
|
128
|
+
</tbody>
|
|
129
|
+
</table>
|
|
130
|
+
</div>
|
|
131
|
+
<p class="mt-3 text-xs text-gray-500 dark:text-gray-400">{{t "settings.telematics.space-reclaim-note"}}</p>
|
|
132
|
+
{{else if this.loadUsage.isRunning}}
|
|
133
|
+
<div class="flex items-center justify-center py-8">
|
|
134
|
+
<Spinner />
|
|
135
|
+
</div>
|
|
136
|
+
{{else}}
|
|
137
|
+
<div class="text-center py-8 text-sm text-gray-400 dark:text-gray-500">
|
|
138
|
+
{{t "settings.telematics.usage-unavailable"}}
|
|
139
|
+
</div>
|
|
140
|
+
{{/if}}
|
|
141
|
+
</ContentPanel>
|
|
142
|
+
<Spacer @height="200px" />
|
|
143
|
+
</div>
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import Component from '@glimmer/component';
|
|
2
|
+
import { tracked } from '@glimmer/tracking';
|
|
3
|
+
import { inject as service } from '@ember/service';
|
|
4
|
+
import { action } from '@ember/object';
|
|
5
|
+
import { task, timeout } from 'ember-concurrency';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* System-wide telematics policy, storage diagnostics and operational controls.
|
|
9
|
+
*/
|
|
10
|
+
export default class AdminTelematicsSettingsComponent extends Component {
|
|
11
|
+
@service fetch;
|
|
12
|
+
@service notifications;
|
|
13
|
+
@service intl;
|
|
14
|
+
@service modalsManager;
|
|
15
|
+
@tracked eventRetentionDays = 30;
|
|
16
|
+
@tracked maxEventRetentionDays = 0;
|
|
17
|
+
@tracked eventCompactAfterDays = 7;
|
|
18
|
+
@tracked positionRetentionDays = 90;
|
|
19
|
+
@tracked maxPositionRetentionDays = 0;
|
|
20
|
+
@tracked processedRetentionHours = 24;
|
|
21
|
+
@tracked quarantineRetentionDays = 7;
|
|
22
|
+
@tracked syncRunRetentionDays = 7;
|
|
23
|
+
@tracked logTelemetryActivity = false;
|
|
24
|
+
@tracked settingsLoaded = false;
|
|
25
|
+
@tracked usage = null;
|
|
26
|
+
|
|
27
|
+
constructor() {
|
|
28
|
+
super(...arguments);
|
|
29
|
+
this.loadSettings.perform();
|
|
30
|
+
this.loadUsage.perform();
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
@task({ drop: true }) *loadSettings() {
|
|
34
|
+
try {
|
|
35
|
+
const settings = yield this.fetch.get('fleet-ops/settings/admin-telematics-settings');
|
|
36
|
+
this.applySettings(settings);
|
|
37
|
+
this.settingsLoaded = true;
|
|
38
|
+
} catch (error) {
|
|
39
|
+
this.notifications.serverError(error);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
@task({ drop: true }) *saveSettings() {
|
|
44
|
+
if (!this.settingsLoaded) {
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
try {
|
|
49
|
+
const settings = yield this.fetch.post('fleet-ops/settings/admin-telematics-settings', this.settingsPayload);
|
|
50
|
+
this.applySettings(settings);
|
|
51
|
+
this.notifications.success('System telematics settings saved.');
|
|
52
|
+
} catch (error) {
|
|
53
|
+
this.notifications.serverError(error);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/** Load system-wide storage usage across all organizations. */
|
|
58
|
+
@task({ drop: true }) *loadUsage() {
|
|
59
|
+
const abortController = new AbortController();
|
|
60
|
+
const requestTimeout = setTimeout(() => abortController.abort(), 30000);
|
|
61
|
+
|
|
62
|
+
try {
|
|
63
|
+
// Pass the signal as request data; fetch.get options do not forward it.
|
|
64
|
+
const usage = yield this.fetch.request('fleet-ops/settings/telematics-storage-usage?include_payload_counts=0', 'GET', { signal: abortController.signal });
|
|
65
|
+
if (usage?.scope !== 'system') {
|
|
66
|
+
throw new Error(this.intl.t('settings.telematics.usage-unavailable'));
|
|
67
|
+
}
|
|
68
|
+
this.usage = usage;
|
|
69
|
+
} catch (error) {
|
|
70
|
+
this.notifications.serverError(abortController.signal.aborted ? new Error(this.intl.t('settings.telematics.usage-unavailable')) : error);
|
|
71
|
+
} finally {
|
|
72
|
+
clearTimeout(requestTimeout);
|
|
73
|
+
abortController.abort();
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/** Queue cleanup for all organizations using the saved policy. */
|
|
78
|
+
@task({ drop: true }) *runCleanup() {
|
|
79
|
+
try {
|
|
80
|
+
const cleanup = yield this.fetch.post('fleet-ops/settings/telematics-retention/run');
|
|
81
|
+
if (cleanup?.scope !== 'system') {
|
|
82
|
+
throw new Error(this.intl.t('settings.telematics.cleanup-unavailable'));
|
|
83
|
+
}
|
|
84
|
+
this.notifications.success(this.intl.t('settings.telematics.cleanup-queued'));
|
|
85
|
+
yield timeout(5000);
|
|
86
|
+
yield this.loadUsage.perform();
|
|
87
|
+
} catch (error) {
|
|
88
|
+
this.notifications.serverError(error);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
@action confirmRunCleanup() {
|
|
93
|
+
return this.modalsManager.confirm({
|
|
94
|
+
title: this.intl.t('settings.telematics.run-cleanup'),
|
|
95
|
+
body: this.intl.t('settings.telematics.run-cleanup-confirm'),
|
|
96
|
+
acceptButtonText: this.intl.t('settings.telematics.run-cleanup'),
|
|
97
|
+
acceptButtonIcon: 'broom',
|
|
98
|
+
onConfirm: () => this.runCleanup.perform(),
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
get usageRows() {
|
|
103
|
+
const tables = this.usage?.tables ?? {};
|
|
104
|
+
|
|
105
|
+
return ['device_events', 'positions', 'telematic_deliveries', 'telematic_sync_runs']
|
|
106
|
+
.filter((table) => tables[table])
|
|
107
|
+
.map((table) => ({ table, label: this.intl.t(`settings.telematics.tables.${table}`), ...tables[table] }));
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
get settingsPayload() {
|
|
111
|
+
return {
|
|
112
|
+
event_retention_days: this.toInteger(this.eventRetentionDays),
|
|
113
|
+
max_event_retention_days: this.maxEventRetentionDays,
|
|
114
|
+
event_compact_after_days: this.toInteger(this.eventCompactAfterDays),
|
|
115
|
+
position_retention_days: this.toInteger(this.positionRetentionDays),
|
|
116
|
+
max_position_retention_days: this.maxPositionRetentionDays,
|
|
117
|
+
processed_retention_hours: this.toInteger(this.processedRetentionHours),
|
|
118
|
+
quarantine_retention_days: this.toInteger(this.quarantineRetentionDays),
|
|
119
|
+
sync_run_retention_days: this.toInteger(this.syncRunRetentionDays),
|
|
120
|
+
log_telemetry_activity: Boolean(this.logTelemetryActivity),
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
applySettings(settings = {}) {
|
|
125
|
+
if (!Object.prototype.hasOwnProperty.call(settings ?? {}, 'max_event_retention_days') || !Object.prototype.hasOwnProperty.call(settings ?? {}, 'max_position_retention_days')) {
|
|
126
|
+
throw new Error(this.intl.t('settings.telematics.settings-unavailable'));
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
this.eventRetentionDays = settings.event_retention_days ?? this.eventRetentionDays;
|
|
130
|
+
this.maxEventRetentionDays = settings.max_event_retention_days ?? this.maxEventRetentionDays;
|
|
131
|
+
this.eventCompactAfterDays = settings.event_compact_after_days ?? this.eventCompactAfterDays;
|
|
132
|
+
this.positionRetentionDays = settings.position_retention_days ?? this.positionRetentionDays;
|
|
133
|
+
this.maxPositionRetentionDays = settings.max_position_retention_days ?? this.maxPositionRetentionDays;
|
|
134
|
+
this.processedRetentionHours = settings.processed_retention_hours ?? this.processedRetentionHours;
|
|
135
|
+
this.quarantineRetentionDays = settings.quarantine_retention_days ?? this.quarantineRetentionDays;
|
|
136
|
+
this.syncRunRetentionDays = settings.sync_run_retention_days ?? this.syncRunRetentionDays;
|
|
137
|
+
this.logTelemetryActivity = settings.log_telemetry_activity ?? this.logTelemetryActivity;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
toInteger(value) {
|
|
141
|
+
const number = parseInt(value, 10);
|
|
142
|
+
|
|
143
|
+
return Number.isFinite(number) && number > 0 ? number : 0;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
</div>
|
|
18
18
|
<div class="flex flex-shrink-0 items-center gap-2 whitespace-nowrap">
|
|
19
19
|
<Button @icon="refresh" @size="sm" @helpText={{t "common.reload"}} @onClick={{@onRefresh}} />
|
|
20
|
-
<Button @icon="plus" @text="Connect Integration" @type="primary" @size="sm" @onClick={{this.createIntegration}} />
|
|
20
|
+
<Button @icon="plus" @text="Connect Integration" @type="primary" @size="sm" @permission="fleet-ops create fuel-provider-connection" @onClick={{this.createIntegration}} />
|
|
21
21
|
</div>
|
|
22
22
|
</div>
|
|
23
23
|
</section>
|
|
@@ -151,14 +151,14 @@ export default class LayoutFleetOpsSidebarComponent extends Component {
|
|
|
151
151
|
this.createItem('menu.contacts', 'address-book', 'management.contacts', 'fleet-ops list contact', 'fleet-ops see contact'),
|
|
152
152
|
this.createItem('menu.places', 'location-dot', 'management.places', 'fleet-ops list place', 'fleet-ops see place'),
|
|
153
153
|
this.createItem('menu.fuel-reports', 'gas-pump', 'management.fuel-reports', 'fleet-ops list fuel-report', 'fleet-ops see fuel-report'),
|
|
154
|
-
this.createItem('menu.fuel-transactions', 'credit-card', 'management.fuel-transactions', 'fleet-ops list fuel-
|
|
154
|
+
this.createItem('menu.fuel-transactions', 'credit-card', 'management.fuel-transactions', 'fleet-ops list fuel-provider-transaction', 'fleet-ops see fuel-provider-transaction'),
|
|
155
155
|
this.createItem('menu.issues', 'triangle-exclamation', 'management.issues', 'fleet-ops list issue', 'fleet-ops see issue'),
|
|
156
156
|
]);
|
|
157
157
|
}
|
|
158
158
|
|
|
159
159
|
get maintenanceItems() {
|
|
160
160
|
return this.withRegistryItems('maintenance', [
|
|
161
|
-
this.createHubItem('Maintenance Hub', 'wrench', 'maintenance.index', 'fleet-ops list
|
|
161
|
+
this.createHubItem('Maintenance Hub', 'wrench', 'maintenance.index', 'fleet-ops list work-order', 'fleet-ops see work-order', [
|
|
162
162
|
'maintenance hub',
|
|
163
163
|
'service readiness',
|
|
164
164
|
'maintenance control panel',
|
|
@@ -182,7 +182,9 @@ export default class LayoutFleetOpsSidebarComponent extends Component {
|
|
|
182
182
|
get connectivityItems() {
|
|
183
183
|
return this.withRegistryItems('connectivity', [
|
|
184
184
|
this.createHubItem(this.intl.t('menu.telematics'), 'satellite-dish', 'connectivity.telematics', 'fleet-ops list telematic', 'fleet-ops see telematic', ['connectivity hub']),
|
|
185
|
-
this.createItem('menu.fuel-providers', 'gas-pump', 'connectivity.fuel-providers', 'fleet-ops list fuel-
|
|
185
|
+
this.createItem('menu.fuel-providers', 'gas-pump', 'connectivity.fuel-providers', 'fleet-ops list fuel-provider-connection', 'fleet-ops see fuel-provider-connection', [
|
|
186
|
+
'fuel integrations',
|
|
187
|
+
]),
|
|
186
188
|
this.createItem('menu.devices', 'hard-drive', 'connectivity.devices', 'fleet-ops list device', 'fleet-ops see device'),
|
|
187
189
|
this.createItem('menu.sensors', 'temperature-full', 'connectivity.sensors', 'fleet-ops list sensor', 'fleet-ops see sensor'),
|
|
188
190
|
this.createItem('menu.events', 'stream', 'connectivity.events', 'fleet-ops list device-event', 'fleet-ops see device-event'),
|
|
@@ -191,18 +193,14 @@ export default class LayoutFleetOpsSidebarComponent extends Component {
|
|
|
191
193
|
|
|
192
194
|
get analyticsItems() {
|
|
193
195
|
return this.withRegistryItems('analytics', [
|
|
194
|
-
this.createHubItem('Dashboard', 'chart-line', 'analytics.index', '
|
|
195
|
-
this.createItem('menu.reports', 'file-import', 'analytics.reports', 'iam list report', '
|
|
196
|
+
this.createHubItem('Dashboard', 'chart-line', 'analytics.index', 'fleet-ops view analytics', 'fleet-ops see analytics', ['dashboard', 'fleetops dashboard', 'metrics']),
|
|
197
|
+
this.createItem('menu.reports', 'file-import', 'analytics.reports', 'iam list report', 'iam see report'),
|
|
196
198
|
]);
|
|
197
199
|
}
|
|
198
200
|
|
|
199
201
|
get settingsItems() {
|
|
200
202
|
return this.withRegistryItems('settings', [
|
|
201
|
-
this.createHubItem('Settings Hub', 'sliders', 'settings.index',
|
|
202
|
-
'settings hub',
|
|
203
|
-
'configuration dashboard',
|
|
204
|
-
'setup focus',
|
|
205
|
-
]),
|
|
203
|
+
this.createHubItem('Settings Hub', 'sliders', 'settings.index', null, null, ['settings hub', 'configuration dashboard', 'setup focus']),
|
|
206
204
|
this.createItem('menu.navigator-app', 'location-arrow', 'settings.navigator-app', 'fleet-ops view navigator-settings', 'fleet-ops see navigator-settings'),
|
|
207
205
|
this.createItem('menu.map', 'map', 'settings.map', 'fleet-ops view map-settings', 'fleet-ops see map-settings'),
|
|
208
206
|
this.createItem('menu.payments', 'cash-register', 'settings.payments', 'fleet-ops view payments', 'fleet-ops see payments'),
|
|
@@ -210,8 +208,9 @@ export default class LayoutFleetOpsSidebarComponent extends Component {
|
|
|
210
208
|
this.createItem('menu.routing', 'route', 'settings.routing', 'fleet-ops view routing-settings', 'fleet-ops see routing-settings'),
|
|
211
209
|
this.createItem('menu.orchestrator', 'circle-nodes', 'settings.orchestrator', 'fleet-ops view routing-settings', 'fleet-ops see routing-settings'),
|
|
212
210
|
this.createItem('menu.scheduling', 'calendar-days', 'settings.scheduling', 'fleet-ops view scheduling-settings', 'fleet-ops see scheduling-settings'),
|
|
213
|
-
this.createItem('menu.
|
|
214
|
-
this.createItem('menu.
|
|
211
|
+
this.createItem('menu.telematics-settings', 'satellite-dish', 'settings.telematics', 'fleet-ops view telematics-settings', 'fleet-ops see telematics-settings'),
|
|
212
|
+
this.createItem('menu.custom-fields', 'pen-to-square', 'settings.custom-fields', 'fleet-ops list custom-field', 'fleet-ops see custom-field'),
|
|
213
|
+
this.createItem('menu.avatars', 'icons', 'settings.avatars', 'fleet-ops list avatar', 'fleet-ops see avatar'),
|
|
215
214
|
]);
|
|
216
215
|
}
|
|
217
216
|
|
|
@@ -265,18 +264,36 @@ export default class LayoutFleetOpsSidebarComponent extends Component {
|
|
|
265
264
|
}
|
|
266
265
|
|
|
267
266
|
createBranch({ id, label, icon, route, defaultRoute, requiresVisibleChildren = false, children, keywords = [] }) {
|
|
267
|
+
const visibleChildren = children.filter((item) => item.visible !== false);
|
|
268
|
+
|
|
268
269
|
return {
|
|
269
270
|
id,
|
|
270
271
|
label,
|
|
271
272
|
icon,
|
|
272
273
|
route: this.fullRoute(route),
|
|
273
|
-
defaultRoute: this.fullRoute(defaultRoute),
|
|
274
|
+
defaultRoute: this.resolveDefaultRoute(this.fullRoute(defaultRoute), visibleChildren),
|
|
274
275
|
requiresVisibleChildren,
|
|
275
|
-
children:
|
|
276
|
+
children: visibleChildren,
|
|
276
277
|
keywords,
|
|
277
278
|
};
|
|
278
279
|
}
|
|
279
280
|
|
|
281
|
+
/**
|
|
282
|
+
* Keep the branch's default route when the user may open it; otherwise fall back to the
|
|
283
|
+
* first child route they are permitted to open, so clicking the branch does not land on a
|
|
284
|
+
* route guard that bounces them back out.
|
|
285
|
+
*/
|
|
286
|
+
resolveDefaultRoute(defaultRoute, children = []) {
|
|
287
|
+
const permitted = (item) => [item.visiblePermission, item.permission].every((permission) => !permission || this.abilities.can(permission));
|
|
288
|
+
const defaultChild = children.find((item) => item.route === defaultRoute);
|
|
289
|
+
|
|
290
|
+
if (!defaultChild || permitted(defaultChild)) {
|
|
291
|
+
return defaultRoute;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
return children.find((item) => item.route && permitted(item))?.route ?? defaultRoute;
|
|
295
|
+
}
|
|
296
|
+
|
|
280
297
|
createItem(intl, icon, route, permission, ability, keywords = []) {
|
|
281
298
|
return {
|
|
282
299
|
priority: this.defaultPriorityForRoute(route),
|
|
@@ -290,7 +307,7 @@ export default class LayoutFleetOpsSidebarComponent extends Component {
|
|
|
290
307
|
};
|
|
291
308
|
}
|
|
292
309
|
|
|
293
|
-
createHubItem(label, icon, route,
|
|
310
|
+
createHubItem(label, icon, route, permission, ability, keywords = []) {
|
|
294
311
|
return {
|
|
295
312
|
pinnedFirst: true,
|
|
296
313
|
priority: this.defaultPriorityForRoute(route),
|
|
@@ -298,6 +315,8 @@ export default class LayoutFleetOpsSidebarComponent extends Component {
|
|
|
298
315
|
description: label,
|
|
299
316
|
icon,
|
|
300
317
|
route: this.fullRoute(route),
|
|
318
|
+
permission,
|
|
319
|
+
visiblePermission: ability,
|
|
301
320
|
isNavigationHub: true,
|
|
302
321
|
keywords: [label, route, ...keywords].filter(Boolean),
|
|
303
322
|
};
|
|
@@ -387,8 +406,9 @@ export default class LayoutFleetOpsSidebarComponent extends Component {
|
|
|
387
406
|
'settings.routing': 5,
|
|
388
407
|
'settings.orchestrator': 6,
|
|
389
408
|
'settings.scheduling': 7,
|
|
390
|
-
'settings.
|
|
391
|
-
'settings.
|
|
409
|
+
'settings.telematics': 8,
|
|
410
|
+
'settings.custom-fields': 9,
|
|
411
|
+
'settings.avatars': 10,
|
|
392
412
|
};
|
|
393
413
|
|
|
394
414
|
return priorities[route] ?? 0;
|