@fleetbase/fleetops-engine 0.2.1 → 0.2.3
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/driver-card.hbs +1 -1
- package/addon/components/leaflet-drift-marker.js +53 -0
- package/addon/components/live-map.hbs +17 -4
- package/addon/components/live-map.js +121 -20
- package/addon/components/map-container/toolbar.hbs +6 -0
- package/addon/controllers/management/contacts/index.js +3 -3
- package/addon/controllers/management/drivers/index.js +1 -1
- package/addon/controllers/management/vehicles/index.js +1 -1
- package/addon/controllers/operations/orders/index/new.js +68 -21
- package/addon/controllers/operations/orders/index/view.js +16 -5
- package/addon/controllers/operations/orders/index.js +69 -5
- package/addon/controllers/operations/service-rates/index/edit.js +1 -1
- package/addon/controllers/operations/service-rates/index/new.js +10 -11
- package/addon/controllers/operations/service-rates/index.js +8 -0
- package/addon/initializers/load-leaflet-assets.js +6 -1
- package/addon/instance-initializers/register-leaflet-drift-marker.js +17 -0
- package/addon/routes/operations/orders/index/new.js +3 -1
- package/addon/routes/operations/orders/index/view.js +46 -0
- package/addon/routes/operations/service-rates/index/edit.js +7 -0
- package/addon/templates/operations/orders/index.hbs +1 -1
- package/addon/templates/operations/service-rates/index/new.hbs +2 -2
- package/app/components/leaflet-drift-marker.js +1 -0
- package/assets/images/boxes/large.png +0 -0
- package/assets/images/boxes/medium.png +0 -0
- package/assets/images/boxes/small.png +0 -0
- package/assets/images/boxes/x-large.png +0 -0
- package/assets/images/building-marker.png +0 -0
- package/assets/images/map-marker.png +0 -0
- package/index.js +16 -0
- package/package.json +6 -5
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<div class="driver-card flex flex-1"
|
|
1
|
+
<div class="driver-card flex flex-1" ...attributes>
|
|
2
2
|
<a href="javascript:;" class="driver-card-details flex flex-1 bg-black bg-opacity-25 rounded-md px-4 py-3 shadow-sm" {{on "click" this.onClick}}>
|
|
3
3
|
<div class="flex flex-row">
|
|
4
4
|
<div class="mr-3">
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import MarkerLayer from 'ember-leaflet/components/marker-layer';
|
|
2
|
+
|
|
3
|
+
export default class LeafletDriftMarkerComponent extends MarkerLayer {
|
|
4
|
+
leafletOptions = [
|
|
5
|
+
...this.leafletOptions,
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Required, duration im miliseconds marker will take to destination point.
|
|
9
|
+
*
|
|
10
|
+
* @argument duration
|
|
11
|
+
* @type {Number}
|
|
12
|
+
*/
|
|
13
|
+
'duration',
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Makes map view follow marker.
|
|
17
|
+
*
|
|
18
|
+
* @argument keepAtCenter
|
|
19
|
+
* @type {Boolean}
|
|
20
|
+
*/
|
|
21
|
+
'keepAtCenter',
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Rotation angle, in degrees, clockwise.
|
|
25
|
+
*
|
|
26
|
+
* @argument rotationAngle
|
|
27
|
+
* @type {Number}
|
|
28
|
+
*/
|
|
29
|
+
'rotationAngle',
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* The rotation center, as a transform-origin CSS rule.
|
|
33
|
+
*
|
|
34
|
+
* @argument rotationOrigin
|
|
35
|
+
* @type {String}
|
|
36
|
+
*/
|
|
37
|
+
'rotationOrigin',
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* The Public ID of the driver.
|
|
41
|
+
*
|
|
42
|
+
* @argument publicId
|
|
43
|
+
* @type {String}
|
|
44
|
+
*/
|
|
45
|
+
'publicId',
|
|
46
|
+
];
|
|
47
|
+
|
|
48
|
+
createLayer() {
|
|
49
|
+
const { DriftMarker } = window;
|
|
50
|
+
|
|
51
|
+
return new DriftMarker(...this.requiredOptions, this.options);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
@@ -4,11 +4,24 @@
|
|
|
4
4
|
|
|
5
5
|
{{#if this.isDriversVisible}}
|
|
6
6
|
{{#each this.drivers as |driver|}}
|
|
7
|
-
<layers.
|
|
8
|
-
|
|
7
|
+
<layers.drift-marker @rotationAngle={{driver.heading}} @duration={{300}} @icon={{icon iconUrl=driver.vehicle_avatar iconSize=(array 24 24)}} @location={{point-to-coordinates driver.location}} @publicId={{driver.public_id}} @onAdd={{fn this.onAction "onDriverAdded" driver}} as |marker|>
|
|
8
|
+
<marker.popup @maxWidth="500" @minWidth="225">
|
|
9
9
|
<DriverCard @driver={{driver}} @showCoordinates={{true}} @textClass="text-gray-900 dark:text-gray-100" />
|
|
10
|
-
</marker.popup>
|
|
11
|
-
|
|
10
|
+
</marker.popup>
|
|
11
|
+
<marker.tooltip @permanent={{false}} @sticky={{true}}>{{driver.name}}</marker.tooltip>
|
|
12
|
+
</layers.drift-marker>
|
|
13
|
+
{{/each}}
|
|
14
|
+
{{/if}}
|
|
15
|
+
|
|
16
|
+
{{#if this.isPlacesVisible}}
|
|
17
|
+
{{#each this.places as |place|}}
|
|
18
|
+
<layers.marker @icon={{icon iconUrl="/engines-dist/images/building-marker.png" iconSize=(array 16 16)}} @location={{point-to-coordinates place.location}} @riseOnHover={{true}} @title={{place.address}} @alt={{place.address}} as |marker|>
|
|
19
|
+
<marker.popup>
|
|
20
|
+
<div>{{place.address}}</div>
|
|
21
|
+
<div>{{format-point place.location}}</div>
|
|
22
|
+
</marker.popup>
|
|
23
|
+
<marker.tooltip @permanent={{false}} @sticky={{true}} @direction="bottom">{{place.name}}</marker.tooltip>
|
|
24
|
+
</layers.marker>
|
|
12
25
|
{{/each}}
|
|
13
26
|
{{/if}}
|
|
14
27
|
|
|
@@ -25,10 +25,12 @@ export default class LiveMapComponent extends Component {
|
|
|
25
25
|
|
|
26
26
|
@tracked routes = [];
|
|
27
27
|
@tracked drivers = [];
|
|
28
|
+
@tracked places = [];
|
|
28
29
|
@tracked channels = [];
|
|
29
30
|
@tracked isLoading = true;
|
|
30
31
|
@tracked isReady = false;
|
|
31
32
|
@tracked isDriversVisible = true;
|
|
33
|
+
@tracked isPlacesVisible = true;
|
|
32
34
|
@tracked isRoutesVisible = true;
|
|
33
35
|
@tracked isDrawControlsVisible = false;
|
|
34
36
|
@tracked isCreatingServiceArea = false;
|
|
@@ -105,10 +107,12 @@ export default class LiveMapComponent extends Component {
|
|
|
105
107
|
|
|
106
108
|
this.routes = await this.fetchActiveRoutes();
|
|
107
109
|
this.drivers = await this.fetchActiveDrivers();
|
|
110
|
+
this.places = await this.fetchActivePlaces();
|
|
108
111
|
this.serviceAreaRecords = await this.fetchServiceAreas();
|
|
109
112
|
this.isReady = true;
|
|
110
113
|
|
|
111
114
|
this.watchDrivers(this.drivers);
|
|
115
|
+
this.listenForOrders();
|
|
112
116
|
|
|
113
117
|
if (typeof this.args.onReady === 'function') {
|
|
114
118
|
this.args.onReady(this);
|
|
@@ -331,6 +335,11 @@ export default class LiveMapComponent extends Component {
|
|
|
331
335
|
@action onDriverAdded(driver, event) {
|
|
332
336
|
const { target } = event;
|
|
333
337
|
|
|
338
|
+
// set the marker instance to the driver model
|
|
339
|
+
set(driver, '_marker', target);
|
|
340
|
+
|
|
341
|
+
console.log('onDriverAdded()', ...arguments);
|
|
342
|
+
|
|
334
343
|
this.createContextMenuForDriver(driver, target);
|
|
335
344
|
}
|
|
336
345
|
|
|
@@ -478,6 +487,18 @@ export default class LiveMapComponent extends Component {
|
|
|
478
487
|
this.isDriversVisible = !this.isDriversVisible;
|
|
479
488
|
}
|
|
480
489
|
|
|
490
|
+
@action hidePlaces() {
|
|
491
|
+
this.isPlacesVisible = false;
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
@action showPlaces() {
|
|
495
|
+
this.isPlacesVisible = true;
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
@action togglePlaces() {
|
|
499
|
+
this.isPlacesVisible = !this.isPlacesVisible;
|
|
500
|
+
}
|
|
501
|
+
|
|
481
502
|
@action hideRoutes() {
|
|
482
503
|
this.isRoutesVisible = false;
|
|
483
504
|
}
|
|
@@ -706,6 +727,30 @@ export default class LiveMapComponent extends Component {
|
|
|
706
727
|
* Functions are used to fetch date or handle socket callbacks/initializations.
|
|
707
728
|
*
|
|
708
729
|
*/
|
|
730
|
+
@action async listenForOrders() {
|
|
731
|
+
// setup socket
|
|
732
|
+
const socket = this.socket.instance();
|
|
733
|
+
|
|
734
|
+
// listen on company channel
|
|
735
|
+
const channelId = `company.${this.currentUser.companyId}`;
|
|
736
|
+
const channel = socket.subscribe(channelId);
|
|
737
|
+
|
|
738
|
+
// track channel
|
|
739
|
+
this.channels.pushObject(channel);
|
|
740
|
+
|
|
741
|
+
// listen to channel for events
|
|
742
|
+
await channel.listener('subscribe').once();
|
|
743
|
+
|
|
744
|
+
// get incoming data and console out
|
|
745
|
+
(async () => {
|
|
746
|
+
for await (let output of channel) {
|
|
747
|
+
const { event, data } = output;
|
|
748
|
+
|
|
749
|
+
console.log(`[channel ${channelId}]`, output, event, data);
|
|
750
|
+
}
|
|
751
|
+
})();
|
|
752
|
+
}
|
|
753
|
+
|
|
709
754
|
@action watchDrivers(drivers = []) {
|
|
710
755
|
// setup socket
|
|
711
756
|
const socket = this.socket.instance();
|
|
@@ -719,29 +764,54 @@ export default class LiveMapComponent extends Component {
|
|
|
719
764
|
|
|
720
765
|
@action async listenForDriver(driver, socket) {
|
|
721
766
|
// listen on company channel
|
|
722
|
-
const channelId = `driver.${driver.
|
|
767
|
+
const channelId = `driver.${driver.id}`;
|
|
723
768
|
const channel = socket.subscribe(channelId);
|
|
724
769
|
|
|
725
|
-
// debug
|
|
726
|
-
// console.log(`socket subscribed to ${channelId}`);
|
|
727
|
-
|
|
728
770
|
// track channel
|
|
729
771
|
this.channels.pushObject(channel);
|
|
730
772
|
|
|
731
773
|
// listen to channel for events
|
|
732
774
|
await channel.listener('subscribe').once();
|
|
733
775
|
|
|
776
|
+
// Initialize an empty buffer to store incoming events
|
|
777
|
+
const eventBuffer = [];
|
|
778
|
+
|
|
779
|
+
// Time to wait in milliseconds before processing buffered events
|
|
780
|
+
const bufferTime = 1000 * 10;
|
|
781
|
+
|
|
782
|
+
// Function to process buffered events
|
|
783
|
+
const processBuffer = () => {
|
|
784
|
+
// Sort events by created_at
|
|
785
|
+
eventBuffer.sort((a, b) => new Date(a.created_at) - new Date(b.created_at));
|
|
786
|
+
|
|
787
|
+
// Process sorted events
|
|
788
|
+
for (const output of eventBuffer) {
|
|
789
|
+
const { event, data } = output;
|
|
790
|
+
console.log(`${event} - #${data.additionalData.index} (${output.created_at}) [ ${data.location.coordinates.join(' ')} ]`);
|
|
791
|
+
// update driver heading degree
|
|
792
|
+
driver._marker.setRotationAngle(data.heading);
|
|
793
|
+
// move driver's marker to new coordinates
|
|
794
|
+
driver._marker.slideTo(data.location.coordinates, { duration: 2000 });
|
|
795
|
+
}
|
|
796
|
+
|
|
797
|
+
// Clear the buffer
|
|
798
|
+
eventBuffer.length = 0;
|
|
799
|
+
};
|
|
800
|
+
|
|
801
|
+
// Start a timer to process the buffer at intervals
|
|
802
|
+
setInterval(processBuffer, bufferTime);
|
|
803
|
+
|
|
734
804
|
// get incoming data and console out
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
driver.
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
805
|
+
(async () => {
|
|
806
|
+
for await (let output of channel) {
|
|
807
|
+
const { event, data } = output;
|
|
808
|
+
|
|
809
|
+
if (event === 'driver.location_changed' || event === 'driver.simulated_location_changed') {
|
|
810
|
+
// Add the incoming event to the buffer
|
|
811
|
+
eventBuffer.push(output);
|
|
812
|
+
}
|
|
743
813
|
}
|
|
744
|
-
}
|
|
814
|
+
})();
|
|
745
815
|
}
|
|
746
816
|
|
|
747
817
|
@action closeChannels() {
|
|
@@ -814,15 +884,20 @@ export default class LiveMapComponent extends Component {
|
|
|
814
884
|
this.isLoading = true;
|
|
815
885
|
|
|
816
886
|
return new Promise((resolve) => {
|
|
817
|
-
this.fetch
|
|
818
|
-
|
|
887
|
+
this.fetch
|
|
888
|
+
.get('fleet-ops/live/routes')
|
|
889
|
+
.then((routes) => {
|
|
890
|
+
this.isLoading = false;
|
|
819
891
|
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
892
|
+
if (typeof this.args.onRoutesLoaded === 'function') {
|
|
893
|
+
this.args.onRoutesLoaded(routes);
|
|
894
|
+
}
|
|
823
895
|
|
|
824
|
-
|
|
825
|
-
|
|
896
|
+
resolve(routes);
|
|
897
|
+
})
|
|
898
|
+
.catch(() => {
|
|
899
|
+
resolve([]);
|
|
900
|
+
});
|
|
826
901
|
});
|
|
827
902
|
}
|
|
828
903
|
|
|
@@ -839,6 +914,32 @@ export default class LiveMapComponent extends Component {
|
|
|
839
914
|
|
|
840
915
|
resolve(drivers);
|
|
841
916
|
});
|
|
917
|
+
}).catch(() => {
|
|
918
|
+
resolve([]);
|
|
919
|
+
});
|
|
920
|
+
}
|
|
921
|
+
|
|
922
|
+
@action fetchActivePlaces() {
|
|
923
|
+
this.isLoading = true;
|
|
924
|
+
|
|
925
|
+
// get the center of map
|
|
926
|
+
const center = this.leafletMap.getCenter();
|
|
927
|
+
|
|
928
|
+
return new Promise((resolve) => {
|
|
929
|
+
this.fetch
|
|
930
|
+
.get('fleet-ops/live/places', { within: center }, { normalizeToEmberData: true, normalizeModelType: 'place' })
|
|
931
|
+
.then((places) => {
|
|
932
|
+
this.isLoading = false;
|
|
933
|
+
|
|
934
|
+
if (typeof this.args.onPlacesLoaded === 'function') {
|
|
935
|
+
this.args.onPlacesLoaded(places);
|
|
936
|
+
}
|
|
937
|
+
|
|
938
|
+
resolve(places);
|
|
939
|
+
})
|
|
940
|
+
.catch(() => {
|
|
941
|
+
resolve([]);
|
|
942
|
+
});
|
|
842
943
|
});
|
|
843
944
|
}
|
|
844
945
|
|
|
@@ -47,5 +47,11 @@
|
|
|
47
47
|
<MapContainer::Toolbar::ZonesPanel @dd={{dd}} @map={{@map}} @onPressCreateServiceArea={{@onPressCreateServiceArea}} />
|
|
48
48
|
</dd.Content>
|
|
49
49
|
</BasicDropdown>
|
|
50
|
+
<button type="button" class="toolbar-button relative" {{on "click" (fn this.onAction "onPressDisplayPlaces")}}>
|
|
51
|
+
<FaIcon @icon="city" />
|
|
52
|
+
<Attach::Tooltip @class="clean" @animation="scale" @placement="right">
|
|
53
|
+
<InputInfo @text="Toggle Places" @iconClass="hidden" class="py-1 px-2 bg-gray-900 -mt-1" />
|
|
54
|
+
</Attach::Tooltip>
|
|
55
|
+
</button>
|
|
50
56
|
</div>
|
|
51
57
|
</MapContainer::ToolbarContainer>
|
|
@@ -384,13 +384,13 @@ export default class ManagementContactsIndexController extends Controller {
|
|
|
384
384
|
{
|
|
385
385
|
path: `uploads/${contact.company_uuid}/contacts/${contact.slug}`,
|
|
386
386
|
subject_uuid: contact.id,
|
|
387
|
-
subject_type:
|
|
388
|
-
type:
|
|
387
|
+
subject_type: 'contact',
|
|
388
|
+
type: 'contact_photo',
|
|
389
389
|
},
|
|
390
390
|
(uploadedFile) => {
|
|
391
391
|
contact.setProperties({
|
|
392
392
|
photo_uuid: uploadedFile.id,
|
|
393
|
-
photo_url: uploadedFile.
|
|
393
|
+
photo_url: uploadedFile.url,
|
|
394
394
|
photo: uploadedFile,
|
|
395
395
|
});
|
|
396
396
|
}
|
|
@@ -580,7 +580,7 @@ export default class ManagementDriversIndexController extends Controller {
|
|
|
580
580
|
icon: 'headphones',
|
|
581
581
|
action: () => {
|
|
582
582
|
this.modalsManager.done().then(() => {
|
|
583
|
-
this.hostRouter.transitionTo('console.developers
|
|
583
|
+
this.hostRouter.transitionTo('console.developers.sockets.view', `driver.${driver.public_id}`);
|
|
584
584
|
});
|
|
585
585
|
},
|
|
586
586
|
},
|
|
@@ -562,7 +562,7 @@ export default class ManagementVehiclesIndexController extends ManagementControl
|
|
|
562
562
|
(uploadedFile) => {
|
|
563
563
|
vehicle.setProperties({
|
|
564
564
|
photo_uuid: uploadedFile.id,
|
|
565
|
-
photo_url: uploadedFile.
|
|
565
|
+
photo_url: uploadedFile.url,
|
|
566
566
|
photo: uploadedFile,
|
|
567
567
|
});
|
|
568
568
|
}
|
|
@@ -5,7 +5,7 @@ import { action, computed, setProperties, set, get } from '@ember/object';
|
|
|
5
5
|
import { not, equal, alias } from '@ember/object/computed';
|
|
6
6
|
import { isArray } from '@ember/array';
|
|
7
7
|
import { dasherize } from '@ember/string';
|
|
8
|
-
import { later } from '@ember/runloop';
|
|
8
|
+
import { later, next } from '@ember/runloop';
|
|
9
9
|
import { OSRMv1, Control as RoutingControl } from '@fleetbase/leaflet-routing-machine';
|
|
10
10
|
import polyline from '@fleetbase/ember-core/utils/polyline';
|
|
11
11
|
import findClosestWaypoint from '@fleetbase/ember-core/utils/find-closest-waypoint';
|
|
@@ -494,7 +494,9 @@ export default class OperationsOrdersIndexNewController extends Controller {
|
|
|
494
494
|
}
|
|
495
495
|
|
|
496
496
|
@action newPlace() {
|
|
497
|
-
this.placesController
|
|
497
|
+
if (this.placesController) {
|
|
498
|
+
return this.placesController.createPlace();
|
|
499
|
+
}
|
|
498
500
|
}
|
|
499
501
|
|
|
500
502
|
@action async getQuotes(service) {
|
|
@@ -564,26 +566,39 @@ export default class OperationsOrdersIndexNewController extends Controller {
|
|
|
564
566
|
}
|
|
565
567
|
|
|
566
568
|
@action setupInterface() {
|
|
567
|
-
this.leafletMap
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
569
|
+
if (this.leafletMap && this.leafletMap.liveMap) {
|
|
570
|
+
this.leafletMap.liveMap.hideDrivers();
|
|
571
|
+
this.leafletMap.liveMap.hideRoutes();
|
|
572
|
+
|
|
573
|
+
// track all layers added from this view
|
|
574
|
+
this.leafletMap.on('layeradd', ({ layer }) => {
|
|
575
|
+
// disable dragging of layer
|
|
576
|
+
if (layer.dragging && typeof layer.dragging.disable === 'function') {
|
|
577
|
+
layer.dragging.disable();
|
|
578
|
+
}
|
|
574
579
|
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
580
|
+
next(this, function () {
|
|
581
|
+
if (isArray(this.leafletLayers) && !this.leafletLayers.includes(layer)) {
|
|
582
|
+
this.leafletLayers.pushObject(layer);
|
|
583
|
+
}
|
|
584
|
+
});
|
|
585
|
+
});
|
|
586
|
+
} else {
|
|
587
|
+
// setup interface when livemap is ready
|
|
588
|
+
this.universe.on('livemap.ready', () => {
|
|
589
|
+
this.setupInterface();
|
|
590
|
+
});
|
|
591
|
+
}
|
|
579
592
|
|
|
580
593
|
// switch to map mode
|
|
581
594
|
this.ordersController.setLayoutMode('map');
|
|
582
595
|
}
|
|
583
596
|
|
|
584
597
|
@action resetInterface() {
|
|
585
|
-
this.leafletMap
|
|
586
|
-
|
|
598
|
+
if (this.leafletMap && this.leafletMap.liveMap) {
|
|
599
|
+
this.leafletMap.liveMap.showDrivers();
|
|
600
|
+
this.leafletMap.liveMap.showRoutes();
|
|
601
|
+
}
|
|
587
602
|
}
|
|
588
603
|
|
|
589
604
|
@action getRoute() {
|
|
@@ -674,15 +689,47 @@ export default class OperationsOrdersIndexNewController extends Controller {
|
|
|
674
689
|
}
|
|
675
690
|
|
|
676
691
|
@action clearLayers() {
|
|
677
|
-
|
|
692
|
+
if (this.leafletMap) {
|
|
693
|
+
try {
|
|
694
|
+
this.leafletMap.eachLayer((layer) => {
|
|
695
|
+
if (isArray(this.leafletLayers) && this.leafletLayers.includes(layer)) {
|
|
696
|
+
this.leafletMap.removeLayer(layer);
|
|
697
|
+
}
|
|
698
|
+
});
|
|
699
|
+
} catch (error) {
|
|
700
|
+
// fallback method with tracked layers
|
|
701
|
+
if (isArray(this.leafletLayers)) {
|
|
702
|
+
this.leafletLayers.forEach((layer) => {
|
|
703
|
+
try {
|
|
704
|
+
this.leafletMap.removeLayer(layer);
|
|
705
|
+
} catch (error) {
|
|
706
|
+
// silent error just continue with order processing if any
|
|
707
|
+
}
|
|
708
|
+
});
|
|
709
|
+
}
|
|
710
|
+
}
|
|
711
|
+
}
|
|
712
|
+
}
|
|
678
713
|
|
|
679
|
-
|
|
714
|
+
@action clearAllLayers() {
|
|
715
|
+
if (this.leafletMap) {
|
|
680
716
|
try {
|
|
681
|
-
leafletMap.
|
|
717
|
+
this.leafletMap.eachLayer((layer) => {
|
|
718
|
+
this.leafletMap.removeLayer(layer);
|
|
719
|
+
});
|
|
682
720
|
} catch (error) {
|
|
683
|
-
//
|
|
721
|
+
// fallback method with tracked layers
|
|
722
|
+
if (isArray(this.leafletLayers)) {
|
|
723
|
+
this.leafletLayers.forEach((layer) => {
|
|
724
|
+
try {
|
|
725
|
+
this.leafletMap.removeLayer(layer);
|
|
726
|
+
} catch (error) {
|
|
727
|
+
// silent error just continue with order processing if any
|
|
728
|
+
}
|
|
729
|
+
});
|
|
730
|
+
}
|
|
684
731
|
}
|
|
685
|
-
}
|
|
732
|
+
}
|
|
686
733
|
}
|
|
687
734
|
|
|
688
735
|
@action createPlaceArrayFromPayload(payload, waypoints, isMultipleDropoffOrder = false) {
|
|
@@ -1220,7 +1267,7 @@ export default class OperationsOrdersIndexNewController extends Controller {
|
|
|
1220
1267
|
(uploadedFile) => {
|
|
1221
1268
|
entity.setProperties({
|
|
1222
1269
|
photo_uuid: uploadedFile.id,
|
|
1223
|
-
photo_url: uploadedFile.
|
|
1270
|
+
photo_url: uploadedFile.url,
|
|
1224
1271
|
photo: uploadedFile,
|
|
1225
1272
|
});
|
|
1226
1273
|
}
|
|
@@ -81,6 +81,13 @@ export default class OperationsOrdersIndexViewController extends Controller {
|
|
|
81
81
|
*/
|
|
82
82
|
@service hostRouter;
|
|
83
83
|
|
|
84
|
+
/**
|
|
85
|
+
* Inject the `socket` service
|
|
86
|
+
*
|
|
87
|
+
* @var {Service}
|
|
88
|
+
*/
|
|
89
|
+
@service socket;
|
|
90
|
+
|
|
84
91
|
/**
|
|
85
92
|
* Inject the `universe` service
|
|
86
93
|
*
|
|
@@ -162,8 +169,10 @@ export default class OperationsOrdersIndexViewController extends Controller {
|
|
|
162
169
|
}
|
|
163
170
|
|
|
164
171
|
@action resetInterface() {
|
|
165
|
-
this.leafletMap
|
|
166
|
-
|
|
172
|
+
if (this.leafletMap && this.leafletMap.liveMap) {
|
|
173
|
+
this.leafletMap.liveMap.showDrivers();
|
|
174
|
+
this.leafletMap.liveMap.showRoutes();
|
|
175
|
+
}
|
|
167
176
|
}
|
|
168
177
|
|
|
169
178
|
@action removeRoutingControlPreview() {
|
|
@@ -209,8 +218,10 @@ export default class OperationsOrdersIndexViewController extends Controller {
|
|
|
209
218
|
return later(
|
|
210
219
|
this,
|
|
211
220
|
() => {
|
|
212
|
-
this.leafletMap
|
|
213
|
-
|
|
221
|
+
if (this.leafletMap && this.leafletMap.liveMap) {
|
|
222
|
+
this.leafletMap.liveMap.hideDrivers();
|
|
223
|
+
this.leafletMap.liveMap.hideRoutes();
|
|
224
|
+
}
|
|
214
225
|
|
|
215
226
|
// display order route on map
|
|
216
227
|
this.displayOrderRoute();
|
|
@@ -833,7 +844,7 @@ export default class OperationsOrdersIndexViewController extends Controller {
|
|
|
833
844
|
(uploadedFile) => {
|
|
834
845
|
entity.setProperties({
|
|
835
846
|
photo_uuid: uploadedFile.id,
|
|
836
|
-
photo_url: uploadedFile.
|
|
847
|
+
photo_url: uploadedFile.url,
|
|
837
848
|
photo: uploadedFile,
|
|
838
849
|
});
|
|
839
850
|
}
|
|
@@ -80,6 +80,13 @@ export default class OperationsOrdersIndexController extends Controller {
|
|
|
80
80
|
*/
|
|
81
81
|
@service universe;
|
|
82
82
|
|
|
83
|
+
/**
|
|
84
|
+
* Inject the `socket` service
|
|
85
|
+
*
|
|
86
|
+
* @var {Service}
|
|
87
|
+
*/
|
|
88
|
+
@service socket;
|
|
89
|
+
|
|
83
90
|
/**
|
|
84
91
|
* Queryable parameters for this controller's model
|
|
85
92
|
*
|
|
@@ -537,6 +544,54 @@ export default class OperationsOrdersIndexController extends Controller {
|
|
|
537
544
|
},
|
|
538
545
|
];
|
|
539
546
|
|
|
547
|
+
/**
|
|
548
|
+
* Creates an instance of OperationsOrdersIndexController.
|
|
549
|
+
* @memberof OperationsOrdersIndexController
|
|
550
|
+
*/
|
|
551
|
+
constructor() {
|
|
552
|
+
super(...arguments);
|
|
553
|
+
this.listenForOrderEvents();
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
/**
|
|
557
|
+
* Listen for incoming order events to refresh listing.
|
|
558
|
+
*
|
|
559
|
+
* @memberof OperationsOrdersIndexController
|
|
560
|
+
*/
|
|
561
|
+
@action async listenForOrderEvents() {
|
|
562
|
+
// wait for user to be loaded into service
|
|
563
|
+
this.currentUser.on('user.loaded', () => {
|
|
564
|
+
// Get socket instance
|
|
565
|
+
const socket = this.socket.instance();
|
|
566
|
+
|
|
567
|
+
// The channel ID to listen on
|
|
568
|
+
const channelId = `company.${this.currentUser.companyId}`;
|
|
569
|
+
|
|
570
|
+
// Listed on company channel
|
|
571
|
+
const channel = socket.subscribe(channelId);
|
|
572
|
+
|
|
573
|
+
// Events which should trigger refresh
|
|
574
|
+
const listening = ['order.ready', 'order.driver_assigned'];
|
|
575
|
+
|
|
576
|
+
// Listen for channel subscription
|
|
577
|
+
(async () => {
|
|
578
|
+
for await (let output of channel) {
|
|
579
|
+
const { event } = output;
|
|
580
|
+
|
|
581
|
+
// if an order event refresh orders
|
|
582
|
+
if (typeof event === 'string' && listening.includes(event)) {
|
|
583
|
+
this.hostRouter.refresh();
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
})();
|
|
587
|
+
|
|
588
|
+
// disconnect when transitioning
|
|
589
|
+
this.hostRouter.on('routeWillChange', () => {
|
|
590
|
+
channel.close();
|
|
591
|
+
});
|
|
592
|
+
});
|
|
593
|
+
}
|
|
594
|
+
|
|
540
595
|
/**
|
|
541
596
|
* The search task.
|
|
542
597
|
*
|
|
@@ -561,12 +616,21 @@ export default class OperationsOrdersIndexController extends Controller {
|
|
|
561
616
|
this.query = value;
|
|
562
617
|
}
|
|
563
618
|
|
|
564
|
-
@action
|
|
565
|
-
const {
|
|
619
|
+
@action viewPlacesOnMap() {
|
|
620
|
+
const {
|
|
621
|
+
leafletMap: { liveMap },
|
|
622
|
+
} = this;
|
|
566
623
|
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
624
|
+
if (liveMap) {
|
|
625
|
+
liveMap.togglePlaces();
|
|
626
|
+
}
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
@action resetView() {
|
|
630
|
+
if (this.leafletMap && this.leafletMap.liveMap) {
|
|
631
|
+
this.leafletMap.liveMap.hideDrivers();
|
|
632
|
+
this.leafletMap.liveMap.hideRoutes();
|
|
633
|
+
}
|
|
570
634
|
}
|
|
571
635
|
|
|
572
636
|
@action toggleSearch() {
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import OperationsServiceRatesIndexNewController from './new';
|
|
2
2
|
import { tracked } from '@glimmer/tracking';
|
|
3
3
|
import { action } from '@ember/object';
|
|
4
|
-
// import { alias } from '@ember/object/computed';
|
|
5
4
|
|
|
6
5
|
export default class OperationsServiceRatesIndexEditController extends OperationsServiceRatesIndexNewController {
|
|
7
6
|
/**
|
|
@@ -44,6 +43,7 @@ export default class OperationsServiceRatesIndexEditController extends Operation
|
|
|
44
43
|
return this.transitionToRoute('operations.service-rates.index').then(() => {
|
|
45
44
|
this.notifications.success(`Service rate '${serviceRate.service_name}' updated`);
|
|
46
45
|
this.resetForm();
|
|
46
|
+
this.hostRouter.refresh();
|
|
47
47
|
});
|
|
48
48
|
})
|
|
49
49
|
.catch(this.notifications.serverError)
|
|
@@ -1,17 +1,10 @@
|
|
|
1
|
-
import Controller
|
|
1
|
+
import Controller from '@ember/controller';
|
|
2
2
|
import { inject as service } from '@ember/service';
|
|
3
3
|
import { tracked } from '@glimmer/tracking';
|
|
4
4
|
import { action, computed } from '@ember/object';
|
|
5
5
|
import { isBlank } from '@ember/utils';
|
|
6
6
|
|
|
7
7
|
export default class OperationsServiceRatesIndexNewController extends Controller {
|
|
8
|
-
/**
|
|
9
|
-
* Inject the `operations.service-rates.index` controller
|
|
10
|
-
*
|
|
11
|
-
* @var {Controller}
|
|
12
|
-
*/
|
|
13
|
-
@controller('operations.service-rates.index') index;
|
|
14
|
-
|
|
15
8
|
/**
|
|
16
9
|
* Inject the `currentUser` service
|
|
17
10
|
*
|
|
@@ -33,12 +26,19 @@ export default class OperationsServiceRatesIndexNewController extends Controller
|
|
|
33
26
|
*/
|
|
34
27
|
@service loader;
|
|
35
28
|
|
|
29
|
+
/**
|
|
30
|
+
* Inject the `hostRouter` service
|
|
31
|
+
*
|
|
32
|
+
* @var {Service}
|
|
33
|
+
*/
|
|
34
|
+
@service hostRouter;
|
|
35
|
+
|
|
36
36
|
/**
|
|
37
37
|
* The service rate being created.
|
|
38
38
|
*
|
|
39
39
|
* @var {ServiceRateModel}
|
|
40
40
|
*/
|
|
41
|
-
@tracked serviceRate = this.store.createRecord('service-rate');
|
|
41
|
+
@tracked serviceRate = this.store.createRecord('service-rate', { per_meter_unit: 'm' });
|
|
42
42
|
|
|
43
43
|
/**
|
|
44
44
|
* Different service types available, based on order type.
|
|
@@ -300,11 +300,10 @@ export default class OperationsServiceRatesIndexNewController extends Controller
|
|
|
300
300
|
return serviceRate
|
|
301
301
|
.save()
|
|
302
302
|
.then((serviceRate) => {
|
|
303
|
-
this.index.table.addRow(serviceRate);
|
|
304
|
-
|
|
305
303
|
return this.transitionToRoute('operations.service-rates.index').then(() => {
|
|
306
304
|
this.notifications.success(`New Service Rate ${serviceRate.service_name} Created`);
|
|
307
305
|
this.resetForm();
|
|
306
|
+
this.hostRouter.refresh();
|
|
308
307
|
});
|
|
309
308
|
})
|
|
310
309
|
.catch((error) => {
|
|
@@ -56,6 +56,14 @@ export default class OperationsServiceRatesIndexController extends Controller {
|
|
|
56
56
|
*/
|
|
57
57
|
@service modalsManager;
|
|
58
58
|
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Inject the `hostRouter` service
|
|
62
|
+
*
|
|
63
|
+
* @var {Service}
|
|
64
|
+
*/
|
|
65
|
+
@service hostRouter;
|
|
66
|
+
|
|
59
67
|
/**
|
|
60
68
|
* Inject the `loader` service
|
|
61
69
|
*
|
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
export function initialize() {
|
|
2
2
|
const path = '/engines-dist/leaflet/';
|
|
3
|
-
const scripts = ['leaflet.contextmenu.js', 'leaflet.draw-src.js', 'leaflet.rotatedMarker.js'];
|
|
3
|
+
const scripts = ['leaflet.contextmenu.js', 'leaflet.draw-src.js', 'leaflet.rotatedMarker.js', 'leaflet-drift-marker.js'];
|
|
4
4
|
const stylesheets = ['leaflet.contextmenu.css', 'leaflet.draw.css'];
|
|
5
5
|
|
|
6
|
+
// Define exports on window
|
|
7
|
+
const exportsScript = document.createElement('script');
|
|
8
|
+
exportsScript.innerHTML = 'window.exports = window.exports || {};';
|
|
9
|
+
document.body.appendChild(exportsScript);
|
|
10
|
+
|
|
6
11
|
for (let i = 0; i < scripts.length; i++) {
|
|
7
12
|
const script = document.createElement('script');
|
|
8
13
|
script.src = path + scripts[i];
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import LeafletDriftMarkerComponent from '../components/leaflet-drift-marker';
|
|
2
|
+
|
|
3
|
+
export function initialize(owner) {
|
|
4
|
+
let emberLeafletService = owner.lookup('service:ember-leaflet');
|
|
5
|
+
|
|
6
|
+
if (emberLeafletService) {
|
|
7
|
+
// we then invoke the `registerComponent` method
|
|
8
|
+
emberLeafletService.registerComponent('leaflet-drift-marker', {
|
|
9
|
+
as: 'drift-marker',
|
|
10
|
+
component: LeafletDriftMarkerComponent,
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export default {
|
|
16
|
+
initialize,
|
|
17
|
+
};
|
|
@@ -4,7 +4,9 @@ import { action } from '@ember/object';
|
|
|
4
4
|
|
|
5
5
|
export default class OperationsOrdersIndexViewRoute extends Route {
|
|
6
6
|
@service currentUser;
|
|
7
|
+
@service notifications;
|
|
7
8
|
@service store;
|
|
9
|
+
@service socket;
|
|
8
10
|
|
|
9
11
|
@action willTransition() {
|
|
10
12
|
if (this.controller) {
|
|
@@ -12,6 +14,11 @@ export default class OperationsOrdersIndexViewRoute extends Route {
|
|
|
12
14
|
}
|
|
13
15
|
}
|
|
14
16
|
|
|
17
|
+
@action error(error, transition) {
|
|
18
|
+
this.notifications.serverError(error);
|
|
19
|
+
return this.transitionTo('operations.orders.index');
|
|
20
|
+
}
|
|
21
|
+
|
|
15
22
|
model(order) {
|
|
16
23
|
const { public_id } = order;
|
|
17
24
|
|
|
@@ -22,6 +29,45 @@ export default class OperationsOrdersIndexViewRoute extends Route {
|
|
|
22
29
|
});
|
|
23
30
|
}
|
|
24
31
|
|
|
32
|
+
/**
|
|
33
|
+
* Handle resolved model
|
|
34
|
+
*
|
|
35
|
+
* @param {OrderModel} model
|
|
36
|
+
* @memberof OperationsOrdersIndexViewRoute
|
|
37
|
+
*/
|
|
38
|
+
afterModel(model) {
|
|
39
|
+
this.listenForOrderEvents(model);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Listen to order channel for update events to refresh data
|
|
44
|
+
*
|
|
45
|
+
* @param {OrderModel} model
|
|
46
|
+
* @memberof OperationsOrdersIndexViewRoute
|
|
47
|
+
*/
|
|
48
|
+
async listenForOrderEvents(model) {
|
|
49
|
+
// Get socket instance
|
|
50
|
+
const socket = this.socket.instance();
|
|
51
|
+
|
|
52
|
+
// The channel ID to listen on
|
|
53
|
+
const channelId = `order.${model.public_id}`;
|
|
54
|
+
|
|
55
|
+
// Listed on company channel
|
|
56
|
+
const channel = socket.subscribe(channelId);
|
|
57
|
+
|
|
58
|
+
// Listen for channel subscription
|
|
59
|
+
(async () => {
|
|
60
|
+
for await (let output of channel) {
|
|
61
|
+
this.refresh();
|
|
62
|
+
}
|
|
63
|
+
})();
|
|
64
|
+
|
|
65
|
+
// disconnect when transitioning
|
|
66
|
+
this.on('willTransition', () => {
|
|
67
|
+
channel.close();
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
|
|
25
71
|
async setupController(controller, model) {
|
|
26
72
|
super.setupController(controller, model);
|
|
27
73
|
|
|
@@ -1,12 +1,19 @@
|
|
|
1
1
|
import Route from '@ember/routing/route';
|
|
2
2
|
import { inject as service } from '@ember/service';
|
|
3
|
+
import { action } from '@ember/object';
|
|
3
4
|
|
|
4
5
|
export default class OperationsServiceRatesIndexEditRoute extends Route {
|
|
5
6
|
@service store;
|
|
6
7
|
@service currentUser;
|
|
8
|
+
@service notifications;
|
|
7
9
|
|
|
8
10
|
templateName = 'operations.service-rates.index.new';
|
|
9
11
|
|
|
12
|
+
@action error(error, transition) {
|
|
13
|
+
this.notifications.serverError(error);
|
|
14
|
+
return this.transitionTo('operations.service-rates.index');
|
|
15
|
+
}
|
|
16
|
+
|
|
10
17
|
model({ public_id }) {
|
|
11
18
|
return this.store.queryRecord('service-rate', {
|
|
12
19
|
public_id,
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
{{#if this.isMapLayout}}
|
|
14
14
|
<MapContainer @layout={{this.layout}} @onReady={{this.onMapContainerReady}}>
|
|
15
15
|
<GlobalSearch @visible={{this.isSearchVisible}} @onPressOrder={{this.viewOrder}} />
|
|
16
|
-
<MapContainer::Toolbar @activeOrdersCount={{this.activeOrdersCount}} @map={{this.leafletMap}} @onPressViewOrders={{this.toggleOrdersPanel}} @onPressSearch={{this.toggleSearch}} @onPressCreateOrder={{this.createOrder}} @onPressCreateDriver={{this.driversController.createDriver}} @onPressDriverProfile={{this.driversController.viewDriver}} />
|
|
16
|
+
<MapContainer::Toolbar @activeOrdersCount={{this.activeOrdersCount}} @map={{this.leafletMap}} @onPressDisplayPlaces={{this.viewPlacesOnMap}} @onPressViewOrders={{this.toggleOrdersPanel}} @onPressSearch={{this.toggleSearch}} @onPressCreateOrder={{this.createOrder}} @onPressCreateDriver={{this.driversController.createDriver}} @onPressDriverProfile={{this.driversController.viewDriver}} />
|
|
17
17
|
<OrderListOverlay @noBackdrop={{true}} @fullHeight={{true}} @outView={{not this.isOrdersPanelVisible}} @width={{if (media 'isMobile') "100%" "338px"}} @onPressCancel={{this.hideOrdersPanel}} @onPressCreateOrder={{this.createOrder}} @onPressViewOrder={{this.viewOrder}} @onPressCreateFleet={{this.fleetController.createFleet}} @onPressManageFleet={{this.fleetController.viewFleet}} @onPressCancelOrders={{this.bulkCancelOrders}} @onPressDeleteOrders={{this.bulkDeleteOrders}} />
|
|
18
18
|
<LiveMap id="leafletMap" class="next-leaflet-container-map" @lat={{1.3521}} @lng={{103.8198}} @zoom={{12}} @zoomControl={{false}} @onLoad={{this.setMapReference}} {{set-container-dimensions}} />
|
|
19
19
|
</MapContainer>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<Overlay @position="right" @noBackdrop={{true}} @fullHeight={{true}} @width="
|
|
1
|
+
<Overlay @position="right" @noBackdrop={{true}} @isResizable={{true}} @fullHeight={{true}} @width="800px">
|
|
2
2
|
<Overlay::Header @title={{if this.serviceRate.id this.serviceRate.service_name "New service rate"}} @status={{this.serviceRate.public_id}} @hideStatusDot={{true}} @createdAt={{this.serviceRate.createdAt}} @onPressCancel={{this.transitionBack}}>
|
|
3
3
|
{{#if this.serviceRate.id}}
|
|
4
4
|
<Button @icon="save" @type="primary" @text="Save Service Rate" @onClick={{this.updateServiceRate}} @isLoading={{this.isUpdatingServiceRate}} @isSubscriptionRequired={{true}} />
|
|
@@ -179,7 +179,7 @@
|
|
|
179
179
|
<div class="dark:text-gray-100">
|
|
180
180
|
<div class="grid grid-cols-7">
|
|
181
181
|
<div class="flex flex-col items-start justify-start pt-3">
|
|
182
|
-
<img src="/images/boxes/{{parcelFee.size}}.png" alt="parcel size {{parcelFee.size}}" width="44" class="w-11">
|
|
182
|
+
<img src="/engines-dist/images/boxes/{{parcelFee.size}}.png" alt="parcel size {{parcelFee.size}}" width="44" class="w-11">
|
|
183
183
|
<label class="mt-2">{{humanize parcelFee.size}}</label>
|
|
184
184
|
</div>
|
|
185
185
|
<div class="col-span-6 dimensions-box">
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from '@fleetbase/fleetops-engine/components/leaflet-drift-marker';
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/index.js
CHANGED
|
@@ -33,6 +33,21 @@ module.exports = buildEngine({
|
|
|
33
33
|
{ package: 'leaflet-contextmenu', include: undefined, exclude: [...alwaysExclude], path: ['dist'] },
|
|
34
34
|
{ package: 'leaflet-draw', include: undefined, exclude: [...alwaysExclude], path: ['dist'] },
|
|
35
35
|
{ package: 'leaflet-rotatedmarker', include: undefined, exclude: [...alwaysExclude], path: [] },
|
|
36
|
+
{
|
|
37
|
+
package: 'leaflet-drift-marker',
|
|
38
|
+
include: ['index.js', 'index.js.map'],
|
|
39
|
+
exclude: [...alwaysExclude],
|
|
40
|
+
path: ['lib'],
|
|
41
|
+
getDestinationPath: (relativePath) => {
|
|
42
|
+
if (relativePath === 'index.js') {
|
|
43
|
+
return 'leaflet-drift-marker.js';
|
|
44
|
+
}
|
|
45
|
+
if (relativePath === 'index.js.map') {
|
|
46
|
+
return 'leaflet-drift-marker.js.map';
|
|
47
|
+
}
|
|
48
|
+
return relativePath;
|
|
49
|
+
},
|
|
50
|
+
},
|
|
36
51
|
];
|
|
37
52
|
const trees = [];
|
|
38
53
|
|
|
@@ -45,6 +60,7 @@ module.exports = buildEngine({
|
|
|
45
60
|
destDir: 'leaflet',
|
|
46
61
|
include: leafletAdddon.include,
|
|
47
62
|
exclude: leafletAdddon.exclude,
|
|
63
|
+
getDestinationPath: leafletAdddon.getDestinationPath,
|
|
48
64
|
})
|
|
49
65
|
);
|
|
50
66
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fleetbase/fleetops-engine",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.3",
|
|
4
4
|
"description": "Fleetbase Fleet-Ops extension provides a fleet management and last mile delivery operations system module.",
|
|
5
5
|
"fleetbase": {
|
|
6
6
|
"route": "fleet-ops",
|
|
@@ -39,9 +39,9 @@
|
|
|
39
39
|
"publish:github": "npm config set '@fleetbase:registry' https://npm.pkg.github.com/ && npm publish"
|
|
40
40
|
},
|
|
41
41
|
"dependencies": {
|
|
42
|
-
"@fleetbase/ember-core": "^0.1.
|
|
43
|
-
"@fleetbase/ember-ui": "^0.1.
|
|
44
|
-
"@fleetbase/fleetops-data": "^0.0.
|
|
42
|
+
"@fleetbase/ember-core": "^0.1.2",
|
|
43
|
+
"@fleetbase/ember-ui": "^0.1.8",
|
|
44
|
+
"@fleetbase/fleetops-data": "^0.0.7",
|
|
45
45
|
"@fleetbase/leaflet-routing-machine": "^3.2.16",
|
|
46
46
|
"@fortawesome/ember-fontawesome": "^0.4.1",
|
|
47
47
|
"@fortawesome/fontawesome-svg-core": "^6.4.0",
|
|
@@ -50,16 +50,17 @@
|
|
|
50
50
|
"@zestia/ember-dragula": "^12.0.0",
|
|
51
51
|
"broccoli-funnel": "^3.0.8",
|
|
52
52
|
"broccoli-merge-trees": "^4.2.0",
|
|
53
|
-
"ember-intl": "^6.0.0-beta.6",
|
|
54
53
|
"ember-cli-babel": "^7.26.11",
|
|
55
54
|
"ember-cli-es6-transform": "^1.0.0",
|
|
56
55
|
"ember-cli-htmlbars": "^6.1.0",
|
|
56
|
+
"ember-intl": "^6.0.0-beta.6",
|
|
57
57
|
"ember-leaflet": "^5.1.1",
|
|
58
58
|
"ember-radio-button": "^3.0.0-beta.1",
|
|
59
59
|
"ember-wormhole": "^0.6.0",
|
|
60
60
|
"leaflet": "^1.9.4",
|
|
61
61
|
"leaflet-contextmenu": "^1.4.0",
|
|
62
62
|
"leaflet-draw": "^1.0.4",
|
|
63
|
+
"leaflet-drift-marker": "^2.0.0",
|
|
63
64
|
"leaflet-rotatedmarker": "^0.2.0"
|
|
64
65
|
},
|
|
65
66
|
"devDependencies": {
|