@mis-wis/common 0.1.8 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/esm2020/lib/components/create-non-shift-modal/create-non-shift-modal.component.mjs +233 -0
- package/esm2020/lib/constants/assets.constants.mjs +8 -0
- package/esm2020/lib/models/configurations.model.mjs +1 -1
- package/esm2020/lib/models/env.model.mjs +1 -1
- package/esm2020/lib/models/session.model.mjs +2 -0
- package/esm2020/lib/services/http.service.mjs +29 -9
- package/esm2020/lib/services/mfe-communication.service.mjs +7 -1
- package/esm2020/lib/services/session.errors.mjs +28 -0
- package/esm2020/lib/services/session.service.mjs +148 -0
- package/esm2020/lib/wis-common.module.mjs +13 -8
- package/esm2020/public-api.mjs +5 -1
- package/fesm2015/mis-wis-common.mjs +465 -25
- package/fesm2015/mis-wis-common.mjs.map +1 -1
- package/fesm2020/mis-wis-common.mjs +457 -25
- package/fesm2020/mis-wis-common.mjs.map +1 -1
- package/lib/components/create-non-shift-modal/create-non-shift-modal.component.d.ts +56 -0
- package/lib/constants/assets.constants.d.ts +7 -0
- package/lib/models/configurations.model.d.ts +8 -0
- package/lib/models/env.model.d.ts +1 -0
- package/lib/models/session.model.d.ts +21 -0
- package/lib/services/http.service.d.ts +16 -5
- package/lib/services/mfe-communication.service.d.ts +3 -0
- package/lib/services/session.errors.d.ts +15 -0
- package/lib/services/session.service.d.ts +49 -0
- package/lib/wis-common.module.d.ts +9 -4
- package/mis-wis-common-0.2.0.tgz +0 -0
- package/package.json +3 -2
- package/public-api.d.ts +4 -0
- package/src/assets/calendar.svg +7 -0
- package/src/assets/images/icons/Wis-icon.svg +4 -0
- package/src/assets/images/icons/brand.png +0 -0
- package/src/assets/images/icons/broascast.svg +3 -0
- package/src/assets/images/icons/bulk-upload.svg +3 -0
- package/src/assets/images/icons/desk-mgmt.svg +6 -0
- package/src/assets/images/icons/employees-sidebar.svg +3 -0
- package/src/assets/images/icons/help-section.svg +4 -0
- package/src/assets/images/icons/home.svg +3 -0
- package/src/assets/images/icons/logout.svg +4 -0
- package/src/assets/images/icons/manage-premise.svg +3 -0
- package/src/assets/images/icons/meeting-room.svg +7 -0
- package/src/assets/images/icons/mis-icon.svg +3 -0
- package/src/assets/images/icons/my-bookings.svg +5 -0
- package/src/assets/images/icons/profile.svg +3 -0
- package/src/assets/images/icons/reception.svg +14 -0
- package/src/assets/images/icons/report.svg +3 -0
- package/src/assets/images/icons/resource-group.svg +3 -0
- package/src/assets/images/icons/roles.svg +3 -0
- package/src/assets/images/icons/sanitize.svg +10 -0
- package/src/assets/images/icons/seat-mgmt.svg +3 -0
- package/src/assets/images/icons/settings-sidebar.svg +3 -0
- package/src/assets/images/icons/signout.svg +4 -0
- package/src/assets/images/icons/user-group.svg +6 -0
- package/src/assets/images/icons/user-permission.svg +5 -0
- package/src/assets/images/icons/utilisation.svg +3 -0
- package/src/assets/images/icons/vaccine_approval.svg +8 -0
- package/src/assets/images/icons/vaccine_upload.png +0 -0
- package/src/assets/images/icons/work-planner-sidebar.svg +3 -0
- package/src/assets/images/icons/workInSyncText.svg +14 -0
|
@@ -1,18 +1,28 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
2
|
import { Injectable, NgModule, Component, Inject } from '@angular/core';
|
|
3
|
-
import * as
|
|
3
|
+
import * as i5 from '@angular/common';
|
|
4
4
|
import { CommonModule } from '@angular/common';
|
|
5
|
-
import * as i1$
|
|
6
|
-
import { HttpErrorResponse } from '@angular/common/http';
|
|
7
|
-
import { tap } from 'rxjs/operators';
|
|
5
|
+
import * as i1$2 from '@angular/common/http';
|
|
6
|
+
import { HttpErrorResponse, HttpClientModule } from '@angular/common/http';
|
|
7
|
+
import { tap, finalize } from 'rxjs/operators';
|
|
8
8
|
import * as i1 from '@angular/router';
|
|
9
9
|
import * as i2 from 'mis-crystal-design-system/toast';
|
|
10
|
-
import * as i1$
|
|
10
|
+
import * as i1$1 from '@angular/cdk/overlay';
|
|
11
11
|
import { OverlayConfig, OverlayModule } from '@angular/cdk/overlay';
|
|
12
12
|
import { ComponentPortal } from '@angular/cdk/portal';
|
|
13
13
|
import * as i2$1 from 'mis-crystal-design-system/loader';
|
|
14
14
|
import { LoaderModule } from 'mis-crystal-design-system/loader';
|
|
15
|
-
import { ReplaySubject } from 'rxjs';
|
|
15
|
+
import { map, forkJoin, ReplaySubject } from 'rxjs';
|
|
16
|
+
import * as i2$2 from '@angular/forms';
|
|
17
|
+
import { Validators, ReactiveFormsModule } from '@angular/forms';
|
|
18
|
+
import { parseZone } from 'moment';
|
|
19
|
+
import * as i1$3 from 'mis-design-system/mis-modal';
|
|
20
|
+
import { MODAL_DATA_VAR } from 'mis-design-system/mis-modal';
|
|
21
|
+
import * as i6 from 'mis-crystal-design-system/dropdown';
|
|
22
|
+
import { DropdownModule } from 'mis-crystal-design-system/dropdown';
|
|
23
|
+
import * as i7 from 'mis-crystal-design-system/datepicker_v2';
|
|
24
|
+
import { DatepickerModuleV2 } from 'mis-crystal-design-system/datepicker_v2';
|
|
25
|
+
import jwtDecode from 'jwt-decode';
|
|
16
26
|
|
|
17
27
|
class AuthService {
|
|
18
28
|
constructor() { }
|
|
@@ -151,7 +161,7 @@ class LoaderComponent {
|
|
|
151
161
|
ngOnInit() { }
|
|
152
162
|
}
|
|
153
163
|
LoaderComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: LoaderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
154
|
-
LoaderComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: LoaderComponent, selector: "mis-common-loader", ngImport: i0, template: "<div class=\"message-wrapper\" *ngIf=\"message; else noMessageLoader\">\n <span><mis-loader type=\"block\"></mis-loader></span>\n <p>{{ message }}</p>\n</div>\n<ng-template #noMessageLoader>\n <mis-loader></mis-loader>\n</ng-template>\n", styles: [".message-wrapper{max-width:343px;background-color:#fff;display:flex;flex-wrap:nowrap;align-items:center;padding:20px 16px;border-radius:6px}.message-wrapper span{position:relative;background-color:#fff;display:inline-block;width:40px;height:40px;margin-right:16px}.message-wrapper p{margin:0}\n"], dependencies: [{ kind: "directive", type:
|
|
164
|
+
LoaderComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: LoaderComponent, selector: "mis-common-loader", ngImport: i0, template: "<div class=\"message-wrapper\" *ngIf=\"message; else noMessageLoader\">\n <span><mis-loader type=\"block\"></mis-loader></span>\n <p>{{ message }}</p>\n</div>\n<ng-template #noMessageLoader>\n <mis-loader></mis-loader>\n</ng-template>\n", styles: [".message-wrapper{max-width:343px;background-color:#fff;display:flex;flex-wrap:nowrap;align-items:center;padding:20px 16px;border-radius:6px}.message-wrapper span{position:relative;background-color:#fff;display:inline-block;width:40px;height:40px;margin-right:16px}.message-wrapper p{margin:0}\n"], dependencies: [{ kind: "directive", type: i5.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i2$1.LoaderComponent, selector: "mis-loader", inputs: ["mobileView"] }] });
|
|
155
165
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: LoaderComponent, decorators: [{
|
|
156
166
|
type: Component,
|
|
157
167
|
args: [{ selector: "mis-common-loader", template: "<div class=\"message-wrapper\" *ngIf=\"message; else noMessageLoader\">\n <span><mis-loader type=\"block\"></mis-loader></span>\n <p>{{ message }}</p>\n</div>\n<ng-template #noMessageLoader>\n <mis-loader></mis-loader>\n</ng-template>\n", styles: [".message-wrapper{max-width:343px;background-color:#fff;display:flex;flex-wrap:nowrap;align-items:center;padding:20px 16px;border-radius:6px}.message-wrapper span{position:relative;background-color:#fff;display:inline-block;width:40px;height:40px;margin-right:16px}.message-wrapper p{margin:0}\n"] }]
|
|
@@ -203,14 +213,14 @@ class LoaderService {
|
|
|
203
213
|
return { positionStrategy, width, backdropClass, hasMessage };
|
|
204
214
|
}
|
|
205
215
|
}
|
|
206
|
-
LoaderService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: LoaderService, deps: [{ token: i1$
|
|
216
|
+
LoaderService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: LoaderService, deps: [{ token: i1$1.Overlay }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
207
217
|
LoaderService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: LoaderService, providedIn: "root" });
|
|
208
218
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: LoaderService, decorators: [{
|
|
209
219
|
type: Injectable,
|
|
210
220
|
args: [{
|
|
211
221
|
providedIn: "root"
|
|
212
222
|
}]
|
|
213
|
-
}], ctorParameters: function () { return [{ type: i1$
|
|
223
|
+
}], ctorParameters: function () { return [{ type: i1$1.Overlay }]; } });
|
|
214
224
|
|
|
215
225
|
/** @format */
|
|
216
226
|
const CONSTANTS_LOGGER = {
|
|
@@ -268,14 +278,14 @@ class LoggerService {
|
|
|
268
278
|
this.logRequest({ ...data, componentName, serviceUrl }, "error");
|
|
269
279
|
}
|
|
270
280
|
}
|
|
271
|
-
LoggerService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: LoggerService, deps: [{ token: i1$
|
|
281
|
+
LoggerService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: LoggerService, deps: [{ token: i1$2.HttpClient }, { token: CONSTANTS_LOGGER.APP_NAME }, { token: CONSTANTS_LOGGER.ENV_VAR }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
272
282
|
LoggerService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: LoggerService, providedIn: "root" });
|
|
273
283
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: LoggerService, decorators: [{
|
|
274
284
|
type: Injectable,
|
|
275
285
|
args: [{
|
|
276
286
|
providedIn: "root"
|
|
277
287
|
}]
|
|
278
|
-
}], ctorParameters: function () { return [{ type: i1$
|
|
288
|
+
}], ctorParameters: function () { return [{ type: i1$2.HttpClient }, { type: undefined, decorators: [{
|
|
279
289
|
type: Inject,
|
|
280
290
|
args: [CONSTANTS_LOGGER.APP_NAME]
|
|
281
291
|
}] }, { type: undefined, decorators: [{
|
|
@@ -328,23 +338,43 @@ const API_URLS = {
|
|
|
328
338
|
CONFIGURATIONS: "configurations"
|
|
329
339
|
};
|
|
330
340
|
class HttpService {
|
|
331
|
-
constructor(env,
|
|
341
|
+
constructor(env, http) {
|
|
332
342
|
this.env = env;
|
|
333
|
-
this.auth = auth;
|
|
334
343
|
this.http = http;
|
|
335
344
|
}
|
|
336
|
-
|
|
337
|
-
return this.http.get(`${this.env.
|
|
345
|
+
getProperties(Porperties) {
|
|
346
|
+
return this.http.get(`${this.env.ets}/ets/apis/properties/${Porperties.join(",")}`).pipe(map((res) => {
|
|
347
|
+
return res.reduce((acc, item) => {
|
|
348
|
+
acc[item.propertyName] = item.propertyValue === "true" ? true : item.propertyValue === "false" ? false : item.propertyValue;
|
|
349
|
+
return acc;
|
|
350
|
+
}, {});
|
|
351
|
+
}));
|
|
352
|
+
}
|
|
353
|
+
getOffices(nonce) {
|
|
354
|
+
const body = `CSRF_NONCE=${nonce}&method=getOfficeList`;
|
|
355
|
+
return this.http.post(`${this.env.ets}/Locality_Servlet`, body, { headers: { "Content-Type": "application/x-www-form-urlencoded" } });
|
|
356
|
+
}
|
|
357
|
+
listTransportLocalities(nonce) {
|
|
358
|
+
const body = `CSRF_NONCE=${nonce}&method=listTransportLocalities`;
|
|
359
|
+
return this.http.post(`${this.env.ets}/Locality_Servlet`, body, { headers: { "Content-Type": "application/x-www-form-urlencoded" } });
|
|
360
|
+
}
|
|
361
|
+
createEmptyIrregularTripSheet(nonce, direction) {
|
|
362
|
+
const body = `CSRF_NONCE=${nonce}&method=createEmptyIrregularTripSheet&direction=${direction}`;
|
|
363
|
+
return this.http.post(`${this.env.ets}/Tripsheet_Edit_Servlet`, body, { headers: { "Content-Type": "application/x-www-form-urlencoded" } });
|
|
364
|
+
}
|
|
365
|
+
addEmployeeToTripSheet(nonce, params) {
|
|
366
|
+
const body = `CSRF_NONCE=${nonce}&method=addEmployeeToTripSheet&tripsheet=${encodeURIComponent(JSON.stringify(params.tripsheet))}&employee=${encodeURIComponent(JSON.stringify(params.employee))}&pickupLoc=${encodeURIComponent(JSON.stringify(params.pickupLoc))}&dropLoc=${encodeURIComponent(JSON.stringify(params.dropLoc))}&pickUpTime="${params.pickUpTime}"&dropTime="${params.dropTime}"&position=${params.position}${params.routeSource ? "&routeSource=" + params.routeSource : ""}${params.assetList ? "&assetList=" + encodeURIComponent(JSON.stringify(params.assetList)) : ""}`;
|
|
367
|
+
return this.http.post(`${this.env.ets}/Tripsheet_Edit_Servlet`, body, { headers: { "Content-Type": "application/x-www-form-urlencoded" } });
|
|
338
368
|
}
|
|
339
369
|
}
|
|
340
|
-
HttpService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: HttpService, deps: [{ token: CONSTANTS_WIS_COMMON }, { token:
|
|
370
|
+
HttpService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: HttpService, deps: [{ token: CONSTANTS_WIS_COMMON }, { token: i1$2.HttpClient }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
341
371
|
HttpService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: HttpService });
|
|
342
372
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: HttpService, decorators: [{
|
|
343
373
|
type: Injectable
|
|
344
374
|
}], ctorParameters: function () { return [{ type: undefined, decorators: [{
|
|
345
375
|
type: Inject,
|
|
346
376
|
args: [CONSTANTS_WIS_COMMON]
|
|
347
|
-
}] }, { type:
|
|
377
|
+
}] }, { type: i1$2.HttpClient }]; } });
|
|
348
378
|
|
|
349
379
|
class SidenavComponent {
|
|
350
380
|
constructor() { }
|
|
@@ -357,24 +387,250 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImpor
|
|
|
357
387
|
args: [{ selector: "wis-common-sidenav", template: "<div class=\"wis-sidenav-wrapper\">\n <div class=\"wis-sidenav-header\">\n <div class=\"wis-sidenav-header-logo\">\n <img src=\"assets/sidenav/assets/Wis-icon.svg\" alt=\"\" />\n </div>\n <div class=\"wis-sidenav-header-title\">\n <h1>WIS</h1>\n </div>\n </div>\n <div class=\"wis-sidenav-body\">\n <div class=\"wis-sidenav-body-item\">\n <div class=\"wis-sidenav-body-item-icon\">\n <i class=\"fas fa-home\"></i>\n </div>\n <div class=\"wis-sidenav-body-item-text\">\n <h3>Home</h3>\n </div>\n </div>\n <div class=\"wis-sidenav-body-item\">\n <div class=\"wis-sidenav-body-item-icon\">\n <i class=\"fas fa-user\"></i>\n </div>\n <div class=\"wis-sidenav-body-item-text\">\n <h3>Profile</h3>\n </div>\n </div>\n <div class=\"wis-sidenav-body-item\">\n <div class=\"wis-sidenav-body-item-icon\">\n <i class=\"fas fa-users\"></i>\n </div>\n <div class=\"wis-sidenav-body-item-text\">\n <h3>Users</h3>\n </div>\n </div>\n <div class=\"wis-sidenav-body-item\">\n <div class=\"wis-sidenav-body-item-icon\">\n <i class=\"fas fa-cog\"></i>\n </div>\n <div class=\"wis-sidenav-body-item-text\">\n <h3>Settings</h3>\n </div>\n </div>\n </div>\n</div>\n", styles: [".wis-sidenav-wrapper{width:72px;border-right:1px solid #e0e0e0}\n"] }]
|
|
358
388
|
}], ctorParameters: function () { return []; } });
|
|
359
389
|
|
|
390
|
+
/** @format */
|
|
391
|
+
const CONSTANTS_ASSETS_WIS_COMMON = {
|
|
392
|
+
IMAGES: {
|
|
393
|
+
CALENDAR_ICON: "assets/libraries/wis-common/calendar.svg"
|
|
394
|
+
},
|
|
395
|
+
ICONS: {}
|
|
396
|
+
};
|
|
397
|
+
|
|
398
|
+
const PROPERTIES = ["NON_SHIFT_TRIPS_CATEGORIES", "USE_VALID_OFFICE_FOR_IRREGULAR_TRIPS"];
|
|
399
|
+
class CreateNonShiftModalComponent {
|
|
400
|
+
constructor(modalData, modalRef, fb, http, toast) {
|
|
401
|
+
this.modalData = modalData;
|
|
402
|
+
this.modalRef = modalRef;
|
|
403
|
+
this.fb = fb;
|
|
404
|
+
this.http = http;
|
|
405
|
+
this.toast = toast;
|
|
406
|
+
this.CONSTANTS_ASSETS_WIS_COMMON = CONSTANTS_ASSETS_WIS_COMMON;
|
|
407
|
+
this.dateConfig = {
|
|
408
|
+
minDate: parseZone().format("DD/MM/YYYY"),
|
|
409
|
+
format: "DD/MM/YYYY"
|
|
410
|
+
};
|
|
411
|
+
this.offices = [];
|
|
412
|
+
this.locationDropdownData = [];
|
|
413
|
+
this.categoryDropdownData = [];
|
|
414
|
+
this.hoursDropdownData = [];
|
|
415
|
+
this.minutesDropdownData = [];
|
|
416
|
+
this.showOtherAddress = false;
|
|
417
|
+
this.loading = false;
|
|
418
|
+
this.isSubmitting = false;
|
|
419
|
+
this.TYPE_OFFICE = 6;
|
|
420
|
+
this.TYPE_TRANSPORT = 3;
|
|
421
|
+
this.TYPE_OTHER = 4;
|
|
422
|
+
this.properties = {};
|
|
423
|
+
}
|
|
424
|
+
ngOnInit() {
|
|
425
|
+
this.loading = true;
|
|
426
|
+
const $office = this.http.getOffices(this.modalData.nonce);
|
|
427
|
+
const $properties = this.http.getProperties(PROPERTIES);
|
|
428
|
+
forkJoin([$office, $properties])
|
|
429
|
+
.pipe(finalize(() => (this.loading = false)))
|
|
430
|
+
.subscribe({
|
|
431
|
+
next: ([offices, properties]) => {
|
|
432
|
+
this.properties = properties;
|
|
433
|
+
this.initializeForm();
|
|
434
|
+
this.initializeDropdownData(offices);
|
|
435
|
+
this.setupFormListeners();
|
|
436
|
+
},
|
|
437
|
+
error: error => {
|
|
438
|
+
console.error("Error loading form data:", error);
|
|
439
|
+
this.modalRef.close();
|
|
440
|
+
}
|
|
441
|
+
});
|
|
442
|
+
}
|
|
443
|
+
initializeForm() {
|
|
444
|
+
const currentTime = this.modalData?.date ?? parseZone().format("DD/MM/YYYY");
|
|
445
|
+
this.createTripsheetForm = this.fb.group({
|
|
446
|
+
direction: [this.modalData?.shiftType === "logout" ? "OUT" : "IN", Validators.required],
|
|
447
|
+
location: [{ label: "", value: "" }],
|
|
448
|
+
otherAddress: "",
|
|
449
|
+
tripCategory: [{ label: "", value: "" }],
|
|
450
|
+
date: [currentTime, Validators.required],
|
|
451
|
+
hours: [{ label: "", value: "" }],
|
|
452
|
+
mins: [{ label: "", value: "" }]
|
|
453
|
+
});
|
|
454
|
+
}
|
|
455
|
+
initializeDropdownData(offices) {
|
|
456
|
+
this.locationDropdownData = offices.map((office) => ({
|
|
457
|
+
label: office.address,
|
|
458
|
+
value: { type: this.TYPE_OFFICE, office: office || null }
|
|
459
|
+
}));
|
|
460
|
+
this.createTripsheetForm.get("location")?.setValue(this.locationDropdownData[0]);
|
|
461
|
+
if (!this.properties?.["USE_VALID_OFFICE_FOR_IRREGULAR_TRIPS"]) {
|
|
462
|
+
this.locationDropdownData.push({ label: "Airport", value: { type: this.TYPE_TRANSPORT, office: null } }, { label: "Other", value: { type: this.TYPE_OTHER, office: null } });
|
|
463
|
+
}
|
|
464
|
+
// Initialize category dropdown
|
|
465
|
+
const categoriesString = this.properties?.["NON_SHIFT_TRIPS_CATEGORIES"];
|
|
466
|
+
if (categoriesString && typeof categoriesString === "string") {
|
|
467
|
+
const categories = categoriesString.split(",").filter(cat => cat && cat.trim());
|
|
468
|
+
if (categories.length > 0) {
|
|
469
|
+
this.categoryDropdownData = categories.map(category => ({
|
|
470
|
+
label: category.trim(),
|
|
471
|
+
value: category.trim()
|
|
472
|
+
}));
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
const currentHour = new Date().getHours();
|
|
476
|
+
this.hoursDropdownData = Array.from({ length: 24 }, (_, i) => ({
|
|
477
|
+
label: this.padZero(i),
|
|
478
|
+
value: this.padZero(i)
|
|
479
|
+
}));
|
|
480
|
+
this.createTripsheetForm.patchValue({ hours: this.hoursDropdownData[currentHour] });
|
|
481
|
+
const currentMinute = new Date().getMinutes();
|
|
482
|
+
this.minutesDropdownData = Array.from({ length: 60 }, (_, i) => ({
|
|
483
|
+
label: this.padZero(i),
|
|
484
|
+
value: this.padZero(i)
|
|
485
|
+
}));
|
|
486
|
+
this.createTripsheetForm.patchValue({ mins: this.minutesDropdownData[currentMinute] });
|
|
487
|
+
}
|
|
488
|
+
setupFormListeners() {
|
|
489
|
+
this.createTripsheetForm?.valueChanges.subscribe(value => {
|
|
490
|
+
const { location } = this.createTripsheetForm?.value;
|
|
491
|
+
if (this.showOtherAddress !== (location?.value?.type === this.TYPE_OTHER)) {
|
|
492
|
+
this.showOtherAddress = location?.value?.type === this.TYPE_OTHER;
|
|
493
|
+
if (this.showOtherAddress) {
|
|
494
|
+
this.createTripsheetForm.get("otherAddress")?.setValidators([Validators.required]);
|
|
495
|
+
}
|
|
496
|
+
else {
|
|
497
|
+
this.createTripsheetForm.get("otherAddress")?.clearValidators();
|
|
498
|
+
}
|
|
499
|
+
this.createTripsheetForm.get("otherAddress")?.updateValueAndValidity();
|
|
500
|
+
}
|
|
501
|
+
});
|
|
502
|
+
}
|
|
503
|
+
padZero(num) {
|
|
504
|
+
return num.toString().padStart(2, "0");
|
|
505
|
+
}
|
|
506
|
+
onCancel() {
|
|
507
|
+
this.modalRef.close();
|
|
508
|
+
}
|
|
509
|
+
onSubmit() {
|
|
510
|
+
if (this.createTripsheetForm.invalid) {
|
|
511
|
+
return;
|
|
512
|
+
}
|
|
513
|
+
const formValue = this.createTripsheetForm.value;
|
|
514
|
+
const pickupTime = `${formValue.date} ${formValue.hours.value}/${formValue.mins.value}/00`;
|
|
515
|
+
const pickupTimeDate = parseZone(pickupTime).toDate();
|
|
516
|
+
if (this.isDateAndTimeFromPast(pickupTimeDate)) {
|
|
517
|
+
this.toast.displayMsg("Please select a future date and time.");
|
|
518
|
+
return;
|
|
519
|
+
}
|
|
520
|
+
if (this.categoryDropdownData.length > 0 && (!formValue.tripCategory || !formValue.tripCategory.value)) {
|
|
521
|
+
this.toast.displayMsg("Please provide a trip category.");
|
|
522
|
+
return;
|
|
523
|
+
}
|
|
524
|
+
if (formValue.location?.value?.type === this.TYPE_OTHER) {
|
|
525
|
+
if (!formValue.otherAddress || formValue.otherAddress.trim() === "") {
|
|
526
|
+
this.toast.displayMsg("Please provide the address.");
|
|
527
|
+
return;
|
|
528
|
+
}
|
|
529
|
+
if (formValue.otherAddress.includes(",")) {
|
|
530
|
+
this.toast.displayMsg("Special character (,) not allowed in address.");
|
|
531
|
+
return;
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
this.isSubmitting = true;
|
|
535
|
+
this.http.createEmptyIrregularTripSheet(this.modalData.nonce, formValue.direction).subscribe({
|
|
536
|
+
next: routeTripSheet => {
|
|
537
|
+
const pickupLoc = routeTripSheet.dir === "IN" ? this.modalData.employee.home : this.getLocation(formValue);
|
|
538
|
+
const dropLoc = routeTripSheet.dir === "OUT" ? this.modalData.employee.home : this.getLocation(formValue);
|
|
539
|
+
const pickupTimeFormatted = pickupTime;
|
|
540
|
+
const dropTimeFormatted = pickupTime;
|
|
541
|
+
const employee = { ...this.modalData.employee, employee_status: 1 };
|
|
542
|
+
const addEmployeeParams = {
|
|
543
|
+
tripsheet: routeTripSheet,
|
|
544
|
+
employee: employee,
|
|
545
|
+
pickupLoc: pickupLoc,
|
|
546
|
+
dropLoc: dropLoc,
|
|
547
|
+
pickUpTime: pickupTimeFormatted,
|
|
548
|
+
dropTime: dropTimeFormatted,
|
|
549
|
+
position: 0,
|
|
550
|
+
routeSource: this.modalData.routeSource,
|
|
551
|
+
assetList: this.modalData.assetList
|
|
552
|
+
};
|
|
553
|
+
this.http.addEmployeeToTripSheet(this.modalData.nonce, addEmployeeParams).subscribe({
|
|
554
|
+
next: updatedTripSheet => {
|
|
555
|
+
if (!updatedTripSheet.customMap) {
|
|
556
|
+
updatedTripSheet.customMap = {};
|
|
557
|
+
}
|
|
558
|
+
updatedTripSheet.customMap.tripCategory = formValue.tripCategory?.value || "";
|
|
559
|
+
this.modalRef.close({
|
|
560
|
+
success: true,
|
|
561
|
+
tripsheet: updatedTripSheet
|
|
562
|
+
});
|
|
563
|
+
},
|
|
564
|
+
error: error => {
|
|
565
|
+
console.error("Error adding employee to tripsheet:", error);
|
|
566
|
+
this.toast.displayMsg("Failed to add employee to tripsheet. Please try again.");
|
|
567
|
+
this.isSubmitting = false;
|
|
568
|
+
}
|
|
569
|
+
});
|
|
570
|
+
},
|
|
571
|
+
error: error => {
|
|
572
|
+
console.error("Error creating tripsheet:", error);
|
|
573
|
+
this.toast.displayMsg("Failed to create tripsheet. Please try again.");
|
|
574
|
+
this.isSubmitting = false;
|
|
575
|
+
}
|
|
576
|
+
});
|
|
577
|
+
}
|
|
578
|
+
isDateAndTimeFromPast(date) {
|
|
579
|
+
const now = new Date();
|
|
580
|
+
return date < now;
|
|
581
|
+
}
|
|
582
|
+
getLocation(formValue) {
|
|
583
|
+
const location = formValue.location?.value;
|
|
584
|
+
if (!location) {
|
|
585
|
+
return null;
|
|
586
|
+
}
|
|
587
|
+
const locType = location.type;
|
|
588
|
+
switch (locType) {
|
|
589
|
+
case this.TYPE_OFFICE:
|
|
590
|
+
return location.office;
|
|
591
|
+
case this.TYPE_TRANSPORT:
|
|
592
|
+
return {
|
|
593
|
+
id: null,
|
|
594
|
+
type: this.TYPE_TRANSPORT,
|
|
595
|
+
address: "Airport",
|
|
596
|
+
geoCord: null
|
|
597
|
+
};
|
|
598
|
+
case this.TYPE_OTHER:
|
|
599
|
+
return {
|
|
600
|
+
...location.office,
|
|
601
|
+
address: formValue.otherAddress || ""
|
|
602
|
+
};
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
CreateNonShiftModalComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: CreateNonShiftModalComponent, deps: [{ token: MODAL_DATA_VAR }, { token: i1$3.ModalRef }, { token: i2$2.FormBuilder }, { token: HttpService }, { token: i2.ToastService }], target: i0.ɵɵFactoryTarget.Component });
|
|
607
|
+
CreateNonShiftModalComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: CreateNonShiftModalComponent, selector: "app-create-non-shift-modal", ngImport: i0, template: "<div class=\"createTripsheet\">\n <h2 class=\"modal-header\">Create Non-Shift Tripsheet</h2>\n\n <div *ngIf=\"loading\" class=\"loading-container\">\n <div class=\"spinner\"></div>\n <p>Loading...</p>\n </div>\n\n <form\n *ngIf=\"!loading && createTripsheetForm\"\n [formGroup]=\"createTripsheetForm\"\n (ngSubmit)=\"onSubmit()\"\n class=\"createTripsheetForm\"\n id=\"createTripsheetForm\"\n >\n <div class=\"form-content\">\n <!-- Radio buttons row -->\n <div [ngClass]=\"{ 'radio-row': true, disabled: modalData?.shiftSelectionDisabled }\">\n <label class=\"radio-label\">\n <input class=\"modern-checkbox\" type=\"radio\" formControlName=\"direction\" value=\"OUT\" id=\"startLoc\" />\n <span>Start Location Fixed (Logout)</span>\n </label>\n <label class=\"radio-label\">\n <input class=\"modern-checkbox\" type=\"radio\" formControlName=\"direction\" value=\"IN\" id=\"endLoc\" />\n <span>End Location Fixed (Login)</span>\n </label>\n </div>\n\n <!-- Location field -->\n <div class=\"form-field\">\n <div class=\"label-cell\">\n <label class=\"locText\">Location</label>\n </div>\n <div class=\"input-cell\">\n <mis-dropdown\n [searchEnabled]=\"true\"\n [width]=\"'100%'\"\n [height]=\"'40px'\"\n [data]=\"locationDropdownData\"\n [selectedItem]=\"createTripsheetForm.get('location')?.value\"\n [label]=\"'Select location...'\"\n (onChange)=\"createTripsheetForm.get('location')?.setValue($event)\"\n ></mis-dropdown>\n </div>\n </div>\n\n <!-- Other address field -->\n <div class=\"form-field otherAddress\" *ngIf=\"showOtherAddress\">\n <div class=\"label-cell\">\n <label>Pick/Drop point <sup>*</sup></label>\n </div>\n <div class=\"input-cell\">\n <input type=\"text\" formControlName=\"otherAddress\" class=\"modern-input\" />\n </div>\n </div>\n\n <!-- Trip category field -->\n <div class=\"form-field\" *ngIf=\"categoryDropdownData.length > 0\">\n <div class=\"label-cell\">\n <label>Trip Category</label>\n </div>\n <div class=\"input-cell\">\n <mis-dropdown\n [searchEnabled]=\"false\"\n [width]=\"'250px'\"\n [height]=\"'40px'\"\n [data]=\"categoryDropdownData\"\n [selectedItem]=\"createTripsheetForm.get('tripCategory')?.value\"\n [label]=\"'Select category...'\"\n (onChange)=\"createTripsheetForm.get('tripCategory')?.setValue($event)\"\n ></mis-dropdown>\n </div>\n </div>\n\n <!-- Time field -->\n <div class=\"form-field\">\n <div class=\"label-cell\">\n <label class=\"fixedTimeText\">Time</label>\n </div>\n <div class=\"input-cell modern-date-container\">\n <div class=\"date-select\">\n <input\n misTzDp\n readonly\n [dpConfig]=\"dateConfig\"\n [formControl]=\"createTripsheetForm.get('date')\"\n style=\"height: 44px !important; font-size: 16px !important; cursor: pointer; vertical-align: middle !important\"\n />\n <img [src]=\"CONSTANTS_ASSETS_WIS_COMMON.IMAGES.CALENDAR_ICON\" alt=\"Calendar Icon\" class=\"date-icon data-picker-icon\" />\n </div>\n\n <mis-dropdown\n [searchEnabled]=\"false\"\n [width]=\"'5rem'\"\n [height]=\"'40px'\"\n [data]=\"hoursDropdownData\"\n [selectedItem]=\"createTripsheetForm.get('hours')?.value\"\n [label]=\"'HH'\"\n (onChange)=\"createTripsheetForm.get('hours')?.setValue($event)\"\n ></mis-dropdown>\n\n <mis-dropdown\n [searchEnabled]=\"false\"\n [width]=\"'5rem'\"\n [height]=\"'40px'\"\n [data]=\"minutesDropdownData\"\n [selectedItem]=\"createTripsheetForm.get('mins')?.value\"\n [label]=\"'MM'\"\n (onChange)=\"createTripsheetForm.get('mins')?.setValue($event)\"\n ></mis-dropdown>\n </div>\n </div>\n </div>\n\n <div class=\"form-actions\">\n <button mis-button type=\"outline\" (click)=\"onCancel()\" [disabled]=\"isSubmitting\">Cancel</button>\n <button mis-button type=\"primary\" [disabled]=\"isSubmitting || createTripsheetForm?.invalid\">\n {{ isSubmitting ? \"Creating...\" : \"Create\" }}\n </button>\n </div>\n </form>\n</div>\n", styles: [".createTripsheet{width:40rem;margin:auto;background:#fff;border-radius:.5rem;padding:1.25rem}.createTripsheet .modal-header{font-size:1.25rem;font-weight:600;color:#333;margin:0 0 1.25rem;padding-bottom:.9375rem;border-bottom:.0625rem solid #e0e0e0}.createTripsheet .loading-container{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:3.75rem 1.25rem;min-height:12.5rem}.createTripsheet .loading-container .spinner{border:.1875rem solid #f3f3f3;border-top:.1875rem solid #007bff;border-radius:50%;width:2.5rem;height:2.5rem;animation:spin 1s linear infinite}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.createTripsheet .createTripsheetForm .form-content{display:flex;flex-direction:column}.createTripsheet .createTripsheetForm .form-field{display:flex;align-items:flex-start;gap:1.25rem;padding:.9375rem 0}.createTripsheet .createTripsheetForm .form-field .label-cell{flex:0 0 30%;padding-top:.5rem}.createTripsheet .createTripsheetForm .form-field .label-cell label{font-size:.875rem;font-weight:500;color:#333}.createTripsheet .createTripsheetForm .form-field .input-cell{flex:1;display:flex}.createTripsheet .createTripsheetForm .radio-row{display:flex;gap:1.25rem;padding:.9375rem 0}.createTripsheet .createTripsheetForm .radio-label{font-size:.875rem;display:flex;align-items:center;cursor:pointer;margin:0}.createTripsheet .createTripsheetForm .radio-label .modern-checkbox{margin-right:.625rem;vertical-align:sub;cursor:pointer;width:1rem;height:1rem;accent-color:#007bff}.createTripsheet .createTripsheetForm .radio-label span{-webkit-user-select:none;user-select:none;white-space:nowrap}.createTripsheet .createTripsheetForm .modern-input{width:100%;padding:.5rem .75rem;border:.0625rem solid #ddd;border-radius:.25rem;font-size:.875rem;transition:border-color .3s}.createTripsheet .createTripsheetForm .modern-input:focus{outline:none;border-color:#007bff;box-shadow:0 0 0 .2rem #007bff40}.createTripsheet .createTripsheetForm .modern-input:disabled{background-color:#f5f5f5;cursor:not-allowed}.createTripsheet .createTripsheetForm sup{color:#dc3545}.createTripsheet .createTripsheetForm ::ng-deep mis-dropdown{display:block;width:100%}.createTripsheet .createTripsheetForm .modern-date-container{position:inherit;float:inherit;display:flex;align-items:center;gap:.625rem}.createTripsheet .createTripsheetForm .ng-invalid{border:.0625rem solid #dc3545}.createTripsheet .createTripsheetForm .form-actions{text-align:right;margin:.625rem;border-top:.0625rem solid #e0e0e0;padding:.625rem;display:flex;justify-content:flex-end;gap:.625rem;margin-bottom:0}.createTripsheet .createTripsheetForm .form-actions button{padding:.625rem 1.5rem;font-size:.875rem;font-weight:500;border-radius:.375rem;border:none;cursor:pointer;transition:all .3s ease;min-width:6.25rem}.createTripsheet .createTripsheetForm .form-actions button[type=primary]{background-color:#0937b2;color:#fff;border:.0625rem solid #0937b2}.createTripsheet .createTripsheetForm .form-actions button[type=outline]{background-color:transparent;color:#6c757d;border:.0625rem solid #ddd}.createTripsheet .createTripsheetForm .form-actions button:disabled{opacity:.6;cursor:not-allowed;box-shadow:none}.date-select{height:2.5rem;border:.0625rem solid #e0e0e0;padding:0;border-radius:.375rem;display:flex;flex-wrap:nowrap;justify-content:space-between;align-items:center;position:relative;overflow:hidden;left:-.5%;flex-shrink:0}.date-select input{background-color:transparent;display:inline-block;padding:.25rem 0 .25rem .75rem;width:100%;border:none;outline:none;cursor:pointer;font-size:.875rem}.date-select img{position:relative;right:1rem}.radio-row.disabled{pointer-events:none;opacity:.5}\n"], dependencies: [{ kind: "directive", type: i5.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i5.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i6.DropdownComponent, selector: "mis-dropdown", inputs: ["data", "height", "ariaLabel", "width", "label", "itemSizeForCdk", "showOnlyIcon", "higlightSelectedValue", "dropdownListHeight", "dropdownListWidth", "dropdownListPosition", "config", "searchEnabled", "selectedItem", "noDataMessage", "multiLine", "additionalInfoMessage", "scrollIntoView", "searchLabel", "customStyles", "activeItem"], outputs: ["onChange"] }, { kind: "directive", type: i2$2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2$2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2$2.RadioControlValueAccessor, selector: "input[type=radio][formControlName],input[type=radio][formControl],input[type=radio][ngModel]", inputs: ["name", "formControlName", "value"] }, { kind: "directive", type: i2$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2$2.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i2$2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2$2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i7.TzDatepickerDirective, selector: "input[misTzDp]", inputs: ["dpConfig", "selectedDate", "datesDisabled", "dateMessages", "positionX", "positionY", "offsetX", "offsetY", "allowBookingOnDisabledDay", "disableBoxShadow", "disableOverLay", "openElement"], outputs: ["dateChange"] }] });
|
|
608
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: CreateNonShiftModalComponent, decorators: [{
|
|
609
|
+
type: Component,
|
|
610
|
+
args: [{ selector: "app-create-non-shift-modal", template: "<div class=\"createTripsheet\">\n <h2 class=\"modal-header\">Create Non-Shift Tripsheet</h2>\n\n <div *ngIf=\"loading\" class=\"loading-container\">\n <div class=\"spinner\"></div>\n <p>Loading...</p>\n </div>\n\n <form\n *ngIf=\"!loading && createTripsheetForm\"\n [formGroup]=\"createTripsheetForm\"\n (ngSubmit)=\"onSubmit()\"\n class=\"createTripsheetForm\"\n id=\"createTripsheetForm\"\n >\n <div class=\"form-content\">\n <!-- Radio buttons row -->\n <div [ngClass]=\"{ 'radio-row': true, disabled: modalData?.shiftSelectionDisabled }\">\n <label class=\"radio-label\">\n <input class=\"modern-checkbox\" type=\"radio\" formControlName=\"direction\" value=\"OUT\" id=\"startLoc\" />\n <span>Start Location Fixed (Logout)</span>\n </label>\n <label class=\"radio-label\">\n <input class=\"modern-checkbox\" type=\"radio\" formControlName=\"direction\" value=\"IN\" id=\"endLoc\" />\n <span>End Location Fixed (Login)</span>\n </label>\n </div>\n\n <!-- Location field -->\n <div class=\"form-field\">\n <div class=\"label-cell\">\n <label class=\"locText\">Location</label>\n </div>\n <div class=\"input-cell\">\n <mis-dropdown\n [searchEnabled]=\"true\"\n [width]=\"'100%'\"\n [height]=\"'40px'\"\n [data]=\"locationDropdownData\"\n [selectedItem]=\"createTripsheetForm.get('location')?.value\"\n [label]=\"'Select location...'\"\n (onChange)=\"createTripsheetForm.get('location')?.setValue($event)\"\n ></mis-dropdown>\n </div>\n </div>\n\n <!-- Other address field -->\n <div class=\"form-field otherAddress\" *ngIf=\"showOtherAddress\">\n <div class=\"label-cell\">\n <label>Pick/Drop point <sup>*</sup></label>\n </div>\n <div class=\"input-cell\">\n <input type=\"text\" formControlName=\"otherAddress\" class=\"modern-input\" />\n </div>\n </div>\n\n <!-- Trip category field -->\n <div class=\"form-field\" *ngIf=\"categoryDropdownData.length > 0\">\n <div class=\"label-cell\">\n <label>Trip Category</label>\n </div>\n <div class=\"input-cell\">\n <mis-dropdown\n [searchEnabled]=\"false\"\n [width]=\"'250px'\"\n [height]=\"'40px'\"\n [data]=\"categoryDropdownData\"\n [selectedItem]=\"createTripsheetForm.get('tripCategory')?.value\"\n [label]=\"'Select category...'\"\n (onChange)=\"createTripsheetForm.get('tripCategory')?.setValue($event)\"\n ></mis-dropdown>\n </div>\n </div>\n\n <!-- Time field -->\n <div class=\"form-field\">\n <div class=\"label-cell\">\n <label class=\"fixedTimeText\">Time</label>\n </div>\n <div class=\"input-cell modern-date-container\">\n <div class=\"date-select\">\n <input\n misTzDp\n readonly\n [dpConfig]=\"dateConfig\"\n [formControl]=\"createTripsheetForm.get('date')\"\n style=\"height: 44px !important; font-size: 16px !important; cursor: pointer; vertical-align: middle !important\"\n />\n <img [src]=\"CONSTANTS_ASSETS_WIS_COMMON.IMAGES.CALENDAR_ICON\" alt=\"Calendar Icon\" class=\"date-icon data-picker-icon\" />\n </div>\n\n <mis-dropdown\n [searchEnabled]=\"false\"\n [width]=\"'5rem'\"\n [height]=\"'40px'\"\n [data]=\"hoursDropdownData\"\n [selectedItem]=\"createTripsheetForm.get('hours')?.value\"\n [label]=\"'HH'\"\n (onChange)=\"createTripsheetForm.get('hours')?.setValue($event)\"\n ></mis-dropdown>\n\n <mis-dropdown\n [searchEnabled]=\"false\"\n [width]=\"'5rem'\"\n [height]=\"'40px'\"\n [data]=\"minutesDropdownData\"\n [selectedItem]=\"createTripsheetForm.get('mins')?.value\"\n [label]=\"'MM'\"\n (onChange)=\"createTripsheetForm.get('mins')?.setValue($event)\"\n ></mis-dropdown>\n </div>\n </div>\n </div>\n\n <div class=\"form-actions\">\n <button mis-button type=\"outline\" (click)=\"onCancel()\" [disabled]=\"isSubmitting\">Cancel</button>\n <button mis-button type=\"primary\" [disabled]=\"isSubmitting || createTripsheetForm?.invalid\">\n {{ isSubmitting ? \"Creating...\" : \"Create\" }}\n </button>\n </div>\n </form>\n</div>\n", styles: [".createTripsheet{width:40rem;margin:auto;background:#fff;border-radius:.5rem;padding:1.25rem}.createTripsheet .modal-header{font-size:1.25rem;font-weight:600;color:#333;margin:0 0 1.25rem;padding-bottom:.9375rem;border-bottom:.0625rem solid #e0e0e0}.createTripsheet .loading-container{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:3.75rem 1.25rem;min-height:12.5rem}.createTripsheet .loading-container .spinner{border:.1875rem solid #f3f3f3;border-top:.1875rem solid #007bff;border-radius:50%;width:2.5rem;height:2.5rem;animation:spin 1s linear infinite}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.createTripsheet .createTripsheetForm .form-content{display:flex;flex-direction:column}.createTripsheet .createTripsheetForm .form-field{display:flex;align-items:flex-start;gap:1.25rem;padding:.9375rem 0}.createTripsheet .createTripsheetForm .form-field .label-cell{flex:0 0 30%;padding-top:.5rem}.createTripsheet .createTripsheetForm .form-field .label-cell label{font-size:.875rem;font-weight:500;color:#333}.createTripsheet .createTripsheetForm .form-field .input-cell{flex:1;display:flex}.createTripsheet .createTripsheetForm .radio-row{display:flex;gap:1.25rem;padding:.9375rem 0}.createTripsheet .createTripsheetForm .radio-label{font-size:.875rem;display:flex;align-items:center;cursor:pointer;margin:0}.createTripsheet .createTripsheetForm .radio-label .modern-checkbox{margin-right:.625rem;vertical-align:sub;cursor:pointer;width:1rem;height:1rem;accent-color:#007bff}.createTripsheet .createTripsheetForm .radio-label span{-webkit-user-select:none;user-select:none;white-space:nowrap}.createTripsheet .createTripsheetForm .modern-input{width:100%;padding:.5rem .75rem;border:.0625rem solid #ddd;border-radius:.25rem;font-size:.875rem;transition:border-color .3s}.createTripsheet .createTripsheetForm .modern-input:focus{outline:none;border-color:#007bff;box-shadow:0 0 0 .2rem #007bff40}.createTripsheet .createTripsheetForm .modern-input:disabled{background-color:#f5f5f5;cursor:not-allowed}.createTripsheet .createTripsheetForm sup{color:#dc3545}.createTripsheet .createTripsheetForm ::ng-deep mis-dropdown{display:block;width:100%}.createTripsheet .createTripsheetForm .modern-date-container{position:inherit;float:inherit;display:flex;align-items:center;gap:.625rem}.createTripsheet .createTripsheetForm .ng-invalid{border:.0625rem solid #dc3545}.createTripsheet .createTripsheetForm .form-actions{text-align:right;margin:.625rem;border-top:.0625rem solid #e0e0e0;padding:.625rem;display:flex;justify-content:flex-end;gap:.625rem;margin-bottom:0}.createTripsheet .createTripsheetForm .form-actions button{padding:.625rem 1.5rem;font-size:.875rem;font-weight:500;border-radius:.375rem;border:none;cursor:pointer;transition:all .3s ease;min-width:6.25rem}.createTripsheet .createTripsheetForm .form-actions button[type=primary]{background-color:#0937b2;color:#fff;border:.0625rem solid #0937b2}.createTripsheet .createTripsheetForm .form-actions button[type=outline]{background-color:transparent;color:#6c757d;border:.0625rem solid #ddd}.createTripsheet .createTripsheetForm .form-actions button:disabled{opacity:.6;cursor:not-allowed;box-shadow:none}.date-select{height:2.5rem;border:.0625rem solid #e0e0e0;padding:0;border-radius:.375rem;display:flex;flex-wrap:nowrap;justify-content:space-between;align-items:center;position:relative;overflow:hidden;left:-.5%;flex-shrink:0}.date-select input{background-color:transparent;display:inline-block;padding:.25rem 0 .25rem .75rem;width:100%;border:none;outline:none;cursor:pointer;font-size:.875rem}.date-select img{position:relative;right:1rem}.radio-row.disabled{pointer-events:none;opacity:.5}\n"] }]
|
|
611
|
+
}], ctorParameters: function () { return [{ type: undefined, decorators: [{
|
|
612
|
+
type: Inject,
|
|
613
|
+
args: [MODAL_DATA_VAR]
|
|
614
|
+
}] }, { type: i1$3.ModalRef }, { type: i2$2.FormBuilder }, { type: HttpService }, { type: i2.ToastService }]; } });
|
|
615
|
+
|
|
360
616
|
class WisCommonModule {
|
|
361
617
|
static forRoot(env) {
|
|
362
618
|
return {
|
|
363
619
|
ngModule: WisCommonModule,
|
|
364
|
-
providers: [{ provide: CONSTANTS_WIS_COMMON, useValue: env }, ConfigurationService, LoaderService]
|
|
620
|
+
providers: [HttpService, { provide: CONSTANTS_WIS_COMMON, useValue: env }, ConfigurationService, LoaderService]
|
|
365
621
|
};
|
|
366
622
|
}
|
|
367
623
|
}
|
|
368
624
|
WisCommonModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: WisCommonModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
369
|
-
WisCommonModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "14.3.0", ngImport: i0, type: WisCommonModule, declarations: [LoaderComponent, SidenavComponent], imports: [CommonModule, OverlayModule, LoaderModule], exports: [SidenavComponent] });
|
|
370
|
-
WisCommonModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: WisCommonModule,
|
|
625
|
+
WisCommonModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "14.3.0", ngImport: i0, type: WisCommonModule, declarations: [LoaderComponent, SidenavComponent, CreateNonShiftModalComponent], imports: [CommonModule, HttpClientModule, OverlayModule, LoaderModule, DropdownModule, ReactiveFormsModule, DatepickerModuleV2], exports: [SidenavComponent, CreateNonShiftModalComponent] });
|
|
626
|
+
WisCommonModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: WisCommonModule, imports: [CommonModule, HttpClientModule, OverlayModule, LoaderModule, DropdownModule, ReactiveFormsModule, DatepickerModuleV2] });
|
|
371
627
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: WisCommonModule, decorators: [{
|
|
372
628
|
type: NgModule,
|
|
373
629
|
args: [{
|
|
374
|
-
declarations: [LoaderComponent, SidenavComponent],
|
|
375
|
-
imports: [CommonModule, OverlayModule, LoaderModule],
|
|
376
|
-
providers: [
|
|
377
|
-
exports: [SidenavComponent]
|
|
630
|
+
declarations: [LoaderComponent, SidenavComponent, CreateNonShiftModalComponent],
|
|
631
|
+
imports: [CommonModule, HttpClientModule, OverlayModule, LoaderModule, DropdownModule, ReactiveFormsModule, DatepickerModuleV2,],
|
|
632
|
+
providers: [],
|
|
633
|
+
exports: [SidenavComponent, CreateNonShiftModalComponent]
|
|
378
634
|
}]
|
|
379
635
|
}] });
|
|
380
636
|
|
|
@@ -388,6 +644,12 @@ class MfeCommunicationService {
|
|
|
388
644
|
this.paymentsDetails = new ReplaySubject(1);
|
|
389
645
|
this.visitorMgmt = new ReplaySubject(1);
|
|
390
646
|
}
|
|
647
|
+
setUserDetails(userDetails) {
|
|
648
|
+
this._etsLoginUser = userDetails;
|
|
649
|
+
}
|
|
650
|
+
getUserDetails() {
|
|
651
|
+
return this._etsLoginUser;
|
|
652
|
+
}
|
|
391
653
|
}
|
|
392
654
|
MfeCommunicationService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: MfeCommunicationService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
393
655
|
MfeCommunicationService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: MfeCommunicationService, providedIn: 'root' });
|
|
@@ -398,6 +660,176 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImpor
|
|
|
398
660
|
}]
|
|
399
661
|
}], ctorParameters: function () { return []; } });
|
|
400
662
|
|
|
663
|
+
class SessionError extends Error {
|
|
664
|
+
}
|
|
665
|
+
class SessionTokenNotFoundError extends SessionError {
|
|
666
|
+
constructor() {
|
|
667
|
+
super('Session token was not found.');
|
|
668
|
+
this.name = 'SessionTokenNotFoundError';
|
|
669
|
+
}
|
|
670
|
+
}
|
|
671
|
+
class SessionTokenExpiredError extends SessionError {
|
|
672
|
+
constructor() {
|
|
673
|
+
super('Session token has expired.');
|
|
674
|
+
this.name = 'SessionTokenExpiredError';
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
class SessionTokenInvalidError extends SessionError {
|
|
678
|
+
constructor() {
|
|
679
|
+
super('Session token could not be decoded.');
|
|
680
|
+
this.name = 'SessionTokenInvalidError';
|
|
681
|
+
}
|
|
682
|
+
}
|
|
683
|
+
class SessionClaimNotFoundError extends SessionError {
|
|
684
|
+
constructor(claim) {
|
|
685
|
+
super(`Session claim "${claim}" was not found in the token.`);
|
|
686
|
+
this.claim = claim;
|
|
687
|
+
this.name = 'SessionClaimNotFoundError';
|
|
688
|
+
}
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
const DEFAULT_SESSION_TOKEN_PREFIX = 'sso-wis-token';
|
|
692
|
+
const DEFAULT_SESSION_TOKEN_FALLBACK_KEY = 'x-wis-token';
|
|
693
|
+
const DEFAULT_VET_TOKEN_PREFIX = 'x-vet-token';
|
|
694
|
+
const LAUNCH_SOURCE_VET = 'VET';
|
|
695
|
+
class SessionService {
|
|
696
|
+
constructor() {
|
|
697
|
+
this.config = {};
|
|
698
|
+
this.cachedToken = null;
|
|
699
|
+
this.cachedState = null;
|
|
700
|
+
}
|
|
701
|
+
init(config) {
|
|
702
|
+
this.config = { ...config };
|
|
703
|
+
this.cachedToken = null;
|
|
704
|
+
this.cachedState = null;
|
|
705
|
+
}
|
|
706
|
+
/**
|
|
707
|
+
* Runs `handlers.next` and returns its result, or `handlers.error(error)` if it throws a `SessionError`.
|
|
708
|
+
* Centralizes the try/catch mechanics; the caller still supplies the actual handling logic.
|
|
709
|
+
*/
|
|
710
|
+
read(handlers) {
|
|
711
|
+
try {
|
|
712
|
+
return handlers.next(this);
|
|
713
|
+
}
|
|
714
|
+
catch (e) {
|
|
715
|
+
if (e instanceof SessionError) {
|
|
716
|
+
return handlers.error(e);
|
|
717
|
+
}
|
|
718
|
+
throw e;
|
|
719
|
+
}
|
|
720
|
+
}
|
|
721
|
+
/**
|
|
722
|
+
* Statement-style variant of `read` for blocks of assignments/side effects with no return value.
|
|
723
|
+
*/
|
|
724
|
+
run(handlers) {
|
|
725
|
+
this.read({
|
|
726
|
+
next: s => { handlers.next(s); return undefined; },
|
|
727
|
+
error: err => { handlers.error(err); return undefined; }
|
|
728
|
+
});
|
|
729
|
+
}
|
|
730
|
+
get isVET() {
|
|
731
|
+
return this.state.isVET;
|
|
732
|
+
}
|
|
733
|
+
get sub() { return this.getClaim('sub'); }
|
|
734
|
+
get empGuid() { return this.getClaim('employeeGUID'); }
|
|
735
|
+
get internalSsoRole() { return this.getClaim('internal_sso_role'); }
|
|
736
|
+
get roles() { return this.getClaim('roles'); }
|
|
737
|
+
get sessionId() { return this.getClaim('sessionId'); }
|
|
738
|
+
get loggedInUser() { return this.getClaim('loggedInUser'); }
|
|
739
|
+
get exp() { return this.getClaim('exp'); }
|
|
740
|
+
get iat() { return this.getClaim('iat'); }
|
|
741
|
+
get businessUnitId() { return this.getClaim('businessUnitId'); }
|
|
742
|
+
get allowedBuids() { return this.getClaim('ALLOWED_BUIDS'); }
|
|
743
|
+
get vetUserEmailId() { return this.getClaim('vetUserEmailId'); }
|
|
744
|
+
get vetUserId() { return this.getClaim('vetUserId'); }
|
|
745
|
+
get source() { return this.getClaim('source'); }
|
|
746
|
+
get roleId() {
|
|
747
|
+
const claims = this.getClaims();
|
|
748
|
+
const raw = claims.internal_sso_role?.trim() || claims.roles?.[0]?.trim();
|
|
749
|
+
if (!raw || !/^\d+$/.test(raw)) {
|
|
750
|
+
throw new SessionClaimNotFoundError('roleId');
|
|
751
|
+
}
|
|
752
|
+
return Number(raw);
|
|
753
|
+
}
|
|
754
|
+
getClaims() {
|
|
755
|
+
const state = this.state;
|
|
756
|
+
if (state.status === 'ok') {
|
|
757
|
+
return state.claims;
|
|
758
|
+
}
|
|
759
|
+
if (state.status === 'not-found') {
|
|
760
|
+
throw new SessionTokenNotFoundError();
|
|
761
|
+
}
|
|
762
|
+
if (state.status === 'expired') {
|
|
763
|
+
throw new SessionTokenExpiredError();
|
|
764
|
+
}
|
|
765
|
+
throw new SessionTokenInvalidError();
|
|
766
|
+
}
|
|
767
|
+
getClaim(key) {
|
|
768
|
+
const claims = this.getClaims();
|
|
769
|
+
const value = claims[key];
|
|
770
|
+
const isEmptyString = typeof value === 'string' && value.trim() === '';
|
|
771
|
+
if (value === undefined || value === null || isEmptyString) {
|
|
772
|
+
throw new SessionClaimNotFoundError(key);
|
|
773
|
+
}
|
|
774
|
+
return (typeof value === 'string' ? value.trim() : value);
|
|
775
|
+
}
|
|
776
|
+
get state() {
|
|
777
|
+
const { token, isVET } = this.findToken();
|
|
778
|
+
if (!this.cachedState || token !== this.cachedToken) {
|
|
779
|
+
this.cachedToken = token;
|
|
780
|
+
this.cachedState = this.build(token, isVET);
|
|
781
|
+
}
|
|
782
|
+
return this.cachedState;
|
|
783
|
+
}
|
|
784
|
+
build(token, isVET) {
|
|
785
|
+
if (!token) {
|
|
786
|
+
return { status: 'not-found', isVET };
|
|
787
|
+
}
|
|
788
|
+
let claims;
|
|
789
|
+
try {
|
|
790
|
+
claims = jwtDecode(token);
|
|
791
|
+
}
|
|
792
|
+
catch {
|
|
793
|
+
return { status: 'invalid', isVET };
|
|
794
|
+
}
|
|
795
|
+
if (this.isExpired(claims)) {
|
|
796
|
+
return { status: 'expired', isVET };
|
|
797
|
+
}
|
|
798
|
+
return { status: 'ok', claims, isVET };
|
|
799
|
+
}
|
|
800
|
+
isExpired(claims) {
|
|
801
|
+
return typeof claims.exp === 'number' && claims.exp * 1000 <= Date.now();
|
|
802
|
+
}
|
|
803
|
+
isVETSource() {
|
|
804
|
+
return getQueryParam('source') === LAUNCH_SOURCE_VET;
|
|
805
|
+
}
|
|
806
|
+
resolveBuid() {
|
|
807
|
+
return getQueryParam('buid') || getCookie('buid') || null;
|
|
808
|
+
}
|
|
809
|
+
findToken() {
|
|
810
|
+
const buid = this.resolveBuid();
|
|
811
|
+
if (this.isVETSource()) {
|
|
812
|
+
const vetKey = this.config.vetTokenCookieKey ?? (buid ? `${DEFAULT_VET_TOKEN_PREFIX}-${buid}` : null);
|
|
813
|
+
const vetToken = (vetKey ? getCookie(vetKey) : '') || '';
|
|
814
|
+
if (vetToken) {
|
|
815
|
+
return { token: vetToken, isVET: true };
|
|
816
|
+
}
|
|
817
|
+
}
|
|
818
|
+
const sessionToken = this.config.sessionTokenCookieKey
|
|
819
|
+
? getCookie(this.config.sessionTokenCookieKey)
|
|
820
|
+
: (buid ? getCookie(`${DEFAULT_SESSION_TOKEN_PREFIX}-${buid}`) : '') || getCookie(DEFAULT_SESSION_TOKEN_FALLBACK_KEY);
|
|
821
|
+
return { token: sessionToken || '', isVET: false };
|
|
822
|
+
}
|
|
823
|
+
}
|
|
824
|
+
SessionService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: SessionService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
825
|
+
SessionService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: SessionService, providedIn: 'root' });
|
|
826
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: SessionService, decorators: [{
|
|
827
|
+
type: Injectable,
|
|
828
|
+
args: [{
|
|
829
|
+
providedIn: 'root'
|
|
830
|
+
}]
|
|
831
|
+
}] });
|
|
832
|
+
|
|
401
833
|
/*
|
|
402
834
|
* Public API Surface of wis-common
|
|
403
835
|
*/
|
|
@@ -406,5 +838,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImpor
|
|
|
406
838
|
* Generated bundle index. Do not edit.
|
|
407
839
|
*/
|
|
408
840
|
|
|
409
|
-
export { AuthInterceptor, AuthModule, AuthService, ConfigurationService, LoaderService, LoggerModule, LoggerService, MfeCommunicationService, SidenavComponent, WisCommonModule, filterNavList, getCookie, getQueryParam, removeCookie, setCookie };
|
|
841
|
+
export { AuthInterceptor, AuthModule, AuthService, ConfigurationService, CreateNonShiftModalComponent, LoaderService, LoggerModule, LoggerService, MfeCommunicationService, SessionClaimNotFoundError, SessionError, SessionService, SessionTokenExpiredError, SessionTokenInvalidError, SessionTokenNotFoundError, SidenavComponent, WisCommonModule, filterNavList, getCookie, getQueryParam, removeCookie, setCookie };
|
|
410
842
|
//# sourceMappingURL=mis-wis-common.mjs.map
|