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