@sumaris-net/ngx-components 2.18.0-alpha4 → 2.18.0-alpha6

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.
Files changed (52) hide show
  1. package/esm2022/public_api.mjs +2 -1
  2. package/esm2022/src/app/admin/users/users.mjs +2 -2
  3. package/esm2022/src/app/core/account/account.page.mjs +1 -1
  4. package/esm2022/src/app/core/form/array/form-array.mjs +2 -1
  5. package/esm2022/src/app/core/form/form.class.mjs +7 -14
  6. package/esm2022/src/app/core/form/properties/properties.form.mjs +132 -47
  7. package/esm2022/src/app/core/form/properties/property.validator.mjs +21 -7
  8. package/esm2022/src/app/core/form/properties/testing/properties-form.test.mjs +3 -3
  9. package/esm2022/src/app/core/register/register.form.mjs +1 -1
  10. package/esm2022/src/app/core/services/model/entity.model.mjs +4 -2
  11. package/esm2022/src/app/core/services/validator/local-settings.validator.mjs +19 -8
  12. package/esm2022/src/app/core/settings/settings.module.mjs +5 -4
  13. package/esm2022/src/app/core/settings/settings.page.mjs +43 -45
  14. package/esm2022/src/app/core/table/column/nav-actions-column.component.mjs +4 -4
  15. package/esm2022/src/app/core/table/column/row-field.component.mjs +1 -1
  16. package/esm2022/src/app/core/table/testing/table.testing.mjs +1 -1
  17. package/esm2022/src/app/core/table/testing/table2.testing.mjs +1 -1
  18. package/esm2022/src/app/shared/dates.mjs +4 -8
  19. package/esm2022/src/app/shared/form/field.component.mjs +33 -14
  20. package/esm2022/src/app/shared/functions.mjs +16 -1
  21. package/esm2022/src/app/shared/image/gallery/image-gallery.component.mjs +9 -10
  22. package/esm2022/src/app/shared/material/autocomplete/material.autocomplete.config.mjs +1 -1
  23. package/esm2022/src/app/shared/material/autocomplete/material.autocomplete.mjs +36 -19
  24. package/esm2022/src/app/shared/material/autocomplete/testing/autocomplete.test.mjs +1 -1
  25. package/esm2022/src/app/shared/material/chips/material.chips.mjs +3 -3
  26. package/esm2022/src/app/shared/named-filter/named-filter-selector.component.mjs +33 -20
  27. package/esm2022/src/app/shared/named-filter/testing/named-filter-selector.testing.mjs +15 -10
  28. package/esm2022/src/app/shared/pipes/html.pipes.mjs +52 -0
  29. package/esm2022/src/app/shared/pipes/pipes.module.mjs +10 -3
  30. package/esm2022/src/app/social/job/progression/job-progression.list.mjs +8 -9
  31. package/fesm2022/sumaris-net.ngx-components.mjs +670 -453
  32. package/fesm2022/sumaris-net.ngx-components.mjs.map +1 -1
  33. package/package.json +1 -1
  34. package/public_api.d.ts +1 -0
  35. package/src/app/core/form/array/form-array.d.ts +1 -1
  36. package/src/app/core/form/form.class.d.ts +2 -5
  37. package/src/app/core/form/properties/properties.form.d.ts +32 -10
  38. package/src/app/core/form/properties/property.validator.d.ts +9 -3
  39. package/src/app/core/services/validator/local-settings.validator.d.ts +6 -2
  40. package/src/app/core/settings/settings.module.d.ts +2 -1
  41. package/src/app/core/settings/settings.page.d.ts +22 -12
  42. package/src/app/shared/dates.d.ts +9 -3
  43. package/src/app/shared/form/field.component.d.ts +3 -2
  44. package/src/app/shared/functions.d.ts +2 -0
  45. package/src/app/shared/material/autocomplete/material.autocomplete.config.d.ts +4 -0
  46. package/src/app/shared/material/autocomplete/material.autocomplete.d.ts +12 -4
  47. package/src/app/shared/named-filter/named-filter-selector.component.d.ts +9 -6
  48. package/src/app/shared/named-filter/testing/named-filter-selector.testing.d.ts +4 -1
  49. package/src/app/shared/pipes/html.pipes.d.ts +15 -0
  50. package/src/app/shared/pipes/pipes.module.d.ts +5 -4
  51. package/src/assets/i18n/fr.json +3 -2
  52. package/src/assets/manifest.json +1 -1
@@ -1,4 +1,4 @@
1
- import { booleanAttribute, Component, EventEmitter, Input, Optional, Output, ViewChild, } from '@angular/core';
1
+ import { booleanAttribute, ChangeDetectionStrategy, Component, EventEmitter, Input, Optional, Output, ViewChild, } from '@angular/core';
2
2
  import { MatColumnDef } from '@angular/material/table';
3
3
  import { MatMenuTrigger } from '@angular/material/menu';
4
4
  import { Subject, Subscription } from 'rxjs';
@@ -73,11 +73,11 @@ export class NavActionsColumnComponent {
73
73
  this._backwardEventSubject.next({ event, row });
74
74
  }
75
75
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.8", ngImport: i0, type: NavActionsColumnComponent, deps: [{ token: i1.MatTable }, { token: i0.ChangeDetectorRef }, { token: i2.AppTable, optional: true }, { token: i3.AppAsyncTable, optional: true }], target: i0.ɵɵFactoryTarget.Component });
76
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.8", type: NavActionsColumnComponent, selector: "app-nav-actions-column", inputs: { appTable: "appTable", matColumnDef: "matColumnDef", style: "style", stickyEnd: ["stickyEnd", "stickyEnd", booleanAttribute], showPending: ["showPending", "showPending", booleanAttribute], dirtyIcon: "dirtyIcon", optionsTitle: "optionsTitle", classList: ["class", "classList"], cellTemplate: "cellTemplate", throttleTime: "throttleTime" }, outputs: { optionsClick: "optionsClick" }, viewQueries: [{ propertyName: "columnDef", first: true, predicate: MatColumnDef, descendants: true }, { propertyName: "matMenuTrigger", first: true, predicate: MatMenuTrigger, descendants: true }], ngImport: i0, template: "<ng-container [matColumnDef]=\"matColumnDef\" [stickyEnd]=\"stickyEnd\" [ngSwitch]=\"style\">\n <ng-container *ngSwitchCase=\"'table'\">\n <th mat-header-cell *matHeaderCellDef [class]=\"classList\" [class.mat-column-sticky]=\"stickyEnd\">\n <button\n mat-icon-button\n *ngIf=\"optionsClick.observed\"\n [title]=\"optionsTitle | translate\"\n (click)=\"optionsClick.emit($event)\"\n >\n <mat-icon>more_vert</mat-icon>\n </button>\n <ng-content select=\"[matHeader]\"></ng-content>\n </th>\n <td mat-cell *matCellDef=\"let row\" [class]=\"classList\">\n @if (row.editing) {\n <!-- pending -->\n @if (row.validator?.pending) {\n <ion-spinner [class.cdk-visually-hidden]=\"!showPending\" name=\"dots\" class=\"center\"></ion-spinner>\n }\n\n <!-- invalid new row -->\n @if (row.id === -1 && row.validator?.invalid) {\n <!-- delete button -->\n <button\n mat-icon-button\n color=\"light\"\n [title]=\"'COMMON.BTN_DELETE' | translate\"\n (click)=\"cancelOrDelete($event, row)\"\n >\n <mat-icon>delete_outline</mat-icon>\n </button>\n\n <!-- valid row or invalid existing row -->\n } @else {\n <!-- forward button (invisible - focusable only) -->\n <button class=\"mat-row-action-button-navigation\" (focus)=\"confirmAndForward($event, row)\"></button>\n }\n\n <!-- NOT editing row -->\n } @else {\n <!-- dirty icon -->\n @if (dirtyIcon && row.validator?.dirty) {\n <ion-icon [name]=\"dirtyIcon\" color=\"accent\" class=\"dirty-icon\" tabindex=\"-1\"></ion-icon>\n }\n\n <!-- backward button (invisible - focusable only) -->\n <button\n mat-icon-button\n class=\"mat-row-action-button-navigation\"\n (focus)=\"confirmAndBackward($event, row)\"\n ></button>\n }\n\n <ng-container *ngTemplateOutlet=\"cellTemplate; context: { $implicit: row }\"></ng-container>\n </td>\n\n <td mat-footer-cell *matFooterCellDef>\n <ng-content select=\"[matFooter]\"></ng-content>\n </td>\n </ng-container>\n\n <ng-container *ngSwitchCase=\"'mat-table'\">\n <mat-header-cell *matHeaderCellDef [class]=\"classList\" [class.mat-column-sticky]=\"stickyEnd\">\n <button\n mat-icon-button\n *ngIf=\"optionsClick.observed\"\n [title]=\"optionsTitle | translate\"\n (click)=\"optionsClick.emit($event)\"\n >\n <mat-icon>more_vert</mat-icon>\n </button>\n <ng-content select=\"[matHeader]\"></ng-content>\n </mat-header-cell>\n <mat-cell *matCellDef=\"let row\" [class]=\"classList\">\n @if (row.editing) {\n <!-- pending -->\n @if (row.validator?.pending) {\n <ion-spinner [class.cdk-visually-hidden]=\"!showPending\" name=\"dots\" class=\"center\"></ion-spinner>\n }\n\n <!-- invalid new row -->\n @if (row.id === -1 && row.validator?.invalid) {\n <!-- delete button -->\n <button\n mat-icon-button\n color=\"light\"\n [title]=\"'COMMON.BTN_DELETE' | translate\"\n (click)=\"cancelOrDelete($event, row)\"\n >\n <mat-icon>delete_outline</mat-icon>\n </button>\n } @else {\n <!-- forward button (invisible - focusable only) -->\n <button class=\"mat-row-action-button-navigation\" (focus)=\"confirmAndForward($event, row)\"></button>\n }\n\n <!-- not editing row -->\n } @else {\n <!-- dirty icon -->\n @if (dirtyIcon && row.validator?.dirty) {\n <ion-icon [name]=\"dirtyIcon\" color=\"accent\" class=\"dirty-icon\"></ion-icon>\n }\n\n <!-- backward button (invisible - focusable only) -->\n <button\n mat-icon-button\n class=\"mat-row-action-button-navigation\"\n (focus)=\"confirmAndBackward($event, row)\"\n ></button>\n }\n\n <ng-container *ngTemplateOutlet=\"cellTemplate; context: { $implicit: row }\"></ng-container>\n </mat-cell>\n\n <mat-footer-cell *matFooterCellDef>\n <ng-content select=\"[matFooter]\"></ng-content>\n </mat-footer-cell>\n </ng-container>\n</ng-container>\n", styles: [".mat-column-actions .mat-row-action-button-navigation{color:transparent;position:relative;top:0;margin:0!important;padding:0!important;width:0!important;height:1px}\n"], dependencies: [{ kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i4.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i4.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: i4.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "component", type: i5.IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: i5.IonSpinner, selector: "ion-spinner", inputs: ["color", "duration", "name", "paused"] }, { kind: "directive", type: i1.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i1.MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: i1.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i1.MatFooterCellDef, selector: "[matFooterCellDef]" }, { kind: "directive", type: i1.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i1.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "directive", type: i1.MatFooterCell, selector: "mat-footer-cell, td[mat-footer-cell]" }, { kind: "component", type: i6.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i7.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "pipe", type: i8.TranslatePipe, name: "translate" }] });
76
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.8", type: NavActionsColumnComponent, selector: "app-nav-actions-column", inputs: { appTable: "appTable", matColumnDef: "matColumnDef", style: "style", stickyEnd: ["stickyEnd", "stickyEnd", booleanAttribute], showPending: ["showPending", "showPending", booleanAttribute], dirtyIcon: "dirtyIcon", optionsTitle: "optionsTitle", classList: ["class", "classList"], cellTemplate: "cellTemplate", throttleTime: "throttleTime" }, outputs: { optionsClick: "optionsClick" }, viewQueries: [{ propertyName: "columnDef", first: true, predicate: MatColumnDef, descendants: true }, { propertyName: "matMenuTrigger", first: true, predicate: MatMenuTrigger, descendants: true }], ngImport: i0, template: "<ng-container [matColumnDef]=\"matColumnDef\" [stickyEnd]=\"stickyEnd\" [ngSwitch]=\"style\">\n <ng-container *ngSwitchCase=\"'table'\">\n <th mat-header-cell *matHeaderCellDef [class]=\"classList\" [class.mat-column-sticky]=\"stickyEnd\">\n <button\n mat-icon-button\n *ngIf=\"optionsClick.observed\"\n [title]=\"optionsTitle | translate\"\n (click)=\"optionsClick.emit($event)\"\n >\n <mat-icon>more_vert</mat-icon>\n </button>\n <ng-content select=\"[matHeader]\"></ng-content>\n </th>\n <td mat-cell *matCellDef=\"let row\" [class]=\"classList\">\n @if (row.editing) {\n <!-- pending -->\n @if (row.validator?.pending) {\n <ion-spinner [class.cdk-visually-hidden]=\"!showPending\" name=\"dots\" class=\"center\"></ion-spinner>\n }\n\n <!-- invalid new row -->\n @if (row.id === -1 && row.validator?.invalid) {\n <!-- delete button -->\n <button\n mat-icon-button\n color=\"light\"\n [title]=\"'COMMON.BTN_DELETE' | translate\"\n (click)=\"cancelOrDelete($event, row)\"\n >\n <mat-icon>delete_outline</mat-icon>\n </button>\n\n <!-- valid row or invalid existing row -->\n } @else {\n <!-- forward button (invisible - focusable only) -->\n <button class=\"mat-row-action-button-navigation\" (focus)=\"confirmAndForward($event, row)\"></button>\n }\n\n <!-- NOT editing row -->\n } @else {\n <!-- dirty icon -->\n @if (dirtyIcon && row.validator?.dirty) {\n <ion-icon [name]=\"dirtyIcon\" color=\"accent\" class=\"dirty-icon\" tabindex=\"-1\"></ion-icon>\n }\n\n <!-- backward button (invisible - focusable only) -->\n <button\n mat-icon-button\n class=\"mat-row-action-button-navigation\"\n (focus)=\"confirmAndBackward($event, row)\"\n ></button>\n }\n\n <ng-container *ngTemplateOutlet=\"cellTemplate; context: { $implicit: row }\"></ng-container>\n </td>\n\n <td mat-footer-cell *matFooterCellDef>\n <ng-content select=\"[matFooter]\"></ng-content>\n </td>\n </ng-container>\n\n <ng-container *ngSwitchCase=\"'mat-table'\">\n <mat-header-cell *matHeaderCellDef [class]=\"classList\" [class.mat-column-sticky]=\"stickyEnd\">\n <button\n mat-icon-button\n *ngIf=\"optionsClick.observed\"\n [title]=\"optionsTitle | translate\"\n (click)=\"optionsClick.emit($event)\"\n >\n <mat-icon>more_vert</mat-icon>\n </button>\n <ng-content select=\"[matHeader]\"></ng-content>\n </mat-header-cell>\n <mat-cell *matCellDef=\"let row\" [class]=\"classList\">\n @if (row.editing) {\n <!-- pending -->\n @if (row.validator?.pending) {\n <ion-spinner [class.cdk-visually-hidden]=\"!showPending\" name=\"dots\" class=\"center\"></ion-spinner>\n }\n\n <!-- invalid new row -->\n @if (row.id === -1 && row.validator?.invalid) {\n <!-- delete button -->\n <button\n mat-icon-button\n color=\"light\"\n [title]=\"'COMMON.BTN_DELETE' | translate\"\n (click)=\"cancelOrDelete($event, row)\"\n >\n <mat-icon>delete_outline</mat-icon>\n </button>\n } @else {\n <!-- forward button (invisible - focusable only) -->\n <button class=\"mat-row-action-button-navigation\" (focus)=\"confirmAndForward($event, row)\"></button>\n }\n\n <!-- not editing row -->\n } @else {\n <!-- dirty icon -->\n @if (dirtyIcon && row.validator?.dirty) {\n <ion-icon [name]=\"dirtyIcon\" color=\"accent\" class=\"dirty-icon\"></ion-icon>\n }\n\n <!-- backward button (invisible - focusable only) -->\n <button\n mat-icon-button\n class=\"mat-row-action-button-navigation\"\n (focus)=\"confirmAndBackward($event, row)\"\n ></button>\n }\n\n <ng-container *ngTemplateOutlet=\"cellTemplate; context: { $implicit: row }\"></ng-container>\n </mat-cell>\n\n <mat-footer-cell *matFooterCellDef>\n <ng-content select=\"[matFooter]\"></ng-content>\n </mat-footer-cell>\n </ng-container>\n</ng-container>\n", styles: [".mat-column-actions .mat-row-action-button-navigation{color:transparent;position:relative;top:0;margin:0!important;padding:0!important;width:0!important;height:1px}\n"], dependencies: [{ kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i4.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i4.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: i4.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "component", type: i5.IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: i5.IonSpinner, selector: "ion-spinner", inputs: ["color", "duration", "name", "paused"] }, { kind: "directive", type: i1.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i1.MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: i1.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i1.MatFooterCellDef, selector: "[matFooterCellDef]" }, { kind: "directive", type: i1.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i1.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "directive", type: i1.MatFooterCell, selector: "mat-footer-cell, td[mat-footer-cell]" }, { kind: "component", type: i6.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i7.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "pipe", type: i8.TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
77
77
  }
78
78
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.8", ngImport: i0, type: NavActionsColumnComponent, decorators: [{
79
79
  type: Component,
80
- args: [{ selector: 'app-nav-actions-column', template: "<ng-container [matColumnDef]=\"matColumnDef\" [stickyEnd]=\"stickyEnd\" [ngSwitch]=\"style\">\n <ng-container *ngSwitchCase=\"'table'\">\n <th mat-header-cell *matHeaderCellDef [class]=\"classList\" [class.mat-column-sticky]=\"stickyEnd\">\n <button\n mat-icon-button\n *ngIf=\"optionsClick.observed\"\n [title]=\"optionsTitle | translate\"\n (click)=\"optionsClick.emit($event)\"\n >\n <mat-icon>more_vert</mat-icon>\n </button>\n <ng-content select=\"[matHeader]\"></ng-content>\n </th>\n <td mat-cell *matCellDef=\"let row\" [class]=\"classList\">\n @if (row.editing) {\n <!-- pending -->\n @if (row.validator?.pending) {\n <ion-spinner [class.cdk-visually-hidden]=\"!showPending\" name=\"dots\" class=\"center\"></ion-spinner>\n }\n\n <!-- invalid new row -->\n @if (row.id === -1 && row.validator?.invalid) {\n <!-- delete button -->\n <button\n mat-icon-button\n color=\"light\"\n [title]=\"'COMMON.BTN_DELETE' | translate\"\n (click)=\"cancelOrDelete($event, row)\"\n >\n <mat-icon>delete_outline</mat-icon>\n </button>\n\n <!-- valid row or invalid existing row -->\n } @else {\n <!-- forward button (invisible - focusable only) -->\n <button class=\"mat-row-action-button-navigation\" (focus)=\"confirmAndForward($event, row)\"></button>\n }\n\n <!-- NOT editing row -->\n } @else {\n <!-- dirty icon -->\n @if (dirtyIcon && row.validator?.dirty) {\n <ion-icon [name]=\"dirtyIcon\" color=\"accent\" class=\"dirty-icon\" tabindex=\"-1\"></ion-icon>\n }\n\n <!-- backward button (invisible - focusable only) -->\n <button\n mat-icon-button\n class=\"mat-row-action-button-navigation\"\n (focus)=\"confirmAndBackward($event, row)\"\n ></button>\n }\n\n <ng-container *ngTemplateOutlet=\"cellTemplate; context: { $implicit: row }\"></ng-container>\n </td>\n\n <td mat-footer-cell *matFooterCellDef>\n <ng-content select=\"[matFooter]\"></ng-content>\n </td>\n </ng-container>\n\n <ng-container *ngSwitchCase=\"'mat-table'\">\n <mat-header-cell *matHeaderCellDef [class]=\"classList\" [class.mat-column-sticky]=\"stickyEnd\">\n <button\n mat-icon-button\n *ngIf=\"optionsClick.observed\"\n [title]=\"optionsTitle | translate\"\n (click)=\"optionsClick.emit($event)\"\n >\n <mat-icon>more_vert</mat-icon>\n </button>\n <ng-content select=\"[matHeader]\"></ng-content>\n </mat-header-cell>\n <mat-cell *matCellDef=\"let row\" [class]=\"classList\">\n @if (row.editing) {\n <!-- pending -->\n @if (row.validator?.pending) {\n <ion-spinner [class.cdk-visually-hidden]=\"!showPending\" name=\"dots\" class=\"center\"></ion-spinner>\n }\n\n <!-- invalid new row -->\n @if (row.id === -1 && row.validator?.invalid) {\n <!-- delete button -->\n <button\n mat-icon-button\n color=\"light\"\n [title]=\"'COMMON.BTN_DELETE' | translate\"\n (click)=\"cancelOrDelete($event, row)\"\n >\n <mat-icon>delete_outline</mat-icon>\n </button>\n } @else {\n <!-- forward button (invisible - focusable only) -->\n <button class=\"mat-row-action-button-navigation\" (focus)=\"confirmAndForward($event, row)\"></button>\n }\n\n <!-- not editing row -->\n } @else {\n <!-- dirty icon -->\n @if (dirtyIcon && row.validator?.dirty) {\n <ion-icon [name]=\"dirtyIcon\" color=\"accent\" class=\"dirty-icon\"></ion-icon>\n }\n\n <!-- backward button (invisible - focusable only) -->\n <button\n mat-icon-button\n class=\"mat-row-action-button-navigation\"\n (focus)=\"confirmAndBackward($event, row)\"\n ></button>\n }\n\n <ng-container *ngTemplateOutlet=\"cellTemplate; context: { $implicit: row }\"></ng-container>\n </mat-cell>\n\n <mat-footer-cell *matFooterCellDef>\n <ng-content select=\"[matFooter]\"></ng-content>\n </mat-footer-cell>\n </ng-container>\n</ng-container>\n", styles: [".mat-column-actions .mat-row-action-button-navigation{color:transparent;position:relative;top:0;margin:0!important;padding:0!important;width:0!important;height:1px}\n"] }]
80
+ args: [{ selector: 'app-nav-actions-column', changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-container [matColumnDef]=\"matColumnDef\" [stickyEnd]=\"stickyEnd\" [ngSwitch]=\"style\">\n <ng-container *ngSwitchCase=\"'table'\">\n <th mat-header-cell *matHeaderCellDef [class]=\"classList\" [class.mat-column-sticky]=\"stickyEnd\">\n <button\n mat-icon-button\n *ngIf=\"optionsClick.observed\"\n [title]=\"optionsTitle | translate\"\n (click)=\"optionsClick.emit($event)\"\n >\n <mat-icon>more_vert</mat-icon>\n </button>\n <ng-content select=\"[matHeader]\"></ng-content>\n </th>\n <td mat-cell *matCellDef=\"let row\" [class]=\"classList\">\n @if (row.editing) {\n <!-- pending -->\n @if (row.validator?.pending) {\n <ion-spinner [class.cdk-visually-hidden]=\"!showPending\" name=\"dots\" class=\"center\"></ion-spinner>\n }\n\n <!-- invalid new row -->\n @if (row.id === -1 && row.validator?.invalid) {\n <!-- delete button -->\n <button\n mat-icon-button\n color=\"light\"\n [title]=\"'COMMON.BTN_DELETE' | translate\"\n (click)=\"cancelOrDelete($event, row)\"\n >\n <mat-icon>delete_outline</mat-icon>\n </button>\n\n <!-- valid row or invalid existing row -->\n } @else {\n <!-- forward button (invisible - focusable only) -->\n <button class=\"mat-row-action-button-navigation\" (focus)=\"confirmAndForward($event, row)\"></button>\n }\n\n <!-- NOT editing row -->\n } @else {\n <!-- dirty icon -->\n @if (dirtyIcon && row.validator?.dirty) {\n <ion-icon [name]=\"dirtyIcon\" color=\"accent\" class=\"dirty-icon\" tabindex=\"-1\"></ion-icon>\n }\n\n <!-- backward button (invisible - focusable only) -->\n <button\n mat-icon-button\n class=\"mat-row-action-button-navigation\"\n (focus)=\"confirmAndBackward($event, row)\"\n ></button>\n }\n\n <ng-container *ngTemplateOutlet=\"cellTemplate; context: { $implicit: row }\"></ng-container>\n </td>\n\n <td mat-footer-cell *matFooterCellDef>\n <ng-content select=\"[matFooter]\"></ng-content>\n </td>\n </ng-container>\n\n <ng-container *ngSwitchCase=\"'mat-table'\">\n <mat-header-cell *matHeaderCellDef [class]=\"classList\" [class.mat-column-sticky]=\"stickyEnd\">\n <button\n mat-icon-button\n *ngIf=\"optionsClick.observed\"\n [title]=\"optionsTitle | translate\"\n (click)=\"optionsClick.emit($event)\"\n >\n <mat-icon>more_vert</mat-icon>\n </button>\n <ng-content select=\"[matHeader]\"></ng-content>\n </mat-header-cell>\n <mat-cell *matCellDef=\"let row\" [class]=\"classList\">\n @if (row.editing) {\n <!-- pending -->\n @if (row.validator?.pending) {\n <ion-spinner [class.cdk-visually-hidden]=\"!showPending\" name=\"dots\" class=\"center\"></ion-spinner>\n }\n\n <!-- invalid new row -->\n @if (row.id === -1 && row.validator?.invalid) {\n <!-- delete button -->\n <button\n mat-icon-button\n color=\"light\"\n [title]=\"'COMMON.BTN_DELETE' | translate\"\n (click)=\"cancelOrDelete($event, row)\"\n >\n <mat-icon>delete_outline</mat-icon>\n </button>\n } @else {\n <!-- forward button (invisible - focusable only) -->\n <button class=\"mat-row-action-button-navigation\" (focus)=\"confirmAndForward($event, row)\"></button>\n }\n\n <!-- not editing row -->\n } @else {\n <!-- dirty icon -->\n @if (dirtyIcon && row.validator?.dirty) {\n <ion-icon [name]=\"dirtyIcon\" color=\"accent\" class=\"dirty-icon\"></ion-icon>\n }\n\n <!-- backward button (invisible - focusable only) -->\n <button\n mat-icon-button\n class=\"mat-row-action-button-navigation\"\n (focus)=\"confirmAndBackward($event, row)\"\n ></button>\n }\n\n <ng-container *ngTemplateOutlet=\"cellTemplate; context: { $implicit: row }\"></ng-container>\n </mat-cell>\n\n <mat-footer-cell *matFooterCellDef>\n <ng-content select=\"[matFooter]\"></ng-content>\n </mat-footer-cell>\n </ng-container>\n</ng-container>\n", styles: [".mat-column-actions .mat-row-action-button-navigation{color:transparent;position:relative;top:0;margin:0!important;padding:0!important;width:0!important;height:1px}\n"] }]
81
81
  }], ctorParameters: () => [{ type: i1.MatTable }, { type: i0.ChangeDetectorRef }, { type: i2.AppTable, decorators: [{
82
82
  type: Optional
83
83
  }] }, { type: i3.AppAsyncTable, decorators: [{
@@ -114,4 +114,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.8", ngImpor
114
114
  }], optionsClick: [{
115
115
  type: Output
116
116
  }] } });
117
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmF2LWFjdGlvbnMtY29sdW1uLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uLy4uL3NyYy9hcHAvY29yZS90YWJsZS9jb2x1bW4vbmF2LWFjdGlvbnMtY29sdW1uLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uLy4uLy4uL3NyYy9hcHAvY29yZS90YWJsZS9jb2x1bW4vbmF2LWFjdGlvbnMtY29sdW1uLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFDTCxnQkFBZ0IsRUFFaEIsU0FBUyxFQUNULFlBQVksRUFDWixLQUFLLEVBR0wsUUFBUSxFQUNSLE1BQU0sRUFFTixTQUFTLEdBQ1YsTUFBTSxlQUFlLENBQUM7QUFFdkIsT0FBTyxFQUFFLFlBQVksRUFBWSxNQUFNLHlCQUF5QixDQUFDO0FBQ2pFLE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUd4RCxPQUFPLEVBQUUsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUM3QyxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7Ozs7Ozs7Ozs7QUFPOUMsTUFBTSxPQUFPLHlCQUF5QjtJQXVCMUI7SUFDQTtJQXZCVixhQUFhLEdBQUcsSUFBSSxZQUFZLEVBQUUsQ0FBQztJQUNuQyxvQkFBb0IsR0FBRyxJQUFJLE9BQU8sRUFBNEIsQ0FBQztJQUMvRCxxQkFBcUIsR0FBRyxJQUFJLE9BQU8sRUFBNEIsQ0FBQztJQUV2QyxTQUFTLENBQWU7SUFDdEIsY0FBYyxDQUFpQjtJQUVqRCxRQUFRLENBQXFDO0lBQzdDLFlBQVksR0FBRyxTQUFTLENBQUM7SUFDekIsS0FBSyxHQUEwQixPQUFPLENBQUM7SUFDUixTQUFTLEdBQUcsS0FBSyxDQUFDO0lBQ2xCLFdBQVcsQ0FBVTtJQUNwRCxTQUFTLENBQW1CO0lBQzVCLFlBQVksR0FBRyxvQkFBb0IsQ0FBQztJQUM3QywyREFBMkQ7SUFDM0MsU0FBUyxDQUFTO0lBQ3pCLFlBQVksQ0FBZ0M7SUFDNUMsWUFBWSxHQUFHLEdBQUcsQ0FBQztJQUVsQixZQUFZLEdBQUcsSUFBSSxZQUFZLEVBQVMsQ0FBQztJQUVuRCxZQUNVLFFBQXVCLEVBQ3ZCLEVBQXFCLEVBQ2pCLFFBQXVCLEVBQ3ZCLGFBQWlDO1FBSHJDLGFBQVEsR0FBUixRQUFRLENBQWU7UUFDdkIsT0FBRSxHQUFGLEVBQUUsQ0FBbUI7UUFJN0IsSUFBSSxDQUFDLFFBQVE7WUFBRSxNQUFNLElBQUksS0FBSyxDQUFDLDRFQUE0RSxDQUFDLENBQUM7UUFDN0csSUFBSSxDQUFDLFFBQVEsR0FBRyxRQUFRLElBQUksYUFBYSxDQUFDO1FBQzFDLElBQUksQ0FBQyxhQUFhLEdBQUcsSUFBSSxZQUFZLEVBQUUsQ0FBQztJQUMxQyxDQUFDO0lBRUQsUUFBUTtRQUNOLGlCQUFpQjtRQUNqQixJQUFJLENBQUMsV0FBVyxHQUFHLElBQUksQ0FBQyxXQUFXLElBQUksSUFBSSxDQUFDO1FBQzVDLElBQUksQ0FBQyxTQUFTLEdBQUcsSUFBSSxDQUFDLFNBQVMsS0FBSyxJQUFJLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsS0FBSyxLQUFLLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsSUFBSSxNQUFNLENBQUM7UUFFL0csSUFBSSxDQUFDLEVBQUUsQ0FBQyxhQUFhLEVBQUUsQ0FBQztRQUN4QixJQUFJLENBQUMsUUFBUSxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUM7UUFFM0MsSUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRO1lBQ2hCLE1BQU0sSUFBSSxLQUFLLENBQUMsNkdBQTZHLENBQUMsQ0FBQztRQUVqSSxJQUFJLENBQUMsYUFBYSxDQUFDLEdBQUcsQ0FDcEIsSUFBSSxDQUFDLG9CQUFvQjthQUN0QixJQUFJLENBQ0gsWUFBWSxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsQ0FBQyxxREFBcUQ7U0FDdEY7YUFDQSxTQUFTLENBQUMsQ0FBQyxFQUFFLEtBQUssRUFBRSxHQUFHLEVBQUUsRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxpQkFBaUIsQ0FBQyxLQUFLLEVBQUUsR0FBVSxDQUFDLENBQUMsQ0FDckYsQ0FBQztRQUVGLElBQUksQ0FBQyxhQUFhLENBQUMsR0FBRyxDQUNwQixJQUFJLENBQUMscUJBQXFCO2FBQ3ZCLElBQUksQ0FDSCxZQUFZLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxDQUFDLDBEQUEwRDtTQUMzRjthQUNBLFNBQVMsQ0FBQyxDQUFDLEVBQUUsS0FBSyxFQUFFLEdBQUcsRUFBRSxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLGtCQUFrQixDQUFDLEtBQUssRUFBRSxHQUFVLENBQUMsQ0FBQyxDQUN0RixDQUFDO0lBQ0osQ0FBQztJQUVELFdBQVc7UUFDVCxJQUFJLENBQUMsUUFBUSxDQUFDLGVBQWUsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUM7UUFDOUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxRQUFRLEVBQUUsQ0FBQztRQUM3QixJQUFJLENBQUMsWUFBWSxDQUFDLFdBQVcsRUFBRSxDQUFDO1FBQ2hDLElBQUksQ0FBQyxhQUFhLENBQUMsV0FBVyxFQUFFLENBQUM7SUFDbkMsQ0FBQztJQUVTLGNBQWMsQ0FBQyxLQUFZLEVBQUUsR0FBTTtRQUMzQyxJQUFJLENBQUMsUUFBUSxDQUFDLGNBQWMsQ0FBQyxLQUFLLEVBQUUsR0FBVSxDQUFDLENBQUM7SUFDbEQsQ0FBQztJQUVTLGlCQUFpQixDQUFDLEtBQVksRUFBRSxHQUFNO1FBQzlDLElBQUksQ0FBQyxvQkFBb0IsQ0FBQyxJQUFJLENBQUMsRUFBRSxLQUFLLEVBQUUsR0FBRyxFQUFFLENBQUMsQ0FBQztJQUNqRCxDQUFDO0lBRVMsa0JBQWtCLENBQUMsS0FBWSxFQUFFLEdBQU07UUFDL0MsSUFBSSxDQUFDLHFCQUFxQixDQUFDLElBQUksQ0FBQyxFQUFFLEtBQUssRUFBRSxHQUFHLEVBQUUsQ0FBQyxDQUFDO0lBQ2xELENBQUM7dUdBOUVVLHlCQUF5QjsyRkFBekIseUJBQXlCLDBKQVdoQixnQkFBZ0IsK0NBQ2hCLGdCQUFnQix3UUFQekIsWUFBWSxpRkFDWixjQUFjLGdEQ2hDM0IsK3dJQXVIQTs7MkZEN0ZhLHlCQUF5QjtrQkFMckMsU0FBUzsrQkFDRSx3QkFBd0I7OzBCQTZCL0IsUUFBUTs7MEJBQ1IsUUFBUTt5Q0FyQmMsU0FBUztzQkFBakMsU0FBUzt1QkFBQyxZQUFZO2dCQUNJLGNBQWM7c0JBQXhDLFNBQVM7dUJBQUMsY0FBYztnQkFFaEIsUUFBUTtzQkFBaEIsS0FBSztnQkFDRyxZQUFZO3NCQUFwQixLQUFLO2dCQUNHLEtBQUs7c0JBQWIsS0FBSztnQkFDa0MsU0FBUztzQkFBaEQsS0FBSzt1QkFBQyxFQUFFLFNBQVMsRUFBRSxnQkFBZ0IsRUFBRTtnQkFDRSxXQUFXO3NCQUFsRCxLQUFLO3VCQUFDLEVBQUUsU0FBUyxFQUFFLGdCQUFnQixFQUFFO2dCQUM3QixTQUFTO3NCQUFqQixLQUFLO2dCQUNHLFlBQVk7c0JBQXBCLEtBQUs7Z0JBRVUsU0FBUztzQkFBeEIsS0FBSzt1QkFBQyxPQUFPO2dCQUNMLFlBQVk7c0JBQXBCLEtBQUs7Z0JBQ0csWUFBWTtzQkFBcEIsS0FBSztnQkFFSSxZQUFZO3NCQUFyQixNQUFNIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgYm9vbGVhbkF0dHJpYnV0ZSxcbiAgQ2hhbmdlRGV0ZWN0b3JSZWYsXG4gIENvbXBvbmVudCxcbiAgRXZlbnRFbWl0dGVyLFxuICBJbnB1dCxcbiAgT25EZXN0cm95LFxuICBPbkluaXQsXG4gIE9wdGlvbmFsLFxuICBPdXRwdXQsXG4gIFRlbXBsYXRlUmVmLFxuICBWaWV3Q2hpbGQsXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgQXN5bmNUYWJsZUVsZW1lbnQsIFRhYmxlRWxlbWVudCB9IGZyb20gJ0BlLWlzL25neC1tYXRlcmlhbC10YWJsZSc7XG5pbXBvcnQgeyBNYXRDb2x1bW5EZWYsIE1hdFRhYmxlIH0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvdGFibGUnO1xuaW1wb3J0IHsgTWF0TWVudVRyaWdnZXIgfSBmcm9tICdAYW5ndWxhci9tYXRlcmlhbC9tZW51JztcbmltcG9ydCB7IEFwcFRhYmxlIH0gZnJvbSAnLi4vdGFibGUuY2xhc3MnO1xuaW1wb3J0IHsgQXBwQXN5bmNUYWJsZSB9IGZyb20gJy4uL2FzeW5jLXRhYmxlLmNsYXNzJztcbmltcG9ydCB7IFN1YmplY3QsIFN1YnNjcmlwdGlvbiB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgdGhyb3R0bGVUaW1lIH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdhcHAtbmF2LWFjdGlvbnMtY29sdW1uJyxcbiAgc3R5bGVVcmxzOiBbJy4vYWN0aW9ucy1jb2x1bW4uY29tcG9uZW50LnNjc3MnXSxcbiAgdGVtcGxhdGVVcmw6ICcuL25hdi1hY3Rpb25zLWNvbHVtbi5jb21wb25lbnQuaHRtbCcsXG59KVxuZXhwb3J0IGNsYXNzIE5hdkFjdGlvbnNDb2x1bW5Db21wb25lbnQ8VCBleHRlbmRzIFRhYmxlRWxlbWVudDxhbnk+IHwgQXN5bmNUYWJsZUVsZW1lbnQ8YW55PiA9IFRhYmxlRWxlbWVudDxhbnk+PiBpbXBsZW1lbnRzIE9uSW5pdCwgT25EZXN0cm95IHtcbiAgX3N1YnNjcmlwdGlvbiA9IG5ldyBTdWJzY3JpcHRpb24oKTtcbiAgX2ZvcndhcmRFdmVudFN1YmplY3QgPSBuZXcgU3ViamVjdDx7IGV2ZW50OiBFdmVudDsgcm93OiBUIH0+KCk7XG4gIF9iYWNrd2FyZEV2ZW50U3ViamVjdCA9IG5ldyBTdWJqZWN0PHsgZXZlbnQ6IEV2ZW50OyByb3c6IFQgfT4oKTtcblxuICBAVmlld0NoaWxkKE1hdENvbHVtbkRlZikgY29sdW1uRGVmOiBNYXRDb2x1bW5EZWY7XG4gIEBWaWV3Q2hpbGQoTWF0TWVudVRyaWdnZXIpIG1hdE1lbnVUcmlnZ2VyOiBNYXRNZW51VHJpZ2dlcjtcblxuICBASW5wdXQoKSBhcHBUYWJsZTogQXBwVGFibGU8YW55PiB8IEFwcEFzeW5jVGFibGU8YW55PjtcbiAgQElucHV0KCkgbWF0Q29sdW1uRGVmID0gJ2FjdGlvbnMnO1xuICBASW5wdXQoKSBzdHlsZTogJ3RhYmxlJyB8ICdtYXQtdGFibGUnID0gJ3RhYmxlJztcbiAgQElucHV0KHsgdHJhbnNmb3JtOiBib29sZWFuQXR0cmlidXRlIH0pIHN0aWNreUVuZCA9IGZhbHNlO1xuICBASW5wdXQoeyB0cmFuc2Zvcm06IGJvb2xlYW5BdHRyaWJ1dGUgfSkgc2hvd1BlbmRpbmc6IGJvb2xlYW47XG4gIEBJbnB1dCgpIGRpcnR5SWNvbjogYm9vbGVhbiB8IHN0cmluZztcbiAgQElucHV0KCkgb3B0aW9uc1RpdGxlID0gJ0NPTU1PTi5CVE5fT1BUSU9OUyc7XG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAYW5ndWxhci1lc2xpbnQvbm8taW5wdXQtcmVuYW1lXG4gIEBJbnB1dCgnY2xhc3MnKSBjbGFzc0xpc3Q6IHN0cmluZztcbiAgQElucHV0KCkgY2VsbFRlbXBsYXRlOiBUZW1wbGF0ZVJlZjx7ICRpbXBsaWNpdDogVCB9PjtcbiAgQElucHV0KCkgdGhyb3R0bGVUaW1lID0gMjUwO1xuXG4gIEBPdXRwdXQoKSBvcHRpb25zQ2xpY2sgPSBuZXcgRXZlbnRFbWl0dGVyPEV2ZW50PigpO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgbWF0VGFibGU6IE1hdFRhYmxlPGFueT4sXG4gICAgcHJpdmF0ZSBjZDogQ2hhbmdlRGV0ZWN0b3JSZWYsXG4gICAgQE9wdGlvbmFsKCkgYXBwVGFibGU6IEFwcFRhYmxlPGFueT4sXG4gICAgQE9wdGlvbmFsKCkgYXBwQXN5bmNUYWJsZTogQXBwQXN5bmNUYWJsZTxhbnk+XG4gICkge1xuICAgIGlmICghbWF0VGFibGUpIHRocm93IG5ldyBFcnJvcihgW2FjdGlvbnMtY29sdW1uXSB0aGlzIGNvbHVtbiBjb21wb25lbnQgbXVzdCBiZSBpbnNpZGUgYSBNYXRUYWJsZSBjb21wb25lbnRgKTtcbiAgICB0aGlzLmFwcFRhYmxlID0gYXBwVGFibGUgPz8gYXBwQXN5bmNUYWJsZTtcbiAgICB0aGlzLl9zdWJzY3JpcHRpb24gPSBuZXcgU3Vic2NyaXB0aW9uKCk7XG4gIH1cblxuICBuZ09uSW5pdCgpOiB2b2lkIHtcbiAgICAvLyBEZWZhdWx0IHZhbHVlc1xuICAgIHRoaXMuc2hvd1BlbmRpbmcgPSB0aGlzLnNob3dQZW5kaW5nID8/IHRydWU7XG4gICAgdGhpcy5kaXJ0eUljb24gPSB0aGlzLmRpcnR5SWNvbiA9PT0gdHJ1ZSA/ICdzdGFyJyA6IHRoaXMuZGlydHlJY29uID09PSBmYWxzZSA/IG51bGwgOiB0aGlzLmRpcnR5SWNvbiA/PyAnc3Rhcic7XG5cbiAgICB0aGlzLmNkLmRldGVjdENoYW5nZXMoKTtcbiAgICB0aGlzLm1hdFRhYmxlLmFkZENvbHVtbkRlZih0aGlzLmNvbHVtbkRlZik7XG5cbiAgICBpZiAoIXRoaXMuYXBwVGFibGUpXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYFtuYXYtYWN0aW9ucy1jb2x1bW5dIE5vIEFwcFRhYmxlIG9yIEFwcEFzeW5jVGFibGUgZm91bmQuIFBsZWFzZSBkZWZpbmUgYSBwcm92aWRlciBvciBzZXQgaW5wdXQgJ1thcHBUYWJsZV0nYCk7XG5cbiAgICB0aGlzLl9zdWJzY3JpcHRpb24uYWRkKFxuICAgICAgdGhpcy5fZm9yd2FyZEV2ZW50U3ViamVjdFxuICAgICAgICAucGlwZShcbiAgICAgICAgICB0aHJvdHRsZVRpbWUodGhpcy50aHJvdHRsZVRpbWUpIC8vIEF2b2lkIHRvbyBtYW55IGV2ZW50LCB3aGVuIGxlYXZpbmcgVGFiIGtleSBwcmVzc2VkXG4gICAgICAgIClcbiAgICAgICAgLnN1YnNjcmliZSgoeyBldmVudCwgcm93IH0pID0+IHRoaXMuYXBwVGFibGUuY29uZmlybUFuZEZvcndhcmQoZXZlbnQsIHJvdyBhcyBhbnkpKVxuICAgICk7XG5cbiAgICB0aGlzLl9zdWJzY3JpcHRpb24uYWRkKFxuICAgICAgdGhpcy5fYmFja3dhcmRFdmVudFN1YmplY3RcbiAgICAgICAgLnBpcGUoXG4gICAgICAgICAgdGhyb3R0bGVUaW1lKHRoaXMudGhyb3R0bGVUaW1lKSAvLyBBdm9pZCB0b28gbWFueSBldmVudCwgd2hlbiBsZWF2aW5nIEJhY2stVGFiIGtleSBwcmVzc2VkXG4gICAgICAgIClcbiAgICAgICAgLnN1YnNjcmliZSgoeyBldmVudCwgcm93IH0pID0+IHRoaXMuYXBwVGFibGUuY29uZmlybUFuZEJhY2t3YXJkKGV2ZW50LCByb3cgYXMgYW55KSlcbiAgICApO1xuICB9XG5cbiAgbmdPbkRlc3Ryb3koKSB7XG4gICAgdGhpcy5tYXRUYWJsZS5yZW1vdmVDb2x1bW5EZWYodGhpcy5jb2x1bW5EZWYpO1xuICAgIHRoaXMub3B0aW9uc0NsaWNrLmNvbXBsZXRlKCk7XG4gICAgdGhpcy5vcHRpb25zQ2xpY2sudW5zdWJzY3JpYmUoKTtcbiAgICB0aGlzLl9zdWJzY3JpcHRpb24udW5zdWJzY3JpYmUoKTtcbiAgfVxuXG4gIHByb3RlY3RlZCBjYW5jZWxPckRlbGV0ZShldmVudDogRXZlbnQsIHJvdzogVCkge1xuICAgIHRoaXMuYXBwVGFibGUuY2FuY2VsT3JEZWxldGUoZXZlbnQsIHJvdyBhcyBhbnkpO1xuICB9XG5cbiAgcHJvdGVjdGVkIGNvbmZpcm1BbmRGb3J3YXJkKGV2ZW50OiBFdmVudCwgcm93OiBUKSB7XG4gICAgdGhpcy5fZm9yd2FyZEV2ZW50U3ViamVjdC5uZXh0KHsgZXZlbnQsIHJvdyB9KTtcbiAgfVxuXG4gIHByb3RlY3RlZCBjb25maXJtQW5kQmFja3dhcmQoZXZlbnQ6IEV2ZW50LCByb3c6IFQpIHtcbiAgICB0aGlzLl9iYWNrd2FyZEV2ZW50U3ViamVjdC5uZXh0KHsgZXZlbnQsIHJvdyB9KTtcbiAgfVxufVxuIiwiPG5nLWNvbnRhaW5lciBbbWF0Q29sdW1uRGVmXT1cIm1hdENvbHVtbkRlZlwiIFtzdGlja3lFbmRdPVwic3RpY2t5RW5kXCIgW25nU3dpdGNoXT1cInN0eWxlXCI+XG4gIDxuZy1jb250YWluZXIgKm5nU3dpdGNoQ2FzZT1cIid0YWJsZSdcIj5cbiAgICA8dGggbWF0LWhlYWRlci1jZWxsICptYXRIZWFkZXJDZWxsRGVmIFtjbGFzc109XCJjbGFzc0xpc3RcIiBbY2xhc3MubWF0LWNvbHVtbi1zdGlja3ldPVwic3RpY2t5RW5kXCI+XG4gICAgICA8YnV0dG9uXG4gICAgICAgIG1hdC1pY29uLWJ1dHRvblxuICAgICAgICAqbmdJZj1cIm9wdGlvbnNDbGljay5vYnNlcnZlZFwiXG4gICAgICAgIFt0aXRsZV09XCJvcHRpb25zVGl0bGUgfCB0cmFuc2xhdGVcIlxuICAgICAgICAoY2xpY2spPVwib3B0aW9uc0NsaWNrLmVtaXQoJGV2ZW50KVwiXG4gICAgICA+XG4gICAgICAgIDxtYXQtaWNvbj5tb3JlX3ZlcnQ8L21hdC1pY29uPlxuICAgICAgPC9idXR0b24+XG4gICAgICA8bmctY29udGVudCBzZWxlY3Q9XCJbbWF0SGVhZGVyXVwiPjwvbmctY29udGVudD5cbiAgICA8L3RoPlxuICAgIDx0ZCBtYXQtY2VsbCAqbWF0Q2VsbERlZj1cImxldCByb3dcIiBbY2xhc3NdPVwiY2xhc3NMaXN0XCI+XG4gICAgICBAaWYgKHJvdy5lZGl0aW5nKSB7XG4gICAgICAgIDwhLS0gcGVuZGluZyAtLT5cbiAgICAgICAgQGlmIChyb3cudmFsaWRhdG9yPy5wZW5kaW5nKSB7XG4gICAgICAgICAgPGlvbi1zcGlubmVyIFtjbGFzcy5jZGstdmlzdWFsbHktaGlkZGVuXT1cIiFzaG93UGVuZGluZ1wiIG5hbWU9XCJkb3RzXCIgY2xhc3M9XCJjZW50ZXJcIj48L2lvbi1zcGlubmVyPlxuICAgICAgICB9XG5cbiAgICAgICAgPCEtLSBpbnZhbGlkIG5ldyByb3cgLS0+XG4gICAgICAgIEBpZiAocm93LmlkID09PSAtMSAmJiByb3cudmFsaWRhdG9yPy5pbnZhbGlkKSB7XG4gICAgICAgICAgPCEtLSBkZWxldGUgYnV0dG9uIC0tPlxuICAgICAgICAgIDxidXR0b25cbiAgICAgICAgICAgIG1hdC1pY29uLWJ1dHRvblxuICAgICAgICAgICAgY29sb3I9XCJsaWdodFwiXG4gICAgICAgICAgICBbdGl0bGVdPVwiJ0NPTU1PTi5CVE5fREVMRVRFJyB8IHRyYW5zbGF0ZVwiXG4gICAgICAgICAgICAoY2xpY2spPVwiY2FuY2VsT3JEZWxldGUoJGV2ZW50LCByb3cpXCJcbiAgICAgICAgICA+XG4gICAgICAgICAgICA8bWF0LWljb24+ZGVsZXRlX291dGxpbmU8L21hdC1pY29uPlxuICAgICAgICAgIDwvYnV0dG9uPlxuXG4gICAgICAgICAgPCEtLSB2YWxpZCByb3cgb3IgaW52YWxpZCBleGlzdGluZyByb3cgLS0+XG4gICAgICAgIH0gQGVsc2Uge1xuICAgICAgICAgIDwhLS0gZm9yd2FyZCBidXR0b24gKGludmlzaWJsZSAtIGZvY3VzYWJsZSBvbmx5KSAtLT5cbiAgICAgICAgICA8YnV0dG9uIGNsYXNzPVwibWF0LXJvdy1hY3Rpb24tYnV0dG9uLW5hdmlnYXRpb25cIiAoZm9jdXMpPVwiY29uZmlybUFuZEZvcndhcmQoJGV2ZW50LCByb3cpXCI+PC9idXR0b24+XG4gICAgICAgIH1cblxuICAgICAgICA8IS0tIE5PVCBlZGl0aW5nIHJvdyAtLT5cbiAgICAgIH0gQGVsc2Uge1xuICAgICAgICA8IS0tIGRpcnR5IGljb24gLS0+XG4gICAgICAgIEBpZiAoZGlydHlJY29uICYmIHJvdy52YWxpZGF0b3I/LmRpcnR5KSB7XG4gICAgICAgICAgPGlvbi1pY29uIFtuYW1lXT1cImRpcnR5SWNvblwiIGNvbG9yPVwiYWNjZW50XCIgY2xhc3M9XCJkaXJ0eS1pY29uXCIgdGFiaW5kZXg9XCItMVwiPjwvaW9uLWljb24+XG4gICAgICAgIH1cblxuICAgICAgICA8IS0tIGJhY2t3YXJkIGJ1dHRvbiAoaW52aXNpYmxlIC0gZm9jdXNhYmxlIG9ubHkpIC0tPlxuICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgbWF0LWljb24tYnV0dG9uXG4gICAgICAgICAgY2xhc3M9XCJtYXQtcm93LWFjdGlvbi1idXR0b24tbmF2aWdhdGlvblwiXG4gICAgICAgICAgKGZvY3VzKT1cImNvbmZpcm1BbmRCYWNrd2FyZCgkZXZlbnQsIHJvdylcIlxuICAgICAgICA+PC9idXR0b24+XG4gICAgICB9XG5cbiAgICAgIDxuZy1jb250YWluZXIgKm5nVGVtcGxhdGVPdXRsZXQ9XCJjZWxsVGVtcGxhdGU7IGNvbnRleHQ6IHsgJGltcGxpY2l0OiByb3cgfVwiPjwvbmctY29udGFpbmVyPlxuICAgIDwvdGQ+XG5cbiAgICA8dGQgbWF0LWZvb3Rlci1jZWxsICptYXRGb290ZXJDZWxsRGVmPlxuICAgICAgPG5nLWNvbnRlbnQgc2VsZWN0PVwiW21hdEZvb3Rlcl1cIj48L25nLWNvbnRlbnQ+XG4gICAgPC90ZD5cbiAgPC9uZy1jb250YWluZXI+XG5cbiAgPG5nLWNvbnRhaW5lciAqbmdTd2l0Y2hDYXNlPVwiJ21hdC10YWJsZSdcIj5cbiAgICA8bWF0LWhlYWRlci1jZWxsICptYXRIZWFkZXJDZWxsRGVmIFtjbGFzc109XCJjbGFzc0xpc3RcIiBbY2xhc3MubWF0LWNvbHVtbi1zdGlja3ldPVwic3RpY2t5RW5kXCI+XG4gICAgICA8YnV0dG9uXG4gICAgICAgIG1hdC1pY29uLWJ1dHRvblxuICAgICAgICAqbmdJZj1cIm9wdGlvbnNDbGljay5vYnNlcnZlZFwiXG4gICAgICAgIFt0aXRsZV09XCJvcHRpb25zVGl0bGUgfCB0cmFuc2xhdGVcIlxuICAgICAgICAoY2xpY2spPVwib3B0aW9uc0NsaWNrLmVtaXQoJGV2ZW50KVwiXG4gICAgICA+XG4gICAgICAgIDxtYXQtaWNvbj5tb3JlX3ZlcnQ8L21hdC1pY29uPlxuICAgICAgPC9idXR0b24+XG4gICAgICA8bmctY29udGVudCBzZWxlY3Q9XCJbbWF0SGVhZGVyXVwiPjwvbmctY29udGVudD5cbiAgICA8L21hdC1oZWFkZXItY2VsbD5cbiAgICA8bWF0LWNlbGwgKm1hdENlbGxEZWY9XCJsZXQgcm93XCIgW2NsYXNzXT1cImNsYXNzTGlzdFwiPlxuICAgICAgQGlmIChyb3cuZWRpdGluZykge1xuICAgICAgICA8IS0tIHBlbmRpbmcgLS0+XG4gICAgICAgIEBpZiAocm93LnZhbGlkYXRvcj8ucGVuZGluZykge1xuICAgICAgICAgIDxpb24tc3Bpbm5lciBbY2xhc3MuY2RrLXZpc3VhbGx5LWhpZGRlbl09XCIhc2hvd1BlbmRpbmdcIiBuYW1lPVwiZG90c1wiIGNsYXNzPVwiY2VudGVyXCI+PC9pb24tc3Bpbm5lcj5cbiAgICAgICAgfVxuXG4gICAgICAgIDwhLS0gaW52YWxpZCBuZXcgcm93IC0tPlxuICAgICAgICBAaWYgKHJvdy5pZCA9PT0gLTEgJiYgcm93LnZhbGlkYXRvcj8uaW52YWxpZCkge1xuICAgICAgICAgIDwhLS0gZGVsZXRlIGJ1dHRvbiAtLT5cbiAgICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgICBtYXQtaWNvbi1idXR0b25cbiAgICAgICAgICAgIGNvbG9yPVwibGlnaHRcIlxuICAgICAgICAgICAgW3RpdGxlXT1cIidDT01NT04uQlROX0RFTEVURScgfCB0cmFuc2xhdGVcIlxuICAgICAgICAgICAgKGNsaWNrKT1cImNhbmNlbE9yRGVsZXRlKCRldmVudCwgcm93KVwiXG4gICAgICAgICAgPlxuICAgICAgICAgICAgPG1hdC1pY29uPmRlbGV0ZV9vdXRsaW5lPC9tYXQtaWNvbj5cbiAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgfSBAZWxzZSB7XG4gICAgICAgICAgPCEtLSBmb3J3YXJkIGJ1dHRvbiAoaW52aXNpYmxlIC0gZm9jdXNhYmxlIG9ubHkpIC0tPlxuICAgICAgICAgIDxidXR0b24gY2xhc3M9XCJtYXQtcm93LWFjdGlvbi1idXR0b24tbmF2aWdhdGlvblwiIChmb2N1cyk9XCJjb25maXJtQW5kRm9yd2FyZCgkZXZlbnQsIHJvdylcIj48L2J1dHRvbj5cbiAgICAgICAgfVxuXG4gICAgICAgIDwhLS0gbm90IGVkaXRpbmcgcm93IC0tPlxuICAgICAgfSBAZWxzZSB7XG4gICAgICAgIDwhLS0gZGlydHkgaWNvbiAtLT5cbiAgICAgICAgQGlmIChkaXJ0eUljb24gJiYgcm93LnZhbGlkYXRvcj8uZGlydHkpIHtcbiAgICAgICAgICA8aW9uLWljb24gW25hbWVdPVwiZGlydHlJY29uXCIgY29sb3I9XCJhY2NlbnRcIiBjbGFzcz1cImRpcnR5LWljb25cIj48L2lvbi1pY29uPlxuICAgICAgICB9XG5cbiAgICAgICAgPCEtLSBiYWNrd2FyZCBidXR0b24gKGludmlzaWJsZSAtIGZvY3VzYWJsZSBvbmx5KSAtLT5cbiAgICAgICAgPGJ1dHRvblxuICAgICAgICAgIG1hdC1pY29uLWJ1dHRvblxuICAgICAgICAgIGNsYXNzPVwibWF0LXJvdy1hY3Rpb24tYnV0dG9uLW5hdmlnYXRpb25cIlxuICAgICAgICAgIChmb2N1cyk9XCJjb25maXJtQW5kQmFja3dhcmQoJGV2ZW50LCByb3cpXCJcbiAgICAgICAgPjwvYnV0dG9uPlxuICAgICAgfVxuXG4gICAgICA8bmctY29udGFpbmVyICpuZ1RlbXBsYXRlT3V0bGV0PVwiY2VsbFRlbXBsYXRlOyBjb250ZXh0OiB7ICRpbXBsaWNpdDogcm93IH1cIj48L25nLWNvbnRhaW5lcj5cbiAgICA8L21hdC1jZWxsPlxuXG4gICAgPG1hdC1mb290ZXItY2VsbCAqbWF0Rm9vdGVyQ2VsbERlZj5cbiAgICAgIDxuZy1jb250ZW50IHNlbGVjdD1cIlttYXRGb290ZXJdXCI+PC9uZy1jb250ZW50PlxuICAgIDwvbWF0LWZvb3Rlci1jZWxsPlxuICA8L25nLWNvbnRhaW5lcj5cbjwvbmctY29udGFpbmVyPlxuIl19
117
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmF2LWFjdGlvbnMtY29sdW1uLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uLy4uL3NyYy9hcHAvY29yZS90YWJsZS9jb2x1bW4vbmF2LWFjdGlvbnMtY29sdW1uLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uLy4uLy4uL3NyYy9hcHAvY29yZS90YWJsZS9jb2x1bW4vbmF2LWFjdGlvbnMtY29sdW1uLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFDTCxnQkFBZ0IsRUFDaEIsdUJBQXVCLEVBRXZCLFNBQVMsRUFDVCxZQUFZLEVBQ1osS0FBSyxFQUdMLFFBQVEsRUFDUixNQUFNLEVBRU4sU0FBUyxHQUNWLE1BQU0sZUFBZSxDQUFDO0FBRXZCLE9BQU8sRUFBRSxZQUFZLEVBQVksTUFBTSx5QkFBeUIsQ0FBQztBQUNqRSxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFHeEQsT0FBTyxFQUFFLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDN0MsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLGdCQUFnQixDQUFDOzs7Ozs7Ozs7O0FBUTlDLE1BQU0sT0FBTyx5QkFBeUI7SUF1QjFCO0lBQ0E7SUF2QlYsYUFBYSxHQUFHLElBQUksWUFBWSxFQUFFLENBQUM7SUFDbkMsb0JBQW9CLEdBQUcsSUFBSSxPQUFPLEVBQTRCLENBQUM7SUFDL0QscUJBQXFCLEdBQUcsSUFBSSxPQUFPLEVBQTRCLENBQUM7SUFFdkMsU0FBUyxDQUFlO0lBQ3RCLGNBQWMsQ0FBaUI7SUFFakQsUUFBUSxDQUFxQztJQUM3QyxZQUFZLEdBQUcsU0FBUyxDQUFDO0lBQ3pCLEtBQUssR0FBMEIsT0FBTyxDQUFDO0lBQ1IsU0FBUyxHQUFHLEtBQUssQ0FBQztJQUNsQixXQUFXLENBQVU7SUFDcEQsU0FBUyxDQUFtQjtJQUM1QixZQUFZLEdBQUcsb0JBQW9CLENBQUM7SUFDN0MsMkRBQTJEO0lBQzNDLFNBQVMsQ0FBUztJQUN6QixZQUFZLENBQWdDO0lBQzVDLFlBQVksR0FBRyxHQUFHLENBQUM7SUFFbEIsWUFBWSxHQUFHLElBQUksWUFBWSxFQUFTLENBQUM7SUFFbkQsWUFDVSxRQUF1QixFQUN2QixFQUFxQixFQUNqQixRQUF1QixFQUN2QixhQUFpQztRQUhyQyxhQUFRLEdBQVIsUUFBUSxDQUFlO1FBQ3ZCLE9BQUUsR0FBRixFQUFFLENBQW1CO1FBSTdCLElBQUksQ0FBQyxRQUFRO1lBQUUsTUFBTSxJQUFJLEtBQUssQ0FBQyw0RUFBNEUsQ0FBQyxDQUFDO1FBQzdHLElBQUksQ0FBQyxRQUFRLEdBQUcsUUFBUSxJQUFJLGFBQWEsQ0FBQztRQUMxQyxJQUFJLENBQUMsYUFBYSxHQUFHLElBQUksWUFBWSxFQUFFLENBQUM7SUFDMUMsQ0FBQztJQUVELFFBQVE7UUFDTixpQkFBaUI7UUFDakIsSUFBSSxDQUFDLFdBQVcsR0FBRyxJQUFJLENBQUMsV0FBVyxJQUFJLElBQUksQ0FBQztRQUM1QyxJQUFJLENBQUMsU0FBUyxHQUFHLElBQUksQ0FBQyxTQUFTLEtBQUssSUFBSSxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEtBQUssS0FBSyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLElBQUksTUFBTSxDQUFDO1FBRS9HLElBQUksQ0FBQyxFQUFFLENBQUMsYUFBYSxFQUFFLENBQUM7UUFDeEIsSUFBSSxDQUFDLFFBQVEsQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDO1FBRTNDLElBQUksQ0FBQyxJQUFJLENBQUMsUUFBUTtZQUNoQixNQUFNLElBQUksS0FBSyxDQUFDLDZHQUE2RyxDQUFDLENBQUM7UUFFakksSUFBSSxDQUFDLGFBQWEsQ0FBQyxHQUFHLENBQ3BCLElBQUksQ0FBQyxvQkFBb0I7YUFDdEIsSUFBSSxDQUNILFlBQVksQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLENBQUMscURBQXFEO1NBQ3RGO2FBQ0EsU0FBUyxDQUFDLENBQUMsRUFBRSxLQUFLLEVBQUUsR0FBRyxFQUFFLEVBQUUsRUFBRSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsaUJBQWlCLENBQUMsS0FBSyxFQUFFLEdBQVUsQ0FBQyxDQUFDLENBQ3JGLENBQUM7UUFFRixJQUFJLENBQUMsYUFBYSxDQUFDLEdBQUcsQ0FDcEIsSUFBSSxDQUFDLHFCQUFxQjthQUN2QixJQUFJLENBQ0gsWUFBWSxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsQ0FBQywwREFBMEQ7U0FDM0Y7YUFDQSxTQUFTLENBQUMsQ0FBQyxFQUFFLEtBQUssRUFBRSxHQUFHLEVBQUUsRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxrQkFBa0IsQ0FBQyxLQUFLLEVBQUUsR0FBVSxDQUFDLENBQUMsQ0FDdEYsQ0FBQztJQUNKLENBQUM7SUFFRCxXQUFXO1FBQ1QsSUFBSSxDQUFDLFFBQVEsQ0FBQyxlQUFlLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDO1FBQzlDLElBQUksQ0FBQyxZQUFZLENBQUMsUUFBUSxFQUFFLENBQUM7UUFDN0IsSUFBSSxDQUFDLFlBQVksQ0FBQyxXQUFXLEVBQUUsQ0FBQztRQUNoQyxJQUFJLENBQUMsYUFBYSxDQUFDLFdBQVcsRUFBRSxDQUFDO0lBQ25DLENBQUM7SUFFUyxjQUFjLENBQUMsS0FBWSxFQUFFLEdBQU07UUFDM0MsSUFBSSxDQUFDLFFBQVEsQ0FBQyxjQUFjLENBQUMsS0FBSyxFQUFFLEdBQVUsQ0FBQyxDQUFDO0lBQ2xELENBQUM7SUFFUyxpQkFBaUIsQ0FBQyxLQUFZLEVBQUUsR0FBTTtRQUM5QyxJQUFJLENBQUMsb0JBQW9CLENBQUMsSUFBSSxDQUFDLEVBQUUsS0FBSyxFQUFFLEdBQUcsRUFBRSxDQUFDLENBQUM7SUFDakQsQ0FBQztJQUVTLGtCQUFrQixDQUFDLEtBQVksRUFBRSxHQUFNO1FBQy9DLElBQUksQ0FBQyxxQkFBcUIsQ0FBQyxJQUFJLENBQUMsRUFBRSxLQUFLLEVBQUUsR0FBRyxFQUFFLENBQUMsQ0FBQztJQUNsRCxDQUFDO3VHQTlFVSx5QkFBeUI7MkZBQXpCLHlCQUF5QiwwSkFXaEIsZ0JBQWdCLCtDQUNoQixnQkFBZ0Isd1FBUHpCLFlBQVksaUZBQ1osY0FBYyxnRENsQzNCLCt3SUF1SEE7OzJGRDNGYSx5QkFBeUI7a0JBTnJDLFNBQVM7K0JBQ0Usd0JBQXdCLG1CQUdqQix1QkFBdUIsQ0FBQyxNQUFNOzswQkEyQjVDLFFBQVE7OzBCQUNSLFFBQVE7eUNBckJjLFNBQVM7c0JBQWpDLFNBQVM7dUJBQUMsWUFBWTtnQkFDSSxjQUFjO3NCQUF4QyxTQUFTO3VCQUFDLGNBQWM7Z0JBRWhCLFFBQVE7c0JBQWhCLEtBQUs7Z0JBQ0csWUFBWTtzQkFBcEIsS0FBSztnQkFDRyxLQUFLO3NCQUFiLEtBQUs7Z0JBQ2tDLFNBQVM7c0JBQWhELEtBQUs7dUJBQUMsRUFBRSxTQUFTLEVBQUUsZ0JBQWdCLEVBQUU7Z0JBQ0UsV0FBVztzQkFBbEQsS0FBSzt1QkFBQyxFQUFFLFNBQVMsRUFBRSxnQkFBZ0IsRUFBRTtnQkFDN0IsU0FBUztzQkFBakIsS0FBSztnQkFDRyxZQUFZO3NCQUFwQixLQUFLO2dCQUVVLFNBQVM7c0JBQXhCLEtBQUs7dUJBQUMsT0FBTztnQkFDTCxZQUFZO3NCQUFwQixLQUFLO2dCQUNHLFlBQVk7c0JBQXBCLEtBQUs7Z0JBRUksWUFBWTtzQkFBckIsTUFBTSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIGJvb2xlYW5BdHRyaWJ1dGUsXG4gIENoYW5nZURldGVjdGlvblN0cmF0ZWd5LFxuICBDaGFuZ2VEZXRlY3RvclJlZixcbiAgQ29tcG9uZW50LFxuICBFdmVudEVtaXR0ZXIsXG4gIElucHV0LFxuICBPbkRlc3Ryb3ksXG4gIE9uSW5pdCxcbiAgT3B0aW9uYWwsXG4gIE91dHB1dCxcbiAgVGVtcGxhdGVSZWYsXG4gIFZpZXdDaGlsZCxcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBBc3luY1RhYmxlRWxlbWVudCwgVGFibGVFbGVtZW50IH0gZnJvbSAnQGUtaXMvbmd4LW1hdGVyaWFsLXRhYmxlJztcbmltcG9ydCB7IE1hdENvbHVtbkRlZiwgTWF0VGFibGUgfSBmcm9tICdAYW5ndWxhci9tYXRlcmlhbC90YWJsZSc7XG5pbXBvcnQgeyBNYXRNZW51VHJpZ2dlciB9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL21lbnUnO1xuaW1wb3J0IHsgQXBwVGFibGUgfSBmcm9tICcuLi90YWJsZS5jbGFzcyc7XG5pbXBvcnQgeyBBcHBBc3luY1RhYmxlIH0gZnJvbSAnLi4vYXN5bmMtdGFibGUuY2xhc3MnO1xuaW1wb3J0IHsgU3ViamVjdCwgU3Vic2NyaXB0aW9uIH0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyB0aHJvdHRsZVRpbWUgfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ2FwcC1uYXYtYWN0aW9ucy1jb2x1bW4nLFxuICBzdHlsZVVybHM6IFsnLi9hY3Rpb25zLWNvbHVtbi5jb21wb25lbnQuc2NzcyddLFxuICB0ZW1wbGF0ZVVybDogJy4vbmF2LWFjdGlvbnMtY29sdW1uLmNvbXBvbmVudC5odG1sJyxcbiAgY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2gsXG59KVxuZXhwb3J0IGNsYXNzIE5hdkFjdGlvbnNDb2x1bW5Db21wb25lbnQ8VCBleHRlbmRzIFRhYmxlRWxlbWVudDxhbnk+IHwgQXN5bmNUYWJsZUVsZW1lbnQ8YW55PiA9IFRhYmxlRWxlbWVudDxhbnk+PiBpbXBsZW1lbnRzIE9uSW5pdCwgT25EZXN0cm95IHtcbiAgX3N1YnNjcmlwdGlvbiA9IG5ldyBTdWJzY3JpcHRpb24oKTtcbiAgX2ZvcndhcmRFdmVudFN1YmplY3QgPSBuZXcgU3ViamVjdDx7IGV2ZW50OiBFdmVudDsgcm93OiBUIH0+KCk7XG4gIF9iYWNrd2FyZEV2ZW50U3ViamVjdCA9IG5ldyBTdWJqZWN0PHsgZXZlbnQ6IEV2ZW50OyByb3c6IFQgfT4oKTtcblxuICBAVmlld0NoaWxkKE1hdENvbHVtbkRlZikgY29sdW1uRGVmOiBNYXRDb2x1bW5EZWY7XG4gIEBWaWV3Q2hpbGQoTWF0TWVudVRyaWdnZXIpIG1hdE1lbnVUcmlnZ2VyOiBNYXRNZW51VHJpZ2dlcjtcblxuICBASW5wdXQoKSBhcHBUYWJsZTogQXBwVGFibGU8YW55PiB8IEFwcEFzeW5jVGFibGU8YW55PjtcbiAgQElucHV0KCkgbWF0Q29sdW1uRGVmID0gJ2FjdGlvbnMnO1xuICBASW5wdXQoKSBzdHlsZTogJ3RhYmxlJyB8ICdtYXQtdGFibGUnID0gJ3RhYmxlJztcbiAgQElucHV0KHsgdHJhbnNmb3JtOiBib29sZWFuQXR0cmlidXRlIH0pIHN0aWNreUVuZCA9IGZhbHNlO1xuICBASW5wdXQoeyB0cmFuc2Zvcm06IGJvb2xlYW5BdHRyaWJ1dGUgfSkgc2hvd1BlbmRpbmc6IGJvb2xlYW47XG4gIEBJbnB1dCgpIGRpcnR5SWNvbjogYm9vbGVhbiB8IHN0cmluZztcbiAgQElucHV0KCkgb3B0aW9uc1RpdGxlID0gJ0NPTU1PTi5CVE5fT1BUSU9OUyc7XG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAYW5ndWxhci1lc2xpbnQvbm8taW5wdXQtcmVuYW1lXG4gIEBJbnB1dCgnY2xhc3MnKSBjbGFzc0xpc3Q6IHN0cmluZztcbiAgQElucHV0KCkgY2VsbFRlbXBsYXRlOiBUZW1wbGF0ZVJlZjx7ICRpbXBsaWNpdDogVCB9PjtcbiAgQElucHV0KCkgdGhyb3R0bGVUaW1lID0gMjUwO1xuXG4gIEBPdXRwdXQoKSBvcHRpb25zQ2xpY2sgPSBuZXcgRXZlbnRFbWl0dGVyPEV2ZW50PigpO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgbWF0VGFibGU6IE1hdFRhYmxlPGFueT4sXG4gICAgcHJpdmF0ZSBjZDogQ2hhbmdlRGV0ZWN0b3JSZWYsXG4gICAgQE9wdGlvbmFsKCkgYXBwVGFibGU6IEFwcFRhYmxlPGFueT4sXG4gICAgQE9wdGlvbmFsKCkgYXBwQXN5bmNUYWJsZTogQXBwQXN5bmNUYWJsZTxhbnk+XG4gICkge1xuICAgIGlmICghbWF0VGFibGUpIHRocm93IG5ldyBFcnJvcihgW2FjdGlvbnMtY29sdW1uXSB0aGlzIGNvbHVtbiBjb21wb25lbnQgbXVzdCBiZSBpbnNpZGUgYSBNYXRUYWJsZSBjb21wb25lbnRgKTtcbiAgICB0aGlzLmFwcFRhYmxlID0gYXBwVGFibGUgPz8gYXBwQXN5bmNUYWJsZTtcbiAgICB0aGlzLl9zdWJzY3JpcHRpb24gPSBuZXcgU3Vic2NyaXB0aW9uKCk7XG4gIH1cblxuICBuZ09uSW5pdCgpOiB2b2lkIHtcbiAgICAvLyBEZWZhdWx0IHZhbHVlc1xuICAgIHRoaXMuc2hvd1BlbmRpbmcgPSB0aGlzLnNob3dQZW5kaW5nID8/IHRydWU7XG4gICAgdGhpcy5kaXJ0eUljb24gPSB0aGlzLmRpcnR5SWNvbiA9PT0gdHJ1ZSA/ICdzdGFyJyA6IHRoaXMuZGlydHlJY29uID09PSBmYWxzZSA/IG51bGwgOiB0aGlzLmRpcnR5SWNvbiA/PyAnc3Rhcic7XG5cbiAgICB0aGlzLmNkLmRldGVjdENoYW5nZXMoKTtcbiAgICB0aGlzLm1hdFRhYmxlLmFkZENvbHVtbkRlZih0aGlzLmNvbHVtbkRlZik7XG5cbiAgICBpZiAoIXRoaXMuYXBwVGFibGUpXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYFtuYXYtYWN0aW9ucy1jb2x1bW5dIE5vIEFwcFRhYmxlIG9yIEFwcEFzeW5jVGFibGUgZm91bmQuIFBsZWFzZSBkZWZpbmUgYSBwcm92aWRlciBvciBzZXQgaW5wdXQgJ1thcHBUYWJsZV0nYCk7XG5cbiAgICB0aGlzLl9zdWJzY3JpcHRpb24uYWRkKFxuICAgICAgdGhpcy5fZm9yd2FyZEV2ZW50U3ViamVjdFxuICAgICAgICAucGlwZShcbiAgICAgICAgICB0aHJvdHRsZVRpbWUodGhpcy50aHJvdHRsZVRpbWUpIC8vIEF2b2lkIHRvbyBtYW55IGV2ZW50LCB3aGVuIGxlYXZpbmcgVGFiIGtleSBwcmVzc2VkXG4gICAgICAgIClcbiAgICAgICAgLnN1YnNjcmliZSgoeyBldmVudCwgcm93IH0pID0+IHRoaXMuYXBwVGFibGUuY29uZmlybUFuZEZvcndhcmQoZXZlbnQsIHJvdyBhcyBhbnkpKVxuICAgICk7XG5cbiAgICB0aGlzLl9zdWJzY3JpcHRpb24uYWRkKFxuICAgICAgdGhpcy5fYmFja3dhcmRFdmVudFN1YmplY3RcbiAgICAgICAgLnBpcGUoXG4gICAgICAgICAgdGhyb3R0bGVUaW1lKHRoaXMudGhyb3R0bGVUaW1lKSAvLyBBdm9pZCB0b28gbWFueSBldmVudCwgd2hlbiBsZWF2aW5nIEJhY2stVGFiIGtleSBwcmVzc2VkXG4gICAgICAgIClcbiAgICAgICAgLnN1YnNjcmliZSgoeyBldmVudCwgcm93IH0pID0+IHRoaXMuYXBwVGFibGUuY29uZmlybUFuZEJhY2t3YXJkKGV2ZW50LCByb3cgYXMgYW55KSlcbiAgICApO1xuICB9XG5cbiAgbmdPbkRlc3Ryb3koKSB7XG4gICAgdGhpcy5tYXRUYWJsZS5yZW1vdmVDb2x1bW5EZWYodGhpcy5jb2x1bW5EZWYpO1xuICAgIHRoaXMub3B0aW9uc0NsaWNrLmNvbXBsZXRlKCk7XG4gICAgdGhpcy5vcHRpb25zQ2xpY2sudW5zdWJzY3JpYmUoKTtcbiAgICB0aGlzLl9zdWJzY3JpcHRpb24udW5zdWJzY3JpYmUoKTtcbiAgfVxuXG4gIHByb3RlY3RlZCBjYW5jZWxPckRlbGV0ZShldmVudDogRXZlbnQsIHJvdzogVCkge1xuICAgIHRoaXMuYXBwVGFibGUuY2FuY2VsT3JEZWxldGUoZXZlbnQsIHJvdyBhcyBhbnkpO1xuICB9XG5cbiAgcHJvdGVjdGVkIGNvbmZpcm1BbmRGb3J3YXJkKGV2ZW50OiBFdmVudCwgcm93OiBUKSB7XG4gICAgdGhpcy5fZm9yd2FyZEV2ZW50U3ViamVjdC5uZXh0KHsgZXZlbnQsIHJvdyB9KTtcbiAgfVxuXG4gIHByb3RlY3RlZCBjb25maXJtQW5kQmFja3dhcmQoZXZlbnQ6IEV2ZW50LCByb3c6IFQpIHtcbiAgICB0aGlzLl9iYWNrd2FyZEV2ZW50U3ViamVjdC5uZXh0KHsgZXZlbnQsIHJvdyB9KTtcbiAgfVxufVxuIiwiPG5nLWNvbnRhaW5lciBbbWF0Q29sdW1uRGVmXT1cIm1hdENvbHVtbkRlZlwiIFtzdGlja3lFbmRdPVwic3RpY2t5RW5kXCIgW25nU3dpdGNoXT1cInN0eWxlXCI+XG4gIDxuZy1jb250YWluZXIgKm5nU3dpdGNoQ2FzZT1cIid0YWJsZSdcIj5cbiAgICA8dGggbWF0LWhlYWRlci1jZWxsICptYXRIZWFkZXJDZWxsRGVmIFtjbGFzc109XCJjbGFzc0xpc3RcIiBbY2xhc3MubWF0LWNvbHVtbi1zdGlja3ldPVwic3RpY2t5RW5kXCI+XG4gICAgICA8YnV0dG9uXG4gICAgICAgIG1hdC1pY29uLWJ1dHRvblxuICAgICAgICAqbmdJZj1cIm9wdGlvbnNDbGljay5vYnNlcnZlZFwiXG4gICAgICAgIFt0aXRsZV09XCJvcHRpb25zVGl0bGUgfCB0cmFuc2xhdGVcIlxuICAgICAgICAoY2xpY2spPVwib3B0aW9uc0NsaWNrLmVtaXQoJGV2ZW50KVwiXG4gICAgICA+XG4gICAgICAgIDxtYXQtaWNvbj5tb3JlX3ZlcnQ8L21hdC1pY29uPlxuICAgICAgPC9idXR0b24+XG4gICAgICA8bmctY29udGVudCBzZWxlY3Q9XCJbbWF0SGVhZGVyXVwiPjwvbmctY29udGVudD5cbiAgICA8L3RoPlxuICAgIDx0ZCBtYXQtY2VsbCAqbWF0Q2VsbERlZj1cImxldCByb3dcIiBbY2xhc3NdPVwiY2xhc3NMaXN0XCI+XG4gICAgICBAaWYgKHJvdy5lZGl0aW5nKSB7XG4gICAgICAgIDwhLS0gcGVuZGluZyAtLT5cbiAgICAgICAgQGlmIChyb3cudmFsaWRhdG9yPy5wZW5kaW5nKSB7XG4gICAgICAgICAgPGlvbi1zcGlubmVyIFtjbGFzcy5jZGstdmlzdWFsbHktaGlkZGVuXT1cIiFzaG93UGVuZGluZ1wiIG5hbWU9XCJkb3RzXCIgY2xhc3M9XCJjZW50ZXJcIj48L2lvbi1zcGlubmVyPlxuICAgICAgICB9XG5cbiAgICAgICAgPCEtLSBpbnZhbGlkIG5ldyByb3cgLS0+XG4gICAgICAgIEBpZiAocm93LmlkID09PSAtMSAmJiByb3cudmFsaWRhdG9yPy5pbnZhbGlkKSB7XG4gICAgICAgICAgPCEtLSBkZWxldGUgYnV0dG9uIC0tPlxuICAgICAgICAgIDxidXR0b25cbiAgICAgICAgICAgIG1hdC1pY29uLWJ1dHRvblxuICAgICAgICAgICAgY29sb3I9XCJsaWdodFwiXG4gICAgICAgICAgICBbdGl0bGVdPVwiJ0NPTU1PTi5CVE5fREVMRVRFJyB8IHRyYW5zbGF0ZVwiXG4gICAgICAgICAgICAoY2xpY2spPVwiY2FuY2VsT3JEZWxldGUoJGV2ZW50LCByb3cpXCJcbiAgICAgICAgICA+XG4gICAgICAgICAgICA8bWF0LWljb24+ZGVsZXRlX291dGxpbmU8L21hdC1pY29uPlxuICAgICAgICAgIDwvYnV0dG9uPlxuXG4gICAgICAgICAgPCEtLSB2YWxpZCByb3cgb3IgaW52YWxpZCBleGlzdGluZyByb3cgLS0+XG4gICAgICAgIH0gQGVsc2Uge1xuICAgICAgICAgIDwhLS0gZm9yd2FyZCBidXR0b24gKGludmlzaWJsZSAtIGZvY3VzYWJsZSBvbmx5KSAtLT5cbiAgICAgICAgICA8YnV0dG9uIGNsYXNzPVwibWF0LXJvdy1hY3Rpb24tYnV0dG9uLW5hdmlnYXRpb25cIiAoZm9jdXMpPVwiY29uZmlybUFuZEZvcndhcmQoJGV2ZW50LCByb3cpXCI+PC9idXR0b24+XG4gICAgICAgIH1cblxuICAgICAgICA8IS0tIE5PVCBlZGl0aW5nIHJvdyAtLT5cbiAgICAgIH0gQGVsc2Uge1xuICAgICAgICA8IS0tIGRpcnR5IGljb24gLS0+XG4gICAgICAgIEBpZiAoZGlydHlJY29uICYmIHJvdy52YWxpZGF0b3I/LmRpcnR5KSB7XG4gICAgICAgICAgPGlvbi1pY29uIFtuYW1lXT1cImRpcnR5SWNvblwiIGNvbG9yPVwiYWNjZW50XCIgY2xhc3M9XCJkaXJ0eS1pY29uXCIgdGFiaW5kZXg9XCItMVwiPjwvaW9uLWljb24+XG4gICAgICAgIH1cblxuICAgICAgICA8IS0tIGJhY2t3YXJkIGJ1dHRvbiAoaW52aXNpYmxlIC0gZm9jdXNhYmxlIG9ubHkpIC0tPlxuICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgbWF0LWljb24tYnV0dG9uXG4gICAgICAgICAgY2xhc3M9XCJtYXQtcm93LWFjdGlvbi1idXR0b24tbmF2aWdhdGlvblwiXG4gICAgICAgICAgKGZvY3VzKT1cImNvbmZpcm1BbmRCYWNrd2FyZCgkZXZlbnQsIHJvdylcIlxuICAgICAgICA+PC9idXR0b24+XG4gICAgICB9XG5cbiAgICAgIDxuZy1jb250YWluZXIgKm5nVGVtcGxhdGVPdXRsZXQ9XCJjZWxsVGVtcGxhdGU7IGNvbnRleHQ6IHsgJGltcGxpY2l0OiByb3cgfVwiPjwvbmctY29udGFpbmVyPlxuICAgIDwvdGQ+XG5cbiAgICA8dGQgbWF0LWZvb3Rlci1jZWxsICptYXRGb290ZXJDZWxsRGVmPlxuICAgICAgPG5nLWNvbnRlbnQgc2VsZWN0PVwiW21hdEZvb3Rlcl1cIj48L25nLWNvbnRlbnQ+XG4gICAgPC90ZD5cbiAgPC9uZy1jb250YWluZXI+XG5cbiAgPG5nLWNvbnRhaW5lciAqbmdTd2l0Y2hDYXNlPVwiJ21hdC10YWJsZSdcIj5cbiAgICA8bWF0LWhlYWRlci1jZWxsICptYXRIZWFkZXJDZWxsRGVmIFtjbGFzc109XCJjbGFzc0xpc3RcIiBbY2xhc3MubWF0LWNvbHVtbi1zdGlja3ldPVwic3RpY2t5RW5kXCI+XG4gICAgICA8YnV0dG9uXG4gICAgICAgIG1hdC1pY29uLWJ1dHRvblxuICAgICAgICAqbmdJZj1cIm9wdGlvbnNDbGljay5vYnNlcnZlZFwiXG4gICAgICAgIFt0aXRsZV09XCJvcHRpb25zVGl0bGUgfCB0cmFuc2xhdGVcIlxuICAgICAgICAoY2xpY2spPVwib3B0aW9uc0NsaWNrLmVtaXQoJGV2ZW50KVwiXG4gICAgICA+XG4gICAgICAgIDxtYXQtaWNvbj5tb3JlX3ZlcnQ8L21hdC1pY29uPlxuICAgICAgPC9idXR0b24+XG4gICAgICA8bmctY29udGVudCBzZWxlY3Q9XCJbbWF0SGVhZGVyXVwiPjwvbmctY29udGVudD5cbiAgICA8L21hdC1oZWFkZXItY2VsbD5cbiAgICA8bWF0LWNlbGwgKm1hdENlbGxEZWY9XCJsZXQgcm93XCIgW2NsYXNzXT1cImNsYXNzTGlzdFwiPlxuICAgICAgQGlmIChyb3cuZWRpdGluZykge1xuICAgICAgICA8IS0tIHBlbmRpbmcgLS0+XG4gICAgICAgIEBpZiAocm93LnZhbGlkYXRvcj8ucGVuZGluZykge1xuICAgICAgICAgIDxpb24tc3Bpbm5lciBbY2xhc3MuY2RrLXZpc3VhbGx5LWhpZGRlbl09XCIhc2hvd1BlbmRpbmdcIiBuYW1lPVwiZG90c1wiIGNsYXNzPVwiY2VudGVyXCI+PC9pb24tc3Bpbm5lcj5cbiAgICAgICAgfVxuXG4gICAgICAgIDwhLS0gaW52YWxpZCBuZXcgcm93IC0tPlxuICAgICAgICBAaWYgKHJvdy5pZCA9PT0gLTEgJiYgcm93LnZhbGlkYXRvcj8uaW52YWxpZCkge1xuICAgICAgICAgIDwhLS0gZGVsZXRlIGJ1dHRvbiAtLT5cbiAgICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgICBtYXQtaWNvbi1idXR0b25cbiAgICAgICAgICAgIGNvbG9yPVwibGlnaHRcIlxuICAgICAgICAgICAgW3RpdGxlXT1cIidDT01NT04uQlROX0RFTEVURScgfCB0cmFuc2xhdGVcIlxuICAgICAgICAgICAgKGNsaWNrKT1cImNhbmNlbE9yRGVsZXRlKCRldmVudCwgcm93KVwiXG4gICAgICAgICAgPlxuICAgICAgICAgICAgPG1hdC1pY29uPmRlbGV0ZV9vdXRsaW5lPC9tYXQtaWNvbj5cbiAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgfSBAZWxzZSB7XG4gICAgICAgICAgPCEtLSBmb3J3YXJkIGJ1dHRvbiAoaW52aXNpYmxlIC0gZm9jdXNhYmxlIG9ubHkpIC0tPlxuICAgICAgICAgIDxidXR0b24gY2xhc3M9XCJtYXQtcm93LWFjdGlvbi1idXR0b24tbmF2aWdhdGlvblwiIChmb2N1cyk9XCJjb25maXJtQW5kRm9yd2FyZCgkZXZlbnQsIHJvdylcIj48L2J1dHRvbj5cbiAgICAgICAgfVxuXG4gICAgICAgIDwhLS0gbm90IGVkaXRpbmcgcm93IC0tPlxuICAgICAgfSBAZWxzZSB7XG4gICAgICAgIDwhLS0gZGlydHkgaWNvbiAtLT5cbiAgICAgICAgQGlmIChkaXJ0eUljb24gJiYgcm93LnZhbGlkYXRvcj8uZGlydHkpIHtcbiAgICAgICAgICA8aW9uLWljb24gW25hbWVdPVwiZGlydHlJY29uXCIgY29sb3I9XCJhY2NlbnRcIiBjbGFzcz1cImRpcnR5LWljb25cIj48L2lvbi1pY29uPlxuICAgICAgICB9XG5cbiAgICAgICAgPCEtLSBiYWNrd2FyZCBidXR0b24gKGludmlzaWJsZSAtIGZvY3VzYWJsZSBvbmx5KSAtLT5cbiAgICAgICAgPGJ1dHRvblxuICAgICAgICAgIG1hdC1pY29uLWJ1dHRvblxuICAgICAgICAgIGNsYXNzPVwibWF0LXJvdy1hY3Rpb24tYnV0dG9uLW5hdmlnYXRpb25cIlxuICAgICAgICAgIChmb2N1cyk9XCJjb25maXJtQW5kQmFja3dhcmQoJGV2ZW50LCByb3cpXCJcbiAgICAgICAgPjwvYnV0dG9uPlxuICAgICAgfVxuXG4gICAgICA8bmctY29udGFpbmVyICpuZ1RlbXBsYXRlT3V0bGV0PVwiY2VsbFRlbXBsYXRlOyBjb250ZXh0OiB7ICRpbXBsaWNpdDogcm93IH1cIj48L25nLWNvbnRhaW5lcj5cbiAgICA8L21hdC1jZWxsPlxuXG4gICAgPG1hdC1mb290ZXItY2VsbCAqbWF0Rm9vdGVyQ2VsbERlZj5cbiAgICAgIDxuZy1jb250ZW50IHNlbGVjdD1cIlttYXRGb290ZXJdXCI+PC9uZy1jb250ZW50PlxuICAgIDwvbWF0LWZvb3Rlci1jZWxsPlxuICA8L25nLWNvbnRhaW5lcj5cbjwvbmctY29udGFpbmVyPlxuIl19
@@ -61,7 +61,7 @@ export class AppRowField {
61
61
  this.matTable.removeColumnDef(this.columnDef);
62
62
  }
63
63
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.8", ngImport: i0, type: AppRowField, deps: [{ token: i0.ChangeDetectorRef }, { token: i1.MatTable }], target: i0.ɵɵFactoryTarget.Component });
64
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.8", 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: i2.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: i3.IonLabel, selector: "ion-label", inputs: ["color", "mode", "position"] }, { kind: "directive", type: i4.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i4.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i4.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i5.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.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i1.MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: i1.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i1.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i1.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "component", type: i6.MatSortHeader, selector: "[mat-sort-header]", inputs: ["mat-sort-header", "arrowPosition", "start", "disabled", "sortActionDescription", "disableClear"], exportAs: ["matSortHeader"] }, { kind: "directive", type: i7.AutofocusDirective, selector: "[autofocus], input[appAutofocus]", inputs: ["appAutofocus", "autofocusDelay"] }, { kind: "directive", type: i8.AutoTitleDirective, selector: "[appAutoTitle]" }, { kind: "component", type: i9.AppFormField, selector: "app-form-field", inputs: ["definition", "required", "readonly", "disabled", "formControl", "formControlName", "placeholder", "compact", "floatLabel", "appearance", "tabindex", "autofocus", "clearable", "chipColor", "class", "debug"], outputs: ["keyup.enter"] }, { kind: "component", type: i10.ResizableComponent, selector: "th[resizable]", inputs: ["resizable"], outputs: ["sizeChanged"] }, { kind: "directive", type: i11.ResizableDirective, selector: "[resizable]", outputs: ["resizable", "fit"] }, { kind: "pipe", type: i12.TranslatePipe, name: "translate" }, { kind: "pipe", type: i13.PropertyGetPipe, name: "propertyGet" }, { kind: "pipe", type: i13.ValueFormatPipe, name: "valueFormat" }, { kind: "pipe", type: i14.FormGetControlPipe, name: "formGetControl" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
64
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.8", 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: i2.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: i3.IonLabel, selector: "ion-label", inputs: ["color", "mode", "position"] }, { kind: "directive", type: i4.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i4.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i4.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i5.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.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i1.MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: i1.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i1.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i1.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "component", type: i6.MatSortHeader, selector: "[mat-sort-header]", inputs: ["mat-sort-header", "arrowPosition", "start", "disabled", "sortActionDescription", "disableClear"], exportAs: ["matSortHeader"] }, { kind: "directive", type: i7.AutofocusDirective, selector: "[autofocus], input[appAutofocus]", inputs: ["appAutofocus", "autofocusDelay"] }, { kind: "directive", type: i8.AutoTitleDirective, selector: "[appAutoTitle]" }, { kind: "component", type: i9.AppFormField, selector: "app-form-field", inputs: ["definition", "required", "readonly", "disabled", "formControl", "formControlName", "placeholder", "compact", "floatLabel", "appearance", "subscriptSizing", "tabindex", "autofocus", "clearable", "chipColor", "class", "debug"], outputs: ["keyup.enter"] }, { kind: "component", type: i10.ResizableComponent, selector: "th[resizable]", inputs: ["resizable"], outputs: ["sizeChanged"] }, { kind: "directive", type: i11.ResizableDirective, selector: "[resizable]", outputs: ["resizable", "fit"] }, { kind: "pipe", type: i12.TranslatePipe, name: "translate" }, { kind: "pipe", type: i13.PropertyGetPipe, name: "propertyGet" }, { kind: "pipe", type: i13.ValueFormatPipe, name: "valueFormat" }, { kind: "pipe", type: i14.FormGetControlPipe, name: "formGetControl" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
65
65
  }
66
66
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.8", ngImport: i0, type: AppRowField, decorators: [{
67
67
  type: Component,
@@ -297,7 +297,7 @@ export class TableTestPage extends AppTable {
297
297
  provide: AppTable,
298
298
  useExisting: forwardRef(() => TableTestPage),
299
299
  },
300
- ], 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 [autofocus]=\"focusColumn === 'latitude'\"\n ></mat-latlong-field>\n } @else {\n <ion-label appAutoTitle>\n {{ row.validator | formGetValue: 'properties.latitude' | latitudeFormat }}\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: i4.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: i4.IonButtons, selector: "ion-buttons", inputs: ["collapse"] }, { kind: "component", type: i4.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: i4.IonContent, selector: "ion-content", inputs: ["color", "fixedSlotPlacement", "forceOverscroll", "fullscreen", "scrollEvents", "scrollX", "scrollY"] }, { kind: "component", type: i4.IonFab, selector: "ion-fab", inputs: ["activated", "edge", "horizontal", "vertical"] }, { kind: "component", type: i4.IonFabButton, selector: "ion-fab-button", inputs: ["activated", "closeIcon", "color", "disabled", "download", "href", "mode", "rel", "routerAnimation", "routerDirection", "show", "size", "target", "translucent", "type"] }, { kind: "component", type: i4.IonFooter, selector: "ion-footer", inputs: ["collapse", "mode", "translucent"] }, { kind: "component", type: i4.IonGrid, selector: "ion-grid", inputs: ["fixed"] }, { kind: "component", type: i4.IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: i4.IonInfiniteScroll, selector: "ion-infinite-scroll", inputs: ["disabled", "position", "threshold"] }, { kind: "component", type: i4.IonInfiniteScrollContent, selector: "ion-infinite-scroll-content", inputs: ["loadingSpinner", "loadingText"] }, { kind: "component", type: i4.IonItem, selector: "ion-item", inputs: ["button", "color", "detail", "detailIcon", "disabled", "download", "href", "lines", "mode", "rel", "routerAnimation", "routerDirection", "target", "type"] }, { kind: "component", type: i4.IonLabel, selector: "ion-label", inputs: ["color", "mode", "position"] }, { kind: "component", type: i4.IonRefresher, selector: "ion-refresher", inputs: ["closeDuration", "disabled", "mode", "pullFactor", "pullMax", "pullMin", "snapbackDuration"] }, { kind: "component", type: i4.IonRefresherContent, selector: "ion-refresher-content", inputs: ["pullingIcon", "pullingText", "refreshingSpinner", "refreshingText"] }, { kind: "component", type: i4.IonRow, selector: "ion-row" }, { kind: "component", type: i4.IonSkeletonText, selector: "ion-skeleton-text", inputs: ["animated"] }, { kind: "component", type: i4.IonText, selector: "ion-text", inputs: ["color", "mode"] }, { kind: "component", type: i4.IonTitle, selector: "ion-title", inputs: ["color", "size"] }, { kind: "directive", type: i5.TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }, { kind: "directive", type: i2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i2.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i6.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: i7.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i7.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i7.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i7.MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: i7.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i7.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i7.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i7.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "component", type: i7.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i7.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "directive", type: i8.MatSort, selector: "[matSort]", inputs: ["matSortActive", "matSortStart", "matSortDirection", "matSortDisableClear", "matSortDisabled"], outputs: ["matSortChange"], exportAs: ["matSort"] }, { kind: "component", type: i8.MatSortHeader, selector: "[mat-sort-header]", inputs: ["mat-sort-header", "arrowPosition", "start", "disabled", "sortActionDescription", "disableClear"], exportAs: ["matSortHeader"] }, { kind: "component", type: i9.MatPaginator, selector: "mat-paginator", inputs: ["color", "pageIndex", "length", "pageSize", "pageSizeOptions", "hidePageSize", "showFirstLastButtons", "selectConfig", "disabled"], outputs: ["page"], exportAs: ["matPaginator"] }, { kind: "component", type: i10.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i10.MatLabel, selector: "mat-label" }, { kind: "directive", type: i10.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "directive", type: i10.MatPrefix, selector: "[matPrefix], [matIconPrefix], [matTextPrefix]", inputs: ["matTextPrefix"] }, { kind: "directive", type: i10.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "directive", type: i11.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: i12.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.MatExpansionPanel, selector: "mat-expansion-panel", inputs: ["hideToggle", "togglePosition"], outputs: ["afterExpand", "afterCollapse"], exportAs: ["matExpansionPanel"] }, { kind: "directive", type: i13.MatExpansionPanelActionRow, selector: "mat-action-row" }, { kind: "component", type: i14.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i15.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "component", type: i16.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: i17.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "directive", type: i18.MatBadge, selector: "[matBadge]", inputs: ["matBadgeColor", "matBadgeOverlap", "matBadgeDisabled", "matBadgePosition", "matBadge", "matBadgeDescription", "matBadgeSize", "matBadgeHidden"] }, { kind: "directive", type: i19.CdkTrapFocus, selector: "[cdkTrapFocus]", inputs: ["cdkTrapFocus", "cdkTrapFocusAutoCapture"], exportAs: ["cdkTrapFocus"] }, { kind: "component", type: i20.MatAutocompleteField, selector: "mat-autocomplete-field", inputs: ["equals", "logPrefix", "formControl", "formControlName", "floatLabel", "appearance", "subscriptSizing", "placeholder", "suggestFn", "required", "mobile", "clearable", "debounceTime", "displaySeparator", "displayWith", "displayAttributes", "displayColumnSizes", "displayColumnNames", "highlightAccent", "showAllOnFocus", "showPanelOnFocus", "autofocus", "config", "i18nPrefix", "noResultMessage", "panelClass", "panelWidth", "disableRipple", "matAutocompletePosition", "multiple", "fetchMoreThreshold", "suggestLengthThreshold", "showLoadingSpinner", "debug", "showSearchBar", "stickySearchBar", "applyImplicitValue", "dropButtonTitle", "clearButtonTitle", "trimSearchText", "splitSearchText", "class", "filter", "readonly", "tabindex", "items"], outputs: ["click", "blur", "focus", "dropButtonClick", "keydown.escape", "keyup.enter", "optionSelected"] }, { kind: "component", type: i21.MatLatLongField, selector: "mat-latlong-field", inputs: ["formControl", "formControlName", "type", "latLongPattern", "required", "floatLabel", "placeholder", "tabindex", "defaultSign", "maxDecimals", "placeholderChar", "autofocus", "mobile", "appearance", "readonly", "subscriptSizing"], outputs: ["onBlur", "onFocus"] }, { kind: "component", type: i22.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: i23.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", "blur"] }, { kind: "directive", type: i24.AutofocusDirective, selector: "[autofocus], input[appAutofocus]", inputs: ["appAutofocus", "autofocusDelay"] }, { kind: "directive", type: i25.AutoTitleDirective, selector: "[appAutoTitle]" }, { kind: "component", type: i26.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: i27.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: i28.NavActionsColumnComponent, selector: "app-nav-actions-column", inputs: ["appTable", "matColumnDef", "style", "stickyEnd", "showPending", "dirtyIcon", "optionsTitle", "class", "cellTemplate", "throttleTime"], outputs: ["optionsClick"] }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i29.ResizableComponent, selector: "th[resizable]", inputs: ["resizable"], outputs: ["sizeChanged"] }, { kind: "directive", type: i30.ResizableDirective, selector: "[resizable]", outputs: ["resizable", "fit"] }, { kind: "pipe", type: i3.AsyncPipe, name: "async" }, { kind: "pipe", type: i5.TranslatePipe, name: "translate" }, { kind: "pipe", type: i31.DateFormatPipe, name: "dateFormat" }, { kind: "pipe", type: i32.LatitudeFormatPipe, name: "latitudeFormat" }, { kind: "pipe", type: i33.NumberFormatPipe, name: "numberFormat" }, { kind: "pipe", type: i34.ArrayLengthPipe, name: "isArrayLength" }, { kind: "pipe", type: i35.FormGetControlPipe, name: "formGetControl" }, { kind: "pipe", type: i35.FormGetValuePipe, name: "formGetValue" }, { kind: "pipe", type: i36.IsSelectedPipe, name: "isSelected" }, { kind: "pipe", type: i36.IsEmptySelectionPipe, name: "isEmptySelection" }, { kind: "pipe", type: i36.IsMultipleSelectionPipe, name: "isMultipleSelection" }, { kind: "pipe", type: i37.IsAllSelectedPipe, name: "isAllSelected" }, { kind: "pipe", type: i37.IsNotAllSelectedPipe, name: "isNotAllSelected" }, { kind: "pipe", type: i38.ReferentialToStringPipe, name: "referentialToString" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
300
+ ], 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 [autofocus]=\"focusColumn === 'latitude'\"\n ></mat-latlong-field>\n } @else {\n <ion-label appAutoTitle>\n {{ row.validator | formGetValue: 'properties.latitude' | latitudeFormat }}\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: i4.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: i4.IonButtons, selector: "ion-buttons", inputs: ["collapse"] }, { kind: "component", type: i4.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: i4.IonContent, selector: "ion-content", inputs: ["color", "fixedSlotPlacement", "forceOverscroll", "fullscreen", "scrollEvents", "scrollX", "scrollY"] }, { kind: "component", type: i4.IonFab, selector: "ion-fab", inputs: ["activated", "edge", "horizontal", "vertical"] }, { kind: "component", type: i4.IonFabButton, selector: "ion-fab-button", inputs: ["activated", "closeIcon", "color", "disabled", "download", "href", "mode", "rel", "routerAnimation", "routerDirection", "show", "size", "target", "translucent", "type"] }, { kind: "component", type: i4.IonFooter, selector: "ion-footer", inputs: ["collapse", "mode", "translucent"] }, { kind: "component", type: i4.IonGrid, selector: "ion-grid", inputs: ["fixed"] }, { kind: "component", type: i4.IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: i4.IonInfiniteScroll, selector: "ion-infinite-scroll", inputs: ["disabled", "position", "threshold"] }, { kind: "component", type: i4.IonInfiniteScrollContent, selector: "ion-infinite-scroll-content", inputs: ["loadingSpinner", "loadingText"] }, { kind: "component", type: i4.IonItem, selector: "ion-item", inputs: ["button", "color", "detail", "detailIcon", "disabled", "download", "href", "lines", "mode", "rel", "routerAnimation", "routerDirection", "target", "type"] }, { kind: "component", type: i4.IonLabel, selector: "ion-label", inputs: ["color", "mode", "position"] }, { kind: "component", type: i4.IonRefresher, selector: "ion-refresher", inputs: ["closeDuration", "disabled", "mode", "pullFactor", "pullMax", "pullMin", "snapbackDuration"] }, { kind: "component", type: i4.IonRefresherContent, selector: "ion-refresher-content", inputs: ["pullingIcon", "pullingText", "refreshingSpinner", "refreshingText"] }, { kind: "component", type: i4.IonRow, selector: "ion-row" }, { kind: "component", type: i4.IonSkeletonText, selector: "ion-skeleton-text", inputs: ["animated"] }, { kind: "component", type: i4.IonText, selector: "ion-text", inputs: ["color", "mode"] }, { kind: "component", type: i4.IonTitle, selector: "ion-title", inputs: ["color", "size"] }, { kind: "directive", type: i5.TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }, { kind: "directive", type: i2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i2.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i6.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: i7.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i7.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i7.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i7.MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: i7.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i7.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i7.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i7.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "component", type: i7.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i7.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "directive", type: i8.MatSort, selector: "[matSort]", inputs: ["matSortActive", "matSortStart", "matSortDirection", "matSortDisableClear", "matSortDisabled"], outputs: ["matSortChange"], exportAs: ["matSort"] }, { kind: "component", type: i8.MatSortHeader, selector: "[mat-sort-header]", inputs: ["mat-sort-header", "arrowPosition", "start", "disabled", "sortActionDescription", "disableClear"], exportAs: ["matSortHeader"] }, { kind: "component", type: i9.MatPaginator, selector: "mat-paginator", inputs: ["color", "pageIndex", "length", "pageSize", "pageSizeOptions", "hidePageSize", "showFirstLastButtons", "selectConfig", "disabled"], outputs: ["page"], exportAs: ["matPaginator"] }, { kind: "component", type: i10.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i10.MatLabel, selector: "mat-label" }, { kind: "directive", type: i10.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "directive", type: i10.MatPrefix, selector: "[matPrefix], [matIconPrefix], [matTextPrefix]", inputs: ["matTextPrefix"] }, { kind: "directive", type: i10.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "directive", type: i11.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: i12.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.MatExpansionPanel, selector: "mat-expansion-panel", inputs: ["hideToggle", "togglePosition"], outputs: ["afterExpand", "afterCollapse"], exportAs: ["matExpansionPanel"] }, { kind: "directive", type: i13.MatExpansionPanelActionRow, selector: "mat-action-row" }, { kind: "component", type: i14.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i15.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "component", type: i16.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: i17.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "directive", type: i18.MatBadge, selector: "[matBadge]", inputs: ["matBadgeColor", "matBadgeOverlap", "matBadgeDisabled", "matBadgePosition", "matBadge", "matBadgeDescription", "matBadgeSize", "matBadgeHidden"] }, { kind: "directive", type: i19.CdkTrapFocus, selector: "[cdkTrapFocus]", inputs: ["cdkTrapFocus", "cdkTrapFocusAutoCapture"], exportAs: ["cdkTrapFocus"] }, { kind: "component", type: i20.MatAutocompleteField, selector: "mat-autocomplete-field", inputs: ["equals", "logPrefix", "formControl", "formControlName", "floatLabel", "appearance", "subscriptSizing", "placeholder", "suggestFn", "required", "mobile", "clearable", "debounceTime", "displaySeparator", "displayWith", "displayAttributes", "displayColumnSizes", "displayColumnNames", "highlightAccent", "showAllOnFocus", "showPanelOnFocus", "autofocus", "config", "i18nPrefix", "noResultMessage", "panelClass", "panelWidth", "disableRipple", "matAutocompletePosition", "multiple", "fetchMoreThreshold", "suggestLengthThreshold", "showLoadingSpinner", "debug", "showSearchBar", "stickySearchBar", "applyImplicitValue", "dropButtonTitle", "clearButtonTitle", "trimSearchText", "splitSearchText", "selectInputContentOnFocus", "class", "filter", "readonly", "tabindex", "items"], outputs: ["click", "blur", "focus", "dropButtonClick", "keydown.escape", "keyup.enter", "selectionChange"] }, { kind: "component", type: i21.MatLatLongField, selector: "mat-latlong-field", inputs: ["formControl", "formControlName", "type", "latLongPattern", "required", "floatLabel", "placeholder", "tabindex", "defaultSign", "maxDecimals", "placeholderChar", "autofocus", "mobile", "appearance", "readonly", "subscriptSizing"], outputs: ["onBlur", "onFocus"] }, { kind: "component", type: i22.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: i23.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", "blur"] }, { kind: "directive", type: i24.AutofocusDirective, selector: "[autofocus], input[appAutofocus]", inputs: ["appAutofocus", "autofocusDelay"] }, { kind: "directive", type: i25.AutoTitleDirective, selector: "[appAutoTitle]" }, { kind: "component", type: i26.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: i27.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: i28.NavActionsColumnComponent, selector: "app-nav-actions-column", inputs: ["appTable", "matColumnDef", "style", "stickyEnd", "showPending", "dirtyIcon", "optionsTitle", "class", "cellTemplate", "throttleTime"], outputs: ["optionsClick"] }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i29.ResizableComponent, selector: "th[resizable]", inputs: ["resizable"], outputs: ["sizeChanged"] }, { kind: "directive", type: i30.ResizableDirective, selector: "[resizable]", outputs: ["resizable", "fit"] }, { kind: "pipe", type: i3.AsyncPipe, name: "async" }, { kind: "pipe", type: i5.TranslatePipe, name: "translate" }, { kind: "pipe", type: i31.DateFormatPipe, name: "dateFormat" }, { kind: "pipe", type: i32.LatitudeFormatPipe, name: "latitudeFormat" }, { kind: "pipe", type: i33.NumberFormatPipe, name: "numberFormat" }, { kind: "pipe", type: i34.ArrayLengthPipe, name: "isArrayLength" }, { kind: "pipe", type: i35.FormGetControlPipe, name: "formGetControl" }, { kind: "pipe", type: i35.FormGetValuePipe, name: "formGetValue" }, { kind: "pipe", type: i36.IsSelectedPipe, name: "isSelected" }, { kind: "pipe", type: i36.IsEmptySelectionPipe, name: "isEmptySelection" }, { kind: "pipe", type: i36.IsMultipleSelectionPipe, name: "isMultipleSelection" }, { kind: "pipe", type: i37.IsAllSelectedPipe, name: "isAllSelected" }, { kind: "pipe", type: i37.IsNotAllSelectedPipe, name: "isNotAllSelected" }, { kind: "pipe", type: i38.ReferentialToStringPipe, name: "referentialToString" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
301
301
  }
302
302
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.8", ngImport: i0, type: TableTestPage, decorators: [{
303
303
  type: Component,