@aggdirect/coolmap-services 4.0.8 → 10.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/README.md +18 -43
- package/esm2022/aggdirect-coolmap-services.mjs +5 -0
- package/esm2022/lib/service/coolmap.service.mjs +626 -0
- package/esm2022/lib/service/data-model.mjs +90 -0
- package/esm2022/lib/service/utils.service.mjs +363 -0
- package/esm2022/public-api.mjs +7 -0
- package/fesm2022/aggdirect-coolmap-services.mjs +708 -1140
- package/fesm2022/aggdirect-coolmap-services.mjs.map +1 -1
- package/index.d.ts +3 -265
- package/lib/service/coolmap.service.d.ts +47 -0
- package/lib/service/data-model.d.ts +92 -0
- package/lib/service/utils.service.d.ts +61 -0
- package/package.json +29 -6
- package/public-api.d.ts +3 -0
|
@@ -1,133 +1,121 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import {
|
|
3
|
-
import
|
|
4
|
-
import mapboxgl from 'mapbox-gl/dist/mapbox-gl-csp.js';
|
|
2
|
+
import { Injectable, Inject } from '@angular/core';
|
|
3
|
+
import * as mapboxgl from 'mapbox-gl';
|
|
5
4
|
import * as turf from '@turf/turf';
|
|
6
|
-
import {
|
|
5
|
+
import { BehaviorSubject } from 'rxjs';
|
|
6
|
+
import { MapboxLayer } from '@deck.gl/mapbox';
|
|
7
|
+
import { ArcLayer } from '@deck.gl/layers';
|
|
8
|
+
import * as i1 from '@angular/common/http';
|
|
9
|
+
import * as i2 from '@angular/material/snack-bar';
|
|
10
|
+
import * as i2$1 from '@angular/platform-browser';
|
|
7
11
|
|
|
8
|
-
class
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
12
|
+
class Route {
|
|
13
|
+
index = 0;
|
|
14
|
+
type;
|
|
15
|
+
// Job Code
|
|
16
|
+
customer_contact;
|
|
17
|
+
customer_name;
|
|
18
|
+
delivery_contact;
|
|
19
|
+
delivery_lat;
|
|
20
|
+
delivery_location;
|
|
21
|
+
delivery_lon;
|
|
22
|
+
driver_list;
|
|
23
|
+
material;
|
|
24
|
+
order_number;
|
|
25
|
+
pickup_lat;
|
|
26
|
+
pickup_location;
|
|
27
|
+
pickup_lon;
|
|
28
|
+
project;
|
|
29
|
+
total_count;
|
|
30
|
+
unit;
|
|
31
|
+
values;
|
|
32
|
+
job_id;
|
|
33
|
+
isSelected;
|
|
34
|
+
date;
|
|
35
|
+
// Add Route
|
|
36
|
+
created_at;
|
|
37
|
+
created_by_name;
|
|
38
|
+
customer_id;
|
|
39
|
+
delivery_lat_lng;
|
|
40
|
+
estimated_distance;
|
|
41
|
+
estimated_time;
|
|
42
|
+
materials_id;
|
|
43
|
+
path;
|
|
44
|
+
pickup_lat_lng;
|
|
45
|
+
route_id;
|
|
46
|
+
route_name;
|
|
47
|
+
unit_id;
|
|
48
|
+
note;
|
|
49
|
+
materialLabel;
|
|
50
|
+
isActive;
|
|
51
|
+
prevent;
|
|
15
52
|
}
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
const
|
|
36
|
-
|
|
37
|
-
function
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
};
|
|
53
|
+
const EstinationData = ['estimated_distance', 'estimated_time'];
|
|
54
|
+
var EstinationEnum;
|
|
55
|
+
(function (EstinationEnum) {
|
|
56
|
+
EstinationEnum["estimated_distance"] = "miles";
|
|
57
|
+
EstinationEnum["estimated_time"] = "time";
|
|
58
|
+
})(EstinationEnum || (EstinationEnum = {}));
|
|
59
|
+
const JobCodeOverviewData = ['order_number', 'customer_name', 'project', 'unit', 'material', 'customer_contact', 'delivery_contact', 'pickup_location', 'delivery_location'];
|
|
60
|
+
var JobCodeOverviewEnum;
|
|
61
|
+
(function (JobCodeOverviewEnum) {
|
|
62
|
+
JobCodeOverviewEnum["material"] = "Material";
|
|
63
|
+
JobCodeOverviewEnum["order_number"] = "Job Code";
|
|
64
|
+
JobCodeOverviewEnum["customer_name"] = "Customer";
|
|
65
|
+
JobCodeOverviewEnum["customer_contact"] = "Customer Contact";
|
|
66
|
+
JobCodeOverviewEnum["delivery_contact"] = "Delivery Contact";
|
|
67
|
+
JobCodeOverviewEnum["project"] = "Project Name";
|
|
68
|
+
JobCodeOverviewEnum["unit"] = "Job Type";
|
|
69
|
+
JobCodeOverviewEnum["pickup_location"] = "Pickup";
|
|
70
|
+
JobCodeOverviewEnum["delivery_location"] = "Delivery";
|
|
71
|
+
})(JobCodeOverviewEnum || (JobCodeOverviewEnum = {}));
|
|
72
|
+
const DriversmsCardKey = ['order_number', 'date', 'values', 'material', 'unit', 'pickup_location', 'delivery_location'];
|
|
73
|
+
var DriverSmsCardEnum;
|
|
74
|
+
(function (DriverSmsCardEnum) {
|
|
75
|
+
DriverSmsCardEnum["order_number"] = "Jobcode";
|
|
76
|
+
DriverSmsCardEnum["date"] = "Date";
|
|
77
|
+
DriverSmsCardEnum["values"] = "Total tasks";
|
|
78
|
+
DriverSmsCardEnum["material"] = "Material";
|
|
79
|
+
DriverSmsCardEnum["unit"] = "Unit";
|
|
80
|
+
DriverSmsCardEnum["pickup_location"] = "Pickup Address";
|
|
81
|
+
DriverSmsCardEnum["delivery_location"] = "Delivery Address";
|
|
82
|
+
})(DriverSmsCardEnum || (DriverSmsCardEnum = {}));
|
|
83
|
+
class PopupData {
|
|
84
|
+
coordinate;
|
|
85
|
+
pickup;
|
|
86
|
+
jobCode;
|
|
87
|
+
customer;
|
|
88
|
+
drop;
|
|
89
|
+
routeType;
|
|
90
|
+
title;
|
|
91
|
+
material;
|
|
92
|
+
type;
|
|
57
93
|
}
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
toastPosition = computed(() => this.position(), ...(ngDevMode ? [{ debugName: "toastPosition" }] : []));
|
|
65
|
-
generateId() {
|
|
66
|
-
return `toast-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
|
|
67
|
-
}
|
|
68
|
-
setPosition(pos) {
|
|
69
|
-
this.position.set(pos);
|
|
70
|
-
}
|
|
71
|
-
show(config) {
|
|
72
|
-
// Prevent duplicate toasts
|
|
73
|
-
const currentToasts = this._toasts();
|
|
74
|
-
const incomingVariant = config.variant || 'info';
|
|
75
|
-
const isDuplicate = currentToasts.find(t => t.message === config.message && t.variant === incomingVariant && t.title === config.title);
|
|
76
|
-
if (isDuplicate) {
|
|
77
|
-
return isDuplicate.id;
|
|
78
|
-
}
|
|
79
|
-
const toast = {
|
|
80
|
-
id: this.generateId(),
|
|
81
|
-
message: config.message,
|
|
82
|
-
title: config.title,
|
|
83
|
-
variant: incomingVariant,
|
|
84
|
-
duration: config.duration ?? this.defaultDuration,
|
|
85
|
-
dismissible: config.dismissible ?? true,
|
|
86
|
-
action: config.action,
|
|
87
|
-
createdAt: new Date()
|
|
88
|
-
};
|
|
89
|
-
this._toasts.update(toasts => [...toasts, toast]);
|
|
90
|
-
// Auto-dismiss if duration > 0
|
|
91
|
-
if (toast.duration > 0) {
|
|
92
|
-
setTimeout(() => {
|
|
93
|
-
this.dismiss(toast.id);
|
|
94
|
-
}, toast.duration);
|
|
95
|
-
}
|
|
96
|
-
return toast.id;
|
|
97
|
-
}
|
|
98
|
-
success(message, title, duration) {
|
|
99
|
-
return this.show({ message, title, variant: 'success', duration });
|
|
100
|
-
}
|
|
101
|
-
error(message, title, duration) {
|
|
102
|
-
return this.show({ message, title, variant: 'error', duration });
|
|
103
|
-
}
|
|
104
|
-
warning(message, title, duration) {
|
|
105
|
-
return this.show({ message, title, variant: 'warning', duration });
|
|
106
|
-
}
|
|
107
|
-
info(message, title, duration) {
|
|
108
|
-
return this.show({ message, title, variant: 'info', duration });
|
|
109
|
-
}
|
|
110
|
-
dismiss(id) {
|
|
111
|
-
this._toasts.update(toasts => toasts.filter(t => t.id !== id));
|
|
112
|
-
}
|
|
113
|
-
dismissAll() {
|
|
114
|
-
this._toasts.set([]);
|
|
115
|
-
}
|
|
116
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.24", ngImport: i0, type: AgToastService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
117
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.24", ngImport: i0, type: AgToastService, providedIn: 'root' });
|
|
94
|
+
class CoolmapConfigModel {
|
|
95
|
+
analyticsRESTURL;
|
|
96
|
+
RESTURLPrefix;
|
|
97
|
+
repository;
|
|
98
|
+
mapboxStyle;
|
|
99
|
+
mapboxAccessToken;
|
|
118
100
|
}
|
|
119
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.24", ngImport: i0, type: AgToastService, decorators: [{
|
|
120
|
-
type: Injectable,
|
|
121
|
-
args: [{
|
|
122
|
-
providedIn: 'root'
|
|
123
|
-
}]
|
|
124
|
-
}] });
|
|
125
101
|
|
|
126
102
|
class UtilsService {
|
|
127
|
-
http
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
103
|
+
http;
|
|
104
|
+
snackBar;
|
|
105
|
+
config;
|
|
106
|
+
ngZone;
|
|
107
|
+
analyticsRESTURL = '';
|
|
108
|
+
RESTURLPrefix = '';
|
|
109
|
+
pickupOptions = [];
|
|
110
|
+
destOptions = [];
|
|
111
|
+
ownerOptions = [];
|
|
112
|
+
customerOptions = [];
|
|
113
|
+
unitOptions = [];
|
|
114
|
+
materialOptions = [];
|
|
115
|
+
jcodeOptions = [];
|
|
116
|
+
driverOption = [];
|
|
117
|
+
truckingCompanayOption = [];
|
|
118
|
+
routeNameOptions = [];
|
|
131
119
|
preventnavChange = new BehaviorSubject(false);
|
|
132
120
|
navChangeObserve = this.preventnavChange.asObservable();
|
|
133
121
|
clearViewRouteforJobCode = new BehaviorSubject(false);
|
|
@@ -143,110 +131,92 @@ class UtilsService {
|
|
|
143
131
|
materialsList;
|
|
144
132
|
materialsListForCustomer;
|
|
145
133
|
customersList;
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
jcodeOptions = [];
|
|
155
|
-
driverOption = [];
|
|
156
|
-
truckingCompanayOption = [];
|
|
157
|
-
routeNameOptions = [];
|
|
134
|
+
constructor(http, snackBar, config, ngZone) {
|
|
135
|
+
this.http = http;
|
|
136
|
+
this.snackBar = snackBar;
|
|
137
|
+
this.config = config;
|
|
138
|
+
this.ngZone = ngZone;
|
|
139
|
+
this.analyticsRESTURL = config.analyticsRESTURL;
|
|
140
|
+
this.RESTURLPrefix = config.RESTURLPrefix;
|
|
141
|
+
}
|
|
158
142
|
getDateFormat(strVal, seprater) {
|
|
159
143
|
seprater = seprater ? seprater : '-';
|
|
160
144
|
const mydate = strVal;
|
|
161
|
-
|
|
162
|
-
return '';
|
|
163
|
-
const month = String(mydate.getMonth() + 1).padStart(2, '0');
|
|
164
|
-
const day = String(mydate.getDate()).padStart(2, '0');
|
|
165
|
-
return (mydate.getFullYear() +
|
|
145
|
+
return (mydate?.getFullYear() +
|
|
166
146
|
seprater +
|
|
167
|
-
|
|
147
|
+
((mydate ? mydate.getMonth() : 0) + 1) +
|
|
168
148
|
seprater +
|
|
169
|
-
|
|
149
|
+
mydate?.getDate());
|
|
170
150
|
}
|
|
171
151
|
getData(path) {
|
|
172
|
-
return this.http.get(`${this.
|
|
173
|
-
}
|
|
174
|
-
getRestData(path) {
|
|
175
|
-
return this.http.get(`${this.config.RESTURLPrefix}${path}`);
|
|
152
|
+
return this.http.get(`${this.analyticsRESTURL}${this.config.repository}/${path}`);
|
|
176
153
|
}
|
|
177
154
|
postdata(path, data) {
|
|
178
|
-
return this.http.post(`${this.
|
|
155
|
+
return this.http.post(`${this.analyticsRESTURL}${this.config.repository}/${path}`, data);
|
|
179
156
|
}
|
|
180
157
|
postDataWithRestUrl(path, data) {
|
|
181
|
-
return this.http.post(`${this.
|
|
158
|
+
return this.http.post(`${this.RESTURLPrefix}${path}`, data);
|
|
182
159
|
}
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
this.toastService.info(message);
|
|
197
|
-
}
|
|
160
|
+
autocomplete(searchElementRef, form) {
|
|
161
|
+
return new Promise((resolve, reject) => {
|
|
162
|
+
const autocomplete = new google.maps.places.Autocomplete(searchElementRef.nativeElement, {
|
|
163
|
+
types: ['address']
|
|
164
|
+
});
|
|
165
|
+
google.maps.event.addListener(autocomplete, 'place_changed', () => {
|
|
166
|
+
this.ngZone.run(() => {
|
|
167
|
+
const place = autocomplete.getPlace();
|
|
168
|
+
console.log(place.geometry.location.lat(), place.geometry.location.lng());
|
|
169
|
+
resolve({ lat: place.geometry.location.lat(), lng: place.geometry.location.lng() });
|
|
170
|
+
});
|
|
171
|
+
});
|
|
172
|
+
});
|
|
198
173
|
}
|
|
199
|
-
|
|
200
|
-
this.
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
this.jcodeOptions = [];
|
|
207
|
-
this.routeNameOptions = [];
|
|
174
|
+
openSnackBar(message, className) {
|
|
175
|
+
this.snackBar.open(message, '', {
|
|
176
|
+
duration: 5000,
|
|
177
|
+
verticalPosition: 'top',
|
|
178
|
+
horizontalPosition: 'center',
|
|
179
|
+
panelClass: [className ? className : 'default'],
|
|
180
|
+
});
|
|
208
181
|
}
|
|
209
182
|
makeOptions(item) {
|
|
210
|
-
// Porting V1 makeOptions safely
|
|
211
183
|
if (item.order_number) {
|
|
212
|
-
|
|
213
|
-
this.jcodeOptions.push({
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
184
|
+
this.jcodeOptions.findIndex((elem) => elem.job_id === item.job_id) === -1
|
|
185
|
+
? this.jcodeOptions.push({
|
|
186
|
+
job_code: item.order_number,
|
|
187
|
+
job_id: item.job_id,
|
|
188
|
+
})
|
|
189
|
+
: null;
|
|
190
|
+
if (item.driver_list && item.driver_list?.length > 0) {
|
|
191
|
+
item.driver_list.forEach((driver) => {
|
|
192
|
+
this.driverOption.findIndex((elem) => elem === driver['driver_name']) === -1
|
|
193
|
+
? this.driverOption.push(driver['driver_name'])
|
|
194
|
+
: null;
|
|
195
|
+
this.truckingCompanayOption.findIndex((elem) => elem === driver['trucking_company']) === -1
|
|
196
|
+
? this.truckingCompanayOption.push(driver['trucking_company'])
|
|
197
|
+
: null;
|
|
225
198
|
});
|
|
226
199
|
}
|
|
227
200
|
}
|
|
228
|
-
|
|
229
|
-
this.pickupOptions.push(item.pickup_location)
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
this.
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
}
|
|
248
|
-
removedictValue(key) {
|
|
249
|
-
this.dict.delete(key);
|
|
201
|
+
this.pickupOptions.findIndex((elem) => elem === item.pickup_location) === -1
|
|
202
|
+
? this.pickupOptions.push(item.pickup_location)
|
|
203
|
+
: null;
|
|
204
|
+
this.destOptions.findIndex((elem) => elem === item.delivery_location) === -1
|
|
205
|
+
? this.destOptions.push(item.delivery_location)
|
|
206
|
+
: null;
|
|
207
|
+
this.customerOptions.findIndex((customer) => customer === item.customer_name) === -1
|
|
208
|
+
? this.customerOptions.push(item.customer_name)
|
|
209
|
+
: null;
|
|
210
|
+
this.unitOptions.findIndex((elem) => elem === item.unit) === -1
|
|
211
|
+
? this.unitOptions.push(item.unit)
|
|
212
|
+
: null;
|
|
213
|
+
this.materialOptions.findIndex((elem) => elem === item.material) === -1
|
|
214
|
+
? this.materialOptions.push(item.material)
|
|
215
|
+
: null;
|
|
216
|
+
if (item.route_name)
|
|
217
|
+
this.routeNameOptions.findIndex((elem) => elem === item.route_name) === -1
|
|
218
|
+
? this.routeNameOptions.push(item.route_name)
|
|
219
|
+
: null;
|
|
250
220
|
}
|
|
251
221
|
filter(value, filters) {
|
|
252
222
|
if (typeof value !== 'string') {
|
|
@@ -257,24 +227,22 @@ class UtilsService {
|
|
|
257
227
|
return [];
|
|
258
228
|
}
|
|
259
229
|
const searchResults = [];
|
|
260
|
-
this.unitOptions.
|
|
230
|
+
this.unitOptions.map((unit) => {
|
|
261
231
|
if (unit.toLowerCase().includes(filterValue)) {
|
|
262
232
|
searchResults.push({ type: 'unit', label: unit, value: unit });
|
|
263
233
|
}
|
|
264
234
|
});
|
|
265
|
-
this.customerOptions.
|
|
235
|
+
this.customerOptions.map((unit) => {
|
|
266
236
|
if (unit.toLowerCase().includes(filterValue)) {
|
|
267
237
|
searchResults.push({ type: 'customer', label: unit, value: unit });
|
|
268
238
|
}
|
|
269
239
|
});
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
}
|
|
277
|
-
this.pickupOptions.forEach((unit) => {
|
|
240
|
+
this.materialOptions.map((unit) => {
|
|
241
|
+
if (unit.toLowerCase().includes(filterValue)) {
|
|
242
|
+
searchResults.push({ type: 'material', label: unit, value: unit });
|
|
243
|
+
}
|
|
244
|
+
});
|
|
245
|
+
this.pickupOptions.map((unit) => {
|
|
278
246
|
if (unit.toLowerCase().includes(filterValue)) {
|
|
279
247
|
searchResults.push({
|
|
280
248
|
type: 'pickup location',
|
|
@@ -283,7 +251,7 @@ class UtilsService {
|
|
|
283
251
|
});
|
|
284
252
|
}
|
|
285
253
|
});
|
|
286
|
-
this.destOptions.
|
|
254
|
+
this.destOptions.map((unit) => {
|
|
287
255
|
if (unit.toLowerCase().includes(filterValue)) {
|
|
288
256
|
searchResults.push({
|
|
289
257
|
type: 'destination location',
|
|
@@ -292,7 +260,7 @@ class UtilsService {
|
|
|
292
260
|
});
|
|
293
261
|
}
|
|
294
262
|
});
|
|
295
|
-
this.jcodeOptions.
|
|
263
|
+
this.jcodeOptions.map((unit) => {
|
|
296
264
|
if (unit.job_code.toLowerCase().includes(filterValue)) {
|
|
297
265
|
searchResults.push({
|
|
298
266
|
type: 'job',
|
|
@@ -301,12 +269,12 @@ class UtilsService {
|
|
|
301
269
|
});
|
|
302
270
|
}
|
|
303
271
|
});
|
|
304
|
-
this.driverOption.
|
|
272
|
+
this.driverOption.map((unit) => {
|
|
305
273
|
if (unit.toLowerCase().includes(filterValue)) {
|
|
306
274
|
searchResults.push({ type: 'Driver', label: unit, value: unit });
|
|
307
275
|
}
|
|
308
276
|
});
|
|
309
|
-
this.truckingCompanayOption.
|
|
277
|
+
this.truckingCompanayOption.map((unit) => {
|
|
310
278
|
if (unit.toLowerCase().includes(filterValue)) {
|
|
311
279
|
searchResults.push({
|
|
312
280
|
type: 'Trucking Company',
|
|
@@ -315,19 +283,20 @@ class UtilsService {
|
|
|
315
283
|
});
|
|
316
284
|
}
|
|
317
285
|
});
|
|
318
|
-
this.routeNameOptions.
|
|
286
|
+
this.routeNameOptions.map((unit) => {
|
|
319
287
|
if (unit.toLowerCase().includes(filterValue)) {
|
|
320
288
|
searchResults.push({ type: 'Route name', label: unit, value: unit });
|
|
321
289
|
}
|
|
322
290
|
});
|
|
323
|
-
// Filter out options that are already selected in the filters array
|
|
324
291
|
const searchDict = {};
|
|
325
|
-
filters.
|
|
292
|
+
filters.map((filter) => {
|
|
326
293
|
searchDict[filter['name'] + filter['type']] = filter;
|
|
327
294
|
});
|
|
328
295
|
const furtherFilter = [];
|
|
329
|
-
searchResults.
|
|
330
|
-
if (
|
|
296
|
+
searchResults.map((search) => {
|
|
297
|
+
if (search['label'] + search['type'] in searchDict) {
|
|
298
|
+
}
|
|
299
|
+
else {
|
|
331
300
|
furtherFilter.push(search);
|
|
332
301
|
}
|
|
333
302
|
});
|
|
@@ -338,13 +307,15 @@ class UtilsService {
|
|
|
338
307
|
const result_list_boolean = [];
|
|
339
308
|
if (filterval.length > 0) {
|
|
340
309
|
if (filterval[0]['type'] === 'unit') {
|
|
341
|
-
result_list_boolean.push(filterval[0]['name'] ===
|
|
310
|
+
result_list_boolean.push(filterval[0]['name'] ===
|
|
311
|
+
element[filterval[0]['type']]);
|
|
342
312
|
}
|
|
343
313
|
if (filterval[0]['type'] === 'customer') {
|
|
344
314
|
result_list_boolean.push(filterval[0]['name'] === element['customer_name']);
|
|
345
315
|
}
|
|
346
316
|
if (filterval[0]['type'] === 'material') {
|
|
347
|
-
result_list_boolean.push(filterval[0]['name'] ===
|
|
317
|
+
result_list_boolean.push(filterval[0]['name'] ===
|
|
318
|
+
element[filterval[0]['type']]);
|
|
348
319
|
}
|
|
349
320
|
if (filterval[0]['type'] === 'pickup location') {
|
|
350
321
|
result_list_boolean.push(filterval[0]['name'] === element['pickup_location']);
|
|
@@ -359,16 +330,14 @@ class UtilsService {
|
|
|
359
330
|
result_list_boolean.push(filterval[0]['name'] === element['route_name']);
|
|
360
331
|
}
|
|
361
332
|
if (filterval[0]['type'] === 'Driver') {
|
|
362
|
-
const
|
|
363
|
-
const index = driverList.findIndex((ele) => {
|
|
333
|
+
const index = element.driver_list?.findIndex((ele) => {
|
|
364
334
|
return filterval[0]['name'] === ele['driver_name'];
|
|
365
335
|
});
|
|
366
336
|
if (index !== -1)
|
|
367
337
|
result_list_boolean.push(true);
|
|
368
338
|
}
|
|
369
339
|
if (filterval[0]['type'] === 'Trucking Company') {
|
|
370
|
-
const
|
|
371
|
-
const index = driverList.findIndex((ele) => {
|
|
340
|
+
const index = element.driver_list?.findIndex((ele) => {
|
|
372
341
|
return filterval[0]['name'] === ele['trucking_company'];
|
|
373
342
|
});
|
|
374
343
|
if (index !== -1)
|
|
@@ -381,8 +350,32 @@ class UtilsService {
|
|
|
381
350
|
return false;
|
|
382
351
|
});
|
|
383
352
|
}
|
|
353
|
+
clearOptions() {
|
|
354
|
+
this.pickupOptions = [];
|
|
355
|
+
this.destOptions = [];
|
|
356
|
+
this.ownerOptions = [];
|
|
357
|
+
this.customerOptions = [];
|
|
358
|
+
this.unitOptions = [];
|
|
359
|
+
this.materialOptions = [];
|
|
360
|
+
this.jcodeOptions = [];
|
|
361
|
+
this.routeNameOptions = [];
|
|
362
|
+
}
|
|
363
|
+
setdictValue(key, value) {
|
|
364
|
+
this.dict.set(key, value);
|
|
365
|
+
}
|
|
366
|
+
getdictValue(key) {
|
|
367
|
+
return JSON.parse(this.dict.get(key));
|
|
368
|
+
}
|
|
369
|
+
removedictValue(key) {
|
|
370
|
+
this.dict.delete(key);
|
|
371
|
+
}
|
|
372
|
+
conveySearchIcon(value) {
|
|
373
|
+
if (value && typeof value !== 'object')
|
|
374
|
+
return true;
|
|
375
|
+
return false;
|
|
376
|
+
}
|
|
384
377
|
fetchUnitsList() {
|
|
385
|
-
return new Promise((resolve) => {
|
|
378
|
+
return new Promise((resolve, reject) => {
|
|
386
379
|
if (!this.unitsList) {
|
|
387
380
|
this.getData('unit/list/view').subscribe((res) => {
|
|
388
381
|
if (res) {
|
|
@@ -396,38 +389,49 @@ class UtilsService {
|
|
|
396
389
|
}
|
|
397
390
|
});
|
|
398
391
|
}
|
|
399
|
-
|
|
400
|
-
return new Promise((resolve) => {
|
|
401
|
-
if (!this.
|
|
392
|
+
fetchMaterialsList() {
|
|
393
|
+
return new Promise((resolve, reject) => {
|
|
394
|
+
if (!this.materialsList) {
|
|
402
395
|
this.getData('material/list/view').subscribe((res) => {
|
|
403
|
-
|
|
404
|
-
|
|
396
|
+
res.data.sort((a, b) => a.material.localeCompare(b.material));
|
|
397
|
+
this.materialsList = res.data;
|
|
398
|
+
resolve(this.materialsList);
|
|
405
399
|
});
|
|
406
400
|
}
|
|
407
401
|
else {
|
|
408
|
-
resolve(this.
|
|
402
|
+
resolve(this.materialsList);
|
|
409
403
|
}
|
|
410
404
|
});
|
|
411
405
|
}
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
406
|
+
fetchMaterialsListForCustomer() {
|
|
407
|
+
return new Promise((resolve, reject) => {
|
|
408
|
+
if (!this.materialsListForCustomer) {
|
|
409
|
+
this.getData('material/list/view').subscribe((res) => {
|
|
410
|
+
let meterialListDetails = [];
|
|
411
|
+
res.data.map((item) => {
|
|
412
|
+
if (item.sub.length > 0) {
|
|
413
|
+
item.sub.map((subItem) => {
|
|
414
|
+
if (subItem.add_to_marketplace) {
|
|
415
|
+
subItem.material = item.material;
|
|
416
|
+
subItem.material_id = item.material_id;
|
|
417
|
+
subItem.label = item.material + ' | ' + subItem.sub_material;
|
|
418
|
+
meterialListDetails.push(subItem);
|
|
419
|
+
}
|
|
420
|
+
});
|
|
421
|
+
}
|
|
422
|
+
});
|
|
423
|
+
meterialListDetails.sort((a, b) => a.label.localeCompare(b.label));
|
|
424
|
+
this.materialsListForCustomer = meterialListDetails;
|
|
425
|
+
resolve(this.materialsListForCustomer);
|
|
423
426
|
});
|
|
424
427
|
}
|
|
428
|
+
else {
|
|
429
|
+
resolve(this.materialsListForCustomer);
|
|
430
|
+
}
|
|
425
431
|
});
|
|
426
|
-
meterialList.sort((a, b) => a.label.localeCompare(b.label));
|
|
427
|
-
return meterialList;
|
|
428
432
|
}
|
|
429
433
|
fetchCustomersList() {
|
|
430
|
-
return new Promise((resolve) => {
|
|
434
|
+
return new Promise((resolve, reject) => {
|
|
431
435
|
if (!this.customersList) {
|
|
432
436
|
this.getData('company/list/view').subscribe((res) => {
|
|
433
437
|
if (res) {
|
|
@@ -441,168 +445,74 @@ class UtilsService {
|
|
|
441
445
|
}
|
|
442
446
|
});
|
|
443
447
|
}
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
this.getRestData('locations/all').subscribe({
|
|
447
|
-
next: (res) => {
|
|
448
|
-
if (res) {
|
|
449
|
-
this.locationList = res.data.map((object) => {
|
|
450
|
-
object.formatted_address = `${object.name} | ${object.street} ${object.city}, ${object.state} ${object.zip}`;
|
|
451
|
-
return {
|
|
452
|
-
city: object.city,
|
|
453
|
-
lng: object.longitude,
|
|
454
|
-
location_id: object.location_id,
|
|
455
|
-
lat: object.latitude,
|
|
456
|
-
name: object.name,
|
|
457
|
-
state: object.state,
|
|
458
|
-
street: object.street,
|
|
459
|
-
zip: object.zip,
|
|
460
|
-
formatted_address: object.formatted_address
|
|
461
|
-
};
|
|
462
|
-
});
|
|
463
|
-
resolve(this.locationList);
|
|
464
|
-
}
|
|
465
|
-
},
|
|
466
|
-
error: (err) => {
|
|
467
|
-
console.error(err);
|
|
468
|
-
reject(err);
|
|
469
|
-
}
|
|
470
|
-
});
|
|
471
|
-
});
|
|
472
|
-
}
|
|
473
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.24", ngImport: i0, type: UtilsService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
474
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.24", ngImport: i0, type: UtilsService, providedIn: 'root' });
|
|
448
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.2.1", ngImport: i0, type: UtilsService, deps: [{ token: i1.HttpClient }, { token: i2.MatSnackBar }, { token: 'memberData' }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
449
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.2.1", ngImport: i0, type: UtilsService, providedIn: 'root' });
|
|
475
450
|
}
|
|
476
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
451
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.2.1", ngImport: i0, type: UtilsService, decorators: [{
|
|
477
452
|
type: Injectable,
|
|
478
453
|
args: [{ providedIn: 'root' }]
|
|
479
|
-
}] }
|
|
454
|
+
}], ctorParameters: () => [{ type: i1.HttpClient }, { type: i2.MatSnackBar }, { type: CoolmapConfigModel, decorators: [{
|
|
455
|
+
type: Inject,
|
|
456
|
+
args: ['memberData']
|
|
457
|
+
}] }, { type: i0.NgZone }] });
|
|
480
458
|
|
|
481
|
-
class
|
|
459
|
+
class CoolmapService {
|
|
460
|
+
utils;
|
|
461
|
+
eventManager;
|
|
462
|
+
config;
|
|
482
463
|
map;
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
markerOriginList = new Map();
|
|
486
|
-
markerDestinationList = new Map();
|
|
487
|
-
activeRoutesRegistry = new Map();
|
|
488
|
-
pathCache = new Map();
|
|
489
|
-
// Native 3D Simulation Engine
|
|
490
|
-
svgOverlay = null;
|
|
491
|
-
activeArcs = {};
|
|
464
|
+
markerOriginList = [];
|
|
465
|
+
markerDestinationList = [];
|
|
492
466
|
initiatecoolmap = new BehaviorSubject(true);
|
|
493
467
|
reintiatecoolmap = this.initiatecoolmap.asObservable();
|
|
494
|
-
isMapReady = signal(false, ...(ngDevMode ? [{ debugName: "isMapReady" }] : []));
|
|
495
468
|
bounds = new mapboxgl.LngLatBounds();
|
|
496
|
-
originDestinationCordinates =
|
|
469
|
+
originDestinationCordinates = [];
|
|
497
470
|
padding;
|
|
498
|
-
windowActualHeightWidth
|
|
471
|
+
windowActualHeightWidth;
|
|
499
472
|
popup;
|
|
500
473
|
customTopForCustomer;
|
|
501
|
-
utils
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
ensureMapboxWorker();
|
|
474
|
+
constructor(utils, eventManager, config) {
|
|
475
|
+
this.utils = utils;
|
|
476
|
+
this.eventManager = eventManager;
|
|
477
|
+
this.config = config;
|
|
506
478
|
this.customTopForCustomer = this.config.repository === 'customer' ? 65 : 0;
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
window.addEventListener('resize', this.onResize.bind(this));
|
|
510
|
-
}
|
|
479
|
+
this.windowActualHeightWidth = { availHeight: 0 };
|
|
480
|
+
window.addEventListener('resize', this.onResize.bind(this));
|
|
511
481
|
}
|
|
512
|
-
|
|
513
|
-
if (!this.map) {
|
|
514
|
-
this.currentStyleIsDark = isDark;
|
|
515
|
-
return;
|
|
516
|
-
}
|
|
517
|
-
if (this.currentStyleIsDark === isDark)
|
|
518
|
-
return;
|
|
519
|
-
this.currentStyleIsDark = isDark;
|
|
520
|
-
const style = isDark
|
|
521
|
-
? 'mapbox://styles/mapbox/dark-v11'
|
|
522
|
-
: 'mapbox://styles/mapbox/light-v11';
|
|
523
|
-
this.map.setStyle(style);
|
|
524
|
-
this.map.once('style.load', () => {
|
|
525
|
-
this.reAddLayers();
|
|
526
|
-
});
|
|
527
|
-
}
|
|
528
|
-
getRegistryKeys() {
|
|
529
|
-
return Array.from(this.activeRoutesRegistry.keys());
|
|
530
|
-
}
|
|
531
|
-
// Renamed to initializeMap to preserve the existing bindings in coolmap.component.ts
|
|
532
|
-
initializeMap(el, isDark = false) {
|
|
533
|
-
this.currentStyleIsDark = isDark;
|
|
534
|
-
const styleUrl = isDark ? 'mapbox://styles/mapbox/dark-v11' : 'mapbox://styles/mapbox/light-v11';
|
|
535
|
-
// If map already exists for this container, just update style and clear routes to avoid flickering
|
|
536
|
-
if (this.map && this.mapContainer === el) {
|
|
537
|
-
el.style.transition = 'opacity 0.3s ease-in-out';
|
|
538
|
-
el.style.opacity = '0.7';
|
|
539
|
-
this.map.setStyle(styleUrl);
|
|
540
|
-
return new Promise((resolve) => {
|
|
541
|
-
this.map.once('style.load', () => {
|
|
542
|
-
this.clearAllRoutes();
|
|
543
|
-
this.isMapReady.set(true);
|
|
544
|
-
el.style.opacity = '1';
|
|
545
|
-
resolve(this.map);
|
|
546
|
-
});
|
|
547
|
-
});
|
|
548
|
-
}
|
|
482
|
+
initiateMapForAddRoute(el) {
|
|
549
483
|
return new Promise((resolve, reject) => {
|
|
550
|
-
this.
|
|
551
|
-
if (this.map) {
|
|
484
|
+
if (this.map)
|
|
552
485
|
this.map.remove();
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
this.resizeObserver = null;
|
|
556
|
-
}
|
|
557
|
-
}
|
|
558
|
-
// Add a smooth fade-in for fresh initialization
|
|
559
|
-
el.style.transition = 'opacity 0.5s ease-in-out';
|
|
560
|
-
el.style.opacity = '0';
|
|
561
|
-
const token = typeof window !== 'undefined' ? window.__env?.mapboxAccessToken || '' : '';
|
|
562
|
-
const mapbox = ensureMapboxWorker();
|
|
563
|
-
mapbox.accessToken = token;
|
|
564
|
-
this.map = new mapbox.Map({
|
|
486
|
+
this.map = new mapboxgl.Map({
|
|
487
|
+
accessToken: this.config.mapboxAccessToken,
|
|
565
488
|
container: el,
|
|
566
|
-
style:
|
|
489
|
+
style: this.config.mapboxStyle,
|
|
567
490
|
center: [-77.036873, 38.907192],
|
|
568
491
|
zoom: 10,
|
|
569
492
|
bearing: 0,
|
|
570
493
|
pitch: 65,
|
|
571
494
|
interactive: true,
|
|
572
|
-
attributionControl: false,
|
|
573
|
-
antialias: true,
|
|
574
|
-
projection: { name: 'globe' }
|
|
575
|
-
});
|
|
576
|
-
this.map.addControl(new mapboxgl.AttributionControl({ compact: true }), 'bottom-right');
|
|
577
|
-
this.map.addControl(new mapboxgl.NavigationControl({ showCompass: false }), 'top-right');
|
|
578
|
-
this.resizeObserver = new ResizeObserver(() => {
|
|
579
|
-
if (this.map) {
|
|
580
|
-
this.map.resize();
|
|
581
|
-
}
|
|
582
495
|
});
|
|
583
|
-
this.resizeObserver.observe(el);
|
|
584
496
|
this.map.once('load', (res) => {
|
|
585
|
-
this.isMapReady.set(true);
|
|
586
|
-
if (this.mapContainer)
|
|
587
|
-
this.mapContainer.style.opacity = '1';
|
|
588
497
|
resolve(res);
|
|
589
498
|
});
|
|
590
499
|
});
|
|
591
500
|
}
|
|
592
|
-
//
|
|
593
|
-
loadMapProperty(pinRouteGeojson, index, unit,
|
|
594
|
-
return new Promise((resolve) => {
|
|
595
|
-
|
|
596
|
-
return resolve(false);
|
|
597
|
-
const origin = pinRouteGeojson.features[0].geometry.coordinates[0];
|
|
501
|
+
// Below method Load route with animation
|
|
502
|
+
loadMapProperty(pinRouteGeojson, index, unit, route, bottom) {
|
|
503
|
+
return new Promise((resolve, reject) => {
|
|
504
|
+
let origin = pinRouteGeojson.features[0].geometry.coordinates[0];
|
|
598
505
|
const linecolor = unit === 'Ton' ? '#ff7272' : unit === 'Load' ? '#a3c52e' : '#ae23d1';
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
this.extendBound(pinRouteGeojson.features[0].geometry.coordinates, true, registryId).then(() => {
|
|
506
|
+
let destination = pinRouteGeojson.features[0].geometry.coordinates[pinRouteGeojson.features[0].geometry.coordinates.length - 1];
|
|
507
|
+
this.extendBound(pinRouteGeojson.features[0].geometry.coordinates, true).then((res) => {
|
|
602
508
|
const point = {
|
|
603
509
|
type: 'FeatureCollection',
|
|
604
510
|
features: [
|
|
605
|
-
{
|
|
511
|
+
{
|
|
512
|
+
type: 'Feature',
|
|
513
|
+
properties: {},
|
|
514
|
+
geometry: { type: 'Point', coordinates: origin },
|
|
515
|
+
},
|
|
606
516
|
],
|
|
607
517
|
};
|
|
608
518
|
const lineDistance = turf.length(pinRouteGeojson.features[0]);
|
|
@@ -614,356 +524,256 @@ class MapboxService {
|
|
|
614
524
|
}
|
|
615
525
|
pinRouteGeojson.features[0].geometry.coordinates = arc;
|
|
616
526
|
const pinRoute = pinRouteGeojson.features[0].geometry.coordinates;
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
this.removeRouteAndMarker(index, 'addroute').then(() => { });
|
|
624
|
-
}
|
|
625
|
-
this.map.addSource(`line${index}`, {
|
|
626
|
-
type: 'geojson',
|
|
627
|
-
lineMetrics: true,
|
|
628
|
-
data: pinRouteGeojson,
|
|
629
|
-
});
|
|
630
|
-
this.map.addLayer({
|
|
631
|
-
type: 'line',
|
|
632
|
-
source: `line${index}`,
|
|
633
|
-
id: `line${index}`,
|
|
634
|
-
paint: {
|
|
635
|
-
'line-width': 2,
|
|
636
|
-
'line-gradient': [
|
|
637
|
-
'interpolate', ['linear'], ['line-progress'],
|
|
638
|
-
0, unit === 'Ton' ? '#d7f7e4' : unit === 'Load' ? '#c9d8f5' : '#f5dcc1',
|
|
639
|
-
1, unit === 'Ton' ? '#ff7272' : unit === 'Load' ? '#a3c52e' : '#ae23d1',
|
|
640
|
-
],
|
|
641
|
-
},
|
|
642
|
-
layout: { 'line-cap': 'round', 'line-join': 'round' },
|
|
643
|
-
});
|
|
644
|
-
const dataSetForMap = {
|
|
645
|
-
counter: 0,
|
|
646
|
-
pinRouteGeojson,
|
|
647
|
-
steps,
|
|
648
|
-
point,
|
|
649
|
-
pointId: `point${index}`,
|
|
650
|
-
marker,
|
|
651
|
-
pinRoute,
|
|
652
|
-
lineId: `line${index}`,
|
|
653
|
-
index,
|
|
654
|
-
origin,
|
|
655
|
-
destination,
|
|
656
|
-
lineDistance,
|
|
657
|
-
linecolor,
|
|
658
|
-
route: routeProps,
|
|
659
|
-
routeType: 'addroute',
|
|
660
|
-
isViewRoute: true,
|
|
661
|
-
};
|
|
662
|
-
this.createMarker(dataSetForMap);
|
|
663
|
-
this.map.on('mouseenter', `line${index}`, (e) => {
|
|
664
|
-
this.map.setPaintProperty(`line${index}`, 'line-width', 5);
|
|
665
|
-
this.map.setPaintProperty(`line${index}`, 'line-opacity', 1);
|
|
666
|
-
const datasetForPopup = {
|
|
667
|
-
coordinate: [e.lngLat.lng, e.lngLat.lat],
|
|
668
|
-
pickup: routeProps?.pickup_location || '',
|
|
669
|
-
drop: routeProps?.delivery_location || '',
|
|
670
|
-
routeType: routeProps?.project ? 'Project' : 'Route',
|
|
671
|
-
title: routeProps?.project ? routeProps.project : routeProps?.route_name || '',
|
|
672
|
-
material: routeProps?.material || '',
|
|
673
|
-
type: routeProps?.unit || '',
|
|
674
|
-
};
|
|
675
|
-
if (this.popup)
|
|
676
|
-
this.popup.remove();
|
|
677
|
-
this.createPopup(datasetForPopup);
|
|
678
|
-
});
|
|
679
|
-
this.map.on('mouseleave', `line${index}`, () => {
|
|
680
|
-
this.map.setPaintProperty(`line${index}`, 'line-width', 2);
|
|
681
|
-
if (this.popup)
|
|
682
|
-
this.popup.remove();
|
|
683
|
-
});
|
|
527
|
+
const marker = new mapboxgl.Marker(document.createElement('div'))
|
|
528
|
+
.setLngLat(pinRoute[0])
|
|
529
|
+
.addTo(this.map)
|
|
530
|
+
.togglePopup();
|
|
531
|
+
if (this.map.getSource(`line${index}`)) {
|
|
532
|
+
this.removeRouteAndMarker(index).then(() => { });
|
|
684
533
|
}
|
|
534
|
+
this.map.addSource(`line${index}`, {
|
|
535
|
+
type: 'geojson',
|
|
536
|
+
lineMetrics: true,
|
|
537
|
+
data: pinRouteGeojson,
|
|
538
|
+
});
|
|
539
|
+
this.map.addLayer({
|
|
540
|
+
type: 'line',
|
|
541
|
+
source: `line${index}`,
|
|
542
|
+
id: `line${index}`,
|
|
543
|
+
paint: {
|
|
544
|
+
'line-width': 2,
|
|
545
|
+
'line-gradient': [
|
|
546
|
+
'interpolate',
|
|
547
|
+
['linear'],
|
|
548
|
+
['line-progress'],
|
|
549
|
+
0,
|
|
550
|
+
unit === 'Ton'
|
|
551
|
+
? '#d7f7e4'
|
|
552
|
+
: unit === 'Load'
|
|
553
|
+
? '#c9d8f5'
|
|
554
|
+
: '#f5dcc1',
|
|
555
|
+
1,
|
|
556
|
+
unit === 'Ton'
|
|
557
|
+
? '#ff7272'
|
|
558
|
+
: unit === 'Load'
|
|
559
|
+
? '#a3c52e'
|
|
560
|
+
: '#ae23d1',
|
|
561
|
+
],
|
|
562
|
+
},
|
|
563
|
+
layout: { 'line-cap': 'round', 'line-join': 'round' },
|
|
564
|
+
});
|
|
565
|
+
const dataSetForMap = {
|
|
566
|
+
counter: 0,
|
|
567
|
+
pinRouteGeojson,
|
|
568
|
+
steps,
|
|
569
|
+
point,
|
|
570
|
+
pointId: `point${index}`,
|
|
571
|
+
marker,
|
|
572
|
+
pinRoute,
|
|
573
|
+
lineId: `line${index}`,
|
|
574
|
+
index,
|
|
575
|
+
origin,
|
|
576
|
+
destination,
|
|
577
|
+
lineDistance,
|
|
578
|
+
linecolor,
|
|
579
|
+
route,
|
|
580
|
+
isViewRoute: true,
|
|
581
|
+
};
|
|
582
|
+
this.createMarker(dataSetForMap);
|
|
583
|
+
this.map.on('mouseenter', `line${index}`, (e) => {
|
|
584
|
+
this.map.setPaintProperty(`line${index}`, 'line-width', 5);
|
|
585
|
+
this.map.setPaintProperty(`line${index}`, 'line-opacity', 1);
|
|
586
|
+
const datasetForPopup = {
|
|
587
|
+
coordinate: [e.lngLat.lng, e.lngLat.lat],
|
|
588
|
+
pickup: route.pickup_location ? route.pickup_location : '',
|
|
589
|
+
drop: route.delivery_location ? route.delivery_location : '',
|
|
590
|
+
routeType: route.project ? 'Project' : 'Route',
|
|
591
|
+
title: route.project
|
|
592
|
+
? route.project
|
|
593
|
+
: route.route_name
|
|
594
|
+
? route.route_name
|
|
595
|
+
: '',
|
|
596
|
+
material: route.materialLabel ? route.materialLabel : '',
|
|
597
|
+
type: route.unit ? route.unit : '',
|
|
598
|
+
};
|
|
599
|
+
this.createPopup(datasetForPopup);
|
|
600
|
+
});
|
|
601
|
+
this.map.on('mouseleave', `line${index}`, (e) => {
|
|
602
|
+
this.map.setPaintProperty(`line${index}`, 'line-width', 2);
|
|
603
|
+
if (this.popup) {
|
|
604
|
+
this.popup.remove();
|
|
605
|
+
}
|
|
606
|
+
});
|
|
685
607
|
});
|
|
686
|
-
this.map.once('idle', () => {
|
|
608
|
+
this.map.once('idle', (res) => {
|
|
687
609
|
resolve(true);
|
|
688
610
|
});
|
|
689
611
|
});
|
|
690
612
|
}
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
popup.remove();
|
|
716
|
-
});
|
|
717
|
-
// Destination Marker (Delivery)
|
|
718
|
-
const elementForDestination = document.createElement('div');
|
|
719
|
-
elementForDestination.className = 'cursor-pointer active:scale-95 transition-transform duration-200 drop-shadow-lg';
|
|
720
|
-
elementForDestination.style.zIndex = '100';
|
|
721
|
-
const deliveryLabel = 'D';
|
|
722
|
-
elementForDestination.innerHTML = `
|
|
723
|
-
<svg width="30" height="38" viewBox="0 0 30 38" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
724
|
-
<path d="M15 0C6.71573 0 0 6.71573 0 15C0 26.25 15 38 15 38C15 38 30 26.25 30 15C30 6.71573 23.2843 0 15 0Z" fill="${routeDetails.linecolor}"/>
|
|
725
|
-
<circle cx="15" cy="15" r="9" fill="white"/>
|
|
726
|
-
<text x="15" y="19" text-anchor="middle" fill="black" style="font-family: Inter, sans-serif; font-size: 13px; font-weight: 800;">${deliveryLabel}</text>
|
|
727
|
-
</svg>
|
|
728
|
-
`;
|
|
729
|
-
const destinationMarker = new mapboxgl.Marker({ element: elementForDestination, anchor: 'bottom' })
|
|
730
|
-
.setLngLat(routeDetails.destination)
|
|
731
|
-
.addTo(this.map);
|
|
732
|
-
destinationMarker.getElement().addEventListener('mouseenter', () => {
|
|
733
|
-
popupForDestination.setLngLat(routeDetails.destination).addTo(this.map);
|
|
734
|
-
});
|
|
735
|
-
destinationMarker.getElement().addEventListener('mouseleave', () => {
|
|
736
|
-
popupForDestination.remove();
|
|
737
|
-
});
|
|
738
|
-
const id = `${routeDetails.routeType}-${routeDetails.index}`;
|
|
739
|
-
this.markerOriginList.set(id, originMarker);
|
|
740
|
-
this.markerDestinationList.set(id, destinationMarker);
|
|
741
|
-
// True 3D Elevated Arc Simulation Engine using Native SVG Overlays
|
|
742
|
-
try {
|
|
743
|
-
this.initSvgOverlay();
|
|
744
|
-
const pathEl = document.createElementNS('http://www.w3.org/2000/svg', 'path');
|
|
745
|
-
pathEl.setAttribute('fill', 'none');
|
|
746
|
-
pathEl.setAttribute('stroke-width', '3');
|
|
747
|
-
pathEl.style.cursor = 'pointer';
|
|
748
|
-
pathEl.style.pointerEvents = 'stroke'; // Allow interactivity!
|
|
749
|
-
const gradId = `arc-grad-${id}`;
|
|
750
|
-
const defs = this.svgOverlay.querySelector('defs');
|
|
751
|
-
let grad = defs.querySelector(`#${gradId}`);
|
|
752
|
-
if (!grad) {
|
|
753
|
-
grad = document.createElementNS('http://www.w3.org/2000/svg', 'linearGradient');
|
|
754
|
-
grad.setAttribute('id', gradId);
|
|
755
|
-
defs.appendChild(grad);
|
|
613
|
+
// Below method Load route without animation
|
|
614
|
+
drawLine(cordinates, index, route, enablefitbound, routeType) {
|
|
615
|
+
let linecolor;
|
|
616
|
+
let origin = cordinates[0];
|
|
617
|
+
let destination = cordinates[cordinates.length - 1];
|
|
618
|
+
if (origin[0] &&
|
|
619
|
+
origin[1] &&
|
|
620
|
+
destination &&
|
|
621
|
+
destination[0] &&
|
|
622
|
+
destination[1]) {
|
|
623
|
+
linecolor = this.provideLineColor(route['unit'], routeType);
|
|
624
|
+
if (enablefitbound) {
|
|
625
|
+
const padding = {
|
|
626
|
+
top: this.padding.top + this.customTopForCustomer,
|
|
627
|
+
bottom: this.padding.bottom +
|
|
628
|
+
(this.windowActualHeightWidth.availHeight -
|
|
629
|
+
(window.innerHeight - 65)),
|
|
630
|
+
left: this.padding.left,
|
|
631
|
+
right: this.padding.right,
|
|
632
|
+
};
|
|
633
|
+
this.map.fitBounds([origin, destination], { padding, pitch: 65 }, { fitboundCompleteJob: true });
|
|
634
|
+
}
|
|
635
|
+
if (this.map.getSource(`route-source-for-job-code${index}`)) {
|
|
636
|
+
this.removeRouteAndMarker(index).then(() => { });
|
|
756
637
|
}
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
638
|
+
this.map.addSource(`route-source-for-job-code${index}`, {
|
|
639
|
+
type: 'geojson',
|
|
640
|
+
data: {
|
|
641
|
+
type: 'Feature',
|
|
642
|
+
properties: {},
|
|
643
|
+
geometry: { type: 'LineString', coordinates: cordinates },
|
|
644
|
+
},
|
|
645
|
+
});
|
|
646
|
+
this.map.addLayer({
|
|
647
|
+
id: `route-for-job-code${index}`,
|
|
648
|
+
type: 'line',
|
|
649
|
+
source: `route-source-for-job-code${index}`,
|
|
650
|
+
paint: { 'line-color': linecolor, 'line-width': 2 },
|
|
651
|
+
layout: { 'line-cap': 'round', 'line-join': 'round' },
|
|
652
|
+
});
|
|
653
|
+
const dataSetForMap = {
|
|
654
|
+
origin,
|
|
655
|
+
destination,
|
|
656
|
+
index,
|
|
657
|
+
linecolor,
|
|
658
|
+
route,
|
|
768
659
|
};
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
coordinate: [lngLat.lng, lngLat.lat],
|
|
778
|
-
|
|
660
|
+
this.createMarker(dataSetForMap);
|
|
661
|
+
this.map.on('mouseenter', `route-for-job-code${index}`, (e) => {
|
|
662
|
+
if (this.popup) {
|
|
663
|
+
this.popup.remove();
|
|
664
|
+
}
|
|
665
|
+
this.map.setPaintProperty(`route-for-job-code${index}`, 'line-width', 5);
|
|
666
|
+
this.map.setPaintProperty(`route-for-job-code${index}`, 'line-opacity', 1);
|
|
667
|
+
const datasetForPopup = {
|
|
668
|
+
coordinate: [e.lngLat.lng, e.lngLat.lat],
|
|
669
|
+
pickup: route.pickup_location ? route.pickup_location : '',
|
|
670
|
+
drop: route.delivery_location ? route.delivery_location : '',
|
|
671
|
+
jobCode: route.project ? route.order_number : null,
|
|
672
|
+
customer: route.project ? route.customer_name : null,
|
|
673
|
+
routeType: route.project ? 'Project' : 'Route',
|
|
674
|
+
title: route.project
|
|
675
|
+
? route.project
|
|
676
|
+
: route.route_name
|
|
677
|
+
? route.route_name
|
|
678
|
+
: '',
|
|
679
|
+
material: route.materialLabel ? route.materialLabel : '',
|
|
680
|
+
type: route.unit ? route.unit : '',
|
|
779
681
|
};
|
|
780
|
-
this.
|
|
682
|
+
this.createPopup(datasetForPopup);
|
|
781
683
|
});
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
684
|
+
this.map.on('mouseleave', `route-for-job-code${index}`, (e) => {
|
|
685
|
+
this.map.setPaintProperty(`route-for-job-code${index}`, 'line-width', 2);
|
|
686
|
+
if (this.popup) {
|
|
687
|
+
this.popup.remove();
|
|
688
|
+
}
|
|
786
689
|
});
|
|
787
|
-
this.updateSvgPaths(); // Force plot
|
|
788
690
|
}
|
|
789
|
-
|
|
790
|
-
|
|
691
|
+
}
|
|
692
|
+
provideLineColor(unitType, type) {
|
|
693
|
+
let checkType = type && !['jobrouteList', 'addroute'].includes(type) ? true : false;
|
|
694
|
+
let color;
|
|
695
|
+
switch (unitType) {
|
|
696
|
+
case 'Ton':
|
|
697
|
+
color = checkType ? '#39c471' : '#ff7272';
|
|
698
|
+
break;
|
|
699
|
+
case 'Load':
|
|
700
|
+
color = checkType ? '#326ad3' : '#a3c52e';
|
|
701
|
+
break;
|
|
702
|
+
case 'Hourly':
|
|
703
|
+
color = checkType ? '#ffad56' : '#ae23d1';
|
|
704
|
+
break;
|
|
791
705
|
}
|
|
706
|
+
return color;
|
|
792
707
|
}
|
|
793
708
|
showRoutePopup(arcDetails, event, isViewRoute) {
|
|
794
|
-
const data = arcDetails.layer.props.data;
|
|
795
|
-
const layerId = isViewRoute
|
|
796
|
-
? `line${data.index}`
|
|
797
|
-
: `route-layer-${data.routeType || 'jobcode'}-${data.index}`;
|
|
798
709
|
if (this.popup) {
|
|
799
710
|
this.popup.remove();
|
|
800
|
-
|
|
801
|
-
this.map.setPaintProperty(layerId, 'line-width', 2);
|
|
802
|
-
}
|
|
711
|
+
this.map.setPaintProperty(`${isViewRoute ? 'line' : 'route-for-job-code'}${arcDetails.layer.props.data.index}`, 'line-width', 2);
|
|
803
712
|
}
|
|
804
|
-
if (arcDetails.color &&
|
|
805
|
-
this.map.
|
|
806
|
-
|
|
713
|
+
if (arcDetails.color &&
|
|
714
|
+
this.map.getLayoutProperty(arcDetails.layer.id, 'visibility') !== 'none') {
|
|
715
|
+
this.map.setPaintProperty(`${isViewRoute ? 'line' : 'route-for-job-code'}${arcDetails.layer.props.data.index}`, 'line-width', 5);
|
|
716
|
+
this.map.setPaintProperty(`${isViewRoute ? 'line' : 'route-for-job-code'}${arcDetails.layer.props.data.index}`, 'line-opacity', 1);
|
|
807
717
|
const datasetForPopup = {
|
|
808
718
|
coordinate: arcDetails.coordinate,
|
|
809
|
-
pickup: arcDetails.layer.props.data.route.pickup_location
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
719
|
+
pickup: arcDetails.layer.props.data.route.pickup_location
|
|
720
|
+
? arcDetails.layer.props.data.route.pickup_location
|
|
721
|
+
: '',
|
|
722
|
+
drop: arcDetails.layer.props.data.route.delivery_location
|
|
723
|
+
? arcDetails.layer.props.data.route.delivery_location
|
|
724
|
+
: '',
|
|
725
|
+
jobCode: arcDetails.layer.props.data.route.project
|
|
726
|
+
? arcDetails.layer.props.data.route.order_number
|
|
727
|
+
: '',
|
|
728
|
+
customer: arcDetails.layer.props.data.route.project
|
|
729
|
+
? arcDetails.layer.props.data.route.customer_name
|
|
730
|
+
: '',
|
|
731
|
+
routeType: arcDetails.layer.props.data.route.project
|
|
732
|
+
? 'Project'
|
|
733
|
+
: 'Route',
|
|
734
|
+
title: arcDetails.layer.props.data.route.project
|
|
735
|
+
? arcDetails.layer.props.data.route.project
|
|
736
|
+
: arcDetails.layer.props.data.route.route_name
|
|
737
|
+
? arcDetails.layer.props.data.route.route_name
|
|
738
|
+
: '',
|
|
739
|
+
material: arcDetails.layer.props.data.route.materialLabel
|
|
740
|
+
? arcDetails.layer.props.data.route.materialLabel
|
|
741
|
+
: '',
|
|
742
|
+
type: arcDetails.layer.props.data.route.unit
|
|
743
|
+
? arcDetails.layer.props.data.route.unit
|
|
744
|
+
: '',
|
|
817
745
|
};
|
|
818
746
|
this.createPopup(datasetForPopup);
|
|
819
747
|
}
|
|
820
748
|
}
|
|
821
749
|
createPopup(datasetForPopup) {
|
|
822
|
-
if (!this.map)
|
|
823
|
-
return;
|
|
824
750
|
this.popup = new mapboxgl.Popup({
|
|
825
751
|
closeButton: false,
|
|
826
752
|
closeOnClick: false,
|
|
827
753
|
closeOnMove: true,
|
|
828
|
-
className: 'pointer-events-none',
|
|
829
754
|
anchor: 'bottom-left',
|
|
830
755
|
});
|
|
831
|
-
// Extract location short names
|
|
832
|
-
const pickupDisplay = datasetForPopup.pickup?.split('|')[1] || datasetForPopup.pickup || 'Unknown Pickup';
|
|
833
|
-
const dropDisplay = datasetForPopup.drop?.split('|')[1] || datasetForPopup.drop || 'Unknown Delivery';
|
|
834
756
|
this.popup
|
|
835
757
|
.setLngLat(datasetForPopup.coordinate)
|
|
836
|
-
.setHTML(
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
<p class="
|
|
758
|
+
.setHTML(`
|
|
759
|
+
<div class="destination">
|
|
760
|
+
<div class="duration">
|
|
761
|
+
<p class="pickprt"><b>Pickup Location:</b> ${datasetForPopup.pickup}</p>
|
|
762
|
+
<p class="dropprt"><b>Drop Location:</b> ${datasetForPopup.drop}</p>
|
|
840
763
|
</div>
|
|
841
|
-
${datasetForPopup.jobCode
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
${datasetForPopup.
|
|
845
|
-
|
|
846
|
-
|
|
764
|
+
${datasetForPopup.jobCode
|
|
765
|
+
? '<span><b>Job Code:</b> ' + datasetForPopup.jobCode + '</span>'
|
|
766
|
+
: ''}
|
|
767
|
+
${datasetForPopup.customer
|
|
768
|
+
? '<span><b>Customer:</b> ' + datasetForPopup.customer + '</span>'
|
|
769
|
+
: ''}
|
|
770
|
+
<span><b>${datasetForPopup.routeType} Name:</b> ${datasetForPopup.title}</span>
|
|
771
|
+
<span><b>Material:</b> ${datasetForPopup.material}</span>
|
|
772
|
+
<span><b>Type:</b> ${datasetForPopup.type}</span>
|
|
773
|
+
</div>
|
|
774
|
+
`)
|
|
847
775
|
.addTo(this.map);
|
|
848
776
|
}
|
|
849
|
-
// Draw Line
|
|
850
|
-
drawLine(cordinates, index, route, enablefitbound, routeType, isStyleRefresh) {
|
|
851
|
-
return new Promise((resolve) => {
|
|
852
|
-
if (!this.map || !this.isMapReady()) {
|
|
853
|
-
resolve();
|
|
854
|
-
return;
|
|
855
|
-
}
|
|
856
|
-
// Calculate bounds for this specific route
|
|
857
|
-
const routeBounds = new mapboxgl.LngLatBounds();
|
|
858
|
-
if (cordinates && cordinates.length > 0) {
|
|
859
|
-
cordinates.forEach((coord) => routeBounds.extend(coord));
|
|
860
|
-
}
|
|
861
|
-
const registryId = `${routeType}-${index}`;
|
|
862
|
-
// Register the route with its coordinates and pre-calculated bounds
|
|
863
|
-
this.activeRoutesRegistry.set(registryId, {
|
|
864
|
-
cordinates,
|
|
865
|
-
route,
|
|
866
|
-
routeType,
|
|
867
|
-
bounds: routeBounds,
|
|
868
|
-
index
|
|
869
|
-
});
|
|
870
|
-
let origin = cordinates[0];
|
|
871
|
-
let destination = cordinates[cordinates.length - 1];
|
|
872
|
-
if (origin[0] && origin[1] && destination && destination[0] && destination[1]) {
|
|
873
|
-
// Execute plotting logic IMMEDIATELY to trigger the map's render cycle
|
|
874
|
-
const linecolor = this.provideLineColor(route['unit'], routeType);
|
|
875
|
-
if (enablefitbound) {
|
|
876
|
-
const padTop = Math.max(0, (this.padding?.top || 0) + this.customTopForCustomer + 50);
|
|
877
|
-
const padBot = Math.max(0, (this.padding?.bottom || 0) + (this.windowActualHeightWidth.availHeight - (window.innerHeight - 65)) + 50);
|
|
878
|
-
const padLeft = Math.max(0, (this.padding?.left || 0) + 350);
|
|
879
|
-
const padRight = Math.max(0, (this.padding?.right || 0) + 50);
|
|
880
|
-
const customPadding = { top: padTop, bottom: padBot, left: padLeft, right: padRight };
|
|
881
|
-
this.map.fitBounds([origin, destination], { padding: customPadding, pitch: 65 }, { fitboundCompleteJob: true });
|
|
882
|
-
}
|
|
883
|
-
const sourceId = `route-source-${routeType}-${index}`;
|
|
884
|
-
const layerId = `route-layer-${routeType}-${index}`;
|
|
885
|
-
if (this.map.getSource(sourceId)) {
|
|
886
|
-
this.removeRouteAndMarker(index, routeType).then(() => {
|
|
887
|
-
this.extendBound(cordinates, enablefitbound, registryId);
|
|
888
|
-
});
|
|
889
|
-
}
|
|
890
|
-
this.map.addSource(sourceId, {
|
|
891
|
-
type: 'geojson',
|
|
892
|
-
data: {
|
|
893
|
-
type: 'Feature',
|
|
894
|
-
properties: {},
|
|
895
|
-
geometry: { type: 'LineString', coordinates: cordinates },
|
|
896
|
-
},
|
|
897
|
-
});
|
|
898
|
-
this.map.addLayer({
|
|
899
|
-
id: layerId,
|
|
900
|
-
type: 'line',
|
|
901
|
-
source: sourceId,
|
|
902
|
-
paint: { 'line-color': linecolor, 'line-width': 2 },
|
|
903
|
-
layout: { 'line-cap': 'round', 'line-join': 'round' },
|
|
904
|
-
});
|
|
905
|
-
if (!isStyleRefresh) {
|
|
906
|
-
const dataSetForMap = { origin, destination, index, linecolor, route, routeType };
|
|
907
|
-
this.createMarker(dataSetForMap);
|
|
908
|
-
}
|
|
909
|
-
this.map.on('mouseenter', layerId, (e) => {
|
|
910
|
-
if (this.popup)
|
|
911
|
-
this.popup.remove();
|
|
912
|
-
this.map.setPaintProperty(layerId, 'line-width', 5);
|
|
913
|
-
this.map.setPaintProperty(layerId, 'line-opacity', 1);
|
|
914
|
-
const datasetForPopup = {
|
|
915
|
-
coordinate: [e.lngLat.lng, e.lngLat.lat],
|
|
916
|
-
pickup: route.pickup_location || '',
|
|
917
|
-
drop: route.delivery_location || '',
|
|
918
|
-
jobCode: route.project ? route.order_number : null,
|
|
919
|
-
customer: route.project ? route.customer_name : null,
|
|
920
|
-
routeType: route.project ? 'Project' : 'Route',
|
|
921
|
-
title: route.project ? route.project : route.route_name || '',
|
|
922
|
-
material: route.material || '',
|
|
923
|
-
type: route.unit || '',
|
|
924
|
-
};
|
|
925
|
-
this.createPopup(datasetForPopup);
|
|
926
|
-
});
|
|
927
|
-
this.map.on('mouseleave', layerId, () => {
|
|
928
|
-
this.map.setPaintProperty(layerId, 'line-width', 2);
|
|
929
|
-
if (this.popup)
|
|
930
|
-
this.popup.remove();
|
|
931
|
-
});
|
|
932
|
-
// SAFETY: Use a timeout to ensure resolve() is always called even if 'idle' event skips
|
|
933
|
-
let resolved = false;
|
|
934
|
-
const complete = () => {
|
|
935
|
-
if (!resolved) {
|
|
936
|
-
resolved = true;
|
|
937
|
-
resolve();
|
|
938
|
-
}
|
|
939
|
-
};
|
|
940
|
-
this.map.once('idle', complete);
|
|
941
|
-
setTimeout(complete, 500); // 500ms safety timeout
|
|
942
|
-
}
|
|
943
|
-
else {
|
|
944
|
-
resolve();
|
|
945
|
-
}
|
|
946
|
-
});
|
|
947
|
-
}
|
|
948
|
-
provideLineColor(unitType, type) {
|
|
949
|
-
let checkType = type && !['jobrouteList', 'addroute', 'viewroute'].includes(type) ? true : false;
|
|
950
|
-
let color;
|
|
951
|
-
switch (unitType) {
|
|
952
|
-
case 'Ton':
|
|
953
|
-
color = checkType ? '#39c471' : '#ff7272';
|
|
954
|
-
break;
|
|
955
|
-
case 'Load':
|
|
956
|
-
color = checkType ? '#326ad3' : '#a3c52e';
|
|
957
|
-
break;
|
|
958
|
-
case 'Hourly':
|
|
959
|
-
color = checkType ? '#ffad56' : '#ae23d1';
|
|
960
|
-
break;
|
|
961
|
-
default:
|
|
962
|
-
color = '#3b82f6';
|
|
963
|
-
break;
|
|
964
|
-
}
|
|
965
|
-
return color;
|
|
966
|
-
}
|
|
967
777
|
hexToRGB(hex) {
|
|
968
778
|
return hex
|
|
969
779
|
.replace(/^#?([a-f\d])([a-f\d])([a-f\d])$/i, (m, r, g, b) => '#' + r + r + g + g + b + b)
|
|
@@ -971,147 +781,105 @@ class MapboxService {
|
|
|
971
781
|
.match(/.{2}/g)
|
|
972
782
|
.map((x) => parseInt(x, 16));
|
|
973
783
|
}
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
const
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
const
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
const maxY = Math.max(p1.y, p2.y, controlY);
|
|
1026
|
-
const w = Math.max(1, maxX - minX);
|
|
1027
|
-
const h = Math.max(1, maxY - minY);
|
|
1028
|
-
grad.setAttribute('x1', `${((p1.x - minX) / w) * 100}%`);
|
|
1029
|
-
grad.setAttribute('y1', `${((p1.y - minY) / h) * 100}%`);
|
|
1030
|
-
grad.setAttribute('x2', `${((p2.x - minX) / w) * 100}%`);
|
|
1031
|
-
grad.setAttribute('y2', `${((p2.y - minY) / h) * 100}%`);
|
|
1032
|
-
}
|
|
784
|
+
createMarker(routeDetails) {
|
|
785
|
+
if (routeDetails.origin[0] &&
|
|
786
|
+
routeDetails.origin[1] &&
|
|
787
|
+
routeDetails.destination[0] &&
|
|
788
|
+
routeDetails.destination[1]) {
|
|
789
|
+
const popup = new mapboxgl.Popup({ closeButton: false }).setHTML('<b>Pickup: </b>' + routeDetails.route?.pickup_location);
|
|
790
|
+
const popupForDestination = new mapboxgl.Popup({
|
|
791
|
+
closeButton: false,
|
|
792
|
+
}).setHTML('<b>Delivery: </b>' + routeDetails.route?.delivery_location);
|
|
793
|
+
const el = document.createElement('div');
|
|
794
|
+
el.className = 'marker';
|
|
795
|
+
el.innerHTML = `<span class='markerPointer' style='background:${routeDetails.linecolor}'><b>P</b><span class='markerSpan' style='border-top: 10px solid ${routeDetails.linecolor}'></span></span>`;
|
|
796
|
+
const originMarker = new mapboxgl.Marker(el)
|
|
797
|
+
.setPopup(popup)
|
|
798
|
+
.setLngLat(routeDetails.origin)
|
|
799
|
+
.addTo(this.map);
|
|
800
|
+
originMarker
|
|
801
|
+
.getElement()
|
|
802
|
+
.addEventListener('mouseenter', () => originMarker.togglePopup());
|
|
803
|
+
originMarker
|
|
804
|
+
.getElement()
|
|
805
|
+
.addEventListener('mouseleave', () => originMarker.togglePopup());
|
|
806
|
+
const elementForDestination = document.createElement('div');
|
|
807
|
+
elementForDestination.className = 'marker';
|
|
808
|
+
elementForDestination.innerHTML = `<span class='markerPointer' style='background:${routeDetails.linecolor}'><b>D</b><span class='markerSpan' style='border-top: 10px solid ${routeDetails.linecolor}'></span></span>`;
|
|
809
|
+
const destinationMarker = new mapboxgl.Marker(elementForDestination)
|
|
810
|
+
.setPopup(popupForDestination)
|
|
811
|
+
.setLngLat(routeDetails.destination)
|
|
812
|
+
.addTo(this.map);
|
|
813
|
+
destinationMarker
|
|
814
|
+
.getElement()
|
|
815
|
+
.addEventListener('mouseenter', () => destinationMarker.togglePopup());
|
|
816
|
+
destinationMarker
|
|
817
|
+
.getElement()
|
|
818
|
+
.addEventListener('mouseleave', () => destinationMarker.togglePopup());
|
|
819
|
+
this.markerOriginList[routeDetails.index] = originMarker;
|
|
820
|
+
this.markerDestinationList[routeDetails.index] = destinationMarker;
|
|
821
|
+
const colorArray = this.hexToRGB(routeDetails.linecolor);
|
|
822
|
+
const arcLayer = new MapboxLayer({
|
|
823
|
+
id: 'arc-layer' + routeDetails.index,
|
|
824
|
+
type: ArcLayer,
|
|
825
|
+
pickable: true,
|
|
826
|
+
data: { route: routeDetails.route, index: routeDetails.index },
|
|
827
|
+
getWidth: 1,
|
|
828
|
+
getSourcePosition: routeDetails.origin,
|
|
829
|
+
getTargetPosition: routeDetails.destination,
|
|
830
|
+
getTargetColor: [255, 255, 255],
|
|
831
|
+
getSourceColor: [colorArray[0], colorArray[1], colorArray[2]],
|
|
832
|
+
onHover: (info, event) => this.showRoutePopup(info, event, routeDetails.isViewRoute),
|
|
833
|
+
});
|
|
834
|
+
this.map.addLayer(arcLayer);
|
|
1033
835
|
}
|
|
1034
836
|
}
|
|
1035
|
-
async removeRouteAndMarker(index
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
}
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
this.
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
this.markerOriginList.get(registryId)?.remove();
|
|
1062
|
-
this.markerOriginList.delete(registryId);
|
|
1063
|
-
this.markerDestinationList.get(registryId)?.remove();
|
|
1064
|
-
this.markerDestinationList.delete(registryId);
|
|
1065
|
-
this.markerOriginList.get(String(index))?.remove();
|
|
1066
|
-
this.markerDestinationList.get(String(index))?.remove();
|
|
1067
|
-
this.originDestinationCordinates.delete(registryId);
|
|
1068
|
-
this.originDestinationCordinates.delete(String(index));
|
|
1069
|
-
if (this.popup)
|
|
1070
|
-
this.popup.remove();
|
|
1071
|
-
return true;
|
|
1072
|
-
}
|
|
1073
|
-
catch (e) {
|
|
1074
|
-
console.warn('Error removing route/marker:', e);
|
|
1075
|
-
return false;
|
|
837
|
+
async removeRouteAndMarker(index) {
|
|
838
|
+
if (this.map) {
|
|
839
|
+
this.map.getLayer(`arc-layer${index}`)
|
|
840
|
+
? this.map.removeLayer(`arc-layer${index}`)
|
|
841
|
+
: '';
|
|
842
|
+
this.map.getLayer(`line${index}`)
|
|
843
|
+
? this.map.removeLayer(`line${index}`)
|
|
844
|
+
: '';
|
|
845
|
+
this.map.getLayer(`custom_layer${index}`)
|
|
846
|
+
? this.map.removeLayer(`custom_layer${index}`)
|
|
847
|
+
: '';
|
|
848
|
+
this.map.getSource(`line${index}`)
|
|
849
|
+
? this.map.removeSource(`line${index}`)
|
|
850
|
+
: '';
|
|
851
|
+
this.map.getLayer(`route-for-job-code${index}`)
|
|
852
|
+
? this.map.removeLayer(`route-for-job-code${index}`)
|
|
853
|
+
: '';
|
|
854
|
+
this.map.getSource(`route-source-for-job-code${index}`)
|
|
855
|
+
? this.map.removeSource(`route-source-for-job-code${index}`)
|
|
856
|
+
: '';
|
|
857
|
+
this.findMarkerBound(index);
|
|
858
|
+
this.markerOriginList[index] ? this.markerOriginList[index].remove() : '';
|
|
859
|
+
this.markerDestinationList[index]
|
|
860
|
+
? this.markerDestinationList[index].remove()
|
|
861
|
+
: '';
|
|
862
|
+
await true;
|
|
1076
863
|
}
|
|
1077
864
|
}
|
|
1078
|
-
reAddLayers() {
|
|
1079
|
-
this.activeRoutesRegistry.forEach((data, regId) => {
|
|
1080
|
-
// Use the stored raw index instead of the composite registry key
|
|
1081
|
-
this.drawLine(data.cordinates, data.index, data.route, false, data.routeType, true);
|
|
1082
|
-
});
|
|
1083
|
-
}
|
|
1084
865
|
findMarkerBound(index) {
|
|
1085
|
-
const
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
if (
|
|
1090
|
-
|
|
1091
|
-
if (x[0][0].toFixed(6) === originLng.toFixed(6) &&
|
|
1092
|
-
x[0][1].toFixed(6) === originLat.toFixed(6)) {
|
|
1093
|
-
this.originDestinationCordinates.delete(key);
|
|
1094
|
-
break;
|
|
1095
|
-
}
|
|
1096
|
-
}
|
|
866
|
+
const indexOfCordinates = this.originDestinationCordinates.findIndex((x) => x[0][0].toFixed(6) ==
|
|
867
|
+
this.markerOriginList[index]?.getLngLat()?.lng.toFixed(6) &&
|
|
868
|
+
x[0][1].toFixed(6) ==
|
|
869
|
+
this.markerOriginList[index]?.getLngLat()?.lat.toFixed(6));
|
|
870
|
+
if (indexOfCordinates >= 0) {
|
|
871
|
+
this.originDestinationCordinates.splice(indexOfCordinates, 1);
|
|
1097
872
|
}
|
|
1098
873
|
}
|
|
1099
874
|
async filterRoute(ID, visibility, showAllFitbound) {
|
|
1100
|
-
if (ID
|
|
875
|
+
if (ID) {
|
|
1101
876
|
if (this.map.getLayer(`route-for-job-code${ID}`)) {
|
|
1102
877
|
this.map.setLayoutProperty(`route-for-job-code${ID}`, 'visibility', visibility);
|
|
1103
|
-
const
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
const destinationM = this.markerDestinationList.get(id);
|
|
1109
|
-
if (destinationM) {
|
|
1110
|
-
destinationM.getElement().style.display = visibility === 'visible' ? 'block' : 'none';
|
|
1111
|
-
}
|
|
1112
|
-
if (this.activeArcs[ID]) {
|
|
1113
|
-
this.activeArcs[ID].pathEl.style.display = visibility === 'visible' ? 'block' : 'none';
|
|
1114
|
-
}
|
|
878
|
+
const originM = this.markerOriginList[ID].getElement();
|
|
879
|
+
originM.style.display = visibility === 'visible' ? 'block' : visibility;
|
|
880
|
+
const destinationM = this.markerDestinationList[ID].getElement();
|
|
881
|
+
destinationM.style.display =
|
|
882
|
+
visibility === 'visible' ? 'block' : visibility;
|
|
1115
883
|
if (visibility === 'none' && showAllFitbound) {
|
|
1116
884
|
this.findMarkerBound(ID);
|
|
1117
885
|
this.extendReBound();
|
|
@@ -1121,320 +889,154 @@ class MapboxService {
|
|
|
1121
889
|
this.map.setLayoutProperty(`arc-layer${ID}`, 'visibility', visibility);
|
|
1122
890
|
}
|
|
1123
891
|
}
|
|
1124
|
-
|
|
892
|
+
await true;
|
|
1125
893
|
}
|
|
1126
|
-
extendBound(route, showAllFitbound
|
|
1127
|
-
return new Promise((resolve) => {
|
|
1128
|
-
if (route
|
|
894
|
+
extendBound(route, showAllFitbound) {
|
|
895
|
+
return new Promise((resolve, reject) => {
|
|
896
|
+
if (route) {
|
|
1129
897
|
if (typeof route === 'string') {
|
|
1130
898
|
let path = route.split(';');
|
|
1131
|
-
path = path.map((ele) =>
|
|
1132
|
-
|
|
899
|
+
path = path.map((ele) => {
|
|
900
|
+
return (ele = this.formateLatLong(ele));
|
|
901
|
+
});
|
|
902
|
+
path.forEach((ele, index) => {
|
|
903
|
+
if (ele.length === 1)
|
|
904
|
+
path.splice(index, 1);
|
|
905
|
+
});
|
|
1133
906
|
route = path;
|
|
1134
907
|
}
|
|
1135
|
-
if (route[0]
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
routeItem.forEach((coord) => {
|
|
1143
|
-
localBounds.extend(coord);
|
|
908
|
+
if (route[0][0] &&
|
|
909
|
+
route[0][1] &&
|
|
910
|
+
route[route.length - 1][0] &&
|
|
911
|
+
route[route.length - 1][1]) {
|
|
912
|
+
this.originDestinationCordinates.push(route);
|
|
913
|
+
route.map((item) => {
|
|
914
|
+
this.bounds.extend(item);
|
|
1144
915
|
});
|
|
1145
|
-
}
|
|
916
|
+
}
|
|
1146
917
|
}
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
pitch: 65,
|
|
1153
|
-
maxZoom: 12,
|
|
1154
|
-
padding: 100,
|
|
1155
|
-
duration: 1000
|
|
1156
|
-
}, { fitboundComplete: true });
|
|
1157
|
-
});
|
|
918
|
+
if (showAllFitbound) {
|
|
919
|
+
setTimeout(() => {
|
|
920
|
+
if (showAllFitbound && Object.keys(this.bounds).length > 0)
|
|
921
|
+
this.map.fitBounds(this.bounds, { pitch: 65 }, { fitboundComplete: true });
|
|
922
|
+
}, 100);
|
|
1158
923
|
this.map.once('moveend', (event) => {
|
|
1159
924
|
if (event.fitboundComplete) {
|
|
1160
925
|
resolve(true);
|
|
1161
926
|
}
|
|
1162
927
|
});
|
|
1163
928
|
}
|
|
1164
|
-
else {
|
|
1165
|
-
resolve(true);
|
|
1166
|
-
}
|
|
1167
929
|
});
|
|
1168
930
|
}
|
|
1169
931
|
extendReBound(bottom) {
|
|
1170
|
-
return new Promise((resolve) => {
|
|
1171
|
-
|
|
1172
|
-
if (this.originDestinationCordinates.
|
|
1173
|
-
this.originDestinationCordinates.
|
|
1174
|
-
item.
|
|
1175
|
-
|
|
932
|
+
return new Promise((resolve, reject) => {
|
|
933
|
+
this.bounds = new mapboxgl.LngLatBounds();
|
|
934
|
+
if (this.originDestinationCordinates.length >= 0) {
|
|
935
|
+
this.originDestinationCordinates.map((item, index) => {
|
|
936
|
+
item.map((route) => {
|
|
937
|
+
this.bounds.extend(route);
|
|
1176
938
|
});
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
padding: customPadding,
|
|
1192
|
-
pitch: 65,
|
|
1193
|
-
maxZoom: 12,
|
|
1194
|
-
duration: 1000
|
|
1195
|
-
});
|
|
939
|
+
if (index === this.originDestinationCordinates.length - 1) {
|
|
940
|
+
const padding = {
|
|
941
|
+
top: this.padding.top + this.customTopForCustomer,
|
|
942
|
+
bottom: this.padding.bottom +
|
|
943
|
+
(this.windowActualHeightWidth.availHeight -
|
|
944
|
+
(window.innerHeight - 65)),
|
|
945
|
+
left: this.padding.left,
|
|
946
|
+
right: this.padding.right,
|
|
947
|
+
};
|
|
948
|
+
setTimeout(() => {
|
|
949
|
+
if (this.originDestinationCordinates.length > 0)
|
|
950
|
+
this.map.fitBounds(this.bounds, { padding, pitch: 65 });
|
|
951
|
+
}, 500);
|
|
952
|
+
resolve(true);
|
|
1196
953
|
}
|
|
1197
954
|
});
|
|
1198
|
-
resolve(true);
|
|
1199
955
|
}
|
|
1200
956
|
else {
|
|
1201
957
|
resolve(true);
|
|
1202
958
|
}
|
|
1203
959
|
});
|
|
1204
960
|
}
|
|
1205
|
-
|
|
1206
|
-
const cacheKey = route['job_id'] || route['route_id'];
|
|
1207
|
-
// 1. Check cache FIRST
|
|
1208
|
-
if (this.pathCache.has(cacheKey)) {
|
|
1209
|
-
const path = this.pathCache.get(cacheKey);
|
|
1210
|
-
route['path'] = path;
|
|
1211
|
-
this.extendBound(path, showAllFitbound);
|
|
1212
|
-
await this.drawLine(path, i, route, enablefitbound, type);
|
|
1213
|
-
route['index'] = i;
|
|
1214
|
-
return true;
|
|
1215
|
-
}
|
|
1216
|
-
// 2. Check for inline path (Avoid API if already available)
|
|
1217
|
-
if (route['path'] && (Array.isArray(route['path']) || typeof route['path'] === 'string')) {
|
|
1218
|
-
let path = typeof route['path'] === 'string' ? route['path'].split(';') : route['path'];
|
|
1219
|
-
if (Array.isArray(path) && path.length > 0) {
|
|
1220
|
-
// Format if they are still strings
|
|
1221
|
-
if (typeof path[0] === 'string') {
|
|
1222
|
-
path = path.map((ele) => this.formateLatLong(ele));
|
|
1223
|
-
path = path.filter((ele) => ele && ele.length > 1);
|
|
1224
|
-
}
|
|
1225
|
-
if (path.length > 0) {
|
|
1226
|
-
this.pathCache.set(cacheKey, path);
|
|
1227
|
-
route['path'] = path;
|
|
1228
|
-
this.extendBound(path, showAllFitbound);
|
|
1229
|
-
await this.drawLine(path, i, route, enablefitbound, type);
|
|
1230
|
-
route['index'] = i;
|
|
1231
|
-
return true;
|
|
1232
|
-
}
|
|
1233
|
-
}
|
|
1234
|
-
}
|
|
1235
|
-
// 3. Fallback to API call ONLY for jobcode (if path was missing)
|
|
961
|
+
plotRoute(route, i, type, enablefitbound, showAllFitbound) {
|
|
1236
962
|
return new Promise((resolve, reject) => {
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
}
|
|
1259
|
-
|
|
1260
|
-
|
|
963
|
+
let param = {};
|
|
964
|
+
if (['jobcode'].includes(type)) {
|
|
965
|
+
param['job'] = route['job_id'];
|
|
966
|
+
this.utils.postDataWithRestUrl('schedule/job/path', param).subscribe((res) => {
|
|
967
|
+
if (res['data']['route']) {
|
|
968
|
+
let path = res['data']['route'].split(';');
|
|
969
|
+
path = path.map((ele) => {
|
|
970
|
+
return (ele = this.formateLatLong(ele));
|
|
971
|
+
});
|
|
972
|
+
path.forEach((ele, index) => {
|
|
973
|
+
if (ele.length === 1)
|
|
974
|
+
path.splice(index, 1);
|
|
975
|
+
});
|
|
976
|
+
route['path'] = path;
|
|
977
|
+
this.extendBound(route['path'], showAllFitbound);
|
|
978
|
+
if (route['path'] && route['path'].length > 0)
|
|
979
|
+
this.drawLine(route['path'], i, route, enablefitbound, type);
|
|
980
|
+
route['index'] = i;
|
|
981
|
+
}
|
|
982
|
+
else {
|
|
983
|
+
this.extendBound(null, showAllFitbound);
|
|
984
|
+
}
|
|
985
|
+
resolve(true);
|
|
986
|
+
}, (err) => {
|
|
987
|
+
if (err) {
|
|
1261
988
|
reject(false);
|
|
1262
989
|
}
|
|
1263
990
|
});
|
|
1264
991
|
}
|
|
1265
|
-
else {
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
const showAll = showAllOverride !== undefined ? showAllOverride : (visibleIds.length === 0);
|
|
1278
|
-
this.activeRoutesRegistry.forEach((data, id) => {
|
|
1279
|
-
const registryId = String(id).trim();
|
|
1280
|
-
// If a prefix is provided, only operate on routes matching that prefix.
|
|
1281
|
-
if (prefix && !registryId.startsWith(`${prefix}-`)) {
|
|
1282
|
-
return;
|
|
1283
|
-
}
|
|
1284
|
-
const isVisible = showAll || visibleIds.includes(registryId);
|
|
1285
|
-
const visibility = isVisible ? 'visible' : 'none';
|
|
1286
|
-
const display = isVisible ? 'block' : 'none';
|
|
1287
|
-
// Toggle New Layer Format
|
|
1288
|
-
const newLayerId = `route-layer-${data.routeType}-${data.index || id}`;
|
|
1289
|
-
if (this.map.getLayer(newLayerId)) {
|
|
1290
|
-
this.map.setLayoutProperty(newLayerId, 'visibility', visibility);
|
|
1291
|
-
}
|
|
1292
|
-
// Legacy/Alternate Layer Formats
|
|
1293
|
-
const legacyId = `route-for-job-code${id}`;
|
|
1294
|
-
if (this.map.getLayer(legacyId)) {
|
|
1295
|
-
this.map.setLayoutProperty(legacyId, 'visibility', visibility);
|
|
1296
|
-
}
|
|
1297
|
-
if (this.map.getLayer(`line${id}`)) {
|
|
1298
|
-
this.map.setLayoutProperty(`line${id}`, 'visibility', visibility);
|
|
1299
|
-
}
|
|
1300
|
-
// Toggle Markers
|
|
1301
|
-
const originM = this.markerOriginList.get(registryId);
|
|
1302
|
-
if (originM)
|
|
1303
|
-
originM.getElement().style.display = display;
|
|
1304
|
-
const destM = this.markerDestinationList.get(registryId);
|
|
1305
|
-
if (destM)
|
|
1306
|
-
destM.getElement().style.display = display;
|
|
1307
|
-
// Toggle Arcs
|
|
1308
|
-
if (this.activeArcs[registryId]) {
|
|
1309
|
-
this.activeArcs[registryId].pathEl.style.display = display;
|
|
1310
|
-
}
|
|
1311
|
-
});
|
|
1312
|
-
// Recalculate bounds based on visible routes
|
|
1313
|
-
this.recalculateVisibleBounds(visibleIds, prefix, showAll);
|
|
1314
|
-
}
|
|
1315
|
-
recalculateVisibleBounds(visibleIds, prefix, showAllOverride) {
|
|
1316
|
-
const showAll = showAllOverride !== undefined ? showAllOverride : (visibleIds.length === 0);
|
|
1317
|
-
this.bounds = new mapboxgl.LngLatBounds();
|
|
1318
|
-
this.originDestinationCordinates.clear();
|
|
1319
|
-
const normalizedVisibleIds = visibleIds.map(vid => String(vid).trim());
|
|
1320
|
-
this.activeRoutesRegistry.forEach((data, id) => {
|
|
1321
|
-
const registryId = String(id).trim();
|
|
1322
|
-
// If a prefix is provided, only include routes that match it for the bounding box.
|
|
1323
|
-
// This prevents "showAll" from zooming to hidden routes from other sections.
|
|
1324
|
-
if (prefix && !registryId.startsWith(`${prefix}-`)) {
|
|
1325
|
-
return;
|
|
1326
|
-
}
|
|
1327
|
-
if (showAll || normalizedVisibleIds.includes(registryId)) {
|
|
1328
|
-
if (data.bounds && !data.bounds.isEmpty()) {
|
|
1329
|
-
this.bounds.extend(data.bounds);
|
|
1330
|
-
this.originDestinationCordinates.set(registryId, data.cordinates);
|
|
1331
|
-
}
|
|
1332
|
-
else if (data.cordinates && data.cordinates.length > 0) {
|
|
1333
|
-
// Fallback if bounds weren't pre-calculated
|
|
1334
|
-
data.cordinates.forEach((coord) => this.bounds.extend(coord));
|
|
1335
|
-
this.originDestinationCordinates.set(registryId, data.cordinates);
|
|
992
|
+
else if (['jobrouteList', 'addroute'].includes(type)) {
|
|
993
|
+
if (route['path'] && route['path'].length > 0) {
|
|
994
|
+
let path = route['path'].split(';');
|
|
995
|
+
path = path.map((ele) => {
|
|
996
|
+
return (ele = this.formateLatLong(ele));
|
|
997
|
+
});
|
|
998
|
+
path.forEach((ele, index) => {
|
|
999
|
+
if (ele.length === 1)
|
|
1000
|
+
path.splice(index, 1);
|
|
1001
|
+
});
|
|
1002
|
+
this.extendBound(path, showAllFitbound);
|
|
1003
|
+
this.drawLine(path, i, route, enablefitbound, type);
|
|
1336
1004
|
}
|
|
1337
1005
|
}
|
|
1338
1006
|
});
|
|
1339
|
-
if (!this.bounds.isEmpty() && this.map) {
|
|
1340
|
-
const canvas = this.map.getCanvas();
|
|
1341
|
-
const mapW = canvas.clientWidth;
|
|
1342
|
-
const mapH = canvas.clientHeight;
|
|
1343
|
-
let padTop = Math.max(0, (Number(this.padding?.top) || 0) + (Number(this.customTopForCustomer) || 0) + 80);
|
|
1344
|
-
let padBot = Math.max(0, (Number(this.padding?.bottom) || 0) + (Math.max(0, Number(this.windowActualHeightWidth.availHeight) - (Number(window.innerHeight) - 65))) + 80);
|
|
1345
|
-
let padLeft = Math.max(0, (Number(this.padding?.left) || 0) + (window.innerWidth > 1000 ? 350 : 50));
|
|
1346
|
-
let padRight = Math.max(0, (Number(this.padding?.right) || 0) + 80);
|
|
1347
|
-
// Safety Clamps: Ensure padding doesn't exceed canvas size
|
|
1348
|
-
const maxHorizPad = mapW * 0.8;
|
|
1349
|
-
const maxVertPad = mapH * 0.8;
|
|
1350
|
-
if (padLeft + padRight > maxHorizPad) {
|
|
1351
|
-
const factor = maxHorizPad / (padLeft + padRight);
|
|
1352
|
-
padLeft *= factor;
|
|
1353
|
-
padRight *= factor;
|
|
1354
|
-
}
|
|
1355
|
-
if (padTop + padBot > maxVertPad) {
|
|
1356
|
-
const factor = maxVertPad / (padTop + padBot);
|
|
1357
|
-
padTop *= factor;
|
|
1358
|
-
padBot *= factor;
|
|
1359
|
-
}
|
|
1360
|
-
try {
|
|
1361
|
-
this.map.fitBounds(this.bounds, {
|
|
1362
|
-
padding: { top: padTop, bottom: padBot, left: padLeft, right: padRight },
|
|
1363
|
-
pitch: 65,
|
|
1364
|
-
maxZoom: 12,
|
|
1365
|
-
duration: 800
|
|
1366
|
-
});
|
|
1367
|
-
}
|
|
1368
|
-
catch (err) {
|
|
1369
|
-
console.warn('fitBounds failed, trying with default padding', err);
|
|
1370
|
-
this.map.fitBounds(this.bounds, { padding: 50, pitch: 65, maxZoom: 12 });
|
|
1371
|
-
}
|
|
1372
|
-
}
|
|
1373
|
-
}
|
|
1374
|
-
async clearAllRoutes() {
|
|
1375
|
-
// 1. Remove all markers
|
|
1376
|
-
this.markerOriginList.forEach(marker => marker.remove());
|
|
1377
|
-
this.markerDestinationList.forEach(marker => marker.remove());
|
|
1378
|
-
this.markerOriginList.clear();
|
|
1379
|
-
this.markerDestinationList.clear();
|
|
1380
|
-
// 2. Remove all arcs
|
|
1381
|
-
Object.keys(this.activeArcs).forEach(index => {
|
|
1382
|
-
const arc = this.activeArcs[index];
|
|
1383
|
-
if (arc.pathEl.parentNode)
|
|
1384
|
-
arc.pathEl.parentNode.removeChild(arc.pathEl);
|
|
1385
|
-
if (this.svgOverlay) {
|
|
1386
|
-
const grad = this.svgOverlay.querySelector(`defs #arc-grad-${index}`);
|
|
1387
|
-
if (grad && grad.parentNode)
|
|
1388
|
-
grad.parentNode.removeChild(grad);
|
|
1389
|
-
}
|
|
1390
|
-
});
|
|
1391
|
-
this.activeArcs = {};
|
|
1392
|
-
// 3. Remove all line layers and sources using registry metadata
|
|
1393
|
-
this.activeRoutesRegistry.forEach((data, regId) => {
|
|
1394
|
-
const type = data.routeType || 'jobcode';
|
|
1395
|
-
const idx = data.index || regId.split('-').pop();
|
|
1396
|
-
const layerId = `route-layer-${type}-${idx}`;
|
|
1397
|
-
const sourceId = `route-source-${type}-${idx}`;
|
|
1398
|
-
this.map.getLayer(layerId) ? this.map.removeLayer(layerId) : null;
|
|
1399
|
-
this.map.getSource(sourceId) ? this.map.removeSource(sourceId) : null;
|
|
1400
|
-
// Legacy fallback cleanup
|
|
1401
|
-
this.map.getLayer(`line${idx}`) ? this.map.removeLayer(`line${idx}`) : null;
|
|
1402
|
-
this.map.getSource(`line${idx}`) ? this.map.removeSource(`line${idx}`) : null;
|
|
1403
|
-
this.map.getLayer(`route-for-job-code${idx}`) ? this.map.removeLayer(`route-for-job-code${idx}`) : null;
|
|
1404
|
-
this.map.getSource(`route-source-for-job-code${idx}`) ? this.map.removeSource(`route-source-for-job-code${idx}`) : null;
|
|
1405
|
-
});
|
|
1406
|
-
// 4. Reset registries and bounds
|
|
1407
|
-
this.activeRoutesRegistry.clear();
|
|
1408
|
-
this.originDestinationCordinates.clear();
|
|
1409
|
-
this.bounds = new mapboxgl.LngLatBounds();
|
|
1410
|
-
if (this.popup)
|
|
1411
|
-
this.popup.remove();
|
|
1412
|
-
return true;
|
|
1413
1007
|
}
|
|
1414
1008
|
clearBound() {
|
|
1415
1009
|
this.bounds = new mapboxgl.LngLatBounds();
|
|
1416
|
-
this.originDestinationCordinates
|
|
1010
|
+
this.originDestinationCordinates = [];
|
|
1417
1011
|
this.clearPadding();
|
|
1418
1012
|
}
|
|
1419
1013
|
formateLatLong(latlong) {
|
|
1420
|
-
return latlong
|
|
1014
|
+
return latlong
|
|
1015
|
+
? latlong
|
|
1016
|
+
.split(',')
|
|
1017
|
+
.map((x) => +x)
|
|
1018
|
+
.reverse()
|
|
1019
|
+
: null;
|
|
1421
1020
|
}
|
|
1422
1021
|
clearBoundWithCordinates() {
|
|
1423
1022
|
this.bounds = new mapboxgl.LngLatBounds();
|
|
1424
|
-
this.originDestinationCordinates
|
|
1023
|
+
this.originDestinationCordinates = [];
|
|
1425
1024
|
}
|
|
1426
1025
|
onResize(event) {
|
|
1427
|
-
if (!this.bounds.isEmpty()
|
|
1026
|
+
if (!this.bounds.isEmpty()) {
|
|
1428
1027
|
this.windowActualHeightWidth.availHeight =
|
|
1429
|
-
window.innerHeight > window.screen.availHeight
|
|
1028
|
+
window.innerHeight > window.screen.availHeight
|
|
1029
|
+
? window.innerHeight
|
|
1030
|
+
: window.screen.availHeight;
|
|
1430
1031
|
setTimeout(() => {
|
|
1431
|
-
const hRes = event.target ? event.target.innerHeight : window.innerHeight;
|
|
1432
1032
|
this.map.fitBounds(this.bounds, {
|
|
1433
1033
|
padding: {
|
|
1434
|
-
top:
|
|
1435
|
-
bottom:
|
|
1436
|
-
|
|
1437
|
-
|
|
1034
|
+
top: this.padding.top + this.customTopForCustomer,
|
|
1035
|
+
bottom: this.padding.bottom +
|
|
1036
|
+
(this.windowActualHeightWidth.availHeight -
|
|
1037
|
+
(event.target.innerHeight - 65)),
|
|
1038
|
+
left: this.padding.left,
|
|
1039
|
+
right: this.padding.right,
|
|
1438
1040
|
},
|
|
1439
1041
|
pitch: 65,
|
|
1440
1042
|
});
|
|
@@ -1451,7 +1053,7 @@ class MapboxService {
|
|
|
1451
1053
|
this.padding = null;
|
|
1452
1054
|
}
|
|
1453
1055
|
removeJobFromMap(data) {
|
|
1454
|
-
data.
|
|
1056
|
+
data.map((ele, index) => {
|
|
1455
1057
|
const id = ele['job_id'] ? ele['job_id'] : ele['route_id'];
|
|
1456
1058
|
this.removeRouteAndMarker(id);
|
|
1457
1059
|
if (index === data.length - 1) {
|
|
@@ -1459,58 +1061,24 @@ class MapboxService {
|
|
|
1459
1061
|
}
|
|
1460
1062
|
});
|
|
1461
1063
|
}
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
setTimeout(() => this.map.resize(), 0);
|
|
1465
|
-
}
|
|
1466
|
-
}
|
|
1467
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.24", ngImport: i0, type: MapboxService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
1468
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.24", ngImport: i0, type: MapboxService, providedIn: 'root' });
|
|
1469
|
-
}
|
|
1470
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.24", ngImport: i0, type: MapboxService, decorators: [{
|
|
1471
|
-
type: Injectable,
|
|
1472
|
-
args: [{
|
|
1473
|
-
providedIn: 'root'
|
|
1474
|
-
}]
|
|
1475
|
-
}], ctorParameters: () => [] });
|
|
1476
|
-
|
|
1477
|
-
class CoolmapService {
|
|
1478
|
-
mapbox = inject(MapboxService);
|
|
1479
|
-
isLoading = signal(true, ...(ngDevMode ? [{ debugName: "isLoading" }] : []));
|
|
1480
|
-
isDataFetched = signal(false, ...(ngDevMode ? [{ debugName: "isDataFetched" }] : []));
|
|
1481
|
-
plottingIds = signal(new Set(), ...(ngDevMode ? [{ debugName: "plottingIds" }] : []));
|
|
1482
|
-
resetModals = signal(0, ...(ngDevMode ? [{ debugName: "resetModals" }] : []));
|
|
1483
|
-
plotRoute(route, i, type = 'jobcode', enablefitbound, showAllFitbound) {
|
|
1484
|
-
if (!route)
|
|
1485
|
-
return;
|
|
1486
|
-
return this.mapbox.plotRoute(route, i, type, enablefitbound, showAllFitbound);
|
|
1487
|
-
}
|
|
1488
|
-
loadMapProperty(pinRouteGeojson, index, unit, routeProps) {
|
|
1489
|
-
this.mapbox.loadMapProperty(pinRouteGeojson, index, unit, routeProps);
|
|
1490
|
-
}
|
|
1491
|
-
removeRouteAndMarker(index, type = 'jobcode') {
|
|
1492
|
-
return this.mapbox.removeRouteAndMarker(index, type);
|
|
1493
|
-
}
|
|
1494
|
-
clearAllRoutes() {
|
|
1495
|
-
return this.mapbox.clearAllRoutes();
|
|
1496
|
-
}
|
|
1497
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.24", ngImport: i0, type: CoolmapService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
1498
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.24", ngImport: i0, type: CoolmapService, providedIn: 'root' });
|
|
1064
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.2.1", ngImport: i0, type: CoolmapService, deps: [{ token: UtilsService }, { token: i2$1.EventManager }, { token: 'memberData' }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
1065
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.2.1", ngImport: i0, type: CoolmapService, providedIn: 'root' });
|
|
1499
1066
|
}
|
|
1500
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
1067
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.2.1", ngImport: i0, type: CoolmapService, decorators: [{
|
|
1501
1068
|
type: Injectable,
|
|
1502
|
-
args: [{
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1069
|
+
args: [{ providedIn: 'root' }]
|
|
1070
|
+
}], ctorParameters: () => [{ type: UtilsService }, { type: i2$1.EventManager }, { type: CoolmapConfigModel, decorators: [{
|
|
1071
|
+
type: Inject,
|
|
1072
|
+
args: ['memberData']
|
|
1073
|
+
}] }] });
|
|
1506
1074
|
|
|
1507
1075
|
/*
|
|
1508
|
-
* Public API Surface of coolmap-services
|
|
1076
|
+
* Public API Surface of @aggdirect/coolmap-services
|
|
1509
1077
|
*/
|
|
1510
1078
|
|
|
1511
1079
|
/**
|
|
1512
1080
|
* Generated bundle index. Do not edit.
|
|
1513
1081
|
*/
|
|
1514
1082
|
|
|
1515
|
-
export {
|
|
1083
|
+
export { CoolmapConfigModel, CoolmapService, DriverSmsCardEnum, DriversmsCardKey, EstinationData, EstinationEnum, JobCodeOverviewData, JobCodeOverviewEnum, PopupData, Route, UtilsService };
|
|
1516
1084
|
//# sourceMappingURL=aggdirect-coolmap-services.mjs.map
|