@fleetbase/fleetops-engine 0.6.49 → 0.6.51

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 (271) hide show
  1. package/README.md +185 -67
  2. package/addon/components/contact/panel-header.hbs +11 -48
  3. package/addon/components/customer/create-order-form.hbs +2 -2
  4. package/addon/components/customer/details.hbs +1 -2
  5. package/addon/components/customer/form.hbs +62 -50
  6. package/addon/components/customer/form.js +27 -1
  7. package/addon/components/customer/order-form.hbs +2 -2
  8. package/addon/components/customer/orders.hbs +50 -2
  9. package/addon/components/customer/orders.js +67 -5
  10. package/addon/components/display-place.hbs +2 -2
  11. package/addon/components/driver/form.hbs +1 -1
  12. package/addon/components/home/getting-started-guidance.hbs +113 -0
  13. package/addon/components/home/getting-started-guidance.js +107 -0
  14. package/addon/components/issue/details/comments.hbs +3 -0
  15. package/addon/components/issue/details/comments.js +3 -0
  16. package/addon/components/issue/details/correspondence.hbs +9 -0
  17. package/addon/components/issue/details/correspondence.js +83 -0
  18. package/addon/components/issue/details/documents.hbs +69 -0
  19. package/addon/components/issue/details/documents.js +85 -0
  20. package/addon/components/issue/details.hbs +220 -59
  21. package/addon/components/issue/details.js +245 -0
  22. package/addon/components/issue/form.hbs +19 -1
  23. package/addon/components/issue/panel-header.hbs +43 -0
  24. package/addon/components/issue/panel-header.js +22 -0
  25. package/addon/components/issue/timeline.hbs +40 -0
  26. package/addon/components/issue/timeline.js +45 -0
  27. package/addon/components/leaflet-tracking-marker.js +3 -0
  28. package/addon/components/map/drawer/position-listing.js +3 -0
  29. package/addon/components/map/google-live-map.js +6 -2
  30. package/addon/components/map/leaflet-live-map.hbs +48 -14
  31. package/addon/components/map/leaflet-live-map.js +201 -20
  32. package/addon/components/map/order-list-overlay.hbs +4 -4
  33. package/addon/components/modals/convert-customer-to-vendor.hbs +30 -0
  34. package/addon/components/modals/convert-customer-to-vendor.js +55 -0
  35. package/addon/components/modals/issue-assign.hbs +20 -0
  36. package/addon/components/modals/issue-assign.js +49 -0
  37. package/addon/components/modals/issue-close.hbs +30 -0
  38. package/addon/components/modals/issue-close.js +73 -0
  39. package/addon/components/modals/issue-status.hbs +20 -0
  40. package/addon/components/modals/issue-status.js +43 -0
  41. package/addon/components/modals/order-change-destination.hbs +46 -0
  42. package/addon/components/modals/order-change-destination.js +106 -0
  43. package/addon/components/modals/reset-customer-credentials.js +12 -6
  44. package/addon/components/modals/stop-activity.hbs +28 -0
  45. package/addon/components/modals/stop-activity.js +52 -0
  46. package/addon/components/modals/update-order-activity.hbs +78 -2
  47. package/addon/components/modals/update-order-activity.js +197 -5
  48. package/addon/components/orchestrator/resource-panel.hbs +0 -10
  49. package/addon/components/orchestrator/resource-panel.js +2 -4
  50. package/addon/components/order/activity-list.hbs +2 -2
  51. package/addon/components/order/activity-timeline.hbs +31 -29
  52. package/addon/components/order/details/activity.hbs +3 -3
  53. package/addon/components/order/details/activity.js +13 -2
  54. package/addon/components/order/details/documents.js +2 -0
  55. package/addon/components/order/details/proof.hbs +40 -38
  56. package/addon/components/order/details/proof.js +31 -4
  57. package/addon/components/order/details/purchase-rate.hbs +2 -2
  58. package/addon/components/order/details/route.hbs +11 -3
  59. package/addon/components/order/details/route.js +91 -14
  60. package/addon/components/order/details/tracking.hbs +101 -72
  61. package/addon/components/order/details/tracking.js +149 -2
  62. package/addon/components/order/details.hbs +5 -5
  63. package/addon/components/order/details.js +19 -1
  64. package/addon/components/order/form/details.hbs +3 -3
  65. package/addon/components/order/form/documents.js +11 -4
  66. package/addon/components/order/form/route.hbs +108 -104
  67. package/addon/components/order/form/route.js +37 -1
  68. package/addon/components/order/form/service-rate.hbs +2 -2
  69. package/addon/components/order/header.hbs +1 -1
  70. package/addon/components/order-config-manager/activity-flow.hbs +4 -1
  71. package/addon/components/order-config-manager/activity-flow.js +178 -12
  72. package/addon/components/place/address.js +1 -1
  73. package/addon/components/route-list.hbs +17 -29
  74. package/addon/components/route-list.js +42 -10
  75. package/addon/components/service-rate/details.hbs +42 -1
  76. package/addon/components/service-rate/form.hbs +119 -1
  77. package/addon/components/service-rate/form.js +59 -0
  78. package/addon/components/vehicle/form.js +1 -1
  79. package/addon/components/vehicle/pill.hbs +1 -1
  80. package/addon/components/vendor/personnel-manager.hbs +166 -0
  81. package/addon/components/vendor/personnel-manager.js +143 -0
  82. package/addon/components/widget/live-fleet.hbs +1 -0
  83. package/addon/components/widget/live-fleet.js +2 -7
  84. package/addon/components/widget/revenue-trend.hbs +1 -1
  85. package/addon/components/widget/revenue-trend.js +75 -2
  86. package/addon/controllers/management/contacts/customers/details.js +31 -13
  87. package/addon/controllers/management/contacts/customers.js +16 -5
  88. package/addon/controllers/management/contacts/index/details.js +31 -13
  89. package/addon/controllers/management/contacts/index.js +7 -0
  90. package/addon/controllers/management/issues/index/details.js +52 -6
  91. package/addon/controllers/management/vehicles/index/new.js +1 -1
  92. package/addon/controllers/management/vendors/index/details.js +4 -0
  93. package/addon/controllers/operations/orders/index/details.js +15 -7
  94. package/addon/controllers/operations/orders/index.js +15 -1
  95. package/addon/extension.js +19 -12
  96. package/addon/helpers/format-duration.js +1 -38
  97. package/addon/helpers/place-address-html.js +2 -2
  98. package/addon/initializers/load-leaflet-assets.js +5 -6
  99. package/addon/initializers/patch-ember-leaflet-tooltip-layer.js +51 -0
  100. package/addon/routes/management/issues/index/details.js +1 -1
  101. package/addon/routes/operations/service-rates/index.js +1 -1
  102. package/addon/routes.js +1 -0
  103. package/addon/services/contact-actions.js +231 -1
  104. package/addon/services/geofence.js +163 -19
  105. package/addon/services/getting-started.js +44 -0
  106. package/addon/services/issue-actions.js +71 -0
  107. package/addon/services/leaflet-contextmenu-manager.js +27 -0
  108. package/addon/services/leaflet-map-manager.js +2 -0
  109. package/addon/services/map-adapter/leaflet.js +19 -0
  110. package/addon/services/service-areas.js +3 -0
  111. package/addon/services/vehicle-actions.js +1 -1
  112. package/addon/styles/fleetops-engine.css +1127 -1
  113. package/addon/templates/management/contacts/customers/details.hbs +1 -1
  114. package/addon/templates/management/contacts/index/details.hbs +1 -1
  115. package/addon/templates/management/contacts.hbs +2 -2
  116. package/addon/templates/management/issues/index/details/index.hbs +3 -1
  117. package/addon/templates/management/issues/index/details.hbs +3 -2
  118. package/addon/templates/management/vendors/index/details/personnel.hbs +1 -2
  119. package/addon/templates/operations/orders/index/details/index.hbs +2 -2
  120. package/addon/templates/operations/orders/index.hbs +1 -1
  121. package/addon/templates/operations/service-rates/index/edit.hbs +1 -0
  122. package/addon/templates/operations/service-rates/index/new.hbs +1 -0
  123. package/addon/templates/settings/payments/onboard.hbs +8 -8
  124. package/addon/utils/fleet-ops-options.js +2 -1
  125. package/addon/utils/leaflet-draw-namespace-guard.js +22 -0
  126. package/addon/utils/leaflet-plugin-loader.js +219 -0
  127. package/addon/utils/normalize-order-config-flow.js +41 -0
  128. package/addon/utils/place-address-html.js +3 -2
  129. package/addon/utils/route-visualization.js +54 -7
  130. package/addon/utils/setup-customer-portal.js +4 -64
  131. package/app/components/home/getting-started-guidance.js +1 -0
  132. package/app/components/issue/details/comments.js +1 -0
  133. package/app/components/issue/details/correspondence.js +1 -0
  134. package/app/components/issue/details/documents.js +1 -0
  135. package/app/components/issue/panel-header.js +1 -0
  136. package/app/components/modals/convert-customer-to-vendor.js +1 -0
  137. package/app/components/modals/issue-assign.js +1 -0
  138. package/app/components/modals/issue-close.js +1 -0
  139. package/app/components/modals/issue-status.js +1 -0
  140. package/app/components/modals/order-change-destination.js +1 -0
  141. package/app/components/modals/stop-activity.js +1 -0
  142. package/app/components/vendor/personnel-manager.js +1 -0
  143. package/app/helpers/format-duration.js +1 -1
  144. package/app/services/getting-started.js +1 -0
  145. package/app/utils/leaflet-draw-namespace-guard.js +1 -0
  146. package/app/utils/leaflet-plugin-loader.js +1 -0
  147. package/composer.json +1 -1
  148. package/extension.json +1 -1
  149. package/package.json +5 -5
  150. package/server/migrations/2026_05_21_000001_add_geographic_rules_to_service_rate_fees_table.php +37 -0
  151. package/server/migrations/2026_05_25_000001_add_endpoint_tracking_refs_to_payloads_table.php +50 -0
  152. package/server/migrations/2026_05_27_000001_default_driver_vehicle_statuses_to_available.php +48 -0
  153. package/server/migrations/2026_05_31_000001_add_portal_fields_to_vendor_personnels_table.php +30 -0
  154. package/server/migrations/2026_06_03_000000_ensure_tags_column_on_issues_table.php +31 -0
  155. package/server/migrations/2026_06_03_000001_add_order_uuid_to_issues_table.php +25 -0
  156. package/server/migrations/2026_06_04_000001_backfill_order_transaction_subjects.php +39 -0
  157. package/server/migrations/2026_06_04_000002_backfill_order_transaction_directions.php +24 -0
  158. package/server/resources/views/labels/default.php +57 -49
  159. package/server/resources/views/labels/waypoint-label.php +27 -20
  160. package/server/resources/views/mail/customer-credentials.blade.php +16 -13
  161. package/server/seeders/Testing/ConnectivitySeeder.php +1 -0
  162. package/server/seeders/Testing/FleetSeeder.php +22 -22
  163. package/server/seeders/Testing/OrdersSeeder.php +6 -22
  164. package/server/seeders/Testing/VroomOrchestrationSeeder.php +21 -21
  165. package/server/src/Console/Commands/AuditCustomerUserConflicts.php +75 -0
  166. package/server/src/Exceptions/CustomerUserConflictException.php +13 -0
  167. package/server/src/Expansions/UserFilterExpansion.php +28 -0
  168. package/server/src/Http/Controllers/Api/v1/ContactController.php +17 -2
  169. package/server/src/Http/Controllers/Api/v1/CustomerController.php +876 -0
  170. package/server/src/Http/Controllers/Api/v1/DriverController.php +1 -1
  171. package/server/src/Http/Controllers/Api/v1/IssueController.php +2 -0
  172. package/server/src/Http/Controllers/Api/v1/OrderConfigController.php +54 -0
  173. package/server/src/Http/Controllers/Api/v1/OrderController.php +109 -80
  174. package/server/src/Http/Controllers/Api/v1/PlaceController.php +10 -58
  175. package/server/src/Http/Controllers/Api/v1/ServiceAreaController.php +2 -2
  176. package/server/src/Http/Controllers/Api/v1/VehicleController.php +20 -3
  177. package/server/src/Http/Controllers/Internal/v1/ContactController.php +154 -0
  178. package/server/src/Http/Controllers/Internal/v1/CustomerController.php +116 -6
  179. package/server/src/Http/Controllers/Internal/v1/GettingStartedController.php +17 -0
  180. package/server/src/Http/Controllers/Internal/v1/IssueController.php +251 -0
  181. package/server/src/Http/Controllers/Internal/v1/LiveController.php +101 -66
  182. package/server/src/Http/Controllers/Internal/v1/OrderController.php +530 -52
  183. package/server/src/Http/Controllers/Internal/v1/PlaceController.php +10 -68
  184. package/server/src/Http/Controllers/Internal/v1/ServiceQuoteController.php +1 -1
  185. package/server/src/Http/Controllers/Internal/v1/SettingController.php +2 -2
  186. package/server/src/Http/Controllers/Internal/v1/VehicleController.php +54 -1
  187. package/server/src/Http/Controllers/Internal/v1/VendorController.php +89 -0
  188. package/server/src/Http/Middleware/AuthenticateCustomerToken.php +34 -0
  189. package/server/src/Http/Requests/CreateCustomerOrderRequest.php +63 -0
  190. package/server/src/Http/Requests/CreateCustomerRequest.php +48 -0
  191. package/server/src/Http/Requests/CreateDriverRequest.php +1 -1
  192. package/server/src/Http/Requests/CreateIssueRequest.php +4 -0
  193. package/server/src/Http/Requests/CreateVehicleRequest.php +25 -1
  194. package/server/src/Http/Requests/Internal/CreateDriverRequest.php +1 -1
  195. package/server/src/Http/Requests/UpdateIssueRequest.php +4 -0
  196. package/server/src/Http/Requests/VerifyCreateCustomerRequest.php +29 -0
  197. package/server/src/Http/Resources/Internal/v1/OrderConfig.php +41 -0
  198. package/server/src/Http/Resources/v1/Customer.php +79 -0
  199. package/server/src/Http/Resources/v1/Index/Order.php +12 -9
  200. package/server/src/Http/Resources/v1/Issue.php +25 -0
  201. package/server/src/Http/Resources/v1/Order.php +20 -18
  202. package/server/src/Http/Resources/v1/OrderConfig.php +74 -0
  203. package/server/src/Http/Resources/v1/Payload.php +23 -20
  204. package/server/src/Http/Resources/v1/ServiceArea.php +33 -19
  205. package/server/src/Http/Resources/v1/ServiceRateFee.php +7 -0
  206. package/server/src/Listeners/HandleOrderDispatched.php +2 -2
  207. package/server/src/Mail/CustomerCredentialsMail.php +5 -6
  208. package/server/src/Models/Contact.php +122 -66
  209. package/server/src/Models/Customer.php +64 -0
  210. package/server/src/Models/Driver.php +12 -3
  211. package/server/src/Models/Entity.php +2 -2
  212. package/server/src/Models/Issue.php +47 -6
  213. package/server/src/Models/Order.php +62 -10
  214. package/server/src/Models/Payload.php +17 -1
  215. package/server/src/Models/ServiceArea.php +1 -1
  216. package/server/src/Models/ServiceRate.php +273 -1
  217. package/server/src/Models/ServiceRateFee.php +39 -9
  218. package/server/src/Models/TrackingNumber.php +8 -2
  219. package/server/src/Models/Vehicle.php +18 -2
  220. package/server/src/Models/VendorPersonnel.php +10 -1
  221. package/server/src/Models/Waypoint.php +2 -2
  222. package/server/src/Models/Zone.php +1 -1
  223. package/server/src/Notifications/LateDeparture.php +2 -2
  224. package/server/src/Notifications/ProlongedStoppage.php +2 -2
  225. package/server/src/Notifications/RouteDeviation.php +2 -2
  226. package/server/src/Observers/ContactObserver.php +2 -0
  227. package/server/src/Observers/PurchaseRateObserver.php +20 -0
  228. package/server/src/Observers/ServiceRateObserver.php +6 -6
  229. package/server/src/Observers/ZoneObserver.php +56 -0
  230. package/server/src/Orchestration/Engines/VroomOrchestrationEngine.php +1 -1
  231. package/server/src/Providers/FleetOpsServiceProvider.php +2 -0
  232. package/server/src/Support/Analytics/AbstractAnalytics.php +6 -6
  233. package/server/src/Support/Analytics/FuelEfficiency.php +2 -2
  234. package/server/src/Support/Analytics/OrdersByStatus.php +1 -1
  235. package/server/src/Support/Analytics/RevenueTrend.php +0 -1
  236. package/server/src/Support/Analytics/TopDrivers.php +10 -2
  237. package/server/src/Support/CustomerAuth.php +98 -0
  238. package/server/src/Support/GettingStarted.php +144 -0
  239. package/server/src/Support/LabelPdf.php +52 -0
  240. package/server/src/Support/Metrics/AbstractMetric.php +4 -4
  241. package/server/src/Support/PlaceSearch.php +282 -0
  242. package/server/src/Support/ResolvesOrderServiceStops.php +522 -0
  243. package/server/src/Tracking/TrackingContextBuilder.php +41 -38
  244. package/server/src/Tracking/TrackingIntelligenceService.php +109 -9
  245. package/server/src/Tracking/TrackingStop.php +13 -11
  246. package/server/src/routes.php +76 -10
  247. package/server/tests/AnalyticsRoutesTest.php +8 -0
  248. package/server/tests/CapacityAllocationEngineTest.php +10 -10
  249. package/server/tests/CustomerContactIdentitySafetyTest.php +95 -0
  250. package/server/tests/CustomerEndpointTest.php +199 -0
  251. package/server/tests/DriverVehicleStatusDefaultTest.php +39 -0
  252. package/server/tests/GettingStartedStatusTest.php +21 -0
  253. package/server/tests/LabelPdfRenderingTest.php +23 -0
  254. package/server/tests/LiveControllerViewportTest.php +60 -0
  255. package/server/tests/MetricsRegistryTest.php +4 -8
  256. package/server/tests/OrchestrationPayloadBuilderTest.php +2 -2
  257. package/server/tests/OrderActivityFlowRegressionTest.php +116 -0
  258. package/server/tests/OrderConfigEndpointTest.php +86 -0
  259. package/server/tests/OrderFileAttachmentTest.php +20 -0
  260. package/server/tests/ServiceAreaZoneApiShapeTest.php +78 -0
  261. package/server/tests/VehicleDriverAssignmentTest.php +18 -0
  262. package/translations/ar-ae.yml +9 -0
  263. package/translations/bg-bg.yaml +9 -0
  264. package/translations/en-us.yaml +12 -0
  265. package/translations/es-pa.yaml +9 -0
  266. package/translations/fr-fr.yaml +9 -0
  267. package/translations/mn-mn.yaml +9 -0
  268. package/translations/pt-br.yaml +9 -0
  269. package/translations/ru-ru.yaml +9 -0
  270. package/translations/vi-vn.yaml +9 -0
  271. package/server/migrations/2026_05_13_000001_repair_customer_contact_user_types.php +0 -86
@@ -0,0 +1,43 @@
1
+ <div class="issue-panel-header">
2
+ <div class="issue-panel-header-main">
3
+ <div class="issue-panel-header-icon">
4
+ <FaIcon @icon="triangle-exclamation" />
5
+ </div>
6
+ <div class="issue-panel-header-content">
7
+ <div class="issue-panel-header-title-row">
8
+ <h1 class="issue-panel-header-title">{{this.title}}</h1>
9
+ </div>
10
+ {{#if @resource.public_id}}
11
+ <ClickToCopy @value={{@resource.public_id}} class="issue-panel-header-id">
12
+ <FaIcon @icon="hashtag" />
13
+ <span>{{@resource.public_id}}</span>
14
+ </ClickToCopy>
15
+ {{/if}}
16
+ <div class="issue-panel-header-meta">
17
+ {{#if this.subtitle}}
18
+ <span>{{titleize this.subtitle}}</span>
19
+ {{/if}}
20
+ {{#if @resource.createdAt}}
21
+ <span>Reported {{@resource.createdAt}}</span>
22
+ {{/if}}
23
+ </div>
24
+ </div>
25
+ </div>
26
+
27
+ <div class="issue-panel-header-actions">
28
+ <div class="issue-panel-header-badges">
29
+ <Badge @status={{@resource.status}} />
30
+ <Badge @status={{@resource.priority}} />
31
+ </div>
32
+ <Layout::Resource::Panel::HeaderActions
33
+ @resource={{@resource}}
34
+ @saveTask={{@saveTask}}
35
+ @saveOptions={{@saveOptions}}
36
+ @saveDisabled={{@saveDisabled}}
37
+ @pojoResource={{@pojoResource}}
38
+ @authSchema={{@authSchema}}
39
+ @actionButtons={{@actionButtons}}
40
+ @onPressCancel={{@onPressCancel}}
41
+ />
42
+ </div>
43
+ </div>
@@ -0,0 +1,22 @@
1
+ import Component from '@glimmer/component';
2
+
3
+ export default class IssuePanelHeaderComponent extends Component {
4
+ get resource() {
5
+ return this.args.resource;
6
+ }
7
+
8
+ get title() {
9
+ return this.resource?.title || `Issue reported on ${this.resource?.createdAt || 'unknown date'}`;
10
+ }
11
+
12
+ get tags() {
13
+ return Array.isArray(this.resource?.tags) ? this.resource.tags.filter(Boolean) : [];
14
+ }
15
+
16
+ get subtitle() {
17
+ return [this.resource?.type, this.resource?.category]
18
+ .filter(Boolean)
19
+ .map((value) => value.replace(/[-_]/g, ' '))
20
+ .join(' / ');
21
+ }
22
+ }
@@ -0,0 +1,40 @@
1
+ <div class="issue-timeline" {{did-update this.reload this.issueId}} ...attributes>
2
+ {{#if this.loadTimeline.isRunning}}
3
+ <div class="issue-timeline-loading">
4
+ <Spinner @loadingMessage="Loading timeline..." />
5
+ </div>
6
+ {{else if this.hasEvents}}
7
+ <ol class="issue-timeline-list">
8
+ {{#each this.events as |event|}}
9
+ <li class="issue-timeline-event tone-{{event.tone}}">
10
+ <div class="issue-timeline-marker">
11
+ <FaIcon @icon={{event.icon}} />
12
+ </div>
13
+ <div class="issue-timeline-card">
14
+ <div class="issue-timeline-card-header">
15
+ <div>
16
+ <div class="issue-timeline-label">{{event.label}}</div>
17
+ <div class="issue-timeline-actor">{{n-a event.actor_name "Someone"}}</div>
18
+ </div>
19
+ <time>{{n-a (format-date-fns event.created_at "dd MMM yyyy HH:mm")}}</time>
20
+ </div>
21
+ {{#if event.description}}
22
+ <p>{{event.description}}</p>
23
+ {{/if}}
24
+ {{#if event.meta.file_url}}
25
+ <a href={{event.meta.file_url}} target="_blank" rel="noopener noreferrer" class="issue-timeline-link">
26
+ <FaIcon @icon="download" />
27
+ <span>{{n-a event.meta.file_name "Download file"}}</span>
28
+ </a>
29
+ {{/if}}
30
+ </div>
31
+ </li>
32
+ {{/each}}
33
+ </ol>
34
+ {{else}}
35
+ <div class="issue-detail-empty issue-detail-empty-compact">
36
+ <FaIcon @icon="timeline" />
37
+ <span>No issue activity yet.</span>
38
+ </div>
39
+ {{/if}}
40
+ </div>
@@ -0,0 +1,45 @@
1
+ import Component from '@glimmer/component';
2
+ import { tracked } from '@glimmer/tracking';
3
+ import { inject as service } from '@ember/service';
4
+ import { action } from '@ember/object';
5
+ import { debug } from '@ember/debug';
6
+ import { task } from 'ember-concurrency';
7
+
8
+ export default class IssueTimelineComponent extends Component {
9
+ @service fetch;
10
+ @service notifications;
11
+
12
+ @tracked events = [];
13
+
14
+ constructor() {
15
+ super(...arguments);
16
+ this.loadTimeline.perform();
17
+ }
18
+
19
+ get issueId() {
20
+ return this.args.resource?.id || this.args.resource?.uuid || this.args.resource?.public_id;
21
+ }
22
+
23
+ get hasEvents() {
24
+ return this.events.length > 0;
25
+ }
26
+
27
+ @task *loadTimeline() {
28
+ if (!this.issueId) {
29
+ this.events = [];
30
+ return;
31
+ }
32
+
33
+ try {
34
+ const response = yield this.fetch.get(`issues/${this.issueId}/timeline`, {}, { namespace: 'int/v1' });
35
+ this.events = response.events ?? response.timeline ?? [];
36
+ } catch (err) {
37
+ debug('Failed to load issue timeline: ' + err.message);
38
+ this.notifications.serverError(err);
39
+ }
40
+ }
41
+
42
+ @action reload() {
43
+ this.loadTimeline.perform();
44
+ }
45
+ }
@@ -1,5 +1,6 @@
1
1
  import MarkerLayer from 'ember-leaflet/components/marker-layer';
2
2
  import { isArray } from '@ember/array';
3
+ import ensureLeafletDrawEditNamespace from '../utils/leaflet-draw-namespace-guard';
3
4
 
4
5
  const __draggingHotfix = (layer) => {
5
6
  if (!layer.dragging) {
@@ -23,6 +24,7 @@ const arrayFromLatLng = (latlng) => {
23
24
  };
24
25
 
25
26
  const L = window.leaflet || window.L;
27
+ ensureLeafletDrawEditNamespace(L);
26
28
  const oldIE = L.DomUtil.TRANSFORM === 'msTransform';
27
29
  L.TrackingMarker = L.Marker.extend({
28
30
  // eslint-disable-next-line ember/avoid-leaking-state-in-ember-objects
@@ -291,6 +293,7 @@ export default class LeafletTrackingMarkerComponent extends MarkerLayer {
291
293
  }
292
294
 
293
295
  createLayer() {
296
+ ensureLeafletDrawEditNamespace(L);
294
297
  const { rotationAngle, location } = this.args;
295
298
  const bearingAngle = rotationAngle ?? computeBearing([0, 0], location);
296
299
  return new L.TrackingMarker(...this.requiredOptions, { ...this.options, bearingAngle });
@@ -7,6 +7,7 @@ import { isArray } from '@ember/array';
7
7
  import { htmlSafe } from '@ember/template';
8
8
  import { startOfWeek, endOfWeek, format } from 'date-fns';
9
9
  import getModelName from '@fleetbase/ember-core/utils/get-model-name';
10
+ import ensureLeafletDrawEditNamespace from '../../../utils/leaflet-draw-namespace-guard';
10
11
 
11
12
  const L = window.leaflet || window.L;
12
13
 
@@ -412,6 +413,8 @@ export default class MapDrawerPositionListingComponent extends Component {
412
413
  return;
413
414
  }
414
415
 
416
+ ensureLeafletDrawEditNamespace(L);
417
+ ensureLeafletDrawEditNamespace();
415
418
  const marker = L.circleMarker([lat, lng], {
416
419
  radius: 3,
417
420
  color: '#3b82f6',
@@ -276,15 +276,19 @@ export default class MapGoogleLiveMapComponent extends Component {
276
276
  }
277
277
 
278
278
  _showServiceAreaContextMenu(serviceArea, event) {
279
- const items = this.mapManager.getComposedContextMenuItems(`service-area:${serviceArea.public_id}`);
279
+ const items = this.mapManager.getComposedContextMenuItems(this._resourceContextKey('service-area', serviceArea));
280
280
  this.mapManager.showContextMenu(event, items);
281
281
  }
282
282
 
283
283
  _showZoneContextMenu(zone, event) {
284
- const items = this.mapManager.getComposedContextMenuItems(`zone:${zone.public_id}`);
284
+ const items = this.mapManager.getComposedContextMenuItems(this._resourceContextKey('zone', zone));
285
285
  this.mapManager.showContextMenu(event, items);
286
286
  }
287
287
 
288
+ _resourceContextKey(type, resource) {
289
+ return `${type}:${resource?.public_id ?? resource?.id}`;
290
+ }
291
+
288
292
  _closeAllInfoWindows() {
289
293
  this._infoWindows.forEach((iw) => iw.close());
290
294
  this.mapManager.closeContextMenu();
@@ -13,7 +13,7 @@
13
13
  through the provider-agnostic MapManagerService.
14
14
  }}
15
15
 
16
- <div class="live-map-component {{@wrapperClass}}">
16
+ <div class="live-map-component {{@wrapperClass}}" {{did-update this.syncServiceAreaContextMenus this.serviceAreaActions.serviceAreas this.serviceAreaActions.serviceAreas.length}}>
17
17
 
18
18
  {{#if this.shouldUseGoogleMaps}}
19
19
  {{! ─── Google Maps branch ──────────────────────────────────────────── }}
@@ -39,7 +39,7 @@
39
39
  @mapClass={{@mapClass}}
40
40
  ...attributes
41
41
  />
42
- {{else}}
42
+ {{else if this.leafletPluginsReady}}
43
43
  {{! ─── Leaflet branch (default) ────────────────────────────────────── }}
44
44
  <LeafletMap
45
45
  id={{this.id}}
@@ -87,7 +87,11 @@
87
87
  <div class="flex items-center gap-1.5 text-xs font-semibold mb-1.5">
88
88
  <span class="inline-block w-2 h-2 rounded-full {{if driver.online 'bg-green-400' 'bg-red-500'}}"></span>
89
89
  <span>{{driver.name}}</span>
90
- <div class="status-badge {{if driver.status (dasherize driver.status) 'default'}}-status-badge status-badge-{{if driver.status (dasherize driver.status) 'default'}} shadow-none ml-auto">
90
+ <div
91
+ class="status-badge
92
+ {{if driver.status (dasherize driver.status) 'default'}}-status-badge status-badge-{{if driver.status (dasherize driver.status) 'default'}}
93
+ shadow-none ml-auto"
94
+ >
91
95
  <span class="rounded-full text-[9px] px-1.5 py-0.5">{{n-a driver.meta.status_label (smart-humanize driver.status)}}</span>
92
96
  </div>
93
97
  </div>
@@ -122,7 +126,10 @@
122
126
  </div>
123
127
  <div class="rounded bg-gray-900 shadow-md px-1.5 py-1 min-w-0">
124
128
  <div class="text-[9px] font-semibold uppercase text-gray-400 leading-none">Location</div>
125
- <div class="text-[11px] text-white leading-tight whitespace-normal break-words">{{n-a driver.meta.location_coordinates (point-coordinates driver.location)}}</div>
129
+ <div class="text-[11px] text-white leading-tight whitespace-normal break-words">{{n-a
130
+ driver.meta.location_coordinates
131
+ (point-coordinates driver.location)
132
+ }}</div>
126
133
  </div>
127
134
  </div>
128
135
  </div>
@@ -132,7 +139,11 @@
132
139
  <div class="flex items-center gap-1.5 text-xs font-semibold mb-1.5">
133
140
  <span class="inline-block w-2 h-2 rounded-full {{if driver.online 'bg-green-400' 'bg-red-500'}}"></span>
134
141
  <span>{{driver.name}}</span>
135
- <div class="status-badge {{if driver.status (dasherize driver.status) 'default'}}-status-badge status-badge-{{if driver.status (dasherize driver.status) 'default'}} shadow-none ml-auto">
142
+ <div
143
+ class="status-badge
144
+ {{if driver.status (dasherize driver.status) 'default'}}-status-badge status-badge-{{if driver.status (dasherize driver.status) 'default'}}
145
+ shadow-none ml-auto"
146
+ >
136
147
  <span class="rounded-full text-[9px] px-1.5 py-0.5">{{n-a driver.meta.status_label (smart-humanize driver.status)}}</span>
137
148
  </div>
138
149
  </div>
@@ -167,7 +178,10 @@
167
178
  </div>
168
179
  <div class="rounded bg-gray-900 shadow-md px-1.5 py-1 min-w-0">
169
180
  <div class="text-[9px] font-semibold uppercase text-gray-400 leading-none">Location</div>
170
- <div class="text-[11px] text-white leading-tight whitespace-normal break-words">{{n-a driver.meta.location_coordinates (point-coordinates driver.location)}}</div>
181
+ <div class="text-[11px] text-white leading-tight whitespace-normal break-words">{{n-a
182
+ driver.meta.location_coordinates
183
+ (point-coordinates driver.location)
184
+ }}</div>
171
185
  </div>
172
186
  </div>
173
187
  </div>
@@ -192,14 +206,24 @@
192
206
  <div class="flex items-center gap-1.5 text-xs font-semibold mb-1.5">
193
207
  <span class="inline-block w-2 h-2 rounded-full {{if vehicle.online 'bg-green-400' 'bg-red-500'}}"></span>
194
208
  <span>{{vehicle.displayName}}</span>
195
- <div class="status-badge {{if vehicle.status (dasherize vehicle.status) 'default'}}-status-badge status-badge-{{if vehicle.status (dasherize vehicle.status) 'default'}} shadow-none ml-auto">
209
+ <div
210
+ class="status-badge
211
+ {{if vehicle.status (dasherize vehicle.status) 'default'}}-status-badge status-badge-{{if vehicle.status (dasherize vehicle.status) 'default'}}
212
+ shadow-none ml-auto"
213
+ >
196
214
  <span class="rounded-full text-[9px] px-1.5 py-0.5">{{n-a vehicle.meta.status_label}}</span>
197
215
  </div>
198
216
  </div>
199
217
  <div class="grid grid-cols-2 gap-1">
200
218
  <div class="rounded bg-gray-900 shadow-md px-1.5 py-1 min-w-0">
201
219
  <div class="text-[9px] font-semibold uppercase text-gray-400 leading-none">Vehicle #</div>
202
- <div class="text-[11px] text-white leading-tight whitespace-normal break-words">{{n-a vehicle.internal_id vehicle.public_id vehicle.plate_number vehicle.serial_number vehicle.vin}}</div>
220
+ <div class="text-[11px] text-white leading-tight whitespace-normal break-words">{{n-a
221
+ vehicle.internal_id
222
+ vehicle.public_id
223
+ vehicle.plate_number
224
+ vehicle.serial_number
225
+ vehicle.vin
226
+ }}</div>
203
227
  </div>
204
228
  <div class="rounded bg-gray-900 shadow-md px-1.5 py-1 min-w-0">
205
229
  <div class="text-[9px] font-semibold uppercase text-gray-400 leading-none">Driver</div>
@@ -229,14 +253,24 @@
229
253
  <div class="flex items-center gap-1.5 text-xs font-semibold mb-1.5">
230
254
  <span class="inline-block w-2 h-2 rounded-full {{if vehicle.online 'bg-green-400' 'bg-red-500'}}"></span>
231
255
  <span>{{vehicle.displayName}}</span>
232
- <div class="status-badge {{if vehicle.status (dasherize vehicle.status) 'default'}}-status-badge status-badge-{{if vehicle.status (dasherize vehicle.status) 'default'}} shadow-none ml-auto">
256
+ <div
257
+ class="status-badge
258
+ {{if vehicle.status (dasherize vehicle.status) 'default'}}-status-badge status-badge-{{if vehicle.status (dasherize vehicle.status) 'default'}}
259
+ shadow-none ml-auto"
260
+ >
233
261
  <span class="rounded-full text-[9px] px-1.5 py-0.5">{{n-a vehicle.meta.status_label}}</span>
234
262
  </div>
235
263
  </div>
236
264
  <div class="grid grid-cols-2 gap-1">
237
265
  <div class="rounded bg-gray-900 shadow-md px-1.5 py-1 min-w-0">
238
266
  <div class="text-[9px] font-semibold uppercase text-gray-400 leading-none">Vehicle #</div>
239
- <div class="text-[11px] text-white leading-tight whitespace-normal break-words">{{n-a vehicle.internal_id vehicle.public_id vehicle.plate_number vehicle.serial_number vehicle.vin}}</div>
267
+ <div class="text-[11px] text-white leading-tight whitespace-normal break-words">{{n-a
268
+ vehicle.internal_id
269
+ vehicle.public_id
270
+ vehicle.plate_number
271
+ vehicle.serial_number
272
+ vehicle.vin
273
+ }}</div>
240
274
  </div>
241
275
  <div class="rounded bg-gray-900 shadow-md px-1.5 py-1 min-w-0">
242
276
  <div class="text-[9px] font-semibold uppercase text-gray-400 leading-none">Driver</div>
@@ -291,8 +325,8 @@
291
325
  @id={{serviceArea.id}}
292
326
  @record={{serviceArea}}
293
327
  @locations={{unwrap-coordinates serviceArea.leafletCoordinates}}
294
- @fillColor={{serviceArea.color}}
295
- @color={{serviceArea.stroke_color}}
328
+ @fillColor={{or serviceArea.color "#3388ff"}}
329
+ @color={{or serviceArea.stroke_color serviceArea.color "#3388ff"}}
296
330
  @onAdd={{fn this.trigger "onServiceAreaLayerAdded" serviceArea}}
297
331
  as |polygon|
298
332
  >
@@ -304,8 +338,8 @@
304
338
  @id={{zone.id}}
305
339
  @record={{zone}}
306
340
  @locations={{unwrap-coordinates zone.leafletCoordinates}}
307
- @fillColor={{zone.color}}
308
- @color={{zone.stroke_color}}
341
+ @fillColor={{or zone.color "#3388ff"}}
342
+ @color={{or zone.stroke_color zone.color "#3388ff"}}
309
343
  @onAdd={{fn this.trigger "onZoneLayerAdd" zone}}
310
344
  as |polygon|
311
345
  >