@sumaris-net/ngx-components 2.7.5-rc9 → 2.7.6-rc1

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 (44) hide show
  1. package/README.md +4 -3
  2. package/esm2022/src/app/core/account/new-token.modal.mjs +6 -8
  3. package/esm2022/src/app/core/account/token.table.mjs +2 -3
  4. package/esm2022/src/app/core/form/properties/properties.table.mjs +1 -1
  5. package/esm2022/src/app/core/form/text-popover/testing/text-popover.testing.mjs +9 -10
  6. package/esm2022/src/app/core/services/account.service.mjs +3 -2
  7. package/esm2022/src/app/core/services/model/referential.model.mjs +12 -4
  8. package/esm2022/src/app/core/services/platform.service.mjs +37 -16
  9. package/esm2022/src/app/core/table/testing/table.testing.mjs +1 -1
  10. package/esm2022/src/app/core/table/testing/table2.testing.mjs +1 -1
  11. package/esm2022/src/app/shared/alerts.mjs +14 -12
  12. package/esm2022/src/app/shared/form/field.component.mjs +3 -3
  13. package/esm2022/src/app/shared/material/autocomplete/material.autocomplete.mjs +7 -4
  14. package/esm2022/src/app/shared/material/autocomplete/testing/autocomplete.test.mjs +1 -1
  15. package/esm2022/src/app/shared/material/boolean/material.boolean.mjs +6 -3
  16. package/esm2022/src/app/shared/material/boolean/testing/boolean.test.page.mjs +1 -1
  17. package/esm2022/src/app/shared/material/chips/material.chips.mjs +7 -4
  18. package/esm2022/src/app/shared/material/chips/testing/chips.test.mjs +1 -1
  19. package/esm2022/src/app/shared/material/latlong/material.latlong.mjs +3 -3
  20. package/esm2022/src/app/shared/material/swipe/material.swipe.mjs +6 -3
  21. package/esm2022/src/app/shared/material/swipe/testing/swipe.test.mjs +1 -1
  22. package/esm2022/src/app/shared/material/testing/common.test.mjs +1 -1
  23. package/esm2022/src/app/shared/named-filter/named-filter-selector.component.mjs +28 -7
  24. package/esm2022/src/app/shared/pipes/date-format.pipe.mjs +1 -1
  25. package/esm2022/src/app/shared/storage/storage-explorer.component.mjs +18 -23
  26. package/esm2022/src/app/shared/toolbar/toolbar.mjs +15 -15
  27. package/esm2022/src/app/social/message/message.form.mjs +1 -1
  28. package/fesm2022/sumaris-net.ngx-components.mjs +151 -95
  29. package/fesm2022/sumaris-net.ngx-components.mjs.map +1 -1
  30. package/package.json +1 -1
  31. package/src/app/core/account/new-token.modal.d.ts +1 -1
  32. package/src/app/core/form/text-popover/testing/text-popover.testing.d.ts +3 -1
  33. package/src/app/core/services/model/referential.model.d.ts +5 -1
  34. package/src/app/core/services/platform.service.d.ts +6 -2
  35. package/src/app/shared/alerts.d.ts +4 -2
  36. package/src/app/shared/material/autocomplete/material.autocomplete.d.ts +3 -2
  37. package/src/app/shared/material/boolean/material.boolean.d.ts +3 -2
  38. package/src/app/shared/material/chips/material.chips.d.ts +3 -2
  39. package/src/app/shared/material/swipe/material.swipe.d.ts +3 -2
  40. package/src/app/shared/named-filter/named-filter-selector.component.d.ts +8 -5
  41. package/src/app/shared/pipes/date-format.pipe.d.ts +1 -1
  42. package/src/app/shared/storage/storage-explorer.component.d.ts +4 -3
  43. package/src/app/shared/toolbar/toolbar.d.ts +2 -2
  44. package/src/assets/manifest.json +1 -1
@@ -285,7 +285,7 @@ export class TableTestPage extends AppTable {
285
285
  provide: AppTable,
286
286
  useExisting: forwardRef(() => TableTestPage),
287
287
  },
288
- ], 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 <ng-container *ngIf=\"!selection.hasValue(); else hasSelection\">\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 </ng-container>\n\n <!-- if row selection -->\n <ng-template #hasSelection>\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 </ng-template>\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 #filterExpansionPanel class=\"filter-panel filter-panel-floating\">\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 <!-- Close panel -->\n <ion-button\n mat-button\n fill=\"clear\"\n color=\"dark\"\n (click)=\"filterExpansionPanel.close()\"\n [disabled]=\"loadingSubject | async\"\n >\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 >\n\n <!-- group header cells -->\n\n <ng-container matColumnDef=\"top-start\" [sticky]=\"useSticky\">\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]=\"3\">\n <ion-label translate>{{ i18nColumnPrefix + 'GROUP_2' }}</ion-label>\n </th>\n </ng-container>\n\n <ng-container matColumnDef=\"top-end\">\n <th mat-header-cell *matHeaderCellDef [attr.colspan]=\"2\">\n <!-- end spacer -->\n </th>\n </ng-container>\n\n <ng-container matColumnDef=\"select\" [sticky]=\"useSticky\" [class.mat-column-sticky]=\"useSticky\">\n <th mat-header-cell *matHeaderCellDef [class.cdk-visually-hidden]=\"!canEdit\">\n <mat-checkbox\n (change)=\"$event ? masterToggle() : null\"\n [checked]=\"selection.hasValue() && isAllSelected()\"\n [indeterminate]=\"selection.hasValue() && !isAllSelected()\"\n ></mat-checkbox>\n </th>\n <td mat-cell *matCellDef=\"let row\" [class.cdk-visually-hidden]=\"!canEdit\">\n <mat-checkbox (click)=\"toggleSelectRow($event, row)\" [checked]=\"selection.isSelected(row)\"></mat-checkbox>\n </td>\n </ng-container>\n\n <!-- Id column -->\n <ng-container matColumnDef=\"id\" [sticky]=\"useSticky\" [class.mat-column-sticky]=\"useSticky\">\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 <mat-form-field *ngIf=\"row.editing; else readonlyCell\" [hideRequiredMarker]=\"false\">\n <input\n matInput\n autocomplete=\"off\"\n [formControl]=\"row.validator.controls['label']\"\n [placeholder]=\"'TABLE.TESTING.LABEL' | translate\"\n [appAutofocus]=\"row.editing && 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 <ng-template #readonlyCell>\n <ion-label appAutoTitle>\n {{ row.validator | formGetValue: 'label' }}\n </ion-label>\n </ng-template>\n </td>\n </ng-container>\n\n <!-- Name column -->\n <ng-container matColumnDef=\"name\">\n <th mat-header-cell *matHeaderCellDef 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 <mat-form-field *ngIf=\"row.editing; else readonlyCell\">\n <input\n matInput\n [formControl]=\"row.validator?.controls.name\"\n [placeholder]=\"'TABLE.TESTING.NAME' | translate\"\n [appAutofocus]=\"row.editing && 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 <ng-template #readonlyCell>\n <ion-label appAutoTitle>\n {{ row.validator | formGetValue: 'name' }}\n </ion-label>\n </ng-template>\n </td>\n </ng-container>\n\n <!-- Level column -->\n <ng-container matColumnDef=\"levelId\">\n <th mat-header-cell *matHeaderCellDef 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 <mat-autocomplete-field\n *ngIf=\"row.editing; else readonlyCell\"\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 <ng-template #readonlyCell>\n <ion-label appAutoTitle>\n {{ row.validator | formGetValue: 'levelId' | referentialToString: autocompleteFields.level.attributes }}\n </ion-label>\n </ng-template>\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 mat-cell *matCellDef=\"let row\"\n [class.mat-form-field-disabled]=\"!row.editing\"\n (click)=\"focusColumn = 'statusId'\">\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 <mat-boolean-field\n *ngIf=\"!readOnly && row.editing; else readOnlyTemplate\"\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 <ng-template #readOnlyTemplate>\n <ion-label appAutoTitle>\n {{ (row.validator | formGetValue: 'properties.boolean') ? '&#x2714;' : '&#x2718;' }}\n </ion-label>\n </ng-template>\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 <mat-date-time-field\n *ngIf=\"!readOnly && row.editing && row.validator | formGetControl: 'properties.date'; let dateControl; else readOnlyTemplate\"\n floatLabel=\"never\"\n [formControl]=\"dateControl\"\n [autofocus]=\"focusColumn === 'date'\"\n [compact]=\"true\"\n ></mat-date-time-field>\n <ng-template #readOnlyTemplate>\n <ion-label appAutoTitle>\n {{ (row.validator | formGetValue: 'properties.date') | dateFormat: { time: true } }}\n </ion-label>\n </ng-template>\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 <mat-latlong-field\n *ngIf=\"!readOnly && row.editing && row.validator | formGetControl: 'properties.latitude'; let latitudeControl; else readOnlyTemplate\"\n floatLabel=\"never\"\n [formControl]=\"latitudeControl\"\n [latLongPattern]=\"'DDMM'\"\n [autofocus]=\"focusColumn === 'latitude'\"\n ></mat-latlong-field>\n <ng-template #readOnlyTemplate>\n <ion-label appAutoTitle>\n {{ (row.validator | formGetValue: 'properties.latitude') | latitudeFormat }}\n </ion-label>\n </ng-template>\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 buttons column -->\n <app-actions-column\n [stickyEnd]=\"true\"\n [canCancel]=\"false\"\n [style]=\"'table'\"\n (optionsClick)=\"openSelectColumnsModal($event)\"\n (cancelOrDeleteClick)=\"cancelOrDelete($event.event, $event.row)\"\n (confirmAndAddClick)=\"confirmAndAdd($event.event, $event.row)\"\n (backward)=\"confirmAndBackward($event.event, $event.row)\"\n (forward)=\"confirmAndForward($event.event, $event.row)\"\n [cellTemplate]=\"cellInjection\"\n >\n <!-- cell injection-->\n <ng-template #cellInjection let-row>\n <span *ngIf=\"row.editing && !row.validator.dirty\">-</span>\n </ng-template>\n </app-actions-column>\n\n <tr mat-header-row *matHeaderRowDef=\"groupColumns\" class=\"mat-toolbar\"></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.validator?.invalid\"\n [class.mat-mdc-row-disabled]=\"!row.editing\"\n [class.mat-mdc-row-dirty]=\"row.validator?.dirty\"\n (click)=\"clickRow($event, row)\"\n (keydown.escape)=\"escapeEditingRow($event)\"\n [cdkTrapFocus]=\"row.validator?.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", "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", "counter", "counterFormatter", "detail", "detailIcon", "disabled", "download", "fill", "href", "lines", "mode", "rel", "routerAnimation", "routerDirection", "shape", "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"], 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", "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", "placeholder", "suggestFn", "required", "mobile", "clearable", "debounceTime", "displayWith", "displayAttributes", "displayColumnSizes", "displayColumnNames", "highlightAccent", "showAllOnFocus", "showPanelOnFocus", "autofocus", "config", "i18nPrefix", "noResultMessage", "class", "panelWidth", "matAutocompletePosition", "multiple", "fetchMoreThreshold", "suggestLengthThreshold", "showLoadingSpinner", "debug", "showSearchBar", "stickySearchBar", "applyImplicitValue", "dropButtonTitle", "clearButtonTitle", "filter", "readonly", "tabindex", "items"], outputs: ["click", "blur", "focus", "dropButtonClick", "keydown.escape", "keyup.enter"] }, { kind: "component", type: i21.MatLatLongField, selector: "mat-latlong-field", inputs: ["formControl", "formControlName", "type", "latLongPattern", "required", "floatLabel", "placeholder", "tabindex", "defaultSign", "maxDecimals", "placeholderChar", "autofocus", "appearance", "readonly", "subscriptSizing"], outputs: ["onBlur", "onFocus"] }, { kind: "component", type: i22.MatDateTime, selector: "mat-date-time-field", inputs: ["placeholder", "floatLabel", "mobile", "compact", "autofocus", "startDate", "clearable", "datePickerFilter", "appearance", "subscriptSizing", "formControl", "formControlName", "required", "readonly", "tabindex"] }, { kind: "component", type: i23.MatBooleanField, selector: "mat-boolean-field", inputs: ["disabled", "formControl", "formControlName", "placeholder", "floatLabel", "appearance", "readonly", "required", "compact", "style", "buttonsColCount", "class", "yesLabel", "noLabel", "showButtonIcons", "yesIcon", "noIcon", "tabindex", "value"], outputs: ["keyup.enter", "onBlur"] }, { 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", "classList", "saveButtonColor", "backText", "cancelText", "nextText", "showBack", "showCancel", "showNext", "showSave", "showSaveAndClose", "showSaveAndNext"], outputs: ["onCancel", "onSave", "onNext", "onBack", "onSaveAndClose", "onSaveAndNext"] }, { kind: "component", type: i28.ActionsColumnComponent, selector: "app-actions-column", inputs: ["matColumnDef", "style", "stickyEnd", "canCancel", "canConfirm", "canDelete", "canBackward", "canForward", "canConfirmAndAdd", "dirtyIcon", "optionsTitle", "class", "cellTemplate"], outputs: ["optionsClick", "cancelOrDeleteClick", "confirmEditCreateClick", "confirmAndAddClick", "backward", "forward"] }, { kind: "directive", type: 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.ReferentialToStringPipe, name: "referentialToString" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
288
+ ], 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 <ng-container *ngIf=\"!selection.hasValue(); else hasSelection\">\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 </ng-container>\n\n <!-- if row selection -->\n <ng-template #hasSelection>\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 </ng-template>\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 #filterExpansionPanel class=\"filter-panel filter-panel-floating\">\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 <!-- Close panel -->\n <ion-button\n mat-button\n fill=\"clear\"\n color=\"dark\"\n (click)=\"filterExpansionPanel.close()\"\n [disabled]=\"loadingSubject | async\"\n >\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 >\n\n <!-- group header cells -->\n\n <ng-container matColumnDef=\"top-start\" [sticky]=\"useSticky\">\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]=\"3\">\n <ion-label translate>{{ i18nColumnPrefix + 'GROUP_2' }}</ion-label>\n </th>\n </ng-container>\n\n <ng-container matColumnDef=\"top-end\">\n <th mat-header-cell *matHeaderCellDef [attr.colspan]=\"2\">\n <!-- end spacer -->\n </th>\n </ng-container>\n\n <ng-container matColumnDef=\"select\" [sticky]=\"useSticky\" [class.mat-column-sticky]=\"useSticky\">\n <th mat-header-cell *matHeaderCellDef [class.cdk-visually-hidden]=\"!canEdit\">\n <mat-checkbox\n (change)=\"$event ? masterToggle() : null\"\n [checked]=\"selection.hasValue() && isAllSelected()\"\n [indeterminate]=\"selection.hasValue() && !isAllSelected()\"\n ></mat-checkbox>\n </th>\n <td mat-cell *matCellDef=\"let row\" [class.cdk-visually-hidden]=\"!canEdit\">\n <mat-checkbox (click)=\"toggleSelectRow($event, row)\" [checked]=\"selection.isSelected(row)\"></mat-checkbox>\n </td>\n </ng-container>\n\n <!-- Id column -->\n <ng-container matColumnDef=\"id\" [sticky]=\"useSticky\" [class.mat-column-sticky]=\"useSticky\">\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 <mat-form-field *ngIf=\"row.editing; else readonlyCell\" [hideRequiredMarker]=\"false\">\n <input\n matInput\n autocomplete=\"off\"\n [formControl]=\"row.validator.controls['label']\"\n [placeholder]=\"'TABLE.TESTING.LABEL' | translate\"\n [appAutofocus]=\"row.editing && 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 <ng-template #readonlyCell>\n <ion-label appAutoTitle>\n {{ row.validator | formGetValue: 'label' }}\n </ion-label>\n </ng-template>\n </td>\n </ng-container>\n\n <!-- Name column -->\n <ng-container matColumnDef=\"name\">\n <th mat-header-cell *matHeaderCellDef 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 <mat-form-field *ngIf=\"row.editing; else readonlyCell\">\n <input\n matInput\n [formControl]=\"row.validator?.controls.name\"\n [placeholder]=\"'TABLE.TESTING.NAME' | translate\"\n [appAutofocus]=\"row.editing && 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 <ng-template #readonlyCell>\n <ion-label appAutoTitle>\n {{ row.validator | formGetValue: 'name' }}\n </ion-label>\n </ng-template>\n </td>\n </ng-container>\n\n <!-- Level column -->\n <ng-container matColumnDef=\"levelId\">\n <th mat-header-cell *matHeaderCellDef 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 <mat-autocomplete-field\n *ngIf=\"row.editing; else readonlyCell\"\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 <ng-template #readonlyCell>\n <ion-label appAutoTitle>\n {{ row.validator | formGetValue: 'levelId' | referentialToString: autocompleteFields.level.attributes }}\n </ion-label>\n </ng-template>\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 mat-cell *matCellDef=\"let row\"\n [class.mat-form-field-disabled]=\"!row.editing\"\n (click)=\"focusColumn = 'statusId'\">\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 <mat-boolean-field\n *ngIf=\"!readOnly && row.editing; else readOnlyTemplate\"\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 <ng-template #readOnlyTemplate>\n <ion-label appAutoTitle>\n {{ (row.validator | formGetValue: 'properties.boolean') ? '&#x2714;' : '&#x2718;' }}\n </ion-label>\n </ng-template>\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 <mat-date-time-field\n *ngIf=\"!readOnly && row.editing && row.validator | formGetControl: 'properties.date'; let dateControl; else readOnlyTemplate\"\n floatLabel=\"never\"\n [formControl]=\"dateControl\"\n [autofocus]=\"focusColumn === 'date'\"\n [compact]=\"true\"\n ></mat-date-time-field>\n <ng-template #readOnlyTemplate>\n <ion-label appAutoTitle>\n {{ (row.validator | formGetValue: 'properties.date') | dateFormat: { time: true } }}\n </ion-label>\n </ng-template>\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 <mat-latlong-field\n *ngIf=\"!readOnly && row.editing && row.validator | formGetControl: 'properties.latitude'; let latitudeControl; else readOnlyTemplate\"\n floatLabel=\"never\"\n [formControl]=\"latitudeControl\"\n [latLongPattern]=\"'DDMM'\"\n [autofocus]=\"focusColumn === 'latitude'\"\n ></mat-latlong-field>\n <ng-template #readOnlyTemplate>\n <ion-label appAutoTitle>\n {{ (row.validator | formGetValue: 'properties.latitude') | latitudeFormat }}\n </ion-label>\n </ng-template>\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 buttons column -->\n <app-actions-column\n [stickyEnd]=\"true\"\n [canCancel]=\"false\"\n [style]=\"'table'\"\n (optionsClick)=\"openSelectColumnsModal($event)\"\n (cancelOrDeleteClick)=\"cancelOrDelete($event.event, $event.row)\"\n (confirmAndAddClick)=\"confirmAndAdd($event.event, $event.row)\"\n (backward)=\"confirmAndBackward($event.event, $event.row)\"\n (forward)=\"confirmAndForward($event.event, $event.row)\"\n [cellTemplate]=\"cellInjection\"\n >\n <!-- cell injection-->\n <ng-template #cellInjection let-row>\n <span *ngIf=\"row.editing && !row.validator.dirty\">-</span>\n </ng-template>\n </app-actions-column>\n\n <tr mat-header-row *matHeaderRowDef=\"groupColumns\" class=\"mat-toolbar\"></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.validator?.invalid\"\n [class.mat-mdc-row-disabled]=\"!row.editing\"\n [class.mat-mdc-row-dirty]=\"row.validator?.dirty\"\n (click)=\"clickRow($event, row)\"\n (keydown.escape)=\"escapeEditingRow($event)\"\n [cdkTrapFocus]=\"row.validator?.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", "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", "counter", "counterFormatter", "detail", "detailIcon", "disabled", "download", "fill", "href", "lines", "mode", "rel", "routerAnimation", "routerDirection", "shape", "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"], 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", "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", "displayWith", "displayAttributes", "displayColumnSizes", "displayColumnNames", "highlightAccent", "showAllOnFocus", "showPanelOnFocus", "autofocus", "config", "i18nPrefix", "noResultMessage", "class", "panelWidth", "matAutocompletePosition", "multiple", "fetchMoreThreshold", "suggestLengthThreshold", "showLoadingSpinner", "debug", "showSearchBar", "stickySearchBar", "applyImplicitValue", "dropButtonTitle", "clearButtonTitle", "filter", "readonly", "tabindex", "items"], outputs: ["click", "blur", "focus", "dropButtonClick", "keydown.escape", "keyup.enter"] }, { kind: "component", type: i21.MatLatLongField, selector: "mat-latlong-field", inputs: ["formControl", "formControlName", "type", "latLongPattern", "required", "floatLabel", "placeholder", "tabindex", "defaultSign", "maxDecimals", "placeholderChar", "autofocus", "appearance", "readonly", "subscriptSizing"], outputs: ["onBlur", "onFocus"] }, { kind: "component", type: i22.MatDateTime, selector: "mat-date-time-field", inputs: ["placeholder", "floatLabel", "mobile", "compact", "autofocus", "startDate", "clearable", "datePickerFilter", "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", "tabindex", "value"], outputs: ["keyup.enter", "onBlur"] }, { 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", "classList", "saveButtonColor", "backText", "cancelText", "nextText", "showBack", "showCancel", "showNext", "showSave", "showSaveAndClose", "showSaveAndNext"], outputs: ["onCancel", "onSave", "onNext", "onBack", "onSaveAndClose", "onSaveAndNext"] }, { kind: "component", type: i28.ActionsColumnComponent, selector: "app-actions-column", inputs: ["matColumnDef", "style", "stickyEnd", "canCancel", "canConfirm", "canDelete", "canBackward", "canForward", "canConfirmAndAdd", "dirtyIcon", "optionsTitle", "class", "cellTemplate"], outputs: ["optionsClick", "cancelOrDeleteClick", "confirmEditCreateClick", "confirmAndAddClick", "backward", "forward"] }, { kind: "directive", type: 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.ReferentialToStringPipe, name: "referentialToString" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
289
289
  }
290
290
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.2.4", ngImport: i0, type: TableTestPage, decorators: [{
291
291
  type: Component,
@@ -228,7 +228,7 @@ export class Table2TestPage extends AppTable {
228
228
  provide: AppTable,
229
229
  useExisting: forwardRef(() => Table2TestPage),
230
230
  },
231
- ], 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 select)</ion-title>\n\n <ion-buttons slot=\"end\">\n <ng-container *ngIf=\"!selection.hasValue(); else hasSelection\">\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 </ng-container>\n\n <!-- if row selection -->\n <ng-template #hasSelection>\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 </ng-template>\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 #filterExpansionPanel class=\"filter-panel filter-panel-floating\">\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 <!-- Close panel -->\n <ion-button\n mat-button\n fill=\"clear\"\n color=\"dark\"\n (click)=\"filterExpansionPanel.close()\"\n [disabled]=\"loadingSubject | async\"\n >\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 >\n <ng-container matColumnDef=\"select\" [sticky]=\"checkBoxSelection\" [class.mat-column-sticky]=\"checkBoxSelection\">\n <th mat-header-cell *matHeaderCellDef [class.cdk-visually-hidden]=\"!checkBoxSelection\">\n <mat-checkbox\n [checked]=\"selection.hasValue() && isAllSelected()\"\n [indeterminate]=\"selection.hasValue() && !isAllSelected()\"\n [hidden]=\"!selection.isMultipleSelection()\"\n (change)=\"$event ? masterToggle() : null\"\n ></mat-checkbox>\n </th>\n <td mat-cell *matCellDef=\"let row\" [class.cdk-visually-hidden]=\"!checkBoxSelection\">\n <mat-checkbox [checked]=\"selection.isSelected(row)\" (click)=\"toggleSelectRow($event, row)\"></mat-checkbox>\n </td>\n </ng-container>\n\n <!-- Id column -->\n <ng-container matColumnDef=\"id\" [sticky]=\"true\">\n <th mat-header-cell *matHeaderCellDef>\n <span mat-sort-header>\n <ion-label title=\"Id\">#</ion-label>\n <ion-label color=\"danger\" [innerHTML]=\"'&nbsp;*'\"></ion-label>\n </span>\n </th>\n <td mat-cell *matCellDef=\"let row\">\n <mat-form-field *ngIf=\"!readOnly && row.id === -1 && row.editing; else readOnlyId\">\n <input\n matInput\n autocomplete=\"off\"\n required\n [formControl]=\"row.validator | formGetControl: 'id'\"\n placeholder=\"Id\"\n [appAutofocus]=\"true\"\n />\n <mat-error *ngIf=\"(row.validator | formGetControl: 'id').hasError('required')\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n <mat-error *ngIf=\"(row.validator | formGetControl: 'id').hasError('alreadyExists')\" translate>\n ERROR.FIELD_NOT_UNIQUE_ID\n </mat-error>\n </mat-form-field>\n\n <ng-template #readOnlyId>\n <ion-label appAutoTitle>\n {{ (row.validator | formGetValue: 'id') || (row.currentData | propertyGet: 'id') }}\n </ion-label>\n </ng-template>\n </td>\n </ng-container>\n\n <!-- Name column -->\n <ng-container matColumnDef=\"name\">\n <th mat-header-cell *matHeaderCellDef [resizable]=\"resizable\">\n <!-- if sortable, wrap the header with a mat-sort-header -->\n <span mat-sort-header>\n <ion-label [title]=\"'TABLE.TESTING.NAME' | translate\">{{ 'TABLE.TESTING.NAME' | translate }}</ion-label>\n <ion-label color=\"danger\" [innerHTML]=\"'&nbsp;*'\"></ion-label>\n </span>\n </th>\n <td mat-cell *matCellDef=\"let row\">\n <mat-form-field *ngIf=\"!readOnly && row.editing; else readOnlyTemplate\">\n <input\n matInput\n autocomplete=\"off\"\n [required]=\"true\"\n [formControl]=\"row.validator | formGetControl: 'name'\"\n [placeholder]=\"'TABLE.TESTING.NAME' | translate\"\n [appAutofocus]=\"row.id === -1\"\n />\n <ng-content select=\"[suffix]\"></ng-content>\n <mat-error *ngIf=\"(row.validator | formGetControl: 'name').hasError('required')\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n <mat-error *ngIf=\"(row.validator | formGetControl: 'name').hasError('maxlength')\" translate>\n ERROR.FIELD_MAX_LENGTH_COMPACT\n </mat-error>\n <mat-error *ngIf=\"(row.validator | formGetControl: 'name').hasError('minlength')\" translate>\n ERROR.FIELD_MIN_LENGTH_COMPACT\n </mat-error>\n </mat-form-field>\n <ng-template #readOnlyTemplate>\n <ion-label appAutoTitle>\n {{ (row.validator | formGetValue: 'name') || (row.currentData | propertyGet: 'name') }}\n </ion-label>\n </ng-template>\n </td>\n </ng-container>\n\n <!-- Level column -->\n <ng-container matColumnDef=\"levelId\">\n <th mat-header-cell *matHeaderCellDef [resizable]=\"resizable\">\n <span mat-sort-header>\n <ion-label>{{ 'TABLE.TESTING.LEVEL_ID' | translate }}</ion-label>\n <ion-label color=\"danger\" [innerHTML]=\"'&nbsp;*'\"></ion-label>\n </span>\n </th>\n <td mat-cell *matCellDef=\"let row\">\n <mat-autocomplete-field\n *ngIf=\"!readOnly && row.editing; else readOnlyTemplate\"\n panelWidth=\"750px\"\n [formControl]=\"row.validator | formGetControl: 'levelId'\"\n [placeholder]=\"'TABLE.TESTING.LEVEL_ID' | translate\"\n floatLabel=\"never\"\n [required]=\"true\"\n [config]=\"autocompleteFields.level\"\n [highlightAccent]=\"true\"\n >\n <mat-error matError *ngIf=\"(row.validator | formGetControl: 'levelId').hasError('invalid')\" translate>\n ERROR.FIELD_INVALID\n </mat-error>\n </mat-autocomplete-field>\n <ng-template #readOnlyTemplate>\n <ion-label appAutoTitle>\n {{\n autocompleteFields.level?.displayWith(\n (row.validator | formGetValue: 'levelId') || (row.currentData | propertyGet: 'levelId')\n ) ||\n ((row.validator | formGetValue: 'levelId') || (row.currentData | propertyGet: 'levelId')\n | referentialToString)\n }}\n </ion-label>\n </ng-template>\n </td>\n </ng-container>\n\n <ng-container matColumnDef=\"boolean\">\n <th mat-header-cell *matHeaderCellDef cdkDrag [resizable]=\"resizable\">\n <!-- if sortable, wrap the header with a mat-sort-header -->\n <span mat-sort-header>\n <ion-label>Boolean</ion-label>\n </span>\n </th>\n <td mat-cell *matCellDef=\"let row\">\n <mat-boolean-field\n *ngIf=\"!readOnly && row.editing; else readOnlyTemplate\"\n floatLabel=\"never\"\n [style]=\"'checkbox'\"\n [formControl]=\"\n (row.validator | formGetControl: 'boolean') || formBuilder.control(row.currentData['boolean'])\n \"\n ></mat-boolean-field>\n <ng-template #readOnlyTemplate>\n <ion-label appAutoTitle>\n {{\n (row.validator | formGetValue: 'boolean') || (row.currentData | propertyGet: 'boolean')\n ? ('COMMON.YES' | translate)\n : ('COMMON.NO' | translate)\n }}\n </ion-label>\n </ng-template>\n </td>\n </ng-container>\n\n <ng-container matColumnDef=\"boolean2\">\n <th mat-header-cell *matHeaderCellDef cdkDrag [resizable]=\"resizable\">\n <!-- if sortable, wrap the header with a mat-sort-header -->\n <span mat-sort-header>\n <ion-label>Boolean 2</ion-label>\n </span>\n </th>\n <td mat-cell *matCellDef=\"let row\">\n <mat-boolean-field\n *ngIf=\"!readOnly && row.editing; else readOnlyTemplate\"\n floatLabel=\"never\"\n [style]=\"'radio'\"\n [formControl]=\"\n (row.validator | formGetControl: 'boolean2') || formBuilder.control(row.currentData['boolean2'])\n \"\n ></mat-boolean-field>\n <ng-template #readOnlyTemplate>\n <ion-label appAutoTitle>\n {{\n (row.validator | formGetValue: 'boolean2') || (row.currentData | propertyGet: 'boolean2')\n ? ('COMMON.YES' | translate)\n : ('COMMON.NO' | translate)\n }}\n </ion-label>\n </ng-template>\n </td>\n </ng-container>\n\n <!-- Actions buttons column -->\n <app-actions-column\n [stickyEnd]=\"true\"\n [canCancel]=\"false\"\n (optionsClick)=\"openSelectColumnsModal($event)\"\n (cancelOrDeleteClick)=\"cancelOrDelete($event.event, $event.row)\"\n (confirmAndAddClick)=\"confirmAndAdd($event.event, $event.row)\"\n (backward)=\"confirmAndBackward($event.event, $event.row)\"\n (forward)=\"confirmAndForward($event.event, $event.row)\"\n [cellTemplate]=\"cellInjection\"\n >\n <!-- cell injection-->\n <ng-template #cellInjection let-row>\n <span *ngIf=\"row.editing && !row.validator.dirty\">-</span>\n </ng-template>\n </app-actions-column>\n\n <tr mat-header-row *matHeaderRowDef=\"displayedColumns; sticky: true\"></tr>\n <tr\n mat-row\n *matRowDef=\"let row; columns: displayedColumns\"\n [class.mat-row-selected]=\"row.editing\"\n [class.mat-row-error]=\"row.validator?.invalid\"\n [class.mat-row-disabled]=\"!row.editing\"\n [class.mat-row-dirty]=\"row.validator?.dirty\"\n (click)=\"clickRow($event, row)\"\n (keydown.escape)=\"escapeEditingRow($event)\"\n [cdkTrapFocus]=\"row.validator?.invalid\"\n ></tr>\n </table>\n\n <ng-container *ngIf=\"loadingSubject | async; else noResult\">\n <ion-item>\n <ion-skeleton-text animated></ion-skeleton-text>\n </ion-item>\n </ng-container>\n\n <ng-template #noResult>\n <ion-item *ngIf=\"totalRowCount === 0\">\n <ion-text color=\"danger\" class=\"text-italic\" translate>COMMON.NO_RESULT</ion-text>\n </ion-item>\n </ng-template>\n\n <ion-infinite-scroll\n *ngIf=\"enableInfiniteScroll\"\n [threshold]=\"mobile ? '10%' : '2%'\"\n position=\"bottom\"\n (ionInfinite)=\"fetchMore($event)\"\n >\n <ion-infinite-scroll-content\n loadingSpinner=\"circles\"\n [loadingText]=\"'COMMON.LOADING_DOTS' | translate\"\n ></ion-infinite-scroll-content>\n </ion-infinite-scroll>\n </div>\n</ion-content>\n\n<ion-footer>\n <!-- Paginator -->\n <mat-paginator\n *ngIf=\"!enableInfiniteScroll\"\n [length]=\"totalRowCount\"\n [pageSize]=\"defaultPageSize\"\n [pageSizeOptions]=\"defaultPageSizeOptions\"\n showFirstLastButtons\n ></mat-paginator>\n\n <app-form-buttons-bar\n *ngIf=\"canEdit && !mobile\"\n (onCancel)=\"load()\"\n (onSave)=\"save()\"\n [disabled]=\"(loadingSubject | async) || !dirty\"\n >\n <!-- error -->\n <ion-item *ngIf=\"error$ | async\" lines=\"none\">\n <ion-icon color=\"danger\" slot=\"start\" name=\"alert-circle\"></ion-icon>\n <ion-label color=\"danger\" [innerHTML]=\"error | translate\"></ion-label>\n </ion-item>\n </app-form-buttons-bar>\n</ion-footer>\n\n<ion-fab slot=\"fixed\" vertical=\"bottom\" horizontal=\"end\" *ngIf=\"canEdit && mobile\">\n <ion-fab-button color=\"tertiary\" (click)=\"addRow($event)\">\n <ion-icon name=\"add\"></ion-icon>\n </ion-fab-button>\n</ion-fab>\n", styles: [".table-container .mat-mdc-table .mat-column-select{min-width:30px}.table-container .mat-mdc-table .mat-column-id{min-width:30px;max-width:30px}.table-container .mat-mdc-table .mat-column-label,.table-container .mat-mdc-table .mat-column-name,.table-container .mat-mdc-table .mat-column-levelId,.table-container .mat-mdc-table .mat-column-statusId{min-width:150px}.table-container .mat-mdc-table .mat-column-comments{min-width:100px;max-width:100px}.table-container .mat-mdc-table .mat-column-updateDate{min-width:110px;max-width:110px}\n"], dependencies: [{ kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: 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", "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", "counter", "counterFormatter", "detail", "detailIcon", "disabled", "download", "fill", "href", "lines", "mode", "rel", "routerAnimation", "routerDirection", "shape", "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"], 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", "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: "directive", type: i16.MatBadge, selector: "[matBadge]", inputs: ["matBadgeColor", "matBadgeOverlap", "matBadgeDisabled", "matBadgePosition", "matBadge", "matBadgeDescription", "matBadgeSize", "matBadgeHidden"] }, { kind: "directive", type: i17.CdkTrapFocus, selector: "[cdkTrapFocus]", inputs: ["cdkTrapFocus", "cdkTrapFocusAutoCapture"], exportAs: ["cdkTrapFocus"] }, { kind: "component", type: i18.MatAutocompleteField, selector: "mat-autocomplete-field", inputs: ["equals", "logPrefix", "formControl", "formControlName", "floatLabel", "appearance", "placeholder", "suggestFn", "required", "mobile", "clearable", "debounceTime", "displayWith", "displayAttributes", "displayColumnSizes", "displayColumnNames", "highlightAccent", "showAllOnFocus", "showPanelOnFocus", "autofocus", "config", "i18nPrefix", "noResultMessage", "class", "panelWidth", "matAutocompletePosition", "multiple", "fetchMoreThreshold", "suggestLengthThreshold", "showLoadingSpinner", "debug", "showSearchBar", "stickySearchBar", "applyImplicitValue", "dropButtonTitle", "clearButtonTitle", "filter", "readonly", "tabindex", "items"], outputs: ["click", "blur", "focus", "dropButtonClick", "keydown.escape", "keyup.enter"] }, { kind: "component", type: i19.MatBooleanField, selector: "mat-boolean-field", inputs: ["disabled", "formControl", "formControlName", "placeholder", "floatLabel", "appearance", "readonly", "required", "compact", "style", "buttonsColCount", "class", "yesLabel", "noLabel", "showButtonIcons", "yesIcon", "noIcon", "tabindex", "value"], outputs: ["keyup.enter", "onBlur"] }, { kind: "directive", type: i20.AutofocusDirective, selector: "[autofocus], input[appAutofocus]", inputs: ["appAutofocus", "autofocusDelay"] }, { kind: "directive", type: i21.AutoTitleDirective, selector: "[appAutoTitle]" }, { kind: "component", type: i22.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: i23.FormButtonsBarComponent, selector: "app-form-buttons-bar", inputs: ["disabled", "disabledCancel", "classList", "saveButtonColor", "backText", "cancelText", "nextText", "showBack", "showCancel", "showNext", "showSave", "showSaveAndClose", "showSaveAndNext"], outputs: ["onCancel", "onSave", "onNext", "onBack", "onSaveAndClose", "onSaveAndNext"] }, { kind: "component", type: i24.ActionsColumnComponent, selector: "app-actions-column", inputs: ["matColumnDef", "style", "stickyEnd", "canCancel", "canConfirm", "canDelete", "canBackward", "canForward", "canConfirmAndAdd", "dirtyIcon", "optionsTitle", "class", "cellTemplate"], outputs: ["optionsClick", "cancelOrDeleteClick", "confirmEditCreateClick", "confirmAndAddClick", "backward", "forward"] }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i25.ResizableComponent, selector: "th[resizable]", inputs: ["resizable"], outputs: ["sizeChanged"] }, { kind: "directive", type: i26.ResizableDirective, selector: "[resizable]", outputs: ["resizable", "fit"] }, { kind: "pipe", type: i3.AsyncPipe, name: "async" }, { kind: "pipe", type: i5.TranslatePipe, name: "translate" }, { kind: "pipe", type: i27.PropertyGetPipe, name: "propertyGet" }, { kind: "pipe", type: i28.NumberFormatPipe, name: "numberFormat" }, { kind: "pipe", type: i29.ArrayLengthPipe, name: "isArrayLength" }, { kind: "pipe", type: i30.FormGetControlPipe, name: "formGetControl" }, { kind: "pipe", type: i30.FormGetValuePipe, name: "formGetValue" }, { kind: "pipe", type: i31.ReferentialToStringPipe, name: "referentialToString" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
231
+ ], 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 select)</ion-title>\n\n <ion-buttons slot=\"end\">\n <ng-container *ngIf=\"!selection.hasValue(); else hasSelection\">\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 </ng-container>\n\n <!-- if row selection -->\n <ng-template #hasSelection>\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 </ng-template>\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 #filterExpansionPanel class=\"filter-panel filter-panel-floating\">\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 <!-- Close panel -->\n <ion-button\n mat-button\n fill=\"clear\"\n color=\"dark\"\n (click)=\"filterExpansionPanel.close()\"\n [disabled]=\"loadingSubject | async\"\n >\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 >\n <ng-container matColumnDef=\"select\" [sticky]=\"checkBoxSelection\" [class.mat-column-sticky]=\"checkBoxSelection\">\n <th mat-header-cell *matHeaderCellDef [class.cdk-visually-hidden]=\"!checkBoxSelection\">\n <mat-checkbox\n [checked]=\"selection.hasValue() && isAllSelected()\"\n [indeterminate]=\"selection.hasValue() && !isAllSelected()\"\n [hidden]=\"!selection.isMultipleSelection()\"\n (change)=\"$event ? masterToggle() : null\"\n ></mat-checkbox>\n </th>\n <td mat-cell *matCellDef=\"let row\" [class.cdk-visually-hidden]=\"!checkBoxSelection\">\n <mat-checkbox [checked]=\"selection.isSelected(row)\" (click)=\"toggleSelectRow($event, row)\"></mat-checkbox>\n </td>\n </ng-container>\n\n <!-- Id column -->\n <ng-container matColumnDef=\"id\" [sticky]=\"true\">\n <th mat-header-cell *matHeaderCellDef>\n <span mat-sort-header>\n <ion-label title=\"Id\">#</ion-label>\n <ion-label color=\"danger\" [innerHTML]=\"'&nbsp;*'\"></ion-label>\n </span>\n </th>\n <td mat-cell *matCellDef=\"let row\">\n <mat-form-field *ngIf=\"!readOnly && row.id === -1 && row.editing; else readOnlyId\">\n <input\n matInput\n autocomplete=\"off\"\n required\n [formControl]=\"row.validator | formGetControl: 'id'\"\n placeholder=\"Id\"\n [appAutofocus]=\"true\"\n />\n <mat-error *ngIf=\"(row.validator | formGetControl: 'id').hasError('required')\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n <mat-error *ngIf=\"(row.validator | formGetControl: 'id').hasError('alreadyExists')\" translate>\n ERROR.FIELD_NOT_UNIQUE_ID\n </mat-error>\n </mat-form-field>\n\n <ng-template #readOnlyId>\n <ion-label appAutoTitle>\n {{ (row.validator | formGetValue: 'id') || (row.currentData | propertyGet: 'id') }}\n </ion-label>\n </ng-template>\n </td>\n </ng-container>\n\n <!-- Name column -->\n <ng-container matColumnDef=\"name\">\n <th mat-header-cell *matHeaderCellDef [resizable]=\"resizable\">\n <!-- if sortable, wrap the header with a mat-sort-header -->\n <span mat-sort-header>\n <ion-label [title]=\"'TABLE.TESTING.NAME' | translate\">{{ 'TABLE.TESTING.NAME' | translate }}</ion-label>\n <ion-label color=\"danger\" [innerHTML]=\"'&nbsp;*'\"></ion-label>\n </span>\n </th>\n <td mat-cell *matCellDef=\"let row\">\n <mat-form-field *ngIf=\"!readOnly && row.editing; else readOnlyTemplate\">\n <input\n matInput\n autocomplete=\"off\"\n [required]=\"true\"\n [formControl]=\"row.validator | formGetControl: 'name'\"\n [placeholder]=\"'TABLE.TESTING.NAME' | translate\"\n [appAutofocus]=\"row.id === -1\"\n />\n <ng-content select=\"[suffix]\"></ng-content>\n <mat-error *ngIf=\"(row.validator | formGetControl: 'name').hasError('required')\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n <mat-error *ngIf=\"(row.validator | formGetControl: 'name').hasError('maxlength')\" translate>\n ERROR.FIELD_MAX_LENGTH_COMPACT\n </mat-error>\n <mat-error *ngIf=\"(row.validator | formGetControl: 'name').hasError('minlength')\" translate>\n ERROR.FIELD_MIN_LENGTH_COMPACT\n </mat-error>\n </mat-form-field>\n <ng-template #readOnlyTemplate>\n <ion-label appAutoTitle>\n {{ (row.validator | formGetValue: 'name') || (row.currentData | propertyGet: 'name') }}\n </ion-label>\n </ng-template>\n </td>\n </ng-container>\n\n <!-- Level column -->\n <ng-container matColumnDef=\"levelId\">\n <th mat-header-cell *matHeaderCellDef [resizable]=\"resizable\">\n <span mat-sort-header>\n <ion-label>{{ 'TABLE.TESTING.LEVEL_ID' | translate }}</ion-label>\n <ion-label color=\"danger\" [innerHTML]=\"'&nbsp;*'\"></ion-label>\n </span>\n </th>\n <td mat-cell *matCellDef=\"let row\">\n <mat-autocomplete-field\n *ngIf=\"!readOnly && row.editing; else readOnlyTemplate\"\n panelWidth=\"750px\"\n [formControl]=\"row.validator | formGetControl: 'levelId'\"\n [placeholder]=\"'TABLE.TESTING.LEVEL_ID' | translate\"\n floatLabel=\"never\"\n [required]=\"true\"\n [config]=\"autocompleteFields.level\"\n [highlightAccent]=\"true\"\n >\n <mat-error matError *ngIf=\"(row.validator | formGetControl: 'levelId').hasError('invalid')\" translate>\n ERROR.FIELD_INVALID\n </mat-error>\n </mat-autocomplete-field>\n <ng-template #readOnlyTemplate>\n <ion-label appAutoTitle>\n {{\n autocompleteFields.level?.displayWith(\n (row.validator | formGetValue: 'levelId') || (row.currentData | propertyGet: 'levelId')\n ) ||\n ((row.validator | formGetValue: 'levelId') || (row.currentData | propertyGet: 'levelId')\n | referentialToString)\n }}\n </ion-label>\n </ng-template>\n </td>\n </ng-container>\n\n <ng-container matColumnDef=\"boolean\">\n <th mat-header-cell *matHeaderCellDef cdkDrag [resizable]=\"resizable\">\n <!-- if sortable, wrap the header with a mat-sort-header -->\n <span mat-sort-header>\n <ion-label>Boolean</ion-label>\n </span>\n </th>\n <td mat-cell *matCellDef=\"let row\">\n <mat-boolean-field\n *ngIf=\"!readOnly && row.editing; else readOnlyTemplate\"\n floatLabel=\"never\"\n [style]=\"'checkbox'\"\n [formControl]=\"\n (row.validator | formGetControl: 'boolean') || formBuilder.control(row.currentData['boolean'])\n \"\n ></mat-boolean-field>\n <ng-template #readOnlyTemplate>\n <ion-label appAutoTitle>\n {{\n (row.validator | formGetValue: 'boolean') || (row.currentData | propertyGet: 'boolean')\n ? ('COMMON.YES' | translate)\n : ('COMMON.NO' | translate)\n }}\n </ion-label>\n </ng-template>\n </td>\n </ng-container>\n\n <ng-container matColumnDef=\"boolean2\">\n <th mat-header-cell *matHeaderCellDef cdkDrag [resizable]=\"resizable\">\n <!-- if sortable, wrap the header with a mat-sort-header -->\n <span mat-sort-header>\n <ion-label>Boolean 2</ion-label>\n </span>\n </th>\n <td mat-cell *matCellDef=\"let row\">\n <mat-boolean-field\n *ngIf=\"!readOnly && row.editing; else readOnlyTemplate\"\n floatLabel=\"never\"\n [style]=\"'radio'\"\n [formControl]=\"\n (row.validator | formGetControl: 'boolean2') || formBuilder.control(row.currentData['boolean2'])\n \"\n ></mat-boolean-field>\n <ng-template #readOnlyTemplate>\n <ion-label appAutoTitle>\n {{\n (row.validator | formGetValue: 'boolean2') || (row.currentData | propertyGet: 'boolean2')\n ? ('COMMON.YES' | translate)\n : ('COMMON.NO' | translate)\n }}\n </ion-label>\n </ng-template>\n </td>\n </ng-container>\n\n <!-- Actions buttons column -->\n <app-actions-column\n [stickyEnd]=\"true\"\n [canCancel]=\"false\"\n (optionsClick)=\"openSelectColumnsModal($event)\"\n (cancelOrDeleteClick)=\"cancelOrDelete($event.event, $event.row)\"\n (confirmAndAddClick)=\"confirmAndAdd($event.event, $event.row)\"\n (backward)=\"confirmAndBackward($event.event, $event.row)\"\n (forward)=\"confirmAndForward($event.event, $event.row)\"\n [cellTemplate]=\"cellInjection\"\n >\n <!-- cell injection-->\n <ng-template #cellInjection let-row>\n <span *ngIf=\"row.editing && !row.validator.dirty\">-</span>\n </ng-template>\n </app-actions-column>\n\n <tr mat-header-row *matHeaderRowDef=\"displayedColumns; sticky: true\"></tr>\n <tr\n mat-row\n *matRowDef=\"let row; columns: displayedColumns\"\n [class.mat-row-selected]=\"row.editing\"\n [class.mat-row-error]=\"row.validator?.invalid\"\n [class.mat-row-disabled]=\"!row.editing\"\n [class.mat-row-dirty]=\"row.validator?.dirty\"\n (click)=\"clickRow($event, row)\"\n (keydown.escape)=\"escapeEditingRow($event)\"\n [cdkTrapFocus]=\"row.validator?.invalid\"\n ></tr>\n </table>\n\n <ng-container *ngIf=\"loadingSubject | async; else noResult\">\n <ion-item>\n <ion-skeleton-text animated></ion-skeleton-text>\n </ion-item>\n </ng-container>\n\n <ng-template #noResult>\n <ion-item *ngIf=\"totalRowCount === 0\">\n <ion-text color=\"danger\" class=\"text-italic\" translate>COMMON.NO_RESULT</ion-text>\n </ion-item>\n </ng-template>\n\n <ion-infinite-scroll\n *ngIf=\"enableInfiniteScroll\"\n [threshold]=\"mobile ? '10%' : '2%'\"\n position=\"bottom\"\n (ionInfinite)=\"fetchMore($event)\"\n >\n <ion-infinite-scroll-content\n loadingSpinner=\"circles\"\n [loadingText]=\"'COMMON.LOADING_DOTS' | translate\"\n ></ion-infinite-scroll-content>\n </ion-infinite-scroll>\n </div>\n</ion-content>\n\n<ion-footer>\n <!-- Paginator -->\n <mat-paginator\n *ngIf=\"!enableInfiniteScroll\"\n [length]=\"totalRowCount\"\n [pageSize]=\"defaultPageSize\"\n [pageSizeOptions]=\"defaultPageSizeOptions\"\n showFirstLastButtons\n ></mat-paginator>\n\n <app-form-buttons-bar\n *ngIf=\"canEdit && !mobile\"\n (onCancel)=\"load()\"\n (onSave)=\"save()\"\n [disabled]=\"(loadingSubject | async) || !dirty\"\n >\n <!-- error -->\n <ion-item *ngIf=\"error$ | async\" lines=\"none\">\n <ion-icon color=\"danger\" slot=\"start\" name=\"alert-circle\"></ion-icon>\n <ion-label color=\"danger\" [innerHTML]=\"error | translate\"></ion-label>\n </ion-item>\n </app-form-buttons-bar>\n</ion-footer>\n\n<ion-fab slot=\"fixed\" vertical=\"bottom\" horizontal=\"end\" *ngIf=\"canEdit && mobile\">\n <ion-fab-button color=\"tertiary\" (click)=\"addRow($event)\">\n <ion-icon name=\"add\"></ion-icon>\n </ion-fab-button>\n</ion-fab>\n", styles: [".table-container .mat-mdc-table .mat-column-select{min-width:30px}.table-container .mat-mdc-table .mat-column-id{min-width:30px;max-width:30px}.table-container .mat-mdc-table .mat-column-label,.table-container .mat-mdc-table .mat-column-name,.table-container .mat-mdc-table .mat-column-levelId,.table-container .mat-mdc-table .mat-column-statusId{min-width:150px}.table-container .mat-mdc-table .mat-column-comments{min-width:100px;max-width:100px}.table-container .mat-mdc-table .mat-column-updateDate{min-width:110px;max-width:110px}\n"], dependencies: [{ kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: 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", "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", "counter", "counterFormatter", "detail", "detailIcon", "disabled", "download", "fill", "href", "lines", "mode", "rel", "routerAnimation", "routerDirection", "shape", "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"], 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", "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: "directive", type: i16.MatBadge, selector: "[matBadge]", inputs: ["matBadgeColor", "matBadgeOverlap", "matBadgeDisabled", "matBadgePosition", "matBadge", "matBadgeDescription", "matBadgeSize", "matBadgeHidden"] }, { kind: "directive", type: i17.CdkTrapFocus, selector: "[cdkTrapFocus]", inputs: ["cdkTrapFocus", "cdkTrapFocusAutoCapture"], exportAs: ["cdkTrapFocus"] }, { kind: "component", type: i18.MatAutocompleteField, selector: "mat-autocomplete-field", inputs: ["equals", "logPrefix", "formControl", "formControlName", "floatLabel", "appearance", "subscriptSizing", "placeholder", "suggestFn", "required", "mobile", "clearable", "debounceTime", "displayWith", "displayAttributes", "displayColumnSizes", "displayColumnNames", "highlightAccent", "showAllOnFocus", "showPanelOnFocus", "autofocus", "config", "i18nPrefix", "noResultMessage", "class", "panelWidth", "matAutocompletePosition", "multiple", "fetchMoreThreshold", "suggestLengthThreshold", "showLoadingSpinner", "debug", "showSearchBar", "stickySearchBar", "applyImplicitValue", "dropButtonTitle", "clearButtonTitle", "filter", "readonly", "tabindex", "items"], outputs: ["click", "blur", "focus", "dropButtonClick", "keydown.escape", "keyup.enter"] }, { kind: "component", type: i19.MatBooleanField, selector: "mat-boolean-field", inputs: ["disabled", "formControl", "formControlName", "placeholder", "floatLabel", "appearance", "subscriptSizing", "readonly", "required", "compact", "style", "buttonsColCount", "class", "yesLabel", "noLabel", "showButtonIcons", "yesIcon", "noIcon", "tabindex", "value"], outputs: ["keyup.enter", "onBlur"] }, { kind: "directive", type: i20.AutofocusDirective, selector: "[autofocus], input[appAutofocus]", inputs: ["appAutofocus", "autofocusDelay"] }, { kind: "directive", type: i21.AutoTitleDirective, selector: "[appAutoTitle]" }, { kind: "component", type: i22.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: i23.FormButtonsBarComponent, selector: "app-form-buttons-bar", inputs: ["disabled", "disabledCancel", "classList", "saveButtonColor", "backText", "cancelText", "nextText", "showBack", "showCancel", "showNext", "showSave", "showSaveAndClose", "showSaveAndNext"], outputs: ["onCancel", "onSave", "onNext", "onBack", "onSaveAndClose", "onSaveAndNext"] }, { kind: "component", type: i24.ActionsColumnComponent, selector: "app-actions-column", inputs: ["matColumnDef", "style", "stickyEnd", "canCancel", "canConfirm", "canDelete", "canBackward", "canForward", "canConfirmAndAdd", "dirtyIcon", "optionsTitle", "class", "cellTemplate"], outputs: ["optionsClick", "cancelOrDeleteClick", "confirmEditCreateClick", "confirmAndAddClick", "backward", "forward"] }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i25.ResizableComponent, selector: "th[resizable]", inputs: ["resizable"], outputs: ["sizeChanged"] }, { kind: "directive", type: i26.ResizableDirective, selector: "[resizable]", outputs: ["resizable", "fit"] }, { kind: "pipe", type: i3.AsyncPipe, name: "async" }, { kind: "pipe", type: i5.TranslatePipe, name: "translate" }, { kind: "pipe", type: i27.PropertyGetPipe, name: "propertyGet" }, { kind: "pipe", type: i28.NumberFormatPipe, name: "numberFormat" }, { kind: "pipe", type: i29.ArrayLengthPipe, name: "isArrayLength" }, { kind: "pipe", type: i30.FormGetControlPipe, name: "formGetControl" }, { kind: "pipe", type: i30.FormGetValuePipe, name: "formGetValue" }, { kind: "pipe", type: i31.ReferentialToStringPipe, name: "referentialToString" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
232
232
  }
233
233
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.2.4", ngImport: i0, type: Table2TestPage, decorators: [{
234
234
  type: Component,
@@ -160,16 +160,18 @@ export class Alerts {
160
160
  }
161
161
  return false; // Leave without saving
162
162
  }
163
- static async askSaveBeforeAction(alertCtrl, translate, event, interpolateParams) {
163
+ static async askSaveBeforeAction(alertCtrl, translate, opts, interpolateParams) {
164
164
  let save = false;
165
- let confirm = false;
165
+ let confirmed = false;
166
166
  let alert;
167
+ const validMessageI18n = opts?.validMessageI18n || 'CONFIRM.SAVE_BEFORE_CONTINUE';
168
+ const invalidMessageI18n = opts?.invalidMessageI18n || 'CONFIRM.CANCEL_CHANGES';
167
169
  // Ask user before save
168
- if (event && event.valid) {
169
- const translations = translate.instant(['COMMON.BTN_CANCEL', 'COMMON.BTN_SAVE', 'COMMON.BTN_ABORT_CHANGES', 'CONFIRM.SAVE_BEFORE_CONTINUE', 'CONFIRM.ALERT_HEADER'], interpolateParams);
170
+ if (opts?.valid) {
171
+ const translations = translate.instant(['COMMON.BTN_CANCEL', 'COMMON.BTN_SAVE', 'COMMON.BTN_ABORT_CHANGES', 'CONFIRM.ALERT_HEADER', validMessageI18n], interpolateParams);
170
172
  alert = await alertCtrl.create({
171
173
  header: translations['CONFIRM.ALERT_HEADER'],
172
- message: translations['CONFIRM.SAVE_BEFORE_CONTINUE'],
174
+ message: translations[validMessageI18n],
173
175
  buttons: [
174
176
  {
175
177
  text: translations['COMMON.BTN_CANCEL'],
@@ -181,30 +183,30 @@ export class Alerts {
181
183
  text: translations['COMMON.BTN_ABORT_CHANGES'],
182
184
  cssClass: 'secondary',
183
185
  handler: () => {
184
- confirm = true;
186
+ confirmed = true;
185
187
  },
186
188
  },
187
189
  {
188
190
  text: translations['COMMON.BTN_SAVE'],
189
191
  handler: () => {
190
192
  save = true;
191
- confirm = true;
193
+ confirmed = true;
192
194
  },
193
195
  },
194
196
  ],
195
197
  });
196
198
  }
197
199
  else {
198
- const translations = translate.instant(['COMMON.BTN_ABORT_CHANGES', 'COMMON.BTN_CANCEL', 'CONFIRM.CANCEL_CHANGES', 'CONFIRM.ALERT_HEADER'], interpolateParams);
200
+ const translations = translate.instant(['COMMON.BTN_ABORT_CHANGES', 'COMMON.BTN_CANCEL', 'CONFIRM.ALERT_HEADER', invalidMessageI18n], interpolateParams);
199
201
  alert = await alertCtrl.create({
200
202
  header: translations['CONFIRM.ALERT_HEADER'],
201
- message: translations['CONFIRM.CANCEL_CHANGES'],
203
+ message: translations[invalidMessageI18n],
202
204
  buttons: [
203
205
  {
204
206
  text: translations['COMMON.BTN_ABORT_CHANGES'],
205
207
  cssClass: 'secondary',
206
208
  handler: () => {
207
- confirm = true;
209
+ confirmed = true;
208
210
  },
209
211
  },
210
212
  {
@@ -217,7 +219,7 @@ export class Alerts {
217
219
  }
218
220
  await alert.present();
219
221
  await alert.onDidDismiss();
220
- return { confirmed: confirm, save };
222
+ return { confirmed, save };
221
223
  }
222
224
  static async showError(messageKey, alertCtrl, translate, opts, interpolateParams) {
223
225
  if (!messageKey || !alertCtrl || !translate)
@@ -238,4 +240,4 @@ export class Alerts {
238
240
  await alert.onDidDismiss();
239
241
  }
240
242
  }
241
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWxlcnRzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vc3JjL2FwcC9zaGFyZWQvYWxlcnRzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUdBLE1BQU0sT0FBTyxNQUFNO0lBQ2pCOzs7Ozs7OztPQVFHO0lBQ0gsTUFBTSxDQUFDLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxTQUEwQixFQUFFLFNBQTJCLEVBQUUsS0FBYTtRQUNwRyxJQUFJLE9BQU8sR0FBRyxLQUFLLENBQUM7UUFDcEIsSUFBSSxNQUFNLEdBQUcsS0FBSyxDQUFDO1FBQ25CLE1BQU0sWUFBWSxHQUFHLFNBQVMsQ0FBQyxPQUFPLENBQUM7WUFDckMsaUJBQWlCO1lBQ2pCLG1CQUFtQjtZQUNuQiwwQkFBMEI7WUFDMUIsY0FBYztZQUNkLHNCQUFzQjtTQUN2QixDQUFDLENBQUM7UUFDSCxNQUFNLEtBQUssR0FBRyxNQUFNLFNBQVMsQ0FBQyxNQUFNLENBQUM7WUFDbkMsTUFBTSxFQUFFLFlBQVksQ0FBQyxzQkFBc0IsQ0FBQztZQUM1QyxPQUFPLEVBQUUsWUFBWSxDQUFDLGNBQWMsQ0FBQztZQUNyQyxPQUFPLEVBQUU7Z0JBQ1A7b0JBQ0UsSUFBSSxFQUFFLFlBQVksQ0FBQyxtQkFBbUIsQ0FBQztvQkFDdkMsSUFBSSxFQUFFLFFBQVE7b0JBQ2QsUUFBUSxFQUFFLFdBQVc7b0JBQ3JCLE9BQU8sRUFBRSxHQUFHLEVBQUU7d0JBQ1osTUFBTSxHQUFHLElBQUksQ0FBQztvQkFDaEIsQ0FBQztpQkFDRjtnQkFDRDtvQkFDRSxJQUFJLEVBQUUsWUFBWSxDQUFDLDBCQUEwQixDQUFDO29CQUM5QyxRQUFRLEVBQUUsV0FBVztvQkFDckIsT0FBTyxFQUFFLEdBQUcsRUFBRSxHQUFFLENBQUM7aUJBQ2xCO2dCQUNEO29CQUNFLElBQUksRUFBRSxZQUFZLENBQUMsaUJBQWlCLENBQUM7b0JBQ3JDLE9BQU8sRUFBRSxHQUFHLEVBQUU7d0JBQ1osT0FBTyxHQUFHLElB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LEtBQUssQ0FBQyx3RUFBd0UsQ0FBQyxDQUFDO1FBQ3ZJLE1BQU0sUUFBUSxHQUFHLENBQUMsSUFBSSxJQUFJLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxvQkFBb0IsQ0FBQztRQUNqRSxNQUFNLFlBQVksR0FBRyxTQUFTLENBQUMsT0FBTyxDQUFDLENBQUMsZUFBZSxFQUFFLFVBQVUsRUFBRSxRQUFRLENBQUMsRUFBRSxpQkFBaUIsQ0FBQyxDQUFDO1FBQ25HLE1BQU0sS0FBSyxHQUFHLE1BQU0sU0FBUyxDQUFDLE1BQU0sQ0FBQztZQUNuQyxNQUFNLEVBQUUsWUFBWSxDQUFDLFFBQVEsQ0FBQztZQUM5QixPQUFPLEVBQUUsWUFBWSxDQUFDLFVBQVUsQ0FBQztZQUNqQyxPQUFPLEVBQUU7Z0JBQ1A7b0JBQ0UsSUFBSSxFQUFFLFlBQVksQ0FBQyxlQUFlLENBQUM7b0JBQ25DLElBQUksRUFBRSxRQUFRO2lCQUNmO2FBQ0Y7U0FDRixDQUFDLENBQUM7UUFDSCxNQUFNLEtBQUssQ0FBQyxPQUFPLEVBQUUsQ0FBQztRQUN0QixNQUFNLEtBQUssQ0FBQyxZQUFZLEVBQUUsQ0FBQztJQUM3QixDQUFDO0NBQ0YiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBBbGVydENvbnRyb2xsZXIgfSBmcm9tICdAaW9uaWMvYW5ndWxhcic7XG5pbXBvcnQgeyBUcmFuc2xhdGVTZXJ2aWNlIH0gZnJvbSAnQG5neC10cmFuc2xhdGUvY29yZSc7XG5cbmV4cG9ydCBjbGFzcyBBbGVydHMge1xuICAvKipcbiAgICogQXNrIHRoZSB1c2VyIHRvIHNhdmUgYmVmb3JlIGxlYXZpbmcuIElmIHJldHVybiB1bmRlZmluZWQ6IHVzZXIgaGFzIGNhbmNlbGxlZFxuICAgKiA8cD5cbiAgICogICBmcm9tIGEgcm91dGVkIHBhZ2UsIHByZWZlciB1c2luZyBDb21wb25lbnREaXJ0eUd1YXJkXG4gICAqXG4gICAqIEBwYXJhbSBhbGVydEN0cmxcbiAgICogQHBhcmFtIHRyYW5zbGF0ZVxuICAgKiBAcGFyYW0gZXZlbnRcbiAgICovXG4gIHN0YXRpYyBhc3luYyBhc2tTYXZlQmVmb3JlTGVhdmUoYWxlcnRDdHJsOiBBbGVydENvbnRyb2xsZXIsIHRyYW5zbGF0ZTogVHJhbnNsYXRlU2VydmljZSwgZXZlbnQ/OiBFdmVudCk6IFByb21pc2U8Ym9vbGVhbiB8IHVuZGVmaW5lZD4ge1xuICAgIGxldCBjb25maXJtID0gZmFsc2U7XG4gICAgbGV0IGNhbmNlbCA9IGZhbHNlO1xuICAgIGNvbnN0IHRyYW5zbGF0aW9ucyA9IHRyYW5zbGF0ZS5pbnN0YW50KFtcbiAgICAgICdDT01NT04uQlROX1NBVkUnLFxuICAgICAgJ0NPTU1PTi5CVE5fQ0FOQ0VMJyxcbiAgICAgICdDT01NT04uQlROX0FCT1JUX0NIQU5HRVMnLFxuICAgICAgJ0NPTkZJUk0uU0FWRScsXG4gICAgICAnQ09ORklSTS5BTEVSVF9IRUFERVInLFxuICAgIF0pO1xuICAgIGNvbnN0IGFsZXJ0ID0gYXdhaXQgYWxlcnRDdHJsLmNyZWF0ZSh7XG4gICAgICBoZWFkZXI6IHRyYW5zbGF0aW9uc1snQ09ORklSTS5BTEVSVF9IRUFERVInXSxcbiAgICAgIG1lc3NhZ2U6IHRyYW5zbGF0aW9uc1snQ09ORklSTS5TQVZFJ10sXG4gICAgICBidXR0b25zOiBbXG4gICAgICAgIHtcbiAgICAgICAgICB0ZXh0OiB0cmFuc2xhdGlvbnNbJ0NPTU1PTi5CVE5fQ0FOQ0VMJ10sXG4gICAgICAgICAgcm9sZTogJ2NhbmNlbCcsXG4gICAgICAgICAgY3NzQ2xhc3M6ICdzZWNvbmRhcnknLFxuICAgICAgICAgIGhhbmRsZXI6ICgpID0+IHtcbiAgICAgICAgICAgIGNhbmNlbCA9IHRydWU7XG4gICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICAgIHRleHQ6IHRyYW5zbGF0aW9uc1snQ09NTU9OLkJUTl9BQk9SVF9DSEFOR0VTJ10sXG4gICAgICAgICAgY3NzQ2xhc3M6ICdzZWNvbmRhcnknLFxuICAgICAgICAgIGhhbmRsZXI6ICgpID0+IHt9LFxuICAgICAgICB9LFxuICAgICAgICB7XG4gICAgICAgICAgdGV4dDogdHJhbnNsYXRpb25zWydDT01NT04uQlROX1NBVkUnXSxcbiAgICAgICAgICBoYW5kbGVyOiAoKSA9PiB7XG4gICAgICAgICAgICBjb25maXJtID0gdHJ1ZTsgLy8gdXBkYXRlIHVwcGVyIHZhbHVlXG4gICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgIF0sXG4gICAgfSk7XG4gICAgYXdhaXQgYWxlcnQucHJlc2VudCgpO1xuICAgIGF3YWl0IGFsZXJ0Lm9uRGlkRGlzbWlzcygpO1xuXG4gICAgaWYgKGNvbmZpcm0pIHJldHVybiB0cnVlOyAvLyA9IERvIHNhdmUgYW5kIGxlYXZlXG5cbiAgICBpZiAoY2FuY2VsKSB7XG4gICAgICAvLyBTdG9wIHRoZSBldmVudFxuICAgICAgaWYgKGV2ZW50KSBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXG4gICAgICByZXR1cm4gdW5kZWZpbmVkOyAvLyBVc2VyIGNhbmNlbGxlZFxuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTsgLy8gTGVhdmUgd2l0aG91dCBzYXZpbmdcbiAgfVxuXG4gIC8qKlxuICAgKiBBc2sgdGhlIHVzZXIgdG8gY29uZm9ybSBhbiBhY3Rpb24uIElmIHJldHVybiB1bmRlZmluZWQ6IHVzZXIgaGFzIGNhbmNlbGxlZFxuICAgKlxuICAgKiBAcGFyYW0gYWxlcnRDdHJsXG4gICAqIEBwYXJhbSB0cmFuc2xhdGVcbiAgICogQHBhcmFtIGltbWVkaWF0ZSBpcyBhY3Rpb24gaGFzIGFuIGltbWVkaWF0ZSBlZmZlY3QgP1xuICAgKiBAcGFyYW0gZXZlbnRcbiAgICogQHBhcmFtIGludGVycG9sYXRlUGFyYW1zXG4gICAqL1xuICBzdGF0aWMgYXN5bmMgYXNrQWN0aW9uQ29uZmlybWF0aW9uKFxuICAgIGFsZXJ0Q3RybDogQWxlcnRDb250cm9sbGVyLFxuICAgIHRyYW5zbGF0ZTogVHJhbnNsYXRlU2VydmljZSxcbiAgICBpbW1lZGlhdGU/OiBib29sZWFuLFxuICAgIGV2ZW50PzogRXZlbnQsXG4gICAgaW50ZXJwb2xhdGVQYXJhbXM/OiBhbnlcbiAgKTogUHJvbWlzZTxib29sZWFuIHwgdW5kZWZpbmVkPiB7XG4gICAgY29uc3QgbWVzc2FnZUtleSA9IGltbWVkaWF0ZSA9PT0gdHJ1ZSA/ICdDT05GSVJNLkFDVElPTl9JTU1FRElBVEUnIDogJ0NPTkZJUk0uQUNUSU9OJztcbiAgICByZXR1cm4gQWxlcnRzLmFza0NvbmZpcm1hdGlvbihtZXNzYWdlS2V5LCBhbGVydEN0cmwsIHRyYW5zbGF0ZSwgZXZlbnQsIGludGVycG9sYXRlUGFyYW1zKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBc2sgdGhlIHVzZXIgdG8gY29uZmlybS4gSWYgcmV0dXJuIHVuZGVmaW5lZDogdXNlciBoYXMgY2FuY2VsbGVkXG4gICAqXG4gICAqIEBwcmFtIG1lc3NhZ2VLZXkgaTE4biBtZXNzYWdlIGtleVxuICAgKiBAcGFyYW0gbWVzc2FnZUtleVxuICAgKiBAcGFyYW0gYWxlcnRDdHJsXG4gICAqIEBwYXJhbSB0cmFuc2xhdGVcbiAgICogQHBhcmFtIGV2ZW50XG4gICAqIEBwYXJhbSBpbnRlcnBvbGF0ZVBhcmFtc1xuICAgKi9cbiAgc3RhdGljIGFzeW5jIGFza0NvbmZpcm1hdGlvbihcbiAgICBtZXNzYWdlS2V5OiBzdHJpbmcsXG4gICAgYWxlcnRDdHJsOiBBbGVydENvbnRyb2xsZXIsXG4gICAgdHJhbnNsYXRlOiBUcmFuc2xhdGVTZXJ2aWNlLFxuICAgIGV2ZW50PzogRXZlbnQsXG4gICAgaW50ZXJwb2xhdGVQYXJhbXM/OiBhbnlcbiAgKTogUHJvbWlzZTxib29sZWFuIHwgdW5kZWZpbmVkPiB7XG4gICAgaWYgKCFhbGVydEN0cmwgfHwgIXRyYW5zbGF0ZSkgdGhyb3cgbmV3IEVycm9yKFwiTWlzc2luZyByZXF1aXJlZCBhcmd1bWVudCAnYWxlcnRDdHJsJyBvciAndHJhbnNsYXRlJ1wiKTtcbiAgICBsZXQgY29uZmlybSA9IGZhbHNlO1xuICAgIGxldCBjYW5jZWwgPSBmYWxzZTtcbiAgICBjb25zdCB0cmFuc2xhdGlvbnMgPSB0cmFuc2xhdGUuaW5zdGFudChbJ0NPTU1PTi5CVE5fWUVTX0NPTlRJTlVFJywgJ0NPTU1PTi5CVE5fQ0FOQ0VMJywgbWVzc2FnZUtleSwgJ0NPTkZJUk0uQUxFUlRfSEVBREVSJ10sIGludGVycG9sYXRlUGFyYW1zKTtcbiAgICBjb25zdCBhbGVydCA9IGF3YWl0IGFsZXJ0Q3RybC5jcmVhdGUoe1xuICAgICAgaGVhZGVyOiB0cmFuc2xhdGlvbnNbJ0NPTkZJUk0uQUxFUlRfSEVBREVSJ10sXG4gICAgICBtZXNzYWdlOiB0cmFuc2xhdGlvbnNbbWVzc2FnZUtleV0sXG4gICAgICBidXR0b25zOiBbXG4gICAgICAgIHtcbiAgICAgICAgICB0ZXh0OiB0cmFuc2xhdGlvbnNbJ0NPTU1PTi5CVE5fQ0FOQ0VMJ10sXG4gICAgICAgICAgcm9sZTogJ2NhbmNlbCcsXG4gICAgICAgICAgY3NzQ2xhc3M6ICdzZWNvbmRhcnknLFxuICAgICAgICAgIGhhbmRsZXI6ICgpID0+IHtcbiAgICAgICAgICAgIGNhbmNlbCA9IHRydWU7XG4gICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICAgIHRleHQ6IHRyYW5zbGF0aW9uc1snQ09NTU9OLkJUTl9ZRVNfQ09OVElOVUUnXSxcbiAgICAgICAgICBoYW5kbGVyOiAoKSA9PiB7XG4gICAgICAgICAgICBjb25maXJtID0gdHJ1ZTsgLy8gdXBkYXRlIHVwcGVyIHZhbHVlXG4gICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgIF0sXG4gICAgfSk7XG4gICAgYXdhaXQgYWxlcnQucHJlc2VudCgpO1xuICAgIGF3YWl0IGFsZXJ0Lm9uRGlkRGlzbWlzcygpO1xuXG4gICAgaWYgKGNvbmZpcm0pIHJldHVybiB0cnVlOyAvLyA9IERvIHNhdmUgYW5kIGxlYXZlXG5cbiAgICBpZiAoY2FuY2VsKSB7XG4gICAgICAvLyBTdG9wIHRoZSBldmVudFxuICAgICAgaWYgKGV2ZW50KSBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXG4gICAgICByZXR1cm4gdW5kZWZpbmVkOyAvLyBVc2VyIGNhbmNlbGxlZFxuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTsgLy8gTGVhdmUgd2l0aG91dCBzYXZpbmdcbiAgfVxuXG4gIC8qKlxuICAgKiBBc2sgdGhlIHVzZXIgdG8gc2F2ZSBiZWZvcmUgbGVhdmluZy4gSWYgcmV0dXJuIHVuZGVmaW5lZDogdXNlciBoYXMgY2FuY2VsbGVkXG4gICAqXG4gICAqIEBwYXJhbSBhbGVydEN0cmxcbiAgICogQHBhcmFtIHRyYW5zbGF0ZVxuICAgKiBAcGFyYW0gZXZlbnRcbiAgICogQHBhcmFtIGludGVycG9sYXRlUGFyYW1zXG4gICAqL1xuICBzdGF0aWMgYXN5bmMgYXNrRGVsZXRlQ29uZmlybWF0aW9uKFxuICAgIGFsZXJ0Q3RybDogQWxlcnRDb250cm9sbGVyLFxuICAgIHRyYW5zbGF0ZTogVHJhbnNsYXRlU2VydmljZSxcbiAgICBldmVudD86IEV2ZW50LFxuICAgIGludGVycG9sYXRlUGFyYW1zPzogYW55XG4gICk6IFByb21pc2U8Ym9vbGVhbiB8IHVuZGVmaW5lZD4ge1xuICAgIGxldCBjb25maXJtID0gZmFsc2U7XG4gICAgbGV0IGNhbmNlbCA9IGZhbHNlO1xuICAgIGNvbnN0IHRyYW5zbGF0aW9ucyA9IHRyYW5zbGF0ZS5pbnN0YW50KFxuICAgICAgWydDT01NT04uQlROX1lFU19ERUxFVEUnLCAnQ09NTU9OLkJUTl9DQU5DRUwnLCAnQ09ORklSTS5ERUxFVEUnLCAnQ09ORklSTS5BTEVSVF9IRUFERVInXSxcbiAgICAgIGludGVycG9sYXRlUGFyYW1zXG4gICAgKTtcbiAgICBjb25zdCBhbGVydCA9IGF3YWl0IGFsZXJ0Q3RybC5jcmVhdGUoe1xuICAgICAgaGVhZGVyOiB0cmFuc2xhdGlvbnNbJ0NPTkZJUk0uQUxFUlRfSEVBREVSJ10sXG4gICAgICBtZXNzYWdlOiB0cmFuc2xhdGlvbnNbJ0NPTkZJUk0uREVMRVRFJ10sXG4gICAgICBidXR0b25zOiBbXG4gICAgICAgIHtcbiAgICAgICAgICB0ZXh0OiB0cmFuc2xhdGlvbnNbJ0NPTU1PTi5CVE5fQ0FOQ0VMJ10sXG4gICAgICAgICAgcm9sZTogJ2NhbmNlbCcsXG4gICAgICAgICAgY3NzQ2xhc3M6ICdzZWNvbmRhcnknLFxuICAgICAgICAgIGhhbmRsZXI6ICgpID0+IHtcbiAgICAgICAgICAgIGNhbmNlbCA9IHRydWU7XG4gICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICAgIHRleHQ6IHRyYW5zbGF0aW9uc1snQ09NTU9OLkJUTl9ZRVNfREVMRVRFJ10sXG4gICAgICAgICAgaGFuZGxlcjogKCkgPT4ge1xuICAgICAgICAgICAgY29uZmlybSA9IHRydWU7IC8vIHVwZGF0ZSB1cHBlciB2YWx1ZVxuICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICBdLFxuICAgIH0pO1xuICAgIGF3YWl0IGFsZXJ0LnByZXNlbnQoKTtcbiAgICBhd2FpdCBhbGVydC5vbkRpZERpc21pc3MoKTtcblxuICAgIGlmIChjb25maXJtKSByZXR1cm4gdHJ1ZTsgLy8gPSBEbyBzYXZlIGFuZCBsZWF2ZVxuXG4gICAgaWYgKGNhbmNlbCkge1xuICAgICAgLy8gU3RvcCB0aGUgZXZlbnRcbiAgICAgIGlmIChldmVudCkgZXZlbnQucHJldmVudERlZmF1bHQoKTtcblxuICAgICAgcmV0dXJuIHVuZGVmaW5lZDsgLy8gVXNlciBjYW5jZWxsZWRcbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7IC8vIExlYXZlIHdpdGhvdXQgc2F2aW5nXG4gIH1cblxuICBzdGF0aWMgYXN5bmMgYXNrU2F2ZUJlZm9yZUFjdGlvbihcbiAgICBhbGVydEN0cmw6IEFsZXJ0Q29udHJvbGxlcixcbiAgICB0cmFuc2xhdGU6IFRyYW5zbGF0ZVNlcnZpY2UsXG4gICAgZXZlbnQ/OiB7IHZhbGlkOiBib29sZWFuIH0sXG4gICAgaW50ZXJwb2xhdGVQYXJhbXM/OiBhbnlcbiAgKTogUHJvbWlzZTx7IGNvbmZpcm1lZDogYm9vbGVhbjsgc2F2ZTogYm9vbGVhbiB9IHwgdW5kZWZpbmVkPiB7XG4gICAgbGV0IHNhdmUgPSBmYWxzZTtcbiAgICBsZXQgY29uZmlybSA9IGZhbHNlO1xuICAgIGxldCBhbGVydDogSFRNTElvbkFsZXJ0RWxlbWVudDtcblxuICAgIC8vIEFzayB1c2VyIGJlZm9yZSBzYXZlXG4gICAgaWYgKGV2ZW50ICYmIGV2ZW50LnZhbGlkKSB7XG4gICAgICBjb25zdCB0cmFuc2xhdGlvbnMgPSB0cmFuc2xhdGUuaW5zdGFudChcbiAgICAgICAgWydDT01NT04uQlROX0NBTkNFTCcsICdDT01NT04uQlROX1NBVkUnLCAnQ09NTU9OLkJUTl9BQk9SVF9DSEFOR0VTJywgJ0NPTkZJUk0uU0FWRV9CRUZPUkVfQ09OVElOVUUnLCAnQ09ORklSTS5BTEVSVF9IRUFERVInXSxcbiAgICAgICAgaW50ZXJwb2xhdGVQYXJhbXNcbiAgICAgICk7XG4gICAgICBhbGVydCA9IGF3YWl0IGFsZXJ0Q3RybC5jcmVhdGUoe1xuICAgICAgICBoZWFkZXI6IHRyYW5zbGF0aW9uc1snQ09ORklSTS5BTEVSVF9IRUFERVInXSxcbiAgICAgICAgbWVzc2FnZTogdHJhbnNsYXRpb25zWydDT05GSVJNLlNBVkVfQkVGT1JFX0NPTlRJTlVFJ10sXG4gICAgICAgIGJ1dHRvbnM6IFtcbiAgICAgICAgICB7XG4gICAgICAgICAgICB0ZXh0OiB0cmFuc2xhdGlvbnNbJ0NPTU1PTi5CVE5fQ0FOQ0VMJ10sXG4gICAgICAgICAgICByb2xlOiAnY2FuY2VsJyxcbiAgICAgICAgICAgIGNzc0NsYXNzOiAnc2Vjb25kYXJ5JyxcbiAgICAgICAgICAgIGhhbmRsZXI6ICgpID0+IHt9LFxuICAgICAgICAgIH0sXG4gICAgICAgICAge1xuICAgICAgICAgICAgdGV4dDogdHJhbnNsYXRpb25zWydDT01NT04uQlROX0FCT1JUX0NIQU5HRVMnXSxcbiAgICAgICAgICAgIGNzc0NsYXNzOiAnc2Vjb25kYXJ5JyxcbiAgICAgICAgICAgIGhhbmRsZXI6ICgpID0+IHtcbiAgICAgICAgICAgICAgY29uZmlybSA9IHRydWU7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH0sXG4gICAgICAgICAge1xuICAgICAgICAgICAgdGV4dDogdHJhbnNsYXRpb25zWydDT01NT04uQlROX1NBVkUnXSxcbiAgICAgICAgICAgIGhhbmRsZXI6ICgpID0+IHtcbiAgICAgICAgICAgICAgc2F2ZSA9IHRydWU7XG4gICAgICAgICAgICAgIGNvbmZpcm0gPSB0cnVlO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICB9LFxuICAgICAgICBdLFxuICAgICAgfSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnN0IHRyYW5zbGF0aW9ucyA9IHRyYW5zbGF0ZS5pbnN0YW50KFxuICAgICAgICBbJ0NPTU1PTi5CVE5fQUJPUlRfQ0hBTkdFUycsICdDT01NT04uQlROX0NBTkNFTCcsICdDT05GSVJNLkNBTkNFTF9DSEFOR0VTJywgJ0NPTkZJUk0uQUxFUlRfSEVBREVSJ10sXG4gICAgICAgIGludGVycG9sYXRlUGFyYW1zXG4gICAgICApO1xuXG4gICAgICBhbGVydCA9IGF3YWl0IGFsZXJ0Q3RybC5jcmVhdGUoe1xuICAgICAgICBoZWFkZXI6IHRyYW5zbGF0aW9uc1snQ09ORklSTS5BTEVSVF9IRUFERVInXSxcbiAgICAgICAgbWVzc2FnZTogdHJhbnNsYXRpb25zWydDT05GSVJNLkNBTkNFTF9DSEFOR0VTJ10sXG4gICAgICAgIGJ1dHRvbnM6IFtcbiAgICAgICAgICB7XG4gICAgICAgICAgICB0ZXh0OiB0cmFuc2xhdGlvbnNbJ0NPTU1PTi5CVE5fQUJPUlRfQ0hBTkdFUyddLFxuICAgICAgICAgICAgY3NzQ2xhc3M6ICdzZWNvbmRhcnknLFxuICAgICAgICAgICAgaGFuZGxlcjogKCkgPT4ge1xuICAgICAgICAgICAgICBjb25maXJtID0gdHJ1ZTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgfSxcbiAgICAgICAgICB7XG4gICAgICAgICAgICB0ZXh0OiB0cmFuc2xhdGlvbnNbJ0NPTU1PTi5CVE5fQ0FOQ0VMJ10sXG4gICAgICAgICAgICByb2xlOiAnY2FuY2VsJyxcbiAgICAgICAgICAgIGhhbmRsZXI6ICgpID0+IHt9LFxuICAgICAgICAgIH0sXG4gICAgICAgIF0sXG4gICAgICB9KTtcbiAgICB9XG5cbiAgICBhd2FpdCBhbGVydC5wcmVzZW50KCk7XG4gICAgYXdhaXQgYWxlcnQub25EaWREaXNtaXNzKCk7XG5cbiAgICByZXR1cm4geyBjb25maXJtZWQ6IGNvbmZpcm0sIHNhdmUgfTtcbiAgfVxuXG4gIHN0YXRpYyBhc3luYyBzaG93RXJyb3IoXG4gICAgbWVzc2FnZUtleTogc3RyaW5nLFxuICAgIGFsZXJ0Q3RybDogQWxlcnRDb250cm9sbGVyLFxuICAgIHRyYW5zbGF0ZTogVHJhbnNsYXRlU2VydmljZSxcbiAgICBvcHRzPzoge1xuICAgICAgdGl0bGVLZXk/OiBzdHJpbmc7XG4gICAgfSxcbiAgICBpbnRlcnBvbGF0ZVBhcmFtcz86IGFueVxuICApIHtcbiAgICBpZiAoIW1lc3NhZ2VLZXkgfHwgIWFsZXJ0Q3RybCB8fCAhdHJhbnNsYXRlKSB0aHJvdyBuZXcgRXJyb3IoXCJNaXNzaW5nIGEgcmVxdWlyZWQgYXJndW1lbnQgKCdtZXNzYWdlS2V5JywgJ2FsZXJ0Q3RybCcgb3IgJ3RyYW5zbGF0ZScpXCIpO1xuICAgIGNvbnN0IHRpdGxlS2V5ID0gKG9wdHMgJiYgb3B0cy50aXRsZUtleSkgfHwgJ0VSUk9SLkFMRVJUX0hFQURFUic7XG4gICAgY29uc3QgdHJhbnNsYXRpb25zID0gdHJhbnNsYXRlLmluc3RhbnQoWydDT01NT04uQlROX09LJywgbWVzc2FnZUtleSwgdGl0bGVLZXldLCBpbnRlcnBvbGF0ZVBhcmFtcyk7XG4gICAgY29uc3QgYWxlcnQgPSBhd2FpdCBhbGVydEN0cmwuY3JlYXRlKHtcbiAgICAgIGhlYWRlcjogdHJhbnNsYXRpb25zW3RpdGxlS2V5XSxcbiAgICAgIG1lc3NhZ2U6IHRyYW5zbGF0aW9uc1ttZXNzYWdlS2V5XSxcbiAgICAgIGJ1dHRvbnM6IFtcbiAgICAgICAge1xuICAgICAgICAgIHRleHQ6IHRyYW5zbGF0aW9uc1snQ09NTU9OLkJUTl9PSyddLFxuICAgICAgICAgIHJvbGU6ICdjYW5jZWwnLFxuICAgICAgICB9LFxuICAgICAgXSxcbiAgICB9KTtcbiAgICBhd2FpdCBhbGVydC5wcmVzZW50KCk7XG4gICAgYXdhaXQgYWxlcnQub25EaWREaXNtaXNzKCk7XG4gIH1cbn1cbiJdfQ==
243
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWxlcnRzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vc3JjL2FwcC9zaGFyZWQvYWxlcnRzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUdBLE1BQU0sT0FBTyxNQUFNO0lBQ2pCOzs7Ozs7OztPQVFHO0lBQ0gsTUFBTSxDQUFDLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxTQUEwQixFQUFFLFNBQTJCLEVBQUUsS0FBYTtRQUNwRyxJQUFJLE9BQU8sR0FBRyxLQUFLLENBQUM7UUFDcEIsSUFBSSxNQUFNLEdBQUcsS0FBSyxDQUFDO1FBQ25CLE1BQU0sWUFBWSxHQUFHLFNBQVMsQ0FBQyxPQUFPLENBQUM7WUFDckMsaUJBQWlCO1lBQ2pCLG1CQUFtQjtZQUNuQiwwQkFBMEI7WUFDMUIsY0FBYztZQUNkLHNCQUFzQjtTQUN2QixDQUFDLENBQUM7UUFDSCxNQUFNLEtBQUssR0FBRyxNQUFNLFNBQVMsQ0FBQyxNQUFNLENBQUM7WUFDbkMsTUFBTSxFQUFFLFlBQVksQ0FBQyxzQkFBc0IsQ0FBQztZQUM1QyxPQUFPLEVBQUUsWUFBWSxDQUFDLGNBQWMsQ0FBQztZQUNyQyxPQUFPLEVBQUU7Z0JBQ1A7b0JBQ0UsSUFBSSxFQUFFLFlBQVksQ0FBQyxtQkFBbUIsQ0FBQztvQkFDdkMsSUFBSSxFQUFFLFFBQVE7b0JBQ2QsUUFBUSxFQUFFLFdBQVc7b0JBQ3JCLE9BQU8sRUFBRSxHQUFHLEVBQUU7d0JBQ1osTUFBTSxHQUFHLElBQUksQ0FBQztvQkFDaEIsQ0FBQztpQkFDRjtnQkFDRDtvQkFDRSxJQUFJLEVBQUUsWUFBWSxDQUFDLDBCQUEwQixDQUFDO29CQUM5QyxRQUFRLEVBQUUsV0FBVztvQkFDckIsT0FBTyxFQUFFLEdBQUcsRUFBRSxHQUFFLENBQUM7aUJBQ2xCO2dCQUNEO29CQUNFLElBQUksRUFBRSxZQUFZLENBQUMsaUJBQWlCLENBQUM7b0JBQ3JDLE9BQU8sRUFBRSxHQUFHLEVBQUU7d0JBQ1osT0FBTyxHQUFHLElB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U0FBMkIsRUFDM0IsSUFFQyxFQUNELGlCQUF1QjtRQUV2QixJQUFJLENBQUMsVUFBVSxJQUFJLENBQUMsU0FBUyxJQUFJLENBQUMsU0FBUztZQUFFLE1BQU0sSUFBSSxLQUFLLENBQUMsd0VBQXdFLENBQUMsQ0FBQztRQUN2SSxNQUFNLFFBQVEsR0FBRyxDQUFDLElBQUksSUFBSSxJQUFJLENBQUMsUUFBUSxDQUFDLElBQUksb0JBQW9CLENBQUM7UUFDakUsTUFBTSxZQUFZLEdBQUcsU0FBUyxDQUFDLE9BQU8sQ0FBQyxDQUFDLGVBQWUsRUFBRSxVQUFVLEVBQUUsUUFBUSxDQUFDLEVBQUUsaUJBQWlCLENBQUMsQ0FBQztRQUNuRyxNQUFNLEtBQUssR0FBRyxNQUFNLFNBQVMsQ0FBQyxNQUFNLENBQUM7WUFDbkMsTUFBTSxFQUFFLFlBQVksQ0FBQyxRQUFRLENBQUM7WUFDOUIsT0FBTyxFQUFFLFlBQVksQ0FBQyxVQUFVLENBQUM7WUFDakMsT0FBTyxFQUFFO2dCQUNQO29CQUNFLElBQUksRUFBRSxZQUFZLENBQUMsZUFBZSxDQUFDO29CQUNuQyxJQUFJLEVBQUUsUUFBUTtpQkFDZjthQUNGO1NBQ0YsQ0FBQyxDQUFDO1FBQ0gsTUFBTSxLQUFLLENBQUMsT0FBTyxFQUFFLENBQUM7UUFDdEIsTUFBTSxLQUFLLENBQUMsWUFBWSxFQUFFLENBQUM7SUFDN0IsQ0FBQztDQUNGIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQWxlcnRDb250cm9sbGVyIH0gZnJvbSAnQGlvbmljL2FuZ3VsYXInO1xuaW1wb3J0IHsgVHJhbnNsYXRlU2VydmljZSB9IGZyb20gJ0BuZ3gtdHJhbnNsYXRlL2NvcmUnO1xuXG5leHBvcnQgY2xhc3MgQWxlcnRzIHtcbiAgLyoqXG4gICAqIEFzayB0aGUgdXNlciB0byBzYXZlIGJlZm9yZSBsZWF2aW5nLiBJZiByZXR1cm4gdW5kZWZpbmVkOiB1c2VyIGhhcyBjYW5jZWxsZWRcbiAgICogPHA+XG4gICAqICAgZnJvbSBhIHJvdXRlZCBwYWdlLCBwcmVmZXIgdXNpbmcgQ29tcG9uZW50RGlydHlHdWFyZFxuICAgKlxuICAgKiBAcGFyYW0gYWxlcnRDdHJsXG4gICAqIEBwYXJhbSB0cmFuc2xhdGVcbiAgICogQHBhcmFtIGV2ZW50XG4gICAqL1xuICBzdGF0aWMgYXN5bmMgYXNrU2F2ZUJlZm9yZUxlYXZlKGFsZXJ0Q3RybDogQWxlcnRDb250cm9sbGVyLCB0cmFuc2xhdGU6IFRyYW5zbGF0ZVNlcnZpY2UsIGV2ZW50PzogRXZlbnQpOiBQcm9taXNlPGJvb2xlYW4gfCB1bmRlZmluZWQ+IHtcbiAgICBsZXQgY29uZmlybSA9IGZhbHNlO1xuICAgIGxldCBjYW5jZWwgPSBmYWxzZTtcbiAgICBjb25zdCB0cmFuc2xhdGlvbnMgPSB0cmFuc2xhdGUuaW5zdGFudChbXG4gICAgICAnQ09NTU9OLkJUTl9TQVZFJyxcbiAgICAgICdDT01NT04uQlROX0NBTkNFTCcsXG4gICAgICAnQ09NTU9OLkJUTl9BQk9SVF9DSEFOR0VTJyxcbiAgICAgICdDT05GSVJNLlNBVkUnLFxuICAgICAgJ0NPTkZJUk0uQUxFUlRfSEVBREVSJyxcbiAgICBdKTtcbiAgICBjb25zdCBhbGVydCA9IGF3YWl0IGFsZXJ0Q3RybC5jcmVhdGUoe1xuICAgICAgaGVhZGVyOiB0cmFuc2xhdGlvbnNbJ0NPTkZJUk0uQUxFUlRfSEVBREVSJ10sXG4gICAgICBtZXNzYWdlOiB0cmFuc2xhdGlvbnNbJ0NPTkZJUk0uU0FWRSddLFxuICAgICAgYnV0dG9uczogW1xuICAgICAgICB7XG4gICAgICAgICAgdGV4dDogdHJhbnNsYXRpb25zWydDT01NT04uQlROX0NBTkNFTCddLFxuICAgICAgICAgIHJvbGU6ICdjYW5jZWwnLFxuICAgICAgICAgIGNzc0NsYXNzOiAnc2Vjb25kYXJ5JyxcbiAgICAgICAgICBoYW5kbGVyOiAoKSA9PiB7XG4gICAgICAgICAgICBjYW5jZWwgPSB0cnVlO1xuICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICAgIHtcbiAgICAgICAgICB0ZXh0OiB0cmFuc2xhdGlvbnNbJ0NPTU1PTi5CVE5fQUJPUlRfQ0hBTkdFUyddLFxuICAgICAgICAgIGNzc0NsYXNzOiAnc2Vjb25kYXJ5JyxcbiAgICAgICAgICBoYW5kbGVyOiAoKSA9PiB7fSxcbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICAgIHRleHQ6IHRyYW5zbGF0aW9uc1snQ09NTU9OLkJUTl9TQVZFJ10sXG4gICAgICAgICAgaGFuZGxlcjogKCkgPT4ge1xuICAgICAgICAgICAgY29uZmlybSA9IHRydWU7IC8vIHVwZGF0ZSB1cHBlciB2YWx1ZVxuICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICBdLFxuICAgIH0pO1xuICAgIGF3YWl0IGFsZXJ0LnByZXNlbnQoKTtcbiAgICBhd2FpdCBhbGVydC5vbkRpZERpc21pc3MoKTtcblxuICAgIGlmIChjb25maXJtKSByZXR1cm4gdHJ1ZTsgLy8gPSBEbyBzYXZlIGFuZCBsZWF2ZVxuXG4gICAgaWYgKGNhbmNlbCkge1xuICAgICAgLy8gU3RvcCB0aGUgZXZlbnRcbiAgICAgIGlmIChldmVudCkgZXZlbnQucHJldmVudERlZmF1bHQoKTtcblxuICAgICAgcmV0dXJuIHVuZGVmaW5lZDsgLy8gVXNlciBjYW5jZWxsZWRcbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7IC8vIExlYXZlIHdpdGhvdXQgc2F2aW5nXG4gIH1cblxuICAvKipcbiAgICogQXNrIHRoZSB1c2VyIHRvIGNvbmZvcm0gYW4gYWN0aW9uLiBJZiByZXR1cm4gdW5kZWZpbmVkOiB1c2VyIGhhcyBjYW5jZWxsZWRcbiAgICpcbiAgICogQHBhcmFtIGFsZXJ0Q3RybFxuICAgKiBAcGFyYW0gdHJhbnNsYXRlXG4gICAqIEBwYXJhbSBpbW1lZGlhdGUgaXMgYWN0aW9uIGhhcyBhbiBpbW1lZGlhdGUgZWZmZWN0ID9cbiAgICogQHBhcmFtIGV2ZW50XG4gICAqIEBwYXJhbSBpbnRlcnBvbGF0ZVBhcmFtc1xuICAgKi9cbiAgc3RhdGljIGFzeW5jIGFza0FjdGlvbkNvbmZpcm1hdGlvbihcbiAgICBhbGVydEN0cmw6IEFsZXJ0Q29udHJvbGxlcixcbiAgICB0cmFuc2xhdGU6IFRyYW5zbGF0ZVNlcnZpY2UsXG4gICAgaW1tZWRpYXRlPzogYm9vbGVhbixcbiAgICBldmVudD86IEV2ZW50LFxuICAgIGludGVycG9sYXRlUGFyYW1zPzogYW55XG4gICk6IFByb21pc2U8Ym9vbGVhbiB8IHVuZGVmaW5lZD4ge1xuICAgIGNvbnN0IG1lc3NhZ2VLZXkgPSBpbW1lZGlhdGUgPT09IHRydWUgPyAnQ09ORklSTS5BQ1RJT05fSU1NRURJQVRFJyA6ICdDT05GSVJNLkFDVElPTic7XG4gICAgcmV0dXJuIEFsZXJ0cy5hc2tDb25maXJtYXRpb24obWVzc2FnZUtleSwgYWxlcnRDdHJsLCB0cmFuc2xhdGUsIGV2ZW50LCBpbnRlcnBvbGF0ZVBhcmFtcyk7XG4gIH1cblxuICAvKipcbiAgICogQXNrIHRoZSB1c2VyIHRvIGNvbmZpcm0uIElmIHJldHVybiB1bmRlZmluZWQ6IHVzZXIgaGFzIGNhbmNlbGxlZFxuICAgKlxuICAgKiBAcHJhbSBtZXNzYWdlS2V5IGkxOG4gbWVzc2FnZSBrZXlcbiAgICogQHBhcmFtIG1lc3NhZ2VLZXlcbiAgICogQHBhcmFtIGFsZXJ0Q3RybFxuICAgKiBAcGFyYW0gdHJhbnNsYXRlXG4gICAqIEBwYXJhbSBldmVudFxuICAgKiBAcGFyYW0gaW50ZXJwb2xhdGVQYXJhbXNcbiAgICovXG4gIHN0YXRpYyBhc3luYyBhc2tDb25maXJtYXRpb24oXG4gICAgbWVzc2FnZUtleTogc3RyaW5nLFxuICAgIGFsZXJ0Q3RybDogQWxlcnRDb250cm9sbGVyLFxuICAgIHRyYW5zbGF0ZTogVHJhbnNsYXRlU2VydmljZSxcbiAgICBldmVudD86IEV2ZW50LFxuICAgIGludGVycG9sYXRlUGFyYW1zPzogYW55XG4gICk6IFByb21pc2U8Ym9vbGVhbiB8IHVuZGVmaW5lZD4ge1xuICAgIGlmICghYWxlcnRDdHJsIHx8ICF0cmFuc2xhdGUpIHRocm93IG5ldyBFcnJvcihcIk1pc3NpbmcgcmVxdWlyZWQgYXJndW1lbnQgJ2FsZXJ0Q3RybCcgb3IgJ3RyYW5zbGF0ZSdcIik7XG4gICAgbGV0IGNvbmZpcm0gPSBmYWxzZTtcbiAgICBsZXQgY2FuY2VsID0gZmFsc2U7XG4gICAgY29uc3QgdHJhbnNsYXRpb25zID0gdHJhbnNsYXRlLmluc3RhbnQoWydDT01NT04uQlROX1lFU19DT05USU5VRScsICdDT01NT04uQlROX0NBTkNFTCcsIG1lc3NhZ2VLZXksICdDT05GSVJNLkFMRVJUX0hFQURFUiddLCBpbnRlcnBvbGF0ZVBhcmFtcyk7XG4gICAgY29uc3QgYWxlcnQgPSBhd2FpdCBhbGVydEN0cmwuY3JlYXRlKHtcbiAgICAgIGhlYWRlcjogdHJhbnNsYXRpb25zWydDT05GSVJNLkFMRVJUX0hFQURFUiddLFxuICAgICAgbWVzc2FnZTogdHJhbnNsYXRpb25zW21lc3NhZ2VLZXldLFxuICAgICAgYnV0dG9uczogW1xuICAgICAgICB7XG4gICAgICAgICAgdGV4dDogdHJhbnNsYXRpb25zWydDT01NT04uQlROX0NBTkNFTCddLFxuICAgICAgICAgIHJvbGU6ICdjYW5jZWwnLFxuICAgICAgICAgIGNzc0NsYXNzOiAnc2Vjb25kYXJ5JyxcbiAgICAgICAgICBoYW5kbGVyOiAoKSA9PiB7XG4gICAgICAgICAgICBjYW5jZWwgPSB0cnVlO1xuICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICAgIHtcbiAgICAgICAgICB0ZXh0OiB0cmFuc2xhdGlvbnNbJ0NPTU1PTi5CVE5fWUVTX0NPTlRJTlVFJ10sXG4gICAgICAgICAgaGFuZGxlcjogKCkgPT4ge1xuICAgICAgICAgICAgY29uZmlybSA9IHRydWU7IC8vIHVwZGF0ZSB1cHBlciB2YWx1ZVxuICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICBdLFxuICAgIH0pO1xuICAgIGF3YWl0IGFsZXJ0LnByZXNlbnQoKTtcbiAgICBhd2FpdCBhbGVydC5vbkRpZERpc21pc3MoKTtcblxuICAgIGlmIChjb25maXJtKSByZXR1cm4gdHJ1ZTsgLy8gPSBEbyBzYXZlIGFuZCBsZWF2ZVxuXG4gICAgaWYgKGNhbmNlbCkge1xuICAgICAgLy8gU3RvcCB0aGUgZXZlbnRcbiAgICAgIGlmIChldmVudCkgZXZlbnQucHJldmVudERlZmF1bHQoKTtcblxuICAgICAgcmV0dXJuIHVuZGVmaW5lZDsgLy8gVXNlciBjYW5jZWxsZWRcbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7IC8vIExlYXZlIHdpdGhvdXQgc2F2aW5nXG4gIH1cblxuICAvKipcbiAgICogQXNrIHRoZSB1c2VyIHRvIHNhdmUgYmVmb3JlIGxlYXZpbmcuIElmIHJldHVybiB1bmRlZmluZWQ6IHVzZXIgaGFzIGNhbmNlbGxlZFxuICAgKlxuICAgKiBAcGFyYW0gYWxlcnRDdHJsXG4gICAqIEBwYXJhbSB0cmFuc2xhdGVcbiAgICogQHBhcmFtIGV2ZW50XG4gICAqIEBwYXJhbSBpbnRlcnBvbGF0ZVBhcmFtc1xuICAgKi9cbiAgc3RhdGljIGFzeW5jIGFza0RlbGV0ZUNvbmZpcm1hdGlvbihcbiAgICBhbGVydEN0cmw6IEFsZXJ0Q29udHJvbGxlcixcbiAgICB0cmFuc2xhdGU6IFRyYW5zbGF0ZVNlcnZpY2UsXG4gICAgZXZlbnQ/OiBFdmVudCxcbiAgICBpbnRlcnBvbGF0ZVBhcmFtcz86IGFueVxuICApOiBQcm9taXNlPGJvb2xlYW4gfCB1bmRlZmluZWQ+IHtcbiAgICBsZXQgY29uZmlybSA9IGZhbHNlO1xuICAgIGxldCBjYW5jZWwgPSBmYWxzZTtcbiAgICBjb25zdCB0cmFuc2xhdGlvbnMgPSB0cmFuc2xhdGUuaW5zdGFudChcbiAgICAgIFsnQ09NTU9OLkJUTl9ZRVNfREVMRVRFJywgJ0NPTU1PTi5CVE5fQ0FOQ0VMJywgJ0NPTkZJUk0uREVMRVRFJywgJ0NPTkZJUk0uQUxFUlRfSEVBREVSJ10sXG4gICAgICBpbnRlcnBvbGF0ZVBhcmFtc1xuICAgICk7XG4gICAgY29uc3QgYWxlcnQgPSBhd2FpdCBhbGVydEN0cmwuY3JlYXRlKHtcbiAgICAgIGhlYWRlcjogdHJhbnNsYXRpb25zWydDT05GSVJNLkFMRVJUX0hFQURFUiddLFxuICAgICAgbWVzc2FnZTogdHJhbnNsYXRpb25zWydDT05GSVJNLkRFTEVURSddLFxuICAgICAgYnV0dG9uczogW1xuICAgICAgICB7XG4gICAgICAgICAgdGV4dDogdHJhbnNsYXRpb25zWydDT01NT04uQlROX0NBTkNFTCddLFxuICAgICAgICAgIHJvbGU6ICdjYW5jZWwnLFxuICAgICAgICAgIGNzc0NsYXNzOiAnc2Vjb25kYXJ5JyxcbiAgICAgICAgICBoYW5kbGVyOiAoKSA9PiB7XG4gICAgICAgICAgICBjYW5jZWwgPSB0cnVlO1xuICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICAgIHtcbiAgICAgICAgICB0ZXh0OiB0cmFuc2xhdGlvbnNbJ0NPTU1PTi5CVE5fWUVTX0RFTEVURSddLFxuICAgICAgICAgIGhhbmRsZXI6ICgpID0+IHtcbiAgICAgICAgICAgIGNvbmZpcm0gPSB0cnVlOyAvLyB1cGRhdGUgdXBwZXIgdmFsdWVcbiAgICAgICAgICB9LFxuICAgICAgICB9LFxuICAgICAgXSxcbiAgICB9KTtcbiAgICBhd2FpdCBhbGVydC5wcmVzZW50KCk7XG4gICAgYXdhaXQgYWxlcnQub25EaWREaXNtaXNzKCk7XG5cbiAgICBpZiAoY29uZmlybSkgcmV0dXJuIHRydWU7IC8vID0gRG8gc2F2ZSBhbmQgbGVhdmVcblxuICAgIGlmIChjYW5jZWwpIHtcbiAgICAgIC8vIFN0b3AgdGhlIGV2ZW50XG4gICAgICBpZiAoZXZlbnQpIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cbiAgICAgIHJldHVybiB1bmRlZmluZWQ7IC8vIFVzZXIgY2FuY2VsbGVkXG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlOyAvLyBMZWF2ZSB3aXRob3V0IHNhdmluZ1xuICB9XG5cbiAgc3RhdGljIGFzeW5jIGFza1NhdmVCZWZvcmVBY3Rpb24oXG4gICAgYWxlcnRDdHJsOiBBbGVydENvbnRyb2xsZXIsXG4gICAgdHJhbnNsYXRlOiBUcmFuc2xhdGVTZXJ2aWNlLFxuICAgIG9wdHM/OiB7IHZhbGlkPzogYm9vbGVhbjsgdmFsaWRNZXNzYWdlSTE4bj86IHN0cmluZzsgaW52YWxpZE1lc3NhZ2VJMThuPzogc3RyaW5nIH0sXG4gICAgaW50ZXJwb2xhdGVQYXJhbXM/OiBhbnlcbiAgKTogUHJvbWlzZTx7IGNvbmZpcm1lZDogYm9vbGVhbjsgc2F2ZTogYm9vbGVhbiB9IHwgdW5kZWZpbmVkPiB7XG4gICAgbGV0IHNhdmUgPSBmYWxzZTtcbiAgICBsZXQgY29uZmlybWVkID0gZmFsc2U7XG4gICAgbGV0IGFsZXJ0OiBIVE1MSW9uQWxlcnRFbGVtZW50O1xuICAgIGNvbnN0IHZhbGlkTWVzc2FnZUkxOG4gPSBvcHRzPy52YWxpZE1lc3NhZ2VJMThuIHx8ICdDT05GSVJNLlNBVkVfQkVGT1JFX0NPTlRJTlVFJztcbiAgICBjb25zdCBpbnZhbGlkTWVzc2FnZUkxOG4gPSBvcHRzPy5pbnZhbGlkTWVzc2FnZUkxOG4gfHwgJ0NPTkZJUk0uQ0FOQ0VMX0NIQU5HRVMnO1xuXG4gICAgLy8gQXNrIHVzZXIgYmVmb3JlIHNhdmVcbiAgICBpZiAob3B0cz8udmFsaWQpIHtcbiAgICAgIGNvbnN0IHRyYW5zbGF0aW9ucyA9IHRyYW5zbGF0ZS5pbnN0YW50KFxuICAgICAgICBbJ0NPTU1PTi5CVE5fQ0FOQ0VMJywgJ0NPTU1PTi5CVE5fU0FWRScsICdDT01NT04uQlROX0FCT1JUX0NIQU5HRVMnLCAnQ09ORklSTS5BTEVSVF9IRUFERVInLCB2YWxpZE1lc3NhZ2VJMThuXSxcbiAgICAgICAgaW50ZXJwb2xhdGVQYXJhbXNcbiAgICAgICk7XG4gICAgICBhbGVydCA9IGF3YWl0IGFsZXJ0Q3RybC5jcmVhdGUoe1xuICAgICAgICBoZWFkZXI6IHRyYW5zbGF0aW9uc1snQ09ORklSTS5BTEVSVF9IRUFERVInXSxcbiAgICAgICAgbWVzc2FnZTogdHJhbnNsYXRpb25zW3ZhbGlkTWVzc2FnZUkxOG5dLFxuICAgICAgICBidXR0b25zOiBbXG4gICAgICAgICAge1xuICAgICAgICAgICAgdGV4dDogdHJhbnNsYXRpb25zWydDT01NT04uQlROX0NBTkNFTCddLFxuICAgICAgICAgICAgcm9sZTogJ2NhbmNlbCcsXG4gICAgICAgICAgICBjc3NDbGFzczogJ3NlY29uZGFyeScsXG4gICAgICAgICAgICBoYW5kbGVyOiAoKSA9PiB7fSxcbiAgICAgICAgICB9LFxuICAgICAgICAgIHtcbiAgICAgICAgICAgIHRleHQ6IHRyYW5zbGF0aW9uc1snQ09NTU9OLkJUTl9BQk9SVF9DSEFOR0VTJ10sXG4gICAgICAgICAgICBjc3NDbGFzczogJ3NlY29uZGFyeScsXG4gICAgICAgICAgICBoYW5kbGVyOiAoKSA9PiB7XG4gICAgICAgICAgICAgIGNvbmZpcm1lZCA9IHRydWU7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH0sXG4gICAgICAgICAge1xuICAgICAgICAgICAgdGV4dDogdHJhbnNsYXRpb25zWydDT01NT04uQlROX1NBVkUnXSxcbiAgICAgICAgICAgIGhhbmRsZXI6ICgpID0+IHtcbiAgICAgICAgICAgICAgc2F2ZSA9IHRydWU7XG4gICAgICAgICAgICAgIGNvbmZpcm1lZCA9IHRydWU7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH0sXG4gICAgICAgIF0sXG4gICAgICB9KTtcbiAgICB9IGVsc2Uge1xuICAgICAgY29uc3QgdHJhbnNsYXRpb25zID0gdHJhbnNsYXRlLmluc3RhbnQoXG4gICAgICAgIFsnQ09NTU9OLkJUTl9BQk9SVF9DSEFOR0VTJywgJ0NPTU1PTi5CVE5fQ0FOQ0VMJywgJ0NPTkZJUk0uQUxFUlRfSEVBREVSJywgaW52YWxpZE1lc3NhZ2VJMThuXSxcbiAgICAgICAgaW50ZXJwb2xhdGVQYXJhbXNcbiAgICAgICk7XG5cbiAgICAgIGFsZXJ0ID0gYXdhaXQgYWxlcnRDdHJsLmNyZWF0ZSh7XG4gICAgICAgIGhlYWRlcjogdHJhbnNsYXRpb25zWydDT05GSVJNLkFMRVJUX0hFQURFUiddLFxuICAgICAgICBtZXNzYWdlOiB0cmFuc2xhdGlvbnNbaW52YWxpZE1lc3NhZ2VJMThuXSxcbiAgICAgICAgYnV0dG9uczogW1xuICAgICAgICAgIHtcbiAgICAgICAgICAgIHRleHQ6IHRyYW5zbGF0aW9uc1snQ09NTU9OLkJUTl9BQk9SVF9DSEFOR0VTJ10sXG4gICAgICAgICAgICBjc3NDbGFzczogJ3NlY29uZGFyeScsXG4gICAgICAgICAgICBoYW5kbGVyOiAoKSA9PiB7XG4gICAgICAgICAgICAgIGNvbmZpcm1lZCA9IHRydWU7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH0sXG4gICAgICAgICAge1xuICAgICAgICAgICAgdGV4dDogdHJhbnNsYXRpb25zWydDT01NT04uQlROX0NBTkNFTCddLFxuICAgICAgICAgICAgcm9sZTogJ2NhbmNlbCcsXG4gICAgICAgICAgICBoYW5kbGVyOiAoKSA9PiB7fSxcbiAgICAgICAgICB9LFxuICAgICAgICBdLFxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgYXdhaXQgYWxlcnQucHJlc2VudCgpO1xuICAgIGF3YWl0IGFsZXJ0Lm9uRGlkRGlzbWlzcygpO1xuXG4gICAgcmV0dXJuIHsgY29uZmlybWVkLCBzYXZlIH07XG4gIH1cblxuICBzdGF0aWMgYXN5bmMgc2hvd0Vycm9yKFxuICAgIG1lc3NhZ2VLZXk6IHN0cmluZyxcbiAgICBhbGVydEN0cmw6IEFsZXJ0Q29udHJvbGxlcixcbiAgICB0cmFuc2xhdGU6IFRyYW5zbGF0ZVNlcnZpY2UsXG4gICAgb3B0cz86IHtcbiAgICAgIHRpdGxlS2V5Pzogc3RyaW5nO1xuICAgIH0sXG4gICAgaW50ZXJwb2xhdGVQYXJhbXM/OiBhbnlcbiAgKSB7XG4gICAgaWYgKCFtZXNzYWdlS2V5IHx8ICFhbGVydEN0cmwgfHwgIXRyYW5zbGF0ZSkgdGhyb3cgbmV3IEVycm9yKFwiTWlzc2luZyBhIHJlcXVpcmVkIGFyZ3VtZW50ICgnbWVzc2FnZUtleScsICdhbGVydEN0cmwnIG9yICd0cmFuc2xhdGUnKVwiKTtcbiAgICBjb25zdCB0aXRsZUtleSA9IChvcHRzICYmIG9wdHMudGl0bGVLZXkpIHx8ICdFUlJPUi5BTEVSVF9IRUFERVInO1xuICAgIGNvbnN0IHRyYW5zbGF0aW9ucyA9IHRyYW5zbGF0ZS5pbnN0YW50KFsnQ09NTU9OLkJUTl9PSycsIG1lc3NhZ2VLZXksIHRpdGxlS2V5XSwgaW50ZXJwb2xhdGVQYXJhbXMpO1xuICAgIGNvbnN0IGFsZXJ0ID0gYXdhaXQgYWxlcnRDdHJsLmNyZWF0ZSh7XG4gICAgICBoZWFkZXI6IHRyYW5zbGF0aW9uc1t0aXRsZUtleV0sXG4gICAgICBtZXNzYWdlOiB0cmFuc2xhdGlvbnNbbWVzc2FnZUtleV0sXG4gICAgICBidXR0b25zOiBbXG4gICAgICAgIHtcbiAgICAgICAgICB0ZXh0OiB0cmFuc2xhdGlvbnNbJ0NPTU1PTi5CVE5fT0snXSxcbiAgICAgICAgICByb2xlOiAnY2FuY2VsJyxcbiAgICAgICAgfSxcbiAgICAgIF0sXG4gICAgfSk7XG4gICAgYXdhaXQgYWxlcnQucHJlc2VudCgpO1xuICAgIGF3YWl0IGFsZXJ0Lm9uRGlkRGlzbWlzcygpO1xuICB9XG59XG4iXX0=