@fleetbase/fleetops-engine 0.0.1

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 (446) hide show
  1. package/LICENSE.md +9 -0
  2. package/README.md +32 -0
  3. package/addon/components/cell/driver-name.hbs +13 -0
  4. package/addon/components/cell/driver-name.js +30 -0
  5. package/addon/components/custom-field-value.hbs +11 -0
  6. package/addon/components/custom-field-value.js +41 -0
  7. package/addon/components/custom-field.hbs +42 -0
  8. package/addon/components/custom-field.js +46 -0
  9. package/addon/components/display-place.hbs +52 -0
  10. package/addon/components/display-place.js +11 -0
  11. package/addon/components/driver-card-mini.hbs +12 -0
  12. package/addon/components/driver-card-mini.js +25 -0
  13. package/addon/components/driver-card.hbs +27 -0
  14. package/addon/components/driver-card.js +14 -0
  15. package/addon/components/event-timeline/event.hbs +5 -0
  16. package/addon/components/event-timeline.hbs +7 -0
  17. package/addon/components/event-timeline.js +423 -0
  18. package/addon/components/file-icon.js +1 -0
  19. package/addon/components/fleet-driver-listing.hbs +73 -0
  20. package/addon/components/fleet-driver-listing.js +117 -0
  21. package/addon/components/full-calendar/draggable.js +1 -0
  22. package/addon/components/full-calendar.js +1 -0
  23. package/addon/components/full-size.js +1 -0
  24. package/addon/components/global-search.hbs +84 -0
  25. package/addon/components/global-search.js +52 -0
  26. package/addon/components/horizontal-route.hbs +33 -0
  27. package/addon/components/horizontal-route.js +48 -0
  28. package/addon/components/integrated-order-details.hbs +117 -0
  29. package/addon/components/integrated-order-details.js +10 -0
  30. package/addon/components/leaflet-draw-control.js +147 -0
  31. package/addon/components/leaflet-rotated-marker.js +24 -0
  32. package/addon/components/live-map.hbs +63 -0
  33. package/addon/components/live-map.js +856 -0
  34. package/addon/components/map-container/toolbar/zones-panel.hbs +41 -0
  35. package/addon/components/map-container/toolbar/zones-panel.js +106 -0
  36. package/addon/components/map-container/toolbar-container.hbs +1 -0
  37. package/addon/components/map-container/toolbar-container.js +3 -0
  38. package/addon/components/map-container/toolbar.hbs +51 -0
  39. package/addon/components/map-container/toolbar.js +34 -0
  40. package/addon/components/map-container/topbar.hbs +1 -0
  41. package/addon/components/map-container/topbar.js +3 -0
  42. package/addon/components/map-container/view-switch.hbs +1 -0
  43. package/addon/components/map-container/view-switch.js +3 -0
  44. package/addon/components/map-container.hbs +1 -0
  45. package/addon/components/map-container.js +15 -0
  46. package/addon/components/modals/assign-driver.hbs +24 -0
  47. package/addon/components/modals/assign-driver.js +3 -0
  48. package/addon/components/modals/clone-config-form.hbs +6 -0
  49. package/addon/components/modals/contact-details.hbs +44 -0
  50. package/addon/components/modals/contact-form.hbs +56 -0
  51. package/addon/components/modals/driver-assign-order.hbs +67 -0
  52. package/addon/components/modals/driver-assign-vehicle.hbs +20 -0
  53. package/addon/components/modals/driver-assign-vendor.hbs +20 -0
  54. package/addon/components/modals/driver-details.hbs +85 -0
  55. package/addon/components/modals/driver-form.hbs +83 -0
  56. package/addon/components/modals/edit-meta-form.hbs +20 -0
  57. package/addon/components/modals/entity-form.hbs +57 -0
  58. package/addon/components/modals/entity-meta-field-prompt.hbs +6 -0
  59. package/addon/components/modals/fleet-details.hbs +31 -0
  60. package/addon/components/modals/fleet-form.hbs +26 -0
  61. package/addon/components/modals/fuel-report-details.hbs +34 -0
  62. package/addon/components/modals/fuel-report-form.hbs +26 -0
  63. package/addon/components/modals/group-details.hbs +42 -0
  64. package/addon/components/modals/group-form.hbs +54 -0
  65. package/addon/components/modals/install-prompt.hbs +21 -0
  66. package/addon/components/modals/map-field-form.hbs +9 -0
  67. package/addon/components/modals/map-field-group-form.hbs +6 -0
  68. package/addon/components/modals/map-layer-form.hbs +29 -0
  69. package/addon/components/modals/meta-field-form.hbs +8 -0
  70. package/addon/components/modals/meta-field-group-form.hbs +5 -0
  71. package/addon/components/modals/new-order-config.hbs +11 -0
  72. package/addon/components/modals/option-prompt.hbs +17 -0
  73. package/addon/components/modals/order-assign-driver.hbs +25 -0
  74. package/addon/components/modals/order-config-new-status.hbs +5 -0
  75. package/addon/components/modals/order-event.hbs +18 -0
  76. package/addon/components/modals/order-form.hbs +63 -0
  77. package/addon/components/modals/order-import.hbs +84 -0
  78. package/addon/components/modals/order-label.hbs +7 -0
  79. package/addon/components/modals/order-meta.hbs +12 -0
  80. package/addon/components/modals/order-new-activity.hbs +62 -0
  81. package/addon/components/modals/order-route-form.hbs +111 -0
  82. package/addon/components/modals/place-assign-vendor.hbs +20 -0
  83. package/addon/components/modals/place-details.hbs +105 -0
  84. package/addon/components/modals/place-form.hbs +30 -0
  85. package/addon/components/modals/point-map.hbs +16 -0
  86. package/addon/components/modals/policy-form.hbs +22 -0
  87. package/addon/components/modals/resend-verification-email.hbs +25 -0
  88. package/addon/components/modals/role-form.hbs +16 -0
  89. package/addon/components/modals/select-payment-method.hbs +12 -0
  90. package/addon/components/modals/service-area-form.hbs +31 -0
  91. package/addon/components/modals/set-password.hbs +15 -0
  92. package/addon/components/modals/uninstall-prompt.hbs +21 -0
  93. package/addon/components/modals/user-form.hbs +56 -0
  94. package/addon/components/modals/vehicle-details.hbs +227 -0
  95. package/addon/components/modals/vehicle-form.hbs +282 -0
  96. package/addon/components/modals/vendor-details.hbs +77 -0
  97. package/addon/components/modals/vendor-form.hbs +168 -0
  98. package/addon/components/modals/view-service-area.hbs +12 -0
  99. package/addon/components/modals/view-zone.hbs +12 -0
  100. package/addon/components/modals/zone-form.hbs +16 -0
  101. package/addon/components/operations-pane/pane.hbs +1 -0
  102. package/addon/components/order/header.hbs +48 -0
  103. package/addon/components/order/header.js +26 -0
  104. package/addon/components/order/place-card.hbs +51 -0
  105. package/addon/components/order/place-card.js +33 -0
  106. package/addon/components/order/schedule-card.hbs +35 -0
  107. package/addon/components/order/schedule-card.js +17 -0
  108. package/addon/components/order/sub-header/item.hbs +16 -0
  109. package/addon/components/order/sub-header.hbs +3 -0
  110. package/addon/components/order-config/activity-flow-editor.hbs +108 -0
  111. package/addon/components/order-config/activity-flow-editor.js +374 -0
  112. package/addon/components/order-config/details-editor.hbs +32 -0
  113. package/addon/components/order-config/details-editor.js +16 -0
  114. package/addon/components/order-config/entities-editor.hbs +84 -0
  115. package/addon/components/order-config/entities-editor.js +123 -0
  116. package/addon/components/order-config/fields-editor.hbs +122 -0
  117. package/addon/components/order-config/fields-editor.js +233 -0
  118. package/addon/components/order-config/selector.hbs +1 -0
  119. package/addon/components/order-config/selector.js +3 -0
  120. package/addon/components/order-config.hbs +66 -0
  121. package/addon/components/order-config.js +296 -0
  122. package/addon/components/order-list-overlay/driver-panel-title.hbs +6 -0
  123. package/addon/components/order-list-overlay/order.hbs +22 -0
  124. package/addon/components/order-list-overlay/order.js +3 -0
  125. package/addon/components/order-list-overlay.hbs +120 -0
  126. package/addon/components/order-list-overlay.js +227 -0
  127. package/addon/components/route-list.hbs +47 -0
  128. package/addon/components/route-list.js +11 -0
  129. package/addon/components/settings-window.hbs +15 -0
  130. package/addon/components/settings-window.js +62 -0
  131. package/addon/components/split-grid.js +1 -0
  132. package/addon/components/widget/fleet-ops-quickstart.hbs +40 -0
  133. package/addon/components/widget/fleet-ops-quickstart.js +58 -0
  134. package/addon/components/widget/issues.hbs +1 -0
  135. package/addon/components/widget/key-metrics.hbs +121 -0
  136. package/addon/components/widget/key-metrics.js +46 -0
  137. package/addon/components/widget/live-order-map.hbs +59 -0
  138. package/addon/components/widget/live-order-map.js +11 -0
  139. package/addon/components/widget/recent-orders.hbs +35 -0
  140. package/addon/components/widget/recent-orders.js +24 -0
  141. package/addon/components/widget/transaction-earnings.hbs +1 -0
  142. package/addon/components/widget/transactions.hbs +36 -0
  143. package/addon/components/widget/transactions.js +29 -0
  144. package/addon/components/widget/weekly-orders.hbs +1 -0
  145. package/addon/components/widget/weekly-orders.js +3 -0
  146. package/addon/controllers/application.js +40 -0
  147. package/addon/controllers/management/contacts/index.js +438 -0
  148. package/addon/controllers/management/drivers/index.js +868 -0
  149. package/addon/controllers/management/fleets/index.js +507 -0
  150. package/addon/controllers/management/fuel-reports/index.js +428 -0
  151. package/addon/controllers/management/issues/index.js +335 -0
  152. package/addon/controllers/management/places/index.js +571 -0
  153. package/addon/controllers/management/vehicles/index.js +616 -0
  154. package/addon/controllers/management/vendors/index.js +626 -0
  155. package/addon/controllers/management.js +5 -0
  156. package/addon/controllers/operations/orders/index/config/types.js +17 -0
  157. package/addon/controllers/operations/orders/index/config.js +13 -0
  158. package/addon/controllers/operations/orders/index/new.js +1213 -0
  159. package/addon/controllers/operations/orders/index/view.js +794 -0
  160. package/addon/controllers/operations/orders/index.js +674 -0
  161. package/addon/controllers/operations/scheduler/index.js +110 -0
  162. package/addon/controllers/operations/service-rates/index/edit.js +59 -0
  163. package/addon/controllers/operations/service-rates/index/new.js +369 -0
  164. package/addon/controllers/operations/service-rates/index.js +275 -0
  165. package/addon/controllers/operations/zones/index.js +470 -0
  166. package/addon/engine.js +19 -0
  167. package/addon/helpers/avatar-url.js +9 -0
  168. package/addon/helpers/extract-coordinates.js +6 -0
  169. package/addon/helpers/feature-group.js +14 -0
  170. package/addon/helpers/flow-raw-status.js +13 -0
  171. package/addon/helpers/format-point.js +13 -0
  172. package/addon/helpers/get-tip-amount.js +19 -0
  173. package/addon/helpers/is-active-route.js +1 -0
  174. package/addon/helpers/is-facilitator-supported-place.js +6 -0
  175. package/addon/helpers/is-not-facilitator-supported-place.js +6 -0
  176. package/addon/helpers/is-waypoint-record.js +6 -0
  177. package/addon/helpers/point-coordinates.js +10 -0
  178. package/addon/helpers/point-to-coordinates.js +28 -0
  179. package/addon/helpers/service-name.js +6 -0
  180. package/addon/helpers/waypoint-label.js +1 -0
  181. package/addon/instance-initializers/register-leaflet-draw-control-layer.js +17 -0
  182. package/addon/instance-initializers/register-leaflet-rotated-marker.js +17 -0
  183. package/addon/modifiers/translate-x.js +5 -0
  184. package/addon/routes/application.js +25 -0
  185. package/addon/routes/comms/chat.js +3 -0
  186. package/addon/routes/comms/intercom.js +3 -0
  187. package/addon/routes/comms.js +3 -0
  188. package/addon/routes/home.js +20 -0
  189. package/addon/routes/management/contacts/index.js +24 -0
  190. package/addon/routes/management/contacts.js +3 -0
  191. package/addon/routes/management/drivers/index.js +33 -0
  192. package/addon/routes/management/drivers.js +3 -0
  193. package/addon/routes/management/fleets/index.js +27 -0
  194. package/addon/routes/management/fleets.js +3 -0
  195. package/addon/routes/management/fuel-reports/index.js +23 -0
  196. package/addon/routes/management/fuel-reports.js +3 -0
  197. package/addon/routes/management/index.js +3 -0
  198. package/addon/routes/management/issues/index.js +24 -0
  199. package/addon/routes/management/issues.js +3 -0
  200. package/addon/routes/management/places/index.js +18 -0
  201. package/addon/routes/management/places.js +3 -0
  202. package/addon/routes/management/vehicles/index.js +35 -0
  203. package/addon/routes/management/vehicles.js +3 -0
  204. package/addon/routes/management/vendors/index.js +34 -0
  205. package/addon/routes/management/vendors.js +3 -0
  206. package/addon/routes/management.js +3 -0
  207. package/addon/routes/operations/dispatch.js +3 -0
  208. package/addon/routes/operations/orders/index/config/types.js +17 -0
  209. package/addon/routes/operations/orders/index/config.js +3 -0
  210. package/addon/routes/operations/orders/index/new.js +16 -0
  211. package/addon/routes/operations/orders/index/view.js +37 -0
  212. package/addon/routes/operations/orders/index.js +35 -0
  213. package/addon/routes/operations/orders.js +4 -0
  214. package/addon/routes/operations/scheduler/index.js +10 -0
  215. package/addon/routes/operations/scheduler.js +3 -0
  216. package/addon/routes/operations/service-rates/index/edit.js +35 -0
  217. package/addon/routes/operations/service-rates/index/new.js +15 -0
  218. package/addon/routes/operations/service-rates/index.js +49 -0
  219. package/addon/routes/operations/service-rates.js +10 -0
  220. package/addon/routes/operations/zones/index.js +25 -0
  221. package/addon/routes/operations/zones.js +7 -0
  222. package/addon/routes/operations.js +3 -0
  223. package/addon/routes.js +55 -0
  224. package/addon/services/map-manager.js +3 -0
  225. package/addon/services/service-areas.js +385 -0
  226. package/addon/templates/application.hbs +27 -0
  227. package/addon/templates/comms/chat.hbs +1 -0
  228. package/addon/templates/comms/intercom.hbs +1 -0
  229. package/addon/templates/comms.hbs +1 -0
  230. package/addon/templates/home.hbs +1 -0
  231. package/addon/templates/management/contacts/index.hbs +23 -0
  232. package/addon/templates/management/contacts.hbs +1 -0
  233. package/addon/templates/management/drivers/index.hbs +35 -0
  234. package/addon/templates/management/drivers.hbs +1 -0
  235. package/addon/templates/management/fleets/index.hbs +22 -0
  236. package/addon/templates/management/fleets.hbs +1 -0
  237. package/addon/templates/management/fuel-reports/index.hbs +21 -0
  238. package/addon/templates/management/fuel-reports.hbs +1 -0
  239. package/addon/templates/management/index.hbs +53 -0
  240. package/addon/templates/management/issues/index.hbs +21 -0
  241. package/addon/templates/management/issues.hbs +1 -0
  242. package/addon/templates/management/places/index.hbs +34 -0
  243. package/addon/templates/management/places.hbs +1 -0
  244. package/addon/templates/management/vehicles/index.hbs +22 -0
  245. package/addon/templates/management/vehicles.hbs +1 -0
  246. package/addon/templates/management/vendors/index.hbs +22 -0
  247. package/addon/templates/management/vendors.hbs +1 -0
  248. package/addon/templates/management.hbs +1 -0
  249. package/addon/templates/operations/dispatch.hbs +1 -0
  250. package/addon/templates/operations/orders/index/config/types.hbs +26 -0
  251. package/addon/templates/operations/orders/index/config.hbs +24 -0
  252. package/addon/templates/operations/orders/index/new.hbs +506 -0
  253. package/addon/templates/operations/orders/index/view.hbs +428 -0
  254. package/addon/templates/operations/orders/index.hbs +48 -0
  255. package/addon/templates/operations/orders.hbs +1 -0
  256. package/addon/templates/operations/scheduler/index.hbs +30 -0
  257. package/addon/templates/operations/scheduler.hbs +1 -0
  258. package/addon/templates/operations/service-rates/index/edit.hbs +1 -0
  259. package/addon/templates/operations/service-rates/index/new.hbs +308 -0
  260. package/addon/templates/operations/service-rates/index.hbs +23 -0
  261. package/addon/templates/operations/service-rates.hbs +1 -0
  262. package/addon/templates/operations/zones/index.hbs +72 -0
  263. package/addon/templates/operations/zones.hbs +1 -0
  264. package/addon/templates/operations.hbs +1 -0
  265. package/addon/utils/calculate-percentage.js +1 -0
  266. package/addon/utils/extract-coordinates.js +1 -0
  267. package/addon/utils/format-currency.js +1 -0
  268. package/addon/utils/geojson/geo-json.js +17 -0
  269. package/addon/utils/is-facilitator-supported-place.js +14 -0
  270. package/addon/utils/to-model.js +1 -0
  271. package/app/components/cell/driver-name.js +1 -0
  272. package/app/components/custom-field-value.js +1 -0
  273. package/app/components/custom-field.js +1 -0
  274. package/app/components/display-place.js +1 -0
  275. package/app/components/driver-card-mini.js +1 -0
  276. package/app/components/driver-card.js +1 -0
  277. package/app/components/event-timeline/event.js +1 -0
  278. package/app/components/event-timeline.js +1 -0
  279. package/app/components/file-icon.js +1 -0
  280. package/app/components/fleet-driver-listing.js +1 -0
  281. package/app/components/full-calendar/draggable.js +1 -0
  282. package/app/components/full-calendar.js +1 -0
  283. package/app/components/full-size.js +1 -0
  284. package/app/components/global-search.js +1 -0
  285. package/app/components/horizontal-route.js +1 -0
  286. package/app/components/integrated-order-details.js +1 -0
  287. package/app/components/leaflet-draw-control.js +1 -0
  288. package/app/components/leaflet-rotated-marker.js +1 -0
  289. package/app/components/live-map.js +1 -0
  290. package/app/components/map-container/toolbar/zones-panel.js +1 -0
  291. package/app/components/map-container/toolbar-container.js +1 -0
  292. package/app/components/map-container/toolbar.js +1 -0
  293. package/app/components/map-container/topbar.js +1 -0
  294. package/app/components/map-container/view-switch.js +1 -0
  295. package/app/components/map-container.js +1 -0
  296. package/app/components/modals/assign-driver.js +1 -0
  297. package/app/components/modals/clone-config-form.js +1 -0
  298. package/app/components/modals/contact-details.js +1 -0
  299. package/app/components/modals/contact-form.js +1 -0
  300. package/app/components/modals/driver-assign-order.js +1 -0
  301. package/app/components/modals/driver-assign-vehicle.js +1 -0
  302. package/app/components/modals/driver-assign-vendor.js +1 -0
  303. package/app/components/modals/driver-details.js +1 -0
  304. package/app/components/modals/driver-form.js +1 -0
  305. package/app/components/modals/edit-meta-form.js +1 -0
  306. package/app/components/modals/entity-form.js +1 -0
  307. package/app/components/modals/entity-meta-field-prompt.js +1 -0
  308. package/app/components/modals/fleet-details.js +1 -0
  309. package/app/components/modals/fleet-form.js +1 -0
  310. package/app/components/modals/fuel-report-details.js +1 -0
  311. package/app/components/modals/fuel-report-form.js +1 -0
  312. package/app/components/modals/group-details.js +1 -0
  313. package/app/components/modals/group-form.js +1 -0
  314. package/app/components/modals/install-prompt.js +1 -0
  315. package/app/components/modals/map-field-form.js +1 -0
  316. package/app/components/modals/map-field-group-form.js +1 -0
  317. package/app/components/modals/map-layer-form.js +1 -0
  318. package/app/components/modals/meta-field-form.js +1 -0
  319. package/app/components/modals/meta-field-group-form.js +1 -0
  320. package/app/components/modals/new-order-config.js +1 -0
  321. package/app/components/modals/option-prompt.js +1 -0
  322. package/app/components/modals/order-assign-driver.js +1 -0
  323. package/app/components/modals/order-config-new-status.js +1 -0
  324. package/app/components/modals/order-event.js +1 -0
  325. package/app/components/modals/order-form.js +1 -0
  326. package/app/components/modals/order-import.js +1 -0
  327. package/app/components/modals/order-label.js +1 -0
  328. package/app/components/modals/order-meta.js +1 -0
  329. package/app/components/modals/order-new-activity.js +1 -0
  330. package/app/components/modals/order-route-form.js +1 -0
  331. package/app/components/modals/place-assign-vendor.js +1 -0
  332. package/app/components/modals/place-details.js +1 -0
  333. package/app/components/modals/place-form.js +1 -0
  334. package/app/components/modals/point-map.js +1 -0
  335. package/app/components/modals/policy-form.js +1 -0
  336. package/app/components/modals/resend-verification-email.js +1 -0
  337. package/app/components/modals/role-form.js +1 -0
  338. package/app/components/modals/select-payment-method.js +1 -0
  339. package/app/components/modals/service-area-form.js +1 -0
  340. package/app/components/modals/set-password.js +1 -0
  341. package/app/components/modals/uninstall-prompt.js +1 -0
  342. package/app/components/modals/user-form.js +1 -0
  343. package/app/components/modals/vehicle-details.js +1 -0
  344. package/app/components/modals/vehicle-form.js +1 -0
  345. package/app/components/modals/vendor-details.js +1 -0
  346. package/app/components/modals/vendor-form.js +1 -0
  347. package/app/components/modals/view-service-area.js +1 -0
  348. package/app/components/modals/view-zone.js +1 -0
  349. package/app/components/modals/zone-form.js +1 -0
  350. package/app/components/operations-pane/pane.js +1 -0
  351. package/app/components/order/header.js +1 -0
  352. package/app/components/order/place-card.js +1 -0
  353. package/app/components/order/schedule-card.js +1 -0
  354. package/app/components/order/sub-header/item.js +1 -0
  355. package/app/components/order/sub-header.js +1 -0
  356. package/app/components/order-config/activity-flow-editor.js +1 -0
  357. package/app/components/order-config/details-editor.js +1 -0
  358. package/app/components/order-config/entities-editor.js +1 -0
  359. package/app/components/order-config/fields-editor.js +1 -0
  360. package/app/components/order-config/selector.js +1 -0
  361. package/app/components/order-config.js +1 -0
  362. package/app/components/order-list-overlay/driver-panel-title.js +1 -0
  363. package/app/components/order-list-overlay/order.js +1 -0
  364. package/app/components/order-list-overlay.js +1 -0
  365. package/app/components/route-list.js +1 -0
  366. package/app/components/settings-window.js +1 -0
  367. package/app/components/split-grid.js +1 -0
  368. package/app/components/widget/issues.js +1 -0
  369. package/app/components/widget/key-metrics.js +1 -0
  370. package/app/components/widget/live-order-map.js +1 -0
  371. package/app/components/widget/recent-orders.js +1 -0
  372. package/app/components/widget/recommended-todo.js +1 -0
  373. package/app/components/widget/transaction-earnings.js +1 -0
  374. package/app/components/widget/transactions.js +1 -0
  375. package/app/components/widget/weekly-orders.js +1 -0
  376. package/app/controllers/application.js +1 -0
  377. package/app/controllers/management/contacts/index.js +1 -0
  378. package/app/controllers/management/drivers/index/details.js +1 -0
  379. package/app/controllers/management/drivers/index.js +1 -0
  380. package/app/controllers/management/fleets/index/details.js +1 -0
  381. package/app/controllers/management/fleets/index.js +1 -0
  382. package/app/controllers/management/fuel-reports/index.js +1 -0
  383. package/app/controllers/management/issues/index.js +1 -0
  384. package/app/controllers/management/places/index.js +1 -0
  385. package/app/controllers/management/vehicles/index.js +1 -0
  386. package/app/controllers/management/vendors/index/details/remarks.js +1 -0
  387. package/app/controllers/management/vendors/index/details.js +1 -0
  388. package/app/controllers/management/vendors/index.js +1 -0
  389. package/app/controllers/management.js +1 -0
  390. package/app/controllers/operations/orders/index/config/types.js +1 -0
  391. package/app/controllers/operations/orders/index/config.js +1 -0
  392. package/app/controllers/operations/orders/index/new.js +1 -0
  393. package/app/controllers/operations/orders/index/view.js +1 -0
  394. package/app/controllers/operations/scheduler/index.js +1 -0
  395. package/app/controllers/operations/service-rates/index/edit.js +1 -0
  396. package/app/controllers/operations/service-rates/index/new.js +1 -0
  397. package/app/controllers/operations/service-rates/index.js +1 -0
  398. package/app/controllers/operations/zones/index.js +1 -0
  399. package/app/helpers/avatar-url.js +1 -0
  400. package/app/helpers/extract-coordinates.js +1 -0
  401. package/app/helpers/feature-group.js +1 -0
  402. package/app/helpers/flow-raw-status.js +1 -0
  403. package/app/helpers/format-point.js +1 -0
  404. package/app/helpers/get-tip-amount.js +1 -0
  405. package/app/helpers/is-facilitator-supported-place.js +1 -0
  406. package/app/helpers/is-not-facilitator-supported-place.js +1 -0
  407. package/app/helpers/is-waypoint-record.js +1 -0
  408. package/app/helpers/point-coordinates.js +1 -0
  409. package/app/helpers/point-to-coordinates.js +1 -0
  410. package/app/helpers/service-name.js +1 -0
  411. package/app/helpers/waypoint-label.js +1 -0
  412. package/app/modifiers/translate-x.js +1 -0
  413. package/app/routes/home.js +1 -0
  414. package/app/routes/management/fleets/index/details.js +1 -0
  415. package/app/routes/operations/orders/index/config/types.js +1 -0
  416. package/app/routes/operations/orders/index/config.js +1 -0
  417. package/app/routes/operations/orders/index/new.js +1 -0
  418. package/app/routes/operations/orders/index/view.js +1 -0
  419. package/app/routes/operations/scheduler/index.js +1 -0
  420. package/app/routes/operations/scheduler.js +1 -0
  421. package/app/routes/operations/service-rates/index/edit.js +1 -0
  422. package/app/routes/operations/service-rates/index/new.js +1 -0
  423. package/app/services/map-manager.js +1 -0
  424. package/app/services/service-areas.js +1 -0
  425. package/app/templates/home.js +1 -0
  426. package/app/templates/management/fleets/index/details.js +1 -0
  427. package/app/templates/operations/orders/index/config/types.js +1 -0
  428. package/app/templates/operations/orders/index/config.js +1 -0
  429. package/app/templates/operations/orders/index/new.js +1 -0
  430. package/app/templates/operations/orders/index/view.js +1 -0
  431. package/app/templates/operations/scheduler/index.js +1 -0
  432. package/app/templates/operations/scheduler.js +1 -0
  433. package/app/templates/operations/service-rates/index/edit.js +1 -0
  434. package/app/templates/operations/service-rates/index/new.js +1 -0
  435. package/app/utils/calculate-percentage.js +1 -0
  436. package/app/utils/extract-coordinates.js +1 -0
  437. package/app/utils/format-currency.js +1 -0
  438. package/app/utils/geojson/geo-json.js +1 -0
  439. package/app/utils/is-facilitator-supported-place.js +1 -0
  440. package/app/utils/is-latitude.js +1 -0
  441. package/app/utils/to-model.js +1 -0
  442. package/assets/images/drawing-controls-spritesheet-inverted.png +0 -0
  443. package/config/environment.js +25 -0
  444. package/index.js +73 -0
  445. package/package.json +132 -0
  446. package/pnpm-lock.yaml +12613 -0
@@ -0,0 +1,856 @@
1
+ import 'leaflet-contextmenu';
2
+ import Component from '@glimmer/component';
3
+ import { tracked } from '@glimmer/tracking';
4
+ import { inject as service } from '@ember/service';
5
+ import { action, computed, set } from '@ember/object';
6
+ import { isArray } from '@ember/array';
7
+ import { isEmpty } from '@ember/utils';
8
+ import { dasherize } from '@ember/string';
9
+ import { alias } from '@ember/object/computed';
10
+ import { guidFor } from '@ember/object/internals';
11
+ import { later } from '@ember/runloop';
12
+ import { allSettled } from 'rsvp';
13
+ import extractCoordinates from '@fleetbase/ember-core/utils/extract-coordinates';
14
+ import config from 'ember-get-config';
15
+
16
+ const L = window.L;
17
+ const DEFAULT_LATITUDE = 1.369;
18
+ const DEFAULT_LONGITUDE = 103.8864;
19
+
20
+ export default class LiveMapComponent extends Component {
21
+ @service store;
22
+ @service fetch;
23
+ @service currentUser;
24
+ @service notifications;
25
+ @service serviceAreas;
26
+ @service appCache;
27
+
28
+ @tracked routes = [];
29
+ @tracked drivers = [];
30
+ @tracked channels = [];
31
+ @tracked isLoading = true;
32
+ @tracked isReady = false;
33
+ @tracked isDriversVisible = true;
34
+ @tracked isRoutesVisible = true;
35
+ @tracked isDrawControlsVisible = false;
36
+ @tracked isCreatingServiceArea = false;
37
+ @tracked isCreatingZone = false;
38
+ @tracked currentContextMenuItems = [];
39
+ @tracked activeServiceAreas = [];
40
+ @tracked editableLayers = [];
41
+ @tracked leafletMap;
42
+ @tracked activeFeatureGroup;
43
+ @tracked drawFeatureGroup;
44
+ @tracked drawControl;
45
+ @tracked latitude = DEFAULT_LATITUDE;
46
+ @tracked longitude = DEFAULT_LONGITUDE;
47
+ @tracked mapId = guidFor(this);
48
+ @alias('currentUser.latitude') userLatitude;
49
+ @alias('currentUser.longitude') userLongitude;
50
+
51
+ @computed('args.zoom') get zoom() {
52
+ return this.args.zoom || 12;
53
+ }
54
+
55
+ @computed('args.{tileSourceUrl,darkMode}') get tileSourceUrl() {
56
+ const { darkMode, tileSourceUrl } = this.args;
57
+
58
+ if (darkMode === true) {
59
+ return 'https://{s}.tile.jawg.io/jawg-matrix/{z}/{x}/{y}{r}.png?access-token=';
60
+ }
61
+
62
+ return tileSourceUrl ?? 'https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png';
63
+ }
64
+
65
+ /**
66
+ * ----------------------------------------------------------------------------
67
+ * SETUP
68
+ * ----------------------------------------------------------------------------
69
+ *
70
+ * Functions for initialization and setup.
71
+ */
72
+
73
+ @action async setupLiveMap() {
74
+ if (this.appCache.has(['map_latitude', 'map_longitude'])) {
75
+ this.latitude = this.appCache.get('map_latitude');
76
+ this.longitude = this.appCache.get('map_longitude');
77
+ this.isReady = true;
78
+ }
79
+
80
+ const { latitude, longitude } = await this.getInitialCoordinates();
81
+
82
+ if (this.appCache.doesntHave(['map_latitude', 'map_longitude'])) {
83
+ this.appCache.set('map_latitude', latitude);
84
+ this.appCache.set('map_longitude', longitude);
85
+ }
86
+
87
+ this.latitude = latitude;
88
+ this.longitude = longitude;
89
+ this.routes = await this.fetchActiveRoutes();
90
+ this.drivers = await this.fetchActiveDrivers();
91
+ this.serviceAreaRecords = await this.fetchServiceAreas();
92
+ this.isReady = true;
93
+
94
+ this.watchDrivers(this.drivers);
95
+
96
+ if (typeof this.args.onReady === 'function') {
97
+ this.args.onReady(this);
98
+ }
99
+ }
100
+
101
+ @action setMapReference(event) {
102
+ const { target } = event;
103
+
104
+ // set liveMapComponent component to instance
105
+ set(event, 'target.liveMap', this);
106
+
107
+ // set map instance
108
+ this.leafletMap = target;
109
+
110
+ // setup context menu
111
+ this.setupContextMenu(target);
112
+
113
+ // hide draw controls by default
114
+ this.hideDrawControls();
115
+
116
+ // set instance to service areas service
117
+ this.serviceAreas.setMapInstance(target);
118
+
119
+ if (typeof this.args.onLoad === 'function') {
120
+ this.args.onLoad(...arguments);
121
+ }
122
+ }
123
+
124
+ @action setupContextMenu(map) {
125
+ if (!map?.contextmenu) {
126
+ return;
127
+ }
128
+
129
+ // reset items if any
130
+ if (typeof map?.contextmenu?.removeAllItems === 'function') {
131
+ map?.contextmenu?.removeAllItems();
132
+ }
133
+
134
+ const { contextmenu } = map;
135
+ const contextMenuItems = this.buildContextMenuItems();
136
+
137
+ contextMenuItems.forEach((options) => contextmenu.addItem(options));
138
+
139
+ if (contextmenu.enabled === true || contextmenu._enabled === true) {
140
+ return;
141
+ }
142
+
143
+ contextmenu.enable();
144
+ }
145
+
146
+ @action toggleDrawControlContextMenuItem() {
147
+ const index = this.currentContextMenuItems.findIndex((options) => options.text?.includes('draw controls'));
148
+ const options = this.currentContextMenuItems.objectAt(index);
149
+
150
+ set(options, 'text', this.isDrawControlsVisible ? `Hide draw controls...` : `Enable draw controls...`);
151
+
152
+ if (index > 0) {
153
+ this.leafletMap?.contextmenu?.removeItem(index);
154
+ this.leafletMap?.contextmenu?.insertItem(options, index);
155
+ }
156
+ }
157
+
158
+ @action removeServiceAreaFromContextMenu(serviceArea) {
159
+ const index = this.currentContextMenuItems.findIndex((options) => options.text?.includes(`Focus Service Area: ${serviceArea.name}`));
160
+
161
+ if (index > 0) {
162
+ this.leafletMap?.contextmenu?.removeItem(index);
163
+ }
164
+ }
165
+
166
+ @action rebuildContextMenu() {
167
+ const map = this.leafletMap;
168
+
169
+ if (map) {
170
+ this.setupContextMenu(map);
171
+ }
172
+ }
173
+
174
+ @action setFn(actionName, callback) {
175
+ this[actionName] = callback;
176
+ }
177
+
178
+ /**
179
+ * ----------------------------------------------------------------------------
180
+ * TRACKED LAYER UTILITIES
181
+ * ----------------------------------------------------------------------------
182
+ *
183
+ * Functions provide utility for managing tracked editable layers.
184
+ */
185
+
186
+ @action pushEditableLayer(layer) {
187
+ if (!this.editableLayers.includes(layer)) {
188
+ this.editableLayers.pushObject(layer);
189
+ }
190
+ }
191
+
192
+ @action removeEditableLayerByRecordId(record) {
193
+ const index = this.editableLayers.findIndex((layer) => layer.record_id === record?.id ?? record);
194
+ const layer = this.editableLayers.objectAt(index);
195
+
196
+ this.drawFeatureGroup?.addLayer(layer);
197
+ this.editableLayers.removeAt(index);
198
+ }
199
+
200
+ @action findEditableLayerByRecordId(record) {
201
+ return this.editableLayers.find((layer) => layer.record_id === record?.id ?? record);
202
+ }
203
+
204
+ @action peekRecordForLayer(layer) {
205
+ if (layer.record_id && layer.record_type) {
206
+ return this.store.peekRecord(dasherize(layer.record_type), layer.record_id);
207
+ }
208
+
209
+ return null;
210
+ }
211
+
212
+ /**
213
+ * ----------------------------------------------------------------------------
214
+ * LAYER EVENTS
215
+ * ----------------------------------------------------------------------------
216
+ *
217
+ * Functions that are only triggered from the `LiveMap` Leaflet Layer Component callbacks.
218
+ */
219
+
220
+ @action onAction(actionName, ...params) {
221
+ if (typeof this[actionName] === 'function') {
222
+ this[actionName](...params);
223
+ }
224
+
225
+ if (typeof this.args[actionName] === 'function') {
226
+ this.args[actionName](...params);
227
+ }
228
+ }
229
+
230
+ @action onDrawDrawstop(event, layer) {
231
+ this.serviceAreas.createGenericLayer(event, layer);
232
+ }
233
+
234
+ @action onDrawDeleted(event) {
235
+ /** @var {L.LayerGroup} layers */
236
+ const { layers } = event;
237
+
238
+ const records = layers.getLayers().map(this.peekRecordForLayer).filter(Boolean);
239
+ const requests = records.map((record) => {
240
+ this.blurServiceArea(record);
241
+ this.removeServiceAreaFromContextMenu(record);
242
+
243
+ return record.destroyRecord();
244
+ });
245
+
246
+ allSettled(requests).then(() => {
247
+ records.forEach((record) => this.serviceAreas.removeFromCache(record));
248
+ });
249
+ }
250
+
251
+ @action onDrawEdited(event) {
252
+ /** @var {L.LayerGroup} layers */
253
+ const { layers } = event;
254
+
255
+ const requests = layers.getLayers().map((layer) => {
256
+ const record = this.peekRecordForLayer(layer);
257
+
258
+ let border;
259
+
260
+ if (layer.record_type === 'zone') {
261
+ border = this.serviceAreas.layerToTerraformerPrimitive(layer);
262
+ } else {
263
+ border = this.serviceAreas.layerToTerraformerMultiPolygon(layer);
264
+ }
265
+
266
+ record.set('border', border);
267
+
268
+ return record.save();
269
+ });
270
+
271
+ allSettled(requests);
272
+ }
273
+
274
+ @action onServiceAreaLayerAdded(serviceArea, event) {
275
+ const { target } = event;
276
+
277
+ set(target, 'record_id', serviceArea.id);
278
+ set(target, 'record_type', 'service-area');
279
+
280
+ // add to draw feature group
281
+ this.drawFeatureGroup?.addLayer(target);
282
+
283
+ // this.flyToBoundsOnly(target);
284
+ this.createContextMenuForServiceArea(serviceArea, target);
285
+ this.pushEditableLayer(target);
286
+ }
287
+
288
+ @action onZoneLayerAdd(zone, event) {
289
+ const { target } = event;
290
+
291
+ set(target, 'record_id', zone.id);
292
+ set(target, 'record_type', 'zone');
293
+
294
+ // add to draw feature group
295
+ this.drawFeatureGroup?.addLayer(target);
296
+
297
+ this.createContextMenuForZone(zone, target);
298
+ this.pushEditableLayer(target);
299
+ }
300
+
301
+ @action onDrawFeatureGroupCreated(drawFeatureGroup) {
302
+ this.drawFeatureGroup = drawFeatureGroup;
303
+ }
304
+
305
+ @action onDriverAdded(driver, event) {
306
+ const { target } = event;
307
+
308
+ this.createContextMenuForDriver(driver, target);
309
+ }
310
+
311
+ @action onDrawControlCreated(drawControl) {
312
+ this.drawControl = drawControl;
313
+ }
314
+
315
+ /**
316
+ * ----------------------------------------------------------------------------
317
+ * LEAFLET UTILITIES
318
+ * ----------------------------------------------------------------------------
319
+ *
320
+ * Functions are used to help or utilize on Leaflet Layers/ Controls.
321
+ *
322
+ */
323
+
324
+ @action removeDrawingControl() {
325
+ if (isEmpty(this.drawControl)) {
326
+ return;
327
+ }
328
+
329
+ this.isDrawControlsVisible = false;
330
+ this.leafletMap?.removeControl(this.drawControl);
331
+ this.toggleDrawControlContextMenuItem();
332
+ }
333
+
334
+ // alias for `removeDrawingControl()`
335
+ @action hideDrawControls() {
336
+ this.removeDrawingControl();
337
+ }
338
+
339
+ @action enableDrawControls() {
340
+ this.isDrawControlsVisible = true;
341
+ this.leafletMap?.addControl(this.drawControl);
342
+ this.toggleDrawControlContextMenuItem();
343
+ }
344
+
345
+ @action focusLayerByRecord(record) {
346
+ const layer = this.findEditableLayerByRecordId(record);
347
+
348
+ if (layer) {
349
+ this.flyToBoundsOnly(layer);
350
+ }
351
+ }
352
+
353
+ @action flyToServiceArea(serviceArea) {
354
+ const layer = this.findEditableLayerByRecordId(serviceArea);
355
+
356
+ if (layer) {
357
+ this.flyToBoundsOnly(layer);
358
+ }
359
+ }
360
+
361
+ // alias for `flyToServiceArea()`
362
+ @action jumpToServiceArea(serviceArea) {
363
+ return this.flyToServiceArea(serviceArea);
364
+ }
365
+
366
+ @action focusServiceArea(serviceArea) {
367
+ this.activateServiceArea(serviceArea);
368
+
369
+ later(
370
+ this,
371
+ () => {
372
+ this.flyToServiceArea(serviceArea);
373
+ },
374
+ 100
375
+ );
376
+ }
377
+
378
+ @action blurAllServiceAreas(except = []) {
379
+ if (!isArray(except)) {
380
+ except = [];
381
+ }
382
+
383
+ // map except into ids only
384
+ except = except
385
+ .filter(Boolean)
386
+ .filter((record) => !record?.id)
387
+ .map((record) => record.id);
388
+
389
+ for (let i = 0; i < this.activeServiceAreas.length; i++) {
390
+ const serviceArea = this.activeServiceAreas.objectAt(i);
391
+
392
+ if (isArray(except) && except.includes(serviceArea.id)) {
393
+ continue;
394
+ }
395
+
396
+ this.blurServiceArea(serviceArea);
397
+ }
398
+
399
+ for (let i = 0; i < this.editableLayers.length; i++) {
400
+ const layer = this.editableLayers.objectAt(i);
401
+
402
+ if (isArray(except) && except.includes(layer.record_id)) {
403
+ continue;
404
+ }
405
+
406
+ this.editableLayers.removeObject(layer);
407
+ }
408
+ }
409
+
410
+ @action focusAllServiceAreas(except = []) {
411
+ if (!isArray(except)) {
412
+ except = [];
413
+ }
414
+
415
+ // map except into ids only
416
+ except = except
417
+ .filter(Boolean)
418
+ .filter((record) => !record?.id)
419
+ .map((record) => record.id);
420
+
421
+ for (let i = 0; i < this.serviceAreaRecords.length; i++) {
422
+ const serviceArea = this.serviceAreaRecords.objectAt(i);
423
+
424
+ if (isArray(except) && except.includes(serviceArea.id)) {
425
+ continue;
426
+ }
427
+
428
+ this.activateServiceArea(serviceArea);
429
+ }
430
+ }
431
+
432
+ @action blurServiceArea(serviceArea) {
433
+ if (this.activeServiceAreas.includes(serviceArea)) {
434
+ this.activeServiceAreas.removeObject(serviceArea);
435
+ }
436
+ }
437
+
438
+ @action activateServiceArea(serviceArea) {
439
+ if (!this.activeServiceAreas.includes(serviceArea)) {
440
+ this.activeServiceAreas.pushObject(serviceArea);
441
+ }
442
+ }
443
+
444
+ @action hideDrivers() {
445
+ this.isDriversVisible = false;
446
+ }
447
+
448
+ @action showDrivers() {
449
+ this.isDriversVisible = true;
450
+ }
451
+
452
+ @action toggleDrivers() {
453
+ this.isDriversVisible = !this.isDriversVisible;
454
+ }
455
+
456
+ @action hideRoutes() {
457
+ this.isRoutesVisible = false;
458
+ }
459
+
460
+ @action showRoutes() {
461
+ this.isRoutesVisible = true;
462
+ }
463
+
464
+ @action toggleRoutes() {
465
+ this.isRoutesVisible = !this.isRoutesVisible;
466
+ }
467
+
468
+ @action showCoordinates(event) {
469
+ this.notifications.info(event.latlng);
470
+ }
471
+
472
+ @action centerMap(event) {
473
+ this.leafletMap?.panTo(event.latlng);
474
+ }
475
+
476
+ @action zoomIn() {
477
+ this.leafletMap?.zoomIn();
478
+ }
479
+
480
+ @action zoomOut() {
481
+ this.leafletMap?.zoomOut();
482
+ }
483
+
484
+ @action setMaxBoundsFromLayer(layer) {
485
+ const bounds = layer?.getBounds();
486
+
487
+ this.leafletMap?.flyToBounds(bounds);
488
+ this.leafletMap?.setMaxBounds(bounds);
489
+ }
490
+
491
+ @action flyToBoundsOnly(layer) {
492
+ const bounds = layer?.getBounds();
493
+
494
+ this.leafletMap?.flyToBounds(bounds);
495
+ }
496
+
497
+ /**
498
+ * ----------------------------------------------------------------------------
499
+ * CONTEXT MENU INITIALIZERS
500
+ * ----------------------------------------------------------------------------
501
+ *
502
+ * Functions that are used to build context menu for layers and controls on the map.
503
+ *
504
+ */
505
+
506
+ @action buildContextMenuItems() {
507
+ const contextmenuItems = [
508
+ {
509
+ text: 'Show coordinates...',
510
+ callback: this.showCoordinates,
511
+ index: 0,
512
+ },
513
+ {
514
+ text: 'Center map here...',
515
+ callback: this.centerMap,
516
+ index: 1,
517
+ },
518
+ {
519
+ text: 'Zoom in...',
520
+ callback: this.zoomIn,
521
+ index: 2,
522
+ },
523
+ {
524
+ text: 'Zoom out...',
525
+ callback: this.zoomOut,
526
+ index: 3,
527
+ },
528
+ {
529
+ text: this.isDrawControlsVisible ? `Hide draw controls...` : `Enable draw controls...`,
530
+ callback: () => (this.isDrawControlsVisible ? this.hideDrawControls() : this.enableDrawControls()),
531
+ index: 4,
532
+ },
533
+ {
534
+ separator: true,
535
+ },
536
+ {
537
+ text: 'Create new Service Area...',
538
+ callback: this.serviceAreas.createServiceArea,
539
+ index: 5,
540
+ },
541
+ ];
542
+
543
+ // add service areas to context menu
544
+ const serviceAreas = this.serviceAreas.getFromCache() ?? [];
545
+
546
+ if (serviceAreas?.length > 0) {
547
+ contextmenuItems.pushObject({
548
+ separator: true,
549
+ });
550
+ }
551
+
552
+ // add to context menu
553
+ for (let i = 0; i < serviceAreas?.length; i++) {
554
+ const serviceArea = serviceAreas.objectAt(i);
555
+
556
+ contextmenuItems.pushObject({
557
+ text: `Focus Service Area: ${serviceArea.name}`,
558
+ callback: () => this.focusServiceArea(serviceArea),
559
+ index: (contextmenuItems.lastObject?.index ?? 0) + 1 + i,
560
+ });
561
+ }
562
+
563
+ this.currentContextMenuItems = contextmenuItems;
564
+
565
+ return contextmenuItems;
566
+ }
567
+
568
+ @action createContextMenuForDriver(driver, layer) {
569
+ const contextmenuItems = [
570
+ {
571
+ separator: true,
572
+ },
573
+ {
574
+ text: `View Driver: ${driver.name}`,
575
+ // callback: () => this.editServiceAreaDetails(serviceArea)
576
+ },
577
+ {
578
+ text: `Edit Driver: ${driver.name}`,
579
+ // callback: () => this.editServiceAreaDetails(serviceArea)
580
+ },
581
+ {
582
+ text: `Delete Driver: ${driver.name}`,
583
+ // callback: () => this.deleteServiceArea(serviceArea)
584
+ },
585
+ {
586
+ text: `Assign Order to Driver: ${driver.name}`,
587
+ // callback: () => this.deleteServiceArea(serviceArea)
588
+ },
589
+ {
590
+ text: `View Vehicle for: ${driver.name}`,
591
+ // callback: () => this.deleteServiceArea(serviceArea)
592
+ },
593
+ ];
594
+
595
+ if (typeof layer?.bindContextMenu === 'function') {
596
+ layer.bindContextMenu({
597
+ contextmenu: true,
598
+ contextmenuItems,
599
+ });
600
+ }
601
+ }
602
+
603
+ @action createContextMenuForZone(zone, layer) {
604
+ const contextmenuItems = [
605
+ {
606
+ separator: true,
607
+ },
608
+ {
609
+ text: `Edit Zone: ${zone.name}`,
610
+ callback: () => this.serviceAreas.editZone(zone),
611
+ },
612
+ {
613
+ text: `Delete Zone: ${zone.name}`,
614
+ callback: () =>
615
+ this.serviceAreas.deleteZone(zone, {
616
+ onFinish: () => {
617
+ this.removeEditableLayerByRecordId(zone);
618
+ },
619
+ }),
620
+ },
621
+ {
622
+ text: `Assign Fleet to Zone: (${zone.name})`,
623
+ callback: () => {},
624
+ },
625
+ ];
626
+
627
+ if (typeof layer?.bindContextMenu === 'function') {
628
+ layer.bindContextMenu({
629
+ contextmenu: true,
630
+ contextmenuItems,
631
+ });
632
+ }
633
+ }
634
+
635
+ @action createContextMenuForServiceArea(serviceArea, layer) {
636
+ const contextmenuItems = [
637
+ {
638
+ separator: true,
639
+ },
640
+ {
641
+ text: `Blur Service Area: ${serviceArea.name}`,
642
+ callback: () => this.blurServiceArea(serviceArea),
643
+ },
644
+ {
645
+ text: `Create Zone within: ${serviceArea.name}`,
646
+ callback: () => this.serviceAreas.createZone(serviceArea),
647
+ },
648
+ {
649
+ text: `Assign Fleet to Service Area: ${serviceArea.name}`,
650
+ callback: () => {},
651
+ },
652
+ {
653
+ text: `Edit Service Area: ${serviceArea.name}`,
654
+ callback: () => this.serviceAreas.editServiceAreaDetails(serviceArea),
655
+ },
656
+ {
657
+ text: `Delete Service Area: ${serviceArea.name}`,
658
+ callback: () =>
659
+ this.serviceAreas.deleteServiceArea(serviceArea, {
660
+ onFinish: () => {
661
+ this.rebuildContextMenu();
662
+ this.removeEditableLayerByRecordId(serviceArea);
663
+ },
664
+ }),
665
+ },
666
+ ];
667
+
668
+ if (typeof layer?.bindContextMenu === 'function') {
669
+ layer.bindContextMenu({
670
+ contextmenu: true,
671
+ contextmenuItems,
672
+ });
673
+ }
674
+ }
675
+
676
+ /**
677
+ * ----------------------------------------------------------------------------
678
+ * Async/Socket Functions
679
+ * ----------------------------------------------------------------------------
680
+ *
681
+ * Functions are used to fetch date or handle socket callbacks/initializations.
682
+ *
683
+ */
684
+
685
+ @action watchDrivers(drivers = []) {
686
+ // setup socket
687
+ const socket = socketClusterClient.create(config.socket);
688
+
689
+ // listen for stivers
690
+ for (let i = 0; i < drivers.length; i++) {
691
+ const driver = drivers.objectAt(i);
692
+ this.listenForDriver(driver, socket);
693
+ }
694
+ }
695
+
696
+ @action async listenForDriver(driver, socket) {
697
+ // listen on company channel
698
+ const channelId = `driver.${driver.uuid}`;
699
+ const channel = socket.subscribe(channelId);
700
+
701
+ // debug
702
+ // console.log(`socket subscribed to ${channelId}`);
703
+
704
+ // track channel
705
+ this.channels.pushObject(channel);
706
+
707
+ // listen to channel for events
708
+ await channel.listener('subscribe').once();
709
+
710
+ // get incoming data and console out
711
+ for await (let output of channel) {
712
+ const { event, data } = output;
713
+
714
+ if (event === 'driver.location_changed') {
715
+ driver.location = data.location;
716
+ driver.altitude = data.altitude;
717
+ driver.heading = data.heading;
718
+ driver.speed = data.speed;
719
+ }
720
+ }
721
+ }
722
+
723
+ @action closeChannels() {
724
+ for (let i = 0; i < this.channels.length; i++) {
725
+ const channel = this.channels.objectAt(i);
726
+
727
+ channel.close();
728
+ }
729
+ }
730
+
731
+ @action getInitialCoordinates() {
732
+ const initialCoordinates = {
733
+ latitude: DEFAULT_LATITUDE,
734
+ longitude: DEFAULT_LONGITUDE,
735
+ };
736
+
737
+ const getCoordinateFromNavigator = () => {
738
+ return new Promise((resolve) => {
739
+ // eslint-disable-next-line no-undef
740
+ if (window.navigator && window.navigator.geolocation) {
741
+ // eslint-disable-next-line no-undef
742
+ return navigator.geolocation.getCurrentPosition(
743
+ ({ coords }) => {
744
+ const { latitude, longitude } = coords;
745
+
746
+ initialCoordinates.latitude = latitude;
747
+ initialCoordinates.longitude = longitude;
748
+
749
+ resolve(initialCoordinates);
750
+ },
751
+ () => {
752
+ // if failed use default user lat/lng
753
+ initialCoordinates.latitude = this.getLocalLatitude();
754
+ initialCoordinates.longitude = this.getLocalLongitude();
755
+
756
+ resolve(initialCoordinates);
757
+ }
758
+ );
759
+ }
760
+ });
761
+ };
762
+
763
+ return new Promise((resolve) => {
764
+ // get location from active orders
765
+ this.fetch
766
+ .get('fleet-ops/live/coordinates')
767
+ .then((coordinates) => {
768
+ if (!coordinates) {
769
+ return getCoordinateFromNavigator().then((navigatorCoordinates) => {
770
+ resolve(navigatorCoordinates);
771
+ });
772
+ }
773
+
774
+ // from the `get-active-order-coordinates` the responded coordinates will always be [longitude, latitude]
775
+ // const [latitude, longitude] = extractCoordinates(coordinates.firstObject.coordinates);
776
+ const [longitude, latitude] = coordinates.filter((point) => point.cordinates[0] !== 0).firstObject?.coordinates;
777
+
778
+ initialCoordinates.latitude = latitude;
779
+ initialCoordinates.longitude = longitude;
780
+
781
+ resolve(initialCoordinates);
782
+ })
783
+ .catch(() => {
784
+ getCoordinateFromNavigator().then(resolve);
785
+ });
786
+ });
787
+ }
788
+
789
+ @action fetchActiveRoutes() {
790
+ this.isLoading = true;
791
+
792
+ return new Promise((resolve) => {
793
+ this.fetch.get('fleet-ops/live/routes').then((routes) => {
794
+ this.isLoading = false;
795
+
796
+ if (typeof this.args.onRoutesLoaded === 'function') {
797
+ this.args.onRoutesLoaded(routes);
798
+ }
799
+
800
+ resolve(routes);
801
+ });
802
+ });
803
+ }
804
+
805
+ @action fetchActiveDrivers() {
806
+ this.isLoading = true;
807
+
808
+ return new Promise((resolve) => {
809
+ this.fetch.get('fleet-ops/live/drivers', {}, { normalizeToEmberData: true, normalizeModelType: 'driver' }).then((drivers) => {
810
+ this.isLoading = false;
811
+
812
+ if (typeof this.args.onDriversLoaded === 'function') {
813
+ this.args.onDriversLoaded(drivers);
814
+ }
815
+
816
+ resolve(drivers);
817
+ });
818
+ });
819
+ }
820
+
821
+ @action fetchServiceAreas() {
822
+ this.isLoading = true;
823
+
824
+ return new Promise((resolve) => {
825
+ const cachedRecords = this.serviceAreas?.getFromCache('serviceAreas', 'service-area');
826
+
827
+ if (cachedRecords) {
828
+ resolve(cachedRecords);
829
+ }
830
+
831
+ return this.store
832
+ .query('service-area', { with: ['zones'] })
833
+ .then((serviceAreaRecords) => {
834
+ this.appCache.setEmberData('serviceAreas', serviceAreaRecords);
835
+ resolve(serviceAreaRecords);
836
+ })
837
+ .finally(() => {
838
+ this.isLoading = false;
839
+ });
840
+ });
841
+ }
842
+
843
+ @action getLocalLatitude() {
844
+ const whois = this.currentUser.getOption('whois');
845
+ const latitude = this.appCache.get('map_latitude');
846
+
847
+ return latitude || whois?.latitude || DEFAULT_LATITUDE;
848
+ }
849
+
850
+ @action getLocalLongitude() {
851
+ const whois = this.currentUser.getOption('whois');
852
+ const longitude = this.appCache.get('map_longitude');
853
+
854
+ return longitude || whois?.longitude || DEFAULT_LONGITUDE;
855
+ }
856
+ }