@fleetbase/fleetops-engine 0.6.45 → 0.6.47
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/admin/map-settings.hbs +26 -0
- package/addon/components/admin/map-settings.js +46 -0
- package/addon/components/admin/routing-settings.hbs +11 -0
- package/addon/components/cell/order-route-type.hbs +46 -0
- package/addon/components/cell/order-route-type.js +90 -0
- package/addon/components/cell/place-address.hbs +1 -0
- package/addon/components/display-place.hbs +45 -56
- package/addon/components/display-place.js +21 -0
- package/addon/components/layout/fleet-ops-sidebar/driver-listing.js +5 -5
- package/addon/components/layout/fleet-ops-sidebar/fleet-listing.js +5 -5
- package/addon/components/layout/fleet-ops-sidebar.js +8 -0
- package/addon/components/maintenance-schedule/form.js +2 -1
- package/addon/components/map/drawer/driver-listing.js +5 -5
- package/addon/components/map/drawer/place-listing.js +5 -5
- package/addon/components/map/drawer/position-listing.js +102 -21
- package/addon/components/map/drawer/vehicle-listing.js +5 -5
- package/addon/components/map/google-live-map.hbs +9 -0
- package/addon/components/map/google-live-map.js +445 -0
- package/addon/components/map/leaflet-live-map.hbs +186 -142
- package/addon/components/map/leaflet-live-map.js +121 -41
- package/addon/components/map/toolbar/visibility-control-panel.js +2 -2
- package/addon/components/map/toolbar/zones-panel.hbs +9 -9
- package/addon/components/map/toolbar.hbs +3 -3
- package/addon/components/map/toolbar.js +9 -1
- package/addon/components/modals/map-layer-form.hbs +132 -63
- package/addon/components/modals/orchestrator-import.hbs +4 -11
- package/addon/components/modals/orchestrator-import.js +17 -1
- package/addon/components/modals/update-order-activity.hbs +1 -1
- package/addon/components/orchestrator/order-pool.js +3 -2
- package/addon/components/orchestrator-workbench.js +29 -41
- package/addon/components/order/details/detail.js +2 -2
- package/addon/components/order/details/payload.hbs +5 -5
- package/addon/components/order/details/payload.js +18 -1
- package/addon/components/order/details/route.hbs +2 -2
- package/addon/components/order/details/route.js +76 -3
- package/addon/components/order/form/details.hbs +1 -2
- package/addon/components/order/form/details.js +6 -0
- package/addon/components/order/form/payload.hbs +33 -0
- package/addon/components/order/form/payload.js +1 -0
- package/addon/components/order/form/route.hbs +8 -8
- package/addon/components/order/form/route.js +86 -18
- package/addon/components/order/form.js +2 -2
- package/addon/components/order/route-editor.hbs +209 -147
- package/addon/components/order/route-editor.js +143 -102
- package/addon/components/place/address.hbs +1 -0
- package/addon/components/place/address.js +12 -0
- package/addon/components/route-list.hbs +43 -55
- package/addon/components/route-list.js +47 -0
- package/addon/components/route-optimization-wizard-panel.js +3 -4
- package/addon/components/vehicle/card.hbs +4 -4
- package/addon/controllers/maintenance/schedules/index.js +2 -1
- package/addon/controllers/operations/orders/index/details.js +110 -37
- package/addon/controllers/operations/orders/index/new.js +1 -1
- package/addon/controllers/operations/orders/index.js +8 -1
- package/addon/controllers/settings/map.js +97 -0
- package/addon/controllers/settings/payments/index.js +1 -1
- package/addon/controllers/settings/routing.js +47 -12
- package/addon/extension.js +11 -0
- package/addon/helpers/place-address-html.js +6 -0
- package/addon/instance-initializers/register-google-routes.js +17 -0
- package/addon/instance-initializers/register-osrm.js +5 -0
- package/addon/routes/application.js +6 -0
- package/addon/routes/operations/orchestrator.js +13 -0
- package/addon/routes/operations/orders/index/details.js +29 -22
- package/addon/routes/operations/orders/index/new.js +9 -0
- package/addon/routes/operations/orders/index.js +0 -1
- package/addon/routes/settings/map.js +3 -0
- package/addon/routes.js +1 -0
- package/addon/services/entity-actions.js +1 -1
- package/addon/services/geofence-event-bus.js +2 -1
- package/addon/services/geofence.js +204 -168
- package/addon/services/google-routes.js +300 -0
- package/addon/services/leaflet-draw-restriction.js +2 -1
- package/addon/services/leaflet-map-manager.js +17 -0
- package/addon/services/map-adapter/google.js +2205 -0
- package/addon/services/map-adapter/leaflet.js +1042 -0
- package/addon/services/map-adapter-interface.js +551 -0
- package/addon/services/map-manager.js +768 -0
- package/addon/services/map-settings.js +75 -0
- package/addon/services/movement-tracker.js +83 -32
- package/addon/services/order-actions.js +11 -1
- package/addon/services/osrm.js +79 -6
- package/addon/services/position-playback.js +135 -62
- package/addon/services/route-engine.js +83 -0
- package/addon/services/service-areas.js +8 -1
- package/addon/styles/fleetops-engine.css +555 -0
- package/addon/templates/management/vehicles/index.hbs +0 -1
- package/addon/templates/operations/orders/index/details.hbs +0 -1
- package/addon/templates/settings/map.hbs +53 -0
- package/addon/templates/settings/routing.hbs +15 -4
- package/addon/utils/fleet-ops-options.js +1 -0
- package/addon/utils/has-valid-coordinates.js +6 -0
- package/addon/utils/map-provider-options.js +6 -0
- package/addon/utils/order-route-editing.js +86 -0
- package/addon/utils/order-route-summary.js +20 -0
- package/addon/utils/place-address-html.js +41 -0
- package/addon/utils/route-colors.js +43 -12
- package/addon/utils/route-visualization.js +93 -0
- package/addon/utils/vendor-integration.js +2 -1
- package/app/components/admin/map-settings.js +1 -0
- package/app/components/admin/routing-settings.js +1 -0
- package/app/components/cell/order-route-type.js +1 -0
- package/app/components/cell/place-address.js +1 -0
- package/app/components/map/google-live-map.js +1 -0
- package/app/components/place/address.js +1 -0
- package/app/controllers/settings/map.js +1 -0
- package/app/helpers/place-address-html.js +1 -0
- package/app/routes/settings/map.js +1 -0
- package/app/services/map-adapter/google.js +1 -0
- package/app/services/map-adapter/leaflet.js +1 -0
- package/app/services/map-adapter-interface.js +1 -0
- package/app/services/map-manager.js +1 -0
- package/app/services/map-settings.js +1 -0
- package/app/templates/settings/map.js +1 -0
- package/app/utils/has-valid-coordinates.js +1 -0
- package/app/utils/order-route-editing.js +2 -0
- package/app/utils/order-route-summary.js +1 -0
- package/app/utils/place-address-html.js +1 -0
- package/app/utils/route-colors.js +1 -1
- package/app/utils/route-visualization.js +1 -0
- package/assets/images/drawing-controls-spritesheet.svg +156 -0
- package/composer.json +1 -1
- package/extension.json +1 -1
- package/package.json +4 -4
- package/pnpm-workspace.yaml +7 -0
- package/server/src/Auth/Schemas/FleetOps.php +5 -0
- package/server/src/Http/Controllers/Api/v1/OrderController.php +31 -3
- package/server/src/Http/Controllers/Api/v1/PayloadController.php +14 -1
- package/server/src/Http/Controllers/Api/v1/ServiceAreaController.php +2 -0
- package/server/src/Http/Controllers/Api/v1/ServiceQuoteController.php +3 -2
- package/server/src/Http/Controllers/Api/v1/ZoneController.php +2 -0
- package/server/src/Http/Controllers/Internal/v1/LiveController.php +2 -1
- package/server/src/Http/Controllers/Internal/v1/OrchestrationController.php +7 -4
- package/server/src/Http/Controllers/Internal/v1/OrderController.php +90 -34
- package/server/src/Http/Controllers/Internal/v1/ServiceQuoteController.php +3 -2
- package/server/src/Http/Controllers/Internal/v1/SettingController.php +106 -3
- package/server/src/Http/Filter/OrderFilter.php +2 -1
- package/server/src/Http/Resources/v1/Index/Payload.php +9 -7
- package/server/src/Http/Resources/v1/Order.php +20 -1
- package/server/src/Models/Order.php +42 -1
- package/server/src/Models/OrderConfig.php +15 -0
- package/server/src/Models/Payload.php +131 -27
- package/server/src/Models/Place.php +182 -48
- package/server/src/Models/ServiceRate.php +4 -3
- package/server/src/Orchestration/Engines/VroomOrchestrationEngine.php +59 -23
- package/server/src/Support/Utils.php +36 -2
- package/server/src/routes.php +4 -0
- package/translations/en-us.yaml +1937 -1916
|
@@ -0,0 +1,300 @@
|
|
|
1
|
+
/* global google */
|
|
2
|
+
import RouteOptimizationInterfaceService from './route-optimization-interface';
|
|
3
|
+
import { isArray } from '@ember/array';
|
|
4
|
+
import { inject as service } from '@ember/service';
|
|
5
|
+
|
|
6
|
+
export default class GoogleRoutesService extends RouteOptimizationInterfaceService {
|
|
7
|
+
@service mapSettings;
|
|
8
|
+
|
|
9
|
+
name = 'Google';
|
|
10
|
+
_apiLoadPromise = null;
|
|
11
|
+
|
|
12
|
+
async computeRoute(waypoints = [], options = {}) {
|
|
13
|
+
const normalizedWaypoints = this.#normalizeWaypoints(waypoints);
|
|
14
|
+
if (normalizedWaypoints.length < 2) {
|
|
15
|
+
throw new Error('At least 2 waypoints are required to compute a route.');
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
await this.#ensureApiLoaded(options);
|
|
19
|
+
const { Route, TravelMode, RoutingPreference } = await google.maps.importLibrary('routes');
|
|
20
|
+
const optimizeWaypointOrder = options.optimizeWaypointOrder === true;
|
|
21
|
+
const request = {
|
|
22
|
+
origin: normalizedWaypoints[0],
|
|
23
|
+
destination: normalizedWaypoints[normalizedWaypoints.length - 1],
|
|
24
|
+
travelMode: TravelMode.DRIVING,
|
|
25
|
+
routingPreference: optimizeWaypointOrder ? RoutingPreference.TRAFFIC_AWARE : RoutingPreference.TRAFFIC_AWARE_OPTIMAL,
|
|
26
|
+
fields: ['path', 'viewport', 'distanceMeters', 'durationMillis', 'legs', 'optimizedIntermediateWaypointIndices'],
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
if (normalizedWaypoints.length > 2) {
|
|
30
|
+
request.intermediates = normalizedWaypoints.slice(1, -1).map((waypoint) => ({ location: waypoint, via: false }));
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if (optimizeWaypointOrder) {
|
|
34
|
+
request.optimizeWaypointOrder = true;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const response = await Route.computeRoutes(request);
|
|
38
|
+
const route = response?.routes?.[0];
|
|
39
|
+
|
|
40
|
+
if (!route?.path?.length) {
|
|
41
|
+
throw new Error('Google route computation returned no path.');
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const coordinates = route.path.map((point) => [typeof point.lat === 'function' ? point.lat() : point.lat, typeof point.lng === 'function' ? point.lng() : point.lng]);
|
|
45
|
+
const optimizedIndices = isArray(route.optimizedIntermediateWaypointIndices) ? route.optimizedIntermediateWaypointIndices : [];
|
|
46
|
+
const bounds = this.#extractBounds(route.viewport) ?? this.#boundsFromCoordinates(coordinates);
|
|
47
|
+
|
|
48
|
+
return {
|
|
49
|
+
engine: 'google',
|
|
50
|
+
waypoints: this.#reorderWaypoints(waypoints, optimizedIndices),
|
|
51
|
+
coordinates,
|
|
52
|
+
bounds,
|
|
53
|
+
summary: {
|
|
54
|
+
totalDistance: route.distanceMeters ?? 0,
|
|
55
|
+
totalTime: route.durationMillis ? route.durationMillis / 1000 : 0,
|
|
56
|
+
},
|
|
57
|
+
legs: isArray(route.legs)
|
|
58
|
+
? route.legs.map((leg) => ({
|
|
59
|
+
distanceMeters: leg.distanceMeters ?? 0,
|
|
60
|
+
durationMillis: leg.durationMillis ?? 0,
|
|
61
|
+
startLocation: leg.startLocation,
|
|
62
|
+
endLocation: leg.endLocation,
|
|
63
|
+
}))
|
|
64
|
+
: [],
|
|
65
|
+
raw: route,
|
|
66
|
+
optimizedIntermediateWaypointIndices: optimizedIndices,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
async optimize({ order, waypoints, coordinates, preserveEndpoints = false }, options = {}) {
|
|
71
|
+
const route = await this.computeRoute(this.#normalizeOptimizationCoordinates(order, coordinates), {
|
|
72
|
+
...options,
|
|
73
|
+
optimizeWaypointOrder: true,
|
|
74
|
+
});
|
|
75
|
+
let sortedWaypoints = waypoints;
|
|
76
|
+
|
|
77
|
+
if (isArray(route.waypoints) && route.waypoints.length > 0) {
|
|
78
|
+
sortedWaypoints = this.#reorderModelsByRouteWaypoints(waypoints, route.waypoints, preserveEndpoints);
|
|
79
|
+
} else if (isArray(route.optimizedIntermediateWaypointIndices) && route.optimizedIntermediateWaypointIndices.length > 0) {
|
|
80
|
+
sortedWaypoints = this.#reorderModelWaypoints(waypoints, route.optimizedIntermediateWaypointIndices, preserveEndpoints);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return {
|
|
84
|
+
sortedWaypoints,
|
|
85
|
+
route: route.coordinates,
|
|
86
|
+
trip: {
|
|
87
|
+
distance: route.summary.totalDistance,
|
|
88
|
+
duration: route.summary.totalTime,
|
|
89
|
+
legs: route.legs,
|
|
90
|
+
},
|
|
91
|
+
result: route.raw,
|
|
92
|
+
engine: 'google',
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
#normalizeOptimizationCoordinates(order, coordinates = []) {
|
|
97
|
+
const driverPosition = order?.driver_assigned?.location?.coordinates;
|
|
98
|
+
const normalized = (isArray(coordinates) ? coordinates : []).map(([lng, lat]) => [lat, lng]);
|
|
99
|
+
|
|
100
|
+
if (this.#isValidDriverPosition(driverPosition)) {
|
|
101
|
+
return [[driverPosition[1], driverPosition[0]], ...normalized];
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
return normalized;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
#isValidDriverPosition(driverPosition) {
|
|
108
|
+
if (!isArray(driverPosition) || driverPosition.length < 2) {
|
|
109
|
+
return false;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const [lng, lat] = driverPosition.map(Number);
|
|
113
|
+
|
|
114
|
+
if (!Number.isFinite(lat) || !Number.isFinite(lng)) {
|
|
115
|
+
return false;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
return lat !== 0 && lng !== 0;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
#normalizeWaypoints(waypoints = []) {
|
|
122
|
+
return (isArray(waypoints) ? waypoints : [])
|
|
123
|
+
.map((waypoint) => {
|
|
124
|
+
if (isArray(waypoint) && waypoint.length >= 2) {
|
|
125
|
+
return { lat: Number(waypoint[0]), lng: Number(waypoint[1]) };
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
if (Number.isFinite(waypoint?.lat) && Number.isFinite(waypoint?.lng)) {
|
|
129
|
+
return { lat: Number(waypoint.lat), lng: Number(waypoint.lng) };
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
return null;
|
|
133
|
+
})
|
|
134
|
+
.filter((waypoint) => Number.isFinite(waypoint?.lat) && Number.isFinite(waypoint?.lng));
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
#reorderWaypoints(waypoints = [], optimizedIndices = []) {
|
|
138
|
+
if (!isArray(optimizedIndices) || optimizedIndices.length === 0 || waypoints.length < 3) {
|
|
139
|
+
return waypoints;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
const start = waypoints[0];
|
|
143
|
+
const end = waypoints[waypoints.length - 1];
|
|
144
|
+
const intermediates = waypoints.slice(1, -1);
|
|
145
|
+
const orderedIntermediates = optimizedIndices.map((index) => intermediates[index]).filter(Boolean);
|
|
146
|
+
|
|
147
|
+
return [start, ...orderedIntermediates, end];
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
#reorderModelWaypoints(waypoints = [], optimizedIndices = [], preserveEndpoints = false) {
|
|
151
|
+
if (!isArray(optimizedIndices) || optimizedIndices.length === 0 || !isArray(waypoints) || waypoints.length < 3) {
|
|
152
|
+
return waypoints;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
if (!preserveEndpoints) {
|
|
156
|
+
const start = waypoints[0];
|
|
157
|
+
const end = waypoints[waypoints.length - 1];
|
|
158
|
+
const intermediates = waypoints.slice(1, -1);
|
|
159
|
+
const orderedIntermediates = optimizedIndices.map((index) => intermediates[index]).filter(Boolean);
|
|
160
|
+
|
|
161
|
+
return [start, ...orderedIntermediates, end];
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
const start = waypoints[0];
|
|
165
|
+
const end = waypoints[waypoints.length - 1];
|
|
166
|
+
const intermediates = waypoints.slice(1, -1);
|
|
167
|
+
const orderedIntermediates = optimizedIndices.map((index) => intermediates[index]).filter(Boolean);
|
|
168
|
+
|
|
169
|
+
return [start, ...orderedIntermediates, end];
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
#reorderModelsByRouteWaypoints(waypoints = [], routeWaypoints = [], preserveEndpoints = false) {
|
|
173
|
+
if (!isArray(waypoints) || !waypoints.length || !isArray(routeWaypoints) || !routeWaypoints.length) {
|
|
174
|
+
return waypoints;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
const waypointOrder = preserveEndpoints ? routeWaypoints.slice(1, -1) : routeWaypoints;
|
|
178
|
+
const buckets = new Map();
|
|
179
|
+
|
|
180
|
+
for (const waypoint of waypoints) {
|
|
181
|
+
const key = this.#modelCoordinateKey(waypoint);
|
|
182
|
+
|
|
183
|
+
if (!key) {
|
|
184
|
+
continue;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
if (!buckets.has(key)) {
|
|
188
|
+
buckets.set(key, []);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
buckets.get(key).push(waypoint);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
const orderedWaypoints = [];
|
|
195
|
+
for (const routeWaypoint of waypointOrder) {
|
|
196
|
+
const key = this.#coordinateKey(routeWaypoint?.lat, routeWaypoint?.lng);
|
|
197
|
+
const bucket = buckets.get(key);
|
|
198
|
+
|
|
199
|
+
if (bucket?.length) {
|
|
200
|
+
orderedWaypoints.push(bucket.shift());
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
if (orderedWaypoints.length === waypoints.length) {
|
|
205
|
+
return orderedWaypoints;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
return waypoints;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
#modelCoordinateKey(waypoint) {
|
|
212
|
+
const place = waypoint?.place ?? waypoint;
|
|
213
|
+
return this.#coordinateKey(place?.latitude ?? waypoint?.latitude, place?.longitude ?? waypoint?.longitude);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
#coordinateKey(lat, lng) {
|
|
217
|
+
const normalizedLat = Number(lat);
|
|
218
|
+
const normalizedLng = Number(lng);
|
|
219
|
+
|
|
220
|
+
if (!Number.isFinite(normalizedLat) || !Number.isFinite(normalizedLng)) {
|
|
221
|
+
return null;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
return `${normalizedLat.toFixed(6)}:${normalizedLng.toFixed(6)}`;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
#boundsFromCoordinates(coordinates = []) {
|
|
228
|
+
if (!coordinates.length) {
|
|
229
|
+
return [
|
|
230
|
+
[0, 0],
|
|
231
|
+
[0, 0],
|
|
232
|
+
];
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
const lats = coordinates.map(([lat]) => lat);
|
|
236
|
+
const lngs = coordinates.map(([, lng]) => lng);
|
|
237
|
+
|
|
238
|
+
return [
|
|
239
|
+
[Math.min(...lats), Math.min(...lngs)],
|
|
240
|
+
[Math.max(...lats), Math.max(...lngs)],
|
|
241
|
+
];
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
#extractBounds(viewport) {
|
|
245
|
+
if (!viewport) return null;
|
|
246
|
+
|
|
247
|
+
if (typeof viewport.getSouthWest === 'function' && typeof viewport.getNorthEast === 'function') {
|
|
248
|
+
const sw = viewport.getSouthWest();
|
|
249
|
+
const ne = viewport.getNorthEast();
|
|
250
|
+
return [
|
|
251
|
+
[sw.lat(), sw.lng()],
|
|
252
|
+
[ne.lat(), ne.lng()],
|
|
253
|
+
];
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
if (Number.isFinite(viewport.south) && Number.isFinite(viewport.west) && Number.isFinite(viewport.north) && Number.isFinite(viewport.east)) {
|
|
257
|
+
return [
|
|
258
|
+
[viewport.south, viewport.west],
|
|
259
|
+
[viewport.north, viewport.east],
|
|
260
|
+
];
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
return null;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
async #ensureApiLoaded(options = {}) {
|
|
267
|
+
if (window.google?.maps?.importLibrary) {
|
|
268
|
+
return true;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
if (this._apiLoadPromise) {
|
|
272
|
+
return this._apiLoadPromise;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
const apiKey = options.apiKey ?? this.mapSettings.googleMapsApiKey;
|
|
276
|
+
if (!apiKey) {
|
|
277
|
+
throw new Error('Google Maps API key is required for Google route computation.');
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
this._apiLoadPromise = new Promise((resolve, reject) => {
|
|
281
|
+
const callbackName = `__fleetopsGoogleRoutesInit_${Date.now().toString(36)}`;
|
|
282
|
+
window[callbackName] = () => {
|
|
283
|
+
delete window[callbackName];
|
|
284
|
+
resolve(true);
|
|
285
|
+
};
|
|
286
|
+
|
|
287
|
+
const script = document.createElement('script');
|
|
288
|
+
script.async = true;
|
|
289
|
+
script.defer = true;
|
|
290
|
+
script.onerror = (error) => {
|
|
291
|
+
delete window[callbackName];
|
|
292
|
+
reject(error);
|
|
293
|
+
};
|
|
294
|
+
script.src = `https://maps.googleapis.com/maps/api/js?key=${apiKey}&libraries=routes,geometry,marker&callback=${callbackName}&loading=async`;
|
|
295
|
+
document.head.appendChild(script);
|
|
296
|
+
});
|
|
297
|
+
|
|
298
|
+
return this._apiLoadPromise;
|
|
299
|
+
}
|
|
300
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import Service from '@ember/service';
|
|
2
|
+
import { isArray } from '@ember/array';
|
|
2
3
|
import booleanPointInPolygon from '@turf/boolean-point-in-polygon';
|
|
3
4
|
import { point as turfPoint, polygon as turfPolygon } from '@turf/helpers';
|
|
4
5
|
|
|
@@ -124,7 +125,7 @@ export default class LeafletMapManagerService extends Service {
|
|
|
124
125
|
#everyVertexInside(latlngs) {
|
|
125
126
|
// latlngs can be nested (poly: [ring], multi: [[ring]...])
|
|
126
127
|
const walk = (arr) => {
|
|
127
|
-
if (!
|
|
128
|
+
if (!isArray(arr)) return true;
|
|
128
129
|
if (arr.length && arr[0]?.lat != null) {
|
|
129
130
|
return arr.every((ll) => this.#isInside(ll));
|
|
130
131
|
}
|
|
@@ -10,6 +10,7 @@ import isUuid from '@fleetbase/ember-core/utils/is-uuid';
|
|
|
10
10
|
|
|
11
11
|
export default class LeafletMapManagerService extends Service {
|
|
12
12
|
@service leafletRoutingControl;
|
|
13
|
+
@service mapManager;
|
|
13
14
|
@service notifications;
|
|
14
15
|
@tracked map;
|
|
15
16
|
@tracked _livemap;
|
|
@@ -222,6 +223,10 @@ export default class LeafletMapManagerService extends Service {
|
|
|
222
223
|
/** routing methods */
|
|
223
224
|
/* eslint-disable no-empty */
|
|
224
225
|
async addRoutingControl(waypoints, options = {}) {
|
|
226
|
+
if (this.mapManager?.providerName && this.mapManager.providerName !== 'leaflet') {
|
|
227
|
+
return this.mapManager.addRoutingControl(waypoints, options);
|
|
228
|
+
}
|
|
229
|
+
|
|
225
230
|
if (!isArray(waypoints) || waypoints.length === 0) return;
|
|
226
231
|
|
|
227
232
|
const map = await this.ensureInteractive({ timeoutMs: 8000 });
|
|
@@ -280,6 +285,10 @@ export default class LeafletMapManagerService extends Service {
|
|
|
280
285
|
}
|
|
281
286
|
|
|
282
287
|
positionWaypoints(waypoints) {
|
|
288
|
+
if (this.mapManager?.providerName && this.mapManager.providerName !== 'leaflet') {
|
|
289
|
+
return this.mapManager.positionWaypoints(waypoints);
|
|
290
|
+
}
|
|
291
|
+
|
|
283
292
|
if (waypoints.length === 1) {
|
|
284
293
|
this.map.flyTo(waypoints[0], 18);
|
|
285
294
|
this.map.once('moveend', () => this.map.panBy([200, 0]));
|
|
@@ -298,6 +307,10 @@ export default class LeafletMapManagerService extends Service {
|
|
|
298
307
|
}
|
|
299
308
|
|
|
300
309
|
async replaceRoutingControl(waypoints, routingControl, options = {}) {
|
|
310
|
+
if (this.mapManager?.providerName && this.mapManager.providerName !== 'leaflet') {
|
|
311
|
+
return this.mapManager.replaceRoutingControl(waypoints, routingControl, options);
|
|
312
|
+
}
|
|
313
|
+
|
|
301
314
|
const removeOptions = options.removeOptions ?? {};
|
|
302
315
|
if (routingControl) {
|
|
303
316
|
await this.removeRoutingControl(routingControl, removeOptions);
|
|
@@ -311,6 +324,10 @@ export default class LeafletMapManagerService extends Service {
|
|
|
311
324
|
|
|
312
325
|
/* eslint-disable no-empty */
|
|
313
326
|
removeRoutingControl(routingControl, options = {}) {
|
|
327
|
+
if (this.mapManager?.providerName && this.mapManager.providerName !== 'leaflet') {
|
|
328
|
+
return Promise.resolve(this.mapManager.removeRoutingControl(routingControl, options));
|
|
329
|
+
}
|
|
330
|
+
|
|
314
331
|
return new Promise((resolve) => {
|
|
315
332
|
let removed = false;
|
|
316
333
|
|