@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
@@ -0,0 +1,145 @@
1
+ import Component from '@glimmer/component';
2
+ import { action } from '@ember/object';
3
+
4
+ const MATCHING_FIELDS = [
5
+ {
6
+ key: 'plate_number',
7
+ label: 'Plate number',
8
+ source: 'Provider plate number',
9
+ target: 'Vehicle plate number',
10
+ description: 'Best default for fuel card imports. Matches license plates with normalized spacing and casing.',
11
+ },
12
+ {
13
+ key: 'internal_id',
14
+ label: 'Internal ID',
15
+ source: 'Provider internal fleet number',
16
+ target: 'Vehicle internal ID',
17
+ description: 'Use when the provider fleet number is the same identifier operators maintain on the vehicle.',
18
+ },
19
+ {
20
+ key: 'vin',
21
+ label: 'VIN',
22
+ source: 'Provider VIN',
23
+ target: 'Vehicle VIN',
24
+ description: 'Matches the vehicle identification number when the provider sends it with the transaction.',
25
+ },
26
+ {
27
+ key: 'serial_number',
28
+ label: 'Serial number',
29
+ source: 'Provider serial number',
30
+ target: 'Vehicle serial number',
31
+ description: 'Matches manufacturer or fleet serial numbers recorded on the vehicle.',
32
+ },
33
+ {
34
+ key: 'call_sign',
35
+ label: 'Call sign',
36
+ source: 'Provider call sign',
37
+ target: 'Vehicle call sign',
38
+ description: 'Matches operational call signs when those are shared with the fuel provider.',
39
+ },
40
+ {
41
+ key: 'fuel_card_number',
42
+ label: 'Fuel card number',
43
+ source: 'Provider fuel card number',
44
+ target: 'Vehicle fuel card number',
45
+ description: 'Use when each vehicle has a dedicated fuel card number saved on the vehicle record.',
46
+ },
47
+ {
48
+ key: 'trip_number',
49
+ label: 'Trip number / order reference',
50
+ source: 'Provider trip/order reference',
51
+ target: 'Order public ID, internal ID, or tracking number',
52
+ description: 'Links the transaction to an order when the provider sends a trip or order reference. It does not identify the vehicle by itself.',
53
+ },
54
+ {
55
+ key: 'provider_vehicle_id',
56
+ label: 'Provider vehicle ID',
57
+ source: 'Provider-specific vehicle ID',
58
+ target: 'Vehicle provider metadata',
59
+ description: 'Advanced fallback only. Use it when provider vehicle IDs have been intentionally stored on vehicle metadata.',
60
+ },
61
+ ];
62
+
63
+ const DEFAULT_MATCHING_ORDER = ['plate_number', 'internal_id', 'vin', 'serial_number', 'call_sign', 'fuel_card_number', 'trip_number'];
64
+ const LEGACY_DEFAULT_MATCHING_ORDER = ['provider_vehicle_id', 'internal_number', 'structure_number', 'plate_number', 'vehicle_card_id', 'trip_number'];
65
+ const LEGACY_FIELD_ALIASES = {
66
+ internal_number: 'internal_id',
67
+ vehicle_card_id: 'fuel_card_number',
68
+ };
69
+
70
+ export default class FuelIntegrationMatchingPriorityComponent extends Component {
71
+ fields = MATCHING_FIELDS;
72
+
73
+ get order() {
74
+ if (Array.isArray(this.args.order)) {
75
+ if (this.args.order.join('|') === LEGACY_DEFAULT_MATCHING_ORDER.join('|')) {
76
+ return DEFAULT_MATCHING_ORDER;
77
+ }
78
+
79
+ return Array.from(this.args.order)
80
+ .map((key) => LEGACY_FIELD_ALIASES[key] ?? key)
81
+ .filter((key, index, order) => key && order.indexOf(key) === index);
82
+ }
83
+
84
+ return DEFAULT_MATCHING_ORDER;
85
+ }
86
+
87
+ get selectedFields() {
88
+ const lastIndex = this.order.length - 1;
89
+
90
+ return this.order
91
+ .map((key, index) => {
92
+ const field = this.fields.find((option) => option.key === key);
93
+ if (!field) {
94
+ return null;
95
+ }
96
+
97
+ return {
98
+ ...field,
99
+ index,
100
+ priority: index + 1,
101
+ canMoveUp: index > 0,
102
+ canMoveDown: index < lastIndex,
103
+ };
104
+ })
105
+ .filter(Boolean);
106
+ }
107
+
108
+ get availableFields() {
109
+ const selected = new Set(this.order);
110
+ return this.fields.filter((field) => !selected.has(field.key));
111
+ }
112
+
113
+ get hasSelectedFields() {
114
+ return this.selectedFields.length > 0;
115
+ }
116
+
117
+ updateOrder(order) {
118
+ this.args.onChange?.(order);
119
+ }
120
+
121
+ @action addField(field) {
122
+ if (this.order.includes(field.key)) {
123
+ return;
124
+ }
125
+
126
+ this.updateOrder([...this.order, field.key]);
127
+ }
128
+
129
+ @action removeField(field) {
130
+ this.updateOrder(this.order.filter((key) => key !== field.key));
131
+ }
132
+
133
+ @action moveField(field, direction) {
134
+ const currentIndex = this.order.indexOf(field.key);
135
+ const nextIndex = currentIndex + direction;
136
+
137
+ if (currentIndex < 0 || nextIndex < 0 || nextIndex >= this.order.length) {
138
+ return;
139
+ }
140
+
141
+ const nextOrder = [...this.order];
142
+ [nextOrder[currentIndex], nextOrder[nextIndex]] = [nextOrder[nextIndex], nextOrder[currentIndex]];
143
+ this.updateOrder(nextOrder);
144
+ }
145
+ }
@@ -9,6 +9,18 @@
9
9
  <div class="field-name">{{t "common.status"}}</div>
10
10
  <div class="field-value"><Badge @status={{@resource.status}} /></div>
11
11
  </div>
12
+ {{#if @resource.source}}
13
+ <div class="field-info-container">
14
+ <div class="field-name">Source</div>
15
+ <div class="field-value"><Badge @status={{@resource.source}} /></div>
16
+ </div>
17
+ {{/if}}
18
+ {{#if @resource.provider}}
19
+ <div class="field-info-container">
20
+ <div class="field-name">Provider</div>
21
+ <div class="field-value uppercase">{{@resource.provider}}</div>
22
+ </div>
23
+ {{/if}}
12
24
  <div class="field-info-container">
13
25
  <div class="field-name">{{t "fuel-report.fields.reporter"}}</div>
14
26
  <div class="field-value">{{n-a @resource.reporter_name}}</div>
@@ -45,4 +57,4 @@
45
57
  </ContentPanel>
46
58
 
47
59
  <CustomField::Yield @subject={{@resource}} @viewMode={{true}} @wrapperClass="bordered-top" />
48
- </div>
60
+ </div>
@@ -0,0 +1,113 @@
1
+ {{#unless this.isComplete}}
2
+ <section class="fleet-ops-home-guidance px-4 pt-4 lg:px-6 {{@class}}" ...attributes>
3
+ <div class="fleet-ops-home-guidance-grid">
4
+ <div class="fleet-ops-get-started rounded-md border border-gray-200 bg-white shadow-md dark:border-gray-700 dark:bg-gray-800">
5
+ <div class="flex items-center justify-between border-b border-gray-200 px-3 py-2 dark:border-gray-700">
6
+ <div class="min-w-0">
7
+ <div class="truncate text-sm font-bold text-gray-900 dark:text-gray-100">{{t "widget.get-started.title"}}</div>
8
+ <div class="truncate text-[11px] text-gray-500 dark:text-gray-400">{{t "widget.get-started.subtitle"}}</div>
9
+ </div>
10
+ <button type="button" class="text-gray-400 hover:text-gray-600 dark:hover:text-gray-200" {{on "click" this.refresh}} title={{t "widget.refresh"}}>
11
+ <FaIcon @icon="rotate" class={{if this.gettingStarted.load.isRunning "animate-spin"}} />
12
+ </button>
13
+ </div>
14
+
15
+ <div class="fleet-ops-get-started-content grid grid-cols-1 gap-3 p-3">
16
+ <div class="flex min-h-0 flex-col gap-2">
17
+ {{#if this.gettingStarted.load.isRunning}}
18
+ <div class="flex flex-1 items-center justify-center"><Spinner /></div>
19
+ {{else if this.gettingStarted.error}}
20
+ <div class="flex flex-1 items-center justify-center text-xs text-red-500">{{this.gettingStarted.error}}</div>
21
+ {{else}}
22
+ <div class="mb-1 flex items-center justify-between">
23
+ <span class="text-[11px] font-semibold text-gray-600 dark:text-gray-300">
24
+ {{this.progress.completed}}/{{this.progress.total}}
25
+ {{t "widget.get-started.completed"}}
26
+ </span>
27
+ <span class="text-[11px] font-semibold text-blue-600 dark:text-blue-300">{{this.progress.percent}}%</span>
28
+ </div>
29
+ <div class="h-1.5 overflow-hidden rounded-full bg-gray-100 dark:bg-gray-700">
30
+ <div class="h-full rounded-full bg-blue-600 transition-all" style={{html-safe (concat "width:" this.progress.percent "%")}}></div>
31
+ </div>
32
+
33
+ <div class="mt-1 flex min-h-0 flex-1 flex-col gap-1.5">
34
+ {{#each this.steps as |step index|}}
35
+ <button
36
+ type="button"
37
+ class="fleet-ops-get-started-step flex min-h-[58px] w-full items-center gap-2 rounded-md border p-2 text-left transition
38
+ {{if step.completed 'border-gray-200 bg-gray-50 dark:border-gray-700 dark:bg-gray-800/70'}}
39
+ {{if (this.isActiveStep step) 'border-blue-500 bg-blue-50 shadow-sm dark:border-blue-400 dark:bg-blue-950/30'}}
40
+ {{if (this.isInactiveStep step) 'border-gray-200 bg-white hover:border-gray-300 dark:border-gray-700 dark:bg-gray-800 dark:hover:border-gray-600'}}"
41
+ {{on "click" (fn this.startStep step)}}
42
+ >
43
+ <div
44
+ class="flex h-8 w-8 flex-shrink-0 items-center justify-center rounded-full
45
+ {{if
46
+ step.completed
47
+ 'bg-green-100 text-green-600 dark:bg-green-900/40 dark:text-green-300'
48
+ 'bg-blue-100 text-blue-600 dark:bg-blue-900/40 dark:text-blue-300'
49
+ }}"
50
+ >
51
+ {{#if step.completed}}
52
+ <FaIcon @icon="check" />
53
+ {{else}}
54
+ <FaIcon @icon={{step.icon}} />
55
+ {{/if}}
56
+ </div>
57
+ <div class="min-w-0 flex-1">
58
+ <div class="flex items-center gap-1.5">
59
+ <span class="text-[12px] font-bold text-gray-900 dark:text-gray-100">{{add index 1}}. {{step.title}}</span>
60
+ <span class="hidden text-[10px] text-gray-400 sm:inline"><FaIcon @icon="clock" /> {{step.estimate}}</span>
61
+ </div>
62
+ <div class="truncate text-[11px] text-gray-500 dark:text-gray-400">{{step.description}}</div>
63
+ </div>
64
+ <span class="rounded-full px-2 py-0.5 text-[10px] font-bold {{this.statusClass step}}">{{this.statusText step}}</span>
65
+ </button>
66
+ {{/each}}
67
+ </div>
68
+ {{/if}}
69
+ </div>
70
+ </div>
71
+ </div>
72
+
73
+ <div class="fleet-ops-recommended-features rounded-md border border-gray-200 bg-white shadow-md dark:border-gray-700 dark:bg-gray-800">
74
+ <div class="border-b border-gray-200 px-3 py-2 dark:border-gray-700">
75
+ <div class="truncate text-sm font-bold text-gray-900 dark:text-gray-100">{{t "widget.recommended-features.title"}}</div>
76
+ <div class="truncate text-[11px] text-gray-500 dark:text-gray-400">{{t "widget.recommended-features.subtitle"}}</div>
77
+ </div>
78
+
79
+ <div class="p-3">
80
+ {{#if this.gettingStarted.load.isRunning}}
81
+ <div class="fleet-ops-recommended-features-loading flex items-center justify-center"><Spinner /></div>
82
+ {{else if this.gettingStarted.error}}
83
+ <div class="fleet-ops-recommended-features-loading flex items-center justify-center text-xs text-red-500">{{this.gettingStarted.error}}</div>
84
+ {{else}}
85
+ <div class="grid gap-2 sm:grid-cols-2">
86
+ {{#each this.recommendations as |feature|}}
87
+ <button
88
+ type="button"
89
+ class="fleet-ops-recommended-feature
90
+ {{this.accentClass feature}}
91
+ group flex min-h-[92px] items-start gap-3 rounded-md border border-gray-200 bg-gray-50 p-3 text-left transition hover:border-gray-300 hover:bg-white hover:shadow-sm dark:border-gray-700 dark:bg-gray-800 dark:hover:border-gray-600 dark:hover:bg-gray-700"
92
+ {{on "click" (fn this.openFeature feature)}}
93
+ >
94
+ <div class="fleet-ops-recommended-feature-icon flex h-9 w-9 flex-shrink-0 items-center justify-center rounded-md">
95
+ <FaIcon @icon={{feature.icon}} />
96
+ </div>
97
+ <div class="flex min-h-0 flex-1 flex-col">
98
+ <div class="truncate text-[12px] font-bold text-gray-900 dark:text-gray-100">{{feature.title}}</div>
99
+ <p class="mt-1 line-clamp-2 flex-1 text-[11px] leading-4 text-gray-500 dark:text-gray-400">{{feature.description}}</p>
100
+ <div class="mt-2 flex items-center gap-1 text-[11px] font-bold text-blue-600 dark:text-blue-300">
101
+ <span>{{t "widget.recommended-features.learn-more"}}</span>
102
+ <FaIcon @icon="arrow-right" class="transition group-hover:translate-x-0.5" />
103
+ </div>
104
+ </div>
105
+ </button>
106
+ {{/each}}
107
+ </div>
108
+ {{/if}}
109
+ </div>
110
+ </div>
111
+ </div>
112
+ </section>
113
+ {{/unless}}
@@ -0,0 +1,107 @@
1
+ import Component from '@glimmer/component';
2
+ import { action } from '@ember/object';
3
+ import { inject as service } from '@ember/service';
4
+
5
+ const ACCENT_CLASS = {
6
+ blue: 'feature-accent-blue',
7
+ green: 'feature-accent-green',
8
+ amber: 'feature-accent-amber',
9
+ purple: 'feature-accent-purple',
10
+ };
11
+
12
+ export default class HomeGettingStartedGuidanceComponent extends Component {
13
+ @service gettingStarted;
14
+ @service router;
15
+ @service docsPanel;
16
+
17
+ constructor() {
18
+ super(...arguments);
19
+ this.gettingStarted.load.perform();
20
+ }
21
+
22
+ get steps() {
23
+ return this.gettingStarted.steps;
24
+ }
25
+
26
+ get recommendations() {
27
+ return this.gettingStarted.recommendations.slice(0, 4);
28
+ }
29
+
30
+ get progress() {
31
+ return this.gettingStarted.progress;
32
+ }
33
+
34
+ get nextStep() {
35
+ return this.gettingStarted.nextStep;
36
+ }
37
+
38
+ get isComplete() {
39
+ return this.gettingStarted.isCompleted;
40
+ }
41
+
42
+ @action
43
+ isActiveStep(step) {
44
+ return this.nextStep?.key === step.key && !step.completed;
45
+ }
46
+
47
+ @action
48
+ isInactiveStep(step) {
49
+ return !step.completed && !this.isActiveStep(step);
50
+ }
51
+
52
+ @action
53
+ statusText(step) {
54
+ if (step.completed) {
55
+ return 'Done';
56
+ }
57
+
58
+ return this.isActiveStep(step) ? 'Next' : 'Not started';
59
+ }
60
+
61
+ @action
62
+ statusClass(step) {
63
+ if (step.completed) {
64
+ return 'bg-green-100 text-green-700 dark:bg-green-900/40 dark:text-green-300';
65
+ }
66
+
67
+ if (this.isActiveStep(step)) {
68
+ return 'bg-blue-100 text-blue-700 dark:bg-blue-900/40 dark:text-blue-300';
69
+ }
70
+
71
+ return 'bg-gray-100 text-gray-500 dark:bg-gray-700 dark:text-gray-300';
72
+ }
73
+
74
+ @action
75
+ accentClass(feature) {
76
+ return ACCENT_CLASS[feature.accent] ?? ACCENT_CLASS.blue;
77
+ }
78
+
79
+ @action
80
+ startStep(step) {
81
+ if (step?.route) {
82
+ return this.router.transitionTo(step.route);
83
+ }
84
+
85
+ if (step?.docs_url) {
86
+ return this.openDocs(step.docs_url, step.title, 'fleet-ops-getting-started-guidance');
87
+ }
88
+ }
89
+
90
+ @action
91
+ openFeature(feature) {
92
+ return this.openDocs(feature.docs_url, feature.title, 'fleet-ops-recommended-features-guidance');
93
+ }
94
+
95
+ openDocs(url, title, source) {
96
+ if (this.docsPanel?.open) {
97
+ return this.docsPanel.open(url, { title, source });
98
+ }
99
+
100
+ return window.open(url, '_docs');
101
+ }
102
+
103
+ @action
104
+ refresh() {
105
+ this.gettingStarted.load.perform();
106
+ }
107
+ }
@@ -0,0 +1,3 @@
1
+ <ContentPanel @title="Correspondence" @open={{true}} @wrapperClass="bordered-top">
2
+ <CommentThread @subject={{@resource}} @subjectType="fleet-ops:issue" />
3
+ </ContentPanel>
@@ -0,0 +1,3 @@
1
+ import Component from '@glimmer/component';
2
+
3
+ export default class IssueDetailsCommentsComponent extends Component {}
@@ -0,0 +1,9 @@
1
+ <div class="issue-detail-comment-thread" {{did-insert this.loadComments}} {{did-update this.loadComments this.issueId}}>
2
+ <CommentThread
3
+ @subject={{@resource}}
4
+ @subjectType="Fleetbase\FleetOps\Models\Issue"
5
+ @comments={{this.comments}}
6
+ @onReloadComments={{this.reloadCommentsForIssue}}
7
+ @onPublishComment={{this.publishComment}}
8
+ />
9
+ </div>
@@ -0,0 +1,83 @@
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
+
6
+ const ISSUE_SUBJECT_TYPE = 'Fleetbase\\FleetOps\\Models\\Issue';
7
+ const UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
8
+
9
+ export default class IssueDetailsCorrespondenceComponent extends Component {
10
+ @service store;
11
+ @service notifications;
12
+
13
+ @tracked comments = [];
14
+
15
+ get resource() {
16
+ return this.args.resource;
17
+ }
18
+
19
+ get issueId() {
20
+ return this.resource?.id || this.resource?.public_id || this.resource?.uuid;
21
+ }
22
+
23
+ get subjectUuid() {
24
+ if (this.resource?.uuid) {
25
+ return this.resource.uuid;
26
+ }
27
+
28
+ if (UUID_PATTERN.test(this.resource?.id ?? '')) {
29
+ return this.resource.id;
30
+ }
31
+
32
+ return null;
33
+ }
34
+
35
+ get subjectPublicId() {
36
+ return this.resource?.public_id || this.resource?.id || this.resource?.uuid;
37
+ }
38
+
39
+ @action loadComments() {
40
+ this.reloadCommentsForIssue();
41
+ }
42
+
43
+ @action async reloadCommentsForIssue() {
44
+ const query = {
45
+ withoutParent: 1,
46
+ sort: '-created_at',
47
+ subject_type: ISSUE_SUBJECT_TYPE,
48
+ };
49
+
50
+ if (this.subjectUuid) {
51
+ query.subject_uuid = this.subjectUuid;
52
+ } else {
53
+ query.subject = this.subjectPublicId;
54
+ }
55
+
56
+ const comments = await this.store.query('comment', query);
57
+ this.comments = comments;
58
+
59
+ return comments;
60
+ }
61
+
62
+ @action async publishComment(content) {
63
+ const subjectUuid = this.subjectUuid;
64
+ if (!subjectUuid) {
65
+ const error = new Error('Unable to publish comment because the issue UUID is missing.');
66
+ this.notifications.error(error.message);
67
+ throw error;
68
+ }
69
+
70
+ const comment = this.store.createRecord('comment', {
71
+ content,
72
+ subject_uuid: subjectUuid,
73
+ subject_type: ISSUE_SUBJECT_TYPE,
74
+ });
75
+
76
+ try {
77
+ await comment.save();
78
+ } catch (error) {
79
+ this.notifications.serverError(error);
80
+ throw error;
81
+ }
82
+ }
83
+ }
@@ -0,0 +1,69 @@
1
+ <div class="issue-detail-documents">
2
+ <div class="issue-detail-documents-header">
3
+ <div class="issue-detail-documents-title">
4
+ <FaIcon @icon="paperclip" />
5
+ <span>Attachments</span>
6
+ </div>
7
+ </div>
8
+
9
+ {{#if this.queueFile.isRunning}}
10
+ <div class="issue-detail-dropzone is-loading">
11
+ <Spinner @loadingMessage="Uploading..." />
12
+ </div>
13
+ {{else}}
14
+ {{#let (file-queue name="issue-files" onFileAdded=(perform this.queueFile) accept=(join "," this.acceptedFileTypes)) as |queue|}}
15
+ <FileDropzone @queue={{queue}} class="issue-detail-dropzone file-dropzone" @disabled={{cannot-write @resource}} as |dropzone|>
16
+ {{#if dropzone.active}}
17
+ {{#if dropzone.valid}}
18
+ Drop files to attach them to this issue.
19
+ {{else}}
20
+ This file type is not supported.
21
+ {{/if}}
22
+ {{else if queue.files.length}}
23
+ <div class="issue-detail-dropzone-ready">
24
+ <FaIcon @icon="folder-open" />
25
+ <span>{{pluralize queue.files.length "file"}} ready for upload</span>
26
+ </div>
27
+ <div class="issue-detail-dropzone-progress">{{queue.progress}}%</div>
28
+ {{else}}
29
+ <div class="issue-detail-dropzone-empty">
30
+ <FaIcon @icon="folder-open" />
31
+ <span>Drop documents or images here</span>
32
+ <FileUpload
33
+ @name="issue-files"
34
+ @for="issue-files"
35
+ @accept={{join "," this.acceptedFileTypes}}
36
+ @multiple={{true}}
37
+ @onFileAdded={{perform this.queueFile}}
38
+ @disabled={{cannot-write @resource}}
39
+ >
40
+ <a tabindex={{0}} class="btn btn-sm btn-default">select files</a>
41
+ </FileUpload>
42
+ </div>
43
+ {{/if}}
44
+ </FileDropzone>
45
+ {{/let}}
46
+ {{/if}}
47
+
48
+ {{#if this.uploadQueue}}
49
+ <div class="issue-detail-upload-queue mt-4">
50
+ {{#each this.uploadQueue as |file|}}
51
+ <div class="issue-detail-upload-row">
52
+ <span>{{truncate-filename file.name 40}}</span>
53
+ <div class="flex flex-row items-center">
54
+ <Spinner class="mr-1" />
55
+ <strong>{{round file.progress}}%</strong>
56
+ </div>
57
+ </div>
58
+ {{/each}}
59
+ </div>
60
+ {{/if}}
61
+
62
+ {{#if this.files.length}}
63
+ <div class="issue-detail-file-grid mt-4">
64
+ {{#each this.files as |file|}}
65
+ <File @file={{file}} @onDownload={{this.downloadFile}} @onDelete={{perform this.removeFile}} />
66
+ {{/each}}
67
+ </div>
68
+ {{/if}}
69
+ </div>
@@ -0,0 +1,85 @@
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 IssueDetailsDocumentsComponent extends Component {
9
+ @service fetch;
10
+ @service notifications;
11
+ @tracked uploadQueue = [];
12
+ @tracked acceptedFileTypes = [
13
+ 'application/vnd.ms-excel',
14
+ 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
15
+ 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
16
+ 'application/msword',
17
+ 'application/pdf',
18
+ 'application/x-pdf',
19
+ 'image/jpeg',
20
+ 'image/png',
21
+ 'image/gif',
22
+ 'image/webp',
23
+ 'video/mp4',
24
+ 'video/quicktime',
25
+ 'video/x-msvideo',
26
+ 'video/x-flv',
27
+ 'video/x-ms-wmv',
28
+ 'audio/mpeg',
29
+ 'application/zip',
30
+ 'application/x-tar',
31
+ ];
32
+
33
+ get files() {
34
+ return this.args.resource?.files ?? [];
35
+ }
36
+
37
+ @task *queueFile(file) {
38
+ if (['queued', 'failed', 'timed_out', 'aborted'].indexOf(file.state) === -1) return;
39
+
40
+ try {
41
+ this.uploadQueue.pushObject(file);
42
+ yield this.fetch.uploadFile.perform(
43
+ file,
44
+ {
45
+ path: 'uploads/fleet-ops/issue-files',
46
+ subject_uuid: this.args.resource.id,
47
+ subject_type: 'fleet-ops:issue',
48
+ type: 'issue_file',
49
+ },
50
+ (uploadedFile) => {
51
+ if (this.args.resource.files?.pushObject) {
52
+ this.args.resource.files.pushObject(uploadedFile);
53
+ }
54
+ this.uploadQueue.removeObject(file);
55
+ },
56
+ () => {
57
+ this.uploadQueue.removeObject(file);
58
+ if (file.queue && typeof file.queue.remove === 'function') {
59
+ file.queue.remove(file);
60
+ }
61
+ }
62
+ );
63
+ } catch (err) {
64
+ debug('Issue document upload failed: ' + err.message);
65
+ this.notifications.serverError(err);
66
+ }
67
+ }
68
+
69
+ @task *removeFile(file) {
70
+ yield file.destroyRecord();
71
+ if (this.args.resource.files?.removeObject) {
72
+ this.args.resource.files.removeObject(file);
73
+ }
74
+ }
75
+
76
+ @action downloadFile(file) {
77
+ if (typeof file.download === 'function') {
78
+ return file.download();
79
+ }
80
+
81
+ if (file.url) {
82
+ window.open(file.url, '_blank');
83
+ }
84
+ }
85
+ }