@fleetbase/fleetops-engine 0.6.50 → 0.6.52
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/README.md +183 -67
- package/addon/components/cell/telematic-provider.hbs +16 -0
- package/addon/components/cell/telematic-provider.js +36 -0
- package/addon/components/cell/telematic-status.hbs +1 -0
- package/addon/components/cell/telematic-status.js +39 -0
- package/addon/components/contact/panel-header.hbs +11 -48
- package/addon/components/customer/details.hbs +1 -2
- package/addon/components/customer/form.hbs +63 -51
- package/addon/components/customer/form.js +27 -1
- package/addon/components/customer/orders.hbs +48 -0
- package/addon/components/customer/orders.js +67 -5
- package/addon/components/device/manager.hbs +5 -6
- package/addon/components/device/manager.js +12 -15
- package/addon/components/driver/details.hbs +1 -1
- package/addon/components/driver/form.hbs +1 -1
- package/addon/components/fleet/vehicle-listing.js +1 -0
- package/addon/components/fuel-integration/form.hbs +200 -0
- package/addon/components/fuel-integration/form.js +242 -0
- package/addon/components/fuel-integration/hub.hbs +154 -0
- package/addon/components/fuel-integration/hub.js +165 -0
- package/addon/components/fuel-integration/matching-priority.hbs +76 -0
- package/addon/components/fuel-integration/matching-priority.js +145 -0
- package/addon/components/fuel-report/details.hbs +13 -1
- package/addon/components/home/getting-started-guidance.hbs +113 -0
- package/addon/components/home/getting-started-guidance.js +107 -0
- package/addon/components/issue/details/comments.hbs +3 -0
- package/addon/components/issue/details/comments.js +3 -0
- package/addon/components/issue/details/correspondence.hbs +9 -0
- package/addon/components/issue/details/correspondence.js +83 -0
- package/addon/components/issue/details/documents.hbs +69 -0
- package/addon/components/issue/details/documents.js +85 -0
- package/addon/components/issue/details.hbs +166 -59
- package/addon/components/issue/details.js +149 -0
- package/addon/components/issue/form.hbs +19 -1
- package/addon/components/issue/panel-header.hbs +43 -0
- package/addon/components/issue/panel-header.js +22 -0
- package/addon/components/issue/timeline.hbs +40 -0
- package/addon/components/issue/timeline.js +45 -0
- package/addon/components/layout/fleet-ops-sidebar.js +20 -2
- package/addon/components/leaflet-tracking-marker.js +3 -0
- package/addon/components/map/drawer/device-event-listing.hbs +12 -2
- package/addon/components/map/drawer/driver-listing.hbs +14 -1
- package/addon/components/map/drawer/place-listing.hbs +14 -1
- package/addon/components/map/drawer/position-listing.hbs +12 -2
- package/addon/components/map/drawer/position-listing.js +3 -0
- package/addon/components/map/drawer/vehicle-listing.hbs +14 -1
- package/addon/components/map/leaflet-live-map.hbs +2 -2
- package/addon/components/map/leaflet-live-map.js +17 -0
- package/addon/components/map/order-list-overlay.hbs +4 -4
- package/addon/components/modals/assigned-orders.hbs +40 -0
- package/addon/components/modals/attach-device.hbs +4 -3
- package/addon/components/modals/attach-telematic-device.hbs +25 -0
- package/addon/components/modals/attach-telematic-device.js +3 -0
- package/addon/components/modals/convert-customer-to-vendor.hbs +30 -0
- package/addon/components/modals/convert-customer-to-vendor.js +55 -0
- package/addon/components/modals/driver-assign-order.hbs +7 -58
- package/addon/components/modals/driver-assign-vehicle.hbs +10 -2
- package/addon/components/modals/fleet-assign-driver.hbs +18 -0
- package/addon/components/modals/fleet-assign-driver.js +3 -0
- package/addon/components/modals/fleet-assign-vehicle.hbs +18 -0
- package/addon/components/modals/fleet-assign-vehicle.js +3 -0
- package/addon/components/modals/issue-assign.hbs +20 -0
- package/addon/components/modals/issue-assign.js +49 -0
- package/addon/components/modals/issue-close.hbs +30 -0
- package/addon/components/modals/issue-close.js +73 -0
- package/addon/components/modals/issue-status.hbs +20 -0
- package/addon/components/modals/issue-status.js +43 -0
- package/addon/components/modals/reset-customer-credentials.js +12 -6
- package/addon/components/modals/telematic-connection-diagnostics.hbs +75 -0
- package/addon/components/modals/telematic-connection-diagnostics.js +287 -0
- package/addon/components/modals/update-order-activity.hbs +51 -17
- package/addon/components/modals/update-order-activity.js +59 -5
- package/addon/components/modals/vehicle-details.hbs +6 -1
- package/addon/components/modals/vehicle-form.hbs +8 -1
- package/addon/components/order/card.hbs +106 -0
- package/addon/components/order/card.js +257 -0
- package/addon/components/order/details/activity.js +2 -2
- package/addon/components/order/details/proof.hbs +40 -38
- package/addon/components/order/details/proof.js +31 -4
- package/addon/components/order/details.hbs +5 -5
- package/addon/components/order/details.js +19 -1
- package/addon/components/order/form/service-rate.hbs +2 -0
- package/addon/components/order/header.hbs +1 -1
- package/addon/components/route-list.hbs +0 -12
- package/addon/components/service-rate/details.hbs +1 -1
- package/addon/components/service-rate/form.hbs +4 -3
- package/addon/components/service-rate/form.js +4 -0
- package/addon/components/telematic/details.hbs +98 -87
- package/addon/components/telematic/details.js +230 -1
- package/addon/components/telematic/form.hbs +303 -72
- package/addon/components/telematic/form.js +519 -3
- package/addon/components/telematic/hub.hbs +149 -0
- package/addon/components/telematic/hub.js +142 -0
- package/addon/components/telematic/settings.hbs +152 -0
- package/addon/components/telematic/settings.js +45 -0
- package/addon/components/telematic/tab-empty-state.hbs +29 -0
- package/addon/components/telematic/tab-empty-state.js +33 -0
- package/addon/components/vehicle/details.hbs +6 -1
- package/addon/components/vehicle/form.hbs +2 -1
- package/addon/components/vendor/personnel-manager.hbs +166 -0
- package/addon/components/vendor/personnel-manager.js +143 -0
- package/addon/components/widget/fuel-providers.hbs +43 -0
- package/addon/components/widget/fuel-providers.js +27 -0
- package/addon/components/widget/live-fleet.hbs +1 -0
- package/addon/components/widget/live-fleet.js +2 -7
- package/addon/components/widget/revenue-trend.hbs +1 -1
- package/addon/components/widget/revenue-trend.js +75 -2
- package/addon/controllers/connectivity/devices/index/details.js +27 -1
- package/addon/controllers/connectivity/devices/index.js +14 -0
- package/addon/controllers/connectivity/fuel-providers/details/sync.js +18 -0
- package/addon/controllers/connectivity/fuel-providers/details/transactions.js +24 -0
- package/addon/controllers/connectivity/fuel-providers/details.js +69 -0
- package/addon/controllers/connectivity/fuel-providers/edit.js +24 -0
- package/addon/controllers/connectivity/fuel-providers/index.js +177 -0
- package/addon/controllers/connectivity/fuel-providers/new.js +37 -0
- package/addon/controllers/connectivity/telematics/details/attachments.js +247 -0
- package/addon/controllers/connectivity/telematics/details/devices.js +368 -0
- package/addon/controllers/connectivity/telematics/details/events.js +244 -0
- package/addon/controllers/connectivity/telematics/details/index.js +3 -0
- package/addon/controllers/connectivity/telematics/details/logs.js +43 -0
- package/addon/controllers/connectivity/telematics/details/sensors.js +270 -0
- package/addon/controllers/connectivity/telematics/details.js +149 -0
- package/addon/controllers/connectivity/telematics/{index/edit.js → edit.js} +15 -4
- package/addon/controllers/connectivity/telematics/index.js +25 -5
- package/addon/controllers/connectivity/telematics/{index/new.js → new.js} +8 -2
- package/addon/controllers/management/contacts/customers/details.js +31 -13
- package/addon/controllers/management/contacts/customers.js +16 -5
- package/addon/controllers/management/contacts/index/details.js +31 -13
- package/addon/controllers/management/contacts/index.js +7 -0
- package/addon/controllers/management/drivers/index/details.js +78 -1
- package/addon/controllers/management/drivers/index.js +39 -0
- package/addon/controllers/management/fleets/index/details.js +23 -1
- package/addon/controllers/management/fleets/index.js +6 -1
- package/addon/controllers/management/fuel-reports/index.js +37 -1
- package/addon/controllers/management/fuel-transactions/index/details.js +70 -0
- package/addon/controllers/management/fuel-transactions/index.js +240 -0
- package/addon/controllers/management/issues/index/details.js +52 -6
- package/addon/controllers/management/vehicles/index/details.js +32 -0
- package/addon/controllers/management/vehicles/index.js +26 -0
- package/addon/controllers/management/vendors/index/details.js +4 -0
- package/addon/controllers/operations/orders/index/details.js +11 -3
- package/addon/controllers/operations/orders/index.js +5 -1
- package/addon/controllers/settings/payments/index.js +5 -0
- package/addon/extension.js +29 -12
- package/addon/helpers/format-duration.js +1 -38
- package/addon/initializers/load-leaflet-assets.js +5 -6
- package/addon/initializers/patch-ember-leaflet-tooltip-layer.js +51 -0
- package/addon/routes/connectivity/fuel-providers/details/index.js +7 -0
- package/addon/routes/connectivity/fuel-providers/details/matching.js +7 -0
- package/addon/routes/connectivity/fuel-providers/details/settings.js +7 -0
- package/addon/routes/connectivity/fuel-providers/details/sync.js +18 -0
- package/addon/routes/connectivity/fuel-providers/details/transactions.js +14 -0
- package/addon/routes/connectivity/fuel-providers/details.js +18 -0
- package/addon/routes/connectivity/fuel-providers/edit.js +18 -0
- package/addon/routes/connectivity/fuel-providers/index.js +20 -0
- package/addon/routes/connectivity/fuel-providers/new.js +3 -0
- package/addon/routes/connectivity/fuel-providers.js +3 -0
- package/addon/routes/connectivity/telematics/details/attachments.js +28 -0
- package/addon/routes/connectivity/telematics/details/devices.js +30 -0
- package/addon/routes/connectivity/telematics/details/events.js +33 -0
- package/addon/routes/connectivity/telematics/details/index.js +3 -0
- package/addon/routes/connectivity/telematics/details/logs.js +17 -0
- package/addon/routes/connectivity/telematics/details/sensors.js +29 -0
- package/addon/routes/connectivity/telematics/{index/details.js → details.js} +1 -1
- package/addon/routes/connectivity/telematics/{index/edit.js → edit.js} +1 -1
- package/addon/routes/connectivity/telematics/new.js +3 -0
- package/addon/routes/management/drivers/index/details/activity.js +3 -0
- package/addon/routes/management/fuel-reports/index.js +2 -0
- package/addon/routes/management/fuel-transactions/index/details.js +18 -0
- package/addon/routes/management/fuel-transactions/index.js +21 -0
- package/addon/routes/management/fuel-transactions.js +3 -0
- package/addon/routes/management/issues/index/details.js +1 -1
- package/addon/routes.js +29 -9
- package/addon/services/contact-actions.js +231 -1
- package/addon/services/device-actions.js +64 -1
- package/addon/services/device-event-actions.js +12 -1
- package/addon/services/driver-actions.js +147 -11
- package/addon/services/fleet-actions.js +66 -1
- package/addon/services/fuel-integration-actions.js +31 -0
- package/addon/services/getting-started.js +44 -0
- package/addon/services/issue-actions.js +72 -1
- package/addon/services/leaflet-map-manager.js +2 -0
- package/addon/services/map-adapter/leaflet.js +19 -0
- package/addon/services/service-areas.js +3 -0
- package/addon/services/telematic-actions.js +9 -3
- package/addon/services/vehicle-actions.js +125 -0
- package/addon/styles/fleetops-engine.css +1313 -1
- package/addon/templates/analytics/reports/index.hbs +19 -1
- package/addon/templates/connectivity/devices/index.hbs +19 -1
- package/addon/templates/connectivity/events/index.hbs +16 -1
- package/addon/templates/connectivity/fuel-providers/details/index.hbs +38 -0
- package/addon/templates/connectivity/fuel-providers/details/matching.hbs +13 -0
- package/addon/templates/connectivity/fuel-providers/details/settings.hbs +11 -0
- package/addon/templates/connectivity/fuel-providers/details/sync.hbs +48 -0
- package/addon/templates/connectivity/fuel-providers/details/transactions.hbs +21 -0
- package/addon/templates/connectivity/fuel-providers/details.hbs +51 -0
- package/addon/templates/connectivity/fuel-providers/edit.hbs +24 -0
- package/addon/templates/connectivity/fuel-providers/index.hbs +12 -0
- package/addon/templates/connectivity/fuel-providers/new.hbs +22 -0
- package/addon/templates/connectivity/fuel-providers.hbs +1 -0
- package/addon/templates/connectivity/sensors/index.hbs +19 -1
- package/addon/templates/connectivity/telematics/details/attachments.hbs +163 -0
- package/addon/templates/connectivity/telematics/details/devices.hbs +88 -0
- package/addon/templates/connectivity/telematics/details/events.hbs +101 -0
- package/addon/templates/connectivity/telematics/{index/details → details}/index.hbs +0 -1
- package/addon/templates/connectivity/telematics/details/logs.hbs +69 -0
- package/addon/templates/connectivity/telematics/details/sensors.hbs +88 -0
- package/addon/templates/connectivity/telematics/details.hbs +53 -0
- package/addon/templates/connectivity/telematics/edit.hbs +27 -0
- package/addon/templates/connectivity/telematics/index.hbs +6 -8
- package/addon/templates/connectivity/telematics/new.hbs +24 -0
- package/addon/templates/maintenance/equipment/index.hbs +19 -1
- package/addon/templates/maintenance/maintenances/index.hbs +15 -1
- package/addon/templates/maintenance/parts/index.hbs +19 -1
- package/addon/templates/maintenance/schedules/index.hbs +19 -1
- package/addon/templates/maintenance/work-orders/index.hbs +19 -1
- package/addon/templates/management/contacts/customers/details.hbs +1 -1
- package/addon/templates/management/contacts/customers.hbs +15 -1
- package/addon/templates/management/contacts/index/details.hbs +1 -1
- package/addon/templates/management/contacts/index.hbs +19 -1
- package/addon/templates/management/contacts.hbs +2 -2
- package/addon/templates/management/drivers/index/details/activity.hbs +1 -0
- package/addon/templates/management/drivers/index.hbs +19 -1
- package/addon/templates/management/fleets/index.hbs +19 -1
- package/addon/templates/management/fuel-reports/index.hbs +19 -1
- package/addon/templates/management/fuel-transactions/index/details.hbs +73 -0
- package/addon/templates/management/fuel-transactions/index.hbs +58 -0
- package/addon/templates/management/fuel-transactions.hbs +1 -0
- package/addon/templates/management/issues/index/details/index.hbs +3 -1
- package/addon/templates/management/issues/index/details.hbs +3 -2
- package/addon/templates/management/issues/index.hbs +19 -1
- package/addon/templates/management/places/index.hbs +19 -1
- package/addon/templates/management/vehicles/index.hbs +19 -1
- package/addon/templates/management/vendors/index/details/personnel.hbs +1 -2
- package/addon/templates/management/vendors/index.hbs +19 -1
- package/addon/templates/management/vendors/integrated.hbs +13 -1
- package/addon/templates/operations/orders/index/details/index.hbs +2 -2
- package/addon/templates/operations/orders/index.hbs +20 -2
- package/addon/templates/operations/service-rates/index/edit.hbs +1 -0
- package/addon/templates/operations/service-rates/index/new.hbs +1 -0
- package/addon/templates/operations/service-rates/index.hbs +19 -1
- package/addon/templates/settings/payments/index.hbs +15 -1
- package/addon/templates/settings/payments/onboard.hbs +8 -8
- package/addon/utils/fleet-ops-options.js +3 -0
- package/addon/utils/leaflet-draw-namespace-guard.js +22 -0
- package/addon/utils/leaflet-plugin-loader.js +219 -0
- package/addon/utils/setup-customer-portal.js +4 -64
- package/app/components/cell/telematic-provider.js +1 -0
- package/app/components/cell/telematic-status.js +1 -0
- package/app/components/fuel-integration/form.js +1 -0
- package/app/components/fuel-integration/hub.js +1 -0
- package/app/components/fuel-integration/matching-priority.js +1 -0
- package/app/components/home/getting-started-guidance.js +1 -0
- package/app/components/issue/details/comments.js +1 -0
- package/app/components/issue/details/correspondence.js +1 -0
- package/app/components/issue/details/documents.js +1 -0
- package/app/components/issue/panel-header.js +1 -0
- package/app/components/modals/assigned-orders.js +1 -0
- package/app/components/modals/attach-telematic-device.js +1 -0
- package/app/components/modals/convert-customer-to-vendor.js +1 -0
- package/app/components/modals/fleet-assign-driver.js +1 -0
- package/app/components/modals/fleet-assign-vehicle.js +1 -0
- package/app/components/modals/issue-assign.js +1 -0
- package/app/components/modals/issue-close.js +1 -0
- package/app/components/modals/issue-status.js +1 -0
- package/app/components/modals/telematic-connection-diagnostics.js +1 -0
- package/app/components/order/card.js +1 -0
- package/app/components/telematic/hub.js +1 -0
- package/app/components/telematic/settings.js +1 -0
- package/app/components/telematic/tab-empty-state.js +1 -0
- package/app/components/vendor/personnel-manager.js +1 -0
- package/app/components/widget/fuel-providers.js +1 -0
- package/app/controllers/connectivity/fuel-providers/details/sync.js +1 -0
- package/app/controllers/connectivity/{telematics/index/details/devices.js → fuel-providers/details/transactions.js} +1 -1
- package/app/controllers/connectivity/{telematics/index → fuel-providers}/details.js +1 -1
- package/app/controllers/connectivity/{telematics/index → fuel-providers}/edit.js +1 -1
- package/app/controllers/connectivity/{telematics/index/details → fuel-providers}/index.js +1 -1
- package/app/controllers/connectivity/{telematics/index → fuel-providers}/new.js +1 -1
- package/app/controllers/connectivity/telematics/details/attachments.js +1 -0
- package/app/controllers/connectivity/telematics/details/devices.js +1 -0
- package/app/controllers/connectivity/telematics/details/events.js +1 -0
- package/app/controllers/connectivity/telematics/details/index.js +1 -0
- package/app/controllers/connectivity/telematics/details/logs.js +1 -0
- package/app/controllers/connectivity/telematics/details/sensors.js +1 -0
- package/app/controllers/connectivity/telematics/details.js +1 -0
- package/app/controllers/connectivity/telematics/edit.js +1 -0
- package/app/controllers/connectivity/telematics/new.js +1 -0
- package/app/controllers/management/fuel-transactions/index/details.js +1 -0
- package/app/controllers/management/fuel-transactions/index.js +1 -0
- package/app/helpers/format-duration.js +1 -1
- package/app/routes/connectivity/{telematics/index → fuel-providers}/details/index.js +1 -1
- package/app/routes/connectivity/{telematics/index/details/events.js → fuel-providers/details/matching.js} +1 -1
- package/app/routes/connectivity/fuel-providers/details/settings.js +1 -0
- package/app/routes/connectivity/fuel-providers/details/sync.js +1 -0
- package/app/routes/connectivity/{telematics/index/details/devices.js → fuel-providers/details/transactions.js} +1 -1
- package/app/routes/connectivity/{telematics/index → fuel-providers}/details.js +1 -1
- package/app/routes/connectivity/{telematics/index → fuel-providers}/edit.js +1 -1
- package/app/routes/connectivity/fuel-providers/index.js +1 -0
- package/app/routes/connectivity/{telematics/index → fuel-providers}/new.js +1 -1
- package/app/routes/connectivity/fuel-providers.js +1 -0
- package/app/routes/connectivity/telematics/details/attachments.js +1 -0
- package/app/routes/connectivity/telematics/details/devices.js +1 -0
- package/app/routes/connectivity/telematics/details/events.js +1 -0
- package/app/routes/connectivity/telematics/details/index.js +1 -0
- package/app/routes/connectivity/telematics/details/logs.js +1 -0
- package/app/routes/connectivity/telematics/details/sensors.js +1 -0
- package/app/routes/connectivity/telematics/details.js +1 -0
- package/app/routes/connectivity/telematics/edit.js +1 -0
- package/app/routes/connectivity/telematics/new.js +1 -0
- package/app/routes/management/drivers/index/details/activity.js +1 -0
- package/app/routes/management/fuel-transactions/index/details.js +1 -0
- package/app/routes/management/fuel-transactions/index.js +1 -0
- package/app/routes/management/fuel-transactions.js +1 -0
- package/app/services/fuel-integration-actions.js +1 -0
- package/app/services/getting-started.js +1 -0
- package/app/templates/connectivity/{telematics/index → fuel-providers}/details/index.js +1 -1
- package/app/templates/connectivity/{telematics/index/details/events.js → fuel-providers/details/matching.js} +1 -1
- package/app/templates/connectivity/fuel-providers/details/settings.js +1 -0
- package/app/templates/connectivity/fuel-providers/details/sync.js +1 -0
- package/app/templates/connectivity/{telematics/index/details/devices.js → fuel-providers/details/transactions.js} +1 -1
- package/app/templates/connectivity/{telematics/index → fuel-providers}/details.js +1 -1
- package/app/templates/connectivity/{telematics/index → fuel-providers}/edit.js +1 -1
- package/app/templates/connectivity/fuel-providers/index.js +1 -0
- package/app/templates/connectivity/{telematics/index → fuel-providers}/new.js +1 -1
- package/app/templates/connectivity/fuel-providers.js +1 -0
- package/app/templates/connectivity/telematics/details/attachments.js +1 -0
- package/app/templates/connectivity/telematics/details/devices.js +1 -0
- package/app/templates/connectivity/telematics/details/events.js +1 -0
- package/app/templates/connectivity/telematics/details/index.js +1 -0
- package/app/templates/connectivity/telematics/details/logs.js +1 -0
- package/app/templates/connectivity/telematics/details/sensors.js +1 -0
- package/app/templates/connectivity/telematics/details.js +1 -0
- package/app/templates/connectivity/telematics/edit.js +1 -0
- package/app/templates/connectivity/telematics/new.js +1 -0
- package/app/templates/management/drivers/index/details/activity.js +1 -0
- package/app/templates/management/fuel-transactions/index/details.js +1 -0
- package/app/templates/management/fuel-transactions/index.js +1 -0
- package/app/templates/management/fuel-transactions.js +1 -0
- package/app/utils/leaflet-draw-namespace-guard.js +1 -0
- package/app/utils/leaflet-plugin-loader.js +1 -0
- package/assets/images/telematics/providers/afaqy.webp +0 -0
- package/assets/images/telematics/providers/default.webp +0 -0
- package/assets/images/telematics/providers/flespi.webp +0 -0
- package/assets/images/telematics/providers/geotab.webp +0 -0
- package/assets/images/telematics/providers/safee.webp +0 -0
- package/assets/images/telematics/providers/samsara.webp +0 -0
- package/composer.json +1 -1
- package/extension.json +1 -1
- package/package.json +5 -5
- package/server/config/fuel-providers.php +42 -0
- package/server/config/telematics.php +139 -130
- package/server/migrations/2026_05_31_000001_add_portal_fields_to_vendor_personnels_table.php +30 -0
- package/server/migrations/2026_06_03_000000_ensure_tags_column_on_issues_table.php +31 -0
- package/server/migrations/2026_06_03_000001_add_order_uuid_to_issues_table.php +25 -0
- package/server/migrations/2026_06_04_000001_backfill_order_transaction_subjects.php +39 -0
- package/server/migrations/2026_06_04_000002_backfill_order_transaction_directions.php +24 -0
- package/server/migrations/2026_06_06_000001_harden_device_events_telematics_contract.php +59 -0
- package/server/migrations/2026_06_08_000001_create_fuel_provider_connections_table.php +37 -0
- package/server/migrations/2026_06_08_000002_create_fuel_provider_transactions_table.php +53 -0
- package/server/migrations/2026_06_08_000003_create_fuel_provider_sync_runs_table.php +40 -0
- package/server/migrations/2026_06_10_000001_add_fuel_card_number_to_vehicles_table.php +25 -0
- package/server/migrations/2026_06_10_000002_add_vehicle_identity_columns_to_fuel_provider_transactions_table.php +39 -0
- package/server/resources/views/mail/customer-credentials.blade.php +16 -13
- package/server/src/Contracts/FuelProvider.php +30 -0
- package/server/src/Contracts/TelematicProviderDescriptor.php +3 -1
- package/server/src/Events/FuelProviderTransactionImported.php +17 -0
- package/server/src/Events/FuelProviderTransactionMatched.php +17 -0
- package/server/src/Events/FuelProviderTransactionUnmatched.php +17 -0
- package/server/src/Events/FuelReportCreatedFromProvider.php +18 -0
- package/server/src/Expansions/UserFilterExpansion.php +28 -0
- package/server/src/Http/Controllers/Api/v1/IssueController.php +2 -0
- package/server/src/Http/Controllers/Api/v1/OrderController.php +26 -25
- package/server/src/Http/Controllers/Api/v1/PlaceController.php +10 -58
- package/server/src/Http/Controllers/Internal/v1/AnalyticsController.php +6 -0
- package/server/src/Http/Controllers/Internal/v1/ContactController.php +135 -0
- package/server/src/Http/Controllers/Internal/v1/CustomerController.php +116 -6
- package/server/src/Http/Controllers/Internal/v1/DeviceController.php +76 -2
- package/server/src/Http/Controllers/Internal/v1/DeviceEventController.php +44 -0
- package/server/src/Http/Controllers/Internal/v1/DriverController.php +158 -7
- package/server/src/Http/Controllers/Internal/v1/FuelProviderConnectionController.php +124 -0
- package/server/src/Http/Controllers/Internal/v1/FuelProviderSyncRunController.php +10 -0
- package/server/src/Http/Controllers/Internal/v1/FuelProviderTransactionController.php +76 -0
- package/server/src/Http/Controllers/Internal/v1/GettingStartedController.php +17 -0
- package/server/src/Http/Controllers/Internal/v1/IssueController.php +251 -0
- package/server/src/Http/Controllers/Internal/v1/OrderController.php +172 -97
- package/server/src/Http/Controllers/Internal/v1/PlaceController.php +10 -68
- package/server/src/Http/Controllers/Internal/v1/SensorController.php +1 -1
- package/server/src/Http/Controllers/Internal/v1/TelematicController.php +178 -15
- package/server/src/Http/Controllers/Internal/v1/VehicleController.php +165 -0
- package/server/src/Http/Controllers/Internal/v1/VendorController.php +89 -0
- package/server/src/Http/Controllers/TelematicWebhookController.php +103 -19
- package/server/src/Http/Filter/FuelProviderConnectionFilter.php +33 -0
- package/server/src/Http/Filter/FuelProviderSyncRunFilter.php +28 -0
- package/server/src/Http/Filter/FuelProviderTransactionFilter.php +59 -0
- package/server/src/Http/Filter/FuelReportFilter.php +10 -0
- package/server/src/Http/Requests/CreateIssueRequest.php +4 -0
- package/server/src/Http/Requests/UpdateIssueRequest.php +4 -0
- package/server/src/Http/Resources/v1/Driver.php +15 -0
- package/server/src/Http/Resources/v1/FuelProviderConnection.php +30 -0
- package/server/src/Http/Resources/v1/FuelProviderSyncRun.php +36 -0
- package/server/src/Http/Resources/v1/FuelProviderTransaction.php +54 -0
- package/server/src/Http/Resources/v1/FuelReport.php +28 -22
- package/server/src/Http/Resources/v1/Index/Driver.php +26 -20
- package/server/src/Http/Resources/v1/Index/Order.php +12 -9
- package/server/src/Http/Resources/v1/Index/Vehicle.php +29 -22
- package/server/src/Http/Resources/v1/Issue.php +25 -0
- package/server/src/Http/Resources/v1/Order.php +20 -18
- package/server/src/Http/Resources/v1/Vehicle.php +17 -0
- package/server/src/Http/Resources/v1/VehicleWithoutDriver.php +2 -0
- package/server/src/Jobs/SyncFuelProviderTransactionsJob.php +57 -0
- package/server/src/Jobs/SyncTelematicDevicesJob.php +36 -6
- package/server/src/Jobs/TestTelematicConnectionJob.php +9 -22
- package/server/src/Mail/CustomerCredentialsMail.php +5 -6
- package/server/src/Models/Asset.php +2 -1
- package/server/src/Models/Contact.php +32 -52
- package/server/src/Models/Device.php +27 -4
- package/server/src/Models/DeviceEvent.php +40 -3
- package/server/src/Models/Driver.php +2 -1
- package/server/src/Models/Equipment.php +2 -1
- package/server/src/Models/Fleet.php +2 -1
- package/server/src/Models/FuelProviderConnection.php +60 -0
- package/server/src/Models/FuelProviderSyncRun.php +58 -0
- package/server/src/Models/FuelProviderTransaction.php +119 -0
- package/server/src/Models/FuelReport.php +16 -1
- package/server/src/Models/Issue.php +47 -6
- package/server/src/Models/Order.php +33 -6
- package/server/src/Models/Part.php +2 -1
- package/server/src/Models/Sensor.php +21 -4
- package/server/src/Models/ServiceArea.php +1 -1
- package/server/src/Models/ServiceRate.php +39 -2
- package/server/src/Models/Vehicle.php +14 -2
- package/server/src/Models/Vendor.php +2 -1
- package/server/src/Models/VendorPersonnel.php +10 -1
- package/server/src/Models/Zone.php +1 -1
- package/server/src/Observers/PurchaseRateObserver.php +20 -0
- package/server/src/Observers/ZoneObserver.php +56 -0
- package/server/src/Providers/FleetOpsServiceProvider.php +11 -0
- package/server/src/Support/Analytics/FuelProviderSummary.php +42 -0
- package/server/src/Support/Analytics/TopDrivers.php +9 -1
- package/server/src/Support/FuelProviders/FuelProviderDescriptor.php +55 -0
- package/server/src/Support/FuelProviders/FuelProviderRegistry.php +75 -0
- package/server/src/Support/FuelProviders/FuelProviderService.php +447 -0
- package/server/src/Support/FuelProviders/Providers/AbstractFuelProvider.php +98 -0
- package/server/src/Support/FuelProviders/Providers/PetroAppFuelProvider.php +167 -0
- package/server/src/Support/GettingStarted.php +144 -0
- package/server/src/Support/PlaceSearch.php +282 -0
- package/server/src/Support/ResolvesOrderServiceStops.php +22 -12
- package/server/src/Support/Telematics/Providers/AbstractProvider.php +27 -6
- package/server/src/Support/Telematics/Providers/AfaqyProvider.php +55 -26
- package/server/src/Support/Telematics/Providers/FlespiProvider.php +1 -0
- package/server/src/Support/Telematics/Providers/GeotabProvider.php +1 -0
- package/server/src/Support/Telematics/Providers/SafeeProvider.php +32 -22
- package/server/src/Support/Telematics/Providers/SamsaraProvider.php +3 -1
- package/server/src/Support/Telematics/TelematicService.php +340 -21
- package/server/src/routes.php +74 -5
- package/server/tests/AnalyticsRoutesTest.php +8 -0
- package/server/tests/CustomerContactIdentitySafetyTest.php +41 -0
- package/server/tests/DriverVehicleStatusDefaultTest.php +2 -2
- package/server/tests/FuelProviderRegistryTest.php +416 -0
- package/server/tests/GettingStartedStatusTest.php +21 -0
- package/server/tests/OrderActivityFlowRegressionTest.php +116 -0
- package/server/tests/ServiceAreaZoneApiShapeTest.php +44 -0
- package/server/tests/ServiceRateAlgorithmWeightVariablesTest.php +44 -0
- package/server/tests/TelematicsHardeningTest.php +268 -0
- package/server/tests/VehicleDriverAssignmentTest.php +51 -0
- package/translations/ar-ae.yml +31 -0
- package/translations/bg-bg.yaml +81 -0
- package/translations/en-us.yaml +94 -0
- package/translations/es-pa.yaml +81 -0
- package/translations/fr-fr.yaml +81 -0
- package/translations/mn-mn.yaml +81 -0
- package/translations/pt-br.yaml +81 -0
- package/translations/ru-ru.yaml +81 -0
- package/translations/vi-vn.yaml +106 -0
- package/addon/controllers/connectivity/telematics/index/details/devices.js +0 -3
- package/addon/controllers/connectivity/telematics/index/details/events.js +0 -3
- package/addon/controllers/connectivity/telematics/index/details/index.js +0 -3
- package/addon/controllers/connectivity/telematics/index/details/sensors.js +0 -3
- package/addon/controllers/connectivity/telematics/index/details.js +0 -24
- package/addon/routes/connectivity/telematics/index/details/devices.js +0 -3
- package/addon/routes/connectivity/telematics/index/details/events.js +0 -3
- package/addon/routes/connectivity/telematics/index/details/index.js +0 -3
- package/addon/routes/connectivity/telematics/index/details/sensors.js +0 -3
- package/addon/routes/connectivity/telematics/index/new.js +0 -3
- 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/index/details.hbs +0 -14
- package/addon/templates/connectivity/telematics/index/edit.hbs +0 -12
- package/addon/templates/connectivity/telematics/index/new.hbs +0 -12
- package/app/controllers/connectivity/telematics/index/details/events.js +0 -1
- package/app/controllers/connectivity/telematics/index/details/sensors.js +0 -1
- package/app/routes/connectivity/telematics/index/details/sensors.js +0 -1
- package/app/templates/connectivity/telematics/index/details/sensors.js +0 -1
|
@@ -11,12 +11,17 @@ export default class CustomerFormComponent extends Component {
|
|
|
11
11
|
@service currentUser;
|
|
12
12
|
@service notifications;
|
|
13
13
|
@service modalsManager;
|
|
14
|
+
@service('universe/extension-manager') extensionManager;
|
|
15
|
+
|
|
14
16
|
@tracked userAccountActionButtons = [
|
|
15
17
|
{
|
|
16
18
|
icon: 'user-plus',
|
|
17
19
|
size: 'xs',
|
|
18
20
|
permission: 'iam create user',
|
|
19
|
-
onClick: () => {
|
|
21
|
+
onClick: async () => {
|
|
22
|
+
// Load IAM engine for user-form modal component
|
|
23
|
+
await this.extensionManager.ensureEngineLoaded('@fleetbase/iam-engine');
|
|
24
|
+
|
|
20
25
|
const user = this.store.createRecord('user', {
|
|
21
26
|
status: 'pending',
|
|
22
27
|
type: 'user',
|
|
@@ -61,6 +66,27 @@ export default class CustomerFormComponent extends Component {
|
|
|
61
66
|
},
|
|
62
67
|
];
|
|
63
68
|
|
|
69
|
+
get showWelcomeEmailOption() {
|
|
70
|
+
return this.args.resource?.isNew && this.extensionManager.isInstalled('@fleetbase/customer-portal-engine');
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
get sendWelcomeEmail() {
|
|
74
|
+
return Boolean(this.args.resource?.meta?.customer_portal?.send_welcome_email);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
@action toggleWelcomeEmail(value = !this.sendWelcomeEmail) {
|
|
78
|
+
const meta = this.args.resource.meta ?? {};
|
|
79
|
+
const customerPortal = meta.customer_portal ?? {};
|
|
80
|
+
|
|
81
|
+
this.args.resource.set('meta', {
|
|
82
|
+
...meta,
|
|
83
|
+
customer_portal: {
|
|
84
|
+
...customerPortal,
|
|
85
|
+
send_welcome_email: value,
|
|
86
|
+
},
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
|
|
64
90
|
@action selectPlace(place) {
|
|
65
91
|
if (!place) return;
|
|
66
92
|
this.args.resource.setProperties({
|
|
@@ -121,6 +121,7 @@
|
|
|
121
121
|
<Button @helpText="View Label" @icon="print" @onClick={{this.viewOrderLabel}} />
|
|
122
122
|
<Button @helpText="View Route" @icon="route" @onClick={{this.locateOrderRoute}} />
|
|
123
123
|
<Button @helpText="Locate Driver" @icon="truck" @onClick={{this.locateDriver}} @disabled={{not order.has_driver_assigned}} />
|
|
124
|
+
<Button @helpText="Cancel Order" @icon="ban" @onClick={{this.cancelOrder}} @disabled={{or order.isCompleted order.isCanceled}} />
|
|
124
125
|
</div>
|
|
125
126
|
</div>
|
|
126
127
|
</div>
|
|
@@ -161,6 +162,53 @@
|
|
|
161
162
|
</div>
|
|
162
163
|
</div>
|
|
163
164
|
<div class="customer-order-details-seperator"></div>
|
|
165
|
+
<div>
|
|
166
|
+
<div class="mb-2 ml-1">
|
|
167
|
+
<h1 class="font-bold text-sm">Delivery Options:</h1>
|
|
168
|
+
</div>
|
|
169
|
+
<div class="grid grid-cols-1 lg:grid-cols-2 gap-2">
|
|
170
|
+
<InputGroup @name="Scheduled At" @type="datetime-local" @value={{this.scheduledAt}} />
|
|
171
|
+
<div class="flex items-end">
|
|
172
|
+
<Button @type="primary" @icon="calendar" @text="Reschedule" @onClick={{this.rescheduleOrder}} @disabled={{or order.isCompleted order.isCanceled}} />
|
|
173
|
+
</div>
|
|
174
|
+
<InputGroup @name="Access Notes">
|
|
175
|
+
<Input
|
|
176
|
+
@value={{this.deliveryInstructions.access_notes}}
|
|
177
|
+
class="form-input w-full"
|
|
178
|
+
placeholder="Gate code, loading dock, reception notes"
|
|
179
|
+
{{on "input" (fn this.updateDeliveryInstruction "access_notes")}}
|
|
180
|
+
/>
|
|
181
|
+
</InputGroup>
|
|
182
|
+
<InputGroup @name="Safe Place">
|
|
183
|
+
<Input
|
|
184
|
+
@value={{this.deliveryInstructions.safe_place}}
|
|
185
|
+
class="form-input w-full"
|
|
186
|
+
placeholder="Leave-at-door or safe-place instructions"
|
|
187
|
+
{{on "input" (fn this.updateDeliveryInstruction "safe_place")}}
|
|
188
|
+
/>
|
|
189
|
+
</InputGroup>
|
|
190
|
+
<InputGroup @name="Contact Phone">
|
|
191
|
+
<Input
|
|
192
|
+
@value={{this.deliveryInstructions.contact_phone}}
|
|
193
|
+
class="form-input w-full"
|
|
194
|
+
placeholder="Delivery contact phone"
|
|
195
|
+
{{on "input" (fn this.updateDeliveryInstruction "contact_phone")}}
|
|
196
|
+
/>
|
|
197
|
+
</InputGroup>
|
|
198
|
+
<InputGroup @name="Special Handling">
|
|
199
|
+
<Input
|
|
200
|
+
@value={{this.deliveryInstructions.special_handling}}
|
|
201
|
+
class="form-input w-full"
|
|
202
|
+
placeholder="Fragile, temperature, access, or handling notes"
|
|
203
|
+
{{on "input" (fn this.updateDeliveryInstruction "special_handling")}}
|
|
204
|
+
/>
|
|
205
|
+
</InputGroup>
|
|
206
|
+
</div>
|
|
207
|
+
<div class="mt-2">
|
|
208
|
+
<Button @icon="save" @text="Save Delivery Instructions" @onClick={{this.saveDeliveryInstructions}} @disabled={{or order.isCompleted order.isCanceled}} />
|
|
209
|
+
</div>
|
|
210
|
+
</div>
|
|
211
|
+
<div class="customer-order-details-seperator"></div>
|
|
164
212
|
<div>
|
|
165
213
|
<div class="mb-2 ml-1">
|
|
166
214
|
<h1 class="font-bold text-sm">Items:</h1>
|
|
@@ -39,6 +39,8 @@ export default class CustomerOrdersComponent extends Component {
|
|
|
39
39
|
@tracked route;
|
|
40
40
|
@tracked query;
|
|
41
41
|
@tracked tileSourceUrl = 'https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png';
|
|
42
|
+
@tracked scheduledAt;
|
|
43
|
+
@tracked deliveryInstructions = {};
|
|
42
44
|
|
|
43
45
|
get modalsManager() {
|
|
44
46
|
const owner = getOwner(this);
|
|
@@ -71,7 +73,7 @@ export default class CustomerOrdersComponent extends Component {
|
|
|
71
73
|
this.query = query;
|
|
72
74
|
|
|
73
75
|
try {
|
|
74
|
-
this.orders = yield this.store.query('order', { customer: this.
|
|
76
|
+
this.orders = yield this.store.query('order', { customer: this.customerAccountId, customer_type: this.customerTypeParam, ...params, query });
|
|
75
77
|
this.orders = this.orders.toArray().filter((_) => !_.isNew);
|
|
76
78
|
this.restoreSelectedOrder();
|
|
77
79
|
} catch (error) {
|
|
@@ -87,7 +89,7 @@ export default class CustomerOrdersComponent extends Component {
|
|
|
87
89
|
yield timeout(300);
|
|
88
90
|
|
|
89
91
|
try {
|
|
90
|
-
this.orders = yield this.store.query('order', { query, with_tracker_data: true });
|
|
92
|
+
this.orders = yield this.store.query('order', { query, customer: this.customerAccountId, customer_type: this.customerTypeParam, with_tracker_data: true });
|
|
91
93
|
} catch (error) {
|
|
92
94
|
this.notifications.serverError(error);
|
|
93
95
|
}
|
|
@@ -97,9 +99,9 @@ export default class CustomerOrdersComponent extends Component {
|
|
|
97
99
|
this.unselectOrder();
|
|
98
100
|
this.newOrder = this.store.createRecord('order', {
|
|
99
101
|
type: 'transport',
|
|
100
|
-
customer_uuid: this.
|
|
101
|
-
customer_type:
|
|
102
|
-
customer: this.customerSession.
|
|
102
|
+
customer_uuid: this.customerAccountId,
|
|
103
|
+
customer_type: this.customerTypeParam,
|
|
104
|
+
customer: this.customerSession.getAccount(),
|
|
103
105
|
meta: [],
|
|
104
106
|
});
|
|
105
107
|
this.urlSearchParams.addParamToCurrentUrl('creating', 1);
|
|
@@ -135,6 +137,8 @@ export default class CustomerOrdersComponent extends Component {
|
|
|
135
137
|
|
|
136
138
|
@action viewOrder(order, options = { resetOrderRoute: false }) {
|
|
137
139
|
this.selectedOrder = order;
|
|
140
|
+
this.scheduledAt = order.scheduled_at;
|
|
141
|
+
this.deliveryInstructions = order.meta?.customer_portal?.delivery_instructions ?? {};
|
|
138
142
|
// start loading order tracking activity
|
|
139
143
|
order.loadTrackingActivity();
|
|
140
144
|
this.urlSearchParams.addParamToCurrentUrl('order', order.public_id);
|
|
@@ -340,11 +344,69 @@ export default class CustomerOrdersComponent extends Component {
|
|
|
340
344
|
}
|
|
341
345
|
}
|
|
342
346
|
|
|
347
|
+
@action async cancelOrder() {
|
|
348
|
+
if (!this.selectedOrder) {
|
|
349
|
+
return;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
try {
|
|
353
|
+
const response = await this.fetch.post(`customer-portal/orders/${this.selectedOrder.public_id}/cancel`, {}, { namespace: 'fleet-ops/int/v1' });
|
|
354
|
+
this.selectedOrder.set('status', response.order?.status ?? 'canceled');
|
|
355
|
+
this.notifications.success('Order canceled.');
|
|
356
|
+
} catch (error) {
|
|
357
|
+
this.notifications.serverError(error);
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
@action async rescheduleOrder() {
|
|
362
|
+
if (!this.selectedOrder || !this.scheduledAt) {
|
|
363
|
+
return;
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
try {
|
|
367
|
+
const response = await this.fetch.post(
|
|
368
|
+
`customer-portal/orders/${this.selectedOrder.public_id}/reschedule`,
|
|
369
|
+
{ scheduled_at: this.scheduledAt },
|
|
370
|
+
{ namespace: 'fleet-ops/int/v1' }
|
|
371
|
+
);
|
|
372
|
+
this.selectedOrder.set('scheduled_at', response.order?.scheduled_at ?? this.scheduledAt);
|
|
373
|
+
this.notifications.success('Order rescheduled.');
|
|
374
|
+
} catch (error) {
|
|
375
|
+
this.notifications.serverError(error);
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
@action updateDeliveryInstruction(key, event) {
|
|
380
|
+
this.deliveryInstructions = { ...this.deliveryInstructions, [key]: event.target.value };
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
@action async saveDeliveryInstructions() {
|
|
384
|
+
if (!this.selectedOrder) {
|
|
385
|
+
return;
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
try {
|
|
389
|
+
await this.fetch.post(`customer-portal/orders/${this.selectedOrder.public_id}/delivery-instructions`, this.deliveryInstructions, { namespace: 'fleet-ops/int/v1' });
|
|
390
|
+
this.notifications.success('Delivery instructions saved.');
|
|
391
|
+
} catch (error) {
|
|
392
|
+
this.notifications.serverError(error);
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
|
|
343
396
|
isCreatingOrder() {
|
|
344
397
|
const isCreating = this.urlSearchParams.get('creating');
|
|
345
398
|
return isCreating === '1' || isCreating === 1;
|
|
346
399
|
}
|
|
347
400
|
|
|
401
|
+
get customerAccountId() {
|
|
402
|
+
return this.customerSession.get('uuid') || this.customerSession.get('id');
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
get customerTypeParam() {
|
|
406
|
+
const customerType = this.customerSession.get('customer_type', 'contact');
|
|
407
|
+
return customerType === 'vendor' ? 'fleet-ops:vendor' : 'fleet-ops:contact';
|
|
408
|
+
}
|
|
409
|
+
|
|
348
410
|
cannotRouteWaypoints(waypoints = []) {
|
|
349
411
|
return !this.map || !isArray(waypoints) || waypoints.length < 2;
|
|
350
412
|
}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
<div class="flex flex-row items-center justify-between mb-4 px-3 pt-2">
|
|
3
3
|
<div></div>
|
|
4
4
|
<div>
|
|
5
|
-
<Button @icon="plus" @text="
|
|
5
|
+
<Button @icon="plus" @text={{t "device.actions.attach-device"}} @onClick={{this.addDevice}} @disabled={{not @resource}} />
|
|
6
6
|
</div>
|
|
7
7
|
</div>
|
|
8
8
|
<div>
|
|
@@ -10,20 +10,19 @@
|
|
|
10
10
|
<div class="flex flex-row justify-between px-3 py-4 border-t border-gray-200 dark:border-gray-700">
|
|
11
11
|
<Device::Pill @device={{device}} />
|
|
12
12
|
<div>
|
|
13
|
-
<Button @type="danger" @icon="times" @text="
|
|
13
|
+
<Button @type="danger" @icon="times" @text={{t "device.actions.detach-from-vehicle"}} @size="xs" @onClick={{fn this.removeDevice device}} />
|
|
14
14
|
</div>
|
|
15
15
|
</div>
|
|
16
16
|
{{else}}
|
|
17
17
|
<div class="empty-state bg-white dark:bg-gray-800 rounded-lg shadow-sm p-12 text-center">
|
|
18
18
|
<FaIcon @icon="hard-drive" @size="2x" class="text-gray-400 mb-2" />
|
|
19
19
|
<h3 class="text-base font-semibold text-gray-700 dark:text-gray-300">
|
|
20
|
-
|
|
20
|
+
{{t "device.prompts.no-devices-attached-title"}}
|
|
21
21
|
</h3>
|
|
22
22
|
<p class="text-sm text-gray-500 dark:text-gray-400">
|
|
23
|
-
|
|
24
|
-
{{get-model-name @resource}}
|
|
23
|
+
{{t "device.prompts.no-devices-attached-body" resourceType=(get-model-name @resource)}}
|
|
25
24
|
</p>
|
|
26
25
|
</div>
|
|
27
26
|
{{/each}}
|
|
28
27
|
</div>
|
|
29
|
-
</div>
|
|
28
|
+
</div>
|
|
@@ -8,8 +8,10 @@ import getModelName from '@fleetbase/ember-core/utils/get-model-name';
|
|
|
8
8
|
|
|
9
9
|
export default class DeviceManagerComponent extends Component {
|
|
10
10
|
@service store;
|
|
11
|
+
@service fetch;
|
|
11
12
|
@service modalsManager;
|
|
12
13
|
@service notifications;
|
|
14
|
+
@service intl;
|
|
13
15
|
@tracked devices = [];
|
|
14
16
|
|
|
15
17
|
get resourceName() {
|
|
@@ -33,24 +35,19 @@ export default class DeviceManagerComponent extends Component {
|
|
|
33
35
|
|
|
34
36
|
@action addDevice() {
|
|
35
37
|
this.modalsManager.show('modals/attach-device', {
|
|
36
|
-
title: '
|
|
37
|
-
acceptButtonText: '
|
|
38
|
+
title: this.intl.t('device.prompts.select-device-to-attach-title', { resourceName: this.resourceName }),
|
|
39
|
+
acceptButtonText: this.intl.t('device.prompts.confirm-attach-device'),
|
|
38
40
|
selectedDevice: null,
|
|
39
41
|
confirm: async (modal) => {
|
|
40
42
|
const selectedDevice = modal.getOption('selectedDevice');
|
|
41
43
|
if (!selectedDevice) return;
|
|
42
44
|
|
|
43
|
-
selectedDevice.setProperties({
|
|
44
|
-
attachable_uuid: this.args.resource.id,
|
|
45
|
-
attachable_type: `fleet-ops:${getModelName(this.args.resource)}`,
|
|
46
|
-
});
|
|
47
|
-
|
|
48
45
|
modal.startLoading();
|
|
49
46
|
|
|
50
47
|
try {
|
|
51
|
-
await selectedDevice.
|
|
48
|
+
await this.fetch.post(`vehicles/${this.args.resource.id}/attach-device`, { device: selectedDevice.id });
|
|
52
49
|
await this.loadDevices.perform();
|
|
53
|
-
this.notifications.success('
|
|
50
|
+
this.notifications.success(this.intl.t('device.prompts.attach-device-success'));
|
|
54
51
|
modal.done();
|
|
55
52
|
} catch (err) {
|
|
56
53
|
this.notifications.serverError(err);
|
|
@@ -61,18 +58,18 @@ export default class DeviceManagerComponent extends Component {
|
|
|
61
58
|
}
|
|
62
59
|
|
|
63
60
|
@action removeDevice(device) {
|
|
61
|
+
const deviceName = device.displayName ?? device.name ?? device.device_id ?? this.intl.t('resource.device');
|
|
62
|
+
|
|
64
63
|
this.modalsManager.confirm({
|
|
65
|
-
title:
|
|
66
|
-
body:
|
|
64
|
+
title: this.intl.t('device.prompts.detach-from-resource-title', { deviceName, resourceName: this.resourceName }),
|
|
65
|
+
body: this.intl.t('device.prompts.detach-from-resource-body', { deviceName, resourceName: this.resourceName, resourceType: getModelName(this.args.resource) }),
|
|
67
66
|
confirm: async (modal) => {
|
|
68
67
|
modal.startLoading();
|
|
69
68
|
|
|
70
|
-
device.setProperties({ attachable_uuid: null, attachable_type: null });
|
|
71
|
-
|
|
72
69
|
try {
|
|
73
|
-
await device.
|
|
70
|
+
await this.fetch.post(`vehicles/${this.args.resource.id}/detach-device`, { device: device.id });
|
|
74
71
|
await this.loadDevices.perform();
|
|
75
|
-
this.notifications.success('
|
|
72
|
+
this.notifications.success(this.intl.t('device.prompts.detach-from-resource-success', { deviceName, resourceName: this.resourceName }));
|
|
76
73
|
modal.done();
|
|
77
74
|
} catch (error) {
|
|
78
75
|
this.notifications.serverError(error);
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
</div>
|
|
33
33
|
<div class="field-info-container">
|
|
34
34
|
<div class="field-name">{{t "driver.fields.license-expiry"}}</div>
|
|
35
|
-
<div class="field-value">{{n-a @resource.license_expiry}}</div>
|
|
35
|
+
<div class="field-value">{{n-a (format-date-fns @resource.license_expiry)}}</div>
|
|
36
36
|
</div>
|
|
37
37
|
<div class="field-info-container">
|
|
38
38
|
<div class="field-name">{{t "resource.vendor"}}</div>
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
@modelName="user"
|
|
7
7
|
@selectedModel={{@resource.user}}
|
|
8
8
|
@placeholder={{t "driver.fields.select-user"}}
|
|
9
|
-
@query={{hash doesnt_have_driver=true}}
|
|
9
|
+
@query={{hash doesnt_have_driver=true can_be_driver=true}}
|
|
10
10
|
@triggerClass="form-select form-input"
|
|
11
11
|
@infiniteScroll={{false}}
|
|
12
12
|
@renderInPlace={{true}}
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
<div class="flex min-h-0 flex-1 flex-col" ...attributes>
|
|
2
|
+
<div class="min-h-0 flex-1 overflow-y-auto px-4 py-4 md:px-6">
|
|
3
|
+
<div class="mx-auto flex w-full max-w-6xl flex-col gap-4">
|
|
4
|
+
<section class="rounded-md border border-gray-200 bg-white p-3 shadow-sm dark:border-gray-700 dark:bg-gray-800">
|
|
5
|
+
<div class="grid grid-cols-1 gap-2 md:grid-cols-5">
|
|
6
|
+
{{#each this.setupSteps as |step index|}}
|
|
7
|
+
<button type="button" class="rounded-md border p-2 text-left transition {{if step.active 'border-blue-500 bg-blue-50 dark:border-blue-400 dark:bg-blue-500/10' 'border-gray-200 bg-white hover:border-gray-300 dark:border-gray-700 dark:bg-gray-800 dark:hover:border-gray-600'}}" {{on "click" (fn this.goToStep index)}}>
|
|
8
|
+
<div class="flex items-center gap-2">
|
|
9
|
+
<div class="flex h-7 w-7 flex-shrink-0 items-center justify-center rounded-md text-xs {{if step.active 'bg-blue-600 text-white dark:bg-blue-500' (if step.complete 'bg-green-100 text-green-700 dark:bg-green-900/30 dark:text-green-300' 'bg-gray-100 text-gray-500 dark:bg-gray-700 dark:text-gray-300')}}">
|
|
10
|
+
<FaIcon @icon={{if step.complete "check" step.icon}} />
|
|
11
|
+
</div>
|
|
12
|
+
<div class="min-w-0">
|
|
13
|
+
<div class="text-[10px] font-semibold uppercase text-gray-400 dark:text-gray-500">{{add index 1}}</div>
|
|
14
|
+
<div class="truncate text-xs font-bold text-gray-900 dark:text-gray-100">{{step.label}}</div>
|
|
15
|
+
</div>
|
|
16
|
+
</div>
|
|
17
|
+
</button>
|
|
18
|
+
{{/each}}
|
|
19
|
+
</div>
|
|
20
|
+
</section>
|
|
21
|
+
|
|
22
|
+
{{#if (eq this.activeStep 0)}}
|
|
23
|
+
<section class="rounded-md border border-gray-200 bg-white p-4 shadow-sm dark:border-gray-700 dark:bg-gray-800">
|
|
24
|
+
<div class="mb-3">
|
|
25
|
+
<h2 class="text-sm font-bold text-gray-900 dark:text-gray-100">Choose Fuel Integration</h2>
|
|
26
|
+
<p class="text-xs text-gray-500 dark:text-gray-300">Select the system to connect for fuel card bills, purchase transactions, station locations, or vehicle fuel identifiers.</p>
|
|
27
|
+
</div>
|
|
28
|
+
|
|
29
|
+
{{#if this.loadProviders.isRunning}}
|
|
30
|
+
<div class="flex min-h-[140px] items-center justify-center"><Spinner /></div>
|
|
31
|
+
{{else}}
|
|
32
|
+
<div class="grid grid-cols-1 gap-3 md:grid-cols-2 xl:grid-cols-4">
|
|
33
|
+
{{#each this.providerCards as |provider|}}
|
|
34
|
+
<button type="button" class="flex min-h-[148px] flex-col rounded-md border p-3 text-left transition {{if provider.selected 'border-blue-500 bg-blue-50 dark:border-blue-400 dark:bg-gray-800' 'border-gray-200 bg-white hover:border-blue-300 dark:border-gray-700 dark:bg-gray-800 dark:hover:border-blue-400'}}" {{on "click" (fn this.selectProvider provider)}}>
|
|
35
|
+
<div class="flex items-start justify-between gap-3">
|
|
36
|
+
<div class="flex min-w-0 items-center gap-2">
|
|
37
|
+
<div class="flex h-8 w-8 flex-shrink-0 items-center justify-center rounded-md bg-blue-50 text-blue-600 dark:bg-blue-900/20 dark:text-blue-300">
|
|
38
|
+
<FaIcon @icon={{or provider.icon "gas-pump"}} />
|
|
39
|
+
</div>
|
|
40
|
+
<div class="min-w-0">
|
|
41
|
+
<div class="truncate text-sm font-bold text-gray-900 dark:text-gray-100">{{provider.label}}</div>
|
|
42
|
+
<div class="truncate text-[11px] uppercase text-gray-400 dark:text-gray-500">{{provider.categoryLabel}}</div>
|
|
43
|
+
</div>
|
|
44
|
+
</div>
|
|
45
|
+
{{#if provider.selected}}
|
|
46
|
+
<Badge @status="success" @hideStatusDot={{true}}>Selected</Badge>
|
|
47
|
+
{{/if}}
|
|
48
|
+
</div>
|
|
49
|
+
<p class="mt-3 line-clamp-2 flex-1 text-xs leading-5 text-gray-500 dark:text-gray-300">{{provider.description}}</p>
|
|
50
|
+
<div class="mt-3 flex flex-wrap gap-1">
|
|
51
|
+
{{#each provider.capabilities as |capability|}}
|
|
52
|
+
<span class="rounded bg-gray-100 px-2 py-0.5 text-[11px] text-gray-600 dark:bg-gray-700 dark:text-gray-300">{{capability}}</span>
|
|
53
|
+
{{/each}}
|
|
54
|
+
</div>
|
|
55
|
+
</button>
|
|
56
|
+
{{/each}}
|
|
57
|
+
</div>
|
|
58
|
+
{{/if}}
|
|
59
|
+
</section>
|
|
60
|
+
{{else if (eq this.activeStep 1)}}
|
|
61
|
+
<section class="grid grid-cols-1 gap-4 lg:grid-cols-3">
|
|
62
|
+
<div class="rounded-md border border-gray-200 bg-white p-4 shadow-sm dark:border-gray-700 dark:bg-gray-800 lg:col-span-2">
|
|
63
|
+
<div class="mb-3">
|
|
64
|
+
<h2 class="text-sm font-bold text-gray-900 dark:text-gray-100">Credentials</h2>
|
|
65
|
+
<p class="text-xs text-gray-500 dark:text-gray-300">These credentials are stored on the connection and used to test and import provider transactions.</p>
|
|
66
|
+
</div>
|
|
67
|
+
|
|
68
|
+
{{#if this.selectedProvider}}
|
|
69
|
+
<div class="grid grid-cols-1 gap-2 lg:grid-cols-2 no-input-group-padding text-xs">
|
|
70
|
+
{{#each this.selectedProvider.required_fields as |field|}}
|
|
71
|
+
<InputGroup @name={{field.label}} @value={{get @resource.credentials field.name}} @required={{field.required}} @type={{field.type}} @helpText={{field.help_text}} {{on "input" (fn this.setCredential field)}} />
|
|
72
|
+
{{/each}}
|
|
73
|
+
</div>
|
|
74
|
+
{{else}}
|
|
75
|
+
<div class="rounded-md border border-dashed border-gray-300 p-6 text-center text-xs text-gray-500 dark:border-gray-700 dark:text-gray-300">
|
|
76
|
+
Choose a fuel integration before entering credentials.
|
|
77
|
+
</div>
|
|
78
|
+
{{/if}}
|
|
79
|
+
</div>
|
|
80
|
+
|
|
81
|
+
{{#if this.selectedProvider}}
|
|
82
|
+
<aside class="rounded-md border border-gray-200 bg-white p-4 shadow-sm dark:border-gray-700 dark:bg-gray-800">
|
|
83
|
+
<div class="flex items-start gap-3">
|
|
84
|
+
<div class="flex h-9 w-9 flex-shrink-0 items-center justify-center rounded-md bg-blue-50 text-blue-600 dark:bg-blue-900/20 dark:text-blue-300">
|
|
85
|
+
<FaIcon @icon={{or this.selectedProvider.icon "gas-pump"}} />
|
|
86
|
+
</div>
|
|
87
|
+
<div class="min-w-0">
|
|
88
|
+
<div class="truncate text-sm font-bold text-gray-900 dark:text-gray-100">{{this.selectedProvider.label}}</div>
|
|
89
|
+
<p class="mt-1 text-xs leading-5 text-gray-500 dark:text-gray-300">{{this.selectedProvider.description}}</p>
|
|
90
|
+
</div>
|
|
91
|
+
</div>
|
|
92
|
+
<div class="mt-3 flex flex-wrap gap-2">
|
|
93
|
+
{{#each this.selectedProvider.capabilities as |capability|}}
|
|
94
|
+
<Badge @status="info" @hideStatusDot={{true}}>{{capability}}</Badge>
|
|
95
|
+
{{/each}}
|
|
96
|
+
</div>
|
|
97
|
+
</aside>
|
|
98
|
+
{{/if}}
|
|
99
|
+
</section>
|
|
100
|
+
{{else if (eq this.activeStep 2)}}
|
|
101
|
+
<section class="rounded-md border border-gray-200 bg-white p-4 shadow-sm dark:border-gray-700 dark:bg-gray-800">
|
|
102
|
+
<div class="mb-3">
|
|
103
|
+
<h2 class="text-sm font-bold text-gray-900 dark:text-gray-100">Test Connection</h2>
|
|
104
|
+
<p class="text-xs text-gray-500 dark:text-gray-300">Confirm the provider accepts the credentials before saving this fuel integration.</p>
|
|
105
|
+
</div>
|
|
106
|
+
|
|
107
|
+
<div class="rounded-md border p-4 text-xs transition {{if (eq this.connectionState 'success') 'border-green-200 bg-green-50 dark:border-green-800 dark:bg-green-900/10'}} {{if (eq this.connectionState 'failed') 'border-red-200 bg-red-50 dark:border-red-800 dark:bg-red-900/10'}} {{if (eq this.connectionState 'testing') 'border-blue-200 bg-blue-50 dark:border-blue-800 dark:bg-blue-900/10'}} {{if (eq this.connectionState 'idle') 'border-dashed border-gray-300 bg-white dark:border-gray-700 dark:bg-gray-800'}}">
|
|
108
|
+
<div class="flex flex-col gap-3 md:flex-row md:items-start md:justify-between">
|
|
109
|
+
<div class="flex min-w-0 items-start gap-3">
|
|
110
|
+
<div class="flex h-9 w-9 flex-shrink-0 items-center justify-center rounded-md {{if (eq this.connectionState 'success') 'bg-green-100 text-green-700 dark:bg-green-900/40 dark:text-green-300'}} {{if (eq this.connectionState 'failed') 'bg-red-100 text-red-700 dark:bg-red-900/40 dark:text-red-300'}} {{if (eq this.connectionState 'testing') 'bg-blue-100 text-blue-700 dark:bg-blue-900/40 dark:text-blue-300 animate-pulse'}} {{if (eq this.connectionState 'idle') 'bg-gray-100 text-gray-500 dark:bg-gray-700 dark:text-gray-300'}}">
|
|
111
|
+
{{#if (eq this.connectionState "testing")}}<Spinner />{{else if (eq this.connectionState "success")}}<FaIcon @icon="check" />{{else if (eq this.connectionState "failed")}}<FaIcon @icon="triangle-exclamation" />{{else}}<FaIcon @icon="plug" />{{/if}}
|
|
112
|
+
</div>
|
|
113
|
+
<div class="min-w-0">
|
|
114
|
+
<div class="text-sm font-bold text-gray-900 dark:text-gray-100">{{this.connectionStateTitle}}</div>
|
|
115
|
+
<p class="mt-1 max-w-3xl text-xs leading-5 text-gray-600 dark:text-gray-300">{{this.connectionStateMessage}}</p>
|
|
116
|
+
{{#if this.connectionMetadataEntries.length}}
|
|
117
|
+
<div class="mt-3 flex flex-wrap gap-2">
|
|
118
|
+
{{#each this.connectionMetadataEntries as |item|}}
|
|
119
|
+
<span class="inline-flex items-center rounded-md border border-gray-200 bg-white px-2 py-1 text-[11px] text-gray-600 dark:border-gray-700 dark:bg-gray-800 dark:text-gray-300">
|
|
120
|
+
<span class="mr-1 font-semibold text-gray-900 dark:text-gray-100">{{item.label}}</span>
|
|
121
|
+
{{item.value}}
|
|
122
|
+
</span>
|
|
123
|
+
{{/each}}
|
|
124
|
+
</div>
|
|
125
|
+
{{/if}}
|
|
126
|
+
</div>
|
|
127
|
+
</div>
|
|
128
|
+
|
|
129
|
+
<Button @icon="plug" @text={{if (eq this.connectionState "success") "Test Again" "Test Connection"}} @size="xs" @isLoading={{this.testConnection.isRunning}} @disabled={{this.testConnection.isRunning}} @onClick={{perform this.testConnection}} />
|
|
130
|
+
</div>
|
|
131
|
+
|
|
132
|
+
<div class="mt-4 border-t border-gray-200 pt-3 dark:border-gray-700">
|
|
133
|
+
<div class="flex flex-col gap-2 md:flex-row md:items-center md:justify-between">
|
|
134
|
+
<button type="button" class="inline-flex items-center gap-2 text-xs font-semibold text-blue-600 hover:text-blue-700 dark:text-blue-300 dark:hover:text-blue-200" {{on "click" (fn (mut this.showDiagnostics) (not this.showDiagnostics))}}>
|
|
135
|
+
<FaIcon @icon={{if this.showDiagnostics "chevron-up" "chevron-down"}} class="text-[10px]" />
|
|
136
|
+
<span>{{if this.showDiagnostics "Hide diagnostics" "Show diagnostics"}}</span>
|
|
137
|
+
</button>
|
|
138
|
+
|
|
139
|
+
{{#if this.showDiagnostics}}
|
|
140
|
+
<Button @icon="copy" @text="Copy diagnostics" @size="xs" @onClick={{this.copyDiagnostics}} />
|
|
141
|
+
{{/if}}
|
|
142
|
+
</div>
|
|
143
|
+
|
|
144
|
+
{{#if this.showDiagnostics}}
|
|
145
|
+
<div class="mt-3 max-h-56 overflow-y-auto rounded-md border border-gray-800 bg-gray-900 p-3 font-mono text-[11px] leading-5 shadow-inner dark:border-gray-700 dark:bg-gray-900">
|
|
146
|
+
{{#each this.diagnosticEntries as |entry|}}
|
|
147
|
+
<div class="flex gap-3 {{if (eq entry.tone 'success') 'text-green-300'}} {{if (eq entry.tone 'danger') 'text-red-300'}} {{if (eq entry.tone 'info') 'text-blue-300'}}">
|
|
148
|
+
<span class="flex-shrink-0 text-gray-500">[{{entry.time}}]</span>
|
|
149
|
+
<span class="min-w-0 break-words">{{entry.text}}</span>
|
|
150
|
+
</div>
|
|
151
|
+
{{/each}}
|
|
152
|
+
</div>
|
|
153
|
+
{{/if}}
|
|
154
|
+
</div>
|
|
155
|
+
</div>
|
|
156
|
+
</section>
|
|
157
|
+
{{else if (eq this.activeStep 3)}}
|
|
158
|
+
<section class="rounded-md border border-gray-200 bg-white p-4 shadow-sm dark:border-gray-700 dark:bg-gray-800">
|
|
159
|
+
<div class="mb-3">
|
|
160
|
+
<h2 class="text-sm font-bold text-gray-900 dark:text-gray-100">Sync Settings</h2>
|
|
161
|
+
<p class="text-xs text-gray-500 dark:text-gray-300">Choose how fuel transactions are imported from this system.</p>
|
|
162
|
+
</div>
|
|
163
|
+
|
|
164
|
+
<div class="grid grid-cols-1 gap-3 lg:grid-cols-2 no-input-group-padding text-xs">
|
|
165
|
+
<InputGroup @name="Integration name" @value={{@resource.name}} {{on "input" this.setName}} />
|
|
166
|
+
<InputGroup @name="Default sync window" @helpText="Number of days to import when no explicit date range is provided.">
|
|
167
|
+
<Input @type="number" min="1" max="90" class="form-input w-full" @value={{this.syncSettings.window_days}} {{on "input" (fn this.setSyncSetting "window_days")}} />
|
|
168
|
+
</InputGroup>
|
|
169
|
+
<div class="rounded-md border border-gray-200 p-3 dark:border-gray-700 lg:col-span-2">
|
|
170
|
+
<Checkbox @value={{this.syncSettings.auto_create_fuel_reports}} @label="Create Fuel Reports after vehicle match" @onToggle={{fn this.setSyncSetting "auto_create_fuel_reports"}} @alignItems="center" @labelClass="mb-0i" />
|
|
171
|
+
<p class="mt-2 text-xs leading-5 text-gray-500 dark:text-gray-300">Provider bills remain in Fuel Transactions. Fuel Reports are created only when a transaction is matched to a vehicle.</p>
|
|
172
|
+
</div>
|
|
173
|
+
</div>
|
|
174
|
+
</section>
|
|
175
|
+
{{else}}
|
|
176
|
+
<section class="rounded-md border border-gray-200 bg-white p-4 shadow-sm dark:border-gray-700 dark:bg-gray-800">
|
|
177
|
+
<div class="mb-3">
|
|
178
|
+
<h2 class="text-sm font-bold text-gray-900 dark:text-gray-100">Vehicle Matching Priority</h2>
|
|
179
|
+
<p class="text-xs leading-5 text-gray-500 dark:text-gray-300">Choose which provider identifiers should be used for automatic matching and put the most reliable identifier first.</p>
|
|
180
|
+
</div>
|
|
181
|
+
|
|
182
|
+
<FuelIntegration::MatchingPriority @order={{this.matchingOrder}} @onChange={{this.setMatchingOrder}} @editable={{true}} />
|
|
183
|
+
</section>
|
|
184
|
+
{{/if}}
|
|
185
|
+
</div>
|
|
186
|
+
</div>
|
|
187
|
+
|
|
188
|
+
<div class="flex flex-shrink-0 items-center justify-between border-t border-gray-200 bg-white px-4 py-3 dark:border-gray-700 dark:bg-gray-900 md:px-6">
|
|
189
|
+
<div class="text-xs text-gray-500 dark:text-gray-300">{{@footerHelp}}</div>
|
|
190
|
+
<div class="flex items-center gap-2">
|
|
191
|
+
<Button @icon="arrow-left" @text="Back" @size="sm" @disabled={{eq this.activeStep 0}} @onClick={{this.previousStep}} />
|
|
192
|
+
{{#if (eq this.activeStep 4)}}
|
|
193
|
+
<Button @icon="save" @text={{@saveLabel}} @type="primary" @size="sm" @isLoading={{@isSaving}} @disabled={{@isSaving}} @onClick={{@onSave}} />
|
|
194
|
+
{{else}}
|
|
195
|
+
<Button @icon="arrow-right" @text="Next" @type="primary" @size="sm" @onClick={{this.nextStep}} />
|
|
196
|
+
{{/if}}
|
|
197
|
+
<Button @icon="times" @text="Cancel" @size="sm" @onClick={{@onCancel}} />
|
|
198
|
+
</div>
|
|
199
|
+
</div>
|
|
200
|
+
</div>
|