@fleetbase/fleetops-engine 0.4.3 → 0.4.5
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.
- package/addon/components/contact-form-panel.hbs +1 -0
- package/addon/components/driver-panel.hbs +1 -0
- package/addon/components/edit-order-route-panel.hbs +183 -0
- package/addon/components/edit-order-route-panel.js +265 -0
- package/addon/components/fleet-form-panel.hbs +1 -0
- package/addon/components/fleet-panel.hbs +1 -0
- package/addon/components/fleet-panel.js +3 -3
- package/addon/components/fuel-report-form-panel.hbs +1 -0
- package/addon/components/fuel-report-panel.hbs +1 -0
- package/addon/components/issue-form-panel.hbs +1 -0
- package/addon/components/issue-panel.hbs +1 -0
- package/addon/components/map-container/toolbar.hbs +2 -2
- package/addon/components/modals/order-route-form.hbs +1 -1
- package/addon/components/place-form-panel.hbs +1 -0
- package/addon/components/place-panel.hbs +1 -0
- package/addon/components/vehicle-form-panel.hbs +1 -0
- package/addon/components/vehicle-panel.hbs +1 -0
- package/addon/components/vendor-form-panel.hbs +1 -0
- package/addon/components/vendor-panel.hbs +1 -0
- package/addon/components/widget/fleet-ops-key-metrics.hbs +19 -0
- package/addon/components/widget/fleet-ops-key-metrics.js +85 -0
- package/addon/controllers/operations/orders/index/new.js +66 -22
- package/addon/controllers/operations/orders/index/view.js +131 -126
- package/addon/controllers/operations/orders/index.js +1 -1
- package/addon/engine.js +18 -12
- package/addon/routes/operations/orders/index/view.js +1 -1
- package/addon/services/context-panel.js +6 -0
- package/addon/styles/fleetops-engine.css +7 -2
- package/addon/templates/operations/orders/index/new.hbs +390 -58
- package/addon/templates/operations/orders/index/view.hbs +135 -105
- package/addon/templates/operations/service-rates/index/new.hbs +3 -1
- package/app/components/widget/{issues.js → fleet-ops-key-metrics.js} +1 -1
- package/composer.json +6 -6
- package/extension.json +1 -1
- package/package.json +5 -6
- package/server/src/Casts/MultiPolygon.php +3 -3
- package/server/src/Casts/Point.php +2 -2
- package/server/src/Casts/Polygon.php +3 -3
- package/server/src/Console/Commands/DispatchAdhocOrders.php +1 -1
- package/server/src/Events/DriverSimulatedLocationChanged.php +1 -1
- package/server/src/Flow/Activity.php +12 -0
- package/server/src/Flow/Config.php +7 -0
- package/server/src/Flow/Logic.php +7 -0
- package/server/src/Http/Controllers/Api/v1/DriverController.php +61 -21
- package/server/src/Http/Controllers/Api/v1/OrderController.php +5 -3
- package/server/src/Http/Controllers/Api/v1/PlaceController.php +1 -1
- package/server/src/Http/Controllers/Api/v1/ServiceAreaController.php +1 -1
- package/server/src/Http/Controllers/Api/v1/TrackingStatusController.php +1 -1
- package/server/src/Http/Controllers/Api/v1/ZoneController.php +1 -1
- package/server/src/Http/Controllers/Internal/v1/DriverController.php +17 -4
- package/server/src/Http/Controllers/Internal/v1/GeocoderController.php +2 -2
- package/server/src/Http/Controllers/Internal/v1/MetricsController.php +6 -50
- package/server/src/Http/Controllers/Internal/v1/OrderController.php +13 -2
- package/server/src/Http/Controllers/Internal/v1/PlaceController.php +1 -1
- package/server/src/Http/Filter/PlaceFilter.php +1 -1
- package/server/src/Http/Resources/v1/Driver.php +1 -1
- package/server/src/Http/Resources/v1/FuelReport.php +1 -1
- package/server/src/Http/Resources/v1/Issue.php +1 -1
- package/server/src/Http/Resources/v1/Order.php +3 -0
- package/server/src/Http/Resources/v1/Payload.php +1 -0
- package/server/src/Http/Resources/v1/Place.php +1 -1
- package/server/src/Http/Resources/v1/PurchaseRate.php +2 -1
- package/server/src/Http/Resources/v1/ServiceQuote.php +1 -0
- package/server/src/Http/Resources/v1/ServiceQuoteItem.php +29 -0
- package/server/src/Http/Resources/v1/TrackingStatus.php +1 -1
- package/server/src/Http/Resources/v1/Vehicle.php +1 -1
- package/server/src/Http/Resources/v1/VehicleWithoutDriver.php +1 -1
- package/server/src/Http/Resources/v1/Waypoint.php +2 -4
- package/server/src/Integrations/Lalamove/LalamoveDeliveryStop.php +2 -2
- package/server/src/Jobs/SimulateWaypointReached.php +2 -2
- package/server/src/Models/Contact.php +6 -18
- package/server/src/Models/Driver.php +8 -20
- package/server/src/Models/Fleet.php +6 -25
- package/server/src/Models/FuelReport.php +1 -1
- package/server/src/Models/Issue.php +1 -1
- package/server/src/Models/Order.php +31 -19
- package/server/src/Models/Payload.php +7 -7
- package/server/src/Models/Place.php +16 -16
- package/server/src/Models/Position.php +1 -1
- package/server/src/Models/ServiceArea.php +14 -14
- package/server/src/Models/TrackingNumber.php +1 -1
- package/server/src/Models/TrackingStatus.php +1 -1
- package/server/src/Models/Vehicle.php +7 -19
- package/server/src/Models/VehicleDeviceEvent.php +1 -1
- package/server/src/Models/Vendor.php +8 -25
- package/server/src/Models/Waypoint.php +6 -6
- package/server/src/Models/Zone.php +8 -8
- package/server/src/Observers/DriverObserver.php +7 -2
- package/server/src/Observers/TrackingNumberObserver.php +1 -1
- package/server/src/Rules/ResolvablePoint.php +1 -1
- package/server/src/Support/Encoding/Polyline.php +1 -1
- package/server/src/Support/OSRM.php +1 -1
- package/server/src/Support/Utils.php +60 -60
- package/server/src/Traits/HasTrackingNumber.php +3 -3
- package/server/src/routes.php +2 -4
- package/translations/en-us.yaml +10 -2
- package/addon/components/widget/fleet-ops-quickstart.hbs +0 -40
- package/addon/components/widget/fleet-ops-quickstart.js +0 -59
- package/addon/components/widget/issues.hbs +0 -1
- package/addon/components/widget/key-metrics.hbs +0 -121
- package/addon/components/widget/key-metrics.js +0 -46
- package/addon/components/widget/live-order-map.hbs +0 -59
- package/addon/components/widget/live-order-map.js +0 -11
- package/addon/components/widget/recent-orders.hbs +0 -35
- package/addon/components/widget/recent-orders.js +0 -24
- package/addon/components/widget/transaction-earnings.hbs +0 -1
- package/addon/components/widget/transactions.hbs +0 -36
- package/addon/components/widget/transactions.js +0 -29
- package/addon/components/widget/weekly-orders.hbs +0 -1
- package/addon/components/widget/weekly-orders.js +0 -3
- package/app/components/widget/key-metrics.js +0 -1
- package/app/components/widget/live-order-map.js +0 -1
- package/app/components/widget/recent-orders.js +0 -1
- package/app/components/widget/transaction-earnings.js +0 -1
- package/app/components/widget/transactions.js +0 -1
- package/app/components/widget/weekly-orders.js +0 -1
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
<Overlay
|
|
2
|
+
@onLoad={{this.setOverlayContext}}
|
|
3
|
+
@onOpen={{this.onOpen}}
|
|
4
|
+
@onClose={{this.onClose}}
|
|
5
|
+
@onToggle={{this.onToggle}}
|
|
6
|
+
@position="right"
|
|
7
|
+
@noBackdrop={{true}}
|
|
8
|
+
@fullHeight={{true}}
|
|
9
|
+
@isResizeble={{or this.isResizable @isResizable}}
|
|
10
|
+
@width={{or this.width @width "570px"}}
|
|
11
|
+
>
|
|
12
|
+
<Overlay::Header @title={{concat "Edit order " this.order.public_id " route"}}>
|
|
13
|
+
<Button @type="primary" @icon="check" @text="Save" @helpText="Save order route changes" @onClick={{this.onSave}} @wrapperClass="mr-2" />
|
|
14
|
+
<Button @type="default" @icon="times" @helpText={{t "fleet-ops.common.cancel"}} @onClick={{this.onPressCancel}} />
|
|
15
|
+
</Overlay::Header>
|
|
16
|
+
|
|
17
|
+
<Overlay::Body @increaseInnerBodyHeightBy={{1000}}>
|
|
18
|
+
<div class="p-4">
|
|
19
|
+
<div class="flex flex-row justify-between mb-6">
|
|
20
|
+
<div class="flex">
|
|
21
|
+
<Toggle @isToggled={{this.order.payload.isMultiDrop}} @onToggle={{this.toggleMultiDropOrder}} @label={{t "fleet-ops.component.modals.order-route-form.toggle"}} />
|
|
22
|
+
</div>
|
|
23
|
+
<div class="flex flex-1 justify-end space-x-2">
|
|
24
|
+
{{#if this.order.payload.isMultiDrop}}
|
|
25
|
+
{{!-- <Button @type="magic" @icon="magic" @text={{t "fleet-ops.component.modals.order-route-form.optimize"}} @size="sm" @onClick={{fn this.optimizeRoute}} @helpText={{t "fleet-ops.component.modals.order-route-form.optimize-text"}} @disabled={{lt this.order.payload.waypoints.length 3}} @isLoading={{this.isOptimizingRoute}} /> --}}
|
|
26
|
+
<Button
|
|
27
|
+
@icon="map-marked-alt"
|
|
28
|
+
@text={{t "fleet-ops.component.modals.order-route-form.add"}}
|
|
29
|
+
@size="sm"
|
|
30
|
+
@onClick={{this.addWaypoint}}
|
|
31
|
+
@helpText={{t "fleet-ops.component.modals.order-route-form.add-text"}}
|
|
32
|
+
/>
|
|
33
|
+
{{/if}}
|
|
34
|
+
</div>
|
|
35
|
+
</div>
|
|
36
|
+
|
|
37
|
+
{{#if this.order.payload.isMultiDrop}}
|
|
38
|
+
<DragSortList class="overflow-visible" @items={{this.order.payload.waypoints}} @dragEndAction={{this.sortWaypoints}} as |waypoint index|>
|
|
39
|
+
<div id={{concat "waypoint_" (add index 1)}} class="py-1 mb-3">
|
|
40
|
+
<div class="flex items-center justify-between">
|
|
41
|
+
<div class="flex items-center justify-between cursor-move">
|
|
42
|
+
<FaIcon @icon="grip-lines" @prefix="fas" class="mr-3 text-gray-100" />
|
|
43
|
+
<label class="waypoint-label dark:text-gray-100 text-sm">
|
|
44
|
+
{{waypoint-label (add index 1)}}
|
|
45
|
+
</label>
|
|
46
|
+
</div>
|
|
47
|
+
|
|
48
|
+
<div class="flex-1 px-4">
|
|
49
|
+
<ModelSelect
|
|
50
|
+
@modelName="place"
|
|
51
|
+
@selectedModel={{waypoint}}
|
|
52
|
+
@placeholder={{concat (t "fleet-ops.operations.orders.index.new.select-waypoint-placeholder") " " (add index 1)}}
|
|
53
|
+
@triggerClass="form-select form-input truncate max-w-300px"
|
|
54
|
+
@infiniteScroll={{false}}
|
|
55
|
+
@customSearchEndpoint="places/search"
|
|
56
|
+
@query={{hash geo=true latitude=this.latitude longitude=this.longitude}}
|
|
57
|
+
@renderInPlace={{true}}
|
|
58
|
+
@onChange={{fn this.setWaypointPlace index}}
|
|
59
|
+
as |model|
|
|
60
|
+
>
|
|
61
|
+
{{model.address}}
|
|
62
|
+
</ModelSelect>
|
|
63
|
+
|
|
64
|
+
{{#unless waypoint.isNew}}
|
|
65
|
+
{{#if waypoint.hasInvalidCoordinates}}
|
|
66
|
+
<div class="leading-5 text-sm text-red-400 mt-2">
|
|
67
|
+
<FaIcon @icon="exclamation-triangle" class="mr-1" />
|
|
68
|
+
{{t "fleet-ops.component.modals.order-route-form.invalid"}}
|
|
69
|
+
</div>
|
|
70
|
+
{{/if}}
|
|
71
|
+
{{/unless}}
|
|
72
|
+
</div>
|
|
73
|
+
|
|
74
|
+
<div class="flex items-center">
|
|
75
|
+
<Button class="mr-2" @icon="edit" @size="sm" @onClick={{fn this.editPlace waypoint}} />
|
|
76
|
+
<Button @type="danger" @icon="trash" @iconPrefix="fas" @size="sm" @onClick={{fn this.removeWaypoint waypoint}} />
|
|
77
|
+
</div>
|
|
78
|
+
</div>
|
|
79
|
+
</div>
|
|
80
|
+
</DragSortList>
|
|
81
|
+
{{else}}
|
|
82
|
+
<div class="grid grid-cols-1 md:grid-cols-2 gap-3 text-xs dark:text-gray-100">
|
|
83
|
+
<div class="input-group">
|
|
84
|
+
<div class="flex items-center justify-between">
|
|
85
|
+
<label>{{t "fleet-ops.component.modals.order-route-form.pickup"}}</label>
|
|
86
|
+
|
|
87
|
+
{{#if this.order.payload.pickup}}
|
|
88
|
+
<a href="javascript:;" {{on "click" (fn this.editPlace this.order.payload.pickup)}}>{{t "fleet-ops.component.modals.order-route-form.edit-address"}}</a>
|
|
89
|
+
{{/if}}
|
|
90
|
+
</div>
|
|
91
|
+
|
|
92
|
+
<ModelSelect
|
|
93
|
+
@modelName="place"
|
|
94
|
+
@selectedModel={{this.order.payload.pickup}}
|
|
95
|
+
@placeholder={{t "fleet-ops.component.modals.order-route-form.select-pickup"}}
|
|
96
|
+
@triggerClass="form-select form-input"
|
|
97
|
+
@infiniteScroll={{false}}
|
|
98
|
+
@customSearchEndpoint="places/search"
|
|
99
|
+
@query={{hash geo=true latitude=this.latitude longitude=this.longitude}}
|
|
100
|
+
@renderInPlace={{true}}
|
|
101
|
+
@onChange={{fn this.setPayloadPlace "pickup"}}
|
|
102
|
+
as |model|
|
|
103
|
+
>
|
|
104
|
+
{{model.address}}
|
|
105
|
+
</ModelSelect>
|
|
106
|
+
|
|
107
|
+
{{#if this.order.payload.pickup.hasInvalidCoordinates}}
|
|
108
|
+
<div class="leading-5 text-sm text-red-400 mt-2">
|
|
109
|
+
<FaIcon @icon="exclamation-triangle" class="mr-1" />
|
|
110
|
+
{{t "fleet-ops.component.modals.order-route-form.invalid"}}
|
|
111
|
+
</div>
|
|
112
|
+
{{/if}}
|
|
113
|
+
</div>
|
|
114
|
+
|
|
115
|
+
<div class="input-group">
|
|
116
|
+
<div class="flex items-center justify-between">
|
|
117
|
+
<label>{{t "fleet-ops.component.modals.order-route-form.dropoff"}}</label>
|
|
118
|
+
|
|
119
|
+
{{#if this.order.payload.dropoff}}
|
|
120
|
+
<a href="javascript:;" {{on "click" (fn this.editPlace this.order.payload.dropoff)}}>{{t "fleet-ops.component.modals.order-route-form.edit-address"}}</a>
|
|
121
|
+
{{/if}}
|
|
122
|
+
</div>
|
|
123
|
+
|
|
124
|
+
<ModelSelect
|
|
125
|
+
@modelName="place"
|
|
126
|
+
@selectedModel={{this.order.payload.dropoff}}
|
|
127
|
+
@placeholder={{t "fleet-ops.component.modals.order-route-form.select-dropoff"}}
|
|
128
|
+
@triggerClass="form-select form-input"
|
|
129
|
+
@infiniteScroll={{false}}
|
|
130
|
+
@customSearchEndpoint="places/search"
|
|
131
|
+
@query={{hash geo=true latitude=this.latitude longitude=this.longitude}}
|
|
132
|
+
@renderInPlace={{true}}
|
|
133
|
+
@onChange={{fn this.setPayloadPlace "dropoff"}}
|
|
134
|
+
as |model|
|
|
135
|
+
>
|
|
136
|
+
{{model.address}}
|
|
137
|
+
</ModelSelect>
|
|
138
|
+
|
|
139
|
+
{{#if this.order.payload.dropoff.hasInvalidCoordinates}}
|
|
140
|
+
<div class="leading-5 text-sm text-red-400 mt-2">
|
|
141
|
+
<FaIcon @icon="exclamation-triangle" class="mr-1" />
|
|
142
|
+
{{t "fleet-ops.component.modals.order-route-form.invalid"}}
|
|
143
|
+
</div>
|
|
144
|
+
{{/if}}
|
|
145
|
+
</div>
|
|
146
|
+
|
|
147
|
+
<div class="input-group">
|
|
148
|
+
<div class="flex items-center justify-between">
|
|
149
|
+
<label>{{t "fleet-ops.component.modals.order-route-form.return"}}</label>
|
|
150
|
+
|
|
151
|
+
{{#if this.order.payload.return}}
|
|
152
|
+
<a href="javascript:;" {{on "click" (fn this.editPlace this.order.payload.return)}}>{{t "fleet-ops.component.modals.order-route-form.edit-address"}}</a>
|
|
153
|
+
{{/if}}
|
|
154
|
+
</div>
|
|
155
|
+
|
|
156
|
+
<ModelSelect
|
|
157
|
+
@modelName="place"
|
|
158
|
+
@selectedModel={{this.order.payload.return}}
|
|
159
|
+
@placeholder={{t "fleet-ops.component.modals.order-route-form.select-return"}}
|
|
160
|
+
@triggerClass="form-select form-input"
|
|
161
|
+
@infiniteScroll={{false}}
|
|
162
|
+
@customSearchEndpoint="places/search"
|
|
163
|
+
@query={{hash geo=true latitude=this.latitude longitude=this.longitude}}
|
|
164
|
+
@renderInPlace={{true}}
|
|
165
|
+
@onChange={{fn this.setPayloadPlace "return"}}
|
|
166
|
+
as |model|
|
|
167
|
+
>
|
|
168
|
+
{{model.address}}
|
|
169
|
+
</ModelSelect>
|
|
170
|
+
|
|
171
|
+
{{#if this.order.payload.return.hasInvalidCoordinates}}
|
|
172
|
+
<div class="leading-5 text-sm text-red-400 mt-2">
|
|
173
|
+
<FaIcon @icon="exclamation-triangle" class="mr-1" />
|
|
174
|
+
{{t "fleet-ops.component.modals.order-route-form.invalid"}}
|
|
175
|
+
</div>
|
|
176
|
+
{{/if}}
|
|
177
|
+
</div>
|
|
178
|
+
</div>
|
|
179
|
+
{{/if}}
|
|
180
|
+
</div>
|
|
181
|
+
<Spacer @height="300px" />
|
|
182
|
+
</Overlay::Body>
|
|
183
|
+
</Overlay>
|
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
import Component from '@glimmer/component';
|
|
2
|
+
import { tracked } from '@glimmer/tracking';
|
|
3
|
+
import { action } from '@ember/object';
|
|
4
|
+
import { inject as service } from '@ember/service';
|
|
5
|
+
import { isArray } from '@ember/array';
|
|
6
|
+
import contextComponentCallback from '../utils/context-component-callback';
|
|
7
|
+
import applyContextComponentArguments from '../utils/apply-context-component-arguments';
|
|
8
|
+
import getRoutingHost from '@fleetbase/ember-core/utils/get-routing-host';
|
|
9
|
+
import Point from '@fleetbase/fleetops-data/utils/geojson/point';
|
|
10
|
+
import findClosestWaypoint from '@fleetbase/ember-core/utils/find-closest-waypoint';
|
|
11
|
+
|
|
12
|
+
export default class EditOrderRoutePanelComponent extends Component {
|
|
13
|
+
/**
|
|
14
|
+
* Fetch service.
|
|
15
|
+
*
|
|
16
|
+
* @type {Service}
|
|
17
|
+
*/
|
|
18
|
+
@service fetch;
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Ember data store service.
|
|
22
|
+
*
|
|
23
|
+
* @type {Service}
|
|
24
|
+
*/
|
|
25
|
+
@service store;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Service for managing routing within the host app.
|
|
29
|
+
*
|
|
30
|
+
* @type {Service}
|
|
31
|
+
*/
|
|
32
|
+
@service hostRouter;
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Service for managing the modals.
|
|
36
|
+
*
|
|
37
|
+
* @type {Service}
|
|
38
|
+
*/
|
|
39
|
+
@service modalsManager;
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Service for managing the context panel.
|
|
43
|
+
*
|
|
44
|
+
* @type {Service}
|
|
45
|
+
*/
|
|
46
|
+
@service contextPanel;
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Service for internationalization.
|
|
50
|
+
*
|
|
51
|
+
* @type {Service}
|
|
52
|
+
*/
|
|
53
|
+
@service intl;
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Service for notifications
|
|
57
|
+
*
|
|
58
|
+
* @type {Service}
|
|
59
|
+
*/
|
|
60
|
+
@service notifications;
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* The orderwhich route is being edited.
|
|
64
|
+
*
|
|
65
|
+
* @type {OrderModel}
|
|
66
|
+
* @tracked
|
|
67
|
+
*/
|
|
68
|
+
@tracked order;
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Initializes the vehicle panel component.
|
|
72
|
+
*/
|
|
73
|
+
constructor() {
|
|
74
|
+
super(...arguments);
|
|
75
|
+
this.order = this.args.order;
|
|
76
|
+
applyContextComponentArguments(this);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Sets the overlay context.
|
|
81
|
+
*
|
|
82
|
+
* @action
|
|
83
|
+
* @param {OverlayContextObject} overlayContext
|
|
84
|
+
*/
|
|
85
|
+
@action setOverlayContext(overlayContext) {
|
|
86
|
+
this.context = overlayContext;
|
|
87
|
+
contextComponentCallback(this, 'onLoad', ...arguments);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Handles save action for the order route.
|
|
92
|
+
*
|
|
93
|
+
* @method
|
|
94
|
+
* @action
|
|
95
|
+
*/
|
|
96
|
+
@action onSave() {
|
|
97
|
+
const isActionOverrided = contextComponentCallback(this, 'onSave', this.order);
|
|
98
|
+
|
|
99
|
+
if (!isActionOverrided) {
|
|
100
|
+
return this.order
|
|
101
|
+
.save()
|
|
102
|
+
.then((order) => {
|
|
103
|
+
this.notifications.success(this.intl.t('fleet-ops.operations.orders.index.view.update-success', { orderId: order.public_id }));
|
|
104
|
+
contextComponentCallback(this, 'onAfterSave', order);
|
|
105
|
+
})
|
|
106
|
+
.catch((error) => {
|
|
107
|
+
this.notifications.serverError(error);
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Handles the cancel action.
|
|
114
|
+
*
|
|
115
|
+
* @method
|
|
116
|
+
* @action
|
|
117
|
+
* @returns {Boolean} Indicates whether the cancel action was overridden.
|
|
118
|
+
*/
|
|
119
|
+
@action onPressCancel() {
|
|
120
|
+
return contextComponentCallback(this, 'onPressCancel', this.order);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
@action async editPlace(place) {
|
|
124
|
+
await this.modalsManager.done();
|
|
125
|
+
|
|
126
|
+
this.contextPanel.focus(place, 'editing', {
|
|
127
|
+
args: {
|
|
128
|
+
onClose: () => {
|
|
129
|
+
this.editOrderRoute(this.order);
|
|
130
|
+
},
|
|
131
|
+
},
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
@action toggleMultiDropOrder(isMultiDrop) {
|
|
136
|
+
const { pickup, dropoff } = this.order.payload;
|
|
137
|
+
|
|
138
|
+
if (isMultiDrop) {
|
|
139
|
+
// if pickup move it to multipdrop
|
|
140
|
+
if (pickup) {
|
|
141
|
+
this.addWaypointFromExistingPlace(pickup);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// if pickup move it to multipdrop
|
|
145
|
+
if (dropoff) {
|
|
146
|
+
this.addWaypointFromExistingPlace(dropoff);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
this.order.payload.setProperties({
|
|
150
|
+
pickup_uuid: null,
|
|
151
|
+
dropoff_uuid: null,
|
|
152
|
+
});
|
|
153
|
+
} else {
|
|
154
|
+
const waypoint = this.store.createRecord('waypoint');
|
|
155
|
+
this.order.payload.waypoints.pushObject(waypoint);
|
|
156
|
+
|
|
157
|
+
this.order.payload.setProperties({
|
|
158
|
+
pickup_uuid: null,
|
|
159
|
+
dropoff_uuid: null,
|
|
160
|
+
pickup: null,
|
|
161
|
+
dropoff: null,
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
contextComponentCallback(this, 'onRouteChanged');
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
addWaypointFromExistingPlace(place) {
|
|
169
|
+
const waypoint = this.store.createRecord('waypoint', { place, location: place.location });
|
|
170
|
+
this.order.payload.waypoints.pushObject(waypoint);
|
|
171
|
+
|
|
172
|
+
// fire callback
|
|
173
|
+
contextComponentCallback(this, 'onWaypointAdded', waypoint);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
@action removeWaypoint(waypoint) {
|
|
177
|
+
this.order.payload.waypoints.removeObject(waypoint);
|
|
178
|
+
|
|
179
|
+
// fire callback
|
|
180
|
+
contextComponentCallback(this, 'onWaypointRemoved', waypoint);
|
|
181
|
+
contextComponentCallback(this, 'onRouteChanged');
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
@action addWaypoint() {
|
|
185
|
+
const location = new Point(0, 0);
|
|
186
|
+
const place = this.store.createRecord('place', { location });
|
|
187
|
+
const waypoint = this.store.createRecord('waypoint', { place, location });
|
|
188
|
+
|
|
189
|
+
this.order.payload.waypoints.pushObject(waypoint);
|
|
190
|
+
// fire callback
|
|
191
|
+
contextComponentCallback(this, 'onWaypointAdded', waypoint);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
@action setWaypointPlace(index, place) {
|
|
195
|
+
if (isArray(this.order.payload.waypoints) && !this.order.payload.waypoints.objectAt(index)) {
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
this.order.payload.waypoints.objectAt(index).setProperties({
|
|
200
|
+
name: place.name,
|
|
201
|
+
place_uuid: place.id,
|
|
202
|
+
location: place.location,
|
|
203
|
+
place,
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
// fire callback waypoint place selected
|
|
207
|
+
contextComponentCallback(this, 'onWaypointPlaceSelected', place);
|
|
208
|
+
contextComponentCallback(this, 'onRouteChanged');
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
@action setPayloadPlace(prop, place) {
|
|
212
|
+
this.order.payload.set(prop, place);
|
|
213
|
+
|
|
214
|
+
// fire callback
|
|
215
|
+
contextComponentCallback(this, 'onPlaceSelected', place);
|
|
216
|
+
contextComponentCallback(this, 'onRouteChanged');
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
@action async optimizeRoute() {
|
|
220
|
+
this.isOptimizingRoute = true;
|
|
221
|
+
|
|
222
|
+
const coordinates = this.order.payload.payloadCoordinates;
|
|
223
|
+
const routingHost = getRoutingHost(this.order.payload, this.order.payload.waypoints);
|
|
224
|
+
let sortedWaypoints = [];
|
|
225
|
+
|
|
226
|
+
const response = await this.fetch.routing(coordinates, { source: 'any', destination: 'any', annotations: true }, { host: routingHost }).catch(() => {
|
|
227
|
+
this.notifications.error(this.intl.t('fleet-ops.operations.orders.index.view.route-error'));
|
|
228
|
+
this.isOptimizingRoute = false;
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
if (response && response.code === 'Ok') {
|
|
232
|
+
if (response.waypoints && isArray(response.waypoints)) {
|
|
233
|
+
const responseWaypoints = response.waypoints.sortBy('waypoint_index');
|
|
234
|
+
|
|
235
|
+
for (let i = 0; i < responseWaypoints.length; i++) {
|
|
236
|
+
const optimizedWaypoint = responseWaypoints.objectAt(i);
|
|
237
|
+
const optimizedWaypointLongitude = optimizedWaypoint.location.firstObject;
|
|
238
|
+
const optimizedWaypointLatitude = optimizedWaypoint.location.lastObject;
|
|
239
|
+
const waypointModel = findClosestWaypoint(optimizedWaypointLatitude, optimizedWaypointLongitude, this.order.payload.waypoints);
|
|
240
|
+
|
|
241
|
+
sortedWaypoints.pushObject(waypointModel);
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
this.order.payload.waypoints = sortedWaypoints;
|
|
245
|
+
}
|
|
246
|
+
} else {
|
|
247
|
+
this.notifications.error(this.intl.t('fleet-ops.operations.orders.index.view.route-error'));
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
this.isOptimizingRoute = false;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
@action sortWaypoints({ sourceList, sourceIndex, targetList, targetIndex }) {
|
|
254
|
+
if (sourceList === targetList && sourceIndex === targetIndex) {
|
|
255
|
+
return;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
const item = sourceList.objectAt(sourceIndex);
|
|
259
|
+
|
|
260
|
+
sourceList.removeAt(sourceIndex);
|
|
261
|
+
targetList.insertAt(targetIndex, item);
|
|
262
|
+
|
|
263
|
+
contextComponentCallback(this, 'onRouteChanged');
|
|
264
|
+
}
|
|
265
|
+
}
|
|
@@ -61,12 +61,12 @@ export default class FleetPanelComponent extends Component {
|
|
|
61
61
|
@tracked tab;
|
|
62
62
|
|
|
63
63
|
/**
|
|
64
|
-
* The
|
|
64
|
+
* The fleet being displayed or edited.
|
|
65
65
|
*
|
|
66
|
-
* @type {
|
|
66
|
+
* @type {FleetModel}
|
|
67
67
|
* @tracked
|
|
68
68
|
*/
|
|
69
|
-
@tracked
|
|
69
|
+
@tracked fleet;
|
|
70
70
|
|
|
71
71
|
/**
|
|
72
72
|
* Returns the array of tabs available for the panel.
|
|
@@ -33,14 +33,14 @@
|
|
|
33
33
|
</div>
|
|
34
34
|
<FaIcon @icon="layer-group" />
|
|
35
35
|
<Attach::Tooltip @class="clean" @animation="scale" @placement="right">
|
|
36
|
-
<InputInfo @text={{t "fleet-ops.component.map-container.toolbar.view"}} @iconClass="hidden" class="py-1 px-2 bg-gray-900 -mt-1" />
|
|
36
|
+
<InputInfo @text={{t "fleet-ops.component.map-container.toolbar.view-order"}} @iconClass="hidden" class="py-1 px-2 bg-gray-900 -mt-1" />
|
|
37
37
|
</Attach::Tooltip>
|
|
38
38
|
</button>
|
|
39
39
|
<BasicDropdown id="map-toolbar-service-areas-button" @horizontalPosition="right" @calculatePosition={{this.calculatePosition}} @renderInPlace={{true}} as |dd|>
|
|
40
40
|
<dd.Trigger class="toolbar-button">
|
|
41
41
|
<FaIcon @icon="map-marked-alt" />
|
|
42
42
|
<Attach::Tooltip @class="clean" @animation="scale" @placement="right">
|
|
43
|
-
<InputInfo @text={{t "fleet-ops.component.map-container.toolbar.view"}} @iconClass="hidden" class="{{if dd.isOpen 'hidden'}} py-1 px-2 bg-gray-900 -mt-1" />
|
|
43
|
+
<InputInfo @text={{t "fleet-ops.component.map-container.toolbar.view-service-area"}} @iconClass="hidden" class="{{if dd.isOpen 'hidden'}} py-1 px-2 bg-gray-900 -mt-1" />
|
|
44
44
|
</Attach::Tooltip>
|
|
45
45
|
</dd.Trigger>
|
|
46
46
|
<dd.Content>
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
<div class="modal-body-container">
|
|
3
3
|
<div class="flex flex-row justify-between mb-6">
|
|
4
4
|
<div class="flex">
|
|
5
|
-
<
|
|
5
|
+
<Toggle @isToggled={{@options.order.payload.isMultiDrop}} @onToggle={{@options.toggleMultiDropOrder}} @label={{t "fleet-ops.component.modals.order-route-form.toggle"}} />
|
|
6
6
|
</div>
|
|
7
7
|
<div class="flex flex-1 justify-end space-x-2">
|
|
8
8
|
{{#if @options.order.payload.isMultiDrop}}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
<div class="fleet-ops-key-metrics" ...attributes>
|
|
2
|
+
<div class="flex flex-col">
|
|
3
|
+
<div class="flex flex-row items-center justify-between px-4 py-2 border dark:border-gray-700 border-gray-200 dark:bg-gray-800 bg-gray-50 rounded-lg shadow-sm">
|
|
4
|
+
<span class="text-base font-bold text-black dark:text-gray-100">{{t "fleet-ops.component.widget.key-metrics.title"}}</span>
|
|
5
|
+
</div>
|
|
6
|
+
|
|
7
|
+
<div class="mt-4">
|
|
8
|
+
{{#if this.getDashboardMetrics.isRunning}}
|
|
9
|
+
<Spinner />
|
|
10
|
+
{{else}}
|
|
11
|
+
<div class="grid grid-cols-2 lg:grid-cols-12 gap-4">
|
|
12
|
+
{{#each-in this.metrics as |title options|}}
|
|
13
|
+
<Dashboard::Count @title={{smart-humanize title}} @options={{options}} />
|
|
14
|
+
{{/each-in}}
|
|
15
|
+
</div>
|
|
16
|
+
{{/if}}
|
|
17
|
+
</div>
|
|
18
|
+
</div>
|
|
19
|
+
</div>
|