@fleetbase/fleetops-engine 0.6.63 → 0.6.65
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/RELEASE.md +7 -6
- package/addon/components/attachment-list.hbs +65 -0
- package/addon/components/attachment-list.js +8 -0
- package/addon/components/cell/attached-vehicle.hbs +1 -1
- package/addon/components/cell/attached-vehicle.js +3 -3
- package/addon/components/cell/driver-identity.js +4 -4
- package/addon/components/cell/driver-name.hbs +1 -1
- package/addon/components/cell/translated-value.hbs +9 -0
- package/addon/components/cell/translated-value.js +57 -0
- package/addon/components/contact/card.hbs +58 -0
- package/addon/components/contact/card.js +19 -0
- package/addon/components/contact/form.hbs +1 -1
- package/addon/components/contact/panel-header.hbs +1 -1
- package/addon/components/customer/form.hbs +2 -2
- package/addon/components/device/manager.hbs +26 -28
- package/addon/components/device/manager.js +28 -2
- package/addon/components/device/panel-tabs/vehicle.hbs +13 -13
- package/addon/components/device/panel-tabs/vehicle.js +8 -0
- package/addon/components/driver/card.hbs +24 -13
- package/addon/components/driver/card.js +20 -6
- package/addon/components/driver/form.hbs +3 -3
- package/addon/components/driver/panel-header.hbs +2 -2
- package/addon/components/driver/pill.hbs +2 -2
- package/addon/components/equipment/form.js +11 -4
- package/addon/components/equipment/pill.hbs +20 -0
- package/addon/components/equipment/pill.js +3 -0
- package/addon/components/filter/multi-model.hbs +19 -0
- package/addon/components/filter/multi-model.js +90 -0
- package/addon/components/fleet/driver-listing.hbs +1 -1
- package/addon/components/fleet/vehicle-listing.hbs +1 -1
- package/addon/components/fleet-panel/driver-listing.hbs +1 -1
- package/addon/components/fleet-panel/vehicle-listing.hbs +1 -1
- package/addon/components/layout/fleet-ops-sidebar.js +9 -7
- package/addon/components/maintenance/form.js +12 -4
- package/addon/components/maintenance-schedule/form.js +13 -7
- package/addon/components/map/leaflet-live-map.hbs +52 -0
- package/addon/components/map/order-list-overlay/order.hbs +4 -4
- package/addon/components/modals/attach-equipment.hbs +22 -0
- package/addon/components/modals/attach-equipment.js +3 -0
- package/addon/components/modals/attach-telematic-device.hbs +13 -8
- package/addon/components/modals/attach-telematic-device.js +11 -1
- package/addon/components/modals/attach-trailer.hbs +30 -0
- package/addon/components/modals/attach-trailer.js +3 -0
- package/addon/components/modals/contact-form.hbs +2 -2
- package/addon/components/modals/convert-customer-to-vendor.hbs +1 -1
- package/addon/components/modals/driver-form.hbs +2 -2
- package/addon/components/modals/select-trailer.hbs +35 -0
- package/addon/components/modals/select-trailer.js +3 -0
- package/addon/components/modals/vehicle-form.hbs +2 -2
- package/addon/components/orchestrator/resource-panel.hbs +2 -2
- package/addon/components/order/customer-avatar-stack.hbs +2 -2
- package/addon/components/order/details/detail.hbs +4 -4
- package/addon/components/order/details/payload.hbs +2 -2
- package/addon/components/order/kanban-card.hbs +4 -4
- package/addon/components/order-list-overlay/order.hbs +4 -4
- package/addon/components/trailer/card.hbs +68 -0
- package/addon/components/trailer/card.js +22 -0
- package/addon/components/trailer/details/connections.hbs +57 -0
- package/addon/components/trailer/details/connections.js +59 -0
- package/addon/components/trailer/details/equipment.hbs +25 -0
- package/addon/components/trailer/details/equipment.js +52 -0
- package/addon/components/trailer/details/maintenance-history.hbs +47 -0
- package/addon/components/trailer/details/maintenance-history.js +40 -0
- package/addon/components/trailer/details/schedules.hbs +45 -0
- package/addon/components/trailer/details/schedules.js +40 -0
- package/addon/components/trailer/details/work-orders.hbs +47 -0
- package/addon/components/trailer/details/work-orders.js +40 -0
- package/addon/components/trailer/details.hbs +399 -0
- package/addon/components/trailer/details.js +118 -0
- package/addon/components/trailer/form.hbs +447 -0
- package/addon/components/trailer/form.js +165 -0
- package/addon/components/trailer/panel-header.hbs +45 -0
- package/addon/components/trailer/panel-header.js +3 -0
- package/addon/components/trailer/pill.hbs +21 -0
- package/addon/components/trailer/pill.js +3 -0
- package/addon/components/vehicle/card.hbs +42 -11
- package/addon/components/vehicle/card.js +31 -0
- package/addon/components/vehicle/details/equipment.hbs +25 -0
- package/addon/components/vehicle/details/equipment.js +55 -0
- package/addon/components/vehicle/details/trailers.hbs +35 -0
- package/addon/components/vehicle/details/trailers.js +55 -0
- package/addon/components/vehicle/form.hbs +2 -2
- package/addon/components/vehicle/panel-header.hbs +2 -2
- package/addon/components/vehicle/pill.hbs +2 -2
- package/addon/components/vendor/card.hbs +58 -0
- package/addon/components/vendor/card.js +6 -0
- package/addon/components/vendor/panel-header.hbs +2 -2
- package/addon/components/vendor/personnel-manager.hbs +2 -2
- package/addon/components/work-order/form.js +12 -4
- package/addon/controllers/connectivity/devices/index/details/vehicle.js +11 -0
- package/addon/controllers/connectivity/devices/index/details.js +3 -3
- package/addon/controllers/connectivity/devices/index.js +1 -0
- package/addon/controllers/connectivity/telematics/details/attachments.js +28 -47
- package/addon/controllers/connectivity/telematics/details/devices.js +1 -0
- package/addon/controllers/management/contacts/customers.js +4 -0
- package/addon/controllers/management/contacts/index.js +32 -0
- package/addon/controllers/management/trailers/index/details.js +119 -0
- package/addon/controllers/management/trailers/index/edit.js +67 -0
- package/addon/controllers/management/trailers/index/new.js +43 -0
- package/addon/controllers/management/trailers/index.js +599 -0
- package/addon/controllers/management/vehicles/index/details.js +16 -0
- package/addon/controllers/management/vehicles/index.js +78 -4
- package/addon/controllers/management/vendors/index.js +32 -0
- package/addon/controllers/operations/orders/index.js +3 -1
- package/addon/controllers/settings/custom-fields.js +8 -0
- package/addon/extension.js +7 -0
- package/addon/helpers/placeholder-image.js +6 -0
- package/addon/helpers/resource-image.js +10 -0
- package/addon/helpers/trailer-placeholder-image.js +6 -0
- package/addon/routes/management/trailers/index/details/connections.js +2 -0
- package/addon/routes/management/trailers/index/details/devices.js +2 -0
- package/addon/routes/management/trailers/index/details/equipment.js +2 -0
- package/addon/routes/management/trailers/index/details/index.js +2 -0
- package/addon/routes/management/trailers/index/details/maintenance-history.js +2 -0
- package/addon/routes/management/trailers/index/details/positions.js +2 -0
- package/addon/routes/management/trailers/index/details/schedules.js +2 -0
- package/addon/routes/management/trailers/index/details/work-orders.js +2 -0
- package/addon/routes/management/trailers/index/details.js +30 -0
- package/addon/routes/management/trailers/index/edit.js +23 -0
- package/addon/routes/management/trailers/index/new.js +14 -0
- package/addon/routes/management/trailers/index.js +42 -0
- package/addon/routes/management/vehicles/index/details/trailers.js +2 -0
- package/addon/routes/management/vehicles/index.js +7 -1
- package/addon/routes.js +17 -0
- package/addon/services/device-actions.js +26 -16
- package/addon/services/trailer-actions.js +394 -0
- package/addon/services/vehicle-actions.js +111 -0
- package/addon/styles/fleetops-engine.css +349 -0
- package/addon/templates/connectivity/devices/index/details/vehicle.hbs +19 -19
- package/addon/templates/connectivity/telematics/details/attachments.hbs +15 -15
- package/addon/templates/management/contacts/customers.hbs +48 -29
- package/addon/templates/management/contacts/index.hbs +52 -33
- package/addon/templates/management/trailers/index/details/connections.hbs +1 -0
- package/addon/templates/management/trailers/index/details/devices.hbs +1 -0
- package/addon/templates/management/trailers/index/details/equipment.hbs +1 -0
- package/addon/templates/management/trailers/index/details/index.hbs +1 -0
- package/addon/templates/management/trailers/index/details/maintenance-history.hbs +1 -0
- package/addon/templates/management/trailers/index/details/positions.hbs +1 -0
- package/addon/templates/management/trailers/index/details/schedules.hbs +1 -0
- package/addon/templates/management/trailers/index/details/work-orders.hbs +1 -0
- package/addon/templates/management/trailers/index/details.hbs +15 -0
- package/addon/templates/management/trailers/index/edit.hbs +12 -0
- package/addon/templates/management/trailers/index/new.hbs +11 -0
- package/addon/templates/management/trailers/index.hbs +67 -0
- package/addon/templates/management/vehicles/index/details/equipment.hbs +1 -1
- package/addon/templates/management/vehicles/index/details/trailers.hbs +1 -0
- package/addon/templates/management/vehicles/index/details.hbs +1 -1
- package/addon/templates/management/vendors/index.hbs +66 -32
- package/addon/utils/device-table-columns.js +10 -6
- package/addon/utils/live-map-card-content.js +56 -0
- package/addon/utils/placeholder-images.js +71 -0
- package/addon/utils/trailer-placeholder-image.js +11 -0
- package/app/components/attachment-list.js +1 -0
- package/app/components/cell/translated-value.js +1 -0
- package/app/components/contact/card.js +1 -0
- package/app/components/equipment/pill.js +1 -0
- package/app/components/filter/multi-model.js +1 -0
- package/app/components/modals/attach-equipment.js +1 -0
- package/app/components/modals/attach-trailer.js +1 -0
- package/app/components/modals/select-trailer.js +1 -0
- package/app/components/trailer/card.js +1 -0
- package/app/components/trailer/details/connections.js +1 -0
- package/app/components/trailer/details/equipment.js +1 -0
- package/app/components/trailer/details/maintenance-history.js +1 -0
- package/app/components/trailer/details/schedules.js +1 -0
- package/app/components/trailer/details/work-orders.js +1 -0
- package/app/components/trailer/details.js +1 -0
- package/app/components/trailer/form.js +1 -0
- package/app/components/trailer/panel-header.js +1 -0
- package/app/components/trailer/pill.js +1 -0
- package/app/components/vehicle/details/equipment.js +1 -0
- package/app/components/vehicle/details/trailers.js +1 -0
- package/app/components/vendor/card.js +1 -0
- package/app/controllers/management/trailers/index/details.js +1 -0
- package/app/controllers/management/trailers/index/edit.js +1 -0
- package/app/controllers/management/trailers/index/new.js +1 -0
- package/app/controllers/management/trailers/index.js +1 -0
- package/app/helpers/placeholder-image.js +1 -0
- package/app/helpers/resource-image.js +1 -0
- package/app/helpers/trailer-placeholder-image.js +1 -0
- package/app/routes/management/trailers/index/details/connections.js +1 -0
- package/app/routes/management/trailers/index/details/devices.js +1 -0
- package/app/routes/management/trailers/index/details/equipment.js +1 -0
- package/app/routes/management/trailers/index/details/index.js +1 -0
- package/app/routes/management/trailers/index/details/maintenance-history.js +1 -0
- package/app/routes/management/trailers/index/details/positions.js +1 -0
- package/app/routes/management/trailers/index/details/schedules.js +1 -0
- package/app/routes/management/trailers/index/details/work-orders.js +1 -0
- package/app/routes/management/trailers/index/details.js +1 -0
- package/app/routes/management/trailers/index/edit.js +1 -0
- package/app/routes/management/trailers/index/new.js +1 -0
- package/app/routes/management/trailers/index.js +1 -0
- package/app/routes/management/vehicles/index/details/trailers.js +1 -0
- package/app/services/trailer-actions.js +1 -0
- package/app/templates/management/trailers/index/details/connections.js +1 -0
- package/app/templates/management/trailers/index/details/devices.js +1 -0
- package/app/templates/management/trailers/index/details/equipment.js +1 -0
- package/app/templates/management/trailers/index/details/index.js +1 -0
- package/app/templates/management/trailers/index/details/maintenance-history.js +1 -0
- package/app/templates/management/trailers/index/details/positions.js +1 -0
- package/app/templates/management/trailers/index/details/schedules.js +1 -0
- package/app/templates/management/trailers/index/details/work-orders.js +1 -0
- package/app/templates/management/trailers/index/details.js +1 -0
- package/app/templates/management/trailers/index/edit.js +1 -0
- package/app/templates/management/trailers/index/new.js +1 -0
- package/app/templates/management/trailers/index.js +1 -0
- package/app/templates/management/vehicles/index/details/trailers.js +1 -0
- package/composer.json +1 -1
- package/extension.json +1 -1
- package/package.json +1 -1
- package/server/migrations/2026_09_03_000001_add_first_class_trailer_columns_to_assets_table.php +58 -0
- package/server/migrations/2026_09_03_000002_create_asset_connections_table.php +43 -0
- package/server/migrations/2026_09_03_000003_create_device_installations_table.php +33 -0
- package/server/src/Auth/Schemas/FleetOps.php +7 -0
- package/server/src/Events/TrailerLocationChanged.php +70 -0
- package/server/src/Exceptions/DeviceAlreadyAttachedException.php +18 -0
- package/server/src/Exports/TrailerExport.php +31 -0
- package/server/src/Http/Controllers/Api/v1/Concerns/ResolvesFleetOpsApiResources.php +8 -2
- package/server/src/Http/Controllers/Api/v1/DeviceController.php +22 -15
- package/server/src/Http/Controllers/Api/v1/EquipmentController.php +47 -0
- package/server/src/Http/Controllers/Api/v1/TrailerController.php +362 -0
- package/server/src/Http/Controllers/Api/v1/VehicleController.php +1 -0
- package/server/src/Http/Controllers/Internal/v1/DeviceController.php +3 -0
- package/server/src/Http/Controllers/Internal/v1/LiveController.php +1 -1
- package/server/src/Http/Controllers/Internal/v1/SearchController.php +16 -0
- package/server/src/Http/Controllers/Internal/v1/TrailerController.php +360 -0
- package/server/src/Http/Controllers/Internal/v1/VehicleController.php +74 -0
- package/server/src/Http/Filter/EquipmentFilter.php +51 -0
- package/server/src/Http/Filter/OrderFilter.php +15 -0
- package/server/src/Http/Filter/TrailerFilter.php +269 -0
- package/server/src/Http/Filter/VehicleFilter.php +70 -3
- package/server/src/Http/Requests/CreateDeviceRequest.php +1 -1
- package/server/src/Http/Requests/CreateEquipmentRequest.php +1 -1
- package/server/src/Http/Requests/CreateTrailerRequest.php +54 -0
- package/server/src/Http/Requests/UpdateTrailerRequest.php +7 -0
- package/server/src/Http/Resources/v1/AssetConnection.php +90 -0
- package/server/src/Http/Resources/v1/Concerns/ResolvesPublicRelationFields.php +29 -3
- package/server/src/Http/Resources/v1/Device.php +3 -1
- package/server/src/Http/Resources/v1/Equipment.php +3 -1
- package/server/src/Http/Resources/v1/Fleet.php +3 -1
- package/server/src/Http/Resources/v1/Index/Vehicle.php +10 -0
- package/server/src/Http/Resources/v1/Trailer.php +199 -0
- package/server/src/Http/Resources/v1/Vehicle.php +2 -0
- package/server/src/Http/Resources/v1/VehicleWithoutDriver.php +3 -0
- package/server/src/Imports/TrailerImport.php +33 -0
- package/server/src/Models/Asset.php +39 -10
- package/server/src/Models/AssetConnection.php +43 -0
- package/server/src/Models/Device.php +39 -8
- package/server/src/Models/DeviceInstallation.php +27 -0
- package/server/src/Models/Equipment.php +2 -0
- package/server/src/Models/Trailer.php +181 -0
- package/server/src/Models/Vehicle.php +13 -0
- package/server/src/Providers/FleetOpsServiceProvider.php +4 -2
- package/server/src/Support/Ai/FleetOpsAiQueryResources.php +22 -0
- package/server/src/Support/Reporting/FleetOpsReportSchema.php +38 -0
- package/server/src/Support/Telematics/TelematicService.php +35 -0
- package/server/src/Support/TrailerSummary.php +35 -0
- package/server/src/routes.php +29 -0
- package/server/tests/CompactResourceSerializationTest.php +36 -0
- package/server/tests/ControllerFilterContractsTest.php +29 -0
- package/server/tests/Feature/Http/Api/DeviceControllerContractsTest.php +30 -13
- package/server/tests/Feature/Http/Api/TrailerControllerLifecycleTest.php +640 -0
- package/server/tests/Feature/Http/Api/VehiclePublicContractTest.php +23 -0
- package/server/tests/Feature/Http/Internal/DeviceControllerContractsTest.php +20 -5
- package/server/tests/Feature/Http/Internal/LiveControllerEndpointsTest.php +19 -0
- package/server/tests/ModelAccessorContractsTest.php +10 -0
- package/server/tests/OrderFilterExecutionTest.php +5 -0
- package/server/tests/PublicApiControllerInputContractsTest.php +11 -0
- package/server/tests/PublicFleetOpsRestEndpointsTest.php +15 -3
- package/server/tests/ReportSchemaContractsTest.php +4 -0
- package/server/tests/TelematicsHardeningTest.php +4 -2
- package/server/tests/TrailerSupportCoverageTest.php +524 -0
- package/server/tests/Unit/Http/Resources/FleetResourceTest.php +17 -0
- package/server/tests/Unit/Http/Resources/IndexVehicleResourceTest.php +35 -0
- package/server/tests/Unit/Models/EquipmentTest.php +22 -0
- package/server/tests/Unit/Models/ModelLookupFallbackSeamsTest.php +7 -3
- package/server/tests/Unit/Models/TrailerTest.php +204 -0
- package/server/tests/Unit/Support/Telematics/TelematicServiceTelemetryTest.php +93 -0
- package/server/tests/VehicleControllerHelperContractsTest.php +14 -0
- package/server/tests/VehicleResourceContractsTest.php +39 -0
- package/translations/ar-ae.yml +396 -0
- package/translations/bg-bg.yaml +424 -0
- package/translations/en-us.yaml +423 -0
- package/translations/es-pa.yaml +425 -0
- package/translations/fr-fr.yaml +424 -0
- package/translations/mn-mn.yaml +424 -0
- package/translations/pt-br.yaml +424 -0
- package/translations/ru-ru.yaml +424 -0
- package/translations/vi-vn.yaml +435 -0
package/RELEASE.md
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
|
-
> v0.6.
|
|
1
|
+
> v0.6.65 ~ "First-class trailer operations"
|
|
2
2
|
|
|
3
3
|
---
|
|
4
|
-
##
|
|
5
|
-
- **
|
|
6
|
-
- **
|
|
4
|
+
## What's New
|
|
5
|
+
- **Trailers become a first-class Fleet-Ops resource.** Create and manage trailers independently, attach them to vehicles, connect equipment and telematics devices, and review operational, maintenance, location, and towing details from dedicated Trailer screens.
|
|
6
|
+
- **Vehicle and equipment relationships are easier to understand.** Vehicle details expose attached trailers and equipment, while Trailer details show the current towing vehicle and installed equipment.
|
|
7
|
+
- **Trailer APIs support complete integrations.** Internal and public endpoints cover trailer lifecycle, filtering, towing connections, equipment, devices, telemetry, imports, and exports.
|
|
7
8
|
|
|
8
9
|
---
|
|
9
10
|
## Testing
|
|
10
|
-
- Added
|
|
11
|
-
-
|
|
11
|
+
- Added frontend, backend, API-contract, attachment, telematics, spatial-data, permission, and serialization coverage for first-class trailers.
|
|
12
|
+
- Expanded the Fleetbase Postman collection and documentation alongside the Fleet-Ops implementation.
|
|
12
13
|
|
|
13
14
|
---
|
|
14
15
|
## Need help?
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
<div class="fleetops-attachment-list {{@wrapperClass}}" ...attributes>
|
|
2
|
+
<div class="fleetops-attachment-list-header">
|
|
3
|
+
<div class="min-w-0">
|
|
4
|
+
<h3 class="text-sm font-semibold text-gray-900 dark:text-gray-100">{{@title}}</h3>
|
|
5
|
+
{{#if @description}}
|
|
6
|
+
<p class="text-xs text-gray-500 dark:text-gray-400">{{@description}}</p>
|
|
7
|
+
{{/if}}
|
|
8
|
+
</div>
|
|
9
|
+
<div class="flex flex-row items-center space-x-2 shrink-0">
|
|
10
|
+
{{yield to="actions"}}
|
|
11
|
+
{{#if @actionText}}
|
|
12
|
+
<Button
|
|
13
|
+
@icon={{or @actionIcon "plus"}}
|
|
14
|
+
@text={{@actionText}}
|
|
15
|
+
@size="xs"
|
|
16
|
+
@type={{or @actionType "primary"}}
|
|
17
|
+
@onClick={{@onAction}}
|
|
18
|
+
@permission={{@actionPermission}}
|
|
19
|
+
@disabled={{@actionDisabled}}
|
|
20
|
+
/>
|
|
21
|
+
{{/if}}
|
|
22
|
+
</div>
|
|
23
|
+
</div>
|
|
24
|
+
|
|
25
|
+
{{#if @isLoading}}
|
|
26
|
+
<div class="fleetops-attachment-list-loading">
|
|
27
|
+
<Spinner />
|
|
28
|
+
</div>
|
|
29
|
+
{{else if @items.length}}
|
|
30
|
+
<div class="fleetops-attachment-list-items" role="list">
|
|
31
|
+
{{#each @items as |item index|}}
|
|
32
|
+
<div class="fleetops-attachment-list-item" role="listitem">
|
|
33
|
+
<div class="fleetops-attachment-list-item-content">
|
|
34
|
+
{{yield item index to="item"}}
|
|
35
|
+
</div>
|
|
36
|
+
{{#if (has-block "itemActions")}}
|
|
37
|
+
<div class="fleetops-attachment-list-item-actions">
|
|
38
|
+
{{yield item index to="itemActions"}}
|
|
39
|
+
</div>
|
|
40
|
+
{{/if}}
|
|
41
|
+
</div>
|
|
42
|
+
{{/each}}
|
|
43
|
+
</div>
|
|
44
|
+
{{else}}
|
|
45
|
+
<div class="fleetops-attachment-list-empty">
|
|
46
|
+
<FaIcon @icon={{or @emptyIcon "box-open"}} @size="2x" class="text-gray-400 dark:text-gray-500 mb-2" />
|
|
47
|
+
<h3 class="text-base font-semibold text-gray-700 dark:text-gray-300">{{@emptyTitle}}</h3>
|
|
48
|
+
{{#if @emptyDescription}}
|
|
49
|
+
<p class="text-sm text-gray-500 dark:text-gray-400">{{@emptyDescription}}</p>
|
|
50
|
+
{{/if}}
|
|
51
|
+
{{#if (and @actionText (not @hideEmptyAction))}}
|
|
52
|
+
<Button
|
|
53
|
+
@icon={{or @actionIcon "plus"}}
|
|
54
|
+
@text={{@actionText}}
|
|
55
|
+
@size="xs"
|
|
56
|
+
@type={{or @actionType "primary"}}
|
|
57
|
+
@onClick={{@onAction}}
|
|
58
|
+
@permission={{@actionPermission}}
|
|
59
|
+
@disabled={{@actionDisabled}}
|
|
60
|
+
class="mt-3"
|
|
61
|
+
/>
|
|
62
|
+
{{/if}}
|
|
63
|
+
</div>
|
|
64
|
+
{{/if}}
|
|
65
|
+
</div>
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import Component from '@glimmer/component';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Shared layout for "things attached to an asset" tabs (devices, equipment,
|
|
5
|
+
* trailers, towing history) so every attachment tab reads the same way: a
|
|
6
|
+
* header with a description and primary action, uniform rows, one empty state.
|
|
7
|
+
*/
|
|
8
|
+
export default class AttachmentListComponent extends Component {}
|
|
@@ -31,13 +31,13 @@ export default class CellAttachedVehicleComponent extends Component {
|
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
get hasVehicle() {
|
|
34
|
-
return Boolean(this.device?.attachable_uuid && this.
|
|
34
|
+
return Boolean(this.device?.attachable_uuid && this.isSupportedAttachment);
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
-
get
|
|
37
|
+
get isSupportedAttachment() {
|
|
38
38
|
const attachableType = `${this.device?.attachable_type ?? ''}`.toLowerCase();
|
|
39
39
|
|
|
40
|
-
return !attachableType || attachableType.includes('vehicle');
|
|
40
|
+
return !attachableType || attachableType.includes('vehicle') || attachableType.includes('trailer');
|
|
41
41
|
}
|
|
42
42
|
|
|
43
43
|
@action onClick(_vehicle, event) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import Component from '@glimmer/component';
|
|
2
2
|
import { action, get } from '@ember/object';
|
|
3
|
-
import
|
|
3
|
+
import { getPlaceholderImage, resolveResourceImage } from '../../utils/placeholder-images';
|
|
4
4
|
import { resolveIdentityCellResource } from '../../utils/identity-cell-resource';
|
|
5
5
|
|
|
6
6
|
const DEFAULT_STATUS_TONES = {
|
|
@@ -34,11 +34,11 @@ export default class CellDriverIdentityComponent extends Component {
|
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
get mediaUrl() {
|
|
37
|
-
return get(this.resource, 'photo_url');
|
|
37
|
+
return resolveResourceImage(get(this.resource, 'photo_url'), 'driver');
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
get fallbackImage() {
|
|
41
|
-
return
|
|
41
|
+
return getPlaceholderImage('driver');
|
|
42
42
|
}
|
|
43
43
|
|
|
44
44
|
get hasCompactStatusDot() {
|
|
@@ -97,7 +97,7 @@ export default class CellDriverIdentityComponent extends Component {
|
|
|
97
97
|
...(this.args.column ?? {}),
|
|
98
98
|
labelPath: 'name',
|
|
99
99
|
mediaPath: 'photo_url',
|
|
100
|
-
fallbackImage:
|
|
100
|
+
fallbackImage: getPlaceholderImage('driver'),
|
|
101
101
|
statusPath: 'status',
|
|
102
102
|
onlinePath: 'online',
|
|
103
103
|
showStatusBadge: this.args.column?.showStatusBadge ?? true,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{{#let (or @row.driver this.driver) as |driver|}}
|
|
2
2
|
{{#if driver}}
|
|
3
3
|
<div class="relative flex items-center" ...attributes>
|
|
4
|
-
<img src={{driver.photo_url}} alt={{driver.name}} {{fallback-img-src (
|
|
4
|
+
<img src={{resource-image driver.photo_url "driver"}} alt={{driver.name}} {{fallback-img-src (placeholder-image "driver")}} class="w-5 h-5 mr-2 rounded-md" />
|
|
5
5
|
<a href="javascript:;" class="relative flex flex-row items-center" disabled={{and @column.permission (cannot @column.permission)}} {{on "click" (fn this.onClick driver)}}>
|
|
6
6
|
<span>{{get-default-value driver.name}}</span>
|
|
7
7
|
{{#if @row.vehicle_assigned}}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
{{#if this.label}}
|
|
2
|
+
{{#if this.isBadge}}
|
|
3
|
+
<Badge @status={{this.value}} @text={{this.label}} @icon={{this.icon}} @hideStatusDot={{unless this.icon false true}} ...attributes />
|
|
4
|
+
{{else}}
|
|
5
|
+
<span class={{@column.className}} ...attributes>{{this.label}}</span>
|
|
6
|
+
{{/if}}
|
|
7
|
+
{{else}}
|
|
8
|
+
<span class="text-gray-400 dark:text-gray-500" ...attributes>{{this.emptyText}}</span>
|
|
9
|
+
{{/if}}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import Component from '@glimmer/component';
|
|
2
|
+
import { inject as service } from '@ember/service';
|
|
3
|
+
import { get } from '@ember/object';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Table cell that renders a stable enum value (`dry_van`, `never_connected`, ...)
|
|
7
|
+
* through its localized label. Configure the column with:
|
|
8
|
+
*
|
|
9
|
+
* translationPrefix: 'trailer.types' // required, joined with the raw value
|
|
10
|
+
* badge: true // optional, render as a status badge
|
|
11
|
+
* badgeIconPath / badgeIcons // optional badge icon per value
|
|
12
|
+
*/
|
|
13
|
+
export default class CellTranslatedValueComponent extends Component {
|
|
14
|
+
@service intl;
|
|
15
|
+
|
|
16
|
+
get value() {
|
|
17
|
+
const row = this.args.row;
|
|
18
|
+
const valuePath = this.args.column?.valuePath;
|
|
19
|
+
|
|
20
|
+
if (this.args.value !== undefined && this.args.value !== null) {
|
|
21
|
+
return this.args.value;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
return valuePath ? get(row, valuePath) : null;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
get label() {
|
|
28
|
+
const value = this.value;
|
|
29
|
+
const prefix = this.args.column?.translationPrefix;
|
|
30
|
+
|
|
31
|
+
if (value === null || value === undefined || value === '') {
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
if (!prefix) {
|
|
36
|
+
return String(value);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const key = `${prefix}.${value}`;
|
|
40
|
+
|
|
41
|
+
return this.intl.exists(key) ? this.intl.t(key) : String(value);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
get isBadge() {
|
|
45
|
+
return Boolean(this.args.column?.badge);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
get icon() {
|
|
49
|
+
const icons = this.args.column?.badgeIcons;
|
|
50
|
+
|
|
51
|
+
return icons && this.value ? icons[this.value] : undefined;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
get emptyText() {
|
|
55
|
+
return this.args.column?.emptyText ?? '-';
|
|
56
|
+
}
|
|
57
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
<Layout::Resource::Card class="fleetops-resource-card contact-card" ...attributes as |Card|>
|
|
2
|
+
<Card.header class={{@headerClass}}>
|
|
3
|
+
<RegistryYield @registry="fleet-ops:component:contact:card:header:start" as |RegistryComponent|>
|
|
4
|
+
<RegistryComponent @resource={{@resource}} />
|
|
5
|
+
</RegistryYield>
|
|
6
|
+
<div class="fleetops-card-title">
|
|
7
|
+
<div class="font-semibold flex-1 truncate">{{n-a @resource.name}}</div>
|
|
8
|
+
</div>
|
|
9
|
+
<div class="text-gray-400 dark:text-gray-500 text-sm w-full truncate">{{n-a @resource.title @resource.internal_id @resource.public_id}}</div>
|
|
10
|
+
{{#if (has-block "header")}}
|
|
11
|
+
{{yield to="header"}}
|
|
12
|
+
{{/if}}
|
|
13
|
+
<RegistryYield @registry="fleet-ops:component:contact:card:header:end" as |RegistryComponent|>
|
|
14
|
+
<RegistryComponent @resource={{@resource}} />
|
|
15
|
+
</RegistryYield>
|
|
16
|
+
</Card.header>
|
|
17
|
+
<Card.body class="{{@bodyClass}} h-40 overflow-hidden">
|
|
18
|
+
<Image src={{resource-image @resource.photo_url this.placeholderType}} @fallbackSrc={{(placeholder-image this.placeholderType)}} alt={{@resource.name}} class="fleetops-card-image fleetops-card-image--cover" />
|
|
19
|
+
{{#if (has-block "body")}}
|
|
20
|
+
{{yield to="body"}}
|
|
21
|
+
{{/if}}
|
|
22
|
+
</Card.body>
|
|
23
|
+
<Card.footer class={{@footerClass}}>
|
|
24
|
+
<RegistryYield @registry="fleet-ops:component:contact:card:footer:start" as |RegistryComponent|>
|
|
25
|
+
<RegistryComponent @resource={{@resource}} />
|
|
26
|
+
</RegistryYield>
|
|
27
|
+
<div class="flex flex-row items-center justify-between w-full">
|
|
28
|
+
<Badge @status={{or @resource.status @resource.type "default"}} @size="xs" />
|
|
29
|
+
<div class="flex flex-row items-center space-x-1">
|
|
30
|
+
<Button @icon="eye" @size="xs" @helpText={{t "common.view"}} @onClick={{fn this.resourceActions.transition.view @resource}} @permission="fleet-ops view contact" />
|
|
31
|
+
<Button @icon="pencil" @size="xs" @helpText={{t "common.edit"}} @onClick={{fn this.resourceActions.transition.edit @resource}} @permission="fleet-ops update contact" />
|
|
32
|
+
<Button @icon="trash" @size="xs" @type="danger" @helpText={{t "common.delete"}} @onClick={{fn this.resourceActions.delete @resource}} @permission="fleet-ops delete contact" />
|
|
33
|
+
</div>
|
|
34
|
+
</div>
|
|
35
|
+
<RegistryYield @registry="fleet-ops:component:contact:card:footer:end" as |RegistryComponent|>
|
|
36
|
+
<RegistryComponent @resource={{@resource}} />
|
|
37
|
+
</RegistryYield>
|
|
38
|
+
{{#if (has-block "footer")}}
|
|
39
|
+
{{yield to="footer"}}
|
|
40
|
+
{{/if}}
|
|
41
|
+
<div class="fleetops-card-meta-list">
|
|
42
|
+
<div class="fleetops-card-meta">
|
|
43
|
+
<FaIcon @icon="envelope" @prefix="fas" />
|
|
44
|
+
<span class="fleetops-card-meta-value">{{#if @resource.email}}<a href="mailto:{{@resource.email}}" class="fleetops-card-meta-link">{{@resource.email}}</a>{{else}}-{{/if}}</span>
|
|
45
|
+
</div>
|
|
46
|
+
<div class="fleetops-card-meta">
|
|
47
|
+
<FaIcon @icon="phone" @prefix="fas" />
|
|
48
|
+
<span class="fleetops-card-meta-value">{{#if @resource.phone}}<a href="tel:{{@resource.phone}}" class="fleetops-card-meta-link">{{@resource.phone}}</a>{{else}}-{{/if}}</span>
|
|
49
|
+
</div>
|
|
50
|
+
<div class="fleetops-card-meta">
|
|
51
|
+
<FaIcon @icon="location-dot" @prefix="fas" />
|
|
52
|
+
<span class="fleetops-card-meta-value">{{n-a @resource.address @resource.place.address}}</span>
|
|
53
|
+
</div>
|
|
54
|
+
<div class="fleetops-card-meta">{{t "common.last-modified"}}: {{@resource.updatedAt}}</div>
|
|
55
|
+
</div>
|
|
56
|
+
</Card.footer>
|
|
57
|
+
</Layout::Resource::Card>
|
|
58
|
+
{{yield}}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import Component from '@glimmer/component';
|
|
2
|
+
import { inject as service } from '@ember/service';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Card for contacts and customers. Customers are contacts driven by the customer
|
|
6
|
+
* actions service, so the actions service can be passed in as `@resourceActions`.
|
|
7
|
+
*/
|
|
8
|
+
export default class ContactCardComponent extends Component {
|
|
9
|
+
@service contactActions;
|
|
10
|
+
|
|
11
|
+
get resourceActions() {
|
|
12
|
+
return this.args.resourceActions ?? this.contactActions;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/** Customers get their own silhouette; plain contacts the generic one. */
|
|
16
|
+
get placeholderType() {
|
|
17
|
+
return this.args.placeholderType ?? 'contact';
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
<ContentPanel @title={{t "contact.fields.contact-details"}} @open={{true}} @wrapperClass="bordered-top">
|
|
3
3
|
<div class="flex flex-row space-x-3 mb-3">
|
|
4
4
|
<div class="flex items-center justify-start rounded-full">
|
|
5
|
-
<Image src={{@resource.photo_url}} @fallbackSrc={{
|
|
5
|
+
<Image src={{resource-image @resource.photo_url "contact"}} @fallbackSrc={{(placeholder-image "contact")}} alt={{@resource.name}} height="48" width="48" class="h-14 w-14 rounded-full shadow-sm" />
|
|
6
6
|
<Attach::Tooltip @class="clean" @animation="scale" @placement="top">
|
|
7
7
|
<InputInfo @text={{t "common.upload-new-photo"}} />
|
|
8
8
|
</Attach::Tooltip>
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
<div class="flex flex-1 flex-row items-start justify-between">
|
|
3
3
|
<div class="flex flex-row space-x-3">
|
|
4
4
|
<div class="flex items-start justify-start rounded-full">
|
|
5
|
-
<Image src={{@resource.photo_url}} @fallbackSrc={{
|
|
5
|
+
<Image src={{resource-image @resource.photo_url "contact"}} @fallbackSrc={{(placeholder-image "contact")}} alt={{@resource.name}} height="48" width="48" class="h-14 w-14 rounded-full shadow-sm" />
|
|
6
6
|
<Attach::Tooltip @class="clean" @animation="scale" @placement="top">
|
|
7
7
|
<InputInfo @text={{@resource.name}} />
|
|
8
8
|
</Attach::Tooltip>
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
<div class="flex flex-row space-x-3 mb-3">
|
|
4
4
|
<div class="flex items-center justify-start rounded-full">
|
|
5
5
|
<Image
|
|
6
|
-
src={{@resource.photo_url}}
|
|
7
|
-
@fallbackSrc={{
|
|
6
|
+
src={{resource-image @resource.photo_url "customer"}}
|
|
7
|
+
@fallbackSrc={{(placeholder-image "customer")}}
|
|
8
8
|
alt={{@resource.name}}
|
|
9
9
|
height="48"
|
|
10
10
|
width="48"
|
|
@@ -1,28 +1,26 @@
|
|
|
1
|
-
<
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
</div>
|
|
28
|
-
</div>
|
|
1
|
+
<AttachmentList
|
|
2
|
+
@title={{t "resource.devices"}}
|
|
3
|
+
@description={{t "device.prompts.manager-description" resourceType=(get-model-name @resource)}}
|
|
4
|
+
@actionText={{t "device.actions.attach-device"}}
|
|
5
|
+
@actionIcon="plus"
|
|
6
|
+
@onAction={{this.addDevice}}
|
|
7
|
+
@actionDisabled={{not @resource}}
|
|
8
|
+
@isLoading={{this.loadDevices.isRunning}}
|
|
9
|
+
@items={{this.devices}}
|
|
10
|
+
@emptyIcon="hard-drive"
|
|
11
|
+
@emptyTitle={{t "device.prompts.no-devices-attached-title"}}
|
|
12
|
+
@emptyDescription={{t "device.prompts.no-devices-attached-body" resourceType=(get-model-name @resource)}}
|
|
13
|
+
class="fleetops-device-manager"
|
|
14
|
+
...attributes
|
|
15
|
+
>
|
|
16
|
+
<:item as |device|>
|
|
17
|
+
<Device::Pill @device={{device}} @onClick={{fn this.viewDevice device}} />
|
|
18
|
+
{{#if device.status}}
|
|
19
|
+
<Badge @status={{device.status}} @size="xs" class="fleetops-attachment-list-item-badge" />
|
|
20
|
+
{{/if}}
|
|
21
|
+
</:item>
|
|
22
|
+
<:itemActions as |device|>
|
|
23
|
+
<Button @icon="eye" @size="xs" @helpText={{t "common.view"}} @onClick={{fn this.viewDevice device}} />
|
|
24
|
+
<Button @type="danger" @icon="unlink" @size="xs" @helpText={{t "device.attachment.detach"}} @onClick={{fn this.removeDevice device}} />
|
|
25
|
+
</:itemActions>
|
|
26
|
+
</AttachmentList>
|
|
@@ -5,6 +5,8 @@ import { inject as service } from '@ember/service';
|
|
|
5
5
|
import { debug } from '@ember/debug';
|
|
6
6
|
import { task } from 'ember-concurrency';
|
|
7
7
|
import getModelName from '@fleetbase/ember-core/utils/get-model-name';
|
|
8
|
+
import { pluralize } from 'ember-inflector';
|
|
9
|
+
import { dasherize } from '@ember/string';
|
|
8
10
|
|
|
9
11
|
export default class DeviceManagerComponent extends Component {
|
|
10
12
|
@service store;
|
|
@@ -12,6 +14,7 @@ export default class DeviceManagerComponent extends Component {
|
|
|
12
14
|
@service modalsManager;
|
|
13
15
|
@service notifications;
|
|
14
16
|
@service intl;
|
|
17
|
+
@service deviceActions;
|
|
15
18
|
@tracked devices = [];
|
|
16
19
|
|
|
17
20
|
get resourceName() {
|
|
@@ -28,6 +31,21 @@ export default class DeviceManagerComponent extends Component {
|
|
|
28
31
|
);
|
|
29
32
|
}
|
|
30
33
|
|
|
34
|
+
/**
|
|
35
|
+
* The internal attach/detach endpoints are namespaced by the attachable resource
|
|
36
|
+
* (`vehicles/{id}/attach-device`, `trailers/{id}/attach-device`). Derive the prefix
|
|
37
|
+
* from the resource's model name unless an explicit `@endpoint` is given.
|
|
38
|
+
*/
|
|
39
|
+
get endpoint() {
|
|
40
|
+
if (this.args.endpoint) {
|
|
41
|
+
return this.args.endpoint;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const modelName = getModelName(this.args.resource);
|
|
45
|
+
|
|
46
|
+
return modelName ? dasherize(pluralize(modelName)) : 'vehicles';
|
|
47
|
+
}
|
|
48
|
+
|
|
31
49
|
constructor() {
|
|
32
50
|
super(...arguments);
|
|
33
51
|
this.loadDevices.perform();
|
|
@@ -45,7 +63,7 @@ export default class DeviceManagerComponent extends Component {
|
|
|
45
63
|
modal.startLoading();
|
|
46
64
|
|
|
47
65
|
try {
|
|
48
|
-
await this.fetch.post(
|
|
66
|
+
await this.fetch.post(`${this.endpoint}/${this.args.resource.id}/attach-device`, { device: selectedDevice.id });
|
|
49
67
|
await this.loadDevices.perform();
|
|
50
68
|
this.notifications.success(this.intl.t('device.prompts.attach-device-success'));
|
|
51
69
|
modal.done();
|
|
@@ -57,6 +75,14 @@ export default class DeviceManagerComponent extends Component {
|
|
|
57
75
|
});
|
|
58
76
|
}
|
|
59
77
|
|
|
78
|
+
@action viewDevice(device) {
|
|
79
|
+
if (this.deviceActions.panel?.view) {
|
|
80
|
+
return this.deviceActions.panel.view(device);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return this.deviceActions.transition.view(device);
|
|
84
|
+
}
|
|
85
|
+
|
|
60
86
|
@action removeDevice(device) {
|
|
61
87
|
const deviceName = device.displayName ?? device.name ?? device.device_id ?? this.intl.t('resource.device');
|
|
62
88
|
|
|
@@ -67,7 +93,7 @@ export default class DeviceManagerComponent extends Component {
|
|
|
67
93
|
modal.startLoading();
|
|
68
94
|
|
|
69
95
|
try {
|
|
70
|
-
await this.fetch.post(
|
|
96
|
+
await this.fetch.post(`${this.endpoint}/${this.args.resource.id}/detach-device`, { device: device.id });
|
|
71
97
|
await this.loadDevices.perform();
|
|
72
98
|
this.notifications.success(this.intl.t('device.prompts.detach-from-resource-success', { deviceName, resourceName: this.resourceName }));
|
|
73
99
|
modal.done();
|
|
@@ -1,21 +1,21 @@
|
|
|
1
1
|
<div class="flex flex-col gap-3 p-3" ...attributes>
|
|
2
2
|
<div class="flex items-start justify-between gap-3">
|
|
3
3
|
<div class="min-w-0">
|
|
4
|
-
<h2 class="text-base font-bold text-gray-900 dark:text-gray-100">
|
|
5
|
-
<p class="mt-0.5 text-xs text-gray-500 dark:text-gray-300">
|
|
4
|
+
<h2 class="text-base font-bold text-gray-900 dark:text-gray-100">{{t "device.attachment.title"}}</h2>
|
|
5
|
+
<p class="mt-0.5 text-xs text-gray-500 dark:text-gray-300">{{t "device.attachment.description"}}</p>
|
|
6
6
|
</div>
|
|
7
7
|
<div class="flex flex-wrap items-center justify-end gap-2">
|
|
8
8
|
{{#if this.hasVehicle}}
|
|
9
9
|
{{#if this.canOpenVehicle}}
|
|
10
|
-
<Button @icon="eye" @text=
|
|
10
|
+
<Button @icon="eye" @text={{t "device.attachment.open"}} @size="xs" @onClick={{this.openVehicle}} />
|
|
11
11
|
{{/if}}
|
|
12
12
|
{{#if this.canLocateVehicle}}
|
|
13
|
-
<Button @icon="location-dot" @text="
|
|
13
|
+
<Button @icon="location-dot" @text={{t "device.attachment.locate"}} @size="xs" @onClick={{this.locateVehicle}} />
|
|
14
14
|
{{/if}}
|
|
15
|
-
<Button @icon="shuffle" @text=
|
|
16
|
-
<Button @icon="unlink" @text="
|
|
15
|
+
<Button @icon="shuffle" @text={{t "device.attachment.change"}} @size="xs" @onClick={{this.attachToVehicle}} />
|
|
16
|
+
<Button @icon="unlink" @text={{t "device.attachment.detach"}} @size="xs" @type="danger" @onClick={{this.detachFromVehicle}} />
|
|
17
17
|
{{else}}
|
|
18
|
-
<Button @icon="link" @text=
|
|
18
|
+
<Button @icon="link" @text={{t "device.actions.attach-to-asset"}} @size="xs" @onClick={{this.attachToVehicle}} />
|
|
19
19
|
{{/if}}
|
|
20
20
|
</div>
|
|
21
21
|
</div>
|
|
@@ -39,15 +39,15 @@
|
|
|
39
39
|
<div class="mt-1 text-xs text-gray-500 dark:text-gray-300">{{n-a this.vehicleSubtitle}}</div>
|
|
40
40
|
<div class="mt-3 grid grid-cols-1 gap-2 text-xs sm:grid-cols-3">
|
|
41
41
|
<div>
|
|
42
|
-
<div class="font-semibold uppercase text-gray-400 dark:text-gray-500">
|
|
42
|
+
<div class="font-semibold uppercase text-gray-400 dark:text-gray-500">{{t "resource.driver"}}</div>
|
|
43
43
|
<div class="truncate text-gray-800 dark:text-gray-100">{{n-a this.vehicleDriverName}}</div>
|
|
44
44
|
</div>
|
|
45
45
|
<div>
|
|
46
|
-
<div class="font-semibold uppercase text-gray-400 dark:text-gray-500">
|
|
46
|
+
<div class="font-semibold uppercase text-gray-400 dark:text-gray-500">{{t "device.attachment.attached-device"}}</div>
|
|
47
47
|
<div class="truncate text-gray-800 dark:text-gray-100">{{n-a this.device.displayName this.device.name}}</div>
|
|
48
48
|
</div>
|
|
49
49
|
<div>
|
|
50
|
-
<div class="font-semibold uppercase text-gray-400 dark:text-gray-500">
|
|
50
|
+
<div class="font-semibold uppercase text-gray-400 dark:text-gray-500">{{t "device.attachment.last-seen"}}</div>
|
|
51
51
|
<div class="truncate text-gray-800 dark:text-gray-100">{{n-a (format-date-fns this.device.last_online_at "dd MMM yyyy, HH:mm")}}</div>
|
|
52
52
|
</div>
|
|
53
53
|
</div>
|
|
@@ -58,9 +58,9 @@
|
|
|
58
58
|
<Telematic::TabEmptyState
|
|
59
59
|
@tone="warning"
|
|
60
60
|
@icon="link-slash"
|
|
61
|
-
@title=
|
|
62
|
-
@message="
|
|
63
|
-
@primaryText=
|
|
61
|
+
@title={{t "device.attachment.none-title"}}
|
|
62
|
+
@message={{t "device.attachment.none-message"}}
|
|
63
|
+
@primaryText={{t "device.actions.attach-to-asset"}}
|
|
64
64
|
@primaryIcon="link"
|
|
65
65
|
@primaryAction={{this.attachToVehicle}}
|
|
66
66
|
/>
|
|
@@ -7,6 +7,7 @@ export default class DevicePanelTabsVehicleComponent extends Component {
|
|
|
7
7
|
@service hostRouter;
|
|
8
8
|
@service mapManager;
|
|
9
9
|
@service vehicleActions;
|
|
10
|
+
@service trailerActions;
|
|
10
11
|
|
|
11
12
|
get device() {
|
|
12
13
|
return this.args.resource ?? this.args.model;
|
|
@@ -16,6 +17,10 @@ export default class DevicePanelTabsVehicleComponent extends Component {
|
|
|
16
17
|
return this.device?.attachable;
|
|
17
18
|
}
|
|
18
19
|
|
|
20
|
+
get isTrailer() {
|
|
21
|
+
return `${this.device?.attachable_type ?? ''}`.toLowerCase().includes('trailer');
|
|
22
|
+
}
|
|
23
|
+
|
|
19
24
|
get vehicleName() {
|
|
20
25
|
return this.device?.attached_to_name ?? this.vehicle?.displayName ?? this.vehicle?.display_name ?? this.vehicle?.name;
|
|
21
26
|
}
|
|
@@ -58,6 +63,9 @@ export default class DevicePanelTabsVehicleComponent extends Component {
|
|
|
58
63
|
|
|
59
64
|
@action openVehicle() {
|
|
60
65
|
if (this.vehicle?.id) {
|
|
66
|
+
if (this.isTrailer) {
|
|
67
|
+
return this.trailerActions.transition.view(this.vehicle);
|
|
68
|
+
}
|
|
61
69
|
return this.vehicleActions.panel?.view
|
|
62
70
|
? this.vehicleActions.panel.view(this.vehicle)
|
|
63
71
|
: this.hostRouter.transitionTo('console.fleet-ops.management.vehicles.index.details', this.vehicle);
|