@fleetbase/fleetops-engine 0.6.37 → 0.6.39
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/addon/components/activity/form.hbs +2 -12
- package/addon/components/activity/logic-builder.hbs +1 -1
- package/addon/components/custom-entity/form.hbs +4 -20
- package/addon/components/device/form.hbs +3 -15
- package/addon/components/device/panel-header.hbs +13 -2
- package/addon/components/driver/details.hbs +33 -2
- package/addon/components/driver/form.hbs +42 -0
- package/addon/components/driver/panel-header.hbs +8 -1
- package/addon/components/driver/schedule.hbs +115 -76
- package/addon/components/driver/schedule.js +349 -157
- package/addon/components/driver-onboard-settings.hbs +2 -8
- package/addon/components/entity-field-editing-settings.hbs +2 -5
- package/addon/components/equipment/card.hbs +49 -0
- package/addon/components/equipment/card.js +6 -0
- package/addon/components/equipment/details.hbs +83 -44
- package/addon/components/equipment/form.hbs +111 -41
- package/addon/components/equipment/form.js +78 -10
- package/addon/components/equipment/panel-header.hbs +36 -0
- package/addon/components/equipment/panel-header.js +2 -0
- package/addon/components/fleet/driver-listing.hbs +3 -1
- package/addon/components/fleet/vehicle-listing.hbs +4 -7
- package/addon/components/fleet-panel/vehicle-listing.hbs +1 -6
- package/addon/components/fuel-report/form.hbs +1 -5
- package/addon/components/layout/fleet-ops-sidebar.hbs +40 -36
- package/addon/components/layout/fleet-ops-sidebar.js +61 -10
- package/addon/components/maintenance/cost-panel.hbs +176 -0
- package/addon/components/maintenance/cost-panel.js +241 -0
- package/addon/components/maintenance/details.hbs +123 -60
- package/addon/components/maintenance/form.hbs +138 -78
- package/addon/components/maintenance/form.js +131 -6
- package/addon/components/maintenance/panel-header.hbs +31 -0
- package/addon/components/maintenance/panel-header.js +2 -0
- package/addon/components/maintenance-schedule/details.hbs +260 -0
- package/addon/components/maintenance-schedule/details.js +158 -0
- package/addon/components/maintenance-schedule/form.hbs +287 -0
- package/addon/components/maintenance-schedule/form.js +199 -0
- package/addon/components/map/container.hbs +1 -1
- package/addon/components/map/drawer/device-event-listing.hbs +1 -1
- package/addon/components/map/drawer/driver-listing.hbs +1 -6
- package/addon/components/map/drawer/place-listing.hbs +1 -6
- package/addon/components/map/drawer/vehicle-listing.hbs +1 -6
- package/addon/components/map/drawer.hbs +8 -1
- package/addon/components/map/leaflet-live-map.hbs +2 -1
- package/addon/components/map/toolbar/visibility-control-panel.hbs +1 -1
- package/addon/components/map/toolbar.hbs +4 -29
- package/addon/components/modals/add-driver-shift.hbs +155 -0
- package/addon/components/modals/add-driver-shift.js +210 -0
- package/addon/components/modals/bulk-assign-orders.hbs +67 -0
- package/addon/components/modals/driver-shift.hbs +43 -0
- package/addon/components/modals/driver-shift.js +56 -0
- package/addon/components/modals/entity-form.hbs +5 -28
- package/addon/components/modals/orchestrator-import.hbs +351 -0
- package/addon/components/modals/orchestrator-import.js +807 -0
- package/addon/components/modals/order-config-new-status.hbs +1 -5
- package/addon/components/modals/scheduling-conflict.hbs +47 -0
- package/addon/components/modals/scheduling-conflict.js +53 -0
- package/addon/components/modals/send-work-order.hbs +91 -0
- package/addon/components/modals/send-work-order.js +3 -0
- package/addon/components/modals/service-area-form.hbs +1 -6
- package/addon/components/modals/set-driver-availability.hbs +50 -0
- package/addon/components/modals/set-driver-availability.js +57 -0
- package/addon/components/modals/update-order-activity.hbs +13 -9
- package/addon/components/modals/user-form.hbs +1 -5
- package/addon/components/modals/vehicle-form.hbs +17 -102
- package/addon/components/modals/vendor-form.hbs +15 -82
- package/addon/components/orchestrator/card-fields-settings.hbs +76 -0
- package/addon/components/orchestrator/card-fields-settings.js +134 -0
- package/addon/components/orchestrator/order-pool.hbs +264 -0
- package/addon/components/orchestrator/order-pool.js +394 -0
- package/addon/components/orchestrator/phase-builder.hbs +162 -0
- package/addon/components/orchestrator/phase-builder.js +162 -0
- package/addon/components/orchestrator/plan-viewer.hbs +278 -0
- package/addon/components/orchestrator/plan-viewer.js +342 -0
- package/addon/components/orchestrator/resource-panel.hbs +301 -0
- package/addon/components/orchestrator/resource-panel.js +106 -0
- package/addon/components/orchestrator-workbench.hbs +318 -0
- package/addon/components/orchestrator-workbench.js +1087 -0
- package/addon/components/order/details/custom-fields.hbs +10 -1
- package/addon/components/order/details/detail.hbs +37 -2
- package/addon/components/order/details/detail.js +0 -1
- package/addon/components/order/details/integrated-vendor-details.hbs +4 -4
- package/addon/components/order/details/notes.hbs +1 -7
- package/addon/components/order/details/route.hbs +1 -5
- package/addon/components/order/form/details.hbs +44 -10
- package/addon/components/order/form/details.js +57 -0
- package/addon/components/order/form/notes.hbs +1 -7
- package/addon/components/order/form/payload.hbs +1 -7
- package/addon/components/order/form/route.hbs +3 -15
- package/addon/components/order/header.hbs +1 -7
- package/addon/components/order/route-editor.hbs +4 -25
- package/addon/components/order/schedule-card.hbs +102 -95
- package/addon/components/order/schedule-card.js +8 -3
- package/addon/components/order-config-manager/details.hbs +2 -10
- package/addon/components/order-config-manager/entities.hbs +1 -7
- package/addon/components/order-config-manager.hbs +1 -6
- package/addon/components/part/card.hbs +49 -0
- package/addon/components/part/card.js +6 -0
- package/addon/components/part/details.hbs +102 -56
- package/addon/components/part/form.hbs +131 -56
- package/addon/components/part/form.js +78 -11
- package/addon/components/part/panel-header.hbs +36 -0
- package/addon/components/part/panel-header.js +2 -0
- package/addon/components/place/form.hbs +1 -7
- package/addon/components/sensor/details.hbs +1 -1
- package/addon/components/sensor/form.hbs +5 -3
- package/addon/components/sensor/panel-header.hbs +8 -1
- package/addon/components/service-area/form.hbs +1 -6
- package/addon/components/service-rate/form.hbs +12 -60
- package/addon/components/telematic/form.hbs +6 -2
- package/addon/components/vehicle/details/maintenance-history.hbs +42 -0
- package/addon/components/vehicle/details/maintenance-history.js +32 -0
- package/addon/components/vehicle/details/schedules.hbs +40 -0
- package/addon/components/vehicle/details/schedules.js +32 -0
- package/addon/components/vehicle/details/work-orders.hbs +42 -0
- package/addon/components/vehicle/details/work-orders.js +32 -0
- package/addon/components/vehicle/details.hbs +30 -0
- package/addon/components/vehicle/form.hbs +39 -0
- package/addon/components/vehicle/panel-header.hbs +19 -49
- package/addon/components/warranty/details.hbs +3 -2
- package/addon/components/warranty/form.hbs +3 -17
- package/addon/components/work-order/details.hbs +135 -40
- package/addon/components/work-order/form.hbs +178 -45
- package/addon/components/work-order/form.js +197 -4
- package/addon/components/work-order/panel-header.hbs +31 -0
- package/addon/components/work-order/panel-header.js +2 -0
- package/addon/controllers/connectivity/devices/index/details.js +1 -1
- package/addon/controllers/maintenance/equipment/index/details/index.js +0 -1
- package/addon/controllers/maintenance/equipment/index/details.js +36 -1
- package/addon/controllers/maintenance/equipment/index/edit.js +56 -1
- package/addon/controllers/maintenance/equipment/index/new.js +32 -1
- package/addon/controllers/maintenance/equipment/index.js +127 -113
- package/addon/controllers/maintenance/maintenances/index/details/index.js +3 -0
- package/addon/controllers/maintenance/maintenances/index/details.js +54 -0
- package/addon/controllers/maintenance/maintenances/index/edit.js +68 -0
- package/addon/controllers/maintenance/maintenances/index/new.js +34 -0
- package/addon/controllers/maintenance/maintenances/index.js +191 -0
- package/addon/controllers/maintenance/parts/index/details/index.js +0 -1
- package/addon/controllers/maintenance/parts/index/details.js +36 -1
- package/addon/controllers/maintenance/parts/index/edit.js +56 -1
- package/addon/controllers/maintenance/parts/index/new.js +32 -1
- package/addon/controllers/maintenance/parts/index.js +135 -113
- package/addon/controllers/maintenance/schedules/index/details.js +115 -0
- package/addon/controllers/maintenance/schedules/index/edit.js +41 -0
- package/addon/controllers/maintenance/schedules/index/new.js +33 -0
- package/addon/controllers/maintenance/schedules/index.js +280 -0
- package/addon/controllers/maintenance/work-orders/index/details.js +41 -1
- package/addon/controllers/maintenance/work-orders/index/edit.js +67 -1
- package/addon/controllers/maintenance/work-orders/index/new.js +43 -1
- package/addon/controllers/maintenance/work-orders/index.js +105 -113
- package/addon/controllers/management/drivers/index/details.js +6 -1
- package/addon/controllers/management/vehicles/index/details.js +65 -0
- package/addon/controllers/management/vehicles/index.js +18 -0
- package/addon/controllers/operations/orchestrator.js +10 -0
- package/addon/controllers/operations/orders/index/details.js +5 -0
- package/addon/controllers/operations/orders/index.js +6 -0
- package/addon/controllers/operations/scheduler/fleet-schedule.js +341 -0
- package/addon/controllers/operations/scheduler/index.js +799 -275
- package/addon/controllers/operations/scheduler.js +21 -0
- package/addon/controllers/settings/orchestrator.js +70 -0
- package/addon/controllers/settings/scheduling.js +155 -0
- package/addon/extension.js +74 -1
- package/addon/instance-initializers/register-vroom-allocation.js +27 -0
- package/addon/models/maintenance-schedule.js +61 -0
- package/addon/routes/maintenance/equipment/index/details.js +27 -1
- package/addon/routes/maintenance/equipment/index/edit.js +27 -1
- package/addon/routes/maintenance/maintenances/index/details/index.js +3 -0
- package/addon/routes/maintenance/maintenances/index/details.js +29 -0
- package/addon/routes/maintenance/maintenances/index/edit.js +29 -0
- package/addon/routes/maintenance/maintenances/index/new.js +3 -0
- package/addon/routes/maintenance/maintenances/index.js +23 -0
- package/addon/routes/maintenance/maintenances.js +3 -0
- package/addon/routes/maintenance/parts/index/details.js +27 -1
- package/addon/routes/maintenance/parts/index/edit.js +27 -1
- package/addon/routes/maintenance/schedules/index/details/index.js +2 -0
- package/addon/routes/maintenance/schedules/index/details/work-orders.js +11 -0
- package/addon/routes/maintenance/schedules/index/details.js +25 -0
- package/addon/routes/maintenance/schedules/index/edit.js +25 -0
- package/addon/routes/maintenance/schedules/index/new.js +2 -0
- package/addon/routes/maintenance/schedules/index.js +21 -0
- package/addon/routes/maintenance/schedules.js +2 -0
- package/addon/routes/maintenance/work-orders/index/details.js +27 -1
- package/addon/routes/maintenance/work-orders/index/edit.js +27 -1
- package/addon/routes/management/vehicles/index/details/maintenance-history.js +3 -0
- package/addon/routes/management/vehicles/index/details/schedules.js +3 -0
- package/addon/routes/management/vehicles/index/details/work-orders.js +3 -0
- package/addon/routes/operations/orchestrator.js +23 -0
- package/addon/routes/operations/orders/index/details/virtual.js +23 -0
- package/addon/routes/operations/scheduler/fleet-schedule.js +28 -0
- package/addon/routes/operations/scheduler/index.js +48 -26
- package/addon/routes/operations/scheduler.js +14 -1
- package/addon/routes/settings/orchestrator.js +27 -0
- package/addon/routes/settings/scheduling.js +3 -0
- package/addon/routes.js +33 -1
- package/addon/services/driver-actions.js +40 -7
- package/addon/services/driver-scheduling.js +4 -1
- package/addon/services/equipment-actions.js +15 -5
- package/addon/services/leaflet-map-manager.js +14 -6
- package/addon/services/maintenance-actions.js +17 -14
- package/addon/services/maintenance-schedule-actions.js +118 -0
- package/addon/services/orchestration-engine-interface.js +49 -0
- package/addon/services/orchestration-engine.js +74 -0
- package/addon/services/order-actions.js +15 -0
- package/addon/services/order-allocation.js +116 -0
- package/addon/services/part-actions.js +12 -2
- package/addon/services/scheduling.js +316 -0
- package/addon/services/vehicle-actions.js +70 -7
- package/addon/services/vroom-allocation-engine.js +45 -0
- package/addon/services/work-order-actions.js +80 -0
- package/addon/styles/fleetops-engine.css +1658 -0
- package/addon/templates/analytics/reports/index/edit.hbs +1 -1
- package/addon/templates/analytics/reports/index/new.hbs +1 -1
- package/addon/templates/application.hbs +6 -1
- package/addon/templates/connectivity/devices/index/details/events.hbs +0 -1
- package/addon/templates/connectivity/devices.hbs +0 -1
- package/addon/templates/connectivity/events/index/details.hbs +0 -1
- package/addon/templates/connectivity/events.hbs +0 -1
- package/addon/templates/connectivity/sensors.hbs +0 -1
- package/addon/templates/connectivity/telematics/index/details/devices.hbs +0 -1
- package/addon/templates/connectivity/telematics/index/details/events.hbs +0 -1
- package/addon/templates/connectivity/telematics/index/details/sensors.hbs +0 -1
- package/addon/templates/connectivity/telematics.hbs +0 -1
- package/addon/templates/connectivity/tracking.hbs +0 -1
- package/addon/templates/connectivity.hbs +0 -1
- package/addon/templates/maintenance/equipment/index/details/index.hbs +1 -2
- package/addon/templates/maintenance/equipment/index/details.hbs +15 -2
- package/addon/templates/maintenance/equipment/index/edit.hbs +12 -2
- package/addon/templates/maintenance/equipment/index/new.hbs +1 -2
- package/addon/templates/maintenance/equipment/index.hbs +48 -13
- package/addon/templates/maintenance/equipment.hbs +0 -1
- package/addon/templates/maintenance/maintenances/index/details/index.hbs +1 -0
- package/addon/templates/maintenance/maintenances/index/details.hbs +15 -0
- package/addon/templates/maintenance/maintenances/index/edit.hbs +12 -0
- package/addon/templates/maintenance/maintenances/index/new.hbs +11 -0
- package/addon/templates/maintenance/maintenances/index.hbs +14 -0
- package/addon/templates/maintenance/maintenances.hbs +1 -0
- package/addon/templates/maintenance/parts/index/details/index.hbs +1 -2
- package/addon/templates/maintenance/parts/index/details.hbs +15 -2
- package/addon/templates/maintenance/parts/index/edit.hbs +12 -2
- package/addon/templates/maintenance/parts/index/new.hbs +1 -2
- package/addon/templates/maintenance/parts/index.hbs +48 -13
- package/addon/templates/maintenance/parts.hbs +0 -1
- package/addon/templates/maintenance/schedules/index/details/index.hbs +1 -0
- package/addon/templates/maintenance/schedules/index/details/work-orders.hbs +39 -0
- package/addon/templates/maintenance/schedules/index/details.hbs +14 -0
- package/addon/templates/maintenance/schedules/index/edit.hbs +12 -0
- package/addon/templates/maintenance/schedules/index/new.hbs +11 -0
- package/addon/templates/maintenance/schedules/index.hbs +40 -0
- package/addon/templates/maintenance/schedules.hbs +1 -0
- package/addon/templates/maintenance/work-orders/index/details.hbs +2 -1
- package/addon/templates/maintenance/work-orders/index/edit.hbs +2 -4
- package/addon/templates/maintenance/work-orders/index/new.hbs +1 -2
- package/addon/templates/maintenance/work-orders.hbs +0 -1
- package/addon/templates/management/contacts/customers/edit.hbs +1 -2
- package/addon/templates/management/contacts/customers/new.hbs +1 -2
- package/addon/templates/management/contacts/customers.hbs +1 -1
- package/addon/templates/management/contacts/index/edit.hbs +1 -2
- package/addon/templates/management/contacts/index/new.hbs +1 -2
- package/addon/templates/management/drivers/index/details/orders.hbs +0 -1
- package/addon/templates/management/drivers/index/edit.hbs +1 -2
- package/addon/templates/management/drivers/index/new.hbs +1 -2
- package/addon/templates/management/fleets/index/edit.hbs +1 -2
- package/addon/templates/management/fleets/index/new.hbs +1 -2
- package/addon/templates/management/fleets/index.hbs +1 -2
- package/addon/templates/management/fuel-reports/index/edit.hbs +1 -2
- package/addon/templates/management/fuel-reports/index/new.hbs +1 -2
- package/addon/templates/management/fuel-reports/index.hbs +1 -2
- package/addon/templates/management/issues/index/edit.hbs +1 -2
- package/addon/templates/management/issues/index/new.hbs +1 -2
- package/addon/templates/management/issues/index.hbs +1 -2
- package/addon/templates/management/places/index/details/activity.hbs +0 -1
- package/addon/templates/management/places/index/details/comments.hbs +0 -1
- package/addon/templates/management/places/index/details/documents.hbs +0 -1
- package/addon/templates/management/places/index/details/map.hbs +0 -1
- package/addon/templates/management/places/index/details/operations.hbs +0 -1
- package/addon/templates/management/places/index/details/performance.hbs +0 -1
- package/addon/templates/management/places/index/details/rules.hbs +0 -1
- package/addon/templates/management/vehicles/index/details/equipment.hbs +0 -1
- package/addon/templates/management/vehicles/index/details/maintenance-history.hbs +2 -0
- package/addon/templates/management/vehicles/index/details/schedules.hbs +2 -0
- package/addon/templates/management/vehicles/index/details/work-orders.hbs +2 -0
- package/addon/templates/management/vehicles/index/details.hbs +1 -1
- package/addon/templates/management/vehicles/index/edit.hbs +1 -2
- package/addon/templates/management/vehicles/index/new.hbs +1 -2
- package/addon/templates/management/vendors/index/edit.hbs +1 -2
- package/addon/templates/management/vendors/index/new.hbs +1 -2
- package/addon/templates/management/vendors/index.hbs +1 -2
- package/addon/templates/management/vendors/integrated.hbs +1 -2
- package/addon/templates/operations/orchestrator.hbs +1 -0
- package/addon/templates/operations/orders/index/details/virtual.hbs +1 -0
- package/addon/templates/operations/orders/index.hbs +6 -1
- package/addon/templates/operations/scheduler/fleet-schedule.hbs +41 -0
- package/addon/templates/operations/scheduler/index.hbs +147 -88
- package/addon/templates/operations/scheduler.hbs +7 -1
- package/addon/templates/settings/avatars.hbs +1 -1
- package/addon/templates/settings/orchestrator.hbs +65 -0
- package/addon/templates/settings/payments/index.hbs +1 -5
- package/addon/templates/settings/scheduling.hbs +82 -0
- package/addon/utils/create-full-calendar-event-from-order.js +52 -14
- package/addon/utils/create-full-calendar-event-from-schedule-item.js +50 -0
- package/addon/utils/fleet-ops-options.js +254 -0
- package/addon/utils/route-colors.js +99 -0
- package/addon/utils/to-calendar-date.js +70 -0
- package/app/components/driver/schedule.js +1 -0
- package/app/components/maintenance/cost-panel.js +1 -0
- package/app/components/maintenance/panel-header.js +1 -0
- package/app/components/maintenance-schedule/details.js +1 -0
- package/app/components/maintenance-schedule/form.js +1 -0
- package/app/components/modals/add-driver-shift.js +1 -0
- package/app/components/modals/bulk-assign-orders.js +1 -0
- package/app/components/modals/driver-shift.js +1 -0
- package/app/components/modals/orchestrator-import.js +1 -0
- package/app/components/modals/scheduling-conflict.js +1 -0
- package/app/components/modals/send-work-order.js +1 -0
- package/app/components/modals/set-driver-availability.js +1 -0
- package/app/components/orchestrator/card-fields-settings.js +1 -0
- package/app/components/orchestrator/order-pool.js +1 -0
- package/app/components/orchestrator/phase-builder.js +1 -0
- package/app/components/orchestrator/plan-viewer.js +1 -0
- package/app/components/orchestrator/resource-panel.js +1 -0
- package/app/components/orchestrator-workbench.js +1 -0
- package/app/components/vehicle/details/maintenance-history.js +1 -0
- package/app/components/vehicle/details/schedules.js +1 -0
- package/app/components/vehicle/details/work-orders.js +1 -0
- package/app/controllers/operations/orchestrator.js +1 -0
- package/app/controllers/settings/orchestrator.js +1 -0
- package/app/controllers/settings/scheduling.js +1 -0
- package/app/routes/operations/orchestrator.js +1 -0
- package/app/routes/operations/orders/index/details/virtual.js +1 -0
- package/app/routes/settings/orchestrator.js +1 -0
- package/app/routes/settings/scheduling.js +1 -0
- package/app/services/maintenance-schedule-actions.js +1 -0
- package/app/services/orchestration-engine-interface.js +1 -0
- package/app/services/orchestration-engine.js +1 -0
- package/app/services/order-allocation.js +1 -0
- package/app/services/scheduling.js +1 -0
- package/app/services/vroom-allocation-engine.js +1 -0
- package/app/templates/operations/orders/index/details/virtual.js +1 -0
- package/app/templates/settings/scheduling.js +1 -0
- package/app/utils/create-full-calendar-event-from-schedule-item.js +1 -0
- package/app/utils/route-colors.js +1 -0
- package/composer.json +5 -3
- package/extension.json +1 -1
- package/package.json +6 -5
- package/server/config/fleetops.php +20 -1
- package/server/migrations/2025_08_28_054927_create_parts_table.php +2 -2
- package/server/migrations/2025_08_28_054932_add_public_id_to_maintenance_tables.php +45 -0
- package/server/migrations/2025_09_01_000001_create_maintenance_schedules_table.php +88 -0
- package/server/migrations/2026_04_01_000001_fix_monetary_columns_in_parts_table.php +48 -0
- package/server/migrations/2026_04_01_000003_add_photo_uuid_to_equipment_and_parts_tables.php +61 -0
- package/server/migrations/2026_04_01_000004_add_public_id_to_equipments_table.php +38 -0
- package/server/migrations/2026_04_01_000005_add_missing_columns_to_parts_table.php +67 -0
- package/server/migrations/2026_04_04_000001_add_reminder_offsets_to_maintenance_schedules.php +44 -0
- package/server/migrations/2026_04_08_000001_add_orchestrator_columns_to_vehicles_table.php +58 -0
- package/server/migrations/2026_04_08_000002_add_orchestrator_columns_to_drivers_table.php +41 -0
- package/server/migrations/2026_04_08_000003_add_orchestrator_columns_to_orders_table.php +38 -0
- package/server/migrations/2026_04_08_000004_add_orchestrator_columns_to_payloads_table.php +41 -0
- package/server/migrations/2026_04_08_000005_add_orchestrator_columns_to_waypoints_table.php +38 -0
- package/server/migrations/2026_04_09_000001_create_manifests_table.php +48 -0
- package/server/migrations/2026_04_09_000002_create_manifest_stops_table.php +48 -0
- package/server/migrations/2026_04_09_000003_add_manifest_uuid_to_orders_table.php +28 -0
- package/server/migrations/2026_04_13_000001_add_pod_notes_columns_to_waypoints_table.php +39 -0
- package/server/resources/views/mail/maintenance-schedule-reminder.blade.php +59 -0
- package/server/resources/views/mail/work-order-dispatched.blade.php +67 -0
- package/server/src/Auth/Schemas/FleetOps.php +44 -0
- package/server/src/Console/Commands/ProcessMaintenanceTriggers.php +150 -0
- package/server/src/Console/Commands/SendMaintenanceReminders.php +128 -0
- package/server/src/Http/Controllers/Internal/v1/DriverController.php +1 -0
- package/server/src/Http/Controllers/Internal/v1/EquipmentController.php +27 -0
- package/server/src/Http/Controllers/Internal/v1/LiveController.php +9 -2
- package/server/src/Http/Controllers/Internal/v1/MaintenanceController.php +165 -0
- package/server/src/Http/Controllers/Internal/v1/MaintenanceScheduleController.php +304 -0
- package/server/src/Http/Controllers/Internal/v1/ManifestController.php +138 -0
- package/server/src/Http/Controllers/Internal/v1/OrchestrationController.php +975 -0
- package/server/src/Http/Controllers/Internal/v1/OrderController.php +42 -0
- package/server/src/Http/Controllers/Internal/v1/PartController.php +27 -0
- package/server/src/Http/Controllers/Internal/v1/SettingController.php +118 -0
- package/server/src/Http/Controllers/Internal/v1/Traits/DriverSchedulingTrait.php +214 -0
- package/server/src/Http/Controllers/Internal/v1/WorkOrderController.php +68 -0
- package/server/src/Http/Resources/v1/Driver.php +1 -0
- package/server/src/Http/Resources/v1/Maintenance.php +138 -0
- package/server/src/Http/Resources/v1/MaintenanceSchedule.php +137 -0
- package/server/src/Http/Resources/v1/Orchestrator/Order.php +116 -0
- package/server/src/Http/Resources/v1/Order.php +7 -4
- package/server/src/Http/Resources/v1/Waypoint.php +7 -0
- package/server/src/Http/Resources/v1/WorkOrder.php +136 -0
- package/server/src/Imports/EquipmentImport.php +32 -0
- package/server/src/Imports/MaintenanceImport.php +32 -0
- package/server/src/Imports/MaintenanceScheduleImport.php +32 -0
- package/server/src/Imports/PartImport.php +32 -0
- package/server/src/Imports/WorkOrderImport.php +32 -0
- package/server/src/Jobs/ProcessAllocationJob.php +119 -0
- package/server/src/Listeners/HandleDeliveryCompletion.php +47 -0
- package/server/src/Listeners/NotifyDriverOnShiftChange.php +63 -0
- package/server/src/Mail/MaintenanceScheduleReminder.php +68 -0
- package/server/src/Mail/WorkOrderDispatched.php +58 -0
- package/server/src/Models/Asset.php +2 -2
- package/server/src/Models/Device.php +1 -1
- package/server/src/Models/Driver.php +82 -4
- package/server/src/Models/Equipment.php +62 -2
- package/server/src/Models/Maintenance.php +127 -9
- package/server/src/Models/MaintenanceSchedule.php +353 -0
- package/server/src/Models/Manifest.php +214 -0
- package/server/src/Models/ManifestStop.php +162 -0
- package/server/src/Models/Order.php +70 -0
- package/server/src/Models/OrderConfig.php +5 -2
- package/server/src/Models/Part.php +69 -3
- package/server/src/Models/Payload.php +7 -2
- package/server/src/Models/Place.php +1 -1
- package/server/src/Models/Sensor.php +1 -1
- package/server/src/Models/ServiceQuote.php +1 -1
- package/server/src/Models/Vehicle.php +20 -1
- package/server/src/Models/Warranty.php +1 -1
- package/server/src/Models/Waypoint.php +7 -1
- package/server/src/Models/WorkOrder.php +122 -12
- package/server/src/Notifications/DriverShiftChanged.php +110 -0
- package/server/src/Observers/WorkOrderObserver.php +107 -0
- package/server/src/Orchestration/Contracts/OrchestrationEngineInterface.php +63 -0
- package/server/src/Orchestration/Engines/DriverAssignmentEngine.php +265 -0
- package/server/src/Orchestration/Engines/GreedyOrchestrationEngine.php +155 -0
- package/server/src/Orchestration/Engines/RouteSequencingEngine.php +272 -0
- package/server/src/Orchestration/Engines/VroomOrchestrationEngine.php +192 -0
- package/server/src/Orchestration/OrchestrationEngineRegistry.php +83 -0
- package/server/src/Orchestration/Support/OrchestrationPayloadBuilder.php +290 -0
- package/server/src/Providers/EventServiceProvider.php +7 -1
- package/server/src/Providers/FleetOpsServiceProvider.php +42 -15
- package/server/src/routes.php +65 -4
- package/translations/ar-ae.yml +44 -12
- package/translations/bg-bg.yaml +51 -10
- package/translations/en-us.yaml +444 -1
- package/translations/fr-fr.yaml +51 -10
- package/translations/mn-mn.yaml +51 -10
- package/translations/pt-br.yaml +51 -10
- package/translations/ru-ru.yaml +51 -10
- package/translations/vi-vn.yaml +48 -12
|
@@ -58,11 +58,7 @@
|
|
|
58
58
|
<InputGroup
|
|
59
59
|
@name={{smart-humanize param.key}}
|
|
60
60
|
@value={{mut (get @options.integratedVendor.credentials param.key)}}
|
|
61
|
-
@helpText={{concat
|
|
62
|
-
(t "modals.vendor-form.optionally")
|
|
63
|
-
(smart-humanize param.key)
|
|
64
|
-
(t "modals.vendor-form.configure-vendor")
|
|
65
|
-
}}
|
|
61
|
+
@helpText={{concat (t "modals.vendor-form.optionally") (smart-humanize param.key) (t "modals.vendor-form.configure-vendor")}}
|
|
66
62
|
/>
|
|
67
63
|
{{/each}}
|
|
68
64
|
</div>
|
|
@@ -85,11 +81,7 @@
|
|
|
85
81
|
<InputGroup
|
|
86
82
|
@name={{smart-humanize param.key}}
|
|
87
83
|
@value={{mut (get @options.integratedVendor.options param.key)}}
|
|
88
|
-
@helpText={{concat
|
|
89
|
-
(t "modals.vendor-form.optionally")
|
|
90
|
-
(smart-humanize param.key)
|
|
91
|
-
(t "modals.vendor-form.configure-vendor")
|
|
92
|
-
}}
|
|
84
|
+
@helpText={{concat (t "modals.vendor-form.optionally") (smart-humanize param.key) (t "modals.vendor-form.configure-vendor")}}
|
|
93
85
|
/>
|
|
94
86
|
{{/if}}
|
|
95
87
|
{{/each}}
|
|
@@ -112,21 +104,9 @@
|
|
|
112
104
|
{{/if}}
|
|
113
105
|
</button>
|
|
114
106
|
{{#if @options.showAdvancedOptions}}
|
|
115
|
-
<InputGroup
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
@helpText={{t "modals.vendor-form.host-text"}}
|
|
119
|
-
/>
|
|
120
|
-
<InputGroup
|
|
121
|
-
@name={{t "modals.vendor-form.custom-namespace"}}
|
|
122
|
-
@value={{@options.integratedVendor.namespace}}
|
|
123
|
-
@helpText={{t "modals.vendor-form.namespace-text"}}
|
|
124
|
-
/>
|
|
125
|
-
<InputGroup
|
|
126
|
-
@name={{t "modals.vendor-form.webhook"}}
|
|
127
|
-
@value={{@options.integratedVendor.webhook_url}}
|
|
128
|
-
@helpText={{t "modals.vendor-form.webhook-text"}}
|
|
129
|
-
/>
|
|
107
|
+
<InputGroup @name={{t "modals.vendor-form.custom-host"}} @value={{@options.integratedVendor.host}} @helpText={{t "modals.vendor-form.host-text"}} />
|
|
108
|
+
<InputGroup @name={{t "modals.vendor-form.custom-namespace"}} @value={{@options.integratedVendor.namespace}} @helpText={{t "modals.vendor-form.namespace-text"}} />
|
|
109
|
+
<InputGroup @name={{t "modals.vendor-form.webhook"}} @value={{@options.integratedVendor.webhook_url}} @helpText={{t "modals.vendor-form.webhook-text"}} />
|
|
130
110
|
{{/if}}
|
|
131
111
|
</div>
|
|
132
112
|
{{/if}}
|
|
@@ -147,21 +127,11 @@
|
|
|
147
127
|
<InputGroup
|
|
148
128
|
@name={{smart-humanize param.key}}
|
|
149
129
|
@value={{mut (get @options.vendor.credentials param.key)}}
|
|
150
|
-
@helpText={{concat
|
|
151
|
-
(t "modals.vendor-form.optionally")
|
|
152
|
-
(smart-humanize param.key)
|
|
153
|
-
(t "modals.vendor-form.configure-vendor")
|
|
154
|
-
}}
|
|
130
|
+
@helpText={{concat (t "modals.vendor-form.optionally") (smart-humanize param.key) (t "modals.vendor-form.configure-vendor")}}
|
|
155
131
|
/>
|
|
156
132
|
{{/each}}
|
|
157
133
|
<div class="my-4">
|
|
158
|
-
<Button
|
|
159
|
-
@text={{t "modals.vendor-form.cancel-credentials"}}
|
|
160
|
-
@type="danger"
|
|
161
|
-
@size="sm"
|
|
162
|
-
@icon="times"
|
|
163
|
-
@onClick={{@options.toggleCredentialsReset}}
|
|
164
|
-
/>
|
|
134
|
+
<Button @text={{t "modals.vendor-form.cancel-credentials"}} @type="danger" @size="sm" @icon="times" @onClick={{@options.toggleCredentialsReset}} />
|
|
165
135
|
</div>
|
|
166
136
|
{{else}}
|
|
167
137
|
<div>
|
|
@@ -175,11 +145,7 @@
|
|
|
175
145
|
@name={{smart-humanize param.key}}
|
|
176
146
|
@value="*********"
|
|
177
147
|
@disabled="true"
|
|
178
|
-
@helpText={{concat
|
|
179
|
-
(t "modals.vendor-form.optionally")
|
|
180
|
-
(smart-humanize param.key)
|
|
181
|
-
(t "modals.vendor-form.configure-vendor")
|
|
182
|
-
}}
|
|
148
|
+
@helpText={{concat (t "modals.vendor-form.optionally") (smart-humanize param.key) (t "modals.vendor-form.configure-vendor")}}
|
|
183
149
|
/>
|
|
184
150
|
{{/each}}
|
|
185
151
|
{{/if}}
|
|
@@ -203,11 +169,7 @@
|
|
|
203
169
|
<InputGroup
|
|
204
170
|
@name={{smart-humanize param.key}}
|
|
205
171
|
@value={{mut (get @options.vendor.options param.key)}}
|
|
206
|
-
@helpText={{concat
|
|
207
|
-
(t "modals.vendor-form.optionally")
|
|
208
|
-
(smart-humanize param.key)
|
|
209
|
-
(t "modals.vendor-form.configure-vendor")
|
|
210
|
-
}}
|
|
172
|
+
@helpText={{concat (t "modals.vendor-form.optionally") (smart-humanize param.key) (t "modals.vendor-form.configure-vendor")}}
|
|
211
173
|
/>
|
|
212
174
|
{{/if}}
|
|
213
175
|
{{/each}}
|
|
@@ -224,46 +186,17 @@
|
|
|
224
186
|
{{/if}}
|
|
225
187
|
</button>
|
|
226
188
|
{{#if @options.showAdvancedOptions}}
|
|
227
|
-
<InputGroup
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
@helpText={{t "modals.vendor-form.host-text"}}
|
|
231
|
-
/>
|
|
232
|
-
<InputGroup
|
|
233
|
-
@name={{t "modals.vendor-form.custom-namespace"}}
|
|
234
|
-
@value={{@options.vendor.namespace}}
|
|
235
|
-
@helpText={{t "modals.vendor-form.namespace-text"}}
|
|
236
|
-
/>
|
|
237
|
-
<InputGroup
|
|
238
|
-
@name={{t "modals.vendor-form.webhook"}}
|
|
239
|
-
@value={{@options.vendor.webhook_url}}
|
|
240
|
-
@helpText={{t "modals.vendor-form.webhook-text"}}
|
|
241
|
-
/>
|
|
189
|
+
<InputGroup @name={{t "modals.vendor-form.custom-host"}} @value={{@options.vendor.host}} @helpText={{t "modals.vendor-form.host-text"}} />
|
|
190
|
+
<InputGroup @name={{t "modals.vendor-form.custom-namespace"}} @value={{@options.vendor.namespace}} @helpText={{t "modals.vendor-form.namespace-text"}} />
|
|
191
|
+
<InputGroup @name={{t "modals.vendor-form.webhook"}} @value={{@options.vendor.webhook_url}} @helpText={{t "modals.vendor-form.webhook-text"}} />
|
|
242
192
|
{{/if}}
|
|
243
193
|
</div>
|
|
244
194
|
{{else}}
|
|
245
195
|
<div class="grid lg:grid-cols-2 grid-cols-1 gap-2 text-xs dark:text-gray-100">
|
|
246
196
|
<InputGroup @name={{t "common.name"}} @value={{@options.vendor.name}} @wrapperClass="mb-0" @helpText={{t "modals.vendor-form.name-text"}} />
|
|
247
|
-
<InputGroup
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
@value={{@options.vendor.email}}
|
|
251
|
-
@wrapperClass="mb-0"
|
|
252
|
-
@helpText={{t "modals.vendor-form.email-text"}}
|
|
253
|
-
/>
|
|
254
|
-
<InputGroup
|
|
255
|
-
@name={{t "common.phone"}}
|
|
256
|
-
@type="tel"
|
|
257
|
-
@value={{@options.vendor.phone}}
|
|
258
|
-
@wrapperClass="mb-0"
|
|
259
|
-
@helpText={{t "modals.vendor-form.phone-text"}}
|
|
260
|
-
/>
|
|
261
|
-
<InputGroup
|
|
262
|
-
@name={{t "common.website"}}
|
|
263
|
-
@value={{@options.vendor.website}}
|
|
264
|
-
@wrapperClass="mb-0"
|
|
265
|
-
@helpText={{t "modals.vendor-form.website-text"}}
|
|
266
|
-
/>
|
|
197
|
+
<InputGroup @name={{t "common.email"}} @type="email" @value={{@options.vendor.email}} @wrapperClass="mb-0" @helpText={{t "modals.vendor-form.email-text"}} />
|
|
198
|
+
<InputGroup @name={{t "common.phone"}} @type="tel" @value={{@options.vendor.phone}} @wrapperClass="mb-0" @helpText={{t "modals.vendor-form.phone-text"}} />
|
|
199
|
+
<InputGroup @name={{t "common.website"}} @value={{@options.vendor.website}} @wrapperClass="mb-0" @helpText={{t "modals.vendor-form.website-text"}} />
|
|
267
200
|
<InputGroup @wrapperClass="mb-0 col-span-2">
|
|
268
201
|
<div class="flex items-start justify-between">
|
|
269
202
|
<label>
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
{{! Orchestrator::CardFieldsSettings — Configure which fields show on order cards }}
|
|
2
|
+
<div class="card-fields-settings" ...attributes>
|
|
3
|
+
{{#if this.loadData.isRunning}}
|
|
4
|
+
<div class="flex justify-center py-8"><Spinner /></div>
|
|
5
|
+
{{else}}
|
|
6
|
+
<div class="card-fields-settings-container {{@wrapperClass}}">
|
|
7
|
+
{{! Standard fields }}
|
|
8
|
+
<ContentPanel @title={{t "orchestrator.standard-fields"}} @open={{true}} @wrapperClass="bordered-top">
|
|
9
|
+
<p class="text-xs text-gray-500 dark:text-gray-400 mb-3">{{t "orchestrator.standard-fields-description"}}</p>
|
|
10
|
+
<div class="grid grid-cols-2 gap-2">
|
|
11
|
+
{{#each this.standardFieldOptions as |field|}}
|
|
12
|
+
<label class="flex items-center gap-2 cursor-pointer">
|
|
13
|
+
<input
|
|
14
|
+
type="checkbox"
|
|
15
|
+
class="form-checkbox h-3.5 w-3.5 rounded text-indigo-600"
|
|
16
|
+
checked={{this.isStandardSelected field.key}}
|
|
17
|
+
{{on "change" (fn this.toggleStandardField field.key)}}
|
|
18
|
+
/>
|
|
19
|
+
<span class="text-xs text-gray-700 dark:text-gray-300">{{field.label}}</span>
|
|
20
|
+
</label>
|
|
21
|
+
{{/each}}
|
|
22
|
+
</div>
|
|
23
|
+
</ContentPanel>
|
|
24
|
+
|
|
25
|
+
{{! Per-order-config custom fields.
|
|
26
|
+
Backend returns { id, uuid, name, key, fields: [{key, label, type, required}] }
|
|
27
|
+
We use config.uuid as the settings key so it matches
|
|
28
|
+
order.order_config_uuid on the card renderer. }}
|
|
29
|
+
{{! Backend already excludes configs with no custom fields }}
|
|
30
|
+
{{#each this.orderConfigs as |config|}}
|
|
31
|
+
<ContentPanel @title={{config.name}} @open={{true}} @wrapperClass="bordered-top">
|
|
32
|
+
<p class="text-xs text-gray-500 dark:text-gray-400 mb-3">
|
|
33
|
+
{{t "orchestrator.config-fields-description" name=config.name}}
|
|
34
|
+
</p>
|
|
35
|
+
<div class="grid grid-cols-2 gap-2">
|
|
36
|
+
{{#each config.fields as |field|}}
|
|
37
|
+
<label class="flex items-center gap-2 cursor-pointer">
|
|
38
|
+
<input
|
|
39
|
+
type="checkbox"
|
|
40
|
+
class="form-checkbox h-3.5 w-3.5 rounded text-indigo-600"
|
|
41
|
+
checked={{this.isConfigFieldSelected config.uuid field.key}}
|
|
42
|
+
{{on "change" (fn this.toggleConfigField config.uuid field.key)}}
|
|
43
|
+
/>
|
|
44
|
+
<span class="text-xs text-gray-700 dark:text-gray-300" title={{field.key}}>{{field.label}}</span>
|
|
45
|
+
</label>
|
|
46
|
+
{{/each}}
|
|
47
|
+
</div>
|
|
48
|
+
</ContentPanel>
|
|
49
|
+
{{/each}}
|
|
50
|
+
|
|
51
|
+
{{! Meta fields — only shown when the company has orders with meta keys }}
|
|
52
|
+
{{#if this.availableMetaKeys.length}}
|
|
53
|
+
<ContentPanel @title={{t "orchestrator.meta-fields"}} @open={{true}} @wrapperClass="bordered-top">
|
|
54
|
+
<p class="text-xs text-gray-500 dark:text-gray-400 mb-3">{{t "orchestrator.meta-fields-description"}}</p>
|
|
55
|
+
<div class="grid grid-cols-2 gap-2">
|
|
56
|
+
{{#each this.availableMetaKeys as |key|}}
|
|
57
|
+
<label class="flex items-center gap-2 cursor-pointer">
|
|
58
|
+
<input
|
|
59
|
+
type="checkbox"
|
|
60
|
+
class="form-checkbox h-3.5 w-3.5 rounded text-indigo-600"
|
|
61
|
+
checked={{this.isMetaKeySelected key}}
|
|
62
|
+
{{on "change" (fn this.toggleMetaKey key)}}
|
|
63
|
+
/>
|
|
64
|
+
<span class="text-xs font-mono text-gray-600 dark:text-gray-400 truncate">{{key}}</span>
|
|
65
|
+
</label>
|
|
66
|
+
{{/each}}
|
|
67
|
+
</div>
|
|
68
|
+
</ContentPanel>
|
|
69
|
+
{{/if}}
|
|
70
|
+
</div>
|
|
71
|
+
{{! Save button }}
|
|
72
|
+
<div class="px-3 py-2 border-t dark:border-gray-700 flex-shrink-0 bg-gray-50 dark:bg-gray-800">
|
|
73
|
+
<Button @text={{t "orchestrator.save-card-fields"}} @type="primary" @size="sm" @isLoading={{this.saveSettings.isRunning}} @onClick={{perform this.saveSettings}} />
|
|
74
|
+
</div>
|
|
75
|
+
{{/if}}
|
|
76
|
+
</div>
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import Component from '@glimmer/component';
|
|
2
|
+
import { tracked } from '@glimmer/tracking';
|
|
3
|
+
import { action } from '@ember/object';
|
|
4
|
+
import { inject as service } from '@ember/service';
|
|
5
|
+
import { task } from 'ember-concurrency';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Orchestrator::CardFieldsSettings
|
|
9
|
+
*
|
|
10
|
+
* Settings panel for configuring which fields appear on order cards in the
|
|
11
|
+
* workbench. Fields are grouped by order config so the dispatcher can see
|
|
12
|
+
* exactly which custom fields belong to which order type.
|
|
13
|
+
*
|
|
14
|
+
* Saves to company settings key: fleetops.orchestrator_card_fields
|
|
15
|
+
* Shape: { standard: string[], byConfig: { [configUuid]: string[] }, meta: string[] }
|
|
16
|
+
*
|
|
17
|
+
* @arg onSaved - Optional action called after settings are saved
|
|
18
|
+
*/
|
|
19
|
+
export default class OrchestratorCardFieldsSettingsComponent extends Component {
|
|
20
|
+
@service fetch;
|
|
21
|
+
@service notifications;
|
|
22
|
+
@service intl;
|
|
23
|
+
|
|
24
|
+
/** Available order configs with their custom field definitions. */
|
|
25
|
+
@tracked orderConfigs = [];
|
|
26
|
+
|
|
27
|
+
/** Available meta keys discovered from recent orders. */
|
|
28
|
+
@tracked availableMetaKeys = [];
|
|
29
|
+
|
|
30
|
+
/** Current saved settings. */
|
|
31
|
+
@tracked settings = {
|
|
32
|
+
standard: ['pickup', 'dropoff', 'scheduled_at', 'customer', 'driver_assigned', 'vehicle_assigned', 'created_at'],
|
|
33
|
+
byConfig: {},
|
|
34
|
+
meta: [],
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
@tracked isLoaded = false;
|
|
38
|
+
|
|
39
|
+
constructor() {
|
|
40
|
+
super(...arguments);
|
|
41
|
+
this.loadData.perform();
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
get standardFieldOptions() {
|
|
45
|
+
return [
|
|
46
|
+
{ key: 'tracking', label: this.intl.t('orchestrator.field-tracking') },
|
|
47
|
+
{ key: 'status', label: this.intl.t('orchestrator.field-status') },
|
|
48
|
+
{ key: 'scheduled_at', label: this.intl.t('orchestrator.field-scheduled-at') },
|
|
49
|
+
{ key: 'customer', label: this.intl.t('orchestrator.field-customer') },
|
|
50
|
+
{ key: 'type', label: this.intl.t('orchestrator.field-type') },
|
|
51
|
+
{ key: 'notes', label: this.intl.t('orchestrator.field-notes') },
|
|
52
|
+
{ key: 'priority', label: this.intl.t('orchestrator.field-priority') },
|
|
53
|
+
{ key: 'dropoff', label: this.intl.t('orchestrator.dropoff') },
|
|
54
|
+
{ key: 'pickup', label: this.intl.t('orchestrator.pickup') },
|
|
55
|
+
{ key: 'driver_assigned', label: this.intl.t('orchestrator.driver-assigned') },
|
|
56
|
+
{ key: 'vehicle_assigned', label: this.intl.t('orchestrator.vehicle-assigned') },
|
|
57
|
+
{ key: 'created_at', label: this.intl.t('orchestrator.created') },
|
|
58
|
+
];
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
@task *loadData() {
|
|
62
|
+
try {
|
|
63
|
+
const [configsResult, settingsResult] = yield Promise.all([
|
|
64
|
+
this.fetch.get('fleet-ops/orchestrator/order-config-fields'),
|
|
65
|
+
this.fetch.get('fleet-ops/settings/orchestrator-card-fields').catch(() => null),
|
|
66
|
+
]);
|
|
67
|
+
|
|
68
|
+
// Backend returns { configs: [...], meta_keys: [...] }
|
|
69
|
+
this.orderConfigs = configsResult?.configs ?? [];
|
|
70
|
+
this.availableMetaKeys = configsResult?.meta_keys ?? [];
|
|
71
|
+
|
|
72
|
+
if (settingsResult?.settings) {
|
|
73
|
+
this.settings = {
|
|
74
|
+
standard: settingsResult.settings.standard ?? this.settings.standard,
|
|
75
|
+
byConfig: settingsResult.settings.byConfig ?? {},
|
|
76
|
+
meta: settingsResult.settings.meta ?? [],
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
} catch (error) {
|
|
80
|
+
this.notifications.serverError(error);
|
|
81
|
+
} finally {
|
|
82
|
+
this.isLoaded = true;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
@task *saveSettings() {
|
|
87
|
+
try {
|
|
88
|
+
yield this.fetch.post('fleet-ops/settings/orchestrator-card-fields', {
|
|
89
|
+
settings: this.settings,
|
|
90
|
+
});
|
|
91
|
+
this.notifications.success(this.intl.t('orchestrator.card-fields-saved'));
|
|
92
|
+
this.args.onSaved?.();
|
|
93
|
+
} catch (error) {
|
|
94
|
+
this.notifications.serverError(error);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
@action toggleStandardField(key) {
|
|
99
|
+
const current = this.settings.standard ?? [];
|
|
100
|
+
const updated = current.includes(key) ? current.filter((k) => k !== key) : [...current, key];
|
|
101
|
+
this.settings = { ...this.settings, standard: updated };
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// configUuid here is the real UUID (not public_id) so it matches order.order_config_uuid
|
|
105
|
+
@action toggleConfigField(configUuid, fieldKey) {
|
|
106
|
+
const byConfig = { ...(this.settings.byConfig ?? {}) };
|
|
107
|
+
const current = byConfig[configUuid] ?? [];
|
|
108
|
+
byConfig[configUuid] = current.includes(fieldKey) ? current.filter((k) => k !== fieldKey) : [...current, fieldKey];
|
|
109
|
+
this.settings = { ...this.settings, byConfig };
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
@action toggleMetaKey(key) {
|
|
113
|
+
const current = this.settings.meta ?? [];
|
|
114
|
+
const updated = current.includes(key) ? current.filter((k) => k !== key) : [...current, key];
|
|
115
|
+
this.settings = { ...this.settings, meta: updated };
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* These three methods are called with arguments from HBS so they must be
|
|
120
|
+
* decorated with @action to satisfy Glimmer's template invocation rules.
|
|
121
|
+
*/
|
|
122
|
+
@action isStandardSelected(key) {
|
|
123
|
+
return (this.settings.standard ?? []).includes(key);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// configUuid here is the real UUID (not public_id) so it matches order.order_config_uuid
|
|
127
|
+
@action isConfigFieldSelected(configUuid, fieldKey) {
|
|
128
|
+
return (this.settings.byConfig?.[configUuid] ?? []).includes(fieldKey);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
@action isMetaKeySelected(key) {
|
|
132
|
+
return (this.settings.meta ?? []).includes(key);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
{{! Orchestrator::OrderPool — left panel of the workbench }}
|
|
2
|
+
<div class="order-pool flex flex-col h-full overflow-hidden">
|
|
3
|
+
|
|
4
|
+
{{! Search + count }}
|
|
5
|
+
<div class="px-3 py-2 border-b dark:border-gray-700 flex items-center space-x-2 flex-shrink-0">
|
|
6
|
+
<div class="relative flex-1">
|
|
7
|
+
<span class="absolute inset-y-0 left-0 flex items-center justify-center pointer-events-none text-gray-400 w-8">
|
|
8
|
+
<FaIcon @icon="magnifying-glass" @size="xs" class="block align-baseline" />
|
|
9
|
+
</span>
|
|
10
|
+
<input type="text" class="form-input form-input-sm w-full pl-7i" placeholder={{t "orchestrator.search-orders"}} value={{this.orderSearch}} {{on "input" this.onSearchInput}} />
|
|
11
|
+
</div>
|
|
12
|
+
<span class="text-xs text-gray-400 flex-shrink-0 tabular-nums">
|
|
13
|
+
{{this.filteredOrders.length}}/{{@orders.length}}
|
|
14
|
+
</span>
|
|
15
|
+
</div>
|
|
16
|
+
|
|
17
|
+
{{! Quick filter chips }}
|
|
18
|
+
<div class="px-3 py-1.5 border-b dark:border-gray-700 flex items-center gap-1 flex-wrap flex-shrink-0">
|
|
19
|
+
<button
|
|
20
|
+
type="button"
|
|
21
|
+
class="px-2 py-0.5 rounded text-xs transition-colors
|
|
22
|
+
{{if (eq this.orderFilter 'all') 'bg-indigo-500 text-white' 'bg-gray-100 dark:bg-gray-700 text-gray-600 dark:text-gray-300 hover:bg-gray-200 dark:hover:bg-gray-600'}}"
|
|
23
|
+
{{on "click" (fn this.setFilter "all")}}
|
|
24
|
+
>{{t "orchestrator.filter-all"}}</button>
|
|
25
|
+
<button
|
|
26
|
+
type="button"
|
|
27
|
+
class="px-2 py-0.5 rounded text-xs transition-colors
|
|
28
|
+
{{if (eq this.orderFilter 'scheduled') 'bg-indigo-500 text-white' 'bg-gray-100 dark:bg-gray-700 text-gray-600 dark:text-gray-300 hover:bg-gray-200 dark:hover:bg-gray-600'}}"
|
|
29
|
+
{{on "click" (fn this.setFilter "scheduled")}}
|
|
30
|
+
>{{t "orchestrator.filter-scheduled"}}</button>
|
|
31
|
+
<button
|
|
32
|
+
type="button"
|
|
33
|
+
class="px-2 py-0.5 rounded text-xs transition-colors
|
|
34
|
+
{{if (eq this.orderFilter 'today') 'bg-indigo-500 text-white' 'bg-gray-100 dark:bg-gray-700 text-gray-600 dark:text-gray-300 hover:bg-gray-200 dark:hover:bg-gray-600'}}"
|
|
35
|
+
{{on "click" (fn this.setFilter "today")}}
|
|
36
|
+
>{{t "orchestrator.filter-today"}}</button>
|
|
37
|
+
<button
|
|
38
|
+
type="button"
|
|
39
|
+
class="px-2 py-0.5 rounded text-xs transition-colors
|
|
40
|
+
{{if (eq this.orderFilter 'urgent') 'bg-indigo-500 text-white' 'bg-gray-100 dark:bg-gray-700 text-gray-600 dark:text-gray-300 hover:bg-gray-200 dark:hover:bg-gray-600'}}"
|
|
41
|
+
{{on "click" (fn this.setFilter "urgent")}}
|
|
42
|
+
>{{t "orchestrator.filter-urgent"}}</button>
|
|
43
|
+
<button
|
|
44
|
+
type="button"
|
|
45
|
+
class="px-2 py-0.5 rounded text-xs transition-colors
|
|
46
|
+
{{if (eq this.orderFilter 'unassigned') 'bg-indigo-500 text-white' 'bg-gray-100 dark:bg-gray-700 text-gray-600 dark:text-gray-300 hover:bg-gray-200 dark:hover:bg-gray-600'}}"
|
|
47
|
+
{{on "click" (fn this.setFilter "unassigned")}}
|
|
48
|
+
>{{t "orchestrator.filter-unassigned"}}</button>
|
|
49
|
+
<button
|
|
50
|
+
type="button"
|
|
51
|
+
class="px-2 py-0.5 rounded text-xs transition-colors
|
|
52
|
+
{{if (eq this.orderFilter 'imported') 'bg-indigo-500 text-white' 'bg-gray-100 dark:bg-gray-700 text-gray-600 dark:text-gray-300 hover:bg-gray-200 dark:hover:bg-gray-600'}}"
|
|
53
|
+
{{on "click" (fn this.setFilter "imported")}}
|
|
54
|
+
>{{t "orchestrator.filter-imported"}}</button>
|
|
55
|
+
</div>
|
|
56
|
+
|
|
57
|
+
{{! Advanced Filters toggle — on its own row }}
|
|
58
|
+
<div class="px-3 py-1 border-b dark:border-gray-700 flex items-center flex-shrink-0">
|
|
59
|
+
<button
|
|
60
|
+
type="button"
|
|
61
|
+
class="px-2 py-0.5 rounded text-xs transition-colors flex items-center gap-1
|
|
62
|
+
{{if this.showAdvanced 'bg-indigo-500 text-white' 'bg-gray-100 dark:bg-gray-700 text-gray-600 dark:text-gray-300 hover:bg-gray-200 dark:hover:bg-gray-600'}}
|
|
63
|
+
{{if this.hasAdvancedFilters 'ring-1 ring-indigo-400' ''}}"
|
|
64
|
+
{{on "click" this.toggleAdvanced}}
|
|
65
|
+
>
|
|
66
|
+
<FaIcon @icon="sliders" @size="xs" />
|
|
67
|
+
{{t "orchestrator.advanced-filters"}}
|
|
68
|
+
{{#if this.hasAdvancedFilters}}
|
|
69
|
+
<span class="w-1.5 h-1.5 rounded-full bg-yellow-400 inline-block"></span>
|
|
70
|
+
{{/if}}
|
|
71
|
+
</button>
|
|
72
|
+
</div>
|
|
73
|
+
|
|
74
|
+
{{! Advanced filter panel }}
|
|
75
|
+
{{#if this.showAdvanced}}
|
|
76
|
+
<div class="px-3 py-2 border-b dark:border-gray-700 bg-gray-50 dark:bg-gray-800/50 flex-shrink-0 space-y-2">
|
|
77
|
+
<div class="grid grid-cols-2 gap-2">
|
|
78
|
+
{{! Country }}
|
|
79
|
+
<div class="input-group">
|
|
80
|
+
<label class="input-label text-xs">{{t "orchestrator.filter-country"}}</label>
|
|
81
|
+
<CountrySelect
|
|
82
|
+
class="form-input form-input-sm w-full"
|
|
83
|
+
@value={{this.advancedCountry}}
|
|
84
|
+
@onChange={{this.setAdvancedCountry}}
|
|
85
|
+
@placeholder={{t "orchestrator.filter-country-placeholder"}}
|
|
86
|
+
/>
|
|
87
|
+
</div>
|
|
88
|
+
{{! Order Type }}
|
|
89
|
+
<div class="input-group">
|
|
90
|
+
<label class="input-label text-xs">{{t "orchestrator.filter-type"}}</label>
|
|
91
|
+
<select class="form-select form-input-sm w-full" {{on "change" this.setAdvancedType}}>
|
|
92
|
+
<option value="">{{t "orchestrator.filter-type-placeholder"}}</option>
|
|
93
|
+
{{#each this.availableTypes as |type|}}
|
|
94
|
+
<option value={{type}} selected={{eq type this.advancedType}}>{{type}}</option>
|
|
95
|
+
{{/each}}
|
|
96
|
+
</select>
|
|
97
|
+
</div>
|
|
98
|
+
{{! Status }}
|
|
99
|
+
<div class="input-group">
|
|
100
|
+
<label class="input-label text-xs">{{t "orchestrator.filter-status"}}</label>
|
|
101
|
+
<select class="form-select form-input-sm w-full" {{on "change" this.setAdvancedStatus}}>
|
|
102
|
+
<option value="">{{t "orchestrator.filter-status-placeholder"}}</option>
|
|
103
|
+
{{#each this.availableStatuses as |status|}}
|
|
104
|
+
<option value={{status}} selected={{eq status this.advancedStatus}}>{{status}}</option>
|
|
105
|
+
{{/each}}
|
|
106
|
+
</select>
|
|
107
|
+
</div>
|
|
108
|
+
{{! Scheduled Date }}
|
|
109
|
+
<div class="input-group">
|
|
110
|
+
<label class="input-label text-xs">{{t "orchestrator.filter-date"}}</label>
|
|
111
|
+
<input type="date" class="form-input form-input-sm w-full" value={{this.advancedDate}} {{on "change" this.setAdvancedDate}} />
|
|
112
|
+
</div>
|
|
113
|
+
</div>
|
|
114
|
+
{{#if this.hasAdvancedFilters}}
|
|
115
|
+
<button type="button" class="text-xs text-indigo-400 hover:text-indigo-300" {{on "click" this.clearAdvancedFilters}}>
|
|
116
|
+
<FaIcon @icon="xmark" @size="xs" class="mr-0.5" />{{t "orchestrator.clear-filters"}}
|
|
117
|
+
</button>
|
|
118
|
+
{{/if}}
|
|
119
|
+
</div>
|
|
120
|
+
{{/if}}
|
|
121
|
+
|
|
122
|
+
{{! Order list }}
|
|
123
|
+
<div class="flex-1 overflow-y-auto space-y-2">
|
|
124
|
+
{{#if @isLoading}}
|
|
125
|
+
<div class="flex justify-center py-8"><Spinner /></div>
|
|
126
|
+
{{else if this.filteredOrders.length}}
|
|
127
|
+
{{! Single collapse/expand-all toggle }}
|
|
128
|
+
<div class="px-3 pt-1.5 pb-0.5 flex items-center flex-shrink-0">
|
|
129
|
+
<button type="button" class="text-xs text-gray-400 hover:text-indigo-400 transition-colors flex items-center gap-1" {{on "click" this.toggleAllWaypoints}}>
|
|
130
|
+
<FaIcon @icon={{if this.allWaypointsCollapsed "chevron-down" "chevron-up"}} @size="xs" />
|
|
131
|
+
{{if this.allWaypointsCollapsed (t "orchestrator.expand-all") (t "orchestrator.collapse-all")}}
|
|
132
|
+
</button>
|
|
133
|
+
</div>
|
|
134
|
+
{{#each this.filteredOrders as |order|}}
|
|
135
|
+
<div
|
|
136
|
+
class="order-pool-card mx-2 my-1 rounded border overflow-hidden select-none
|
|
137
|
+
{{if
|
|
138
|
+
(includes order.public_id this.selectedOrderIdsArray)
|
|
139
|
+
'ring-2 ring-indigo-500 border-indigo-400 dark:border-indigo-500 cursor-grab'
|
|
140
|
+
'border-gray-200 dark:border-gray-700 cursor-pointer hover:border-indigo-400 dark:hover:border-indigo-500 hover:ring-1 hover:ring-indigo-400'
|
|
141
|
+
}}"
|
|
142
|
+
draggable="true"
|
|
143
|
+
data-order-id={{order.public_id}}
|
|
144
|
+
{{on "dragstart" (fn @onDragStart order)}}
|
|
145
|
+
{{on "click" (fn @onToggleSelection order)}}
|
|
146
|
+
>
|
|
147
|
+
{{! Header: checkbox + tracking number + priority/status badges + collapse toggle }}
|
|
148
|
+
<div class="flex items-center gap-1.5 px-2 py-1.5 bg-gray-50 dark:bg-gray-800 border-b border-gray-200 dark:border-gray-700">
|
|
149
|
+
<input
|
|
150
|
+
type="checkbox"
|
|
151
|
+
class="form-checkbox h-3.5 w-3.5 rounded text-indigo-600 border-gray-300 dark:border-gray-600 cursor-pointer flex-shrink-0"
|
|
152
|
+
checked={{includes order.public_id this.selectedOrderIdsArray}}
|
|
153
|
+
{{on "change" (fn @onToggleSelection order)}}
|
|
154
|
+
{{on "click" this.stopPropagation}}
|
|
155
|
+
/>
|
|
156
|
+
<span class="flex-1 min-w-0 truncate text-xs font-semibold text-gray-800 dark:text-gray-100">
|
|
157
|
+
{{or order.tracking order.public_id}}
|
|
158
|
+
</span>
|
|
159
|
+
<div class="flex-shrink-0 flex items-center gap-1">
|
|
160
|
+
{{#if order.orchestrator_priority}}
|
|
161
|
+
<Badge @status={{this.priorityBadgeStatus order.orchestrator_priority}}>P{{order.orchestrator_priority}}</Badge>
|
|
162
|
+
{{/if}}
|
|
163
|
+
<Badge @status={{order.status}} />
|
|
164
|
+
{{! Waypoint collapse toggle }}
|
|
165
|
+
<button
|
|
166
|
+
type="button"
|
|
167
|
+
class="ml-0.5 w-5 h-5 flex items-center justify-center rounded text-gray-400 hover:text-indigo-400 hover:bg-gray-200 dark:hover:bg-gray-700 transition-colors flex-shrink-0"
|
|
168
|
+
title={{if (this.isWaypointCollapsed order.public_id) (t "orchestrator.expand-route") (t "orchestrator.collapse-route")}}
|
|
169
|
+
{{on "click" (fn this.toggleWaypointCollapse order.public_id)}}
|
|
170
|
+
>
|
|
171
|
+
<FaIcon @icon={{if (this.isWaypointCollapsed order.public_id) "chevron-down" "chevron-up"}} @size="xs" />
|
|
172
|
+
</button>
|
|
173
|
+
</div>
|
|
174
|
+
</div>
|
|
175
|
+
|
|
176
|
+
{{! Card body — hidden when collapsed }}
|
|
177
|
+
{{#unless (this.isWaypointCollapsed order.public_id)}}
|
|
178
|
+
<div class="bg-white dark:bg-gray-900 px-2 py-1.5">
|
|
179
|
+
<dl class="grid grid-cols-[auto_1fr] gap-x-2 gap-y-0.5">
|
|
180
|
+
{{#each (this.resolvedCardFields order) as |field|}}
|
|
181
|
+
<dt class="flex items-center gap-1 text-xs text-gray-500 dark:text-gray-400 whitespace-nowrap">
|
|
182
|
+
{{#if field.icon}}
|
|
183
|
+
<FaIcon @icon={{field.icon}} @size="xs" class="w-3 text-center {{if field.iconClass field.iconClass ''}}" />
|
|
184
|
+
{{/if}}
|
|
185
|
+
{{field.label}}
|
|
186
|
+
</dt>
|
|
187
|
+
<dd class="truncate text-right text-xs {{if field.highlight field.highlight 'text-gray-700 dark:text-gray-300'}}">
|
|
188
|
+
{{or field.value "-"}}
|
|
189
|
+
</dd>
|
|
190
|
+
{{/each}}
|
|
191
|
+
</dl>
|
|
192
|
+
|
|
193
|
+
{{! Inline route stop list }}
|
|
194
|
+
{{#let (this.orderRouteStops order) as |stops|}}
|
|
195
|
+
{{#if stops.length}}
|
|
196
|
+
<div class="mt-1.5 border-t border-gray-100 dark:border-gray-700 pt-1">
|
|
197
|
+
{{! Route header with toggle }}
|
|
198
|
+
<button
|
|
199
|
+
type="button"
|
|
200
|
+
class="w-full flex items-center justify-between text-xs text-gray-500 dark:text-gray-400 hover:text-indigo-500 dark:hover:text-indigo-400 transition-colors"
|
|
201
|
+
{{on "click" (fn this.toggleRouteCollapse order.public_id)}}
|
|
202
|
+
>
|
|
203
|
+
<span class="flex items-center gap-1">
|
|
204
|
+
<FaIcon @icon="route" @size="xs" class="text-indigo-400" />
|
|
205
|
+
<span class="font-medium">{{t "orchestrator.route"}} · {{stops.length}} {{t "orchestrator.stops"}}</span>
|
|
206
|
+
</span>
|
|
207
|
+
<FaIcon @icon={{if (this.isRouteCollapsed order.public_id) "chevron-down" "chevron-up"}} @size="xs" />
|
|
208
|
+
</button>
|
|
209
|
+
{{! Stop list }}
|
|
210
|
+
{{#unless (this.isRouteCollapsed order.public_id)}}
|
|
211
|
+
<ol class="mt-1 space-y-1.5">
|
|
212
|
+
{{#each stops as |stop|}}
|
|
213
|
+
<li class="flex items-start gap-1.5 text-xs">
|
|
214
|
+
<span
|
|
215
|
+
class="flex-shrink-0 w-4 h-4 rounded-full bg-indigo-100 dark:bg-indigo-900 text-indigo-600 dark:text-indigo-300 text-[0.6rem] font-bold flex items-center justify-center leading-none"
|
|
216
|
+
>
|
|
217
|
+
{{stop.label}}
|
|
218
|
+
</span>
|
|
219
|
+
<span class="text-gray-600 dark:text-gray-300 leading-4 line-clamp-2">{{stop.address}}</span>
|
|
220
|
+
</li>
|
|
221
|
+
{{/each}}
|
|
222
|
+
</ol>
|
|
223
|
+
{{/unless}}
|
|
224
|
+
</div>
|
|
225
|
+
{{/if}}
|
|
226
|
+
{{/let}}
|
|
227
|
+
|
|
228
|
+
{{#if order.required_skills.length}}
|
|
229
|
+
<div class="flex flex-wrap gap-0.5 mt-1">
|
|
230
|
+
{{#each order.required_skills as |skill|}}
|
|
231
|
+
<span class="skill-tag">{{skill}}</span>
|
|
232
|
+
{{/each}}
|
|
233
|
+
</div>
|
|
234
|
+
{{/if}}
|
|
235
|
+
</div>
|
|
236
|
+
{{/unless}}
|
|
237
|
+
</div>
|
|
238
|
+
{{/each}}
|
|
239
|
+
{{else}}
|
|
240
|
+
<div class="flex flex-col items-center justify-center py-12 text-gray-400 text-xs">
|
|
241
|
+
<FaIcon @icon="check-circle" @size="2x" class="mb-2 text-green-400" />
|
|
242
|
+
{{t "orchestrator.no-unassigned-orders"}}
|
|
243
|
+
</div>
|
|
244
|
+
{{/if}}
|
|
245
|
+
<Spacer @height="200px" />
|
|
246
|
+
</div>
|
|
247
|
+
|
|
248
|
+
{{! Bulk action bar + import }}
|
|
249
|
+
<div class="px-3 py-2 border-t dark:border-gray-700 flex items-center justify-between flex-shrink-0">
|
|
250
|
+
<Button @icon="file-import" @text={{t "orchestrator.import-orders"}} @type="default" @size="xs" @onClick={{@onOpenImport}} />
|
|
251
|
+
{{#if this.selectedOrderIdsArray.length}}
|
|
252
|
+
<div class="flex items-center gap-1.5">
|
|
253
|
+
<span class="text-xs text-blue-400">
|
|
254
|
+
{{this.selectedOrderIdsArray.length}}
|
|
255
|
+
{{t "orchestrator.selected"}}
|
|
256
|
+
</span>
|
|
257
|
+
<button type="button" class="text-xs text-gray-400 hover:text-white" {{on "click" @onClearSelection}}>
|
|
258
|
+
{{t "orchestrator.clear-selection"}}
|
|
259
|
+
</button>
|
|
260
|
+
</div>
|
|
261
|
+
{{/if}}
|
|
262
|
+
</div>
|
|
263
|
+
|
|
264
|
+
</div>
|