@fleetbase/fleetops-engine 0.6.52 → 0.6.54

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 (151) hide show
  1. package/addon/components/device/details.hbs +106 -135
  2. package/addon/components/device/details.js +174 -1
  3. package/addon/components/device/panel-header.hbs +2 -2
  4. package/addon/components/layout/fleet-ops-sidebar/operations-monitor.hbs +201 -0
  5. package/addon/components/layout/fleet-ops-sidebar/operations-monitor.js +654 -0
  6. package/addon/components/layout/fleet-ops-sidebar.hbs +19 -233
  7. package/addon/components/layout/fleet-ops-sidebar.js +364 -395
  8. package/addon/components/maintenance-schedule/form.js +1 -0
  9. package/addon/components/order/form/details.hbs +1 -43
  10. package/addon/components/order/form/details.js +18 -53
  11. package/addon/components/order/form/orchestrator-constraints.hbs +40 -0
  12. package/addon/components/order/form/orchestrator-constraints.js +61 -0
  13. package/addon/components/order/form/payload.js +50 -2
  14. package/addon/components/order/form/route.js +15 -0
  15. package/addon/components/order/form/service-rate.hbs +62 -11
  16. package/addon/components/order/form/service-rate.js +124 -2
  17. package/addon/components/order/form.hbs +2 -0
  18. package/addon/components/telematic/details.hbs +7 -1
  19. package/addon/components/telematic/form.js +16 -8
  20. package/addon/components/work-order/details.hbs +5 -1
  21. package/addon/components/work-order/form.hbs +26 -4
  22. package/addon/components/work-order/form.js +5 -1
  23. package/addon/controllers/connectivity/devices/index/details/events.js +244 -1
  24. package/addon/controllers/connectivity/devices/index/details/sensors.js +199 -0
  25. package/addon/controllers/connectivity/devices/index/details/vehicle.js +74 -0
  26. package/addon/controllers/connectivity/devices/index/details.js +12 -0
  27. package/addon/controllers/connectivity/devices/index.js +4 -1
  28. package/addon/controllers/connectivity/telematics/details/attachments.js +220 -54
  29. package/addon/controllers/connectivity/telematics/details/devices.js +90 -41
  30. package/addon/controllers/connectivity/telematics/details/events.js +39 -11
  31. package/addon/controllers/connectivity/telematics/details/sensors.js +39 -19
  32. package/addon/controllers/maintenance/index.js +100 -0
  33. package/addon/controllers/maintenance/work-orders/index.js +18 -1
  34. package/addon/controllers/management/fuel-transactions/index.js +1 -1
  35. package/addon/controllers/management/index.js +88 -0
  36. package/addon/controllers/settings/index.js +142 -0
  37. package/addon/extension.js +21 -0
  38. package/addon/routes/analytics/index.js +3 -0
  39. package/addon/routes/connectivity/devices/index/details/events.js +37 -1
  40. package/addon/routes/connectivity/devices/index/details/sensors.js +35 -0
  41. package/addon/routes/connectivity/devices/index/details/vehicle.js +7 -0
  42. package/addon/routes/connectivity/devices/index.js +3 -0
  43. package/addon/routes/connectivity/telematics/details/attachments.js +72 -9
  44. package/addon/routes/connectivity/telematics/details/devices.js +4 -0
  45. package/addon/routes/connectivity/telematics/details/sensors.js +1 -0
  46. package/addon/routes/connectivity/telematics/details.js +1 -1
  47. package/addon/routes/connectivity/telematics/edit.js +1 -1
  48. package/addon/routes/maintenance/index.js +3 -0
  49. package/addon/routes/maintenance/work-orders/index.js +3 -0
  50. package/addon/routes/settings/index.js +3 -0
  51. package/addon/routes.js +2 -0
  52. package/addon/services/order-creation.js +54 -1
  53. package/addon/services/order-validation.js +3 -2
  54. package/addon/services/service-rate-actions.js +1 -0
  55. package/addon/styles/fleetops-engine.css +1821 -6
  56. package/addon/templates/analytics/index.hbs +14 -0
  57. package/addon/templates/analytics/reports/index.hbs +4 -4
  58. package/addon/templates/connectivity/devices/index/details/events.hbs +85 -1
  59. package/addon/templates/connectivity/devices/index/details/sensors.hbs +73 -0
  60. package/addon/templates/connectivity/devices/index/details/vehicle.hbs +84 -0
  61. package/addon/templates/connectivity/telematics/details/attachments.hbs +198 -121
  62. package/addon/templates/connectivity/telematics/details/devices.hbs +4 -1
  63. package/addon/templates/connectivity/telematics/details/events.hbs +4 -1
  64. package/addon/templates/connectivity/telematics/details/sensors.hbs +3 -0
  65. package/addon/templates/maintenance/index.hbs +113 -0
  66. package/addon/templates/management/fuel-transactions/index/details.hbs +1 -1
  67. package/addon/templates/management/index.hbs +109 -73
  68. package/addon/templates/management/vehicles/index/edit.hbs +1 -1
  69. package/addon/templates/operations/orders/index.hbs +1 -1
  70. package/addon/templates/operations/service-rates/index.hbs +1 -1
  71. package/addon/templates/settings/index.hbs +83 -0
  72. package/addon/templates/settings/routing.hbs +2 -2
  73. package/addon/utils/fleet-ops-options.js +38 -0
  74. package/app/components/order/form/orchestrator-constraints.js +1 -0
  75. package/app/controllers/connectivity/devices/index/details/sensors.js +1 -0
  76. package/app/controllers/connectivity/devices/index/details/vehicle.js +1 -0
  77. package/app/controllers/maintenance/index.js +1 -0
  78. package/app/controllers/management/index.js +1 -0
  79. package/app/controllers/settings/index.js +1 -0
  80. package/app/routes/analytics/index.js +1 -0
  81. package/app/routes/connectivity/devices/index/details/sensors.js +1 -0
  82. package/app/routes/connectivity/devices/index/details/vehicle.js +1 -0
  83. package/app/routes/maintenance/index.js +1 -0
  84. package/app/routes/settings/index.js +1 -0
  85. package/app/templates/analytics/index.js +1 -0
  86. package/app/templates/connectivity/devices/index/details/sensors.js +1 -0
  87. package/app/templates/connectivity/devices/index/details/vehicle.js +1 -0
  88. package/app/templates/maintenance/index.js +1 -0
  89. package/app/templates/management/index.js +1 -0
  90. package/app/templates/settings/index.js +1 -0
  91. package/composer.json +1 -1
  92. package/extension.json +1 -1
  93. package/package.json +3 -3
  94. package/server/migrations/2025_08_28_054930_create_work_orders_table.php +1 -0
  95. package/server/migrations/2026_06_15_000001_normalize_device_attachable_vehicle_morph_types.php +30 -0
  96. package/server/migrations/2026_06_18_000001_add_category_to_work_orders_table.php +32 -0
  97. package/server/seeders/Testing/MaintenanceSeeder.php +5 -4
  98. package/server/src/Console/Commands/FixInvalidPolymorphicRelationTypeNamespaces.php +1 -0
  99. package/server/src/Console/Commands/ProcessMaintenanceTriggers.php +1 -0
  100. package/server/src/Console/Commands/SyncTelematics.php +89 -0
  101. package/server/src/Exceptions/TelematicProviderException.php +13 -2
  102. package/server/src/Http/Controllers/Api/v1/OrderController.php +6 -21
  103. package/server/src/Http/Controllers/Internal/v1/DeviceController.php +112 -11
  104. package/server/src/Http/Controllers/Internal/v1/DeviceEventController.php +16 -5
  105. package/server/src/Http/Controllers/Internal/v1/FleetController.php +9 -0
  106. package/server/src/Http/Controllers/Internal/v1/HubController.php +300 -0
  107. package/server/src/Http/Controllers/Internal/v1/LiveController.php +177 -0
  108. package/server/src/Http/Controllers/Internal/v1/MaintenanceScheduleController.php +1 -0
  109. package/server/src/Http/Controllers/Internal/v1/OrderController.php +4 -32
  110. package/server/src/Http/Controllers/Internal/v1/SearchController.php +506 -0
  111. package/server/src/Http/Controllers/Internal/v1/ServiceQuoteController.php +4 -4
  112. package/server/src/Http/Controllers/Internal/v1/TelematicController.php +1 -1
  113. package/server/src/Http/Controllers/Internal/v1/VehicleController.php +94 -10
  114. package/server/src/Http/Filter/DeviceEventFilter.php +44 -0
  115. package/server/src/Http/Filter/DeviceFilter.php +131 -0
  116. package/server/src/Http/Filter/DriverFilter.php +6 -0
  117. package/server/src/Http/Filter/SensorFilter.php +125 -0
  118. package/server/src/Http/Filter/VehicleFilter.php +19 -0
  119. package/server/src/Http/Requests/CreateDriverRequest.php +14 -13
  120. package/server/src/Http/Requests/Internal/CreateDriverRequest.php +1 -0
  121. package/server/src/Http/Resources/v1/Driver.php +11 -2
  122. package/server/src/Http/Resources/v1/WorkOrder.php +1 -0
  123. package/server/src/Jobs/FinalizeApiOrderCreation.php +47 -0
  124. package/server/src/Jobs/FinalizeInternalOrderCreation.php +35 -0
  125. package/server/src/Jobs/NotifyBulkAssignedDriver.php +47 -0
  126. package/server/src/Jobs/SyncTelematicDevicesJob.php +181 -66
  127. package/server/src/Models/Device.php +15 -1
  128. package/server/src/Models/DeviceEvent.php +1 -1
  129. package/server/src/Models/Driver.php +17 -1
  130. package/server/src/Models/Sensor.php +15 -2
  131. package/server/src/Models/Telematic.php +1 -1
  132. package/server/src/Models/Vehicle.php +5 -1
  133. package/server/src/Models/WorkOrder.php +5 -2
  134. package/server/src/Observers/DriverObserver.php +3 -3
  135. package/server/src/Observers/FleetObserver.php +23 -0
  136. package/server/src/Observers/VehicleObserver.php +3 -3
  137. package/server/src/Providers/FleetOpsServiceProvider.php +12 -0
  138. package/server/src/Support/LiveCacheService.php +1 -1
  139. package/server/src/Support/Telematics/Providers/AfaqyProvider.php +188 -28
  140. package/server/src/Support/Telematics/Providers/SafeeProvider.php +44 -3
  141. package/server/src/Support/Telematics/TelematicService.php +330 -30
  142. package/server/src/routes.php +10 -0
  143. package/server/tests/DeviceFilterTest.php +36 -0
  144. package/server/tests/HubRoutesTest.php +62 -0
  145. package/server/tests/OperationsMonitorEndpointTest.php +38 -0
  146. package/server/tests/OrderQueuedClosureRegressionTest.php +36 -0
  147. package/server/tests/TelematicsHardeningTest.php +455 -3
  148. package/server/tests/VehicleDriverAssignmentTest.php +27 -0
  149. package/translations/ar-ae.yml +1 -1
  150. package/translations/en-us.yaml +1 -0
  151. package/translations/vi-vn.yaml +1 -1
@@ -1,77 +1,113 @@
1
- <div class="content">
2
- <div class="row">
3
- <div class="col-12 col-lg-3 col-xl-3">
4
- <LinkTo
5
- @route="dashboard.fleet-ops.management.vendors"
6
- class="group hover:bg-flb-blue p-4 cursor-pointer bg-white rounded max-w-xs w-full shadow-lg select-none overflow-hidden mx-auto mb-6"
7
- >
8
- <p class="font-semibold text-lg mb-1 text-black group-hover:text-white">{{t "fleet-ops.management.vendors.index.title"}}</p>
9
- <p class="text-grey-darker group-hover:text-white mb-2">{{t "fleet-ops.common.manage-message"}}</p>
10
- </LinkTo>
1
+ <div class="fleet-ops-control-hub" data-test-fleet-ops-resources-hub>
2
+ <section class="fleet-ops-control-hub-header">
3
+ <div class="fleet-ops-control-hub-header-copy">
4
+ <div class="fleet-ops-control-hub-eyebrow">Resources</div>
5
+ <h1 class="fleet-ops-control-hub-title">Resources Hub</h1>
6
+ <p class="fleet-ops-control-hub-subtitle">Manage the people, vehicles, places, partners, and operating records that keep dispatch grounded.</p>
11
7
  </div>
12
- <div class="col-12 col-lg-3 col-xl-3">
13
- <LinkTo
14
- @route="dashboard.fleet-ops.management.fleets"
15
- class="group hover:bg-flb-blue p-4 cursor-pointer bg-white rounded max-w-xs w-full shadow-lg select-none overflow-hidden mx-auto mb-6"
16
- >
17
- <p class="font-semibold text-lg mb-1 text-black group-hover:text-white">{{t "fleet-ops.management.fleets.index.title"}}</p>
18
- <p class="text-grey-darker group-hover:text-white mb-2">{{t "fleet-ops.common.manage-message"}}</p>
19
- </LinkTo>
20
- </div>
21
- <div class="col-12 col-lg-3 col-xl-3">
22
- <LinkTo
23
- @route="dashboard.fleet-ops.management.drivers"
24
- class="group hover:bg-flb-blue p-4 cursor-pointer bg-white rounded max-w-xs w-full shadow-lg select-none overflow-hidden mx-auto mb-6"
25
- >
26
- <p class="font-semibold text-lg mb-1 text-black group-hover:text-white">{{t "fleet-ops.management.drivers.index.title"}}</p>
27
- <p class="text-grey-darker group-hover:text-white mb-2">{{t "fleet-ops.common.manage-message"}}</p>
28
- </LinkTo>
29
- </div>
30
- <div class="col-12 col-lg-3 col-xl-3">
31
- <LinkTo
32
- @route="dashboard.fleet-ops.management.vehicles"
33
- class="group hover:bg-flb-blue p-4 cursor-pointer bg-white rounded max-w-xs w-full shadow-lg select-none overflow-hidden mx-auto mb-6"
34
- >
35
- <p class="font-semibold text-lg mb-1 text-black group-hover:text-white">{{t "fleet-ops.management.vehicles.index.title"}}</p>
36
- <p class="text-grey-darker group-hover:text-white mb-2">{{t "fleet-ops.common.manage-message"}}</p>
37
- </LinkTo>
38
- </div>
39
- <div class="col-12 col-lg-3 col-xl-3">
40
- <LinkTo
41
- @route="dashboard.fleet-ops.management.places"
42
- class="group hover:bg-flb-blue p-4 cursor-pointer bg-white rounded max-w-xs w-full shadow-lg select-none overflow-hidden mx-auto mb-6"
43
- >
44
- <p class="font-semibold text-lg mb-1 text-black group-hover:text-white">{{t "fleet-ops.management.places.index.title"}}</p>
45
- <p class="text-grey-darker group-hover:text-white mb-2">{{t "fleet-ops.common.manage-message"}}</p>
46
- </LinkTo>
47
- </div>
48
- <div class="col-12 col-lg-3 col-xl-3">
49
- <LinkTo
50
- @route="dashboard.fleet-ops.management.contacts."
51
- class="group hover:bg-flb-blue p-4 cursor-pointer bg-white rounded max-w-xs w-full shadow-lg select-none overflow-hidden mx-auto mb-6"
52
- >
53
- <p class="font-semibold text-lg mb-1 text-black group-hover:text-white">{{t "fleet-ops.management.contacts.index.title"}}</p>
54
- <p class="text-grey-darker group-hover:text-white mb-2">{{t "fleet-ops.common.manage-message"}}</p>
55
- </LinkTo>
56
- </div>
57
- <div class="col-12 col-lg-3 col-xl-3">
58
- <LinkTo
59
- @route="dashboard.fleet-ops.management.issues"
60
- class="group hover:bg-flb-blue p-4 cursor-pointer bg-white rounded max-w-xs w-full shadow-lg select-none overflow-hidden mx-auto mb-6"
61
- >
62
- <p class="font-semibold text-lg mb-1 text-black group-hover:text-white">{{t "fleet-ops.management.issues.index.title"}}</p>
63
- <p class="text-grey-darker group-hover:text-white mb-2">{{t "fleet-ops.common.manage-message"}}</p>
64
- </LinkTo>
65
- </div>
66
- <div class="col-12 col-lg-3 col-xl-3">
67
- <LinkTo
68
- @route="dashboard.fleet-ops.management.fuel-reports"
69
- class="group hover:bg-flb-blue p-4 cursor-pointer bg-white rounded max-w-xs w-full shadow-lg select-none overflow-hidden mx-auto mb-6"
70
- >
71
- <p class="font-semibold text-lg mb-1 text-black group-hover:text-white">{{t "fleet-ops.management.fuel-reports.index.title"}}</p>
72
- <p class="text-grey-darker group-hover:text-white mb-2">{{t "fleet-ops.common.manage-message"}}</p>
73
- </LinkTo>
8
+ <div class="fleet-ops-control-hub-header-actions">
9
+ <Button @icon="refresh" @size="sm" @helpText={{t "common.reload"}} @onClick={{perform this.loadHub}} />
74
10
  </div>
11
+ </section>
12
+
13
+ <div class="fleet-ops-control-hub-body">
14
+ <section class="fleet-ops-control-hub-kpis">
15
+ {{#each this.kpis as |kpi|}}
16
+ <LinkTo @route={{kpi.route}} class="fleet-ops-control-hub-kpi fleet-ops-control-hub-tone-{{kpi.tone}}" data-test-fleet-ops-resources-kpi={{kpi.key}}>
17
+ <div class="fleet-ops-control-hub-kpi-copy">
18
+ <div class="fleet-ops-control-hub-kpi-label">{{kpi.label}}</div>
19
+ <div class="fleet-ops-control-hub-kpi-value">{{kpi.value}}</div>
20
+ <div class="fleet-ops-control-hub-kpi-caption">{{kpi.caption}}</div>
21
+ <div class="fleet-ops-control-hub-kpi-action">
22
+ <span>{{kpi.actionLabel}}</span>
23
+ <FaIcon @icon="arrow-right" />
24
+ </div>
25
+ </div>
26
+ <div class="fleet-ops-control-hub-kpi-icon"><FaIcon @icon={{kpi.icon}} /></div>
27
+ </LinkTo>
28
+ {{/each}}
29
+ </section>
30
+
31
+ <section class="fleet-ops-control-hub-grid">
32
+ <div class="fleet-ops-control-hub-main">
33
+ {{#each this.sections as |section|}}
34
+ <div class="fleet-ops-control-hub-panel" data-test-fleet-ops-resources-section={{section.key}}>
35
+ <div class="fleet-ops-control-hub-panel-header">
36
+ <div>
37
+ <h2>{{section.title}}</h2>
38
+ <p>{{section.description}}</p>
39
+ </div>
40
+ </div>
41
+
42
+ <div class="fleet-ops-control-hub-link-grid">
43
+ {{#each section.links as |link|}}
44
+ <LinkTo @route={{link.route}} class="fleet-ops-control-hub-link" data-test-fleet-ops-hub-card={{link.label}}>
45
+ <span class="fleet-ops-control-hub-link-icon"><FaIcon @icon={{link.icon}} /></span>
46
+ <span class="fleet-ops-control-hub-link-copy">
47
+ <span class="fleet-ops-control-hub-link-title">{{link.label}}</span>
48
+ <span class="fleet-ops-control-hub-link-description">{{link.description}}</span>
49
+ </span>
50
+ <span class="fleet-ops-control-hub-link-count">{{link.count}}</span>
51
+ </LinkTo>
52
+ {{/each}}
53
+ </div>
54
+ </div>
55
+ {{/each}}
56
+ </div>
57
+
58
+ <aside class="fleet-ops-control-hub-side">
59
+ <div class="fleet-ops-control-hub-panel">
60
+ <div class="fleet-ops-control-hub-panel-header">
61
+ <div>
62
+ <h2>Action Queue</h2>
63
+ <p>Prioritized from current resource readiness.</p>
64
+ </div>
65
+ </div>
66
+
67
+ <div class="fleet-ops-control-hub-action-list">
68
+ {{#each this.actions as |action|}}
69
+ {{#if action.route}}
70
+ <LinkTo @route={{action.route}} @query={{action.query}} class="fleet-ops-control-hub-action fleet-ops-control-hub-tone-{{action.tone}}">
71
+ <FaIcon @icon={{action.icon}} />
72
+ <span>
73
+ <strong>{{action.label}}</strong>
74
+ <small>{{action.description}}</small>
75
+ </span>
76
+ </LinkTo>
77
+ {{else}}
78
+ <div class="fleet-ops-control-hub-action fleet-ops-control-hub-tone-{{action.tone}}">
79
+ <FaIcon @icon={{action.icon}} />
80
+ <span>
81
+ <strong>{{action.label}}</strong>
82
+ <small>{{action.description}}</small>
83
+ </span>
84
+ </div>
85
+ {{/if}}
86
+ {{/each}}
87
+ </div>
88
+ </div>
89
+
90
+ <div class="fleet-ops-control-hub-doc-note">
91
+ <div class="fleet-ops-control-hub-doc-note-heading">
92
+ <FaIcon @icon="lightbulb" />
93
+ <span>Guides</span>
94
+ </div>
95
+ <p class="fleet-ops-control-hub-doc-note-copy">Read the guide before changing resource setup.</p>
96
+ <div class="fleet-ops-control-hub-doc-grid">
97
+ {{#each this.docs as |doc|}}
98
+ <button type="button" class="fleet-ops-control-hub-doc-link" {{on "click" (fn this.openDocs doc)}}>
99
+ <FaIcon @icon={{doc.icon}} />
100
+ <span class="fleet-ops-control-hub-doc-copy">
101
+ <strong>Read the guide on {{doc.label}}</strong>
102
+ <small>{{doc.description}}</small>
103
+ </span>
104
+ </button>
105
+ {{/each}}
106
+ </div>
107
+ </div>
108
+ </aside>
109
+ </section>
75
110
  </div>
76
111
  </div>
77
- {{outlet}}
112
+
113
+ {{outlet}}
@@ -1,7 +1,7 @@
1
1
  <Layout::Resource::Panel
2
2
  @resource={{@model}}
3
3
  @controller={{this}}
4
- @headerTitle={{t "common.edit-resource-name" resourceName=@model.display_name}}
4
+ @headerTitle={{t "common.edit-resource-name" resourceName=@model.displayName}}
5
5
  @actionButtons={{this.actionButtons}}
6
6
  @saveTask={{this.save}}
7
7
  @onPressCancel={{this.cancel}}
@@ -51,7 +51,7 @@
51
51
  "table/empty-state"
52
52
  icon="paper-plane"
53
53
  title="Create your first order"
54
- description="Orders are the center of FleetOps: plan routes, assign drivers and vehicles, track progress, and collect proof."
54
+ description="Orders are the center of Fleet-Ops: plan routes, assign drivers and vehicles, track progress, and collect proof."
55
55
  filteredTitle="No orders match your filters"
56
56
  filteredDescription="Adjust the search, bulk search, or filters to find another order."
57
57
  primaryText="New order"
@@ -14,7 +14,7 @@
14
14
  "table/empty-state"
15
15
  icon="route"
16
16
  title="Set up your first service rate"
17
- description="Service rates define how FleetOps prices routes, zones, distance, and other service rules."
17
+ description="Service rates define how Fleet-Ops prices routes, zones, distance, and other service rules."
18
18
  filteredTitle="No service rates match your filters"
19
19
  filteredDescription="Adjust the search or filters to find another service rate."
20
20
  primaryText="New service rate"
@@ -0,0 +1,83 @@
1
+ <div class="fleet-ops-control-hub fleet-ops-settings-control-hub" data-test-fleet-ops-settings-hub>
2
+ <section class="fleet-ops-control-hub-header">
3
+ <div class="fleet-ops-control-hub-header-copy">
4
+ <div class="fleet-ops-control-hub-eyebrow">Settings</div>
5
+ <h1 class="fleet-ops-control-hub-title">Fleet-Ops Settings</h1>
6
+ <p class="fleet-ops-control-hub-subtitle">Configure the operator, driver, routing, notification, and data rules that shape Fleet-Ops workflows.</p>
7
+ </div>
8
+ </section>
9
+
10
+ <div class="fleet-ops-control-hub-body">
11
+ <section class="fleet-ops-control-hub-grid">
12
+ <div class="fleet-ops-control-hub-main">
13
+ {{#each this.groups as |group|}}
14
+ <div class="fleet-ops-control-hub-panel">
15
+ <div class="fleet-ops-control-hub-panel-header">
16
+ <div>
17
+ <h2>{{group.title}}</h2>
18
+ <p>{{group.description}}</p>
19
+ </div>
20
+ </div>
21
+
22
+ <div class="fleet-ops-control-hub-link-grid fleet-ops-control-hub-link-grid-compact">
23
+ {{#each group.links as |link|}}
24
+ <LinkTo @route={{link.route}} class="fleet-ops-control-hub-link" data-test-fleet-ops-hub-card={{link.label}}>
25
+ <span class="fleet-ops-control-hub-link-icon"><FaIcon @icon={{link.icon}} /></span>
26
+ <span class="fleet-ops-control-hub-link-copy">
27
+ <span class="fleet-ops-control-hub-link-title">{{link.label}}</span>
28
+ <span class="fleet-ops-control-hub-link-description">{{link.description}}</span>
29
+ </span>
30
+ <FaIcon @icon="arrow-right" class="fleet-ops-control-hub-link-arrow" />
31
+ </LinkTo>
32
+ {{/each}}
33
+ </div>
34
+ </div>
35
+ {{/each}}
36
+ </div>
37
+
38
+ <aside class="fleet-ops-control-hub-side">
39
+ <div class="fleet-ops-control-hub-panel">
40
+ <div class="fleet-ops-control-hub-panel-header">
41
+ <div>
42
+ <h2>Setup Focus</h2>
43
+ <p>Compact next steps for operators.</p>
44
+ </div>
45
+ </div>
46
+
47
+ <div class="fleet-ops-control-hub-action-list">
48
+ {{#each this.actions as |action|}}
49
+ <LinkTo @route={{action.route}} class="fleet-ops-control-hub-action fleet-ops-control-hub-tone-{{action.tone}}">
50
+ <FaIcon @icon={{action.icon}} />
51
+ <span>
52
+ <strong>{{action.label}}</strong>
53
+ <small>{{action.description}}</small>
54
+ </span>
55
+ </LinkTo>
56
+ {{/each}}
57
+ </div>
58
+ </div>
59
+
60
+ <div class="fleet-ops-control-hub-doc-note">
61
+ <div class="fleet-ops-control-hub-doc-note-heading">
62
+ <FaIcon @icon="lightbulb" />
63
+ <span>Guides</span>
64
+ </div>
65
+ <p class="fleet-ops-control-hub-doc-note-copy">Read the guide before changing settings.</p>
66
+ <div class="fleet-ops-control-hub-doc-grid">
67
+ {{#each this.docs as |doc|}}
68
+ <button type="button" class="fleet-ops-control-hub-doc-link" {{on "click" (fn this.openDocs doc)}}>
69
+ <FaIcon @icon={{doc.icon}} />
70
+ <span class="fleet-ops-control-hub-doc-copy">
71
+ <strong>Read the guide on {{doc.label}}</strong>
72
+ <small>{{doc.description}}</small>
73
+ </span>
74
+ </button>
75
+ {{/each}}
76
+ </div>
77
+ </div>
78
+ </aside>
79
+ </section>
80
+ </div>
81
+ </div>
82
+
83
+ {{outlet}}
@@ -1,4 +1,4 @@
1
- <Layout::Section::Header @title="FleetOps Routing & Tracking">
1
+ <Layout::Section::Header @title="Fleet-Ops Routing & Tracking">
2
2
  <Button
3
3
  @type="primary"
4
4
  @size="sm"
@@ -132,4 +132,4 @@
132
132
  </div>
133
133
  <Spacer @height="600px" />
134
134
  </div>
135
- </Layout::Section::Body>
135
+ </Layout::Section::Body>
@@ -216,6 +216,42 @@ export const fuelReportStatuses = [
216
216
  { label: 'Reimbursed', value: 'reimbursed', description: 'Driver expense reimbursed' },
217
217
  ];
218
218
 
219
+ export const workOrderStatuses = [
220
+ { label: 'Open', value: 'open', description: 'Work order has been created and is awaiting planning or assignment' },
221
+ { label: 'Scheduled', value: 'scheduled', description: 'Work has been planned for a specific service window' },
222
+ { label: 'Assigned', value: 'assigned', description: 'A technician, vendor, or team has been assigned' },
223
+ { label: 'In Progress', value: 'in_progress', description: 'Work is actively being performed' },
224
+ { label: 'Awaiting Parts', value: 'awaiting_parts', description: 'Work is blocked until required parts are available' },
225
+ { label: 'Awaiting Vendor', value: 'awaiting_vendor', description: 'Work is waiting on a third-party vendor or repair shop' },
226
+ { label: 'On Hold', value: 'on_hold', description: 'Work is temporarily paused' },
227
+ { label: 'Quality Check', value: 'quality_check', description: 'Work is complete and awaiting verification or road-readiness check' },
228
+ { label: 'Closed', value: 'closed', description: 'Work is complete and recorded in maintenance history' },
229
+ { label: 'Canceled', value: 'canceled', description: 'Work order was canceled before completion' },
230
+ ];
231
+
232
+ export const workOrderCategories = [
233
+ { label: 'Preventive Maintenance (PM)', value: 'preventive_maintenance', description: 'Scheduled service intended to prevent failures and downtime' },
234
+ { label: 'Predictive Maintenance', value: 'predictive_maintenance', description: 'Maintenance triggered by forecasts, telematics, diagnostics, or condition trends' },
235
+ { label: 'Condition-Based Maintenance', value: 'condition_based_maintenance', description: 'Service based on measured asset condition or threshold readings' },
236
+ { label: 'Inspection Request', value: 'inspection_request', description: 'Technician or compliance inspection requested for the asset' },
237
+ { label: 'Failed Inspection', value: 'failed_inspection', description: 'Follow-up work created from a failed inspection or DVIR item' },
238
+ { label: 'Recall', value: 'recall', description: 'Manufacturer, regulatory, or safety recall work' },
239
+ { label: 'Compliance / Safety', value: 'compliance_safety', description: 'Required safety, regulatory, or roadworthiness work' },
240
+ { label: 'General Repair', value: 'general_repair', description: 'General corrective repair that does not fit a more specific category' },
241
+ { label: 'Mechanical Complaint', value: 'mechanical_complaint', description: 'Engine, drivetrain, suspension, steering, or other mechanical concern' },
242
+ { label: 'Electrical Complaint', value: 'electrical_complaint', description: 'Battery, charging, lighting, wiring, sensor, or electrical system concern' },
243
+ { label: 'Brake Issue', value: 'brake_issue', description: 'Brake wear, performance, air brake, ABS, or related safety concern' },
244
+ { label: 'Tire Issue', value: 'tire_issue', description: 'Tire wear, puncture, blowout, alignment, rotation, or replacement' },
245
+ { label: 'HVAC / Air Conditioning Issue', value: 'hvac_issue', description: 'Heating, ventilation, defrost, or air conditioning concern' },
246
+ { label: 'AdBlue / DEF', value: 'adblue_def', description: 'Diesel exhaust fluid, SCR, emissions fluid, or dosing system issue' },
247
+ { label: 'Fluid Leak', value: 'fluid_leak', description: 'Oil, coolant, fuel, hydraulic, brake fluid, or other leak' },
248
+ { label: 'Body Damage', value: 'body_damage', description: 'Non-accident body, panel, paint, glass, door, or cosmetic damage' },
249
+ { label: 'Accident Damage', value: 'accident_damage', description: 'Collision or incident-related inspection and repair' },
250
+ { label: 'Roadside Assistance', value: 'roadside_assistance', description: 'Tow, recovery, jump start, lockout, or field service request' },
251
+ { label: 'Breakdown', value: 'breakdown', description: 'Unplanned asset failure requiring urgent repair' },
252
+ { label: 'Other', value: 'other', description: 'Work that does not fit another operational category' },
253
+ ];
254
+
219
255
  export const issueStatuses = [
220
256
  { label: 'Open', value: 'open', description: 'Issue is open and unresolved' },
221
257
  { label: 'Pending', value: 'pending', description: 'Issue is logged but work has not yet started' },
@@ -862,6 +898,8 @@ export default function fleetOpsOptions(key) {
862
898
  contactStatuses,
863
899
  fuelReportTypes,
864
900
  fuelReportStatuses,
901
+ workOrderStatuses,
902
+ workOrderCategories,
865
903
  issueTypes,
866
904
  issueStatuses,
867
905
  issueCategories,
@@ -0,0 +1 @@
1
+ export { default } from '@fleetbase/fleetops-engine/components/order/form/orchestrator-constraints';
@@ -0,0 +1 @@
1
+ export { default } from '@fleetbase/fleetops-engine/controllers/connectivity/devices/index/details/sensors';
@@ -0,0 +1 @@
1
+ export { default } from '@fleetbase/fleetops-engine/controllers/connectivity/devices/index/details/vehicle';
@@ -0,0 +1 @@
1
+ export { default } from '@fleetbase/fleetops-engine/controllers/maintenance/index';
@@ -0,0 +1 @@
1
+ export { default } from '@fleetbase/fleetops-engine/controllers/management/index';
@@ -0,0 +1 @@
1
+ export { default } from '@fleetbase/fleetops-engine/controllers/settings/index';
@@ -0,0 +1 @@
1
+ export { default } from '@fleetbase/fleetops-engine/routes/analytics/index';
@@ -0,0 +1 @@
1
+ export { default } from '@fleetbase/fleetops-engine/routes/connectivity/devices/index/details/sensors';
@@ -0,0 +1 @@
1
+ export { default } from '@fleetbase/fleetops-engine/routes/connectivity/devices/index/details/vehicle';
@@ -0,0 +1 @@
1
+ export { default } from '@fleetbase/fleetops-engine/routes/maintenance/index';
@@ -0,0 +1 @@
1
+ export { default } from '@fleetbase/fleetops-engine/routes/settings/index';
@@ -0,0 +1 @@
1
+ export { default } from '@fleetbase/fleetops-engine/templates/analytics/index';
@@ -0,0 +1 @@
1
+ export { default } from '@fleetbase/fleetops-engine/templates/connectivity/devices/index/details/sensors';
@@ -0,0 +1 @@
1
+ export { default } from '@fleetbase/fleetops-engine/templates/connectivity/devices/index/details/vehicle';
@@ -0,0 +1 @@
1
+ export { default } from '@fleetbase/fleetops-engine/templates/maintenance/index';
@@ -0,0 +1 @@
1
+ export { default } from '@fleetbase/fleetops-engine/templates/management/index';
@@ -0,0 +1 @@
1
+ export { default } from '@fleetbase/fleetops-engine/templates/settings/index';
package/composer.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fleetbase/fleetops-api",
3
- "version": "0.6.52",
3
+ "version": "0.6.54",
4
4
  "description": "Fleet & Transport Management Extension for Fleetbase",
5
5
  "keywords": [
6
6
  "fleetbase-extension",
package/extension.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "Fleet-Ops",
3
- "version": "0.6.52",
3
+ "version": "0.6.54",
4
4
  "description": "Fleet & Transport Management Extension for Fleetbase",
5
5
  "repository": "https://github.com/fleetbase/fleetops",
6
6
  "license": "AGPL-3.0-or-later",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fleetbase/fleetops-engine",
3
- "version": "0.6.52",
3
+ "version": "0.6.54",
4
4
  "description": "Fleet & Transport Management Extension for Fleetbase",
5
5
  "fleetbase": {
6
6
  "route": "fleet-ops"
@@ -43,8 +43,8 @@
43
43
  "dependencies": {
44
44
  "@babel/core": "^7.23.2",
45
45
  "@fleetbase/ember-core": "^0.3.22",
46
- "@fleetbase/ember-ui": "^0.3.34",
47
- "@fleetbase/fleetops-data": "^0.1.37",
46
+ "@fleetbase/ember-ui": "^0.3.36",
47
+ "@fleetbase/fleetops-data": "^0.1.39",
48
48
  "@fleetbase/leaflet-routing-machine": "^3.2.17",
49
49
  "@fortawesome/ember-fontawesome": "^2.0.0",
50
50
  "@fortawesome/fontawesome-svg-core": "6.4.0",
@@ -19,6 +19,7 @@ return new class extends Migration {
19
19
 
20
20
  $table->string('code')->nullable()->index(); // external WO number
21
21
  $table->string('subject')->index();
22
+ $table->string('category')->nullable()->index(); // preventive_maintenance, tire_issue, breakdown, etc.
22
23
  $table->string('status')->default('open')->index(); // open, in_progress, blocked, done, canceled
23
24
  $table->string('priority')->nullable()->index(); // low, normal, high, critical
24
25
 
@@ -0,0 +1,30 @@
1
+ <?php
2
+
3
+ use Fleetbase\FleetOps\Models\Vehicle;
4
+ use Illuminate\Database\Migrations\Migration;
5
+ use Illuminate\Support\Facades\DB;
6
+ use Illuminate\Support\Facades\Schema;
7
+
8
+ return new class extends Migration {
9
+ public function up(): void
10
+ {
11
+ if (!Schema::hasTable('devices') || !Schema::hasColumn('devices', 'attachable_type') || !Schema::hasColumn('devices', 'attachable_uuid')) {
12
+ return;
13
+ }
14
+
15
+ DB::table('devices')
16
+ ->whereNotNull('attachable_uuid')
17
+ ->whereIn('attachable_type', [
18
+ 'Fleetbase\\Models\\Vehicle',
19
+ '\\Fleetbase\\Models\\Vehicle',
20
+ ])
21
+ ->update([
22
+ 'attachable_type' => Vehicle::class,
23
+ ]);
24
+ }
25
+
26
+ public function down(): void
27
+ {
28
+ // Intentionally do not restore invalid legacy morph class names.
29
+ }
30
+ };
@@ -0,0 +1,32 @@
1
+ <?php
2
+
3
+ use Illuminate\Database\Migrations\Migration;
4
+ use Illuminate\Database\Schema\Blueprint;
5
+ use Illuminate\Support\Facades\Schema;
6
+
7
+ return new class extends Migration {
8
+ /**
9
+ * Run the migrations.
10
+ */
11
+ public function up(): void
12
+ {
13
+ if (!Schema::hasColumn('work_orders', 'category')) {
14
+ Schema::table('work_orders', function (Blueprint $table) {
15
+ $table->string('category')->nullable()->index()->after('subject');
16
+ });
17
+ }
18
+ }
19
+
20
+ /**
21
+ * Reverse the migrations.
22
+ */
23
+ public function down(): void
24
+ {
25
+ if (Schema::hasColumn('work_orders', 'category')) {
26
+ Schema::table('work_orders', function (Blueprint $table) {
27
+ $table->dropIndex(['category']);
28
+ $table->dropColumn('category');
29
+ });
30
+ }
31
+ }
32
+ };
@@ -155,18 +155,19 @@ class MaintenanceSeeder extends Seeder
155
155
  $driver = $this->seededModel(Driver::class, 'driver_mira');
156
156
  $vehicle = $this->seededModel(Vehicle::class, 'truck_maintenance');
157
157
  $workOrders = [
158
- 'work_order_open' => ['WO-TEST-OPEN', 'Open Inspection', 'open', 'medium', $this->timestamp(-4), $this->timestamp(24), null, 'schedule_due_soon'],
159
- 'work_order_overdue' => ['WO-TEST-OVERDUE', 'Overdue Service', 'open', 'high', $this->timestamp(-120), $this->timestamp(-24), null, 'schedule_overdue'],
160
- 'work_order_completed' => ['WO-TEST-CLOSED', 'Completed Repair', 'completed', 'low', $this->timestamp(-240), $this->timestamp(-120), $this->timestamp(-96), 'schedule_overdue'],
158
+ 'work_order_open' => ['WO-TEST-OPEN', 'Open Inspection', 'inspection_request', 'open', 'medium', $this->timestamp(-4), $this->timestamp(24), null, 'schedule_due_soon'],
159
+ 'work_order_overdue' => ['WO-TEST-OVERDUE', 'Overdue Service', 'preventive_maintenance', 'open', 'high', $this->timestamp(-120), $this->timestamp(-24), null, 'schedule_overdue'],
160
+ 'work_order_completed' => ['WO-TEST-CLOSED', 'Completed Repair', 'general_repair', 'completed', 'low', $this->timestamp(-240), $this->timestamp(-120), $this->timestamp(-96), 'schedule_overdue'],
161
161
  ];
162
162
 
163
163
  $models = [];
164
- foreach ($workOrders as $seedId => [$code, $subject, $status, $priority, $openedAt, $dueAt, $closedAt, $scheduleSeedId]) {
164
+ foreach ($workOrders as $seedId => [$code, $subject, $category, $status, $priority, $openedAt, $dueAt, $closedAt, $scheduleSeedId]) {
165
165
  $models[$seedId] = $this->createRecord(WorkOrder::class, [
166
166
  '_key' => $this->fixtureKey($seedId),
167
167
  'company_uuid' => $company->uuid,
168
168
  'code' => $code,
169
169
  'subject' => $subject,
170
+ 'category' => $category,
170
171
  'status' => $status,
171
172
  'priority' => $priority,
172
173
  'target_type' => Vehicle::class,
@@ -37,6 +37,7 @@ class FixInvalidPolymorphicRelationTypeNamespaces extends Command
37
37
  ['model' => \Fleetbase\FleetOps\Models\Place::class, 'columns' => ['owner_type']],
38
38
  ['model' => \Fleetbase\FleetOps\Models\Entity::class, 'columns' => ['customer_type']],
39
39
  ['model' => \Fleetbase\FleetOps\Models\PurchaseRate::class, 'columns' => ['customer_type']],
40
+ ['model' => \Fleetbase\FleetOps\Models\Device::class, 'columns' => ['attachable_type']],
40
41
  ];
41
42
 
42
43
  foreach ($models as $modelConfig) {
@@ -124,6 +124,7 @@ class ProcessMaintenanceTriggers extends Command
124
124
  'company_uuid' => $schedule->company_uuid,
125
125
  'schedule_uuid' => $schedule->uuid,
126
126
  'subject' => $schedule->name,
127
+ 'category' => 'preventive_maintenance',
127
128
  'code' => $woCode,
128
129
  'status' => 'open',
129
130
  'priority' => $schedule->default_priority ?? 'normal',