@fleetbase/fleetops-engine 0.6.14 → 0.6.15
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/customer/orders.js +2 -2
- package/addon/components/live-map.hbs +1 -1
- package/addon/components/live-map.js +2 -2
- package/addon/components/route-optimization-engine-select-button.hbs +2 -1
- package/addon/components/route-optimization-wizard-panel.hbs +24 -0
- package/addon/components/route-optimization-wizard-panel.js +46 -0
- package/addon/controllers/operations/orders/index/new.js +6 -5
- package/addon/controllers/operations/orders/index/view.js +2 -2
- package/addon/controllers/operations/orders/index.js +26 -1
- package/addon/controllers/operations/routes/index/new.js +36 -0
- package/addon/controllers/operations/routes/index/view.js +3 -0
- package/addon/controllers/operations/routes/index.js +13 -0
- package/addon/controllers/settings/routing.js +25 -3
- package/addon/engine.js +6 -5
- package/addon/routes/operations/routes/index/new.js +9 -0
- package/addon/routes/operations/routes/index/view.js +3 -0
- package/addon/routes/operations/routes/index.js +3 -0
- package/addon/routes/operations/routes.js +3 -0
- package/addon/routes.js +6 -0
- package/addon/services/leaflet-routing-control.js +64 -0
- package/addon/services/osrm.js +1 -1
- package/addon/templates/operations/routes/index/new.hbs +2 -0
- package/addon/templates/operations/routes/index/view.hbs +1 -0
- package/addon/templates/operations/routes/index.hbs +13 -0
- package/addon/templates/operations/routes.hbs +1 -0
- package/addon/templates/settings/routing.hbs +15 -1
- package/app/components/route-optimization-wizard-panel.js +1 -0
- package/app/controllers/operations/routes/index/new.js +1 -0
- package/app/controllers/operations/routes/index/view.js +1 -0
- package/app/routes/operations/routes/index/new.js +1 -0
- package/app/routes/operations/routes/index/view.js +1 -0
- package/app/routes/operations/routes/index.js +1 -0
- package/app/routes/operations/routes.js +1 -0
- package/app/services/leaflet-routing-control.js +1 -0
- package/app/templates/operations/routes/index/new.js +1 -0
- package/app/templates/operations/routes/index/view.js +1 -0
- package/app/templates/operations/routes/index.js +1 -0
- package/app/templates/operations/routes.js +1 -0
- package/composer.json +1 -1
- package/extension.json +1 -1
- package/package.json +1 -1
- package/server/src/Http/Controllers/Internal/v1/SettingController.php +8 -2
- package/server/src/Http/Filter/OrderFilter.php +5 -0
- package/server/src/Http/Requests/CreateDriverRequest.php +1 -1
- package/server/src/Listeners/NotifyOrderEvent.php +1 -1
- package/translations/en-us.yaml +1 -0
|
@@ -25,7 +25,7 @@ export default class CustomerOrdersComponent extends Component {
|
|
|
25
25
|
@service modalsManager;
|
|
26
26
|
@service customerSession;
|
|
27
27
|
@service hostRouter;
|
|
28
|
-
@service
|
|
28
|
+
@service leafletRoutingControl;
|
|
29
29
|
@engineService('@fleetbase/fleetops-engine') movementTracker;
|
|
30
30
|
@engineService('@fleetbase/fleetops-engine') location;
|
|
31
31
|
@tracked orders = [];
|
|
@@ -240,7 +240,7 @@ export default class CustomerOrdersComponent extends Component {
|
|
|
240
240
|
}
|
|
241
241
|
|
|
242
242
|
const routingService = this.currentUser.getOption('routing', { router: 'osrm' }).router;
|
|
243
|
-
const { router, formatter } = this.
|
|
243
|
+
const { router, formatter } = this.leafletRoutingControl.get(routingService);
|
|
244
244
|
|
|
245
245
|
this.routeControl = new RoutingControl({
|
|
246
246
|
router,
|
|
@@ -36,7 +36,7 @@ export default class LiveMapComponent extends Component {
|
|
|
36
36
|
@service contextPanel;
|
|
37
37
|
@service leafletMapManager;
|
|
38
38
|
@service leafletContextmenuManager;
|
|
39
|
-
@service
|
|
39
|
+
@service leafletRoutingControl;
|
|
40
40
|
@service theme;
|
|
41
41
|
|
|
42
42
|
/**
|
|
@@ -1140,7 +1140,7 @@ export default class LiveMapComponent extends Component {
|
|
|
1140
1140
|
}
|
|
1141
1141
|
|
|
1142
1142
|
const routingService = this.currentUser.getOption('routing', { router: 'osrm' }).router;
|
|
1143
|
-
const { router, formatter } = this.
|
|
1143
|
+
const { router, formatter } = this.leafletRoutingControl.get(routingService);
|
|
1144
1144
|
|
|
1145
1145
|
this.routeControl = new RoutingControl({
|
|
1146
1146
|
router,
|
|
@@ -15,7 +15,8 @@
|
|
|
15
15
|
<div class="px-1">
|
|
16
16
|
{{#each this.routeOptimization.availableServices as |service|}}
|
|
17
17
|
<a href="javascript:;" class="next-dd-item" {{on "click" (dropdown-fn dd this.handleClick service)}}>
|
|
18
|
-
<div >
|
|
18
|
+
<div class="flex flex-row items-center">
|
|
19
|
+
<div class="mr-2"><FaIcon @icon="arrow-right" /></div>
|
|
19
20
|
<div class="text-sm">{{service.name}}</div>
|
|
20
21
|
</div>
|
|
21
22
|
</a>
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
<Overlay
|
|
2
|
+
@isOpen={{true}}
|
|
3
|
+
@onLoad={{this.setOverlayContext}}
|
|
4
|
+
@position="right"
|
|
5
|
+
@noBackdrop={{true}}
|
|
6
|
+
@fullHeight={{true}}
|
|
7
|
+
@isResizeble={{true}}
|
|
8
|
+
@width="450px"
|
|
9
|
+
@overlayClass="route-optimization-wizard-panel"
|
|
10
|
+
>
|
|
11
|
+
<Overlay::Header @title="New Route Optimization">
|
|
12
|
+
<div class="flex flex-1 justify-end">
|
|
13
|
+
<Button @icon="play" @type="primary" @text="Run" @wrapperClass="mr-2" />
|
|
14
|
+
<Button @type="default" @icon="times" />
|
|
15
|
+
</div>
|
|
16
|
+
</Overlay::Header>
|
|
17
|
+
|
|
18
|
+
<Overlay::Body @wrapperClass="px-4 space-y-4 pt-4">
|
|
19
|
+
{{#each @waypoints as |waypoint|}}
|
|
20
|
+
<div class="border rounded p-4 flex items-center mb-3">{{waypoint.address}}</div>
|
|
21
|
+
{{/each}}
|
|
22
|
+
<Spacer @height="300px" />
|
|
23
|
+
</Overlay::Body>
|
|
24
|
+
</Overlay>
|
|
@@ -0,0 +1,46 @@
|
|
|
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 contextComponentCallback from '@fleetbase/ember-core/utils/context-component-callback';
|
|
6
|
+
import applyContextComponentArguments from '@fleetbase/ember-core/utils/apply-context-component-arguments';
|
|
7
|
+
|
|
8
|
+
export default class RouteOptimizationWizardPanelComponent extends Component {
|
|
9
|
+
@service universe;
|
|
10
|
+
@tracked context;
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Constructs the component and applies initial state.
|
|
14
|
+
*/
|
|
15
|
+
constructor(owner, { controller }) {
|
|
16
|
+
super(...arguments);
|
|
17
|
+
this.controller = controller;
|
|
18
|
+
applyContextComponentArguments(this);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Sets the overlay context.
|
|
23
|
+
*
|
|
24
|
+
* @action
|
|
25
|
+
* @param {OverlayContextObject} overlayContext
|
|
26
|
+
*/
|
|
27
|
+
@action setOverlayContext(overlayContext) {
|
|
28
|
+
this.context = overlayContext;
|
|
29
|
+
// hide sidebar
|
|
30
|
+
if (this.universe.sidebarContext) {
|
|
31
|
+
this.universe.sidebarContext.hide();
|
|
32
|
+
}
|
|
33
|
+
contextComponentCallback(this, 'onLoad', ...arguments);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Handles the cancel action.
|
|
38
|
+
*
|
|
39
|
+
* @method
|
|
40
|
+
* @action
|
|
41
|
+
* @returns {Boolean} Indicates whether the cancel action was overridden.
|
|
42
|
+
*/
|
|
43
|
+
@action onPressCancel() {
|
|
44
|
+
return contextComponentCallback(this, 'onPressCancel');
|
|
45
|
+
}
|
|
46
|
+
}
|
|
@@ -41,7 +41,7 @@ export default class OperationsOrdersIndexNewController extends BaseController {
|
|
|
41
41
|
@service contextPanel;
|
|
42
42
|
@service universe;
|
|
43
43
|
@service routeOptimization;
|
|
44
|
-
@service
|
|
44
|
+
@service leafletRoutingControl;
|
|
45
45
|
@service osrm;
|
|
46
46
|
|
|
47
47
|
@tracked order = this.store.createRecord('order', { meta: [] });
|
|
@@ -613,7 +613,7 @@ export default class OperationsOrdersIndexNewController extends BaseController {
|
|
|
613
613
|
return route;
|
|
614
614
|
}
|
|
615
615
|
|
|
616
|
-
@action setOptimizedRoute(route, trip, waypoints) {
|
|
616
|
+
@action setOptimizedRoute(route, trip, waypoints, engine = 'osrm') {
|
|
617
617
|
let summary = { totalDistance: trip.distance, totalTime: trip.duration };
|
|
618
618
|
let payload = {
|
|
619
619
|
optimized: true,
|
|
@@ -621,6 +621,7 @@ export default class OperationsOrdersIndexNewController extends BaseController {
|
|
|
621
621
|
waypoints,
|
|
622
622
|
trip,
|
|
623
623
|
summary,
|
|
624
|
+
engine,
|
|
624
625
|
};
|
|
625
626
|
|
|
626
627
|
this.leafletOptimizedRoute = payload;
|
|
@@ -792,7 +793,7 @@ export default class OperationsOrdersIndexNewController extends BaseController {
|
|
|
792
793
|
|
|
793
794
|
if (canPreviewRoute) {
|
|
794
795
|
const routingService = this.currentUser.getOption('routing', { router: 'osrm' }).router;
|
|
795
|
-
const { router, formatter } = this.
|
|
796
|
+
const { router, formatter } = this.leafletRoutingControl.get(routingService);
|
|
796
797
|
|
|
797
798
|
this.previewRouteControl = new RoutingControl({
|
|
798
799
|
router,
|
|
@@ -886,7 +887,7 @@ export default class OperationsOrdersIndexNewController extends BaseController {
|
|
|
886
887
|
}
|
|
887
888
|
}
|
|
888
889
|
|
|
889
|
-
handleRouteOptimization({ sortedWaypoints, route, trip, result }) {
|
|
890
|
+
handleRouteOptimization({ sortedWaypoints, route, trip, result, engine = 'osrm' }) {
|
|
890
891
|
// Update map layers & UI
|
|
891
892
|
this.removeRoutingControlPreview();
|
|
892
893
|
this.removeOptimizedRoute(this.leafletMap);
|
|
@@ -895,7 +896,7 @@ export default class OperationsOrdersIndexNewController extends BaseController {
|
|
|
895
896
|
// Update controller state
|
|
896
897
|
this.waypoints = sortedWaypoints;
|
|
897
898
|
if (route) {
|
|
898
|
-
this.setOptimizedRoute(route, trip, result.waypoints);
|
|
899
|
+
this.setOptimizedRoute(route, trip, result.waypoints, engine);
|
|
899
900
|
}
|
|
900
901
|
this.previewDraftOrderRoute(this.payload, this.waypoints, this.isMultipleDropoffOrder);
|
|
901
902
|
this.updatePayloadCoordinates();
|
|
@@ -23,7 +23,7 @@ export default class OperationsOrdersIndexViewController extends BaseController
|
|
|
23
23
|
@service socket;
|
|
24
24
|
@service universe;
|
|
25
25
|
@service contextPanel;
|
|
26
|
-
@service
|
|
26
|
+
@service leafletRoutingControl;
|
|
27
27
|
|
|
28
28
|
@tracked isLoadingAdditionalData = false;
|
|
29
29
|
@tracked isWaypointsCollapsed;
|
|
@@ -383,7 +383,7 @@ export default class OperationsOrdersIndexViewController extends BaseController
|
|
|
383
383
|
leafletMap.flyTo(waypoints.firstObject);
|
|
384
384
|
|
|
385
385
|
const routingService = this.currentUser.getOption('routing', { router: 'osrm' }).router;
|
|
386
|
-
const { router, formatter } = this.
|
|
386
|
+
const { router, formatter } = this.leafletRoutingControl.get(routingService);
|
|
387
387
|
|
|
388
388
|
this.routeControl = new RoutingControl({
|
|
389
389
|
router,
|
|
@@ -22,6 +22,7 @@ export default class OperationsOrdersIndexController extends BaseController {
|
|
|
22
22
|
@service socket;
|
|
23
23
|
@service abilities;
|
|
24
24
|
@service theme;
|
|
25
|
+
@service routeOptimization;
|
|
25
26
|
|
|
26
27
|
/**
|
|
27
28
|
* Queryable parameters for this controller's model
|
|
@@ -1130,7 +1131,6 @@ export default class OperationsOrdersIndexController extends BaseController {
|
|
|
1130
1131
|
*/
|
|
1131
1132
|
@action bulkAssignDriver(selected = []) {
|
|
1132
1133
|
selected = selected.length > 0 ? selected : this.table.selectedRows;
|
|
1133
|
-
|
|
1134
1134
|
if (!isArray(selected) || selected.length === 0) {
|
|
1135
1135
|
return;
|
|
1136
1136
|
}
|
|
@@ -1199,12 +1199,37 @@ export default class OperationsOrdersIndexController extends BaseController {
|
|
|
1199
1199
|
});
|
|
1200
1200
|
}
|
|
1201
1201
|
|
|
1202
|
+
/**
|
|
1203
|
+
* Commits the bulk query to the server for results.
|
|
1204
|
+
* @action
|
|
1205
|
+
* @memberof OperationsOrdersIndexController
|
|
1206
|
+
*/
|
|
1202
1207
|
@action commitBulkQuery() {
|
|
1203
1208
|
this.bulk_query = this.bulkSearchValue;
|
|
1204
1209
|
}
|
|
1205
1210
|
|
|
1211
|
+
/**
|
|
1212
|
+
* Resets/clear the bulk query search.
|
|
1213
|
+
* @action
|
|
1214
|
+
* @memberof OperationsOrdersIndexController
|
|
1215
|
+
*/
|
|
1206
1216
|
@action removeBulkQuery() {
|
|
1207
1217
|
this.bulkSearchValue = '';
|
|
1208
1218
|
this.bulk_query = null;
|
|
1209
1219
|
}
|
|
1220
|
+
|
|
1221
|
+
/**
|
|
1222
|
+
* Run route optimization wizard.
|
|
1223
|
+
* @action
|
|
1224
|
+
* @memberof OperationsOrdersIndexController
|
|
1225
|
+
*/
|
|
1226
|
+
@action optimizeOrderRoutes(selected = []) {
|
|
1227
|
+
selected = selected.length > 0 ? selected : this.table.selectedRows;
|
|
1228
|
+
|
|
1229
|
+
return this.hostRouter.transitionTo('console.fleet-ops.operations.routes.index.new', {
|
|
1230
|
+
queryParams: {
|
|
1231
|
+
selectedOrders: selected.map((_) => _.public_id).join(','),
|
|
1232
|
+
},
|
|
1233
|
+
});
|
|
1234
|
+
}
|
|
1210
1235
|
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import Controller from '@ember/controller';
|
|
2
|
+
import { tracked } from '@glimmer/tracking';
|
|
3
|
+
import { inject as service } from '@ember/service';
|
|
4
|
+
import { action } from '@ember/object';
|
|
5
|
+
import { task } from 'ember-concurrency';
|
|
6
|
+
|
|
7
|
+
export default class OperationsRoutesIndexNewController extends Controller {
|
|
8
|
+
@service store;
|
|
9
|
+
@tracked panel;
|
|
10
|
+
@tracked selectedOrders = '';
|
|
11
|
+
@tracked waypoints = [];
|
|
12
|
+
|
|
13
|
+
@action setOverlayPanelContext(overlayPanelContext) {
|
|
14
|
+
this.panel = overlayPanelContext;
|
|
15
|
+
this.loadSelectedOrders.perform(this.selectedOrders.split(','));
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
@task *loadSelectedOrders(selectedOrders) {
|
|
19
|
+
const orders = yield this.store.query('order', { only: selectedOrders });
|
|
20
|
+
console.log('[orders]', orders);
|
|
21
|
+
this.extractWaypoints(orders);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
extractWaypoints(orders = []) {
|
|
25
|
+
const extracted = [];
|
|
26
|
+
|
|
27
|
+
orders.forEach((order) => {
|
|
28
|
+
const pickup = order.get('payload.pickup');
|
|
29
|
+
const dropoff = order.get('payload.dropoff');
|
|
30
|
+
const waypoints = order.get('payload.waypoints')?.toArray() ?? [];
|
|
31
|
+
extracted.push(pickup, dropoff, ...waypoints);
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
this.waypoints = extracted.filter(Boolean);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import Controller from '@ember/controller';
|
|
2
|
+
import { tracked } from '@glimmer/tracking';
|
|
3
|
+
import { action } from '@ember/object';
|
|
4
|
+
|
|
5
|
+
export default class OperationsRoutesIndexController extends Controller {
|
|
6
|
+
@tracked leafletMap;
|
|
7
|
+
@tracked liveMap;
|
|
8
|
+
|
|
9
|
+
@action setMapReference({ target }) {
|
|
10
|
+
this.leafletMap = target;
|
|
11
|
+
this.liveMap = target.liveMap;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
@@ -7,8 +7,14 @@ export default class SettingsRoutingController extends Controller {
|
|
|
7
7
|
@service fetch;
|
|
8
8
|
@service notifications;
|
|
9
9
|
@service currentUser;
|
|
10
|
-
@service
|
|
10
|
+
@service leafletRoutingControl;
|
|
11
11
|
@tracked routerService = 'osrm';
|
|
12
|
+
@tracked routingUnit = 'km';
|
|
13
|
+
@tracked routingUnitOptions = [
|
|
14
|
+
{ label: 'Kilometers', value: 'km' },
|
|
15
|
+
{ label: 'Miles', value: 'mi' },
|
|
16
|
+
];
|
|
17
|
+
@tracked saveTasks = [];
|
|
12
18
|
|
|
13
19
|
constructor() {
|
|
14
20
|
super(...arguments);
|
|
@@ -23,8 +29,9 @@ export default class SettingsRoutingController extends Controller {
|
|
|
23
29
|
@task *saveSettings() {
|
|
24
30
|
try {
|
|
25
31
|
yield this.fetch.post('fleet-ops/settings/routing-settings', { router: this.routerService });
|
|
32
|
+
yield this.performAdditionalSaveTasks();
|
|
26
33
|
// Save in local memory too
|
|
27
|
-
this.currentUser.setOption('routing', { router: this.routerService });
|
|
34
|
+
this.currentUser.setOption('routing', { router: this.routerService, unit: this.routingUnit });
|
|
28
35
|
this.notifications.success('Routing setting saved.');
|
|
29
36
|
} catch (error) {
|
|
30
37
|
this.notifications.serverError(error);
|
|
@@ -38,10 +45,25 @@ export default class SettingsRoutingController extends Controller {
|
|
|
38
45
|
*/
|
|
39
46
|
@task *getSettings() {
|
|
40
47
|
try {
|
|
41
|
-
const { router } = yield this.fetch.get('fleet-ops/settings/routing-settings');
|
|
48
|
+
const { router, unit } = yield this.fetch.get('fleet-ops/settings/routing-settings');
|
|
42
49
|
this.routerService = router;
|
|
50
|
+
this.routingUnit = unit;
|
|
43
51
|
} catch (error) {
|
|
44
52
|
this.notifications.serverError(error);
|
|
45
53
|
}
|
|
46
54
|
}
|
|
55
|
+
|
|
56
|
+
registerSaveTask(task) {
|
|
57
|
+
this.saveTasks.push(task);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
async performAdditionalSaveTasks() {
|
|
61
|
+
for (let i = 0; i < this.saveTasks.length; i++) {
|
|
62
|
+
const task = this.saveTasks[i];
|
|
63
|
+
if (typeof task.perform === 'function') {
|
|
64
|
+
await task.perform();
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return true;
|
|
68
|
+
}
|
|
47
69
|
}
|
package/addon/engine.js
CHANGED
|
@@ -9,7 +9,7 @@ import AdminAvatarManagementComponent from './components/admin/avatar-management
|
|
|
9
9
|
import CustomerOrdersComponent from './components/customer/orders';
|
|
10
10
|
import CustomerAdminSettingsComponent from './components/customer/admin-settings';
|
|
11
11
|
import OrderTrackingLookupComponent from './components/order-tracking-lookup';
|
|
12
|
-
import {
|
|
12
|
+
import { RoutingControl } from './services/leaflet-routing-control';
|
|
13
13
|
import { OSRMv1 } from '@fleetbase/leaflet-routing-machine';
|
|
14
14
|
import getRoutingHost from '@fleetbase/ember-core/utils/get-routing-host';
|
|
15
15
|
|
|
@@ -68,12 +68,12 @@ export default class FleetOpsEngine extends Engine {
|
|
|
68
68
|
}
|
|
69
69
|
|
|
70
70
|
// Register OSRM as Routing Controler
|
|
71
|
-
const
|
|
72
|
-
if (
|
|
71
|
+
const leafletRoutingControl = app.lookup('service:leaflet-routing-control');
|
|
72
|
+
if (leafletRoutingControl) {
|
|
73
73
|
const routingHost = getRoutingHost();
|
|
74
|
-
|
|
74
|
+
leafletRoutingControl.register(
|
|
75
75
|
'osrm',
|
|
76
|
-
new
|
|
76
|
+
new RoutingControl({
|
|
77
77
|
name: 'OSRM',
|
|
78
78
|
router: new OSRMv1({
|
|
79
79
|
serviceUrl: `${routingHost}/route/v1`,
|
|
@@ -133,6 +133,7 @@ export default class FleetOpsEngine extends Engine {
|
|
|
133
133
|
'fleet-ops:template:operations:orders:new',
|
|
134
134
|
'fleet-ops:template:operations:orders:new:entities-input',
|
|
135
135
|
'fleet-ops:template:operations:orders:new:entities-input:entity',
|
|
136
|
+
'fleet-ops:template:settings:routing',
|
|
136
137
|
]);
|
|
137
138
|
|
|
138
139
|
universe.afterBoot(function (universe) {
|
package/addon/routes.js
CHANGED
|
@@ -31,6 +31,12 @@ export default buildRoutes(function () {
|
|
|
31
31
|
});
|
|
32
32
|
});
|
|
33
33
|
});
|
|
34
|
+
this.route('routes', function () {
|
|
35
|
+
this.route('index', { path: '/' }, function () {
|
|
36
|
+
this.route('new');
|
|
37
|
+
this.route('view', { path: '/:public_id' });
|
|
38
|
+
});
|
|
39
|
+
});
|
|
34
40
|
});
|
|
35
41
|
this.route('management', { path: '/manage' }, function () {
|
|
36
42
|
this.route('fleets', function () {
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import Service, { inject as service } from '@ember/service';
|
|
2
|
+
import { tracked } from '@glimmer/tracking';
|
|
3
|
+
import { underscore } from '@ember/string';
|
|
4
|
+
|
|
5
|
+
export class RoutingControlRegistry {
|
|
6
|
+
@tracked routers = {};
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export class RoutingControl {
|
|
10
|
+
@tracked name;
|
|
11
|
+
@tracked router;
|
|
12
|
+
@tracked formatter;
|
|
13
|
+
|
|
14
|
+
constructor(init) {
|
|
15
|
+
const { name, router, formatter } = typeof init === 'function' ? init() : init;
|
|
16
|
+
this.name = name;
|
|
17
|
+
this.router = router;
|
|
18
|
+
this.formatter = formatter;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export default class LeafletRoutingControlService extends Service {
|
|
23
|
+
@service universe;
|
|
24
|
+
registry = this.#initializeRegistry();
|
|
25
|
+
|
|
26
|
+
get availableEngines() {
|
|
27
|
+
return Object.keys(this.registry.routers).map(underscore);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
get availableServices() {
|
|
31
|
+
return Object.entries(this.registry.routers).map(([key, control]) => ({
|
|
32
|
+
key,
|
|
33
|
+
name: control.name ?? key,
|
|
34
|
+
}));
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
register(name, getter) {
|
|
38
|
+
this.registry.routers = {
|
|
39
|
+
...this.registry.routers,
|
|
40
|
+
[underscore(name)]: getter,
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/* eslint-disable no-unused-vars */
|
|
45
|
+
unregister(name) {
|
|
46
|
+
let key = underscore(name);
|
|
47
|
+
let { [key]: _, ...rest } = this.registry.routers;
|
|
48
|
+
this.registry.routers = rest;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
get(name) {
|
|
52
|
+
return this.registry.routers[underscore(name)];
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
#initializeRegistry() {
|
|
56
|
+
const registry = 'registry:routing-controls';
|
|
57
|
+
const application = this.universe.getApplicationInstance();
|
|
58
|
+
if (!application.hasRegistration(registry)) {
|
|
59
|
+
application.register(registry, new RoutingControlRegistry(), { instantiate: false });
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return application.resolveRegistration(registry);
|
|
63
|
+
}
|
|
64
|
+
}
|
package/addon/services/osrm.js
CHANGED
|
@@ -37,7 +37,7 @@ export default class OsrmService extends RouteOptimizationInterfaceService {
|
|
|
37
37
|
const trip = result.trips?.[0];
|
|
38
38
|
const route = polyline.decode(trip.geometry);
|
|
39
39
|
|
|
40
|
-
return { sortedWaypoints, trip, route, result };
|
|
40
|
+
return { sortedWaypoints, trip, route, result, engine: 'osrm' };
|
|
41
41
|
} catch (err) {
|
|
42
42
|
debug(`[OSRM] Error routing trip : ${err.message}`);
|
|
43
43
|
throw err;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{{outlet}}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
<LiveMap
|
|
2
|
+
id="leafletMap"
|
|
3
|
+
class="next-leaflet-container-map"
|
|
4
|
+
@lat={{1.3521}}
|
|
5
|
+
@lng={{103.8198}}
|
|
6
|
+
@zoom={{12}}
|
|
7
|
+
@zoomControl={{false}}
|
|
8
|
+
@drawerTab={{false}}
|
|
9
|
+
@onLoad={{this.setMapReference}}
|
|
10
|
+
@darkMode={{eq this.theme.activeTheme "dark"}}
|
|
11
|
+
{{set-container-dimensions}}
|
|
12
|
+
/>
|
|
13
|
+
{{outlet}}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{{outlet}}
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
<InputGroup @name="Routing Service" @helpText="Select the service which is responsible for calculating and plotting routes on the map.">
|
|
18
18
|
<Select
|
|
19
19
|
@value={{this.routerService}}
|
|
20
|
-
@options={{this.
|
|
20
|
+
@options={{this.leafletRoutingControl.availableServices}}
|
|
21
21
|
@optionLabel="name"
|
|
22
22
|
@optionValue="key"
|
|
23
23
|
@onSelect={{fn (mut this.routerService)}}
|
|
@@ -25,7 +25,21 @@
|
|
|
25
25
|
class="w-full"
|
|
26
26
|
/>
|
|
27
27
|
</InputGroup>
|
|
28
|
+
<InputGroup @name="Routing Distance Unit" @helpText="The unit used for calculating distance and routes.">
|
|
29
|
+
<Select
|
|
30
|
+
@value={{this.routingUnit}}
|
|
31
|
+
@options={{this.routingUnitOptions}}
|
|
32
|
+
@optionLabel="label"
|
|
33
|
+
@optionValue="value"
|
|
34
|
+
@onSelect={{fn (mut this.routingUnit)}}
|
|
35
|
+
@placeholder="Select routing unit..."
|
|
36
|
+
class="w-full"
|
|
37
|
+
/>
|
|
38
|
+
</InputGroup>
|
|
28
39
|
</ContentPanel>
|
|
40
|
+
<RegistryYield @registry="fleet-ops:template:settings:routing" as |RegistryComponent|>
|
|
41
|
+
<RegistryComponent @controller={{this}} />
|
|
42
|
+
</RegistryYield>
|
|
29
43
|
</div>
|
|
30
44
|
</div>
|
|
31
45
|
<Spacer @height="600px" />
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from '@fleetbase/fleetops-engine/components/route-optimization-wizard-panel';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from '@fleetbase/fleetops-engine/controllers/operations/routes/index/new';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from '@fleetbase/fleetops-engine/controllers/operations/routes/index/view';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from '@fleetbase/fleetops-engine/routes/operations/routes/index/new';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from '@fleetbase/fleetops-engine/routes/operations/routes/index/view';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from '@fleetbase/fleetops-engine/routes/operations/routes/index';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from '@fleetbase/fleetops-engine/routes/operations/routes';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from '@fleetbase/fleetops-engine/services/leaflet-routing-control';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from '@fleetbase/fleetops-engine/templates/operations/routes/index/new';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from '@fleetbase/fleetops-engine/templates/operations/routes/index/view';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from '@fleetbase/fleetops-engine/templates/operations/routes/index';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from '@fleetbase/fleetops-engine/templates/operations/routes';
|
package/composer.json
CHANGED
package/extension.json
CHANGED
package/package.json
CHANGED
|
@@ -185,7 +185,8 @@ class SettingController extends Controller
|
|
|
185
185
|
public function saveRoutingSettings(Request $request)
|
|
186
186
|
{
|
|
187
187
|
$router = $request->input('router');
|
|
188
|
-
|
|
188
|
+
$unit = $request->input('unit', 'km');
|
|
189
|
+
Setting::configureCompany('routing', ['router' => $router, 'unit' => $unit]);
|
|
189
190
|
|
|
190
191
|
return response()->json([
|
|
191
192
|
'status' => 'ok',
|
|
@@ -200,7 +201,12 @@ class SettingController extends Controller
|
|
|
200
201
|
*/
|
|
201
202
|
public function getRoutingSettings()
|
|
202
203
|
{
|
|
203
|
-
$routingSettings = Setting::lookupCompany('routing', ['router' => 'osrm']);
|
|
204
|
+
$routingSettings = Setting::lookupCompany('routing', ['router' => 'osrm', 'unit' => 'km']);
|
|
205
|
+
|
|
206
|
+
// always default to km if no unit is set
|
|
207
|
+
if (!isset($routingSettings['unit'])) {
|
|
208
|
+
$routingSettings['unit'] = 'km';
|
|
209
|
+
}
|
|
204
210
|
|
|
205
211
|
return response()->json($routingSettings);
|
|
206
212
|
}
|
|
@@ -34,7 +34,7 @@ class CreateDriverRequest extends FleetbaseRequest
|
|
|
34
34
|
'password' => 'nullable|string',
|
|
35
35
|
'country' => 'nullable|size:2',
|
|
36
36
|
'city' => 'nullable|string',
|
|
37
|
-
'vehicle' => 'nullable|string|starts_with:vehicle_|exists:
|
|
37
|
+
'vehicle' => 'nullable|string|starts_with:vehicle_|exists:vehicles,public_id',
|
|
38
38
|
'status' => 'nullable|string|in:active,inactive',
|
|
39
39
|
'vendor' => 'nullable|exists:vendors,public_id',
|
|
40
40
|
'job' => 'nullable|exists:orders,public_id',
|
|
@@ -34,7 +34,7 @@ class NotifyOrderEvent implements ShouldQueue
|
|
|
34
34
|
$reason = $event->activity ? $event->activity->get('details') : '';
|
|
35
35
|
NotificationRegistry::notify(OrderCanceled::class, $order, $reason, $event->waypoint);
|
|
36
36
|
}
|
|
37
|
-
|
|
37
|
+
|
|
38
38
|
if ($event instanceof \Fleetbase\FleetOps\Events\OrderCompleted) {
|
|
39
39
|
NotificationRegistry::notify(OrderCompleted::class, $order, $event->waypoint);
|
|
40
40
|
}
|
package/translations/en-us.yaml
CHANGED
|
@@ -1332,6 +1332,7 @@ fleet-ops:
|
|
|
1332
1332
|
delete-orders: Delete Orders
|
|
1333
1333
|
dispatch-orders: Dispatch Orders
|
|
1334
1334
|
assign-driver: Assign Driver
|
|
1335
|
+
route-optimization: Route Optimization
|
|
1335
1336
|
bulk-assign-driver-helptext: Select a driver to assign to multiple orders.
|
|
1336
1337
|
new:
|
|
1337
1338
|
create-new-customer: Create new customer
|