@fleetbase/fleetops-engine 0.6.8 → 0.6.10

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 (73) hide show
  1. package/addon/components/activity-event-selector.js +4 -0
  2. package/addon/components/admin/navigator-app.js +1 -1
  3. package/addon/components/custom-field-form-panel.js +1 -1
  4. package/addon/components/display-place.hbs +27 -3
  5. package/addon/components/driver-onboard-settings.js +1 -1
  6. package/addon/components/driver-panel/orders.js +1 -1
  7. package/addon/components/edit-order-route-panel.js +1 -1
  8. package/addon/components/entity-field-editing-settings.js +1 -1
  9. package/addon/components/fleet-driver-listing.js +1 -2
  10. package/addon/components/fleet-panel/driver-listing.js +1 -2
  11. package/addon/components/fleet-panel/vehicle-listing.js +1 -2
  12. package/addon/components/fleet-vehicle-listing.js +1 -2
  13. package/addon/components/layout/fleet-ops-sidebar/driver-listing.js +1 -1
  14. package/addon/components/layout/fleet-ops-sidebar/fleet-listing.js +1 -1
  15. package/addon/components/live-map.js +1 -1
  16. package/addon/components/map-container/toolbar/zones-panel.js +1 -1
  17. package/addon/components/order-config-manager/activity-flow.js +1 -1
  18. package/addon/components/order-config-manager/custom-fields.js +1 -1
  19. package/addon/components/order-config-manager/entities.js +1 -1
  20. package/addon/components/order-config-manager.js +1 -1
  21. package/addon/components/route-list.hbs +3 -3
  22. package/addon/components/vendor-panel/drivers.js +1 -2
  23. package/addon/components/widget/fleet-ops-key-metrics.js +1 -1
  24. package/addon/controllers/management/contacts/index.js +1 -2
  25. package/addon/controllers/management/drivers/index.js +1 -2
  26. package/addon/controllers/management/fleets/index.js +1 -2
  27. package/addon/controllers/management/fuel-reports/index.js +1 -2
  28. package/addon/controllers/management/issues/index.js +1 -2
  29. package/addon/controllers/management/vehicles/index.js +1 -2
  30. package/addon/controllers/management/vendors/index.js +1 -2
  31. package/addon/controllers/operations/orders/index/new.js +40 -48
  32. package/addon/controllers/operations/orders/index/view.js +1 -1
  33. package/addon/controllers/operations/orders/index.js +1 -6
  34. package/addon/controllers/operations/service-rates/index.js +1 -2
  35. package/addon/routes/operations/orders/index/view.js +18 -1
  36. package/addon/services/movement-tracker.js +1 -1
  37. package/addon/services/order-creation.js +1 -1
  38. package/addon/styles/fleetops-engine.css +7 -0
  39. package/addon/templates/operations/orders/index/new.hbs +2 -2
  40. package/addon/templates/operations/orders/index/view.hbs +5 -1
  41. package/addon/templates/operations/orders/index.hbs +6 -1
  42. package/addon/templates/settings/notifications.hbs +9 -1
  43. package/composer.json +1 -1
  44. package/extension.json +1 -1
  45. package/package.json +2 -3
  46. package/server/src/Console/Commands/TrackOrderDistanceAndTime.php +2 -2
  47. package/server/src/Events/OrderCanceled.php +6 -0
  48. package/server/src/Events/OrderCompleted.php +6 -0
  49. package/server/src/Events/OrderDispatched.php +6 -0
  50. package/server/src/Events/OrderFailed.php +6 -0
  51. package/server/src/Events/WaypointActivityChanged.php +119 -0
  52. package/server/src/Events/WaypointCompleted.php +119 -0
  53. package/server/src/Flow/Activity.php +28 -10
  54. package/server/src/Flow/Event.php +26 -2
  55. package/server/src/Http/Controllers/Api/v1/DriverController.php +19 -2
  56. package/server/src/Http/Controllers/Api/v1/OrderController.php +274 -164
  57. package/server/src/Http/Controllers/Internal/v1/OrderController.php +15 -8
  58. package/server/src/Http/Filter/OrderFilter.php +4 -4
  59. package/server/src/Http/Resources/v1/Payload.php +1 -1
  60. package/server/src/Listeners/HandleOrderCanceled.php +0 -10
  61. package/server/src/Listeners/NotifyOrderEvent.php +4 -4
  62. package/server/src/Models/OrderConfig.php +50 -35
  63. package/server/src/Models/Payload.php +26 -7
  64. package/server/src/Models/Waypoint.php +10 -0
  65. package/server/src/Notifications/OrderAssigned.php +3 -5
  66. package/server/src/Notifications/OrderCanceled.php +32 -12
  67. package/server/src/Notifications/OrderCompleted.php +31 -11
  68. package/server/src/Notifications/OrderDispatchFailed.php +3 -5
  69. package/server/src/Notifications/OrderDispatched.php +31 -11
  70. package/server/src/Notifications/OrderFailed.php +32 -12
  71. package/server/src/Notifications/OrderPing.php +2 -6
  72. package/server/src/Notifications/OrderSplit.php +1 -1
  73. package/server/src/Notifications/WaypointCompleted.php +157 -0
@@ -45,6 +45,10 @@ export default class ActivityEventSelectorComponent extends Component {
45
45
  name: 'order.canceled',
46
46
  description: 'Triggers when an order is canceled by a user, driver, or system process.',
47
47
  },
48
+ 'order.completed': {
49
+ name: 'order.completed',
50
+ description: 'Triggers when an order is completed by a driver, or system process.',
51
+ },
48
52
  };
49
53
 
50
54
  /**
@@ -1,7 +1,7 @@
1
1
  import Component from '@glimmer/component';
2
2
  import { tracked } from '@glimmer/tracking';
3
3
  import { inject as service } from '@ember/service';
4
- import { task } from 'ember-concurrency-decorators';
4
+ import { task } from 'ember-concurrency';
5
5
 
6
6
  export default class NavigatorAppControlsComponent extends Component {
7
7
  @service fetch;
@@ -3,7 +3,7 @@ import { tracked } from '@glimmer/tracking';
3
3
  import { inject as service } from '@ember/service';
4
4
  import { action } from '@ember/object';
5
5
  import { dasherize, camelize } from '@ember/string';
6
- import { task } from 'ember-concurrency-decorators';
6
+ import { task } from 'ember-concurrency';
7
7
  import isObject from '@fleetbase/ember-core/utils/is-object';
8
8
  import contextComponentCallback from '@fleetbase/ember-core/utils/context-component-callback';
9
9
  import applyContextComponentArguments from '@fleetbase/ember-core/utils/apply-context-component-arguments';
@@ -11,9 +11,33 @@
11
11
  </span>
12
12
  </div>
13
13
  {{else}}
14
- {{#if @eta}}
15
- <Badge @status="warning" @hideStatusDot={{true}} class="my-1"><span class="font-bold">ETA:</span> {{format-duration @eta}}</Badge>
16
- {{/if}}
14
+ <div class="flex flex-row item-center space-x-2 {{if (or place.status_code @eta) 'mb-2'}}">
15
+ {{#if place.status_code}}
16
+ <Badge @status={{place.status_code}} />
17
+ {{/if}}
18
+ {{#if @eta}}
19
+ <Badge @status="warning" @hideStatusDot={{true}}><span class="font-bold">ETA:</span> {{format-duration @eta}}</Badge>
20
+ {{/if}}
21
+ {{#if @waypointActions}}
22
+ <DropdownButton @iconClass="icon-text-height" @size="xs" @buttonClass="fleetops-btn-xxs" @icon="ellipsis-h" @iconPrefix="fas" @contentClass="dropdown-menu" as |dd|>
23
+ <div class="next-dd-menu mt-1 mx-0" aria-labelledby="user-menu">
24
+ <div class="px-1">
25
+ <div class="text-sm flex flex-row items-center px-3 py-1 rounded-md my-1 text-gray-300">
26
+ {{t "fleet-ops.operations.orders.index.view.waypoint-actions"}}
27
+ </div>
28
+ </div>
29
+ <div class="next-dd-menu-seperator"></div>
30
+ {{#each-in @waypointActions as |actionId action|}}
31
+ <div class="px-1">
32
+ <a href="javascript:;" class="next-dd-item" disabled={{cannot "fleet-ops view order"}} {{on "click" (fn action.fn place dd)}}>
33
+ {{action.label}}
34
+ </a>
35
+ </div>
36
+ {{/each-in}}
37
+ </div>
38
+ </DropdownButton>
39
+ {{/if}}
40
+ </div>
17
41
  <address class={{@addressClass}}>
18
42
  {{#if place.name}}
19
43
  {{place.name}}<br />
@@ -2,7 +2,7 @@ import Component from '@glimmer/component';
2
2
  import { tracked } from '@glimmer/tracking';
3
3
  import { inject as service } from '@ember/service';
4
4
  import { action } from '@ember/object';
5
- import { task } from 'ember-concurrency-decorators';
5
+ import { task } from 'ember-concurrency';
6
6
 
7
7
  export default class DriverOnboardSettingsComponent extends Component {
8
8
  @service fetch;
@@ -2,7 +2,7 @@ import Component from '@glimmer/component';
2
2
  import { tracked } from '@glimmer/tracking';
3
3
  import { inject as service } from '@ember/service';
4
4
  import { action, computed } from '@ember/object';
5
- import { task } from 'ember-concurrency-decorators';
5
+ import { task } from 'ember-concurrency';
6
6
 
7
7
  export default class CustomerOrderHistoryComponent extends Component {
8
8
  @service store;
@@ -3,7 +3,7 @@ import { tracked } from '@glimmer/tracking';
3
3
  import { action } from '@ember/object';
4
4
  import { inject as service } from '@ember/service';
5
5
  import { isArray } from '@ember/array';
6
- import { task } from 'ember-concurrency-decorators';
6
+ import { task } from 'ember-concurrency';
7
7
  import contextComponentCallback from '@fleetbase/ember-core/utils/context-component-callback';
8
8
  import applyContextComponentArguments from '@fleetbase/ember-core/utils/apply-context-component-arguments';
9
9
  import getRoutingHost from '@fleetbase/ember-core/utils/get-routing-host';
@@ -4,7 +4,7 @@ import { inject as service } from '@ember/service';
4
4
  import { action } from '@ember/object';
5
5
  import { isArray } from '@ember/array';
6
6
  import { isNone } from '@ember/utils';
7
- import { task } from 'ember-concurrency-decorators';
7
+ import { task } from 'ember-concurrency';
8
8
 
9
9
  export default class EntityFieldEditingSettingsComponent extends Component {
10
10
  @service notifications;
@@ -4,8 +4,7 @@ import { inject as service } from '@ember/service';
4
4
  import { action, computed } from '@ember/object';
5
5
  import { isArray } from '@ember/array';
6
6
  import { isBlank } from '@ember/utils';
7
- import { timeout } from 'ember-concurrency';
8
- import { task } from 'ember-concurrency-decorators';
7
+ import { timeout, task } from 'ember-concurrency';
9
8
 
10
9
  export default class FleetDriverListingComponent extends Component {
11
10
  @service store;
@@ -3,8 +3,7 @@ import { tracked } from '@glimmer/tracking';
3
3
  import { inject as service } from '@ember/service';
4
4
  import { isBlank } from '@ember/utils';
5
5
  import { action, set } from '@ember/object';
6
- import { timeout } from 'ember-concurrency';
7
- import { task } from 'ember-concurrency-decorators';
6
+ import { timeout, task } from 'ember-concurrency';
8
7
  import contextComponentCallback from '@fleetbase/ember-core/utils/context-component-callback';
9
8
 
10
9
  export default class FleetPanelDriverListingComponent extends Component {
@@ -3,8 +3,7 @@ import { tracked } from '@glimmer/tracking';
3
3
  import { inject as service } from '@ember/service';
4
4
  import { isBlank } from '@ember/utils';
5
5
  import { action, set } from '@ember/object';
6
- import { timeout } from 'ember-concurrency';
7
- import { task } from 'ember-concurrency-decorators';
6
+ import { timeout, task } from 'ember-concurrency';
8
7
  import contextComponentCallback from '@fleetbase/ember-core/utils/context-component-callback';
9
8
 
10
9
  export default class FleetPanelVehicleListingComponent extends Component {
@@ -4,8 +4,7 @@ import { inject as service } from '@ember/service';
4
4
  import { action, computed } from '@ember/object';
5
5
  import { isArray } from '@ember/array';
6
6
  import { isBlank } from '@ember/utils';
7
- import { timeout } from 'ember-concurrency';
8
- import { task } from 'ember-concurrency-decorators';
7
+ import { timeout, task } from 'ember-concurrency';
9
8
 
10
9
  export default class FleetVehicleListingComponent extends Component {
11
10
  @service store;
@@ -3,7 +3,7 @@ import { tracked } from '@glimmer/tracking';
3
3
  import { inject as service } from '@ember/service';
4
4
  import { action } from '@ember/object';
5
5
  import { later } from '@ember/runloop';
6
- import { task } from 'ember-concurrency-decorators';
6
+ import { task } from 'ember-concurrency';
7
7
 
8
8
  export default class LayoutFleetOpsSidebarDriverListingComponent extends Component {
9
9
  @service store;
@@ -3,7 +3,7 @@ import { tracked } from '@glimmer/tracking';
3
3
  import { inject as service } from '@ember/service';
4
4
  import { action } from '@ember/object';
5
5
  import { later } from '@ember/runloop';
6
- import { task } from 'ember-concurrency-decorators';
6
+ import { task } from 'ember-concurrency';
7
7
 
8
8
  export default class LayoutFleetOpsSidebarFleetListingComponent extends Component {
9
9
  @service store;
@@ -8,7 +8,7 @@ import { singularize } from 'ember-inflector';
8
8
  import { later } from '@ember/runloop';
9
9
  import { debug } from '@ember/debug';
10
10
  import { allSettled } from 'rsvp';
11
- import { task } from 'ember-concurrency-decorators';
11
+ import { task } from 'ember-concurrency';
12
12
  import { OSRMv1, Control as RoutingControl } from '@fleetbase/leaflet-routing-machine';
13
13
  import getRoutingHost from '@fleetbase/ember-core/utils/get-routing-host';
14
14
  import getWithDefault from '@fleetbase/ember-core/utils/get-with-default';
@@ -5,7 +5,7 @@ import { action } from '@ember/object';
5
5
  import { later } from '@ember/runloop';
6
6
  import { classify } from '@ember/string';
7
7
  import { calculateInPlacePosition } from 'ember-basic-dropdown/utils/calculate-position';
8
- import { task } from 'ember-concurrency-decorators';
8
+ import { task } from 'ember-concurrency';
9
9
 
10
10
  /**
11
11
  * @class MapContainerToolbarZonesPanelComponent
@@ -7,7 +7,7 @@ import { action } from '@ember/object';
7
7
  import { isArray } from '@ember/array';
8
8
  import { later } from '@ember/runloop';
9
9
  import { debug } from '@ember/debug';
10
- import { task } from 'ember-concurrency-decorators';
10
+ import { task } from 'ember-concurrency';
11
11
  import generateUUID from '@fleetbase/ember-core/utils/generate-uuid';
12
12
  import createFlowActivity from '../../utils/create-flow-activity';
13
13
  import contextComponentCallback from '@fleetbase/ember-core/utils/context-component-callback';
@@ -4,7 +4,7 @@ import { inject as service } from '@ember/service';
4
4
  import { action } from '@ember/object';
5
5
  import { isArray } from '@ember/array';
6
6
  import { later } from '@ember/runloop';
7
- import { task } from 'ember-concurrency-decorators';
7
+ import { task } from 'ember-concurrency';
8
8
  import isObject from '@fleetbase/ember-core/utils/is-object';
9
9
  import contextComponentCallback from '@fleetbase/ember-core/utils/context-component-callback';
10
10
 
@@ -4,7 +4,7 @@ import { inject as service } from '@ember/service';
4
4
  import { action } from '@ember/object';
5
5
  import { isArray } from '@ember/array';
6
6
  import { later } from '@ember/runloop';
7
- import { task } from 'ember-concurrency-decorators';
7
+ import { task } from 'ember-concurrency';
8
8
  import getWithDefault from '@fleetbase/ember-core/utils/get-with-default';
9
9
  import ObjectProxy from '@ember/object/proxy';
10
10
  import createCustomEntity from '../../utils/create-custom-entity';
@@ -6,7 +6,7 @@ import { inject as service } from '@ember/service';
6
6
  import { action } from '@ember/object';
7
7
  import { isArray } from '@ember/array';
8
8
  import { dasherize } from '@ember/string';
9
- import { task } from 'ember-concurrency-decorators';
9
+ import { task } from 'ember-concurrency';
10
10
  import isModel from '@fleetbase/ember-core/utils/is-model';
11
11
  import getModelName from '@fleetbase/ember-core/utils/get-model-name';
12
12
  import contextComponentCallback from '@fleetbase/ember-core/utils/context-component-callback';
@@ -6,7 +6,7 @@
6
6
  <div class="index-count">1</div>
7
7
  </div>
8
8
  <div class="order-route-location {{@routeLocationClass}} dark:text-gray-100">
9
- <DisplayPlace @place={{@order.payload.firstWaypoint}} @eta={{get @eta @order.payload.firstWaypoint.id}} />
9
+ <DisplayPlace @place={{@order.payload.firstWaypoint}} @eta={{get @eta @order.payload.firstWaypoint.id}} @waypointActions={{@waypointActions}} />
10
10
  </div>
11
11
  </div>
12
12
  {{/if}}
@@ -28,7 +28,7 @@
28
28
  <div class="index-count">{{add index 2}}</div>
29
29
  </div>
30
30
  <div class="order-route-location {{@routeLocationClass}} dark:text-gray-100">
31
- <DisplayPlace @place={{waypoint}} @eta={{get @eta waypoint.id}} />
31
+ <DisplayPlace @place={{waypoint}} @eta={{get @eta waypoint.id}} @waypointActions={{@waypointActions}} />
32
32
  </div>
33
33
  </div>
34
34
  {{/each}}
@@ -41,7 +41,7 @@
41
41
  <div class="index-count">{{add @order.payload.middleWaypoints.length 2}}</div>
42
42
  </div>
43
43
  <div class="order-route-location {{@routeLocationClass}} dark:text-gray-100">
44
- <DisplayPlace @place={{@order.payload.lastWaypoint}} @eta={{get @eta @order.payload.lastWaypoint.id}} />
44
+ <DisplayPlace @place={{@order.payload.lastWaypoint}} @eta={{get @eta @order.payload.lastWaypoint.id}} @waypointActions={{@waypointActions}} />
45
45
  </div>
46
46
  </div>
47
47
  {{/if}}
@@ -3,8 +3,7 @@ import { tracked } from '@glimmer/tracking';
3
3
  import { inject as service } from '@ember/service';
4
4
  import { isBlank } from '@ember/utils';
5
5
  import { action, set } from '@ember/object';
6
- import { timeout } from 'ember-concurrency';
7
- import { task } from 'ember-concurrency-decorators';
6
+ import { timeout, task } from 'ember-concurrency';
8
7
  import contextComponentCallback from '@fleetbase/ember-core/utils/context-component-callback';
9
8
 
10
9
  export default class VendorPanelDriversComponent extends Component {
@@ -1,7 +1,7 @@
1
1
  import Component from '@glimmer/component';
2
2
  import { tracked } from '@glimmer/tracking';
3
3
  import { inject as service } from '@ember/service';
4
- import { task } from 'ember-concurrency-decorators';
4
+ import { task } from 'ember-concurrency';
5
5
 
6
6
  export default class WidgetFleetOpsKeyMetricsComponent extends Component {
7
7
  /**
@@ -3,8 +3,7 @@ import { inject as service } from '@ember/service';
3
3
  import { tracked } from '@glimmer/tracking';
4
4
  import { action } from '@ember/object';
5
5
  import { isBlank } from '@ember/utils';
6
- import { timeout } from 'ember-concurrency';
7
- import { task } from 'ember-concurrency-decorators';
6
+ import { timeout, task } from 'ember-concurrency';
8
7
 
9
8
  export default class ManagementContactsIndexController extends BaseController {
10
9
  @service store;
@@ -4,8 +4,7 @@ import { tracked } from '@glimmer/tracking';
4
4
  import { action } from '@ember/object';
5
5
  import { isBlank } from '@ember/utils';
6
6
  import { equal } from '@ember/object/computed';
7
- import { timeout } from 'ember-concurrency';
8
- import { task } from 'ember-concurrency-decorators';
7
+ import { timeout, task } from 'ember-concurrency';
9
8
 
10
9
  export default class ManagementDriversIndexController extends BaseController {
11
10
  @service notifications;
@@ -3,8 +3,7 @@ import { inject as service } from '@ember/service';
3
3
  import { tracked } from '@glimmer/tracking';
4
4
  import { action } from '@ember/object';
5
5
  import { isBlank } from '@ember/utils';
6
- import { timeout } from 'ember-concurrency';
7
- import { task } from 'ember-concurrency-decorators';
6
+ import { timeout, task } from 'ember-concurrency';
8
7
 
9
8
  export default class ManagementFleetsIndexController extends BaseController {
10
9
  @service notifications;
@@ -3,8 +3,7 @@ import { inject as service } from '@ember/service';
3
3
  import { tracked } from '@glimmer/tracking';
4
4
  import { action } from '@ember/object';
5
5
  import { isBlank } from '@ember/utils';
6
- import { timeout } from 'ember-concurrency';
7
- import { task } from 'ember-concurrency-decorators';
6
+ import { timeout, task } from 'ember-concurrency';
8
7
 
9
8
  export default class ManagementFuelReportsIndexController extends BaseController {
10
9
  @service notifications;
@@ -3,8 +3,7 @@ import { inject as service } from '@ember/service';
3
3
  import { tracked } from '@glimmer/tracking';
4
4
  import { action } from '@ember/object';
5
5
  import { isBlank } from '@ember/object';
6
- import { timeout } from 'ember-concurrency';
7
- import { task } from 'ember-concurrency-decorators';
6
+ import { timeout, task } from 'ember-concurrency';
8
7
  import getIssueTypes from '../../../utils/get-issue-types';
9
8
  import getIssueCategories from '../../../utils/get-issue-categories';
10
9
 
@@ -3,8 +3,7 @@ import { inject as service } from '@ember/service';
3
3
  import { tracked } from '@glimmer/tracking';
4
4
  import { action } from '@ember/object';
5
5
  import { isBlank } from '@ember/utils';
6
- import { timeout } from 'ember-concurrency';
7
- import { task } from 'ember-concurrency-decorators';
6
+ import { timeout, task } from 'ember-concurrency';
8
7
 
9
8
  export default class ManagementVehiclesIndexController extends BaseController {
10
9
  @service contextPanel;
@@ -3,8 +3,7 @@ import { inject as service } from '@ember/service';
3
3
  import { tracked } from '@glimmer/tracking';
4
4
  import { action } from '@ember/object';
5
5
  import { isBlank } from '@ember/utils';
6
- import { timeout } from 'ember-concurrency';
7
- import { task } from 'ember-concurrency-decorators';
6
+ import { timeout, task } from 'ember-concurrency';
8
7
  import getVendorStatusOptions from '../../../utils/get-vendor-status-options';
9
8
 
10
9
  export default class ManagementVendorsIndexController extends BaseController {
@@ -8,11 +8,10 @@ import { isArray } from '@ember/array';
8
8
  import { isBlank } from '@ember/utils';
9
9
  import { dasherize } from '@ember/string';
10
10
  import { next } from '@ember/runloop';
11
- import { task } from 'ember-concurrency-decorators';
11
+ import { task } from 'ember-concurrency';
12
12
  import { OSRMv1, Control as RoutingControl } from '@fleetbase/leaflet-routing-machine';
13
13
  import { debug } from '@ember/debug';
14
14
  import polyline from '@fleetbase/ember-core/utils/polyline';
15
- import findClosestWaypoint from '@fleetbase/ember-core/utils/find-closest-waypoint';
16
15
  import isNotEmpty from '@fleetbase/ember-core/utils/is-not-empty';
17
16
  import getRoutingHost from '@fleetbase/ember-core/utils/get-routing-host';
18
17
  import getWithDefault from '@fleetbase/ember-core/utils/get-with-default';
@@ -939,66 +938,59 @@ export default class OperationsOrdersIndexNewController extends BaseController {
939
938
  @task *optimizeRoute() {
940
939
  this.isOptimizingRoute = true;
941
940
 
941
+ // Build the coordinate list we’ll send to OSRM
942
942
  const driverAssigned = this.order.driver_assigned;
943
- const driverPosition = driverAssigned ? driverAssigned.location.coordinates : null;
944
- const leafletMap = this.leafletMap;
943
+ const driverPosition = driverAssigned?.location?.coordinates; // [lon,lat] | undefined
944
+ const originalCoords = this.getCoordinatesFromPayload(); // [[lon,lat], …]
945
+ const coordinates = driverPosition ? [driverPosition, ...originalCoords] : [...originalCoords];
946
+ const hasDriverStart = Boolean(driverPosition);
947
+ const source = hasDriverStart ? 'first' : 'any';
948
+ const destination = 'any';
949
+ const roundtrip = false; // don’t loop back
945
950
  const routingHost = getRoutingHost(this.payload, this.waypoints);
946
951
 
947
- let originalCoordinates = this.getCoordinatesFromPayload();
948
- let coordinates = [...originalCoordinates]; // clone
949
-
950
- let source = 'any';
951
- let destination = 'any';
952
- let hasDriverStart = false;
953
-
954
- // Inject driver location as starting point if available
955
- if (driverPosition && Array.isArray(driverPosition) && driverPosition.length === 2) {
956
- coordinates.unshift([driverPosition[0], driverPosition[1]]);
957
- source = 'first';
958
- hasDriverStart = true;
959
- }
960
-
952
+ // Call the OSRM /trip service
961
953
  try {
962
- const response = yield this.fetch.routing(coordinates, { source, destination, annotations: true }, { host: routingHost });
954
+ const response = yield this.fetch.routing(coordinates, { source, destination, roundtrip, annotations: true }, { host: routingHost });
963
955
 
964
- if (response?.code === 'Ok') {
965
- this.removeRoutingControlPreview();
966
- this.removeOptimizedRoute(leafletMap);
967
- this.clearLayers();
956
+ if (response?.code !== 'Ok') {
957
+ throw new Error(`OSRM error: ${response?.code}`);
958
+ }
968
959
 
969
- const trip = response.trips?.firstObject;
970
- const route = polyline.decode(trip.geometry);
971
- const responseWaypoints = response.waypoints || [];
960
+ // Pair each OSRM waypoint with its Waypoint model
961
+ const modelsByInputIndex = hasDriverStart ? [null, ...this.waypoints] : this.waypoints;
972
962
 
973
- let sortedWaypoints = [];
963
+ const pairs = response.waypoints.map((wp, idx) => ({
964
+ model: modelsByInputIndex[idx], // Ember model or null (driver)
965
+ wp,
966
+ }));
974
967
 
975
- for (let i = 0; i < responseWaypoints.length; i++) {
976
- // Skip driver position (first coordinate) if it was included
977
- if (hasDriverStart && i === 0) {
978
- continue;
979
- }
968
+ // Drop the driver start if present
969
+ const payloadPairs = hasDriverStart ? pairs.slice(1) : pairs;
980
970
 
981
- const wp = responseWaypoints[i];
982
- const lat = wp.location[1];
983
- const lng = wp.location[0];
971
+ // Sort by the optimised order
972
+ payloadPairs.sort((a, b) => a.wp.waypoint_index - b.wp.waypoint_index);
984
973
 
985
- const model = findClosestWaypoint(lat, lng, this.waypoints);
974
+ // Extract the Ember models (null-safe)
975
+ const sortedWaypoints = payloadPairs.map((p) => p.model).filter(Boolean);
986
976
 
987
- if (model) {
988
- sortedWaypoints.pushObject(model);
989
- }
990
- }
977
+ // Update map layers & UI
978
+ this.removeRoutingControlPreview();
979
+ this.removeOptimizedRoute(this.leafletMap);
980
+ this.clearLayers();
991
981
 
992
- this.waypoints = sortedWaypoints;
993
- this.setOptimizedRoute(route, trip, responseWaypoints);
994
- this.previewDraftOrderRoute(this.payload, this.waypoints, this.isMultipleDropoffOrder);
995
- this.updatePayloadCoordinates();
982
+ const trip = response.trips?.[0];
983
+ const route = polyline.decode(trip.geometry); // [[lat,lon], …]
996
984
 
997
- this.order.set('is_route_optimized', true);
985
+ this.waypoints = sortedWaypoints;
986
+ this.setOptimizedRoute(route, trip, response.waypoints);
987
+ this.previewDraftOrderRoute(this.payload, this.waypoints, this.isMultipleDropoffOrder);
988
+ this.updatePayloadCoordinates();
998
989
 
999
- if (this.isUsingIntegratedVendor) {
1000
- this.getQuotes();
1001
- }
990
+ this.order.set('is_route_optimized', true);
991
+
992
+ if (this.isUsingIntegratedVendor) {
993
+ this.getQuotes();
1002
994
  }
1003
995
  } catch (err) {
1004
996
  debug('Error optimizing route', err);
@@ -5,7 +5,7 @@ import { tracked } from '@glimmer/tracking';
5
5
  import { action, computed } from '@ember/object';
6
6
  import { later } from '@ember/runloop';
7
7
  import { not, notEmpty, alias } from '@ember/object/computed';
8
- import { task } from 'ember-concurrency-decorators';
8
+ import { task } from 'ember-concurrency';
9
9
  import { OSRMv1, Control as RoutingControl } from '@fleetbase/leaflet-routing-machine';
10
10
  import getRoutingHost from '@fleetbase/ember-core/utils/get-routing-host';
11
11
 
@@ -6,8 +6,7 @@ import { equal } from '@ember/object/computed';
6
6
  import { debug } from '@ember/debug';
7
7
  import { isArray } from '@ember/array';
8
8
  import { isBlank } from '@ember/utils';
9
- import { timeout } from 'ember-concurrency';
10
- import { task } from 'ember-concurrency-decorators';
9
+ import { timeout, task } from 'ember-concurrency';
11
10
 
12
11
  export default class OperationsOrdersIndexController extends BaseController {
13
12
  @service currentUser;
@@ -1047,7 +1046,6 @@ export default class OperationsOrdersIndexController extends BaseController {
1047
1046
  selected = selected.length > 0 ? selected : this.table.selectedRows;
1048
1047
 
1049
1048
  this.crud.bulkDelete(selected, {
1050
- modelNamePath: `public_id`,
1051
1049
  acceptButtonText: 'Delete Orders',
1052
1050
  resolveModelName: (model) => `${model.get('tracking_number.tracking_number')} - ${model.get('public_id')}`,
1053
1051
  onSuccess: async () => {
@@ -1075,7 +1073,6 @@ export default class OperationsOrdersIndexController extends BaseController {
1075
1073
  acceptButtonText: 'Cancel Orders',
1076
1074
  acceptButtonScheme: 'danger',
1077
1075
  acceptButtonIcon: 'ban',
1078
- modelNamePath: `public_id`,
1079
1076
  actionPath: `orders/bulk-cancel`,
1080
1077
  actionMethod: `PATCH`,
1081
1078
  resolveModelName: (model) => `${model.get('tracking_number.tracking_number')} - ${model.get('public_id')}`,
@@ -1109,7 +1106,6 @@ export default class OperationsOrdersIndexController extends BaseController {
1109
1106
  acceptButtonText: 'Dispatch Orders',
1110
1107
  acceptButtonScheme: 'magic',
1111
1108
  acceptButtonIcon: 'rocket',
1112
- modelNamePath: 'public_id',
1113
1109
  actionPath: 'orders/bulk-dispatch',
1114
1110
  actionMethod: 'POST',
1115
1111
  resolveModelName: (model) => `${model.get('tracking_number.tracking_number')} - ${model.get('public_id')}`,
@@ -1152,7 +1148,6 @@ export default class OperationsOrdersIndexController extends BaseController {
1152
1148
  acceptButtonScheme: 'magic',
1153
1149
  acceptButtonIcon: 'user-plus',
1154
1150
  acceptButtonDisabled: true,
1155
- modelNamePath: 'public_id',
1156
1151
  actionPath: 'orders/bulk-assign-driver',
1157
1152
  actionMethod: 'PATCH',
1158
1153
  driverAssigned: null,
@@ -3,8 +3,7 @@ import { inject as service } from '@ember/service';
3
3
  import { tracked } from '@glimmer/tracking';
4
4
  import { action } from '@ember/object';
5
5
  import { isBlank } from '@ember/utils';
6
- import { timeout } from 'ember-concurrency';
7
- import { task } from 'ember-concurrency-decorators';
6
+ import { timeout, task } from 'ember-concurrency';
8
7
 
9
8
  export default class OperationsServiceRatesIndexController extends BaseController {
10
9
  @service store;
@@ -1,6 +1,7 @@
1
1
  import Route from '@ember/routing/route';
2
2
  import { inject as service } from '@ember/service';
3
3
  import { action } from '@ember/object';
4
+ import { debug } from '@ember/debug';
4
5
 
5
6
  export default class OperationsOrdersIndexViewRoute extends Route {
6
7
  @service currentUser;
@@ -66,7 +67,23 @@ export default class OperationsOrdersIndexViewRoute extends Route {
66
67
  // Listen for channel subscription
67
68
  (async () => {
68
69
  for await (let output of channel) {
69
- this.refresh();
70
+ const { event, data } = output;
71
+
72
+ // debug output
73
+ debug(`Socket Event : ${event} : ${JSON.stringify(output)}`);
74
+
75
+ // Only reload if the order has a status change stemming from an updated event OR
76
+ // if a waypoint has been completed which will trigger `order.completed`
77
+ const statusChanged = event === 'order.updated' && data.status !== model.status;
78
+ const shouldReload = ['order.completed', 'waypoint.activity', 'order.created'].includes(event);
79
+ if (statusChanged || shouldReload) {
80
+ this.refresh();
81
+
82
+ // reload the controller stuff as well
83
+ if (this.controller) {
84
+ this.controller.loadOrderRelations.perform(model);
85
+ }
86
+ }
70
87
 
71
88
  if (typeof this.onOrderEvent === 'function') {
72
89
  this.onOrderEvent(output);
@@ -155,7 +155,7 @@ export default class MovementTrackerService extends Service {
155
155
 
156
156
  if (event === `${type}.location_changed` || event === `${type}.simulated_location_changed`) {
157
157
  eventBuffer.add(output);
158
- debug(`Incoming socket event added to buffer: ${event}`);
158
+ debug(`Socket Event : ${event} : Added to EventBuffer : ${JSON.stringify(output)}`);
159
159
  }
160
160
  }
161
161
  })();
@@ -6,7 +6,7 @@ import { tracked } from '@glimmer/tracking';
6
6
  // import { isBlank } from '@ember/utils';
7
7
  // import { dasherize } from '@ember/string';
8
8
  // import { later, next } from '@ember/runloop';
9
- // import { task } from 'ember-concurrency-decorators';
9
+ // import { task } from 'ember-concurrency';
10
10
  // import { OSRMv1, Control as RoutingControl } from '@fleetbase/leaflet-routing-machine';
11
11
  // import polyline from '@fleetbase/ember-core/utils/polyline';
12
12
  // import findClosestWaypoint from '@fleetbase/ember-core/utils/find-closest-waypoint';
@@ -1623,3 +1623,10 @@ body[data-theme='dark']
1623
1623
  .justify-end-i {
1624
1624
  justify-content: end !important;
1625
1625
  }
1626
+
1627
+ button.fleetops-btn-xxs.btn,
1628
+ button.fleetops-btn-xxs,
1629
+ .fleetops-btn-xxs {
1630
+ padding-top: 0.2rem !important;
1631
+ padding-bottom: 0.2rem !important;
1632
+ }