@fleetbase/fleetops-engine 0.6.50 → 0.6.52

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 (494) hide show
  1. package/README.md +183 -67
  2. package/addon/components/cell/telematic-provider.hbs +16 -0
  3. package/addon/components/cell/telematic-provider.js +36 -0
  4. package/addon/components/cell/telematic-status.hbs +1 -0
  5. package/addon/components/cell/telematic-status.js +39 -0
  6. package/addon/components/contact/panel-header.hbs +11 -48
  7. package/addon/components/customer/details.hbs +1 -2
  8. package/addon/components/customer/form.hbs +63 -51
  9. package/addon/components/customer/form.js +27 -1
  10. package/addon/components/customer/orders.hbs +48 -0
  11. package/addon/components/customer/orders.js +67 -5
  12. package/addon/components/device/manager.hbs +5 -6
  13. package/addon/components/device/manager.js +12 -15
  14. package/addon/components/driver/details.hbs +1 -1
  15. package/addon/components/driver/form.hbs +1 -1
  16. package/addon/components/fleet/vehicle-listing.js +1 -0
  17. package/addon/components/fuel-integration/form.hbs +200 -0
  18. package/addon/components/fuel-integration/form.js +242 -0
  19. package/addon/components/fuel-integration/hub.hbs +154 -0
  20. package/addon/components/fuel-integration/hub.js +165 -0
  21. package/addon/components/fuel-integration/matching-priority.hbs +76 -0
  22. package/addon/components/fuel-integration/matching-priority.js +145 -0
  23. package/addon/components/fuel-report/details.hbs +13 -1
  24. package/addon/components/home/getting-started-guidance.hbs +113 -0
  25. package/addon/components/home/getting-started-guidance.js +107 -0
  26. package/addon/components/issue/details/comments.hbs +3 -0
  27. package/addon/components/issue/details/comments.js +3 -0
  28. package/addon/components/issue/details/correspondence.hbs +9 -0
  29. package/addon/components/issue/details/correspondence.js +83 -0
  30. package/addon/components/issue/details/documents.hbs +69 -0
  31. package/addon/components/issue/details/documents.js +85 -0
  32. package/addon/components/issue/details.hbs +166 -59
  33. package/addon/components/issue/details.js +149 -0
  34. package/addon/components/issue/form.hbs +19 -1
  35. package/addon/components/issue/panel-header.hbs +43 -0
  36. package/addon/components/issue/panel-header.js +22 -0
  37. package/addon/components/issue/timeline.hbs +40 -0
  38. package/addon/components/issue/timeline.js +45 -0
  39. package/addon/components/layout/fleet-ops-sidebar.js +20 -2
  40. package/addon/components/leaflet-tracking-marker.js +3 -0
  41. package/addon/components/map/drawer/device-event-listing.hbs +12 -2
  42. package/addon/components/map/drawer/driver-listing.hbs +14 -1
  43. package/addon/components/map/drawer/place-listing.hbs +14 -1
  44. package/addon/components/map/drawer/position-listing.hbs +12 -2
  45. package/addon/components/map/drawer/position-listing.js +3 -0
  46. package/addon/components/map/drawer/vehicle-listing.hbs +14 -1
  47. package/addon/components/map/leaflet-live-map.hbs +2 -2
  48. package/addon/components/map/leaflet-live-map.js +17 -0
  49. package/addon/components/map/order-list-overlay.hbs +4 -4
  50. package/addon/components/modals/assigned-orders.hbs +40 -0
  51. package/addon/components/modals/attach-device.hbs +4 -3
  52. package/addon/components/modals/attach-telematic-device.hbs +25 -0
  53. package/addon/components/modals/attach-telematic-device.js +3 -0
  54. package/addon/components/modals/convert-customer-to-vendor.hbs +30 -0
  55. package/addon/components/modals/convert-customer-to-vendor.js +55 -0
  56. package/addon/components/modals/driver-assign-order.hbs +7 -58
  57. package/addon/components/modals/driver-assign-vehicle.hbs +10 -2
  58. package/addon/components/modals/fleet-assign-driver.hbs +18 -0
  59. package/addon/components/modals/fleet-assign-driver.js +3 -0
  60. package/addon/components/modals/fleet-assign-vehicle.hbs +18 -0
  61. package/addon/components/modals/fleet-assign-vehicle.js +3 -0
  62. package/addon/components/modals/issue-assign.hbs +20 -0
  63. package/addon/components/modals/issue-assign.js +49 -0
  64. package/addon/components/modals/issue-close.hbs +30 -0
  65. package/addon/components/modals/issue-close.js +73 -0
  66. package/addon/components/modals/issue-status.hbs +20 -0
  67. package/addon/components/modals/issue-status.js +43 -0
  68. package/addon/components/modals/reset-customer-credentials.js +12 -6
  69. package/addon/components/modals/telematic-connection-diagnostics.hbs +75 -0
  70. package/addon/components/modals/telematic-connection-diagnostics.js +287 -0
  71. package/addon/components/modals/update-order-activity.hbs +51 -17
  72. package/addon/components/modals/update-order-activity.js +59 -5
  73. package/addon/components/modals/vehicle-details.hbs +6 -1
  74. package/addon/components/modals/vehicle-form.hbs +8 -1
  75. package/addon/components/order/card.hbs +106 -0
  76. package/addon/components/order/card.js +257 -0
  77. package/addon/components/order/details/activity.js +2 -2
  78. package/addon/components/order/details/proof.hbs +40 -38
  79. package/addon/components/order/details/proof.js +31 -4
  80. package/addon/components/order/details.hbs +5 -5
  81. package/addon/components/order/details.js +19 -1
  82. package/addon/components/order/form/service-rate.hbs +2 -0
  83. package/addon/components/order/header.hbs +1 -1
  84. package/addon/components/route-list.hbs +0 -12
  85. package/addon/components/service-rate/details.hbs +1 -1
  86. package/addon/components/service-rate/form.hbs +4 -3
  87. package/addon/components/service-rate/form.js +4 -0
  88. package/addon/components/telematic/details.hbs +98 -87
  89. package/addon/components/telematic/details.js +230 -1
  90. package/addon/components/telematic/form.hbs +303 -72
  91. package/addon/components/telematic/form.js +519 -3
  92. package/addon/components/telematic/hub.hbs +149 -0
  93. package/addon/components/telematic/hub.js +142 -0
  94. package/addon/components/telematic/settings.hbs +152 -0
  95. package/addon/components/telematic/settings.js +45 -0
  96. package/addon/components/telematic/tab-empty-state.hbs +29 -0
  97. package/addon/components/telematic/tab-empty-state.js +33 -0
  98. package/addon/components/vehicle/details.hbs +6 -1
  99. package/addon/components/vehicle/form.hbs +2 -1
  100. package/addon/components/vendor/personnel-manager.hbs +166 -0
  101. package/addon/components/vendor/personnel-manager.js +143 -0
  102. package/addon/components/widget/fuel-providers.hbs +43 -0
  103. package/addon/components/widget/fuel-providers.js +27 -0
  104. package/addon/components/widget/live-fleet.hbs +1 -0
  105. package/addon/components/widget/live-fleet.js +2 -7
  106. package/addon/components/widget/revenue-trend.hbs +1 -1
  107. package/addon/components/widget/revenue-trend.js +75 -2
  108. package/addon/controllers/connectivity/devices/index/details.js +27 -1
  109. package/addon/controllers/connectivity/devices/index.js +14 -0
  110. package/addon/controllers/connectivity/fuel-providers/details/sync.js +18 -0
  111. package/addon/controllers/connectivity/fuel-providers/details/transactions.js +24 -0
  112. package/addon/controllers/connectivity/fuel-providers/details.js +69 -0
  113. package/addon/controllers/connectivity/fuel-providers/edit.js +24 -0
  114. package/addon/controllers/connectivity/fuel-providers/index.js +177 -0
  115. package/addon/controllers/connectivity/fuel-providers/new.js +37 -0
  116. package/addon/controllers/connectivity/telematics/details/attachments.js +247 -0
  117. package/addon/controllers/connectivity/telematics/details/devices.js +368 -0
  118. package/addon/controllers/connectivity/telematics/details/events.js +244 -0
  119. package/addon/controllers/connectivity/telematics/details/index.js +3 -0
  120. package/addon/controllers/connectivity/telematics/details/logs.js +43 -0
  121. package/addon/controllers/connectivity/telematics/details/sensors.js +270 -0
  122. package/addon/controllers/connectivity/telematics/details.js +149 -0
  123. package/addon/controllers/connectivity/telematics/{index/edit.js → edit.js} +15 -4
  124. package/addon/controllers/connectivity/telematics/index.js +25 -5
  125. package/addon/controllers/connectivity/telematics/{index/new.js → new.js} +8 -2
  126. package/addon/controllers/management/contacts/customers/details.js +31 -13
  127. package/addon/controllers/management/contacts/customers.js +16 -5
  128. package/addon/controllers/management/contacts/index/details.js +31 -13
  129. package/addon/controllers/management/contacts/index.js +7 -0
  130. package/addon/controllers/management/drivers/index/details.js +78 -1
  131. package/addon/controllers/management/drivers/index.js +39 -0
  132. package/addon/controllers/management/fleets/index/details.js +23 -1
  133. package/addon/controllers/management/fleets/index.js +6 -1
  134. package/addon/controllers/management/fuel-reports/index.js +37 -1
  135. package/addon/controllers/management/fuel-transactions/index/details.js +70 -0
  136. package/addon/controllers/management/fuel-transactions/index.js +240 -0
  137. package/addon/controllers/management/issues/index/details.js +52 -6
  138. package/addon/controllers/management/vehicles/index/details.js +32 -0
  139. package/addon/controllers/management/vehicles/index.js +26 -0
  140. package/addon/controllers/management/vendors/index/details.js +4 -0
  141. package/addon/controllers/operations/orders/index/details.js +11 -3
  142. package/addon/controllers/operations/orders/index.js +5 -1
  143. package/addon/controllers/settings/payments/index.js +5 -0
  144. package/addon/extension.js +29 -12
  145. package/addon/helpers/format-duration.js +1 -38
  146. package/addon/initializers/load-leaflet-assets.js +5 -6
  147. package/addon/initializers/patch-ember-leaflet-tooltip-layer.js +51 -0
  148. package/addon/routes/connectivity/fuel-providers/details/index.js +7 -0
  149. package/addon/routes/connectivity/fuel-providers/details/matching.js +7 -0
  150. package/addon/routes/connectivity/fuel-providers/details/settings.js +7 -0
  151. package/addon/routes/connectivity/fuel-providers/details/sync.js +18 -0
  152. package/addon/routes/connectivity/fuel-providers/details/transactions.js +14 -0
  153. package/addon/routes/connectivity/fuel-providers/details.js +18 -0
  154. package/addon/routes/connectivity/fuel-providers/edit.js +18 -0
  155. package/addon/routes/connectivity/fuel-providers/index.js +20 -0
  156. package/addon/routes/connectivity/fuel-providers/new.js +3 -0
  157. package/addon/routes/connectivity/fuel-providers.js +3 -0
  158. package/addon/routes/connectivity/telematics/details/attachments.js +28 -0
  159. package/addon/routes/connectivity/telematics/details/devices.js +30 -0
  160. package/addon/routes/connectivity/telematics/details/events.js +33 -0
  161. package/addon/routes/connectivity/telematics/details/index.js +3 -0
  162. package/addon/routes/connectivity/telematics/details/logs.js +17 -0
  163. package/addon/routes/connectivity/telematics/details/sensors.js +29 -0
  164. package/addon/routes/connectivity/telematics/{index/details.js → details.js} +1 -1
  165. package/addon/routes/connectivity/telematics/{index/edit.js → edit.js} +1 -1
  166. package/addon/routes/connectivity/telematics/new.js +3 -0
  167. package/addon/routes/management/drivers/index/details/activity.js +3 -0
  168. package/addon/routes/management/fuel-reports/index.js +2 -0
  169. package/addon/routes/management/fuel-transactions/index/details.js +18 -0
  170. package/addon/routes/management/fuel-transactions/index.js +21 -0
  171. package/addon/routes/management/fuel-transactions.js +3 -0
  172. package/addon/routes/management/issues/index/details.js +1 -1
  173. package/addon/routes.js +29 -9
  174. package/addon/services/contact-actions.js +231 -1
  175. package/addon/services/device-actions.js +64 -1
  176. package/addon/services/device-event-actions.js +12 -1
  177. package/addon/services/driver-actions.js +147 -11
  178. package/addon/services/fleet-actions.js +66 -1
  179. package/addon/services/fuel-integration-actions.js +31 -0
  180. package/addon/services/getting-started.js +44 -0
  181. package/addon/services/issue-actions.js +72 -1
  182. package/addon/services/leaflet-map-manager.js +2 -0
  183. package/addon/services/map-adapter/leaflet.js +19 -0
  184. package/addon/services/service-areas.js +3 -0
  185. package/addon/services/telematic-actions.js +9 -3
  186. package/addon/services/vehicle-actions.js +125 -0
  187. package/addon/styles/fleetops-engine.css +1313 -1
  188. package/addon/templates/analytics/reports/index.hbs +19 -1
  189. package/addon/templates/connectivity/devices/index.hbs +19 -1
  190. package/addon/templates/connectivity/events/index.hbs +16 -1
  191. package/addon/templates/connectivity/fuel-providers/details/index.hbs +38 -0
  192. package/addon/templates/connectivity/fuel-providers/details/matching.hbs +13 -0
  193. package/addon/templates/connectivity/fuel-providers/details/settings.hbs +11 -0
  194. package/addon/templates/connectivity/fuel-providers/details/sync.hbs +48 -0
  195. package/addon/templates/connectivity/fuel-providers/details/transactions.hbs +21 -0
  196. package/addon/templates/connectivity/fuel-providers/details.hbs +51 -0
  197. package/addon/templates/connectivity/fuel-providers/edit.hbs +24 -0
  198. package/addon/templates/connectivity/fuel-providers/index.hbs +12 -0
  199. package/addon/templates/connectivity/fuel-providers/new.hbs +22 -0
  200. package/addon/templates/connectivity/fuel-providers.hbs +1 -0
  201. package/addon/templates/connectivity/sensors/index.hbs +19 -1
  202. package/addon/templates/connectivity/telematics/details/attachments.hbs +163 -0
  203. package/addon/templates/connectivity/telematics/details/devices.hbs +88 -0
  204. package/addon/templates/connectivity/telematics/details/events.hbs +101 -0
  205. package/addon/templates/connectivity/telematics/{index/details → details}/index.hbs +0 -1
  206. package/addon/templates/connectivity/telematics/details/logs.hbs +69 -0
  207. package/addon/templates/connectivity/telematics/details/sensors.hbs +88 -0
  208. package/addon/templates/connectivity/telematics/details.hbs +53 -0
  209. package/addon/templates/connectivity/telematics/edit.hbs +27 -0
  210. package/addon/templates/connectivity/telematics/index.hbs +6 -8
  211. package/addon/templates/connectivity/telematics/new.hbs +24 -0
  212. package/addon/templates/maintenance/equipment/index.hbs +19 -1
  213. package/addon/templates/maintenance/maintenances/index.hbs +15 -1
  214. package/addon/templates/maintenance/parts/index.hbs +19 -1
  215. package/addon/templates/maintenance/schedules/index.hbs +19 -1
  216. package/addon/templates/maintenance/work-orders/index.hbs +19 -1
  217. package/addon/templates/management/contacts/customers/details.hbs +1 -1
  218. package/addon/templates/management/contacts/customers.hbs +15 -1
  219. package/addon/templates/management/contacts/index/details.hbs +1 -1
  220. package/addon/templates/management/contacts/index.hbs +19 -1
  221. package/addon/templates/management/contacts.hbs +2 -2
  222. package/addon/templates/management/drivers/index/details/activity.hbs +1 -0
  223. package/addon/templates/management/drivers/index.hbs +19 -1
  224. package/addon/templates/management/fleets/index.hbs +19 -1
  225. package/addon/templates/management/fuel-reports/index.hbs +19 -1
  226. package/addon/templates/management/fuel-transactions/index/details.hbs +73 -0
  227. package/addon/templates/management/fuel-transactions/index.hbs +58 -0
  228. package/addon/templates/management/fuel-transactions.hbs +1 -0
  229. package/addon/templates/management/issues/index/details/index.hbs +3 -1
  230. package/addon/templates/management/issues/index/details.hbs +3 -2
  231. package/addon/templates/management/issues/index.hbs +19 -1
  232. package/addon/templates/management/places/index.hbs +19 -1
  233. package/addon/templates/management/vehicles/index.hbs +19 -1
  234. package/addon/templates/management/vendors/index/details/personnel.hbs +1 -2
  235. package/addon/templates/management/vendors/index.hbs +19 -1
  236. package/addon/templates/management/vendors/integrated.hbs +13 -1
  237. package/addon/templates/operations/orders/index/details/index.hbs +2 -2
  238. package/addon/templates/operations/orders/index.hbs +20 -2
  239. package/addon/templates/operations/service-rates/index/edit.hbs +1 -0
  240. package/addon/templates/operations/service-rates/index/new.hbs +1 -0
  241. package/addon/templates/operations/service-rates/index.hbs +19 -1
  242. package/addon/templates/settings/payments/index.hbs +15 -1
  243. package/addon/templates/settings/payments/onboard.hbs +8 -8
  244. package/addon/utils/fleet-ops-options.js +3 -0
  245. package/addon/utils/leaflet-draw-namespace-guard.js +22 -0
  246. package/addon/utils/leaflet-plugin-loader.js +219 -0
  247. package/addon/utils/setup-customer-portal.js +4 -64
  248. package/app/components/cell/telematic-provider.js +1 -0
  249. package/app/components/cell/telematic-status.js +1 -0
  250. package/app/components/fuel-integration/form.js +1 -0
  251. package/app/components/fuel-integration/hub.js +1 -0
  252. package/app/components/fuel-integration/matching-priority.js +1 -0
  253. package/app/components/home/getting-started-guidance.js +1 -0
  254. package/app/components/issue/details/comments.js +1 -0
  255. package/app/components/issue/details/correspondence.js +1 -0
  256. package/app/components/issue/details/documents.js +1 -0
  257. package/app/components/issue/panel-header.js +1 -0
  258. package/app/components/modals/assigned-orders.js +1 -0
  259. package/app/components/modals/attach-telematic-device.js +1 -0
  260. package/app/components/modals/convert-customer-to-vendor.js +1 -0
  261. package/app/components/modals/fleet-assign-driver.js +1 -0
  262. package/app/components/modals/fleet-assign-vehicle.js +1 -0
  263. package/app/components/modals/issue-assign.js +1 -0
  264. package/app/components/modals/issue-close.js +1 -0
  265. package/app/components/modals/issue-status.js +1 -0
  266. package/app/components/modals/telematic-connection-diagnostics.js +1 -0
  267. package/app/components/order/card.js +1 -0
  268. package/app/components/telematic/hub.js +1 -0
  269. package/app/components/telematic/settings.js +1 -0
  270. package/app/components/telematic/tab-empty-state.js +1 -0
  271. package/app/components/vendor/personnel-manager.js +1 -0
  272. package/app/components/widget/fuel-providers.js +1 -0
  273. package/app/controllers/connectivity/fuel-providers/details/sync.js +1 -0
  274. package/app/controllers/connectivity/{telematics/index/details/devices.js → fuel-providers/details/transactions.js} +1 -1
  275. package/app/controllers/connectivity/{telematics/index → fuel-providers}/details.js +1 -1
  276. package/app/controllers/connectivity/{telematics/index → fuel-providers}/edit.js +1 -1
  277. package/app/controllers/connectivity/{telematics/index/details → fuel-providers}/index.js +1 -1
  278. package/app/controllers/connectivity/{telematics/index → fuel-providers}/new.js +1 -1
  279. package/app/controllers/connectivity/telematics/details/attachments.js +1 -0
  280. package/app/controllers/connectivity/telematics/details/devices.js +1 -0
  281. package/app/controllers/connectivity/telematics/details/events.js +1 -0
  282. package/app/controllers/connectivity/telematics/details/index.js +1 -0
  283. package/app/controllers/connectivity/telematics/details/logs.js +1 -0
  284. package/app/controllers/connectivity/telematics/details/sensors.js +1 -0
  285. package/app/controllers/connectivity/telematics/details.js +1 -0
  286. package/app/controllers/connectivity/telematics/edit.js +1 -0
  287. package/app/controllers/connectivity/telematics/new.js +1 -0
  288. package/app/controllers/management/fuel-transactions/index/details.js +1 -0
  289. package/app/controllers/management/fuel-transactions/index.js +1 -0
  290. package/app/helpers/format-duration.js +1 -1
  291. package/app/routes/connectivity/{telematics/index → fuel-providers}/details/index.js +1 -1
  292. package/app/routes/connectivity/{telematics/index/details/events.js → fuel-providers/details/matching.js} +1 -1
  293. package/app/routes/connectivity/fuel-providers/details/settings.js +1 -0
  294. package/app/routes/connectivity/fuel-providers/details/sync.js +1 -0
  295. package/app/routes/connectivity/{telematics/index/details/devices.js → fuel-providers/details/transactions.js} +1 -1
  296. package/app/routes/connectivity/{telematics/index → fuel-providers}/details.js +1 -1
  297. package/app/routes/connectivity/{telematics/index → fuel-providers}/edit.js +1 -1
  298. package/app/routes/connectivity/fuel-providers/index.js +1 -0
  299. package/app/routes/connectivity/{telematics/index → fuel-providers}/new.js +1 -1
  300. package/app/routes/connectivity/fuel-providers.js +1 -0
  301. package/app/routes/connectivity/telematics/details/attachments.js +1 -0
  302. package/app/routes/connectivity/telematics/details/devices.js +1 -0
  303. package/app/routes/connectivity/telematics/details/events.js +1 -0
  304. package/app/routes/connectivity/telematics/details/index.js +1 -0
  305. package/app/routes/connectivity/telematics/details/logs.js +1 -0
  306. package/app/routes/connectivity/telematics/details/sensors.js +1 -0
  307. package/app/routes/connectivity/telematics/details.js +1 -0
  308. package/app/routes/connectivity/telematics/edit.js +1 -0
  309. package/app/routes/connectivity/telematics/new.js +1 -0
  310. package/app/routes/management/drivers/index/details/activity.js +1 -0
  311. package/app/routes/management/fuel-transactions/index/details.js +1 -0
  312. package/app/routes/management/fuel-transactions/index.js +1 -0
  313. package/app/routes/management/fuel-transactions.js +1 -0
  314. package/app/services/fuel-integration-actions.js +1 -0
  315. package/app/services/getting-started.js +1 -0
  316. package/app/templates/connectivity/{telematics/index → fuel-providers}/details/index.js +1 -1
  317. package/app/templates/connectivity/{telematics/index/details/events.js → fuel-providers/details/matching.js} +1 -1
  318. package/app/templates/connectivity/fuel-providers/details/settings.js +1 -0
  319. package/app/templates/connectivity/fuel-providers/details/sync.js +1 -0
  320. package/app/templates/connectivity/{telematics/index/details/devices.js → fuel-providers/details/transactions.js} +1 -1
  321. package/app/templates/connectivity/{telematics/index → fuel-providers}/details.js +1 -1
  322. package/app/templates/connectivity/{telematics/index → fuel-providers}/edit.js +1 -1
  323. package/app/templates/connectivity/fuel-providers/index.js +1 -0
  324. package/app/templates/connectivity/{telematics/index → fuel-providers}/new.js +1 -1
  325. package/app/templates/connectivity/fuel-providers.js +1 -0
  326. package/app/templates/connectivity/telematics/details/attachments.js +1 -0
  327. package/app/templates/connectivity/telematics/details/devices.js +1 -0
  328. package/app/templates/connectivity/telematics/details/events.js +1 -0
  329. package/app/templates/connectivity/telematics/details/index.js +1 -0
  330. package/app/templates/connectivity/telematics/details/logs.js +1 -0
  331. package/app/templates/connectivity/telematics/details/sensors.js +1 -0
  332. package/app/templates/connectivity/telematics/details.js +1 -0
  333. package/app/templates/connectivity/telematics/edit.js +1 -0
  334. package/app/templates/connectivity/telematics/new.js +1 -0
  335. package/app/templates/management/drivers/index/details/activity.js +1 -0
  336. package/app/templates/management/fuel-transactions/index/details.js +1 -0
  337. package/app/templates/management/fuel-transactions/index.js +1 -0
  338. package/app/templates/management/fuel-transactions.js +1 -0
  339. package/app/utils/leaflet-draw-namespace-guard.js +1 -0
  340. package/app/utils/leaflet-plugin-loader.js +1 -0
  341. package/assets/images/telematics/providers/afaqy.webp +0 -0
  342. package/assets/images/telematics/providers/default.webp +0 -0
  343. package/assets/images/telematics/providers/flespi.webp +0 -0
  344. package/assets/images/telematics/providers/geotab.webp +0 -0
  345. package/assets/images/telematics/providers/safee.webp +0 -0
  346. package/assets/images/telematics/providers/samsara.webp +0 -0
  347. package/composer.json +1 -1
  348. package/extension.json +1 -1
  349. package/package.json +5 -5
  350. package/server/config/fuel-providers.php +42 -0
  351. package/server/config/telematics.php +139 -130
  352. package/server/migrations/2026_05_31_000001_add_portal_fields_to_vendor_personnels_table.php +30 -0
  353. package/server/migrations/2026_06_03_000000_ensure_tags_column_on_issues_table.php +31 -0
  354. package/server/migrations/2026_06_03_000001_add_order_uuid_to_issues_table.php +25 -0
  355. package/server/migrations/2026_06_04_000001_backfill_order_transaction_subjects.php +39 -0
  356. package/server/migrations/2026_06_04_000002_backfill_order_transaction_directions.php +24 -0
  357. package/server/migrations/2026_06_06_000001_harden_device_events_telematics_contract.php +59 -0
  358. package/server/migrations/2026_06_08_000001_create_fuel_provider_connections_table.php +37 -0
  359. package/server/migrations/2026_06_08_000002_create_fuel_provider_transactions_table.php +53 -0
  360. package/server/migrations/2026_06_08_000003_create_fuel_provider_sync_runs_table.php +40 -0
  361. package/server/migrations/2026_06_10_000001_add_fuel_card_number_to_vehicles_table.php +25 -0
  362. package/server/migrations/2026_06_10_000002_add_vehicle_identity_columns_to_fuel_provider_transactions_table.php +39 -0
  363. package/server/resources/views/mail/customer-credentials.blade.php +16 -13
  364. package/server/src/Contracts/FuelProvider.php +30 -0
  365. package/server/src/Contracts/TelematicProviderDescriptor.php +3 -1
  366. package/server/src/Events/FuelProviderTransactionImported.php +17 -0
  367. package/server/src/Events/FuelProviderTransactionMatched.php +17 -0
  368. package/server/src/Events/FuelProviderTransactionUnmatched.php +17 -0
  369. package/server/src/Events/FuelReportCreatedFromProvider.php +18 -0
  370. package/server/src/Expansions/UserFilterExpansion.php +28 -0
  371. package/server/src/Http/Controllers/Api/v1/IssueController.php +2 -0
  372. package/server/src/Http/Controllers/Api/v1/OrderController.php +26 -25
  373. package/server/src/Http/Controllers/Api/v1/PlaceController.php +10 -58
  374. package/server/src/Http/Controllers/Internal/v1/AnalyticsController.php +6 -0
  375. package/server/src/Http/Controllers/Internal/v1/ContactController.php +135 -0
  376. package/server/src/Http/Controllers/Internal/v1/CustomerController.php +116 -6
  377. package/server/src/Http/Controllers/Internal/v1/DeviceController.php +76 -2
  378. package/server/src/Http/Controllers/Internal/v1/DeviceEventController.php +44 -0
  379. package/server/src/Http/Controllers/Internal/v1/DriverController.php +158 -7
  380. package/server/src/Http/Controllers/Internal/v1/FuelProviderConnectionController.php +124 -0
  381. package/server/src/Http/Controllers/Internal/v1/FuelProviderSyncRunController.php +10 -0
  382. package/server/src/Http/Controllers/Internal/v1/FuelProviderTransactionController.php +76 -0
  383. package/server/src/Http/Controllers/Internal/v1/GettingStartedController.php +17 -0
  384. package/server/src/Http/Controllers/Internal/v1/IssueController.php +251 -0
  385. package/server/src/Http/Controllers/Internal/v1/OrderController.php +172 -97
  386. package/server/src/Http/Controllers/Internal/v1/PlaceController.php +10 -68
  387. package/server/src/Http/Controllers/Internal/v1/SensorController.php +1 -1
  388. package/server/src/Http/Controllers/Internal/v1/TelematicController.php +178 -15
  389. package/server/src/Http/Controllers/Internal/v1/VehicleController.php +165 -0
  390. package/server/src/Http/Controllers/Internal/v1/VendorController.php +89 -0
  391. package/server/src/Http/Controllers/TelematicWebhookController.php +103 -19
  392. package/server/src/Http/Filter/FuelProviderConnectionFilter.php +33 -0
  393. package/server/src/Http/Filter/FuelProviderSyncRunFilter.php +28 -0
  394. package/server/src/Http/Filter/FuelProviderTransactionFilter.php +59 -0
  395. package/server/src/Http/Filter/FuelReportFilter.php +10 -0
  396. package/server/src/Http/Requests/CreateIssueRequest.php +4 -0
  397. package/server/src/Http/Requests/UpdateIssueRequest.php +4 -0
  398. package/server/src/Http/Resources/v1/Driver.php +15 -0
  399. package/server/src/Http/Resources/v1/FuelProviderConnection.php +30 -0
  400. package/server/src/Http/Resources/v1/FuelProviderSyncRun.php +36 -0
  401. package/server/src/Http/Resources/v1/FuelProviderTransaction.php +54 -0
  402. package/server/src/Http/Resources/v1/FuelReport.php +28 -22
  403. package/server/src/Http/Resources/v1/Index/Driver.php +26 -20
  404. package/server/src/Http/Resources/v1/Index/Order.php +12 -9
  405. package/server/src/Http/Resources/v1/Index/Vehicle.php +29 -22
  406. package/server/src/Http/Resources/v1/Issue.php +25 -0
  407. package/server/src/Http/Resources/v1/Order.php +20 -18
  408. package/server/src/Http/Resources/v1/Vehicle.php +17 -0
  409. package/server/src/Http/Resources/v1/VehicleWithoutDriver.php +2 -0
  410. package/server/src/Jobs/SyncFuelProviderTransactionsJob.php +57 -0
  411. package/server/src/Jobs/SyncTelematicDevicesJob.php +36 -6
  412. package/server/src/Jobs/TestTelematicConnectionJob.php +9 -22
  413. package/server/src/Mail/CustomerCredentialsMail.php +5 -6
  414. package/server/src/Models/Asset.php +2 -1
  415. package/server/src/Models/Contact.php +32 -52
  416. package/server/src/Models/Device.php +27 -4
  417. package/server/src/Models/DeviceEvent.php +40 -3
  418. package/server/src/Models/Driver.php +2 -1
  419. package/server/src/Models/Equipment.php +2 -1
  420. package/server/src/Models/Fleet.php +2 -1
  421. package/server/src/Models/FuelProviderConnection.php +60 -0
  422. package/server/src/Models/FuelProviderSyncRun.php +58 -0
  423. package/server/src/Models/FuelProviderTransaction.php +119 -0
  424. package/server/src/Models/FuelReport.php +16 -1
  425. package/server/src/Models/Issue.php +47 -6
  426. package/server/src/Models/Order.php +33 -6
  427. package/server/src/Models/Part.php +2 -1
  428. package/server/src/Models/Sensor.php +21 -4
  429. package/server/src/Models/ServiceArea.php +1 -1
  430. package/server/src/Models/ServiceRate.php +39 -2
  431. package/server/src/Models/Vehicle.php +14 -2
  432. package/server/src/Models/Vendor.php +2 -1
  433. package/server/src/Models/VendorPersonnel.php +10 -1
  434. package/server/src/Models/Zone.php +1 -1
  435. package/server/src/Observers/PurchaseRateObserver.php +20 -0
  436. package/server/src/Observers/ZoneObserver.php +56 -0
  437. package/server/src/Providers/FleetOpsServiceProvider.php +11 -0
  438. package/server/src/Support/Analytics/FuelProviderSummary.php +42 -0
  439. package/server/src/Support/Analytics/TopDrivers.php +9 -1
  440. package/server/src/Support/FuelProviders/FuelProviderDescriptor.php +55 -0
  441. package/server/src/Support/FuelProviders/FuelProviderRegistry.php +75 -0
  442. package/server/src/Support/FuelProviders/FuelProviderService.php +447 -0
  443. package/server/src/Support/FuelProviders/Providers/AbstractFuelProvider.php +98 -0
  444. package/server/src/Support/FuelProviders/Providers/PetroAppFuelProvider.php +167 -0
  445. package/server/src/Support/GettingStarted.php +144 -0
  446. package/server/src/Support/PlaceSearch.php +282 -0
  447. package/server/src/Support/ResolvesOrderServiceStops.php +22 -12
  448. package/server/src/Support/Telematics/Providers/AbstractProvider.php +27 -6
  449. package/server/src/Support/Telematics/Providers/AfaqyProvider.php +55 -26
  450. package/server/src/Support/Telematics/Providers/FlespiProvider.php +1 -0
  451. package/server/src/Support/Telematics/Providers/GeotabProvider.php +1 -0
  452. package/server/src/Support/Telematics/Providers/SafeeProvider.php +32 -22
  453. package/server/src/Support/Telematics/Providers/SamsaraProvider.php +3 -1
  454. package/server/src/Support/Telematics/TelematicService.php +340 -21
  455. package/server/src/routes.php +74 -5
  456. package/server/tests/AnalyticsRoutesTest.php +8 -0
  457. package/server/tests/CustomerContactIdentitySafetyTest.php +41 -0
  458. package/server/tests/DriverVehicleStatusDefaultTest.php +2 -2
  459. package/server/tests/FuelProviderRegistryTest.php +416 -0
  460. package/server/tests/GettingStartedStatusTest.php +21 -0
  461. package/server/tests/OrderActivityFlowRegressionTest.php +116 -0
  462. package/server/tests/ServiceAreaZoneApiShapeTest.php +44 -0
  463. package/server/tests/ServiceRateAlgorithmWeightVariablesTest.php +44 -0
  464. package/server/tests/TelematicsHardeningTest.php +268 -0
  465. package/server/tests/VehicleDriverAssignmentTest.php +51 -0
  466. package/translations/ar-ae.yml +31 -0
  467. package/translations/bg-bg.yaml +81 -0
  468. package/translations/en-us.yaml +94 -0
  469. package/translations/es-pa.yaml +81 -0
  470. package/translations/fr-fr.yaml +81 -0
  471. package/translations/mn-mn.yaml +81 -0
  472. package/translations/pt-br.yaml +81 -0
  473. package/translations/ru-ru.yaml +81 -0
  474. package/translations/vi-vn.yaml +106 -0
  475. package/addon/controllers/connectivity/telematics/index/details/devices.js +0 -3
  476. package/addon/controllers/connectivity/telematics/index/details/events.js +0 -3
  477. package/addon/controllers/connectivity/telematics/index/details/index.js +0 -3
  478. package/addon/controllers/connectivity/telematics/index/details/sensors.js +0 -3
  479. package/addon/controllers/connectivity/telematics/index/details.js +0 -24
  480. package/addon/routes/connectivity/telematics/index/details/devices.js +0 -3
  481. package/addon/routes/connectivity/telematics/index/details/events.js +0 -3
  482. package/addon/routes/connectivity/telematics/index/details/index.js +0 -3
  483. package/addon/routes/connectivity/telematics/index/details/sensors.js +0 -3
  484. package/addon/routes/connectivity/telematics/index/new.js +0 -3
  485. package/addon/templates/connectivity/telematics/index/details/devices.hbs +0 -1
  486. package/addon/templates/connectivity/telematics/index/details/events.hbs +0 -1
  487. package/addon/templates/connectivity/telematics/index/details/sensors.hbs +0 -1
  488. package/addon/templates/connectivity/telematics/index/details.hbs +0 -14
  489. package/addon/templates/connectivity/telematics/index/edit.hbs +0 -12
  490. package/addon/templates/connectivity/telematics/index/new.hbs +0 -12
  491. package/app/controllers/connectivity/telematics/index/details/events.js +0 -1
  492. package/app/controllers/connectivity/telematics/index/details/sensors.js +0 -1
  493. package/app/routes/connectivity/telematics/index/details/sensors.js +0 -1
  494. package/app/templates/connectivity/telematics/index/details/sensors.js +0 -1
@@ -2,12 +2,12 @@
2
2
  {{#if (has-block)}}
3
3
  {{yield
4
4
  (hash
5
- Activity=(component "order/details/activity" resource=@resource onChange=@onActivityChanged isLoadingActivity=@isLoadingActivity isLoading=@isLoading)
5
+ Activity=(component "order/details/activity" resource=@resource onChange=this.handleActivityChanged isLoadingActivity=@isLoadingActivity isLoading=@isLoading)
6
6
  Detail=(component "order/details/detail" resource=@resource onChange=@onDetailsChanged isLoading=@isLoading)
7
7
  CustomFields=(component "order/details/custom-fields" resource=@resource onChange=@onCustomFieldsChanged isLoading=@isLoading)
8
8
  PurchaseRate=(component "order/details/purchase-rate" resource=@resource isLoading=@isLoading)
9
9
  Tracking=(component "order/details/tracking" resource=@resource isLoading=@isLoading)
10
- Proof=(component "order/details/proof" resource=@resource isLoading=@isLoading)
10
+ Proof=(component "order/details/proof" resource=@resource reloadToken=this.effectiveProofReloadToken isLoading=@isLoading)
11
11
  Notes=(component "order/details/notes" resource=@resource onChange=@onNotesChanged isLoading=@isLoading)
12
12
  IntegratedVendorDetails=(component "order/details/integrated-vendor-details" resource=@resource isLoading=@isLoading)
13
13
  Route=(component "order/details/route" resource=@resource onChange=@onRouteChanged isLoading=@isLoading)
@@ -21,12 +21,12 @@
21
21
  )
22
22
  }}
23
23
  {{else}}
24
- <Order::Details::Activity @resource={{@resource}} @onChange={{@onActivityChanged}} @isLoadingActivity={{@isLoadingActivity}} @isLoading={{@isLoading}} />
24
+ <Order::Details::Activity @resource={{@resource}} @onChange={{this.handleActivityChanged}} @isLoadingActivity={{@isLoadingActivity}} @isLoading={{@isLoading}} />
25
25
  <Order::Details::Detail @resource={{@resource}} @onChange={{@onDetailsChanged}} @isLoading={{@isLoading}} />
26
26
  <Order::Details::CustomFields @resource={{@resource}} @onChange={{@onCustomFieldsChanged}} @isLoading={{@isLoading}} />
27
27
  <Order::Details::PurchaseRate @resource={{@resource}} @isLoading={{@isLoading}} />
28
28
  <Order::Details::Tracking @resource={{@resource}} @isLoading={{@isLoading}} />
29
- <Order::Details::Proof @resource={{@resource}} @isLoading={{@isLoading}} />
29
+ <Order::Details::Proof @resource={{@resource}} @reloadToken={{this.effectiveProofReloadToken}} @isLoading={{@isLoading}} />
30
30
  <Order::Details::Notes @resource={{@resource}} @onChange={{@onNotesChanged}} @isLoading={{@isLoading}} />
31
31
  <Order::Details::IntegratedVendorDetails @resource={{@resource}} @isLoading={{@isLoading}} />
32
32
  <Order::Details::Route @resource={{@resource}} @onChange={{@onRouteChanged}} @isLoading={{@isLoading}} />
@@ -38,4 +38,4 @@
38
38
  <Order::Details::Comments @resource={{@resource}} @onChange={{@onCommentsChanged}} @isLoading={{@isLoading}} />
39
39
  <Order::Details::Metadata @resource={{@resource}} @onChange={{@onMetadataChanged}} @isLoading={{@isLoading}} />
40
40
  {{/if}}
41
- </div>
41
+ </div>
@@ -1,3 +1,21 @@
1
1
  import Component from '@glimmer/component';
2
+ import { action } from '@ember/object';
3
+ import { tracked } from '@glimmer/tracking';
2
4
 
3
- export default class OrderDetailsComponent extends Component {}
5
+ export default class OrderDetailsComponent extends Component {
6
+ @tracked proofReloadToken = 0;
7
+
8
+ get effectiveProofReloadToken() {
9
+ return `${this.args.proofReloadToken ?? 0}:${this.proofReloadToken}`;
10
+ }
11
+
12
+ @action handleActivityChanged(optionsOrActivity) {
13
+ if (typeof this.args.onActivityChanged === 'function') {
14
+ this.args.onActivityChanged(optionsOrActivity?.activityCreated ?? optionsOrActivity);
15
+ }
16
+
17
+ if (optionsOrActivity?.proofCreated) {
18
+ this.proofReloadToken++;
19
+ }
20
+ }
21
+ }
@@ -18,6 +18,8 @@
18
18
  @options={{this.serviceRates}}
19
19
  @selected={{this.selectedRate}}
20
20
  @onChange={{perform this.getServiceQuotes}}
21
+ @searchEnabled={{true}}
22
+ @searchField="service_name"
21
23
  @placeholder={{t "order.fields.select-service-rate"}}
22
24
  @triggerClass="form-select form-input"
23
25
  @disabled={{cannot-write @resource}}
@@ -10,7 +10,7 @@
10
10
  <Badge @status={{@order.status}} @helpText={{if (eq @order.status (t "order.header.dispatched")) (concat (t "order.header.dispatched-at") @order.dispatchedAt)}} />
11
11
  {{#if @order.shouldDisplayDispatchLabel}}
12
12
  <Badge @status="info" class="ml-2" @helpText={{t "order.header.dispatched" htmlSafe=true order=@order.dispatchedAt}}>{{t
13
- "fleet-ops.component.order.header.dispatched"
13
+ "order-status.dispatched"
14
14
  }}</Badge>
15
15
  {{/if}}
16
16
  </div>
@@ -20,9 +20,6 @@
20
20
  {{#if this.firstStop.etaSeconds}}
21
21
  <Badge @status="pending" @hideStatusDot={{true}}><span class="font-bold">ETA:</span> {{format-duration this.firstStop.etaSeconds}}</Badge>
22
22
  {{/if}}
23
- {{#if this.firstStop.etaAt}}
24
- <Badge @status="pending" @hideStatusDot={{true}}>{{format-date-fns this.firstStop.etaAt "d MMM HH:mm"}}</Badge>
25
- {{/if}}
26
23
  </div>
27
24
  <DisplayPlace @place={{this.firstStop.place}} @waypointActions={{@waypointActions}} @waypointActionContext={{this.firstStop}} @hideBadges={{true}} />
28
25
  </div>
@@ -58,9 +55,6 @@
58
55
  {{#if stop.etaSeconds}}
59
56
  <Badge @status="pending" @hideStatusDot={{true}}><span class="font-bold">ETA:</span> {{format-duration stop.etaSeconds}}</Badge>
60
57
  {{/if}}
61
- {{#if stop.etaAt}}
62
- <Badge @status="pending" @hideStatusDot={{true}}>{{format-date-fns stop.etaAt "d MMM HH:mm"}}</Badge>
63
- {{/if}}
64
58
  </div>
65
59
  <DisplayPlace @place={{stop.place}} @waypointActions={{@waypointActions}} @waypointActionContext={{stop}} @hideBadges={{true}} />
66
60
  </div>
@@ -86,9 +80,6 @@
86
80
  {{#if stop.etaSeconds}}
87
81
  <Badge @status="pending" @hideStatusDot={{true}}><span class="font-bold">ETA:</span> {{format-duration stop.etaSeconds}}</Badge>
88
82
  {{/if}}
89
- {{#if stop.etaAt}}
90
- <Badge @status="pending" @hideStatusDot={{true}}>{{format-date-fns stop.etaAt "d MMM HH:mm"}}</Badge>
91
- {{/if}}
92
83
  </div>
93
84
  <DisplayPlace @place={{stop.place}} @waypointActions={{@waypointActions}} @waypointActionContext={{stop}} @hideBadges={{true}} />
94
85
  </div>
@@ -117,9 +108,6 @@
117
108
  {{#if this.lastStop.etaSeconds}}
118
109
  <Badge @status="pending" @hideStatusDot={{true}}><span class="font-bold">ETA:</span> {{format-duration this.lastStop.etaSeconds}}</Badge>
119
110
  {{/if}}
120
- {{#if this.lastStop.etaAt}}
121
- <Badge @status="pending" @hideStatusDot={{true}}>{{format-date-fns this.lastStop.etaAt "d MMM HH:mm"}}</Badge>
122
- {{/if}}
123
111
  </div>
124
112
  <DisplayPlace @place={{this.lastStop.place}} @waypointActions={{@waypointActions}} @waypointActionContext={{this.lastStop}} @hideBadges={{true}} />
125
113
  </div>
@@ -199,7 +199,7 @@
199
199
  <div class="field-info-container">
200
200
  <div class="field-name">Algorithm Code</div>
201
201
  <div class="field-value">
202
- <pre class="bg-gray-100 dark:bg-gray-900 font-mono p-3 rounded text-xs overflow-x-auto"><code class="font-mono text-xs">{{n-a @resource.algorithm}}</code></pre>
202
+ <pre class="bg-gray-100 dark:bg-gray-900 font-mono p-3 rounded text-xs overflow-x-auto"><code class="font-mono text-xs whitespace-break-spaces">{{n-a @resource.algorithm}}</code></pre>
203
203
  </div>
204
204
  </div>
205
205
  </ContentPanel>
@@ -10,7 +10,7 @@
10
10
  @disabled={{cannot-write @resource}}
11
11
  />
12
12
 
13
- <InputGroup @name={{t "service-rate.fields.service-order-label"}} @helpText={{t "service-rate.fields.service-order-help-text"}}>
13
+ <InputGroup @name={{t "service-rate.fields.service-order-label"}} @helpText={{t "service-rate.fields.service-order-help-text"}} @required={{true}}>
14
14
  <div class="fleetbase-model-select fleetbase-power-select ember-model-select">
15
15
  <PowerSelect
16
16
  @options={{this.orderConfigActions.allOrderConfigs}}
@@ -379,6 +379,7 @@
379
379
  <li class="leading-5"><code>&#123;stops&#125;</code>: total service stops including pickup, dropoff, and intermediate waypoints.</li>
380
380
  <li class="leading-5"><code>&#123;waypoints&#125;</code>: intermediate waypoint count only.</li>
381
381
  <li class="leading-5"><code>&#123;parcels&#125;</code>, <code>&#123;entities&#125;</code>: parcel count and total payload entity count.</li>
382
+ <li class="leading-5"><code>&#123;weight&#125;</code>, <code>&#123;weight_kg&#125;</code>, <code>&#123;weight_g&#125;</code>, <code>&#123;weight_lb&#125;</code>, <code>&#123;weight_oz&#125;</code>, <code>&#123;weight_tonne&#125;</code>, <code>&#123;weight_t&#125;</code>: total entity weight converted across supported units.</li>
382
383
  <li class="leading-5"><code>&#123;base_fee&#125;</code>: the configured base fee for this service rate.</li>
383
384
  <li class="leading-5">Supported functions: <code>max(a,b)</code>, <code>min(a,b)</code>, <code>ceil(x)</code>, <code>floor(x)</code>, <code>round(x)</code>.</li>
384
385
  </ul>
@@ -399,8 +400,8 @@
399
400
 
400
401
  <div>
401
402
  <h4 class="mb-1 text-sm font-semibold">{{t "service-rate.fields.example"}} 3</h4>
402
- <div class="mb-2 text-inherit">Combine waypoint, parcel, and distance surcharges in one formula.</div>
403
- <code class="text-xs font-mono">max(&#123;waypoints&#125;, 0) * 15 + max(&#123;parcels&#125; - 3, 0) * 2 + max(&#123;distance_km&#125; - 25, 0) * 0.5 + &#123;base_fee&#125;</code>
403
+ <div class="mb-2 text-inherit">Combine waypoint, payload weight, and distance surcharges in one formula.</div>
404
+ <code class="text-xs font-mono">max(&#123;waypoints&#125;, 0) * 15 + max(&#123;weight_kg&#125; - 100, 0) * 0.25 + max(&#123;distance_km&#125; - 25, 0) * 0.5 + &#123;base_fee&#125;</code>
404
405
  </div>
405
406
  </div>
406
407
  </InfoBlock>
@@ -53,6 +53,7 @@ export default class ServiceRateFormComponent extends Component {
53
53
  }
54
54
 
55
55
  @action selectRuleGeographyType(rule, { value }) {
56
+ rule.set('selected_geography_type', value);
56
57
  rule.set('zone', null);
57
58
  rule.set('zone_uuid', null);
58
59
  rule.set('service_area', null);
@@ -61,6 +62,7 @@ export default class ServiceRateFormComponent extends Component {
61
62
  }
62
63
 
63
64
  @action selectRuleServiceArea(rule, serviceArea) {
65
+ rule.set('selected_geography_type', 'service_area');
64
66
  rule.set('service_area', serviceArea);
65
67
  rule.set('service_area_uuid', serviceArea?.id);
66
68
  rule.set('zone', null);
@@ -69,6 +71,7 @@ export default class ServiceRateFormComponent extends Component {
69
71
  }
70
72
 
71
73
  @action selectRuleZone(rule, zone) {
74
+ rule.set('selected_geography_type', 'zone');
72
75
  rule.set('zone', zone);
73
76
  rule.set('zone_uuid', zone?.id);
74
77
  rule.set('service_area', null);
@@ -79,6 +82,7 @@ export default class ServiceRateFormComponent extends Component {
79
82
  @action setRuleFallback(rule, isFallback) {
80
83
  rule.set('is_fallback', Boolean(isFallback));
81
84
  if (isFallback) {
85
+ rule.set('selected_geography_type', 'fallback');
82
86
  rule.set('zone', null);
83
87
  rule.set('zone_uuid', null);
84
88
  rule.set('service_area', null);
@@ -1,95 +1,111 @@
1
- <div class="details-wrapper" ...attributes>
2
- <ContentPanel @title="Telematics Provider" @open={{true}} @wrapperClass="bordered-top">
3
- <div class="field-info-container">
4
- <div class="field-name">Provider</div>
5
- <div class="field-value">
6
- <div class="flex flew-row space-x-2 text-sm">
7
- <div class="pt-1.5">
8
- <Image src={{@resource.provider_descriptor.icon}} class="w-5 h-5" />
1
+ <div class="flex flex-col gap-4 p-4 md:p-6" ...attributes>
2
+ <section class="grid grid-cols-1 gap-3 lg:grid-cols-3">
3
+ {{#each this.healthCards as |card|}}
4
+ <div class="fleet-ops-widget fleet-ops-kpi-tile fleetops-connectivity-kpi-tile {{card.accentClass}} relative min-h-[118px] overflow-hidden rounded-md border bg-white shadow-sm transition hover:-translate-y-px hover:shadow-lg dark:bg-gray-800">
5
+ <div class="flex h-full flex-col justify-between p-3">
6
+ <div class="flex items-start justify-between gap-3">
7
+ <div class="min-w-0">
8
+ <div class="truncate text-[10px] font-bold uppercase text-gray-500 dark:text-gray-400">{{card.label}}</div>
9
+ <div class="mt-2 truncate text-xl font-extrabold leading-none text-gray-900 dark:text-gray-50">{{n-a card.value}}</div>
10
+ <div class="mt-2 truncate text-[11px] text-gray-500 dark:text-gray-400">{{card.help}}</div>
11
+ </div>
12
+ <div class="fleetops-connectivity-kpi-icon flex h-8 w-8 flex-shrink-0 items-center justify-center rounded-md text-[13px]">
13
+ <FaIcon @icon={{card.icon}} />
14
+ </div>
9
15
  </div>
10
- <div>
11
- <div class="font-semibold">{{@resource.provider_descriptor.label}}</div>
12
- <div class="text-xs text-gray-400 dark:text-gray-500">{{n-a @resource.provider_descriptor.description}}</div>
16
+
17
+ <div class="mt-3 flex items-center justify-between gap-2 text-[11px]">
18
+ <span class="flex-shrink-0 font-semibold text-gray-500 dark:text-gray-400">{{card.detailLabel}}</span>
19
+ <span class="min-w-0 truncate text-right text-gray-500 dark:text-gray-400">
20
+ {{#if card.detailIsDate}}
21
+ {{n-a (format-date-fns card.detail "dd MMM yyyy, HH:mm")}}
22
+ {{else}}
23
+ {{n-a card.detail}}
24
+ {{/if}}
25
+ </span>
13
26
  </div>
14
27
  </div>
15
28
  </div>
16
- </div>
17
- </ContentPanel>
18
-
19
- <ContentPanel @title="Integration Details" @open={{true}} @wrapperClass="bordered-top">
20
- <div class="grid grid-cols-1 gap-2 lg:grid-cols-2 lg:gap-2 no-input-group-padding text-xs">
21
- <div class="field-info-container">
22
- <div class="field-name">Integration Name</div>
23
- <div class="field-value">{{n-a @resource.name}}</div>
24
- </div>
25
-
26
- {{#if @resource.provider_descriptor.supportsWebhooks}}
27
- <InputGroup @name="Webhook URL" @helpText={{concat "Configure the URL in your " @resource.provider_descriptor.label " dashboard to receive real-time updates."}}>
28
- <ClickToCopy @value={{@resource.provider_descriptor.webhook_url}}>
29
- <Input @value={{@resource.provider_descriptor.webhook_url}} class="form-input" readonly />
30
- </ClickToCopy>
31
- <small class="form-text text-muted">
32
- Configure this URL in your
33
- {{@resource.provider_descriptor.label}}
34
- dashboard to receive real-time updates.
35
- </small>
36
- </InputGroup>
37
- {{/if}}
38
- </div>
39
- </ContentPanel>
40
-
41
- <ContentPanel @title="Telematic Blackbox" @open={{true}} @wrapperClass="bordered-top">
42
- <div class="grid grid-cols-1 lg:grid-cols-3 gap-2">
43
- <div class="field-info-container">
44
- <div class="field-name">Model</div>
45
- <div class="field-value">{{n-a @resource.model}}</div>
46
- </div>
47
-
48
- <div class="field-info-container">
49
- <div class="field-name">Serial Number</div>
50
- <div class="field-value">{{n-a @resource.serial_number}}</div>
51
- </div>
52
-
53
- <div class="field-info-container">
54
- <div class="field-name">Firmware Version</div>
55
- <div class="field-value">{{n-a @resource.firmware_version}}</div>
56
- </div>
29
+ {{/each}}
30
+ </section>
57
31
 
58
- <div class="field-info-container">
59
- <div class="field-name">Status</div>
60
- <div class="field-value">
61
- <Badge @status={{@resource.status}}>{{smart-humanize @resource.status}}</Badge>
32
+ {{#if this.attentionItems.length}}
33
+ <section class="flex flex-col gap-3">
34
+ {{#each this.attentionItems as |item|}}
35
+ <div class="w-full rounded-md border border-yellow-200 bg-yellow-50 p-3 dark:border-yellow-700 dark:bg-gray-800">
36
+ <div class="flex items-start gap-3">
37
+ <div class="flex h-9 w-9 flex-shrink-0 items-center justify-center rounded-md bg-yellow-100 text-yellow-700 dark:bg-yellow-900/30 dark:text-yellow-300">
38
+ <FaIcon @icon={{item.icon}} />
39
+ </div>
40
+ <div class="min-w-0">
41
+ <div class="text-sm font-bold text-gray-900 dark:text-gray-100">{{item.title}}</div>
42
+ <p class="mt-1 text-xs leading-5 text-yellow-800 dark:text-yellow-300">{{item.description}}</p>
43
+ </div>
44
+ </div>
45
+ </div>
46
+ {{/each}}
47
+ </section>
48
+ {{else}}
49
+ <section class="rounded-md border border-green-200 bg-green-50 p-3 dark:border-green-700 dark:bg-green-900/20">
50
+ <div class="flex items-center gap-3">
51
+ <div class="flex h-9 w-9 items-center justify-center rounded-md bg-green-100 text-green-700 dark:bg-green-900/30 dark:text-green-300">
52
+ <FaIcon @icon="check" />
53
+ </div>
54
+ <div>
55
+ <div class="text-sm font-bold text-gray-900 dark:text-gray-100">No immediate attention needed</div>
56
+ <div class="text-xs text-green-800 dark:text-green-300">Connection, sync, and telemetry status are ready for review.</div>
62
57
  </div>
63
58
  </div>
59
+ </section>
60
+ {{/if}}
64
61
 
65
- <div class="field-info-container">
66
- <div class="field-name">IMEI</div>
67
- <div class="field-value">{{n-a @resource.imei}}</div>
68
- </div>
69
-
70
- <div class="field-info-container">
71
- <div class="field-name">ICCID</div>
72
- <div class="field-value">{{n-a @resource.iccid}}</div>
73
- </div>
74
-
75
- <div class="field-info-container">
76
- <div class="field-name">IMSI</div>
77
- <div class="field-value">{{n-a @resource.imsi}}</div>
62
+ <section class="grid grid-cols-1 gap-4 lg:grid-cols-3">
63
+ <div class="rounded-md border border-gray-200 bg-white p-4 dark:border-gray-700 dark:bg-gray-800 lg:col-span-2">
64
+ <div class="mb-3">
65
+ <h2 class="text-sm font-bold text-gray-900 dark:text-gray-100">Provider Connection</h2>
66
+ <p class="text-xs text-gray-500 dark:text-gray-300">External provider identity and public webhook configuration.</p>
78
67
  </div>
79
-
80
- <div class="field-info-container">
81
- <div class="field-name">MSISDN</div>
82
- <div class="field-value">{{n-a @resource.msisdn}}</div>
68
+ <div class="grid grid-cols-1 gap-3 text-xs md:grid-cols-2">
69
+ <div class="rounded-md border border-gray-200 p-3 dark:border-gray-700">
70
+ <div class="text-gray-400 dark:text-gray-500">Provider</div>
71
+ <div class="mt-1 flex items-center gap-2 font-bold text-gray-900 dark:text-gray-100">
72
+ <Image src={{@resource.provider_descriptor.icon}} class="h-5 w-5 rounded" />
73
+ {{@resource.provider_descriptor.label}}
74
+ </div>
75
+ </div>
76
+ <div class="rounded-md border border-gray-200 p-3 dark:border-gray-700">
77
+ <div class="text-gray-400 dark:text-gray-500">Integration ID</div>
78
+ <div class="mt-1 font-mono font-bold text-gray-900 dark:text-gray-100">{{n-a @resource.public_id}}</div>
79
+ </div>
80
+ {{#if @resource.provider_descriptor.supports_webhooks}}
81
+ <div class="rounded-md border border-gray-200 p-3 dark:border-gray-700 md:col-span-2">
82
+ <div class="mb-2 text-gray-400 dark:text-gray-500">Webhook URL</div>
83
+ {{#if this.hasWebhookUrl}}
84
+ <ClickToCopy @value={{this.webhookUrl}}>
85
+ <Input @value={{this.webhookUrl}} class="form-input w-full" readonly />
86
+ </ClickToCopy>
87
+ {{else}}
88
+ <div class="text-yellow-700 dark:text-yellow-300">Webhook URL unavailable until this integration has a public ID.</div>
89
+ {{/if}}
90
+ </div>
91
+ {{/if}}
83
92
  </div>
93
+ </div>
84
94
 
85
- <div class="field-info-container">
86
- <div class="field-name">Last Seen</div>
87
- <div class="field-value">{{n-a (format-date @resource.last_seen_at)}}</div>
95
+ <div class="rounded-md border border-gray-200 bg-white p-4 dark:border-gray-700 dark:bg-gray-800">
96
+ <div class="mb-3">
97
+ <h2 class="text-sm font-bold text-gray-900 dark:text-gray-100">Hardware Identity</h2>
98
+ <p class="text-xs text-gray-500 dark:text-gray-300">Provider blackbox metadata stored on the integration.</p>
88
99
  </div>
89
-
90
- <div class="field-info-container">
91
- <div class="field-name">Online Status</div>
92
- <div class="field-value">
100
+ <div class="grid gap-2 text-xs">
101
+ {{#each this.hardwareFields as |field|}}
102
+ <div class="flex items-center justify-between gap-3 border-b border-gray-100 py-1.5 last:border-b-0 dark:border-gray-700">
103
+ <span class="text-gray-400 dark:text-gray-500">{{field.label}}</span>
104
+ <span class="truncate font-semibold text-gray-900 dark:text-gray-100">{{n-a field.value}}</span>
105
+ </div>
106
+ {{/each}}
107
+ <div class="flex items-center justify-between gap-3 border-b border-gray-100 py-1.5 last:border-b-0 dark:border-gray-700">
108
+ <span class="text-gray-400 dark:text-gray-500">Online</span>
93
109
  {{#if @resource.is_online}}
94
110
  <Badge @status="online">Online</Badge>
95
111
  {{else}}
@@ -97,13 +113,8 @@
97
113
  {{/if}}
98
114
  </div>
99
115
  </div>
100
-
101
- <div class="field-info-container">
102
- <div class="field-name">Signal Strength</div>
103
- <div class="field-value">{{n-a @resource.signal_strength}}</div>
104
- </div>
105
116
  </div>
106
- </ContentPanel>
117
+ </section>
107
118
 
108
119
  <CustomField::Yield @subject={{@resource}} @viewMode={{true}} @wrapperClass="bordered-top" />
109
- </div>
120
+ </div>
@@ -1,3 +1,232 @@
1
1
  import Component from '@glimmer/component';
2
2
 
3
- export default class TelematicDetailsComponent extends Component {}
3
+ export default class TelematicDetailsComponent extends Component {
4
+ get webhookUrl() {
5
+ const url = this.args.resource?.provider_descriptor?.webhook_url;
6
+ const id = this.args.resource?.public_id;
7
+
8
+ if (!url || !id) {
9
+ return null;
10
+ }
11
+
12
+ const separator = url.includes('?') ? '&' : '?';
13
+ return `${url}${separator}telematic=${id}`;
14
+ }
15
+
16
+ get hasWebhookUrl() {
17
+ return Boolean(this.webhookUrl);
18
+ }
19
+
20
+ get lastTestStatus() {
21
+ const result = this.args.resource?.meta?.last_test_result;
22
+
23
+ if (result === 'success') {
24
+ return {
25
+ status: 'success',
26
+ label: 'Verified',
27
+ };
28
+ }
29
+
30
+ if (result === 'failed') {
31
+ return {
32
+ status: 'danger',
33
+ label: 'Failed',
34
+ };
35
+ }
36
+
37
+ return null;
38
+ }
39
+
40
+ get lastSyncStatus() {
41
+ if (this.args.resource?.status === 'synchronizing') {
42
+ return {
43
+ status: 'info',
44
+ label: 'Syncing',
45
+ };
46
+ }
47
+
48
+ const result = this.args.resource?.meta?.last_sync_result;
49
+
50
+ if (result === 'success') {
51
+ return {
52
+ status: 'success',
53
+ label: 'Synced',
54
+ };
55
+ }
56
+
57
+ if (result === 'failed') {
58
+ return {
59
+ status: 'danger',
60
+ label: 'Failed',
61
+ };
62
+ }
63
+
64
+ return null;
65
+ }
66
+
67
+ get connectionTestValue() {
68
+ return this.lastTestStatus?.label ?? 'Not tested';
69
+ }
70
+
71
+ get deviceSyncValue() {
72
+ if (this.args.resource?.status === 'synchronizing') {
73
+ return 'Syncing provider devices';
74
+ }
75
+
76
+ if (this.args.resource?.meta?.last_sync_result === 'success') {
77
+ return 'Synced';
78
+ }
79
+
80
+ if (this.args.resource?.meta?.last_sync_result === 'failed') {
81
+ return 'Failed';
82
+ }
83
+
84
+ return 'Not synced';
85
+ }
86
+
87
+ get deviceSyncDetail() {
88
+ if (this.args.resource?.status === 'synchronizing') {
89
+ return this.args.resource?.meta?.last_sync_started_at;
90
+ }
91
+
92
+ return this.args.resource?.meta?.last_sync_completed_at;
93
+ }
94
+
95
+ get connectionTestAccentClass() {
96
+ if (this.lastTestStatus?.status === 'danger') {
97
+ return 'fleetops-connectivity-kpi-accent-rose';
98
+ }
99
+
100
+ if (this.lastTestStatus?.status === 'success') {
101
+ return 'fleetops-connectivity-kpi-accent-green';
102
+ }
103
+
104
+ return 'fleetops-connectivity-kpi-accent-blue';
105
+ }
106
+
107
+ get deviceSyncAccentClass() {
108
+ if (this.lastSyncStatus?.status === 'danger') {
109
+ return 'fleetops-connectivity-kpi-accent-rose';
110
+ }
111
+
112
+ if (this.lastSyncStatus?.status === 'success') {
113
+ return 'fleetops-connectivity-kpi-accent-green';
114
+ }
115
+
116
+ if (this.args.resource?.status === 'synchronizing') {
117
+ return 'fleetops-connectivity-kpi-accent-blue';
118
+ }
119
+
120
+ return 'fleetops-connectivity-kpi-accent-amber';
121
+ }
122
+
123
+ get devicesSyncedAccentClass() {
124
+ return this.args.resource?.meta?.last_sync_total ? 'fleetops-connectivity-kpi-accent-green' : 'fleetops-connectivity-kpi-accent-blue';
125
+ }
126
+
127
+ get healthCards() {
128
+ const resource = this.args.resource;
129
+
130
+ return [
131
+ {
132
+ icon: 'plug',
133
+ label: 'Connection test',
134
+ value: this.connectionTestValue,
135
+ help: 'Provider credentials',
136
+ detailLabel: 'Last test',
137
+ detail: resource?.meta?.last_connection_test,
138
+ detailIsDate: true,
139
+ status: this.lastTestStatus?.status,
140
+ statusLabel: this.lastTestStatus?.label,
141
+ accentClass: this.connectionTestAccentClass,
142
+ },
143
+ {
144
+ icon: 'satellite-dish',
145
+ label: 'Device sync',
146
+ value: this.deviceSyncValue,
147
+ help: 'Provider device discovery',
148
+ detailLabel: this.args.resource?.status === 'synchronizing' ? 'Started' : 'Last sync',
149
+ detail: this.deviceSyncDetail,
150
+ detailIsDate: true,
151
+ status: this.lastSyncStatus?.status,
152
+ statusLabel: this.lastSyncStatus?.label,
153
+ accentClass: this.deviceSyncAccentClass,
154
+ },
155
+ {
156
+ icon: 'microchip',
157
+ label: 'Devices synced',
158
+ value: resource?.meta?.last_sync_total ?? 0,
159
+ help: 'Devices from provider',
160
+ detailLabel: 'Sync job',
161
+ detail: resource?.meta?.last_sync_job_id,
162
+ detailIsDate: false,
163
+ status: resource?.meta?.last_sync_total ? 'success' : null,
164
+ statusLabel: resource?.meta?.last_sync_total ? 'Available' : null,
165
+ accentClass: this.devicesSyncedAccentClass,
166
+ },
167
+ ];
168
+ }
169
+
170
+ get attentionItems() {
171
+ const resource = this.args.resource;
172
+ const items = [];
173
+
174
+ if (resource?.meta?.last_error) {
175
+ items.push({
176
+ icon: 'triangle-exclamation',
177
+ title: 'Connection issue',
178
+ description: this.userFacingIssueMessage(resource.meta.last_error, 'Connection test failed. Review the provider credentials and try again.'),
179
+ status: 'warning',
180
+ });
181
+ }
182
+
183
+ if (resource?.meta?.last_sync_error) {
184
+ items.push({
185
+ icon: 'circle-exclamation',
186
+ title: 'Sync issue',
187
+ description: this.userFacingIssueMessage(resource.meta.last_sync_error, 'Device sync failed. Review the provider connection and server logs, then try again.'),
188
+ status: 'warning',
189
+ });
190
+ }
191
+
192
+ if (resource?.meta?.unattached_devices_count > 0) {
193
+ items.push({
194
+ icon: 'truck',
195
+ title: 'Devices need vehicles',
196
+ description: `${resource.meta.unattached_devices_count} synced devices are waiting to be attached.`,
197
+ status: 'warning',
198
+ });
199
+ }
200
+
201
+ return items;
202
+ }
203
+
204
+ userFacingIssueMessage(message, fallback) {
205
+ if (!message || this.isSensitiveIssueMessage(message)) {
206
+ return fallback;
207
+ }
208
+
209
+ return String(message);
210
+ }
211
+
212
+ isSensitiveIssueMessage(message) {
213
+ const value = String(message).toLowerCase();
214
+
215
+ return ['sqlstate', 'insert into', 'update `', 'select ', 'schema', 'stack trace', 'connection:', 'pdoexception'].some((fragment) => value.includes(fragment));
216
+ }
217
+
218
+ get hardwareFields() {
219
+ const resource = this.args.resource;
220
+
221
+ return [
222
+ { label: 'Model', value: resource?.model },
223
+ { label: 'Serial Number', value: resource?.serial_number },
224
+ { label: 'Firmware Version', value: resource?.firmware_version },
225
+ { label: 'IMEI', value: resource?.imei },
226
+ { label: 'ICCID', value: resource?.iccid },
227
+ { label: 'IMSI', value: resource?.imsi },
228
+ { label: 'MSISDN', value: resource?.msisdn },
229
+ { label: 'Signal Strength', value: resource?.signal_strength },
230
+ ];
231
+ }
232
+ }