@trudb/tru-common-lib 0.2.461 → 0.2.462
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/fesm2022/trudb-tru-common-lib.mjs +759 -57
- package/fesm2022/trudb-tru-common-lib.mjs.map +1 -1
- package/lib/classes/tru-data-change-parser.d.ts +1 -3
- package/lib/components/login/services/tru-auth.d.ts +5 -1
- package/lib/components/login/services/tru-server-touch-interceptor.d.ts +14 -0
- package/lib/components/login/services/tru-server-touch-tracker.d.ts +31 -0
- package/lib/components/login/services/tru-session-expiry-monitor.d.ts +37 -0
- package/lib/components/login/services/tru-session-keepalive.d.ts +44 -0
- package/lib/components/login/services/tru-user-activity-tracker.d.ts +14 -0
- package/lib/services/tru-app-environment.d.ts +3 -0
- package/lib/services/tru-connection-hub.d.ts +1 -3
- package/lib/services/tru-ui-notification.d.ts +5 -0
- package/package.json +1 -1
|
@@ -5,11 +5,11 @@ import * as i1$1 from '@angular/common';
|
|
|
5
5
|
import { CommonModule, DatePipe, NgIf, NgClass } from '@angular/common';
|
|
6
6
|
import * as i8 from '@angular/forms';
|
|
7
7
|
import { FormsModule, FormControl, ReactiveFormsModule, FormGroup, Validators } from '@angular/forms';
|
|
8
|
-
import { BehaviorSubject, defer, from, of, Subject, Observable, fromEvent, skip, forkJoin, first, finalize, throwError } from 'rxjs';
|
|
8
|
+
import { BehaviorSubject, defer, from, of, Subject, Observable, merge, fromEvent, Subscription, interval, skip, forkJoin, first, finalize, throwError } from 'rxjs';
|
|
9
9
|
import * as _ from 'underscore';
|
|
10
10
|
import ___default from 'underscore';
|
|
11
|
-
import * as
|
|
12
|
-
import { HttpHeaders, HttpClient, HTTP_INTERCEPTORS } from '@angular/common/http';
|
|
11
|
+
import * as i1$2 from '@angular/common/http';
|
|
12
|
+
import { HttpHeaders, HttpErrorResponse, HttpResponse, HttpClient, HTTP_INTERCEPTORS } from '@angular/common/http';
|
|
13
13
|
import * as i1 from '@angular/material/dialog';
|
|
14
14
|
import { MatDialogModule, MAT_DIALOG_DATA } from '@angular/material/dialog';
|
|
15
15
|
import { A11yModule } from '@angular/cdk/a11y';
|
|
@@ -38,7 +38,7 @@ import { MatDividerModule, MatDivider as MatDivider$1 } from '@angular/material/
|
|
|
38
38
|
import * as i4$1 from '@angular/material/expansion';
|
|
39
39
|
import { MatExpansionModule } from '@angular/material/expansion';
|
|
40
40
|
import { MatGridListModule } from '@angular/material/grid-list';
|
|
41
|
-
import * as i2
|
|
41
|
+
import * as i2 from '@angular/material/icon';
|
|
42
42
|
import { MatIconModule, MatIcon } from '@angular/material/icon';
|
|
43
43
|
import * as i7 from '@angular/material/input';
|
|
44
44
|
import { MatInputModule, MatFormField, MatInput } from '@angular/material/input';
|
|
@@ -49,10 +49,10 @@ import { MatMenuModule, MatMenu, MatMenuItem, MatMenuTrigger } from '@angular/ma
|
|
|
49
49
|
import { MatNativeDateModule, MatRippleModule, MatPseudoCheckbox } from '@angular/material/core';
|
|
50
50
|
import { MatPaginatorModule } from '@angular/material/paginator';
|
|
51
51
|
import { MatProgressBarModule } from '@angular/material/progress-bar';
|
|
52
|
-
import * as i1$
|
|
52
|
+
import * as i1$7 from '@angular/material/progress-spinner';
|
|
53
53
|
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
|
|
54
54
|
import { MatRadioModule } from '@angular/material/radio';
|
|
55
|
-
import * as i1$
|
|
55
|
+
import * as i1$4 from '@angular/material/select';
|
|
56
56
|
import { MatSelectModule, MatSelect, MatFormField as MatFormField$1, MatOption as MatOption$1 } from '@angular/material/select';
|
|
57
57
|
import * as i6 from '@angular/material/sidenav';
|
|
58
58
|
import { MatSidenavModule, MatSidenav } from '@angular/material/sidenav';
|
|
@@ -62,19 +62,19 @@ import { MatSnackBarModule } from '@angular/material/snack-bar';
|
|
|
62
62
|
import { MatSortModule } from '@angular/material/sort';
|
|
63
63
|
import * as i5$1 from '@angular/material/table';
|
|
64
64
|
import { MatTableModule, MatTable } from '@angular/material/table';
|
|
65
|
-
import * as i2$
|
|
65
|
+
import * as i2$2 from '@angular/material/tabs';
|
|
66
66
|
import { MatTabsModule, MatTab, MatTabGroup } from '@angular/material/tabs';
|
|
67
67
|
import { MatToolbarModule } from '@angular/material/toolbar';
|
|
68
68
|
import { MatTooltipModule } from '@angular/material/tooltip';
|
|
69
69
|
import { MatTreeModule } from '@angular/material/tree';
|
|
70
|
-
import * as i2$
|
|
70
|
+
import * as i2$1 from '@angular/cdk/overlay';
|
|
71
71
|
import { OverlayModule } from '@angular/cdk/overlay';
|
|
72
72
|
import { PasswordStrengthMeterComponent } from 'angular-password-strength-meter';
|
|
73
|
-
import * as i1$
|
|
74
|
-
import { tap, catchError } from 'rxjs/operators';
|
|
75
|
-
import * as i1$
|
|
73
|
+
import * as i1$3 from 'ngx-toastr';
|
|
74
|
+
import { throttleTime, tap, catchError } from 'rxjs/operators';
|
|
75
|
+
import * as i1$5 from '@angular/router';
|
|
76
76
|
import { RouterModule } from '@angular/router';
|
|
77
|
-
import * as i1$
|
|
77
|
+
import * as i1$6 from '@angular/platform-browser';
|
|
78
78
|
import { BrowserModule } from '@angular/platform-browser';
|
|
79
79
|
import moment from 'moment/moment';
|
|
80
80
|
import { v4 } from 'uuid';
|
|
@@ -364,6 +364,7 @@ class TruAppEnvironment {
|
|
|
364
364
|
_environmentWarning;
|
|
365
365
|
_loginFormTitle;
|
|
366
366
|
_authType;
|
|
367
|
+
_authenticationTimeoutMinutes;
|
|
367
368
|
_maxRecordCount;
|
|
368
369
|
_isSaving = new BehaviorSubject(false);
|
|
369
370
|
_saveComplete = new BehaviorSubject(null);
|
|
@@ -399,6 +400,7 @@ class TruAppEnvironment {
|
|
|
399
400
|
this._environmentWarning = '';
|
|
400
401
|
this._loginFormTitle = '';
|
|
401
402
|
this._authType = 'jwt';
|
|
403
|
+
this._authenticationTimeoutMinutes = 0;
|
|
402
404
|
this._maxRecordCount = 0;
|
|
403
405
|
this.msgModifierKeyLabel = this.isMac ? 'Cmd' : 'Ctrl';
|
|
404
406
|
this.msgConfirmExitWithChangesPending = 'You have unsaved changes that will be lost.';
|
|
@@ -470,6 +472,12 @@ class TruAppEnvironment {
|
|
|
470
472
|
set authType(type) {
|
|
471
473
|
this._authType = type;
|
|
472
474
|
}
|
|
475
|
+
get authenticationTimeoutMinutes() {
|
|
476
|
+
return this._authenticationTimeoutMinutes;
|
|
477
|
+
}
|
|
478
|
+
set authenticationTimeoutMinutes(minutes) {
|
|
479
|
+
this._authenticationTimeoutMinutes = minutes;
|
|
480
|
+
}
|
|
473
481
|
get isSaving() {
|
|
474
482
|
return this._isSaving.getValue();
|
|
475
483
|
}
|
|
@@ -1002,13 +1010,13 @@ class TruPasswordDialog {
|
|
|
1002
1010
|
ngOnDestroy() {
|
|
1003
1011
|
this.subs.forEach(s => s.unsubscribe());
|
|
1004
1012
|
}
|
|
1005
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: TruPasswordDialog, deps: [{ token: i1.MatDialogRef }, { token:
|
|
1013
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: TruPasswordDialog, deps: [{ token: i1.MatDialogRef }, { token: i1$2.HttpClient }, { token: TruAppEnvironment }, { token: TruUiNotification }, { token: MAT_DIALOG_DATA }], target: i0.ɵɵFactoryTarget.Component });
|
|
1006
1014
|
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.17", type: TruPasswordDialog, isStandalone: true, selector: "tru-password-dialog", ngImport: i0, template: "<div mat-dialog-title class=\"mat-dialog-title\">\r\n <p class=\"tru-password-dialog-title\">{{title}}</p>\r\n <p class=\"tru-password-dialog-username\">for {{username}}</p>\r\n</div>\r\n\r\n<div mat-dialog-content class=\"mat-dialog-content tru-control-container tru-password-dialog\">\r\n <p>{{message}}</p>\r\n\r\n <div class=\"tru-password-dialog-control-wrapper\" *ngIf=\"!admin\">\r\n <mat-label>Current Password</mat-label>\r\n <mat-form-field>\r\n <input #currentInput\r\n matInput\r\n autocomplete=\"off webauthn\"\r\n [formControl]=\"currentPasswordControl\"\r\n [type]=\"showPassword ? 'text' : 'password'\" />\r\n </mat-form-field>\r\n <p class=\"tru-password-dialog-error-msg\" *ngIf=\"errorMsg\">{{errorMsg}}</p>\r\n </div>\r\n <div class=\"tru-password-dialog-control-wrapper\">\r\n <mat-label>New Password</mat-label>\r\n <mat-form-field>\r\n <input #newInput\r\n matInput\r\n autocomplete=\"off webauthn\"\r\n [formControl]=\"newPasswordControl\"\r\n [type]=\"showPassword ? 'text' : 'password'\" />\r\n </mat-form-field>\r\n <password-strength-meter [password]=\"newPasswordControl.value\" (strengthChange)=\"onPasswordStrengthChanged($event)\" />\r\n </div>\r\n <div class=\"tru-password-dialog-control-wrapper\">\r\n <mat-label>Confirm New Password</mat-label>\r\n <mat-form-field>\r\n <input #confirmInput\r\n matInput\r\n autocomplete=\"off webauthn\"\r\n [formControl]=\"confirmNewPasswordControl\"\r\n [type]=\"showPassword ? 'text' : 'password'\" />\r\n </mat-form-field>\r\n </div>\r\n <mat-checkbox [formControl]=\"showPasswordControl\"\r\n (click)=\"onShowPasswordClicked()\"\r\n [labelPosition]=\"'before'\">\r\n Show Password\r\n </mat-checkbox>\r\n</div>\r\n\r\n<div mat-dialog-actions class=\"mat-dialog-actions\">\r\n <button mat-raised-button (click)=\"onDismiss()\">Cancel</button>\r\n <button [disabled]=\"!canSubmit() || busy || errorMsg ? 'disabled' : null\" mat-raised-button color=\"primary\" (click)=\"onConfirm()\">Submit</button>\r\n</div>\r\n", styles: ["", "::ng-deep .mat-mdc-dialog-surface{padding:20px}.mat-mdc-dialog-title:before{content:unset!important;height:unset!important;padding:0 0 10px!important}.mdc-dialog__title{padding:20px 0 10px!important}.mdc-dialog__content{padding:10px 0 15px!important;overflow:hidden}.mat-mdc-dialog-content p{margin-bottom:0;font-size:14px;color:#545454}.mat-mdc-dialog-actions{padding:0!important}.mat-mdc-dialog-actions button{margin-right:10px}.tru-password-dialog .tru-password-dialog-control-wrapper{margin-bottom:20px}.tru-password-dialog-title{font-size:26px}.tru-password-dialog-username{font-size:14px;margin:0;color:var(--mdc-dialog-supporting-text-color, rgba(0, 0, 0, .6))}.tru-password-dialog-error-msg{color:red!important;font-size:11px!important}mat-checkbox{float:right!important}.std-control.edit{margin-bottom:10px;margin-right:10px}::ng-deep .tru-password-dialog .mat-mdc-form-field{display:inline!important}::ng-deep .tru-password-dialog .mat-mdc-form-field-infix{padding:0!important;min-height:unset!important}::ng-deep .tru-password-dialog mat-label{font-size:14px;font-weight:700}::ng-deep .tru-password-dialog input{font-size:12px;padding-left:5px}::ng-deep .tru-password-dialog .mat-mdc-form-field-bottom-align:before{content:unset!important}::ng-deep .tru-password-dialog path{color:#a9a9a9}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i8.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: i8.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i8.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: MaterialModule }, { kind: "component", type: i3.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: i4.MatCheckbox, selector: "mat-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "aria-expanded", "aria-controls", "aria-owns", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { kind: "directive", type: i1.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: i1.MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]", inputs: ["align"] }, { kind: "directive", type: i1.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "directive", type: i7.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "component", type: i7.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i7.MatLabel, selector: "mat-label" }, { kind: "component", type: PasswordStrengthMeterComponent, selector: "password-strength-meter", inputs: ["password", "minPasswordLength", "enableFeedback", "enableAsync", "colors", "numberOfProgressBarItems"], outputs: ["strengthChange"] }] });
|
|
1007
1015
|
}
|
|
1008
1016
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: TruPasswordDialog, decorators: [{
|
|
1009
1017
|
type: Component,
|
|
1010
1018
|
args: [{ selector: 'tru-password-dialog', imports: [CommonModule, FormsModule, ReactiveFormsModule, MaterialModule, PasswordStrengthMeterComponent], template: "<div mat-dialog-title class=\"mat-dialog-title\">\r\n <p class=\"tru-password-dialog-title\">{{title}}</p>\r\n <p class=\"tru-password-dialog-username\">for {{username}}</p>\r\n</div>\r\n\r\n<div mat-dialog-content class=\"mat-dialog-content tru-control-container tru-password-dialog\">\r\n <p>{{message}}</p>\r\n\r\n <div class=\"tru-password-dialog-control-wrapper\" *ngIf=\"!admin\">\r\n <mat-label>Current Password</mat-label>\r\n <mat-form-field>\r\n <input #currentInput\r\n matInput\r\n autocomplete=\"off webauthn\"\r\n [formControl]=\"currentPasswordControl\"\r\n [type]=\"showPassword ? 'text' : 'password'\" />\r\n </mat-form-field>\r\n <p class=\"tru-password-dialog-error-msg\" *ngIf=\"errorMsg\">{{errorMsg}}</p>\r\n </div>\r\n <div class=\"tru-password-dialog-control-wrapper\">\r\n <mat-label>New Password</mat-label>\r\n <mat-form-field>\r\n <input #newInput\r\n matInput\r\n autocomplete=\"off webauthn\"\r\n [formControl]=\"newPasswordControl\"\r\n [type]=\"showPassword ? 'text' : 'password'\" />\r\n </mat-form-field>\r\n <password-strength-meter [password]=\"newPasswordControl.value\" (strengthChange)=\"onPasswordStrengthChanged($event)\" />\r\n </div>\r\n <div class=\"tru-password-dialog-control-wrapper\">\r\n <mat-label>Confirm New Password</mat-label>\r\n <mat-form-field>\r\n <input #confirmInput\r\n matInput\r\n autocomplete=\"off webauthn\"\r\n [formControl]=\"confirmNewPasswordControl\"\r\n [type]=\"showPassword ? 'text' : 'password'\" />\r\n </mat-form-field>\r\n </div>\r\n <mat-checkbox [formControl]=\"showPasswordControl\"\r\n (click)=\"onShowPasswordClicked()\"\r\n [labelPosition]=\"'before'\">\r\n Show Password\r\n </mat-checkbox>\r\n</div>\r\n\r\n<div mat-dialog-actions class=\"mat-dialog-actions\">\r\n <button mat-raised-button (click)=\"onDismiss()\">Cancel</button>\r\n <button [disabled]=\"!canSubmit() || busy || errorMsg ? 'disabled' : null\" mat-raised-button color=\"primary\" (click)=\"onConfirm()\">Submit</button>\r\n</div>\r\n", styles: ["::ng-deep .mat-mdc-dialog-surface{padding:20px}.mat-mdc-dialog-title:before{content:unset!important;height:unset!important;padding:0 0 10px!important}.mdc-dialog__title{padding:20px 0 10px!important}.mdc-dialog__content{padding:10px 0 15px!important;overflow:hidden}.mat-mdc-dialog-content p{margin-bottom:0;font-size:14px;color:#545454}.mat-mdc-dialog-actions{padding:0!important}.mat-mdc-dialog-actions button{margin-right:10px}.tru-password-dialog .tru-password-dialog-control-wrapper{margin-bottom:20px}.tru-password-dialog-title{font-size:26px}.tru-password-dialog-username{font-size:14px;margin:0;color:var(--mdc-dialog-supporting-text-color, rgba(0, 0, 0, .6))}.tru-password-dialog-error-msg{color:red!important;font-size:11px!important}mat-checkbox{float:right!important}.std-control.edit{margin-bottom:10px;margin-right:10px}::ng-deep .tru-password-dialog .mat-mdc-form-field{display:inline!important}::ng-deep .tru-password-dialog .mat-mdc-form-field-infix{padding:0!important;min-height:unset!important}::ng-deep .tru-password-dialog mat-label{font-size:14px;font-weight:700}::ng-deep .tru-password-dialog input{font-size:12px;padding-left:5px}::ng-deep .tru-password-dialog .mat-mdc-form-field-bottom-align:before{content:unset!important}::ng-deep .tru-password-dialog path{color:#a9a9a9}\n"] }]
|
|
1011
|
-
}], ctorParameters: () => [{ type: i1.MatDialogRef }, { type:
|
|
1019
|
+
}], ctorParameters: () => [{ type: i1.MatDialogRef }, { type: i1$2.HttpClient }, { type: TruAppEnvironment }, { type: TruUiNotification }, { type: undefined, decorators: [{
|
|
1012
1020
|
type: Inject,
|
|
1013
1021
|
args: [MAT_DIALOG_DATA]
|
|
1014
1022
|
}] }] });
|
|
@@ -1032,7 +1040,7 @@ class TruAboutDialog {
|
|
|
1032
1040
|
this.dialogRef.close(false);
|
|
1033
1041
|
}
|
|
1034
1042
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: TruAboutDialog, deps: [{ token: i1.MatDialogRef }, { token: MAT_DIALOG_DATA }, { token: TruAppEnvironment }], target: i0.ɵɵFactoryTarget.Component });
|
|
1035
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.17", type: TruAboutDialog, isStandalone: true, selector: "tru-about-dialog", ngImport: i0, template: "<div mat-dialog-title class=\"mat-dialog-title\">\r\n <div class=\"mat-dialog-title-container\">\r\n <mat-icon [svgIcon]=\"'about-icon'\"\r\n title=\"Settings\">\r\n </mat-icon>\r\n About - {{appName}}\r\n </div>\r\n</div>\r\n\r\n<div mat-dialog-content class=\"mat-dialog-content\">\r\n <div class=\"tru-about-description\">\r\n {{appDescription}}\r\n </div>\r\n <p>\r\n Powered By TruDB\r\n </p>\r\n <p>\r\n Copyright {{currentYear}} TruDB LLC. All rights reserved.\r\n </p>\r\n</div>\r\n\r\n<div mat-dialog-actions class=\"mat-dialog-actions\">\r\n <button mat-raised-button (click)=\"onDismiss()\">Close</button>\r\n</div>\r\n", styles: ["::ng-deep .mat-mdc-dialog-surface{padding:20px}.mat-mdc-dialog-title:before{content:unset!important;height:unset!important;padding:0 0 10px!important}.mat-dialog-title-container mat-icon{vertical-align:sub;height:24px;width:24px}.mat-dialog-title-container{display:inline}.mdc-dialog__title{padding:0 0 10px!important}.mdc-dialog__content{padding:10px 0 15px!important}.mat-mdc-dialog-content p{margin-bottom:0;font-size:14px;color:#545454}.mat-mdc-dialog-actions{padding:0!important}.mat-mdc-dialog-actions button{margin-right:10px}.tru-about-description{width:550px;height:200px;padding:5px;margin-bottom:5px;border:1px #cbcbcb solid}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: MaterialModule }, { kind: "component", type: i3.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "directive", type: i1.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: i1.MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]", inputs: ["align"] }, { kind: "directive", type: i1.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "component", type: i2
|
|
1043
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.17", type: TruAboutDialog, isStandalone: true, selector: "tru-about-dialog", ngImport: i0, template: "<div mat-dialog-title class=\"mat-dialog-title\">\r\n <div class=\"mat-dialog-title-container\">\r\n <mat-icon [svgIcon]=\"'about-icon'\"\r\n title=\"Settings\">\r\n </mat-icon>\r\n About - {{appName}}\r\n </div>\r\n</div>\r\n\r\n<div mat-dialog-content class=\"mat-dialog-content\">\r\n <div class=\"tru-about-description\">\r\n {{appDescription}}\r\n </div>\r\n <p>\r\n Powered By TruDB\r\n </p>\r\n <p>\r\n Copyright {{currentYear}} TruDB LLC. All rights reserved.\r\n </p>\r\n</div>\r\n\r\n<div mat-dialog-actions class=\"mat-dialog-actions\">\r\n <button mat-raised-button (click)=\"onDismiss()\">Close</button>\r\n</div>\r\n", styles: ["::ng-deep .mat-mdc-dialog-surface{padding:20px}.mat-mdc-dialog-title:before{content:unset!important;height:unset!important;padding:0 0 10px!important}.mat-dialog-title-container mat-icon{vertical-align:sub;height:24px;width:24px}.mat-dialog-title-container{display:inline}.mdc-dialog__title{padding:0 0 10px!important}.mdc-dialog__content{padding:10px 0 15px!important}.mat-mdc-dialog-content p{margin-bottom:0;font-size:14px;color:#545454}.mat-mdc-dialog-actions{padding:0!important}.mat-mdc-dialog-actions button{margin-right:10px}.tru-about-description{width:550px;height:200px;padding:5px;margin-bottom:5px;border:1px #cbcbcb solid}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: MaterialModule }, { kind: "component", type: i3.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "directive", type: i1.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: i1.MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]", inputs: ["align"] }, { kind: "directive", type: i1.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }] });
|
|
1036
1044
|
}
|
|
1037
1045
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: TruAboutDialog, decorators: [{
|
|
1038
1046
|
type: Component,
|
|
@@ -1050,6 +1058,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
|
|
|
1050
1058
|
class TruUiNotification {
|
|
1051
1059
|
toastr;
|
|
1052
1060
|
dialog;
|
|
1061
|
+
static STICKY_TOAST_CONFIG = {
|
|
1062
|
+
disableTimeOut: true,
|
|
1063
|
+
timeOut: 0,
|
|
1064
|
+
extendedTimeOut: 0,
|
|
1065
|
+
tapToDismiss: true,
|
|
1066
|
+
closeButton: false,
|
|
1067
|
+
};
|
|
1053
1068
|
_toastr;
|
|
1054
1069
|
_dialog;
|
|
1055
1070
|
constructor(toastr, dialog) {
|
|
@@ -1094,6 +1109,19 @@ class TruUiNotification {
|
|
|
1094
1109
|
warning = (message, detail = null) => {
|
|
1095
1110
|
this.showMessage((message) => this._toastr.warning(message), this.log, 'Warning', message, detail);
|
|
1096
1111
|
};
|
|
1112
|
+
warningSticky = (message, detail = null) => {
|
|
1113
|
+
return this.showStickyMessage((formatted) => this._toastr.warning(formatted, undefined, TruUiNotification.STICKY_TOAST_CONFIG), 'Warning', message, detail);
|
|
1114
|
+
};
|
|
1115
|
+
infoSticky = (message, detail = null) => {
|
|
1116
|
+
return this.showStickyMessage((formatted) => this._toastr.info(formatted, undefined, TruUiNotification.STICKY_TOAST_CONFIG), 'Info', message, detail);
|
|
1117
|
+
};
|
|
1118
|
+
clearToast = (toastId) => {
|
|
1119
|
+
if (toastId === null)
|
|
1120
|
+
return;
|
|
1121
|
+
if (!Number.isFinite(toastId) || toastId <= 0)
|
|
1122
|
+
return;
|
|
1123
|
+
this._toastr.clear(toastId);
|
|
1124
|
+
};
|
|
1097
1125
|
log = (message) => {
|
|
1098
1126
|
var console = window.console;
|
|
1099
1127
|
!!console && console.log && console.log.apply && console.log.apply(console, [message]);
|
|
@@ -1164,7 +1192,18 @@ class TruUiNotification {
|
|
|
1164
1192
|
});
|
|
1165
1193
|
});
|
|
1166
1194
|
};
|
|
1167
|
-
|
|
1195
|
+
showStickyMessage(popup, prefix, message, detail = null) {
|
|
1196
|
+
let formatted = prefix + ': ' + message;
|
|
1197
|
+
if (detail) {
|
|
1198
|
+
detail.forEach((detailMsg) => {
|
|
1199
|
+
formatted += '\r\n' + detailMsg;
|
|
1200
|
+
});
|
|
1201
|
+
}
|
|
1202
|
+
const toast = popup(formatted);
|
|
1203
|
+
this.log(formatted);
|
|
1204
|
+
return toast?.toastId ?? null;
|
|
1205
|
+
}
|
|
1206
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: TruUiNotification, deps: [{ token: i1$3.ToastrService }, { token: i1.MatDialog }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
1168
1207
|
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: TruUiNotification, providedIn: 'root' });
|
|
1169
1208
|
}
|
|
1170
1209
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: TruUiNotification, decorators: [{
|
|
@@ -1172,7 +1211,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
|
|
|
1172
1211
|
args: [{
|
|
1173
1212
|
providedIn: 'root',
|
|
1174
1213
|
}]
|
|
1175
|
-
}], ctorParameters: () => [{ type: i1$
|
|
1214
|
+
}], ctorParameters: () => [{ type: i1$3.ToastrService }, { type: i1.MatDialog }] });
|
|
1176
1215
|
|
|
1177
1216
|
class TruUtil {
|
|
1178
1217
|
keyboardMap = ["", "", "", "CANCEL", "", "", "HELP", "", "BACK_SPACE", "TAB", "", "", "CLEAR", "ENTER", "RETURN", "", "SHIFT", "CONTROL", "ALT", "PAUSE", "CAPS_LOCK", "KANA", "EISU", "JUNJA", "FINAL", "HANJA", "", "ESCAPE", "CONVERT", "NONCONVERT", "ACCEPT", "MODECHANGE", "SPACE", "PAGE_UP", "PAGE_DOWN", "END", "HOME", "LEFT", "UP", "RIGHT", "DOWN", "SELECT", "PRINT", "EXECUTE", "PRINTSCREEN", "INSERT", "DELETE", "", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "COLON", "SEMICOLON", "LESS_THAN", "EQUALS", "GREATER_THAN", "QUESTION_MARK", "AT", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "WIN", "", "CONTEXT_MENU", "", "SLEEP", "NUMPAD0", "NUMPAD1", "NUMPAD2", "NUMPAD3", "NUMPAD4", "NUMPAD5", "NUMPAD6", "NUMPAD7", "NUMPAD8", "NUMPAD9", "MULTIPLY", "ADD", "SEPARATOR", "SUBTRACT", "DECIMAL", "DIVIDE", "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "F11", "F12", "F13", "F14", "F15", "F16", "F17", "F18", "F19", "F20", "F21", "F22", "F23", "F24", "", "", "", "", "", "", "", "", "NUM_LOCK", "SCROLL_LOCK", "WIN_OEM_FJ_JISHO", "WIN_OEM_FJ_MASSHOU", "WIN_OEM_FJ_TOUROKU", "WIN_OEM_FJ_LOYA", "WIN_OEM_FJ_ROYA", "", "", "", "", "", "", "", "", "", "CIRCUMFLEX", "EXCLAMATION", "DOUBLE_QUOTE", "HASH", "DOLLAR", "PERCENT", "AMPERSAND", "UNDERSCORE", "OPEN_PAREN", "CLOSE_PAREN", "ASTERISK", "PLUS", "PIPE", "HYPHEN_MINUS", "OPEN_CURLY_BRACKET", "CLOSE_CURLY_BRACKET", "TILDE", "", "", "", "", "VOLUME_MUTE", "VOLUME_DOWN", "VOLUME_UP", "", "", "", "", "COMMA", "", "PERIOD", "SLASH", "BACK_QUOTE", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "OPEN_BRACKET", "BACK_SLASH", "CLOSE_BRACKET", "QUOTE", "", "META", "ALTGR", "", "WIN_ICO_HELP", "WIN_ICO_00", "", "WIN_ICO_CLEAR", "", "", "WIN_OEM_RESET", "WIN_OEM_JUMP", "WIN_OEM_PA1", "WIN_OEM_PA2", "WIN_OEM_PA3", "WIN_OEM_WSCTRL", "WIN_OEM_CUSEL", "WIN_OEM_ATTN", "WIN_OEM_FINISH", "WIN_OEM_COPY", "WIN_OEM_AUTO", "WIN_OEM_ENLW", "WIN_OEM_BACKTAB", "ATTN", "CRSEL", "EXSEL", "EREOF", "PLAY", "ZOOM", "", "PA1", "WIN_OEM_CLEAR", ""];
|
|
@@ -1984,12 +2023,12 @@ class TruEntityAccessor {
|
|
|
1984
2023
|
}
|
|
1985
2024
|
});
|
|
1986
2025
|
};
|
|
1987
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: TruEntityAccessor, deps: [{ token:
|
|
2026
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: TruEntityAccessor, deps: [{ token: i1$2.HttpClient }, { token: TruAppEnvironment }, { token: TruUiNotification }, { token: TruTextManager }, { token: TruUser }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
1988
2027
|
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: TruEntityAccessor });
|
|
1989
2028
|
}
|
|
1990
2029
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: TruEntityAccessor, decorators: [{
|
|
1991
2030
|
type: Injectable
|
|
1992
|
-
}], ctorParameters: () => [{ type:
|
|
2031
|
+
}], ctorParameters: () => [{ type: i1$2.HttpClient }, { type: TruAppEnvironment }, { type: TruUiNotification }, { type: TruTextManager }, { type: TruUser }] });
|
|
1993
2032
|
|
|
1994
2033
|
class TruDataContext {
|
|
1995
2034
|
breezeContextFactory;
|
|
@@ -2891,13 +2930,13 @@ class TruIframeView extends TruSearchViewBase {
|
|
|
2891
2930
|
});
|
|
2892
2931
|
this.subs.push(sub);
|
|
2893
2932
|
}
|
|
2894
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: TruIframeView, deps: [{ token: TruDesktopManager }, { token: TruWindowEventHandler }, { token:
|
|
2933
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: TruIframeView, deps: [{ token: TruDesktopManager }, { token: TruWindowEventHandler }, { token: i1$2.HttpClient }, { token: TruUiNotification }], target: i0.ɵɵFactoryTarget.Component });
|
|
2895
2934
|
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.17", type: TruIframeView, isStandalone: true, selector: "tru-iframe-view", inputs: { view: "view" }, viewQueries: [{ propertyName: "iframe", first: true, predicate: ["iframe"], descendants: true, static: true }], usesInheritance: true, ngImport: i0, template: "<div>\n <div class=\"view-busy-overlay\" *ngIf=\"isBusy\"></div>\n <iframe #iframe class=\"iframe-view-frame\" (load)=\"onLoad(iframe)\"></iframe>\n</div>\n\n", styles: [".iframe-view-frame{position:absolute;inset:0;border-style:none;height:100%;width:100%}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] });
|
|
2896
2935
|
}
|
|
2897
2936
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: TruIframeView, decorators: [{
|
|
2898
2937
|
type: Component,
|
|
2899
2938
|
args: [{ selector: 'tru-iframe-view', imports: [CommonModule], template: "<div>\n <div class=\"view-busy-overlay\" *ngIf=\"isBusy\"></div>\n <iframe #iframe class=\"iframe-view-frame\" (load)=\"onLoad(iframe)\"></iframe>\n</div>\n\n", styles: [".iframe-view-frame{position:absolute;inset:0;border-style:none;height:100%;width:100%}\n"] }]
|
|
2900
|
-
}], ctorParameters: () => [{ type: TruDesktopManager }, { type: TruWindowEventHandler }, { type:
|
|
2939
|
+
}], ctorParameters: () => [{ type: TruDesktopManager }, { type: TruWindowEventHandler }, { type: i1$2.HttpClient }, { type: TruUiNotification }], propDecorators: { view: [{
|
|
2901
2940
|
type: Input
|
|
2902
2941
|
}], iframe: [{
|
|
2903
2942
|
type: ViewChild,
|
|
@@ -3073,7 +3112,7 @@ class TruMatSelectPanel {
|
|
|
3073
3112
|
ngOnDestroy() {
|
|
3074
3113
|
this.removeListeners();
|
|
3075
3114
|
}
|
|
3076
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: TruMatSelectPanel, deps: [{ token: i0.Renderer2 }, { token: i1$
|
|
3115
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: TruMatSelectPanel, deps: [{ token: i0.Renderer2 }, { token: i1$4.MatSelect }, { token: TruUtil }], target: i0.ɵɵFactoryTarget.Directive });
|
|
3077
3116
|
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.2.17", type: TruMatSelectPanel, isStandalone: true, selector: "[tru-mat-select-panel]", ngImport: i0 });
|
|
3078
3117
|
}
|
|
3079
3118
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: TruMatSelectPanel, decorators: [{
|
|
@@ -3081,7 +3120,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
|
|
|
3081
3120
|
args: [{
|
|
3082
3121
|
selector: '[tru-mat-select-panel]'
|
|
3083
3122
|
}]
|
|
3084
|
-
}], ctorParameters: () => [{ type: i0.Renderer2 }, { type: i1$
|
|
3123
|
+
}], ctorParameters: () => [{ type: i0.Renderer2 }, { type: i1$4.MatSelect }, { type: TruUtil }] });
|
|
3085
3124
|
|
|
3086
3125
|
class TruOpenOnStart {
|
|
3087
3126
|
transform(openOnStart, args) {
|
|
@@ -3372,21 +3411,633 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
|
|
|
3372
3411
|
}]
|
|
3373
3412
|
}] });
|
|
3374
3413
|
|
|
3414
|
+
class TruServerTouchTracker {
|
|
3415
|
+
appEnvironment;
|
|
3416
|
+
static STORAGE_PREFIX = 'trudb:sessionKeepalive:';
|
|
3417
|
+
lastServerTouchAtMs = 0;
|
|
3418
|
+
lastSessionRenewedAtMs = 0;
|
|
3419
|
+
serverTouchSubject = new BehaviorSubject(0);
|
|
3420
|
+
sessionRenewedSubject = new BehaviorSubject(0);
|
|
3421
|
+
constructor(appEnvironment) {
|
|
3422
|
+
this.appEnvironment = appEnvironment;
|
|
3423
|
+
this.setupCrossTabStorageSync();
|
|
3424
|
+
}
|
|
3425
|
+
get serverTouch$() {
|
|
3426
|
+
return this.serverTouchSubject.asObservable();
|
|
3427
|
+
}
|
|
3428
|
+
get sessionRenewed$() {
|
|
3429
|
+
return this.sessionRenewedSubject.asObservable();
|
|
3430
|
+
}
|
|
3431
|
+
getLastServerTouchAtMs() {
|
|
3432
|
+
const key = this.getStorageKey('lastServerTouchAtMs');
|
|
3433
|
+
const shared = this.readNumber(key);
|
|
3434
|
+
return Math.max(this.lastServerTouchAtMs, shared);
|
|
3435
|
+
}
|
|
3436
|
+
getLastSessionRenewedAtMs() {
|
|
3437
|
+
const key = this.getStorageKey('lastSessionRenewedAtMs');
|
|
3438
|
+
const shared = this.readNumber(key);
|
|
3439
|
+
return Math.max(this.lastSessionRenewedAtMs, shared);
|
|
3440
|
+
}
|
|
3441
|
+
recordServerTouch(atMs = Date.now()) {
|
|
3442
|
+
if (!Number.isFinite(atMs) || atMs <= 0)
|
|
3443
|
+
return;
|
|
3444
|
+
if (atMs > this.lastServerTouchAtMs) {
|
|
3445
|
+
this.lastServerTouchAtMs = atMs;
|
|
3446
|
+
this.serverTouchSubject.next(atMs);
|
|
3447
|
+
}
|
|
3448
|
+
const key = this.getStorageKey('lastServerTouchAtMs');
|
|
3449
|
+
const shared = this.readNumber(key);
|
|
3450
|
+
if (atMs > shared) {
|
|
3451
|
+
this.writeNumber(key, atMs);
|
|
3452
|
+
}
|
|
3453
|
+
this.maybeRecordSessionRenewal(atMs);
|
|
3454
|
+
}
|
|
3455
|
+
tryAcquireKeepaliveLock(ownerId, ttlMs, nowMs = Date.now()) {
|
|
3456
|
+
if (!ownerId)
|
|
3457
|
+
return false;
|
|
3458
|
+
if (!Number.isFinite(ttlMs) || ttlMs <= 0)
|
|
3459
|
+
return true;
|
|
3460
|
+
try {
|
|
3461
|
+
if (typeof localStorage === 'undefined')
|
|
3462
|
+
return true;
|
|
3463
|
+
const key = this.getStorageKey('keepaliveLock');
|
|
3464
|
+
const existing = this.readLock(key);
|
|
3465
|
+
if (existing !== null &&
|
|
3466
|
+
existing.expiresAtMs > nowMs &&
|
|
3467
|
+
existing.ownerId !== ownerId)
|
|
3468
|
+
return false;
|
|
3469
|
+
const lock = {
|
|
3470
|
+
ownerId,
|
|
3471
|
+
expiresAtMs: nowMs + ttlMs,
|
|
3472
|
+
};
|
|
3473
|
+
localStorage.setItem(key, JSON.stringify(lock));
|
|
3474
|
+
const confirmed = this.readLock(key);
|
|
3475
|
+
return confirmed !== null && confirmed.ownerId === ownerId;
|
|
3476
|
+
}
|
|
3477
|
+
catch {
|
|
3478
|
+
return true;
|
|
3479
|
+
}
|
|
3480
|
+
}
|
|
3481
|
+
releaseKeepaliveLock(ownerId) {
|
|
3482
|
+
if (!ownerId)
|
|
3483
|
+
return;
|
|
3484
|
+
try {
|
|
3485
|
+
if (typeof localStorage === 'undefined')
|
|
3486
|
+
return;
|
|
3487
|
+
const key = this.getStorageKey('keepaliveLock');
|
|
3488
|
+
const existing = this.readLock(key);
|
|
3489
|
+
if (existing !== null && existing.ownerId === ownerId) {
|
|
3490
|
+
localStorage.removeItem(key);
|
|
3491
|
+
}
|
|
3492
|
+
}
|
|
3493
|
+
catch {
|
|
3494
|
+
// ignore
|
|
3495
|
+
}
|
|
3496
|
+
}
|
|
3497
|
+
maybeRecordSessionRenewal(atMs) {
|
|
3498
|
+
const timeoutMs = this.getTimeoutMs();
|
|
3499
|
+
if (timeoutMs === null)
|
|
3500
|
+
return;
|
|
3501
|
+
const lastRenewedAtMs = this.getLastSessionRenewedAtMs();
|
|
3502
|
+
const shouldInitialize = lastRenewedAtMs === 0;
|
|
3503
|
+
const elapsedSinceRenewalMs = atMs - lastRenewedAtMs;
|
|
3504
|
+
const shouldRenew = !shouldInitialize &&
|
|
3505
|
+
Number.isFinite(elapsedSinceRenewalMs) &&
|
|
3506
|
+
elapsedSinceRenewalMs > timeoutMs / 2;
|
|
3507
|
+
if (shouldInitialize || shouldRenew)
|
|
3508
|
+
this.recordSessionRenewed(atMs);
|
|
3509
|
+
}
|
|
3510
|
+
recordSessionRenewed(atMs) {
|
|
3511
|
+
if (!Number.isFinite(atMs) || atMs <= 0)
|
|
3512
|
+
return;
|
|
3513
|
+
if (atMs > this.lastSessionRenewedAtMs) {
|
|
3514
|
+
this.lastSessionRenewedAtMs = atMs;
|
|
3515
|
+
this.sessionRenewedSubject.next(atMs);
|
|
3516
|
+
}
|
|
3517
|
+
const key = this.getStorageKey('lastSessionRenewedAtMs');
|
|
3518
|
+
const shared = this.readNumber(key);
|
|
3519
|
+
if (atMs > shared) {
|
|
3520
|
+
this.writeNumber(key, atMs);
|
|
3521
|
+
}
|
|
3522
|
+
}
|
|
3523
|
+
getStorageKey(name) {
|
|
3524
|
+
const appScope = this.getAppScope();
|
|
3525
|
+
return `${TruServerTouchTracker.STORAGE_PREFIX}${encodeURIComponent(appScope)}:${name}`;
|
|
3526
|
+
}
|
|
3527
|
+
getStorageKeyPrefix() {
|
|
3528
|
+
const appScope = this.getAppScope();
|
|
3529
|
+
return `${TruServerTouchTracker.STORAGE_PREFIX}${encodeURIComponent(appScope)}:`;
|
|
3530
|
+
}
|
|
3531
|
+
readLock(key) {
|
|
3532
|
+
try {
|
|
3533
|
+
if (typeof localStorage === 'undefined')
|
|
3534
|
+
return null;
|
|
3535
|
+
const raw = localStorage.getItem(key);
|
|
3536
|
+
if (raw === null)
|
|
3537
|
+
return null;
|
|
3538
|
+
const parsed = JSON.parse(raw);
|
|
3539
|
+
if (typeof parsed.ownerId !== 'string' ||
|
|
3540
|
+
!Number.isFinite(parsed.expiresAtMs))
|
|
3541
|
+
return null;
|
|
3542
|
+
return {
|
|
3543
|
+
ownerId: parsed.ownerId,
|
|
3544
|
+
expiresAtMs: Number(parsed.expiresAtMs),
|
|
3545
|
+
};
|
|
3546
|
+
}
|
|
3547
|
+
catch {
|
|
3548
|
+
return null;
|
|
3549
|
+
}
|
|
3550
|
+
}
|
|
3551
|
+
getAppScope() {
|
|
3552
|
+
if (this.appEnvironment.appUri)
|
|
3553
|
+
return this.appEnvironment.appUri;
|
|
3554
|
+
if (typeof window === 'undefined')
|
|
3555
|
+
return 'unknown';
|
|
3556
|
+
return window.location.origin;
|
|
3557
|
+
}
|
|
3558
|
+
getTimeoutMs() {
|
|
3559
|
+
const timeoutMinutes = this.appEnvironment.authenticationTimeoutMinutes;
|
|
3560
|
+
if (!Number.isFinite(timeoutMinutes) || timeoutMinutes <= 0)
|
|
3561
|
+
return null;
|
|
3562
|
+
return timeoutMinutes * 60_000;
|
|
3563
|
+
}
|
|
3564
|
+
setupCrossTabStorageSync() {
|
|
3565
|
+
try {
|
|
3566
|
+
if (typeof window === 'undefined')
|
|
3567
|
+
return;
|
|
3568
|
+
if (typeof window.addEventListener !== 'function')
|
|
3569
|
+
return;
|
|
3570
|
+
window.addEventListener('storage', (event) => {
|
|
3571
|
+
if (!event.key)
|
|
3572
|
+
return;
|
|
3573
|
+
const prefix = this.getStorageKeyPrefix();
|
|
3574
|
+
if (!event.key.startsWith(prefix))
|
|
3575
|
+
return;
|
|
3576
|
+
if (event.key.endsWith(':lastServerTouchAtMs')) {
|
|
3577
|
+
const atMs = Number(event.newValue);
|
|
3578
|
+
if (Number.isFinite(atMs) && atMs > this.lastServerTouchAtMs) {
|
|
3579
|
+
this.lastServerTouchAtMs = atMs;
|
|
3580
|
+
this.serverTouchSubject.next(atMs);
|
|
3581
|
+
}
|
|
3582
|
+
return;
|
|
3583
|
+
}
|
|
3584
|
+
if (event.key.endsWith(':lastSessionRenewedAtMs')) {
|
|
3585
|
+
const atMs = Number(event.newValue);
|
|
3586
|
+
if (Number.isFinite(atMs) && atMs > this.lastSessionRenewedAtMs) {
|
|
3587
|
+
this.lastSessionRenewedAtMs = atMs;
|
|
3588
|
+
this.sessionRenewedSubject.next(atMs);
|
|
3589
|
+
}
|
|
3590
|
+
}
|
|
3591
|
+
});
|
|
3592
|
+
}
|
|
3593
|
+
catch {
|
|
3594
|
+
// ignore
|
|
3595
|
+
}
|
|
3596
|
+
}
|
|
3597
|
+
readNumber(key) {
|
|
3598
|
+
try {
|
|
3599
|
+
if (typeof localStorage === 'undefined')
|
|
3600
|
+
return 0;
|
|
3601
|
+
const raw = localStorage.getItem(key);
|
|
3602
|
+
if (raw === null)
|
|
3603
|
+
return 0;
|
|
3604
|
+
const value = Number(raw);
|
|
3605
|
+
return Number.isFinite(value) && value > 0 ? value : 0;
|
|
3606
|
+
}
|
|
3607
|
+
catch {
|
|
3608
|
+
return 0;
|
|
3609
|
+
}
|
|
3610
|
+
}
|
|
3611
|
+
writeNumber(key, value) {
|
|
3612
|
+
try {
|
|
3613
|
+
if (typeof localStorage === 'undefined')
|
|
3614
|
+
return;
|
|
3615
|
+
localStorage.setItem(key, String(value));
|
|
3616
|
+
}
|
|
3617
|
+
catch {
|
|
3618
|
+
// ignore (storage may be disabled)
|
|
3619
|
+
}
|
|
3620
|
+
}
|
|
3621
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: TruServerTouchTracker, deps: [{ token: TruAppEnvironment }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
3622
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: TruServerTouchTracker, providedIn: 'root' });
|
|
3623
|
+
}
|
|
3624
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: TruServerTouchTracker, decorators: [{
|
|
3625
|
+
type: Injectable,
|
|
3626
|
+
args: [{
|
|
3627
|
+
providedIn: 'root',
|
|
3628
|
+
}]
|
|
3629
|
+
}], ctorParameters: () => [{ type: TruAppEnvironment }] });
|
|
3630
|
+
|
|
3631
|
+
class TruUserActivityTracker {
|
|
3632
|
+
ngZone;
|
|
3633
|
+
static THROTTLE_MS = 1_000;
|
|
3634
|
+
lastActivityAtMs = 0;
|
|
3635
|
+
activitySubject = new BehaviorSubject(0);
|
|
3636
|
+
constructor(ngZone) {
|
|
3637
|
+
this.ngZone = ngZone;
|
|
3638
|
+
this.ngZone.runOutsideAngular(() => {
|
|
3639
|
+
if (typeof window === 'undefined')
|
|
3640
|
+
return;
|
|
3641
|
+
const activity$ = merge(fromEvent(window, 'keydown'), fromEvent(window, 'mousedown'), fromEvent(window, 'click'), fromEvent(window, 'mousemove'), fromEvent(window, 'wheel'), fromEvent(window, 'scroll'), fromEvent(window, 'touchstart')).pipe(throttleTime(TruUserActivityTracker.THROTTLE_MS, undefined, {
|
|
3642
|
+
leading: true,
|
|
3643
|
+
trailing: true,
|
|
3644
|
+
}));
|
|
3645
|
+
activity$.subscribe(() => {
|
|
3646
|
+
const now = Date.now();
|
|
3647
|
+
this.lastActivityAtMs = now;
|
|
3648
|
+
this.activitySubject.next(now);
|
|
3649
|
+
});
|
|
3650
|
+
});
|
|
3651
|
+
}
|
|
3652
|
+
get lastActivity$() {
|
|
3653
|
+
return this.activitySubject.asObservable();
|
|
3654
|
+
}
|
|
3655
|
+
getLastActivityAtMs() {
|
|
3656
|
+
return this.lastActivityAtMs;
|
|
3657
|
+
}
|
|
3658
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: TruUserActivityTracker, deps: [{ token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
3659
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: TruUserActivityTracker, providedIn: 'root' });
|
|
3660
|
+
}
|
|
3661
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: TruUserActivityTracker, decorators: [{
|
|
3662
|
+
type: Injectable,
|
|
3663
|
+
args: [{
|
|
3664
|
+
providedIn: 'root',
|
|
3665
|
+
}]
|
|
3666
|
+
}], ctorParameters: () => [{ type: i0.NgZone }] });
|
|
3667
|
+
|
|
3668
|
+
class TruSessionKeepalive {
|
|
3669
|
+
http;
|
|
3670
|
+
appEnvironment;
|
|
3671
|
+
serverTouchTracker;
|
|
3672
|
+
activityTracker;
|
|
3673
|
+
ngZone;
|
|
3674
|
+
static ACTIVITY_WINDOW_CAP_MS = 5 * 60_000;
|
|
3675
|
+
static TICK_MS = 15_000;
|
|
3676
|
+
static KEEPALIVE_AFTER_FRACTION = 0.6;
|
|
3677
|
+
static MAX_JITTER_MS = 30_000;
|
|
3678
|
+
static KEEPALIVE_LOCK_TTL_MS = 15_000;
|
|
3679
|
+
static INITIAL_RETRY_DELAY_MS = 30_000;
|
|
3680
|
+
static MAX_RETRY_DELAY_MS = 5 * 60_000;
|
|
3681
|
+
isRunning = false;
|
|
3682
|
+
stop$ = new Subject();
|
|
3683
|
+
subscriptions = new Subscription();
|
|
3684
|
+
tabId = this.generateTabId();
|
|
3685
|
+
keepaliveLockHeld = false;
|
|
3686
|
+
lastSessionRenewedAtMs = 0;
|
|
3687
|
+
nextAttemptAtMs = 0;
|
|
3688
|
+
consecutiveFailures = 0;
|
|
3689
|
+
requestInFlight = false;
|
|
3690
|
+
constructor(http, appEnvironment, serverTouchTracker, activityTracker, ngZone) {
|
|
3691
|
+
this.http = http;
|
|
3692
|
+
this.appEnvironment = appEnvironment;
|
|
3693
|
+
this.serverTouchTracker = serverTouchTracker;
|
|
3694
|
+
this.activityTracker = activityTracker;
|
|
3695
|
+
this.ngZone = ngZone;
|
|
3696
|
+
}
|
|
3697
|
+
start() {
|
|
3698
|
+
if (this.isRunning)
|
|
3699
|
+
return;
|
|
3700
|
+
if (this.appEnvironment.authType !== 'session')
|
|
3701
|
+
return;
|
|
3702
|
+
const timeoutMinutes = this.appEnvironment.authenticationTimeoutMinutes;
|
|
3703
|
+
const timeoutMs = this.getTimeoutMs(timeoutMinutes);
|
|
3704
|
+
if (timeoutMs === null)
|
|
3705
|
+
return;
|
|
3706
|
+
this.isRunning = true;
|
|
3707
|
+
const startedAt = Date.now();
|
|
3708
|
+
this.lastSessionRenewedAtMs =
|
|
3709
|
+
this.serverTouchTracker.getLastSessionRenewedAtMs() || startedAt;
|
|
3710
|
+
this.serverTouchTracker.recordServerTouch(this.lastSessionRenewedAtMs);
|
|
3711
|
+
this.nextAttemptAtMs =
|
|
3712
|
+
this.lastSessionRenewedAtMs + this.getKeepaliveAfterMs(timeoutMinutes);
|
|
3713
|
+
this.ngZone.runOutsideAngular(() => {
|
|
3714
|
+
this.scheduleTicks(timeoutMs, timeoutMinutes);
|
|
3715
|
+
});
|
|
3716
|
+
}
|
|
3717
|
+
stop() {
|
|
3718
|
+
if (!this.isRunning)
|
|
3719
|
+
return;
|
|
3720
|
+
this.isRunning = false;
|
|
3721
|
+
this.releaseKeepaliveLock();
|
|
3722
|
+
this.stop$.next();
|
|
3723
|
+
this.subscriptions.unsubscribe();
|
|
3724
|
+
this.subscriptions = new Subscription();
|
|
3725
|
+
this.lastSessionRenewedAtMs = 0;
|
|
3726
|
+
this.nextAttemptAtMs = 0;
|
|
3727
|
+
this.consecutiveFailures = 0;
|
|
3728
|
+
this.requestInFlight = false;
|
|
3729
|
+
}
|
|
3730
|
+
scheduleTicks(timeoutMs, timeoutMinutes) {
|
|
3731
|
+
const activityWindowMs = this.getActivityWindowMs(timeoutMs);
|
|
3732
|
+
this.subscriptions.add(interval(TruSessionKeepalive.TICK_MS).subscribe(() => {
|
|
3733
|
+
if (!this.isRunning)
|
|
3734
|
+
return;
|
|
3735
|
+
if (this.appEnvironment.authType !== 'session')
|
|
3736
|
+
return;
|
|
3737
|
+
const now = Date.now();
|
|
3738
|
+
this.syncSessionRenewal(timeoutMinutes);
|
|
3739
|
+
const lastActivityAtMs = this.activityTracker.getLastActivityAtMs();
|
|
3740
|
+
const isActive = lastActivityAtMs !== 0 &&
|
|
3741
|
+
now - lastActivityAtMs <= activityWindowMs;
|
|
3742
|
+
if (!isActive)
|
|
3743
|
+
return;
|
|
3744
|
+
if (this.requestInFlight)
|
|
3745
|
+
return;
|
|
3746
|
+
if (now < this.nextAttemptAtMs)
|
|
3747
|
+
return;
|
|
3748
|
+
if (!this.tryAcquireKeepaliveLock(now))
|
|
3749
|
+
return;
|
|
3750
|
+
this.ping(timeoutMs, timeoutMinutes, now);
|
|
3751
|
+
}));
|
|
3752
|
+
}
|
|
3753
|
+
ping(timeoutMs, timeoutMinutes, now) {
|
|
3754
|
+
this.requestInFlight = true;
|
|
3755
|
+
const keepaliveUrl = `${this.appEnvironment.appUri}${TRU_AUTH_CONFIG.authUrl}/keepalive`;
|
|
3756
|
+
this.subscriptions.add(this.http.post(keepaliveUrl, null).subscribe({
|
|
3757
|
+
next: () => {
|
|
3758
|
+
const touchAt = Date.now();
|
|
3759
|
+
this.serverTouchTracker.recordServerTouch(touchAt);
|
|
3760
|
+
this.lastSessionRenewedAtMs =
|
|
3761
|
+
this.serverTouchTracker.getLastSessionRenewedAtMs();
|
|
3762
|
+
this.consecutiveFailures = 0;
|
|
3763
|
+
this.requestInFlight = false;
|
|
3764
|
+
this.releaseKeepaliveLock();
|
|
3765
|
+
this.nextAttemptAtMs =
|
|
3766
|
+
this.lastSessionRenewedAtMs +
|
|
3767
|
+
this.getKeepaliveAfterMs(timeoutMinutes);
|
|
3768
|
+
},
|
|
3769
|
+
error: (error) => {
|
|
3770
|
+
const errorAt = Date.now();
|
|
3771
|
+
this.requestInFlight = false;
|
|
3772
|
+
this.releaseKeepaliveLock();
|
|
3773
|
+
const status = error instanceof HttpErrorResponse
|
|
3774
|
+
? error.status
|
|
3775
|
+
: error?.status;
|
|
3776
|
+
if (status === 401) {
|
|
3777
|
+
this.stop();
|
|
3778
|
+
return;
|
|
3779
|
+
}
|
|
3780
|
+
this.consecutiveFailures += 1;
|
|
3781
|
+
const lastRenewedAtMs = Math.max(this.lastSessionRenewedAtMs, this.serverTouchTracker.getLastSessionRenewedAtMs());
|
|
3782
|
+
const expiresAtMs = lastRenewedAtMs + timeoutMs;
|
|
3783
|
+
const timeUntilExpiryMs = expiresAtMs - errorAt;
|
|
3784
|
+
const retryDelayMs = this.getRetryDelayMs(timeUntilExpiryMs);
|
|
3785
|
+
this.nextAttemptAtMs = errorAt + retryDelayMs;
|
|
3786
|
+
},
|
|
3787
|
+
}));
|
|
3788
|
+
}
|
|
3789
|
+
tryAcquireKeepaliveLock(now) {
|
|
3790
|
+
const acquired = this.serverTouchTracker.tryAcquireKeepaliveLock(this.tabId, TruSessionKeepalive.KEEPALIVE_LOCK_TTL_MS, now);
|
|
3791
|
+
this.keepaliveLockHeld = acquired;
|
|
3792
|
+
return acquired;
|
|
3793
|
+
}
|
|
3794
|
+
releaseKeepaliveLock() {
|
|
3795
|
+
if (!this.keepaliveLockHeld)
|
|
3796
|
+
return;
|
|
3797
|
+
this.keepaliveLockHeld = false;
|
|
3798
|
+
this.serverTouchTracker.releaseKeepaliveLock(this.tabId);
|
|
3799
|
+
}
|
|
3800
|
+
generateTabId() {
|
|
3801
|
+
try {
|
|
3802
|
+
if (typeof crypto !== 'undefined' && 'randomUUID' in crypto)
|
|
3803
|
+
return crypto.randomUUID();
|
|
3804
|
+
}
|
|
3805
|
+
catch {
|
|
3806
|
+
// ignore
|
|
3807
|
+
}
|
|
3808
|
+
return `${Math.random().toString(16).slice(2)}${Date.now().toString(16)}`;
|
|
3809
|
+
}
|
|
3810
|
+
syncSessionRenewal(timeoutMinutes) {
|
|
3811
|
+
const sharedRenewedAtMs = this.serverTouchTracker.getLastSessionRenewedAtMs();
|
|
3812
|
+
if (!Number.isFinite(sharedRenewedAtMs) || sharedRenewedAtMs <= 0)
|
|
3813
|
+
return;
|
|
3814
|
+
if (sharedRenewedAtMs <= this.lastSessionRenewedAtMs)
|
|
3815
|
+
return;
|
|
3816
|
+
this.lastSessionRenewedAtMs = sharedRenewedAtMs;
|
|
3817
|
+
this.consecutiveFailures = 0;
|
|
3818
|
+
this.nextAttemptAtMs =
|
|
3819
|
+
sharedRenewedAtMs + this.getKeepaliveAfterMs(timeoutMinutes);
|
|
3820
|
+
}
|
|
3821
|
+
getKeepaliveAfterMs(timeoutMinutes) {
|
|
3822
|
+
const timeoutMs = timeoutMinutes * 60_000;
|
|
3823
|
+
const keepaliveAfterMs = Math.ceil(timeoutMs * TruSessionKeepalive.KEEPALIVE_AFTER_FRACTION);
|
|
3824
|
+
const jitterMs = Math.floor(Math.random() * TruSessionKeepalive.MAX_JITTER_MS);
|
|
3825
|
+
return keepaliveAfterMs + jitterMs;
|
|
3826
|
+
}
|
|
3827
|
+
getActivityWindowMs(timeoutMs) {
|
|
3828
|
+
if (!Number.isFinite(timeoutMs) || timeoutMs <= 0)
|
|
3829
|
+
return TruSessionKeepalive.ACTIVITY_WINDOW_CAP_MS;
|
|
3830
|
+
return Math.min(TruSessionKeepalive.ACTIVITY_WINDOW_CAP_MS, Math.floor(timeoutMs / 2));
|
|
3831
|
+
}
|
|
3832
|
+
getTimeoutMs(timeoutMinutes) {
|
|
3833
|
+
if (!Number.isFinite(timeoutMinutes) || timeoutMinutes <= 1)
|
|
3834
|
+
return null;
|
|
3835
|
+
return timeoutMinutes * 60_000;
|
|
3836
|
+
}
|
|
3837
|
+
getRetryDelayMs(timeUntilExpiryMs) {
|
|
3838
|
+
const exponentialBackoffMs = Math.min(TruSessionKeepalive.MAX_RETRY_DELAY_MS, TruSessionKeepalive.INITIAL_RETRY_DELAY_MS * 2 ** (this.consecutiveFailures - 1));
|
|
3839
|
+
if (!Number.isFinite(timeUntilExpiryMs) || timeUntilExpiryMs <= 0)
|
|
3840
|
+
return exponentialBackoffMs;
|
|
3841
|
+
const cappedByExpiryMs = Math.max(1_000, Math.floor(timeUntilExpiryMs / 2));
|
|
3842
|
+
return Math.min(exponentialBackoffMs, cappedByExpiryMs);
|
|
3843
|
+
}
|
|
3844
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: TruSessionKeepalive, deps: [{ token: i1$2.HttpClient }, { token: TruAppEnvironment }, { token: TruServerTouchTracker }, { token: TruUserActivityTracker }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
3845
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: TruSessionKeepalive, providedIn: 'root' });
|
|
3846
|
+
}
|
|
3847
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: TruSessionKeepalive, decorators: [{
|
|
3848
|
+
type: Injectable,
|
|
3849
|
+
args: [{
|
|
3850
|
+
providedIn: 'root',
|
|
3851
|
+
}]
|
|
3852
|
+
}], ctorParameters: () => [{ type: i1$2.HttpClient }, { type: TruAppEnvironment }, { type: TruServerTouchTracker }, { type: TruUserActivityTracker }, { type: i0.NgZone }] });
|
|
3853
|
+
|
|
3854
|
+
class TruSessionExpiryMonitor {
|
|
3855
|
+
appEnvironment;
|
|
3856
|
+
serverTouchTracker;
|
|
3857
|
+
activityTracker;
|
|
3858
|
+
uiNotification;
|
|
3859
|
+
ngZone;
|
|
3860
|
+
static MIN_WARNING_MS = 30_000;
|
|
3861
|
+
static MAX_WARNING_MS = 2 * 60_000;
|
|
3862
|
+
static WARN_ONLY_IF_IDLE_MS = 30_000;
|
|
3863
|
+
isRunning = false;
|
|
3864
|
+
onExpired = null;
|
|
3865
|
+
subscriptions = new Subscription();
|
|
3866
|
+
warnTimeoutId = null;
|
|
3867
|
+
logoutTimeoutId = null;
|
|
3868
|
+
currentExpiresAtMs = 0;
|
|
3869
|
+
warnedForExpiresAtMs = 0;
|
|
3870
|
+
warningToastId = null;
|
|
3871
|
+
expiredToastId = null;
|
|
3872
|
+
constructor(appEnvironment, serverTouchTracker, activityTracker, uiNotification, ngZone) {
|
|
3873
|
+
this.appEnvironment = appEnvironment;
|
|
3874
|
+
this.serverTouchTracker = serverTouchTracker;
|
|
3875
|
+
this.activityTracker = activityTracker;
|
|
3876
|
+
this.uiNotification = uiNotification;
|
|
3877
|
+
this.ngZone = ngZone;
|
|
3878
|
+
}
|
|
3879
|
+
start(onExpired) {
|
|
3880
|
+
if (this.isRunning)
|
|
3881
|
+
return;
|
|
3882
|
+
if (this.appEnvironment.authType !== 'session')
|
|
3883
|
+
return;
|
|
3884
|
+
const timeoutMs = this.getTimeoutMs();
|
|
3885
|
+
if (timeoutMs === null)
|
|
3886
|
+
return;
|
|
3887
|
+
this.isRunning = true;
|
|
3888
|
+
this.onExpired = onExpired;
|
|
3889
|
+
this.ngZone.run(() => {
|
|
3890
|
+
this.uiNotification.clearToast(this.expiredToastId);
|
|
3891
|
+
this.expiredToastId = null;
|
|
3892
|
+
this.clearWarningToast();
|
|
3893
|
+
});
|
|
3894
|
+
this.subscriptions.add(this.activityTracker.lastActivity$.subscribe(() => {
|
|
3895
|
+
if (!this.isRunning)
|
|
3896
|
+
return;
|
|
3897
|
+
if (this.warningToastId === null)
|
|
3898
|
+
return;
|
|
3899
|
+
this.ngZone.run(() => {
|
|
3900
|
+
this.clearWarningToast();
|
|
3901
|
+
});
|
|
3902
|
+
}));
|
|
3903
|
+
const baselineAtMs = this.serverTouchTracker.getLastServerTouchAtMs() || Date.now() || 1;
|
|
3904
|
+
this.serverTouchTracker.recordServerTouch(baselineAtMs);
|
|
3905
|
+
const renewedAtMs = this.serverTouchTracker.getLastSessionRenewedAtMs() || baselineAtMs;
|
|
3906
|
+
this.scheduleFromRenewedAt(renewedAtMs, timeoutMs);
|
|
3907
|
+
this.subscriptions.add(this.serverTouchTracker.sessionRenewed$.subscribe((atMs) => {
|
|
3908
|
+
if (!this.isRunning)
|
|
3909
|
+
return;
|
|
3910
|
+
if (!Number.isFinite(atMs) || atMs <= 0)
|
|
3911
|
+
return;
|
|
3912
|
+
this.ngZone.run(() => {
|
|
3913
|
+
this.clearWarningToast();
|
|
3914
|
+
});
|
|
3915
|
+
this.scheduleFromRenewedAt(atMs, timeoutMs);
|
|
3916
|
+
}));
|
|
3917
|
+
}
|
|
3918
|
+
stop() {
|
|
3919
|
+
if (!this.isRunning)
|
|
3920
|
+
return;
|
|
3921
|
+
this.isRunning = false;
|
|
3922
|
+
this.onExpired = null;
|
|
3923
|
+
this.subscriptions.unsubscribe();
|
|
3924
|
+
this.subscriptions = new Subscription();
|
|
3925
|
+
this.clearTimers();
|
|
3926
|
+
this.ngZone.run(() => {
|
|
3927
|
+
this.clearWarningToast();
|
|
3928
|
+
});
|
|
3929
|
+
this.currentExpiresAtMs = 0;
|
|
3930
|
+
this.warnedForExpiresAtMs = 0;
|
|
3931
|
+
}
|
|
3932
|
+
scheduleFromRenewedAt(renewedAtMs, timeoutMs) {
|
|
3933
|
+
if (!Number.isFinite(renewedAtMs) || renewedAtMs <= 0)
|
|
3934
|
+
return;
|
|
3935
|
+
const expiresAtMs = renewedAtMs + timeoutMs;
|
|
3936
|
+
if (expiresAtMs === this.currentExpiresAtMs)
|
|
3937
|
+
return;
|
|
3938
|
+
this.currentExpiresAtMs = expiresAtMs;
|
|
3939
|
+
this.warnedForExpiresAtMs = 0;
|
|
3940
|
+
this.clearTimers();
|
|
3941
|
+
const now = Date.now();
|
|
3942
|
+
const warningLeadMs = this.getWarningLeadMs(timeoutMs);
|
|
3943
|
+
const warnAtMs = expiresAtMs - warningLeadMs;
|
|
3944
|
+
const warnDelayMs = Math.max(0, warnAtMs - now);
|
|
3945
|
+
const logoutDelayMs = Math.max(0, expiresAtMs - now);
|
|
3946
|
+
this.ngZone.runOutsideAngular(() => {
|
|
3947
|
+
this.warnTimeoutId = setTimeout(() => {
|
|
3948
|
+
this.handleWarning(expiresAtMs);
|
|
3949
|
+
}, warnDelayMs);
|
|
3950
|
+
this.logoutTimeoutId = setTimeout(() => {
|
|
3951
|
+
this.handleExpired(expiresAtMs);
|
|
3952
|
+
}, logoutDelayMs);
|
|
3953
|
+
});
|
|
3954
|
+
}
|
|
3955
|
+
handleWarning(expiresAtMs) {
|
|
3956
|
+
if (!this.isRunning)
|
|
3957
|
+
return;
|
|
3958
|
+
if (expiresAtMs !== this.currentExpiresAtMs)
|
|
3959
|
+
return;
|
|
3960
|
+
if (this.warnedForExpiresAtMs === expiresAtMs)
|
|
3961
|
+
return;
|
|
3962
|
+
const now = Date.now();
|
|
3963
|
+
const lastActivityAtMs = this.activityTracker.getLastActivityAtMs();
|
|
3964
|
+
const isIdle = lastActivityAtMs === 0 ||
|
|
3965
|
+
now - lastActivityAtMs >= TruSessionExpiryMonitor.WARN_ONLY_IF_IDLE_MS;
|
|
3966
|
+
if (!isIdle)
|
|
3967
|
+
return;
|
|
3968
|
+
this.warnedForExpiresAtMs = expiresAtMs;
|
|
3969
|
+
this.ngZone.run(() => {
|
|
3970
|
+
this.warningToastId = this.uiNotification.warningSticky('Your session will expire soon due to inactivity.');
|
|
3971
|
+
});
|
|
3972
|
+
}
|
|
3973
|
+
handleExpired(expiresAtMs) {
|
|
3974
|
+
if (!this.isRunning)
|
|
3975
|
+
return;
|
|
3976
|
+
if (expiresAtMs !== this.currentExpiresAtMs)
|
|
3977
|
+
return;
|
|
3978
|
+
this.ngZone.run(() => {
|
|
3979
|
+
this.clearWarningToast();
|
|
3980
|
+
this.expiredToastId = this.uiNotification.infoSticky('Session expired due to inactivity.');
|
|
3981
|
+
this.onExpired?.();
|
|
3982
|
+
});
|
|
3983
|
+
this.stop();
|
|
3984
|
+
}
|
|
3985
|
+
clearWarningToast() {
|
|
3986
|
+
if (this.warningToastId === null)
|
|
3987
|
+
return;
|
|
3988
|
+
this.uiNotification.clearToast(this.warningToastId);
|
|
3989
|
+
this.warningToastId = null;
|
|
3990
|
+
}
|
|
3991
|
+
clearTimers() {
|
|
3992
|
+
if (this.warnTimeoutId !== null) {
|
|
3993
|
+
clearTimeout(this.warnTimeoutId);
|
|
3994
|
+
this.warnTimeoutId = null;
|
|
3995
|
+
}
|
|
3996
|
+
if (this.logoutTimeoutId !== null) {
|
|
3997
|
+
clearTimeout(this.logoutTimeoutId);
|
|
3998
|
+
this.logoutTimeoutId = null;
|
|
3999
|
+
}
|
|
4000
|
+
}
|
|
4001
|
+
getTimeoutMs() {
|
|
4002
|
+
const timeoutMinutes = this.appEnvironment.authenticationTimeoutMinutes;
|
|
4003
|
+
if (!Number.isFinite(timeoutMinutes) || timeoutMinutes <= 0)
|
|
4004
|
+
return null;
|
|
4005
|
+
return timeoutMinutes * 60_000;
|
|
4006
|
+
}
|
|
4007
|
+
getWarningLeadMs(timeoutMs) {
|
|
4008
|
+
const derived = Math.floor(timeoutMs * 0.1);
|
|
4009
|
+
const clamped = Math.min(TruSessionExpiryMonitor.MAX_WARNING_MS, Math.max(TruSessionExpiryMonitor.MIN_WARNING_MS, derived));
|
|
4010
|
+
return Math.min(clamped, Math.max(0, timeoutMs - 1_000));
|
|
4011
|
+
}
|
|
4012
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: TruSessionExpiryMonitor, deps: [{ token: TruAppEnvironment }, { token: TruServerTouchTracker }, { token: TruUserActivityTracker }, { token: TruUiNotification }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
4013
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: TruSessionExpiryMonitor, providedIn: 'root' });
|
|
4014
|
+
}
|
|
4015
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: TruSessionExpiryMonitor, decorators: [{
|
|
4016
|
+
type: Injectable,
|
|
4017
|
+
args: [{
|
|
4018
|
+
providedIn: 'root',
|
|
4019
|
+
}]
|
|
4020
|
+
}], ctorParameters: () => [{ type: TruAppEnvironment }, { type: TruServerTouchTracker }, { type: TruUserActivityTracker }, { type: TruUiNotification }, { type: i0.NgZone }] });
|
|
4021
|
+
|
|
3375
4022
|
class TruAuth {
|
|
3376
4023
|
router;
|
|
3377
4024
|
http;
|
|
3378
4025
|
cache;
|
|
3379
4026
|
user;
|
|
3380
4027
|
appEnvironment;
|
|
4028
|
+
sessionKeepalive;
|
|
4029
|
+
sessionExpiryMonitor;
|
|
3381
4030
|
auth;
|
|
3382
4031
|
loggedIn = new BehaviorSubject(false);
|
|
3383
4032
|
baseUrl = '';
|
|
3384
|
-
constructor(router, http, cache, user, appEnvironment, auth) {
|
|
4033
|
+
constructor(router, http, cache, user, appEnvironment, sessionKeepalive, sessionExpiryMonitor, auth) {
|
|
3385
4034
|
this.router = router;
|
|
3386
4035
|
this.http = http;
|
|
3387
4036
|
this.cache = cache;
|
|
3388
4037
|
this.user = user;
|
|
3389
4038
|
this.appEnvironment = appEnvironment;
|
|
4039
|
+
this.sessionKeepalive = sessionKeepalive;
|
|
4040
|
+
this.sessionExpiryMonitor = sessionExpiryMonitor;
|
|
3390
4041
|
this.auth = auth;
|
|
3391
4042
|
this.baseUrl = this.appEnvironment.appUri;
|
|
3392
4043
|
}
|
|
@@ -3396,6 +4047,12 @@ class TruAuth {
|
|
|
3396
4047
|
.pipe(tap((data) => {
|
|
3397
4048
|
this.auth.doLoginUser(data);
|
|
3398
4049
|
this.loggedIn.next(true);
|
|
4050
|
+
if (this.appEnvironment.authType === 'session') {
|
|
4051
|
+
this.sessionKeepalive.start();
|
|
4052
|
+
this.sessionExpiryMonitor.start(() => {
|
|
4053
|
+
this.doLogoutAndRedirectToLogin();
|
|
4054
|
+
});
|
|
4055
|
+
}
|
|
3399
4056
|
}));
|
|
3400
4057
|
}
|
|
3401
4058
|
setUser() {
|
|
@@ -3434,8 +4091,10 @@ class TruAuth {
|
|
|
3434
4091
|
this.user.destroy();
|
|
3435
4092
|
this.cache.pruneAll();
|
|
3436
4093
|
this.auth.doLogoutUser();
|
|
4094
|
+
this.sessionKeepalive.stop();
|
|
4095
|
+
this.sessionExpiryMonitor.stop();
|
|
3437
4096
|
}
|
|
3438
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: TruAuth, deps: [{ token: i1$
|
|
4097
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: TruAuth, deps: [{ token: i1$5.Router }, { token: i1$2.HttpClient }, { token: TruAuthCache }, { token: TruUser }, { token: TruAppEnvironment }, { token: TruSessionKeepalive }, { token: TruSessionExpiryMonitor }, { token: TRU_AUTH_STRATEGY }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
3439
4098
|
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: TruAuth, providedIn: "root" });
|
|
3440
4099
|
}
|
|
3441
4100
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: TruAuth, decorators: [{
|
|
@@ -3443,7 +4102,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
|
|
|
3443
4102
|
args: [{
|
|
3444
4103
|
providedIn: "root",
|
|
3445
4104
|
}]
|
|
3446
|
-
}], ctorParameters: () => [{ type: i1$
|
|
4105
|
+
}], ctorParameters: () => [{ type: i1$5.Router }, { type: i1$2.HttpClient }, { type: TruAuthCache }, { type: TruUser }, { type: TruAppEnvironment }, { type: TruSessionKeepalive }, { type: TruSessionExpiryMonitor }, { type: undefined, decorators: [{
|
|
3447
4106
|
type: Inject,
|
|
3448
4107
|
args: [TRU_AUTH_STRATEGY]
|
|
3449
4108
|
}] }] });
|
|
@@ -3668,7 +4327,7 @@ class TruIconModule {
|
|
|
3668
4327
|
iconRegistry.addSvgIconLiteral("visibility-icon", sanitizer.bypassSecurityTrustHtml(VISIBILITY_ICON));
|
|
3669
4328
|
iconRegistry.addSvgIconLiteral("visibility-off-icon", sanitizer.bypassSecurityTrustHtml(VISIBILITY_OFF_ICON));
|
|
3670
4329
|
}
|
|
3671
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: TruIconModule, deps: [{ token: i1$
|
|
4330
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: TruIconModule, deps: [{ token: i1$6.DomSanitizer }, { token: i2.MatIconRegistry }], target: i0.ɵɵFactoryTarget.NgModule });
|
|
3672
4331
|
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "19.2.17", ngImport: i0, type: TruIconModule, imports: [CommonModule, FormsModule] });
|
|
3673
4332
|
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: TruIconModule, imports: [CommonModule, FormsModule] });
|
|
3674
4333
|
}
|
|
@@ -3679,7 +4338,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
|
|
|
3679
4338
|
declarations: [],
|
|
3680
4339
|
exports: []
|
|
3681
4340
|
}]
|
|
3682
|
-
}], ctorParameters: () => [{ type: i1$
|
|
4341
|
+
}], ctorParameters: () => [{ type: i1$6.DomSanitizer }, { type: i2.MatIconRegistry }] });
|
|
3683
4342
|
|
|
3684
4343
|
class TruModelTableLookup {
|
|
3685
4344
|
_lookup = new Map();
|
|
@@ -5119,7 +5778,7 @@ class TruAppSettingsDialog {
|
|
|
5119
5778
|
});
|
|
5120
5779
|
}
|
|
5121
5780
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: TruAppSettingsDialog, deps: [{ token: TruAppEnvironment }, { token: i1.MatDialogRef }, { token: MAT_DIALOG_DATA }], target: i0.ɵɵFactoryTarget.Component });
|
|
5122
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.17", type: TruAppSettingsDialog, isStandalone: true, selector: "tru-app-settings-dialog", ngImport: i0, template: "<div mat-dialog-title class=\"mat-dialog-title\">\r\n <div class=\"mat-dialog-title-container\">\r\n <mat-icon [svgIcon]=\"'settings-icon'\"\r\n title=\"Settings\">\r\n </mat-icon>\r\n App Settings\r\n </div>\r\n</div>\r\n\r\n<div mat-dialog-content class=\"mat-dialog-content\">\r\n <mat-sidenav-container class=\"example-sidenav-container\">\r\n <mat-sidenav #snav mode=\"side\" opened>\r\n <mat-nav-list>\r\n <a mat-list-item>Windows</a>\r\n </mat-nav-list>\r\n </mat-sidenav>\r\n <mat-sidenav-content>\r\n <tru-app-window-settings></tru-app-window-settings>\r\n </mat-sidenav-content>\r\n </mat-sidenav-container>\r\n</div>\r\n\r\n<div mat-dialog-actions class=\"mat-dialog-actions\">\r\n <button mat-raised-button (click)=\"onDismiss()\">Close</button>\r\n</div>\r\n", styles: ["::ng-deep .mat-mdc-dialog-surface{padding:20px}.mat-mdc-dialog-title:before{content:unset!important;height:unset!important;padding:0 0 10px!important}.mat-dialog-title-container mat-icon{vertical-align:sub;height:24px;width:24px}mat-nav-list{width:200px}mat-sidenav-content{height:calc(100vh - 400px)}mat-sidenav-content{padding-left:10px}.mat-dialog-title-container{display:inline}.mdc-dialog__title{padding:0 0 10px!important}.mdc-dialog__content{padding:10px 0 15px!important}.mat-mdc-dialog-content p{margin-bottom:0;font-size:14px;color:#545454}.mat-mdc-dialog-actions{padding:0!important}.mat-mdc-dialog-actions button{margin-right:10px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: MaterialModule }, { kind: "component", type: i3.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "directive", type: i1.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: i1.MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]", inputs: ["align"] }, { kind: "directive", type: i1.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "component", type: i2
|
|
5781
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.17", type: TruAppSettingsDialog, isStandalone: true, selector: "tru-app-settings-dialog", ngImport: i0, template: "<div mat-dialog-title class=\"mat-dialog-title\">\r\n <div class=\"mat-dialog-title-container\">\r\n <mat-icon [svgIcon]=\"'settings-icon'\"\r\n title=\"Settings\">\r\n </mat-icon>\r\n App Settings\r\n </div>\r\n</div>\r\n\r\n<div mat-dialog-content class=\"mat-dialog-content\">\r\n <mat-sidenav-container class=\"example-sidenav-container\">\r\n <mat-sidenav #snav mode=\"side\" opened>\r\n <mat-nav-list>\r\n <a mat-list-item>Windows</a>\r\n </mat-nav-list>\r\n </mat-sidenav>\r\n <mat-sidenav-content>\r\n <tru-app-window-settings></tru-app-window-settings>\r\n </mat-sidenav-content>\r\n </mat-sidenav-container>\r\n</div>\r\n\r\n<div mat-dialog-actions class=\"mat-dialog-actions\">\r\n <button mat-raised-button (click)=\"onDismiss()\">Close</button>\r\n</div>\r\n", styles: ["::ng-deep .mat-mdc-dialog-surface{padding:20px}.mat-mdc-dialog-title:before{content:unset!important;height:unset!important;padding:0 0 10px!important}.mat-dialog-title-container mat-icon{vertical-align:sub;height:24px;width:24px}mat-nav-list{width:200px}mat-sidenav-content{height:calc(100vh - 400px)}mat-sidenav-content{padding-left:10px}.mat-dialog-title-container{display:inline}.mdc-dialog__title{padding:0 0 10px!important}.mdc-dialog__content{padding:10px 0 15px!important}.mat-mdc-dialog-content p{margin-bottom:0;font-size:14px;color:#545454}.mat-mdc-dialog-actions{padding:0!important}.mat-mdc-dialog-actions button{margin-right:10px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: MaterialModule }, { kind: "component", type: i3.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "directive", type: i1.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: i1.MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]", inputs: ["align"] }, { kind: "directive", type: i1.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i5$2.MatNavList, selector: "mat-nav-list", exportAs: ["matNavList"] }, { kind: "component", type: i5$2.MatListItem, selector: "mat-list-item, a[mat-list-item], button[mat-list-item]", inputs: ["activated"], exportAs: ["matListItem"] }, { kind: "component", type: i6.MatSidenav, selector: "mat-sidenav", inputs: ["fixedInViewport", "fixedTopGap", "fixedBottomGap"], exportAs: ["matSidenav"] }, { kind: "component", type: i6.MatSidenavContainer, selector: "mat-sidenav-container", exportAs: ["matSidenavContainer"] }, { kind: "component", type: i6.MatSidenavContent, selector: "mat-sidenav-content" }, { kind: "component", type: TruAppWindowSettings, selector: "tru-app-window-settings" }] });
|
|
5123
5782
|
}
|
|
5124
5783
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: TruAppSettingsDialog, decorators: [{
|
|
5125
5784
|
type: Component,
|
|
@@ -6829,7 +7488,7 @@ class TruDataGridPkeyCellRenderer {
|
|
|
6829
7488
|
<span>Insert At Top</span>
|
|
6830
7489
|
</button>
|
|
6831
7490
|
</mat-menu>
|
|
6832
|
-
</div>`, isInline: true, styles: ["::ng-deep .mat-mdc-menu-item{height:25px!important;min-height:25px!important}::ng-deep .mat-mdc-menu-content mat-icon svg{fill:#949494}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2
|
|
7491
|
+
</div>`, isInline: true, styles: ["::ng-deep .mat-mdc-menu-item{height:25px!important;min-height:25px!important}::ng-deep .mat-mdc-menu-content mat-icon svg{fill:#949494}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i5.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i5.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i5.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
6833
7492
|
}
|
|
6834
7493
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: TruDataGridPkeyCellRenderer, decorators: [{
|
|
6835
7494
|
type: Component,
|
|
@@ -6960,7 +7619,7 @@ class TruDataGridHeader {
|
|
|
6960
7619
|
</div>
|
|
6961
7620
|
</div>
|
|
6962
7621
|
</div>
|
|
6963
|
-
</div>`, isInline: true, styles: [".ag-header-control-container{display:flex}.ag-header-control-filter-container{position:absolute;top:1px;right:3px;width:20px;height:20px;display:table}.ag-header-cell-text{position:relative;pointer-events:none;vertical-align:middle;vertical-align:-webkit-baseline-middle}.ag-sort-icon{height:100%;width:100%;margin-left:0!important}.tru-data-grid-select-all-icon{width:16px;font-size:28px;color:#ddd;float:right;position:absolute;top:-1px;right:4px}.ag-sort-icon mat-icon{height:16px;width:16px;padding-top:4px}.ag-column-focus .ag-header-cell-text{color:#3f51b5;font-weight:700}.ag-column-focus{background-color:#ddd;border-bottom:1px solid #3f51b5}::ng-deep .tru-data-grid-select-all-icon path{fill:#d3d3d3;position:relative;z-index:100;pointer-events:all}::ng-deep .ag-header-control-filter-container mat-icon{height:20px!important;width:20px!important;padding-top:2px!important}::ng-deep .ag-filter-icon .ag-header-asc.filtering{position:relative;right:-7px}::ng-deep .ag-filter-icon .ag-header-desc.filtering{position:relative;right:-7px}::ng-deep .ag-filter-icon mat-icon{height:18px!important;width:18px!important;color:#ddd}::ng-deep .ag-filter-icon mat-icon svg{fill:#949494!important}\n"], dependencies: [{ kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2
|
|
7622
|
+
</div>`, isInline: true, styles: [".ag-header-control-container{display:flex}.ag-header-control-filter-container{position:absolute;top:1px;right:3px;width:20px;height:20px;display:table}.ag-header-cell-text{position:relative;pointer-events:none;vertical-align:middle;vertical-align:-webkit-baseline-middle}.ag-sort-icon{height:100%;width:100%;margin-left:0!important}.tru-data-grid-select-all-icon{width:16px;font-size:28px;color:#ddd;float:right;position:absolute;top:-1px;right:4px}.ag-sort-icon mat-icon{height:16px;width:16px;padding-top:4px}.ag-column-focus .ag-header-cell-text{color:#3f51b5;font-weight:700}.ag-column-focus{background-color:#ddd;border-bottom:1px solid #3f51b5}::ng-deep .tru-data-grid-select-all-icon path{fill:#d3d3d3;position:relative;z-index:100;pointer-events:all}::ng-deep .ag-header-control-filter-container mat-icon{height:20px!important;width:20px!important;padding-top:2px!important}::ng-deep .ag-filter-icon .ag-header-asc.filtering{position:relative;right:-7px}::ng-deep .ag-filter-icon .ag-header-desc.filtering{position:relative;right:-7px}::ng-deep .ag-filter-icon mat-icon{height:18px!important;width:18px!important;color:#ddd}::ng-deep .ag-filter-icon mat-icon svg{fill:#949494!important}\n"], dependencies: [{ kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }] });
|
|
6964
7623
|
}
|
|
6965
7624
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: TruDataGridHeader, decorators: [{
|
|
6966
7625
|
type: Component,
|
|
@@ -7080,7 +7739,7 @@ class TruDataGridHeaderFilter {
|
|
|
7080
7739
|
(ngModelChange)="onFilterInputChanged()"
|
|
7081
7740
|
type="text" />
|
|
7082
7741
|
</mat-form-field>
|
|
7083
|
-
</div>`, isInline: true, styles: [".tru-data-grid-header-filter-container{min-width:200px!important}.tru-data-grid-header-filter-container mdc-list{padding-bottom:10px!important}::ng-deep .tru-data-grid-header-filter-container mat-list-option{padding-left:10px!important}::ng-deep .tru-data-grid-header-filter-container mat-icon{height:18px!important;width:18px!important;padding-right:5px;padding-top:4px}::ng-deep .tru-data-grid-header-filter-container .mdc-list-item__primary-text span{font-size:12px!important;vertical-align:text-bottom}::ng-deep .tru-data-grid-header-filter-container .mdc-list-item.mdc-list-item--with-one-line .mdc-list-item__end{display:none!important}::ng-deep .tru-data-grid-header-filter-container mat-divider{padding-top:5px;padding-bottom:5px;margin-left:10px;margin-right:10px}::ng-deep .tru-data-grid-header-filter-container mat-label{margin-left:10px;font-weight:700}::ng-deep .tru-data-grid-header-filter-container .mat-mdc-form-field{display:block!important;margin:0 10px 10px!important}::ng-deep .tru-data-grid-header-filter-container .mat-mdc-form-field-infix{padding:0!important;min-height:unset!important}::ng-deep .tru-data-grid-header-filter-container .mat-mdc-form-field-flex.invalid .mdc-notched-outline__leading{border-color:#bd362f}::ng-deep .tru-data-grid-header-filter-container .mat-mdc-form-field-flex.invalid .mdc-notched-outline__notch{border-color:#bd362f}::ng-deep .tru-data-grid-header-filter-container .mat-mdc-form-field-flex.invalid .mdc-notched-outline__trailing{border-color:#bd362f}::ng-deep .tru-data-grid-header-filter-container .mat-mdc-form-field-bottom-align:before{content:unset!important}::ng-deep .tru-data-grid-header-filter-container .mat-mdc-form-field-icon-prefix>.mat-icon{padding:0 0 5px!important}::ng-deep .tru-data-grid-header-filter-container .mat-mdc-form-field-icon-suffix>.mat-icon{padding:0 0 5px!important}::ng-deep .tru-data-grid-header-filter-container .mat-mdc-form-field-infix{padding:0 0 5px!important;min-height:unset!important}::ng-deep .tru-data-grid-header-filter-search-icon svg{fill:#343434}\n"], dependencies: [{ kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i8.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: i8.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2
|
|
7742
|
+
</div>`, isInline: true, styles: [".tru-data-grid-header-filter-container{min-width:200px!important}.tru-data-grid-header-filter-container mdc-list{padding-bottom:10px!important}::ng-deep .tru-data-grid-header-filter-container mat-list-option{padding-left:10px!important}::ng-deep .tru-data-grid-header-filter-container mat-icon{height:18px!important;width:18px!important;padding-right:5px;padding-top:4px}::ng-deep .tru-data-grid-header-filter-container .mdc-list-item__primary-text span{font-size:12px!important;vertical-align:text-bottom}::ng-deep .tru-data-grid-header-filter-container .mdc-list-item.mdc-list-item--with-one-line .mdc-list-item__end{display:none!important}::ng-deep .tru-data-grid-header-filter-container mat-divider{padding-top:5px;padding-bottom:5px;margin-left:10px;margin-right:10px}::ng-deep .tru-data-grid-header-filter-container mat-label{margin-left:10px;font-weight:700}::ng-deep .tru-data-grid-header-filter-container .mat-mdc-form-field{display:block!important;margin:0 10px 10px!important}::ng-deep .tru-data-grid-header-filter-container .mat-mdc-form-field-infix{padding:0!important;min-height:unset!important}::ng-deep .tru-data-grid-header-filter-container .mat-mdc-form-field-flex.invalid .mdc-notched-outline__leading{border-color:#bd362f}::ng-deep .tru-data-grid-header-filter-container .mat-mdc-form-field-flex.invalid .mdc-notched-outline__notch{border-color:#bd362f}::ng-deep .tru-data-grid-header-filter-container .mat-mdc-form-field-flex.invalid .mdc-notched-outline__trailing{border-color:#bd362f}::ng-deep .tru-data-grid-header-filter-container .mat-mdc-form-field-bottom-align:before{content:unset!important}::ng-deep .tru-data-grid-header-filter-container .mat-mdc-form-field-icon-prefix>.mat-icon{padding:0 0 5px!important}::ng-deep .tru-data-grid-header-filter-container .mat-mdc-form-field-icon-suffix>.mat-icon{padding:0 0 5px!important}::ng-deep .tru-data-grid-header-filter-container .mat-mdc-form-field-infix{padding:0 0 5px!important;min-height:unset!important}::ng-deep .tru-data-grid-header-filter-search-icon svg{fill:#343434}\n"], dependencies: [{ kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i8.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: i8.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: MatSelectionList, selector: "mat-selection-list", inputs: ["color", "compareWith", "multiple", "hideSingleSelectionIndicator", "disabled"], outputs: ["selectionChange"], exportAs: ["matSelectionList"] }, { kind: "component", type: MatListOption, selector: "mat-list-option", inputs: ["togglePosition", "checkboxPosition", "color", "value", "selected"], outputs: ["selectedChange"], exportAs: ["matListOption"] }, { kind: "component", type: MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }, { kind: "component", type: MatFormField$1, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i7.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "directive", type: i7.MatLabel, selector: "mat-label" }, { kind: "directive", type: i7.MatPrefix, selector: "[matPrefix], [matIconPrefix], [matTextPrefix]", inputs: ["matTextPrefix"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i8.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }] });
|
|
7084
7743
|
}
|
|
7085
7744
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: TruDataGridHeaderFilter, decorators: [{
|
|
7086
7745
|
type: Component,
|
|
@@ -7196,7 +7855,7 @@ class TruDataGridRefHeader {
|
|
|
7196
7855
|
(click)="onSelectAllIconClicked()"
|
|
7197
7856
|
class="tru-data-grid-select-all-icon"
|
|
7198
7857
|
title="Select All (Ctrl+A)"></mat-icon>
|
|
7199
|
-
</div>`, isInline: true, styles: [".ag-header-control-container{display:flex}.ag-header-control-filter-container{position:absolute;top:1px;left:5px;width:20px;height:20px;display:table}.ag-header-cell-text{position:relative;pointer-events:none;vertical-align:middle;vertical-align:-webkit-baseline-middle}.ag-sort-icon{height:100%;width:100%;margin-left:0!important}.ag-sort-icon mat-icon{height:16px;width:16px;padding-top:4px}.ag-column-focus .ag-header-cell-text{color:#3f51b5;font-weight:700}.ag-column-focus{background-color:#ddd;border-bottom:1px solid #3f51b5}::ng-deep .ag-header-control-filter-container mat-icon{height:20px!important;width:20px!important;padding-top:2px!important}::ng-deep .ag-filter-icon .ag-header-asc.filtering{position:relative;right:-7px}::ng-deep .ag-filter-icon .ag-header-desc.filtering{position:relative;right:-7px}::ng-deep .ag-filter-icon mat-icon{height:18px!important;width:18px!important;color:#ddd}::ng-deep .ag-filter-icon mat-icon svg{fill:#949494!important}.tru-data-grid-select-all-icon{width:16px;font-size:28px;color:#ddd;float:right;position:absolute;top:-1px;right:4px}::ng-deep .tru-data-grid-select-all-icon path{fill:#d3d3d3;position:relative;z-index:100;pointer-events:all}\n"], dependencies: [{ kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2
|
|
7858
|
+
</div>`, isInline: true, styles: [".ag-header-control-container{display:flex}.ag-header-control-filter-container{position:absolute;top:1px;left:5px;width:20px;height:20px;display:table}.ag-header-cell-text{position:relative;pointer-events:none;vertical-align:middle;vertical-align:-webkit-baseline-middle}.ag-sort-icon{height:100%;width:100%;margin-left:0!important}.ag-sort-icon mat-icon{height:16px;width:16px;padding-top:4px}.ag-column-focus .ag-header-cell-text{color:#3f51b5;font-weight:700}.ag-column-focus{background-color:#ddd;border-bottom:1px solid #3f51b5}::ng-deep .ag-header-control-filter-container mat-icon{height:20px!important;width:20px!important;padding-top:2px!important}::ng-deep .ag-filter-icon .ag-header-asc.filtering{position:relative;right:-7px}::ng-deep .ag-filter-icon .ag-header-desc.filtering{position:relative;right:-7px}::ng-deep .ag-filter-icon mat-icon{height:18px!important;width:18px!important;color:#ddd}::ng-deep .ag-filter-icon mat-icon svg{fill:#949494!important}.tru-data-grid-select-all-icon{width:16px;font-size:28px;color:#ddd;float:right;position:absolute;top:-1px;right:4px}::ng-deep .tru-data-grid-select-all-icon path{fill:#d3d3d3;position:relative;z-index:100;pointer-events:all}\n"], dependencies: [{ kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }] });
|
|
7200
7859
|
}
|
|
7201
7860
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: TruDataGridRefHeader, decorators: [{
|
|
7202
7861
|
type: Component,
|
|
@@ -7416,7 +8075,7 @@ class TruDataGridLoadingOverlay {
|
|
|
7416
8075
|
<span style="font-size:12px;font-weight:bold;vertical-align:middle;line-height:38px;">{{ params.loadingMessage }}</span>
|
|
7417
8076
|
</div>
|
|
7418
8077
|
</div>
|
|
7419
|
-
`, isInline: true, dependencies: [{ kind: "ngmodule", type: MaterialModule }, { kind: "component", type: i1$
|
|
8078
|
+
`, isInline: true, dependencies: [{ kind: "ngmodule", type: MaterialModule }, { kind: "component", type: i1$7.MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "mode", "value", "diameter", "strokeWidth"], exportAs: ["matProgressSpinner"] }] });
|
|
7420
8079
|
}
|
|
7421
8080
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: TruDataGridLoadingOverlay, decorators: [{
|
|
7422
8081
|
type: Component,
|
|
@@ -7483,7 +8142,6 @@ class TruMergeData {
|
|
|
7483
8142
|
|
|
7484
8143
|
class TruDataChangeParser {
|
|
7485
8144
|
appEnvionment;
|
|
7486
|
-
user;
|
|
7487
8145
|
dataContext;
|
|
7488
8146
|
entity;
|
|
7489
8147
|
tableName;
|
|
@@ -7504,9 +8162,8 @@ class TruDataChangeParser {
|
|
|
7504
8162
|
dataChanged(change) {
|
|
7505
8163
|
this.dataChanged$.next(change);
|
|
7506
8164
|
}
|
|
7507
|
-
constructor(connection, appEnviroment,
|
|
8165
|
+
constructor(connection, appEnviroment, dataContext, globalDataContext, entity, tableName, addEntity, getLatestResults, getLatestQuery, contextFilters, expandPaths, isLoaded, modelTypeLookup, modelPropertyLookup) {
|
|
7508
8166
|
this.appEnvionment = appEnviroment;
|
|
7509
|
-
this.user = user;
|
|
7510
8167
|
this.dataContext = dataContext;
|
|
7511
8168
|
this.globalDataContext = globalDataContext;
|
|
7512
8169
|
this.entity = entity;
|
|
@@ -7627,7 +8284,7 @@ class TruDataChangeParser {
|
|
|
7627
8284
|
update = async (payload) => {
|
|
7628
8285
|
await this.isSaving();
|
|
7629
8286
|
var reloadResults = false;
|
|
7630
|
-
payload.changes.
|
|
8287
|
+
payload.changes.forEach(async (change) => {
|
|
7631
8288
|
var foundEntities = [];
|
|
7632
8289
|
var localEntity = this.findEntityInCache(change);
|
|
7633
8290
|
var globalEntity = this.findEntityInGlobalCache(change);
|
|
@@ -7760,14 +8417,12 @@ class TruDataChangeParser {
|
|
|
7760
8417
|
class TruConnectionHub {
|
|
7761
8418
|
dataContext;
|
|
7762
8419
|
appEnvironment;
|
|
7763
|
-
user;
|
|
7764
8420
|
modelTypeLookup;
|
|
7765
8421
|
modelPropertyLookup;
|
|
7766
8422
|
connection;
|
|
7767
|
-
constructor(dataContext, appEnvironment,
|
|
8423
|
+
constructor(dataContext, appEnvironment, modelTypeLookup, modelPropertyLookup) {
|
|
7768
8424
|
this.dataContext = dataContext;
|
|
7769
8425
|
this.appEnvironment = appEnvironment;
|
|
7770
|
-
this.user = user;
|
|
7771
8426
|
this.modelTypeLookup = modelTypeLookup;
|
|
7772
8427
|
this.modelPropertyLookup = modelPropertyLookup;
|
|
7773
8428
|
this.connection = new signalR.HubConnectionBuilder()
|
|
@@ -7801,9 +8456,9 @@ class TruConnectionHub {
|
|
|
7801
8456
|
this.connect();
|
|
7802
8457
|
};
|
|
7803
8458
|
subscribe = (dataContext, entity, tableName, addEntity, getLatestResults, getLatestQuery, contextFilters, expandPaths, isLoaded) => {
|
|
7804
|
-
return new TruDataChangeParser(this.connection, this.appEnvironment,
|
|
8459
|
+
return new TruDataChangeParser(this.connection, this.appEnvironment, dataContext, this.appEnvironment.globalDataContext, entity, tableName, addEntity, getLatestResults, getLatestQuery, contextFilters, expandPaths, isLoaded, this.modelTypeLookup, this.modelPropertyLookup).onDataChanged();
|
|
7805
8460
|
};
|
|
7806
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: TruConnectionHub, deps: [{ token: TruDataContext }, { token: TruAppEnvironment }, { token:
|
|
8461
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: TruConnectionHub, deps: [{ token: TruDataContext }, { token: TruAppEnvironment }, { token: TruModelTypeLookup }, { token: TruModelPropertyLookup }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
7807
8462
|
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: TruConnectionHub, providedIn: 'root' });
|
|
7808
8463
|
}
|
|
7809
8464
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: TruConnectionHub, decorators: [{
|
|
@@ -7811,7 +8466,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
|
|
|
7811
8466
|
args: [{
|
|
7812
8467
|
providedIn: 'root',
|
|
7813
8468
|
}]
|
|
7814
|
-
}], ctorParameters: () => [{ type: TruDataContext }, { type: TruAppEnvironment }, { type:
|
|
8469
|
+
}], ctorParameters: () => [{ type: TruDataContext }, { type: TruAppEnvironment }, { type: TruModelTypeLookup }, { type: TruModelPropertyLookup }] });
|
|
7815
8470
|
|
|
7816
8471
|
class TruTabGroupEventNotifier {
|
|
7817
8472
|
active$ = new BehaviorSubject(false);
|
|
@@ -9166,12 +9821,12 @@ class TruActionInvoke {
|
|
|
9166
9821
|
refs: actionRefs,
|
|
9167
9822
|
});
|
|
9168
9823
|
};
|
|
9169
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: TruActionInvoke, deps: [{ token: TruDataContext }, { token: TruTextManager }, { token: TruDesktopManager }, { token: TruWindowEventHandler }, { token: TruUiNotification }, { token: TruAppEnvironment }, { token:
|
|
9824
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: TruActionInvoke, deps: [{ token: TruDataContext }, { token: TruTextManager }, { token: TruDesktopManager }, { token: TruWindowEventHandler }, { token: TruUiNotification }, { token: TruAppEnvironment }, { token: i1$2.HttpClient }, { token: TruComponentLookup }, { token: TruModelTypeLookup }, { token: TruGlobalDataContext }, { token: TruUser }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
9170
9825
|
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: TruActionInvoke });
|
|
9171
9826
|
}
|
|
9172
9827
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: TruActionInvoke, decorators: [{
|
|
9173
9828
|
type: Injectable
|
|
9174
|
-
}], ctorParameters: () => [{ type: TruDataContext }, { type: TruTextManager }, { type: TruDesktopManager }, { type: TruWindowEventHandler }, { type: TruUiNotification }, { type: TruAppEnvironment }, { type:
|
|
9829
|
+
}], ctorParameters: () => [{ type: TruDataContext }, { type: TruTextManager }, { type: TruDesktopManager }, { type: TruWindowEventHandler }, { type: TruUiNotification }, { type: TruAppEnvironment }, { type: i1$2.HttpClient }, { type: TruComponentLookup }, { type: TruModelTypeLookup }, { type: TruGlobalDataContext }, { type: TruUser }] });
|
|
9175
9830
|
|
|
9176
9831
|
class TruReportManager {
|
|
9177
9832
|
dataContext;
|
|
@@ -9520,7 +10175,7 @@ class TruDesktopWindowStateMonitor {
|
|
|
9520
10175
|
this.tabListener();
|
|
9521
10176
|
this.focusListener();
|
|
9522
10177
|
}
|
|
9523
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: TruDesktopWindowStateMonitor, deps: [{ token: i0.ElementRef }, { token: i0.Renderer2 }, { token: TruWindowEventHandler }, { token: i2$
|
|
10178
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: TruDesktopWindowStateMonitor, deps: [{ token: i0.ElementRef }, { token: i0.Renderer2 }, { token: TruWindowEventHandler }, { token: i2$1.OverlayContainer }], target: i0.ɵɵFactoryTarget.Directive });
|
|
9524
10179
|
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.2.17", type: TruDesktopWindowStateMonitor, isStandalone: true, selector: "[truDesktopWindowStateMonitor]", inputs: { active: ["truDesktopWindowStateMonitor", "active"] }, usesOnChanges: true, ngImport: i0 });
|
|
9525
10180
|
}
|
|
9526
10181
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: TruDesktopWindowStateMonitor, decorators: [{
|
|
@@ -9528,7 +10183,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
|
|
|
9528
10183
|
args: [{
|
|
9529
10184
|
selector: '[truDesktopWindowStateMonitor]'
|
|
9530
10185
|
}]
|
|
9531
|
-
}], ctorParameters: () => [{ type: i0.ElementRef }, { type: i0.Renderer2 }, { type: TruWindowEventHandler }, { type: i2$
|
|
10186
|
+
}], ctorParameters: () => [{ type: i0.ElementRef }, { type: i0.Renderer2 }, { type: TruWindowEventHandler }, { type: i2$1.OverlayContainer }], propDecorators: { active: [{
|
|
9532
10187
|
type: Input,
|
|
9533
10188
|
args: ['truDesktopWindowStateMonitor']
|
|
9534
10189
|
}] } });
|
|
@@ -10947,7 +11602,7 @@ class TruErrorDialog {
|
|
|
10947
11602
|
this.dialogRef.close(false);
|
|
10948
11603
|
}
|
|
10949
11604
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: TruErrorDialog, deps: [{ token: i1.MatDialogRef }, { token: MAT_DIALOG_DATA }], target: i0.ɵɵFactoryTarget.Component });
|
|
10950
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.17", type: TruErrorDialog, isStandalone: true, selector: "tru-error-dialog", ngImport: i0, template: "<div mat-dialog-title class=\"tru-error-dialog-title mat-dialog-title\">\r\n <div class=\"mat-dialog-title-container\">\r\n <mat-icon [svgIcon]=\"'error-icon'\"\r\n title=\"Error\">\r\n </mat-icon>\r\n Error - {{title}}\r\n </div>\r\n</div>\r\n\r\n<div mat-dialog-content class=\"mat-dialog-content\">\r\n <div class=\"tru-about-description\">\r\n {{message}}\r\n </div>\r\n <mat-expansion-panel *ngIf=\"stackTrace\"\r\n (opened)=\"panelOpenState.set(true)\"\r\n (closed)=\"panelOpenState.set(false)\">\r\n <mat-expansion-panel-header>\r\n <mat-panel-description>\r\n Show Stack Trace\r\n </mat-panel-description>\r\n </mat-expansion-panel-header>\r\n <p>{{stackTrace}}</p>\r\n </mat-expansion-panel>\r\n</div>\r\n\r\n<div mat-dialog-actions class=\"mat-dialog-actions\">\r\n <button mat-raised-button (click)=\"onDismiss()\">Close</button>\r\n</div>\r\n", styles: ["::ng-deep .mat-mdc-dialog-surface{padding:20px}.mat-mdc-dialog-title:before{content:unset!important;height:unset!important;padding:0 0 10px!important}.mat-dialog-title-container mat-icon{vertical-align:sub;height:24px;width:24px}.mat-dialog-title-container{display:inline}.mdc-dialog__title{padding:0 0 10px!important}.mdc-dialog__content{padding:10px 0 15px!important}.mat-mdc-dialog-content p{margin-bottom:0;font-size:14px;color:#545454}.mat-mdc-dialog-actions{padding:0!important}.mat-mdc-dialog-actions button{margin-right:10px}.tru-about-description{width:550px;height:200px;padding:5px;margin-bottom:5px;border:1px #cbcbcb solid}.mat-expansion-panel{border-radius:0!important}mat-panel-description{font-size:12px;text-decoration:underline;border-radius:0}::ng-deep .tru-error-dialog-title svg{fill:red}::ng-deep .tru-error-dialog-title svg path{fill:red}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: MaterialModule }, { kind: "component", type: i3.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "directive", type: i1.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: i1.MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]", inputs: ["align"] }, { kind: "directive", type: i1.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "component", type: i4$1.MatExpansionPanel, selector: "mat-expansion-panel", inputs: ["hideToggle", "togglePosition"], outputs: ["afterExpand", "afterCollapse"], exportAs: ["matExpansionPanel"] }, { kind: "component", type: i4$1.MatExpansionPanelHeader, selector: "mat-expansion-panel-header", inputs: ["expandedHeight", "collapsedHeight", "tabIndex"] }, { kind: "directive", type: i4$1.MatExpansionPanelDescription, selector: "mat-panel-description" }, { kind: "component", type: i2
|
|
11605
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.17", type: TruErrorDialog, isStandalone: true, selector: "tru-error-dialog", ngImport: i0, template: "<div mat-dialog-title class=\"tru-error-dialog-title mat-dialog-title\">\r\n <div class=\"mat-dialog-title-container\">\r\n <mat-icon [svgIcon]=\"'error-icon'\"\r\n title=\"Error\">\r\n </mat-icon>\r\n Error - {{title}}\r\n </div>\r\n</div>\r\n\r\n<div mat-dialog-content class=\"mat-dialog-content\">\r\n <div class=\"tru-about-description\">\r\n {{message}}\r\n </div>\r\n <mat-expansion-panel *ngIf=\"stackTrace\"\r\n (opened)=\"panelOpenState.set(true)\"\r\n (closed)=\"panelOpenState.set(false)\">\r\n <mat-expansion-panel-header>\r\n <mat-panel-description>\r\n Show Stack Trace\r\n </mat-panel-description>\r\n </mat-expansion-panel-header>\r\n <p>{{stackTrace}}</p>\r\n </mat-expansion-panel>\r\n</div>\r\n\r\n<div mat-dialog-actions class=\"mat-dialog-actions\">\r\n <button mat-raised-button (click)=\"onDismiss()\">Close</button>\r\n</div>\r\n", styles: ["::ng-deep .mat-mdc-dialog-surface{padding:20px}.mat-mdc-dialog-title:before{content:unset!important;height:unset!important;padding:0 0 10px!important}.mat-dialog-title-container mat-icon{vertical-align:sub;height:24px;width:24px}.mat-dialog-title-container{display:inline}.mdc-dialog__title{padding:0 0 10px!important}.mdc-dialog__content{padding:10px 0 15px!important}.mat-mdc-dialog-content p{margin-bottom:0;font-size:14px;color:#545454}.mat-mdc-dialog-actions{padding:0!important}.mat-mdc-dialog-actions button{margin-right:10px}.tru-about-description{width:550px;height:200px;padding:5px;margin-bottom:5px;border:1px #cbcbcb solid}.mat-expansion-panel{border-radius:0!important}mat-panel-description{font-size:12px;text-decoration:underline;border-radius:0}::ng-deep .tru-error-dialog-title svg{fill:red}::ng-deep .tru-error-dialog-title svg path{fill:red}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: MaterialModule }, { kind: "component", type: i3.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "directive", type: i1.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: i1.MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]", inputs: ["align"] }, { kind: "directive", type: i1.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "component", type: i4$1.MatExpansionPanel, selector: "mat-expansion-panel", inputs: ["hideToggle", "togglePosition"], outputs: ["afterExpand", "afterCollapse"], exportAs: ["matExpansionPanel"] }, { kind: "component", type: i4$1.MatExpansionPanelHeader, selector: "mat-expansion-panel-header", inputs: ["expandedHeight", "collapsedHeight", "tabIndex"] }, { kind: "directive", type: i4$1.MatExpansionPanelDescription, selector: "mat-panel-description" }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatExpansionModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
10951
11606
|
}
|
|
10952
11607
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: TruErrorDialog, decorators: [{
|
|
10953
11608
|
type: Component,
|
|
@@ -11101,7 +11756,7 @@ class TruErrorManager {
|
|
|
11101
11756
|
else
|
|
11102
11757
|
this.handleServerSideError(error);
|
|
11103
11758
|
};
|
|
11104
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: TruErrorManager, deps: [{ token:
|
|
11759
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: TruErrorManager, deps: [{ token: i1$2.HttpClient }, { token: i1.MatDialog }, { token: TruTextManager }, { token: TruUiNotification }, { token: TruComponentLookup }, { token: i0.ComponentFactoryResolver }, { token: i0.ApplicationRef }, { token: i0.Injector }, { token: TruAppEnvironment }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
11105
11760
|
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: TruErrorManager, providedIn: 'root' });
|
|
11106
11761
|
}
|
|
11107
11762
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: TruErrorManager, decorators: [{
|
|
@@ -11109,7 +11764,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
|
|
|
11109
11764
|
args: [{
|
|
11110
11765
|
providedIn: 'root',
|
|
11111
11766
|
}]
|
|
11112
|
-
}], ctorParameters: () => [{ type:
|
|
11767
|
+
}], ctorParameters: () => [{ type: i1$2.HttpClient }, { type: i1.MatDialog }, { type: TruTextManager }, { type: TruUiNotification }, { type: TruComponentLookup }, { type: i0.ComponentFactoryResolver }, { type: i0.ApplicationRef }, { type: i0.Injector }, { type: TruAppEnvironment }] });
|
|
11113
11768
|
|
|
11114
11769
|
class TruErrorInterceptor {
|
|
11115
11770
|
errorManager;
|
|
@@ -11205,7 +11860,7 @@ class TruTab {
|
|
|
11205
11860
|
this.tabGroupEventNotifier.isActive = isActive;
|
|
11206
11861
|
};
|
|
11207
11862
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: TruTab, deps: [{ token: TruTabGroupEventNotifier }], target: i0.ɵɵFactoryTarget.Component });
|
|
11208
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.17", type: TruTab, isStandalone: true, selector: "tru-tab", inputs: { view: "view", label: "label" }, providers: [TruTabGroupEventNotifier], viewQueries: [{ propertyName: "matTab", first: true, predicate: MatTab, descendants: true }], ngImport: i0, template: "<mat-tab [label]=\"label\" [disabled]=\"!view.window.isActive()\">\r\n <ng-content></ng-content>\r\n</mat-tab>\r\n", styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: MatTabsModule }, { kind: "component", type: i2$
|
|
11863
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.17", type: TruTab, isStandalone: true, selector: "tru-tab", inputs: { view: "view", label: "label" }, providers: [TruTabGroupEventNotifier], viewQueries: [{ propertyName: "matTab", first: true, predicate: MatTab, descendants: true }], ngImport: i0, template: "<mat-tab [label]=\"label\" [disabled]=\"!view.window.isActive()\">\r\n <ng-content></ng-content>\r\n</mat-tab>\r\n", styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: MatTabsModule }, { kind: "component", type: i2$2.MatTab, selector: "mat-tab", inputs: ["disabled", "label", "aria-label", "aria-labelledby", "labelClass", "bodyClass", "id"], exportAs: ["matTab"] }], encapsulation: i0.ViewEncapsulation.None });
|
|
11209
11864
|
}
|
|
11210
11865
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: TruTab, decorators: [{
|
|
11211
11866
|
type: Component,
|
|
@@ -11241,7 +11896,7 @@ class TruTabGroup {
|
|
|
11241
11896
|
});
|
|
11242
11897
|
}
|
|
11243
11898
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: TruTabGroup, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
11244
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.17", type: TruTabGroup, isStandalone: true, selector: "tru-tab-group", queries: [{ propertyName: "tabs", predicate: TruTab }], viewQueries: [{ propertyName: "tabGroup", first: true, predicate: MatTabGroup, descendants: true }], ngImport: i0, template: "<mat-tab-group #tabGroup\r\n (selectedTabChange)=\"onChange($event)\"\r\n animationDuration=\"0ms\">\r\n <ng-content #outlet></ng-content>\r\n</mat-tab-group>\r\n", styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: MatTabsModule }, { kind: "component", type: i2$
|
|
11899
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.17", type: TruTabGroup, isStandalone: true, selector: "tru-tab-group", queries: [{ propertyName: "tabs", predicate: TruTab }], viewQueries: [{ propertyName: "tabGroup", first: true, predicate: MatTabGroup, descendants: true }], ngImport: i0, template: "<mat-tab-group #tabGroup\r\n (selectedTabChange)=\"onChange($event)\"\r\n animationDuration=\"0ms\">\r\n <ng-content #outlet></ng-content>\r\n</mat-tab-group>\r\n", styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: MatTabsModule }, { kind: "component", type: i2$2.MatTabGroup, selector: "mat-tab-group", inputs: ["color", "fitInkBarToContent", "mat-stretch-tabs", "mat-align-tabs", "dynamicHeight", "selectedIndex", "headerPosition", "animationDuration", "contentTabIndex", "disablePagination", "disableRipple", "preserveContent", "backgroundColor", "aria-label", "aria-labelledby"], outputs: ["selectedIndexChange", "focusChange", "animationDone", "selectedTabChange"], exportAs: ["matTabGroup"] }], encapsulation: i0.ViewEncapsulation.None });
|
|
11245
11900
|
}
|
|
11246
11901
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: TruTabGroup, decorators: [{
|
|
11247
11902
|
type: Component,
|
|
@@ -11300,7 +11955,7 @@ class TruLogin {
|
|
|
11300
11955
|
}
|
|
11301
11956
|
}
|
|
11302
11957
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: TruLogin, deps: [{ token: TruAuth }, { token: TruAppEnvironment }], target: i0.ɵɵFactoryTarget.Component });
|
|
11303
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.17", type: TruLogin, isStandalone: false, selector: "tru-login", ngImport: i0, template: "<div class=\"login-wrapper\">\r\n <form [formGroup]=\"loginForm\" (ngSubmit)=\"onSubmit()\">\r\n <mat-card class=\"animate-login\">\r\n <mat-card-header>\r\n <mat-card-title> {{title}} </mat-card-title>\r\n </mat-card-header>\r\n <mat-card-content>\r\n <mat-form-field>\r\n <mat-label>Username</mat-label>\r\n <input matInput formControlName=\"username\" placeholder=\"Username\">\r\n </mat-form-field>\r\n <mat-form-field>\r\n <mat-label>Password</mat-label>\r\n <input matInput type=\"password\" formControlName=\"password\" placeholder=\"Password\" [type]=\"passwordVisible ? 'text' : 'password'\">\r\n <button class=\"visibility-button\" [disableRipple]=\"true\" type=\"button\" mat-icon-button matSuffix (click)=\"passwordVisible = !passwordVisible\">\r\n <mat-icon class=\"visibility\" *ngIf=\"passwordVisible\" [svgIcon]=\"'visibility-icon'\">visibility-icon</mat-icon>\r\n <mat-icon class=\"visibility-off\" *ngIf=\"!passwordVisible\" [svgIcon]=\"'visibility-off-icon'\">visibility-off-icon</mat-icon>\r\n </button>\r\n </mat-form-field>\r\n <div *ngIf=\"loginError\" class=\"animate-login-error animated rubberBand\">\r\n <p style=\"color: red; font-weight: bold;\"> {{ loginError }}</p>\r\n </div>\r\n </mat-card-content>\r\n <mat-card-actions>\r\n <button mat-raised-button color=\"primary\" type=\"submit\" [disabled]=\"isDisabled()\">Login</button>\r\n </mat-card-actions>\r\n </mat-card>\r\n </form>\r\n</div>\r\n", styles: [".login-container{display:flex;justify-content:center;align-items:center;height:100vh;margin:0;padding:0}.login-input{margin-bottom:20px}.animate-login{display:flex;flex-direction:column;justify-content:center;align-items:center;height:100%;margin-top:50px}.wrapper{display:flex;justify-content:center;align-items:center;height:100vh}mat-card{max-width:300px;width:100%;max-height:300px;padding:20px}.form-group{width:100%;max-width:400px;margin-bottom:20px}.login-wrapper{display:flex;justify-content:center;align-items:center;height:100vh}::ng-deep .login-wrapper .mat-mdc-text-field-wrapper{padding:0 16px!important}::ng-deep .login-wrapper .mat-mdc-icon-button.mat-mdc-button-base{height:20px;width:20px;padding:0!important}::ng-deep .login-wrapper .mat-icon{height:20px;width:30px;vertical-align:middle}::ng-deep .login-wrapper .material-icons{font-size:18px}::ng-deep .login-wrapper .visibility svg{fill:#006dcc;height:18px;width:18px;margin-top:5px}::ng-deep .login-wrapper .visibility-off svg{fill:#787878;height:18px;width:18px;margin-top:5px}::ng-deep .login-wrapper .visibility-button{--mat-text-button-state-layer-color: none}::ng-deep .login-wrapper button:focus{outline:none!important}::ng-deep .login-wrapper .mat-button-focus-overlay{display:none!important}::ng-deep .login-wrapper .mat-mdc-button-persistent-ripple{display:none!important}\n"], dependencies: [{ kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i3.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: i3.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "component", type: i5$3.MatCard, selector: "mat-card", inputs: ["appearance"], exportAs: ["matCard"] }, { kind: "directive", type: i5$3.MatCardActions, selector: "mat-card-actions", inputs: ["align"], exportAs: ["matCardActions"] }, { kind: "directive", type: i5$3.MatCardContent, selector: "mat-card-content" }, { kind: "component", type: i5$3.MatCardHeader, selector: "mat-card-header" }, { kind: "directive", type: i5$3.MatCardTitle, selector: "mat-card-title, [mat-card-title], [matCardTitle]" }, { kind: "component", type: i2
|
|
11958
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.17", type: TruLogin, isStandalone: false, selector: "tru-login", ngImport: i0, template: "<div class=\"login-wrapper\">\r\n <form [formGroup]=\"loginForm\" (ngSubmit)=\"onSubmit()\">\r\n <mat-card class=\"animate-login\">\r\n <mat-card-header>\r\n <mat-card-title> {{title}} </mat-card-title>\r\n </mat-card-header>\r\n <mat-card-content>\r\n <mat-form-field>\r\n <mat-label>Username</mat-label>\r\n <input matInput formControlName=\"username\" placeholder=\"Username\">\r\n </mat-form-field>\r\n <mat-form-field>\r\n <mat-label>Password</mat-label>\r\n <input matInput type=\"password\" formControlName=\"password\" placeholder=\"Password\" [type]=\"passwordVisible ? 'text' : 'password'\">\r\n <button class=\"visibility-button\" [disableRipple]=\"true\" type=\"button\" mat-icon-button matSuffix (click)=\"passwordVisible = !passwordVisible\">\r\n <mat-icon class=\"visibility\" *ngIf=\"passwordVisible\" [svgIcon]=\"'visibility-icon'\">visibility-icon</mat-icon>\r\n <mat-icon class=\"visibility-off\" *ngIf=\"!passwordVisible\" [svgIcon]=\"'visibility-off-icon'\">visibility-off-icon</mat-icon>\r\n </button>\r\n </mat-form-field>\r\n <div *ngIf=\"loginError\" class=\"animate-login-error animated rubberBand\">\r\n <p style=\"color: red; font-weight: bold;\"> {{ loginError }}</p>\r\n </div>\r\n </mat-card-content>\r\n <mat-card-actions>\r\n <button mat-raised-button color=\"primary\" type=\"submit\" [disabled]=\"isDisabled()\">Login</button>\r\n </mat-card-actions>\r\n </mat-card>\r\n </form>\r\n</div>\r\n", styles: [".login-container{display:flex;justify-content:center;align-items:center;height:100vh;margin:0;padding:0}.login-input{margin-bottom:20px}.animate-login{display:flex;flex-direction:column;justify-content:center;align-items:center;height:100%;margin-top:50px}.wrapper{display:flex;justify-content:center;align-items:center;height:100vh}mat-card{max-width:300px;width:100%;max-height:300px;padding:20px}.form-group{width:100%;max-width:400px;margin-bottom:20px}.login-wrapper{display:flex;justify-content:center;align-items:center;height:100vh}::ng-deep .login-wrapper .mat-mdc-text-field-wrapper{padding:0 16px!important}::ng-deep .login-wrapper .mat-mdc-icon-button.mat-mdc-button-base{height:20px;width:20px;padding:0!important}::ng-deep .login-wrapper .mat-icon{height:20px;width:30px;vertical-align:middle}::ng-deep .login-wrapper .material-icons{font-size:18px}::ng-deep .login-wrapper .visibility svg{fill:#006dcc;height:18px;width:18px;margin-top:5px}::ng-deep .login-wrapper .visibility-off svg{fill:#787878;height:18px;width:18px;margin-top:5px}::ng-deep .login-wrapper .visibility-button{--mat-text-button-state-layer-color: none}::ng-deep .login-wrapper button:focus{outline:none!important}::ng-deep .login-wrapper .mat-button-focus-overlay{display:none!important}::ng-deep .login-wrapper .mat-mdc-button-persistent-ripple{display:none!important}\n"], dependencies: [{ kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i3.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: i3.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "component", type: i5$3.MatCard, selector: "mat-card", inputs: ["appearance"], exportAs: ["matCard"] }, { kind: "directive", type: i5$3.MatCardActions, selector: "mat-card-actions", inputs: ["align"], exportAs: ["matCardActions"] }, { kind: "directive", type: i5$3.MatCardContent, selector: "mat-card-content" }, { kind: "component", type: i5$3.MatCardHeader, selector: "mat-card-header" }, { kind: "directive", type: i5$3.MatCardTitle, selector: "mat-card-title, [mat-card-title], [matCardTitle]" }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: i7.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "component", type: i7.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i7.MatLabel, selector: "mat-label" }, { kind: "directive", type: i7.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "directive", type: i8.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i8.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: i8.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i8.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i8.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i8.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }] });
|
|
11304
11959
|
}
|
|
11305
11960
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: TruLogin, decorators: [{
|
|
11306
11961
|
type: Component,
|
|
@@ -11407,6 +12062,43 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
|
|
|
11407
12062
|
args: [TRU_AUTH_STRATEGY]
|
|
11408
12063
|
}] }] });
|
|
11409
12064
|
|
|
12065
|
+
class TruServerTouchInterceptor {
|
|
12066
|
+
appEnvironment;
|
|
12067
|
+
tracker;
|
|
12068
|
+
constructor(appEnvironment, tracker) {
|
|
12069
|
+
this.appEnvironment = appEnvironment;
|
|
12070
|
+
this.tracker = tracker;
|
|
12071
|
+
}
|
|
12072
|
+
intercept(request, next) {
|
|
12073
|
+
return next.handle(request).pipe(tap((event) => {
|
|
12074
|
+
if (!(event instanceof HttpResponse))
|
|
12075
|
+
return;
|
|
12076
|
+
if (event.status >= 400)
|
|
12077
|
+
return;
|
|
12078
|
+
if (this.appEnvironment.authType !== 'session')
|
|
12079
|
+
return;
|
|
12080
|
+
if (!this.isApiRequest(request.url))
|
|
12081
|
+
return;
|
|
12082
|
+
this.tracker.recordServerTouch(Date.now());
|
|
12083
|
+
}));
|
|
12084
|
+
}
|
|
12085
|
+
isApiRequest(url) {
|
|
12086
|
+
try {
|
|
12087
|
+
const base = this.appEnvironment.appUri || window.location.origin;
|
|
12088
|
+
const parsed = new URL(url, base);
|
|
12089
|
+
return parsed.pathname.includes('/api/');
|
|
12090
|
+
}
|
|
12091
|
+
catch {
|
|
12092
|
+
return url.includes('/api/');
|
|
12093
|
+
}
|
|
12094
|
+
}
|
|
12095
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: TruServerTouchInterceptor, deps: [{ token: TruAppEnvironment }, { token: TruServerTouchTracker }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
12096
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: TruServerTouchInterceptor });
|
|
12097
|
+
}
|
|
12098
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: TruServerTouchInterceptor, decorators: [{
|
|
12099
|
+
type: Injectable
|
|
12100
|
+
}], ctorParameters: () => [{ type: TruAppEnvironment }, { type: TruServerTouchTracker }] });
|
|
12101
|
+
|
|
11410
12102
|
class TruAuthSessionStrategy {
|
|
11411
12103
|
http;
|
|
11412
12104
|
loggedUser;
|
|
@@ -11450,13 +12142,18 @@ const routes = [
|
|
|
11450
12142
|
];
|
|
11451
12143
|
class TruLoginModule {
|
|
11452
12144
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: TruLoginModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
11453
|
-
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "19.2.17", ngImport: i0, type: TruLoginModule, declarations: [TruLogin], imports: [CommonModule, MaterialModule, FormsModule, ReactiveFormsModule, i1$
|
|
12145
|
+
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "19.2.17", ngImport: i0, type: TruLoginModule, declarations: [TruLogin], imports: [CommonModule, MaterialModule, FormsModule, ReactiveFormsModule, i1$5.RouterModule], exports: [TruLogin] });
|
|
11454
12146
|
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: TruLoginModule, providers: [
|
|
11455
12147
|
{
|
|
11456
12148
|
provide: HTTP_INTERCEPTORS,
|
|
11457
12149
|
useClass: TruAuthInterceptor,
|
|
11458
12150
|
multi: true,
|
|
11459
12151
|
},
|
|
12152
|
+
{
|
|
12153
|
+
provide: HTTP_INTERCEPTORS,
|
|
12154
|
+
useClass: TruServerTouchInterceptor,
|
|
12155
|
+
multi: true,
|
|
12156
|
+
},
|
|
11460
12157
|
{
|
|
11461
12158
|
provide: HTTP_INTERCEPTORS,
|
|
11462
12159
|
useClass: TruErrorInterceptor,
|
|
@@ -11477,6 +12174,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
|
|
|
11477
12174
|
useClass: TruAuthInterceptor,
|
|
11478
12175
|
multi: true,
|
|
11479
12176
|
},
|
|
12177
|
+
{
|
|
12178
|
+
provide: HTTP_INTERCEPTORS,
|
|
12179
|
+
useClass: TruServerTouchInterceptor,
|
|
12180
|
+
multi: true,
|
|
12181
|
+
},
|
|
11480
12182
|
{
|
|
11481
12183
|
provide: HTTP_INTERCEPTORS,
|
|
11482
12184
|
useClass: TruErrorInterceptor,
|
|
@@ -13516,7 +14218,7 @@ class TruSearchIconModule {
|
|
|
13516
14218
|
iconRegistry.addSvgIconLiteral("less-than-or-equal-operator-icon", sanitizer.bypassSecurityTrustHtml(LESS_THAN_OR_EQUAL_ICON));
|
|
13517
14219
|
iconRegistry.addSvgIconLiteral("contains-operator-icon", sanitizer.bypassSecurityTrustHtml(CONTAINS_ICON));
|
|
13518
14220
|
}
|
|
13519
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: TruSearchIconModule, deps: [{ token: i1$
|
|
14221
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: TruSearchIconModule, deps: [{ token: i1$6.DomSanitizer }, { token: i2.MatIconRegistry }], target: i0.ɵɵFactoryTarget.NgModule });
|
|
13520
14222
|
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "19.2.17", ngImport: i0, type: TruSearchIconModule, imports: [CommonModule, FormsModule] });
|
|
13521
14223
|
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: TruSearchIconModule, imports: [CommonModule, FormsModule] });
|
|
13522
14224
|
}
|
|
@@ -13527,7 +14229,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
|
|
|
13527
14229
|
declarations: [],
|
|
13528
14230
|
exports: []
|
|
13529
14231
|
}]
|
|
13530
|
-
}], ctorParameters: () => [{ type: i1$
|
|
14232
|
+
}], ctorParameters: () => [{ type: i1$6.DomSanitizer }, { type: i2.MatIconRegistry }] });
|
|
13531
14233
|
|
|
13532
14234
|
class TruCommonModule {
|
|
13533
14235
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: TruCommonModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|