@trudb/tru-common-lib 0.2.461 → 0.2.463

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.
@@ -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 i2 from '@angular/common/http';
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$1 from '@angular/material/icon';
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$6 from '@angular/material/progress-spinner';
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$3 from '@angular/material/select';
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$3 from '@angular/material/tabs';
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$2 from '@angular/cdk/overlay';
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$2 from 'ngx-toastr';
74
- import { tap, catchError } from 'rxjs/operators';
75
- import * as i1$4 from '@angular/router';
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$5 from '@angular/platform-browser';
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: i2.HttpClient }, { token: TruAppEnvironment }, { token: TruUiNotification }, { token: MAT_DIALOG_DATA }], target: i0.ɵɵFactoryTarget.Component });
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: i2.HttpClient }, { type: TruAppEnvironment }, { type: TruUiNotification }, { type: undefined, decorators: [{
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$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }] });
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
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: TruUiNotification, deps: [{ token: i1$2.ToastrService }, { token: i1.MatDialog }], target: i0.ɵɵFactoryTarget.Injectable });
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$2.ToastrService }, { type: i1.MatDialog }] });
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: i2.HttpClient }, { token: TruAppEnvironment }, { token: TruUiNotification }, { token: TruTextManager }, { token: TruUser }], target: i0.ɵɵFactoryTarget.Injectable });
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: i2.HttpClient }, { type: TruAppEnvironment }, { type: TruUiNotification }, { type: TruTextManager }, { type: TruUser }] });
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: i2.HttpClient }, { token: TruUiNotification }], target: i0.ɵɵFactoryTarget.Component });
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: i2.HttpClient }, { type: TruUiNotification }], propDecorators: { view: [{
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$3.MatSelect }, { token: TruUtil }], target: i0.ɵɵFactoryTarget.Directive });
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$3.MatSelect }, { type: TruUtil }] });
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$4.Router }, { token: i2.HttpClient }, { token: TruAuthCache }, { token: TruUser }, { token: TruAppEnvironment }, { token: TRU_AUTH_STRATEGY }], target: i0.ɵɵFactoryTarget.Injectable });
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$4.Router }, { type: i2.HttpClient }, { type: TruAuthCache }, { type: TruUser }, { type: TruAppEnvironment }, { type: undefined, decorators: [{
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$5.DomSanitizer }, { token: i2$1.MatIconRegistry }], target: i0.ɵɵFactoryTarget.NgModule });
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$5.DomSanitizer }, { type: i2$1.MatIconRegistry }] });
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$1.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" }] });
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$1.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 });
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$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }] });
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$1.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"] }] });
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$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }] });
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$6.MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "mode", "value", "diameter", "strokeWidth"], exportAs: ["matProgressSpinner"] }] });
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,
@@ -7627,7 +8286,7 @@ class TruDataChangeParser {
7627
8286
  update = async (payload) => {
7628
8287
  await this.isSaving();
7629
8288
  var reloadResults = false;
7630
- payload.changes.filter((change) => { return change.modifiedRef !== this.user.activeUserRef; }).forEach(async (change) => {
8289
+ payload.changes.forEach(async (change) => {
7631
8290
  var foundEntities = [];
7632
8291
  var localEntity = this.findEntityInCache(change);
7633
8292
  var globalEntity = this.findEntityInGlobalCache(change);
@@ -9166,12 +9825,12 @@ class TruActionInvoke {
9166
9825
  refs: actionRefs,
9167
9826
  });
9168
9827
  };
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: i2.HttpClient }, { token: TruComponentLookup }, { token: TruModelTypeLookup }, { token: TruGlobalDataContext }, { token: TruUser }], target: i0.ɵɵFactoryTarget.Injectable });
9828
+ 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
9829
  static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: TruActionInvoke });
9171
9830
  }
9172
9831
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: TruActionInvoke, decorators: [{
9173
9832
  type: Injectable
9174
- }], ctorParameters: () => [{ type: TruDataContext }, { type: TruTextManager }, { type: TruDesktopManager }, { type: TruWindowEventHandler }, { type: TruUiNotification }, { type: TruAppEnvironment }, { type: i2.HttpClient }, { type: TruComponentLookup }, { type: TruModelTypeLookup }, { type: TruGlobalDataContext }, { type: TruUser }] });
9833
+ }], 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
9834
 
9176
9835
  class TruReportManager {
9177
9836
  dataContext;
@@ -9520,7 +10179,7 @@ class TruDesktopWindowStateMonitor {
9520
10179
  this.tabListener();
9521
10180
  this.focusListener();
9522
10181
  }
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$2.OverlayContainer }], target: i0.ɵɵFactoryTarget.Directive });
10182
+ 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
10183
  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
10184
  }
9526
10185
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: TruDesktopWindowStateMonitor, decorators: [{
@@ -9528,7 +10187,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
9528
10187
  args: [{
9529
10188
  selector: '[truDesktopWindowStateMonitor]'
9530
10189
  }]
9531
- }], ctorParameters: () => [{ type: i0.ElementRef }, { type: i0.Renderer2 }, { type: TruWindowEventHandler }, { type: i2$2.OverlayContainer }], propDecorators: { active: [{
10190
+ }], ctorParameters: () => [{ type: i0.ElementRef }, { type: i0.Renderer2 }, { type: TruWindowEventHandler }, { type: i2$1.OverlayContainer }], propDecorators: { active: [{
9532
10191
  type: Input,
9533
10192
  args: ['truDesktopWindowStateMonitor']
9534
10193
  }] } });
@@ -10947,7 +11606,7 @@ class TruErrorDialog {
10947
11606
  this.dialogRef.close(false);
10948
11607
  }
10949
11608
  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$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatExpansionModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
11609
+ 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
11610
  }
10952
11611
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: TruErrorDialog, decorators: [{
10953
11612
  type: Component,
@@ -11101,7 +11760,7 @@ class TruErrorManager {
11101
11760
  else
11102
11761
  this.handleServerSideError(error);
11103
11762
  };
11104
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: TruErrorManager, deps: [{ token: i2.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 });
11763
+ 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
11764
  static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: TruErrorManager, providedIn: 'root' });
11106
11765
  }
11107
11766
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: TruErrorManager, decorators: [{
@@ -11109,7 +11768,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
11109
11768
  args: [{
11110
11769
  providedIn: 'root',
11111
11770
  }]
11112
- }], ctorParameters: () => [{ type: i2.HttpClient }, { type: i1.MatDialog }, { type: TruTextManager }, { type: TruUiNotification }, { type: TruComponentLookup }, { type: i0.ComponentFactoryResolver }, { type: i0.ApplicationRef }, { type: i0.Injector }, { type: TruAppEnvironment }] });
11771
+ }], 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
11772
 
11114
11773
  class TruErrorInterceptor {
11115
11774
  errorManager;
@@ -11205,7 +11864,7 @@ class TruTab {
11205
11864
  this.tabGroupEventNotifier.isActive = isActive;
11206
11865
  };
11207
11866
  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$3.MatTab, selector: "mat-tab", inputs: ["disabled", "label", "aria-label", "aria-labelledby", "labelClass", "bodyClass", "id"], exportAs: ["matTab"] }], encapsulation: i0.ViewEncapsulation.None });
11867
+ 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
11868
  }
11210
11869
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: TruTab, decorators: [{
11211
11870
  type: Component,
@@ -11241,7 +11900,7 @@ class TruTabGroup {
11241
11900
  });
11242
11901
  }
11243
11902
  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$3.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 });
11903
+ 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
11904
  }
11246
11905
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: TruTabGroup, decorators: [{
11247
11906
  type: Component,
@@ -11300,7 +11959,7 @@ class TruLogin {
11300
11959
  }
11301
11960
  }
11302
11961
  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$1.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"] }] });
11962
+ 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
11963
  }
11305
11964
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: TruLogin, decorators: [{
11306
11965
  type: Component,
@@ -11407,6 +12066,43 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
11407
12066
  args: [TRU_AUTH_STRATEGY]
11408
12067
  }] }] });
11409
12068
 
12069
+ class TruServerTouchInterceptor {
12070
+ appEnvironment;
12071
+ tracker;
12072
+ constructor(appEnvironment, tracker) {
12073
+ this.appEnvironment = appEnvironment;
12074
+ this.tracker = tracker;
12075
+ }
12076
+ intercept(request, next) {
12077
+ return next.handle(request).pipe(tap((event) => {
12078
+ if (!(event instanceof HttpResponse))
12079
+ return;
12080
+ if (event.status >= 400)
12081
+ return;
12082
+ if (this.appEnvironment.authType !== 'session')
12083
+ return;
12084
+ if (!this.isApiRequest(request.url))
12085
+ return;
12086
+ this.tracker.recordServerTouch(Date.now());
12087
+ }));
12088
+ }
12089
+ isApiRequest(url) {
12090
+ try {
12091
+ const base = this.appEnvironment.appUri || window.location.origin;
12092
+ const parsed = new URL(url, base);
12093
+ return parsed.pathname.includes('/api/');
12094
+ }
12095
+ catch {
12096
+ return url.includes('/api/');
12097
+ }
12098
+ }
12099
+ 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 });
12100
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: TruServerTouchInterceptor });
12101
+ }
12102
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: TruServerTouchInterceptor, decorators: [{
12103
+ type: Injectable
12104
+ }], ctorParameters: () => [{ type: TruAppEnvironment }, { type: TruServerTouchTracker }] });
12105
+
11410
12106
  class TruAuthSessionStrategy {
11411
12107
  http;
11412
12108
  loggedUser;
@@ -11450,13 +12146,18 @@ const routes = [
11450
12146
  ];
11451
12147
  class TruLoginModule {
11452
12148
  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$4.RouterModule], exports: [TruLogin] });
12149
+ 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
12150
  static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: TruLoginModule, providers: [
11455
12151
  {
11456
12152
  provide: HTTP_INTERCEPTORS,
11457
12153
  useClass: TruAuthInterceptor,
11458
12154
  multi: true,
11459
12155
  },
12156
+ {
12157
+ provide: HTTP_INTERCEPTORS,
12158
+ useClass: TruServerTouchInterceptor,
12159
+ multi: true,
12160
+ },
11460
12161
  {
11461
12162
  provide: HTTP_INTERCEPTORS,
11462
12163
  useClass: TruErrorInterceptor,
@@ -11477,6 +12178,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
11477
12178
  useClass: TruAuthInterceptor,
11478
12179
  multi: true,
11479
12180
  },
12181
+ {
12182
+ provide: HTTP_INTERCEPTORS,
12183
+ useClass: TruServerTouchInterceptor,
12184
+ multi: true,
12185
+ },
11480
12186
  {
11481
12187
  provide: HTTP_INTERCEPTORS,
11482
12188
  useClass: TruErrorInterceptor,
@@ -13516,7 +14222,7 @@ class TruSearchIconModule {
13516
14222
  iconRegistry.addSvgIconLiteral("less-than-or-equal-operator-icon", sanitizer.bypassSecurityTrustHtml(LESS_THAN_OR_EQUAL_ICON));
13517
14223
  iconRegistry.addSvgIconLiteral("contains-operator-icon", sanitizer.bypassSecurityTrustHtml(CONTAINS_ICON));
13518
14224
  }
13519
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: TruSearchIconModule, deps: [{ token: i1$5.DomSanitizer }, { token: i2$1.MatIconRegistry }], target: i0.ɵɵFactoryTarget.NgModule });
14225
+ 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
14226
  static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "19.2.17", ngImport: i0, type: TruSearchIconModule, imports: [CommonModule, FormsModule] });
13521
14227
  static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: TruSearchIconModule, imports: [CommonModule, FormsModule] });
13522
14228
  }
@@ -13527,7 +14233,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
13527
14233
  declarations: [],
13528
14234
  exports: []
13529
14235
  }]
13530
- }], ctorParameters: () => [{ type: i1$5.DomSanitizer }, { type: i2$1.MatIconRegistry }] });
14236
+ }], ctorParameters: () => [{ type: i1$6.DomSanitizer }, { type: i2.MatIconRegistry }] });
13531
14237
 
13532
14238
  class TruCommonModule {
13533
14239
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: TruCommonModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });