@sumaris-net/ngx-components 18.5.6 → 18.5.8

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.
@@ -68,7 +68,7 @@ import { MatCardModule } from '@angular/material/card';
68
68
  import * as i7$1 from '@angular/material/tabs';
69
69
  import { MatTabsModule } from '@angular/material/tabs';
70
70
  import { MatListModule } from '@angular/material/list';
71
- import * as i6$6 from '@angular/material/progress-spinner';
71
+ import * as i6$5 from '@angular/material/progress-spinner';
72
72
  import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
73
73
  import * as i3$4 from '@angular/material/progress-bar';
74
74
  import { MatProgressBarModule } from '@angular/material/progress-bar';
@@ -108,11 +108,11 @@ import { AudioManagement } from '@ionic-native/audio-management/ngx';
108
108
  import { Haptics } from '@capacitor/haptics';
109
109
  import { NativeAudio } from '@capacitor-community/native-audio';
110
110
  import * as i2$4 from '@angular/common/http';
111
- import { HttpEventType, HttpClient, HttpHeaders, HttpResponse, provideHttpClient, withInterceptorsFromDi } from '@angular/common/http';
111
+ import { HttpEventType, HttpClient, HttpHeaders, HttpErrorResponse, HttpResponse, provideHttpClient, withInterceptorsFromDi } from '@angular/common/http';
112
112
  import { v4 } from 'uuid';
113
- import * as i6$5 from '@angular/cdk/drag-drop';
113
+ import * as i6$4 from '@angular/cdk/drag-drop';
114
114
  import { DragDropModule } from '@angular/cdk/drag-drop';
115
- import * as i6$4 from 'ngx-markdown';
115
+ import * as i7$2 from 'ngx-markdown';
116
116
  import { MarkdownModule } from 'ngx-markdown';
117
117
  import * as i13$1 from '@ionic-native/downloader/ngx';
118
118
  import { NotificationVisibility } from '@ionic-native/downloader/ngx';
@@ -205,8 +205,10 @@ class Environment {
205
205
  // About
206
206
  sourceUrl;
207
207
  reportIssueUrl;
208
- forumUrl;
209
- helpUrl;
208
+ forumUrl; // TODO allow a map by locale ? ex: { [lang: string]: string };
209
+ helpUrl; // TODO allow a map by locale ?
210
+ privacyPolicyUrl; // TODO allow a map by locale ?
211
+ termsOfUseUrl; // TODO allow a map by locale ?
210
212
  // Default authentication /!\ For DEV only
211
213
  // (see values in the test database - XML files in Pod's module)
212
214
  defaultAuthValues;
@@ -11848,6 +11850,8 @@ const environment = Object.freeze({
11848
11850
  reportIssueUrl: 'https://gitlab.ifremer.fr/sih-public/sumaris/ngx-sumaris-components/-/issues',
11849
11851
  forumUrl: null, //'https://forum.sumaris.net',
11850
11852
  helpUrl: 'https://gitlab.ifremer.fr/sih-public/sumaris/sumaris-doc/-/blob/master/user-manual/index_fr.md',
11853
+ privacyPolicyUrl: 'https://gitlab.ifremer.fr/sih-public/sumaris/sumaris-app/-/raw/master/doc/privacy_policy_fr.md?ref_type=heads',
11854
+ termsOfUseUrl: 'https://gitlab.ifremer.fr/sih-public/sumaris/sumaris-app/-/raw/master/doc/terms_of_use_fr.md?ref_type=heads',
11851
11855
  // Development
11852
11856
  defaultAuthValues: {
11853
11857
  // Token auth (using Person.pubkey)
@@ -15706,6 +15710,16 @@ const CORE_CONFIG_OPTIONS = Object.freeze({
15706
15710
  label: 'CONFIGURATION.OPTIONS.REPORT_ISSUE_URL',
15707
15711
  type: 'string',
15708
15712
  },
15713
+ PRIVACY_POLICY_URL: {
15714
+ key: 'sumaris.policy.url',
15715
+ label: 'CONFIGURATION.OPTIONS.PRIVACY_POLICY_URL',
15716
+ type: 'string',
15717
+ },
15718
+ TERMS_OF_USE_URL: {
15719
+ key: 'sumaris.termsOfUse.url',
15720
+ label: 'CONFIGURATION.OPTIONS.TERMS_OF_USE_URL',
15721
+ type: 'string',
15722
+ },
15709
15723
  LOGO_LARGE: {
15710
15724
  key: 'sumaris.logo.large',
15711
15725
  label: 'CONFIGURATION.OPTIONS.HOME.LOGO_LARGE',
@@ -22628,10 +22642,10 @@ class PlatformService extends StartableService {
22628
22642
  cache;
22629
22643
  audioProvider;
22630
22644
  environment;
22631
- loggingService;
22632
22645
  downloader;
22633
22646
  _logger;
22634
22647
  _mobile;
22648
+ _desktop;
22635
22649
  _cordova;
22636
22650
  _capacitor;
22637
22651
  _android;
@@ -22652,7 +22666,6 @@ class PlatformService extends StartableService {
22652
22666
  this.cache = cache;
22653
22667
  this.audioProvider = audioProvider;
22654
22668
  this.environment = environment;
22655
- this.loggingService = loggingService;
22656
22669
  this.downloader = downloader;
22657
22670
  this._logger = loggingService?.getLogger('platform');
22658
22671
  this._debug = !environment.production;
@@ -22711,6 +22724,9 @@ class PlatformService extends StartableService {
22711
22724
  isIOS() {
22712
22725
  return this._ios || false;
22713
22726
  }
22727
+ isMacOSDesktop() {
22728
+ return this._desktop && this.isCordova();
22729
+ }
22714
22730
  /**
22715
22731
  * Is a native App (and NOT a mobile web)
22716
22732
  */
@@ -22742,11 +22758,12 @@ class PlatformService extends StartableService {
22742
22758
  this._logger?.info('ngOnStart', 'Starting platform...');
22743
22759
  try {
22744
22760
  this._mobile = this.is('mobile');
22761
+ this._desktop = this.is('desktop');
22745
22762
  this._cordova = this.is('cordova');
22746
22763
  this._capacitor = this.is('capacitor');
22747
22764
  this._android = this.is('android');
22748
22765
  this._ios = this.is('ios');
22749
- const logMessage = `Detected {mobile: ${this._mobile}, cordova: ${this._cordova}, capacitor: ${this._capacitor}, android: ${this._android}, ios: ${this._ios}}`;
22766
+ const logMessage = `Detected {mobile: ${this._mobile}, desktop: ${this._desktop}, cordova: ${this._cordova}, capacitor: ${this._capacitor}, android: ${this._android}, ios: ${this._ios}}`;
22750
22767
  console.info('[platform] ' + logMessage);
22751
22768
  this._logger?.info('ngOnStart', logMessage);
22752
22769
  // Configure theme
@@ -22786,12 +22803,14 @@ class PlatformService extends StartableService {
22786
22803
  this.accountService.apiTokenEnabled = authApiEnabled;
22787
22804
  }
22788
22805
  }));
22789
- if (this._mobile) {
22806
+ if (this._mobile || this.isMacOSDesktop()) {
22790
22807
  // Hide the splashscreen (if mobile) - after 1s - and play start sound
22791
22808
  setTimeout(async () => {
22792
22809
  await SplashScreen.hide();
22793
22810
  // Play startup sound
22794
- this.audioProvider.playStartupSound();
22811
+ if (this._mobile) {
22812
+ await this.audioProvider.playStartupSound();
22813
+ }
22795
22814
  }, 1000);
22796
22815
  }
22797
22816
  // Check if new version, every 1 min
@@ -23207,12 +23226,24 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImpo
23207
23226
  type: Output
23208
23227
  }] } });
23209
23228
 
23229
+ class AppHelpModalUtils {
23230
+ static async show(modalCtrl, options) {
23231
+ const modal = await modalCtrl.create({
23232
+ component: AppHelpModal,
23233
+ componentProps: options,
23234
+ keyboardClose: true,
23235
+ cssClass: 'modal-large',
23236
+ });
23237
+ await modal.present();
23238
+ }
23239
+ }
23210
23240
  class AppHelpModal {
23211
23241
  injector;
23212
23242
  viewCtrl;
23213
23243
  platform;
23214
23244
  settings;
23215
23245
  translate;
23246
+ network;
23216
23247
  cd;
23217
23248
  debug;
23218
23249
  loading = true;
@@ -23221,12 +23252,13 @@ class AppHelpModal {
23221
23252
  showError = true;
23222
23253
  markdownContent;
23223
23254
  markdownUrl;
23224
- constructor(injector, viewCtrl, platform, settings, translate, cd) {
23255
+ constructor(injector, viewCtrl, platform, settings, translate, network, cd) {
23225
23256
  this.injector = injector;
23226
23257
  this.viewCtrl = viewCtrl;
23227
23258
  this.platform = platform;
23228
23259
  this.settings = settings;
23229
23260
  this.translate = translate;
23261
+ this.network = network;
23230
23262
  this.cd = cd;
23231
23263
  // TODO: for DEV only
23232
23264
  //this.debug = !environment.production;
@@ -23240,18 +23272,26 @@ class AppHelpModal {
23240
23272
  this.cd.markForCheck();
23241
23273
  }
23242
23274
  onLoadError(error) {
23243
- console.error(error);
23244
- this.error = error instanceof Error ? error.message : error;
23275
+ console.error('[help-modal] Error loading help content: ', error);
23276
+ // Translate error
23277
+ if (error instanceof HttpErrorResponse && this.network.offline) {
23278
+ console.error('[help-modal] Error loading help content (offline: true): ', error);
23279
+ this.error = 'NETWORK.INFO.OFFLINE';
23280
+ }
23281
+ else {
23282
+ console.error('[help-modal] Error loading help content: ', error);
23283
+ this.error = 'ERROR.LOAD_DATA_ERROR';
23284
+ }
23245
23285
  this.loading = false;
23246
23286
  this.cd.markForCheck();
23247
23287
  }
23248
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: AppHelpModal, deps: [{ token: i0.Injector }, { token: i2$1.ModalController }, { token: PlatformService }, { token: LocalSettingsService }, { token: i1$1.TranslateService }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
23249
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: AppHelpModal, selector: "app-help-modal", inputs: { title: "title", showError: "showError", markdownContent: "markdownContent", markdownUrl: "markdownUrl" }, ngImport: i0, template: "<app-modal-toolbar\n color=\"light\"\n [title]=\"title | translate\"\n (cancel)=\"close($event)\"\n [showSpinner]=\"loading\"\n></app-modal-toolbar>\n\n<ion-content class=\"ion-padding\">\n <!-- error -->\n <ion-item *ngIf=\"error && showError\" lines=\"none\">\n <ion-icon color=\"danger\" slot=\"start\" name=\"alert-circle\"></ion-icon>\n <ion-label color=\"danger\" class=\"error\" [innerHTML]=\"error | translate\"></ion-label>\n </ion-item>\n\n <markdown *ngIf=\"markdownContent; else useDocUrl\" [data]=\"markdownContent\" (ready)=\"markAsLoaded()\" emoji></markdown>\n\n <ng-template #useDocUrl>\n <markdown\n *ngIf=\"markdownUrl\"\n [src]=\"markdownUrl\"\n (load)=\"markAsLoaded()\"\n (error)=\"onLoadError($event)\"\n emoji\n ></markdown>\n </ng-template>\n</ion-content>\n\n<ion-footer hidden-xs hidden-sm hidden-mobile>\n <ion-toolbar>\n <ion-row class=\"ion-no-padding\" nowrap>\n <ion-col></ion-col>\n <ion-col size=\"auto\">\n <ion-button fill=\"solid\" color=\"tertiary\" (click)=\"close()\">{{ 'COMMON.BTN_CLOSE' | translate }}</ion-button>\n </ion-col>\n </ion-row>\n </ion-toolbar>\n</ion-footer>\n", dependencies: [{ kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i2$1.IonButton, selector: "ion-button", inputs: ["buttonType", "color", "disabled", "download", "expand", "fill", "form", "href", "mode", "rel", "routerAnimation", "routerDirection", "shape", "size", "strong", "target", "type"] }, { kind: "component", type: i2$1.IonCol, selector: "ion-col", inputs: ["offset", "offsetLg", "offsetMd", "offsetSm", "offsetXl", "offsetXs", "pull", "pullLg", "pullMd", "pullSm", "pullXl", "pullXs", "push", "pushLg", "pushMd", "pushSm", "pushXl", "pushXs", "size", "sizeLg", "sizeMd", "sizeSm", "sizeXl", "sizeXs"] }, { kind: "component", type: i2$1.IonContent, selector: "ion-content", inputs: ["color", "forceOverscroll", "fullscreen", "scrollEvents", "scrollX", "scrollY"] }, { kind: "component", type: i2$1.IonFooter, selector: "ion-footer", inputs: ["collapse", "mode", "translucent"] }, { kind: "component", type: i2$1.IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: i2$1.IonItem, selector: "ion-item", inputs: ["button", "color", "counter", "counterFormatter", "detail", "detailIcon", "disabled", "download", "fill", "href", "lines", "mode", "rel", "routerAnimation", "routerDirection", "shape", "target", "type"] }, { kind: "component", type: i2$1.IonLabel, selector: "ion-label", inputs: ["color", "mode", "position"] }, { kind: "component", type: i2$1.IonRow, selector: "ion-row" }, { kind: "component", type: i2$1.IonToolbar, selector: "ion-toolbar", inputs: ["color", "mode"] }, { kind: "component", type: i6$4.MarkdownComponent, selector: "markdown, [markdown]", inputs: ["data", "src", "disableSanitizer", "inline", "clipboard", "clipboardButtonComponent", "clipboardButtonTemplate", "emoji", "katex", "katexOptions", "mermaid", "mermaidOptions", "lineHighlight", "line", "lineOffset", "lineNumbers", "start", "commandLine", "filterOutput", "host", "prompt", "output", "user"], outputs: ["error", "load", "ready"] }, { kind: "component", type: ModalToolbarComponent, selector: "app-modal-toolbar", inputs: ["modalName", "title", "color", "showSpinner", "canValidate", "validateIcon"], outputs: ["cancel", "validate"] }, { kind: "pipe", type: i1$1.TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
23288
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: AppHelpModal, deps: [{ token: i0.Injector }, { token: i2$1.ModalController }, { token: PlatformService }, { token: LocalSettingsService }, { token: i1$1.TranslateService }, { token: NetworkService }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
23289
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: AppHelpModal, selector: "app-help-modal", inputs: { title: "title", showError: "showError", markdownContent: "markdownContent", markdownUrl: "markdownUrl" }, ngImport: i0, template: "@if (title) {\n <app-modal-toolbar\n color=\"light\"\n [title]=\"title | translate\"\n (cancel)=\"close($event)\"\n [showSpinner]=\"loading\"\n ></app-modal-toolbar>\n}\n\n<ion-content class=\"ion-padding\">\n <!-- error -->\n <ion-item *ngIf=\"showError && error\" lines=\"none\">\n <ion-icon color=\"danger\" slot=\"start\" name=\"alert-circle\"></ion-icon>\n <ion-label color=\"danger\" class=\"error\" [innerHTML]=\"error | translate\"></ion-label>\n </ion-item>\n\n <markdown *ngIf=\"markdownContent; else useDocUrl\" [data]=\"markdownContent\" (ready)=\"markAsLoaded()\" emoji></markdown>\n\n <ng-template #useDocUrl>\n <markdown\n *ngIf=\"markdownUrl\"\n [src]=\"markdownUrl\"\n (load)=\"markAsLoaded()\"\n (error)=\"onLoadError($event)\"\n emoji\n ></markdown>\n </ng-template>\n</ion-content>\n\n<ion-footer hidden-xs hidden-sm hidden-mobile>\n <ion-toolbar>\n <ion-row class=\"ion-no-padding\" nowrap>\n <ion-col></ion-col>\n <ion-col size=\"auto\">\n <ion-button fill=\"solid\" color=\"tertiary\" (click)=\"close()\">{{ 'COMMON.BTN_CLOSE' | translate }}</ion-button>\n </ion-col>\n </ion-row>\n </ion-toolbar>\n</ion-footer>\n", dependencies: [{ kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i2$1.IonButton, selector: "ion-button", inputs: ["buttonType", "color", "disabled", "download", "expand", "fill", "form", "href", "mode", "rel", "routerAnimation", "routerDirection", "shape", "size", "strong", "target", "type"] }, { kind: "component", type: i2$1.IonCol, selector: "ion-col", inputs: ["offset", "offsetLg", "offsetMd", "offsetSm", "offsetXl", "offsetXs", "pull", "pullLg", "pullMd", "pullSm", "pullXl", "pullXs", "push", "pushLg", "pushMd", "pushSm", "pushXl", "pushXs", "size", "sizeLg", "sizeMd", "sizeSm", "sizeXl", "sizeXs"] }, { kind: "component", type: i2$1.IonContent, selector: "ion-content", inputs: ["color", "forceOverscroll", "fullscreen", "scrollEvents", "scrollX", "scrollY"] }, { kind: "component", type: i2$1.IonFooter, selector: "ion-footer", inputs: ["collapse", "mode", "translucent"] }, { kind: "component", type: i2$1.IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: i2$1.IonItem, selector: "ion-item", inputs: ["button", "color", "counter", "counterFormatter", "detail", "detailIcon", "disabled", "download", "fill", "href", "lines", "mode", "rel", "routerAnimation", "routerDirection", "shape", "target", "type"] }, { kind: "component", type: i2$1.IonLabel, selector: "ion-label", inputs: ["color", "mode", "position"] }, { kind: "component", type: i2$1.IonRow, selector: "ion-row" }, { kind: "component", type: i2$1.IonToolbar, selector: "ion-toolbar", inputs: ["color", "mode"] }, { kind: "component", type: i7$2.MarkdownComponent, selector: "markdown, [markdown]", inputs: ["data", "src", "disableSanitizer", "inline", "clipboard", "clipboardButtonComponent", "clipboardButtonTemplate", "emoji", "katex", "katexOptions", "mermaid", "mermaidOptions", "lineHighlight", "line", "lineOffset", "lineNumbers", "start", "commandLine", "filterOutput", "host", "prompt", "output", "user"], outputs: ["error", "load", "ready"] }, { kind: "component", type: ModalToolbarComponent, selector: "app-modal-toolbar", inputs: ["modalName", "title", "color", "showSpinner", "canValidate", "validateIcon"], outputs: ["cancel", "validate"] }, { kind: "pipe", type: i1$1.TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
23250
23290
  }
23251
23291
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: AppHelpModal, decorators: [{
23252
23292
  type: Component,
23253
- args: [{ selector: 'app-help-modal', changeDetection: ChangeDetectionStrategy.OnPush, template: "<app-modal-toolbar\n color=\"light\"\n [title]=\"title | translate\"\n (cancel)=\"close($event)\"\n [showSpinner]=\"loading\"\n></app-modal-toolbar>\n\n<ion-content class=\"ion-padding\">\n <!-- error -->\n <ion-item *ngIf=\"error && showError\" lines=\"none\">\n <ion-icon color=\"danger\" slot=\"start\" name=\"alert-circle\"></ion-icon>\n <ion-label color=\"danger\" class=\"error\" [innerHTML]=\"error | translate\"></ion-label>\n </ion-item>\n\n <markdown *ngIf=\"markdownContent; else useDocUrl\" [data]=\"markdownContent\" (ready)=\"markAsLoaded()\" emoji></markdown>\n\n <ng-template #useDocUrl>\n <markdown\n *ngIf=\"markdownUrl\"\n [src]=\"markdownUrl\"\n (load)=\"markAsLoaded()\"\n (error)=\"onLoadError($event)\"\n emoji\n ></markdown>\n </ng-template>\n</ion-content>\n\n<ion-footer hidden-xs hidden-sm hidden-mobile>\n <ion-toolbar>\n <ion-row class=\"ion-no-padding\" nowrap>\n <ion-col></ion-col>\n <ion-col size=\"auto\">\n <ion-button fill=\"solid\" color=\"tertiary\" (click)=\"close()\">{{ 'COMMON.BTN_CLOSE' | translate }}</ion-button>\n </ion-col>\n </ion-row>\n </ion-toolbar>\n</ion-footer>\n" }]
23254
- }], ctorParameters: () => [{ type: i0.Injector }, { type: i2$1.ModalController }, { type: PlatformService }, { type: LocalSettingsService }, { type: i1$1.TranslateService }, { type: i0.ChangeDetectorRef }], propDecorators: { title: [{
23293
+ args: [{ selector: 'app-help-modal', changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (title) {\n <app-modal-toolbar\n color=\"light\"\n [title]=\"title | translate\"\n (cancel)=\"close($event)\"\n [showSpinner]=\"loading\"\n ></app-modal-toolbar>\n}\n\n<ion-content class=\"ion-padding\">\n <!-- error -->\n <ion-item *ngIf=\"showError && error\" lines=\"none\">\n <ion-icon color=\"danger\" slot=\"start\" name=\"alert-circle\"></ion-icon>\n <ion-label color=\"danger\" class=\"error\" [innerHTML]=\"error | translate\"></ion-label>\n </ion-item>\n\n <markdown *ngIf=\"markdownContent; else useDocUrl\" [data]=\"markdownContent\" (ready)=\"markAsLoaded()\" emoji></markdown>\n\n <ng-template #useDocUrl>\n <markdown\n *ngIf=\"markdownUrl\"\n [src]=\"markdownUrl\"\n (load)=\"markAsLoaded()\"\n (error)=\"onLoadError($event)\"\n emoji\n ></markdown>\n </ng-template>\n</ion-content>\n\n<ion-footer hidden-xs hidden-sm hidden-mobile>\n <ion-toolbar>\n <ion-row class=\"ion-no-padding\" nowrap>\n <ion-col></ion-col>\n <ion-col size=\"auto\">\n <ion-button fill=\"solid\" color=\"tertiary\" (click)=\"close()\">{{ 'COMMON.BTN_CLOSE' | translate }}</ion-button>\n </ion-col>\n </ion-row>\n </ion-toolbar>\n</ion-footer>\n" }]
23294
+ }], ctorParameters: () => [{ type: i0.Injector }, { type: i2$1.ModalController }, { type: PlatformService }, { type: LocalSettingsService }, { type: i1$1.TranslateService }, { type: NetworkService }, { type: i0.ChangeDetectorRef }], propDecorators: { title: [{
23255
23295
  type: Input
23256
23296
  }], showError: [{
23257
23297
  type: Input
@@ -27151,7 +27191,7 @@ class AboutModal {
27151
27191
  this.reportIssueUrl = config?.getProperty(CORE_CONFIG_OPTIONS.REPORT_ISSUE_URL) || this.environment.reportIssueUrl;
27152
27192
  }
27153
27193
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: AboutModal, deps: [{ token: i1$1.TranslateService }, { token: i2$1.ModalController }, { token: ConfigService }, { token: ENVIRONMENT, optional: true }, { token: APP_ABOUT_DEVELOPERS, optional: true }, { token: APP_ABOUT_PARTNERS, optional: true }], target: i0.ɵɵFactoryTarget.Component });
27154
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: AboutModal, selector: "app-about-modal", ngImport: i0, template: "<ion-header>\n <ion-toolbar color=\"light\">\n <ion-title>\n {{ 'ABOUT.TITLE' | translate }}\n </ion-title>\n\n <ion-buttons slot=\"end\">\n <ion-button (click)=\"close()\" visible-xs visible-sm visible-mobile>\n {{ 'COMMON.BTN_CLOSE' | translate }}\n </ion-button>\n </ion-buttons>\n </ion-toolbar>\n</ion-header>\n\n<ion-content class=\"ion-padding\">\n <ion-list lines=\"none\">\n <!-- Peer info -->\n @if (config$ | async; as config) {\n <ion-item>\n <span slot=\"start\">&nbsp;</span>\n <ion-label class=\"ion-text-wrap\">\n <h2>\n <b>{{ config.label | capitalize }}</b>\n @if (config.name) {\n -\n <span [innerHTML]=\"config.name\"></span>\n }\n </h2>\n\n @if (config.description) {\n <p>\n <markdown [data]=\"config.description\" emoji></markdown>\n </p>\n }\n </ion-label>\n </ion-item>\n }\n\n <!-- Version info -->\n <ion-item>\n <span slot=\"start\">&nbsp;</span>\n <ion-label class=\"ion-text-wrap\">\n <h2>\n <small *ngIf=\"name\">{{ 'ABOUT.POWERED_BY' | translate }}</small>\n {{ name }}\n <span *ngIf=\"version\" [innerHTML]=\"'ABOUT.VERSION' | translate: { version: version }\"></span>\n </h2>\n <p [innerHTML]=\"'ABOUT.LICENSE' | translate\"></p>\n </ion-label>\n </ion-item>\n\n <!-- Help -->\n <ion-item *ngIf=\"forumUrl || helpUrl\">\n <mat-icon slot=\"start\">help_outline</mat-icon>\n <ion-label>\n <p>\n {{ 'ABOUT.HELP' | translate }}\n </p>\n <p>\n <ion-button fill=\"solid\" color=\"accent\" href=\"{{ helpUrl }}\" target=\"help\" size=\"default\">\n <mat-icon slot=\"start\">description</mat-icon>\n <ion-text translate>ABOUT.USER_MANUAL</ion-text>\n </ion-button>\n <ion-button fill=\"solid\" color=\"secondary\" href=\"{{ forumUrl }}\" target=\"forum\" size=\"default\">\n <ion-icon slot=\"start\" name=\"chatbubbles\"></ion-icon>\n <ion-text translate>ABOUT.FORUM</ion-text>\n </ion-button>\n </p>\n </ion-label>\n </ion-item>\n\n <!-- Report issue -->\n <ion-item *ngIf=\"reportIssueUrl\">\n <ion-icon slot=\"start\" name=\"bug\" color=\"dark\"></ion-icon>\n <ion-label>\n <p>\n {{ 'ABOUT.REPORT_ISSUE' | translate }}\n </p>\n <p>\n <a color=\"primary\" href=\"{{ reportIssueUrl }}\" target=\"_system\" translate>ABOUT.BTN_REPORT_ISSUE</a>\n </p>\n </ion-label>\n </ion-item>\n\n <!-- Source code -->\n <ion-item *ngIf=\"sourceUrl\">\n <ion-icon slot=\"start\" name=\"code\" color=\"dark\"></ion-icon>\n <ion-label>\n <p>\n {{ 'ABOUT.SOURCE_CODE' | translate }}\n </p>\n <p>\n <a color=\"primary\" href=\"{{ sourceUrl }}\" target=\"_system\">{{ sourceUrl }}</a>\n </p>\n </ion-label>\n </ion-item>\n\n <!-- Developers -->\n <ion-item *ngIf=\"developers | isNotEmptyArray\">\n <ion-icon slot=\"start\" name=\"people\" color=\"dark\"></ion-icon>\n <ion-label>\n <p>\n {{ 'ABOUT.DEVELOPED_BY' | translate }}\n </p>\n <ion-list lines=\"none\">\n <ion-item *ngFor=\"let item of developers\" class=\"ion-no-padding\">\n <ion-label>\n <p>\n <a color=\"primary\" href=\"{{ item.siteUrl }}\" target=\"_system\">{{ item.name || item.label }}</a>\n </p>\n </ion-label>\n <ion-img slot=\"end\" [src]=\"item.logo\" />\n </ion-item>\n </ion-list>\n </ion-label>\n </ion-item>\n\n <!-- Partners -->\n <ion-item class=\"item-partners\" *ngIf=\"partners | isNotEmptyArray\">\n <ion-icon slot=\"start\" name=\"megaphone\" color=\"dark\"></ion-icon>\n <ion-text>\n <p>{{ 'ABOUT.PARTNERS' | translate }}</p>\n <p>\n <a *ngFor=\"let item of partners\" href=\"{{ item.siteUrl }}\" class=\"partners\" target=\"_system\">\n <img *ngIf=\"item.logo; else partnerName\" [src]=\"item.logo\" [alt]=\"item.label\" />\n <ng-template #partnerName>\n <ion-text>{{ item.label }}</ion-text>\n </ng-template>\n </a>\n </p>\n </ion-text>\n </ion-item>\n </ion-list>\n</ion-content>\n\n<ion-footer hidden-xs hidden-sm hidden-mobile>\n <ion-toolbar>\n <ion-row class=\"ion-no-padding\" nowrap>\n <ion-col></ion-col>\n <ion-col size=\"auto\">\n <ion-button fill=\"solid\" color=\"tertiary\" (click)=\"close()\">{{ 'COMMON.BTN_CLOSE' | translate }}</ion-button>\n </ion-col>\n </ion-row>\n </ion-toolbar>\n</ion-footer>\n", styles: [".item-partners ion-text{height:auto}.item-partners ion-text p:last-child{display:flex;flex-wrap:wrap;flex-direction:row;justify-content:space-between}.item-partners ion-text p:last-child a{padding:2px}.item-partners ion-text p:last-child a img{text-align:center;display:inline-block;max-height:40px!important}\n"], dependencies: [{ kind: "directive", type: i3.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i2$1.IonButton, selector: "ion-button", inputs: ["buttonType", "color", "disabled", "download", "expand", "fill", "form", "href", "mode", "rel", "routerAnimation", "routerDirection", "shape", "size", "strong", "target", "type"] }, { kind: "component", type: i2$1.IonButtons, selector: "ion-buttons", inputs: ["collapse"] }, { kind: "component", type: i2$1.IonCol, selector: "ion-col", inputs: ["offset", "offsetLg", "offsetMd", "offsetSm", "offsetXl", "offsetXs", "pull", "pullLg", "pullMd", "pullSm", "pullXl", "pullXs", "push", "pushLg", "pushMd", "pushSm", "pushXl", "pushXs", "size", "sizeLg", "sizeMd", "sizeSm", "sizeXl", "sizeXs"] }, { kind: "component", type: i2$1.IonContent, selector: "ion-content", inputs: ["color", "forceOverscroll", "fullscreen", "scrollEvents", "scrollX", "scrollY"] }, { kind: "component", type: i2$1.IonFooter, selector: "ion-footer", inputs: ["collapse", "mode", "translucent"] }, { kind: "component", type: i2$1.IonHeader, selector: "ion-header", inputs: ["collapse", "mode", "translucent"] }, { kind: "component", type: i2$1.IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: i2$1.IonImg, selector: "ion-img", inputs: ["alt", "src"] }, { kind: "component", type: i2$1.IonItem, selector: "ion-item", inputs: ["button", "color", "counter", "counterFormatter", "detail", "detailIcon", "disabled", "download", "fill", "href", "lines", "mode", "rel", "routerAnimation", "routerDirection", "shape", "target", "type"] }, { kind: "component", type: i2$1.IonLabel, selector: "ion-label", inputs: ["color", "mode", "position"] }, { kind: "component", type: i2$1.IonList, selector: "ion-list", inputs: ["inset", "lines", "mode"] }, { kind: "component", type: i2$1.IonRow, selector: "ion-row" }, { kind: "component", type: i2$1.IonText, selector: "ion-text", inputs: ["color", "mode"] }, { kind: "component", type: i2$1.IonTitle, selector: "ion-title", inputs: ["color", "size"] }, { kind: "component", type: i2$1.IonToolbar, selector: "ion-toolbar", inputs: ["color", "mode"] }, { kind: "directive", type: i1$1.TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }, { kind: "component", type: i6$4.MarkdownComponent, selector: "markdown, [markdown]", inputs: ["data", "src", "disableSanitizer", "inline", "clipboard", "clipboardButtonComponent", "clipboardButtonTemplate", "emoji", "katex", "katexOptions", "mermaid", "mermaidOptions", "lineHighlight", "line", "lineOffset", "lineNumbers", "start", "commandLine", "filterOutput", "host", "prompt", "output", "user"], outputs: ["error", "load", "ready"] }, { kind: "component", type: i6$2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "pipe", type: i3.AsyncPipe, name: "async" }, { kind: "pipe", type: i1$1.TranslatePipe, name: "translate" }, { kind: "pipe", type: NotEmptyArrayPipe, name: "isNotEmptyArray" }, { kind: "pipe", type: CapitalizePipe, name: "capitalize" }] });
27194
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: AboutModal, selector: "app-about-modal", ngImport: i0, template: "<ion-header>\n <ion-toolbar color=\"light\">\n <ion-title>\n {{ 'ABOUT.TITLE' | translate }}\n </ion-title>\n\n <ion-buttons slot=\"end\">\n <ion-button (click)=\"close()\" visible-xs visible-sm visible-mobile>\n {{ 'COMMON.BTN_CLOSE' | translate }}\n </ion-button>\n </ion-buttons>\n </ion-toolbar>\n</ion-header>\n\n<ion-content class=\"ion-padding\">\n <ion-list lines=\"none\">\n <!-- Peer info -->\n @if (config$ | async; as config) {\n <ion-item>\n <span slot=\"start\">&nbsp;</span>\n <ion-label class=\"ion-text-wrap\">\n <h2>\n <b>{{ config.label | capitalize }}</b>\n @if (config.name) {\n -\n <span [innerHTML]=\"config.name\"></span>\n }\n </h2>\n\n @if (config.description) {\n <p>\n <markdown [data]=\"config.description\" emoji></markdown>\n </p>\n }\n </ion-label>\n </ion-item>\n }\n\n <!-- Version info -->\n <ion-item>\n <span slot=\"start\">&nbsp;</span>\n <ion-label class=\"ion-text-wrap\">\n <h2>\n <small *ngIf=\"name\">{{ 'ABOUT.POWERED_BY' | translate }}</small>\n {{ name }}\n <span *ngIf=\"version\" [innerHTML]=\"'ABOUT.VERSION' | translate: { version: version }\"></span>\n </h2>\n <p [innerHTML]=\"'ABOUT.LICENSE' | translate\"></p>\n </ion-label>\n </ion-item>\n\n <!-- Help -->\n <ion-item *ngIf=\"forumUrl || helpUrl\">\n <mat-icon slot=\"start\">help_outline</mat-icon>\n <ion-label>\n <p>\n {{ 'ABOUT.HELP' | translate }}\n </p>\n <p>\n <ion-button fill=\"solid\" color=\"accent\" href=\"{{ helpUrl }}\" target=\"help\" size=\"default\">\n <mat-icon slot=\"start\">description</mat-icon>\n <ion-text translate>ABOUT.USER_MANUAL</ion-text>\n </ion-button>\n <ion-button fill=\"solid\" color=\"secondary\" href=\"{{ forumUrl }}\" target=\"forum\" size=\"default\">\n <ion-icon slot=\"start\" name=\"chatbubbles\"></ion-icon>\n <ion-text translate>ABOUT.FORUM</ion-text>\n </ion-button>\n </p>\n </ion-label>\n </ion-item>\n\n <!-- Report issue -->\n <ion-item *ngIf=\"reportIssueUrl\">\n <ion-icon slot=\"start\" name=\"bug\" color=\"dark\"></ion-icon>\n <ion-label>\n <p>\n {{ 'ABOUT.REPORT_ISSUE' | translate }}\n </p>\n <p>\n <a color=\"primary\" href=\"{{ reportIssueUrl }}\" target=\"_system\" translate>ABOUT.BTN_REPORT_ISSUE</a>\n </p>\n </ion-label>\n </ion-item>\n\n <!-- Source code -->\n <ion-item *ngIf=\"sourceUrl\">\n <ion-icon slot=\"start\" name=\"code\" color=\"dark\"></ion-icon>\n <ion-label>\n <p>\n {{ 'ABOUT.SOURCE_CODE' | translate }}\n </p>\n <p>\n <a color=\"primary\" href=\"{{ sourceUrl }}\" target=\"_system\">{{ sourceUrl }}</a>\n </p>\n </ion-label>\n </ion-item>\n\n <!-- Developers -->\n <ion-item *ngIf=\"developers | isNotEmptyArray\">\n <ion-icon slot=\"start\" name=\"people\" color=\"dark\"></ion-icon>\n <ion-label>\n <p>\n {{ 'ABOUT.DEVELOPED_BY' | translate }}\n </p>\n <ion-list lines=\"none\">\n <ion-item *ngFor=\"let item of developers\" class=\"ion-no-padding\">\n <ion-label>\n <p>\n <a color=\"primary\" href=\"{{ item.siteUrl }}\" target=\"_system\">{{ item.name || item.label }}</a>\n </p>\n </ion-label>\n <ion-img slot=\"end\" [src]=\"item.logo\" />\n </ion-item>\n </ion-list>\n </ion-label>\n </ion-item>\n\n <!-- Partners -->\n <ion-item class=\"item-partners\" *ngIf=\"partners | isNotEmptyArray\">\n <ion-icon slot=\"start\" name=\"megaphone\" color=\"dark\"></ion-icon>\n <ion-text>\n <p>{{ 'ABOUT.PARTNERS' | translate }}</p>\n <p>\n <a *ngFor=\"let item of partners\" href=\"{{ item.siteUrl }}\" class=\"partners\" target=\"_system\">\n <img *ngIf=\"item.logo; else partnerName\" [src]=\"item.logo\" [alt]=\"item.label\" />\n <ng-template #partnerName>\n <ion-text>{{ item.label }}</ion-text>\n </ng-template>\n </a>\n </p>\n </ion-text>\n </ion-item>\n </ion-list>\n</ion-content>\n\n<ion-footer hidden-xs hidden-sm hidden-mobile>\n <ion-toolbar>\n <ion-row class=\"ion-no-padding\" nowrap>\n <ion-col></ion-col>\n <ion-col size=\"auto\">\n <ion-button fill=\"solid\" color=\"tertiary\" (click)=\"close()\">{{ 'COMMON.BTN_CLOSE' | translate }}</ion-button>\n </ion-col>\n </ion-row>\n </ion-toolbar>\n</ion-footer>\n", styles: [".item-partners ion-text{height:auto}.item-partners ion-text p:last-child{display:flex;flex-wrap:wrap;flex-direction:row;justify-content:space-between}.item-partners ion-text p:last-child a{padding:2px}.item-partners ion-text p:last-child a img{text-align:center;display:inline-block;max-height:40px!important}\n"], dependencies: [{ kind: "directive", type: i3.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i2$1.IonButton, selector: "ion-button", inputs: ["buttonType", "color", "disabled", "download", "expand", "fill", "form", "href", "mode", "rel", "routerAnimation", "routerDirection", "shape", "size", "strong", "target", "type"] }, { kind: "component", type: i2$1.IonButtons, selector: "ion-buttons", inputs: ["collapse"] }, { kind: "component", type: i2$1.IonCol, selector: "ion-col", inputs: ["offset", "offsetLg", "offsetMd", "offsetSm", "offsetXl", "offsetXs", "pull", "pullLg", "pullMd", "pullSm", "pullXl", "pullXs", "push", "pushLg", "pushMd", "pushSm", "pushXl", "pushXs", "size", "sizeLg", "sizeMd", "sizeSm", "sizeXl", "sizeXs"] }, { kind: "component", type: i2$1.IonContent, selector: "ion-content", inputs: ["color", "forceOverscroll", "fullscreen", "scrollEvents", "scrollX", "scrollY"] }, { kind: "component", type: i2$1.IonFooter, selector: "ion-footer", inputs: ["collapse", "mode", "translucent"] }, { kind: "component", type: i2$1.IonHeader, selector: "ion-header", inputs: ["collapse", "mode", "translucent"] }, { kind: "component", type: i2$1.IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: i2$1.IonImg, selector: "ion-img", inputs: ["alt", "src"] }, { kind: "component", type: i2$1.IonItem, selector: "ion-item", inputs: ["button", "color", "counter", "counterFormatter", "detail", "detailIcon", "disabled", "download", "fill", "href", "lines", "mode", "rel", "routerAnimation", "routerDirection", "shape", "target", "type"] }, { kind: "component", type: i2$1.IonLabel, selector: "ion-label", inputs: ["color", "mode", "position"] }, { kind: "component", type: i2$1.IonList, selector: "ion-list", inputs: ["inset", "lines", "mode"] }, { kind: "component", type: i2$1.IonRow, selector: "ion-row" }, { kind: "component", type: i2$1.IonText, selector: "ion-text", inputs: ["color", "mode"] }, { kind: "component", type: i2$1.IonTitle, selector: "ion-title", inputs: ["color", "size"] }, { kind: "component", type: i2$1.IonToolbar, selector: "ion-toolbar", inputs: ["color", "mode"] }, { kind: "directive", type: i1$1.TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }, { kind: "component", type: i7$2.MarkdownComponent, selector: "markdown, [markdown]", inputs: ["data", "src", "disableSanitizer", "inline", "clipboard", "clipboardButtonComponent", "clipboardButtonTemplate", "emoji", "katex", "katexOptions", "mermaid", "mermaidOptions", "lineHighlight", "line", "lineOffset", "lineNumbers", "start", "commandLine", "filterOutput", "host", "prompt", "output", "user"], outputs: ["error", "load", "ready"] }, { kind: "component", type: i6$2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "pipe", type: i3.AsyncPipe, name: "async" }, { kind: "pipe", type: i1$1.TranslatePipe, name: "translate" }, { kind: "pipe", type: NotEmptyArrayPipe, name: "isNotEmptyArray" }, { kind: "pipe", type: CapitalizePipe, name: "capitalize" }] });
27155
27195
  }
27156
27196
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: AboutModal, decorators: [{
27157
27197
  type: Component,
@@ -29840,6 +29880,7 @@ class HomePage extends RxState {
29840
29880
  _config;
29841
29881
  pageHistory$ = this.select('pageHistory');
29842
29882
  loading$ = this.select('loading');
29883
+ mobile;
29843
29884
  waitingNetwork = false;
29844
29885
  accountName = '';
29845
29886
  isLogin;
@@ -29851,6 +29892,7 @@ class HomePage extends RxState {
29851
29892
  canRegister;
29852
29893
  contentStyle;
29853
29894
  contentCredits;
29895
+ legalInformation;
29854
29896
  offline;
29855
29897
  $filteredButtons = new BehaviorSubject(undefined);
29856
29898
  showAccountButton;
@@ -29878,9 +29920,24 @@ class HomePage extends RxState {
29878
29920
  get showPartnerBanner() {
29879
29921
  return this.get('showPartnerBanner');
29880
29922
  }
29923
+ set showLegalInformation(value) {
29924
+ this.set('showLegalInformation', () => value);
29925
+ }
29926
+ get showLegalInformation() {
29927
+ return this.get('showLegalInformation');
29928
+ }
29929
+ set showInstallLinks(value) {
29930
+ this.set('showInstallLinks', () => value);
29931
+ }
29932
+ get showInstallLinks() {
29933
+ return this.get('showInstallLinks');
29934
+ }
29881
29935
  get currentLocaleCode() {
29882
29936
  return this.loading ? '' : (this.translate.currentLang || this.translate.defaultLang || this.environment.defaultLocale)?.substring(0, 2);
29883
29937
  }
29938
+ get partnerBannerSize() {
29939
+ return this.showLegalInformation ? 9 : 12;
29940
+ }
29884
29941
  constructor(accountService, modalCtrl, translate, toastController, configService, platform, cd, network, settings, environment, locales, buttons) {
29885
29942
  super();
29886
29943
  this.accountService = accountService;
@@ -29900,9 +29957,10 @@ class HomePage extends RxState {
29900
29957
  showPartnerBanner: false,
29901
29958
  showSpinner: !this.platform.started,
29902
29959
  });
29903
- this._debug = !environment.production;
29960
+ this.mobile = this.platform.is('mobile');
29904
29961
  this.platform.ready().then(() => this.start());
29905
- this.showAccountButton = toBoolean(environment.account?.showAccountButton, true);
29962
+ this.showAccountButton = environment.account?.showAccountButton ?? true;
29963
+ this._debug = !environment.production;
29906
29964
  }
29907
29965
  ngOnDestroy() {
29908
29966
  this._subscription.unsubscribe();
@@ -29987,14 +30045,26 @@ class HomePage extends RxState {
29987
30045
  onConfigLoaded(config) {
29988
30046
  console.debug('[home] Applying configuration', config);
29989
30047
  this._config = config;
29990
- this.appName = config.label || this.environment.defaultAppName || 'SUMARiS';
29991
- this.logo = config.largeLogo || config.smallLogo || undefined;
30048
+ this.appName = this._config.label || this.environment.defaultAppName || 'SUMARiS';
30049
+ this.logo = this._config.largeLogo || this._config.smallLogo || undefined;
29992
30050
  this.description = config.name;
29993
30051
  this.isWeb = this.platform.isWeb();
29994
- this.canRegister = config.getPropertyAsBoolean(CORE_CONFIG_OPTIONS.REGISTRATION_ENABLE);
29995
- const partners = (config.partners || []).filter((p) => p && p.logo);
30052
+ this.canRegister = this._config.getPropertyAsBoolean(CORE_CONFIG_OPTIONS.REGISTRATION_ENABLE);
30053
+ this.legalInformation = [
30054
+ {
30055
+ title: 'HOME.PRIVACY_POLICY',
30056
+ path: this._config.getProperty(CORE_CONFIG_OPTIONS.PRIVACY_POLICY_URL) ?? this.environment.privacyPolicyUrl,
30057
+ },
30058
+ {
30059
+ title: 'HOME.TERMS_OF_USE',
30060
+ path: this._config.getProperty(CORE_CONFIG_OPTIONS.TERMS_OF_USE_URL) ?? this.environment.termsOfUseUrl,
30061
+ },
30062
+ ].filter((item) => isNotNilOrBlank(item.path));
30063
+ this.showLegalInformation = isNotEmptyArray(this.legalInformation);
30064
+ const partners = (this._config.partners || []).filter((p) => p && p.logo);
29996
30065
  this.$partners.next(partners);
29997
30066
  this.showPartnerBanner = partners.length > 0;
30067
+ // TODO load install links
29998
30068
  // If not already set, compute the background image
29999
30069
  if (!this.contentStyle) {
30000
30070
  const backgroundImages = (config.backgroundImages || [])
@@ -30064,6 +30134,28 @@ class HomePage extends RxState {
30064
30134
  });
30065
30135
  this.$filteredButtons.next(filteredButtons);
30066
30136
  }
30137
+ async openHelpModal(event, item = null) {
30138
+ if (isNilOrBlank(item?.path))
30139
+ return;
30140
+ // Resolve relative path
30141
+ let url = item.path;
30142
+ if (this.network.peer && (url.startsWith('./') || url.startsWith('/'))) {
30143
+ url = Peer.path(this.network.peer, url);
30144
+ }
30145
+ const pathFilename = UriUtils.getFilename(url);
30146
+ const isMarkdownFile = pathFilename.endsWith('.md');
30147
+ // Open as markdown
30148
+ if (isMarkdownFile) {
30149
+ await AppHelpModalUtils.show(this.modalCtrl, {
30150
+ title: this.translate.instant(item.title, item.titleArgs),
30151
+ markdownUrl: url,
30152
+ });
30153
+ }
30154
+ else {
30155
+ // Open as external link
30156
+ await this.platform.open(url);
30157
+ }
30158
+ }
30067
30159
  async removePageHistory(path) {
30068
30160
  await this.settings.removePageHistory(path);
30069
30161
  }
@@ -30071,11 +30163,11 @@ class HomePage extends RxState {
30071
30163
  this.cd.markForCheck();
30072
30164
  }
30073
30165
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: HomePage, deps: [{ token: AccountService }, { token: i2$1.ModalController }, { token: i1$1.TranslateService }, { token: i2$1.ToastController }, { token: ConfigService }, { token: PlatformService }, { token: i0.ChangeDetectorRef }, { token: NetworkService }, { token: LocalSettingsService }, { token: ENVIRONMENT }, { token: APP_LOCALES }, { token: APP_HOME_BUTTONS, optional: true }], target: i0.ɵɵFactoryTarget.Component });
30074
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: HomePage, selector: "app-page-home", usesInheritance: true, ngImport: i0, template: "<app-toolbar [canGoBack]=\"false\" visible-xs visible-sm visible-mobile>\n <!-- Change locale button -->\n <ion-button slot=\"end\" [matMenuTriggerFor]=\"localeMenu\">\n <ion-icon slot=\"start\" name=\"language\"></ion-icon>\n </ion-button>\n</app-toolbar>\n\n<!-- Change locale menu -->\n<mat-menu #localeMenu=\"matMenu\">\n <ng-template matMenuContent>\n @for (item of locales; track item.key) {\n <button mat-menu-item (click)=\"changeLanguage(item.key)\">\n <ion-label>{{ item.value }}</ion-label>\n </button>\n }\n </ng-template>\n</mat-menu>\n\n<ion-content [ngStyle]=\"contentStyle\" no-padding-xs>\n @if (contentCredits | isNotNilOrBlank) {\n <span class=\"content-credits\">\n <ion-text>{{ contentCredits }}</ion-text>\n </span>\n }\n\n <!-- loading spinner -->\n <div class=\"loading-page\" [class.cdk-visually-hidden]=\"!(loading$ | push)\">\n @if (showSpinner) {\n <div class=\"spinner\">\n <p [innerHTML]=\"'COMMON.LOADING_DOTS' | translate\"></p>\n <div class=\"sk-cube1 sk-cube\"></div>\n <div class=\"sk-cube2 sk-cube\"></div>\n <div class=\"sk-cube4 sk-cube\"></div>\n <div class=\"sk-cube3 sk-cube\"></div>\n </div>\n }\n </div>\n\n <!-- Desktop: translucent top toolbar -->\n <div hidden-xs hidden-sm hidden-mobile>\n <ion-toolbar translucent>\n <ion-buttons slot=\"start\">\n <ion-menu-toggle>\n <ion-button color=\"light\" fill=\"clear\">\n <ion-icon slot=\"icon-only\" name=\"menu\"></ion-icon>\n </ion-button>\n </ion-menu-toggle>\n </ion-buttons>\n\n <ion-buttons slot=\"end\">\n <!-- change locale button -->\n <ion-button\n color=\"secondary\"\n fill=\"solid\"\n [matMenuTriggerFor]=\"localeMenu\"\n [title]=\"'SETTINGS.LOCALE' | translate\"\n >\n <ion-icon slot=\"icon-only\" name=\"language\"></ion-icon>\n </ion-button>\n </ion-buttons>\n </ion-toolbar>\n </div>\n\n <!-- Install (and upgrade) card -->\n <app-install-upgrade-card [isLogin]=\"isLogin\" [showInstallButton]=\"true\"></app-install-upgrade-card>\n\n @if (!(loading$ | push)) {\n <!-- Welcome card -->\n <ion-card class=\"main welcome ion-padding ion-text-center ion-align-self-center\" @fadeInAnimation>\n <ion-card-header>\n <ion-card-title class=\"ion-text-center\">\n <span *ngIf=\"isWeb\" [innerHTML]=\"'HOME.WELCOME_WEB' | translate: { appName: appName }\"></span>\n <span *ngIf=\"!isWeb\" [innerHTML]=\"'HOME.WELCOME_APP' | translate: { appName: appName }\"></span>\n </ion-card-title>\n <ion-card-subtitle [innerHTML]=\"description\"></ion-card-subtitle>\n </ion-card-header>\n <ion-card-content class=\"ion-no-padding\">\n <ion-text color=\"primary\">\n <img *ngIf=\"logo\" [attr.src]=\"logo\" alt=\"Logo\" />\n </ion-text>\n <!-- register help text -->\n <ion-text *ngIf=\"!isLogin && canRegister\">\n <br />\n <span translate>HOME.REGISTER_HELP</span>\n </ion-text>\n <div class=\"ion-padding-top\">\n <!-- If NOT login -->\n <ng-container *ngIf=\"!isLogin; else loginButtons\">\n <ion-button *ngIf=\"canRegister\" expand=\"block\" color=\"tertiary\" (click)=\"register()\">\n <span translate>HOME.BTN_REGISTER</span>\n </ion-button>\n <ion-button expand=\"block\" color=\"light\" [routerLink]=\"['/']\" (click)=\"login()\">\n <span translate>AUTH.BTN_LOGIN</span>\n </ion-button>\n </ng-container>\n\n <!-- If user login -->\n <ng-template #loginButtons>\n <!-- Feature buttons -->\n <ng-container *rxIf=\"$filteredButtons; let buttons\">\n <ng-container *ngFor=\"let item of buttons\">\n <ion-button\n *ngIf=\"item.path\"\n expand=\"block\"\n color=\"tertiary\"\n [class]=\"item.cssClass\"\n [routerLink]=\"item.path\"\n routerDirection=\"root\"\n >\n <ion-icon slot=\"start\" class=\"ion-float-start\" *ngIf=\"item.icon\" [name]=\"item.icon\"></ion-icon>\n <mat-icon slot=\"start\" class=\"ion-float-start\" *ngIf=\"item.matIcon\">{{ item.matIcon }}</mat-icon>\n <ion-text>{{ 'HOME.BTN_DATA_ENTRY' | translate: { name: (item.title | translate) } }}</ion-text>\n </ion-button>\n\n <!-- divider -->\n <div *ngIf=\"!item.path && !item.action\" [class]=\"item.cssClass\">\n <ion-label translate>{{ item.title }}&nbsp;</ion-label>\n </div>\n </ng-container>\n\n <!--<p *ngIf=\"buttons.length\" class=\"visible-mobile\">&nbsp;</p>-->\n </ng-container>\n\n <ion-button *ngIf=\"showAccountButton\" expand=\"block\" color=\"secondary\" [routerLink]=\"['/account']\">\n <ion-icon slot=\"start\" class=\"ion-float-start\" name=\"person-circle\"></ion-icon>\n <ion-text translate>HOME.BTN_MY_ACCOUNT</ion-text>\n </ion-button>\n\n <p hidden-xs hidden-sm hidden-mobile>\n <ion-text\n [innerHTML]=\"'HOME.NOT_THIS_ACCOUNT_QUESTION' | translate: { displayName: accountName }\"\n ></ion-text>\n <br />\n <ion-text>\n <a href=\"#\" (click)=\"logout($event)\">\n <span translate>HOME.BTN_DISCONNECT</span>\n </a>\n </ion-text>\n </p>\n </ng-template>\n </div>\n </ion-card-content>\n </ion-card>\n\n <!-- Page history -->\n @if (isLogin && (pageHistory$ | push); as pageHistory) {\n <ion-grid class=\"history-container ion-align-self-center\">\n <ion-row>\n @for (page of pageHistory; track page.path) {\n <ion-col size=\"12\" size-xl=\"\" class=\"ion-text-center\">\n <ion-card class=\"ion-align-self-start ion-text-start\" @fadeInAnimation>\n <ion-card-header class=\"ion-no-padding\">\n <!-- top bar -->\n <ion-card-subtitle>\n <button\n type=\"button\"\n tabindex=\"-1\"\n (click)=\"removePageHistory(page.path)\"\n mat-icon-button\n class=\"ion-float-start ion-no-margin close-button\"\n >\n <mat-icon>close</mat-icon>\n </button>\n <ion-label [innerHTML]=\"page.subtitle | translate\"></ion-label>\n <ion-text class=\"ion-float-end\" [title]=\"page.time | dateFormat: { time: true }\">\n <small>\n <ion-icon name=\"time-outline\"></ion-icon>\n &nbsp;{{ page.time | dateFromNow }}\n </small>\n &nbsp;\n </ion-text>\n </ion-card-subtitle>\n\n <!-- main page -->\n <ion-card-title class=\"ion-no-margin ion-no-padding\">\n <ion-item\n detail=\"true\"\n tappable\n class=\"text-1x\"\n [routerLink]=\"page.path\"\n routerDirection=\"root\"\n lines=\"none\"\n >\n <!-- page icon-->\n <ion-icon *ngIf=\"page.icon\" slot=\"start\" [name]=\"page.icon\"></ion-icon>\n <mat-icon *ngIf=\"page.matIcon\" slot=\"start\">{{ page.matIcon }}</mat-icon>\n\n <ion-label color=\"primary\" [innerHTML]=\"page.title\"></ion-label>\n </ion-item>\n </ion-card-title>\n </ion-card-header>\n\n <!-- children pages -->\n @if (page.children | isNotEmptyArray) {\n <ion-card-content class=\"ion-no-padding ion-padding-start\">\n <ion-list class=\"ion-no-padding\">\n @for (childPage of page.children; track childPage.path) {\n <ion-item\n detail=\"true\"\n tappable\n class=\"text-1x\"\n [routerLink]=\"childPage.path\"\n routerDirection=\"root\"\n >\n <!-- page icon-->\n <ion-icon *ngIf=\"childPage.icon\" slot=\"start\" color=\"dark\" [name]=\"childPage.icon\"></ion-icon>\n <mat-icon *ngIf=\"childPage.matIcon\" slot=\"start\" color=\"dark\">\n {{ childPage.matIcon }}\n </mat-icon>\n\n <ion-label color=\"dark\" [innerHTML]=\"childPage.title\"></ion-label>\n </ion-item>\n }\n </ion-list>\n </ion-card-content>\n }\n </ion-card>\n </ion-col>\n }\n </ion-row>\n </ion-grid>\n } @else if (showPartnerBanner) {\n <!-- Display partners logos -->\n <div class=\"bottom-banner ion-text-center ion-padding\" @fadeInAnimation>\n @for (item of $partners | async; track $index) {\n <a href=\"{{ item.siteUrl }}\">\n <img class=\"logo\" src=\"{{ item.logo }}\" alt=\"{{ item.label }}\" [title]=\"item.label\" />\n </a>\n }\n </div>\n }\n }\n</ion-content>\n", styles: ["h1,h2,h3,h4,h5{white-space:normal}.center,ion-content ion-card.welcome img{text-align:center;display:inline-block}ion-content{--background: transparent;background-size:cover;-webkit-background-size:cover;-moz-background-size:cover;-o-background-size:cover;background-color:var(--ion-background-color);display:inline-block;padding:15px}ion-content .loading-page{display:block;height:100%;width:100%;position:absolute;background-color:transparent;z-index:5;transition:background .5s linear;-webkit-transition:background 1.5s linear}ion-content .loading-page.hidden{background-color:rgba(var(--ion-color-primary),0)}ion-content ion-card{z-index:9}ion-content ion-card ion-card-header{display:block}ion-content ion-card ion-card-header ion-card-subtitle,ion-content ion-card ion-card-header ion-card-title{display:block;width:100%}ion-content ion-card.main{min-width:240px;max-width:400px;margin-left:auto;margin-right:auto}ion-content ion-card.welcome{background-color:var(--ion-card-background-color)}ion-content ion-card.welcome button{margin-top:16px}ion-content ion-card.welcome img{max-width:250px}ion-content .history-container{margin-left:auto;margin-right:auto}ion-content .history-container ion-card{display:inline-block;box-sizing:border-box;z-index:8;min-width:240px;max-width:400px;width:100%;margin-left:auto;margin-right:auto;background-color:var(--ion-card-background-color)}ion-content .history-container ion-card ion-card-header ion-card-subtitle{height:40px}ion-content .history-container ion-card ion-card-header ion-card-subtitle button[float-start]{--mdc-icon-button-state-layer-size: 40px;padding:8px;z-index:99;margin:0}ion-content .history-container ion-card ion-card-header ion-card-subtitle ion-label{line-height:40px}ion-content .history-container ion-card ion-card-header ion-card-subtitle ion-label[float-end]{padding-right:16px;font-weight:400}ion-content .history-container ion-card ion-card-header ion-card-title ion-item{width:100%;--ion-item-background: $transparent;--ion-item-icon-color: var(--ion-color-primary);--ion-item-text-color: var(--ion-color-primary)}ion-content .history-container ion-card ion-card-header ion-card-title ion-item ion-icon[slot=start],ion-content .history-container ion-card ion-card-header ion-card-title ion-item mat-icon[slot=start]{margin-right:unset;margin-inline-end:16px!important;color:var(--ion-item-icon-color)!important;fill:currentColor;stroke:currentColor}ion-content .history-container ion-card ion-card-header ion-card-title ion-item ion-text,ion-content .history-container ion-card ion-card-header ion-card-title ion-item ion-label{color:var(--ion-item-text-color)!important;-webkit-text-size-adjust:100%;-moz-text-size-adjust:100%;-ms-text-size-adjust:100%;text-size-adjust:100%}ion-content .history-container ion-card ion-card-content ion-list{--ion-item-background: var(--ion-color-transparent)}ion-content .history-container ion-card ion-card-content ion-list ion-item{--ion-item-icon-color: var(--ion-color-dark);--ion-item-text-color: var(--ion-color-dark)}ion-content .history-container ion-card ion-card-content ion-list ion-item ion-icon[slot=start],ion-content .history-container ion-card ion-card-content ion-list ion-item mat-icon[slot=start]{color:var(--ion-item-icon-color)!important;fill:currentColor;stroke:currentColor;margin-right:unset;margin-inline-end:16px!important}ion-content .history-container ion-card ion-card-content ion-list ion-item ion-text,ion-content .history-container ion-card ion-card-content ion-list ion-item ion-label{color:var(--ion-item-text-color)!important}ion-content .bottom-banner{background-color:var(--ion-card-background-color);min-width:240px;z-index:0;position:absolute;left:16px;right:16px;bottom:16px}ion-content .bottom-banner img.logo{max-height:50px;margin-left:8px}ion-content ion-text{text-align:center}@media screen and (max-width: 575px){ion-content ion-card{min-width:160px;width:calc(100% - 20px);max-width:100%;margin-left:10px;margin-right:10px}ion-content ion-card h1{margin-top:0;font-size:20px}ion-content ion-card ion-card-content ion-button{margin-top:8px}ion-content .bottom-banner{display:block;position:unset}ion-content .bottom-banner img.logo{max-height:30px}}@media screen and (max-width: 767px) and (min-width: 576px){ion-content{min-height:555px}ion-content .bottom-banner img.logo{max-height:40px}}@media screen and (min-width: 768px){ion-content{min-height:calc(100% - 100px)}}.content-credits{position:absolute;right:5px;bottom:5px}.content-credits ion-text{padding-inline-start:4px;padding-inline-end:4px;font-size:.8rem;background-color:var(--ion-background-color, white);color:var(--ion-text-color);opacity:.65}\n"], dependencies: [{ kind: "directive", type: i3.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i3.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: i2$1.IonButton, selector: "ion-button", inputs: ["buttonType", "color", "disabled", "download", "expand", "fill", "form", "href", "mode", "rel", "routerAnimation", "routerDirection", "shape", "size", "strong", "target", "type"] }, { kind: "component", type: i2$1.IonButtons, selector: "ion-buttons", inputs: ["collapse"] }, { kind: "component", type: i2$1.IonCard, selector: "ion-card", inputs: ["button", "color", "disabled", "download", "href", "mode", "rel", "routerAnimation", "routerDirection", "target", "type"] }, { kind: "component", type: i2$1.IonCardContent, selector: "ion-card-content", inputs: ["mode"] }, { kind: "component", type: i2$1.IonCardHeader, selector: "ion-card-header", inputs: ["color", "mode", "translucent"] }, { kind: "component", type: i2$1.IonCardSubtitle, selector: "ion-card-subtitle", inputs: ["color", "mode"] }, { kind: "component", type: i2$1.IonCardTitle, selector: "ion-card-title", inputs: ["color", "mode"] }, { kind: "component", type: i2$1.IonCol, selector: "ion-col", inputs: ["offset", "offsetLg", "offsetMd", "offsetSm", "offsetXl", "offsetXs", "pull", "pullLg", "pullMd", "pullSm", "pullXl", "pullXs", "push", "pushLg", "pushMd", "pushSm", "pushXl", "pushXs", "size", "sizeLg", "sizeMd", "sizeSm", "sizeXl", "sizeXs"] }, { kind: "component", type: i2$1.IonContent, selector: "ion-content", inputs: ["color", "forceOverscroll", "fullscreen", "scrollEvents", "scrollX", "scrollY"] }, { kind: "component", type: i2$1.IonGrid, selector: "ion-grid", inputs: ["fixed"] }, { kind: "component", type: i2$1.IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: i2$1.IonItem, selector: "ion-item", inputs: ["button", "color", "counter", "counterFormatter", "detail", "detailIcon", "disabled", "download", "fill", "href", "lines", "mode", "rel", "routerAnimation", "routerDirection", "shape", "target", "type"] }, { kind: "component", type: i2$1.IonLabel, selector: "ion-label", inputs: ["color", "mode", "position"] }, { kind: "component", type: i2$1.IonList, selector: "ion-list", inputs: ["inset", "lines", "mode"] }, { kind: "component", type: i2$1.IonMenuToggle, selector: "ion-menu-toggle", inputs: ["autoHide", "menu"] }, { kind: "component", type: i2$1.IonRow, selector: "ion-row" }, { kind: "component", type: i2$1.IonText, selector: "ion-text", inputs: ["color", "mode"] }, { kind: "component", type: i2$1.IonToolbar, selector: "ion-toolbar", inputs: ["color", "mode"] }, { kind: "directive", type: i2$1.RouterLinkDelegate, selector: ":not(a):not(area)[routerLink]" }, { kind: "directive", type: i1$1.TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }, { kind: "directive", type: i9$2.RxIf, selector: "[rxIf]", inputs: ["rxIf", "rxIfStrategy", "rxIfElse", "rxIfThen", "rxIfSuspense", "rxIfComplete", "rxIfError", "rxIfContextTrigger", "rxIfNextTrigger", "rxIfSuspenseTrigger", "rxIfErrorTrigger", "rxIfCompleteTrigger", "rxIfParent", "rxIfPatchZone", "rxIfRenderCallback"] }, { kind: "component", type: i6$2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i9.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "component", type: i8$1.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: i8$1.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i8$1.MatMenuContent, selector: "ng-template[matMenuContent]" }, { kind: "directive", type: i8$1.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "component", type: ToolbarComponent, selector: "app-toolbar", inputs: ["progressBarMode", "title", "color", "class", "backHref", "defaultBackHref", "hasValidate", "hasClose", "hasSearch", "canGoBack", "canShowMenu"], outputs: ["onValidate", "onClose", "onValidateAndClose", "onBackClick", "onSearch"] }, { kind: "directive", type: i1$5.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "component", type: AppInstallUpgradeCard, selector: "app-install-upgrade-card", inputs: ["isLogin", "showUpgradeWarning", "showOfflineWarning", "showInstallButton", "debug"] }, { kind: "pipe", type: i3.AsyncPipe, name: "async" }, { kind: "pipe", type: i1$1.TranslatePipe, name: "translate" }, { kind: "pipe", type: i5$1.RxPush, name: "push" }, { kind: "pipe", type: DateFormatPipe, name: "dateFormat" }, { kind: "pipe", type: DateFromNowPipe, name: "dateFromNow" }, { kind: "pipe", type: NotEmptyArrayPipe, name: "isNotEmptyArray" }, { kind: "pipe", type: IsNotNilOrBlankPipe, name: "isNotNilOrBlank" }], animations: [fadeInAnimation, slideUpDownAnimation], changeDetection: i0.ChangeDetectionStrategy.OnPush });
30166
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: HomePage, selector: "app-page-home", usesInheritance: true, ngImport: i0, template: "<app-toolbar [canGoBack]=\"false\" visible-xs visible-sm visible-mobile>\n <!-- Change locale button -->\n <ion-button slot=\"end\" [matMenuTriggerFor]=\"localeMenu\">\n <ion-icon slot=\"start\" name=\"language\"></ion-icon>\n </ion-button>\n</app-toolbar>\n\n<!-- Change locale menu -->\n<mat-menu #localeMenu=\"matMenu\">\n <ng-template matMenuContent>\n @for (item of locales; track item.key) {\n <button mat-menu-item (click)=\"changeLanguage(item.key)\">\n <ion-label>{{ item.value }}</ion-label>\n </button>\n }\n </ng-template>\n</mat-menu>\n\n<ion-content [ngStyle]=\"contentStyle\" no-padding-xs>\n @if (contentCredits | isNotNilOrBlank) {\n <span class=\"content-credits\">\n <ion-text>{{ contentCredits }}</ion-text>\n </span>\n }\n\n <!-- loading spinner -->\n <div class=\"loading-page\" [class.cdk-visually-hidden]=\"!(loading$ | push)\">\n @if (showSpinner) {\n <div class=\"spinner\">\n <p [innerHTML]=\"'COMMON.LOADING_DOTS' | translate\"></p>\n <div class=\"sk-cube1 sk-cube\"></div>\n <div class=\"sk-cube2 sk-cube\"></div>\n <div class=\"sk-cube4 sk-cube\"></div>\n <div class=\"sk-cube3 sk-cube\"></div>\n </div>\n }\n </div>\n\n <!-- Desktop: translucent top toolbar -->\n <div hidden-xs hidden-sm hidden-mobile>\n <ion-toolbar translucent>\n <ion-buttons slot=\"start\">\n <ion-menu-toggle>\n <ion-button color=\"light\" fill=\"clear\">\n <ion-icon slot=\"icon-only\" name=\"menu\"></ion-icon>\n </ion-button>\n </ion-menu-toggle>\n </ion-buttons>\n\n <ion-buttons slot=\"end\">\n <!-- change locale button -->\n <ion-button\n color=\"secondary\"\n fill=\"solid\"\n [matMenuTriggerFor]=\"localeMenu\"\n [title]=\"'SETTINGS.LOCALE' | translate\"\n >\n <ion-icon slot=\"icon-only\" name=\"language\"></ion-icon>\n </ion-button>\n </ion-buttons>\n </ion-toolbar>\n </div>\n\n <!-- Install (and upgrade) card -->\n <app-install-upgrade-card [isLogin]=\"isLogin\" [showInstallButton]=\"true\"></app-install-upgrade-card>\n\n @if (!(loading$ | push)) {\n <!-- Welcome card -->\n <ion-card class=\"main welcome ion-padding ion-text-center ion-align-self-center\" @fadeInAnimation>\n <ion-card-header>\n <ion-card-title class=\"ion-text-center\">\n <span *ngIf=\"isWeb\" [innerHTML]=\"'HOME.WELCOME_WEB' | translate: { appName: appName }\"></span>\n <span *ngIf=\"!isWeb\" [innerHTML]=\"'HOME.WELCOME_APP' | translate: { appName: appName }\"></span>\n </ion-card-title>\n <ion-card-subtitle [innerHTML]=\"description\"></ion-card-subtitle>\n </ion-card-header>\n <ion-card-content class=\"ion-no-padding\">\n <ion-text color=\"primary\">\n <img *ngIf=\"logo\" [attr.src]=\"logo\" alt=\"Logo\" />\n </ion-text>\n <!-- register help text -->\n <ion-text *ngIf=\"!isLogin && canRegister\">\n <br />\n <span translate>HOME.REGISTER_HELP</span>\n </ion-text>\n <div class=\"ion-padding-top\">\n <!-- If NOT login -->\n <ng-container *ngIf=\"!isLogin; else loginButtons\">\n <ion-button *ngIf=\"canRegister\" expand=\"block\" color=\"tertiary\" (click)=\"register()\">\n <span translate>HOME.BTN_REGISTER</span>\n </ion-button>\n <ion-button expand=\"block\" color=\"light\" [routerLink]=\"['/']\" (click)=\"login()\">\n <span translate>AUTH.BTN_LOGIN</span>\n </ion-button>\n </ng-container>\n\n <!-- If user login -->\n <ng-template #loginButtons>\n <!-- Feature buttons -->\n <ng-container *rxIf=\"$filteredButtons; let buttons\">\n <ng-container *ngFor=\"let item of buttons\">\n <ion-button\n *ngIf=\"item.path\"\n expand=\"block\"\n color=\"tertiary\"\n [class]=\"item.cssClass\"\n [routerLink]=\"item.path\"\n routerDirection=\"root\"\n >\n <ion-icon slot=\"start\" class=\"ion-float-start\" *ngIf=\"item.icon\" [name]=\"item.icon\"></ion-icon>\n <mat-icon slot=\"start\" class=\"ion-float-start\" *ngIf=\"item.matIcon\">{{ item.matIcon }}</mat-icon>\n <ion-text>{{ 'HOME.BTN_DATA_ENTRY' | translate: { name: (item.title | translate) } }}</ion-text>\n </ion-button>\n\n <!-- divider -->\n <div *ngIf=\"!item.path && !item.action\" [class]=\"item.cssClass\">\n <ion-label translate>{{ item.title }}&nbsp;</ion-label>\n </div>\n </ng-container>\n\n <!--<p *ngIf=\"buttons.length\" class=\"visible-mobile\">&nbsp;</p>-->\n </ng-container>\n\n <ion-button *ngIf=\"showAccountButton\" expand=\"block\" color=\"secondary\" [routerLink]=\"['/account']\">\n <ion-icon slot=\"start\" class=\"ion-float-start\" name=\"person-circle\"></ion-icon>\n <ion-text translate>HOME.BTN_MY_ACCOUNT</ion-text>\n </ion-button>\n\n <p hidden-xs hidden-sm hidden-mobile>\n <ion-text\n [innerHTML]=\"'HOME.NOT_THIS_ACCOUNT_QUESTION' | translate: { displayName: accountName }\"\n ></ion-text>\n <br />\n <ion-text>\n <a href=\"#\" (click)=\"logout($event)\">\n <span translate>HOME.BTN_DISCONNECT</span>\n </a>\n </ion-text>\n </p>\n </ng-template>\n </div>\n </ion-card-content>\n </ion-card>\n\n <!-- Page history -->\n @let pageHistory = isLogin && (pageHistory$ | push);\n @if (pageHistory | isNotEmptyArray) {\n <ion-grid class=\"history-container ion-align-self-center\">\n <ion-row>\n @for (page of pageHistory; track page.path) {\n <ion-col size=\"12\" size-xl=\"\" class=\"ion-text-center\">\n <ion-card class=\"ion-align-self-start ion-text-start\" @fadeInAnimation>\n <ion-card-header class=\"ion-no-padding\">\n <!-- top bar -->\n <ion-card-subtitle>\n <button\n type=\"button\"\n tabindex=\"-1\"\n (click)=\"removePageHistory(page.path)\"\n mat-icon-button\n class=\"ion-float-start ion-no-margin close-button\"\n >\n <mat-icon>close</mat-icon>\n </button>\n <ion-label [innerHTML]=\"page.subtitle | translate\"></ion-label>\n <ion-text class=\"ion-float-end\" [title]=\"page.time | dateFormat: { time: true }\">\n <small>\n <ion-icon name=\"time-outline\"></ion-icon>\n &nbsp;{{ page.time | dateFromNow }}\n </small>\n &nbsp;\n </ion-text>\n </ion-card-subtitle>\n\n <!-- main page -->\n <ion-card-title class=\"ion-no-margin ion-no-padding\">\n <ion-item\n detail=\"true\"\n tappable\n class=\"text-1x\"\n [routerLink]=\"page.path\"\n routerDirection=\"root\"\n lines=\"none\"\n >\n <!-- page icon-->\n <ion-icon *ngIf=\"page.icon\" slot=\"start\" [name]=\"page.icon\"></ion-icon>\n <mat-icon *ngIf=\"page.matIcon\" slot=\"start\">{{ page.matIcon }}</mat-icon>\n\n <ion-label color=\"primary\" [innerHTML]=\"page.title\"></ion-label>\n </ion-item>\n </ion-card-title>\n </ion-card-header>\n\n <!-- children pages -->\n @if (page.children | isNotEmptyArray) {\n <ion-card-content class=\"ion-no-padding ion-padding-start\">\n <ion-list class=\"ion-no-padding\">\n @for (childPage of page.children; track childPage.path) {\n <ion-item\n detail=\"true\"\n tappable\n class=\"text-1x\"\n [routerLink]=\"childPage.path\"\n routerDirection=\"root\"\n >\n <!-- page icon-->\n <ion-icon *ngIf=\"childPage.icon\" slot=\"start\" color=\"dark\" [name]=\"childPage.icon\"></ion-icon>\n <mat-icon *ngIf=\"childPage.matIcon\" slot=\"start\" color=\"dark\">\n {{ childPage.matIcon }}\n </mat-icon>\n\n <ion-label color=\"dark\" [innerHTML]=\"childPage.title\"></ion-label>\n </ion-item>\n }\n </ion-list>\n </ion-card-content>\n }\n </ion-card>\n </ion-col>\n }\n </ion-row>\n </ion-grid>\n } @else if (showPartnerBanner || showLegalInformation) {\n <ng-container *ngTemplateOutlet=\"bottomBanner\"></ng-container>\n }\n }\n</ion-content>\n\n<ng-template #bottomBanner>\n <ion-grid class=\"bottom-banner ion-text-center\" [class.floating]=\"!mobile\" @fadeInAnimation>\n <ion-row>\n @if (showPartnerBanner) {\n <ion-col size=\"12\" [sizeLg]=\"partnerBannerSize\" class=\"ion-text-center\">\n @if (showLegalInformation) {\n <ion-list class=\"legal-info\">\n <ion-list-header>{{ 'HOME.PARTNERS' | translate }}</ion-list-header>\n </ion-list>\n }\n <!-- partners -->\n @for (item of $partners | async; track $index) {\n <a href=\"{{ item.siteUrl }}\">\n <img class=\"logo\" src=\"{{ item.logo }}\" alt=\"{{ item.label }}\" [title]=\"item.label\" />\n </a>\n }\n </ion-col>\n }\n @if (showLegalInformation) {\n <ion-col size=\"4\" size-lg=\"3\" [class.left-border]=\"showPartnerBanner\">\n <ion-list class=\"legal-info\">\n <ion-list-header class=\"ion-text-left\">{{ 'HOME.LEGAL_INFORMATION' | translate }}</ion-list-header>\n @for (item of legalInformation; track item.path) {\n <ion-item (click)=\"openHelpModal($event, item)\" lines=\"none\" [button]=\"true\">\n <ion-label>\n <p>\n {{ item.title | translate: item.titleArgs }}\n </p>\n </ion-label>\n </ion-item>\n }\n </ion-list>\n </ion-col>\n @if (showInstallLinks) {\n <ion-col size=\"12\" size-lg=\"3\" offset-lg=\"9\" [class.left-border]=\"showPartnerBanner\">\n <ion-list class=\"legal-info\">\n <ion-list-header>{{ 'HOME.INSTALL_APP' | translate }}</ion-list-header>\n <!-- TODO -->\n </ion-list>\n </ion-col>\n }\n }\n </ion-row>\n </ion-grid>\n</ng-template>\n", styles: [":host{--ion-card-background-color: rgba(var(--ion-background-color-rgb), .7)}h1,h2,h3,h4,h5{white-space:normal}.center,ion-content ion-card.welcome img{text-align:center;display:inline-block}ion-content{--background: transparent;background-size:cover;-webkit-background-size:cover;-moz-background-size:cover;-o-background-size:cover;background-color:var(--ion-background-color);display:inline-block;padding:15px}ion-content .loading-page{display:block;height:100%;width:100%;position:absolute;background-color:transparent;z-index:5;transition:background .5s linear;-webkit-transition:background 1.5s linear}ion-content .loading-page.hidden{background-color:rgba(var(--ion-color-primary),0)}ion-content ion-card{z-index:9}ion-content ion-card ion-card-header{display:block}ion-content ion-card ion-card-header ion-card-subtitle,ion-content ion-card ion-card-header ion-card-title{display:block;width:100%}ion-content ion-card.main{min-width:240px;max-width:400px;margin-left:auto;margin-right:auto}ion-content ion-card.welcome{background-color:var(--ion-card-background-color)}ion-content ion-card.welcome button{margin-top:16px}ion-content ion-card.welcome img{max-width:250px}ion-content .history-container{margin-left:auto;margin-right:auto}ion-content .history-container ion-card{display:inline-block;box-sizing:border-box;z-index:8;min-width:240px;max-width:400px;width:100%;margin-left:auto;margin-right:auto;background-color:var(--ion-card-background-color)}ion-content .history-container ion-card ion-card-header ion-card-subtitle{height:40px}ion-content .history-container ion-card ion-card-header ion-card-subtitle button[float-start]{--mdc-icon-button-state-layer-size: 40px;padding:8px;z-index:99;margin:0}ion-content .history-container ion-card ion-card-header ion-card-subtitle ion-label{line-height:40px}ion-content .history-container ion-card ion-card-header ion-card-subtitle ion-label[float-end]{padding-right:16px;font-weight:400}ion-content .history-container ion-card ion-card-header ion-card-title ion-item{width:100%;--ion-item-background: $transparent;--ion-item-icon-color: var(--ion-color-primary);--ion-item-text-color: var(--ion-color-primary)}ion-content .history-container ion-card ion-card-header ion-card-title ion-item ion-icon[slot=start],ion-content .history-container ion-card ion-card-header ion-card-title ion-item mat-icon[slot=start]{margin-right:unset;margin-inline-end:16px!important;color:var(--ion-item-icon-color)!important;fill:currentColor;stroke:currentColor}ion-content .history-container ion-card ion-card-header ion-card-title ion-item ion-text,ion-content .history-container ion-card ion-card-header ion-card-title ion-item ion-label{color:var(--ion-item-text-color)!important;-webkit-text-size-adjust:100%;-moz-text-size-adjust:100%;-ms-text-size-adjust:100%;text-size-adjust:100%}ion-content .history-container ion-card ion-card-content ion-list{--ion-item-background: var(--ion-color-transparent)}ion-content .history-container ion-card ion-card-content ion-list ion-item{--ion-item-icon-color: var(--ion-color-dark);--ion-item-text-color: var(--ion-color-dark)}ion-content .history-container ion-card ion-card-content ion-list ion-item ion-icon[slot=start],ion-content .history-container ion-card ion-card-content ion-list ion-item mat-icon[slot=start]{color:var(--ion-item-icon-color)!important;fill:currentColor;stroke:currentColor;margin-right:unset;margin-inline-end:16px!important}ion-content .history-container ion-card ion-card-content ion-list ion-item ion-text,ion-content .history-container ion-card ion-card-content ion-list ion-item ion-label{color:var(--ion-item-text-color)!important}ion-content .bottom-banner{background-color:var(--ion-card-background-color);min-width:240px;z-index:0}ion-content .bottom-banner.floating{position:absolute;left:16px;right:16px;bottom:16px}ion-content .bottom-banner img.logo{max-height:50px;margin-left:8px}ion-content ion-text{text-align:center}@media screen and (max-width: 575px){ion-content ion-card{min-width:160px;width:calc(100% - 20px);max-width:100%;margin-left:10px;margin-right:10px}ion-content ion-card h1{margin-top:0;font-size:20px}ion-content ion-card ion-card-content ion-button{margin-top:8px}ion-content .bottom-banner.floating{display:block;position:unset}ion-content .bottom-banner img.logo{max-height:30px}}@media screen and (max-width: 767px) and (min-width: 576px){ion-content{min-height:555px}ion-content .bottom-banner img.logo{max-height:40px}}@media screen and (min-width: 768px){ion-content{min-height:calc(100% - 100px)}}.content-credits{position:absolute;right:0;bottom:0}.content-credits ion-text{padding-inline-start:4px;padding-inline-end:4px;font-size:.8rem;background-color:var(--ion-background-color, white);color:var(--ion-text-color);opacity:.65}@media screen and (min-width: 992px){.left-border{border-left:1px solid var(--ion-color-medium)}}.bottom-banner ion-list-header{min-height:30px}.bottom-banner ion-item{--min-height: 28px}.bottom-banner ion-item ion-label{margin-top:3px!important;margin-bottom:3px!important}\n"], dependencies: [{ kind: "directive", type: i3.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i3.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i3.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: i2$1.IonButton, selector: "ion-button", inputs: ["buttonType", "color", "disabled", "download", "expand", "fill", "form", "href", "mode", "rel", "routerAnimation", "routerDirection", "shape", "size", "strong", "target", "type"] }, { kind: "component", type: i2$1.IonButtons, selector: "ion-buttons", inputs: ["collapse"] }, { kind: "component", type: i2$1.IonCard, selector: "ion-card", inputs: ["button", "color", "disabled", "download", "href", "mode", "rel", "routerAnimation", "routerDirection", "target", "type"] }, { kind: "component", type: i2$1.IonCardContent, selector: "ion-card-content", inputs: ["mode"] }, { kind: "component", type: i2$1.IonCardHeader, selector: "ion-card-header", inputs: ["color", "mode", "translucent"] }, { kind: "component", type: i2$1.IonCardSubtitle, selector: "ion-card-subtitle", inputs: ["color", "mode"] }, { kind: "component", type: i2$1.IonCardTitle, selector: "ion-card-title", inputs: ["color", "mode"] }, { kind: "component", type: i2$1.IonCol, selector: "ion-col", inputs: ["offset", "offsetLg", "offsetMd", "offsetSm", "offsetXl", "offsetXs", "pull", "pullLg", "pullMd", "pullSm", "pullXl", "pullXs", "push", "pushLg", "pushMd", "pushSm", "pushXl", "pushXs", "size", "sizeLg", "sizeMd", "sizeSm", "sizeXl", "sizeXs"] }, { kind: "component", type: i2$1.IonContent, selector: "ion-content", inputs: ["color", "forceOverscroll", "fullscreen", "scrollEvents", "scrollX", "scrollY"] }, { kind: "component", type: i2$1.IonGrid, selector: "ion-grid", inputs: ["fixed"] }, { kind: "component", type: i2$1.IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: i2$1.IonItem, selector: "ion-item", inputs: ["button", "color", "counter", "counterFormatter", "detail", "detailIcon", "disabled", "download", "fill", "href", "lines", "mode", "rel", "routerAnimation", "routerDirection", "shape", "target", "type"] }, { kind: "component", type: i2$1.IonLabel, selector: "ion-label", inputs: ["color", "mode", "position"] }, { kind: "component", type: i2$1.IonList, selector: "ion-list", inputs: ["inset", "lines", "mode"] }, { kind: "component", type: i2$1.IonListHeader, selector: "ion-list-header", inputs: ["color", "lines", "mode"] }, { kind: "component", type: i2$1.IonMenuToggle, selector: "ion-menu-toggle", inputs: ["autoHide", "menu"] }, { kind: "component", type: i2$1.IonRow, selector: "ion-row" }, { kind: "component", type: i2$1.IonText, selector: "ion-text", inputs: ["color", "mode"] }, { kind: "component", type: i2$1.IonToolbar, selector: "ion-toolbar", inputs: ["color", "mode"] }, { kind: "directive", type: i2$1.RouterLinkDelegate, selector: ":not(a):not(area)[routerLink]" }, { kind: "directive", type: i1$1.TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }, { kind: "directive", type: i9$2.RxIf, selector: "[rxIf]", inputs: ["rxIf", "rxIfStrategy", "rxIfElse", "rxIfThen", "rxIfSuspense", "rxIfComplete", "rxIfError", "rxIfContextTrigger", "rxIfNextTrigger", "rxIfSuspenseTrigger", "rxIfErrorTrigger", "rxIfCompleteTrigger", "rxIfParent", "rxIfPatchZone", "rxIfRenderCallback"] }, { kind: "component", type: i6$2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i9.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "component", type: i8$1.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: i8$1.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i8$1.MatMenuContent, selector: "ng-template[matMenuContent]" }, { kind: "directive", type: i8$1.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "component", type: ToolbarComponent, selector: "app-toolbar", inputs: ["progressBarMode", "title", "color", "class", "backHref", "defaultBackHref", "hasValidate", "hasClose", "hasSearch", "canGoBack", "canShowMenu"], outputs: ["onValidate", "onClose", "onValidateAndClose", "onBackClick", "onSearch"] }, { kind: "directive", type: i1$5.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "component", type: AppInstallUpgradeCard, selector: "app-install-upgrade-card", inputs: ["isLogin", "showUpgradeWarning", "showOfflineWarning", "showInstallButton", "debug"] }, { kind: "pipe", type: i3.AsyncPipe, name: "async" }, { kind: "pipe", type: i1$1.TranslatePipe, name: "translate" }, { kind: "pipe", type: i5$1.RxPush, name: "push" }, { kind: "pipe", type: DateFormatPipe, name: "dateFormat" }, { kind: "pipe", type: DateFromNowPipe, name: "dateFromNow" }, { kind: "pipe", type: NotEmptyArrayPipe, name: "isNotEmptyArray" }, { kind: "pipe", type: IsNotNilOrBlankPipe, name: "isNotNilOrBlank" }], animations: [fadeInAnimation, slideUpDownAnimation], changeDetection: i0.ChangeDetectionStrategy.OnPush });
30075
30167
  }
30076
30168
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: HomePage, decorators: [{
30077
30169
  type: Component,
30078
- args: [{ selector: 'app-page-home', changeDetection: ChangeDetectionStrategy.OnPush, animations: [fadeInAnimation, slideUpDownAnimation], template: "<app-toolbar [canGoBack]=\"false\" visible-xs visible-sm visible-mobile>\n <!-- Change locale button -->\n <ion-button slot=\"end\" [matMenuTriggerFor]=\"localeMenu\">\n <ion-icon slot=\"start\" name=\"language\"></ion-icon>\n </ion-button>\n</app-toolbar>\n\n<!-- Change locale menu -->\n<mat-menu #localeMenu=\"matMenu\">\n <ng-template matMenuContent>\n @for (item of locales; track item.key) {\n <button mat-menu-item (click)=\"changeLanguage(item.key)\">\n <ion-label>{{ item.value }}</ion-label>\n </button>\n }\n </ng-template>\n</mat-menu>\n\n<ion-content [ngStyle]=\"contentStyle\" no-padding-xs>\n @if (contentCredits | isNotNilOrBlank) {\n <span class=\"content-credits\">\n <ion-text>{{ contentCredits }}</ion-text>\n </span>\n }\n\n <!-- loading spinner -->\n <div class=\"loading-page\" [class.cdk-visually-hidden]=\"!(loading$ | push)\">\n @if (showSpinner) {\n <div class=\"spinner\">\n <p [innerHTML]=\"'COMMON.LOADING_DOTS' | translate\"></p>\n <div class=\"sk-cube1 sk-cube\"></div>\n <div class=\"sk-cube2 sk-cube\"></div>\n <div class=\"sk-cube4 sk-cube\"></div>\n <div class=\"sk-cube3 sk-cube\"></div>\n </div>\n }\n </div>\n\n <!-- Desktop: translucent top toolbar -->\n <div hidden-xs hidden-sm hidden-mobile>\n <ion-toolbar translucent>\n <ion-buttons slot=\"start\">\n <ion-menu-toggle>\n <ion-button color=\"light\" fill=\"clear\">\n <ion-icon slot=\"icon-only\" name=\"menu\"></ion-icon>\n </ion-button>\n </ion-menu-toggle>\n </ion-buttons>\n\n <ion-buttons slot=\"end\">\n <!-- change locale button -->\n <ion-button\n color=\"secondary\"\n fill=\"solid\"\n [matMenuTriggerFor]=\"localeMenu\"\n [title]=\"'SETTINGS.LOCALE' | translate\"\n >\n <ion-icon slot=\"icon-only\" name=\"language\"></ion-icon>\n </ion-button>\n </ion-buttons>\n </ion-toolbar>\n </div>\n\n <!-- Install (and upgrade) card -->\n <app-install-upgrade-card [isLogin]=\"isLogin\" [showInstallButton]=\"true\"></app-install-upgrade-card>\n\n @if (!(loading$ | push)) {\n <!-- Welcome card -->\n <ion-card class=\"main welcome ion-padding ion-text-center ion-align-self-center\" @fadeInAnimation>\n <ion-card-header>\n <ion-card-title class=\"ion-text-center\">\n <span *ngIf=\"isWeb\" [innerHTML]=\"'HOME.WELCOME_WEB' | translate: { appName: appName }\"></span>\n <span *ngIf=\"!isWeb\" [innerHTML]=\"'HOME.WELCOME_APP' | translate: { appName: appName }\"></span>\n </ion-card-title>\n <ion-card-subtitle [innerHTML]=\"description\"></ion-card-subtitle>\n </ion-card-header>\n <ion-card-content class=\"ion-no-padding\">\n <ion-text color=\"primary\">\n <img *ngIf=\"logo\" [attr.src]=\"logo\" alt=\"Logo\" />\n </ion-text>\n <!-- register help text -->\n <ion-text *ngIf=\"!isLogin && canRegister\">\n <br />\n <span translate>HOME.REGISTER_HELP</span>\n </ion-text>\n <div class=\"ion-padding-top\">\n <!-- If NOT login -->\n <ng-container *ngIf=\"!isLogin; else loginButtons\">\n <ion-button *ngIf=\"canRegister\" expand=\"block\" color=\"tertiary\" (click)=\"register()\">\n <span translate>HOME.BTN_REGISTER</span>\n </ion-button>\n <ion-button expand=\"block\" color=\"light\" [routerLink]=\"['/']\" (click)=\"login()\">\n <span translate>AUTH.BTN_LOGIN</span>\n </ion-button>\n </ng-container>\n\n <!-- If user login -->\n <ng-template #loginButtons>\n <!-- Feature buttons -->\n <ng-container *rxIf=\"$filteredButtons; let buttons\">\n <ng-container *ngFor=\"let item of buttons\">\n <ion-button\n *ngIf=\"item.path\"\n expand=\"block\"\n color=\"tertiary\"\n [class]=\"item.cssClass\"\n [routerLink]=\"item.path\"\n routerDirection=\"root\"\n >\n <ion-icon slot=\"start\" class=\"ion-float-start\" *ngIf=\"item.icon\" [name]=\"item.icon\"></ion-icon>\n <mat-icon slot=\"start\" class=\"ion-float-start\" *ngIf=\"item.matIcon\">{{ item.matIcon }}</mat-icon>\n <ion-text>{{ 'HOME.BTN_DATA_ENTRY' | translate: { name: (item.title | translate) } }}</ion-text>\n </ion-button>\n\n <!-- divider -->\n <div *ngIf=\"!item.path && !item.action\" [class]=\"item.cssClass\">\n <ion-label translate>{{ item.title }}&nbsp;</ion-label>\n </div>\n </ng-container>\n\n <!--<p *ngIf=\"buttons.length\" class=\"visible-mobile\">&nbsp;</p>-->\n </ng-container>\n\n <ion-button *ngIf=\"showAccountButton\" expand=\"block\" color=\"secondary\" [routerLink]=\"['/account']\">\n <ion-icon slot=\"start\" class=\"ion-float-start\" name=\"person-circle\"></ion-icon>\n <ion-text translate>HOME.BTN_MY_ACCOUNT</ion-text>\n </ion-button>\n\n <p hidden-xs hidden-sm hidden-mobile>\n <ion-text\n [innerHTML]=\"'HOME.NOT_THIS_ACCOUNT_QUESTION' | translate: { displayName: accountName }\"\n ></ion-text>\n <br />\n <ion-text>\n <a href=\"#\" (click)=\"logout($event)\">\n <span translate>HOME.BTN_DISCONNECT</span>\n </a>\n </ion-text>\n </p>\n </ng-template>\n </div>\n </ion-card-content>\n </ion-card>\n\n <!-- Page history -->\n @if (isLogin && (pageHistory$ | push); as pageHistory) {\n <ion-grid class=\"history-container ion-align-self-center\">\n <ion-row>\n @for (page of pageHistory; track page.path) {\n <ion-col size=\"12\" size-xl=\"\" class=\"ion-text-center\">\n <ion-card class=\"ion-align-self-start ion-text-start\" @fadeInAnimation>\n <ion-card-header class=\"ion-no-padding\">\n <!-- top bar -->\n <ion-card-subtitle>\n <button\n type=\"button\"\n tabindex=\"-1\"\n (click)=\"removePageHistory(page.path)\"\n mat-icon-button\n class=\"ion-float-start ion-no-margin close-button\"\n >\n <mat-icon>close</mat-icon>\n </button>\n <ion-label [innerHTML]=\"page.subtitle | translate\"></ion-label>\n <ion-text class=\"ion-float-end\" [title]=\"page.time | dateFormat: { time: true }\">\n <small>\n <ion-icon name=\"time-outline\"></ion-icon>\n &nbsp;{{ page.time | dateFromNow }}\n </small>\n &nbsp;\n </ion-text>\n </ion-card-subtitle>\n\n <!-- main page -->\n <ion-card-title class=\"ion-no-margin ion-no-padding\">\n <ion-item\n detail=\"true\"\n tappable\n class=\"text-1x\"\n [routerLink]=\"page.path\"\n routerDirection=\"root\"\n lines=\"none\"\n >\n <!-- page icon-->\n <ion-icon *ngIf=\"page.icon\" slot=\"start\" [name]=\"page.icon\"></ion-icon>\n <mat-icon *ngIf=\"page.matIcon\" slot=\"start\">{{ page.matIcon }}</mat-icon>\n\n <ion-label color=\"primary\" [innerHTML]=\"page.title\"></ion-label>\n </ion-item>\n </ion-card-title>\n </ion-card-header>\n\n <!-- children pages -->\n @if (page.children | isNotEmptyArray) {\n <ion-card-content class=\"ion-no-padding ion-padding-start\">\n <ion-list class=\"ion-no-padding\">\n @for (childPage of page.children; track childPage.path) {\n <ion-item\n detail=\"true\"\n tappable\n class=\"text-1x\"\n [routerLink]=\"childPage.path\"\n routerDirection=\"root\"\n >\n <!-- page icon-->\n <ion-icon *ngIf=\"childPage.icon\" slot=\"start\" color=\"dark\" [name]=\"childPage.icon\"></ion-icon>\n <mat-icon *ngIf=\"childPage.matIcon\" slot=\"start\" color=\"dark\">\n {{ childPage.matIcon }}\n </mat-icon>\n\n <ion-label color=\"dark\" [innerHTML]=\"childPage.title\"></ion-label>\n </ion-item>\n }\n </ion-list>\n </ion-card-content>\n }\n </ion-card>\n </ion-col>\n }\n </ion-row>\n </ion-grid>\n } @else if (showPartnerBanner) {\n <!-- Display partners logos -->\n <div class=\"bottom-banner ion-text-center ion-padding\" @fadeInAnimation>\n @for (item of $partners | async; track $index) {\n <a href=\"{{ item.siteUrl }}\">\n <img class=\"logo\" src=\"{{ item.logo }}\" alt=\"{{ item.label }}\" [title]=\"item.label\" />\n </a>\n }\n </div>\n }\n }\n</ion-content>\n", styles: ["h1,h2,h3,h4,h5{white-space:normal}.center,ion-content ion-card.welcome img{text-align:center;display:inline-block}ion-content{--background: transparent;background-size:cover;-webkit-background-size:cover;-moz-background-size:cover;-o-background-size:cover;background-color:var(--ion-background-color);display:inline-block;padding:15px}ion-content .loading-page{display:block;height:100%;width:100%;position:absolute;background-color:transparent;z-index:5;transition:background .5s linear;-webkit-transition:background 1.5s linear}ion-content .loading-page.hidden{background-color:rgba(var(--ion-color-primary),0)}ion-content ion-card{z-index:9}ion-content ion-card ion-card-header{display:block}ion-content ion-card ion-card-header ion-card-subtitle,ion-content ion-card ion-card-header ion-card-title{display:block;width:100%}ion-content ion-card.main{min-width:240px;max-width:400px;margin-left:auto;margin-right:auto}ion-content ion-card.welcome{background-color:var(--ion-card-background-color)}ion-content ion-card.welcome button{margin-top:16px}ion-content ion-card.welcome img{max-width:250px}ion-content .history-container{margin-left:auto;margin-right:auto}ion-content .history-container ion-card{display:inline-block;box-sizing:border-box;z-index:8;min-width:240px;max-width:400px;width:100%;margin-left:auto;margin-right:auto;background-color:var(--ion-card-background-color)}ion-content .history-container ion-card ion-card-header ion-card-subtitle{height:40px}ion-content .history-container ion-card ion-card-header ion-card-subtitle button[float-start]{--mdc-icon-button-state-layer-size: 40px;padding:8px;z-index:99;margin:0}ion-content .history-container ion-card ion-card-header ion-card-subtitle ion-label{line-height:40px}ion-content .history-container ion-card ion-card-header ion-card-subtitle ion-label[float-end]{padding-right:16px;font-weight:400}ion-content .history-container ion-card ion-card-header ion-card-title ion-item{width:100%;--ion-item-background: $transparent;--ion-item-icon-color: var(--ion-color-primary);--ion-item-text-color: var(--ion-color-primary)}ion-content .history-container ion-card ion-card-header ion-card-title ion-item ion-icon[slot=start],ion-content .history-container ion-card ion-card-header ion-card-title ion-item mat-icon[slot=start]{margin-right:unset;margin-inline-end:16px!important;color:var(--ion-item-icon-color)!important;fill:currentColor;stroke:currentColor}ion-content .history-container ion-card ion-card-header ion-card-title ion-item ion-text,ion-content .history-container ion-card ion-card-header ion-card-title ion-item ion-label{color:var(--ion-item-text-color)!important;-webkit-text-size-adjust:100%;-moz-text-size-adjust:100%;-ms-text-size-adjust:100%;text-size-adjust:100%}ion-content .history-container ion-card ion-card-content ion-list{--ion-item-background: var(--ion-color-transparent)}ion-content .history-container ion-card ion-card-content ion-list ion-item{--ion-item-icon-color: var(--ion-color-dark);--ion-item-text-color: var(--ion-color-dark)}ion-content .history-container ion-card ion-card-content ion-list ion-item ion-icon[slot=start],ion-content .history-container ion-card ion-card-content ion-list ion-item mat-icon[slot=start]{color:var(--ion-item-icon-color)!important;fill:currentColor;stroke:currentColor;margin-right:unset;margin-inline-end:16px!important}ion-content .history-container ion-card ion-card-content ion-list ion-item ion-text,ion-content .history-container ion-card ion-card-content ion-list ion-item ion-label{color:var(--ion-item-text-color)!important}ion-content .bottom-banner{background-color:var(--ion-card-background-color);min-width:240px;z-index:0;position:absolute;left:16px;right:16px;bottom:16px}ion-content .bottom-banner img.logo{max-height:50px;margin-left:8px}ion-content ion-text{text-align:center}@media screen and (max-width: 575px){ion-content ion-card{min-width:160px;width:calc(100% - 20px);max-width:100%;margin-left:10px;margin-right:10px}ion-content ion-card h1{margin-top:0;font-size:20px}ion-content ion-card ion-card-content ion-button{margin-top:8px}ion-content .bottom-banner{display:block;position:unset}ion-content .bottom-banner img.logo{max-height:30px}}@media screen and (max-width: 767px) and (min-width: 576px){ion-content{min-height:555px}ion-content .bottom-banner img.logo{max-height:40px}}@media screen and (min-width: 768px){ion-content{min-height:calc(100% - 100px)}}.content-credits{position:absolute;right:5px;bottom:5px}.content-credits ion-text{padding-inline-start:4px;padding-inline-end:4px;font-size:.8rem;background-color:var(--ion-background-color, white);color:var(--ion-text-color);opacity:.65}\n"] }]
30170
+ args: [{ selector: 'app-page-home', changeDetection: ChangeDetectionStrategy.OnPush, animations: [fadeInAnimation, slideUpDownAnimation], template: "<app-toolbar [canGoBack]=\"false\" visible-xs visible-sm visible-mobile>\n <!-- Change locale button -->\n <ion-button slot=\"end\" [matMenuTriggerFor]=\"localeMenu\">\n <ion-icon slot=\"start\" name=\"language\"></ion-icon>\n </ion-button>\n</app-toolbar>\n\n<!-- Change locale menu -->\n<mat-menu #localeMenu=\"matMenu\">\n <ng-template matMenuContent>\n @for (item of locales; track item.key) {\n <button mat-menu-item (click)=\"changeLanguage(item.key)\">\n <ion-label>{{ item.value }}</ion-label>\n </button>\n }\n </ng-template>\n</mat-menu>\n\n<ion-content [ngStyle]=\"contentStyle\" no-padding-xs>\n @if (contentCredits | isNotNilOrBlank) {\n <span class=\"content-credits\">\n <ion-text>{{ contentCredits }}</ion-text>\n </span>\n }\n\n <!-- loading spinner -->\n <div class=\"loading-page\" [class.cdk-visually-hidden]=\"!(loading$ | push)\">\n @if (showSpinner) {\n <div class=\"spinner\">\n <p [innerHTML]=\"'COMMON.LOADING_DOTS' | translate\"></p>\n <div class=\"sk-cube1 sk-cube\"></div>\n <div class=\"sk-cube2 sk-cube\"></div>\n <div class=\"sk-cube4 sk-cube\"></div>\n <div class=\"sk-cube3 sk-cube\"></div>\n </div>\n }\n </div>\n\n <!-- Desktop: translucent top toolbar -->\n <div hidden-xs hidden-sm hidden-mobile>\n <ion-toolbar translucent>\n <ion-buttons slot=\"start\">\n <ion-menu-toggle>\n <ion-button color=\"light\" fill=\"clear\">\n <ion-icon slot=\"icon-only\" name=\"menu\"></ion-icon>\n </ion-button>\n </ion-menu-toggle>\n </ion-buttons>\n\n <ion-buttons slot=\"end\">\n <!-- change locale button -->\n <ion-button\n color=\"secondary\"\n fill=\"solid\"\n [matMenuTriggerFor]=\"localeMenu\"\n [title]=\"'SETTINGS.LOCALE' | translate\"\n >\n <ion-icon slot=\"icon-only\" name=\"language\"></ion-icon>\n </ion-button>\n </ion-buttons>\n </ion-toolbar>\n </div>\n\n <!-- Install (and upgrade) card -->\n <app-install-upgrade-card [isLogin]=\"isLogin\" [showInstallButton]=\"true\"></app-install-upgrade-card>\n\n @if (!(loading$ | push)) {\n <!-- Welcome card -->\n <ion-card class=\"main welcome ion-padding ion-text-center ion-align-self-center\" @fadeInAnimation>\n <ion-card-header>\n <ion-card-title class=\"ion-text-center\">\n <span *ngIf=\"isWeb\" [innerHTML]=\"'HOME.WELCOME_WEB' | translate: { appName: appName }\"></span>\n <span *ngIf=\"!isWeb\" [innerHTML]=\"'HOME.WELCOME_APP' | translate: { appName: appName }\"></span>\n </ion-card-title>\n <ion-card-subtitle [innerHTML]=\"description\"></ion-card-subtitle>\n </ion-card-header>\n <ion-card-content class=\"ion-no-padding\">\n <ion-text color=\"primary\">\n <img *ngIf=\"logo\" [attr.src]=\"logo\" alt=\"Logo\" />\n </ion-text>\n <!-- register help text -->\n <ion-text *ngIf=\"!isLogin && canRegister\">\n <br />\n <span translate>HOME.REGISTER_HELP</span>\n </ion-text>\n <div class=\"ion-padding-top\">\n <!-- If NOT login -->\n <ng-container *ngIf=\"!isLogin; else loginButtons\">\n <ion-button *ngIf=\"canRegister\" expand=\"block\" color=\"tertiary\" (click)=\"register()\">\n <span translate>HOME.BTN_REGISTER</span>\n </ion-button>\n <ion-button expand=\"block\" color=\"light\" [routerLink]=\"['/']\" (click)=\"login()\">\n <span translate>AUTH.BTN_LOGIN</span>\n </ion-button>\n </ng-container>\n\n <!-- If user login -->\n <ng-template #loginButtons>\n <!-- Feature buttons -->\n <ng-container *rxIf=\"$filteredButtons; let buttons\">\n <ng-container *ngFor=\"let item of buttons\">\n <ion-button\n *ngIf=\"item.path\"\n expand=\"block\"\n color=\"tertiary\"\n [class]=\"item.cssClass\"\n [routerLink]=\"item.path\"\n routerDirection=\"root\"\n >\n <ion-icon slot=\"start\" class=\"ion-float-start\" *ngIf=\"item.icon\" [name]=\"item.icon\"></ion-icon>\n <mat-icon slot=\"start\" class=\"ion-float-start\" *ngIf=\"item.matIcon\">{{ item.matIcon }}</mat-icon>\n <ion-text>{{ 'HOME.BTN_DATA_ENTRY' | translate: { name: (item.title | translate) } }}</ion-text>\n </ion-button>\n\n <!-- divider -->\n <div *ngIf=\"!item.path && !item.action\" [class]=\"item.cssClass\">\n <ion-label translate>{{ item.title }}&nbsp;</ion-label>\n </div>\n </ng-container>\n\n <!--<p *ngIf=\"buttons.length\" class=\"visible-mobile\">&nbsp;</p>-->\n </ng-container>\n\n <ion-button *ngIf=\"showAccountButton\" expand=\"block\" color=\"secondary\" [routerLink]=\"['/account']\">\n <ion-icon slot=\"start\" class=\"ion-float-start\" name=\"person-circle\"></ion-icon>\n <ion-text translate>HOME.BTN_MY_ACCOUNT</ion-text>\n </ion-button>\n\n <p hidden-xs hidden-sm hidden-mobile>\n <ion-text\n [innerHTML]=\"'HOME.NOT_THIS_ACCOUNT_QUESTION' | translate: { displayName: accountName }\"\n ></ion-text>\n <br />\n <ion-text>\n <a href=\"#\" (click)=\"logout($event)\">\n <span translate>HOME.BTN_DISCONNECT</span>\n </a>\n </ion-text>\n </p>\n </ng-template>\n </div>\n </ion-card-content>\n </ion-card>\n\n <!-- Page history -->\n @let pageHistory = isLogin && (pageHistory$ | push);\n @if (pageHistory | isNotEmptyArray) {\n <ion-grid class=\"history-container ion-align-self-center\">\n <ion-row>\n @for (page of pageHistory; track page.path) {\n <ion-col size=\"12\" size-xl=\"\" class=\"ion-text-center\">\n <ion-card class=\"ion-align-self-start ion-text-start\" @fadeInAnimation>\n <ion-card-header class=\"ion-no-padding\">\n <!-- top bar -->\n <ion-card-subtitle>\n <button\n type=\"button\"\n tabindex=\"-1\"\n (click)=\"removePageHistory(page.path)\"\n mat-icon-button\n class=\"ion-float-start ion-no-margin close-button\"\n >\n <mat-icon>close</mat-icon>\n </button>\n <ion-label [innerHTML]=\"page.subtitle | translate\"></ion-label>\n <ion-text class=\"ion-float-end\" [title]=\"page.time | dateFormat: { time: true }\">\n <small>\n <ion-icon name=\"time-outline\"></ion-icon>\n &nbsp;{{ page.time | dateFromNow }}\n </small>\n &nbsp;\n </ion-text>\n </ion-card-subtitle>\n\n <!-- main page -->\n <ion-card-title class=\"ion-no-margin ion-no-padding\">\n <ion-item\n detail=\"true\"\n tappable\n class=\"text-1x\"\n [routerLink]=\"page.path\"\n routerDirection=\"root\"\n lines=\"none\"\n >\n <!-- page icon-->\n <ion-icon *ngIf=\"page.icon\" slot=\"start\" [name]=\"page.icon\"></ion-icon>\n <mat-icon *ngIf=\"page.matIcon\" slot=\"start\">{{ page.matIcon }}</mat-icon>\n\n <ion-label color=\"primary\" [innerHTML]=\"page.title\"></ion-label>\n </ion-item>\n </ion-card-title>\n </ion-card-header>\n\n <!-- children pages -->\n @if (page.children | isNotEmptyArray) {\n <ion-card-content class=\"ion-no-padding ion-padding-start\">\n <ion-list class=\"ion-no-padding\">\n @for (childPage of page.children; track childPage.path) {\n <ion-item\n detail=\"true\"\n tappable\n class=\"text-1x\"\n [routerLink]=\"childPage.path\"\n routerDirection=\"root\"\n >\n <!-- page icon-->\n <ion-icon *ngIf=\"childPage.icon\" slot=\"start\" color=\"dark\" [name]=\"childPage.icon\"></ion-icon>\n <mat-icon *ngIf=\"childPage.matIcon\" slot=\"start\" color=\"dark\">\n {{ childPage.matIcon }}\n </mat-icon>\n\n <ion-label color=\"dark\" [innerHTML]=\"childPage.title\"></ion-label>\n </ion-item>\n }\n </ion-list>\n </ion-card-content>\n }\n </ion-card>\n </ion-col>\n }\n </ion-row>\n </ion-grid>\n } @else if (showPartnerBanner || showLegalInformation) {\n <ng-container *ngTemplateOutlet=\"bottomBanner\"></ng-container>\n }\n }\n</ion-content>\n\n<ng-template #bottomBanner>\n <ion-grid class=\"bottom-banner ion-text-center\" [class.floating]=\"!mobile\" @fadeInAnimation>\n <ion-row>\n @if (showPartnerBanner) {\n <ion-col size=\"12\" [sizeLg]=\"partnerBannerSize\" class=\"ion-text-center\">\n @if (showLegalInformation) {\n <ion-list class=\"legal-info\">\n <ion-list-header>{{ 'HOME.PARTNERS' | translate }}</ion-list-header>\n </ion-list>\n }\n <!-- partners -->\n @for (item of $partners | async; track $index) {\n <a href=\"{{ item.siteUrl }}\">\n <img class=\"logo\" src=\"{{ item.logo }}\" alt=\"{{ item.label }}\" [title]=\"item.label\" />\n </a>\n }\n </ion-col>\n }\n @if (showLegalInformation) {\n <ion-col size=\"4\" size-lg=\"3\" [class.left-border]=\"showPartnerBanner\">\n <ion-list class=\"legal-info\">\n <ion-list-header class=\"ion-text-left\">{{ 'HOME.LEGAL_INFORMATION' | translate }}</ion-list-header>\n @for (item of legalInformation; track item.path) {\n <ion-item (click)=\"openHelpModal($event, item)\" lines=\"none\" [button]=\"true\">\n <ion-label>\n <p>\n {{ item.title | translate: item.titleArgs }}\n </p>\n </ion-label>\n </ion-item>\n }\n </ion-list>\n </ion-col>\n @if (showInstallLinks) {\n <ion-col size=\"12\" size-lg=\"3\" offset-lg=\"9\" [class.left-border]=\"showPartnerBanner\">\n <ion-list class=\"legal-info\">\n <ion-list-header>{{ 'HOME.INSTALL_APP' | translate }}</ion-list-header>\n <!-- TODO -->\n </ion-list>\n </ion-col>\n }\n }\n </ion-row>\n </ion-grid>\n</ng-template>\n", styles: [":host{--ion-card-background-color: rgba(var(--ion-background-color-rgb), .7)}h1,h2,h3,h4,h5{white-space:normal}.center,ion-content ion-card.welcome img{text-align:center;display:inline-block}ion-content{--background: transparent;background-size:cover;-webkit-background-size:cover;-moz-background-size:cover;-o-background-size:cover;background-color:var(--ion-background-color);display:inline-block;padding:15px}ion-content .loading-page{display:block;height:100%;width:100%;position:absolute;background-color:transparent;z-index:5;transition:background .5s linear;-webkit-transition:background 1.5s linear}ion-content .loading-page.hidden{background-color:rgba(var(--ion-color-primary),0)}ion-content ion-card{z-index:9}ion-content ion-card ion-card-header{display:block}ion-content ion-card ion-card-header ion-card-subtitle,ion-content ion-card ion-card-header ion-card-title{display:block;width:100%}ion-content ion-card.main{min-width:240px;max-width:400px;margin-left:auto;margin-right:auto}ion-content ion-card.welcome{background-color:var(--ion-card-background-color)}ion-content ion-card.welcome button{margin-top:16px}ion-content ion-card.welcome img{max-width:250px}ion-content .history-container{margin-left:auto;margin-right:auto}ion-content .history-container ion-card{display:inline-block;box-sizing:border-box;z-index:8;min-width:240px;max-width:400px;width:100%;margin-left:auto;margin-right:auto;background-color:var(--ion-card-background-color)}ion-content .history-container ion-card ion-card-header ion-card-subtitle{height:40px}ion-content .history-container ion-card ion-card-header ion-card-subtitle button[float-start]{--mdc-icon-button-state-layer-size: 40px;padding:8px;z-index:99;margin:0}ion-content .history-container ion-card ion-card-header ion-card-subtitle ion-label{line-height:40px}ion-content .history-container ion-card ion-card-header ion-card-subtitle ion-label[float-end]{padding-right:16px;font-weight:400}ion-content .history-container ion-card ion-card-header ion-card-title ion-item{width:100%;--ion-item-background: $transparent;--ion-item-icon-color: var(--ion-color-primary);--ion-item-text-color: var(--ion-color-primary)}ion-content .history-container ion-card ion-card-header ion-card-title ion-item ion-icon[slot=start],ion-content .history-container ion-card ion-card-header ion-card-title ion-item mat-icon[slot=start]{margin-right:unset;margin-inline-end:16px!important;color:var(--ion-item-icon-color)!important;fill:currentColor;stroke:currentColor}ion-content .history-container ion-card ion-card-header ion-card-title ion-item ion-text,ion-content .history-container ion-card ion-card-header ion-card-title ion-item ion-label{color:var(--ion-item-text-color)!important;-webkit-text-size-adjust:100%;-moz-text-size-adjust:100%;-ms-text-size-adjust:100%;text-size-adjust:100%}ion-content .history-container ion-card ion-card-content ion-list{--ion-item-background: var(--ion-color-transparent)}ion-content .history-container ion-card ion-card-content ion-list ion-item{--ion-item-icon-color: var(--ion-color-dark);--ion-item-text-color: var(--ion-color-dark)}ion-content .history-container ion-card ion-card-content ion-list ion-item ion-icon[slot=start],ion-content .history-container ion-card ion-card-content ion-list ion-item mat-icon[slot=start]{color:var(--ion-item-icon-color)!important;fill:currentColor;stroke:currentColor;margin-right:unset;margin-inline-end:16px!important}ion-content .history-container ion-card ion-card-content ion-list ion-item ion-text,ion-content .history-container ion-card ion-card-content ion-list ion-item ion-label{color:var(--ion-item-text-color)!important}ion-content .bottom-banner{background-color:var(--ion-card-background-color);min-width:240px;z-index:0}ion-content .bottom-banner.floating{position:absolute;left:16px;right:16px;bottom:16px}ion-content .bottom-banner img.logo{max-height:50px;margin-left:8px}ion-content ion-text{text-align:center}@media screen and (max-width: 575px){ion-content ion-card{min-width:160px;width:calc(100% - 20px);max-width:100%;margin-left:10px;margin-right:10px}ion-content ion-card h1{margin-top:0;font-size:20px}ion-content ion-card ion-card-content ion-button{margin-top:8px}ion-content .bottom-banner.floating{display:block;position:unset}ion-content .bottom-banner img.logo{max-height:30px}}@media screen and (max-width: 767px) and (min-width: 576px){ion-content{min-height:555px}ion-content .bottom-banner img.logo{max-height:40px}}@media screen and (min-width: 768px){ion-content{min-height:calc(100% - 100px)}}.content-credits{position:absolute;right:0;bottom:0}.content-credits ion-text{padding-inline-start:4px;padding-inline-end:4px;font-size:.8rem;background-color:var(--ion-background-color, white);color:var(--ion-text-color);opacity:.65}@media screen and (min-width: 992px){.left-border{border-left:1px solid var(--ion-color-medium)}}.bottom-banner ion-list-header{min-height:30px}.bottom-banner ion-item{--min-height: 28px}.bottom-banner ion-item ion-label{margin-top:3px!important;margin-bottom:3px!important}\n"] }]
30079
30171
  }], ctorParameters: () => [{ type: AccountService }, { type: i2$1.ModalController }, { type: i1$1.TranslateService }, { type: i2$1.ToastController }, { type: ConfigService }, { type: PlatformService }, { type: i0.ChangeDetectorRef }, { type: NetworkService }, { type: LocalSettingsService }, { type: Environment, decorators: [{
30080
30172
  type: Inject,
30081
30173
  args: [ENVIRONMENT]
@@ -33662,7 +33754,7 @@ class AppRowField {
33662
33754
  this.matTable.removeColumnDef(this.columnDef);
33663
33755
  }
33664
33756
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: AppRowField, deps: [{ token: i0.ChangeDetectorRef }, { token: i1$6.MatTable }], target: i0.ɵɵFactoryTarget.Component });
33665
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: AppRowField, selector: "app-row-field", inputs: { name: "name", definition: "definition", definitionFn: "definitionFn", headerI18n: "headerI18n", sortable: "sortable", resizable: "resizable", required: "required", readonly: "readonly", sticky: "sticky", draggable: "draggable", disabled: "disabled", placeholder: "placeholder", compact: "compact", floatLabel: "floatLabel", appearance: "appearance", tabindex: "tabindex", autofocus: "autofocus", clearable: "clearable", chipColor: "chipColor", classList: ["class", "classList"], debug: "debug" }, viewQueries: [{ propertyName: "columnDef", first: true, predicate: MatColumnDef, descendants: true }], ngImport: i0, template: "<ng-container [matColumnDef]=\"name\" [sticky]=\"sticky\">\n <th mat-header-cell *matHeaderCellDef cdkDrag [cdkDragDisabled]=\"sticky || !draggable\" [resizable]=\"resizable\">\n <!-- if sortable, wrap the header with a mat-sort-header -->\n @if (sortable) {\n <span mat-sort-header>\n <ng-container *ngTemplateOutlet=\"headerTemplate\"></ng-container>\n </span>\n } @else {\n <ng-container *ngTemplateOutlet=\"headerTemplate\"></ng-container>\n }\n <ng-template #headerTemplate>\n <ion-label appAutoTitle>{{ headerI18n | translate }}</ion-label>\n @if (required) {\n <ion-label color=\"danger\" [innerHTML]=\"'&nbsp;*'\"></ion-label>\n }\n </ng-template>\n </th>\n <td mat-cell *matCellDef=\"let row\">\n @if (!readonly && row.editing) {\n <app-form-field\n [definition]=\"definition || definitionFn(row)\"\n [required]=\"required\"\n [readonly]=\"readonly\"\n [disabled]=\"disabled\"\n [formControl]=\"row.validator | formGetControl: name\"\n [placeholder]=\"placeholder\"\n [compact]=\"compact\"\n [floatLabel]=\"floatLabel\"\n [appearance]=\"appearance\"\n [tabindex]=\"tabindex\"\n [autofocus]=\"autofocus\"\n [clearable]=\"clearable\"\n [chipColor]=\"chipColor\"\n [class]=\"classList\"\n [debug]=\"debug\"\n ></app-form-field>\n } @else {\n <ion-label appAutoTitle>\n {{ row.currentData | propertyGet: name | valueFormat: definition || definitionFn(row) }}\n </ion-label>\n }\n </td>\n</ng-container>\n", styles: [""], dependencies: [{ kind: "directive", type: i3.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: i2$1.IonLabel, selector: "ion-label", inputs: ["color", "mode", "position"] }, { kind: "directive", type: i1$3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$3.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1$3.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i6$5.CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "directive", type: i1$6.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i1$6.MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: i1$6.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i1$6.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i1$6.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "component", type: i8$2.MatSortHeader, selector: "[mat-sort-header]", inputs: ["mat-sort-header", "arrowPosition", "start", "disabled", "sortActionDescription", "disableClear"], exportAs: ["matSortHeader"] }, { kind: "directive", type: AutofocusDirective, selector: "[autofocus], input[appAutofocus]", inputs: ["appAutofocus", "autofocusDelay"] }, { kind: "directive", type: AutoTitleDirective, selector: "[appAutoTitle]" }, { kind: "component", type: AppFormField, selector: "app-form-field", inputs: ["definition", "readonly", "disabled", "formControl", "formControlName", "placeholder", "compact", "required", "hideRequiredMarker", "floatLabel", "label", "appearance", "subscriptSizing", "tabindex", "autofocus", "clearable", "chipColor", "class", "debug"], outputs: ["keyup.enter"] }, { kind: "component", type: ResizableComponent, selector: "th[resizable]", inputs: ["resizable"], outputs: ["sizeChanged"] }, { kind: "directive", type: ResizableDirective, selector: "[resizable]", outputs: ["resizable", "fit"] }, { kind: "pipe", type: i1$1.TranslatePipe, name: "translate" }, { kind: "pipe", type: PropertyGetPipe, name: "propertyGet" }, { kind: "pipe", type: ValueFormatPipe, name: "valueFormat" }, { kind: "pipe", type: FormGetControlPipe, name: "formGetControl" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
33757
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: AppRowField, selector: "app-row-field", inputs: { name: "name", definition: "definition", definitionFn: "definitionFn", headerI18n: "headerI18n", sortable: "sortable", resizable: "resizable", required: "required", readonly: "readonly", sticky: "sticky", draggable: "draggable", disabled: "disabled", placeholder: "placeholder", compact: "compact", floatLabel: "floatLabel", appearance: "appearance", tabindex: "tabindex", autofocus: "autofocus", clearable: "clearable", chipColor: "chipColor", classList: ["class", "classList"], debug: "debug" }, viewQueries: [{ propertyName: "columnDef", first: true, predicate: MatColumnDef, descendants: true }], ngImport: i0, template: "<ng-container [matColumnDef]=\"name\" [sticky]=\"sticky\">\n <th mat-header-cell *matHeaderCellDef cdkDrag [cdkDragDisabled]=\"sticky || !draggable\" [resizable]=\"resizable\">\n <!-- if sortable, wrap the header with a mat-sort-header -->\n @if (sortable) {\n <span mat-sort-header>\n <ng-container *ngTemplateOutlet=\"headerTemplate\"></ng-container>\n </span>\n } @else {\n <ng-container *ngTemplateOutlet=\"headerTemplate\"></ng-container>\n }\n <ng-template #headerTemplate>\n <ion-label appAutoTitle>{{ headerI18n | translate }}</ion-label>\n @if (required) {\n <ion-label color=\"danger\" [innerHTML]=\"'&nbsp;*'\"></ion-label>\n }\n </ng-template>\n </th>\n <td mat-cell *matCellDef=\"let row\">\n @if (!readonly && row.editing) {\n <app-form-field\n [definition]=\"definition || definitionFn(row)\"\n [required]=\"required\"\n [readonly]=\"readonly\"\n [disabled]=\"disabled\"\n [formControl]=\"row.validator | formGetControl: name\"\n [placeholder]=\"placeholder\"\n [compact]=\"compact\"\n [floatLabel]=\"floatLabel\"\n [appearance]=\"appearance\"\n [tabindex]=\"tabindex\"\n [autofocus]=\"autofocus\"\n [clearable]=\"clearable\"\n [chipColor]=\"chipColor\"\n [class]=\"classList\"\n [debug]=\"debug\"\n ></app-form-field>\n } @else {\n <ion-label appAutoTitle>\n {{ row.currentData | propertyGet: name | valueFormat: definition || definitionFn(row) }}\n </ion-label>\n }\n </td>\n</ng-container>\n", styles: [""], dependencies: [{ kind: "directive", type: i3.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: i2$1.IonLabel, selector: "ion-label", inputs: ["color", "mode", "position"] }, { kind: "directive", type: i1$3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$3.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1$3.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i6$4.CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "directive", type: i1$6.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i1$6.MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: i1$6.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i1$6.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i1$6.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "component", type: i8$2.MatSortHeader, selector: "[mat-sort-header]", inputs: ["mat-sort-header", "arrowPosition", "start", "disabled", "sortActionDescription", "disableClear"], exportAs: ["matSortHeader"] }, { kind: "directive", type: AutofocusDirective, selector: "[autofocus], input[appAutofocus]", inputs: ["appAutofocus", "autofocusDelay"] }, { kind: "directive", type: AutoTitleDirective, selector: "[appAutoTitle]" }, { kind: "component", type: AppFormField, selector: "app-form-field", inputs: ["definition", "readonly", "disabled", "formControl", "formControlName", "placeholder", "compact", "required", "hideRequiredMarker", "floatLabel", "label", "appearance", "subscriptSizing", "tabindex", "autofocus", "clearable", "chipColor", "class", "debug"], outputs: ["keyup.enter"] }, { kind: "component", type: ResizableComponent, selector: "th[resizable]", inputs: ["resizable"], outputs: ["sizeChanged"] }, { kind: "directive", type: ResizableDirective, selector: "[resizable]", outputs: ["resizable", "fit"] }, { kind: "pipe", type: i1$1.TranslatePipe, name: "translate" }, { kind: "pipe", type: PropertyGetPipe, name: "propertyGet" }, { kind: "pipe", type: ValueFormatPipe, name: "valueFormat" }, { kind: "pipe", type: FormGetControlPipe, name: "formGetControl" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
33666
33758
  }
33667
33759
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: AppRowField, decorators: [{
33668
33760
  type: Component,
@@ -41288,7 +41380,7 @@ class JobProgressionIcon extends RxState {
41288
41380
  this._subscriptions.unsubscribe();
41289
41381
  }
41290
41382
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: JobProgressionIcon, deps: [{ token: APP_JOB_PROGRESSION_SERVICE, optional: true }, { token: i2$1.PopoverController }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
41291
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: JobProgressionIcon, selector: "app-job-progression-icon", inputs: { debug: "debug", titleI18n: "titleI18n", options: "options", autoHide: "autoHide", headerActions: "headerActions" }, outputs: { jobFinished: "jobFinished" }, usesInheritance: true, ngImport: i0, template: "<button\n #button\n mat-icon-button\n [title]=\"titleI18n | translate\"\n [disabled]=\"disabled\"\n *rxIf=\"visible$\"\n (click)=\"showList($event)\"\n>\n <mat-icon\n *rxLet=\"jobCount$; let jobCount\"\n [matBadge]=\"jobCount\"\n [matBadgeHidden]=\"!jobCount\"\n matBadgeColor=\"accent\"\n matBadgeSize=\"small\"\n matBadgePosition=\"above after\"\n aria-hidden=\"false\"\n >\n {{ disabled || jobCount ? 'schedule' : 'task_alt' }}\n </mat-icon>\n <mat-spinner\n #spinner\n *rxIf=\"jobCount$\"\n class=\"floating-spinner\"\n [color]=\"color\"\n [mode]=\"mode$ | push\"\n [value]=\"value$ | push\"\n diameter=\"30\"\n strokeWidth=\"3\"\n ></mat-spinner>\n</button>\n", styles: [".floating-spinner{position:absolute;height:24px!important;width:24px!important;top:12px;left:12px}\n"], dependencies: [{ kind: "directive", type: i9$2.RxIf, selector: "[rxIf]", inputs: ["rxIf", "rxIfStrategy", "rxIfElse", "rxIfThen", "rxIfSuspense", "rxIfComplete", "rxIfError", "rxIfContextTrigger", "rxIfNextTrigger", "rxIfSuspenseTrigger", "rxIfErrorTrigger", "rxIfCompleteTrigger", "rxIfParent", "rxIfPatchZone", "rxIfRenderCallback"] }, { kind: "directive", type: i10$2.RxLet, selector: "[rxLet]", inputs: ["rxLet", "rxLetStrategy", "rxLetComplete", "rxLetError", "rxLetSuspense", "rxLetContextTrigger", "rxLetCompleteTrigger", "rxLetErrorTrigger", "rxLetSuspenseTrigger", "rxLetNextTrigger", "rxLetRenderCallback", "rxLetParent", "rxLetPatchZone"], outputs: ["rendered"] }, { kind: "component", type: i6$2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i9.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "component", type: i6$6.MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "mode", "value", "diameter", "strokeWidth"], exportAs: ["matProgressSpinner"] }, { kind: "directive", type: i8.MatBadge, selector: "[matBadge]", inputs: ["matBadgeColor", "matBadgeOverlap", "matBadgeDisabled", "matBadgePosition", "matBadge", "matBadgeDescription", "matBadgeSize", "matBadgeHidden"] }, { kind: "pipe", type: i1$1.TranslatePipe, name: "translate" }, { kind: "pipe", type: i5$1.RxPush, name: "push" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
41383
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: JobProgressionIcon, selector: "app-job-progression-icon", inputs: { debug: "debug", titleI18n: "titleI18n", options: "options", autoHide: "autoHide", headerActions: "headerActions" }, outputs: { jobFinished: "jobFinished" }, usesInheritance: true, ngImport: i0, template: "<button\n #button\n mat-icon-button\n [title]=\"titleI18n | translate\"\n [disabled]=\"disabled\"\n *rxIf=\"visible$\"\n (click)=\"showList($event)\"\n>\n <mat-icon\n *rxLet=\"jobCount$; let jobCount\"\n [matBadge]=\"jobCount\"\n [matBadgeHidden]=\"!jobCount\"\n matBadgeColor=\"accent\"\n matBadgeSize=\"small\"\n matBadgePosition=\"above after\"\n aria-hidden=\"false\"\n >\n {{ disabled || jobCount ? 'schedule' : 'task_alt' }}\n </mat-icon>\n <mat-spinner\n #spinner\n *rxIf=\"jobCount$\"\n class=\"floating-spinner\"\n [color]=\"color\"\n [mode]=\"mode$ | push\"\n [value]=\"value$ | push\"\n diameter=\"30\"\n strokeWidth=\"3\"\n ></mat-spinner>\n</button>\n", styles: [".floating-spinner{position:absolute;height:24px!important;width:24px!important;top:12px;left:12px}\n"], dependencies: [{ kind: "directive", type: i9$2.RxIf, selector: "[rxIf]", inputs: ["rxIf", "rxIfStrategy", "rxIfElse", "rxIfThen", "rxIfSuspense", "rxIfComplete", "rxIfError", "rxIfContextTrigger", "rxIfNextTrigger", "rxIfSuspenseTrigger", "rxIfErrorTrigger", "rxIfCompleteTrigger", "rxIfParent", "rxIfPatchZone", "rxIfRenderCallback"] }, { kind: "directive", type: i10$2.RxLet, selector: "[rxLet]", inputs: ["rxLet", "rxLetStrategy", "rxLetComplete", "rxLetError", "rxLetSuspense", "rxLetContextTrigger", "rxLetCompleteTrigger", "rxLetErrorTrigger", "rxLetSuspenseTrigger", "rxLetNextTrigger", "rxLetRenderCallback", "rxLetParent", "rxLetPatchZone"], outputs: ["rendered"] }, { kind: "component", type: i6$2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i9.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "component", type: i6$5.MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "mode", "value", "diameter", "strokeWidth"], exportAs: ["matProgressSpinner"] }, { kind: "directive", type: i8.MatBadge, selector: "[matBadge]", inputs: ["matBadgeColor", "matBadgeOverlap", "matBadgeDisabled", "matBadgePosition", "matBadge", "matBadgeDescription", "matBadgeSize", "matBadgeHidden"] }, { kind: "pipe", type: i1$1.TranslatePipe, name: "translate" }, { kind: "pipe", type: i5$1.RxPush, name: "push" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
41292
41384
  }
41293
41385
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: JobProgressionIcon, decorators: [{
41294
41386
  type: Component,
@@ -44710,7 +44802,7 @@ class Table2TestPage extends AppTable {
44710
44802
  provide: AppTable,
44711
44803
  useExisting: forwardRef(() => Table2TestPage),
44712
44804
  },
44713
- ], viewQueries: [{ propertyName: "filterExpansionPanel", first: true, predicate: MatExpansionPanel, descendants: true, static: true }, { propertyName: "infiniteScroll", first: true, predicate: IonInfiniteScroll, descendants: true }], usesInheritance: true, ngImport: i0, template: "<app-toolbar\n color=\"primary\"\n [canGoBack]=\"true\"\n [hasValidate]=\"(loadingSubject | async) !== true && (dirtySubject | async) === true\"\n (onValidate)=\"save()\"\n [backHref]=\"'/testing'\"\n>\n <ion-title>Table 2 (click to select)</ion-title>\n\n <ion-buttons slot=\"end\">\n @if (selection | isEmptySelection) {\n <input matInput type=\"number\" step=\"1\" style=\"color: black; width: 50px\" [(ngModel)]=\"rowHeight\" />\n\n <!-- Add -->\n <button mat-icon-button *ngIf=\"canEdit && !mobile\" [title]=\"'COMMON.BTN_ADD' | translate\" (click)=\"addRow()\">\n <mat-icon>add</mat-icon>\n </button>\n\n <!-- reset filter -->\n <button mat-icon-button (click)=\"resetFilter()\" *ngIf=\"filterCriteriaCount\">\n <mat-icon color=\"accent\">filter_list_alt</mat-icon>\n <mat-icon class=\"icon-secondary\" style=\"left: 16px; top: 5px; font-weight: bold\">close</mat-icon>\n </button>\n\n <!-- show filter -->\n <button mat-icon-button (click)=\"filterExpansionPanel.toggle()\">\n <mat-icon\n *ngIf=\"filterCriteriaCount; else emptyFilter\"\n [matBadge]=\"filterCriteriaCount\"\n matBadgeColor=\"accent\"\n matBadgeSize=\"small\"\n matBadgePosition=\"above after\"\n aria-hidden=\"false\"\n >\n filter_list_alt\n </mat-icon>\n <ng-template #emptyFilter>\n <mat-icon>filter_list_alt</mat-icon>\n </ng-template>\n </button>\n\n <!-- save -->\n <button mat-icon-button *ngIf=\"mobile\" [disabled]=\"(dirtySubject | async) !== true\" (click)=\"save()\">\n <mat-icon>save</mat-icon>\n </button>\n } @else {\n <!-- if row selection -->\n <!-- delete -->\n <button\n mat-icon-button\n *ngIf=\"canEdit\"\n [title]=\"'COMMON.BTN_DELETE' | translate\"\n (click)=\"deleteSelection($event)\"\n >\n <mat-icon>delete</mat-icon>\n </button>\n\n <!-- duplicate -->\n <button\n mat-icon-button\n *ngIf=\"canEdit && selection.selected | isArrayLength: { equals: 1 }\"\n [title]=\"'COMMON.BTN_DUPLICATE' | translate\"\n (click)=\"duplicateRow($event, selection.selected[0])\"\n >\n <mat-icon>file_copy</mat-icon>\n </button>\n }\n </ion-buttons>\n</app-toolbar>\n<ion-content class=\"ion-no-padding\">\n <ion-refresher slot=\"fixed\" *ngIf=\"mobile\" (ionRefresh)=\"doRefresh($event)\">\n <ion-refresher-content></ion-refresher-content>\n </ion-refresher>\n\n <!-- error -->\n <ion-item *ngIf=\"mobile && error\" lines=\"none\" @slideUpDownAnimation>\n <ion-icon color=\"danger\" slot=\"start\" name=\"alert-circle\"></ion-icon>\n <ion-label color=\"danger\" class=\"error\" [innerHTML]=\"error | translate\"></ion-label>\n </ion-item>\n\n <!-- search -->\n <mat-expansion-panel\n #filterExpansionPanel\n class=\"filter-panel\"\n [class.filter-panel-floating]=\"filterPanelFloating\"\n [class.filter-panel-pinned]=\"!filterPanelFloating\"\n >\n <form class=\"form-container ion-padding-top\" [formGroup]=\"filterForm\" (ngSubmit)=\"applyFilterAndClosePanel($event)\">\n <ion-grid>\n <ion-row>\n <ion-col>\n <!-- search text -->\n <mat-form-field>\n <mat-label>{{ 'TABLE.TESTING.SEARCH_TEXT' | translate }}</mat-label>\n <ion-icon matPrefix name=\"search\"></ion-icon>\n <input matInput formControlName=\"searchText\" autocomplete=\"off\" />\n <button\n mat-icon-button\n matSuffix\n tabindex=\"-1\"\n type=\"button\"\n (click)=\"clearControlValue($event, filterForm.controls.searchText)\"\n [hidden]=\"filterForm.controls.searchText.disabled || !filterForm.controls.searchText.value\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n </ion-col>\n </ion-row>\n </ion-grid>\n </form>\n\n <mat-action-row>\n <!-- Counter -->\n <ion-label\n [hidden]=\"(loadingSubject | async) || filterForm.dirty\"\n [color]=\"empty && 'danger'\"\n class=\"ion-padding\"\n >\n {{\n (totalRowCount ? 'COMMON.RESULT_COUNT' : 'COMMON.NO_RESULT')\n | translate\n : {\n count: (totalRowCount | numberFormat)\n }\n }}\n </ion-label>\n\n <div class=\"toolbar-spacer\"></div>\n\n <button\n mat-icon-button\n color=\"accent\"\n *ngIf=\"filterPanelFloating\"\n (click)=\"toggleFilterPanelFloating()\"\n class=\"hidden-xs hidden-sm hidden-md\"\n [title]=\"(filterPanelFloating ? 'COMMON.BTN_EXPAND' : 'COMMON.BTN_HIDE') | translate\"\n >\n <mat-icon>\n <span style=\"transform: rotate(90deg)\">{{ filterPanelFloating ? '&#xbb;' : '&#xab;' }}</span>\n </mat-icon>\n </button>\n\n <!-- Close panel -->\n <ion-button mat-button fill=\"clear\" color=\"dark\" (click)=\"closeFilterPanel()\" [disabled]=\"loadingSubject | async\">\n <ion-text translate>COMMON.BTN_CLOSE</ion-text>\n </ion-button>\n\n <!-- Search button -->\n <ion-button\n mat-button\n [color]=\"filterForm.dirty ? 'tertiary' : 'dark'\"\n [fill]=\"filterForm.dirty ? 'solid' : 'clear'\"\n (click)=\"applyFilterAndClosePanel($event)\"\n >\n <ion-text translate>COMMON.BTN_APPLY</ion-text>\n </ion-button>\n </mat-action-row>\n </mat-expansion-panel>\n\n <!-- table -->\n <div [class.table-container]=\"!enableInfiniteScroll\">\n <table\n #table\n mat-table\n matSort\n matSortDisableClear\n [dataSource]=\"dataSource\"\n [matSortActive]=\"defaultSortBy\"\n [matSortDirection]=\"defaultSortDirection\"\n [trackBy]=\"trackByFn\"\n [style.--mat-row-height]=\"rowHeight + 'px'\"\n >\n <ng-container matColumnDef=\"select\" [sticky]=\"checkBoxSelection\" [class.mat-column-sticky]=\"checkBoxSelection\">\n <th mat-header-cell *matHeaderCellDef [class.cdk-visually-hidden]=\"!checkBoxSelection\">\n @if (selection | isMultipleSelection) {\n <mat-checkbox\n [checked]=\"this | isAllSelected\"\n [indeterminate]=\"this | isNotAllSelected\"\n (change)=\"$event ? masterToggle() : null\"\n ></mat-checkbox>\n }\n </th>\n <td mat-cell *matCellDef=\"let row\" [class.cdk-visually-hidden]=\"!checkBoxSelection\">\n <mat-checkbox [checked]=\"selection | isSelected: row\" (click)=\"toggleSelectRow($event, row)\"></mat-checkbox>\n </td>\n </ng-container>\n\n <!-- Id column -->\n <ng-container matColumnDef=\"id\" [sticky]=\"sticky\">\n <th mat-header-cell *matHeaderCellDef>\n <span mat-sort-header>\n <ion-label title=\"Id\">#</ion-label>\n <ion-label color=\"danger\" [innerHTML]=\"'&nbsp;*'\"></ion-label>\n </span>\n </th>\n <td mat-cell *matCellDef=\"let row\">\n <mat-form-field *ngIf=\"!readOnly && row.id === -1 && row.editing; else readOnlyId\">\n <input\n matInput\n autocomplete=\"off\"\n required\n [formControl]=\"row.validator | formGetControl: 'id'\"\n placeholder=\"Id\"\n [appAutofocus]=\"true\"\n />\n <mat-error *ngIf=\"(row.validator | formGetControl: 'id').hasError('required')\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n <mat-error *ngIf=\"(row.validator | formGetControl: 'id').hasError('alreadyExists')\" translate>\n ERROR.FIELD_NOT_UNIQUE_ID\n </mat-error>\n </mat-form-field>\n\n <ng-template #readOnlyId>\n <ion-label appAutoTitle>\n {{ (row.validator | formGetValue: 'id') || (row.currentData | propertyGet: 'id') }}\n </ion-label>\n </ng-template>\n </td>\n </ng-container>\n\n <!-- Name column -->\n <ng-container matColumnDef=\"name\">\n <th mat-header-cell *matHeaderCellDef [resizable]=\"resizable\">\n <!-- if sortable, wrap the header with a mat-sort-header -->\n <span mat-sort-header>\n <ion-label [title]=\"'TABLE.TESTING.NAME' | translate\">{{ 'TABLE.TESTING.NAME' | translate }}</ion-label>\n <ion-label color=\"danger\" [innerHTML]=\"'&nbsp;*'\"></ion-label>\n </span>\n </th>\n <td mat-cell *matCellDef=\"let row\" (click)=\"focusColumn = 'name'\">\n <mat-form-field *ngIf=\"!readOnly && row.editing; else readOnlyTemplate\">\n <input\n matInput\n autocomplete=\"off\"\n [required]=\"true\"\n [formControl]=\"row.validator | formGetControl: 'name'\"\n [placeholder]=\"'TABLE.TESTING.NAME' | translate\"\n [appAutofocus]=\"row.id === -1 || focusColumn === 'name'\"\n />\n <ng-content select=\"[suffix]\"></ng-content>\n <mat-error *ngIf=\"(row.validator | formGetControl: 'name').hasError('required')\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n <mat-error *ngIf=\"(row.validator | formGetControl: 'name').hasError('maxlength')\" translate>\n ERROR.FIELD_MAX_LENGTH_COMPACT\n </mat-error>\n <mat-error *ngIf=\"(row.validator | formGetControl: 'name').hasError('minlength')\" translate>\n ERROR.FIELD_MIN_LENGTH_COMPACT\n </mat-error>\n </mat-form-field>\n <ng-template #readOnlyTemplate>\n <ion-label appAutoTitle>\n {{ (row.validator | formGetValue: 'name') || (row.currentData | propertyGet: 'name') }}\n </ion-label>\n </ng-template>\n </td>\n </ng-container>\n\n <!-- Level column -->\n <ng-container matColumnDef=\"levelId\">\n <th mat-header-cell *matHeaderCellDef [resizable]=\"resizable\">\n <span mat-sort-header>\n <ion-label>{{ 'TABLE.TESTING.LEVEL_ID' | translate }}</ion-label>\n <ion-label color=\"danger\" [innerHTML]=\"'&nbsp;*'\"></ion-label>\n </span>\n </th>\n <td mat-cell *matCellDef=\"let row\">\n <mat-autocomplete-field\n *ngIf=\"!readOnly && row.editing; else readOnlyTemplate\"\n panelWidth=\"750px\"\n [formControl]=\"row.validator | formGetControl: 'levelId'\"\n [placeholder]=\"'TABLE.TESTING.LEVEL_ID' | translate\"\n floatLabel=\"never\"\n [required]=\"true\"\n [config]=\"autocompleteFields.level\"\n [highlightAccent]=\"true\"\n >\n <mat-error matError *ngIf=\"(row.validator | formGetControl: 'levelId').hasError('invalid')\" translate>\n ERROR.FIELD_INVALID\n </mat-error>\n </mat-autocomplete-field>\n <ng-template #readOnlyTemplate>\n <ion-label appAutoTitle>\n {{\n autocompleteFields.level?.displayWith(\n (row.validator | formGetValue: 'levelId') || (row.currentData | propertyGet: 'levelId')\n ) ||\n ((row.validator | formGetValue: 'levelId') || (row.currentData | propertyGet: 'levelId')\n | referentialToString)\n }}\n </ion-label>\n </ng-template>\n </td>\n </ng-container>\n\n <ng-container matColumnDef=\"boolean\">\n <th mat-header-cell *matHeaderCellDef cdkDrag [resizable]=\"resizable\">\n <!-- if sortable, wrap the header with a mat-sort-header -->\n <span mat-sort-header>\n <ion-label>Boolean</ion-label>\n </span>\n </th>\n <td mat-cell *matCellDef=\"let row\">\n <mat-boolean-field\n *ngIf=\"!readOnly && row.editing; else readOnlyTemplate\"\n floatLabel=\"never\"\n [style]=\"'checkbox'\"\n [formControl]=\"\n (row.validator | formGetControl: 'boolean') || formBuilder.control(row.currentData['boolean'])\n \"\n [compact]=\"true\"\n ></mat-boolean-field>\n <ng-template #readOnlyTemplate>\n <ion-label appAutoTitle>\n {{\n (row.validator | formGetValue: 'boolean') || (row.currentData | propertyGet: 'boolean')\n ? ('COMMON.YES' | translate)\n : ('COMMON.NO' | translate)\n }}\n </ion-label>\n </ng-template>\n </td>\n </ng-container>\n\n <ng-container matColumnDef=\"boolean2\">\n <th mat-header-cell *matHeaderCellDef cdkDrag [resizable]=\"resizable\">\n <!-- if sortable, wrap the header with a mat-sort-header -->\n <span mat-sort-header>\n <ion-label>Boolean 2</ion-label>\n </span>\n </th>\n <td mat-cell *matCellDef=\"let row\">\n <mat-boolean-field\n *ngIf=\"!readOnly && row.editing; else readOnlyTemplate\"\n [floatLabel]=\"'never'\"\n [style]=\"'radio'\"\n [showRadio]=\"true\"\n [formControl]=\"\n (row.validator | formGetControl: 'boolean2') || formBuilder.control(row.currentData['boolean2'])\n \"\n ></mat-boolean-field>\n <ng-template #readOnlyTemplate>\n <ion-label appAutoTitle>\n {{\n (row.validator | formGetValue: 'boolean2') || (row.currentData | propertyGet: 'boolean2')\n ? ('COMMON.YES' | translate)\n : ('COMMON.NO' | translate)\n }}\n </ion-label>\n </ng-template>\n </td>\n </ng-container>\n\n <ng-container matColumnDef=\"boolean3\">\n <th mat-header-cell *matHeaderCellDef cdkDrag [resizable]=\"resizable\">\n <!-- if sortable, wrap the header with a mat-sort-header -->\n <span mat-sort-header>\n <ion-label>Boolean 3</ion-label>\n </span>\n </th>\n <td mat-cell *matCellDef=\"let row\">\n <mat-boolean-field\n *ngIf=\"!readOnly && row.editing; else readOnlyTemplate\"\n floatLabel=\"never\"\n [style]=\"'button'\"\n [formControl]=\"\n (row.validator | formGetControl: 'boolean2') || formBuilder.control(row.currentData['boolean2'])\n \"\n ></mat-boolean-field>\n <ng-template #readOnlyTemplate>\n <ion-label appAutoTitle>\n {{\n (row.validator | formGetValue: 'boolean2') || (row.currentData | propertyGet: 'boolean2')\n ? ('COMMON.YES' | translate)\n : ('COMMON.NO' | translate)\n }}\n </ion-label>\n </ng-template>\n </td>\n </ng-container>\n\n <!-- Actions buttons column -->\n <app-actions-column\n [stickyEnd]=\"stickyEnd\"\n [canCancel]=\"false\"\n [style]=\"'table'\"\n (optionsClick)=\"openSelectColumnsModal($event)\"\n (cancelOrDeleteClick)=\"cancelOrDelete($event.event, $event.row)\"\n (confirmAndAddClick)=\"confirmAndAdd($event.event, $event.row)\"\n (backward)=\"confirmAndBackward($event.event, $event.row)\"\n (forward)=\"confirmAndForward($event.event, $event.row)\"\n [cellTemplate]=\"cellInjection\"\n >\n <!-- cell injection-->\n <ng-template #cellInjection let-row>\n <span *ngIf=\"row.editing && !row.validator.dirty\">-</span>\n </ng-template>\n </app-actions-column>\n\n <tr mat-header-row *matHeaderRowDef=\"displayedColumns; sticky: true\"></tr>\n <tr\n mat-row\n *matRowDef=\"let row; columns: displayedColumns\"\n [class.mat-row-selected]=\"row.editing\"\n [class.mat-row-error]=\"row.invalid\"\n [class.mat-row-disabled]=\"!row.editing\"\n [class.mat-row-dirty]=\"row.dirty\"\n (click)=\"clickRow($event, row)\"\n (keydown.escape)=\"escapeEditingRow($event)\"\n [cdkTrapFocus]=\"row.invalid\"\n ></tr>\n </table>\n\n <ng-container *ngIf=\"loadingSubject | async; else noResult\">\n <ion-item>\n <ion-skeleton-text animated></ion-skeleton-text>\n </ion-item>\n </ng-container>\n\n <ng-template #noResult>\n <ion-item *ngIf=\"totalRowCount === 0\">\n <ion-text color=\"danger\" class=\"text-italic\" translate>COMMON.NO_RESULT</ion-text>\n </ion-item>\n </ng-template>\n\n <ion-infinite-scroll\n *ngIf=\"enableInfiniteScroll\"\n [threshold]=\"mobile ? '10%' : '2%'\"\n position=\"bottom\"\n (ionInfinite)=\"fetchMore($event)\"\n >\n <ion-infinite-scroll-content\n loadingSpinner=\"circles\"\n [loadingText]=\"'COMMON.LOADING_DOTS' | translate\"\n ></ion-infinite-scroll-content>\n </ion-infinite-scroll>\n </div>\n</ion-content>\n\n<ion-footer>\n <!-- Paginator -->\n <mat-paginator\n *ngIf=\"!enableInfiniteScroll\"\n [length]=\"totalRowCount\"\n [pageSize]=\"defaultPageSize\"\n [pageSizeOptions]=\"defaultPageSizeOptions\"\n showFirstLastButtons\n ></mat-paginator>\n\n <app-form-buttons-bar\n *ngIf=\"canEdit && !mobile\"\n (onCancel)=\"load()\"\n (onSave)=\"save()\"\n [disabled]=\"(loadingSubject | async) || !dirty\"\n >\n <!-- error -->\n <ion-item *ngIf=\"error$ | async\" lines=\"none\">\n <ion-icon color=\"danger\" slot=\"start\" name=\"alert-circle\"></ion-icon>\n <ion-label color=\"danger\" [innerHTML]=\"error | translate\"></ion-label>\n </ion-item>\n </app-form-buttons-bar>\n</ion-footer>\n\n<ion-fab slot=\"fixed\" vertical=\"bottom\" horizontal=\"end\" *ngIf=\"canEdit && mobile\">\n <ion-fab-button color=\"tertiary\" (click)=\"addRow($event)\">\n <ion-icon name=\"add\"></ion-icon>\n </ion-fab-button>\n</ion-fab>\n", styles: [".table-container .mat-mdc-table .mat-column-select{min-width:30px}.table-container .mat-mdc-table .mat-column-id{min-width:30px;max-width:30px}.table-container .mat-mdc-table .mat-column-label,.table-container .mat-mdc-table .mat-column-name,.table-container .mat-mdc-table .mat-column-levelId,.table-container .mat-mdc-table .mat-column-statusId{min-width:150px}.table-container .mat-mdc-table .mat-column-comments{min-width:100px;max-width:100px}.table-container .mat-mdc-table .mat-column-updateDate{min-width:110px;max-width:110px}\n"], dependencies: [{ kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i2$1.IonButton, selector: "ion-button", inputs: ["buttonType", "color", "disabled", "download", "expand", "fill", "form", "href", "mode", "rel", "routerAnimation", "routerDirection", "shape", "size", "strong", "target", "type"] }, { kind: "component", type: i2$1.IonButtons, selector: "ion-buttons", inputs: ["collapse"] }, { kind: "component", type: i2$1.IonCol, selector: "ion-col", inputs: ["offset", "offsetLg", "offsetMd", "offsetSm", "offsetXl", "offsetXs", "pull", "pullLg", "pullMd", "pullSm", "pullXl", "pullXs", "push", "pushLg", "pushMd", "pushSm", "pushXl", "pushXs", "size", "sizeLg", "sizeMd", "sizeSm", "sizeXl", "sizeXs"] }, { kind: "component", type: i2$1.IonContent, selector: "ion-content", inputs: ["color", "forceOverscroll", "fullscreen", "scrollEvents", "scrollX", "scrollY"] }, { kind: "component", type: i2$1.IonFab, selector: "ion-fab", inputs: ["activated", "edge", "horizontal", "vertical"] }, { kind: "component", type: i2$1.IonFabButton, selector: "ion-fab-button", inputs: ["activated", "closeIcon", "color", "disabled", "download", "href", "mode", "rel", "routerAnimation", "routerDirection", "show", "size", "target", "translucent", "type"] }, { kind: "component", type: i2$1.IonFooter, selector: "ion-footer", inputs: ["collapse", "mode", "translucent"] }, { kind: "component", type: i2$1.IonGrid, selector: "ion-grid", inputs: ["fixed"] }, { kind: "component", type: i2$1.IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: i2$1.IonInfiniteScroll, selector: "ion-infinite-scroll", inputs: ["disabled", "position", "threshold"] }, { kind: "component", type: i2$1.IonInfiniteScrollContent, selector: "ion-infinite-scroll-content", inputs: ["loadingSpinner", "loadingText"] }, { kind: "component", type: i2$1.IonItem, selector: "ion-item", inputs: ["button", "color", "counter", "counterFormatter", "detail", "detailIcon", "disabled", "download", "fill", "href", "lines", "mode", "rel", "routerAnimation", "routerDirection", "shape", "target", "type"] }, { kind: "component", type: i2$1.IonLabel, selector: "ion-label", inputs: ["color", "mode", "position"] }, { kind: "component", type: i2$1.IonRefresher, selector: "ion-refresher", inputs: ["closeDuration", "disabled", "mode", "pullFactor", "pullMax", "pullMin", "snapbackDuration"] }, { kind: "component", type: i2$1.IonRefresherContent, selector: "ion-refresher-content", inputs: ["pullingIcon", "pullingText", "refreshingSpinner", "refreshingText"] }, { kind: "component", type: i2$1.IonRow, selector: "ion-row" }, { kind: "component", type: i2$1.IonSkeletonText, selector: "ion-skeleton-text", inputs: ["animated"] }, { kind: "component", type: i2$1.IonText, selector: "ion-text", inputs: ["color", "mode"] }, { kind: "component", type: i2$1.IonTitle, selector: "ion-title", inputs: ["color", "size"] }, { kind: "directive", type: i1$1.TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }, { kind: "directive", type: i1$3.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$3.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: i1$3.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1$3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$3.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$3.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1$3.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$3.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$3.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i6$5.CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "component", type: i1$6.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i1$6.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i1$6.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i1$6.MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: i1$6.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i1$6.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i1$6.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i1$6.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "component", type: i1$6.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i1$6.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "directive", type: i8$2.MatSort, selector: "[matSort]", inputs: ["matSortActive", "matSortStart", "matSortDirection", "matSortDisableClear", "matSortDisabled"], outputs: ["matSortChange"], exportAs: ["matSort"] }, { kind: "component", type: i8$2.MatSortHeader, selector: "[mat-sort-header]", inputs: ["mat-sort-header", "arrowPosition", "start", "disabled", "sortActionDescription", "disableClear"], exportAs: ["matSortHeader"] }, { kind: "component", type: i9$3.MatPaginator, selector: "mat-paginator", inputs: ["color", "pageIndex", "length", "pageSize", "pageSizeOptions", "hidePageSize", "showFirstLastButtons", "selectConfig", "disabled"], outputs: ["page"], exportAs: ["matPaginator"] }, { kind: "component", type: i6.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i6.MatLabel, selector: "mat-label" }, { kind: "directive", type: i6.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "directive", type: i6.MatPrefix, selector: "[matPrefix], [matIconPrefix], [matTextPrefix]", inputs: ["matTextPrefix"] }, { kind: "directive", type: i6.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { 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"], exportAs: ["matInput"] }, { kind: "component", type: i5.MatCheckbox, selector: "mat-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { kind: "component", type: i13$3.MatExpansionPanel, selector: "mat-expansion-panel", inputs: ["hideToggle", "togglePosition"], outputs: ["afterExpand", "afterCollapse"], exportAs: ["matExpansionPanel"] }, { kind: "directive", type: i13$3.MatExpansionPanelActionRow, selector: "mat-action-row" }, { kind: "component", type: i6$2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i9.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "directive", type: i8.MatBadge, selector: "[matBadge]", inputs: ["matBadgeColor", "matBadgeOverlap", "matBadgeDisabled", "matBadgePosition", "matBadge", "matBadgeDescription", "matBadgeSize", "matBadgeHidden"] }, { kind: "directive", type: i1$4.CdkTrapFocus, selector: "[cdkTrapFocus]", inputs: ["cdkTrapFocus", "cdkTrapFocusAutoCapture"], exportAs: ["cdkTrapFocus"] }, { kind: "component", type: MatAutocompleteField, selector: "mat-autocomplete-field", inputs: ["equals", "logPrefix", "formControl", "formControlName", "floatLabel", "label", "appearance", "subscriptSizing", "placeholder", "suggestFn", "required", "hideRequiredMarker", "mobile", "clearable", "debounceTime", "displaySeparator", "displayWith", "displayAttributes", "displayColumnSizes", "displayColumnNames", "highlightAccent", "showAllOnFocus", "showPanelOnFocus", "reloadItemsOnFocus", "clearInvalidValueOnBlur", "autofocus", "config", "i18nPrefix", "noResultMessage", "panelClass", "panelWidth", "disableRipple", "matAutocompletePosition", "multiple", "fetchMoreThreshold", "suggestLengthThreshold", "showLoadingSpinner", "debug", "showSearchBar", "stickySearchBar", "applyImplicitValue", "dropButtonTitle", "clearButtonTitle", "trimSearchText", "splitSearchText", "selectInputContentOnFocus", "selectInputContentOnFocusDelay", "previewImplicitValue", "class", "filter", "readonly", "tabindex", "items"], outputs: ["click", "blur", "focus", "dropButtonClick", "keydown.escape", "keydown.backspace", "keyup.enter", "selectionChange"] }, { kind: "component", type: MatBooleanField, selector: "mat-boolean-field", inputs: ["disabled", "formControl", "formControlName", "placeholder", "floatLabel", "appearance", "subscriptSizing", "readonly", "required", "compact", "style", "buttonsColCount", "class", "yesLabel", "noLabel", "showButtonIcons", "yesIcon", "noIcon", "clearable", "labelPosition", "tabindex", "showRadio", "value"], outputs: ["keyup.enter", "focus", "blur"] }, { kind: "directive", type: AutofocusDirective, selector: "[autofocus], input[appAutofocus]", inputs: ["appAutofocus", "autofocusDelay"] }, { kind: "directive", type: AutoTitleDirective, selector: "[appAutoTitle]" }, { kind: "component", type: ToolbarComponent, selector: "app-toolbar", inputs: ["progressBarMode", "title", "color", "class", "backHref", "defaultBackHref", "hasValidate", "hasClose", "hasSearch", "canGoBack", "canShowMenu"], outputs: ["onValidate", "onClose", "onValidateAndClose", "onBackClick", "onSearch"] }, { kind: "component", type: FormButtonsBarComponent, selector: "app-form-buttons-bar", inputs: ["disabled", "disabledCancel", "disabledEscape", "classList", "saveButtonColor", "backText", "cancelText", "nextText", "showBack", "showCancel", "showNext", "showSave"], outputs: ["onCancel", "onSave", "onNext", "onBack", "onSaveAndClose", "onSaveAndNext"] }, { kind: "component", type: ActionsColumnComponent, selector: "app-actions-column", inputs: ["matColumnDef", "style", "stickyEnd", "canCancel", "canConfirm", "canDelete", "canBackward", "canForward", "canConfirmAndAdd", "dirtyIcon", "optionsTitle", "class", "cellTemplate"], outputs: ["optionsClick", "cancelOrDeleteClick", "confirmEditCreateClick", "confirmAndAddClick", "backward", "forward"] }, { kind: "directive", type: i1$3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: ResizableComponent, selector: "th[resizable]", inputs: ["resizable"], outputs: ["sizeChanged"] }, { kind: "directive", type: ResizableDirective, selector: "[resizable]", outputs: ["resizable", "fit"] }, { kind: "pipe", type: i3.AsyncPipe, name: "async" }, { kind: "pipe", type: i1$1.TranslatePipe, name: "translate" }, { kind: "pipe", type: PropertyGetPipe, name: "propertyGet" }, { kind: "pipe", type: NumberFormatPipe, name: "numberFormat" }, { kind: "pipe", type: ArrayLengthPipe, name: "isArrayLength" }, { kind: "pipe", type: FormGetControlPipe, name: "formGetControl" }, { kind: "pipe", type: FormGetValuePipe, name: "formGetValue" }, { kind: "pipe", type: IsSelectedPipe, name: "isSelected" }, { kind: "pipe", type: IsEmptySelectionPipe, name: "isEmptySelection" }, { kind: "pipe", type: IsMultipleSelectionPipe, name: "isMultipleSelection" }, { kind: "pipe", type: IsAllSelectedPipe, name: "isAllSelected" }, { kind: "pipe", type: IsNotAllSelectedPipe, name: "isNotAllSelected" }, { kind: "pipe", type: ReferentialToStringPipe, name: "referentialToString" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
44805
+ ], viewQueries: [{ propertyName: "filterExpansionPanel", first: true, predicate: MatExpansionPanel, descendants: true, static: true }, { propertyName: "infiniteScroll", first: true, predicate: IonInfiniteScroll, descendants: true }], usesInheritance: true, ngImport: i0, template: "<app-toolbar\n color=\"primary\"\n [canGoBack]=\"true\"\n [hasValidate]=\"(loadingSubject | async) !== true && (dirtySubject | async) === true\"\n (onValidate)=\"save()\"\n [backHref]=\"'/testing'\"\n>\n <ion-title>Table 2 (click to select)</ion-title>\n\n <ion-buttons slot=\"end\">\n @if (selection | isEmptySelection) {\n <input matInput type=\"number\" step=\"1\" style=\"color: black; width: 50px\" [(ngModel)]=\"rowHeight\" />\n\n <!-- Add -->\n <button mat-icon-button *ngIf=\"canEdit && !mobile\" [title]=\"'COMMON.BTN_ADD' | translate\" (click)=\"addRow()\">\n <mat-icon>add</mat-icon>\n </button>\n\n <!-- reset filter -->\n <button mat-icon-button (click)=\"resetFilter()\" *ngIf=\"filterCriteriaCount\">\n <mat-icon color=\"accent\">filter_list_alt</mat-icon>\n <mat-icon class=\"icon-secondary\" style=\"left: 16px; top: 5px; font-weight: bold\">close</mat-icon>\n </button>\n\n <!-- show filter -->\n <button mat-icon-button (click)=\"filterExpansionPanel.toggle()\">\n <mat-icon\n *ngIf=\"filterCriteriaCount; else emptyFilter\"\n [matBadge]=\"filterCriteriaCount\"\n matBadgeColor=\"accent\"\n matBadgeSize=\"small\"\n matBadgePosition=\"above after\"\n aria-hidden=\"false\"\n >\n filter_list_alt\n </mat-icon>\n <ng-template #emptyFilter>\n <mat-icon>filter_list_alt</mat-icon>\n </ng-template>\n </button>\n\n <!-- save -->\n <button mat-icon-button *ngIf=\"mobile\" [disabled]=\"(dirtySubject | async) !== true\" (click)=\"save()\">\n <mat-icon>save</mat-icon>\n </button>\n } @else {\n <!-- if row selection -->\n <!-- delete -->\n <button\n mat-icon-button\n *ngIf=\"canEdit\"\n [title]=\"'COMMON.BTN_DELETE' | translate\"\n (click)=\"deleteSelection($event)\"\n >\n <mat-icon>delete</mat-icon>\n </button>\n\n <!-- duplicate -->\n <button\n mat-icon-button\n *ngIf=\"canEdit && selection.selected | isArrayLength: { equals: 1 }\"\n [title]=\"'COMMON.BTN_DUPLICATE' | translate\"\n (click)=\"duplicateRow($event, selection.selected[0])\"\n >\n <mat-icon>file_copy</mat-icon>\n </button>\n }\n </ion-buttons>\n</app-toolbar>\n<ion-content class=\"ion-no-padding\">\n <ion-refresher slot=\"fixed\" *ngIf=\"mobile\" (ionRefresh)=\"doRefresh($event)\">\n <ion-refresher-content></ion-refresher-content>\n </ion-refresher>\n\n <!-- error -->\n <ion-item *ngIf=\"mobile && error\" lines=\"none\" @slideUpDownAnimation>\n <ion-icon color=\"danger\" slot=\"start\" name=\"alert-circle\"></ion-icon>\n <ion-label color=\"danger\" class=\"error\" [innerHTML]=\"error | translate\"></ion-label>\n </ion-item>\n\n <!-- search -->\n <mat-expansion-panel\n #filterExpansionPanel\n class=\"filter-panel\"\n [class.filter-panel-floating]=\"filterPanelFloating\"\n [class.filter-panel-pinned]=\"!filterPanelFloating\"\n >\n <form class=\"form-container ion-padding-top\" [formGroup]=\"filterForm\" (ngSubmit)=\"applyFilterAndClosePanel($event)\">\n <ion-grid>\n <ion-row>\n <ion-col>\n <!-- search text -->\n <mat-form-field>\n <mat-label>{{ 'TABLE.TESTING.SEARCH_TEXT' | translate }}</mat-label>\n <ion-icon matPrefix name=\"search\"></ion-icon>\n <input matInput formControlName=\"searchText\" autocomplete=\"off\" />\n <button\n mat-icon-button\n matSuffix\n tabindex=\"-1\"\n type=\"button\"\n (click)=\"clearControlValue($event, filterForm.controls.searchText)\"\n [hidden]=\"filterForm.controls.searchText.disabled || !filterForm.controls.searchText.value\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n </ion-col>\n </ion-row>\n </ion-grid>\n </form>\n\n <mat-action-row>\n <!-- Counter -->\n <ion-label\n [hidden]=\"(loadingSubject | async) || filterForm.dirty\"\n [color]=\"empty && 'danger'\"\n class=\"ion-padding\"\n >\n {{\n (totalRowCount ? 'COMMON.RESULT_COUNT' : 'COMMON.NO_RESULT')\n | translate\n : {\n count: (totalRowCount | numberFormat)\n }\n }}\n </ion-label>\n\n <div class=\"toolbar-spacer\"></div>\n\n <button\n mat-icon-button\n color=\"accent\"\n *ngIf=\"filterPanelFloating\"\n (click)=\"toggleFilterPanelFloating()\"\n class=\"hidden-xs hidden-sm hidden-md\"\n [title]=\"(filterPanelFloating ? 'COMMON.BTN_EXPAND' : 'COMMON.BTN_HIDE') | translate\"\n >\n <mat-icon>\n <span style=\"transform: rotate(90deg)\">{{ filterPanelFloating ? '&#xbb;' : '&#xab;' }}</span>\n </mat-icon>\n </button>\n\n <!-- Close panel -->\n <ion-button mat-button fill=\"clear\" color=\"dark\" (click)=\"closeFilterPanel()\" [disabled]=\"loadingSubject | async\">\n <ion-text translate>COMMON.BTN_CLOSE</ion-text>\n </ion-button>\n\n <!-- Search button -->\n <ion-button\n mat-button\n [color]=\"filterForm.dirty ? 'tertiary' : 'dark'\"\n [fill]=\"filterForm.dirty ? 'solid' : 'clear'\"\n (click)=\"applyFilterAndClosePanel($event)\"\n >\n <ion-text translate>COMMON.BTN_APPLY</ion-text>\n </ion-button>\n </mat-action-row>\n </mat-expansion-panel>\n\n <!-- table -->\n <div [class.table-container]=\"!enableInfiniteScroll\">\n <table\n #table\n mat-table\n matSort\n matSortDisableClear\n [dataSource]=\"dataSource\"\n [matSortActive]=\"defaultSortBy\"\n [matSortDirection]=\"defaultSortDirection\"\n [trackBy]=\"trackByFn\"\n [style.--mat-row-height]=\"rowHeight + 'px'\"\n >\n <ng-container matColumnDef=\"select\" [sticky]=\"checkBoxSelection\" [class.mat-column-sticky]=\"checkBoxSelection\">\n <th mat-header-cell *matHeaderCellDef [class.cdk-visually-hidden]=\"!checkBoxSelection\">\n @if (selection | isMultipleSelection) {\n <mat-checkbox\n [checked]=\"this | isAllSelected\"\n [indeterminate]=\"this | isNotAllSelected\"\n (change)=\"$event ? masterToggle() : null\"\n ></mat-checkbox>\n }\n </th>\n <td mat-cell *matCellDef=\"let row\" [class.cdk-visually-hidden]=\"!checkBoxSelection\">\n <mat-checkbox [checked]=\"selection | isSelected: row\" (click)=\"toggleSelectRow($event, row)\"></mat-checkbox>\n </td>\n </ng-container>\n\n <!-- Id column -->\n <ng-container matColumnDef=\"id\" [sticky]=\"sticky\">\n <th mat-header-cell *matHeaderCellDef>\n <span mat-sort-header>\n <ion-label title=\"Id\">#</ion-label>\n <ion-label color=\"danger\" [innerHTML]=\"'&nbsp;*'\"></ion-label>\n </span>\n </th>\n <td mat-cell *matCellDef=\"let row\">\n <mat-form-field *ngIf=\"!readOnly && row.id === -1 && row.editing; else readOnlyId\">\n <input\n matInput\n autocomplete=\"off\"\n required\n [formControl]=\"row.validator | formGetControl: 'id'\"\n placeholder=\"Id\"\n [appAutofocus]=\"true\"\n />\n <mat-error *ngIf=\"(row.validator | formGetControl: 'id').hasError('required')\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n <mat-error *ngIf=\"(row.validator | formGetControl: 'id').hasError('alreadyExists')\" translate>\n ERROR.FIELD_NOT_UNIQUE_ID\n </mat-error>\n </mat-form-field>\n\n <ng-template #readOnlyId>\n <ion-label appAutoTitle>\n {{ (row.validator | formGetValue: 'id') || (row.currentData | propertyGet: 'id') }}\n </ion-label>\n </ng-template>\n </td>\n </ng-container>\n\n <!-- Name column -->\n <ng-container matColumnDef=\"name\">\n <th mat-header-cell *matHeaderCellDef [resizable]=\"resizable\">\n <!-- if sortable, wrap the header with a mat-sort-header -->\n <span mat-sort-header>\n <ion-label [title]=\"'TABLE.TESTING.NAME' | translate\">{{ 'TABLE.TESTING.NAME' | translate }}</ion-label>\n <ion-label color=\"danger\" [innerHTML]=\"'&nbsp;*'\"></ion-label>\n </span>\n </th>\n <td mat-cell *matCellDef=\"let row\" (click)=\"focusColumn = 'name'\">\n <mat-form-field *ngIf=\"!readOnly && row.editing; else readOnlyTemplate\">\n <input\n matInput\n autocomplete=\"off\"\n [required]=\"true\"\n [formControl]=\"row.validator | formGetControl: 'name'\"\n [placeholder]=\"'TABLE.TESTING.NAME' | translate\"\n [appAutofocus]=\"row.id === -1 || focusColumn === 'name'\"\n />\n <ng-content select=\"[suffix]\"></ng-content>\n <mat-error *ngIf=\"(row.validator | formGetControl: 'name').hasError('required')\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n <mat-error *ngIf=\"(row.validator | formGetControl: 'name').hasError('maxlength')\" translate>\n ERROR.FIELD_MAX_LENGTH_COMPACT\n </mat-error>\n <mat-error *ngIf=\"(row.validator | formGetControl: 'name').hasError('minlength')\" translate>\n ERROR.FIELD_MIN_LENGTH_COMPACT\n </mat-error>\n </mat-form-field>\n <ng-template #readOnlyTemplate>\n <ion-label appAutoTitle>\n {{ (row.validator | formGetValue: 'name') || (row.currentData | propertyGet: 'name') }}\n </ion-label>\n </ng-template>\n </td>\n </ng-container>\n\n <!-- Level column -->\n <ng-container matColumnDef=\"levelId\">\n <th mat-header-cell *matHeaderCellDef [resizable]=\"resizable\">\n <span mat-sort-header>\n <ion-label>{{ 'TABLE.TESTING.LEVEL_ID' | translate }}</ion-label>\n <ion-label color=\"danger\" [innerHTML]=\"'&nbsp;*'\"></ion-label>\n </span>\n </th>\n <td mat-cell *matCellDef=\"let row\">\n <mat-autocomplete-field\n *ngIf=\"!readOnly && row.editing; else readOnlyTemplate\"\n panelWidth=\"750px\"\n [formControl]=\"row.validator | formGetControl: 'levelId'\"\n [placeholder]=\"'TABLE.TESTING.LEVEL_ID' | translate\"\n floatLabel=\"never\"\n [required]=\"true\"\n [config]=\"autocompleteFields.level\"\n [highlightAccent]=\"true\"\n >\n <mat-error matError *ngIf=\"(row.validator | formGetControl: 'levelId').hasError('invalid')\" translate>\n ERROR.FIELD_INVALID\n </mat-error>\n </mat-autocomplete-field>\n <ng-template #readOnlyTemplate>\n <ion-label appAutoTitle>\n {{\n autocompleteFields.level?.displayWith(\n (row.validator | formGetValue: 'levelId') || (row.currentData | propertyGet: 'levelId')\n ) ||\n ((row.validator | formGetValue: 'levelId') || (row.currentData | propertyGet: 'levelId')\n | referentialToString)\n }}\n </ion-label>\n </ng-template>\n </td>\n </ng-container>\n\n <ng-container matColumnDef=\"boolean\">\n <th mat-header-cell *matHeaderCellDef cdkDrag [resizable]=\"resizable\">\n <!-- if sortable, wrap the header with a mat-sort-header -->\n <span mat-sort-header>\n <ion-label>Boolean</ion-label>\n </span>\n </th>\n <td mat-cell *matCellDef=\"let row\">\n <mat-boolean-field\n *ngIf=\"!readOnly && row.editing; else readOnlyTemplate\"\n floatLabel=\"never\"\n [style]=\"'checkbox'\"\n [formControl]=\"\n (row.validator | formGetControl: 'boolean') || formBuilder.control(row.currentData['boolean'])\n \"\n [compact]=\"true\"\n ></mat-boolean-field>\n <ng-template #readOnlyTemplate>\n <ion-label appAutoTitle>\n {{\n (row.validator | formGetValue: 'boolean') || (row.currentData | propertyGet: 'boolean')\n ? ('COMMON.YES' | translate)\n : ('COMMON.NO' | translate)\n }}\n </ion-label>\n </ng-template>\n </td>\n </ng-container>\n\n <ng-container matColumnDef=\"boolean2\">\n <th mat-header-cell *matHeaderCellDef cdkDrag [resizable]=\"resizable\">\n <!-- if sortable, wrap the header with a mat-sort-header -->\n <span mat-sort-header>\n <ion-label>Boolean 2</ion-label>\n </span>\n </th>\n <td mat-cell *matCellDef=\"let row\">\n <mat-boolean-field\n *ngIf=\"!readOnly && row.editing; else readOnlyTemplate\"\n [floatLabel]=\"'never'\"\n [style]=\"'radio'\"\n [showRadio]=\"true\"\n [formControl]=\"\n (row.validator | formGetControl: 'boolean2') || formBuilder.control(row.currentData['boolean2'])\n \"\n ></mat-boolean-field>\n <ng-template #readOnlyTemplate>\n <ion-label appAutoTitle>\n {{\n (row.validator | formGetValue: 'boolean2') || (row.currentData | propertyGet: 'boolean2')\n ? ('COMMON.YES' | translate)\n : ('COMMON.NO' | translate)\n }}\n </ion-label>\n </ng-template>\n </td>\n </ng-container>\n\n <ng-container matColumnDef=\"boolean3\">\n <th mat-header-cell *matHeaderCellDef cdkDrag [resizable]=\"resizable\">\n <!-- if sortable, wrap the header with a mat-sort-header -->\n <span mat-sort-header>\n <ion-label>Boolean 3</ion-label>\n </span>\n </th>\n <td mat-cell *matCellDef=\"let row\">\n <mat-boolean-field\n *ngIf=\"!readOnly && row.editing; else readOnlyTemplate\"\n floatLabel=\"never\"\n [style]=\"'button'\"\n [formControl]=\"\n (row.validator | formGetControl: 'boolean2') || formBuilder.control(row.currentData['boolean2'])\n \"\n ></mat-boolean-field>\n <ng-template #readOnlyTemplate>\n <ion-label appAutoTitle>\n {{\n (row.validator | formGetValue: 'boolean2') || (row.currentData | propertyGet: 'boolean2')\n ? ('COMMON.YES' | translate)\n : ('COMMON.NO' | translate)\n }}\n </ion-label>\n </ng-template>\n </td>\n </ng-container>\n\n <!-- Actions buttons column -->\n <app-actions-column\n [stickyEnd]=\"stickyEnd\"\n [canCancel]=\"false\"\n [style]=\"'table'\"\n (optionsClick)=\"openSelectColumnsModal($event)\"\n (cancelOrDeleteClick)=\"cancelOrDelete($event.event, $event.row)\"\n (confirmAndAddClick)=\"confirmAndAdd($event.event, $event.row)\"\n (backward)=\"confirmAndBackward($event.event, $event.row)\"\n (forward)=\"confirmAndForward($event.event, $event.row)\"\n [cellTemplate]=\"cellInjection\"\n >\n <!-- cell injection-->\n <ng-template #cellInjection let-row>\n <span *ngIf=\"row.editing && !row.validator.dirty\">-</span>\n </ng-template>\n </app-actions-column>\n\n <tr mat-header-row *matHeaderRowDef=\"displayedColumns; sticky: true\"></tr>\n <tr\n mat-row\n *matRowDef=\"let row; columns: displayedColumns\"\n [class.mat-row-selected]=\"row.editing\"\n [class.mat-row-error]=\"row.invalid\"\n [class.mat-row-disabled]=\"!row.editing\"\n [class.mat-row-dirty]=\"row.dirty\"\n (click)=\"clickRow($event, row)\"\n (keydown.escape)=\"escapeEditingRow($event)\"\n [cdkTrapFocus]=\"row.invalid\"\n ></tr>\n </table>\n\n <ng-container *ngIf=\"loadingSubject | async; else noResult\">\n <ion-item>\n <ion-skeleton-text animated></ion-skeleton-text>\n </ion-item>\n </ng-container>\n\n <ng-template #noResult>\n <ion-item *ngIf=\"totalRowCount === 0\">\n <ion-text color=\"danger\" class=\"text-italic\" translate>COMMON.NO_RESULT</ion-text>\n </ion-item>\n </ng-template>\n\n <ion-infinite-scroll\n *ngIf=\"enableInfiniteScroll\"\n [threshold]=\"mobile ? '10%' : '2%'\"\n position=\"bottom\"\n (ionInfinite)=\"fetchMore($event)\"\n >\n <ion-infinite-scroll-content\n loadingSpinner=\"circles\"\n [loadingText]=\"'COMMON.LOADING_DOTS' | translate\"\n ></ion-infinite-scroll-content>\n </ion-infinite-scroll>\n </div>\n</ion-content>\n\n<ion-footer>\n <!-- Paginator -->\n <mat-paginator\n *ngIf=\"!enableInfiniteScroll\"\n [length]=\"totalRowCount\"\n [pageSize]=\"defaultPageSize\"\n [pageSizeOptions]=\"defaultPageSizeOptions\"\n showFirstLastButtons\n ></mat-paginator>\n\n <app-form-buttons-bar\n *ngIf=\"canEdit && !mobile\"\n (onCancel)=\"load()\"\n (onSave)=\"save()\"\n [disabled]=\"(loadingSubject | async) || !dirty\"\n >\n <!-- error -->\n <ion-item *ngIf=\"error$ | async\" lines=\"none\">\n <ion-icon color=\"danger\" slot=\"start\" name=\"alert-circle\"></ion-icon>\n <ion-label color=\"danger\" [innerHTML]=\"error | translate\"></ion-label>\n </ion-item>\n </app-form-buttons-bar>\n</ion-footer>\n\n<ion-fab slot=\"fixed\" vertical=\"bottom\" horizontal=\"end\" *ngIf=\"canEdit && mobile\">\n <ion-fab-button color=\"tertiary\" (click)=\"addRow($event)\">\n <ion-icon name=\"add\"></ion-icon>\n </ion-fab-button>\n</ion-fab>\n", styles: [".table-container .mat-mdc-table .mat-column-select{min-width:30px}.table-container .mat-mdc-table .mat-column-id{min-width:30px;max-width:30px}.table-container .mat-mdc-table .mat-column-label,.table-container .mat-mdc-table .mat-column-name,.table-container .mat-mdc-table .mat-column-levelId,.table-container .mat-mdc-table .mat-column-statusId{min-width:150px}.table-container .mat-mdc-table .mat-column-comments{min-width:100px;max-width:100px}.table-container .mat-mdc-table .mat-column-updateDate{min-width:110px;max-width:110px}\n"], dependencies: [{ kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i2$1.IonButton, selector: "ion-button", inputs: ["buttonType", "color", "disabled", "download", "expand", "fill", "form", "href", "mode", "rel", "routerAnimation", "routerDirection", "shape", "size", "strong", "target", "type"] }, { kind: "component", type: i2$1.IonButtons, selector: "ion-buttons", inputs: ["collapse"] }, { kind: "component", type: i2$1.IonCol, selector: "ion-col", inputs: ["offset", "offsetLg", "offsetMd", "offsetSm", "offsetXl", "offsetXs", "pull", "pullLg", "pullMd", "pullSm", "pullXl", "pullXs", "push", "pushLg", "pushMd", "pushSm", "pushXl", "pushXs", "size", "sizeLg", "sizeMd", "sizeSm", "sizeXl", "sizeXs"] }, { kind: "component", type: i2$1.IonContent, selector: "ion-content", inputs: ["color", "forceOverscroll", "fullscreen", "scrollEvents", "scrollX", "scrollY"] }, { kind: "component", type: i2$1.IonFab, selector: "ion-fab", inputs: ["activated", "edge", "horizontal", "vertical"] }, { kind: "component", type: i2$1.IonFabButton, selector: "ion-fab-button", inputs: ["activated", "closeIcon", "color", "disabled", "download", "href", "mode", "rel", "routerAnimation", "routerDirection", "show", "size", "target", "translucent", "type"] }, { kind: "component", type: i2$1.IonFooter, selector: "ion-footer", inputs: ["collapse", "mode", "translucent"] }, { kind: "component", type: i2$1.IonGrid, selector: "ion-grid", inputs: ["fixed"] }, { kind: "component", type: i2$1.IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: i2$1.IonInfiniteScroll, selector: "ion-infinite-scroll", inputs: ["disabled", "position", "threshold"] }, { kind: "component", type: i2$1.IonInfiniteScrollContent, selector: "ion-infinite-scroll-content", inputs: ["loadingSpinner", "loadingText"] }, { kind: "component", type: i2$1.IonItem, selector: "ion-item", inputs: ["button", "color", "counter", "counterFormatter", "detail", "detailIcon", "disabled", "download", "fill", "href", "lines", "mode", "rel", "routerAnimation", "routerDirection", "shape", "target", "type"] }, { kind: "component", type: i2$1.IonLabel, selector: "ion-label", inputs: ["color", "mode", "position"] }, { kind: "component", type: i2$1.IonRefresher, selector: "ion-refresher", inputs: ["closeDuration", "disabled", "mode", "pullFactor", "pullMax", "pullMin", "snapbackDuration"] }, { kind: "component", type: i2$1.IonRefresherContent, selector: "ion-refresher-content", inputs: ["pullingIcon", "pullingText", "refreshingSpinner", "refreshingText"] }, { kind: "component", type: i2$1.IonRow, selector: "ion-row" }, { kind: "component", type: i2$1.IonSkeletonText, selector: "ion-skeleton-text", inputs: ["animated"] }, { kind: "component", type: i2$1.IonText, selector: "ion-text", inputs: ["color", "mode"] }, { kind: "component", type: i2$1.IonTitle, selector: "ion-title", inputs: ["color", "size"] }, { kind: "directive", type: i1$1.TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }, { kind: "directive", type: i1$3.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$3.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: i1$3.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1$3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$3.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$3.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1$3.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$3.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$3.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i6$4.CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "component", type: i1$6.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i1$6.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i1$6.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i1$6.MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: i1$6.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i1$6.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i1$6.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i1$6.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "component", type: i1$6.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i1$6.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "directive", type: i8$2.MatSort, selector: "[matSort]", inputs: ["matSortActive", "matSortStart", "matSortDirection", "matSortDisableClear", "matSortDisabled"], outputs: ["matSortChange"], exportAs: ["matSort"] }, { kind: "component", type: i8$2.MatSortHeader, selector: "[mat-sort-header]", inputs: ["mat-sort-header", "arrowPosition", "start", "disabled", "sortActionDescription", "disableClear"], exportAs: ["matSortHeader"] }, { kind: "component", type: i9$3.MatPaginator, selector: "mat-paginator", inputs: ["color", "pageIndex", "length", "pageSize", "pageSizeOptions", "hidePageSize", "showFirstLastButtons", "selectConfig", "disabled"], outputs: ["page"], exportAs: ["matPaginator"] }, { kind: "component", type: i6.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i6.MatLabel, selector: "mat-label" }, { kind: "directive", type: i6.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "directive", type: i6.MatPrefix, selector: "[matPrefix], [matIconPrefix], [matTextPrefix]", inputs: ["matTextPrefix"] }, { kind: "directive", type: i6.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { 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"], exportAs: ["matInput"] }, { kind: "component", type: i5.MatCheckbox, selector: "mat-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { kind: "component", type: i13$3.MatExpansionPanel, selector: "mat-expansion-panel", inputs: ["hideToggle", "togglePosition"], outputs: ["afterExpand", "afterCollapse"], exportAs: ["matExpansionPanel"] }, { kind: "directive", type: i13$3.MatExpansionPanelActionRow, selector: "mat-action-row" }, { kind: "component", type: i6$2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i9.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "directive", type: i8.MatBadge, selector: "[matBadge]", inputs: ["matBadgeColor", "matBadgeOverlap", "matBadgeDisabled", "matBadgePosition", "matBadge", "matBadgeDescription", "matBadgeSize", "matBadgeHidden"] }, { kind: "directive", type: i1$4.CdkTrapFocus, selector: "[cdkTrapFocus]", inputs: ["cdkTrapFocus", "cdkTrapFocusAutoCapture"], exportAs: ["cdkTrapFocus"] }, { kind: "component", type: MatAutocompleteField, selector: "mat-autocomplete-field", inputs: ["equals", "logPrefix", "formControl", "formControlName", "floatLabel", "label", "appearance", "subscriptSizing", "placeholder", "suggestFn", "required", "hideRequiredMarker", "mobile", "clearable", "debounceTime", "displaySeparator", "displayWith", "displayAttributes", "displayColumnSizes", "displayColumnNames", "highlightAccent", "showAllOnFocus", "showPanelOnFocus", "reloadItemsOnFocus", "clearInvalidValueOnBlur", "autofocus", "config", "i18nPrefix", "noResultMessage", "panelClass", "panelWidth", "disableRipple", "matAutocompletePosition", "multiple", "fetchMoreThreshold", "suggestLengthThreshold", "showLoadingSpinner", "debug", "showSearchBar", "stickySearchBar", "applyImplicitValue", "dropButtonTitle", "clearButtonTitle", "trimSearchText", "splitSearchText", "selectInputContentOnFocus", "selectInputContentOnFocusDelay", "previewImplicitValue", "class", "filter", "readonly", "tabindex", "items"], outputs: ["click", "blur", "focus", "dropButtonClick", "keydown.escape", "keydown.backspace", "keyup.enter", "selectionChange"] }, { kind: "component", type: MatBooleanField, selector: "mat-boolean-field", inputs: ["disabled", "formControl", "formControlName", "placeholder", "floatLabel", "appearance", "subscriptSizing", "readonly", "required", "compact", "style", "buttonsColCount", "class", "yesLabel", "noLabel", "showButtonIcons", "yesIcon", "noIcon", "clearable", "labelPosition", "tabindex", "showRadio", "value"], outputs: ["keyup.enter", "focus", "blur"] }, { kind: "directive", type: AutofocusDirective, selector: "[autofocus], input[appAutofocus]", inputs: ["appAutofocus", "autofocusDelay"] }, { kind: "directive", type: AutoTitleDirective, selector: "[appAutoTitle]" }, { kind: "component", type: ToolbarComponent, selector: "app-toolbar", inputs: ["progressBarMode", "title", "color", "class", "backHref", "defaultBackHref", "hasValidate", "hasClose", "hasSearch", "canGoBack", "canShowMenu"], outputs: ["onValidate", "onClose", "onValidateAndClose", "onBackClick", "onSearch"] }, { kind: "component", type: FormButtonsBarComponent, selector: "app-form-buttons-bar", inputs: ["disabled", "disabledCancel", "disabledEscape", "classList", "saveButtonColor", "backText", "cancelText", "nextText", "showBack", "showCancel", "showNext", "showSave"], outputs: ["onCancel", "onSave", "onNext", "onBack", "onSaveAndClose", "onSaveAndNext"] }, { kind: "component", type: ActionsColumnComponent, selector: "app-actions-column", inputs: ["matColumnDef", "style", "stickyEnd", "canCancel", "canConfirm", "canDelete", "canBackward", "canForward", "canConfirmAndAdd", "dirtyIcon", "optionsTitle", "class", "cellTemplate"], outputs: ["optionsClick", "cancelOrDeleteClick", "confirmEditCreateClick", "confirmAndAddClick", "backward", "forward"] }, { kind: "directive", type: i1$3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: ResizableComponent, selector: "th[resizable]", inputs: ["resizable"], outputs: ["sizeChanged"] }, { kind: "directive", type: ResizableDirective, selector: "[resizable]", outputs: ["resizable", "fit"] }, { kind: "pipe", type: i3.AsyncPipe, name: "async" }, { kind: "pipe", type: i1$1.TranslatePipe, name: "translate" }, { kind: "pipe", type: PropertyGetPipe, name: "propertyGet" }, { kind: "pipe", type: NumberFormatPipe, name: "numberFormat" }, { kind: "pipe", type: ArrayLengthPipe, name: "isArrayLength" }, { kind: "pipe", type: FormGetControlPipe, name: "formGetControl" }, { kind: "pipe", type: FormGetValuePipe, name: "formGetValue" }, { kind: "pipe", type: IsSelectedPipe, name: "isSelected" }, { kind: "pipe", type: IsEmptySelectionPipe, name: "isEmptySelection" }, { kind: "pipe", type: IsMultipleSelectionPipe, name: "isMultipleSelection" }, { kind: "pipe", type: IsAllSelectedPipe, name: "isAllSelected" }, { kind: "pipe", type: IsNotAllSelectedPipe, name: "isNotAllSelected" }, { kind: "pipe", type: ReferentialToStringPipe, name: "referentialToString" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
44714
44806
  }
44715
44807
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: Table2TestPage, decorators: [{
44716
44808
  type: Component,
@@ -44981,7 +45073,7 @@ class TableTestPage extends AppTable {
44981
45073
  provide: AppTable,
44982
45074
  useExisting: forwardRef(() => TableTestPage),
44983
45075
  },
44984
- ], viewQueries: [{ propertyName: "filterExpansionPanel", first: true, predicate: MatExpansionPanel, descendants: true, static: true }, { propertyName: "infiniteScroll", first: true, predicate: IonInfiniteScroll, descendants: true }], usesInheritance: true, ngImport: i0, template: "<app-toolbar\n color=\"primary\"\n [canGoBack]=\"true\"\n [hasValidate]=\"(loadingSubject | async) !== true && (dirtySubject | async) === true\"\n (onValidate)=\"save()\"\n [backHref]=\"'/testing'\"\n>\n <ion-title>Table (click to edit)</ion-title>\n <ion-buttons slot=\"end\">\n @if (selection | isEmptySelection) {\n <input matInput type=\"number\" step=\"1\" style=\"color: black; width: 50px\" [(ngModel)]=\"rowHeight\" />\n\n <!-- Add -->\n <button mat-icon-button *ngIf=\"canEdit && !mobile\" [title]=\"'COMMON.BTN_ADD' | translate\" (click)=\"addRow()\">\n <mat-icon>add</mat-icon>\n </button>\n\n <!-- reset filter -->\n <button mat-icon-button (click)=\"resetFilter()\" *ngIf=\"filterCriteriaCount\">\n <mat-icon color=\"accent\">filter_list_alt</mat-icon>\n <mat-icon class=\"icon-secondary\" style=\"left: 16px; top: 5px; font-weight: bold\">close</mat-icon>\n </button>\n\n <!-- show filter -->\n <button mat-icon-button (click)=\"filterExpansionPanel.toggle()\">\n <mat-icon\n *ngIf=\"filterCriteriaCount; else emptyFilter\"\n [matBadge]=\"filterCriteriaCount\"\n matBadgeColor=\"accent\"\n matBadgeSize=\"small\"\n matBadgePosition=\"above after\"\n aria-hidden=\"false\"\n >\n filter_list_alt\n </mat-icon>\n <ng-template #emptyFilter>\n <mat-icon>filter_list_alt</mat-icon>\n </ng-template>\n </button>\n\n <!-- save -->\n <button mat-icon-button *ngIf=\"mobile\" [disabled]=\"(dirtySubject | async) !== true\" (click)=\"save()\">\n <mat-icon>save</mat-icon>\n </button>\n\n <!-- start/stop timer to auto-load data -->\n <ion-button *ngIf=\"!timer\" (click)=\"startTimer()\">Start reload</ion-button>\n <ion-button *ngIf=\"timer\" (click)=\"stopTimer()\" color=\"accent\">Stop reload</ion-button>\n } @else {\n <!-- if row selection -->\n <!-- delete -->\n <button\n mat-icon-button\n *ngIf=\"canEdit\"\n [title]=\"'COMMON.BTN_DELETE' | translate\"\n (click)=\"deleteSelection($event)\"\n >\n <mat-icon>delete</mat-icon>\n </button>\n\n <!-- duplicate -->\n <button\n mat-icon-button\n *ngIf=\"canEdit && selection.selected | isArrayLength: { equals: 1 }\"\n [title]=\"'COMMON.BTN_DUPLICATE' | translate\"\n (click)=\"duplicateRow($event, selection.selected[0])\"\n >\n <mat-icon>file_copy</mat-icon>\n </button>\n }\n </ion-buttons>\n</app-toolbar>\n<ion-content class=\"ion-no-padding\">\n <ion-refresher slot=\"fixed\" *ngIf=\"mobile\" (ionRefresh)=\"doRefresh($event)\">\n <ion-refresher-content></ion-refresher-content>\n </ion-refresher>\n\n <!-- error -->\n <ion-item *ngIf=\"mobile && error\" lines=\"none\" @slideUpDownAnimation>\n <ion-icon color=\"danger\" slot=\"start\" name=\"alert-circle\"></ion-icon>\n <ion-label color=\"danger\" class=\"error\" [innerHTML]=\"error | translate\"></ion-label>\n </ion-item>\n\n <!-- search -->\n <mat-expansion-panel\n #filterExpansionPanel\n class=\"filter-panel\"\n [class.filter-panel-floating]=\"filterPanelFloating\"\n [class.filter-panel-pinned]=\"!filterPanelFloating\"\n >\n <form class=\"form-container ion-padding-top\" [formGroup]=\"filterForm\" (ngSubmit)=\"applyFilterAndClosePanel($event)\">\n <ion-grid>\n <ion-row>\n <ion-col>\n <!-- search text -->\n <mat-form-field>\n <mat-label>{{ 'TABLE.TESTING.SEARCH_TEXT' | translate }}</mat-label>\n <ion-icon matPrefix name=\"search\"></ion-icon>\n <input matInput formControlName=\"searchText\" autocomplete=\"off\" />\n <button\n mat-icon-button\n matSuffix\n tabindex=\"-1\"\n type=\"button\"\n (click)=\"clearControlValue($event, filterForm.controls.searchText)\"\n [hidden]=\"filterForm.controls.searchText.disabled || !filterForm.controls.searchText.value\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n </ion-col>\n </ion-row>\n </ion-grid>\n </form>\n\n <mat-action-row>\n <!-- Counter -->\n <ion-label\n [hidden]=\"(loadingSubject | async) || filterForm.dirty\"\n [color]=\"empty && 'danger'\"\n class=\"ion-padding\"\n >\n {{\n (totalRowCount ? 'COMMON.RESULT_COUNT' : 'COMMON.NO_RESULT')\n | translate\n : {\n count: (totalRowCount | numberFormat)\n }\n }}\n </ion-label>\n\n <div class=\"toolbar-spacer\"></div>\n\n <button\n mat-icon-button\n color=\"accent\"\n *ngIf=\"filterPanelFloating\"\n (click)=\"toggleFilterPanelFloating()\"\n class=\"hidden-xs hidden-sm hidden-md\"\n [title]=\"(filterPanelFloating ? 'COMMON.BTN_EXPAND' : 'COMMON.BTN_HIDE') | translate\"\n >\n <mat-icon>\n <span style=\"transform: rotate(90deg)\">{{ filterPanelFloating ? '&#xbb;' : '&#xab;' }}</span>\n </mat-icon>\n </button>\n\n <!-- Close panel -->\n <ion-button mat-button fill=\"clear\" color=\"dark\" (click)=\"closeFilterPanel()\" [disabled]=\"loadingSubject | async\">\n <ion-text translate>COMMON.BTN_CLOSE</ion-text>\n </ion-button>\n\n <!-- Search button -->\n <ion-button\n mat-button\n [color]=\"filterForm.dirty ? 'tertiary' : 'dark'\"\n [fill]=\"filterForm.dirty ? 'solid' : 'clear'\"\n (click)=\"applyFilterAndClosePanel($event)\"\n >\n <ion-text translate>COMMON.BTN_APPLY</ion-text>\n </ion-button>\n </mat-action-row>\n </mat-expansion-panel>\n\n <!-- table -->\n <div [class.table-container]=\"!enableInfiniteScroll\">\n <table\n #table\n mat-table\n matSort\n matSortDisableClear\n [dataSource]=\"dataSource\"\n [matSortActive]=\"defaultSortBy\"\n [matSortDirection]=\"defaultSortDirection\"\n [trackBy]=\"trackByFn\"\n [style.--mat-row-height]=\"rowHeight + 'px'\"\n >\n <!-- group header cells -->\n <ng-container matColumnDef=\"top-start\" [sticky]=\"sticky\">\n <th mat-header-cell *matHeaderCellDef [class.cdk-visually-hidden]=\"!canEdit\" [attr.colspan]=\"2\">\n <!-- start spacer -->\n </th>\n </ng-container>\n\n <ng-container matColumnDef=\"group-1\">\n <th mat-header-cell *matHeaderCellDef [attr.colspan]=\"3\">\n <ion-label translate>{{ i18nColumnPrefix + 'GROUP_1' }}</ion-label>\n </th>\n </ng-container>\n\n <ng-container matColumnDef=\"group-2\">\n <th mat-header-cell *matHeaderCellDef [attr.colspan]=\"displayedColumns.length - 6\">\n <ion-label translate>{{ i18nColumnPrefix + 'GROUP_2' }}</ion-label>\n </th>\n </ng-container>\n\n <ng-container matColumnDef=\"top-end\" [stickyEnd]=\"stickyEnd\">\n <th mat-header-cell *matHeaderCellDef>\n <!-- end spacer -->\n <ion-label></ion-label>\n </th>\n </ng-container>\n\n <ng-container matColumnDef=\"select\" [sticky]=\"sticky\" [class.mat-column-sticky]=\"sticky\">\n <th mat-header-cell *matHeaderCellDef [class.cdk-visually-hidden]=\"!canEdit\">\n @if (selection | isMultipleSelection) {\n <mat-checkbox\n [checked]=\"this | isAllSelected\"\n [indeterminate]=\"this | isNotAllSelected\"\n (change)=\"$event ? masterToggle() : null\"\n ></mat-checkbox>\n }\n </th>\n <td mat-cell *matCellDef=\"let row\" [class.cdk-visually-hidden]=\"!canEdit\">\n <mat-checkbox\n (click)=\"toggleSelectRow($event, row)\"\n [checked]=\"selection | isSelected: row\"\n tabindex=\"-1\"\n ></mat-checkbox>\n </td>\n </ng-container>\n\n <!-- Id column -->\n <ng-container matColumnDef=\"id\" [sticky]=\"sticky\" [class.mat-column-sticky]=\"sticky\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>\n <ion-label>#</ion-label>\n </th>\n <td mat-cell *matCellDef=\"let row\">{{ row.currentData?.id }}</td>\n </ng-container>\n\n <!-- Label column -->\n <ng-container matColumnDef=\"label\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>\n <ion-label translate>TABLE.TESTING.LABEL</ion-label>\n </th>\n <td mat-cell *matCellDef=\"let row\" (click)=\"focusColumn = 'label'\">\n @if (row.editing) {\n <mat-form-field>\n <input\n matInput\n autocomplete=\"off\"\n [formControl]=\"row.validator.controls['label']\"\n [placeholder]=\"'TABLE.TESTING.LABEL' | translate\"\n [appAutofocus]=\"focusColumn === 'label'\"\n [readonly]=\"!row.editing\"\n />\n <mat-error *ngIf=\"row.validator.controls['label'].hasError('required')\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n </mat-form-field>\n } @else {\n <ion-label appAutoTitle>\n {{ row.validator | formGetValue: 'label' }}\n </ion-label>\n }\n </td>\n </ng-container>\n\n <!-- Name column -->\n <ng-container matColumnDef=\"name\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>\n <ion-label translate>TABLE.TESTING.NAME</ion-label>\n </th>\n <td mat-cell *matCellDef=\"let row\" (click)=\"focusColumn = 'name'\">\n @if (row.editing) {\n <mat-form-field>\n <input\n matInput\n [formControl]=\"row.validator?.controls.name\"\n [placeholder]=\"'TABLE.TESTING.NAME' | translate\"\n [appAutofocus]=\"focusColumn === 'name'\"\n />\n <mat-error *ngIf=\"row.validator?.controls.name.hasError('required')\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n </mat-form-field>\n } @else {\n <ion-label appAutoTitle>\n {{ row.validator | formGetValue: 'name' }}\n </ion-label>\n }\n </td>\n </ng-container>\n\n <!-- Level column -->\n <ng-container matColumnDef=\"levelId\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>\n <ion-label translate>TABLE.TESTING.LEVEL_ID</ion-label>\n </th>\n <td mat-cell *matCellDef=\"let row\" (click)=\"focusColumn = 'levelId'\">\n @if (row.editing) {\n <mat-autocomplete-field\n [formControl]=\"row.validator.controls.levelId\"\n [placeholder]=\"'TABLE.TESTING.LEVEL_ID' | translate\"\n floatLabel=\"never\"\n [config]=\"autocompleteFields.level\"\n [readonly]=\"!row.editing\"\n [autofocus]=\"focusColumn === 'levelId'\"\n [required]=\"true\"\n ></mat-autocomplete-field>\n } @else {\n <ion-label appAutoTitle>\n {{ row.validator | formGetValue: 'levelId' | referentialToString: autocompleteFields.level.attributes }}\n </ion-label>\n }\n </td>\n </ng-container>\n\n <!-- Status column -->\n <ng-container matColumnDef=\"statusId\">\n <th mat-header-cell *matHeaderCellDef>\n <span translate>USER.STATUS</span>\n </th>\n <td\n mat-cell\n *matCellDef=\"let row\"\n [class.mat-form-field-disabled]=\"!row.editing\"\n (click)=\"focusColumn = 'statusId'\"\n >\n <mat-form-field>\n <mat-select\n [formControl]=\"row.validator.controls['statusId']\"\n [placeholder]=\"i18nColumnPrefix + 'STATUS_ID' | translate\"\n >\n <mat-option *ngFor=\"let item of statusList\" [value]=\"item.id\">\n <mat-icon><ion-icon [name]=\"item.icon\"></ion-icon></mat-icon>\n <mat-label>{{ item.label | translate }}</mat-label>\n </mat-option>\n </mat-select>\n <mat-error *ngIf=\"row.validator.controls['statusId'].hasError('required')\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n </mat-form-field>\n </td>\n </ng-container>\n\n <!-- Enum column -->\n <!-- NOTE : Never used in table -->\n <!-- <ng-container matColumnDef=\"values\">-->\n <!-- <th mat-header-cell *matHeaderCellDef>-->\n <!-- <span translate>Enums</span>-->\n <!-- </th>-->\n <!-- <td mat-cell *matCellDef=\"let row\" [class.mat-form-field-disabled]=\"!row.editing\">-->\n <!-- <app-form-field-->\n <!-- [formControl]=\"row.validator|formGetControl:'properties.values'\"-->\n <!-- [definition]=\"columnDefinitions['values']\"-->\n <!-- ></app-form-field>-->\n <!-- </td>-->\n <!-- </ng-container>-->\n\n <!-- boolean (as checkbox) -->\n <ng-container matColumnDef=\"boolean\">\n <th mat-header-cell *matHeaderCellDef cdkDrag [resizable]=\"true\">\n <!-- if sortable, wrap the header with a mat-sort-header -->\n <span mat-sort-header>\n <ion-label>Boolean</ion-label>\n </span>\n </th>\n <td mat-cell *matCellDef=\"let row\">\n @if (!readOnly && row.editing) {\n <mat-boolean-field\n floatLabel=\"never\"\n [style]=\"'checkbox'\"\n placeholder=\"Oui/Non\"\n [formControl]=\"row.validator | formGetControl: 'properties.boolean'\"\n [compact]=\"true\"\n ></mat-boolean-field>\n } @else {\n <ion-label appAutoTitle>\n {{ (row.validator | formGetValue: 'properties.boolean') ? '&#x2714;' : '&#x2718;' }}\n </ion-label>\n }\n </td>\n </ng-container>\n\n <!-- date -->\n <ng-container matColumnDef=\"date\">\n <th mat-header-cell *matHeaderCellDef cdkDrag [resizable]=\"true\" class=\"mat-cell-date-time\">\n <!-- if sortable, wrap the header with a mat-sort-header -->\n <span mat-sort-header>\n <ion-label>Date</ion-label>\n </span>\n </th>\n <td mat-cell *matCellDef=\"let row\" class=\"mat-cell-date-time\" (click)=\"focusColumn = 'date'\">\n @if (!readOnly && row.editing) {\n <mat-date-time-field\n floatLabel=\"never\"\n [formControl]=\"row.validator | formGetControl: 'properties.date'\"\n [autofocus]=\"focusColumn === 'date'\"\n placeholder=\"Date/Time\"\n [compact]=\"true\"\n ></mat-date-time-field>\n } @else {\n <ion-label appAutoTitle>\n {{ row.validator | formGetValue: 'properties.date' | dateFormat: { time: true } }}\n </ion-label>\n }\n </td>\n </ng-container>\n\n <!-- latitude -->\n <ng-container matColumnDef=\"latitude\">\n <th mat-header-cell *matHeaderCellDef cdkDrag [resizable]=\"true\">\n <!-- if sortable, wrap the header with a mat-sort-header -->\n <span mat-sort-header>\n <ion-label>Latitude</ion-label>\n </span>\n </th>\n <td mat-cell *matCellDef=\"let row\" (click)=\"focusColumn = 'latitude'\">\n @if (!readOnly && row.editing) {\n <mat-latlong-field\n floatLabel=\"never\"\n [formControl]=\"row.validator | formGetControl: 'properties.latitude'\"\n placeholder=\"Latitude\"\n [latLongPattern]=\"'DDMM'\"\n [type]=\"'latitude'\"\n [autofocus]=\"focusColumn === 'latitude'\"\n ></mat-latlong-field>\n } @else {\n <ion-label appAutoTitle>\n {{ row.validator | formGetValue: 'properties.latitude' | latitudeFormat: { pattern: 'DDMM', placeholderChar: '0' } }}\n </ion-label>\n }\n </td>\n </ng-container>\n\n <!-- Creation date column -->\n <ng-container matColumnDef=\"updateDate\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>\n <ion-label translate>TABLE.TESTING.UPDATE_DATE</ion-label>\n </th>\n <td mat-cell *matCellDef=\"let row\" class=\"mat-form-field-disabled\">\n <ion-text color=\"medium\" *ngIf=\"row.id !== -1\">\n <small>\n {{ row.validator | formGetValue: 'creationDate' | dateFormat: { time: true } }}\n </small>\n </ion-text>\n </td>\n </ng-container>\n\n <!-- Comment column -->\n <ng-container matColumnDef=\"comments\">\n <th mat-header-cell *matHeaderCellDef>\n <ion-label translate>TABLE.TESTING.COMMENTS</ion-label>\n </th>\n <td mat-cell *matCellDef=\"let row\">\n <mat-form-field *ngIf=\"row.editing; else iconComment\">\n <!--<textarea matInput [formControl]=\"row.validator?.controls.comments\"\n [placeholder]=\"'TABLE.TESTING.COMMENTS'|translate\"\n [readonly]=\"!row.editing\"></textarea>-->\n\n <input\n type=\"text\"\n matInput\n [formControl]=\"row.validator?.controls.comments\"\n [placeholder]=\"'TABLE.TESTING.COMMENTS' | translate\"\n [readonly]=\"!row.editing\"\n />\n </mat-form-field>\n\n <ng-template #iconComment>\n <ion-icon\n [color]=\"row.validator?.controls.comments.value ? 'tertiary' : 'medium'\"\n name=\"chatbox\"\n slot=\"icon-only\"\n ></ion-icon>\n </ng-template>\n </td>\n </ng-container>\n\n <!-- Actions column -->\n <app-nav-actions-column\n [stickyEnd]=\"stickyEnd\"\n (optionsClick)=\"openSelectColumnsModal($event)\"\n [cellTemplate]=\"cellInjection\"\n [showPending]=\"true\"\n >\n <!-- cell injection-->\n <ng-template #cellInjection let-row>\n <span *ngIf=\"row.editing && !row.validator.dirty\">-</span>\n </ng-template>\n </app-nav-actions-column>\n\n <tr mat-header-row *matHeaderRowDef=\"groupColumns\"></tr>\n <tr mat-header-row *matHeaderRowDef=\"displayedColumns; sticky: true\"></tr>\n <tr\n mat-row\n *matRowDef=\"let row; columns: displayedColumns\"\n [class.mat-mdc-row-selected]=\"row.editing\"\n [class.mat-mdc-row-error]=\"row.invalid\"\n [class.mat-mdc-row-disabled]=\"!row.editing\"\n [class.mat-mdc-row-dirty]=\"row.dirty\"\n (click)=\"clickRow($event, row)\"\n (keydown.escape)=\"escapeEditingRow($event)\"\n [cdkTrapFocus]=\"row.invalid\"\n ></tr>\n </table>\n\n <ng-container *ngIf=\"loadingSubject | async; else noResult\">\n <ion-item>\n <ion-skeleton-text animated></ion-skeleton-text>\n </ion-item>\n </ng-container>\n\n <ng-template #noResult>\n <ion-item *ngIf=\"totalRowCount === 0\">\n <ion-text color=\"danger\" class=\"text-italic\" translate>COMMON.NO_RESULT</ion-text>\n </ion-item>\n </ng-template>\n\n <ion-infinite-scroll\n *ngIf=\"enableInfiniteScroll\"\n [threshold]=\"mobile ? '10%' : '2%'\"\n position=\"bottom\"\n (ionInfinite)=\"fetchMore($event)\"\n >\n <ion-infinite-scroll-content\n loadingSpinner=\"circles\"\n [loadingText]=\"'COMMON.LOADING_DOTS' | translate\"\n ></ion-infinite-scroll-content>\n </ion-infinite-scroll>\n </div>\n</ion-content>\n\n<ion-footer>\n <!-- Paginator -->\n <mat-paginator\n *ngIf=\"!enableInfiniteScroll\"\n [length]=\"totalRowCount\"\n [pageSize]=\"defaultPageSize\"\n [pageSizeOptions]=\"defaultPageSizeOptions\"\n showFirstLastButtons\n ></mat-paginator>\n\n <app-form-buttons-bar\n *ngIf=\"canEdit && !mobile\"\n (onCancel)=\"load()\"\n (onSave)=\"save()\"\n [disabled]=\"(loadingSubject | async) || !dirty\"\n >\n <!-- error -->\n <ion-item *ngIf=\"error$ | async\" lines=\"none\">\n <ion-icon color=\"danger\" slot=\"start\" name=\"alert-circle\"></ion-icon>\n <ion-label color=\"danger\" [innerHTML]=\"error | translate\"></ion-label>\n </ion-item>\n </app-form-buttons-bar>\n</ion-footer>\n\n<ion-fab slot=\"fixed\" vertical=\"bottom\" horizontal=\"end\" *ngIf=\"canEdit && mobile\">\n <ion-fab-button color=\"tertiary\" (click)=\"addRow($event)\">\n <ion-icon name=\"add\"></ion-icon>\n </ion-fab-button>\n</ion-fab>\n", styles: [".table-container .mat-mdc-table{--mat-column-actions-min-width: 62px;--mat-column-actions-max-width: 62px}.table-container .mat-mdc-table .mat-row-selected{padding:3px}.table-container .mat-mdc-table .mat-column-select{min-width:30px}.table-container .mat-mdc-table .mat-column-id{min-width:30px;max-width:30px}.table-container .mat-mdc-table .mat-column-label,.table-container .mat-mdc-table .mat-column-name,.table-container .mat-mdc-table .mat-column-levelId,.table-container .mat-mdc-table .mat-column-statusId{min-width:150px}.table-container .mat-mdc-table .mat-column-comments{min-width:100px;max-width:100px}.table-container .mat-mdc-table .mat-column-updateDate{min-width:110px;max-width:110px}\n"], dependencies: [{ kind: "directive", type: i3.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i2$1.IonButton, selector: "ion-button", inputs: ["buttonType", "color", "disabled", "download", "expand", "fill", "form", "href", "mode", "rel", "routerAnimation", "routerDirection", "shape", "size", "strong", "target", "type"] }, { kind: "component", type: i2$1.IonButtons, selector: "ion-buttons", inputs: ["collapse"] }, { kind: "component", type: i2$1.IonCol, selector: "ion-col", inputs: ["offset", "offsetLg", "offsetMd", "offsetSm", "offsetXl", "offsetXs", "pull", "pullLg", "pullMd", "pullSm", "pullXl", "pullXs", "push", "pushLg", "pushMd", "pushSm", "pushXl", "pushXs", "size", "sizeLg", "sizeMd", "sizeSm", "sizeXl", "sizeXs"] }, { kind: "component", type: i2$1.IonContent, selector: "ion-content", inputs: ["color", "forceOverscroll", "fullscreen", "scrollEvents", "scrollX", "scrollY"] }, { kind: "component", type: i2$1.IonFab, selector: "ion-fab", inputs: ["activated", "edge", "horizontal", "vertical"] }, { kind: "component", type: i2$1.IonFabButton, selector: "ion-fab-button", inputs: ["activated", "closeIcon", "color", "disabled", "download", "href", "mode", "rel", "routerAnimation", "routerDirection", "show", "size", "target", "translucent", "type"] }, { kind: "component", type: i2$1.IonFooter, selector: "ion-footer", inputs: ["collapse", "mode", "translucent"] }, { kind: "component", type: i2$1.IonGrid, selector: "ion-grid", inputs: ["fixed"] }, { kind: "component", type: i2$1.IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: i2$1.IonInfiniteScroll, selector: "ion-infinite-scroll", inputs: ["disabled", "position", "threshold"] }, { kind: "component", type: i2$1.IonInfiniteScrollContent, selector: "ion-infinite-scroll-content", inputs: ["loadingSpinner", "loadingText"] }, { kind: "component", type: i2$1.IonItem, selector: "ion-item", inputs: ["button", "color", "counter", "counterFormatter", "detail", "detailIcon", "disabled", "download", "fill", "href", "lines", "mode", "rel", "routerAnimation", "routerDirection", "shape", "target", "type"] }, { kind: "component", type: i2$1.IonLabel, selector: "ion-label", inputs: ["color", "mode", "position"] }, { kind: "component", type: i2$1.IonRefresher, selector: "ion-refresher", inputs: ["closeDuration", "disabled", "mode", "pullFactor", "pullMax", "pullMin", "snapbackDuration"] }, { kind: "component", type: i2$1.IonRefresherContent, selector: "ion-refresher-content", inputs: ["pullingIcon", "pullingText", "refreshingSpinner", "refreshingText"] }, { kind: "component", type: i2$1.IonRow, selector: "ion-row" }, { kind: "component", type: i2$1.IonSkeletonText, selector: "ion-skeleton-text", inputs: ["animated"] }, { kind: "component", type: i2$1.IonText, selector: "ion-text", inputs: ["color", "mode"] }, { kind: "component", type: i2$1.IonTitle, selector: "ion-title", inputs: ["color", "size"] }, { kind: "directive", type: i1$1.TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }, { kind: "directive", type: i1$3.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$3.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: i1$3.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1$3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$3.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$3.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1$3.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$3.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$3.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i6$5.CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "component", type: i1$6.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i1$6.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i1$6.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i1$6.MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: i1$6.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i1$6.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i1$6.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i1$6.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "component", type: i1$6.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i1$6.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "directive", type: i8$2.MatSort, selector: "[matSort]", inputs: ["matSortActive", "matSortStart", "matSortDirection", "matSortDisableClear", "matSortDisabled"], outputs: ["matSortChange"], exportAs: ["matSort"] }, { kind: "component", type: i8$2.MatSortHeader, selector: "[mat-sort-header]", inputs: ["mat-sort-header", "arrowPosition", "start", "disabled", "sortActionDescription", "disableClear"], exportAs: ["matSortHeader"] }, { kind: "component", type: i9$3.MatPaginator, selector: "mat-paginator", inputs: ["color", "pageIndex", "length", "pageSize", "pageSizeOptions", "hidePageSize", "showFirstLastButtons", "selectConfig", "disabled"], outputs: ["page"], exportAs: ["matPaginator"] }, { kind: "component", type: i6.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i6.MatLabel, selector: "mat-label" }, { kind: "directive", type: i6.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "directive", type: i6.MatPrefix, selector: "[matPrefix], [matIconPrefix], [matTextPrefix]", inputs: ["matTextPrefix"] }, { kind: "directive", type: i6.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { 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"], exportAs: ["matInput"] }, { kind: "component", type: i5.MatCheckbox, selector: "mat-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { kind: "component", type: i13$3.MatExpansionPanel, selector: "mat-expansion-panel", inputs: ["hideToggle", "togglePosition"], outputs: ["afterExpand", "afterCollapse"], exportAs: ["matExpansionPanel"] }, { kind: "directive", type: i13$3.MatExpansionPanelActionRow, selector: "mat-action-row" }, { kind: "component", type: i6$2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i9.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "component", type: i12.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i2.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "directive", type: i8.MatBadge, selector: "[matBadge]", inputs: ["matBadgeColor", "matBadgeOverlap", "matBadgeDisabled", "matBadgePosition", "matBadge", "matBadgeDescription", "matBadgeSize", "matBadgeHidden"] }, { kind: "directive", type: i1$4.CdkTrapFocus, selector: "[cdkTrapFocus]", inputs: ["cdkTrapFocus", "cdkTrapFocusAutoCapture"], exportAs: ["cdkTrapFocus"] }, { kind: "component", type: MatAutocompleteField, selector: "mat-autocomplete-field", inputs: ["equals", "logPrefix", "formControl", "formControlName", "floatLabel", "label", "appearance", "subscriptSizing", "placeholder", "suggestFn", "required", "hideRequiredMarker", "mobile", "clearable", "debounceTime", "displaySeparator", "displayWith", "displayAttributes", "displayColumnSizes", "displayColumnNames", "highlightAccent", "showAllOnFocus", "showPanelOnFocus", "reloadItemsOnFocus", "clearInvalidValueOnBlur", "autofocus", "config", "i18nPrefix", "noResultMessage", "panelClass", "panelWidth", "disableRipple", "matAutocompletePosition", "multiple", "fetchMoreThreshold", "suggestLengthThreshold", "showLoadingSpinner", "debug", "showSearchBar", "stickySearchBar", "applyImplicitValue", "dropButtonTitle", "clearButtonTitle", "trimSearchText", "splitSearchText", "selectInputContentOnFocus", "selectInputContentOnFocusDelay", "previewImplicitValue", "class", "filter", "readonly", "tabindex", "items"], outputs: ["click", "blur", "focus", "dropButtonClick", "keydown.escape", "keydown.backspace", "keyup.enter", "selectionChange"] }, { kind: "component", type: MatLatLongField, selector: "mat-latlong-field", inputs: ["formControl", "formControlName", "type", "latLongPattern", "maxDecimals", "required", "floatLabel", "placeholder", "defaultSign", "autofocus", "mobile", "clearable", "class", "tabindex", "appearance", "readonly", "subscriptSizing"] }, { kind: "component", type: MatDateTime, selector: "mat-date-time-field", inputs: ["placeholder", "floatLabel", "mobile", "compact", "autofocus", "clearable", "startDate", "datePickerFilter", "allowNoTime", "appearance", "subscriptSizing", "formControl", "formControlName", "required", "readonly", "tabindex"] }, { kind: "component", type: MatBooleanField, selector: "mat-boolean-field", inputs: ["disabled", "formControl", "formControlName", "placeholder", "floatLabel", "appearance", "subscriptSizing", "readonly", "required", "compact", "style", "buttonsColCount", "class", "yesLabel", "noLabel", "showButtonIcons", "yesIcon", "noIcon", "clearable", "labelPosition", "tabindex", "showRadio", "value"], outputs: ["keyup.enter", "focus", "blur"] }, { kind: "directive", type: AutofocusDirective, selector: "[autofocus], input[appAutofocus]", inputs: ["appAutofocus", "autofocusDelay"] }, { kind: "directive", type: AutoTitleDirective, selector: "[appAutoTitle]" }, { kind: "component", type: ToolbarComponent, selector: "app-toolbar", inputs: ["progressBarMode", "title", "color", "class", "backHref", "defaultBackHref", "hasValidate", "hasClose", "hasSearch", "canGoBack", "canShowMenu"], outputs: ["onValidate", "onClose", "onValidateAndClose", "onBackClick", "onSearch"] }, { kind: "component", type: FormButtonsBarComponent, selector: "app-form-buttons-bar", inputs: ["disabled", "disabledCancel", "disabledEscape", "classList", "saveButtonColor", "backText", "cancelText", "nextText", "showBack", "showCancel", "showNext", "showSave"], outputs: ["onCancel", "onSave", "onNext", "onBack", "onSaveAndClose", "onSaveAndNext"] }, { kind: "component", type: NavActionsColumnComponent, selector: "app-nav-actions-column", inputs: ["appTable", "matColumnDef", "style", "stickyEnd", "showPending", "dirtyIcon", "optionsTitle", "class", "cellTemplate", "throttleTime"], outputs: ["optionsClick"] }, { kind: "directive", type: i1$3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: ResizableComponent, selector: "th[resizable]", inputs: ["resizable"], outputs: ["sizeChanged"] }, { kind: "directive", type: ResizableDirective, selector: "[resizable]", outputs: ["resizable", "fit"] }, { kind: "pipe", type: i3.AsyncPipe, name: "async" }, { kind: "pipe", type: i1$1.TranslatePipe, name: "translate" }, { kind: "pipe", type: DateFormatPipe, name: "dateFormat" }, { kind: "pipe", type: LatitudeFormatPipe, name: "latitudeFormat" }, { kind: "pipe", type: NumberFormatPipe, name: "numberFormat" }, { kind: "pipe", type: ArrayLengthPipe, name: "isArrayLength" }, { kind: "pipe", type: FormGetControlPipe, name: "formGetControl" }, { kind: "pipe", type: FormGetValuePipe, name: "formGetValue" }, { kind: "pipe", type: IsSelectedPipe, name: "isSelected" }, { kind: "pipe", type: IsEmptySelectionPipe, name: "isEmptySelection" }, { kind: "pipe", type: IsMultipleSelectionPipe, name: "isMultipleSelection" }, { kind: "pipe", type: IsAllSelectedPipe, name: "isAllSelected" }, { kind: "pipe", type: IsNotAllSelectedPipe, name: "isNotAllSelected" }, { kind: "pipe", type: ReferentialToStringPipe, name: "referentialToString" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
45076
+ ], viewQueries: [{ propertyName: "filterExpansionPanel", first: true, predicate: MatExpansionPanel, descendants: true, static: true }, { propertyName: "infiniteScroll", first: true, predicate: IonInfiniteScroll, descendants: true }], usesInheritance: true, ngImport: i0, template: "<app-toolbar\n color=\"primary\"\n [canGoBack]=\"true\"\n [hasValidate]=\"(loadingSubject | async) !== true && (dirtySubject | async) === true\"\n (onValidate)=\"save()\"\n [backHref]=\"'/testing'\"\n>\n <ion-title>Table (click to edit)</ion-title>\n <ion-buttons slot=\"end\">\n @if (selection | isEmptySelection) {\n <input matInput type=\"number\" step=\"1\" style=\"color: black; width: 50px\" [(ngModel)]=\"rowHeight\" />\n\n <!-- Add -->\n <button mat-icon-button *ngIf=\"canEdit && !mobile\" [title]=\"'COMMON.BTN_ADD' | translate\" (click)=\"addRow()\">\n <mat-icon>add</mat-icon>\n </button>\n\n <!-- reset filter -->\n <button mat-icon-button (click)=\"resetFilter()\" *ngIf=\"filterCriteriaCount\">\n <mat-icon color=\"accent\">filter_list_alt</mat-icon>\n <mat-icon class=\"icon-secondary\" style=\"left: 16px; top: 5px; font-weight: bold\">close</mat-icon>\n </button>\n\n <!-- show filter -->\n <button mat-icon-button (click)=\"filterExpansionPanel.toggle()\">\n <mat-icon\n *ngIf=\"filterCriteriaCount; else emptyFilter\"\n [matBadge]=\"filterCriteriaCount\"\n matBadgeColor=\"accent\"\n matBadgeSize=\"small\"\n matBadgePosition=\"above after\"\n aria-hidden=\"false\"\n >\n filter_list_alt\n </mat-icon>\n <ng-template #emptyFilter>\n <mat-icon>filter_list_alt</mat-icon>\n </ng-template>\n </button>\n\n <!-- save -->\n <button mat-icon-button *ngIf=\"mobile\" [disabled]=\"(dirtySubject | async) !== true\" (click)=\"save()\">\n <mat-icon>save</mat-icon>\n </button>\n\n <!-- start/stop timer to auto-load data -->\n <ion-button *ngIf=\"!timer\" (click)=\"startTimer()\">Start reload</ion-button>\n <ion-button *ngIf=\"timer\" (click)=\"stopTimer()\" color=\"accent\">Stop reload</ion-button>\n } @else {\n <!-- if row selection -->\n <!-- delete -->\n <button\n mat-icon-button\n *ngIf=\"canEdit\"\n [title]=\"'COMMON.BTN_DELETE' | translate\"\n (click)=\"deleteSelection($event)\"\n >\n <mat-icon>delete</mat-icon>\n </button>\n\n <!-- duplicate -->\n <button\n mat-icon-button\n *ngIf=\"canEdit && selection.selected | isArrayLength: { equals: 1 }\"\n [title]=\"'COMMON.BTN_DUPLICATE' | translate\"\n (click)=\"duplicateRow($event, selection.selected[0])\"\n >\n <mat-icon>file_copy</mat-icon>\n </button>\n }\n </ion-buttons>\n</app-toolbar>\n<ion-content class=\"ion-no-padding\">\n <ion-refresher slot=\"fixed\" *ngIf=\"mobile\" (ionRefresh)=\"doRefresh($event)\">\n <ion-refresher-content></ion-refresher-content>\n </ion-refresher>\n\n <!-- error -->\n <ion-item *ngIf=\"mobile && error\" lines=\"none\" @slideUpDownAnimation>\n <ion-icon color=\"danger\" slot=\"start\" name=\"alert-circle\"></ion-icon>\n <ion-label color=\"danger\" class=\"error\" [innerHTML]=\"error | translate\"></ion-label>\n </ion-item>\n\n <!-- search -->\n <mat-expansion-panel\n #filterExpansionPanel\n class=\"filter-panel\"\n [class.filter-panel-floating]=\"filterPanelFloating\"\n [class.filter-panel-pinned]=\"!filterPanelFloating\"\n >\n <form class=\"form-container ion-padding-top\" [formGroup]=\"filterForm\" (ngSubmit)=\"applyFilterAndClosePanel($event)\">\n <ion-grid>\n <ion-row>\n <ion-col>\n <!-- search text -->\n <mat-form-field>\n <mat-label>{{ 'TABLE.TESTING.SEARCH_TEXT' | translate }}</mat-label>\n <ion-icon matPrefix name=\"search\"></ion-icon>\n <input matInput formControlName=\"searchText\" autocomplete=\"off\" />\n <button\n mat-icon-button\n matSuffix\n tabindex=\"-1\"\n type=\"button\"\n (click)=\"clearControlValue($event, filterForm.controls.searchText)\"\n [hidden]=\"filterForm.controls.searchText.disabled || !filterForm.controls.searchText.value\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n </ion-col>\n </ion-row>\n </ion-grid>\n </form>\n\n <mat-action-row>\n <!-- Counter -->\n <ion-label\n [hidden]=\"(loadingSubject | async) || filterForm.dirty\"\n [color]=\"empty && 'danger'\"\n class=\"ion-padding\"\n >\n {{\n (totalRowCount ? 'COMMON.RESULT_COUNT' : 'COMMON.NO_RESULT')\n | translate\n : {\n count: (totalRowCount | numberFormat)\n }\n }}\n </ion-label>\n\n <div class=\"toolbar-spacer\"></div>\n\n <button\n mat-icon-button\n color=\"accent\"\n *ngIf=\"filterPanelFloating\"\n (click)=\"toggleFilterPanelFloating()\"\n class=\"hidden-xs hidden-sm hidden-md\"\n [title]=\"(filterPanelFloating ? 'COMMON.BTN_EXPAND' : 'COMMON.BTN_HIDE') | translate\"\n >\n <mat-icon>\n <span style=\"transform: rotate(90deg)\">{{ filterPanelFloating ? '&#xbb;' : '&#xab;' }}</span>\n </mat-icon>\n </button>\n\n <!-- Close panel -->\n <ion-button mat-button fill=\"clear\" color=\"dark\" (click)=\"closeFilterPanel()\" [disabled]=\"loadingSubject | async\">\n <ion-text translate>COMMON.BTN_CLOSE</ion-text>\n </ion-button>\n\n <!-- Search button -->\n <ion-button\n mat-button\n [color]=\"filterForm.dirty ? 'tertiary' : 'dark'\"\n [fill]=\"filterForm.dirty ? 'solid' : 'clear'\"\n (click)=\"applyFilterAndClosePanel($event)\"\n >\n <ion-text translate>COMMON.BTN_APPLY</ion-text>\n </ion-button>\n </mat-action-row>\n </mat-expansion-panel>\n\n <!-- table -->\n <div [class.table-container]=\"!enableInfiniteScroll\">\n <table\n #table\n mat-table\n matSort\n matSortDisableClear\n [dataSource]=\"dataSource\"\n [matSortActive]=\"defaultSortBy\"\n [matSortDirection]=\"defaultSortDirection\"\n [trackBy]=\"trackByFn\"\n [style.--mat-row-height]=\"rowHeight + 'px'\"\n >\n <!-- group header cells -->\n <ng-container matColumnDef=\"top-start\" [sticky]=\"sticky\">\n <th mat-header-cell *matHeaderCellDef [class.cdk-visually-hidden]=\"!canEdit\" [attr.colspan]=\"2\">\n <!-- start spacer -->\n </th>\n </ng-container>\n\n <ng-container matColumnDef=\"group-1\">\n <th mat-header-cell *matHeaderCellDef [attr.colspan]=\"3\">\n <ion-label translate>{{ i18nColumnPrefix + 'GROUP_1' }}</ion-label>\n </th>\n </ng-container>\n\n <ng-container matColumnDef=\"group-2\">\n <th mat-header-cell *matHeaderCellDef [attr.colspan]=\"displayedColumns.length - 6\">\n <ion-label translate>{{ i18nColumnPrefix + 'GROUP_2' }}</ion-label>\n </th>\n </ng-container>\n\n <ng-container matColumnDef=\"top-end\" [stickyEnd]=\"stickyEnd\">\n <th mat-header-cell *matHeaderCellDef>\n <!-- end spacer -->\n <ion-label></ion-label>\n </th>\n </ng-container>\n\n <ng-container matColumnDef=\"select\" [sticky]=\"sticky\" [class.mat-column-sticky]=\"sticky\">\n <th mat-header-cell *matHeaderCellDef [class.cdk-visually-hidden]=\"!canEdit\">\n @if (selection | isMultipleSelection) {\n <mat-checkbox\n [checked]=\"this | isAllSelected\"\n [indeterminate]=\"this | isNotAllSelected\"\n (change)=\"$event ? masterToggle() : null\"\n ></mat-checkbox>\n }\n </th>\n <td mat-cell *matCellDef=\"let row\" [class.cdk-visually-hidden]=\"!canEdit\">\n <mat-checkbox\n (click)=\"toggleSelectRow($event, row)\"\n [checked]=\"selection | isSelected: row\"\n tabindex=\"-1\"\n ></mat-checkbox>\n </td>\n </ng-container>\n\n <!-- Id column -->\n <ng-container matColumnDef=\"id\" [sticky]=\"sticky\" [class.mat-column-sticky]=\"sticky\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>\n <ion-label>#</ion-label>\n </th>\n <td mat-cell *matCellDef=\"let row\">{{ row.currentData?.id }}</td>\n </ng-container>\n\n <!-- Label column -->\n <ng-container matColumnDef=\"label\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>\n <ion-label translate>TABLE.TESTING.LABEL</ion-label>\n </th>\n <td mat-cell *matCellDef=\"let row\" (click)=\"focusColumn = 'label'\">\n @if (row.editing) {\n <mat-form-field>\n <input\n matInput\n autocomplete=\"off\"\n [formControl]=\"row.validator.controls['label']\"\n [placeholder]=\"'TABLE.TESTING.LABEL' | translate\"\n [appAutofocus]=\"focusColumn === 'label'\"\n [readonly]=\"!row.editing\"\n />\n <mat-error *ngIf=\"row.validator.controls['label'].hasError('required')\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n </mat-form-field>\n } @else {\n <ion-label appAutoTitle>\n {{ row.validator | formGetValue: 'label' }}\n </ion-label>\n }\n </td>\n </ng-container>\n\n <!-- Name column -->\n <ng-container matColumnDef=\"name\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>\n <ion-label translate>TABLE.TESTING.NAME</ion-label>\n </th>\n <td mat-cell *matCellDef=\"let row\" (click)=\"focusColumn = 'name'\">\n @if (row.editing) {\n <mat-form-field>\n <input\n matInput\n [formControl]=\"row.validator?.controls.name\"\n [placeholder]=\"'TABLE.TESTING.NAME' | translate\"\n [appAutofocus]=\"focusColumn === 'name'\"\n />\n <mat-error *ngIf=\"row.validator?.controls.name.hasError('required')\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n </mat-form-field>\n } @else {\n <ion-label appAutoTitle>\n {{ row.validator | formGetValue: 'name' }}\n </ion-label>\n }\n </td>\n </ng-container>\n\n <!-- Level column -->\n <ng-container matColumnDef=\"levelId\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>\n <ion-label translate>TABLE.TESTING.LEVEL_ID</ion-label>\n </th>\n <td mat-cell *matCellDef=\"let row\" (click)=\"focusColumn = 'levelId'\">\n @if (row.editing) {\n <mat-autocomplete-field\n [formControl]=\"row.validator.controls.levelId\"\n [placeholder]=\"'TABLE.TESTING.LEVEL_ID' | translate\"\n floatLabel=\"never\"\n [config]=\"autocompleteFields.level\"\n [readonly]=\"!row.editing\"\n [autofocus]=\"focusColumn === 'levelId'\"\n [required]=\"true\"\n ></mat-autocomplete-field>\n } @else {\n <ion-label appAutoTitle>\n {{ row.validator | formGetValue: 'levelId' | referentialToString: autocompleteFields.level.attributes }}\n </ion-label>\n }\n </td>\n </ng-container>\n\n <!-- Status column -->\n <ng-container matColumnDef=\"statusId\">\n <th mat-header-cell *matHeaderCellDef>\n <span translate>USER.STATUS</span>\n </th>\n <td\n mat-cell\n *matCellDef=\"let row\"\n [class.mat-form-field-disabled]=\"!row.editing\"\n (click)=\"focusColumn = 'statusId'\"\n >\n <mat-form-field>\n <mat-select\n [formControl]=\"row.validator.controls['statusId']\"\n [placeholder]=\"i18nColumnPrefix + 'STATUS_ID' | translate\"\n >\n <mat-option *ngFor=\"let item of statusList\" [value]=\"item.id\">\n <mat-icon><ion-icon [name]=\"item.icon\"></ion-icon></mat-icon>\n <mat-label>{{ item.label | translate }}</mat-label>\n </mat-option>\n </mat-select>\n <mat-error *ngIf=\"row.validator.controls['statusId'].hasError('required')\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n </mat-form-field>\n </td>\n </ng-container>\n\n <!-- Enum column -->\n <!-- NOTE : Never used in table -->\n <!-- <ng-container matColumnDef=\"values\">-->\n <!-- <th mat-header-cell *matHeaderCellDef>-->\n <!-- <span translate>Enums</span>-->\n <!-- </th>-->\n <!-- <td mat-cell *matCellDef=\"let row\" [class.mat-form-field-disabled]=\"!row.editing\">-->\n <!-- <app-form-field-->\n <!-- [formControl]=\"row.validator|formGetControl:'properties.values'\"-->\n <!-- [definition]=\"columnDefinitions['values']\"-->\n <!-- ></app-form-field>-->\n <!-- </td>-->\n <!-- </ng-container>-->\n\n <!-- boolean (as checkbox) -->\n <ng-container matColumnDef=\"boolean\">\n <th mat-header-cell *matHeaderCellDef cdkDrag [resizable]=\"true\">\n <!-- if sortable, wrap the header with a mat-sort-header -->\n <span mat-sort-header>\n <ion-label>Boolean</ion-label>\n </span>\n </th>\n <td mat-cell *matCellDef=\"let row\">\n @if (!readOnly && row.editing) {\n <mat-boolean-field\n floatLabel=\"never\"\n [style]=\"'checkbox'\"\n placeholder=\"Oui/Non\"\n [formControl]=\"row.validator | formGetControl: 'properties.boolean'\"\n [compact]=\"true\"\n ></mat-boolean-field>\n } @else {\n <ion-label appAutoTitle>\n {{ (row.validator | formGetValue: 'properties.boolean') ? '&#x2714;' : '&#x2718;' }}\n </ion-label>\n }\n </td>\n </ng-container>\n\n <!-- date -->\n <ng-container matColumnDef=\"date\">\n <th mat-header-cell *matHeaderCellDef cdkDrag [resizable]=\"true\" class=\"mat-cell-date-time\">\n <!-- if sortable, wrap the header with a mat-sort-header -->\n <span mat-sort-header>\n <ion-label>Date</ion-label>\n </span>\n </th>\n <td mat-cell *matCellDef=\"let row\" class=\"mat-cell-date-time\" (click)=\"focusColumn = 'date'\">\n @if (!readOnly && row.editing) {\n <mat-date-time-field\n floatLabel=\"never\"\n [formControl]=\"row.validator | formGetControl: 'properties.date'\"\n [autofocus]=\"focusColumn === 'date'\"\n placeholder=\"Date/Time\"\n [compact]=\"true\"\n ></mat-date-time-field>\n } @else {\n <ion-label appAutoTitle>\n {{ row.validator | formGetValue: 'properties.date' | dateFormat: { time: true } }}\n </ion-label>\n }\n </td>\n </ng-container>\n\n <!-- latitude -->\n <ng-container matColumnDef=\"latitude\">\n <th mat-header-cell *matHeaderCellDef cdkDrag [resizable]=\"true\">\n <!-- if sortable, wrap the header with a mat-sort-header -->\n <span mat-sort-header>\n <ion-label>Latitude</ion-label>\n </span>\n </th>\n <td mat-cell *matCellDef=\"let row\" (click)=\"focusColumn = 'latitude'\">\n @if (!readOnly && row.editing) {\n <mat-latlong-field\n floatLabel=\"never\"\n [formControl]=\"row.validator | formGetControl: 'properties.latitude'\"\n placeholder=\"Latitude\"\n [latLongPattern]=\"'DDMM'\"\n [type]=\"'latitude'\"\n [autofocus]=\"focusColumn === 'latitude'\"\n ></mat-latlong-field>\n } @else {\n <ion-label appAutoTitle>\n {{ row.validator | formGetValue: 'properties.latitude' | latitudeFormat: { pattern: 'DDMM', placeholderChar: '0' } }}\n </ion-label>\n }\n </td>\n </ng-container>\n\n <!-- Creation date column -->\n <ng-container matColumnDef=\"updateDate\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>\n <ion-label translate>TABLE.TESTING.UPDATE_DATE</ion-label>\n </th>\n <td mat-cell *matCellDef=\"let row\" class=\"mat-form-field-disabled\">\n <ion-text color=\"medium\" *ngIf=\"row.id !== -1\">\n <small>\n {{ row.validator | formGetValue: 'creationDate' | dateFormat: { time: true } }}\n </small>\n </ion-text>\n </td>\n </ng-container>\n\n <!-- Comment column -->\n <ng-container matColumnDef=\"comments\">\n <th mat-header-cell *matHeaderCellDef>\n <ion-label translate>TABLE.TESTING.COMMENTS</ion-label>\n </th>\n <td mat-cell *matCellDef=\"let row\">\n <mat-form-field *ngIf=\"row.editing; else iconComment\">\n <!--<textarea matInput [formControl]=\"row.validator?.controls.comments\"\n [placeholder]=\"'TABLE.TESTING.COMMENTS'|translate\"\n [readonly]=\"!row.editing\"></textarea>-->\n\n <input\n type=\"text\"\n matInput\n [formControl]=\"row.validator?.controls.comments\"\n [placeholder]=\"'TABLE.TESTING.COMMENTS' | translate\"\n [readonly]=\"!row.editing\"\n />\n </mat-form-field>\n\n <ng-template #iconComment>\n <ion-icon\n [color]=\"row.validator?.controls.comments.value ? 'tertiary' : 'medium'\"\n name=\"chatbox\"\n slot=\"icon-only\"\n ></ion-icon>\n </ng-template>\n </td>\n </ng-container>\n\n <!-- Actions column -->\n <app-nav-actions-column\n [stickyEnd]=\"stickyEnd\"\n (optionsClick)=\"openSelectColumnsModal($event)\"\n [cellTemplate]=\"cellInjection\"\n [showPending]=\"true\"\n >\n <!-- cell injection-->\n <ng-template #cellInjection let-row>\n <span *ngIf=\"row.editing && !row.validator.dirty\">-</span>\n </ng-template>\n </app-nav-actions-column>\n\n <tr mat-header-row *matHeaderRowDef=\"groupColumns\"></tr>\n <tr mat-header-row *matHeaderRowDef=\"displayedColumns; sticky: true\"></tr>\n <tr\n mat-row\n *matRowDef=\"let row; columns: displayedColumns\"\n [class.mat-mdc-row-selected]=\"row.editing\"\n [class.mat-mdc-row-error]=\"row.invalid\"\n [class.mat-mdc-row-disabled]=\"!row.editing\"\n [class.mat-mdc-row-dirty]=\"row.dirty\"\n (click)=\"clickRow($event, row)\"\n (keydown.escape)=\"escapeEditingRow($event)\"\n [cdkTrapFocus]=\"row.invalid\"\n ></tr>\n </table>\n\n <ng-container *ngIf=\"loadingSubject | async; else noResult\">\n <ion-item>\n <ion-skeleton-text animated></ion-skeleton-text>\n </ion-item>\n </ng-container>\n\n <ng-template #noResult>\n <ion-item *ngIf=\"totalRowCount === 0\">\n <ion-text color=\"danger\" class=\"text-italic\" translate>COMMON.NO_RESULT</ion-text>\n </ion-item>\n </ng-template>\n\n <ion-infinite-scroll\n *ngIf=\"enableInfiniteScroll\"\n [threshold]=\"mobile ? '10%' : '2%'\"\n position=\"bottom\"\n (ionInfinite)=\"fetchMore($event)\"\n >\n <ion-infinite-scroll-content\n loadingSpinner=\"circles\"\n [loadingText]=\"'COMMON.LOADING_DOTS' | translate\"\n ></ion-infinite-scroll-content>\n </ion-infinite-scroll>\n </div>\n</ion-content>\n\n<ion-footer>\n <!-- Paginator -->\n <mat-paginator\n *ngIf=\"!enableInfiniteScroll\"\n [length]=\"totalRowCount\"\n [pageSize]=\"defaultPageSize\"\n [pageSizeOptions]=\"defaultPageSizeOptions\"\n showFirstLastButtons\n ></mat-paginator>\n\n <app-form-buttons-bar\n *ngIf=\"canEdit && !mobile\"\n (onCancel)=\"load()\"\n (onSave)=\"save()\"\n [disabled]=\"(loadingSubject | async) || !dirty\"\n >\n <!-- error -->\n <ion-item *ngIf=\"error$ | async\" lines=\"none\">\n <ion-icon color=\"danger\" slot=\"start\" name=\"alert-circle\"></ion-icon>\n <ion-label color=\"danger\" [innerHTML]=\"error | translate\"></ion-label>\n </ion-item>\n </app-form-buttons-bar>\n</ion-footer>\n\n<ion-fab slot=\"fixed\" vertical=\"bottom\" horizontal=\"end\" *ngIf=\"canEdit && mobile\">\n <ion-fab-button color=\"tertiary\" (click)=\"addRow($event)\">\n <ion-icon name=\"add\"></ion-icon>\n </ion-fab-button>\n</ion-fab>\n", styles: [".table-container .mat-mdc-table{--mat-column-actions-min-width: 62px;--mat-column-actions-max-width: 62px}.table-container .mat-mdc-table .mat-row-selected{padding:3px}.table-container .mat-mdc-table .mat-column-select{min-width:30px}.table-container .mat-mdc-table .mat-column-id{min-width:30px;max-width:30px}.table-container .mat-mdc-table .mat-column-label,.table-container .mat-mdc-table .mat-column-name,.table-container .mat-mdc-table .mat-column-levelId,.table-container .mat-mdc-table .mat-column-statusId{min-width:150px}.table-container .mat-mdc-table .mat-column-comments{min-width:100px;max-width:100px}.table-container .mat-mdc-table .mat-column-updateDate{min-width:110px;max-width:110px}\n"], dependencies: [{ kind: "directive", type: i3.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i2$1.IonButton, selector: "ion-button", inputs: ["buttonType", "color", "disabled", "download", "expand", "fill", "form", "href", "mode", "rel", "routerAnimation", "routerDirection", "shape", "size", "strong", "target", "type"] }, { kind: "component", type: i2$1.IonButtons, selector: "ion-buttons", inputs: ["collapse"] }, { kind: "component", type: i2$1.IonCol, selector: "ion-col", inputs: ["offset", "offsetLg", "offsetMd", "offsetSm", "offsetXl", "offsetXs", "pull", "pullLg", "pullMd", "pullSm", "pullXl", "pullXs", "push", "pushLg", "pushMd", "pushSm", "pushXl", "pushXs", "size", "sizeLg", "sizeMd", "sizeSm", "sizeXl", "sizeXs"] }, { kind: "component", type: i2$1.IonContent, selector: "ion-content", inputs: ["color", "forceOverscroll", "fullscreen", "scrollEvents", "scrollX", "scrollY"] }, { kind: "component", type: i2$1.IonFab, selector: "ion-fab", inputs: ["activated", "edge", "horizontal", "vertical"] }, { kind: "component", type: i2$1.IonFabButton, selector: "ion-fab-button", inputs: ["activated", "closeIcon", "color", "disabled", "download", "href", "mode", "rel", "routerAnimation", "routerDirection", "show", "size", "target", "translucent", "type"] }, { kind: "component", type: i2$1.IonFooter, selector: "ion-footer", inputs: ["collapse", "mode", "translucent"] }, { kind: "component", type: i2$1.IonGrid, selector: "ion-grid", inputs: ["fixed"] }, { kind: "component", type: i2$1.IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: i2$1.IonInfiniteScroll, selector: "ion-infinite-scroll", inputs: ["disabled", "position", "threshold"] }, { kind: "component", type: i2$1.IonInfiniteScrollContent, selector: "ion-infinite-scroll-content", inputs: ["loadingSpinner", "loadingText"] }, { kind: "component", type: i2$1.IonItem, selector: "ion-item", inputs: ["button", "color", "counter", "counterFormatter", "detail", "detailIcon", "disabled", "download", "fill", "href", "lines", "mode", "rel", "routerAnimation", "routerDirection", "shape", "target", "type"] }, { kind: "component", type: i2$1.IonLabel, selector: "ion-label", inputs: ["color", "mode", "position"] }, { kind: "component", type: i2$1.IonRefresher, selector: "ion-refresher", inputs: ["closeDuration", "disabled", "mode", "pullFactor", "pullMax", "pullMin", "snapbackDuration"] }, { kind: "component", type: i2$1.IonRefresherContent, selector: "ion-refresher-content", inputs: ["pullingIcon", "pullingText", "refreshingSpinner", "refreshingText"] }, { kind: "component", type: i2$1.IonRow, selector: "ion-row" }, { kind: "component", type: i2$1.IonSkeletonText, selector: "ion-skeleton-text", inputs: ["animated"] }, { kind: "component", type: i2$1.IonText, selector: "ion-text", inputs: ["color", "mode"] }, { kind: "component", type: i2$1.IonTitle, selector: "ion-title", inputs: ["color", "size"] }, { kind: "directive", type: i1$1.TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }, { kind: "directive", type: i1$3.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$3.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: i1$3.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1$3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$3.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$3.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1$3.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$3.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$3.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i6$4.CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "component", type: i1$6.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i1$6.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i1$6.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i1$6.MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: i1$6.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i1$6.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i1$6.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i1$6.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "component", type: i1$6.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i1$6.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "directive", type: i8$2.MatSort, selector: "[matSort]", inputs: ["matSortActive", "matSortStart", "matSortDirection", "matSortDisableClear", "matSortDisabled"], outputs: ["matSortChange"], exportAs: ["matSort"] }, { kind: "component", type: i8$2.MatSortHeader, selector: "[mat-sort-header]", inputs: ["mat-sort-header", "arrowPosition", "start", "disabled", "sortActionDescription", "disableClear"], exportAs: ["matSortHeader"] }, { kind: "component", type: i9$3.MatPaginator, selector: "mat-paginator", inputs: ["color", "pageIndex", "length", "pageSize", "pageSizeOptions", "hidePageSize", "showFirstLastButtons", "selectConfig", "disabled"], outputs: ["page"], exportAs: ["matPaginator"] }, { kind: "component", type: i6.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i6.MatLabel, selector: "mat-label" }, { kind: "directive", type: i6.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "directive", type: i6.MatPrefix, selector: "[matPrefix], [matIconPrefix], [matTextPrefix]", inputs: ["matTextPrefix"] }, { kind: "directive", type: i6.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { 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"], exportAs: ["matInput"] }, { kind: "component", type: i5.MatCheckbox, selector: "mat-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { kind: "component", type: i13$3.MatExpansionPanel, selector: "mat-expansion-panel", inputs: ["hideToggle", "togglePosition"], outputs: ["afterExpand", "afterCollapse"], exportAs: ["matExpansionPanel"] }, { kind: "directive", type: i13$3.MatExpansionPanelActionRow, selector: "mat-action-row" }, { kind: "component", type: i6$2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i9.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "component", type: i12.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i2.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "directive", type: i8.MatBadge, selector: "[matBadge]", inputs: ["matBadgeColor", "matBadgeOverlap", "matBadgeDisabled", "matBadgePosition", "matBadge", "matBadgeDescription", "matBadgeSize", "matBadgeHidden"] }, { kind: "directive", type: i1$4.CdkTrapFocus, selector: "[cdkTrapFocus]", inputs: ["cdkTrapFocus", "cdkTrapFocusAutoCapture"], exportAs: ["cdkTrapFocus"] }, { kind: "component", type: MatAutocompleteField, selector: "mat-autocomplete-field", inputs: ["equals", "logPrefix", "formControl", "formControlName", "floatLabel", "label", "appearance", "subscriptSizing", "placeholder", "suggestFn", "required", "hideRequiredMarker", "mobile", "clearable", "debounceTime", "displaySeparator", "displayWith", "displayAttributes", "displayColumnSizes", "displayColumnNames", "highlightAccent", "showAllOnFocus", "showPanelOnFocus", "reloadItemsOnFocus", "clearInvalidValueOnBlur", "autofocus", "config", "i18nPrefix", "noResultMessage", "panelClass", "panelWidth", "disableRipple", "matAutocompletePosition", "multiple", "fetchMoreThreshold", "suggestLengthThreshold", "showLoadingSpinner", "debug", "showSearchBar", "stickySearchBar", "applyImplicitValue", "dropButtonTitle", "clearButtonTitle", "trimSearchText", "splitSearchText", "selectInputContentOnFocus", "selectInputContentOnFocusDelay", "previewImplicitValue", "class", "filter", "readonly", "tabindex", "items"], outputs: ["click", "blur", "focus", "dropButtonClick", "keydown.escape", "keydown.backspace", "keyup.enter", "selectionChange"] }, { kind: "component", type: MatLatLongField, selector: "mat-latlong-field", inputs: ["formControl", "formControlName", "type", "latLongPattern", "maxDecimals", "required", "floatLabel", "placeholder", "defaultSign", "autofocus", "mobile", "clearable", "class", "tabindex", "appearance", "readonly", "subscriptSizing"] }, { kind: "component", type: MatDateTime, selector: "mat-date-time-field", inputs: ["placeholder", "floatLabel", "mobile", "compact", "autofocus", "clearable", "startDate", "datePickerFilter", "allowNoTime", "appearance", "subscriptSizing", "formControl", "formControlName", "required", "readonly", "tabindex"] }, { kind: "component", type: MatBooleanField, selector: "mat-boolean-field", inputs: ["disabled", "formControl", "formControlName", "placeholder", "floatLabel", "appearance", "subscriptSizing", "readonly", "required", "compact", "style", "buttonsColCount", "class", "yesLabel", "noLabel", "showButtonIcons", "yesIcon", "noIcon", "clearable", "labelPosition", "tabindex", "showRadio", "value"], outputs: ["keyup.enter", "focus", "blur"] }, { kind: "directive", type: AutofocusDirective, selector: "[autofocus], input[appAutofocus]", inputs: ["appAutofocus", "autofocusDelay"] }, { kind: "directive", type: AutoTitleDirective, selector: "[appAutoTitle]" }, { kind: "component", type: ToolbarComponent, selector: "app-toolbar", inputs: ["progressBarMode", "title", "color", "class", "backHref", "defaultBackHref", "hasValidate", "hasClose", "hasSearch", "canGoBack", "canShowMenu"], outputs: ["onValidate", "onClose", "onValidateAndClose", "onBackClick", "onSearch"] }, { kind: "component", type: FormButtonsBarComponent, selector: "app-form-buttons-bar", inputs: ["disabled", "disabledCancel", "disabledEscape", "classList", "saveButtonColor", "backText", "cancelText", "nextText", "showBack", "showCancel", "showNext", "showSave"], outputs: ["onCancel", "onSave", "onNext", "onBack", "onSaveAndClose", "onSaveAndNext"] }, { kind: "component", type: NavActionsColumnComponent, selector: "app-nav-actions-column", inputs: ["appTable", "matColumnDef", "style", "stickyEnd", "showPending", "dirtyIcon", "optionsTitle", "class", "cellTemplate", "throttleTime"], outputs: ["optionsClick"] }, { kind: "directive", type: i1$3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: ResizableComponent, selector: "th[resizable]", inputs: ["resizable"], outputs: ["sizeChanged"] }, { kind: "directive", type: ResizableDirective, selector: "[resizable]", outputs: ["resizable", "fit"] }, { kind: "pipe", type: i3.AsyncPipe, name: "async" }, { kind: "pipe", type: i1$1.TranslatePipe, name: "translate" }, { kind: "pipe", type: DateFormatPipe, name: "dateFormat" }, { kind: "pipe", type: LatitudeFormatPipe, name: "latitudeFormat" }, { kind: "pipe", type: NumberFormatPipe, name: "numberFormat" }, { kind: "pipe", type: ArrayLengthPipe, name: "isArrayLength" }, { kind: "pipe", type: FormGetControlPipe, name: "formGetControl" }, { kind: "pipe", type: FormGetValuePipe, name: "formGetValue" }, { kind: "pipe", type: IsSelectedPipe, name: "isSelected" }, { kind: "pipe", type: IsEmptySelectionPipe, name: "isEmptySelection" }, { kind: "pipe", type: IsMultipleSelectionPipe, name: "isMultipleSelection" }, { kind: "pipe", type: IsAllSelectedPipe, name: "isAllSelected" }, { kind: "pipe", type: IsNotAllSelectedPipe, name: "isNotAllSelected" }, { kind: "pipe", type: ReferentialToStringPipe, name: "referentialToString" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
44985
45077
  }
44986
45078
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: TableTestPage, decorators: [{
44987
45079
  type: Component,
@@ -46006,5 +46098,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImpo
46006
46098
  * Generated bundle index. Do not edit.
46007
46099
  */
46008
46100
 
46009
- export { APP_ABOUT_DEVELOPERS, APP_ABOUT_PARTNERS, APP_CONFIG_OPTIONS, APP_DEBUG_DATA_SERVICE, APP_FORM_ERROR_I18N_KEYS, APP_GRAPHQL_FRAGMENTS, APP_GRAPHQL_TYPE_POLICIES, APP_HOME_BUTTONS, APP_HOTKEYS_CONFIG, APP_JOB_PROGRESSION_SERVICE, APP_LOCALES, APP_LOCAL_SETTINGS, APP_LOCAL_SETTINGS_OPTIONS, APP_LOCAL_STORAGE_TYPE_POLICIES, APP_LOGGING_SERVICE, APP_MENU_ITEMS, APP_MENU_OPTIONS, APP_NAMED_FILTER_SERVICE, APP_PROGRESS_BAR_SERVICE, APP_SETTINGS_MENU_ITEMS, APP_STORAGE, APP_STORAGE_EXPLORER_PROTECTED_KEYS, APP_TESTING_PAGES, APP_USER_EVENT_LIST_INFINITE_SCROLL_THRESHOLD, APP_USER_EVENT_SERVICE, APP_USER_SETTINGS_OPTIONS, APP_USER_TOKEN_SCOPES, AboutModal, AbstractNamedFilterService, AbstractSelectionModelPipe, AbstractTableSelectionPipe, AbstractUserEventService, Account, AccountPage, AccountService, AccountToStringPipe, AccountUtils, ActionsColumnComponent, AdminModule, AdminRoutingModule, AdminUsersModule, Alerts, AndroidOsEnvironment, AppAboutModalModule, AppAccountModule, AppAsyncTable, AppAuthForm, AppAuthModal, AppAuthModule, AppChangePasswordModule, AppChangePasswordPage, AppEditor, AppEditorOptions, AppEntityEditor, AppEntityEditorModal, AppEntityEditorModalOptions, AppEntityFormModule, AppForm, AppFormArray, AppFormButtonsBarModule, AppFormContainer, AppFormField, AppFormModule, AppFormProvider, AppFormUtils, AppGestureConfig, AppGraphQLModule, AppHelpModal, AppHomePageModule, AppIconComponent, AppIconModule, AppImageGalleryComponent, AppInMemoryTable, AppInstallUpgradeCard, AppInstallUpgradeCardModule, AppListForm, AppListFormModule, AppLoadingSpinner, AppMenuModule, AppNullForm, AppPropertiesForm, AppPropertiesFormModule, AppPropertiesTable, AppPropertiesUtils, AppPropertyUtils, AppRegisterModule, AppResetPasswordModal, AppRowField, AppSelectPeerModule, AppSettingsPageModule, AppTabEditor, AppTabEditorOptions, AppTable, AppTableModule, AppTableUtils, AppTextPopoverModule, AppUpdateOfflineModeCard, AppUpdateOfflineModeCardModule, AppValidatorService, ArrayFilterPipe, ArrayFirstPipe, ArrayFormTestPage, ArrayIncludesPipe, ArrayJoinPipe, ArrayLastPipe, ArrayLengthPipe, ArrayPluckPipe, AsAnyPipe, AsArrayPipe, AsBooleanPipe, AsFloatLabelTypePipe, AsObservablePipe, AudioProvider, AudioTestingModule, AudioTestingPage, AuthGuardService, AutoTitleDirective, AutocompleteTestPage, AutofocusDirective, BadgeDirective, BadgeNumberPipe, Base58, BaseEntityService, BaseGraphqlService, BaseGraphqlServiceOptions, BaseReferential, Beans, BooleanFormatPipe, BooleanTestPage, CORE_CONFIG_OPTIONS, CORE_TESTING_PAGES, CapitalizePipe, CellValueChangeListener, ChangePasswordForm, ChipsTestPage, Color, ColorScale, ComponentDirtyGuard, ConfigFragments, ConfigService, Configuration, CoreModule, CorePipesModule, CoreTestingModule, CryptoService, CsvUtils, DATE_ISO_PATTERN, DATE_MATCH_REGEXP, DATE_PATTERN, DATE_UNIX_MS_TIMESTAMP, DATE_UNIX_TIMESTAMP, DEFAULT_JOIN_ARRAY_VALUES_SEPARATOR, DEFAULT_JOIN_PROPERTIES_SEPARATOR, DEFAULT_MENU_SHOW_WHEN, DEFAULT_PAGE_SIZE, DEFAULT_PAGE_SIZE_OPTIONS, DEFAULT_PLACEHOLDER_CHAR, DEFAULT_REQUIRED_COLUMNS, DateDiffDurationPipe, DateFormatPipe, DateFormatService, DateFromNowPipe, DateShortTestPage, DateTestPage, DateTimeTestPage, DateUtils, DebugComponent, Department, DepartmentToStringPipe, DisplayWithPipe, DragAndDropDirective, DurationPipe, DurationTestPage, ED25519_SEED_LENGTH, EMPTY_PLACEHOLDER_CHAR, EMPTY_PLACEHOLDER_CHAR_REGEXP_GLOBAL, ENTITIES_STORAGE_KEY_PREFIX, ENVIRONMENT, EmptyArrayPipe, EntitiesAsyncTableDataSource, EntitiesStorage, EntitiesTableDataSource, Entity, EntityClass, EntityClasses, EntityFilter, EntityFilterUtils, EntityMetadataComponent, EntityStore, EntityUtils, Environment, EnvironmentHttpLoader, EnvironmentLoader, ErrorCodes, EvenPipe, FileResponse, FileService, FileSizePipe, FilesUtils, FormArrayHelper, FormArrayTestModule, FormButtonsBarComponent, FormButtonsBarToken, FormErrorPipe, FormErrorTranslatePipe, FormErrorTranslator, FormFieldDefinitionUtils, FormFieldValuesHolder, FormGetArrayPipe, FormGetControlPipe, FormGetGroupPipe, FormGetPipe, FormGetValuePipe, GalleryTestPage, GeolocationUtils, GraphqlService, HAMMER_PRESS_TIME, HAMMER_TAP_TIME, HighlightPipe, HomePage, Hotkeys, HotkeysDialogComponent, IMAGE_DEFAULTS, IPosition, ImageAttachment, ImageAttachmentFilter, ImageAttachmentService, ImageGalleryModule, ImageGalleryTestingModule, ImageModule, ImageService, ImagesUtils, InMemoryEntitiesService, IsAllSelectedPipe, IsEmptySelectionPipe, IsLoginAccountPipe, IsMultipleSelectionPipe, IsNilOrBlankPipe, IsNilOrNaNPipe, IsNilPipe, IsNotAllSelectedPipe, IsNotEmptySelectionPipe, IsNotNilOrBlankPipe, IsNotNilOrNaNPipe, IsNotNilPipe, IsOnDeskPipe, IsOnFieldPipe, IsSelectedPipe, IsSingleSelectionPipe, IsValidDatePipe, JobModule, JobProgression, JobProgressionComponent, JobProgressionIcon, JobProgressionList, JobProgressionService, JobProgressionTestService, JobProgressionTestingPage, JobTestingModule, JobUtils, JsonUtils, KEYBOARD_HIDE_DELAY_MS, LAT_LONG_PATTERNS, LAT_LONG_PATTERN_MAX_DECIMALS, LAT_LONG_VALUE_MAX_DECIMALS, LatLongFormatPipe, LatLongTestPage, LatitudeFormatPipe, LocalSettingsService, LogLevel, LogUtils, Logger, LoggingService, LoggingServiceModule, LongitudeFormatPipe, MASKS, MASK_RANGES, MAT_FORM_FIELD_DEFAULT_APPEARANCE, MAT_FORM_FIELD_DEFAULT_SUBSCRIPT_SIZING, MINIFY_ENTITY_FOR_LOCAL_STORAGE, MINIFY_ENTITY_FOR_POD, MOMENT_NO_TIME_PROPERTY, MapGetPipe, MapKeysPipe, MapValuesPipe, MaskitoPlaceholderPipe, MaskitoTestPage, MatAutocompleteConfigHolder, MatAutocompleteField, MatAutocompleteFieldUtils, MatBadgeTestPage, MatBooleanField, MatChipsField, MatColorPipe, MatCommonTestPage, MatDate, MatDateShort, MatDateTime, MatDuration, MatLatLongField, MatLatLongFieldInput, MatPaginatorI18n, MatStepperI18n, MatSwipeField, MaterialTestingModule, MathAbsPipe, MenuComponent, MenuItem, MenuItems, MenuOptions, MenuService, MenuTestingModule, MenuTestingPage, Message, MessageFilter, MessageForm, MessageModal, MessageModule, MessageService, MessageTypeList, MessageTypes, MimeTypes, ModalToolbarComponent, NETWORK_DEFAULT_CONNECTION_TIMEOUT, NamedFilter, NamedFilterFilter, NamedFilterSelector, NamedFilterSelectorTestingModule, NamedFilterSelectorTestingPage, NavActionsColumnComponent, NetworkService, NewTokenForm, NewTokenModal, NgInitDirective, NgVarDirective, NoHtmlPipe, NotEmptyArrayPipe, NumberFormatPipe, ObservableTestPage, OddPipe, OtherMenuTestingPage, PEER_URL_REGEXP, PLUS_PLACEHOLDER_CHAR_REGEXP_GLOBAL, PRIORITIZED_AUTHORITIES, PUBKEY_REGEXP, Peer, Person, PersonFilter, PersonFragments, PersonService, PersonToStringPipe, PersonUtils, PersonValidatorService, PlatformService, ProgressBarService, ProgressInterceptor, PropertiesFormTestPage, PropertiesFormTestingModule, PropertyEntity, PropertyEntityFilter, PropertyEntityValidator, PropertyFormatPipe, PropertyGetPipe, RESERVED_END_COLUMNS, RESERVED_START_COLUMNS, Referential, ReferentialFilter, ReferentialRef, ReferentialToStringPipe, ReferentialUtils, ReferentialValidatorService, RegExpUtils, RegisterConfirmPage, RegisterForm, RegisterModal, ResizableComponent, ResizableDirective, ResizableModule, RxStateModule, RxStateProperty, RxStateRegister, RxStateSelect, SCRYPT_PARAMS, SETTINGS_DISPLAY_COLUMNS, SETTINGS_FILTER, SETTINGS_PAGE_SIZE, SETTINGS_SORTED_COLUMN, SETTINGS_STORAGE_KEY, SETTINGS_TRANSIENT_PROPERTIES, SHARED_MATERIAL_TESTING_PAGES, SHARED_STORAGE_TESTING_PAGES, SHARED_TESTING_PAGES, SOCIAL_TESTING_PAGES, SPACE_PLACEHOLDER_CHAR, SPACE_PLACEHOLDER_CHAR_REGEXP_GLOBAL, SafeHtmlPipe, SelectPeerModal, SelectionLengthPipe, ServerErrorCodes, SettingsPage, SharedAsyncValidators, SharedBadgeModule, SharedDebugModule, SharedDirectivesModule, SharedFormArrayValidators, SharedFormGroupValidators, SharedHotkeysModule, SharedMatAutocompleteModule, SharedMatBooleanModule, SharedMatChipsModule, SharedMatDateTimeModule, SharedMatDurationModule, SharedMatLatLongModule, SharedMatSwipeModule, SharedMaterialModule, SharedModule, SharedNamedFilterModule, SharedPipesModule, SharedRoutingModule, SharedTestingModule, SharedTestsPage, SharedTextFormModule, SharedToolbarModule, SharedValidators, SocialErrorCodes, SocialModule, SocialModuleOptionsToken, SocialTestingModule, Software, StartableService, StatusById, StatusIds, StatusList, StorageDrivers, StorageExplorerComponent, StorageExplorerModule, StorageExplorerTestingModule, StorageExplorerTestingRoutingModule, StorageService, StrIncludesPipe, StrLengthPipe, SubMenuTabDirective, SwipeTestPage, Table2TestPage, TableSelectColumnsComponent, TableTestPage, TableTestingModule, TableValidatorService, TextForm, TextFormTestingPage, TextPopover, TextPopoverTestingModule, TextPopoverTestingPage, ThrottledClickDirective, ToStringPipe, ToastTestingModule, ToastTestingPage, Toasts, TokenScope, ToolbarComponent, ToolbarToken, TranslatablePipe, TranslateContextPipe, TranslateContextService, TreeItemEntityUtils, UploadFile, UploadFileComponent, UploadFilePopover, UploadFileTestingModule, UploadFileTestingPage, UriUtils, UserEventModule, UserEventNotificationIcon, UserEventNotificationList, UserEventTestService, UserEventTestingModule, UserEventTestingPage, UserSettings, UserToken, UserTokenTable, UsersPage, ValueFormatPipe, accountToString, adaptValueToControl, addValueInArray, arrayDistinct, arrayResize, arraySize, asInputElement, booleanToString, canHaveFocus, capitalizeFirstLetter, chainPromises, changeCaseToUnderscore, clearValueInArray, collectByProperty, computeDecimalDegrees, computeDecimalPart, copyEntity2Form, createPromiseEvent, createPromiseEventEmitter, departmentToString, departmentsToString, disableAndClearControl, disableAndClearControls, disableControl, disableControls, emitPromiseEvent, enableControl, enableControls, enableRxStateProduction, entityToString, equals, equalsOrNil, escapeRegExp, fadeInAnimation, fadeInOutAnimation, fadeInSlowAnimation, filterFalse, filterFormErrors, filterFormErrorsByPath, filterFormErrorsByPrefix, filterNotNil, filterNumberInput, filterTrue, findParentWithClass, firstArrayValue, firstFalse, firstFalsePromise, firstNotNil, firstNotNilPromise, firstTrue, firstTruePromise, focusInput, focusNextInput, focusPreviousInput, formatLatLong, formatLatitude, formatLongitude, fromDateISOString, fromScrollEndEvent, fromUnixMsTimestamp, fromUnixTimestamp, getCaretPosition, getColorContrast, getColorShade, getColorTint, getControlFromPath, getFocusableInputElements, getFormErrors, getFormValueFromEntity, getInputRangeFromCaretIndex, getInputSelectionRangesFromMask, getProperty, getPropertyByPath, getPropertyByPathAsString, getRandomImage, getRandomImageWithCredit, getUserAgent, hexToRgb, hexToRgbArray, initArrayControlsFromValues, intersectArrays, isAndroid, isBlankString, isCapacitor, isChrome, isControlHasInput, isEdge, isEmptyArray, isFirefox, isIOS, isInputElement, isInstanceOf, isInt, isIpad, isMacOS, isMobile, isNil, isNilOrBlank, isNilOrNaN, isNotEmptyArray, isNotNil, isNotNilBoolean, isNotNilObject, isNotNilOrBlank, isNotNilOrNaN, isNotNilString, isNumber, isNumberRange, isOnFieldMode, isProgressEvent, isPromise, isResponseEvent, isSafari, isStartableService, isTouchUi, isWindows, joinProperties, joinPropertiesPath, lastArrayValue, logFormErrors, markAllAsTouched, markAsUntouched, markControlAsTouched, markFormGroupAsTouched, maskitoAutoSelectByMaskPattern, maskitoPrefixPlugin, matchMedia, matchUpperCase, mergeLoadResult, mixHex, moveInputCaretToSeparator, newArray, noHtml, noTrailingSlash, notNilOrDefault, nullIfNilOrBlank, nullIfUndefined, parseLatitudeOrLongitude, propertiesPathComparator, propertyComparator, propertyPathComparator, referentialToString, referentialsToString, remove, removeAll, removeDiacritics, removeDuplicatesFromArray, removeEnd, removeValueInArray, replaceAll, resetCalculatedValue, resizeArray, rgbArrayToHex, rgbToHex, round, scrollFactory, selectInputContent, selectInputContentFromEvent, selectInputRange, setCalculatedValue, setControlEnabled, setControlsEnabled, setPropertyByPath, setTabIndex, sleep, slideInAnimation, slideInOutAnimation, slideUpDownAnimation, sort, splitById, splitByProperty, splitDegreesToDDArray, splitDegreesToDDMMArray, splitDegreesToDDMMSSArray, startsWithUpperCase, suggestFromArray, suggestFromStringArray, tabindexComparator, testUserAgent, toBoolean, toDateISOString, toDuration, toFloat, toInt, toNotNil, toNumber, trimEmptyToNull, uncapitalizeFirstLetter, undefinedIfNull, underscoreToChangeCase, updateValueAndValidity, waitFor, waitForFalse, waitForTrue, waitIdle, waitWhilePending };
46101
+ export { APP_ABOUT_DEVELOPERS, APP_ABOUT_PARTNERS, APP_CONFIG_OPTIONS, APP_DEBUG_DATA_SERVICE, APP_FORM_ERROR_I18N_KEYS, APP_GRAPHQL_FRAGMENTS, APP_GRAPHQL_TYPE_POLICIES, APP_HOME_BUTTONS, APP_HOTKEYS_CONFIG, APP_JOB_PROGRESSION_SERVICE, APP_LOCALES, APP_LOCAL_SETTINGS, APP_LOCAL_SETTINGS_OPTIONS, APP_LOCAL_STORAGE_TYPE_POLICIES, APP_LOGGING_SERVICE, APP_MENU_ITEMS, APP_MENU_OPTIONS, APP_NAMED_FILTER_SERVICE, APP_PROGRESS_BAR_SERVICE, APP_SETTINGS_MENU_ITEMS, APP_STORAGE, APP_STORAGE_EXPLORER_PROTECTED_KEYS, APP_TESTING_PAGES, APP_USER_EVENT_LIST_INFINITE_SCROLL_THRESHOLD, APP_USER_EVENT_SERVICE, APP_USER_SETTINGS_OPTIONS, APP_USER_TOKEN_SCOPES, AboutModal, AbstractNamedFilterService, AbstractSelectionModelPipe, AbstractTableSelectionPipe, AbstractUserEventService, Account, AccountPage, AccountService, AccountToStringPipe, AccountUtils, ActionsColumnComponent, AdminModule, AdminRoutingModule, AdminUsersModule, Alerts, AndroidOsEnvironment, AppAboutModalModule, AppAccountModule, AppAsyncTable, AppAuthForm, AppAuthModal, AppAuthModule, AppChangePasswordModule, AppChangePasswordPage, AppEditor, AppEditorOptions, AppEntityEditor, AppEntityEditorModal, AppEntityEditorModalOptions, AppEntityFormModule, AppForm, AppFormArray, AppFormButtonsBarModule, AppFormContainer, AppFormField, AppFormModule, AppFormProvider, AppFormUtils, AppGestureConfig, AppGraphQLModule, AppHelpModal, AppHelpModalUtils, AppHomePageModule, AppIconComponent, AppIconModule, AppImageGalleryComponent, AppInMemoryTable, AppInstallUpgradeCard, AppInstallUpgradeCardModule, AppListForm, AppListFormModule, AppLoadingSpinner, AppMenuModule, AppNullForm, AppPropertiesForm, AppPropertiesFormModule, AppPropertiesTable, AppPropertiesUtils, AppPropertyUtils, AppRegisterModule, AppResetPasswordModal, AppRowField, AppSelectPeerModule, AppSettingsPageModule, AppTabEditor, AppTabEditorOptions, AppTable, AppTableModule, AppTableUtils, AppTextPopoverModule, AppUpdateOfflineModeCard, AppUpdateOfflineModeCardModule, AppValidatorService, ArrayFilterPipe, ArrayFirstPipe, ArrayFormTestPage, ArrayIncludesPipe, ArrayJoinPipe, ArrayLastPipe, ArrayLengthPipe, ArrayPluckPipe, AsAnyPipe, AsArrayPipe, AsBooleanPipe, AsFloatLabelTypePipe, AsObservablePipe, AudioProvider, AudioTestingModule, AudioTestingPage, AuthGuardService, AutoTitleDirective, AutocompleteTestPage, AutofocusDirective, BadgeDirective, BadgeNumberPipe, Base58, BaseEntityService, BaseGraphqlService, BaseGraphqlServiceOptions, BaseReferential, Beans, BooleanFormatPipe, BooleanTestPage, CORE_CONFIG_OPTIONS, CORE_TESTING_PAGES, CapitalizePipe, CellValueChangeListener, ChangePasswordForm, ChipsTestPage, Color, ColorScale, ComponentDirtyGuard, ConfigFragments, ConfigService, Configuration, CoreModule, CorePipesModule, CoreTestingModule, CryptoService, CsvUtils, DATE_ISO_PATTERN, DATE_MATCH_REGEXP, DATE_PATTERN, DATE_UNIX_MS_TIMESTAMP, DATE_UNIX_TIMESTAMP, DEFAULT_JOIN_ARRAY_VALUES_SEPARATOR, DEFAULT_JOIN_PROPERTIES_SEPARATOR, DEFAULT_MENU_SHOW_WHEN, DEFAULT_PAGE_SIZE, DEFAULT_PAGE_SIZE_OPTIONS, DEFAULT_PLACEHOLDER_CHAR, DEFAULT_REQUIRED_COLUMNS, DateDiffDurationPipe, DateFormatPipe, DateFormatService, DateFromNowPipe, DateShortTestPage, DateTestPage, DateTimeTestPage, DateUtils, DebugComponent, Department, DepartmentToStringPipe, DisplayWithPipe, DragAndDropDirective, DurationPipe, DurationTestPage, ED25519_SEED_LENGTH, EMPTY_PLACEHOLDER_CHAR, EMPTY_PLACEHOLDER_CHAR_REGEXP_GLOBAL, ENTITIES_STORAGE_KEY_PREFIX, ENVIRONMENT, EmptyArrayPipe, EntitiesAsyncTableDataSource, EntitiesStorage, EntitiesTableDataSource, Entity, EntityClass, EntityClasses, EntityFilter, EntityFilterUtils, EntityMetadataComponent, EntityStore, EntityUtils, Environment, EnvironmentHttpLoader, EnvironmentLoader, ErrorCodes, EvenPipe, FileResponse, FileService, FileSizePipe, FilesUtils, FormArrayHelper, FormArrayTestModule, FormButtonsBarComponent, FormButtonsBarToken, FormErrorPipe, FormErrorTranslatePipe, FormErrorTranslator, FormFieldDefinitionUtils, FormFieldValuesHolder, FormGetArrayPipe, FormGetControlPipe, FormGetGroupPipe, FormGetPipe, FormGetValuePipe, GalleryTestPage, GeolocationUtils, GraphqlService, HAMMER_PRESS_TIME, HAMMER_TAP_TIME, HighlightPipe, HomePage, Hotkeys, HotkeysDialogComponent, IMAGE_DEFAULTS, IPosition, ImageAttachment, ImageAttachmentFilter, ImageAttachmentService, ImageGalleryModule, ImageGalleryTestingModule, ImageModule, ImageService, ImagesUtils, InMemoryEntitiesService, IsAllSelectedPipe, IsEmptySelectionPipe, IsLoginAccountPipe, IsMultipleSelectionPipe, IsNilOrBlankPipe, IsNilOrNaNPipe, IsNilPipe, IsNotAllSelectedPipe, IsNotEmptySelectionPipe, IsNotNilOrBlankPipe, IsNotNilOrNaNPipe, IsNotNilPipe, IsOnDeskPipe, IsOnFieldPipe, IsSelectedPipe, IsSingleSelectionPipe, IsValidDatePipe, JobModule, JobProgression, JobProgressionComponent, JobProgressionIcon, JobProgressionList, JobProgressionService, JobProgressionTestService, JobProgressionTestingPage, JobTestingModule, JobUtils, JsonUtils, KEYBOARD_HIDE_DELAY_MS, LAT_LONG_PATTERNS, LAT_LONG_PATTERN_MAX_DECIMALS, LAT_LONG_VALUE_MAX_DECIMALS, LatLongFormatPipe, LatLongTestPage, LatitudeFormatPipe, LocalSettingsService, LogLevel, LogUtils, Logger, LoggingService, LoggingServiceModule, LongitudeFormatPipe, MASKS, MASK_RANGES, MAT_FORM_FIELD_DEFAULT_APPEARANCE, MAT_FORM_FIELD_DEFAULT_SUBSCRIPT_SIZING, MINIFY_ENTITY_FOR_LOCAL_STORAGE, MINIFY_ENTITY_FOR_POD, MOMENT_NO_TIME_PROPERTY, MapGetPipe, MapKeysPipe, MapValuesPipe, MaskitoPlaceholderPipe, MaskitoTestPage, MatAutocompleteConfigHolder, MatAutocompleteField, MatAutocompleteFieldUtils, MatBadgeTestPage, MatBooleanField, MatChipsField, MatColorPipe, MatCommonTestPage, MatDate, MatDateShort, MatDateTime, MatDuration, MatLatLongField, MatLatLongFieldInput, MatPaginatorI18n, MatStepperI18n, MatSwipeField, MaterialTestingModule, MathAbsPipe, MenuComponent, MenuItem, MenuItems, MenuOptions, MenuService, MenuTestingModule, MenuTestingPage, Message, MessageFilter, MessageForm, MessageModal, MessageModule, MessageService, MessageTypeList, MessageTypes, MimeTypes, ModalToolbarComponent, NETWORK_DEFAULT_CONNECTION_TIMEOUT, NamedFilter, NamedFilterFilter, NamedFilterSelector, NamedFilterSelectorTestingModule, NamedFilterSelectorTestingPage, NavActionsColumnComponent, NetworkService, NewTokenForm, NewTokenModal, NgInitDirective, NgVarDirective, NoHtmlPipe, NotEmptyArrayPipe, NumberFormatPipe, ObservableTestPage, OddPipe, OtherMenuTestingPage, PEER_URL_REGEXP, PLUS_PLACEHOLDER_CHAR_REGEXP_GLOBAL, PRIORITIZED_AUTHORITIES, PUBKEY_REGEXP, Peer, Person, PersonFilter, PersonFragments, PersonService, PersonToStringPipe, PersonUtils, PersonValidatorService, PlatformService, ProgressBarService, ProgressInterceptor, PropertiesFormTestPage, PropertiesFormTestingModule, PropertyEntity, PropertyEntityFilter, PropertyEntityValidator, PropertyFormatPipe, PropertyGetPipe, RESERVED_END_COLUMNS, RESERVED_START_COLUMNS, Referential, ReferentialFilter, ReferentialRef, ReferentialToStringPipe, ReferentialUtils, ReferentialValidatorService, RegExpUtils, RegisterConfirmPage, RegisterForm, RegisterModal, ResizableComponent, ResizableDirective, ResizableModule, RxStateModule, RxStateProperty, RxStateRegister, RxStateSelect, SCRYPT_PARAMS, SETTINGS_DISPLAY_COLUMNS, SETTINGS_FILTER, SETTINGS_PAGE_SIZE, SETTINGS_SORTED_COLUMN, SETTINGS_STORAGE_KEY, SETTINGS_TRANSIENT_PROPERTIES, SHARED_MATERIAL_TESTING_PAGES, SHARED_STORAGE_TESTING_PAGES, SHARED_TESTING_PAGES, SOCIAL_TESTING_PAGES, SPACE_PLACEHOLDER_CHAR, SPACE_PLACEHOLDER_CHAR_REGEXP_GLOBAL, SafeHtmlPipe, SelectPeerModal, SelectionLengthPipe, ServerErrorCodes, SettingsPage, SharedAsyncValidators, SharedBadgeModule, SharedDebugModule, SharedDirectivesModule, SharedFormArrayValidators, SharedFormGroupValidators, SharedHotkeysModule, SharedMatAutocompleteModule, SharedMatBooleanModule, SharedMatChipsModule, SharedMatDateTimeModule, SharedMatDurationModule, SharedMatLatLongModule, SharedMatSwipeModule, SharedMaterialModule, SharedModule, SharedNamedFilterModule, SharedPipesModule, SharedRoutingModule, SharedTestingModule, SharedTestsPage, SharedTextFormModule, SharedToolbarModule, SharedValidators, SocialErrorCodes, SocialModule, SocialModuleOptionsToken, SocialTestingModule, Software, StartableService, StatusById, StatusIds, StatusList, StorageDrivers, StorageExplorerComponent, StorageExplorerModule, StorageExplorerTestingModule, StorageExplorerTestingRoutingModule, StorageService, StrIncludesPipe, StrLengthPipe, SubMenuTabDirective, SwipeTestPage, Table2TestPage, TableSelectColumnsComponent, TableTestPage, TableTestingModule, TableValidatorService, TextForm, TextFormTestingPage, TextPopover, TextPopoverTestingModule, TextPopoverTestingPage, ThrottledClickDirective, ToStringPipe, ToastTestingModule, ToastTestingPage, Toasts, TokenScope, ToolbarComponent, ToolbarToken, TranslatablePipe, TranslateContextPipe, TranslateContextService, TreeItemEntityUtils, UploadFile, UploadFileComponent, UploadFilePopover, UploadFileTestingModule, UploadFileTestingPage, UriUtils, UserEventModule, UserEventNotificationIcon, UserEventNotificationList, UserEventTestService, UserEventTestingModule, UserEventTestingPage, UserSettings, UserToken, UserTokenTable, UsersPage, ValueFormatPipe, accountToString, adaptValueToControl, addValueInArray, arrayDistinct, arrayResize, arraySize, asInputElement, booleanToString, canHaveFocus, capitalizeFirstLetter, chainPromises, changeCaseToUnderscore, clearValueInArray, collectByProperty, computeDecimalDegrees, computeDecimalPart, copyEntity2Form, createPromiseEvent, createPromiseEventEmitter, departmentToString, departmentsToString, disableAndClearControl, disableAndClearControls, disableControl, disableControls, emitPromiseEvent, enableControl, enableControls, enableRxStateProduction, entityToString, equals, equalsOrNil, escapeRegExp, fadeInAnimation, fadeInOutAnimation, fadeInSlowAnimation, filterFalse, filterFormErrors, filterFormErrorsByPath, filterFormErrorsByPrefix, filterNotNil, filterNumberInput, filterTrue, findParentWithClass, firstArrayValue, firstFalse, firstFalsePromise, firstNotNil, firstNotNilPromise, firstTrue, firstTruePromise, focusInput, focusNextInput, focusPreviousInput, formatLatLong, formatLatitude, formatLongitude, fromDateISOString, fromScrollEndEvent, fromUnixMsTimestamp, fromUnixTimestamp, getCaretPosition, getColorContrast, getColorShade, getColorTint, getControlFromPath, getFocusableInputElements, getFormErrors, getFormValueFromEntity, getInputRangeFromCaretIndex, getInputSelectionRangesFromMask, getProperty, getPropertyByPath, getPropertyByPathAsString, getRandomImage, getRandomImageWithCredit, getUserAgent, hexToRgb, hexToRgbArray, initArrayControlsFromValues, intersectArrays, isAndroid, isBlankString, isCapacitor, isChrome, isControlHasInput, isEdge, isEmptyArray, isFirefox, isIOS, isInputElement, isInstanceOf, isInt, isIpad, isMacOS, isMobile, isNil, isNilOrBlank, isNilOrNaN, isNotEmptyArray, isNotNil, isNotNilBoolean, isNotNilObject, isNotNilOrBlank, isNotNilOrNaN, isNotNilString, isNumber, isNumberRange, isOnFieldMode, isProgressEvent, isPromise, isResponseEvent, isSafari, isStartableService, isTouchUi, isWindows, joinProperties, joinPropertiesPath, lastArrayValue, logFormErrors, markAllAsTouched, markAsUntouched, markControlAsTouched, markFormGroupAsTouched, maskitoAutoSelectByMaskPattern, maskitoPrefixPlugin, matchMedia, matchUpperCase, mergeLoadResult, mixHex, moveInputCaretToSeparator, newArray, noHtml, noTrailingSlash, notNilOrDefault, nullIfNilOrBlank, nullIfUndefined, parseLatitudeOrLongitude, propertiesPathComparator, propertyComparator, propertyPathComparator, referentialToString, referentialsToString, remove, removeAll, removeDiacritics, removeDuplicatesFromArray, removeEnd, removeValueInArray, replaceAll, resetCalculatedValue, resizeArray, rgbArrayToHex, rgbToHex, round, scrollFactory, selectInputContent, selectInputContentFromEvent, selectInputRange, setCalculatedValue, setControlEnabled, setControlsEnabled, setPropertyByPath, setTabIndex, sleep, slideInAnimation, slideInOutAnimation, slideUpDownAnimation, sort, splitById, splitByProperty, splitDegreesToDDArray, splitDegreesToDDMMArray, splitDegreesToDDMMSSArray, startsWithUpperCase, suggestFromArray, suggestFromStringArray, tabindexComparator, testUserAgent, toBoolean, toDateISOString, toDuration, toFloat, toInt, toNotNil, toNumber, trimEmptyToNull, uncapitalizeFirstLetter, undefinedIfNull, underscoreToChangeCase, updateValueAndValidity, waitFor, waitForFalse, waitForTrue, waitIdle, waitWhilePending };
46010
46102
  //# sourceMappingURL=sumaris-net.ngx-components.mjs.map