@fleetbase/fleetops-engine 0.6.64 → 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 -5
- 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/Device.php +3 -1
- package/server/src/Http/Resources/v1/Equipment.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/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/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/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
|
@@ -57,32 +57,33 @@ export default class ConnectivityTelematicsDetailsAttachmentsController extends
|
|
|
57
57
|
return this.syncedDevices.filter((device) => !device.attachable_uuid).length;
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
-
get
|
|
60
|
+
get mappedAssetsCount() {
|
|
61
61
|
const vehicleIds = new Set(this.syncedDevices.filter((device) => device.attachable_uuid).map((device) => device.attachable_uuid));
|
|
62
62
|
|
|
63
63
|
return vehicleIds.size;
|
|
64
64
|
}
|
|
65
65
|
|
|
66
|
-
get
|
|
66
|
+
get assetGroups() {
|
|
67
67
|
const groups = new Map();
|
|
68
68
|
|
|
69
69
|
for (const device of this.attachedDevices) {
|
|
70
|
-
this.
|
|
70
|
+
this.addDeviceToAssetGroup(groups, device);
|
|
71
71
|
}
|
|
72
72
|
|
|
73
|
-
return this.
|
|
73
|
+
return this.sortAssetGroups(groups);
|
|
74
74
|
}
|
|
75
75
|
|
|
76
|
-
|
|
76
|
+
addDeviceToAssetGroup(groups, device) {
|
|
77
77
|
const key = device.attachable_uuid;
|
|
78
78
|
|
|
79
79
|
if (!groups.has(key)) {
|
|
80
|
-
const
|
|
80
|
+
const asset = device.attachable;
|
|
81
81
|
|
|
82
82
|
groups.set(key, {
|
|
83
83
|
id: key,
|
|
84
|
-
name: this.
|
|
85
|
-
|
|
84
|
+
name: this.getDeviceAssetName(device),
|
|
85
|
+
asset,
|
|
86
|
+
attachableType: device.attachable_type,
|
|
86
87
|
devices: [],
|
|
87
88
|
});
|
|
88
89
|
}
|
|
@@ -90,7 +91,7 @@ export default class ConnectivityTelematicsDetailsAttachmentsController extends
|
|
|
90
91
|
groups.get(key).devices.push(device);
|
|
91
92
|
}
|
|
92
93
|
|
|
93
|
-
|
|
94
|
+
sortAssetGroups(groups) {
|
|
94
95
|
return Array.from(groups.values()).sort((a, b) => String(a.name).localeCompare(String(b.name)));
|
|
95
96
|
}
|
|
96
97
|
|
|
@@ -146,11 +147,11 @@ export default class ConnectivityTelematicsDetailsAttachmentsController extends
|
|
|
146
147
|
}
|
|
147
148
|
|
|
148
149
|
get hasOnlyUnattachedDevices() {
|
|
149
|
-
return this.unattachedDevices.length > 0 && this.
|
|
150
|
+
return this.unattachedDevices.length > 0 && this.assetGroups.length === 0 && !this.hasActiveFilters;
|
|
150
151
|
}
|
|
151
152
|
|
|
152
153
|
get allMapped() {
|
|
153
|
-
return this.hasSyncedDevices && this.unattachedDevices.length === 0 && this.
|
|
154
|
+
return this.hasSyncedDevices && this.unattachedDevices.length === 0 && this.assetGroups.length > 0 && !this.hasActiveFilters;
|
|
154
155
|
}
|
|
155
156
|
|
|
156
157
|
get emptyStateVariant() {
|
|
@@ -234,7 +235,7 @@ export default class ConnectivityTelematicsDetailsAttachmentsController extends
|
|
|
234
235
|
get metrics() {
|
|
235
236
|
return [
|
|
236
237
|
{ label: 'Synced devices', value: this.totalSyncedDevices, icon: 'microchip', accentClass: 'fleetops-connectivity-kpi-accent-blue' },
|
|
237
|
-
{ label: '
|
|
238
|
+
{ label: 'Assets mapped', value: this.mappedAssetsCount, icon: 'truck', accentClass: 'fleetops-connectivity-kpi-accent-blue' },
|
|
238
239
|
{ label: 'Attached devices', value: this.attachedDevicesCount, icon: 'link', accentClass: 'fleetops-connectivity-kpi-accent-green' },
|
|
239
240
|
{ label: 'Unattached devices', value: this.unattachedDevicesCount, icon: 'link-slash', accentClass: 'fleetops-connectivity-kpi-accent-amber' },
|
|
240
241
|
{ label: 'Online devices', value: this.onlineDevicesCount, icon: 'signal', accentClass: 'fleetops-connectivity-kpi-accent-green' },
|
|
@@ -320,40 +321,20 @@ export default class ConnectivityTelematicsDetailsAttachmentsController extends
|
|
|
320
321
|
return;
|
|
321
322
|
}
|
|
322
323
|
|
|
323
|
-
return this.
|
|
324
|
+
return this.attachDeviceToAsset(this.selectedDevice, group.asset ?? { id: group.id, name: group.name }, group.attachableType);
|
|
324
325
|
}
|
|
325
326
|
|
|
326
327
|
@action openAttachDeviceModal(device) {
|
|
327
|
-
this.
|
|
328
|
-
title: this.intl.t('device.prompts.attach-device-to-vehicle-title', { deviceName: device.displayName ?? device.name ?? device.device_id ?? this.intl.t('resource.device') }),
|
|
329
|
-
acceptButtonText: this.intl.t('device.actions.attach-to-vehicle'),
|
|
330
|
-
device,
|
|
331
|
-
selectedVehicle: null,
|
|
332
|
-
confirm: async (modal) => {
|
|
333
|
-
const selectedVehicle = modal.getOption('selectedVehicle');
|
|
334
|
-
if (!selectedVehicle) {
|
|
335
|
-
return;
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
modal.startLoading();
|
|
339
|
-
|
|
340
|
-
try {
|
|
341
|
-
await this.attachDeviceToVehicle(device, selectedVehicle);
|
|
342
|
-
modal.done();
|
|
343
|
-
} catch (error) {
|
|
344
|
-
this.notifications.serverError(error);
|
|
345
|
-
modal.stopLoading();
|
|
346
|
-
}
|
|
347
|
-
},
|
|
348
|
-
});
|
|
328
|
+
return this.deviceActions.attachToAsset(device, { callback: this.refresh });
|
|
349
329
|
}
|
|
350
330
|
|
|
351
|
-
async
|
|
352
|
-
const
|
|
331
|
+
async attachDeviceToAsset(device, selectedAsset, attachableType) {
|
|
332
|
+
const normalizedType = `${attachableType ?? ''}`.toLowerCase().includes('trailer') ? 'fleet-ops:trailer' : 'fleet-ops:vehicle';
|
|
333
|
+
const response = await this.fetch.post(`devices/${device.id}/attach`, { attachable_type: normalizedType, attachable: selectedAsset.id });
|
|
353
334
|
|
|
354
|
-
this.applyDeviceAttachment(device,
|
|
335
|
+
this.applyDeviceAttachment(device, selectedAsset, response?.device, normalizedType);
|
|
355
336
|
this.selectedDevice = null;
|
|
356
|
-
this.notifications.success(this.intl.t('device.prompts.attach-to-
|
|
337
|
+
this.notifications.success(this.intl.t('device.prompts.attach-to-asset-success'));
|
|
357
338
|
}
|
|
358
339
|
|
|
359
340
|
@action detachDevice(device) {
|
|
@@ -369,7 +350,7 @@ export default class ConnectivityTelematicsDetailsAttachmentsController extends
|
|
|
369
350
|
const response = await this.fetch.post(`devices/${device.id}/detach`);
|
|
370
351
|
|
|
371
352
|
this.applyDeviceDetachment(device, response?.device);
|
|
372
|
-
this.notifications.success(this.intl.t('device.prompts.detach-from-
|
|
353
|
+
this.notifications.success(this.intl.t('device.prompts.detach-from-asset-success'));
|
|
373
354
|
modal.done();
|
|
374
355
|
} catch (error) {
|
|
375
356
|
this.notifications.serverError(error);
|
|
@@ -379,16 +360,16 @@ export default class ConnectivityTelematicsDetailsAttachmentsController extends
|
|
|
379
360
|
});
|
|
380
361
|
}
|
|
381
362
|
|
|
382
|
-
|
|
383
|
-
return device.attached_to_name ?? device.attachable?.display_name ?? device.attachable?.name ?? '
|
|
363
|
+
getDeviceAssetName(device) {
|
|
364
|
+
return device.attached_to_name ?? device.attachable?.display_name ?? device.attachable?.name ?? this.intl.t('device.attachment.unknown');
|
|
384
365
|
}
|
|
385
366
|
|
|
386
|
-
applyDeviceAttachment(device,
|
|
367
|
+
applyDeviceAttachment(device, selectedAsset, serverDevice = {}, attachableType = 'fleet-ops:vehicle') {
|
|
387
368
|
this.updateDevice(device, {
|
|
388
|
-
attachable_uuid: serverDevice.attachable_uuid ??
|
|
389
|
-
attachable_type: serverDevice.attachable_type ??
|
|
390
|
-
attached_to_name: serverDevice.attached_to_name ??
|
|
391
|
-
attachable: serverDevice.attachable ??
|
|
369
|
+
attachable_uuid: serverDevice.attachable_uuid ?? selectedAsset.id,
|
|
370
|
+
attachable_type: serverDevice.attachable_type ?? attachableType,
|
|
371
|
+
attached_to_name: serverDevice.attached_to_name ?? selectedAsset.displayName ?? selectedAsset.display_name ?? selectedAsset.name,
|
|
372
|
+
attachable: serverDevice.attachable ?? selectedAsset,
|
|
392
373
|
});
|
|
393
374
|
}
|
|
394
375
|
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import Controller from '@ember/controller';
|
|
2
2
|
import { inject as service } from '@ember/service';
|
|
3
3
|
import { tracked } from '@glimmer/tracking';
|
|
4
|
+
import { action } from '@ember/object';
|
|
4
5
|
|
|
5
6
|
export default class ManagementContactsIndexController extends Controller {
|
|
6
7
|
@service contactActions;
|
|
7
8
|
@service tableContext;
|
|
8
9
|
@service intl;
|
|
10
|
+
@service appCache;
|
|
9
11
|
|
|
10
12
|
/** query params */
|
|
11
13
|
@tracked queryParams = ['page', 'limit', 'sort', 'query', 'public_id', 'internal_id', 'created_by', 'updated_by', 'status', 'title', 'email', 'phone'];
|
|
@@ -19,10 +21,35 @@ export default class ManagementContactsIndexController extends Controller {
|
|
|
19
21
|
@tracked phone;
|
|
20
22
|
@tracked status;
|
|
21
23
|
@tracked table;
|
|
24
|
+
@tracked layout = this.appCache.get(this.layoutCacheKey, 'table');
|
|
25
|
+
|
|
26
|
+
/** cache key that remembers the chosen layout per listing */
|
|
27
|
+
get layoutCacheKey() {
|
|
28
|
+
return 'fleetops:contacts:layout';
|
|
29
|
+
}
|
|
22
30
|
|
|
23
31
|
/** action buttons */
|
|
24
32
|
get actionButtons() {
|
|
25
33
|
return [
|
|
34
|
+
{
|
|
35
|
+
component: 'dropdown-button',
|
|
36
|
+
icon: 'display',
|
|
37
|
+
size: 'xs',
|
|
38
|
+
items: [
|
|
39
|
+
{
|
|
40
|
+
label: this.intl.t('common.table-view'),
|
|
41
|
+
icon: 'table-list',
|
|
42
|
+
onClick: () => this.setLayout('table'),
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
label: this.intl.t('common.grid-view'),
|
|
46
|
+
icon: 'grip',
|
|
47
|
+
onClick: () => this.setLayout('grid'),
|
|
48
|
+
},
|
|
49
|
+
],
|
|
50
|
+
renderInPlace: true,
|
|
51
|
+
helpText: this.intl.t('common.change-layout'),
|
|
52
|
+
},
|
|
26
53
|
{
|
|
27
54
|
icon: 'refresh',
|
|
28
55
|
onClick: this.contactActions.refresh,
|
|
@@ -199,4 +226,9 @@ export default class ManagementContactsIndexController extends Controller {
|
|
|
199
226
|
},
|
|
200
227
|
];
|
|
201
228
|
}
|
|
229
|
+
|
|
230
|
+
@action setLayout(layout) {
|
|
231
|
+
this.layout = layout;
|
|
232
|
+
this.appCache.set(this.layoutCacheKey, layout);
|
|
233
|
+
}
|
|
202
234
|
}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import Controller from '@ember/controller';
|
|
2
|
+
import { inject as service } from '@ember/service';
|
|
3
|
+
import { isArray } from '@ember/array';
|
|
4
|
+
|
|
5
|
+
export default class ManagementTrailersIndexDetailsController extends Controller {
|
|
6
|
+
@service trailerActions;
|
|
7
|
+
@service('universe/menu-service') menuService;
|
|
8
|
+
@service hostRouter;
|
|
9
|
+
@service intl;
|
|
10
|
+
|
|
11
|
+
get tabs() {
|
|
12
|
+
const registeredTabs = this.menuService.getMenuItems('fleet-ops:component:trailer:details');
|
|
13
|
+
|
|
14
|
+
return [
|
|
15
|
+
{ id: 'index', route: 'management.trailers.index.details.index', label: this.intl.t('trailer.tabs.overview') },
|
|
16
|
+
{ id: 'positions', route: 'management.trailers.index.details.positions', label: this.intl.t('trailer.tabs.positions') },
|
|
17
|
+
{ id: 'devices', route: 'management.trailers.index.details.devices', label: this.intl.t('trailer.tabs.devices') },
|
|
18
|
+
{ id: 'equipment', route: 'management.trailers.index.details.equipment', label: this.intl.t('trailer.tabs.equipment') },
|
|
19
|
+
{ id: 'connections', route: 'management.trailers.index.details.connections', label: this.intl.t('trailer.tabs.connections') },
|
|
20
|
+
{ id: 'schedules', route: 'management.trailers.index.details.schedules', label: this.intl.t('trailer.tabs.schedules') },
|
|
21
|
+
{ id: 'work-orders', route: 'management.trailers.index.details.work-orders', label: this.intl.t('trailer.tabs.work-orders') },
|
|
22
|
+
{ id: 'maintenance-history', route: 'management.trailers.index.details.maintenance-history', label: this.intl.t('trailer.tabs.maintenance') },
|
|
23
|
+
...(isArray(registeredTabs) ? registeredTabs : []),
|
|
24
|
+
];
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
get isAttached() {
|
|
28
|
+
return this.model?.isAttached ?? this.model?.attachment_state === 'attached';
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
get actionButtons() {
|
|
32
|
+
return [
|
|
33
|
+
{
|
|
34
|
+
icon: 'pencil',
|
|
35
|
+
fn: () => this.hostRouter.transitionTo('console.fleet-ops.management.trailers.index.edit', this.model),
|
|
36
|
+
permission: 'fleet-ops update trailer',
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
// Actions dropdown — mirrors the row-level actions from the trailers index table
|
|
40
|
+
icon: 'ellipsis-h',
|
|
41
|
+
iconPrefix: 'fas',
|
|
42
|
+
renderInPlace: true,
|
|
43
|
+
items: [
|
|
44
|
+
{
|
|
45
|
+
text: this.intl.t('trailer.actions.locate'),
|
|
46
|
+
icon: 'location-dot',
|
|
47
|
+
fn: () => this.trailerActions.locate(this.model),
|
|
48
|
+
permission: 'fleet-ops view trailer',
|
|
49
|
+
},
|
|
50
|
+
...(this.isAttached
|
|
51
|
+
? [
|
|
52
|
+
{
|
|
53
|
+
text: this.intl.t('trailer.actions.detach-vehicle'),
|
|
54
|
+
icon: 'unlink',
|
|
55
|
+
fn: () => this.trailerActions.detachVehicle(this.model),
|
|
56
|
+
permission: 'fleet-ops detach-vehicle-for trailer',
|
|
57
|
+
},
|
|
58
|
+
]
|
|
59
|
+
: [
|
|
60
|
+
{
|
|
61
|
+
text: this.intl.t('trailer.actions.attach-vehicle'),
|
|
62
|
+
icon: 'link',
|
|
63
|
+
fn: () => this.trailerActions.attachVehicle(this.model),
|
|
64
|
+
permission: 'fleet-ops attach-vehicle-for trailer',
|
|
65
|
+
},
|
|
66
|
+
]),
|
|
67
|
+
{
|
|
68
|
+
text: this.intl.t('trailer.actions.attach-device'),
|
|
69
|
+
icon: 'microchip',
|
|
70
|
+
fn: () => this.trailerActions.attachDevice(this.model),
|
|
71
|
+
permission: 'fleet-ops attach-device-for trailer',
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
text: this.intl.t('trailer.actions.attach-equipment'),
|
|
75
|
+
icon: 'toolbox',
|
|
76
|
+
fn: () => this.trailerActions.attachEquipment(this.model),
|
|
77
|
+
permission: 'fleet-ops attach-equipment-for trailer',
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
separator: true,
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
text: this.intl.t('trailer.actions.schedule-maintenance'),
|
|
84
|
+
icon: 'calendar-check',
|
|
85
|
+
fn: () => this.trailerActions.scheduleMaintenance(this.model),
|
|
86
|
+
permission: 'fleet-ops create maintenance-schedule',
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
text: this.intl.t('trailer.actions.create-work-order'),
|
|
90
|
+
icon: 'clipboard-list',
|
|
91
|
+
fn: () => this.trailerActions.createWorkOrder(this.model),
|
|
92
|
+
permission: 'fleet-ops create work-order',
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
text: this.intl.t('trailer.actions.log-maintenance'),
|
|
96
|
+
icon: 'wrench',
|
|
97
|
+
fn: () => this.trailerActions.logMaintenance(this.model),
|
|
98
|
+
permission: 'fleet-ops create maintenance',
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
separator: true,
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
text: this.intl.t('common.delete-resource', { resource: this.intl.t('resource.trailer') }),
|
|
105
|
+
icon: 'trash',
|
|
106
|
+
fn: () =>
|
|
107
|
+
this.trailerActions.delete(this.model, {
|
|
108
|
+
onConfirm: () => {
|
|
109
|
+
this.hostRouter.transitionTo('console.fleet-ops.management.trailers.index');
|
|
110
|
+
},
|
|
111
|
+
}),
|
|
112
|
+
permission: 'fleet-ops delete trailer',
|
|
113
|
+
class: 'text-red-500 hover:text-red-600',
|
|
114
|
+
},
|
|
115
|
+
],
|
|
116
|
+
},
|
|
117
|
+
];
|
|
118
|
+
}
|
|
119
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import Controller from '@ember/controller';
|
|
2
|
+
import { tracked } from '@glimmer/tracking';
|
|
3
|
+
import { inject as service } from '@ember/service';
|
|
4
|
+
import { action } from '@ember/object';
|
|
5
|
+
import { task } from 'ember-concurrency';
|
|
6
|
+
|
|
7
|
+
export default class ManagementTrailersIndexEditController extends Controller {
|
|
8
|
+
@service hostRouter;
|
|
9
|
+
@service intl;
|
|
10
|
+
@service notifications;
|
|
11
|
+
@service modalsManager;
|
|
12
|
+
@service events;
|
|
13
|
+
@tracked overlay;
|
|
14
|
+
@tracked actionButtons = [
|
|
15
|
+
{
|
|
16
|
+
icon: 'eye',
|
|
17
|
+
fn: this.view,
|
|
18
|
+
},
|
|
19
|
+
];
|
|
20
|
+
|
|
21
|
+
@task *save(trailer) {
|
|
22
|
+
try {
|
|
23
|
+
yield trailer.save();
|
|
24
|
+
this.events.trackResourceUpdated(trailer);
|
|
25
|
+
this.overlay?.close();
|
|
26
|
+
|
|
27
|
+
yield this.hostRouter.transitionTo('console.fleet-ops.management.trailers.index.details', trailer);
|
|
28
|
+
this.notifications.success(
|
|
29
|
+
this.intl.t('common.resource-updated-success', {
|
|
30
|
+
resource: this.intl.t('resource.trailer'),
|
|
31
|
+
resourceName: trailer.displayName,
|
|
32
|
+
})
|
|
33
|
+
);
|
|
34
|
+
} catch (error) {
|
|
35
|
+
this.notifications.serverError(error);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
@action cancel() {
|
|
40
|
+
if (this.model.hasDirtyAttributes) {
|
|
41
|
+
return this.#confirmContinueWithUnsavedChanges(this.model);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return this.hostRouter.transitionTo('console.fleet-ops.management.trailers.index');
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
@action view() {
|
|
48
|
+
if (this.model.hasDirtyAttributes) {
|
|
49
|
+
return this.#confirmContinueWithUnsavedChanges(this.model);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return this.hostRouter.transitionTo('console.fleet-ops.management.trailers.index.details', this.model);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
#confirmContinueWithUnsavedChanges(trailer, options = {}) {
|
|
56
|
+
return this.modalsManager.confirm({
|
|
57
|
+
title: this.intl.t('common.continue-without-saving'),
|
|
58
|
+
body: this.intl.t('common.continue-without-saving-prompt', { resource: this.intl.t('resource.trailer') }),
|
|
59
|
+
acceptButtonText: this.intl.t('common.continue'),
|
|
60
|
+
confirm: async () => {
|
|
61
|
+
trailer.rollbackAttributes();
|
|
62
|
+
await this.hostRouter.transitionTo('console.fleet-ops.management.trailers.index.details', trailer);
|
|
63
|
+
},
|
|
64
|
+
...options,
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import Controller from '@ember/controller';
|
|
2
|
+
import { tracked } from '@glimmer/tracking';
|
|
3
|
+
import { inject as service } from '@ember/service';
|
|
4
|
+
import { action } from '@ember/object';
|
|
5
|
+
import { task } from 'ember-concurrency';
|
|
6
|
+
|
|
7
|
+
const DEFAULT_PROPERTIES = { status: 'available', asset_class: 'trailer', measurement_system: 'metric' };
|
|
8
|
+
|
|
9
|
+
export default class ManagementTrailersIndexNewController extends Controller {
|
|
10
|
+
@service store;
|
|
11
|
+
@service hostRouter;
|
|
12
|
+
@service intl;
|
|
13
|
+
@service notifications;
|
|
14
|
+
@service events;
|
|
15
|
+
@tracked overlay;
|
|
16
|
+
@tracked trailer = this.store.createRecord('trailer', DEFAULT_PROPERTIES);
|
|
17
|
+
|
|
18
|
+
@task *save(trailer) {
|
|
19
|
+
try {
|
|
20
|
+
yield trailer.save();
|
|
21
|
+
this.events.trackResourceCreated(trailer);
|
|
22
|
+
this.overlay?.close();
|
|
23
|
+
|
|
24
|
+
// Transition with the record so the details route renders immediately from the
|
|
25
|
+
// create response; refreshing afterwards reloads the index behind the panel.
|
|
26
|
+
yield this.hostRouter.transitionTo('console.fleet-ops.management.trailers.index.details', trailer);
|
|
27
|
+
yield this.hostRouter.refresh();
|
|
28
|
+
this.notifications.success(
|
|
29
|
+
this.intl.t('common.resource-created-success-name', {
|
|
30
|
+
resource: this.intl.t('resource.trailer'),
|
|
31
|
+
resourceName: trailer.displayName,
|
|
32
|
+
})
|
|
33
|
+
);
|
|
34
|
+
this.resetForm();
|
|
35
|
+
} catch (error) {
|
|
36
|
+
this.notifications.serverError(error);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
@action resetForm() {
|
|
41
|
+
this.trailer = this.store.createRecord('trailer', DEFAULT_PROPERTIES);
|
|
42
|
+
}
|
|
43
|
+
}
|