@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.
Files changed (289) hide show
  1. package/RELEASE.md +7 -6
  2. package/addon/components/attachment-list.hbs +65 -0
  3. package/addon/components/attachment-list.js +8 -0
  4. package/addon/components/cell/attached-vehicle.hbs +1 -1
  5. package/addon/components/cell/attached-vehicle.js +3 -3
  6. package/addon/components/cell/driver-identity.js +4 -4
  7. package/addon/components/cell/driver-name.hbs +1 -1
  8. package/addon/components/cell/translated-value.hbs +9 -0
  9. package/addon/components/cell/translated-value.js +57 -0
  10. package/addon/components/contact/card.hbs +58 -0
  11. package/addon/components/contact/card.js +19 -0
  12. package/addon/components/contact/form.hbs +1 -1
  13. package/addon/components/contact/panel-header.hbs +1 -1
  14. package/addon/components/customer/form.hbs +2 -2
  15. package/addon/components/device/manager.hbs +26 -28
  16. package/addon/components/device/manager.js +28 -2
  17. package/addon/components/device/panel-tabs/vehicle.hbs +13 -13
  18. package/addon/components/device/panel-tabs/vehicle.js +8 -0
  19. package/addon/components/driver/card.hbs +24 -13
  20. package/addon/components/driver/card.js +20 -6
  21. package/addon/components/driver/form.hbs +3 -3
  22. package/addon/components/driver/panel-header.hbs +2 -2
  23. package/addon/components/driver/pill.hbs +2 -2
  24. package/addon/components/equipment/form.js +11 -4
  25. package/addon/components/equipment/pill.hbs +20 -0
  26. package/addon/components/equipment/pill.js +3 -0
  27. package/addon/components/filter/multi-model.hbs +19 -0
  28. package/addon/components/filter/multi-model.js +90 -0
  29. package/addon/components/fleet/driver-listing.hbs +1 -1
  30. package/addon/components/fleet/vehicle-listing.hbs +1 -1
  31. package/addon/components/fleet-panel/driver-listing.hbs +1 -1
  32. package/addon/components/fleet-panel/vehicle-listing.hbs +1 -1
  33. package/addon/components/layout/fleet-ops-sidebar.js +9 -7
  34. package/addon/components/maintenance/form.js +12 -4
  35. package/addon/components/maintenance-schedule/form.js +13 -7
  36. package/addon/components/map/leaflet-live-map.hbs +52 -0
  37. package/addon/components/map/order-list-overlay/order.hbs +4 -4
  38. package/addon/components/modals/attach-equipment.hbs +22 -0
  39. package/addon/components/modals/attach-equipment.js +3 -0
  40. package/addon/components/modals/attach-telematic-device.hbs +13 -8
  41. package/addon/components/modals/attach-telematic-device.js +11 -1
  42. package/addon/components/modals/attach-trailer.hbs +30 -0
  43. package/addon/components/modals/attach-trailer.js +3 -0
  44. package/addon/components/modals/contact-form.hbs +2 -2
  45. package/addon/components/modals/convert-customer-to-vendor.hbs +1 -1
  46. package/addon/components/modals/driver-form.hbs +2 -2
  47. package/addon/components/modals/select-trailer.hbs +35 -0
  48. package/addon/components/modals/select-trailer.js +3 -0
  49. package/addon/components/modals/vehicle-form.hbs +2 -2
  50. package/addon/components/orchestrator/resource-panel.hbs +2 -2
  51. package/addon/components/order/customer-avatar-stack.hbs +2 -2
  52. package/addon/components/order/details/detail.hbs +4 -4
  53. package/addon/components/order/details/payload.hbs +2 -2
  54. package/addon/components/order/kanban-card.hbs +4 -4
  55. package/addon/components/order-list-overlay/order.hbs +4 -4
  56. package/addon/components/trailer/card.hbs +68 -0
  57. package/addon/components/trailer/card.js +22 -0
  58. package/addon/components/trailer/details/connections.hbs +57 -0
  59. package/addon/components/trailer/details/connections.js +59 -0
  60. package/addon/components/trailer/details/equipment.hbs +25 -0
  61. package/addon/components/trailer/details/equipment.js +52 -0
  62. package/addon/components/trailer/details/maintenance-history.hbs +47 -0
  63. package/addon/components/trailer/details/maintenance-history.js +40 -0
  64. package/addon/components/trailer/details/schedules.hbs +45 -0
  65. package/addon/components/trailer/details/schedules.js +40 -0
  66. package/addon/components/trailer/details/work-orders.hbs +47 -0
  67. package/addon/components/trailer/details/work-orders.js +40 -0
  68. package/addon/components/trailer/details.hbs +399 -0
  69. package/addon/components/trailer/details.js +118 -0
  70. package/addon/components/trailer/form.hbs +447 -0
  71. package/addon/components/trailer/form.js +165 -0
  72. package/addon/components/trailer/panel-header.hbs +45 -0
  73. package/addon/components/trailer/panel-header.js +3 -0
  74. package/addon/components/trailer/pill.hbs +21 -0
  75. package/addon/components/trailer/pill.js +3 -0
  76. package/addon/components/vehicle/card.hbs +42 -11
  77. package/addon/components/vehicle/card.js +31 -0
  78. package/addon/components/vehicle/details/equipment.hbs +25 -0
  79. package/addon/components/vehicle/details/equipment.js +55 -0
  80. package/addon/components/vehicle/details/trailers.hbs +35 -0
  81. package/addon/components/vehicle/details/trailers.js +55 -0
  82. package/addon/components/vehicle/form.hbs +2 -2
  83. package/addon/components/vehicle/panel-header.hbs +2 -2
  84. package/addon/components/vehicle/pill.hbs +2 -2
  85. package/addon/components/vendor/card.hbs +58 -0
  86. package/addon/components/vendor/card.js +6 -0
  87. package/addon/components/vendor/panel-header.hbs +2 -2
  88. package/addon/components/vendor/personnel-manager.hbs +2 -2
  89. package/addon/components/work-order/form.js +12 -4
  90. package/addon/controllers/connectivity/devices/index/details/vehicle.js +11 -0
  91. package/addon/controllers/connectivity/devices/index/details.js +3 -3
  92. package/addon/controllers/connectivity/devices/index.js +1 -0
  93. package/addon/controllers/connectivity/telematics/details/attachments.js +28 -47
  94. package/addon/controllers/connectivity/telematics/details/devices.js +1 -0
  95. package/addon/controllers/management/contacts/customers.js +4 -0
  96. package/addon/controllers/management/contacts/index.js +32 -0
  97. package/addon/controllers/management/trailers/index/details.js +119 -0
  98. package/addon/controllers/management/trailers/index/edit.js +67 -0
  99. package/addon/controllers/management/trailers/index/new.js +43 -0
  100. package/addon/controllers/management/trailers/index.js +599 -0
  101. package/addon/controllers/management/vehicles/index/details.js +16 -0
  102. package/addon/controllers/management/vehicles/index.js +78 -4
  103. package/addon/controllers/management/vendors/index.js +32 -0
  104. package/addon/controllers/operations/orders/index.js +3 -1
  105. package/addon/controllers/settings/custom-fields.js +8 -0
  106. package/addon/extension.js +7 -0
  107. package/addon/helpers/placeholder-image.js +6 -0
  108. package/addon/helpers/resource-image.js +10 -0
  109. package/addon/helpers/trailer-placeholder-image.js +6 -0
  110. package/addon/routes/management/trailers/index/details/connections.js +2 -0
  111. package/addon/routes/management/trailers/index/details/devices.js +2 -0
  112. package/addon/routes/management/trailers/index/details/equipment.js +2 -0
  113. package/addon/routes/management/trailers/index/details/index.js +2 -0
  114. package/addon/routes/management/trailers/index/details/maintenance-history.js +2 -0
  115. package/addon/routes/management/trailers/index/details/positions.js +2 -0
  116. package/addon/routes/management/trailers/index/details/schedules.js +2 -0
  117. package/addon/routes/management/trailers/index/details/work-orders.js +2 -0
  118. package/addon/routes/management/trailers/index/details.js +30 -0
  119. package/addon/routes/management/trailers/index/edit.js +23 -0
  120. package/addon/routes/management/trailers/index/new.js +14 -0
  121. package/addon/routes/management/trailers/index.js +42 -0
  122. package/addon/routes/management/vehicles/index/details/trailers.js +2 -0
  123. package/addon/routes/management/vehicles/index.js +7 -1
  124. package/addon/routes.js +17 -0
  125. package/addon/services/device-actions.js +26 -16
  126. package/addon/services/trailer-actions.js +394 -0
  127. package/addon/services/vehicle-actions.js +111 -0
  128. package/addon/styles/fleetops-engine.css +349 -0
  129. package/addon/templates/connectivity/devices/index/details/vehicle.hbs +19 -19
  130. package/addon/templates/connectivity/telematics/details/attachments.hbs +15 -15
  131. package/addon/templates/management/contacts/customers.hbs +48 -29
  132. package/addon/templates/management/contacts/index.hbs +52 -33
  133. package/addon/templates/management/trailers/index/details/connections.hbs +1 -0
  134. package/addon/templates/management/trailers/index/details/devices.hbs +1 -0
  135. package/addon/templates/management/trailers/index/details/equipment.hbs +1 -0
  136. package/addon/templates/management/trailers/index/details/index.hbs +1 -0
  137. package/addon/templates/management/trailers/index/details/maintenance-history.hbs +1 -0
  138. package/addon/templates/management/trailers/index/details/positions.hbs +1 -0
  139. package/addon/templates/management/trailers/index/details/schedules.hbs +1 -0
  140. package/addon/templates/management/trailers/index/details/work-orders.hbs +1 -0
  141. package/addon/templates/management/trailers/index/details.hbs +15 -0
  142. package/addon/templates/management/trailers/index/edit.hbs +12 -0
  143. package/addon/templates/management/trailers/index/new.hbs +11 -0
  144. package/addon/templates/management/trailers/index.hbs +67 -0
  145. package/addon/templates/management/vehicles/index/details/equipment.hbs +1 -1
  146. package/addon/templates/management/vehicles/index/details/trailers.hbs +1 -0
  147. package/addon/templates/management/vehicles/index/details.hbs +1 -1
  148. package/addon/templates/management/vendors/index.hbs +66 -32
  149. package/addon/utils/device-table-columns.js +10 -6
  150. package/addon/utils/live-map-card-content.js +56 -0
  151. package/addon/utils/placeholder-images.js +71 -0
  152. package/addon/utils/trailer-placeholder-image.js +11 -0
  153. package/app/components/attachment-list.js +1 -0
  154. package/app/components/cell/translated-value.js +1 -0
  155. package/app/components/contact/card.js +1 -0
  156. package/app/components/equipment/pill.js +1 -0
  157. package/app/components/filter/multi-model.js +1 -0
  158. package/app/components/modals/attach-equipment.js +1 -0
  159. package/app/components/modals/attach-trailer.js +1 -0
  160. package/app/components/modals/select-trailer.js +1 -0
  161. package/app/components/trailer/card.js +1 -0
  162. package/app/components/trailer/details/connections.js +1 -0
  163. package/app/components/trailer/details/equipment.js +1 -0
  164. package/app/components/trailer/details/maintenance-history.js +1 -0
  165. package/app/components/trailer/details/schedules.js +1 -0
  166. package/app/components/trailer/details/work-orders.js +1 -0
  167. package/app/components/trailer/details.js +1 -0
  168. package/app/components/trailer/form.js +1 -0
  169. package/app/components/trailer/panel-header.js +1 -0
  170. package/app/components/trailer/pill.js +1 -0
  171. package/app/components/vehicle/details/equipment.js +1 -0
  172. package/app/components/vehicle/details/trailers.js +1 -0
  173. package/app/components/vendor/card.js +1 -0
  174. package/app/controllers/management/trailers/index/details.js +1 -0
  175. package/app/controllers/management/trailers/index/edit.js +1 -0
  176. package/app/controllers/management/trailers/index/new.js +1 -0
  177. package/app/controllers/management/trailers/index.js +1 -0
  178. package/app/helpers/placeholder-image.js +1 -0
  179. package/app/helpers/resource-image.js +1 -0
  180. package/app/helpers/trailer-placeholder-image.js +1 -0
  181. package/app/routes/management/trailers/index/details/connections.js +1 -0
  182. package/app/routes/management/trailers/index/details/devices.js +1 -0
  183. package/app/routes/management/trailers/index/details/equipment.js +1 -0
  184. package/app/routes/management/trailers/index/details/index.js +1 -0
  185. package/app/routes/management/trailers/index/details/maintenance-history.js +1 -0
  186. package/app/routes/management/trailers/index/details/positions.js +1 -0
  187. package/app/routes/management/trailers/index/details/schedules.js +1 -0
  188. package/app/routes/management/trailers/index/details/work-orders.js +1 -0
  189. package/app/routes/management/trailers/index/details.js +1 -0
  190. package/app/routes/management/trailers/index/edit.js +1 -0
  191. package/app/routes/management/trailers/index/new.js +1 -0
  192. package/app/routes/management/trailers/index.js +1 -0
  193. package/app/routes/management/vehicles/index/details/trailers.js +1 -0
  194. package/app/services/trailer-actions.js +1 -0
  195. package/app/templates/management/trailers/index/details/connections.js +1 -0
  196. package/app/templates/management/trailers/index/details/devices.js +1 -0
  197. package/app/templates/management/trailers/index/details/equipment.js +1 -0
  198. package/app/templates/management/trailers/index/details/index.js +1 -0
  199. package/app/templates/management/trailers/index/details/maintenance-history.js +1 -0
  200. package/app/templates/management/trailers/index/details/positions.js +1 -0
  201. package/app/templates/management/trailers/index/details/schedules.js +1 -0
  202. package/app/templates/management/trailers/index/details/work-orders.js +1 -0
  203. package/app/templates/management/trailers/index/details.js +1 -0
  204. package/app/templates/management/trailers/index/edit.js +1 -0
  205. package/app/templates/management/trailers/index/new.js +1 -0
  206. package/app/templates/management/trailers/index.js +1 -0
  207. package/app/templates/management/vehicles/index/details/trailers.js +1 -0
  208. package/composer.json +1 -1
  209. package/extension.json +1 -1
  210. package/package.json +1 -1
  211. package/server/migrations/2026_09_03_000001_add_first_class_trailer_columns_to_assets_table.php +58 -0
  212. package/server/migrations/2026_09_03_000002_create_asset_connections_table.php +43 -0
  213. package/server/migrations/2026_09_03_000003_create_device_installations_table.php +33 -0
  214. package/server/src/Auth/Schemas/FleetOps.php +7 -0
  215. package/server/src/Events/TrailerLocationChanged.php +70 -0
  216. package/server/src/Exceptions/DeviceAlreadyAttachedException.php +18 -0
  217. package/server/src/Exports/TrailerExport.php +31 -0
  218. package/server/src/Http/Controllers/Api/v1/Concerns/ResolvesFleetOpsApiResources.php +8 -2
  219. package/server/src/Http/Controllers/Api/v1/DeviceController.php +22 -15
  220. package/server/src/Http/Controllers/Api/v1/EquipmentController.php +47 -0
  221. package/server/src/Http/Controllers/Api/v1/TrailerController.php +362 -0
  222. package/server/src/Http/Controllers/Api/v1/VehicleController.php +1 -0
  223. package/server/src/Http/Controllers/Internal/v1/DeviceController.php +3 -0
  224. package/server/src/Http/Controllers/Internal/v1/LiveController.php +1 -1
  225. package/server/src/Http/Controllers/Internal/v1/SearchController.php +16 -0
  226. package/server/src/Http/Controllers/Internal/v1/TrailerController.php +360 -0
  227. package/server/src/Http/Controllers/Internal/v1/VehicleController.php +74 -0
  228. package/server/src/Http/Filter/EquipmentFilter.php +51 -0
  229. package/server/src/Http/Filter/OrderFilter.php +15 -0
  230. package/server/src/Http/Filter/TrailerFilter.php +269 -0
  231. package/server/src/Http/Filter/VehicleFilter.php +70 -3
  232. package/server/src/Http/Requests/CreateDeviceRequest.php +1 -1
  233. package/server/src/Http/Requests/CreateEquipmentRequest.php +1 -1
  234. package/server/src/Http/Requests/CreateTrailerRequest.php +54 -0
  235. package/server/src/Http/Requests/UpdateTrailerRequest.php +7 -0
  236. package/server/src/Http/Resources/v1/AssetConnection.php +90 -0
  237. package/server/src/Http/Resources/v1/Concerns/ResolvesPublicRelationFields.php +29 -3
  238. package/server/src/Http/Resources/v1/Device.php +3 -1
  239. package/server/src/Http/Resources/v1/Equipment.php +3 -1
  240. package/server/src/Http/Resources/v1/Fleet.php +3 -1
  241. package/server/src/Http/Resources/v1/Index/Vehicle.php +10 -0
  242. package/server/src/Http/Resources/v1/Trailer.php +199 -0
  243. package/server/src/Http/Resources/v1/Vehicle.php +2 -0
  244. package/server/src/Http/Resources/v1/VehicleWithoutDriver.php +3 -0
  245. package/server/src/Imports/TrailerImport.php +33 -0
  246. package/server/src/Models/Asset.php +39 -10
  247. package/server/src/Models/AssetConnection.php +43 -0
  248. package/server/src/Models/Device.php +39 -8
  249. package/server/src/Models/DeviceInstallation.php +27 -0
  250. package/server/src/Models/Equipment.php +2 -0
  251. package/server/src/Models/Trailer.php +181 -0
  252. package/server/src/Models/Vehicle.php +13 -0
  253. package/server/src/Providers/FleetOpsServiceProvider.php +4 -2
  254. package/server/src/Support/Ai/FleetOpsAiQueryResources.php +22 -0
  255. package/server/src/Support/Reporting/FleetOpsReportSchema.php +38 -0
  256. package/server/src/Support/Telematics/TelematicService.php +35 -0
  257. package/server/src/Support/TrailerSummary.php +35 -0
  258. package/server/src/routes.php +29 -0
  259. package/server/tests/CompactResourceSerializationTest.php +36 -0
  260. package/server/tests/ControllerFilterContractsTest.php +29 -0
  261. package/server/tests/Feature/Http/Api/DeviceControllerContractsTest.php +30 -13
  262. package/server/tests/Feature/Http/Api/TrailerControllerLifecycleTest.php +640 -0
  263. package/server/tests/Feature/Http/Api/VehiclePublicContractTest.php +23 -0
  264. package/server/tests/Feature/Http/Internal/DeviceControllerContractsTest.php +20 -5
  265. package/server/tests/Feature/Http/Internal/LiveControllerEndpointsTest.php +19 -0
  266. package/server/tests/ModelAccessorContractsTest.php +10 -0
  267. package/server/tests/OrderFilterExecutionTest.php +5 -0
  268. package/server/tests/PublicApiControllerInputContractsTest.php +11 -0
  269. package/server/tests/PublicFleetOpsRestEndpointsTest.php +15 -3
  270. package/server/tests/ReportSchemaContractsTest.php +4 -0
  271. package/server/tests/TelematicsHardeningTest.php +4 -2
  272. package/server/tests/TrailerSupportCoverageTest.php +524 -0
  273. package/server/tests/Unit/Http/Resources/FleetResourceTest.php +17 -0
  274. package/server/tests/Unit/Http/Resources/IndexVehicleResourceTest.php +35 -0
  275. package/server/tests/Unit/Models/EquipmentTest.php +22 -0
  276. package/server/tests/Unit/Models/ModelLookupFallbackSeamsTest.php +7 -3
  277. package/server/tests/Unit/Models/TrailerTest.php +204 -0
  278. package/server/tests/Unit/Support/Telematics/TelematicServiceTelemetryTest.php +93 -0
  279. package/server/tests/VehicleControllerHelperContractsTest.php +14 -0
  280. package/server/tests/VehicleResourceContractsTest.php +39 -0
  281. package/translations/ar-ae.yml +396 -0
  282. package/translations/bg-bg.yaml +424 -0
  283. package/translations/en-us.yaml +423 -0
  284. package/translations/es-pa.yaml +425 -0
  285. package/translations/fr-fr.yaml +424 -0
  286. package/translations/mn-mn.yaml +424 -0
  287. package/translations/pt-br.yaml +424 -0
  288. package/translations/ru-ru.yaml +424 -0
  289. package/translations/vi-vn.yaml +435 -0
@@ -0,0 +1,599 @@
1
+ import Controller from '@ember/controller';
2
+ import { action } from '@ember/object';
3
+ import { inject as service } from '@ember/service';
4
+ import { tracked } from '@glimmer/tracking';
5
+ import { TRAILER_TYPES, TRAILER_STATUSES, TRAILER_OWNERSHIP_TYPES } from '../../../components/trailer/form';
6
+
7
+ export default class ManagementTrailersIndexController extends Controller {
8
+ @service trailerActions;
9
+ @service vehicleActions;
10
+ @service vendorActions;
11
+ @service tableContext;
12
+ @service intl;
13
+ @service appCache;
14
+ @service store;
15
+
16
+ /** query params */
17
+ @tracked queryParams = [
18
+ 'page',
19
+ 'limit',
20
+ 'sort',
21
+ 'query',
22
+ 'public_id',
23
+ 'name',
24
+ 'code',
25
+ 'trailer_type',
26
+ 'status',
27
+ 'attachment_state',
28
+ 'vehicle',
29
+ 'connectivity_status',
30
+ 'trailer_make',
31
+ 'trailer_model',
32
+ 'trailer_year',
33
+ 'plate_number',
34
+ 'vin',
35
+ 'serial_number',
36
+ 'vendor',
37
+ 'ownership_type',
38
+ 'refrigerated',
39
+ 'device',
40
+ 'last_online_at',
41
+ 'created_at',
42
+ 'updated_at',
43
+ ];
44
+ @tracked query = null;
45
+ @tracked page = 1;
46
+ @tracked limit;
47
+ @tracked sort = '-created_at';
48
+ @tracked public_id;
49
+ @tracked name;
50
+ @tracked code;
51
+ @tracked trailer_type;
52
+ @tracked status;
53
+ @tracked attachment_state;
54
+ @tracked vehicle;
55
+ @tracked connectivity_status;
56
+ @tracked trailer_make;
57
+ @tracked trailer_model;
58
+ @tracked trailer_year;
59
+ @tracked plate_number;
60
+ @tracked vin;
61
+ @tracked serial_number;
62
+ @tracked vendor;
63
+ @tracked ownership_type;
64
+ @tracked refrigerated;
65
+ @tracked device;
66
+ @tracked last_online_at;
67
+ @tracked created_at;
68
+ @tracked updated_at;
69
+ @tracked table;
70
+ @tracked layout = this.appCache.get('fleetops:trailers:layout', 'table');
71
+
72
+ /** action buttons */
73
+ get actionButtons() {
74
+ return [
75
+ {
76
+ component: 'dropdown-button',
77
+ icon: 'display',
78
+ size: 'xs',
79
+ items: [
80
+ {
81
+ label: this.intl.t('common.table-view'),
82
+ icon: 'table-list',
83
+ onClick: () => this.setLayout('table'),
84
+ },
85
+ {
86
+ label: this.intl.t('common.grid-view'),
87
+ icon: 'grip',
88
+ onClick: () => this.setLayout('grid'),
89
+ },
90
+ ],
91
+ renderInPlace: true,
92
+ helpText: this.intl.t('common.change-layout'),
93
+ },
94
+ {
95
+ icon: 'refresh',
96
+ onClick: this.trailerActions.refresh,
97
+ helpText: this.intl.t('common.refresh'),
98
+ },
99
+ {
100
+ text: this.intl.t('common.new'),
101
+ type: 'primary',
102
+ icon: 'plus',
103
+ onClick: this.trailerActions.transition.create,
104
+ permission: 'fleet-ops create trailer',
105
+ },
106
+ {
107
+ text: this.intl.t('common.import'),
108
+ type: 'magic',
109
+ icon: 'upload',
110
+ onClick: this.trailerActions.import,
111
+ permission: 'fleet-ops import trailer',
112
+ },
113
+ {
114
+ text: this.intl.t('common.export'),
115
+ icon: 'long-arrow-up',
116
+ iconClass: 'rotate-icon-45',
117
+ wrapperClass: 'hidden md:flex',
118
+ onClick: this.trailerActions.export,
119
+ permission: 'fleet-ops export trailer',
120
+ },
121
+ ];
122
+ }
123
+
124
+ /** bulk actions */
125
+ get bulkActions() {
126
+ const selected = this.tableContext.getSelectedRows();
127
+
128
+ return [
129
+ {
130
+ label: this.intl.t('common.delete-selected-count', { count: selected.length }),
131
+ class: 'text-red-500',
132
+ fn: this.trailerActions.bulkDelete,
133
+ permission: 'fleet-ops delete trailer',
134
+ },
135
+ ];
136
+ }
137
+
138
+ get trailerTypeOptions() {
139
+ return TRAILER_TYPES.map((value) => ({ value, label: this.intl.t(`trailer.types.${value}`) }));
140
+ }
141
+
142
+ get statusOptions() {
143
+ return TRAILER_STATUSES.map((value) => ({ value, label: this.intl.t(`trailer.statuses.${value}`) }));
144
+ }
145
+
146
+ get attachmentOptions() {
147
+ return ['attached', 'detached'].map((value) => ({ value, label: this.intl.t(`trailer.attachment.${value}`) }));
148
+ }
149
+
150
+ get connectivityOptions() {
151
+ return ['online', 'recently_offline', 'offline', 'never_connected'].map((value) => ({ value, label: this.intl.t(`trailer.connectivity.${value}`) }));
152
+ }
153
+
154
+ get ownershipOptions() {
155
+ return TRAILER_OWNERSHIP_TYPES.map((value) => ({ value, label: this.intl.t(`trailer.ownership-types.${value}`) }));
156
+ }
157
+
158
+ /** columns */
159
+ get columns() {
160
+ return [
161
+ {
162
+ sticky: true,
163
+ label: this.intl.t('trailer.columns.name'),
164
+ valuePath: 'displayName',
165
+ photoPath: 'photo_url',
166
+ cellComponent: 'cell/vehicle-identity',
167
+ compact: true,
168
+ permission: 'fleet-ops view trailer',
169
+ action: this.trailerActions.transition.view,
170
+ resizable: true,
171
+ sortable: true,
172
+ filterable: true,
173
+ filterComponent: 'filter/string',
174
+ filterParam: 'name',
175
+ showOnlineIndicator: true,
176
+ showStatus: false,
177
+ },
178
+ {
179
+ label: this.intl.t('trailer.columns.type'),
180
+ valuePath: 'type',
181
+ cellComponent: 'cell/translated-value',
182
+ translationPrefix: 'trailer.types',
183
+ resizable: true,
184
+ sortable: true,
185
+ filterable: true,
186
+ filterParam: 'trailer_type',
187
+ filterComponent: 'filter/multi-option',
188
+ filterOptions: this.trailerTypeOptions,
189
+ filterOptionLabel: 'label',
190
+ filterOptionValue: 'value',
191
+ width: 130,
192
+ },
193
+ {
194
+ label: this.intl.t('trailer.columns.plate-number'),
195
+ valuePath: 'plate_number',
196
+ cellComponent: 'table/cell/base',
197
+ action: this.trailerActions.transition.view,
198
+ resizable: true,
199
+ sortable: true,
200
+ filterable: true,
201
+ filterComponent: 'filter/string',
202
+ filterParam: 'plate_number',
203
+ },
204
+ {
205
+ label: this.intl.t('trailer.columns.code'),
206
+ valuePath: 'code',
207
+ cellComponent: 'table/cell/base',
208
+ resizable: true,
209
+ sortable: true,
210
+ filterable: true,
211
+ filterComponent: 'filter/string',
212
+ filterParam: 'code',
213
+ },
214
+ {
215
+ label: this.intl.t('trailer.columns.vehicle'),
216
+ valuePath: 'current_vehicle_name',
217
+ cellComponent: 'table/cell/anchor',
218
+ permission: 'fleet-ops view vehicle',
219
+ action: async (trailer) => {
220
+ const vehicle = trailer.current_vehicle ?? (trailer.current_vehicle_id ? await this.store.findRecord('vehicle', trailer.current_vehicle_id) : null);
221
+
222
+ if (vehicle) {
223
+ return this.vehicleActions.panel.view(vehicle);
224
+ }
225
+ },
226
+ emptyText: '-',
227
+ resizable: true,
228
+ filterable: true,
229
+ filterComponent: 'filter/model',
230
+ filterComponentPlaceholder: this.intl.t('trailer.placeholders.filter-vehicle'),
231
+ filterParam: 'vehicle',
232
+ model: 'vehicle',
233
+ },
234
+ {
235
+ label: this.intl.t('trailer.columns.attachment-state'),
236
+ valuePath: 'attachment_state',
237
+ cellComponent: 'cell/translated-value',
238
+ translationPrefix: 'trailer.attachment',
239
+ badge: true,
240
+ badgeIcons: { attached: 'link', detached: 'link-slash' },
241
+ resizable: true,
242
+ filterable: true,
243
+ filterParam: 'attachment_state',
244
+ filterComponent: 'filter/multi-option',
245
+ filterOptions: this.attachmentOptions,
246
+ filterOptionLabel: 'label',
247
+ filterOptionValue: 'value',
248
+ width: 120,
249
+ },
250
+ {
251
+ label: this.intl.t('trailer.columns.status'),
252
+ valuePath: 'status',
253
+ cellComponent: 'cell/translated-value',
254
+ translationPrefix: 'trailer.statuses',
255
+ badge: true,
256
+ resizable: true,
257
+ sortable: true,
258
+ filterable: true,
259
+ filterParam: 'status',
260
+ filterComponent: 'filter/multi-option',
261
+ filterOptions: this.statusOptions,
262
+ filterOptionLabel: 'label',
263
+ filterOptionValue: 'value',
264
+ width: 120,
265
+ },
266
+ {
267
+ label: this.intl.t('trailer.columns.connectivity'),
268
+ valuePath: 'connectivity_status',
269
+ cellComponent: 'cell/translated-value',
270
+ translationPrefix: 'trailer.connectivity',
271
+ badge: true,
272
+ resizable: true,
273
+ filterable: true,
274
+ filterParam: 'connectivity_status',
275
+ filterComponent: 'filter/multi-option',
276
+ filterOptions: this.connectivityOptions,
277
+ filterOptionLabel: 'label',
278
+ filterOptionValue: 'value',
279
+ width: 140,
280
+ },
281
+ {
282
+ label: this.intl.t('trailer.columns.last-online'),
283
+ valuePath: 'lastOnlineAt',
284
+ sortParam: 'last_online_at',
285
+ resizable: true,
286
+ sortable: true,
287
+ filterable: true,
288
+ filterParam: 'last_online_at',
289
+ filterLabel: this.intl.t('trailer.filters.last-online-between'),
290
+ filterComponent: 'filter/date',
291
+ },
292
+ {
293
+ label: this.intl.t('trailer.columns.location'),
294
+ valuePath: 'location',
295
+ cellComponent: 'table/cell/point',
296
+ onClick: this.trailerActions.locate,
297
+ resizable: true,
298
+ hidden: true,
299
+ filterable: false,
300
+ sortable: false,
301
+ },
302
+ {
303
+ label: this.intl.t('trailer.columns.devices'),
304
+ valuePath: 'devices_count',
305
+ cellComponent: 'table/cell/base',
306
+ resizable: true,
307
+ sortable: false,
308
+ filterable: false,
309
+ width: 90,
310
+ },
311
+ {
312
+ label: this.intl.t('trailer.columns.equipment'),
313
+ valuePath: 'equipment_count',
314
+ cellComponent: 'table/cell/base',
315
+ resizable: true,
316
+ sortable: false,
317
+ filterable: false,
318
+ width: 100,
319
+ },
320
+ {
321
+ label: this.intl.t('trailer.columns.id'),
322
+ valuePath: 'public_id',
323
+ cellComponent: 'click-to-copy',
324
+ resizable: true,
325
+ sortable: true,
326
+ hidden: true,
327
+ filterable: true,
328
+ filterComponent: 'filter/string',
329
+ filterParam: 'public_id',
330
+ },
331
+ {
332
+ label: this.intl.t('trailer.columns.vin'),
333
+ valuePath: 'vin',
334
+ cellComponent: 'table/cell/base',
335
+ resizable: true,
336
+ sortable: true,
337
+ hidden: true,
338
+ filterable: true,
339
+ filterComponent: 'filter/string',
340
+ filterParam: 'vin',
341
+ },
342
+ {
343
+ label: this.intl.t('trailer.columns.serial-number'),
344
+ valuePath: 'serial_number',
345
+ cellComponent: 'table/cell/base',
346
+ resizable: true,
347
+ sortable: true,
348
+ hidden: true,
349
+ filterable: true,
350
+ filterComponent: 'filter/string',
351
+ filterParam: 'serial_number',
352
+ },
353
+ {
354
+ label: this.intl.t('trailer.columns.make'),
355
+ valuePath: 'make',
356
+ cellComponent: 'table/cell/base',
357
+ resizable: true,
358
+ sortable: true,
359
+ hidden: true,
360
+ filterable: true,
361
+ filterComponent: 'filter/string',
362
+ filterParam: 'trailer_make',
363
+ },
364
+ {
365
+ label: this.intl.t('trailer.columns.model'),
366
+ valuePath: 'model',
367
+ cellComponent: 'table/cell/base',
368
+ resizable: true,
369
+ sortable: true,
370
+ hidden: true,
371
+ filterable: true,
372
+ filterComponent: 'filter/string',
373
+ filterParam: 'trailer_model',
374
+ },
375
+ {
376
+ label: this.intl.t('trailer.columns.year'),
377
+ valuePath: 'year',
378
+ cellComponent: 'table/cell/base',
379
+ resizable: true,
380
+ sortable: true,
381
+ hidden: true,
382
+ filterable: true,
383
+ filterComponent: 'filter/string',
384
+ filterParam: 'trailer_year',
385
+ },
386
+ {
387
+ label: this.intl.t('trailer.columns.vendor'),
388
+ valuePath: 'vendor_name',
389
+ cellComponent: 'table/cell/anchor',
390
+ permission: 'fleet-ops view vendor',
391
+ action: async ({ vendor_uuid }) => {
392
+ if (!vendor_uuid) {
393
+ return;
394
+ }
395
+
396
+ const vendor = await this.store.findRecord('vendor', vendor_uuid);
397
+ this.vendorActions.viewVendor(vendor);
398
+ },
399
+ hidden: true,
400
+ resizable: true,
401
+ filterable: true,
402
+ filterComponent: 'filter/model',
403
+ filterComponentPlaceholder: this.intl.t('trailer.placeholders.filter-vendor'),
404
+ filterParam: 'vendor',
405
+ model: 'vendor',
406
+ },
407
+ {
408
+ label: this.intl.t('trailer.columns.ownership'),
409
+ valuePath: 'ownership_type',
410
+ cellComponent: 'cell/translated-value',
411
+ translationPrefix: 'trailer.ownership-types',
412
+ resizable: true,
413
+ sortable: true,
414
+ hidden: true,
415
+ filterable: true,
416
+ filterParam: 'ownership_type',
417
+ filterComponent: 'filter/multi-option',
418
+ filterOptions: this.ownershipOptions,
419
+ filterOptionLabel: 'label',
420
+ filterOptionValue: 'value',
421
+ },
422
+ {
423
+ label: this.intl.t('trailer.columns.axles'),
424
+ valuePath: 'axle_count',
425
+ cellComponent: 'table/cell/base',
426
+ resizable: true,
427
+ sortable: true,
428
+ hidden: true,
429
+ filterable: false,
430
+ width: 90,
431
+ },
432
+ {
433
+ label: this.intl.t('trailer.columns.gvwr'),
434
+ valuePath: 'gvwr',
435
+ cellComponent: 'table/cell/base',
436
+ resizable: true,
437
+ sortable: true,
438
+ hidden: true,
439
+ filterable: false,
440
+ },
441
+ {
442
+ label: this.intl.t('trailer.columns.payload-capacity'),
443
+ valuePath: 'payload_capacity',
444
+ cellComponent: 'table/cell/base',
445
+ resizable: true,
446
+ sortable: true,
447
+ hidden: true,
448
+ filterable: false,
449
+ },
450
+ {
451
+ label: this.intl.t('trailer.columns.length'),
452
+ valuePath: 'length',
453
+ cellComponent: 'table/cell/base',
454
+ resizable: true,
455
+ sortable: true,
456
+ hidden: true,
457
+ filterable: false,
458
+ },
459
+ {
460
+ label: this.intl.t('trailer.columns.created-at'),
461
+ valuePath: 'createdAt',
462
+ sortParam: 'created_at',
463
+ resizable: true,
464
+ sortable: true,
465
+ filterable: true,
466
+ filterParam: 'created_at',
467
+ filterLabel: this.intl.t('trailer.filters.created-between'),
468
+ filterComponent: 'filter/date',
469
+ },
470
+ {
471
+ label: this.intl.t('trailer.columns.updated-at'),
472
+ valuePath: 'updatedAt',
473
+ sortParam: 'updated_at',
474
+ resizable: true,
475
+ sortable: true,
476
+ hidden: true,
477
+ filterable: true,
478
+ filterParam: 'updated_at',
479
+ filterLabel: this.intl.t('trailer.filters.updated-between'),
480
+ filterComponent: 'filter/date',
481
+ },
482
+ {
483
+ label: '',
484
+ cellComponent: 'table/cell/dropdown',
485
+ ddButtonText: false,
486
+ ddButtonIcon: 'ellipsis-h',
487
+ ddButtonIconPrefix: 'fas',
488
+ ddMenuLabel: this.intl.t('common.resource-actions', { resource: this.intl.t('resource.trailer') }),
489
+ cellClassNames: 'overflow-visible',
490
+ wrapperClass: 'flex items-center justify-end mx-2',
491
+ sticky: 'right',
492
+ width: 60,
493
+ actions: [
494
+ {
495
+ label: this.intl.t('common.view-resource', { resource: this.intl.t('resource.trailer') }),
496
+ fn: this.trailerActions.transition.view,
497
+ permission: 'fleet-ops view trailer',
498
+ },
499
+ {
500
+ label: this.intl.t('common.edit-resource', { resource: this.intl.t('resource.trailer') }),
501
+ fn: this.trailerActions.transition.edit,
502
+ permission: 'fleet-ops update trailer',
503
+ },
504
+ {
505
+ label: this.intl.t('trailer.actions.locate'),
506
+ fn: this.trailerActions.locate,
507
+ permission: 'fleet-ops view trailer',
508
+ isVisible: (trailer) => Boolean(trailer.hasValidCoordinates),
509
+ },
510
+ {
511
+ separator: true,
512
+ },
513
+ {
514
+ label: this.intl.t('trailer.actions.attach-vehicle'),
515
+ fn: this.trailerActions.attachVehicle,
516
+ permission: 'fleet-ops attach-vehicle-for trailer',
517
+ isVisible: (trailer) => trailer.attachment_state !== 'attached',
518
+ },
519
+ {
520
+ label: this.intl.t('trailer.actions.detach-vehicle'),
521
+ fn: this.trailerActions.detachVehicle,
522
+ permission: 'fleet-ops detach-vehicle-for trailer',
523
+ isVisible: (trailer) => trailer.attachment_state === 'attached',
524
+ },
525
+ {
526
+ label: this.intl.t('trailer.actions.attach-device'),
527
+ fn: this.trailerActions.attachDevice,
528
+ permission: 'fleet-ops attach-device-for trailer',
529
+ },
530
+ {
531
+ label: this.intl.t('trailer.actions.attach-equipment'),
532
+ fn: this.trailerActions.attachEquipment,
533
+ permission: 'fleet-ops attach-equipment-for trailer',
534
+ },
535
+ {
536
+ separator: true,
537
+ },
538
+ {
539
+ label: this.intl.t('trailer.actions.schedule-maintenance'),
540
+ fn: this.trailerActions.scheduleMaintenance,
541
+ permission: 'fleet-ops create maintenance-schedule',
542
+ },
543
+ {
544
+ label: this.intl.t('trailer.actions.create-work-order'),
545
+ fn: this.trailerActions.createWorkOrder,
546
+ permission: 'fleet-ops create work-order',
547
+ },
548
+ {
549
+ label: this.intl.t('trailer.actions.log-maintenance'),
550
+ fn: this.trailerActions.logMaintenance,
551
+ permission: 'fleet-ops create maintenance',
552
+ },
553
+ {
554
+ separator: true,
555
+ },
556
+ {
557
+ label: this.intl.t('common.delete-resource', { resource: this.intl.t('resource.trailer') }),
558
+ fn: this.trailerActions.delete,
559
+ permission: 'fleet-ops delete trailer',
560
+ class: 'text-red-500',
561
+ },
562
+ ],
563
+ sortable: false,
564
+ filterable: false,
565
+ resizable: false,
566
+ searchable: false,
567
+ },
568
+ {
569
+ label: this.intl.t('resource.devices'),
570
+ valuePath: 'devices',
571
+ hidden: true,
572
+ filterable: true,
573
+ filterComponent: 'filter/multi-model',
574
+ filterComponentPlaceholder: this.intl.t('common.select-resource-filter-by', { resource: this.intl.t('resource.device') }),
575
+ filterParam: 'device',
576
+ model: 'device',
577
+ modelNamePath: 'displayName',
578
+ },
579
+ {
580
+ label: this.intl.t('trailer.columns.refrigerated'),
581
+ valuePath: 'refrigerated',
582
+ cellComponent: 'table/cell/checkbox',
583
+ resizable: true,
584
+ sortable: true,
585
+ hidden: true,
586
+ filterable: true,
587
+ filterParam: 'refrigerated',
588
+ filterComponent: 'filter/checkbox',
589
+ noFilterLabel: true,
590
+ width: 110,
591
+ },
592
+ ];
593
+ }
594
+
595
+ @action setLayout(layout) {
596
+ this.layout = layout;
597
+ this.appCache.set('fleetops:trailers:layout', layout);
598
+ }
599
+ }
@@ -14,26 +14,42 @@ export default class ManagementVehiclesIndexDetailsController extends Controller
14
14
  const registeredTabs = this.menuService.getMenuItems('fleet-ops:component:vehicle:details');
15
15
  return [
16
16
  {
17
+ id: 'index',
17
18
  route: 'management.vehicles.index.details.index',
18
19
  label: 'Overview',
19
20
  },
20
21
  {
22
+ id: 'positions',
21
23
  route: 'management.vehicles.index.details.positions',
22
24
  label: 'Positions',
23
25
  },
24
26
  {
27
+ id: 'devices',
25
28
  route: 'management.vehicles.index.details.devices',
26
29
  label: 'Devices',
27
30
  },
28
31
  {
32
+ id: 'trailers',
33
+ route: 'management.vehicles.index.details.trailers',
34
+ label: this.intl.t('resource.trailers'),
35
+ },
36
+ {
37
+ id: 'equipment',
38
+ route: 'management.vehicles.index.details.equipment',
39
+ label: this.intl.t('resource.equipment'),
40
+ },
41
+ {
42
+ id: 'schedules',
29
43
  route: 'management.vehicles.index.details.schedules',
30
44
  label: 'Schedules',
31
45
  },
32
46
  {
47
+ id: 'work-orders',
33
48
  route: 'management.vehicles.index.details.work-orders',
34
49
  label: 'Work Orders',
35
50
  },
36
51
  {
52
+ id: 'maintenance-history',
37
53
  route: 'management.vehicles.index.details.maintenance-history',
38
54
  label: 'Maintenance',
39
55
  },