@fleetbase/fleetops-engine 0.3.8 → 0.4.0

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 (58) hide show
  1. package/addon/components/contact-form-panel.hbs +4 -1
  2. package/addon/components/contact-panel.hbs +1 -1
  3. package/addon/components/driver-form-panel.hbs +5 -12
  4. package/addon/components/driver-panel.hbs +4 -1
  5. package/addon/components/fleet-form-panel.hbs +4 -1
  6. package/addon/components/fleet-listing-panel.hbs +2 -2
  7. package/addon/components/fleet-panel.hbs +1 -1
  8. package/addon/components/fuel-report-form-panel.hbs +4 -1
  9. package/addon/components/fuel-report-panel.hbs +4 -1
  10. package/addon/components/issue-form-panel.hbs +4 -1
  11. package/addon/components/issue-panel.hbs +4 -1
  12. package/addon/components/layout/fleet-ops-sidebar/driver-listing.hbs +5 -0
  13. package/addon/components/layout/fleet-ops-sidebar/driver-listing.js +122 -0
  14. package/addon/components/layout/fleet-ops-sidebar/fleet-listing.hbs +2 -2
  15. package/addon/components/layout/fleet-ops-sidebar/fleet-listing.js +69 -49
  16. package/addon/components/layout/fleet-ops-sidebar.hbs +1 -1
  17. package/addon/components/layout/fleet-ops-sidebar.js +4 -3
  18. package/addon/components/live-map.hbs +90 -9
  19. package/addon/components/live-map.js +28 -11
  20. package/addon/components/map-container/toolbar/zones-panel.js +16 -13
  21. package/addon/components/place-form-panel.hbs +4 -1
  22. package/addon/components/place-panel.hbs +4 -1
  23. package/addon/components/settings-window.hbs +1 -1
  24. package/addon/components/vehicle-form-panel.hbs +4 -1
  25. package/addon/components/vehicle-panel.hbs +4 -1
  26. package/addon/components/vendor-form-panel.hbs +4 -1
  27. package/addon/components/vendor-panel.hbs +4 -1
  28. package/addon/controllers/management/drivers/index.js +10 -90
  29. package/addon/controllers/management/vehicles/index.js +11 -21
  30. package/addon/controllers/operations/orders/index/new.js +5 -5
  31. package/addon/controllers/operations/orders/index/view.js +9 -13
  32. package/addon/helpers/format-point.js +5 -2
  33. package/addon/helpers/point-to-coordinates.js +6 -2
  34. package/addon/services/context-panel.js +23 -18
  35. package/addon/services/driver-actions.js +107 -0
  36. package/addon/services/vehicle-actions.js +42 -0
  37. package/addon/styles/fleetops-engine.css +12 -2
  38. package/addon/templates/operations/orders/index/new.hbs +3 -3
  39. package/addon/utils/fly-to-leaflet-layer.js +7 -0
  40. package/app/components/layout/fleet-ops-sidebar/driver-listing.js +1 -0
  41. package/app/services/driver-actions.js +1 -0
  42. package/app/services/vehicle-actions.js +1 -0
  43. package/composer.json +2 -2
  44. package/extension.json +1 -1
  45. package/package.json +4 -4
  46. package/server/src/Console/Commands/FixDriverCompanies.php +65 -0
  47. package/server/src/Exceptions/IntegratedVendorException.php +44 -1
  48. package/server/src/Http/Controllers/Api/v1/DriverController.php +43 -34
  49. package/server/src/Http/Controllers/Internal/v1/DriverController.php +42 -5
  50. package/server/src/Http/Controllers/Internal/v1/LiveController.php +3 -10
  51. package/server/src/Http/Controllers/Internal/v1/NavigatorController.php +1 -1
  52. package/server/src/Http/Resources/v1/Driver.php +1 -1
  53. package/server/src/Providers/FleetOpsServiceProvider.php +1 -0
  54. package/server/src/Support/Flow.php +19 -2
  55. package/addon/helpers/extract-coordinates.js +0 -6
  56. package/addon/utils/extract-coordinates.js +0 -1
  57. package/app/helpers/extract-coordinates.js +0 -1
  58. 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('extractedLatLng'))
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('fleetops.livemap.ready', () => {
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('extractedLatLng'));
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 optimizedWaypointMarker = new L.Marker(extractCoordinates(optimizedWaypoint.location)).addTo(leafletMap);
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('fleetops.livemap.has_coordinates', this, displayOrderRoute);
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('fleetops.livemap.has_coordinates');
248
+ const isListening = this.universe.has('fleet-ops.live-map.has_coordinates');
256
249
 
257
250
  if (isListening) {
258
- this.universe.off('fleetops.livemap.has_coordinates', this, displayOrderRoute);
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
- this.placesController.editPlace(place, {
476
- onFinish: () => {
477
- this.editOrderRoute(order);
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
- const [latitude, longitude] = extractCoordinates(point.coordinates);
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 extractCoordinates from '../utils/extract-coordinates';
2
+ import { isArray } from '@ember/array';
3
3
 
4
4
  export default helper(function pointToCoordinates([point, format = 'array']) {
5
- const [latitude, longitude] = extractCoordinates(point?.coordinates);
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: '600px' }],
23
+ componentArguments: [{ isResizable: true }, { width: '500px' }],
23
24
  },
24
25
  editing: {
25
26
  component: 'driver-form-panel',
26
- componentArguments: [{ isResizable: true }, { width: '600px' }],
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: '600px' }],
33
+ componentArguments: [{ isResizable: true }, { width: '500px' }],
33
34
  },
34
35
  editing: {
35
36
  component: 'vehicle-form-panel',
36
- componentArguments: [{ isResizable: true }, { width: '600px' }],
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: '600px' }],
43
+ componentArguments: [{ isResizable: true }, { width: '500px' }],
43
44
  },
44
45
  editing: {
45
46
  component: 'fleet-form-panel',
46
- componentArguments: [{ isResizable: true }, { width: '600px' }],
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: '600px' }],
53
+ componentArguments: [{ isResizable: true }, { width: '500px' }],
53
54
  },
54
55
  editing: {
55
56
  component: 'fuel-report-form-panel',
56
- componentArguments: [{ isResizable: true }, { width: '600px' }],
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: '600px' }],
63
+ componentArguments: [{ isResizable: true }, { width: '500px' }],
63
64
  },
64
65
  editing: {
65
66
  component: 'vendor-form-panel',
66
- componentArguments: [{ isResizable: true }, { width: '600px' }],
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: '600px' }],
73
+ componentArguments: [{ isResizable: true }, { width: '500px' }],
73
74
  },
74
75
  editing: {
75
76
  component: 'contact-form-panel',
76
- componentArguments: [{ isResizable: true }, { width: '600px' }],
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: '600px' }],
83
+ componentArguments: [{ isResizable: true }, { width: '500px' }],
83
84
  },
84
85
  editing: {
85
86
  component: 'place-form-panel',
86
- componentArguments: [{ isResizable: true }, { width: '600px' }],
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: '600px' }],
93
+ componentArguments: [{ isResizable: true }, { width: '500px' }],
93
94
  },
94
95
  editing: {
95
96
  component: 'issue-form-panel',
96
- componentArguments: [{ isResizable: true }, { width: '600px' }],
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: 2rem;
47
- --fleet-summary-nav-item-base-padding: 1.25rem;
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.placesController.editPlace this.payload.pickup)}}>
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.placesController.editPlace this.payload.dropoff)}}>
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.placesController.editPlace this.payload.return)}}>Edit Address</a>
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.8",
3
+ "version": "0.4.0",
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.6",
25
+ "fleetbase/core-api": "^1.3.10",
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "Fleet-Ops",
3
- "version": "0.3.8",
3
+ "version": "0.4.0",
4
4
  "description": "Fleet & Transport Management Extension for Fleetbase",
5
5
  "repository": "https://github.com/fleetbase/fleetops",
6
6
  "license": "MIT",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fleetbase/fleetops-engine",
3
- "version": "0.3.8",
3
+ "version": "0.4.0",
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.1.9",
46
- "@fleetbase/ember-ui": "^0.2.8",
47
- "@fleetbase/fleetops-data": "^0.1.6",
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",
@@ -0,0 +1,65 @@
1
+ <?php
2
+
3
+ namespace Fleetbase\FleetOps\Console\Commands;
4
+
5
+ use Fleetbase\FleetOps\Models\Driver;
6
+ use Fleetbase\Models\Company;
7
+ use Fleetbase\Models\CompanyUser;
8
+ use Illuminate\Console\Command;
9
+
10
+ class FixDriverCompanies extends Command
11
+ {
12
+ /**
13
+ * The name and signature of the console command.
14
+ *
15
+ * @var string
16
+ */
17
+ protected $signature = 'fleetops:fix-driver-companies';
18
+
19
+ /**
20
+ * The console command description.
21
+ *
22
+ * @var string
23
+ */
24
+ protected $description = 'This is a command which checks driver\'s users to make sure they are assigned to company, if not it assigns the user to the drivers company';
25
+
26
+ /**
27
+ * Execute the console command.
28
+ *
29
+ * This method is responsible for the main logic of the command.
30
+ * It fetches dispatchable orders, notifies about the current time and number of orders,
31
+ * and then dispatches each order if there are nearby drivers.
32
+ *
33
+ * @return int
34
+ */
35
+ public function handle()
36
+ {
37
+ $drivers = Driver::whereHas('user', function ($query) {
38
+ $query->whereNull('company_uuid');
39
+ $query->withTrashed();
40
+ })->with(['user'])->get();
41
+
42
+ // Fix these drivers
43
+ foreach ($drivers as $driver) {
44
+ $user = $driver->user;
45
+ if ($user) {
46
+ $this->line('Found user ' . $user->name . ' (' . $user->email . ') which has no company assigned');
47
+ // Get company from driver profile
48
+ $company = Company::where('uuid', $driver->company_uuid)->first();
49
+ if ($company) {
50
+ $user->assignCompany($company);
51
+
52
+ // create company user
53
+ CompanyUser::create([
54
+ 'user_uuid' => $user->uuid,
55
+ 'company_uuid' => $company->uuid,
56
+ 'status' => 'active',
57
+ ]);
58
+
59
+ // Inform
60
+ $this->line('User ' . $user->email . ' was assigned to company: ' . $company->name);
61
+ }
62
+ }
63
+ }
64
+ }
65
+ }