@fleetbase/fleetops-engine 0.3.8 → 0.3.9
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 +4 -1
- package/addon/components/contact-panel.hbs +1 -1
- package/addon/components/driver-form-panel.hbs +5 -12
- package/addon/components/driver-panel.hbs +4 -1
- package/addon/components/fleet-form-panel.hbs +4 -1
- package/addon/components/fleet-listing-panel.hbs +2 -2
- package/addon/components/fleet-panel.hbs +1 -1
- package/addon/components/fuel-report-form-panel.hbs +4 -1
- package/addon/components/fuel-report-panel.hbs +4 -1
- package/addon/components/issue-form-panel.hbs +4 -1
- package/addon/components/issue-panel.hbs +4 -1
- package/addon/components/layout/fleet-ops-sidebar/driver-listing.hbs +5 -0
- package/addon/components/layout/fleet-ops-sidebar/driver-listing.js +122 -0
- package/addon/components/layout/fleet-ops-sidebar/fleet-listing.hbs +2 -2
- package/addon/components/layout/fleet-ops-sidebar/fleet-listing.js +69 -49
- package/addon/components/layout/fleet-ops-sidebar.hbs +1 -1
- package/addon/components/layout/fleet-ops-sidebar.js +4 -3
- package/addon/components/live-map.hbs +90 -9
- package/addon/components/live-map.js +28 -11
- package/addon/components/map-container/toolbar/zones-panel.js +16 -13
- package/addon/components/place-form-panel.hbs +4 -1
- package/addon/components/place-panel.hbs +4 -1
- package/addon/components/settings-window.hbs +1 -1
- package/addon/components/vehicle-form-panel.hbs +4 -1
- package/addon/components/vehicle-panel.hbs +4 -1
- package/addon/components/vendor-form-panel.hbs +4 -1
- package/addon/components/vendor-panel.hbs +4 -1
- package/addon/controllers/management/drivers/index.js +10 -90
- package/addon/controllers/management/vehicles/index.js +11 -21
- package/addon/controllers/operations/orders/index/new.js +5 -5
- package/addon/controllers/operations/orders/index/view.js +9 -13
- package/addon/helpers/format-point.js +5 -2
- package/addon/helpers/point-to-coordinates.js +6 -2
- package/addon/services/context-panel.js +23 -18
- package/addon/services/driver-actions.js +107 -0
- package/addon/services/vehicle-actions.js +42 -0
- package/addon/styles/fleetops-engine.css +12 -2
- package/addon/templates/operations/orders/index/new.hbs +3 -3
- package/addon/utils/fly-to-leaflet-layer.js +7 -0
- package/app/components/layout/fleet-ops-sidebar/driver-listing.js +1 -0
- package/app/services/driver-actions.js +1 -0
- package/app/services/vehicle-actions.js +1 -0
- package/composer.json +2 -2
- package/extension.json +1 -1
- package/package.json +4 -4
- package/server/src/Exceptions/IntegratedVendorException.php +45 -1
- package/server/src/Http/Controllers/Api/v1/DriverController.php +2 -2
- package/server/src/Http/Controllers/Internal/v1/DriverController.php +25 -4
- package/server/src/Http/Controllers/Internal/v1/LiveController.php +3 -10
- package/server/src/Http/Controllers/Internal/v1/NavigatorController.php +1 -1
- package/addon/helpers/extract-coordinates.js +0 -6
- package/addon/utils/extract-coordinates.js +0 -1
- package/app/helpers/extract-coordinates.js +0 -1
- package/app/utils/extract-coordinates.js +0 -1
|
@@ -13,7 +13,6 @@ import findClosestWaypoint from '@fleetbase/ember-core/utils/find-closest-waypoi
|
|
|
13
13
|
import isNotEmpty from '@fleetbase/ember-core/utils/is-not-empty';
|
|
14
14
|
import getRoutingHost from '@fleetbase/ember-core/utils/get-routing-host';
|
|
15
15
|
import groupBy from '@fleetbase/ember-core/utils/macros/group-by';
|
|
16
|
-
import extractCoordinates from '@fleetbase/ember-core/utils/extract-coordinates';
|
|
17
16
|
import getWithDefault from '@fleetbase/ember-core/utils/get-with-default';
|
|
18
17
|
|
|
19
18
|
L.Bounds.prototype.intersects = function (bounds) {
|
|
@@ -213,7 +212,7 @@ export default class OperationsOrdersIndexNewController extends BaseController {
|
|
|
213
212
|
return (
|
|
214
213
|
this.routePreviewArray
|
|
215
214
|
// .filter((place) => place.get('hasValidCoordinates'))
|
|
216
|
-
.map((place) => place.get('
|
|
215
|
+
.map((place) => place.get('latlng'))
|
|
217
216
|
);
|
|
218
217
|
}
|
|
219
218
|
|
|
@@ -580,7 +579,7 @@ export default class OperationsOrdersIndexNewController extends BaseController {
|
|
|
580
579
|
});
|
|
581
580
|
} else {
|
|
582
581
|
// setup interface when livemap is ready
|
|
583
|
-
this.universe.on('
|
|
582
|
+
this.universe.on('fleet-ops.live-map.ready', () => {
|
|
584
583
|
this.setupInterface();
|
|
585
584
|
});
|
|
586
585
|
}
|
|
@@ -749,7 +748,7 @@ export default class OperationsOrdersIndexNewController extends BaseController {
|
|
|
749
748
|
}
|
|
750
749
|
|
|
751
750
|
@action createCoordinatesFromRoutePlaceArray(array) {
|
|
752
|
-
return array.filter((place) => place.get('hasValidCoordinates')).map((place) => place.get('
|
|
751
|
+
return array.filter((place) => place.get('hasValidCoordinates')).map((place) => place.get('latlng'));
|
|
753
752
|
}
|
|
754
753
|
|
|
755
754
|
@action previewDraftOrderRoute(payload, waypoints, isMultipleDropoffOrder = false) {
|
|
@@ -875,7 +874,8 @@ export default class OperationsOrdersIndexNewController extends BaseController {
|
|
|
875
874
|
const waypointModel = findClosestWaypoint(optimizedWaypointLatitude, optimizedWaypointLongitude, this.waypoints);
|
|
876
875
|
// eslint-disable-next-line no-undef
|
|
877
876
|
// const optimizedWaypointMarker = new L.Marker(optimizedWaypoint.location.reverse()).addTo(leafletMap);
|
|
878
|
-
const
|
|
877
|
+
const [longitude, latitude] = getWithDefault(optimizedWaypoint.location, 'coordiantes', [0, 0]);
|
|
878
|
+
const optimizedWaypointMarker = new L.Marker([latitude, longitude]).addTo(leafletMap);
|
|
879
879
|
|
|
880
880
|
sortedWaypoints.pushObject(waypointModel);
|
|
881
881
|
optimizedRouteMarkers.pushObject(optimizedWaypointMarker);
|
|
@@ -19,13 +19,6 @@ export default class OperationsOrdersIndexViewController extends BaseController
|
|
|
19
19
|
*/
|
|
20
20
|
@controller('operations.orders.index') ordersController;
|
|
21
21
|
|
|
22
|
-
/**
|
|
23
|
-
* Inject the `operations.orders.index` controller
|
|
24
|
-
*
|
|
25
|
-
* @var {Controller}
|
|
26
|
-
*/
|
|
27
|
-
@controller('management.places.index') placesController;
|
|
28
|
-
|
|
29
22
|
/**
|
|
30
23
|
* Inject the `management.contacts.index` controller
|
|
31
24
|
*
|
|
@@ -248,14 +241,14 @@ export default class OperationsOrdersIndexViewController extends BaseController
|
|
|
248
241
|
};
|
|
249
242
|
|
|
250
243
|
// re-display order routes when livemap has coordinates
|
|
251
|
-
this.universe.on('
|
|
244
|
+
this.universe.on('fleet-ops.live-map.has_coordinates', this, displayOrderRoute);
|
|
252
245
|
|
|
253
246
|
// when transitioning away kill event listener
|
|
254
247
|
this.hostRouter.on('routeWillChange', () => {
|
|
255
|
-
const isListening = this.universe.has('
|
|
248
|
+
const isListening = this.universe.has('fleet-ops.live-map.has_coordinates');
|
|
256
249
|
|
|
257
250
|
if (isListening) {
|
|
258
|
-
this.universe.off('
|
|
251
|
+
this.universe.off('fleet-ops.live-map.has_coordinates', this, displayOrderRoute);
|
|
259
252
|
}
|
|
260
253
|
});
|
|
261
254
|
|
|
@@ -472,9 +465,12 @@ export default class OperationsOrdersIndexViewController extends BaseController
|
|
|
472
465
|
isOptimizingRoute: false,
|
|
473
466
|
editPlace: async (place) => {
|
|
474
467
|
await this.modalsManager.done();
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
468
|
+
|
|
469
|
+
this.contextPanel.focus(place, 'editing', {
|
|
470
|
+
args: {
|
|
471
|
+
onClose: () => {
|
|
472
|
+
this.editOrderRoute(order);
|
|
473
|
+
},
|
|
478
474
|
},
|
|
479
475
|
});
|
|
480
476
|
},
|
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
import { helper } from '@ember/component/helper';
|
|
2
2
|
import { isArray } from '@ember/array';
|
|
3
|
-
import extractCoordinates from '../utils/extract-coordinates';
|
|
4
3
|
|
|
5
4
|
export default helper(function formatPoint([point]) {
|
|
5
|
+
// array assumes [latitude, longitude]
|
|
6
6
|
if (isArray(point)) {
|
|
7
7
|
return `(${point[0]}, ${point[1]})`;
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
let [longitude, latitude] = [0, 0];
|
|
11
|
+
if (point && isArray(point.coordinates)) {
|
|
12
|
+
[longitude, latitude] = point.coordinates;
|
|
13
|
+
}
|
|
11
14
|
|
|
12
15
|
return `(${latitude}, ${longitude})`;
|
|
13
16
|
});
|
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
import { helper } from '@ember/component/helper';
|
|
2
|
-
import
|
|
2
|
+
import { isArray } from '@ember/array';
|
|
3
3
|
|
|
4
4
|
export default helper(function pointToCoordinates([point, format = 'array']) {
|
|
5
|
-
|
|
5
|
+
let [longitude, latitude] = [0, 0];
|
|
6
|
+
|
|
7
|
+
if (point && isArray(point.coordinates)) {
|
|
8
|
+
[longitude, latitude] = point.coordinates;
|
|
9
|
+
}
|
|
6
10
|
|
|
7
11
|
if (format === 'array') {
|
|
8
12
|
return [latitude, longitude];
|
|
@@ -2,6 +2,7 @@ import Service from '@ember/service';
|
|
|
2
2
|
import { tracked } from '@glimmer/tracking';
|
|
3
3
|
import { action } from '@ember/object';
|
|
4
4
|
import getModelName from '@fleetbase/ember-core/utils/get-model-name';
|
|
5
|
+
import getWithDefault from '@fleetbase/ember-core/utils/get-with-default';
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
8
|
* Service for managing the state and interactions of the context panel.
|
|
@@ -19,81 +20,81 @@ export default class ContextPanelService extends Service {
|
|
|
19
20
|
driver: {
|
|
20
21
|
viewing: {
|
|
21
22
|
component: 'driver-panel',
|
|
22
|
-
componentArguments: [{ isResizable: true }, { width: '
|
|
23
|
+
componentArguments: [{ isResizable: true }, { width: '500px' }],
|
|
23
24
|
},
|
|
24
25
|
editing: {
|
|
25
26
|
component: 'driver-form-panel',
|
|
26
|
-
componentArguments: [{ isResizable: true }, { width: '
|
|
27
|
+
componentArguments: [{ isResizable: true }, { width: '500px' }],
|
|
27
28
|
},
|
|
28
29
|
},
|
|
29
30
|
vehicle: {
|
|
30
31
|
viewing: {
|
|
31
32
|
component: 'vehicle-panel',
|
|
32
|
-
componentArguments: [{ isResizable: true }, { width: '
|
|
33
|
+
componentArguments: [{ isResizable: true }, { width: '500px' }],
|
|
33
34
|
},
|
|
34
35
|
editing: {
|
|
35
36
|
component: 'vehicle-form-panel',
|
|
36
|
-
componentArguments: [{ isResizable: true }, { width: '
|
|
37
|
+
componentArguments: [{ isResizable: true }, { width: '500px' }],
|
|
37
38
|
},
|
|
38
39
|
},
|
|
39
40
|
fleet: {
|
|
40
41
|
viewing: {
|
|
41
42
|
component: 'fleet-panel',
|
|
42
|
-
componentArguments: [{ isResizable: true }, { width: '
|
|
43
|
+
componentArguments: [{ isResizable: true }, { width: '500px' }],
|
|
43
44
|
},
|
|
44
45
|
editing: {
|
|
45
46
|
component: 'fleet-form-panel',
|
|
46
|
-
componentArguments: [{ isResizable: true }, { width: '
|
|
47
|
+
componentArguments: [{ isResizable: true }, { width: '500px' }],
|
|
47
48
|
},
|
|
48
49
|
},
|
|
49
50
|
fuelReport: {
|
|
50
51
|
viewing: {
|
|
51
52
|
component: 'fuel-report-panel',
|
|
52
|
-
componentArguments: [{ isResizable: true }, { width: '
|
|
53
|
+
componentArguments: [{ isResizable: true }, { width: '500px' }],
|
|
53
54
|
},
|
|
54
55
|
editing: {
|
|
55
56
|
component: 'fuel-report-form-panel',
|
|
56
|
-
componentArguments: [{ isResizable: true }, { width: '
|
|
57
|
+
componentArguments: [{ isResizable: true }, { width: '500px' }],
|
|
57
58
|
},
|
|
58
59
|
},
|
|
59
60
|
vendor: {
|
|
60
61
|
viewing: {
|
|
61
62
|
component: 'vendor-panel',
|
|
62
|
-
componentArguments: [{ isResizable: true }, { width: '
|
|
63
|
+
componentArguments: [{ isResizable: true }, { width: '500px' }],
|
|
63
64
|
},
|
|
64
65
|
editing: {
|
|
65
66
|
component: 'vendor-form-panel',
|
|
66
|
-
componentArguments: [{ isResizable: true }, { width: '
|
|
67
|
+
componentArguments: [{ isResizable: true }, { width: '500px' }],
|
|
67
68
|
},
|
|
68
69
|
},
|
|
69
70
|
contact: {
|
|
70
71
|
viewing: {
|
|
71
72
|
component: 'contact-panel',
|
|
72
|
-
componentArguments: [{ isResizable: true }, { width: '
|
|
73
|
+
componentArguments: [{ isResizable: true }, { width: '500px' }],
|
|
73
74
|
},
|
|
74
75
|
editing: {
|
|
75
76
|
component: 'contact-form-panel',
|
|
76
|
-
componentArguments: [{ isResizable: true }, { width: '
|
|
77
|
+
componentArguments: [{ isResizable: true }, { width: '500px' }],
|
|
77
78
|
},
|
|
78
79
|
},
|
|
79
80
|
place: {
|
|
80
81
|
viewing: {
|
|
81
82
|
component: 'place-panel',
|
|
82
|
-
componentArguments: [{ isResizable: true }, { width: '
|
|
83
|
+
componentArguments: [{ isResizable: true }, { width: '500px' }],
|
|
83
84
|
},
|
|
84
85
|
editing: {
|
|
85
86
|
component: 'place-form-panel',
|
|
86
|
-
componentArguments: [{ isResizable: true }, { width: '
|
|
87
|
+
componentArguments: [{ isResizable: true }, { width: '500px' }],
|
|
87
88
|
},
|
|
88
89
|
},
|
|
89
90
|
issue: {
|
|
90
91
|
viewing: {
|
|
91
92
|
component: 'issue-panel',
|
|
92
|
-
componentArguments: [{ isResizable: true }, { width: '
|
|
93
|
+
componentArguments: [{ isResizable: true }, { width: '500px' }],
|
|
93
94
|
},
|
|
94
95
|
editing: {
|
|
95
96
|
component: 'issue-form-panel',
|
|
96
|
-
componentArguments: [{ isResizable: true }, { width: '
|
|
97
|
+
componentArguments: [{ isResizable: true }, { width: '500px' }],
|
|
97
98
|
},
|
|
98
99
|
},
|
|
99
100
|
};
|
|
@@ -137,11 +138,12 @@ export default class ContextPanelService extends Service {
|
|
|
137
138
|
@action focus(model, intent = 'viewing', options = {}) {
|
|
138
139
|
const modelName = getModelName(model);
|
|
139
140
|
const registry = this.registry[modelName];
|
|
141
|
+
const dynamicArgs = getWithDefault(options, 'args', {});
|
|
140
142
|
|
|
141
143
|
if (registry && registry[intent]) {
|
|
142
144
|
this.currentContext = model;
|
|
143
145
|
this.currentContextRegistry = registry[intent];
|
|
144
|
-
this.currentContextComponentArguments = this.createDynamicArgsFromRegistry(registry[intent], model);
|
|
146
|
+
this.currentContextComponentArguments = this.createDynamicArgsFromRegistry(registry[intent], model, dynamicArgs);
|
|
145
147
|
this.contextOptions = options;
|
|
146
148
|
}
|
|
147
149
|
}
|
|
@@ -212,7 +214,7 @@ export default class ContextPanelService extends Service {
|
|
|
212
214
|
* @param {Object} model - The model object.
|
|
213
215
|
* @returns {Object} The dynamic arguments.
|
|
214
216
|
*/
|
|
215
|
-
createDynamicArgsFromRegistry(registry, model) {
|
|
217
|
+
createDynamicArgsFromRegistry(registry, model, additionalArgs = {}) {
|
|
216
218
|
// Generate dynamic arguments object
|
|
217
219
|
const dynamicArgs = {};
|
|
218
220
|
const componentArguments = registry.componentArguments || [];
|
|
@@ -228,6 +230,9 @@ export default class ContextPanelService extends Service {
|
|
|
228
230
|
}
|
|
229
231
|
});
|
|
230
232
|
|
|
233
|
+
// Merge additional args
|
|
234
|
+
Object.assign(dynamicArgs, additionalArgs);
|
|
235
|
+
|
|
231
236
|
return dynamicArgs;
|
|
232
237
|
}
|
|
233
238
|
}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import Service, { inject as service } from '@ember/service';
|
|
2
|
+
import leafletIcon from '@fleetbase/ember-core/utils/leaflet-icon';
|
|
3
|
+
import getWithDefault from '@fleetbase/ember-core/utils/get-with-default';
|
|
4
|
+
import config from '../config/environment';
|
|
5
|
+
|
|
6
|
+
export default class DriverActionsService extends Service {
|
|
7
|
+
@service modalsManager;
|
|
8
|
+
@service universe;
|
|
9
|
+
@service crud;
|
|
10
|
+
|
|
11
|
+
assignOrder(driver, options = {}) {
|
|
12
|
+
this.modalsManager.show('modals/driver-assign-order', {
|
|
13
|
+
title: `Assign Order to this Driver`,
|
|
14
|
+
acceptButtonText: 'Assign Order',
|
|
15
|
+
acceptButtonIcon: 'check',
|
|
16
|
+
acceptButtonIconPrefix: 'fas',
|
|
17
|
+
acceptButtonDisabled: true,
|
|
18
|
+
hideDeclineButton: true,
|
|
19
|
+
selectedOrder: null,
|
|
20
|
+
selectOrder: (order) => {
|
|
21
|
+
this.modalsManager.setOption('selectedOrder', order);
|
|
22
|
+
this.modalsManager.setOption('acceptButtonDisabled', false);
|
|
23
|
+
},
|
|
24
|
+
driver,
|
|
25
|
+
confirm: (modal) => {
|
|
26
|
+
const selectedOrder = modal.getOption('selectedOrder');
|
|
27
|
+
if (!selectedOrder) {
|
|
28
|
+
this.notifications.warning('No order selected!');
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
modal.startLoading();
|
|
33
|
+
driver.set('current_job_uuid', selectedOrder.id);
|
|
34
|
+
|
|
35
|
+
return driver
|
|
36
|
+
.save()
|
|
37
|
+
.then(() => {
|
|
38
|
+
this.notifications.success(`${driver.name} assigned to order.`);
|
|
39
|
+
})
|
|
40
|
+
.catch((error) => {
|
|
41
|
+
driver.rollbackAttributes();
|
|
42
|
+
modal.stopLoading();
|
|
43
|
+
this.notifications.serverError(error);
|
|
44
|
+
});
|
|
45
|
+
},
|
|
46
|
+
...options,
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
assignVehicle(driver, options = {}) {
|
|
51
|
+
this.modalsManager.show('modals/driver-assign-vehicle', {
|
|
52
|
+
title: `Assign Vehicle to this Driver`,
|
|
53
|
+
acceptButtonText: 'Confirm & Create',
|
|
54
|
+
acceptButtonIcon: 'check',
|
|
55
|
+
acceptButtonIconPrefix: 'fas',
|
|
56
|
+
hideDeclineButton: true,
|
|
57
|
+
driver,
|
|
58
|
+
confirm: (modal) => {
|
|
59
|
+
modal.startLoading();
|
|
60
|
+
|
|
61
|
+
return driver
|
|
62
|
+
.save()
|
|
63
|
+
.then((driver) => {
|
|
64
|
+
this.notifications.success(`${driver.name} assigned to vehicle.`);
|
|
65
|
+
})
|
|
66
|
+
.catch((error) => {
|
|
67
|
+
driver.rollbackAttributes();
|
|
68
|
+
modal.stopLoading();
|
|
69
|
+
this.notifications.serverError(error);
|
|
70
|
+
});
|
|
71
|
+
},
|
|
72
|
+
...options,
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
locate(driver, options = {}) {
|
|
77
|
+
const { location } = driver;
|
|
78
|
+
const [latitude, longitude] = location.coordinates;
|
|
79
|
+
|
|
80
|
+
this.modalsManager.show('modals/point-map', {
|
|
81
|
+
title: `Current Location of ${driver.name}`,
|
|
82
|
+
acceptButtonText: 'Done',
|
|
83
|
+
acceptButtonIcon: 'check',
|
|
84
|
+
acceptButtonIconPrefix: 'fas',
|
|
85
|
+
modalClass: 'modal-md',
|
|
86
|
+
hideDeclineButton: true,
|
|
87
|
+
latitude,
|
|
88
|
+
longitude,
|
|
89
|
+
location,
|
|
90
|
+
popupText: `${driver.name} (${driver.public_id})`,
|
|
91
|
+
icon: leafletIcon({
|
|
92
|
+
iconUrl: getWithDefault(driver, 'vehicle_avatar', getWithDefault(config, 'defaultValues.vehicleAvatar')),
|
|
93
|
+
iconSize: [40, 40],
|
|
94
|
+
}),
|
|
95
|
+
...options,
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
delete(driver, options = {}) {
|
|
100
|
+
this.crud.delete(driver, {
|
|
101
|
+
onSuccess: () => {
|
|
102
|
+
this.universe.trigger('fleet-ops.driver.deleted', driver);
|
|
103
|
+
},
|
|
104
|
+
...options,
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import Service, { inject as service } from '@ember/service';
|
|
2
|
+
import leafletIcon from '@fleetbase/ember-core/utils/leaflet-icon';
|
|
3
|
+
import getWithDefault from '@fleetbase/ember-core/utils/get-with-default';
|
|
4
|
+
import config from '../config/environment';
|
|
5
|
+
|
|
6
|
+
export default class VehicleActionsService extends Service {
|
|
7
|
+
@service modalsManager;
|
|
8
|
+
@service universe;
|
|
9
|
+
@service crud;
|
|
10
|
+
|
|
11
|
+
locate(vehicle, options = {}) {
|
|
12
|
+
const { location } = vehicle;
|
|
13
|
+
const [latitude, longitude] = location.coordinates;
|
|
14
|
+
|
|
15
|
+
this.modalsManager.show('modals/point-map', {
|
|
16
|
+
title: `Current Location of ${vehicle.displayName}`,
|
|
17
|
+
acceptButtonText: 'Done',
|
|
18
|
+
acceptButtonIcon: 'check',
|
|
19
|
+
acceptButtonIconPrefix: 'fas',
|
|
20
|
+
modalClass: 'modal-md',
|
|
21
|
+
hideDeclineButton: true,
|
|
22
|
+
latitude,
|
|
23
|
+
longitude,
|
|
24
|
+
location,
|
|
25
|
+
popupText: `${vehicle.displayName} (${vehicle.public_id})`,
|
|
26
|
+
icon: leafletIcon({
|
|
27
|
+
iconUrl: getWithDefault(vehicle, 'avatar', getWithDefault(config, 'defaultValues.vehicleAvatar')),
|
|
28
|
+
iconSize: [40, 40],
|
|
29
|
+
}),
|
|
30
|
+
...options,
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
delete(vehicle, options = {}) {
|
|
35
|
+
this.crud.delete(vehicle, {
|
|
36
|
+
onSuccess: () => {
|
|
37
|
+
this.universe.trigger('fleet-ops.vehicle.deleted', vehicle);
|
|
38
|
+
},
|
|
39
|
+
...options,
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
}
|
|
@@ -34,19 +34,29 @@ body[data-theme='dark'] .scheduler-left-sidebar {
|
|
|
34
34
|
overflow: visible !important;
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
+
.next-content-panel-body > .next-content-panel-body-inner > a.next-nav-item > .next-nav-item-icon-container > svg.online-status,
|
|
38
|
+
.next-content-panel-body > .next-content-panel-body-inner > a.next-nav-item > .next-nav-item-icon-container > svg.text-green-500,
|
|
37
39
|
.next-fleet-summary-fleet .next-content-panel-body > .next-content-panel-body-inner > a.next-nav-item > .next-nav-item-icon-container > svg.text-green-500 {
|
|
38
40
|
color: rgb(34 197 94) !important;
|
|
39
41
|
}
|
|
40
42
|
|
|
43
|
+
.next-content-panel-body > .next-content-panel-body-inner > a.next-nav-item > .next-nav-item-icon-container > svg.idle-status,
|
|
44
|
+
.next-content-panel-body > .next-content-panel-body-inner > a.next-nav-item > .next-nav-item-icon-container > svg.text-yellow-200,
|
|
41
45
|
.next-fleet-summary-fleet .next-content-panel-body > .next-content-panel-body-inner > a.next-nav-item > .next-nav-item-icon-container > svg.text-yellow-200 {
|
|
42
46
|
color: rgb(254 240 138) !important;
|
|
43
47
|
}
|
|
44
48
|
|
|
45
49
|
.next-fleet-summary {
|
|
46
|
-
--fleet-summary-toggle-base-padding:
|
|
47
|
-
--fleet-summary-nav-item-base-padding: 1.
|
|
50
|
+
--fleet-summary-toggle-base-padding: 1.5rem;
|
|
51
|
+
--fleet-summary-nav-item-base-padding: 1.5rem;
|
|
48
52
|
}
|
|
49
53
|
|
|
54
|
+
.next-sidebar-panel-container.next-driver-listing > .next-sidebar-panel > .next-content-panel > .next-sidebar-panel-toggle,
|
|
50
55
|
.next-sidebar .next-sidebar-panel-container.next-fleet-summary > .next-sidebar-panel > .next-content-panel > .next-sidebar-panel-toggle {
|
|
51
56
|
padding-left: 2rem;
|
|
52
57
|
}
|
|
58
|
+
|
|
59
|
+
.next-sidebar-panel-container.next-driver-listing > .next-sidebar-panel > .next-content-panel > .next-content-panel-body .next-nav-item,
|
|
60
|
+
.next-sidebar .next-sidebar-panel-container.next-driver-listing > .next-sidebar-panel > .next-content-panel > .next-sidebar-panel-body .next-nav-item.driver-nav-item {
|
|
61
|
+
padding-left: 3.5rem;
|
|
62
|
+
}
|
|
@@ -256,7 +256,7 @@
|
|
|
256
256
|
|
|
257
257
|
<div class="flex-row space-x-2 pr-0.5">
|
|
258
258
|
{{#if this.payload.pickup}}
|
|
259
|
-
<a href="javascript:;" {{on "click" (fn this.
|
|
259
|
+
<a href="javascript:;" {{on "click" (fn this.editPlace this.payload.pickup)}}>
|
|
260
260
|
<FaIcon @icon="edit" />
|
|
261
261
|
</a>
|
|
262
262
|
<a href="javascript:;" {{on "click" (fn this.setPayloadPlace "pickup" null)}}>
|
|
@@ -287,7 +287,7 @@
|
|
|
287
287
|
|
|
288
288
|
<div class="flex-row space-x-2 pr-0.5">
|
|
289
289
|
{{#if this.payload.dropoff}}
|
|
290
|
-
<a href="javascript:;" {{on "click" (fn this.
|
|
290
|
+
<a href="javascript:;" {{on "click" (fn this.editPlace this.payload.dropoff)}}>
|
|
291
291
|
<FaIcon @icon="edit" />
|
|
292
292
|
</a>
|
|
293
293
|
<a href="javascript:;" {{on "click" (fn this.setPayloadPlace "dropoff" null)}}>
|
|
@@ -317,7 +317,7 @@
|
|
|
317
317
|
<label>Return</label>
|
|
318
318
|
|
|
319
319
|
{{#if this.payload.return}}
|
|
320
|
-
<a href="javascript:;" {{on "click" (fn this.
|
|
320
|
+
<a href="javascript:;" {{on "click" (fn this.editPlace this.payload.return)}}>Edit Address</a>
|
|
321
321
|
{{/if}}
|
|
322
322
|
</div>
|
|
323
323
|
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { isBlank } from '@ember/utils';
|
|
2
|
+
|
|
1
3
|
export default function flyToLeafletLayer(map, layer, zoom, options = {}) {
|
|
2
4
|
if (!map || !layer) {
|
|
3
5
|
return;
|
|
@@ -18,6 +20,11 @@ export default function flyToLeafletLayer(map, layer, zoom, options = {}) {
|
|
|
18
20
|
}
|
|
19
21
|
}
|
|
20
22
|
|
|
23
|
+
// set `flyTo` duration
|
|
24
|
+
if (isBlank(options.duration)) {
|
|
25
|
+
options.duration = 5.5;
|
|
26
|
+
}
|
|
27
|
+
|
|
21
28
|
// Check if we have a valid LatLng
|
|
22
29
|
if (targetLatLng) {
|
|
23
30
|
map.flyTo(targetLatLng, zoom, options);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from '@fleetbase/fleetops-engine/components/layout/fleet-ops-sidebar/driver-listing';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from '@fleetbase/fleetops-engine/services/driver-actions';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from '@fleetbase/fleetops-engine/services/vehicle-actions';
|
package/composer.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fleetbase/fleetops-api",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.9",
|
|
4
4
|
"description": "Fleet & Transport Management Extension for Fleetbase",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"fleetbase-extension",
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
],
|
|
23
23
|
"require": {
|
|
24
24
|
"php": "^7.4|^8.0",
|
|
25
|
-
"fleetbase/core-api": "^1.3.
|
|
25
|
+
"fleetbase/core-api": "^1.3.7",
|
|
26
26
|
"barryvdh/laravel-dompdf": "^2.0",
|
|
27
27
|
"brick/geo": "0.7.2",
|
|
28
28
|
"cknow/laravel-money": "^7.1",
|
package/extension.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fleetbase/fleetops-engine",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.9",
|
|
4
4
|
"description": "Fleet & Transport Management Extension for Fleetbase",
|
|
5
5
|
"fleetbase": {
|
|
6
6
|
"route": "fleet-ops",
|
|
@@ -42,9 +42,9 @@
|
|
|
42
42
|
},
|
|
43
43
|
"dependencies": {
|
|
44
44
|
"@babel/core": "^7.23.2",
|
|
45
|
-
"@fleetbase/ember-core": "^0.
|
|
46
|
-
"@fleetbase/ember-ui": "^0.2.
|
|
47
|
-
"@fleetbase/fleetops-data": "^0.1.
|
|
45
|
+
"@fleetbase/ember-core": "^0.2.0",
|
|
46
|
+
"@fleetbase/ember-ui": "^0.2.9",
|
|
47
|
+
"@fleetbase/fleetops-data": "^0.1.7",
|
|
48
48
|
"@fleetbase/leaflet-routing-machine": "^3.2.16",
|
|
49
49
|
"@fortawesome/ember-fontawesome": "^0.4.1",
|
|
50
50
|
"@fortawesome/fontawesome-svg-core": "^6.4.0",
|
|
@@ -3,16 +3,60 @@
|
|
|
3
3
|
namespace Fleetbase\FleetOps\Exceptions;
|
|
4
4
|
|
|
5
5
|
use Fleetbase\FleetOps\Models\IntegratedVendor;
|
|
6
|
+
use Illuminate\Contracts\Support\Responsable;
|
|
7
|
+
use Illuminate\Http\JsonResponse;
|
|
6
8
|
|
|
7
|
-
|
|
9
|
+
/**
|
|
10
|
+
* Class IntegratedVendorException
|
|
11
|
+
*
|
|
12
|
+
* Custom exception class for IntegratedVendor-related exceptions.
|
|
13
|
+
*
|
|
14
|
+
* @package Fleetbase\FleetOps\Exceptions
|
|
15
|
+
*/
|
|
16
|
+
class IntegratedVendorException extends \Exception implements Responsable
|
|
8
17
|
{
|
|
18
|
+
/**
|
|
19
|
+
* @var IntegratedVendor|null The IntegratedVendor instance associated with the exception.
|
|
20
|
+
*/
|
|
9
21
|
public ?IntegratedVendor $integratedVendor;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* @var string The trigger method that caused the exception.
|
|
25
|
+
*/
|
|
10
26
|
public string $triggerMethod;
|
|
11
27
|
|
|
28
|
+
/**
|
|
29
|
+
* IntegratedVendorException constructor.
|
|
30
|
+
*
|
|
31
|
+
* @param string $message The exception message.
|
|
32
|
+
* @param IntegratedVendor|null $integratedVendor The IntegratedVendor instance associated with the exception.
|
|
33
|
+
* @param string|null $triggerMethod The trigger method that caused the exception.
|
|
34
|
+
* @param int $code The exception code.
|
|
35
|
+
* @param \Throwable|null $previous The previous throwable used for the exception chaining.
|
|
36
|
+
*/
|
|
12
37
|
public function __construct(string $message = '', IntegratedVendor $integratedVendor = null, string $triggerMethod = null, int $code = 400, \Throwable $previous = null)
|
|
13
38
|
{
|
|
14
39
|
parent::__construct($message, $code, $previous);
|
|
15
40
|
$this->integratedVendor = $integratedVendor;
|
|
16
41
|
$this->triggerMethod = $triggerMethod;
|
|
17
42
|
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Get the response representing the exception.
|
|
46
|
+
*
|
|
47
|
+
* @param \Illuminate\Http\Request $request
|
|
48
|
+
* @return \Illuminate\Http\JsonResponse
|
|
49
|
+
*/
|
|
50
|
+
public function toResponse($request)
|
|
51
|
+
{
|
|
52
|
+
$errorMessage = $this->getMessage();
|
|
53
|
+
|
|
54
|
+
return new JsonResponse(
|
|
55
|
+
[
|
|
56
|
+
'errors' => [$errorMessage],
|
|
57
|
+
'integratedVendorId' => data_get($this->integratedVendor, 'uuid')
|
|
58
|
+
],
|
|
59
|
+
400
|
|
60
|
+
);
|
|
61
|
+
}
|
|
18
62
|
}
|
|
@@ -447,9 +447,9 @@ class DriverController extends Controller
|
|
|
447
447
|
}
|
|
448
448
|
|
|
449
449
|
// check if user exists
|
|
450
|
-
$user = User::
|
|
450
|
+
$user = User::whereHas('driver')->where(function ($query) use ($identity) {
|
|
451
451
|
$query->where('phone', $identity);
|
|
452
|
-
$query->orWhere('
|
|
452
|
+
$query->orWhere('email', $identity);
|
|
453
453
|
})->first();
|
|
454
454
|
|
|
455
455
|
if (!$user) {
|