@sumaris-net/ngx-components 18.23.49 → 18.23.50
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/doc/changelog.md +4 -0
- package/esm2022/public_api.mjs +2 -1
- package/esm2022/src/app/admin/users/users.mjs +25 -22
- package/esm2022/src/app/core/account/new-token.form.mjs +12 -9
- package/esm2022/src/app/core/account/token.table.mjs +14 -11
- package/esm2022/src/app/core/form/array/testing/form-array.test.mjs +9 -6
- package/esm2022/src/app/core/form/buttons/form-buttons-bar.component.mjs +8 -5
- package/esm2022/src/app/core/form/list/list.form.mjs +8 -5
- package/esm2022/src/app/core/form/properties/properties.form.mjs +12 -9
- package/esm2022/src/app/core/form/properties/properties.table.mjs +15 -12
- package/esm2022/src/app/core/form/text-popover/text-popover.component.mjs +10 -7
- package/esm2022/src/app/core/home/home.mjs +21 -18
- package/esm2022/src/app/core/menu/menu.component.mjs +10 -7
- package/esm2022/src/app/core/settings/settings.page.mjs +10 -7
- package/esm2022/src/app/core/table/column/actions-column.component.mjs +8 -5
- package/esm2022/src/app/core/table/column/nav-actions-column.component.mjs +9 -6
- package/esm2022/src/app/core/table/testing/table.testing.mjs +27 -23
- package/esm2022/src/app/core/table/testing/table2.testing.mjs +25 -22
- package/esm2022/src/app/shared/constants.mjs +3 -1
- package/esm2022/src/app/shared/directives/autotooltip.directive.mjs +35 -0
- package/esm2022/src/app/shared/directives/directives.module.mjs +33 -4
- package/esm2022/src/app/shared/image/gallery/image-gallery.component.mjs +15 -12
- package/esm2022/src/app/shared/material/autocomplete/material.autocomplete.mjs +13 -11
- package/esm2022/src/app/shared/material/autocomplete/material.autocomplete.module.mjs +4 -2
- package/esm2022/src/app/shared/material/boolean/boolean.module.mjs +5 -2
- package/esm2022/src/app/shared/material/boolean/material.boolean.mjs +9 -6
- package/esm2022/src/app/shared/material/boolean/testing/boolean.test.page.mjs +15 -4
- package/esm2022/src/app/shared/material/chips/chips.module.mjs +5 -2
- package/esm2022/src/app/shared/material/chips/material.chips.mjs +14 -12
- package/esm2022/src/app/shared/named-filter/named-filter-selector.component.mjs +8 -5
- package/esm2022/src/app/shared/storage/storage-explorer.component.mjs +11 -9
- package/esm2022/src/app/social/feed/feed.component.mjs +15 -12
- package/esm2022/src/app/social/job/progression/job-progression.icon.mjs +11 -8
- package/esm2022/src/app/social/job/progression/job-progression.list.mjs +12 -9
- package/esm2022/src/app/social/user-event/notification/user-event-notification.icon.mjs +12 -8
- package/esm2022/src/app/social/user-event/notification/user-event-notification.list.mjs +12 -9
- package/esm2022/src/app/social/user-event/notification/user-event-notification.modal.mjs +9 -6
- package/fesm2022/sumaris-net.ngx-components.mjs +194 -89
- package/fesm2022/sumaris-net.ngx-components.mjs.map +1 -1
- package/package.json +1 -1
- package/public_api.d.ts +1 -0
- package/src/app/admin/users/users.d.ts +1 -0
- package/src/app/core/account/new-token.form.d.ts +1 -0
- package/src/app/core/account/token.table.d.ts +1 -0
- package/src/app/core/form/array/testing/form-array.test.d.ts +1 -0
- package/src/app/core/form/buttons/form-buttons-bar.component.d.ts +1 -0
- package/src/app/core/form/list/list.form.d.ts +1 -0
- package/src/app/core/form/properties/properties.form.d.ts +1 -0
- package/src/app/core/form/properties/properties.table.d.ts +1 -0
- package/src/app/core/form/text-popover/text-popover.component.d.ts +1 -0
- package/src/app/core/home/home.d.ts +1 -0
- package/src/app/core/menu/menu.component.d.ts +1 -0
- package/src/app/core/settings/settings.page.d.ts +1 -0
- package/src/app/core/table/column/actions-column.component.d.ts +1 -0
- package/src/app/core/table/column/nav-actions-column.component.d.ts +1 -0
- package/src/app/core/table/testing/table.testing.d.ts +1 -0
- package/src/app/core/table/testing/table2.testing.d.ts +1 -0
- package/src/app/shared/constants.d.ts +2 -0
- package/src/app/shared/directives/autotooltip.directive.d.ts +14 -0
- package/src/app/shared/directives/directives.module.d.ts +4 -3
- package/src/app/shared/image/gallery/image-gallery.component.d.ts +1 -0
- package/src/app/shared/material/autocomplete/material.autocomplete.d.ts +1 -0
- package/src/app/shared/material/autocomplete/material.autocomplete.module.d.ts +2 -1
- package/src/app/shared/material/boolean/boolean.module.d.ts +2 -1
- package/src/app/shared/material/boolean/material.boolean.d.ts +1 -0
- package/src/app/shared/material/boolean/testing/boolean.test.page.d.ts +5 -0
- package/src/app/shared/material/chips/chips.module.d.ts +2 -1
- package/src/app/shared/material/chips/material.chips.d.ts +1 -0
- package/src/app/shared/named-filter/named-filter-selector.component.d.ts +1 -0
- package/src/app/shared/storage/storage-explorer.component.d.ts +1 -0
- package/src/app/social/feed/feed.component.d.ts +1 -0
- package/src/app/social/job/progression/job-progression.icon.d.ts +1 -0
- package/src/app/social/job/progression/job-progression.list.d.ts +1 -0
- package/src/app/social/user-event/notification/user-event-notification.icon.d.ts +1 -0
- package/src/app/social/user-event/notification/user-event-notification.list.d.ts +2 -0
- package/src/app/social/user-event/notification/user-event-notification.modal.d.ts +1 -0
- package/src/assets/manifest.json +1 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ChangeDetectionStrategy, Component, forwardRef, Input, ViewChild } from '@angular/core';
|
|
1
|
+
import { ChangeDetectionStrategy, Component, forwardRef, inject, Input, ViewChild } from '@angular/core';
|
|
2
2
|
import { AppTable } from '../table.class';
|
|
3
3
|
import { Referential } from '../../services/model/referential.model';
|
|
4
4
|
import { IonInfiniteScroll } from '@ionic/angular';
|
|
@@ -14,6 +14,7 @@ import { StatusIds } from '../../services/model/model.enum';
|
|
|
14
14
|
import { AppAsyncTable } from '../async-table.class';
|
|
15
15
|
import { EntitiesAsyncTableDataSource } from '../entities-async-table-datasource.class';
|
|
16
16
|
import { APP_CELL_SELECTION_SERVICE_TOKEN, CellSelectionService, } from '../../../shared/directives/cell-selection/cell-selection.service';
|
|
17
|
+
import { SHOW_TOOLTIP } from '../../../shared/constants';
|
|
17
18
|
import * as i0 from "@angular/core";
|
|
18
19
|
import * as i1 from "../../services/validator/base.validator.class";
|
|
19
20
|
import * as i2 from "@angular/forms";
|
|
@@ -32,24 +33,25 @@ import * as i14 from "@angular/material/icon";
|
|
|
32
33
|
import * as i15 from "@angular/material/button";
|
|
33
34
|
import * as i16 from "@angular/material/badge";
|
|
34
35
|
import * as i17 from "@angular/cdk/a11y";
|
|
35
|
-
import * as i18 from "
|
|
36
|
-
import * as i19 from "../../../shared/material/
|
|
37
|
-
import * as i20 from "../../../shared/
|
|
38
|
-
import * as i21 from "../../../shared/directives/
|
|
39
|
-
import * as i22 from "../../../shared/
|
|
40
|
-
import * as i23 from "
|
|
41
|
-
import * as i24 from "
|
|
42
|
-
import * as i25 from "
|
|
43
|
-
import * as i26 from "../../../shared/directives/resizable/resizable.
|
|
44
|
-
import * as i27 from "../../../shared/directives/
|
|
45
|
-
import * as i28 from "../../../shared/directives/cell-selection/cell-
|
|
46
|
-
import * as i29 from "../../../shared/
|
|
47
|
-
import * as i30 from "../../../shared/pipes/
|
|
48
|
-
import * as i31 from "../../../shared/pipes/
|
|
49
|
-
import * as i32 from "../../../shared/pipes/
|
|
50
|
-
import * as i33 from "../../../shared/pipes/
|
|
51
|
-
import * as i34 from "
|
|
52
|
-
import * as i35 from "
|
|
36
|
+
import * as i18 from "@angular/material/tooltip";
|
|
37
|
+
import * as i19 from "../../../shared/material/autocomplete/material.autocomplete";
|
|
38
|
+
import * as i20 from "../../../shared/material/boolean/material.boolean";
|
|
39
|
+
import * as i21 from "../../../shared/directives/autofocus.directive";
|
|
40
|
+
import * as i22 from "../../../shared/directives/autotooltip.directive";
|
|
41
|
+
import * as i23 from "../../../shared/toolbar/toolbar";
|
|
42
|
+
import * as i24 from "../../form/buttons/form-buttons-bar.component";
|
|
43
|
+
import * as i25 from "../column/actions-column.component";
|
|
44
|
+
import * as i26 from "../../../shared/directives/resizable/resizable.component";
|
|
45
|
+
import * as i27 from "../../../shared/directives/resizable/resizable.directive";
|
|
46
|
+
import * as i28 from "../../../shared/directives/cell-selection/cell-identifier.directive";
|
|
47
|
+
import * as i29 from "../../../shared/directives/cell-selection/cell-selection.directive";
|
|
48
|
+
import * as i30 from "../../../shared/pipes/property.pipes";
|
|
49
|
+
import * as i31 from "../../../shared/pipes/number-format.pipe";
|
|
50
|
+
import * as i32 from "../../../shared/pipes/arrays.pipe";
|
|
51
|
+
import * as i33 from "../../../shared/pipes/form.pipes";
|
|
52
|
+
import * as i34 from "../../../shared/pipes/selection.pipes";
|
|
53
|
+
import * as i35 from "../table.pipes";
|
|
54
|
+
import * as i36 from "../../services/pipes/referential-to-string.pipe";
|
|
53
55
|
export class Table2TestPage extends AppAsyncTable {
|
|
54
56
|
validatorService;
|
|
55
57
|
formBuilder;
|
|
@@ -74,6 +76,7 @@ export class Table2TestPage extends AppAsyncTable {
|
|
|
74
76
|
get dataService() {
|
|
75
77
|
return this._dataSource.dataService;
|
|
76
78
|
}
|
|
79
|
+
showTooltip = inject(SHOW_TOOLTIP);
|
|
77
80
|
constructor(injector, validatorService, formBuilder) {
|
|
78
81
|
super(injector, [
|
|
79
82
|
...RESERVED_START_COLUMNS,
|
|
@@ -273,7 +276,7 @@ export class Table2TestPage extends AppAsyncTable {
|
|
|
273
276
|
provide: APP_CELL_SELECTION_SERVICE_TOKEN,
|
|
274
277
|
useClass: CellSelectionService,
|
|
275
278
|
},
|
|
276
|
-
], viewQueries: [{ propertyName: "filterExpansionPanel", first: true, predicate: MatExpansionPanel, descendants: true, static: true }, { propertyName: "infiniteScroll", first: true, predicate: IonInfiniteScroll, descendants: true }], usesInheritance: true, ngImport: i0, template: "<app-toolbar\n color=\"primary\"\n [canGoBack]=\"true\"\n [hasValidate]=\"(loadingSubject | async) !== true && (dirtySubject | async) === true\"\n (onValidate)=\"save()\"\n [backHref]=\"'/testing'\"\n>\n <ion-title>Table 2 (click to select)</ion-title>\n\n <ion-buttons slot=\"end\">\n @if (selection | isEmptySelection) {\n <input matInput type=\"number\" step=\"1\" style=\"color: black; width: 50px\" [(ngModel)]=\"rowHeight\" />\n\n <!-- Add -->\n <button mat-icon-button *ngIf=\"canEdit && !mobile\" [title]=\"'COMMON.BTN_ADD' | translate\" (click)=\"addRow()\">\n <mat-icon>add</mat-icon>\n </button>\n\n <!-- reset filter -->\n <button mat-icon-button (click)=\"resetFilter()\" *ngIf=\"filterCriteriaCount\">\n <mat-icon color=\"accent\">filter_list_alt</mat-icon>\n <mat-icon class=\"icon-secondary\" style=\"left: 16px; top: 5px; font-weight: bold\">close</mat-icon>\n </button>\n\n <!-- show filter -->\n <button mat-icon-button (click)=\"filterExpansionPanel.toggle()\">\n <mat-icon\n *ngIf=\"filterCriteriaCount; else emptyFilter\"\n [matBadge]=\"filterCriteriaCount\"\n matBadgeColor=\"accent\"\n matBadgeSize=\"small\"\n matBadgePosition=\"above after\"\n aria-hidden=\"false\"\n >\n filter_list_alt\n </mat-icon>\n <ng-template #emptyFilter>\n <mat-icon>filter_list_alt</mat-icon>\n </ng-template>\n </button>\n\n <!-- save -->\n <button mat-icon-button *ngIf=\"mobile\" [disabled]=\"(dirtySubject | async) !== true\" (click)=\"save()\">\n <mat-icon>save</mat-icon>\n </button>\n } @else {\n <!-- if row selection -->\n <!-- delete -->\n <button\n mat-icon-button\n *ngIf=\"canEdit\"\n [title]=\"'COMMON.BTN_DELETE' | translate\"\n (click)=\"deleteSelection($event)\"\n >\n <mat-icon>delete</mat-icon>\n </button>\n\n <!-- duplicate -->\n <button\n mat-icon-button\n *ngIf=\"canEdit && selection.selected | isArrayLength: { equals: 1 }\"\n [title]=\"'COMMON.BTN_DUPLICATE' | translate\"\n (click)=\"duplicateRow($event, selection.selected[0])\"\n >\n <mat-icon>file_copy</mat-icon>\n </button>\n }\n </ion-buttons>\n</app-toolbar>\n<ion-content class=\"ion-no-padding\">\n <ion-refresher slot=\"fixed\" *ngIf=\"mobile\" (ionRefresh)=\"doRefresh($event)\">\n <ion-refresher-content></ion-refresher-content>\n </ion-refresher>\n\n <!-- error -->\n <ion-item *ngIf=\"mobile && error\" lines=\"none\" @slideUpDownAnimation>\n <ion-icon color=\"danger\" slot=\"start\" name=\"alert-circle\"></ion-icon>\n <ion-label color=\"danger\" class=\"error\" [innerHTML]=\"error | translate\"></ion-label>\n </ion-item>\n\n <!-- search -->\n <mat-expansion-panel\n #filterExpansionPanel\n class=\"filter-panel\"\n [class.filter-panel-floating]=\"filterPanelFloating\"\n [class.filter-panel-pinned]=\"!filterPanelFloating\"\n >\n <form class=\"form-container ion-padding-top\" [formGroup]=\"filterForm\" (ngSubmit)=\"applyFilterAndClosePanel($event)\">\n <ion-grid>\n <ion-row>\n <ion-col>\n <!-- search text -->\n <mat-form-field>\n <mat-label>{{ 'TABLE.TESTING.SEARCH_TEXT' | translate }}</mat-label>\n <ion-icon matPrefix name=\"search\"></ion-icon>\n <input matInput formControlName=\"searchText\" autocomplete=\"off\" />\n <button\n mat-icon-button\n matSuffix\n tabindex=\"-1\"\n type=\"button\"\n (click)=\"clearControlValue($event, filterForm.controls.searchText)\"\n [hidden]=\"filterForm.controls.searchText.disabled || !filterForm.controls.searchText.value\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n </ion-col>\n </ion-row>\n </ion-grid>\n </form>\n\n <mat-action-row>\n <!-- Counter -->\n <ion-label\n [hidden]=\"(loadingSubject | async) || filterForm.dirty\"\n [color]=\"empty && 'danger'\"\n class=\"ion-padding\"\n >\n {{\n (totalRowCount ? 'COMMON.RESULT_COUNT' : 'COMMON.NO_RESULT')\n | translate\n : {\n count: (totalRowCount | numberFormat),\n }\n }}\n </ion-label>\n\n <div class=\"toolbar-spacer\"></div>\n\n <button\n mat-icon-button\n color=\"accent\"\n *ngIf=\"filterPanelFloating\"\n (click)=\"toggleFilterPanelFloating()\"\n class=\"hidden-xs hidden-sm hidden-md\"\n [title]=\"(filterPanelFloating ? 'COMMON.BTN_EXPAND' : 'COMMON.BTN_HIDE') | translate\"\n >\n <mat-icon>\n <span style=\"transform: rotate(90deg)\">{{ filterPanelFloating ? '»' : '«' }}</span>\n </mat-icon>\n </button>\n\n <!-- Close panel -->\n <ion-button mat-button fill=\"clear\" color=\"dark\" (click)=\"closeFilterPanel()\" [disabled]=\"loadingSubject | async\">\n <ion-text translate>COMMON.BTN_CLOSE</ion-text>\n </ion-button>\n\n <!-- Search button -->\n <ion-button\n mat-button\n [color]=\"filterForm.dirty ? 'tertiary' : 'dark'\"\n [fill]=\"filterForm.dirty ? 'solid' : 'clear'\"\n (click)=\"applyFilterAndClosePanel($event)\"\n >\n <ion-text translate>COMMON.BTN_APPLY</ion-text>\n </ion-button>\n </mat-action-row>\n </mat-expansion-panel>\n\n <!-- table -->\n <div [class.table-container]=\"!enableInfiniteScroll\" style=\"position: relative\">\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 appCellSelection\n [appSelectableColumns]=\"selectableColumns\"\n (appCellSelectionChange)=\"onCellSelectionChange($event)\"\n (appCellRightClick)=\"onCellRightClick($event)\"\n >\n <ng-container matColumnDef=\"select\" [sticky]=\"checkBoxSelection\" [class.mat-column-sticky]=\"checkBoxSelection\">\n <th mat-header-cell *matHeaderCellDef [class.cdk-visually-hidden]=\"!checkBoxSelection\">\n @if (selection | isMultipleSelection) {\n <mat-checkbox\n [checked]=\"this | isAllSelected\"\n [indeterminate]=\"this | isNotAllSelected\"\n (change)=\"$event ? masterToggle() : null\"\n ></mat-checkbox>\n }\n </th>\n <td mat-cell *matCellDef=\"let row\" [class.cdk-visually-hidden]=\"!checkBoxSelection\">\n <mat-checkbox [checked]=\"selection | isSelected: row\" (click)=\"toggleSelectRow($event, row)\"></mat-checkbox>\n </td>\n </ng-container>\n\n <!-- Id column -->\n <ng-container matColumnDef=\"id\" [sticky]=\"sticky\">\n <th mat-header-cell *matHeaderCellDef>\n <span mat-sort-header>\n <ion-label title=\"Id\">#</ion-label>\n <ion-label color=\"danger\" [innerHTML]=\"' *'\"></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]=\"' *'\"></ion-label>\n </span>\n </th>\n <td\n mat-cell\n *matCellDef=\"let row\"\n (click)=\"focusColumn = 'name'\"\n [appCellId]=\"{ rowId: row.id, columnName: 'name' }\"\n >\n <mat-form-field *ngIf=\"!readOnly && row.editing; else readOnlyTemplate\">\n <input\n matInput\n autocomplete=\"off\"\n [required]=\"true\"\n [formControl]=\"row.validator | formGetControl: 'name'\"\n [placeholder]=\"'TABLE.TESTING.NAME' | translate\"\n [appAutofocus]=\"row.id === -1 || focusColumn === 'name'\"\n />\n <ng-content select=\"[suffix]\"></ng-content>\n <mat-error *ngIf=\"(row.validator | formGetControl: 'name').hasError('required')\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n <mat-error *ngIf=\"(row.validator | formGetControl: 'name').hasError('maxlength')\" translate>\n ERROR.FIELD_MAX_LENGTH_COMPACT\n </mat-error>\n <mat-error *ngIf=\"(row.validator | formGetControl: 'name').hasError('minlength')\" translate>\n ERROR.FIELD_MIN_LENGTH_COMPACT\n </mat-error>\n </mat-form-field>\n <ng-template #readOnlyTemplate>\n <ion-label appAutoTitle>\n {{ (row.validator | formGetValue: 'name') || (row.currentData | propertyGet: 'name') }}\n </ion-label>\n </ng-template>\n </td>\n </ng-container>\n\n <!-- Level column -->\n <ng-container matColumnDef=\"levelId\">\n <th mat-header-cell *matHeaderCellDef [resizable]=\"resizable\">\n <span mat-sort-header>\n <ion-label>{{ 'TABLE.TESTING.LEVEL_ID' | translate }}</ion-label>\n <ion-label color=\"danger\" [innerHTML]=\"' *'\"></ion-label>\n </span>\n </th>\n <td mat-cell *matCellDef=\"let row\" [appCellId]=\"{ rowId: row.id, columnName: 'levelId' }\">\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\" [appCellId]=\"{ rowId: row.id, columnName: 'boolean' }\">\n <mat-boolean-field\n *ngIf=\"!readOnly && row.editing; else readOnlyTemplate\"\n floatLabel=\"never\"\n [style]=\"'checkbox'\"\n [formControl]=\"\n (row.validator | formGetControl: 'boolean') || formBuilder.control(row.currentData['boolean'])\n \"\n [compact]=\"true\"\n ></mat-boolean-field>\n <ng-template #readOnlyTemplate>\n <ion-label appAutoTitle>\n {{\n (row.validator | formGetValue: 'boolean') || (row.currentData | propertyGet: 'boolean')\n ? ('COMMON.YES' | translate)\n : ('COMMON.NO' | translate)\n }}\n </ion-label>\n </ng-template>\n </td>\n </ng-container>\n\n <ng-container matColumnDef=\"boolean2\">\n <th mat-header-cell *matHeaderCellDef cdkDrag [resizable]=\"resizable\">\n <!-- if sortable, wrap the header with a mat-sort-header -->\n <span mat-sort-header>\n <ion-label>Boolean 2</ion-label>\n </span>\n </th>\n <td mat-cell *matCellDef=\"let row\">\n <mat-boolean-field\n *ngIf=\"!readOnly && row.editing; else readOnlyTemplate\"\n [floatLabel]=\"'never'\"\n [style]=\"'radio'\"\n [showRadio]=\"true\"\n [formControl]=\"\n (row.validator | formGetControl: 'boolean2') || formBuilder.control(row.currentData['boolean2'])\n \"\n ></mat-boolean-field>\n <ng-template #readOnlyTemplate>\n <ion-label appAutoTitle>\n {{\n (row.validator | formGetValue: 'boolean2') || (row.currentData | propertyGet: 'boolean2')\n ? ('COMMON.YES' | translate)\n : ('COMMON.NO' | translate)\n }}\n </ion-label>\n </ng-template>\n </td>\n </ng-container>\n\n <ng-container matColumnDef=\"boolean3\">\n <th mat-header-cell *matHeaderCellDef cdkDrag [resizable]=\"resizable\">\n <!-- if sortable, wrap the header with a mat-sort-header -->\n <span mat-sort-header>\n <ion-label>Boolean 3</ion-label>\n </span>\n </th>\n <td mat-cell *matCellDef=\"let row\">\n <mat-boolean-field\n *ngIf=\"!readOnly && row.editing; else readOnlyTemplate\"\n floatLabel=\"never\"\n [style]=\"'button'\"\n [formControl]=\"\n (row.validator | formGetControl: 'boolean2') || formBuilder.control(row.currentData['boolean2'])\n \"\n ></mat-boolean-field>\n <ng-template #readOnlyTemplate>\n <ion-label appAutoTitle>\n {{\n (row.validator | formGetValue: 'boolean2') || (row.currentData | propertyGet: 'boolean2')\n ? ('COMMON.YES' | translate)\n : ('COMMON.NO' | translate)\n }}\n </ion-label>\n </ng-template>\n </td>\n </ng-container>\n\n <!-- Actions buttons column -->\n <app-actions-column\n [stickyEnd]=\"stickyEnd\"\n [canCancel]=\"false\"\n [style]=\"'table'\"\n (optionsClick)=\"openSelectColumnsModal($event)\"\n (cancelOrDeleteClick)=\"cancelOrDelete($event.event, $event.row)\"\n (confirmAndAddClick)=\"confirmAndAdd($event.event, $event.row)\"\n (backward)=\"confirmAndBackward($event.event, $event.row)\"\n (forward)=\"confirmAndForward($event.event, $event.row)\"\n [cellTemplate]=\"cellInjection\"\n >\n <!-- cell injection-->\n <ng-template #cellInjection let-row>\n <span *ngIf=\"row.editing && !row.validator.dirty\">-</span>\n </ng-template>\n </app-actions-column>\n\n <tr mat-header-row *matHeaderRowDef=\"displayedColumns; sticky: true\"></tr>\n <tr\n mat-row\n *matRowDef=\"let row; columns: displayedColumns\"\n [class.mat-row-selected]=\"row.editing\"\n [class.mat-row-error]=\"row.invalid\"\n [class.mat-row-disabled]=\"!row.editing\"\n [class.mat-row-dirty]=\"row.dirty\"\n (click)=\"clickRow($event, row)\"\n (keydown.escape)=\"escapeEditingRow($event)\"\n [cdkTrapFocus]=\"row.invalid\"\n ></tr>\n </table>\n\n <ng-container *ngIf=\"loadingSubject | async; else noResult\">\n <ion-item>\n <ion-skeleton-text animated></ion-skeleton-text>\n </ion-item>\n </ng-container>\n\n <ng-template #noResult>\n <ion-item *ngIf=\"totalRowCount === 0\">\n <ion-text color=\"danger\" class=\"text-italic\" translate>COMMON.NO_RESULT</ion-text>\n </ion-item>\n </ng-template>\n\n <ion-infinite-scroll\n *ngIf=\"enableInfiniteScroll\"\n [threshold]=\"mobile ? '10%' : '2%'\"\n position=\"bottom\"\n (ionInfinite)=\"fetchMore($event)\"\n >\n <ion-infinite-scroll-content\n loadingSpinner=\"circles\"\n [loadingText]=\"'COMMON.LOADING_DOTS' | translate\"\n ></ion-infinite-scroll-content>\n </ion-infinite-scroll>\n </div>\n</ion-content>\n\n<ion-footer>\n <!-- Paginator -->\n <mat-paginator\n *ngIf=\"!enableInfiniteScroll\"\n [length]=\"totalRowCount\"\n [pageSize]=\"defaultPageSize\"\n [pageSizeOptions]=\"defaultPageSizeOptions\"\n showFirstLastButtons\n ></mat-paginator>\n\n <app-form-buttons-bar\n *ngIf=\"canEdit && !mobile\"\n (onCancel)=\"load()\"\n (onSave)=\"save()\"\n [disabled]=\"(loadingSubject | async) || !dirty\"\n >\n <!-- error -->\n <ion-item *ngIf=\"errorSubject | 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", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "component", type: i7.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i7.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i7.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i7.MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: i7.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i7.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i7.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i7.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "component", type: i7.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i7.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "directive", type: i8.MatSort, selector: "[matSort]", inputs: ["matSortActive", "matSortStart", "matSortDirection", "matSortDisableClear", "matSortDisabled"], outputs: ["matSortChange"], exportAs: ["matSort"] }, { kind: "component", type: i8.MatSortHeader, selector: "[mat-sort-header]", inputs: ["mat-sort-header", "arrowPosition", "start", "disabled", "sortActionDescription", "disableClear"], exportAs: ["matSortHeader"] }, { kind: "component", type: i9.MatPaginator, selector: "mat-paginator", inputs: ["color", "pageIndex", "length", "pageSize", "pageSizeOptions", "hidePageSize", "showFirstLastButtons", "selectConfig", "disabled"], outputs: ["page"], exportAs: ["matPaginator"] }, { kind: "component", type: i10.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i10.MatLabel, selector: "mat-label" }, { kind: "directive", type: i10.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "directive", type: i10.MatPrefix, selector: "[matPrefix], [matIconPrefix], [matTextPrefix]", inputs: ["matTextPrefix"] }, { kind: "directive", type: i10.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "directive", type: i11.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "component", type: i12.MatCheckbox, selector: "mat-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { kind: "component", type: i13.MatExpansionPanel, selector: "mat-expansion-panel", inputs: ["hideToggle", "togglePosition"], outputs: ["afterExpand", "afterCollapse"], exportAs: ["matExpansionPanel"] }, { kind: "directive", type: i13.MatExpansionPanelActionRow, selector: "mat-action-row" }, { kind: "component", type: i14.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i15.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "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", "label", "appearance", "subscriptSizing", "placeholder", "suggestFn", "required", "hideRequiredMarker", "mobile", "clearable", "debounceTime", "displaySeparator", "displayWith", "displayAttributes", "displayColumnSizes", "displayColumnNames", "highlightAccent", "showAllOnFocus", "showPanelOnFocus", "reloadItemsOnFocus", "clearInvalidValueOnBlur", "autofocus", "config", "i18nPrefix", "noResultMessage", "panelClass", "panelWidth", "disableRipple", "matAutocompletePosition", "multiple", "fetchMoreThreshold", "suggestLengthThreshold", "showLoadingSpinner", "debug", "showSearchBar", "stickySearchBar", "applyImplicitValue", "dropButtonTitle", "clearButtonTitle", "trimSearchText", "splitSearchText", "selectInputContentOnFocus", "selectInputContentOnFocusDelay", "previewImplicitValue", "showFavorites", "toggleFavoriteTitle", "favoriteItems", "colSizes", "class", "filter", "readonly", "tabindex", "items"], outputs: ["click", "blur", "focus", "dropButtonClick", "keydown.escape", "keydown.backspace", "keyup.enter", "arrowUp", "arrowDown", "enter", "selectionChange", "openedChange", "toggleFavorite"] }, { kind: "component", type: i19.MatBooleanField, selector: "mat-boolean-field", inputs: ["disabled", "formControl", "formControlName", "placeholder", "floatLabel", "appearance", "subscriptSizing", "readonly", "required", "compact", "autofocus", "style", "buttonsColCount", "class", "yesLabel", "noLabel", "showButtonIcons", "yesIcon", "noIcon", "clearable", "labelPosition", "tabindex", "showRadio", "value"], outputs: ["keyup.enter", "focus", "blur"] }, { kind: "directive", type: i20.AutofocusDirective, selector: "[autofocus], input[appAutofocus]", inputs: ["appAutofocus", "autofocusDelay"] }, { kind: "directive", type: i21.AutoTitleDirective, selector: "ion-label[appAutoTitle], mat-label[appAutoTitle]", inputs: ["appAutoTitle"] }, { kind: "component", type: i22.ToolbarComponent, selector: "app-toolbar", inputs: ["progressBarMode", "title", "color", "class", "id", "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", "disabledEscape", "classList", "saveButtonColor", "backText", "cancelText", "nextText", "showBack", "showCancel", "showNext", "showSave"], outputs: ["onCancel", "onSave", "onNext", "onBack", "onSaveAndClose", "onSaveAndNext"] }, { kind: "component", type: i24.ActionsColumnComponent, selector: "app-actions-column", inputs: ["matColumnDef", "style", "showPendingSpinner", "stickyEnd", "canCancel", "canConfirm", "canDelete", "canBackward", "canForward", "canConfirmAndAdd", "dirtyIcon", "optionsTitle", "class", "cellTemplateStart", "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]", inputs: ["minWidth"], outputs: ["resizable", "fit"] }, { kind: "directive", type: i27.CellIdentifierDirective, selector: "[appCellId]", inputs: ["appCellId"] }, { kind: "directive", type: i28.CellSelectionDirective, selector: "[appCellSelection]", inputs: ["appSelectableColumns"], outputs: ["appCellSelectionChange", "appCellRightClick"] }, { kind: "pipe", type: i3.AsyncPipe, name: "async" }, { kind: "pipe", type: i5.TranslatePipe, name: "translate" }, { kind: "pipe", type: i29.PropertyGetPipe, name: "propertyGet" }, { kind: "pipe", type: i30.NumberFormatPipe, name: "numberFormat" }, { kind: "pipe", type: i31.ArrayLengthPipe, name: "isArrayLength" }, { kind: "pipe", type: i32.FormGetControlPipe, name: "formGetControl" }, { kind: "pipe", type: i32.FormGetValuePipe, name: "formGetValue" }, { kind: "pipe", type: i33.IsSelectedPipe, name: "isSelected" }, { kind: "pipe", type: i33.IsEmptySelectionPipe, name: "isEmptySelection" }, { kind: "pipe", type: i33.IsMultipleSelectionPipe, name: "isMultipleSelection" }, { kind: "pipe", type: i34.IsAllSelectedPipe, name: "isAllSelected" }, { kind: "pipe", type: i34.IsNotAllSelectedPipe, name: "isNotAllSelected" }, { kind: "pipe", type: i35.ReferentialToStringPipe, name: "referentialToString" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
279
|
+
], viewQueries: [{ propertyName: "filterExpansionPanel", first: true, predicate: MatExpansionPanel, descendants: true, static: true }, { propertyName: "infiniteScroll", first: true, predicate: IonInfiniteScroll, descendants: true }], usesInheritance: true, ngImport: i0, template: "<app-toolbar\n color=\"primary\"\n [canGoBack]=\"true\"\n [hasValidate]=\"(loadingSubject | async) !== true && (dirtySubject | async) === true\"\n (onValidate)=\"save()\"\n [backHref]=\"'/testing'\"\n>\n <ion-title>Table 2 (click to select)</ion-title>\n\n <ion-buttons slot=\"end\">\n @if (selection | isEmptySelection) {\n <input matInput type=\"number\" step=\"1\" style=\"color: black; width: 50px\" [(ngModel)]=\"rowHeight\" />\n\n <!-- Add -->\n <button\n mat-icon-button\n *ngIf=\"canEdit && !mobile\"\n [title]=\"!showTooltip ? ('COMMON.BTN_ADD' | translate) : ''\"\n [matTooltip]=\"showTooltip ? ('COMMON.BTN_ADD' | translate) : ''\"\n (click)=\"addRow()\"\n >\n <mat-icon>add</mat-icon>\n </button>\n\n <!-- reset filter -->\n <button mat-icon-button (click)=\"resetFilter()\" *ngIf=\"filterCriteriaCount\">\n <mat-icon color=\"accent\">filter_list_alt</mat-icon>\n <mat-icon class=\"icon-secondary\" style=\"left: 16px; top: 5px; font-weight: bold\">close</mat-icon>\n </button>\n\n <!-- show filter -->\n <button mat-icon-button (click)=\"filterExpansionPanel.toggle()\">\n <mat-icon\n *ngIf=\"filterCriteriaCount; else emptyFilter\"\n [matBadge]=\"filterCriteriaCount\"\n matBadgeColor=\"accent\"\n matBadgeSize=\"small\"\n matBadgePosition=\"above after\"\n aria-hidden=\"false\"\n >\n filter_list_alt\n </mat-icon>\n <ng-template #emptyFilter>\n <mat-icon>filter_list_alt</mat-icon>\n </ng-template>\n </button>\n\n <!-- save -->\n <button mat-icon-button *ngIf=\"mobile\" [disabled]=\"(dirtySubject | async) !== true\" (click)=\"save()\">\n <mat-icon>save</mat-icon>\n </button>\n } @else {\n <!-- if row selection -->\n <!-- delete -->\n <button\n mat-icon-button\n *ngIf=\"canEdit\"\n [title]=\"!showTooltip ? ('COMMON.BTN_DELETE' | translate) : ''\"\n [matTooltip]=\"showTooltip ? ('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]=\"!showTooltip ? ('COMMON.BTN_DUPLICATE' | translate) : ''\"\n [matTooltip]=\"showTooltip ? ('COMMON.BTN_DUPLICATE' | translate) : ''\"\n (click)=\"duplicateRow($event, selection.selected[0])\"\n >\n <mat-icon>file_copy</mat-icon>\n </button>\n }\n </ion-buttons>\n</app-toolbar>\n<ion-content class=\"ion-no-padding\">\n <ion-refresher slot=\"fixed\" *ngIf=\"mobile\" (ionRefresh)=\"doRefresh($event)\">\n <ion-refresher-content></ion-refresher-content>\n </ion-refresher>\n\n <!-- error -->\n <ion-item *ngIf=\"mobile && error\" lines=\"none\" @slideUpDownAnimation>\n <ion-icon color=\"danger\" slot=\"start\" name=\"alert-circle\"></ion-icon>\n <ion-label color=\"danger\" class=\"error\" [innerHTML]=\"error | translate\"></ion-label>\n </ion-item>\n\n <!-- search -->\n <mat-expansion-panel\n #filterExpansionPanel\n class=\"filter-panel\"\n [class.filter-panel-floating]=\"filterPanelFloating\"\n [class.filter-panel-pinned]=\"!filterPanelFloating\"\n >\n <form class=\"form-container ion-padding-top\" [formGroup]=\"filterForm\" (ngSubmit)=\"applyFilterAndClosePanel($event)\">\n <ion-grid>\n <ion-row>\n <ion-col>\n <!-- search text -->\n <mat-form-field>\n <mat-label>{{ 'TABLE.TESTING.SEARCH_TEXT' | translate }}</mat-label>\n <ion-icon matPrefix name=\"search\"></ion-icon>\n <input matInput formControlName=\"searchText\" autocomplete=\"off\" />\n <button\n mat-icon-button\n matSuffix\n tabindex=\"-1\"\n type=\"button\"\n (click)=\"clearControlValue($event, filterForm.controls.searchText)\"\n [hidden]=\"filterForm.controls.searchText.disabled || !filterForm.controls.searchText.value\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n </ion-col>\n </ion-row>\n </ion-grid>\n </form>\n\n <mat-action-row>\n <!-- Counter -->\n <ion-label\n [hidden]=\"(loadingSubject | async) || filterForm.dirty\"\n [color]=\"empty && 'danger'\"\n class=\"ion-padding\"\n >\n {{\n (totalRowCount ? 'COMMON.RESULT_COUNT' : 'COMMON.NO_RESULT')\n | translate\n : {\n count: (totalRowCount | numberFormat),\n }\n }}\n </ion-label>\n\n <div class=\"toolbar-spacer\"></div>\n\n <button\n mat-icon-button\n color=\"accent\"\n *ngIf=\"filterPanelFloating\"\n (click)=\"toggleFilterPanelFloating()\"\n class=\"hidden-xs hidden-sm hidden-md\"\n [title]=\"!showTooltip ? ((filterPanelFloating ? 'COMMON.BTN_EXPAND' : 'COMMON.BTN_HIDE') | translate) : ''\"\n [matTooltip]=\"showTooltip ? ((filterPanelFloating ? 'COMMON.BTN_EXPAND' : 'COMMON.BTN_HIDE') | translate) : ''\"\n >\n <mat-icon>\n <span style=\"transform: rotate(90deg)\">{{ filterPanelFloating ? '»' : '«' }}</span>\n </mat-icon>\n </button>\n\n <!-- Close panel -->\n <ion-button mat-button fill=\"clear\" color=\"dark\" (click)=\"closeFilterPanel()\" [disabled]=\"loadingSubject | async\">\n <ion-text translate>COMMON.BTN_CLOSE</ion-text>\n </ion-button>\n\n <!-- Search button -->\n <ion-button\n mat-button\n [color]=\"filterForm.dirty ? 'tertiary' : 'dark'\"\n [fill]=\"filterForm.dirty ? 'solid' : 'clear'\"\n (click)=\"applyFilterAndClosePanel($event)\"\n >\n <ion-text translate>COMMON.BTN_APPLY</ion-text>\n </ion-button>\n </mat-action-row>\n </mat-expansion-panel>\n\n <!-- table -->\n <div [class.table-container]=\"!enableInfiniteScroll\" style=\"position: relative\">\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 appCellSelection\n [appSelectableColumns]=\"selectableColumns\"\n (appCellSelectionChange)=\"onCellSelectionChange($event)\"\n (appCellRightClick)=\"onCellRightClick($event)\"\n >\n <ng-container matColumnDef=\"select\" [sticky]=\"checkBoxSelection\" [class.mat-column-sticky]=\"checkBoxSelection\">\n <th mat-header-cell *matHeaderCellDef [class.cdk-visually-hidden]=\"!checkBoxSelection\">\n @if (selection | isMultipleSelection) {\n <mat-checkbox\n [checked]=\"this | isAllSelected\"\n [indeterminate]=\"this | isNotAllSelected\"\n (change)=\"$event ? masterToggle() : null\"\n ></mat-checkbox>\n }\n </th>\n <td mat-cell *matCellDef=\"let row\" [class.cdk-visually-hidden]=\"!checkBoxSelection\">\n <mat-checkbox [checked]=\"selection | isSelected: row\" (click)=\"toggleSelectRow($event, row)\"></mat-checkbox>\n </td>\n </ng-container>\n\n <!-- Id column -->\n <ng-container matColumnDef=\"id\" [sticky]=\"sticky\">\n <th mat-header-cell *matHeaderCellDef>\n <span mat-sort-header>\n <ion-label title=\"Id\">#</ion-label>\n <ion-label color=\"danger\" [innerHTML]=\"' *'\"></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 appAutoTooltip>\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\n [title]=\"!showTooltip ? ('TABLE.TESTING.NAME' | translate) : ''\"\n [matTooltip]=\"showTooltip ? ('TABLE.TESTING.NAME' | translate) : ''\"\n >\n {{ 'TABLE.TESTING.NAME' | translate }}\n </ion-label>\n <ion-label color=\"danger\" [innerHTML]=\"' *'\"></ion-label>\n </span>\n </th>\n <td\n mat-cell\n *matCellDef=\"let row\"\n (click)=\"focusColumn = 'name'\"\n [appCellId]=\"{ rowId: row.id, columnName: 'name' }\"\n >\n <mat-form-field *ngIf=\"!readOnly && row.editing; else readOnlyTemplate\">\n <input\n matInput\n autocomplete=\"off\"\n [required]=\"true\"\n [formControl]=\"row.validator | formGetControl: 'name'\"\n [placeholder]=\"'TABLE.TESTING.NAME' | translate\"\n [appAutofocus]=\"row.id === -1 || focusColumn === 'name'\"\n />\n <ng-content select=\"[suffix]\"></ng-content>\n <mat-error *ngIf=\"(row.validator | formGetControl: 'name').hasError('required')\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n <mat-error *ngIf=\"(row.validator | formGetControl: 'name').hasError('maxlength')\" translate>\n ERROR.FIELD_MAX_LENGTH_COMPACT\n </mat-error>\n <mat-error *ngIf=\"(row.validator | formGetControl: 'name').hasError('minlength')\" translate>\n ERROR.FIELD_MIN_LENGTH_COMPACT\n </mat-error>\n </mat-form-field>\n <ng-template #readOnlyTemplate>\n <ion-label appAutoTooltip>\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]=\"' *'\"></ion-label>\n </span>\n </th>\n <td mat-cell *matCellDef=\"let row\" [appCellId]=\"{ rowId: row.id, columnName: 'levelId' }\">\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 appAutoTooltip>\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\" [appCellId]=\"{ rowId: row.id, columnName: 'boolean' }\">\n <mat-boolean-field\n *ngIf=\"!readOnly && row.editing; else readOnlyTemplate\"\n floatLabel=\"never\"\n [style]=\"'checkbox'\"\n [formControl]=\"\n (row.validator | formGetControl: 'boolean') || formBuilder.control(row.currentData['boolean'])\n \"\n [compact]=\"true\"\n ></mat-boolean-field>\n <ng-template #readOnlyTemplate>\n <ion-label appAutoTooltip>\n {{\n (row.validator | formGetValue: 'boolean') || (row.currentData | propertyGet: 'boolean')\n ? ('COMMON.YES' | translate)\n : ('COMMON.NO' | translate)\n }}\n </ion-label>\n </ng-template>\n </td>\n </ng-container>\n\n <ng-container matColumnDef=\"boolean2\">\n <th mat-header-cell *matHeaderCellDef cdkDrag [resizable]=\"resizable\">\n <!-- if sortable, wrap the header with a mat-sort-header -->\n <span mat-sort-header>\n <ion-label>Boolean 2</ion-label>\n </span>\n </th>\n <td mat-cell *matCellDef=\"let row\">\n <mat-boolean-field\n *ngIf=\"!readOnly && row.editing; else readOnlyTemplate\"\n [floatLabel]=\"'never'\"\n [style]=\"'radio'\"\n [showRadio]=\"true\"\n [formControl]=\"\n (row.validator | formGetControl: 'boolean2') || formBuilder.control(row.currentData['boolean2'])\n \"\n ></mat-boolean-field>\n <ng-template #readOnlyTemplate>\n <ion-label appAutoTooltip>\n {{\n (row.validator | formGetValue: 'boolean2') || (row.currentData | propertyGet: 'boolean2')\n ? ('COMMON.YES' | translate)\n : ('COMMON.NO' | translate)\n }}\n </ion-label>\n </ng-template>\n </td>\n </ng-container>\n\n <ng-container matColumnDef=\"boolean3\">\n <th mat-header-cell *matHeaderCellDef cdkDrag [resizable]=\"resizable\">\n <!-- if sortable, wrap the header with a mat-sort-header -->\n <span mat-sort-header>\n <ion-label>Boolean 3</ion-label>\n </span>\n </th>\n <td mat-cell *matCellDef=\"let row\">\n <mat-boolean-field\n *ngIf=\"!readOnly && row.editing; else readOnlyTemplate\"\n floatLabel=\"never\"\n [style]=\"'button'\"\n [formControl]=\"\n (row.validator | formGetControl: 'boolean2') || formBuilder.control(row.currentData['boolean2'])\n \"\n ></mat-boolean-field>\n <ng-template #readOnlyTemplate>\n <ion-label appAutoTooltip>\n {{\n (row.validator | formGetValue: 'boolean2') || (row.currentData | propertyGet: 'boolean2')\n ? ('COMMON.YES' | translate)\n : ('COMMON.NO' | translate)\n }}\n </ion-label>\n </ng-template>\n </td>\n </ng-container>\n\n <!-- Actions buttons column -->\n <app-actions-column\n [stickyEnd]=\"stickyEnd\"\n [canCancel]=\"false\"\n [style]=\"'table'\"\n (optionsClick)=\"openSelectColumnsModal($event)\"\n (cancelOrDeleteClick)=\"cancelOrDelete($event.event, $event.row)\"\n (confirmAndAddClick)=\"confirmAndAdd($event.event, $event.row)\"\n (backward)=\"confirmAndBackward($event.event, $event.row)\"\n (forward)=\"confirmAndForward($event.event, $event.row)\"\n [cellTemplate]=\"cellInjection\"\n >\n <!-- cell injection-->\n <ng-template #cellInjection let-row>\n <span *ngIf=\"row.editing && !row.validator.dirty\">-</span>\n </ng-template>\n </app-actions-column>\n\n <tr mat-header-row *matHeaderRowDef=\"displayedColumns; sticky: true\"></tr>\n <tr\n mat-row\n *matRowDef=\"let row; columns: displayedColumns\"\n [class.mat-row-selected]=\"row.editing\"\n [class.mat-row-error]=\"row.invalid\"\n [class.mat-row-disabled]=\"!row.editing\"\n [class.mat-row-dirty]=\"row.dirty\"\n (click)=\"clickRow($event, row)\"\n (keydown.escape)=\"escapeEditingRow($event)\"\n [cdkTrapFocus]=\"row.invalid\"\n ></tr>\n </table>\n\n <ng-container *ngIf=\"loadingSubject | async; else noResult\">\n <ion-item>\n <ion-skeleton-text animated></ion-skeleton-text>\n </ion-item>\n </ng-container>\n\n <ng-template #noResult>\n <ion-item *ngIf=\"totalRowCount === 0\">\n <ion-text color=\"danger\" class=\"text-italic\" translate>COMMON.NO_RESULT</ion-text>\n </ion-item>\n </ng-template>\n\n <ion-infinite-scroll\n *ngIf=\"enableInfiniteScroll\"\n [threshold]=\"mobile ? '10%' : '2%'\"\n position=\"bottom\"\n (ionInfinite)=\"fetchMore($event)\"\n >\n <ion-infinite-scroll-content\n loadingSpinner=\"circles\"\n [loadingText]=\"'COMMON.LOADING_DOTS' | translate\"\n ></ion-infinite-scroll-content>\n </ion-infinite-scroll>\n </div>\n</ion-content>\n\n<ion-footer>\n <!-- Paginator -->\n <mat-paginator\n *ngIf=\"!enableInfiniteScroll\"\n [length]=\"totalRowCount\"\n [pageSize]=\"defaultPageSize\"\n [pageSizeOptions]=\"defaultPageSizeOptions\"\n showFirstLastButtons\n ></mat-paginator>\n\n <app-form-buttons-bar\n *ngIf=\"canEdit && !mobile\"\n (onCancel)=\"load()\"\n (onSave)=\"save()\"\n [disabled]=\"(loadingSubject | async) || !dirty\"\n >\n <!-- error -->\n <ion-item *ngIf=\"errorSubject | 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", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "component", type: i7.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i7.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i7.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i7.MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: i7.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i7.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i7.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i7.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "component", type: i7.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i7.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "directive", type: i8.MatSort, selector: "[matSort]", inputs: ["matSortActive", "matSortStart", "matSortDirection", "matSortDisableClear", "matSortDisabled"], outputs: ["matSortChange"], exportAs: ["matSort"] }, { kind: "component", type: i8.MatSortHeader, selector: "[mat-sort-header]", inputs: ["mat-sort-header", "arrowPosition", "start", "disabled", "sortActionDescription", "disableClear"], exportAs: ["matSortHeader"] }, { kind: "component", type: i9.MatPaginator, selector: "mat-paginator", inputs: ["color", "pageIndex", "length", "pageSize", "pageSizeOptions", "hidePageSize", "showFirstLastButtons", "selectConfig", "disabled"], outputs: ["page"], exportAs: ["matPaginator"] }, { kind: "component", type: i10.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i10.MatLabel, selector: "mat-label" }, { kind: "directive", type: i10.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "directive", type: i10.MatPrefix, selector: "[matPrefix], [matIconPrefix], [matTextPrefix]", inputs: ["matTextPrefix"] }, { kind: "directive", type: i10.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "directive", type: i11.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "component", type: i12.MatCheckbox, selector: "mat-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { kind: "component", type: i13.MatExpansionPanel, selector: "mat-expansion-panel", inputs: ["hideToggle", "togglePosition"], outputs: ["afterExpand", "afterCollapse"], exportAs: ["matExpansionPanel"] }, { kind: "directive", type: i13.MatExpansionPanelActionRow, selector: "mat-action-row" }, { kind: "component", type: i14.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i15.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "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: "directive", type: i18.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "component", type: i19.MatAutocompleteField, selector: "mat-autocomplete-field", inputs: ["equals", "logPrefix", "formControl", "formControlName", "floatLabel", "label", "appearance", "subscriptSizing", "placeholder", "suggestFn", "required", "hideRequiredMarker", "mobile", "clearable", "debounceTime", "displaySeparator", "displayWith", "displayAttributes", "displayColumnSizes", "displayColumnNames", "highlightAccent", "showAllOnFocus", "showPanelOnFocus", "reloadItemsOnFocus", "clearInvalidValueOnBlur", "autofocus", "config", "i18nPrefix", "noResultMessage", "panelClass", "panelWidth", "disableRipple", "matAutocompletePosition", "multiple", "fetchMoreThreshold", "suggestLengthThreshold", "showLoadingSpinner", "debug", "showSearchBar", "stickySearchBar", "applyImplicitValue", "dropButtonTitle", "clearButtonTitle", "trimSearchText", "splitSearchText", "selectInputContentOnFocus", "selectInputContentOnFocusDelay", "previewImplicitValue", "showFavorites", "toggleFavoriteTitle", "favoriteItems", "colSizes", "class", "filter", "readonly", "tabindex", "items"], outputs: ["click", "blur", "focus", "dropButtonClick", "keydown.escape", "keydown.backspace", "keyup.enter", "arrowUp", "arrowDown", "enter", "selectionChange", "openedChange", "toggleFavorite"] }, { kind: "component", type: i20.MatBooleanField, selector: "mat-boolean-field", inputs: ["disabled", "formControl", "formControlName", "placeholder", "floatLabel", "appearance", "subscriptSizing", "readonly", "required", "compact", "autofocus", "style", "buttonsColCount", "class", "yesLabel", "noLabel", "showButtonIcons", "yesIcon", "noIcon", "clearable", "labelPosition", "tabindex", "showRadio", "value"], outputs: ["keyup.enter", "focus", "blur"] }, { kind: "directive", type: i21.AutofocusDirective, selector: "[autofocus], input[appAutofocus]", inputs: ["appAutofocus", "autofocusDelay"] }, { kind: "directive", type: i22.AutoTooltipDirective, selector: "ion-label[appAutoTooltip], mat-label[appAutoTooltip]", inputs: ["appAutoTooltip"] }, { kind: "component", type: i23.ToolbarComponent, selector: "app-toolbar", inputs: ["progressBarMode", "title", "color", "class", "id", "backHref", "defaultBackHref", "hasValidate", "hasClose", "hasSearch", "canGoBack", "canShowMenu"], outputs: ["onValidate", "onClose", "onValidateAndClose", "onBackClick", "onSearch"] }, { kind: "component", type: i24.FormButtonsBarComponent, selector: "app-form-buttons-bar", inputs: ["disabled", "disabledCancel", "disabledEscape", "classList", "saveButtonColor", "backText", "cancelText", "nextText", "showBack", "showCancel", "showNext", "showSave"], outputs: ["onCancel", "onSave", "onNext", "onBack", "onSaveAndClose", "onSaveAndNext"] }, { kind: "component", type: i25.ActionsColumnComponent, selector: "app-actions-column", inputs: ["matColumnDef", "style", "showPendingSpinner", "stickyEnd", "canCancel", "canConfirm", "canDelete", "canBackward", "canForward", "canConfirmAndAdd", "dirtyIcon", "optionsTitle", "class", "cellTemplateStart", "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: i26.ResizableComponent, selector: "th[resizable]", inputs: ["resizable"], outputs: ["sizeChanged"] }, { kind: "directive", type: i27.ResizableDirective, selector: "[resizable]", inputs: ["minWidth"], outputs: ["resizable", "fit"] }, { kind: "directive", type: i28.CellIdentifierDirective, selector: "[appCellId]", inputs: ["appCellId"] }, { kind: "directive", type: i29.CellSelectionDirective, selector: "[appCellSelection]", inputs: ["appSelectableColumns"], outputs: ["appCellSelectionChange", "appCellRightClick"] }, { kind: "pipe", type: i3.AsyncPipe, name: "async" }, { kind: "pipe", type: i5.TranslatePipe, name: "translate" }, { kind: "pipe", type: i30.PropertyGetPipe, name: "propertyGet" }, { kind: "pipe", type: i31.NumberFormatPipe, name: "numberFormat" }, { kind: "pipe", type: i32.ArrayLengthPipe, name: "isArrayLength" }, { kind: "pipe", type: i33.FormGetControlPipe, name: "formGetControl" }, { kind: "pipe", type: i33.FormGetValuePipe, name: "formGetValue" }, { kind: "pipe", type: i34.IsSelectedPipe, name: "isSelected" }, { kind: "pipe", type: i34.IsEmptySelectionPipe, name: "isEmptySelection" }, { kind: "pipe", type: i34.IsMultipleSelectionPipe, name: "isMultipleSelection" }, { kind: "pipe", type: i35.IsAllSelectedPipe, name: "isAllSelected" }, { kind: "pipe", type: i35.IsNotAllSelectedPipe, name: "isNotAllSelected" }, { kind: "pipe", type: i36.ReferentialToStringPipe, name: "referentialToString" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
277
280
|
}
|
|
278
281
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: Table2TestPage, decorators: [{
|
|
279
282
|
type: Component,
|
|
@@ -302,7 +305,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
302
305
|
provide: APP_CELL_SELECTION_SERVICE_TOKEN,
|
|
303
306
|
useClass: CellSelectionService,
|
|
304
307
|
},
|
|
305
|
-
], changeDetection: ChangeDetectionStrategy.OnPush, template: "<app-toolbar\n color=\"primary\"\n [canGoBack]=\"true\"\n [hasValidate]=\"(loadingSubject | async) !== true && (dirtySubject | async) === true\"\n (onValidate)=\"save()\"\n [backHref]=\"'/testing'\"\n>\n <ion-title>Table 2 (click to select)</ion-title>\n\n <ion-buttons slot=\"end\">\n @if (selection | isEmptySelection) {\n <input matInput type=\"number\" step=\"1\" style=\"color: black; width: 50px\" [(ngModel)]=\"rowHeight\" />\n\n <!-- Add -->\n <button mat-icon-button *ngIf=\"canEdit && !mobile\" [title]=\"'COMMON.BTN_ADD' | translate\" (click)=\"addRow()\">\n <mat-icon>add</mat-icon>\n </button>\n\n <!-- reset filter -->\n <button mat-icon-button (click)=\"resetFilter()\" *ngIf=\"filterCriteriaCount\">\n <mat-icon color=\"accent\">filter_list_alt</mat-icon>\n <mat-icon class=\"icon-secondary\" style=\"left: 16px; top: 5px; font-weight: bold\">close</mat-icon>\n </button>\n\n <!-- show filter -->\n <button mat-icon-button (click)=\"filterExpansionPanel.toggle()\">\n <mat-icon\n *ngIf=\"filterCriteriaCount; else emptyFilter\"\n [matBadge]=\"filterCriteriaCount\"\n matBadgeColor=\"accent\"\n matBadgeSize=\"small\"\n matBadgePosition=\"above after\"\n aria-hidden=\"false\"\n >\n filter_list_alt\n </mat-icon>\n <ng-template #emptyFilter>\n <mat-icon>filter_list_alt</mat-icon>\n </ng-template>\n </button>\n\n <!-- save -->\n <button mat-icon-button *ngIf=\"mobile\" [disabled]=\"(dirtySubject | async) !== true\" (click)=\"save()\">\n <mat-icon>save</mat-icon>\n </button>\n } @else {\n <!-- if row selection -->\n <!-- delete -->\n <button\n mat-icon-button\n *ngIf=\"canEdit\"\n [title]=\"'COMMON.BTN_DELETE' | translate\"\n (click)=\"deleteSelection($event)\"\n >\n <mat-icon>delete</mat-icon>\n </button>\n\n <!-- duplicate -->\n <button\n mat-icon-button\n *ngIf=\"canEdit && selection.selected | isArrayLength: { equals: 1 }\"\n [title]=\"'COMMON.BTN_DUPLICATE' | translate\"\n (click)=\"duplicateRow($event, selection.selected[0])\"\n >\n <mat-icon>file_copy</mat-icon>\n </button>\n }\n </ion-buttons>\n</app-toolbar>\n<ion-content class=\"ion-no-padding\">\n <ion-refresher slot=\"fixed\" *ngIf=\"mobile\" (ionRefresh)=\"doRefresh($event)\">\n <ion-refresher-content></ion-refresher-content>\n </ion-refresher>\n\n <!-- error -->\n <ion-item *ngIf=\"mobile && error\" lines=\"none\" @slideUpDownAnimation>\n <ion-icon color=\"danger\" slot=\"start\" name=\"alert-circle\"></ion-icon>\n <ion-label color=\"danger\" class=\"error\" [innerHTML]=\"error | translate\"></ion-label>\n </ion-item>\n\n <!-- search -->\n <mat-expansion-panel\n #filterExpansionPanel\n class=\"filter-panel\"\n [class.filter-panel-floating]=\"filterPanelFloating\"\n [class.filter-panel-pinned]=\"!filterPanelFloating\"\n >\n <form class=\"form-container ion-padding-top\" [formGroup]=\"filterForm\" (ngSubmit)=\"applyFilterAndClosePanel($event)\">\n <ion-grid>\n <ion-row>\n <ion-col>\n <!-- search text -->\n <mat-form-field>\n <mat-label>{{ 'TABLE.TESTING.SEARCH_TEXT' | translate }}</mat-label>\n <ion-icon matPrefix name=\"search\"></ion-icon>\n <input matInput formControlName=\"searchText\" autocomplete=\"off\" />\n <button\n mat-icon-button\n matSuffix\n tabindex=\"-1\"\n type=\"button\"\n (click)=\"clearControlValue($event, filterForm.controls.searchText)\"\n [hidden]=\"filterForm.controls.searchText.disabled || !filterForm.controls.searchText.value\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n </ion-col>\n </ion-row>\n </ion-grid>\n </form>\n\n <mat-action-row>\n <!-- Counter -->\n <ion-label\n [hidden]=\"(loadingSubject | async) || filterForm.dirty\"\n [color]=\"empty && 'danger'\"\n class=\"ion-padding\"\n >\n {{\n (totalRowCount ? 'COMMON.RESULT_COUNT' : 'COMMON.NO_RESULT')\n | translate\n : {\n count: (totalRowCount | numberFormat),\n }\n }}\n </ion-label>\n\n <div class=\"toolbar-spacer\"></div>\n\n <button\n mat-icon-button\n color=\"accent\"\n *ngIf=\"filterPanelFloating\"\n (click)=\"toggleFilterPanelFloating()\"\n class=\"hidden-xs hidden-sm hidden-md\"\n [title]=\"(filterPanelFloating ? 'COMMON.BTN_EXPAND' : 'COMMON.BTN_HIDE') | translate\"\n >\n <mat-icon>\n <span style=\"transform: rotate(90deg)\">{{ filterPanelFloating ? '»' : '«' }}</span>\n </mat-icon>\n </button>\n\n <!-- Close panel -->\n <ion-button mat-button fill=\"clear\" color=\"dark\" (click)=\"closeFilterPanel()\" [disabled]=\"loadingSubject | async\">\n <ion-text translate>COMMON.BTN_CLOSE</ion-text>\n </ion-button>\n\n <!-- Search button -->\n <ion-button\n mat-button\n [color]=\"filterForm.dirty ? 'tertiary' : 'dark'\"\n [fill]=\"filterForm.dirty ? 'solid' : 'clear'\"\n (click)=\"applyFilterAndClosePanel($event)\"\n >\n <ion-text translate>COMMON.BTN_APPLY</ion-text>\n </ion-button>\n </mat-action-row>\n </mat-expansion-panel>\n\n <!-- table -->\n <div [class.table-container]=\"!enableInfiniteScroll\" style=\"position: relative\">\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 appCellSelection\n [appSelectableColumns]=\"selectableColumns\"\n (appCellSelectionChange)=\"onCellSelectionChange($event)\"\n (appCellRightClick)=\"onCellRightClick($event)\"\n >\n <ng-container matColumnDef=\"select\" [sticky]=\"checkBoxSelection\" [class.mat-column-sticky]=\"checkBoxSelection\">\n <th mat-header-cell *matHeaderCellDef [class.cdk-visually-hidden]=\"!checkBoxSelection\">\n @if (selection | isMultipleSelection) {\n <mat-checkbox\n [checked]=\"this | isAllSelected\"\n [indeterminate]=\"this | isNotAllSelected\"\n (change)=\"$event ? masterToggle() : null\"\n ></mat-checkbox>\n }\n </th>\n <td mat-cell *matCellDef=\"let row\" [class.cdk-visually-hidden]=\"!checkBoxSelection\">\n <mat-checkbox [checked]=\"selection | isSelected: row\" (click)=\"toggleSelectRow($event, row)\"></mat-checkbox>\n </td>\n </ng-container>\n\n <!-- Id column -->\n <ng-container matColumnDef=\"id\" [sticky]=\"sticky\">\n <th mat-header-cell *matHeaderCellDef>\n <span mat-sort-header>\n <ion-label title=\"Id\">#</ion-label>\n <ion-label color=\"danger\" [innerHTML]=\"' *'\"></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]=\"' *'\"></ion-label>\n </span>\n </th>\n <td\n mat-cell\n *matCellDef=\"let row\"\n (click)=\"focusColumn = 'name'\"\n [appCellId]=\"{ rowId: row.id, columnName: 'name' }\"\n >\n <mat-form-field *ngIf=\"!readOnly && row.editing; else readOnlyTemplate\">\n <input\n matInput\n autocomplete=\"off\"\n [required]=\"true\"\n [formControl]=\"row.validator | formGetControl: 'name'\"\n [placeholder]=\"'TABLE.TESTING.NAME' | translate\"\n [appAutofocus]=\"row.id === -1 || focusColumn === 'name'\"\n />\n <ng-content select=\"[suffix]\"></ng-content>\n <mat-error *ngIf=\"(row.validator | formGetControl: 'name').hasError('required')\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n <mat-error *ngIf=\"(row.validator | formGetControl: 'name').hasError('maxlength')\" translate>\n ERROR.FIELD_MAX_LENGTH_COMPACT\n </mat-error>\n <mat-error *ngIf=\"(row.validator | formGetControl: 'name').hasError('minlength')\" translate>\n ERROR.FIELD_MIN_LENGTH_COMPACT\n </mat-error>\n </mat-form-field>\n <ng-template #readOnlyTemplate>\n <ion-label appAutoTitle>\n {{ (row.validator | formGetValue: 'name') || (row.currentData | propertyGet: 'name') }}\n </ion-label>\n </ng-template>\n </td>\n </ng-container>\n\n <!-- Level column -->\n <ng-container matColumnDef=\"levelId\">\n <th mat-header-cell *matHeaderCellDef [resizable]=\"resizable\">\n <span mat-sort-header>\n <ion-label>{{ 'TABLE.TESTING.LEVEL_ID' | translate }}</ion-label>\n <ion-label color=\"danger\" [innerHTML]=\"' *'\"></ion-label>\n </span>\n </th>\n <td mat-cell *matCellDef=\"let row\" [appCellId]=\"{ rowId: row.id, columnName: 'levelId' }\">\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\" [appCellId]=\"{ rowId: row.id, columnName: 'boolean' }\">\n <mat-boolean-field\n *ngIf=\"!readOnly && row.editing; else readOnlyTemplate\"\n floatLabel=\"never\"\n [style]=\"'checkbox'\"\n [formControl]=\"\n (row.validator | formGetControl: 'boolean') || formBuilder.control(row.currentData['boolean'])\n \"\n [compact]=\"true\"\n ></mat-boolean-field>\n <ng-template #readOnlyTemplate>\n <ion-label appAutoTitle>\n {{\n (row.validator | formGetValue: 'boolean') || (row.currentData | propertyGet: 'boolean')\n ? ('COMMON.YES' | translate)\n : ('COMMON.NO' | translate)\n }}\n </ion-label>\n </ng-template>\n </td>\n </ng-container>\n\n <ng-container matColumnDef=\"boolean2\">\n <th mat-header-cell *matHeaderCellDef cdkDrag [resizable]=\"resizable\">\n <!-- if sortable, wrap the header with a mat-sort-header -->\n <span mat-sort-header>\n <ion-label>Boolean 2</ion-label>\n </span>\n </th>\n <td mat-cell *matCellDef=\"let row\">\n <mat-boolean-field\n *ngIf=\"!readOnly && row.editing; else readOnlyTemplate\"\n [floatLabel]=\"'never'\"\n [style]=\"'radio'\"\n [showRadio]=\"true\"\n [formControl]=\"\n (row.validator | formGetControl: 'boolean2') || formBuilder.control(row.currentData['boolean2'])\n \"\n ></mat-boolean-field>\n <ng-template #readOnlyTemplate>\n <ion-label appAutoTitle>\n {{\n (row.validator | formGetValue: 'boolean2') || (row.currentData | propertyGet: 'boolean2')\n ? ('COMMON.YES' | translate)\n : ('COMMON.NO' | translate)\n }}\n </ion-label>\n </ng-template>\n </td>\n </ng-container>\n\n <ng-container matColumnDef=\"boolean3\">\n <th mat-header-cell *matHeaderCellDef cdkDrag [resizable]=\"resizable\">\n <!-- if sortable, wrap the header with a mat-sort-header -->\n <span mat-sort-header>\n <ion-label>Boolean 3</ion-label>\n </span>\n </th>\n <td mat-cell *matCellDef=\"let row\">\n <mat-boolean-field\n *ngIf=\"!readOnly && row.editing; else readOnlyTemplate\"\n floatLabel=\"never\"\n [style]=\"'button'\"\n [formControl]=\"\n (row.validator | formGetControl: 'boolean2') || formBuilder.control(row.currentData['boolean2'])\n \"\n ></mat-boolean-field>\n <ng-template #readOnlyTemplate>\n <ion-label appAutoTitle>\n {{\n (row.validator | formGetValue: 'boolean2') || (row.currentData | propertyGet: 'boolean2')\n ? ('COMMON.YES' | translate)\n : ('COMMON.NO' | translate)\n }}\n </ion-label>\n </ng-template>\n </td>\n </ng-container>\n\n <!-- Actions buttons column -->\n <app-actions-column\n [stickyEnd]=\"stickyEnd\"\n [canCancel]=\"false\"\n [style]=\"'table'\"\n (optionsClick)=\"openSelectColumnsModal($event)\"\n (cancelOrDeleteClick)=\"cancelOrDelete($event.event, $event.row)\"\n (confirmAndAddClick)=\"confirmAndAdd($event.event, $event.row)\"\n (backward)=\"confirmAndBackward($event.event, $event.row)\"\n (forward)=\"confirmAndForward($event.event, $event.row)\"\n [cellTemplate]=\"cellInjection\"\n >\n <!-- cell injection-->\n <ng-template #cellInjection let-row>\n <span *ngIf=\"row.editing && !row.validator.dirty\">-</span>\n </ng-template>\n </app-actions-column>\n\n <tr mat-header-row *matHeaderRowDef=\"displayedColumns; sticky: true\"></tr>\n <tr\n mat-row\n *matRowDef=\"let row; columns: displayedColumns\"\n [class.mat-row-selected]=\"row.editing\"\n [class.mat-row-error]=\"row.invalid\"\n [class.mat-row-disabled]=\"!row.editing\"\n [class.mat-row-dirty]=\"row.dirty\"\n (click)=\"clickRow($event, row)\"\n (keydown.escape)=\"escapeEditingRow($event)\"\n [cdkTrapFocus]=\"row.invalid\"\n ></tr>\n </table>\n\n <ng-container *ngIf=\"loadingSubject | async; else noResult\">\n <ion-item>\n <ion-skeleton-text animated></ion-skeleton-text>\n </ion-item>\n </ng-container>\n\n <ng-template #noResult>\n <ion-item *ngIf=\"totalRowCount === 0\">\n <ion-text color=\"danger\" class=\"text-italic\" translate>COMMON.NO_RESULT</ion-text>\n </ion-item>\n </ng-template>\n\n <ion-infinite-scroll\n *ngIf=\"enableInfiniteScroll\"\n [threshold]=\"mobile ? '10%' : '2%'\"\n position=\"bottom\"\n (ionInfinite)=\"fetchMore($event)\"\n >\n <ion-infinite-scroll-content\n loadingSpinner=\"circles\"\n [loadingText]=\"'COMMON.LOADING_DOTS' | translate\"\n ></ion-infinite-scroll-content>\n </ion-infinite-scroll>\n </div>\n</ion-content>\n\n<ion-footer>\n <!-- Paginator -->\n <mat-paginator\n *ngIf=\"!enableInfiniteScroll\"\n [length]=\"totalRowCount\"\n [pageSize]=\"defaultPageSize\"\n [pageSizeOptions]=\"defaultPageSizeOptions\"\n showFirstLastButtons\n ></mat-paginator>\n\n <app-form-buttons-bar\n *ngIf=\"canEdit && !mobile\"\n (onCancel)=\"load()\"\n (onSave)=\"save()\"\n [disabled]=\"(loadingSubject | async) || !dirty\"\n >\n <!-- error -->\n <ion-item *ngIf=\"errorSubject | 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"] }]
|
|
308
|
+
], changeDetection: ChangeDetectionStrategy.OnPush, template: "<app-toolbar\n color=\"primary\"\n [canGoBack]=\"true\"\n [hasValidate]=\"(loadingSubject | async) !== true && (dirtySubject | async) === true\"\n (onValidate)=\"save()\"\n [backHref]=\"'/testing'\"\n>\n <ion-title>Table 2 (click to select)</ion-title>\n\n <ion-buttons slot=\"end\">\n @if (selection | isEmptySelection) {\n <input matInput type=\"number\" step=\"1\" style=\"color: black; width: 50px\" [(ngModel)]=\"rowHeight\" />\n\n <!-- Add -->\n <button\n mat-icon-button\n *ngIf=\"canEdit && !mobile\"\n [title]=\"!showTooltip ? ('COMMON.BTN_ADD' | translate) : ''\"\n [matTooltip]=\"showTooltip ? ('COMMON.BTN_ADD' | translate) : ''\"\n (click)=\"addRow()\"\n >\n <mat-icon>add</mat-icon>\n </button>\n\n <!-- reset filter -->\n <button mat-icon-button (click)=\"resetFilter()\" *ngIf=\"filterCriteriaCount\">\n <mat-icon color=\"accent\">filter_list_alt</mat-icon>\n <mat-icon class=\"icon-secondary\" style=\"left: 16px; top: 5px; font-weight: bold\">close</mat-icon>\n </button>\n\n <!-- show filter -->\n <button mat-icon-button (click)=\"filterExpansionPanel.toggle()\">\n <mat-icon\n *ngIf=\"filterCriteriaCount; else emptyFilter\"\n [matBadge]=\"filterCriteriaCount\"\n matBadgeColor=\"accent\"\n matBadgeSize=\"small\"\n matBadgePosition=\"above after\"\n aria-hidden=\"false\"\n >\n filter_list_alt\n </mat-icon>\n <ng-template #emptyFilter>\n <mat-icon>filter_list_alt</mat-icon>\n </ng-template>\n </button>\n\n <!-- save -->\n <button mat-icon-button *ngIf=\"mobile\" [disabled]=\"(dirtySubject | async) !== true\" (click)=\"save()\">\n <mat-icon>save</mat-icon>\n </button>\n } @else {\n <!-- if row selection -->\n <!-- delete -->\n <button\n mat-icon-button\n *ngIf=\"canEdit\"\n [title]=\"!showTooltip ? ('COMMON.BTN_DELETE' | translate) : ''\"\n [matTooltip]=\"showTooltip ? ('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]=\"!showTooltip ? ('COMMON.BTN_DUPLICATE' | translate) : ''\"\n [matTooltip]=\"showTooltip ? ('COMMON.BTN_DUPLICATE' | translate) : ''\"\n (click)=\"duplicateRow($event, selection.selected[0])\"\n >\n <mat-icon>file_copy</mat-icon>\n </button>\n }\n </ion-buttons>\n</app-toolbar>\n<ion-content class=\"ion-no-padding\">\n <ion-refresher slot=\"fixed\" *ngIf=\"mobile\" (ionRefresh)=\"doRefresh($event)\">\n <ion-refresher-content></ion-refresher-content>\n </ion-refresher>\n\n <!-- error -->\n <ion-item *ngIf=\"mobile && error\" lines=\"none\" @slideUpDownAnimation>\n <ion-icon color=\"danger\" slot=\"start\" name=\"alert-circle\"></ion-icon>\n <ion-label color=\"danger\" class=\"error\" [innerHTML]=\"error | translate\"></ion-label>\n </ion-item>\n\n <!-- search -->\n <mat-expansion-panel\n #filterExpansionPanel\n class=\"filter-panel\"\n [class.filter-panel-floating]=\"filterPanelFloating\"\n [class.filter-panel-pinned]=\"!filterPanelFloating\"\n >\n <form class=\"form-container ion-padding-top\" [formGroup]=\"filterForm\" (ngSubmit)=\"applyFilterAndClosePanel($event)\">\n <ion-grid>\n <ion-row>\n <ion-col>\n <!-- search text -->\n <mat-form-field>\n <mat-label>{{ 'TABLE.TESTING.SEARCH_TEXT' | translate }}</mat-label>\n <ion-icon matPrefix name=\"search\"></ion-icon>\n <input matInput formControlName=\"searchText\" autocomplete=\"off\" />\n <button\n mat-icon-button\n matSuffix\n tabindex=\"-1\"\n type=\"button\"\n (click)=\"clearControlValue($event, filterForm.controls.searchText)\"\n [hidden]=\"filterForm.controls.searchText.disabled || !filterForm.controls.searchText.value\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n </ion-col>\n </ion-row>\n </ion-grid>\n </form>\n\n <mat-action-row>\n <!-- Counter -->\n <ion-label\n [hidden]=\"(loadingSubject | async) || filterForm.dirty\"\n [color]=\"empty && 'danger'\"\n class=\"ion-padding\"\n >\n {{\n (totalRowCount ? 'COMMON.RESULT_COUNT' : 'COMMON.NO_RESULT')\n | translate\n : {\n count: (totalRowCount | numberFormat),\n }\n }}\n </ion-label>\n\n <div class=\"toolbar-spacer\"></div>\n\n <button\n mat-icon-button\n color=\"accent\"\n *ngIf=\"filterPanelFloating\"\n (click)=\"toggleFilterPanelFloating()\"\n class=\"hidden-xs hidden-sm hidden-md\"\n [title]=\"!showTooltip ? ((filterPanelFloating ? 'COMMON.BTN_EXPAND' : 'COMMON.BTN_HIDE') | translate) : ''\"\n [matTooltip]=\"showTooltip ? ((filterPanelFloating ? 'COMMON.BTN_EXPAND' : 'COMMON.BTN_HIDE') | translate) : ''\"\n >\n <mat-icon>\n <span style=\"transform: rotate(90deg)\">{{ filterPanelFloating ? '»' : '«' }}</span>\n </mat-icon>\n </button>\n\n <!-- Close panel -->\n <ion-button mat-button fill=\"clear\" color=\"dark\" (click)=\"closeFilterPanel()\" [disabled]=\"loadingSubject | async\">\n <ion-text translate>COMMON.BTN_CLOSE</ion-text>\n </ion-button>\n\n <!-- Search button -->\n <ion-button\n mat-button\n [color]=\"filterForm.dirty ? 'tertiary' : 'dark'\"\n [fill]=\"filterForm.dirty ? 'solid' : 'clear'\"\n (click)=\"applyFilterAndClosePanel($event)\"\n >\n <ion-text translate>COMMON.BTN_APPLY</ion-text>\n </ion-button>\n </mat-action-row>\n </mat-expansion-panel>\n\n <!-- table -->\n <div [class.table-container]=\"!enableInfiniteScroll\" style=\"position: relative\">\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 appCellSelection\n [appSelectableColumns]=\"selectableColumns\"\n (appCellSelectionChange)=\"onCellSelectionChange($event)\"\n (appCellRightClick)=\"onCellRightClick($event)\"\n >\n <ng-container matColumnDef=\"select\" [sticky]=\"checkBoxSelection\" [class.mat-column-sticky]=\"checkBoxSelection\">\n <th mat-header-cell *matHeaderCellDef [class.cdk-visually-hidden]=\"!checkBoxSelection\">\n @if (selection | isMultipleSelection) {\n <mat-checkbox\n [checked]=\"this | isAllSelected\"\n [indeterminate]=\"this | isNotAllSelected\"\n (change)=\"$event ? masterToggle() : null\"\n ></mat-checkbox>\n }\n </th>\n <td mat-cell *matCellDef=\"let row\" [class.cdk-visually-hidden]=\"!checkBoxSelection\">\n <mat-checkbox [checked]=\"selection | isSelected: row\" (click)=\"toggleSelectRow($event, row)\"></mat-checkbox>\n </td>\n </ng-container>\n\n <!-- Id column -->\n <ng-container matColumnDef=\"id\" [sticky]=\"sticky\">\n <th mat-header-cell *matHeaderCellDef>\n <span mat-sort-header>\n <ion-label title=\"Id\">#</ion-label>\n <ion-label color=\"danger\" [innerHTML]=\"' *'\"></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 appAutoTooltip>\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\n [title]=\"!showTooltip ? ('TABLE.TESTING.NAME' | translate) : ''\"\n [matTooltip]=\"showTooltip ? ('TABLE.TESTING.NAME' | translate) : ''\"\n >\n {{ 'TABLE.TESTING.NAME' | translate }}\n </ion-label>\n <ion-label color=\"danger\" [innerHTML]=\"' *'\"></ion-label>\n </span>\n </th>\n <td\n mat-cell\n *matCellDef=\"let row\"\n (click)=\"focusColumn = 'name'\"\n [appCellId]=\"{ rowId: row.id, columnName: 'name' }\"\n >\n <mat-form-field *ngIf=\"!readOnly && row.editing; else readOnlyTemplate\">\n <input\n matInput\n autocomplete=\"off\"\n [required]=\"true\"\n [formControl]=\"row.validator | formGetControl: 'name'\"\n [placeholder]=\"'TABLE.TESTING.NAME' | translate\"\n [appAutofocus]=\"row.id === -1 || focusColumn === 'name'\"\n />\n <ng-content select=\"[suffix]\"></ng-content>\n <mat-error *ngIf=\"(row.validator | formGetControl: 'name').hasError('required')\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n <mat-error *ngIf=\"(row.validator | formGetControl: 'name').hasError('maxlength')\" translate>\n ERROR.FIELD_MAX_LENGTH_COMPACT\n </mat-error>\n <mat-error *ngIf=\"(row.validator | formGetControl: 'name').hasError('minlength')\" translate>\n ERROR.FIELD_MIN_LENGTH_COMPACT\n </mat-error>\n </mat-form-field>\n <ng-template #readOnlyTemplate>\n <ion-label appAutoTooltip>\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]=\"' *'\"></ion-label>\n </span>\n </th>\n <td mat-cell *matCellDef=\"let row\" [appCellId]=\"{ rowId: row.id, columnName: 'levelId' }\">\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 appAutoTooltip>\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\" [appCellId]=\"{ rowId: row.id, columnName: 'boolean' }\">\n <mat-boolean-field\n *ngIf=\"!readOnly && row.editing; else readOnlyTemplate\"\n floatLabel=\"never\"\n [style]=\"'checkbox'\"\n [formControl]=\"\n (row.validator | formGetControl: 'boolean') || formBuilder.control(row.currentData['boolean'])\n \"\n [compact]=\"true\"\n ></mat-boolean-field>\n <ng-template #readOnlyTemplate>\n <ion-label appAutoTooltip>\n {{\n (row.validator | formGetValue: 'boolean') || (row.currentData | propertyGet: 'boolean')\n ? ('COMMON.YES' | translate)\n : ('COMMON.NO' | translate)\n }}\n </ion-label>\n </ng-template>\n </td>\n </ng-container>\n\n <ng-container matColumnDef=\"boolean2\">\n <th mat-header-cell *matHeaderCellDef cdkDrag [resizable]=\"resizable\">\n <!-- if sortable, wrap the header with a mat-sort-header -->\n <span mat-sort-header>\n <ion-label>Boolean 2</ion-label>\n </span>\n </th>\n <td mat-cell *matCellDef=\"let row\">\n <mat-boolean-field\n *ngIf=\"!readOnly && row.editing; else readOnlyTemplate\"\n [floatLabel]=\"'never'\"\n [style]=\"'radio'\"\n [showRadio]=\"true\"\n [formControl]=\"\n (row.validator | formGetControl: 'boolean2') || formBuilder.control(row.currentData['boolean2'])\n \"\n ></mat-boolean-field>\n <ng-template #readOnlyTemplate>\n <ion-label appAutoTooltip>\n {{\n (row.validator | formGetValue: 'boolean2') || (row.currentData | propertyGet: 'boolean2')\n ? ('COMMON.YES' | translate)\n : ('COMMON.NO' | translate)\n }}\n </ion-label>\n </ng-template>\n </td>\n </ng-container>\n\n <ng-container matColumnDef=\"boolean3\">\n <th mat-header-cell *matHeaderCellDef cdkDrag [resizable]=\"resizable\">\n <!-- if sortable, wrap the header with a mat-sort-header -->\n <span mat-sort-header>\n <ion-label>Boolean 3</ion-label>\n </span>\n </th>\n <td mat-cell *matCellDef=\"let row\">\n <mat-boolean-field\n *ngIf=\"!readOnly && row.editing; else readOnlyTemplate\"\n floatLabel=\"never\"\n [style]=\"'button'\"\n [formControl]=\"\n (row.validator | formGetControl: 'boolean2') || formBuilder.control(row.currentData['boolean2'])\n \"\n ></mat-boolean-field>\n <ng-template #readOnlyTemplate>\n <ion-label appAutoTooltip>\n {{\n (row.validator | formGetValue: 'boolean2') || (row.currentData | propertyGet: 'boolean2')\n ? ('COMMON.YES' | translate)\n : ('COMMON.NO' | translate)\n }}\n </ion-label>\n </ng-template>\n </td>\n </ng-container>\n\n <!-- Actions buttons column -->\n <app-actions-column\n [stickyEnd]=\"stickyEnd\"\n [canCancel]=\"false\"\n [style]=\"'table'\"\n (optionsClick)=\"openSelectColumnsModal($event)\"\n (cancelOrDeleteClick)=\"cancelOrDelete($event.event, $event.row)\"\n (confirmAndAddClick)=\"confirmAndAdd($event.event, $event.row)\"\n (backward)=\"confirmAndBackward($event.event, $event.row)\"\n (forward)=\"confirmAndForward($event.event, $event.row)\"\n [cellTemplate]=\"cellInjection\"\n >\n <!-- cell injection-->\n <ng-template #cellInjection let-row>\n <span *ngIf=\"row.editing && !row.validator.dirty\">-</span>\n </ng-template>\n </app-actions-column>\n\n <tr mat-header-row *matHeaderRowDef=\"displayedColumns; sticky: true\"></tr>\n <tr\n mat-row\n *matRowDef=\"let row; columns: displayedColumns\"\n [class.mat-row-selected]=\"row.editing\"\n [class.mat-row-error]=\"row.invalid\"\n [class.mat-row-disabled]=\"!row.editing\"\n [class.mat-row-dirty]=\"row.dirty\"\n (click)=\"clickRow($event, row)\"\n (keydown.escape)=\"escapeEditingRow($event)\"\n [cdkTrapFocus]=\"row.invalid\"\n ></tr>\n </table>\n\n <ng-container *ngIf=\"loadingSubject | async; else noResult\">\n <ion-item>\n <ion-skeleton-text animated></ion-skeleton-text>\n </ion-item>\n </ng-container>\n\n <ng-template #noResult>\n <ion-item *ngIf=\"totalRowCount === 0\">\n <ion-text color=\"danger\" class=\"text-italic\" translate>COMMON.NO_RESULT</ion-text>\n </ion-item>\n </ng-template>\n\n <ion-infinite-scroll\n *ngIf=\"enableInfiniteScroll\"\n [threshold]=\"mobile ? '10%' : '2%'\"\n position=\"bottom\"\n (ionInfinite)=\"fetchMore($event)\"\n >\n <ion-infinite-scroll-content\n loadingSpinner=\"circles\"\n [loadingText]=\"'COMMON.LOADING_DOTS' | translate\"\n ></ion-infinite-scroll-content>\n </ion-infinite-scroll>\n </div>\n</ion-content>\n\n<ion-footer>\n <!-- Paginator -->\n <mat-paginator\n *ngIf=\"!enableInfiniteScroll\"\n [length]=\"totalRowCount\"\n [pageSize]=\"defaultPageSize\"\n [pageSizeOptions]=\"defaultPageSizeOptions\"\n showFirstLastButtons\n ></mat-paginator>\n\n <app-form-buttons-bar\n *ngIf=\"canEdit && !mobile\"\n (onCancel)=\"load()\"\n (onSave)=\"save()\"\n [disabled]=\"(loadingSubject | async) || !dirty\"\n >\n <!-- error -->\n <ion-item *ngIf=\"errorSubject | 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"] }]
|
|
306
309
|
}], ctorParameters: () => [{ type: i0.Injector }, { type: i1.AppValidatorService }, { type: i2.UntypedFormBuilder }], propDecorators: { filterPanelFloating: [{
|
|
307
310
|
type: Input
|
|
308
311
|
}], sticky: [{
|
|
@@ -316,4 +319,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
316
319
|
type: ViewChild,
|
|
317
320
|
args: [IonInfiniteScroll]
|
|
318
321
|
}] } });
|
|
319
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGFibGUyLnRlc3RpbmcuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBwL2NvcmUvdGFibGUvdGVzdGluZy90YWJsZTIudGVzdGluZy50cyIsIi4uLy4uLy4uLy4uLy4uLy4uLy4uL3NyYy9hcHAvY29yZS90YWJsZS90ZXN0aW5nL3RhYmxlMi50ZXN0aW5nLmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFpQix1QkFBdUIsRUFBRSxTQUFTLEVBQUUsVUFBVSxFQUFZLEtBQUssRUFBcUIsU0FBUyxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQzdJLE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUMxQyxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sd0NBQXdDLENBQUM7QUFDckUsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDbkQsT0FBTyxFQUFFLHVCQUF1QixFQUFFLE1BQU0sc0RBQXNELENBQUM7QUFDL0YsT0FBTyxFQUFFLG1CQUFtQixFQUFFLE1BQU0sK0NBQStDLENBQUM7QUFFcEYsT0FBTyxFQUFFLEtBQUssRUFBRSxNQUFNLDJCQUEyQixDQUFDO0FBQ2xELE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLGlEQUFpRCxDQUFDO0FBQ3BGLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxFQUFFLEdBQUcsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQzNELE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLDZCQUE2QixDQUFDO0FBQ2hFLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxvQkFBb0IsRUFBRSxzQkFBc0IsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQ2pHLE9BQU8sRUFBRSxzQkFBc0IsRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBQ3BFLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQztBQUM1RCxPQUFPLEVB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akIsV0FBVyxFQUFFLFVBQVUsQ0FBQyxHQUFHLEVBQUUsZUFBZSxDQUFDO3lCQUM5Qzt3QkFDRCxvQkFBb0I7d0JBQ3BCLElBQUk7d0JBQ0osc0RBQXNEO3dCQUN0RCx3QkFBd0I7d0JBQ3hCLG9EQUFvRDt3QkFDcEQsb0NBQW9DO3dCQUNwQyw0RUFBNEU7d0JBQzVFLDJGQUEyRjt3QkFDM0YsV0FBVzt3QkFDWCxTQUFTO3dCQUNULE9BQU87d0JBQ1AsS0FBSzt3QkFDTDs0QkFDRSxPQUFPLEVBQUUsZ0NBQWdDOzRCQUN6QyxRQUFRLEVBQUUsb0JBQW9CO3lCQUMvQjtxQkFDRixtQkFDZ0IsdUJBQXVCLENBQUMsTUFBTTtnSkFjdEMsbUJBQW1CO3NCQUEzQixLQUFLO2dCQUNHLE1BQU07c0JBQWQsS0FBSztnQkFDRyxTQUFTO3NCQUFqQixLQUFLO2dCQU0wQyxvQkFBb0I7c0JBQW5FLFNBQVM7dUJBQUMsaUJBQWlCLEVBQUUsRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFO2dCQUNoQixjQUFjO3NCQUEzQyxTQUFTO3VCQUFDLGlCQUFpQiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEFmdGVyVmlld0luaXQsIENoYW5nZURldGVjdGlvblN0cmF0ZWd5LCBDb21wb25lbnQsIGZvcndhcmRSZWYsIEluamVjdG9yLCBJbnB1dCwgT25EZXN0cm95LCBPbkluaXQsIFZpZXdDaGlsZCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgQXBwVGFibGUgfSBmcm9tICcuLi90YWJsZS5jbGFzcyc7XG5pbXBvcnQgeyBSZWZlcmVudGlhbCB9IGZyb20gJy4uLy4uL3NlcnZpY2VzL21vZGVsL3JlZmVyZW50aWFsLm1vZGVsJztcbmltcG9ydCB7IElvbkluZmluaXRlU2Nyb2xsIH0gZnJvbSAnQGlvbmljL2FuZ3VsYXInO1xuaW1wb3J0IHsgSW5NZW1vcnlFbnRpdGllc1NlcnZpY2UgfSBmcm9tICcuLi8uLi8uLi9zaGFyZWQvc2VydmljZXMvbWVtb3J5LWVudGl0eS1zZXJ2aWNlLmNsYXNzJztcbmltcG9ydCB7IEFwcFZhbGlkYXRvclNlcnZpY2UgfSBmcm9tICcuLi8uLi9zZXJ2aWNlcy92YWxpZGF0b3IvYmFzZS52YWxpZGF0b3IuY2xhc3MnO1xuaW1wb3J0IHsgQWJzdHJhY3RDb250cm9sLCBVbnR5cGVkRm9ybUJ1aWxkZXIsIFVudHlwZWRGb3JtR3JvdXAgfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XG5pbXBvcnQgeyBpc05pbCB9IGZyb20gJy4uLy4uLy4uL3NoYXJlZC9mdW5jdGlvbnMnO1xuaW1wb3J0IHsgUmVmZXJlbnRpYWxGaWx0ZXIgfSBmcm9tICcuLi8uLi9zZXJ2aWNlcy90ZXN0aW5nL3JlZmVyZW50aWFsLWZpbHRlci5tb2RlbCc7XG5pbXBvcnQgeyBkZWJvdW5jZVRpbWUsIGZpbHRlciwgdGFwIH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuaW1wb3J0IHsgTWF0RXhwYW5zaW9uUGFuZWwgfSBmcm9tICdAYW5ndWxhci9tYXRlcmlhbC9leHBhbnNpb24nO1xuaW1wb3J0IHsgREVGQVVMVF9QQUdFX1NJWkUsIFJFU0VSVkVEX0VORF9DT0xVTU5TLCBSRVNFUlZFRF9TVEFSVF9DT0xVTU5TIH0gZnJvbSAnLi4vdGFibGUubW9kZWwnO1xuaW1wb3J0IHsgVGFibGUyVmFsaWRhdG9yU2VydmljZSB9IGZyb20gJy4vdGFibGUyLXZhbGlkYXRvci5zZXJ2aWNlJztcbmltcG9ydCB7IFN0YXR1c0lkcyB9IGZyb20gJy4uLy4uL3NlcnZpY2VzL21vZGVsL21vZGVsLmVudW0nO1xuaW1wb3J0IHsgQXBwQXN5bmNUYWJsZSB9IGZyb20gJy4uL2FzeW5jLXRhYmxlLmNsYXNzJztcbmltcG9ydCB7IEVudGl0aWVzQXN5bmNUYWJsZURhdGFTb3VyY2UgfSBmcm9tICcuLi9lbnRpdGllcy1hc3luYy10YWJsZS1kYXRhc291cmNlLmNsYXNzJztcbmltcG9ydCB7XG4gIEFQUF9DRUxMX1NFTEVDVElPTl9TRVJWSUNFX1RPS0VOLFxuICBDZWxsU2VsZWN0aW9uRXZlbnQsXG4gIENlbGxTZWxlY3Rpb25TZXJ2aWNlLFxuICBJQ2VsbElkLFxufSBmcm9tICcuLi8uLi8uLi9zaGFyZWQvZGlyZWN0aXZlcy9jZWxsLXNlbGVjdGlvbi9jZWxsLXNlbGVjdGlvbi5zZXJ2aWNlJztcblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnYXBwLXRhYmxlMi10ZXN0aW5nJyxcbiAgc3R5bGVVcmxzOiBbJ3RhYmxlMi50ZXN0aW5nLnNjc3MnXSxcbiAgdGVtcGxhdGVVcmw6ICd0YWJsZTIudGVzdGluZy5odG1sJyxcbiAgcHJvdmlkZXJzOiBbXG4gICAge1xuICAgICAgcHJvdmlkZTogQXBwVmFsaWRhdG9yU2VydmljZSxcbiAgICAgIHVzZUNsYXNzOiBUYWJsZTJWYWxpZGF0b3JTZXJ2aWNlLFxuICAgIH0sXG4gICAge1xuICAgICAgcHJvdmlkZTogQXBwVGFibGUsXG4gICAgICB1c2VFeGlzdGluZzogZm9yd2FyZFJlZigoKSA9PiBUYWJsZTJUZXN0UGFnZSksXG4gICAgfSxcbiAgICAvLyBQcm92aWRlIG9wdGlvbnMgOlxuICAgIC8vIHtcbiAgICAvLyAgIHByb3ZpZGU6IEFQUF9DRUxMX1NFTEVDVElPTl9TRVJWSUNFX0NPTkZJR19UT0tFTixcbiAgICAvLyAgIHVzZUZhY3Rvcnk6ICgpID0+IHtcbiAgICAvLyAgICAgcmV0dXJuIDxDZWxsU2VsZWN0aW9uU2VydmljZUNvbmZpZzxJQ2VsbElkPj57XG4gICAgLy8gICAgICAgZXF1YWxzOiAoY2VsbDEsIGNlbGwyKSA9PiB7XG4gICAgLy8gICAgICAgICBjb25zb2xlLmRlYnVnKCdbdGFibGUyLXRlc3RdIENvbXBhcmluZyBjZWxsIGlkczonLCBjZWxsMSwgY2VsbDIpO1xuICAgIC8vICAgICAgICAgcmV0dXJuIGNlbGwxPy5yb3dJZCA9PT0gY2VsbDI/LnJvd0lkICYmIGNlbGwxPy5jb2x1bW5OYW1lID09PSBjZWxsMj8uY29sdW1uTmFtZTtcbiAgICAvLyAgICAgICB9LFxuICAgIC8vICAgICB9O1xuICAgIC8vICAgfSxcbiAgICAvLyB9LFxuICAgIHtcbiAgICAgIHByb3ZpZGU6IEFQUF9DRUxMX1NFTEVDVElPTl9TRVJWSUNFX1RPS0VOLFxuICAgICAgdXNlQ2xhc3M6IENlbGxTZWxlY3Rpb25TZXJ2aWNlLFxuICAgIH0sXG4gIF0sXG4gIGNoYW5nZURldGVjdGlvbjogQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3kuT25QdXNoLFxufSlcbmV4cG9ydCBjbGFzcyBUYWJsZTJUZXN0UGFnZSBleHRlbmRzIEFwcEFzeW5jVGFibGU8UmVmZXJlbnRpYWwsIFJlZmVyZW50aWFsRmlsdGVyPiBpbXBsZW1lbnRzIE9uSW5pdCwgT25EZXN0cm95LCBBZnRlclZpZXdJbml0IHtcbiAgc3RhdGljIHJlYWRvbmx5IG1heFJvd0NvdW50ID0gMTAwO1xuXG4gIGNhbkVkaXQgPSB0cnVlO1xuICBkYXRhOiBSZWZlcmVudGlhbFtdO1xuICBmaWx0ZXJGb3JtOiBVbnR5cGVkRm9ybUdyb3VwO1xuICBmaWx0ZXJDcml0ZXJpYUNvdW50ID0gMDtcbiAgcm93SGVpZ2h0ID0gMzM7XG4gIGVuYWJsZUluZmluaXRlU2Nyb2xsOiBib29sZWFuO1xuICBjaGVja0JveFNlbGVjdGlvbiA9IHRydWU7XG4gIHJlc2l6YWJsZSA9IHRydWU7XG5cbiAgQElucHV0KCkgZmlsdGVyUGFuZWxGbG9hdGluZyA9IHRydWU7XG4gIEBJbnB1dCgpIHN0aWNreSA9IHRydWU7XG4gIEBJbnB1dCgpIHN0aWNreUVuZCA9IHRydWU7XG5cbiAgZ2V0IGhhc01vcmVEYXRhKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLmRhdGEubGVuZ3RoIDwgMTAwO1xuICB9XG5cbiAgQFZpZXdDaGlsZChNYXRFeHBhbnNpb25QYW5lbCwgeyBzdGF0aWM6IHRydWUgfSkgZmlsdGVyRXhwYW5zaW9uUGFuZWw6IE1hdEV4cGFuc2lvblBhbmVsO1xuICBAVmlld0NoaWxkKElvbkluZmluaXRlU2Nyb2xsKSBpbmZpbml0ZVNjcm9sbDogSW9uSW5maW5pdGVTY3JvbGw7XG5cbiAgcHJvdGVjdGVkIHJlYWRvbmx5IHNlbGVjdGFibGVDb2x1bW5zID0gWyduYW1lJywgJ2xldmVsSWQnLCAnYm9vbGVhbiddO1xuXG4gIGdldCBkYXRhU2VydmljZSgpOiBJbk1lbW9yeUVudGl0aWVzU2VydmljZTxSZWZlcmVudGlhbD4ge1xuICAgIHJldHVybiB0aGlzLl9kYXRhU291cmNlLmRhdGFTZXJ2aWNlIGFzIEluTWVtb3J5RW50aXRpZXNTZXJ2aWNlPFJlZmVyZW50aWFsPjtcbiAgfVxuXG4gIGNvbnN0cnVjdG9yKFxuICAgIGluamVjdG9yOiBJbmplY3RvcixcbiAgICBwcm90ZWN0ZWQgdmFsaWRhdG9yU2VydmljZTogQXBwVmFsaWRhdG9yU2VydmljZSxcbiAgICBwcm90ZWN0ZWQgZm9ybUJ1aWxkZXI6IFVudHlwZWRGb3JtQnVpbGRlclxuICApIHtcbiAgICBzdXBlcihcbiAgICAgIGluamVjdG9yLFxuICAgICAgW1xuICAgICAgICAuLi5SRVNFUlZFRF9TVEFSVF9DT0xVTU5TLFxuICAgICAgICAnbmFtZScsXG4gICAgICAgICdsZXZlbElkJyxcbiAgICAgICAgJ2Jvb2xlYW4nLFxuICAgICAgICAnYm9vbGVhbjInLFxuICAgICAgICAvLydib29sZWFuMycsXG4gICAgICAgIC4uLlJFU0VSVkVEX0VORF9DT0xVTU5TLFxuICAgICAgXSxcbiAgICAgIG5ldyBFbnRpdGllc0FzeW5jVGFibGVEYXRhU291cmNlKFxuICAgICAgICBSZWZlcmVudGlhbCxcbiAgICAgICAgbmV3IEluTWVtb3J5RW50aXRpZXNTZXJ2aWNlKFJlZmVyZW50aWFsLCBSZWZlcmVudGlhbEZpbHRlciwge1xuICAgICAgICAgIHNvcnRCeVJlcGxhY2VtZW50OiB7IGlkOiAnaWQnIH0sXG4gICAgICAgIH0pLFxuICAgICAgICB2YWxpZGF0b3JTZXJ2aWNlLFxuICAgICAgICB7XG4gICAgICAgICAgc3VwcHJlc3NFcnJvcnM6IGZhbHNlLFxuICAgICAgICB9XG4gICAgICApLFxuICAgICAgbnVsbFxuICAgICk7XG5cbiAgICAvLyBXb3JrcyB3aXRoIHRydWUgYW5kIGZhbHNlXG4gICAgdGhpcy5lbmFibGVJbmZpbml0ZVNjcm9sbCA9IHRoaXMubW9iaWxlO1xuXG4gICAgdGhpcy5hdXRvTG9hZCA9IGZhbHNlO1xuICAgIHRoaXMuaW5saW5lRWRpdGlvbiA9IHRydWU7XG4gICAgdGhpcy5pMThuQ29sdW1uUHJlZml4ID0gJ1RBQkxFLlRFU1RJTkcuJztcblxuICAgIHRoaXMuY29uZmlybUJlZm9yZURlbGV0ZSA9IHRydWU7XG4gICAgdGhpcy5jb25maXJtQmVmb3JlQ2FuY2VsID0gZmFsc2U7XG4gICAgdGhpcy51bmRvYWJsZURlbGV0aW9uID0gZmFsc2U7XG4gICAgdGhpcy5zYXZlQmVmb3JlRGVsZXRlID0gZmFsc2U7XG5cbiAgICB0aGlzLnNhdmVCZWZvcmVTb3J0ID0gdHJ1ZTtcbiAgICB0aGlzLnNhdmVCZWZvcmVGaWx0ZXIgPSB0cnVlO1xuICAgIHRoaXMucHJvcGFnYXRlUm93RXJyb3IgPSB0cnVlO1xuXG4gICAgdGhpcy5maWx0ZXJGb3JtID0gZm9ybUJ1aWxkZXIuZ3JvdXAoe1xuICAgICAgc2VhcmNoVGV4dDogW251bGxdLFxuICAgIH0pO1xuXG4gICAgdGhpcy5vblN0YXJ0RWRpdGluZ1Jvdy5zdWJzY3JpYmUoKHJvdykgPT4ge1xuICAgICAgcm93LnZhbGlkYXRvci5wYXRjaFZhbHVlKHsgZW50aXR5TmFtZTogJ1Rlc3RWTycgfSwgeyBlbWl0RXZlbnQ6IGZhbHNlIH0pO1xuICAgIH0pO1xuICB9XG5cbiAgbmdPbkluaXQoKSB7XG4gICAgc3VwZXIubmdPbkluaXQoKTtcblxuICAgIC8vIFVwZGF0ZSBmaWx0ZXIgd2hlbiBjaGFuZ2VzXG4gICAgdGhpcy5yZWdpc3RlclN1YnNjcmlwdGlvbihcbiAgICAgIHRoaXMuZmlsdGVyRm9ybS52YWx1ZUNoYW5nZXNcbiAgICAgICAgLnBpcGUoXG4gICAgICAgICAgZGVib3VuY2VUaW1lKDI1MCksXG4gICAgICAgICAgZmlsdGVyKCgpID0+IHRoaXMuZmlsdGVyRm9ybS52YWxpZCksXG4gICAgICAgICAgdGFwKCh2YWx1ZSkgPT4ge1xuICAgICAgICAgICAgY29uc3QgZmlsdGVyID0gUmVmZXJlbnRpYWxGaWx0ZXIuZnJvbU9iamVjdCh2YWx1ZSk7XG4gICAgICAgICAgICB0aGlzLmZpbHRlckNyaXRlcmlhQ291bnQgPSBmaWx0ZXIuY291bnROb3RFbXB0eUNyaXRlcmlhKCk7XG4gICAgICAgICAgICB0aGlzLm1hcmtGb3JDaGVjaygpO1xuICAgICAgICAgICAgLy8gQXBwbHlpbmcgdGhlIGZpbHRlclxuICAgICAgICAgICAgdGhpcy5zZXRGaWx0ZXIoZmlsdGVyLCB7IGVtaXRFdmVudDogZmFsc2UgfSk7XG4gICAgICAgICAgfSksXG4gICAgICAgICAgLy8gU2F2ZSBmaWx0ZXIgaW4gc2V0dGluZ3MgKGFmdGVyIGEgZGVib3VuY2UgdGltZSlcbiAgICAgICAgICBkZWJvdW5jZVRpbWUoNTAwKSxcbiAgICAgICAgICB0YXAoKGpzb24pID0+IHRoaXMuc2V0dGluZ3Muc2F2ZVBhZ2VTZXR0aW5nKHRoaXMuc2V0dGluZ3NJZCwganNvbiwgJ2ZpbHRlcicpKVxuICAgICAgICApXG4gICAgICAgIC5zdWJzY3JpYmUoKVxuICAgICk7XG5cbiAgICB0aGlzLnJlZ2lzdGVyQXV0b2NvbXBsZXRlRmllbGQoJ2xldmVsJywge1xuICAgICAgaXRlbXM6IFtcbiAgICAgICAgeyBpZDogMSwgbGFiZWw6ICdBJywgbmFtZTogJ2l0ZW0gQScgfSxcbiAgICAgICAgeyBpZDogMSwgbGFiZWw6ICdCJywgbmFtZTogJ2l0ZW0gQicgfSxcbiAgICAgIF0sXG4gICAgICBtb2JpbGU6IHRoaXMubW9iaWxlLFxuICAgIH0pO1xuXG4gICAgdGhpcy5yZWdpc3RlclN1YnNjcmlwdGlvbihcbiAgICAgIHRoaXMub25SZWZyZXNoLnN1YnNjcmliZSgoKSA9PiB7XG4gICAgICAgIHRoaXMuZmlsdGVyRm9ybS5tYXJrQXNVbnRvdWNoZWQoKTtcbiAgICAgICAgdGhpcy5maWx0ZXJGb3JtLm1hcmtBc1ByaXN0aW5lKCk7XG4gICAgICB9KVxuICAgICk7XG5cbiAgICB0aGlzLm1hcmtBc1JlYWR5KCk7XG4gIH1cblxuICBhc3luYyBuZ0FmdGVyVmlld0luaXQoKSB7XG4gICAgc3VwZXIubmdBZnRlclZpZXdJbml0KCk7XG5cbiAgICAvLyBSZXN0b3JlIGZpbHRlciBmcm9tIHNldHRpbmdzXG4gICAgYXdhaXQgdGhpcy5yZXN0b3JlRmlsdGVyKCk7XG5cbiAgICAvLyBMb2FkIGRhdGFcbiAgICB0aGlzLmxvYWQoKTtcbiAgfVxuXG4gIG5nT25EZXN0cm95KCkge1xuICAgIGNvbnNvbGUuZGVidWcoJ1t0ZXN0LXRhYmxlXSBEZXN0cm95aW5nIHRhYmxlLi4uJyk7XG4gICAgc3VwZXIubmdPbkRlc3Ryb3koKTtcbiAgfVxuXG4gIHByb3RlY3RlZCBhc3luYyByZXN0b3JlRmlsdGVyKCkge1xuICAgIGF3YWl0IHRoaXMuc2V0dGluZ3MucmVhZHkoKTtcblxuICAgIGNvbnN0IGpzb24gPSB0aGlzLnNldHRpbmdzLmdldFBhZ2VTZXR0aW5ncyh0aGlzLnNldHRpbmdzSWQsICdmaWx0ZXInKTtcbiAgICBjb25zb2xlLmRlYnVnKCdbdGFibGUtdGVzdF0gUmVzdG9yaW5nIGZpbHRlciBmcm9tIHNldHRpbmdzLi4uJywganNvbik7XG5cbiAgICBpZiAoanNvbikge1xuICAgICAgY29uc3QgZmlsdGVyID0gUmVmZXJlbnRpYWxGaWx0ZXIuZnJvbU9iamVjdChqc29uKTtcbiAgICAgIHRoaXMuZmlsdGVyRm9ybS5wYXRjaFZhbHVlKGpzb24sIHsgZW1pdEV2ZW50OiBmYWxzZSB9KTtcbiAgICAgIHRoaXMuZmlsdGVyQ3JpdGVyaWFDb3VudCA9IGZpbHRlci5jb3VudE5vdEVtcHR5Q3JpdGVyaWEoKTtcbiAgICAgIHRoaXMuc2V0RmlsdGVyKGZpbHRlciwgeyBlbWl0RXZlbnQ6IHRydWUgfSk7XG4gICAgICB0aGlzLm1hcmtGb3JDaGVjaygpO1xuICAgIH1cbiAgfVxuXG4gIGFzeW5jIGxvYWQoKSB7XG4gICAgY29uc29sZS5kZWJ1ZygnW3Rlc3QtdGFibGVdIFVwZGF0aW5nIGRhdGEuLi4nKTtcbiAgICB0aGlzLm1hcmtBc0xvYWRpbmcoKTtcblxuICAgIGlmIChpc05pbCh0aGlzLmRhdGEpKSB7XG4gICAgICB0aGlzLmRhdGEgPSB0aGlzLmdlbmVyYXRlRGF0YSgwLCBUYWJsZTJUZXN0UGFnZS5tYXhSb3dDb3VudCk7XG4gICAgfVxuICAgIHRoaXMuZGF0YVNlcnZpY2UudmFsdWUgPSB0aGlzLmRhdGE7XG5cbiAgICB0aGlzLmVtaXRSZWZyZXNoKCk7XG4gIH1cblxuICBhc3luYyBmZXRjaE1vcmUoZXZlbnQpIHtcbiAgICBjb25zb2xlLmRlYnVnKCdbdGFibGUtdGVzdF0gTG9hZGluZyBtb3JlLi4uJywgZXZlbnQpO1xuICAgIGNvbnN0IGZldGNoZWQgPSBhd2FpdCB0aGlzLl9kYXRhU291cmNlLmZldGNoTW9yZSgpO1xuXG4gICAgaWYgKGZldGNoZWQgJiYgZXZlbnQ/LnRhcmdldCAmJiBldmVudC50YXJnZXQuY29tcGxldGUpIHtcbiAgICAgIC8vIFdhaXQgZW5kIG9mIGxvYWRcbiAgICAgIGF3YWl0IHRoaXMud2FpdElkbGUoKTtcbiAgICAgIC8vIE1hcmsgdGFyZ2V0IGV2ZW50IGFzIGNvbXBsZXRlZCAoZS5nLiBJb25SZWZyZXNoZXIpXG4gICAgICBldmVudC50YXJnZXQuY29tcGxldGUoKTtcbiAgICB9XG4gIH1cblxuICBhc3luYyBzYXZlKG9wdHM/OiB7IGtlZXBFZGl0aW5nPzogYm9vbGVhbiB9KTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgY29uc3Qgc2F2ZWQgPSBhd2FpdCBzdXBlci5zYXZlKG9wdHMpO1xuICAgIGlmIChzYXZlZCkge1xuICAgICAgLy8gVXBkYXRlIHNvdXJjZSBkYXRhXG4gICAgICB0aGlzLmRhdGEgPSB0aGlzLmRhdGFTZXJ2aWNlLnZhbHVlO1xuICAgIH1cbiAgICByZXR1cm4gc2F2ZWQ7XG4gIH1cblxuICBjbGVhckNvbnRyb2xWYWx1ZShldmVudDogRXZlbnQsIGZvcm1Db250cm9sOiBBYnN0cmFjdENvbnRyb2wpOiBib29sZWFuIHtcbiAgICBpZiAoZXZlbnQpIGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpOyAvLyBBdm9pZCB0byBlbnRlciBpbnB1dCB0aGUgZmllbGRcbiAgICBmb3JtQ29udHJvbC5zZXRWYWx1ZShudWxsKTtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICB0b2dnbGVGaWx0ZXJQYW5lbEZsb2F0aW5nKCkge1xuICAgIHRoaXMuZmlsdGVyUGFuZWxGbG9hdGluZyA9ICF0aGlzLmZpbHRlclBhbmVsRmxvYXRpbmc7XG4gICAgdGhpcy5tYXJrRm9yQ2hlY2soKTtcbiAgfVxuXG4gIGFwcGx5RmlsdGVyQW5kQ2xvc2VQYW5lbChldmVudD86IEV2ZW50KSB7XG4gICAgdGhpcy5kZWZhdWx0UGFnZVNpemUgPSBERUZBVUxUX1BBR0VfU0laRTtcbiAgICB0aGlzLmVtaXRSZWZyZXNoKClcbiAgICBpZiAodGhpcy5maWx0ZXJQYW5lbEZsb2F0aW5nKSB0aGlzLmZpbHRlckV4cGFuc2lvblBhbmVsPy5jbG9zZSgpO1xuICB9XG5cbiAgY2xvc2VGaWx0ZXJQYW5lbCgpIHtcbiAgICB0aGlzLmZpbHRlckV4cGFuc2lvblBhbmVsPy5jbG9zZSgpO1xuICAgIGlmICghdGhpcy5maWx0ZXJQYW5lbEZsb2F0aW5nKSB7XG4gICAgICB0aGlzLmZpbHRlclBhbmVsRmxvYXRpbmcgPSB0cnVlO1xuICAgICAgdGhpcy5tYXJrRm9yQ2hlY2soKTtcbiAgICB9XG4gIH1cblxuICBhc3luYyByZXNldEZpbHRlcihldmVudD86IEV2ZW50KSB7XG4gICAgdGhpcy5maWx0ZXJGb3JtLnJlc2V0KHt9LCB7IGVtaXRFdmVudDogdHJ1ZSB9KTtcbiAgICBhd2FpdCB0aGlzLnNldEZpbHRlcihSZWZlcmVudGlhbEZpbHRlci5mcm9tT2JqZWN0KHt9KSwgeyBlbWl0RXZlbnQ6IHRydWUgfSk7XG4gICAgdGhpcy5maWx0ZXJFeHBhbnNpb25QYW5lbC5jbG9zZSgpO1xuICB9XG5cbiAgcHJvdGVjdGVkIGdlbmVyYXRlRGF0YShvZmZzZXQ/OiBudW1iZXIsIHNpemU/OiBudW1iZXIpOiBSZWZlcmVudGlhbFtdIHtcbiAgICBvZmZzZXQgPSBvZmZzZXQgfHwgMDtcbiAgICBzaXplID0gc2l6ZSB8fCAxMDA7XG5cbiAgICBjb25zdCByZXN1bHQgPSBuZXcgQXJyYXk8UmVmZXJlbnRpYWw+KCk7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBzaXplOyBpKyspIHtcbiAgICAgIGNvbnN0IGlkID0gaSArIDEgKyBvZmZzZXQ7XG4gICAgICBjb25zdCBpdGVtID0gUmVmZXJlbnRpYWwuZnJvbU9iamVjdCh7XG4gICAgICAgIGlkLFxuICAgICAgICBsYWJlbDogJ0NPREUtJyArIGlkLFxuICAgICAgICBuYW1lOiAnTmFtZSAjJyArIGlkLFxuICAgICAgICBsZXZlbElkOiB7IGlkOiAxLCBsYWJlbDogJ0EnLCBuYW1lOiAnSXRlbSBBJyB9LFxuICAgICAgICBzdGF0dXNJZDogU3RhdHVzSWRzLkVOQUJMRSxcbiAgICAgICAgY29tbWVudHM6ICdNeSBjb21tZW50ICMnICsgaWQsXG4gICAgICAgIGJvb2xlYW46IGlkICUgMiA9PT0gMCxcbiAgICAgICAgYm9vbGVhbjI6IHRydWUsXG4gICAgICAgIC8vIGJvb2xlYW4zOiBmYWxzZSxcbiAgICAgICAgZW50aXR5TmFtZTogJ1Rlc3RWTycsXG4gICAgICB9KTtcbiAgICAgIHJlc3VsdC5wdXNoKGl0ZW0pO1xuICAgIH1cblxuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cblxuICBwcm90ZWN0ZWQgb25DZWxsU2VsZWN0aW9uQ2hhbmdlKGV2ZW50OiBDZWxsU2VsZWN0aW9uRXZlbnQ8SUNlbGxJZD4pIHtcbiAgICB0aGlzLm1hcmtGb3JDaGVjaygpO1xuICAgIGNvbnNvbGUuZGVidWcoJ1t0YWJsZTItdGVzdF0gU2VsZWN0aW9uIGNoYW5nZWQ6Jywge1xuICAgICAgc2VsZWN0ZWRDZWxsczogZXZlbnQuc2VsZWN0ZWRDZWxscyxcbiAgICAgIGlzUmFuZ2U6IGV2ZW50LmlzUmFuZ2VTZWxlY3Rpb24sXG4gICAgICBpc1RvZ2dsZTogZXZlbnQuaXNUb2dnbGVTZWxlY3Rpb24sXG4gICAgfSk7XG4gIH1cblxuICBwcm90ZWN0ZWQgb25DZWxsUmlnaHRDbGljayhldmVudDogTW91c2VFdmVudCkge1xuICAgIGNvbnNvbGUuZGVidWcoJ1t0YWJsZTItdGVzdF0gUmlnaHQgY2xpY2sgb24gY2VsbDonLCBldmVudCk7XG4gIH1cbn1cbiIsIjxhcHAtdG9vbGJhclxuICBjb2xvcj1cInByaW1hcnlcIlxuICBbY2FuR29CYWNrXT1cInRydWVcIlxuICBbaGFzVmFsaWRhdGVdPVwiKGxvYWRpbmdTdWJqZWN0IHwgYXN5bmMpICE9PSB0cnVlICYmIChkaXJ0eVN1YmplY3QgfCBhc3luYykgPT09IHRydWVcIlxuICAob25WYWxpZGF0ZSk9XCJzYXZlKClcIlxuICBbYmFja0hyZWZdPVwiJy90ZXN0aW5nJ1wiXG4+XG4gIDxpb24tdGl0bGU+VGFibGUgMiAoY2xpY2sgdG8gc2VsZWN0KTwvaW9uLXRpdGxlPlxuXG4gIDxpb24tYnV0dG9ucyBzbG90PVwiZW5kXCI+XG4gICAgQGlmIChzZWxlY3Rpb24gfCBpc0VtcHR5U2VsZWN0aW9uKSB7XG4gICAgICA8aW5wdXQgbWF0SW5wdXQgdHlwZT1cIm51bWJlclwiIHN0ZXA9XCIxXCIgc3R5bGU9XCJjb2xvcjogYmxhY2s7IHdpZHRoOiA1MHB4XCIgWyhuZ01vZGVsKV09XCJyb3dIZWlnaHRcIiAvPlxuXG4gICAgICA8IS0tIEFkZCAtLT5cbiAgICAgIDxidXR0b24gbWF0LWljb24tYnV0dG9uICpuZ0lmPVwiY2FuRWRpdCAmJiAhbW9iaWxlXCIgW3RpdGxlXT1cIidDT01NT04uQlROX0FERCcgfCB0cmFuc2xhdGVcIiAoY2xpY2spPVwiYWRkUm93KClcIj5cbiAgICAgICAgPG1hdC1pY29uPmFkZDwvbWF0LWljb24+XG4gICAgICA8L2J1dHRvbj5cblxuICAgICAgPCEtLSByZXNldCBmaWx0ZXIgLS0+XG4gICAgICA8YnV0dG9uIG1hdC1pY29uLWJ1dHRvbiAoY2xpY2spPVwicmVzZXRGaWx0ZXIoKVwiICpuZ0lmPVwiZmlsdGVyQ3JpdGVyaWFDb3VudFwiPlxuICAgICAgICA8bWF0LWljb24gY29sb3I9XCJhY2NlbnRcIj5maWx0ZXJfbGlzdF9hbHQ8L21hdC1pY29uPlxuICAgICAgICA8bWF0LWljb24gY2xhc3M9XCJpY29uLXNlY29uZGFyeVwiIHN0eWxlPVwibGVmdDogMTZweDsgdG9wOiA1cHg7IGZvbnQtd2VpZ2h0OiBib2xkXCI+Y2xvc2U8L21hdC1pY29uPlxuICAgICAgPC9idXR0b24+XG5cbiAgICAgIDwhLS0gc2hvdyBmaWx0ZXIgLS0+XG4gICAgICA8YnV0dG9uIG1hdC1pY29uLWJ1dHRvbiAoY2xpY2spPVwiZmlsdGVyRXhwYW5zaW9uUGFuZWwudG9nZ2xlKClcIj5cbiAgICAgICAgPG1hdC1pY29uXG4gICAgICAgICAgKm5nSWY9XCJmaWx0ZXJDcml0ZXJpYUNvdW50OyBlbHNlIGVtcHR5RmlsdGVyXCJcbiAgICAgICAgICBbbWF0QmFkZ2VdPVwiZmlsdGVyQ3JpdGVyaWFDb3VudFwiXG4gICAgICAgICAgbWF0QmFkZ2VDb2xvcj1cImFjY2VudFwiXG4gICAgICAgICAgbWF0QmFkZ2VTaXplPVwic21hbGxcIlxuICAgICAgICAgIG1hdEJhZGdlUG9zaXRpb249XCJhYm92ZSBhZnRlclwiXG4gICAgICAgICAgYXJpYS1oaWRkZW49XCJmYWxzZVwiXG4gICAgICAgID5cbiAgICAgICAgICBmaWx0ZXJfbGlzdF9hbHRcbiAgICAgICAgPC9tYXQtaWNvbj5cbiAgICAgICAgPG5nLXRlbXBsYXRlICNlbXB0eUZpbHRlcj5cbiAgICAgICAgICA8bWF0LWljb24+ZmlsdGVyX2xpc3RfYWx0PC9tYXQtaWNvbj5cbiAgICAgICAgPC9uZy10ZW1wbGF0ZT5cbiAgICAgIDwvYnV0dG9uPlxuXG4gICAgICA8IS0tIHNhdmUgLS0+XG4gICAgICA8YnV0dG9uIG1hdC1pY29uLWJ1dHRvbiAqbmdJZj1cIm1vYmlsZVwiIFtkaXNhYmxlZF09XCIoZGlydHlTdWJqZWN0IHwgYXN5bmMpICE9PSB0cnVlXCIgKGNsaWNrKT1cInNhdmUoKVwiPlxuICAgICAgICA8bWF0LWljb24+c2F2ZTwvbWF0LWljb24+XG4gICAgICA8L2J1dHRvbj5cbiAgICB9IEBlbHNlIHtcbiAgICAgIDwhLS0gaWYgcm93IHNlbGVjdGlvbiAtLT5cbiAgICAgIDwhLS0gZGVsZXRlIC0tPlxuICAgICAgPGJ1dHRvblxuICAgICAgICBtYXQtaWNvbi1idXR0b25cbiAgICAgICAgKm5nSWY9XCJjYW5FZGl0XCJcbiAgICAgICAgW3RpdGxlXT1cIidDT01NT04uQlROX0RFTEVURScgfCB0cmFuc2xhdGVcIlxuICAgICAgICAoY2xpY2spPVwiZGVsZXRlU2VsZWN0aW9uKCRldmVudClcIlxuICAgICAgPlxuICAgICAgICA8bWF0LWljb24+ZGVsZXRlPC9tYXQtaWNvbj5cbiAgICAgIDwvYnV0dG9uPlxuXG4gICAgICA8IS0tIGR1cGxpY2F0ZSAtLT5cbiAgICAgIDxidXR0b25cbiAgICAgICAgbWF0LWljb24tYnV0dG9uXG4gICAgICAgICpuZ0lmPVwiY2FuRWRpdCAmJiBzZWxlY3Rpb24uc2VsZWN0ZWQgfCBpc0FycmF5TGVuZ3RoOiB7IGVxdWFsczogMSB9XCJcbiAgICAgICAgW3RpdGxlXT1cIidDT01NT04uQlROX0RVUExJQ0FURScgfCB0cmFuc2xhdGVcIlxuICAgICAgICAoY2xpY2spPVwiZHVwbGljYXRlUm93KCRldmVudCwgc2VsZWN0aW9uLnNlbGVjdGVkWzBdKVwiXG4gICAgICA+XG4gICAgICAgIDxtYXQtaWNvbj5maWxlX2NvcHk8L21hdC1pY29uPlxuICAgICAgPC9idXR0b24+XG4gICAgfVxuICA8L2lvbi1idXR0b25zPlxuPC9hcHAtdG9vbGJhcj5cbjxpb24tY29udGVudCBjbGFzcz1cImlvbi1uby1wYWRkaW5nXCI+XG4gIDxpb24tcmVmcmVzaGVyIHNsb3Q9XCJmaXhlZFwiICpuZ0lmPVwibW9iaWxlXCIgKGlvblJlZnJlc2gpPVwiZG9SZWZyZXNoKCRldmVudClcIj5cbiAgICA8aW9uLXJlZnJlc2hlci1jb250ZW50PjwvaW9uLXJlZnJlc2hlci1jb250ZW50PlxuICA8L2lvbi1yZWZyZXNoZXI+XG5cbiAgPCEtLSBlcnJvciAtLT5cbiAgPGlvbi1pdGVtICpuZ0lmPVwibW9iaWxlICYmIGVycm9yXCIgbGluZXM9XCJub25lXCIgQHNsaWRlVXBEb3duQW5pbWF0aW9uPlxuICAgIDxpb24taWNvbiBjb2xvcj1cImRhbmdlclwiIHNsb3Q9XCJzdGFydFwiIG5hbWU9XCJhbGVydC1jaXJjbGVcIj48L2lvbi1pY29uPlxuICAgIDxpb24tbGFiZWwgY29sb3I9XCJkYW5nZXJcIiBjbGFzcz1cImVycm9yXCIgW2lubmVySFRNTF09XCJlcnJvciB8IHRyYW5zbGF0ZVwiPjwvaW9uLWxhYmVsPlxuICA8L2lvbi1pdGVtPlxuXG4gIDwhLS0gc2VhcmNoIC0tPlxuICA8bWF0LWV4cGFuc2lvbi1wYW5lbFxuICAgICNmaWx0ZXJFeHBhbnNpb25QYW5lbFxuICAgIGNsYXNzPVwiZmlsdGVyLXBhbmVsXCJcbiAgICBbY2xhc3MuZmlsdGVyLXBhbmVsLWZsb2F0aW5nXT1cImZpbHRlclBhbmVsRmxvYXRpbmdcIlxuICAgIFtjbGFzcy5maWx0ZXItcGFuZWwtcGlubmVkXT1cIiFmaWx0ZXJQYW5lbEZsb2F0aW5nXCJcbiAgPlxuICAgIDxmb3JtIGNsYXNzPVwiZm9ybS1jb250YWluZXIgaW9uLXBhZGRpbmctdG9wXCIgW2Zvcm1Hcm91cF09XCJmaWx0ZXJGb3JtXCIgKG5nU3VibWl0KT1cImFwcGx5RmlsdGVyQW5kQ2xvc2VQYW5lbCgkZXZlbnQpXCI+XG4gICAgICA8aW9uLWdyaWQ+XG4gICAgICAgIDxpb24tcm93PlxuICAgICAgICAgIDxpb24tY29sPlxuICAgICAgICAgICAgPCEtLSBzZWFyY2ggdGV4dCAtLT5cbiAgICAgICAgICAgIDxtYXQtZm9ybS1maWVsZD5cbiAgICAgICAgICAgICAgPG1hdC1sYWJlbD57eyAnVEFCTEUuVEVTVElORy5TRUFSQ0hfVEVYVCcgfCB0cmFuc2xhdGUgfX08L21hdC1sYWJlbD5cbiAgICAgICAgICAgICAgPGlvbi1pY29uIG1hdFByZWZpeCBuYW1lPVwic2VhcmNoXCI+PC9pb24taWNvbj5cbiAgICAgICAgICAgICAgPGlucHV0IG1hdElucHV0IGZvcm1Db250cm9sTmFtZT1cInNlYXJjaFRleHRcIiBhdXRvY29tcGxldGU9XCJvZmZcIiAvPlxuICAgICAgICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgICAgICAgbWF0LWljb24tYnV0dG9uXG4gICAgICAgICAgICAgICAgbWF0U3VmZml4XG4gICAgICAgICAgICAgICAgdGFiaW5kZXg9XCItMVwiXG4gICAgICAgICAgICAgICAgdHlwZT1cImJ1dHRvblwiXG4gICAgICAgICAgICAgICAgKGNsaWNrKT1cImNsZWFyQ29udHJvbFZhbHVlKCRldmVudCwgZmlsdGVyRm9ybS5jb250cm9scy5zZWFyY2hUZXh0KVwiXG4gICAgICAgICAgICAgICAgW2hpZGRlbl09XCJmaWx0ZXJGb3JtLmNvbnRyb2xzLnNlYXJjaFRleHQuZGlzYWJsZWQgfHwgIWZpbHRlckZvcm0uY29udHJvbHMuc2VhcmNoVGV4dC52YWx1ZVwiXG4gICAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICA8bWF0LWljb24+Y2xvc2U8L21hdC1pY29uPlxuICAgICAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgICAgIDwvbWF0LWZvcm0tZmllbGQ+XG4gICAgICAgICAgPC9pb24tY29sPlxuICAgICAgICA8L2lvbi1yb3c+XG4gICAgICA8L2lvbi1ncmlkPlxuICAgIDwvZm9ybT5cblxuICAgIDxtYXQtYWN0aW9uLXJvdz5cbiAgICAgIDwhLS0gQ291bnRlciAgLS0+XG4gICAgICA8aW9uLWxhYmVsXG4gICAgICAgIFtoaWRkZW5dPVwiKGxvYWRpbmdTdWJqZWN0IHwgYXN5bmMpIHx8IGZpbHRlckZvcm0uZGlydHlcIlxuICAgICAgICBbY29sb3JdPVwiZW1wdHkgJiYgJ2RhbmdlcidcIlxuICAgICAgICBjbGFzcz1cImlvbi1wYWRkaW5nXCJcbiAgICAgID5cbiAgICAgICAge3tcbiAgICAgICAgICAodG90YWxSb3dDb3VudCA/ICdDT01NT04uUkVTVUxUX0NPVU5UJyA6ICdDT01NT04uTk9fUkVTVUxUJylcbiAgICAgICAgICAgIHwgdHJhbnNsYXRlXG4gICAgICAgICAgICAgIDoge1xuICAgICAgICAgICAgICAgICAgY291bnQ6ICh0b3RhbFJvd0NvdW50IHwgbnVtYmVyRm9ybWF0KSxcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgIH19XG4gICAgICA8L2lvbi1sYWJlbD5cblxuICAgICAgPGRpdiBjbGFzcz1cInRvb2xiYXItc3BhY2VyXCI+PC9kaXY+XG5cbiAgICAgIDxidXR0b25cbiAgICAgICAgbWF0LWljb24tYnV0dG9uXG4gICAgICAgIGNvbG9yPVwiYWNjZW50XCJcbiAgICAgICAgKm5nSWY9XCJmaWx0ZXJQYW5lbEZsb2F0aW5nXCJcbiAgICAgICAgKGNsaWNrKT1cInRvZ2dsZUZpbHRlclBhbmVsRmxvYXRpbmcoKVwiXG4gICAgICAgIGNsYXNzPVwiaGlkZGVuLXhzIGhpZGRlbi1zbSBoaWRkZW4tbWRcIlxuICAgICAgICBbdGl0bGVdPVwiKGZpbHRlclBhbmVsRmxvYXRpbmcgPyAnQ09NTU9OLkJUTl9FWFBBTkQnIDogJ0NPTU1PTi5CVE5fSElERScpIHwgdHJhbnNsYXRlXCJcbiAgICAgID5cbiAgICAgICAgPG1hdC1pY29uPlxuICAgICAgICAgIDxzcGFuIHN0eWxlPVwidHJhbnNmb3JtOiByb3RhdGUoOTBkZWcpXCI+e3sgZmlsdGVyUGFuZWxGbG9hdGluZyA/ICcmI3hiYjsnIDogJyYjeGFiOycgfX08L3NwYW4+XG4gICAgICAgIDwvbWF0LWljb24+XG4gICAgICA8L2J1dHRvbj5cblxuICAgICAgPCEtLSBDbG9zZSBwYW5lbCAtLT5cbiAgICAgIDxpb24tYnV0dG9uIG1hdC1idXR0b24gZmlsbD1cImNsZWFyXCIgY29sb3I9XCJkYXJrXCIgKGNsaWNrKT1cImNsb3NlRmlsdGVyUGFuZWwoKVwiIFtkaXNhYmxlZF09XCJsb2FkaW5nU3ViamVjdCB8IGFzeW5jXCI+XG4gICAgICAgIDxpb24tdGV4dCB0cmFuc2xhdGU+Q09NTU9OLkJUTl9DTE9TRTwvaW9uLXRleHQ+XG4gICAgICA8L2lvbi1idXR0b24+XG5cbiAgICAgIDwhLS0gU2VhcmNoIGJ1dHRvbiAtLT5cbiAgICAgIDxpb24tYnV0dG9uXG4gICAgICAgIG1hdC1idXR0b25cbiAgICAgICAgW2NvbG9yXT1cImZpbHRlckZvcm0uZGlydHkgPyAndGVydGlhcnknIDogJ2RhcmsnXCJcbiAgICAgICAgW2ZpbGxdPVwiZmlsdGVyRm9ybS5kaXJ0eSA/ICdzb2xpZCcgOiAnY2xlYXInXCJcbiAgICAgICAgKGNsaWNrKT1cImFwcGx5RmlsdGVyQW5kQ2xvc2VQYW5lbCgkZXZlbnQpXCJcbiAgICAgID5cbiAgICAgICAgPGlvbi10ZXh0IHRyYW5zbGF0ZT5DT01NT04uQlROX0FQUExZPC9pb24tdGV4dD5cbiAgICAgIDwvaW9uLWJ1dHRvbj5cbiAgICA8L21hdC1hY3Rpb24tcm93PlxuICA8L21hdC1leHBhbnNpb24tcGFuZWw+XG5cbiAgPCEtLSB0YWJsZSAtLT5cbiAgPGRpdiBbY2xhc3MudGFibGUtY29udGFpbmVyXT1cIiFlbmFibGVJbmZpbml0ZVNjcm9sbFwiIHN0eWxlPVwicG9zaXRpb246IHJlbGF0aXZlXCI+XG4gICAgPHRhYmxlXG4gICAgICAjdGFibGVcbiAgICAgIG1hdC10YWJsZVxuICAgICAgbWF0U29ydFxuICAgICAgbWF0U29ydERpc2FibGVDbGVhclxuICAgICAgW2RhdGFTb3VyY2VdPVwiZGF0YVNvdXJjZVwiXG4gICAgICBbbWF0U29ydEFjdGl2ZV09XCJkZWZhdWx0U29ydEJ5XCJcbiAgICAgIFttYXRTb3J0RGlyZWN0aW9uXT1cImRlZmF1bHRTb3J0RGlyZWN0aW9uXCJcbiAgICAgIFt0cmFja0J5XT1cInRyYWNrQnlGblwiXG4gICAgICBbc3R5bGUuLS1tYXQtcm93LWhlaWdodF09XCJyb3dIZWlnaHQgKyAncHgnXCJcbiAgICAgIGFwcENlbGxTZWxlY3Rpb25cbiAgICAgIFthcHBTZWxlY3RhYmxlQ29sdW1uc109XCJzZWxlY3RhYmxlQ29sdW1uc1wiXG4gICAgICAoYXBwQ2VsbFNlbGVjdGlvbkNoYW5nZSk9XCJvbkNlbGxTZWxlY3Rpb25DaGFuZ2UoJGV2ZW50KVwiXG4gICAgICAoYXBwQ2VsbFJpZ2h0Q2xpY2spPVwib25DZWxsUmlnaHRDbGljaygkZXZlbnQpXCJcbiAgICA+XG4gICAgICA8bmctY29udGFpbmVyIG1hdENvbHVtbkRlZj1cInNlbGVjdFwiIFtzdGlja3ldPVwiY2hlY2tCb3hTZWxlY3Rpb25cIiBbY2xhc3MubWF0LWNvbHVtbi1zdGlja3ldPVwiY2hlY2tCb3hTZWxlY3Rpb25cIj5cbiAgICAgICAgPHRoIG1hdC1oZWFkZXItY2VsbCAqbWF0SGVhZGVyQ2VsbERlZiBbY2xhc3MuY2RrLXZpc3VhbGx5LWhpZGRlbl09XCIhY2hlY2tCb3hTZWxlY3Rpb25cIj5cbiAgICAgICAgICBAaWYgKHNlbGVjdGlvbiB8IGlzTXVsdGlwbGVTZWxlY3Rpb24pIHtcbiAgICAgICAgICAgIDxtYXQtY2hlY2tib3hcbiAgICAgICAgICAgICAgW2NoZWNrZWRdPVwidGhpcyB8IGlzQWxsU2VsZWN0ZWRcIlxuICAgICAgICAgICAgICBbaW5kZXRlcm1pbmF0ZV09XCJ0aGlzIHwgaXNOb3RBbGxTZWxlY3RlZFwiXG4gICAgICAgICAgICAgIChjaGFuZ2UpPVwiJGV2ZW50ID8gbWFzdGVyVG9nZ2xlKCkgOiBudWxsXCJcbiAgICAgICAgICAgID48L21hdC1jaGVja2JveD5cbiAgICAgICAgICB9XG4gICAgICAgIDwvdGg+XG4gICAgICAgIDx0ZCBtYXQtY2VsbCAqbWF0Q2VsbERlZj1cImxldCByb3dcIiBbY2xhc3MuY2RrLXZpc3VhbGx5LWhpZGRlbl09XCIhY2hlY2tCb3hTZWxlY3Rpb25cIj5cbiAgICAgICAgICA8bWF0LWNoZWNrYm94IFtjaGVja2VkXT1cInNlbGVjdGlvbiB8IGlzU2VsZWN0ZWQ6IHJvd1wiIChjbGljayk9XCJ0b2dnbGVTZWxlY3RSb3coJGV2ZW50LCByb3cpXCI+PC9tYXQtY2hlY2tib3g+XG4gICAgICAgIDwvdGQ+XG4gICAgICA8L25nLWNvbnRhaW5lcj5cblxuICAgICAgPCEtLSBJZCBjb2x1bW4gLS0+XG4gICAgICA8bmctY29udGFpbmVyIG1hdENvbHVtbkRlZj1cImlkXCIgW3N0aWNreV09XCJzdGlja3lcIj5cbiAgICAgICAgPHRoIG1hdC1oZWFkZXItY2VsbCAqbWF0SGVhZGVyQ2VsbERlZj5cbiAgICAgICAgICA8c3BhbiBtYXQtc29ydC1oZWFkZXI+XG4gICAgICAgICAgICA8aW9uLWxhYmVsIHRpdGxlPVwiSWRcIj4jPC9pb24tbGFiZWw+XG4gICAgICAgICAgICA8aW9uLWxhYmVsIGNvbG9yPVwiZGFuZ2VyXCIgW2lubmVySFRNTF09XCInJm5ic3A7KidcIj48L2lvbi1sYWJlbD5cbiAgICAgICAgICA8L3NwYW4+XG4gICAgICAgIDwvdGg+XG4gICAgICAgIDx0ZCBtYXQtY2VsbCAqbWF0Q2VsbERlZj1cImxldCByb3dcIj5cbiAgICAgICAgICA8bWF0LWZvcm0tZmllbGQgKm5nSWY9XCIhcmVhZE9ubHkgJiYgcm93LmlkID09PSAtMSAmJiByb3cuZWRpdGluZzsgZWxzZSByZWFkT25seUlkXCI+XG4gICAgICAgICAgICA8aW5wdXRcbiAgICAgICAgICAgICAgbWF0SW5wdXRcbiAgICAgICAgICAgICAgYXV0b2NvbXBsZXRlPVwib2ZmXCJcbiAgICAgICAgICAgICAgcmVxdWlyZWRcbiAgICAgICAgICAgICAgW2Zvcm1Db250cm9sXT1cInJvdy52YWxpZGF0b3IgfCBmb3JtR2V0Q29udHJvbDogJ2lkJ1wiXG4gICAgICAgICAgICAgIHBsYWNlaG9sZGVyPVwiSWRcIlxuICAgICAgICAgICAgICBbYXBwQXV0b2ZvY3VzXT1cInRydWVcIlxuICAgICAgICAgICAgLz5cbiAgICAgICAgICAgIDxtYXQtZXJyb3IgKm5nSWY9XCIocm93LnZhbGlkYXRvciB8IGZvcm1HZXRDb250cm9sOiAnaWQnKS5oYXNFcnJvcigncmVxdWlyZWQnKVwiIHRyYW5zbGF0ZT5cbiAgICAgICAgICAgICAgRVJST1IuRklFTERfUkVRVUlSRURcbiAgICAgICAgICAgIDwvbWF0LWVycm9yPlxuICAgICAgICAgICAgPG1hdC1lcnJvciAqbmdJZj1cIihyb3cudmFsaWRhdG9yIHwgZm9ybUdldENvbnRyb2w6ICdpZCcpLmhhc0Vycm9yKCdhbHJlYWR5RXhpc3RzJylcIiB0cmFuc2xhdGU+XG4gICAgICAgICAgICAgIEVSUk9SLkZJRUxEX05PVF9VTklRVUVfSURcbiAgICAgICAgICAgIDwvbWF0LWVycm9yPlxuICAgICAgICAgIDwvbWF0LWZvcm0tZmllbGQ+XG5cbiAgICAgICAgICA8bmctdGVtcGxhdGUgI3JlYWRPbmx5SWQ+XG4gICAgICAgICAgICA8aW9uLWxhYmVsIGFwcEF1dG9UaXRsZT5cbiAgICAgICAgICAgICAge3sgKHJvdy52YWxpZGF0b3IgfCBmb3JtR2V0VmFsdWU6ICdpZCcpIHx8IChyb3cuY3VycmVudERhdGEgfCBwcm9wZXJ0eUdldDogJ2lkJykgfX1cbiAgICAgICAgICAgIDwvaW9uLWxhYmVsPlxuICAgICAgICAgIDwvbmctdGVtcGxhdGU+XG4gICAgICAgIDwvdGQ+XG4gICAgICA8L25nLWNvbnRhaW5lcj5cblxuICAgICAgPCEtLSBOYW1lIGNvbHVtbiAtLT5cbiAgICAgIDxuZy1jb250YWluZXIgbWF0Q29sdW1uRGVmPVwibmFtZVwiPlxuICAgICAgICA8dGggbWF0LWhlYWRlci1jZWxsICptYXRIZWFkZXJDZWxsRGVmIFtyZXNpemFibGVdPVwicmVzaXphYmxlXCI+XG4gICAgICAgICAgPCEtLSBpZiBzb3J0YWJsZSwgd3JhcCB0aGUgaGVhZGVyIHdpdGggYSBtYXQtc29ydC1oZWFkZXIgLS0+XG4gICAgICAgICAgPHNwYW4gbWF0LXNvcnQtaGVhZGVyPlxuICAgICAgICAgICAgPGlvbi1sYWJlbCBbdGl0bGVdPVwiJ1RBQkxFLlRFU1RJTkcuTkFNRScgfCB0cmFuc2xhdGVcIj57eyAnVEFCTEUuVEVTVElORy5OQU1FJyB8IHRyYW5zbGF0ZSB9fTwvaW9uLWxhYmVsPlxuICAgICAgICAgICAgPGlvbi1sYWJlbCBjb2xvcj1cImRhbmdlclwiIFtpbm5lckhUTUxdPVwiJyZuYnNwOyonXCI+PC9pb24tbGFiZWw+XG4gICAgICAgICAgPC9zcGFuPlxuICAgICAgICA8L3RoPlxuICAgICAgICA8dGRcbiAgICAgICAgICBtYXQtY2VsbFxuICAgICAgICAgICptYXRDZWxsRGVmPVwibGV0IHJvd1wiXG4gICAgICAgICAgKGNsaWNrKT1cImZvY3VzQ29sdW1uID0gJ25hbWUnXCJcbiAgICAgICAgICBbYXBwQ2VsbElkXT1cInsgcm93SWQ6IHJvdy5pZCwgY29sdW1uTmFtZTogJ25hbWUnIH1cIlxuICAgICAgICA+XG4gICAgICAgICAgPG1hdC1mb3JtLWZpZWxkICpuZ0lmPVwiIXJlYWRPbmx5ICYmIHJvdy5lZGl0aW5nOyBlbHNlIHJlYWRPbmx5VGVtcGxhdGVcIj5cbiAgICAgICAgICAgIDxpbnB1dFxuICAgICAgICAgICAgICBtYXRJbnB1dFxuICAgICAgICAgICAgICBhdXRvY29tcGxldGU9XCJvZmZcIlxuICAgICAgICAgICAgICBbcmVxdWlyZWRdPVwidHJ1ZVwiXG4gICAgICAgICAgICAgIFtmb3JtQ29udHJvbF09XCJyb3cudmFsaWRhdG9yIHwgZm9ybUdldENvbnRyb2w6ICduYW1lJ1wiXG4gICAgICAgICAgICAgIFtwbGFjZWhvbGRlcl09XCInVEFCTEUuVEVTVElORy5OQU1FJyB8IHRyYW5zbGF0ZVwiXG4gICAgICAgICAgICAgIFthcHBBdXRvZm9jdXNdPVwicm93LmlkID09PSAtMSB8fCBmb2N1c0NvbHVtbiA9PT0gJ25hbWUnXCJcbiAgICAgICAgICAgIC8+XG4gICAgICAgICAgICA8bmctY29udGVudCBzZWxlY3Q9XCJbc3VmZml4XVwiPjwvbmctY29udGVudD5cbiAgICAgICAgICAgIDxtYXQtZXJyb3IgKm5nSWY9XCIocm93LnZhbGlkYXRvciB8IGZvcm1HZXRDb250cm9sOiAnbmFtZScpLmhhc0Vycm9yKCdyZXF1aXJlZCcpXCIgdHJhbnNsYXRlPlxuICAgICAgICAgICAgICBFUlJPUi5GSUVMRF9SRVFVSVJFRFxuICAgICAgICAgICAgPC9tYXQtZXJyb3I+XG4gICAgICAgICAgICA8bWF0LWVycm9yICpuZ0lmPVwiKHJvdy52YWxpZGF0b3IgfCBmb3JtR2V0Q29udHJvbDogJ25hbWUnKS5oYXNFcnJvcignbWF4bGVuZ3RoJylcIiB0cmFuc2xhdGU+XG4gICAgICAgICAgICAgIEVSUk9SLkZJRUxEX01BWF9MRU5HVEhfQ09NUEFDVFxuICAgICAgICAgICAgPC9tYXQtZXJyb3I+XG4gICAgICAgICAgICA8bWF0LWVycm9yICpuZ0lmPVwiKHJvdy52YWxpZGF0b3IgfCBmb3JtR2V0Q29udHJvbDogJ25hbWUnKS5oYXNFcnJvcignbWlubGVuZ3RoJylcIiB0cmFuc2xhdGU+XG4gICAgICAgICAgICAgIEVSUk9SLkZJRUxEX01JTl9MRU5HVEhfQ09NUEFDVFxuICAgICAgICAgICAgPC9tYXQtZXJyb3I+XG4gICAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cbiAgICAgICAgICA8bmctdGVtcGxhdGUgI3JlYWRPbmx5VGVtcGxhdGU+XG4gICAgICAgICAgICA8aW9uLWxhYmVsIGFwcEF1dG9UaXRsZT5cbiAgICAgICAgICAgICAge3sgKHJvdy52YWxpZGF0b3IgfCBmb3JtR2V0VmFsdWU6ICduYW1lJykgfHwgKHJvdy5jdXJyZW50RGF0YSB8IHByb3BlcnR5R2V0OiAnbmFtZScpIH19XG4gICAgICAgICAgICA8L2lvbi1sYWJlbD5cbiAgICAgICAgICA8L25nLXRlbXBsYXRlPlxuICAgICAgICA8L3RkPlxuICAgICAgPC9uZy1jb250YWluZXI+XG5cbiAgICAgIDwhLS0gTGV2ZWwgY29sdW1uIC0tPlxuICAgICAgPG5nLWNvbnRhaW5lciBtYXRDb2x1bW5EZWY9XCJsZXZlbElkXCI+XG4gICAgICAgIDx0aCBtYXQtaGVhZGVyLWNlbGwgKm1hdEhlYWRlckNlbGxEZWYgW3Jlc2l6YWJsZV09XCJyZXNpemFibGVcIj5cbiAgICAgICAgICA8c3BhbiBtYXQtc29ydC1oZWFkZXI+XG4gICAgICAgICAgICA8aW9uLWxhYmVsPnt7ICdUQUJMRS5URVNUSU5HLkxFVkVMX0lEJyB8IHRyYW5zbGF0ZSB9fTwvaW9uLWxhYmVsPlxuICAgICAgICAgICAgPGlvbi1sYWJlbCBjb2xvcj1cImRhbmdlclwiIFtpbm5lckhUTUxdPVwiJyZuYnNwOyonXCI+PC9pb24tbGFiZWw+XG4gICAgICAgICAgPC9zcGFuPlxuICAgICAgICA8L3RoPlxuICAgICAgICA8dGQgbWF0LWNlbGwgKm1hdENlbGxEZWY9XCJsZXQgcm93XCIgW2FwcENlbGxJZF09XCJ7IHJvd0lkOiByb3cuaWQsIGNvbHVtbk5hbWU6ICdsZXZlbElkJyB9XCI+XG4gICAgICAgICAgPG1hdC1hdXRvY29tcGxldGUtZmllbGRcbiAgICAgICAgICAgICpuZ0lmPVwiIXJlYWRPbmx5ICYmIHJvdy5lZGl0aW5nOyBlbHNlIHJlYWRPbmx5VGVtcGxhdGVcIlxuICAgICAgICAgICAgcGFuZWxXaWR0aD1cIjc1MHB4XCJcbiAgICAgICAgICAgIFtmb3JtQ29udHJvbF09XCJyb3cudmFsaWRhdG9yIHwgZm9ybUdldENvbnRyb2w6ICdsZXZlbElkJ1wiXG4gICAgICAgICAgICBbcGxhY2Vob2xkZXJdPVwiJ1RBQkxFLlRFU1RJTkcuTEVWRUxfSUQnIHwgdHJhbnNsYXRlXCJcbiAgICAgICAgICAgIGZsb2F0TGFiZWw9XCJuZXZlclwiXG4gICAgICAgICAgICBbcmVxdWlyZWRdPVwidHJ1ZVwiXG4gICAgICAgICAgICBbY29uZmlnXT1cImF1dG9jb21wbGV0ZUZpZWxkcy5sZXZlbFwiXG4gICAgICAgICAgICBbaGlnaGxpZ2h0QWNjZW50XT1cInRydWVcIlxuICAgICAgICAgID5cbiAgICAgICAgICAgIDxtYXQtZXJyb3IgbWF0RXJyb3IgKm5nSWY9XCIocm93LnZhbGlkYXRvciB8IGZvcm1HZXRDb250cm9sOiAnbGV2ZWxJZCcpLmhhc0Vycm9yKCdpbnZhbGlkJylcIiB0cmFuc2xhdGU+XG4gICAgICAgICAgICAgIEVSUk9SLkZJRUxEX0lOVkFMSURcbiAgICAgICAgICAgIDwvbWF0LWVycm9yPlxuICAgICAgICAgIDwvbWF0LWF1dG9jb21wbGV0ZS1maWVsZD5cbiAgICAgICAgICA8bmctdGVtcGxhdGUgI3JlYWRPbmx5VGVtcGxhdGU+XG4gICAgICAgICAgICA8aW9uLWxhYmVsIGFwcEF1dG9UaXRsZT5cbiAgICAgICAgICAgICAge3tcbiAgICAgICAgICAgICAgICBhdXRvY29tcGxldGVGaWVsZHMubGV2ZWw/LmRpc3BsYXlXaXRoKFxuICAgICAgICAgICAgICAgICAgKHJvdy52YWxpZGF0b3IgfCBmb3JtR2V0VmFsdWU6ICdsZXZlbElkJykgfHwgKHJvdy5jdXJyZW50RGF0YSB8IHByb3BlcnR5R2V0OiAnbGV2ZWxJZCcpXG4gICAgICAgICAgICAgICAgKSB8fFxuICAgICAgICAgICAgICAgICAgKChyb3cudmFsaWRhdG9yIHwgZm9ybUdldFZhbHVlOiAnbGV2ZWxJZCcpIHx8IChyb3cuY3VycmVudERhdGEgfCBwcm9wZXJ0eUdldDogJ2xldmVsSWQnKVxuICAgICAgICAgICAgICAgICAgICB8IHJlZmVyZW50aWFsVG9TdHJpbmcpXG4gICAgICAgICAgICAgIH19XG4gICAgICAgICAgICA8L2lvbi1sYWJlbD5cbiAgICAgICAgICA8L25nLXRlbXBsYXRlPlxuICAgICAgICA8L3RkPlxuICAgICAgPC9uZy1jb250YWluZXI+XG5cbiAgICAgIDxuZy1jb250YWluZXIgbWF0Q29sdW1uRGVmPVwiYm9vbGVhblwiPlxuICAgICAgICA8dGggbWF0LWhlYWRlci1jZWxsICptYXRIZWFkZXJDZWxsRGVmIGNka0RyYWcgW3Jlc2l6YWJsZV09XCJyZXNpemFibGVcIj5cbiAgICAgICAgICA8IS0tIGlmIHNvcnRhYmxlLCB3cmFwIHRoZSBoZWFkZXIgd2l0aCBhIG1hdC1zb3J0LWhlYWRlciAtLT5cbiAgICAgICAgICA8c3BhbiBtYXQtc29ydC1oZWFkZXI+XG4gICAgICAgICAgICA8aW9uLWxhYmVsPkJvb2xlYW48L2lvbi1sYWJlbD5cbiAgICAgICAgICA8L3NwYW4+XG4gICAgICAgIDwvdGg+XG4gICAgICAgIDx0ZCBtYXQtY2VsbCAqbWF0Q2VsbERlZj1cImxldCByb3dcIiBbYXBwQ2VsbElkXT1cInsgcm93SWQ6IHJvdy5pZCwgY29sdW1uTmFtZTogJ2Jvb2xlYW4nIH1cIj5cbiAgICAgICAgICA8bWF0LWJvb2xlYW4tZmllbGRcbiAgICAgICAgICAgICpuZ0lmPVwiIXJlYWRPbmx5ICYmIHJvdy5lZGl0aW5nOyBlbHNlIHJlYWRPbmx5VGVtcGxhdGVcIlxuICAgICAgICAgICAgZmxvYXRMYWJlbD1cIm5ldmVyXCJcbiAgICAgICAgICAgIFtzdHlsZV09XCInY2hlY2tib3gnXCJcbiAgICAgICAgICAgIFtmb3JtQ29udHJvbF09XCJcbiAgICAgICAgICAgICAgKHJvdy52YWxpZGF0b3IgfCBmb3JtR2V0Q29udHJvbDogJ2Jvb2xlYW4nKSB8fCBmb3JtQnVpbGRlci5jb250cm9sKHJvdy5jdXJyZW50RGF0YVsnYm9vbGVhbiddKVxuICAgICAgICAgICAgXCJcbiAgICAgICAgICAgIFtjb21wYWN0XT1cInRydWVcIlxuICAgICAgICAgID48L21hdC1ib29sZWFuLWZpZWxkPlxuICAgICAgICAgIDxuZy10ZW1wbGF0ZSAjcmVhZE9ubHlUZW1wbGF0ZT5cbiAgICAgICAgICAgIDxpb24tbGFiZWwgYXBwQXV0b1RpdGxlPlxuICAgICAgICAgICAgICB7e1xuICAgICAgICAgICAgICAgIChyb3cudmFsaWRhdG9yIHwgZm9ybUdldFZhbHVlOiAnYm9vbGVhbicpIHx8IChyb3cuY3VycmVudERhdGEgfCBwcm9wZXJ0eUdldDogJ2Jvb2xlYW4nKVxuICAgICAgICAgICAgICAgICAgPyAoJ0NPTU1PTi5ZRVMnIHwgdHJhbnNsYXRlKVxuICAgICAgICAgICAgICAgICAgOiAoJ0NPTU1PTi5OTycgfCB0cmFuc2xhdGUpXG4gICAgICAgICAgICAgIH19XG4gICAgICAgICAgICA8L2lvbi1sYWJlbD5cbiAgICAgICAgICA8L25nLXRlbXBsYXRlPlxuICAgICAgICA8L3RkPlxuICAgICAgPC9uZy1jb250YWluZXI+XG5cbiAgICAgIDxuZy1jb250YWluZXIgbWF0Q29sdW1uRGVmPVwiYm9vbGVhbjJcIj5cbiAgICAgICAgPHRoIG1hdC1oZWFkZXItY2VsbCAqbWF0SGVhZGVyQ2VsbERlZiBjZGtEcmFnIFtyZXNpemFibGVdPVwicmVzaXphYmxlXCI+XG4gICAgICAgICAgPCEtLSBpZiBzb3J0YWJsZSwgd3JhcCB0aGUgaGVhZGVyIHdpdGggYSBtYXQtc29ydC1oZWFkZXIgLS0+XG4gICAgICAgICAgPHNwYW4gbWF0LXNvcnQtaGVhZGVyPlxuICAgICAgICAgICAgPGlvbi1sYWJlbD5Cb29sZWFuIDI8L2lvbi1sYWJlbD5cbiAgICAgICAgICA8L3NwYW4+XG4gICAgICAgIDwvdGg+XG4gICAgICAgIDx0ZCBtYXQtY2VsbCAqbWF0Q2VsbERlZj1cImxldCByb3dcIj5cbiAgICAgICAgICA8bWF0LWJvb2xlYW4tZmllbGRcbiAgICAgICAgICAgICpuZ0lmPVwiIXJlYWRPbmx5ICYmIHJvdy5lZGl0aW5nOyBlbHNlIHJlYWRPbmx5VGVtcGxhdGVcIlxuICAgICAgICAgICAgW2Zsb2F0TGFiZWxdPVwiJ25ldmVyJ1wiXG4gICAgICAgICAgICBbc3R5bGVdPVwiJ3JhZGlvJ1wiXG4gICAgICAgICAgICBbc2hvd1JhZGlvXT1cInRydWVcIlxuICAgICAgICAgICAgW2Zvcm1Db250cm9sXT1cIlxuICAgICAgICAgICAgICAocm93LnZhbGlkYXRvciB8IGZvcm1HZXRDb250cm9sOiAnYm9vbGVhbjInKSB8fCBmb3JtQnVpbGRlci5jb250cm9sKHJvdy5jdXJyZW50RGF0YVsnYm9vbGVhbjInXSlcbiAgICAgICAgICAgIFwiXG4gICAgICAgICAgPjwvbWF0LWJvb2xlYW4tZmllbGQ+XG4gICAgICAgICAgPG5nLXRlbXBsYXRlICNyZWFkT25seVRlbXBsYXRlPlxuICAgICAgICAgICAgPGlvbi1sYWJlbCBhcHBBdXRvVGl0bGU+XG4gICAgICAgICAgICAgIHt7XG4gICAgICAgICAgICAgICAgKHJvdy52YWxpZGF0b3IgfCBmb3JtR2V0VmFsdWU6ICdib29sZWFuMicpIHx8IChyb3cuY3VycmVudERhdGEgfCBwcm9wZXJ0eUdldDogJ2Jvb2xlYW4yJylcbiAgICAgICAgICAgICAgICAgID8gKCdDT01NT04uWUVTJyB8IHRyYW5zbGF0ZSlcbiAgICAgICAgICAgICAgICAgIDogKCdDT01NT04uTk8nIHwgdHJhbnNsYXRlKVxuICAgICAgICAgICAgICB9fVxuICAgICAgICAgICAgPC9pb24tbGFiZWw+XG4gICAgICAgICAgPC9uZy10ZW1wbGF0ZT5cbiAgICAgICAgPC90ZD5cbiAgICAgIDwvbmctY29udGFpbmVyPlxuXG4gICAgICA8bmctY29udGFpbmVyIG1hdENvbHVtbkRlZj1cImJvb2xlYW4zXCI+XG4gICAgICAgIDx0aCBtYXQtaGVhZGVyLWNlbGwgKm1hdEhlYWRlckNlbGxEZWYgY2RrRHJhZyBbcmVzaXphYmxlXT1cInJlc2l6YWJsZVwiPlxuICAgICAgICAgIDwhLS0gaWYgc29ydGFibGUsIHdyYXAgdGhlIGhlYWRlciB3aXRoIGEgbWF0LXNvcnQtaGVhZGVyIC0tPlxuICAgICAgICAgIDxzcGFuIG1hdC1zb3J0LWhlYWRlcj5cbiAgICAgICAgICAgIDxpb24tbGFiZWw+Qm9vbGVhbiAzPC9pb24tbGFiZWw+XG4gICAgICAgICAgPC9zcGFuPlxuICAgICAgICA8L3RoPlxuICAgICAgICA8dGQgbWF0LWNlbGwgKm1hdENlbGxEZWY9XCJsZXQgcm93XCI+XG4gICAgICAgICAgPG1hdC1ib29sZWFuLWZpZWxkXG4gICAgICAgICAgICAqbmdJZj1cIiFyZWFkT25seSAmJiByb3cuZWRpdGluZzsgZWxzZSByZWFkT25seVRlbXBsYXRlXCJcbiAgICAgICAgICAgIGZsb2F0TGFiZWw9XCJuZXZlclwiXG4gICAgICAgICAgICBbc3R5bGVdPVwiJ2J1dHRvbidcIlxuICAgICAgICAgICAgW2Zvcm1Db250cm9sXT1cIlxuICAgICAgICAgICAgICAocm93LnZhbGlkYXRvciB8IGZvcm1HZXRDb250cm9sOiAnYm9vbGVhbjInKSB8fCBmb3JtQnVpbGRlci5jb250cm9sKHJvdy5jdXJyZW50RGF0YVsnYm9vbGVhbjInXSlcbiAgICAgICAgICAgIFwiXG4gICAgICAgICAgPjwvbWF0LWJvb2xlYW4tZmllbGQ+XG4gICAgICAgICAgPG5nLXRlbXBsYXRlICNyZWFkT25seVRlbXBsYXRlPlxuICAgICAgICAgICAgPGlvbi1sYWJlbCBhcHBBdXRvVGl0bGU+XG4gICAgICAgICAgICAgIHt7XG4gICAgICAgICAgICAgICAgKHJvdy52YWxpZGF0b3IgfCBmb3JtR2V0VmFsdWU6ICdib29sZWFuMicpIHx8IChyb3cuY3VycmVudERhdGEgfCBwcm9wZXJ0eUdldDogJ2Jvb2xlYW4yJylcbiAgICAgICAgICAgICAgICAgID8gKCdDT01NT04uWUVTJyB8IHRyYW5zbGF0ZSlcbiAgICAgICAgICAgICAgICAgIDogKCdDT01NT04uTk8nIHwgdHJhbnNsYXRlKVxuICAgICAgICAgICAgICB9fVxuICAgICAgICAgICAgPC9pb24tbGFiZWw+XG4gICAgICAgICAgPC9uZy10ZW1wbGF0ZT5cbiAgICAgICAgPC90ZD5cbiAgICAgIDwvbmctY29udGFpbmVyPlxuXG4gICAgICA8IS0tIEFjdGlvbnMgYnV0dG9ucyBjb2x1bW4gLS0+XG4gICAgICA8YXBwLWFjdGlvbnMtY29sdW1uXG4gICAgICAgIFtzdGlja3lFbmRdPVwic3RpY2t5RW5kXCJcbiAgICAgICAgW2NhbkNhbmNlbF09XCJmYWxzZVwiXG4gICAgICAgIFtzdHlsZV09XCIndGFibGUnXCJcbiAgICAgICAgKG9wdGlvbnNDbGljayk9XCJvcGVuU2VsZWN0Q29sdW1uc01vZGFsKCRldmVudClcIlxuICAgICAgICAoY2FuY2VsT3JEZWxldGVDbGljayk9XCJjYW5jZWxPckRlbGV0ZSgkZXZlbnQuZXZlbnQsICRldmVudC5yb3cpXCJcbiAgICAgICAgKGNvbmZpcm1BbmRBZGRDbGljayk9XCJjb25maXJtQW5kQWRkKCRldmVudC5ldmVudCwgJGV2ZW50LnJvdylcIlxuICAgICAgICAoYmFja3dhcmQpPVwiY29uZmlybUFuZEJhY2t3YXJkKCRldmVudC5ldmVudCwgJGV2ZW50LnJvdylcIlxuICAgICAgICAoZm9yd2FyZCk9XCJjb25maXJtQW5kRm9yd2FyZCgkZXZlbnQuZXZlbnQsICRldmVudC5yb3cpXCJcbiAgICAgICAgW2NlbGxUZW1wbGF0ZV09XCJjZWxsSW5qZWN0aW9uXCJcbiAgICAgID5cbiAgICAgICAgPCEtLSBjZWxsIGluamVjdGlvbi0tPlxuICAgICAgICA8bmctdGVtcGxhdGUgI2NlbGxJbmplY3Rpb24gbGV0LXJvdz5cbiAgICAgICAgICA8c3BhbiAqbmdJZj1cInJvdy5lZGl0aW5nICYmICFyb3cudmFsaWRhdG9yLmRpcnR5XCI+LTwvc3Bhbj5cbiAgICAgICAgPC9uZy10ZW1wbGF0ZT5cbiAgICAgIDwvYXBwLWFjdGlvbnMtY29sdW1uPlxuXG4gICAgICA8dHIgbWF0LWhlYWRlci1yb3cgKm1hdEhlYWRlclJvd0RlZj1cImRpc3BsYXllZENvbHVtbnM7IHN0aWNreTogdHJ1ZVwiPjwvdHI+XG4gICAgICA8dHJcbiAgICAgICAgbWF0LXJvd1xuICAgICAgICAqbWF0Um93RGVmPVwibGV0IHJvdzsgY29sdW1uczogZGlzcGxheWVkQ29sdW1uc1wiXG4gICAgICAgIFtjbGFzcy5tYXQtcm93LXNlbGVjdGVkXT1cInJvdy5lZGl0aW5nXCJcbiAgICAgICAgW2NsYXNzLm1hdC1yb3ctZXJyb3JdPVwicm93LmludmFsaWRcIlxuICAgICAgICBbY2xhc3MubWF0LXJvdy1kaXNhYmxlZF09XCIhcm93LmVkaXRpbmdcIlxuICAgICAgICBbY2xhc3MubWF0LXJvdy1kaXJ0eV09XCJyb3cuZGlydHlcIlxuICAgICAgICAoY2xpY2spPVwiY2xpY2tSb3coJGV2ZW50LCByb3cpXCJcbiAgICAgICAgKGtleWRvd24uZXNjYXBlKT1cImVzY2FwZUVkaXRpbmdSb3coJGV2ZW50KVwiXG4gICAgICAgIFtjZGtUcmFwRm9jdXNdPVwicm93LmludmFsaWRcIlxuICAgICAgPjwvdHI+XG4gICAgPC90YWJsZT5cblxuICAgIDxuZy1jb250YWluZXIgKm5nSWY9XCJsb2FkaW5nU3ViamVjdCB8IGFzeW5jOyBlbHNlIG5vUmVzdWx0XCI+XG4gICAgICA8aW9uLWl0ZW0+XG4gICAgICAgIDxpb24tc2tlbGV0b24tdGV4dCBhbmltYXRlZD48L2lvbi1za2VsZXRvbi10ZXh0PlxuICAgICAgPC9pb24taXRlbT5cbiAgICA8L25nLWNvbnRhaW5lcj5cblxuICAgIDxuZy10ZW1wbGF0ZSAjbm9SZXN1bHQ+XG4gICAgICA8aW9uLWl0ZW0gKm5nSWY9XCJ0b3RhbFJvd0NvdW50ID09PSAwXCI+XG4gICAgICAgIDxpb24tdGV4dCBjb2xvcj1cImRhbmdlclwiIGNsYXNzPVwidGV4dC1pdGFsaWNcIiB0cmFuc2xhdGU+Q09NTU9OLk5PX1JFU1VMVDwvaW9uLXRleHQ+XG4gICAgICA8L2lvbi1pdGVtPlxuICAgIDwvbmctdGVtcGxhdGU+XG5cbiAgICA8aW9uLWluZmluaXRlLXNjcm9sbFxuICAgICAgKm5nSWY9XCJlbmFibGVJbmZpbml0ZVNjcm9sbFwiXG4gICAgICBbdGhyZXNob2xkXT1cIm1vYmlsZSA/ICcxMCUnIDogJzIlJ1wiXG4gICAgICBwb3NpdGlvbj1cImJvdHRvbVwiXG4gICAgICAoaW9uSW5maW5pdGUpPVwiZmV0Y2hNb3JlKCRldmVudClcIlxuICAgID5cbiAgICAgIDxpb24taW5maW5pdGUtc2Nyb2xsLWNvbnRlbnRcbiAgICAgICAgbG9hZGluZ1NwaW5uZXI9XCJjaXJjbGVzXCJcbiAgICAgICAgW2xvYWRpbmdUZXh0XT1cIidDT01NT04uTE9BRElOR19ET1RTJyB8IHRyYW5zbGF0ZVwiXG4gICAgICA+PC9pb24taW5maW5pdGUtc2Nyb2xsLWNvbnRlbnQ+XG4gICAgPC9pb24taW5maW5pdGUtc2Nyb2xsPlxuICA8L2Rpdj5cbjwvaW9uLWNvbnRlbnQ+XG5cbjxpb24tZm9vdGVyPlxuICA8IS0tIFBhZ2luYXRvciAgLS0+XG4gIDxtYXQtcGFnaW5hdG9yXG4gICAgKm5nSWY9XCIhZW5hYmxlSW5maW5pdGVTY3JvbGxcIlxuICAgIFtsZW5ndGhdPVwidG90YWxSb3dDb3VudFwiXG4gICAgW3BhZ2VTaXplXT1cImRlZmF1bHRQYWdlU2l6ZVwiXG4gICAgW3BhZ2VTaXplT3B0aW9uc109XCJkZWZhdWx0UGFnZVNpemVPcHRpb25zXCJcbiAgICBzaG93Rmlyc3RMYXN0QnV0dG9uc1xuICA+PC9tYXQtcGFnaW5hdG9yPlxuXG4gIDxhcHAtZm9ybS1idXR0b25zLWJhclxuICAgICpuZ0lmPVwiY2FuRWRpdCAmJiAhbW9iaWxlXCJcbiAgICAob25DYW5jZWwpPVwibG9hZCgpXCJcbiAgICAob25TYXZlKT1cInNhdmUoKVwiXG4gICAgW2Rpc2FibGVkXT1cIihsb2FkaW5nU3ViamVjdCB8IGFzeW5jKSB8fCAhZGlydHlcIlxuICA+XG4gICAgPCEtLSBlcnJvciAtLT5cbiAgICA8aW9uLWl0ZW0gKm5nSWY9XCJlcnJvclN1YmplY3QgfCBhc3luY1wiIGxpbmVzPVwibm9uZVwiPlxuICAgICAgPGlvbi1pY29uIGNvbG9yPVwiZGFuZ2VyXCIgc2xvdD1cInN0YXJ0XCIgbmFtZT1cImFsZXJ0LWNpcmNsZVwiPjwvaW9uLWljb24+XG4gICAgICA8aW9uLWxhYmVsIGNvbG9yPVwiZGFuZ2VyXCIgW2lubmVySFRNTF09XCJlcnJvciB8IHRyYW5zbGF0ZVwiPjwvaW9uLWxhYmVsPlxuICAgIDwvaW9uLWl0ZW0+XG4gIDwvYXBwLWZvcm0tYnV0dG9ucy1iYXI+XG48L2lvbi1mb290ZXI+XG5cbjxpb24tZmFiIHNsb3Q9XCJmaXhlZFwiIHZlcnRpY2FsPVwiYm90dG9tXCIgaG9yaXpvbnRhbD1cImVuZFwiICpuZ0lmPVwiY2FuRWRpdCAmJiBtb2JpbGVcIj5cbiAgPGlvbi1mYWItYnV0dG9uIGNvbG9yPVwidGVydGlhcnlcIiAoY2xpY2spPVwiYWRkUm93KCRldmVudClcIj5cbiAgICA8aW9uLWljb24gbmFtZT1cImFkZFwiPjwvaW9uLWljb24+XG4gIDwvaW9uLWZhYi1idXR0b24+XG48L2lvbi1mYWI+XG4iXX0=
|
|
322
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGFibGUyLnRlc3RpbmcuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBwL2NvcmUvdGFibGUvdGVzdGluZy90YWJsZTIudGVzdGluZy50cyIsIi4uLy4uLy4uLy4uLy4uLy4uLy4uL3NyYy9hcHAvY29yZS90YWJsZS90ZXN0aW5nL3RhYmxlMi50ZXN0aW5nLmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFpQix1QkFBdUIsRUFBRSxTQUFTLEVBQUUsVUFBVSxFQUFFLE1BQU0sRUFBWSxLQUFLLEVBQXFCLFNBQVMsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUNySixPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDMUMsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLHdDQUF3QyxDQUFDO0FBQ3JFLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQ25ELE9BQU8sRUFBRSx1QkFBdUIsRUFBRSxNQUFNLHNEQUFzRCxDQUFDO0FBQy9GLE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxNQUFNLCtDQUErQyxDQUFDO0FBRXBGLE9BQU8sRUFBRSxLQUFLLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQztBQUNsRCxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSxpREFBaUQsQ0FBQztBQUNwRixPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sRUFBRSxHQUFHLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUMzRCxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSw2QkFBNkIsQ0FBQztBQUNoRSxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsb0JBQW9CLEVBQUUsc0JBQXNCLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUNqRyxPQUFPLEVBQUUsc0JBQXNCLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQztBQUNwRSxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0saUNBQWlDLENBQUM7QUFD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R25CO3dCQUNUOzRCQUNFLE9BQU8sRUFBRSxtQkFBbUI7NEJBQzVCLFFBQVEsRUFBRSxzQkFBc0I7eUJBQ2pDO3dCQUNEOzRCQUNFLE9BQU8sRUFBRSxRQUFROzRCQUNqQixXQUFXLEVBQUUsVUFBVSxDQUFDLEdBQUcsRUFBRSxlQUFlLENBQUM7eUJBQzlDO3dCQUNELG9CQUFvQjt3QkFDcEIsSUFBSTt3QkFDSixzREFBc0Q7d0JBQ3RELHdCQUF3Qjt3QkFDeEIsb0RBQW9EO3dCQUNwRCxvQ0FBb0M7d0JBQ3BDLDRFQUE0RTt3QkFDNUUsMkZBQTJGO3dCQUMzRixXQUFXO3dCQUNYLFNBQVM7d0JBQ1QsT0FBTzt3QkFDUCxLQUFLO3dCQUNMOzRCQUNFLE9BQU8sRUFBRSxnQ0FBZ0M7NEJBQ3pDLFFBQVEsRUFBRSxvQkFBb0I7eUJBQy9CO3FCQUNGLG1CQUNnQix1QkFBdUIsQ0FBQyxNQUFNO2dKQWN0QyxtQkFBbUI7c0JBQTNCLEtBQUs7Z0JBQ0csTUFBTTtzQkFBZCxLQUFLO2dCQUNHLFNBQVM7c0JBQWpCLEtBQUs7Z0JBTTBDLG9CQUFvQjtzQkFBbkUsU0FBUzt1QkFBQyxpQkFBaUIsRUFBRSxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUU7Z0JBQ2hCLGNBQWM7c0JBQTNDLFNBQVM7dUJBQUMsaUJBQWlCIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQWZ0ZXJWaWV3SW5pdCwgQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3ksIENvbXBvbmVudCwgZm9yd2FyZFJlZiwgaW5qZWN0LCBJbmplY3RvciwgSW5wdXQsIE9uRGVzdHJveSwgT25Jbml0LCBWaWV3Q2hpbGQgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IEFwcFRhYmxlIH0gZnJvbSAnLi4vdGFibGUuY2xhc3MnO1xuaW1wb3J0IHsgUmVmZXJlbnRpYWwgfSBmcm9tICcuLi8uLi9zZXJ2aWNlcy9tb2RlbC9yZWZlcmVudGlhbC5tb2RlbCc7XG5pbXBvcnQgeyBJb25JbmZpbml0ZVNjcm9sbCB9IGZyb20gJ0Bpb25pYy9hbmd1bGFyJztcbmltcG9ydCB7IEluTWVtb3J5RW50aXRpZXNTZXJ2aWNlIH0gZnJvbSAnLi4vLi4vLi4vc2hhcmVkL3NlcnZpY2VzL21lbW9yeS1lbnRpdHktc2VydmljZS5jbGFzcyc7XG5pbXBvcnQgeyBBcHBWYWxpZGF0b3JTZXJ2aWNlIH0gZnJvbSAnLi4vLi4vc2VydmljZXMvdmFsaWRhdG9yL2Jhc2UudmFsaWRhdG9yLmNsYXNzJztcbmltcG9ydCB7IEFic3RyYWN0Q29udHJvbCwgVW50eXBlZEZvcm1CdWlsZGVyLCBVbnR5cGVkRm9ybUdyb3VwIH0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xuaW1wb3J0IHsgaXNOaWwgfSBmcm9tICcuLi8uLi8uLi9zaGFyZWQvZnVuY3Rpb25zJztcbmltcG9ydCB7IFJlZmVyZW50aWFsRmlsdGVyIH0gZnJvbSAnLi4vLi4vc2VydmljZXMvdGVzdGluZy9yZWZlcmVudGlhbC1maWx0ZXIubW9kZWwnO1xuaW1wb3J0IHsgZGVib3VuY2VUaW1lLCBmaWx0ZXIsIHRhcCB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcbmltcG9ydCB7IE1hdEV4cGFuc2lvblBhbmVsIH0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvZXhwYW5zaW9uJztcbmltcG9ydCB7IERFRkFVTFRfUEFHRV9TSVpFLCBSRVNFUlZFRF9FTkRfQ09MVU1OUywgUkVTRVJWRURfU1RBUlRfQ09MVU1OUyB9IGZyb20gJy4uL3RhYmxlLm1vZGVsJztcbmltcG9ydCB7IFRhYmxlMlZhbGlkYXRvclNlcnZpY2UgfSBmcm9tICcuL3RhYmxlMi12YWxpZGF0b3Iuc2VydmljZSc7XG5pbXBvcnQgeyBTdGF0dXNJZHMgfSBmcm9tICcuLi8uLi9zZXJ2aWNlcy9tb2RlbC9tb2RlbC5lbnVtJztcbmltcG9ydCB7IEFwcEFzeW5jVGFibGUgfSBmcm9tICcuLi9hc3luYy10YWJsZS5jbGFzcyc7XG5pbXBvcnQgeyBFbnRpdGllc0FzeW5jVGFibGVEYXRhU291cmNlIH0gZnJvbSAnLi4vZW50aXRpZXMtYXN5bmMtdGFibGUtZGF0YXNvdXJjZS5jbGFzcyc7XG5pbXBvcnQge1xuICBBUFBfQ0VMTF9TRUxFQ1RJT05fU0VSVklDRV9UT0tFTixcbiAgQ2VsbFNlbGVjdGlvbkV2ZW50LFxuICBDZWxsU2VsZWN0aW9uU2VydmljZSxcbiAgSUNlbGxJZCxcbn0gZnJvbSAnLi4vLi4vLi4vc2hhcmVkL2RpcmVjdGl2ZXMvY2VsbC1zZWxlY3Rpb24vY2VsbC1zZWxlY3Rpb24uc2VydmljZSc7XG5cbmltcG9ydCB7IFNIT1dfVE9PTFRJUCB9IGZyb20gJy4uLy4uLy4uL3NoYXJlZC9jb25zdGFudHMnO1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdhcHAtdGFibGUyLXRlc3RpbmcnLFxuICBzdHlsZVVybHM6IFsndGFibGUyLnRlc3Rpbmcuc2NzcyddLFxuICB0ZW1wbGF0ZVVybDogJ3RhYmxlMi50ZXN0aW5nLmh0bWwnLFxuICBwcm92aWRlcnM6IFtcbiAgICB7XG4gICAgICBwcm92aWRlOiBBcHBWYWxpZGF0b3JTZXJ2aWNlLFxuICAgICAgdXNlQ2xhc3M6IFRhYmxlMlZhbGlkYXRvclNlcnZpY2UsXG4gICAgfSxcbiAgICB7XG4gICAgICBwcm92aWRlOiBBcHBUYWJsZSxcbiAgICAgIHVzZUV4aXN0aW5nOiBmb3J3YXJkUmVmKCgpID0+IFRhYmxlMlRlc3RQYWdlKSxcbiAgICB9LFxuICAgIC8vIFByb3ZpZGUgb3B0aW9ucyA6XG4gICAgLy8ge1xuICAgIC8vICAgcHJvdmlkZTogQVBQX0NFTExfU0VMRUNUSU9OX1NFUlZJQ0VfQ09ORklHX1RPS0VOLFxuICAgIC8vICAgdXNlRmFjdG9yeTogKCkgPT4ge1xuICAgIC8vICAgICByZXR1cm4gPENlbGxTZWxlY3Rpb25TZXJ2aWNlQ29uZmlnPElDZWxsSWQ+PntcbiAgICAvLyAgICAgICBlcXVhbHM6IChjZWxsMSwgY2VsbDIpID0+IHtcbiAgICAvLyAgICAgICAgIGNvbnNvbGUuZGVidWcoJ1t0YWJsZTItdGVzdF0gQ29tcGFyaW5nIGNlbGwgaWRzOicsIGNlbGwxLCBjZWxsMik7XG4gICAgLy8gICAgICAgICByZXR1cm4gY2VsbDE/LnJvd0lkID09PSBjZWxsMj8ucm93SWQgJiYgY2VsbDE/LmNvbHVtbk5hbWUgPT09IGNlbGwyPy5jb2x1bW5OYW1lO1xuICAgIC8vICAgICAgIH0sXG4gICAgLy8gICAgIH07XG4gICAgLy8gICB9LFxuICAgIC8vIH0sXG4gICAge1xuICAgICAgcHJvdmlkZTogQVBQX0NFTExfU0VMRUNUSU9OX1NFUlZJQ0VfVE9LRU4sXG4gICAgICB1c2VDbGFzczogQ2VsbFNlbGVjdGlvblNlcnZpY2UsXG4gICAgfSxcbiAgXSxcbiAgY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2gsXG59KVxuZXhwb3J0IGNsYXNzIFRhYmxlMlRlc3RQYWdlIGV4dGVuZHMgQXBwQXN5bmNUYWJsZTxSZWZlcmVudGlhbCwgUmVmZXJlbnRpYWxGaWx0ZXI+IGltcGxlbWVudHMgT25Jbml0LCBPbkRlc3Ryb3ksIEFmdGVyVmlld0luaXQge1xuICBzdGF0aWMgcmVhZG9ubHkgbWF4Um93Q291bnQgPSAxMDA7XG5cbiAgY2FuRWRpdCA9IHRydWU7XG4gIGRhdGE6IFJlZmVyZW50aWFsW107XG4gIGZpbHRlckZvcm06IFVudHlwZWRGb3JtR3JvdXA7XG4gIGZpbHRlckNyaXRlcmlhQ291bnQgPSAwO1xuICByb3dIZWlnaHQgPSAzMztcbiAgZW5hYmxlSW5maW5pdGVTY3JvbGw6IGJvb2xlYW47XG4gIGNoZWNrQm94U2VsZWN0aW9uID0gdHJ1ZTtcbiAgcmVzaXphYmxlID0gdHJ1ZTtcblxuICBASW5wdXQoKSBmaWx0ZXJQYW5lbEZsb2F0aW5nID0gdHJ1ZTtcbiAgQElucHV0KCkgc3RpY2t5ID0gdHJ1ZTtcbiAgQElucHV0KCkgc3RpY2t5RW5kID0gdHJ1ZTtcblxuICBnZXQgaGFzTW9yZURhdGEoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMuZGF0YS5sZW5ndGggPCAxMDA7XG4gIH1cblxuICBAVmlld0NoaWxkKE1hdEV4cGFuc2lvblBhbmVsLCB7IHN0YXRpYzogdHJ1ZSB9KSBmaWx0ZXJFeHBhbnNpb25QYW5lbDogTWF0RXhwYW5zaW9uUGFuZWw7XG4gIEBWaWV3Q2hpbGQoSW9uSW5maW5pdGVTY3JvbGwpIGluZmluaXRlU2Nyb2xsOiBJb25JbmZpbml0ZVNjcm9sbDtcblxuICBwcm90ZWN0ZWQgcmVhZG9ubHkgc2VsZWN0YWJsZUNvbHVtbnMgPSBbJ25hbWUnLCAnbGV2ZWxJZCcsICdib29sZWFuJ107XG5cbiAgZ2V0IGRhdGFTZXJ2aWNlKCk6IEluTWVtb3J5RW50aXRpZXNTZXJ2aWNlPFJlZmVyZW50aWFsPiB7XG4gICAgcmV0dXJuIHRoaXMuX2RhdGFTb3VyY2UuZGF0YVNlcnZpY2UgYXMgSW5NZW1vcnlFbnRpdGllc1NlcnZpY2U8UmVmZXJlbnRpYWw+O1xuICB9XG5cbiAgc2hvd1Rvb2x0aXAgPSBpbmplY3QoU0hPV19UT09MVElQKTtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBpbmplY3RvcjogSW5qZWN0b3IsXG4gICAgcHJvdGVjdGVkIHZhbGlkYXRvclNlcnZpY2U6IEFwcFZhbGlkYXRvclNlcnZpY2UsXG4gICAgcHJvdGVjdGVkIGZvcm1CdWlsZGVyOiBVbnR5cGVkRm9ybUJ1aWxkZXJcbiAgKSB7XG4gICAgc3VwZXIoXG4gICAgICBpbmplY3RvcixcbiAgICAgIFtcbiAgICAgICAgLi4uUkVTRVJWRURfU1RBUlRfQ09MVU1OUyxcbiAgICAgICAgJ25hbWUnLFxuICAgICAgICAnbGV2ZWxJZCcsXG4gICAgICAgICdib29sZWFuJyxcbiAgICAgICAgJ2Jvb2xlYW4yJyxcbiAgICAgICAgLy8nYm9vbGVhbjMnLFxuICAgICAgICAuLi5SRVNFUlZFRF9FTkRfQ09MVU1OUyxcbiAgICAgIF0sXG4gICAgICBuZXcgRW50aXRpZXNBc3luY1RhYmxlRGF0YVNvdXJjZShcbiAgICAgICAgUmVmZXJlbnRpYWwsXG4gICAgICAgIG5ldyBJbk1lbW9yeUVudGl0aWVzU2VydmljZShSZWZlcmVudGlhbCwgUmVmZXJlbnRpYWxGaWx0ZXIsIHtcbiAgICAgICAgICBzb3J0QnlSZXBsYWNlbWVudDogeyBpZDogJ2lkJyB9LFxuICAgICAgICB9KSxcbiAgICAgICAgdmFsaWRhdG9yU2VydmljZSxcbiAgICAgICAge1xuICAgICAgICAgIHN1cHByZXNzRXJyb3JzOiBmYWxzZSxcbiAgICAgICAgfVxuICAgICAgKSxcbiAgICAgIG51bGxcbiAgICApO1xuXG4gICAgLy8gV29ya3Mgd2l0aCB0cnVlIGFuZCBmYWxzZVxuICAgIHRoaXMuZW5hYmxlSW5maW5pdGVTY3JvbGwgPSB0aGlzLm1vYmlsZTtcblxuICAgIHRoaXMuYXV0b0xvYWQgPSBmYWxzZTtcbiAgICB0aGlzLmlubGluZUVkaXRpb24gPSB0cnVlO1xuICAgIHRoaXMuaTE4bkNvbHVtblByZWZpeCA9ICdUQUJMRS5URVNUSU5HLic7XG5cbiAgICB0aGlzLmNvbmZpcm1CZWZvcmVEZWxldGUgPSB0cnVlO1xuICAgIHRoaXMuY29uZmlybUJlZm9yZUNhbmNlbCA9IGZhbHNlO1xuICAgIHRoaXMudW5kb2FibGVEZWxldGlvbiA9IGZhbHNlO1xuICAgIHRoaXMuc2F2ZUJlZm9yZURlbGV0ZSA9IGZhbHNlO1xuXG4gICAgdGhpcy5zYXZlQmVmb3JlU29ydCA9IHRydWU7XG4gICAgdGhpcy5zYXZlQmVmb3JlRmlsdGVyID0gdHJ1ZTtcbiAgICB0aGlzLnByb3BhZ2F0ZVJvd0Vycm9yID0gdHJ1ZTtcblxuICAgIHRoaXMuZmlsdGVyRm9ybSA9IGZvcm1CdWlsZGVyLmdyb3VwKHtcbiAgICAgIHNlYXJjaFRleHQ6IFtudWxsXSxcbiAgICB9KTtcblxuICAgIHRoaXMub25TdGFydEVkaXRpbmdSb3cuc3Vic2NyaWJlKChyb3cpID0+IHtcbiAgICAgIHJvdy52YWxpZGF0b3IucGF0Y2hWYWx1ZSh7IGVudGl0eU5hbWU6ICdUZXN0Vk8nIH0sIHsgZW1pdEV2ZW50OiBmYWxzZSB9KTtcbiAgICB9KTtcbiAgfVxuXG4gIG5nT25Jbml0KCkge1xuICAgIHN1cGVyLm5nT25Jbml0KCk7XG5cbiAgICAvLyBVcGRhdGUgZmlsdGVyIHdoZW4gY2hhbmdlc1xuICAgIHRoaXMucmVnaXN0ZXJTdWJzY3JpcHRpb24oXG4gICAgICB0aGlzLmZpbHRlckZvcm0udmFsdWVDaGFuZ2VzXG4gICAgICAgIC5waXBlKFxuICAgICAgICAgIGRlYm91bmNlVGltZSgyNTApLFxuICAgICAgICAgIGZpbHRlcigoKSA9PiB0aGlzLmZpbHRlckZvcm0udmFsaWQpLFxuICAgICAgICAgIHRhcCgodmFsdWUpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGZpbHRlciA9IFJlZmVyZW50aWFsRmlsdGVyLmZyb21PYmplY3QodmFsdWUpO1xuICAgICAgICAgICAgdGhpcy5maWx0ZXJDcml0ZXJpYUNvdW50ID0gZmlsdGVyLmNvdW50Tm90RW1wdHlDcml0ZXJpYSgpO1xuICAgICAgICAgICAgdGhpcy5tYXJrRm9yQ2hlY2soKTtcbiAgICAgICAgICAgIC8vIEFwcGx5aW5nIHRoZSBmaWx0ZXJcbiAgICAgICAgICAgIHRoaXMuc2V0RmlsdGVyKGZpbHRlciwgeyBlbWl0RXZlbnQ6IGZhbHNlIH0pO1xuICAgICAgICAgIH0pLFxuICAgICAgICAgIC8vIFNhdmUgZmlsdGVyIGluIHNldHRpbmdzIChhZnRlciBhIGRlYm91bmNlIHRpbWUpXG4gICAgICAgICAgZGVib3VuY2VUaW1lKDUwMCksXG4gICAgICAgICAgdGFwKChqc29uKSA9PiB0aGlzLnNldHRpbmdzLnNhdmVQYWdlU2V0dGluZyh0aGlzLnNldHRpbmdzSWQsIGpzb24sICdmaWx0ZXInKSlcbiAgICAgICAgKVxuICAgICAgICAuc3Vic2NyaWJlKClcbiAgICApO1xuXG4gICAgdGhpcy5yZWdpc3RlckF1dG9jb21wbGV0ZUZpZWxkKCdsZXZlbCcsIHtcbiAgICAgIGl0ZW1zOiBbXG4gICAgICAgIHsgaWQ6IDEsIGxhYmVsOiAnQScsIG5hbWU6ICdpdGVtIEEnIH0sXG4gICAgICAgIHsgaWQ6IDEsIGxhYmVsOiAnQicsIG5hbWU6ICdpdGVtIEInIH0sXG4gICAgICBdLFxuICAgICAgbW9iaWxlOiB0aGlzLm1vYmlsZSxcbiAgICB9KTtcblxuICAgIHRoaXMucmVnaXN0ZXJTdWJzY3JpcHRpb24oXG4gICAgICB0aGlzLm9uUmVmcmVzaC5zdWJzY3JpYmUoKCkgPT4ge1xuICAgICAgICB0aGlzLmZpbHRlckZvcm0ubWFya0FzVW50b3VjaGVkKCk7XG4gICAgICAgIHRoaXMuZmlsdGVyRm9ybS5tYXJrQXNQcmlzdGluZSgpO1xuICAgICAgfSlcbiAgICApO1xuXG4gICAgdGhpcy5tYXJrQXNSZWFkeSgpO1xuICB9XG5cbiAgYXN5bmMgbmdBZnRlclZpZXdJbml0KCkge1xuICAgIHN1cGVyLm5nQWZ0ZXJWaWV3SW5pdCgpO1xuXG4gICAgLy8gUmVzdG9yZSBmaWx0ZXIgZnJvbSBzZXR0aW5nc1xuICAgIGF3YWl0IHRoaXMucmVzdG9yZUZpbHRlcigpO1xuXG4gICAgLy8gTG9hZCBkYXRhXG4gICAgdGhpcy5sb2FkKCk7XG4gIH1cblxuICBuZ09uRGVzdHJveSgpIHtcbiAgICBjb25zb2xlLmRlYnVnKCdbdGVzdC10YWJsZV0gRGVzdHJveWluZyB0YWJsZS4uLicpO1xuICAgIHN1cGVyLm5nT25EZXN0cm95KCk7XG4gIH1cblxuICBwcm90ZWN0ZWQgYXN5bmMgcmVzdG9yZUZpbHRlcigpIHtcbiAgICBhd2FpdCB0aGlzLnNldHRpbmdzLnJlYWR5KCk7XG5cbiAgICBjb25zdCBqc29uID0gdGhpcy5zZXR0aW5ncy5nZXRQYWdlU2V0dGluZ3ModGhpcy5zZXR0aW5nc0lkLCAnZmlsdGVyJyk7XG4gICAgY29uc29sZS5kZWJ1ZygnW3RhYmxlLXRlc3RdIFJlc3RvcmluZyBmaWx0ZXIgZnJvbSBzZXR0aW5ncy4uLicsIGpzb24pO1xuXG4gICAgaWYgKGpzb24pIHtcbiAgICAgIGNvbnN0IGZpbHRlciA9IFJlZmVyZW50aWFsRmlsdGVyLmZyb21PYmplY3QoanNvbik7XG4gICAgICB0aGlzLmZpbHRlckZvcm0ucGF0Y2hWYWx1ZShqc29uLCB7IGVtaXRFdmVudDogZmFsc2UgfSk7XG4gICAgICB0aGlzLmZpbHRlckNyaXRlcmlhQ291bnQgPSBmaWx0ZXIuY291bnROb3RFbXB0eUNyaXRlcmlhKCk7XG4gICAgICB0aGlzLnNldEZpbHRlcihmaWx0ZXIsIHsgZW1pdEV2ZW50OiB0cnVlIH0pO1xuICAgICAgdGhpcy5tYXJrRm9yQ2hlY2soKTtcbiAgICB9XG4gIH1cblxuICBhc3luYyBsb2FkKCkge1xuICAgIGNvbnNvbGUuZGVidWcoJ1t0ZXN0LXRhYmxlXSBVcGRhdGluZyBkYXRhLi4uJyk7XG4gICAgdGhpcy5tYXJrQXNMb2FkaW5nKCk7XG5cbiAgICBpZiAoaXNOaWwodGhpcy5kYXRhKSkge1xuICAgICAgdGhpcy5kYXRhID0gdGhpcy5nZW5lcmF0ZURhdGEoMCwgVGFibGUyVGVzdFBhZ2UubWF4Um93Q291bnQpO1xuICAgIH1cbiAgICB0aGlzLmRhdGFTZXJ2aWNlLnZhbHVlID0gdGhpcy5kYXRhO1xuXG4gICAgdGhpcy5lbWl0UmVmcmVzaCgpO1xuICB9XG5cbiAgYXN5bmMgZmV0Y2hNb3JlKGV2ZW50KSB7XG4gICAgY29uc29sZS5kZWJ1ZygnW3RhYmxlLXRlc3RdIExvYWRpbmcgbW9yZS4uLicsIGV2ZW50KTtcbiAgICBjb25zdCBmZXRjaGVkID0gYXdhaXQgdGhpcy5fZGF0YVNvdXJjZS5mZXRjaE1vcmUoKTtcblxuICAgIGlmIChmZXRjaGVkICYmIGV2ZW50Py50YXJnZXQgJiYgZXZlbnQudGFyZ2V0LmNvbXBsZXRlKSB7XG4gICAgICAvLyBXYWl0IGVuZCBvZiBsb2FkXG4gICAgICBhd2FpdCB0aGlzLndhaXRJZGxlKCk7XG4gICAgICAvLyBNYXJrIHRhcmdldCBldmVudCBhcyBjb21wbGV0ZWQgKGUuZy4gSW9uUmVmcmVzaGVyKVxuICAgICAgZXZlbnQudGFyZ2V0LmNvbXBsZXRlKCk7XG4gICAgfVxuICB9XG5cbiAgYXN5bmMgc2F2ZShvcHRzPzogeyBrZWVwRWRpdGluZz86IGJvb2xlYW4gfSk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgIGNvbnN0IHNhdmVkID0gYXdhaXQgc3VwZXIuc2F2ZShvcHRzKTtcbiAgICBpZiAoc2F2ZWQpIHtcbiAgICAgIC8vIFVwZGF0ZSBzb3VyY2UgZGF0YVxuICAgICAgdGhpcy5kYXRhID0gdGhpcy5kYXRhU2VydmljZS52YWx1ZTtcbiAgICB9XG4gICAgcmV0dXJuIHNhdmVkO1xuICB9XG5cbiAgY2xlYXJDb250cm9sVmFsdWUoZXZlbnQ6IEV2ZW50LCBmb3JtQ29udHJvbDogQWJzdHJhY3RDb250cm9sKTogYm9vbGVhbiB7XG4gICAgaWYgKGV2ZW50KSBldmVudC5zdG9wUHJvcGFnYXRpb24oKTsgLy8gQXZvaWQgdG8gZW50ZXIgaW5wdXQgdGhlIGZpZWxkXG4gICAgZm9ybUNvbnRyb2wuc2V0VmFsdWUobnVsbCk7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgdG9nZ2xlRmlsdGVyUGFuZWxGbG9hdGluZygpIHtcbiAgICB0aGlzLmZpbHRlclBhbmVsRmxvYXRpbmcgPSAhdGhpcy5maWx0ZXJQYW5lbEZsb2F0aW5nO1xuICAgIHRoaXMubWFya0ZvckNoZWNrKCk7XG4gIH1cblxuICBhcHBseUZpbHRlckFuZENsb3NlUGFuZWwoZXZlbnQ/OiBFdmVudCkge1xuICAgIHRoaXMuZGVmYXVsdFBhZ2VTaXplID0gREVGQVVMVF9QQUdFX1NJWkU7XG4gICAgdGhpcy5lbWl0UmVmcmVzaCgpO1xuICAgIGlmICh0aGlzLmZpbHRlclBhbmVsRmxvYXRpbmcpIHRoaXMuZmlsdGVyRXhwYW5zaW9uUGFuZWw/LmNsb3NlKCk7XG4gIH1cblxuICBjbG9zZUZpbHRlclBhbmVsKCkge1xuICAgIHRoaXMuZmlsdGVyRXhwYW5zaW9uUGFuZWw/LmNsb3NlKCk7XG4gICAgaWYgKCF0aGlzLmZpbHRlclBhbmVsRmxvYXRpbmcpIHtcbiAgICAgIHRoaXMuZmlsdGVyUGFuZWxGbG9hdGluZyA9IHRydWU7XG4gICAgICB0aGlzLm1hcmtGb3JDaGVjaygpO1xuICAgIH1cbiAgfVxuXG4gIGFzeW5jIHJlc2V0RmlsdGVyKGV2ZW50PzogRXZlbnQpIHtcbiAgICB0aGlzLmZpbHRlckZvcm0ucmVzZXQoe30sIHsgZW1pdEV2ZW50OiB0cnVlIH0pO1xuICAgIGF3YWl0IHRoaXMuc2V0RmlsdGVyKFJlZmVyZW50aWFsRmlsdGVyLmZyb21PYmplY3Qoe30pLCB7IGVtaXRFdmVudDogdHJ1ZSB9KTtcbiAgICB0aGlzLmZpbHRlckV4cGFuc2lvblBhbmVsLmNsb3NlKCk7XG4gIH1cblxuICBwcm90ZWN0ZWQgZ2VuZXJhdGVEYXRhKG9mZnNldD86IG51bWJlciwgc2l6ZT86IG51bWJlcik6IFJlZmVyZW50aWFsW10ge1xuICAgIG9mZnNldCA9IG9mZnNldCB8fCAwO1xuICAgIHNpemUgPSBzaXplIHx8IDEwMDtcblxuICAgIGNvbnN0IHJlc3VsdCA9IG5ldyBBcnJheTxSZWZlcmVudGlhbD4oKTtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHNpemU7IGkrKykge1xuICAgICAgY29uc3QgaWQgPSBpICsgMSArIG9mZnNldDtcbiAgICAgIGNvbnN0IGl0ZW0gPSBSZWZlcmVudGlhbC5mcm9tT2JqZWN0KHtcbiAgICAgICAgaWQsXG4gICAgICAgIGxhYmVsOiAnQ09ERS0nICsgaWQsXG4gICAgICAgIG5hbWU6ICdOYW1lICMnICsgaWQsXG4gICAgICAgIGxldmVsSWQ6IHsgaWQ6IDEsIGxhYmVsOiAnQScsIG5hbWU6ICdJdGVtIEEnIH0sXG4gICAgICAgIHN0YXR1c0lkOiBTdGF0dXNJZHMuRU5BQkxFLFxuICAgICAgICBjb21tZW50czogJ015IGNvbW1lbnQgIycgKyBpZCxcbiAgICAgICAgYm9vbGVhbjogaWQgJSAyID09PSAwLFxuICAgICAgICBib29sZWFuMjogdHJ1ZSxcbiAgICAgICAgLy8gYm9vbGVhbjM6IGZhbHNlLFxuICAgICAgICBlbnRpdHlOYW1lOiAnVGVzdFZPJyxcbiAgICAgIH0pO1xuICAgICAgcmVzdWx0LnB1c2goaXRlbSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxuXG4gIHByb3RlY3RlZCBvbkNlbGxTZWxlY3Rpb25DaGFuZ2UoZXZlbnQ6IENlbGxTZWxlY3Rpb25FdmVudDxJQ2VsbElkPikge1xuICAgIHRoaXMubWFya0ZvckNoZWNrKCk7XG4gICAgY29uc29sZS5kZWJ1ZygnW3RhYmxlMi10ZXN0XSBTZWxlY3Rpb24gY2hhbmdlZDonLCB7XG4gICAgICBzZWxlY3RlZENlbGxzOiBldmVudC5zZWxlY3RlZENlbGxzLFxuICAgICAgaXNSYW5nZTogZXZlbnQuaXNSYW5nZVNlbGVjdGlvbixcbiAgICAgIGlzVG9nZ2xlOiBldmVudC5pc1RvZ2dsZVNlbGVjdGlvbixcbiAgICB9KTtcbiAgfVxuXG4gIHByb3RlY3RlZCBvbkNlbGxSaWdodENsaWNrKGV2ZW50OiBNb3VzZUV2ZW50KSB7XG4gICAgY29uc29sZS5kZWJ1ZygnW3RhYmxlMi10ZXN0XSBSaWdodCBjbGljayBvbiBjZWxsOicsIGV2ZW50KTtcbiAgfVxufVxuIiwiPGFwcC10b29sYmFyXG4gIGNvbG9yPVwicHJpbWFyeVwiXG4gIFtjYW5Hb0JhY2tdPVwidHJ1ZVwiXG4gIFtoYXNWYWxpZGF0ZV09XCIobG9hZGluZ1N1YmplY3QgfCBhc3luYykgIT09IHRydWUgJiYgKGRpcnR5U3ViamVjdCB8IGFzeW5jKSA9PT0gdHJ1ZVwiXG4gIChvblZhbGlkYXRlKT1cInNhdmUoKVwiXG4gIFtiYWNrSHJlZl09XCInL3Rlc3RpbmcnXCJcbj5cbiAgPGlvbi10aXRsZT5UYWJsZSAyIChjbGljayB0byBzZWxlY3QpPC9pb24tdGl0bGU+XG5cbiAgPGlvbi1idXR0b25zIHNsb3Q9XCJlbmRcIj5cbiAgICBAaWYgKHNlbGVjdGlvbiB8IGlzRW1wdHlTZWxlY3Rpb24pIHtcbiAgICAgIDxpbnB1dCBtYXRJbnB1dCB0eXBlPVwibnVtYmVyXCIgc3RlcD1cIjFcIiBzdHlsZT1cImNvbG9yOiBibGFjazsgd2lkdGg6IDUwcHhcIiBbKG5nTW9kZWwpXT1cInJvd0hlaWdodFwiIC8+XG5cbiAgICAgIDwhLS0gQWRkIC0tPlxuICAgICAgPGJ1dHRvblxuICAgICAgICBtYXQtaWNvbi1idXR0b25cbiAgICAgICAgKm5nSWY9XCJjYW5FZGl0ICYmICFtb2JpbGVcIlxuICAgICAgICBbdGl0bGVdPVwiIXNob3dUb29sdGlwID8gKCdDT01NT04uQlROX0FERCcgfCB0cmFuc2xhdGUpIDogJydcIlxuICAgICAgICBbbWF0VG9vbHRpcF09XCJzaG93VG9vbHRpcCA/ICgnQ09NTU9OLkJUTl9BREQnIHwgdHJhbnNsYXRlKSA6ICcnXCJcbiAgICAgICAgKGNsaWNrKT1cImFkZFJvdygpXCJcbiAgICAgID5cbiAgICAgICAgPG1hdC1pY29uPmFkZDwvbWF0LWljb24+XG4gICAgICA8L2J1dHRvbj5cblxuICAgICAgPCEtLSByZXNldCBmaWx0ZXIgLS0+XG4gICAgICA8YnV0dG9uIG1hdC1pY29uLWJ1dHRvbiAoY2xpY2spPVwicmVzZXRGaWx0ZXIoKVwiICpuZ0lmPVwiZmlsdGVyQ3JpdGVyaWFDb3VudFwiPlxuICAgICAgICA8bWF0LWljb24gY29sb3I9XCJhY2NlbnRcIj5maWx0ZXJfbGlzdF9hbHQ8L21hdC1pY29uPlxuICAgICAgICA8bWF0LWljb24gY2xhc3M9XCJpY29uLXNlY29uZGFyeVwiIHN0eWxlPVwibGVmdDogMTZweDsgdG9wOiA1cHg7IGZvbnQtd2VpZ2h0OiBib2xkXCI+Y2xvc2U8L21hdC1pY29uPlxuICAgICAgPC9idXR0b24+XG5cbiAgICAgIDwhLS0gc2hvdyBmaWx0ZXIgLS0+XG4gICAgICA8YnV0dG9uIG1hdC1pY29uLWJ1dHRvbiAoY2xpY2spPVwiZmlsdGVyRXhwYW5zaW9uUGFuZWwudG9nZ2xlKClcIj5cbiAgICAgICAgPG1hdC1pY29uXG4gICAgICAgICAgKm5nSWY9XCJmaWx0ZXJDcml0ZXJpYUNvdW50OyBlbHNlIGVtcHR5RmlsdGVyXCJcbiAgICAgICAgICBbbWF0QmFkZ2VdPVwiZmlsdGVyQ3JpdGVyaWFDb3VudFwiXG4gICAgICAgICAgbWF0QmFkZ2VDb2xvcj1cImFjY2VudFwiXG4gICAgICAgICAgbWF0QmFkZ2VTaXplPVwic21hbGxcIlxuICAgICAgICAgIG1hdEJhZGdlUG9zaXRpb249XCJhYm92ZSBhZnRlclwiXG4gICAgICAgICAgYXJpYS1oaWRkZW49XCJmYWxzZVwiXG4gICAgICAgID5cbiAgICAgICAgICBmaWx0ZXJfbGlzdF9hbHRcbiAgICAgICAgPC9tYXQtaWNvbj5cbiAgICAgICAgPG5nLXRlbXBsYXRlICNlbXB0eUZpbHRlcj5cbiAgICAgICAgICA8bWF0LWljb24+ZmlsdGVyX2xpc3RfYWx0PC9tYXQtaWNvbj5cbiAgICAgICAgPC9uZy10ZW1wbGF0ZT5cbiAgICAgIDwvYnV0dG9uPlxuXG4gICAgICA8IS0tIHNhdmUgLS0+XG4gICAgICA8YnV0dG9uIG1hdC1pY29uLWJ1dHRvbiAqbmdJZj1cIm1vYmlsZVwiIFtkaXNhYmxlZF09XCIoZGlydHlTdWJqZWN0IHwgYXN5bmMpICE9PSB0cnVlXCIgKGNsaWNrKT1cInNhdmUoKVwiPlxuICAgICAgICA8bWF0LWljb24+c2F2ZTwvbWF0LWljb24+XG4gICAgICA8L2J1dHRvbj5cbiAgICB9IEBlbHNlIHtcbiAgICAgIDwhLS0gaWYgcm93IHNlbGVjdGlvbiAtLT5cbiAgICAgIDwhLS0gZGVsZXRlIC0tPlxuICAgICAgPGJ1dHRvblxuICAgICAgICBtYXQtaWNvbi1idXR0b25cbiAgICAgICAgKm5nSWY9XCJjYW5FZGl0XCJcbiAgICAgICAgW3RpdGxlXT1cIiFzaG93VG9vbHRpcCA/ICgnQ09NTU9OLkJUTl9ERUxFVEUnIHwgdHJhbnNsYXRlKSA6ICcnXCJcbiAgICAgICAgW21hdFRvb2x0aXBdPVwic2hvd1Rvb2x0aXAgPyAoJ0NPTU1PTi5CVE5fREVMRVRFJyB8IHRyYW5zbGF0ZSkgOiAnJ1wiXG4gICAgICAgIChjbGljayk9XCJkZWxldGVTZWxlY3Rpb24oJGV2ZW50KVwiXG4gICAgICA+XG4gICAgICAgIDxtYXQtaWNvbj5kZWxldGU8L21hdC1pY29uPlxuICAgICAgPC9idXR0b24+XG5cbiAgICAgIDwhLS0gZHVwbGljYXRlIC0tPlxuICAgICAgPGJ1dHRvblxuICAgICAgICBtYXQtaWNvbi1idXR0b25cbiAgICAgICAgKm5nSWY9XCJjYW5FZGl0ICYmIHNlbGVjdGlvbi5zZWxlY3RlZCB8IGlzQXJyYXlMZW5ndGg6IHsgZXF1YWxzOiAxIH1cIlxuICAgICAgICBbdGl0bGVdPVwiIXNob3dUb29sdGlwID8gKCdDT01NT04uQlROX0RVUExJQ0FURScgfCB0cmFuc2xhdGUpIDogJydcIlxuICAgICAgICBbbWF0VG9vbHRpcF09XCJzaG93VG9vbHRpcCA/ICgnQ09NTU9OLkJUTl9EVVBMSUNBVEUnIHwgdHJhbnNsYXRlKSA6ICcnXCJcbiAgICAgICAgKGNsaWNrKT1cImR1cGxpY2F0ZVJvdygkZXZlbnQsIHNlbGVjdGlvbi5zZWxlY3RlZFswXSlcIlxuICAgICAgPlxuICAgICAgICA8bWF0LWljb24+ZmlsZV9jb3B5PC9tYXQtaWNvbj5cbiAgICAgIDwvYnV0dG9uPlxuICAgIH1cbiAgPC9pb24tYnV0dG9ucz5cbjwvYXBwLXRvb2xiYXI+XG48aW9uLWNvbnRlbnQgY2xhc3M9XCJpb24tbm8tcGFkZGluZ1wiPlxuICA8aW9uLXJlZnJlc2hlciBzbG90PVwiZml4ZWRcIiAqbmdJZj1cIm1vYmlsZVwiIChpb25SZWZyZXNoKT1cImRvUmVmcmVzaCgkZXZlbnQpXCI+XG4gICAgPGlvbi1yZWZyZXNoZXItY29udGVudD48L2lvbi1yZWZyZXNoZXItY29udGVudD5cbiAgPC9pb24tcmVmcmVzaGVyPlxuXG4gIDwhLS0gZXJyb3IgLS0+XG4gIDxpb24taXRlbSAqbmdJZj1cIm1vYmlsZSAmJiBlcnJvclwiIGxpbmVzPVwibm9uZVwiIEBzbGlkZVVwRG93bkFuaW1hdGlvbj5cbiAgICA8aW9uLWljb24gY29sb3I9XCJkYW5nZXJcIiBzbG90PVwic3RhcnRcIiBuYW1lPVwiYWxlcnQtY2lyY2xlXCI+PC9pb24taWNvbj5cbiAgICA8aW9uLWxhYmVsIGNvbG9yPVwiZGFuZ2VyXCIgY2xhc3M9XCJlcnJvclwiIFtpbm5lckhUTUxdPVwiZXJyb3IgfCB0cmFuc2xhdGVcIj48L2lvbi1sYWJlbD5cbiAgPC9pb24taXRlbT5cblxuICA8IS0tIHNlYXJjaCAtLT5cbiAgPG1hdC1leHBhbnNpb24tcGFuZWxcbiAgICAjZmlsdGVyRXhwYW5zaW9uUGFuZWxcbiAgICBjbGFzcz1cImZpbHRlci1wYW5lbFwiXG4gICAgW2NsYXNzLmZpbHRlci1wYW5lbC1mbG9hdGluZ109XCJmaWx0ZXJQYW5lbEZsb2F0aW5nXCJcbiAgICBbY2xhc3MuZmlsdGVyLXBhbmVsLXBpbm5lZF09XCIhZmlsdGVyUGFuZWxGbG9hdGluZ1wiXG4gID5cbiAgICA8Zm9ybSBjbGFzcz1cImZvcm0tY29udGFpbmVyIGlvbi1wYWRkaW5nLXRvcFwiIFtmb3JtR3JvdXBdPVwiZmlsdGVyRm9ybVwiIChuZ1N1Ym1pdCk9XCJhcHBseUZpbHRlckFuZENsb3NlUGFuZWwoJGV2ZW50KVwiPlxuICAgICAgPGlvbi1ncmlkPlxuICAgICAgICA8aW9uLXJvdz5cbiAgICAgICAgICA8aW9uLWNvbD5cbiAgICAgICAgICAgIDwhLS0gc2VhcmNoIHRleHQgLS0+XG4gICAgICAgICAgICA8bWF0LWZvcm0tZmllbGQ+XG4gICAgICAgICAgICAgIDxtYXQtbGFiZWw+e3sgJ1RBQkxFLlRFU1RJTkcuU0VBUkNIX1RFWFQnIHwgdHJhbnNsYXRlIH19PC9tYXQtbGFiZWw+XG4gICAgICAgICAgICAgIDxpb24taWNvbiBtYXRQcmVmaXggbmFtZT1cInNlYXJjaFwiPjwvaW9uLWljb24+XG4gICAgICAgICAgICAgIDxpbnB1dCBtYXRJbnB1dCBmb3JtQ29udHJvbE5hbWU9XCJzZWFyY2hUZXh0XCIgYXV0b2NvbXBsZXRlPVwib2ZmXCIgLz5cbiAgICAgICAgICAgICAgPGJ1dHRvblxuICAgICAgICAgICAgICAgIG1hdC1pY29uLWJ1dHRvblxuICAgICAgICAgICAgICAgIG1hdFN1ZmZpeFxuICAgICAgICAgICAgICAgIHRhYmluZGV4PVwiLTFcIlxuICAgICAgICAgICAgICAgIHR5cGU9XCJidXR0b25cIlxuICAgICAgICAgICAgICAgIChjbGljayk9XCJjbGVhckNvbnRyb2xWYWx1ZSgkZXZlbnQsIGZpbHRlckZvcm0uY29udHJvbHMuc2VhcmNoVGV4dClcIlxuICAgICAgICAgICAgICAgIFtoaWRkZW5dPVwiZmlsdGVyRm9ybS5jb250cm9scy5zZWFyY2hUZXh0LmRpc2FibGVkIHx8ICFmaWx0ZXJGb3JtLmNvbnRyb2xzLnNlYXJjaFRleHQudmFsdWVcIlxuICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgPG1hdC1pY29uPmNsb3NlPC9tYXQtaWNvbj5cbiAgICAgICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgICA8L21hdC1mb3JtLWZpZWxkPlxuICAgICAgICAgIDwvaW9uLWNvbD5cbiAgICAgICAgPC9pb24tcm93PlxuICAgICAgPC9pb24tZ3JpZD5cbiAgICA8L2Zvcm0+XG5cbiAgICA8bWF0LWFjdGlvbi1yb3c+XG4gICAgICA8IS0tIENvdW50ZXIgIC0tPlxuICAgICAgPGlvbi1sYWJlbFxuICAgICAgICBbaGlkZGVuXT1cIihsb2FkaW5nU3ViamVjdCB8IGFzeW5jKSB8fCBmaWx0ZXJGb3JtLmRpcnR5XCJcbiAgICAgICAgW2NvbG9yXT1cImVtcHR5ICYmICdkYW5nZXInXCJcbiAgICAgICAgY2xhc3M9XCJpb24tcGFkZGluZ1wiXG4gICAgICA+XG4gICAgICAgIHt7XG4gICAgICAgICAgKHRvdGFsUm93Q291bnQgPyAnQ09NTU9OLlJFU1VMVF9DT1VOVCcgOiAnQ09NTU9OLk5PX1JFU1VMVCcpXG4gICAgICAgICAgICB8IHRyYW5zbGF0ZVxuICAgICAgICAgICAgICA6IHtcbiAgICAgICAgICAgICAgICAgIGNvdW50OiAodG90YWxSb3dDb3VudCB8IG51bWJlckZvcm1hdCksXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICB9fVxuICAgICAgPC9pb24tbGFiZWw+XG5cbiAgICAgIDxkaXYgY2xhc3M9XCJ0b29sYmFyLXNwYWNlclwiPjwvZGl2PlxuXG4gICAgICA8YnV0dG9uXG4gICAgICAgIG1hdC1pY29uLWJ1dHRvblxuICAgICAgICBjb2xvcj1cImFjY2VudFwiXG4gICAgICAgICpuZ0lmPVwiZmlsdGVyUGFuZWxGbG9hdGluZ1wiXG4gICAgICAgIChjbGljayk9XCJ0b2dnbGVGaWx0ZXJQYW5lbEZsb2F0aW5nKClcIlxuICAgICAgICBjbGFzcz1cImhpZGRlbi14cyBoaWRkZW4tc20gaGlkZGVuLW1kXCJcbiAgICAgICAgW3RpdGxlXT1cIiFzaG93VG9vbHRpcCA/ICgoZmlsdGVyUGFuZWxGbG9hdGluZyA/ICdDT01NT04uQlROX0VYUEFORCcgOiAnQ09NTU9OLkJUTl9ISURFJykgfCB0cmFuc2xhdGUpIDogJydcIlxuICAgICAgICBbbWF0VG9vbHRpcF09XCJzaG93VG9vbHRpcCA/ICgoZmlsdGVyUGFuZWxGbG9hdGluZyA/ICdDT01NT04uQlROX0VYUEFORCcgOiAnQ09NTU9OLkJUTl9ISURFJykgfCB0cmFuc2xhdGUpIDogJydcIlxuICAgICAgPlxuICAgICAgICA8bWF0LWljb24+XG4gICAgICAgICAgPHNwYW4gc3R5bGU9XCJ0cmFuc2Zvcm06IHJvdGF0ZSg5MGRlZylcIj57eyBmaWx0ZXJQYW5lbEZsb2F0aW5nID8gJyYjeGJiOycgOiAnJiN4YWI7JyB9fTwvc3Bhbj5cbiAgICAgICAgPC9tYXQtaWNvbj5cbiAgICAgIDwvYnV0dG9uPlxuXG4gICAgICA8IS0tIENsb3NlIHBhbmVsIC0tPlxuICAgICAgPGlvbi1idXR0b24gbWF0LWJ1dHRvbiBmaWxsPVwiY2xlYXJcIiBjb2xvcj1cImRhcmtcIiAoY2xpY2spPVwiY2xvc2VGaWx0ZXJQYW5lbCgpXCIgW2Rpc2FibGVkXT1cImxvYWRpbmdTdWJqZWN0IHwgYXN5bmNcIj5cbiAgICAgICAgPGlvbi10ZXh0IHRyYW5zbGF0ZT5DT01NT04uQlROX0NMT1NFPC9pb24tdGV4dD5cbiAgICAgIDwvaW9uLWJ1dHRvbj5cblxuICAgICAgPCEtLSBTZWFyY2ggYnV0dG9uIC0tPlxuICAgICAgPGlvbi1idXR0b25cbiAgICAgICAgbWF0LWJ1dHRvblxuICAgICAgICBbY29sb3JdPVwiZmlsdGVyRm9ybS5kaXJ0eSA/ICd0ZXJ0aWFyeScgOiAnZGFyaydcIlxuICAgICAgICBbZmlsbF09XCJmaWx0ZXJGb3JtLmRpcnR5ID8gJ3NvbGlkJyA6ICdjbGVhcidcIlxuICAgICAgICAoY2xpY2spPVwiYXBwbHlGaWx0ZXJBbmRDbG9zZVBhbmVsKCRldmVudClcIlxuICAgICAgPlxuICAgICAgICA8aW9uLXRleHQgdHJhbnNsYXRlPkNPTU1PTi5CVE5fQVBQTFk8L2lvbi10ZXh0PlxuICAgICAgPC9pb24tYnV0dG9uPlxuICAgIDwvbWF0LWFjdGlvbi1yb3c+XG4gIDwvbWF0LWV4cGFuc2lvbi1wYW5lbD5cblxuICA8IS0tIHRhYmxlIC0tPlxuICA8ZGl2IFtjbGFzcy50YWJsZS1jb250YWluZXJdPVwiIWVuYWJsZUluZmluaXRlU2Nyb2xsXCIgc3R5bGU9XCJwb3NpdGlvbjogcmVsYXRpdmVcIj5cbiAgICA8dGFibGVcbiAgICAgICN0YWJsZVxuICAgICAgbWF0LXRhYmxlXG4gICAgICBtYXRTb3J0XG4gICAgICBtYXRTb3J0RGlzYWJsZUNsZWFyXG4gICAgICBbZGF0YVNvdXJjZV09XCJkYXRhU291cmNlXCJcbiAgICAgIFttYXRTb3J0QWN0aXZlXT1cImRlZmF1bHRTb3J0QnlcIlxuICAgICAgW21hdFNvcnREaXJlY3Rpb25dPVwiZGVmYXVsdFNvcnREaXJlY3Rpb25cIlxuICAgICAgW3RyYWNrQnldPVwidHJhY2tCeUZuXCJcbiAgICAgIFtzdHlsZS4tLW1hdC1yb3ctaGVpZ2h0XT1cInJvd0hlaWdodCArICdweCdcIlxuICAgICAgYXBwQ2VsbFNlbGVjdGlvblxuICAgICAgW2FwcFNlbGVjdGFibGVDb2x1bW5zXT1cInNlbGVjdGFibGVDb2x1bW5zXCJcbiAgICAgIChhcHBDZWxsU2VsZWN0aW9uQ2hhbmdlKT1cIm9uQ2VsbFNlbGVjdGlvbkNoYW5nZSgkZXZlbnQpXCJcbiAgICAgIChhcHBDZWxsUmlnaHRDbGljayk9XCJvbkNlbGxSaWdodENsaWNrKCRldmVudClcIlxuICAgID5cbiAgICAgIDxuZy1jb250YWluZXIgbWF0Q29sdW1uRGVmPVwic2VsZWN0XCIgW3N0aWNreV09XCJjaGVja0JveFNlbGVjdGlvblwiIFtjbGFzcy5tYXQtY29sdW1uLXN0aWNreV09XCJjaGVja0JveFNlbGVjdGlvblwiPlxuICAgICAgICA8dGggbWF0LWhlYWRlci1jZWxsICptYXRIZWFkZXJDZWxsRGVmIFtjbGFzcy5jZGstdmlzdWFsbHktaGlkZGVuXT1cIiFjaGVja0JveFNlbGVjdGlvblwiPlxuICAgICAgICAgIEBpZiAoc2VsZWN0aW9uIHwgaXNNdWx0aXBsZVNlbGVjdGlvbikge1xuICAgICAgICAgICAgPG1hdC1jaGVja2JveFxuICAgICAgICAgICAgICBbY2hlY2tlZF09XCJ0aGlzIHwgaXNBbGxTZWxlY3RlZFwiXG4gICAgICAgICAgICAgIFtpbmRldGVybWluYXRlXT1cInRoaXMgfCBpc05vdEFsbFNlbGVjdGVkXCJcbiAgICAgICAgICAgICAgKGNoYW5nZSk9XCIkZXZlbnQgPyBtYXN0ZXJUb2dnbGUoKSA6IG51bGxcIlxuICAgICAgICAgICAgPjwvbWF0LWNoZWNrYm94PlxuICAgICAgICAgIH1cbiAgICAgICAgPC90aD5cbiAgICAgICAgPHRkIG1hdC1jZWxsICptYXRDZWxsRGVmPVwibGV0IHJvd1wiIFtjbGFzcy5jZGstdmlzdWFsbHktaGlkZGVuXT1cIiFjaGVja0JveFNlbGVjdGlvblwiPlxuICAgICAgICAgIDxtYXQtY2hlY2tib3ggW2NoZWNrZWRdPVwic2VsZWN0aW9uIHwgaXNTZWxlY3RlZDogcm93XCIgKGNsaWNrKT1cInRvZ2dsZVNlbGVjdFJvdygkZXZlbnQsIHJvdylcIj48L21hdC1jaGVja2JveD5cbiAgICAgICAgPC90ZD5cbiAgICAgIDwvbmctY29udGFpbmVyPlxuXG4gICAgICA8IS0tIElkIGNvbHVtbiAtLT5cbiAgICAgIDxuZy1jb250YWluZXIgbWF0Q29sdW1uRGVmPVwiaWRcIiBbc3RpY2t5XT1cInN0aWNreVwiPlxuICAgICAgICA8dGggbWF0LWhlYWRlci1jZWxsICptYXRIZWFkZXJDZWxsRGVmPlxuICAgICAgICAgIDxzcGFuIG1hdC1zb3J0LWhlYWRlcj5cbiAgICAgICAgICAgIDxpb24tbGFiZWwgdGl0bGU9XCJJZFwiPiM8L2lvbi1sYWJlbD5cbiAgICAgICAgICAgIDxpb24tbGFiZWwgY29sb3I9XCJkYW5nZXJcIiBbaW5uZXJIVE1MXT1cIicmbmJzcDsqJ1wiPjwvaW9uLWxhYmVsPlxuICAgICAgICAgIDwvc3Bhbj5cbiAgICAgICAgPC90aD5cbiAgICAgICAgPHRkIG1hdC1jZWxsICptYXRDZWxsRGVmPVwibGV0IHJvd1wiPlxuICAgICAgICAgIDxtYXQtZm9ybS1maWVsZCAqbmdJZj1cIiFyZWFkT25seSAmJiByb3cuaWQgPT09IC0xICYmIHJvdy5lZGl0aW5nOyBlbHNlIHJlYWRPbmx5SWRcIj5cbiAgICAgICAgICAgIDxpbnB1dFxuICAgICAgICAgICAgICBtYXRJbnB1dFxuICAgICAgICAgICAgICBhdXRvY29tcGxldGU9XCJvZmZcIlxuICAgICAgICAgICAgICByZXF1aXJlZFxuICAgICAgICAgICAgICBbZm9ybUNvbnRyb2xdPVwicm93LnZhbGlkYXRvciB8IGZvcm1HZXRDb250cm9sOiAnaWQnXCJcbiAgICAgICAgICAgICAgcGxhY2Vob2xkZXI9XCJJZFwiXG4gICAgICAgICAgICAgIFthcHBBdXRvZm9jdXNdPVwidHJ1ZVwiXG4gICAgICAgICAgICAvPlxuICAgICAgICAgICAgPG1hdC1lcnJvciAqbmdJZj1cIihyb3cudmFsaWRhdG9yIHwgZm9ybUdldENvbnRyb2w6ICdpZCcpLmhhc0Vycm9yKCdyZXF1aXJlZCcpXCIgdHJhbnNsYXRlPlxuICAgICAgICAgICAgICBFUlJPUi5GSUVMRF9SRVFVSVJFRFxuICAgICAgICAgICAgPC9tYXQtZXJyb3I+XG4gICAgICAgICAgICA8bWF0LWVycm9yICpuZ0lmPVwiKHJvdy52YWxpZGF0b3IgfCBmb3JtR2V0Q29udHJvbDogJ2lkJykuaGFzRXJyb3IoJ2FscmVhZHlFeGlzdHMnKVwiIHRyYW5zbGF0ZT5cbiAgICAgICAgICAgICAgRVJST1IuRklFTERfTk9UX1VOSVFVRV9JRFxuICAgICAgICAgICAgPC9tYXQtZXJyb3I+XG4gICAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cblxuICAgICAgICAgIDxuZy10ZW1wbGF0ZSAjcmVhZE9ubHlJZD5cbiAgICAgICAgICAgIDxpb24tbGFiZWwgYXBwQXV0b1Rvb2x0aXA+XG4gICAgICAgICAgICAgIHt7IChyb3cudmFsaWRhdG9yIHwgZm9ybUdldFZhbHVlOiAnaWQnKSB8fCAocm93LmN1cnJlbnREYXRhIHwgcHJvcGVydHlHZXQ6ICdpZCcpIH19XG4gICAgICAgICAgICA8L2lvbi1sYWJlbD5cbiAgICAgICAgICA8L25nLXRlbXBsYXRlPlxuICAgICAgICA8L3RkPlxuICAgICAgPC9uZy1jb250YWluZXI+XG5cbiAgICAgIDwhLS0gTmFtZSBjb2x1bW4gLS0+XG4gICAgICA8bmctY29udGFpbmVyIG1hdENvbHVtbkRlZj1cIm5hbWVcIj5cbiAgICAgICAgPHRoIG1hdC1oZWFkZXItY2VsbCAqbWF0SGVhZGVyQ2VsbERlZiBbcmVzaXphYmxlXT1cInJlc2l6YWJsZVwiPlxuICAgICAgICAgIDwhLS0gaWYgc29ydGFibGUsIHdyYXAgdGhlIGhlYWRlciB3aXRoIGEgbWF0LXNvcnQtaGVhZGVyIC0tPlxuICAgICAgICAgIDxzcGFuIG1hdC1zb3J0LWhlYWRlcj5cbiAgICAgICAgICAgIDxpb24tbGFiZWxcbiAgICAgICAgICAgICAgW3RpdGxlXT1cIiFzaG93VG9vbHRpcCA/ICgnVEFCTEUuVEVTVElORy5OQU1FJyB8IHRyYW5zbGF0ZSkgOiAnJ1wiXG4gICAgICAgICAgICAgIFttYXRUb29sdGlwXT1cInNob3dUb29sdGlwID8gKCdUQUJMRS5URVNUSU5HLk5BTUUnIHwgdHJhbnNsYXRlKSA6ICcnXCJcbiAgICAgICAgICAgID5cbiAgICAgICAgICAgICAge3sgJ1RBQkxFLlRFU1RJTkcuTkFNRScgfCB0cmFuc2xhdGUgfX1cbiAgICAgICAgICAgIDwvaW9uLWxhYmVsPlxuICAgICAgICAgICAgPGlvbi1sYWJlbCBjb2xvcj1cImRhbmdlclwiIFtpbm5lckhUTUxdPVwiJyZuYnNwOyonXCI+PC9pb24tbGFiZWw+XG4gICAgICAgICAgPC9zcGFuPlxuICAgICAgICA8L3RoPlxuICAgICAgICA8dGRcbiAgICAgICAgICBtYXQtY2VsbFxuICAgICAgICAgICptYXRDZWxsRGVmPVwibGV0IHJvd1wiXG4gICAgICAgICAgKGNsaWNrKT1cImZvY3VzQ29sdW1uID0gJ25hbWUnXCJcbiAgICAgICAgICBbYXBwQ2VsbElkXT1cInsgcm93SWQ6IHJvdy5pZCwgY29sdW1uTmFtZTogJ25hbWUnIH1cIlxuICAgICAgICA+XG4gICAgICAgICAgPG1hdC1mb3JtLWZpZWxkICpuZ0lmPVwiIXJlYWRPbmx5ICYmIHJvdy5lZGl0aW5nOyBlbHNlIHJlYWRPbmx5VGVtcGxhdGVcIj5cbiAgICAgICAgICAgIDxpbnB1dFxuICAgICAgICAgICAgICBtYXRJbnB1dFxuICAgICAgICAgICAgICBhdXRvY29tcGxldGU9XCJvZmZcIlxuICAgICAgICAgICAgICBbcmVxdWlyZWRdPVwidHJ1ZVwiXG4gICAgICAgICAgICAgIFtmb3JtQ29udHJvbF09XCJyb3cudmFsaWRhdG9yIHwgZm9ybUdldENvbnRyb2w6ICduYW1lJ1wiXG4gICAgICAgICAgICAgIFtwbGFjZWhvbGRlcl09XCInVEFCTEUuVEVTVElORy5OQU1FJyB8IHRyYW5zbGF0ZVwiXG4gICAgICAgICAgICAgIFthcHBBdXRvZm9jdXNdPVwicm93LmlkID09PSAtMSB8fCBmb2N1c0NvbHVtbiA9PT0gJ25hbWUnXCJcbiAgICAgICAgICAgIC8+XG4gICAgICAgICAgICA8bmctY29udGVudCBzZWxlY3Q9XCJbc3VmZml4XVwiPjwvbmctY29udGVudD5cbiAgICAgICAgICAgIDxtYXQtZXJyb3IgKm5nSWY9XCIocm93LnZhbGlkYXRvciB8IGZvcm1HZXRDb250cm9sOiAnbmFtZScpLmhhc0Vycm9yKCdyZXF1aXJlZCcpXCIgdHJhbnNsYXRlPlxuICAgICAgICAgICAgICBFUlJPUi5GSUVMRF9SRVFVSVJFRFxuICAgICAgICAgICAgPC9tYXQtZXJyb3I+XG4gICAgICAgICAgICA8bWF0LWVycm9yICpuZ0lmPVwiKHJvdy52YWxpZGF0b3IgfCBmb3JtR2V0Q29udHJvbDogJ25hbWUnKS5oYXNFcnJvcignbWF4bGVuZ3RoJylcIiB0cmFuc2xhdGU+XG4gICAgICAgICAgICAgIEVSUk9SLkZJRUxEX01BWF9MRU5HVEhfQ09NUEFDVFxuICAgICAgICAgICAgPC9tYXQtZXJyb3I+XG4gICAgICAgICAgICA8bWF0LWVycm9yICpuZ0lmPVwiKHJvdy52YWxpZGF0b3IgfCBmb3JtR2V0Q29udHJvbDogJ25hbWUnKS5oYXNFcnJvcignbWlubGVuZ3RoJylcIiB0cmFuc2xhdGU+XG4gICAgICAgICAgICAgIEVSUk9SLkZJRUxEX01JTl9MRU5HVEhfQ09NUEFDVFxuICAgICAgICAgICAgPC9tYXQtZXJyb3I+XG4gICAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cbiAgICAgICAgICA8bmctdGVtcGxhdGUgI3JlYWRPbmx5VGVtcGxhdGU+XG4gICAgICAgICAgICA8aW9uLWxhYmVsIGFwcEF1dG9Ub29sdGlwPlxuICAgICAgICAgICAgICB7eyAocm93LnZhbGlkYXRvciB8IGZvcm1HZXRWYWx1ZTogJ25hbWUnKSB8fCAocm93LmN1cnJlbnREYXRhIHwgcHJvcGVydHlHZXQ6ICduYW1lJykgfX1cbiAgICAgICAgICAgIDwvaW9uLWxhYmVsPlxuICAgICAgICAgIDwvbmctdGVtcGxhdGU+XG4gICAgICAgIDwvdGQ+XG4gICAgICA8L25nLWNvbnRhaW5lcj5cblxuICAgICAgPCEtLSBMZXZlbCBjb2x1bW4gLS0+XG4gICAgICA8bmctY29udGFpbmVyIG1hdENvbHVtbkRlZj1cImxldmVsSWRcIj5cbiAgICAgICAgPHRoIG1hdC1oZWFkZXItY2VsbCAqbWF0SGVhZGVyQ2VsbERlZiBbcmVzaXphYmxlXT1cInJlc2l6YWJsZVwiPlxuICAgICAgICAgIDxzcGFuIG1hdC1zb3J0LWhlYWRlcj5cbiAgICAgICAgICAgIDxpb24tbGFiZWw+e3sgJ1RBQkxFLlRFU1RJTkcuTEVWRUxfSUQnIHwgdHJhbnNsYXRlIH19PC9pb24tbGFiZWw+XG4gICAgICAgICAgICA8aW9uLWxhYmVsIGNvbG9yPVwiZGFuZ2VyXCIgW2lubmVySFRNTF09XCInJm5ic3A7KidcIj48L2lvbi1sYWJlbD5cbiAgICAgICAgICA8L3NwYW4+XG4gICAgICAgIDwvdGg+XG4gICAgICAgIDx0ZCBtYXQtY2VsbCAqbWF0Q2VsbERlZj1cImxldCByb3dcIiBbYXBwQ2VsbElkXT1cInsgcm93SWQ6IHJvdy5pZCwgY29sdW1uTmFtZTogJ2xldmVsSWQnIH1cIj5cbiAgICAgICAgICA8bWF0LWF1dG9jb21wbGV0ZS1maWVsZFxuICAgICAgICAgICAgKm5nSWY9XCIhcmVhZE9ubHkgJiYgcm93LmVkaXRpbmc7IGVsc2UgcmVhZE9ubHlUZW1wbGF0ZVwiXG4gICAgICAgICAgICBwYW5lbFdpZHRoPVwiNzUwcHhcIlxuICAgICAgICAgICAgW2Zvcm1Db250cm9sXT1cInJvdy52YWxpZGF0b3IgfCBmb3JtR2V0Q29udHJvbDogJ2xldmVsSWQnXCJcbiAgICAgICAgICAgIFtwbGFjZWhvbGRlcl09XCInVEFCTEUuVEVTVElORy5MRVZFTF9JRCcgfCB0cmFuc2xhdGVcIlxuICAgICAgICAgICAgZmxvYXRMYWJlbD1cIm5ldmVyXCJcbiAgICAgICAgICAgIFtyZXF1aXJlZF09XCJ0cnVlXCJcbiAgICAgICAgICAgIFtjb25maWddPVwiYXV0b2NvbXBsZXRlRmllbGRzLmxldmVsXCJcbiAgICAgICAgICAgIFtoaWdobGlnaHRBY2NlbnRdPVwidHJ1ZVwiXG4gICAgICAgICAgPlxuICAgICAgICAgICAgPG1hdC1lcnJvciBtYXRFcnJvciAqbmdJZj1cIihyb3cudmFsaWRhdG9yIHwgZm9ybUdldENvbnRyb2w6ICdsZXZlbElkJykuaGFzRXJyb3IoJ2ludmFsaWQnKVwiIHRyYW5zbGF0ZT5cbiAgICAgICAgICAgICAgRVJST1IuRklFTERfSU5WQUxJRFxuICAgICAgICAgICAgPC9tYXQtZXJyb3I+XG4gICAgICAgICAgPC9tYXQtYXV0b2NvbXBsZXRlLWZpZWxkPlxuICAgICAgICAgIDxuZy10ZW1wbGF0ZSAjcmVhZE9ubHlUZW1wbGF0ZT5cbiAgICAgICAgICAgIDxpb24tbGFiZWwgYXBwQXV0b1Rvb2x0aXA+XG4gICAgICAgICAgICAgIHt7XG4gICAgICAgICAgICAgICAgYXV0b2NvbXBsZXRlRmllbGRzLmxldmVsPy5kaXNwbGF5V2l0aChcbiAgICAgICAgICAgICAgICAgIChyb3cudmFsaWRhdG9yIHwgZm9ybUdldFZhbHVlOiAnbGV2ZWxJZCcpIHx8IChyb3cuY3VycmVudERhdGEgfCBwcm9wZXJ0eUdldDogJ2xldmVsSWQnKVxuICAgICAgICAgICAgICAgICkgfHxcbiAgICAgICAgICAgICAgICAgICgocm93LnZhbGlkYXRvciB8IGZvcm1HZXRWYWx1ZTogJ2xldmVsSWQnKSB8fCAocm93LmN1cnJlbnREYXRhIHwgcHJvcGVydHlHZXQ6ICdsZXZlbElkJylcbiAgICAgICAgICAgICAgICAgICAgfCByZWZlcmVudGlhbFRvU3RyaW5nKVxuICAgICAgICAgICAgICB9fVxuICAgICAgICAgICAgPC9pb24tbGFiZWw+XG4gICAgICAgICAgPC9uZy10ZW1wbGF0ZT5cbiAgICAgICAgPC90ZD5cbiAgICAgIDwvbmctY29udGFpbmVyPlxuXG4gICAgICA8bmctY29udGFpbmVyIG1hdENvbHVtbkRlZj1cImJvb2xlYW5cIj5cbiAgICAgICAgPHRoIG1hdC1oZWFkZXItY2VsbCAqbWF0SGVhZGVyQ2VsbERlZiBjZGtEcmFnIFtyZXNpemFibGVdPVwicmVzaXphYmxlXCI+XG4gICAgICAgICAgPCEtLSBpZiBzb3J0YWJsZSwgd3JhcCB0aGUgaGVhZGVyIHdpdGggYSBtYXQtc29ydC1oZWFkZXIgLS0+XG4gICAgICAgICAgPHNwYW4gbWF0LXNvcnQtaGVhZGVyPlxuICAgICAgICAgICAgPGlvbi1sYWJlbD5Cb29sZWFuPC9pb24tbGFiZWw+XG4gICAgICAgICAgPC9zcGFuPlxuICAgICAgICA8L3RoPlxuICAgICAgICA8dGQgbWF0LWNlbGwgKm1hdENlbGxEZWY9XCJsZXQgcm93XCIgW2FwcENlbGxJZF09XCJ7IHJvd0lkOiByb3cuaWQsIGNvbHVtbk5hbWU6ICdib29sZWFuJyB9XCI+XG4gICAgICAgICAgPG1hdC1ib29sZWFuLWZpZWxkXG4gICAgICAgICAgICAqbmdJZj1cIiFyZWFkT25seSAmJiByb3cuZWRpdGluZzsgZWxzZSByZWFkT25seVRlbXBsYXRlXCJcbiAgICAgICAgICAgIGZsb2F0TGFiZWw9XCJuZXZlclwiXG4gICAgICAgICAgICBbc3R5bGVdPVwiJ2NoZWNrYm94J1wiXG4gICAgICAgICAgICBbZm9ybUNvbnRyb2xdPVwiXG4gICAgICAgICAgICAgIChyb3cudmFsaWRhdG9yIHwgZm9ybUdldENvbnRyb2w6ICdib29sZWFuJykgfHwgZm9ybUJ1aWxkZXIuY29udHJvbChyb3cuY3VycmVudERhdGFbJ2Jvb2xlYW4nXSlcbiAgICAgICAgICAgIFwiXG4gICAgICAgICAgICBbY29tcGFjdF09XCJ0cnVlXCJcbiAgICAgICAgICA+PC9tYXQtYm9vbGVhbi1maWVsZD5cbiAgICAgICAgICA8bmctdGVtcGxhdGUgI3JlYWRPbmx5VGVtcGxhdGU+XG4gICAgICAgICAgICA8aW9uLWxhYmVsIGFwcEF1dG9Ub29sdGlwPlxuICAgICAgICAgICAgICB7e1xuICAgICAgICAgICAgICAgIChyb3cudmFsaWRhdG9yIHwgZm9ybUdldFZhbHVlOiAnYm9vbGVhbicpIHx8IChyb3cuY3VycmVudERhdGEgfCBwcm9wZXJ0eUdldDogJ2Jvb2xlYW4nKVxuICAgICAgICAgICAgICAgICAgPyAoJ0NPTU1PTi5ZRVMnIHwgdHJhbnNsYXRlKVxuICAgICAgICAgICAgICAgICAgOiAoJ0NPTU1PTi5OTycgfCB0cmFuc2xhdGUpXG4gICAgICAgICAgICAgIH19XG4gICAgICAgICAgICA8L2lvbi1sYWJlbD5cbiAgICAgICAgICA8L25nLXRlbXBsYXRlPlxuICAgICAgICA8L3RkPlxuICAgICAgPC9uZy1jb250YWluZXI+XG5cbiAgICAgIDxuZy1jb250YWluZXIgbWF0Q29sdW1uRGVmPVwiYm9vbGVhbjJcIj5cbiAgICAgICAgPHRoIG1hdC1oZWFkZXItY2VsbCAqbWF0SGVhZGVyQ2VsbERlZiBjZGtEcmFnIFtyZXNpemFibGVdPVwicmVzaXphYmxlXCI+XG4gICAgICAgICAgPCEtLSBpZiBzb3J0YWJsZSwgd3JhcCB0aGUgaGVhZGVyIHdpdGggYSBtYXQtc29ydC1oZWFkZXIgLS0+XG4gICAgICAgICAgPHNwYW4gbWF0LXNvcnQtaGVhZGVyPlxuICAgICAgICAgICAgPGlvbi1sYWJlbD5Cb29sZWFuIDI8L2lvbi1sYWJlbD5cbiAgICAgICAgICA8L3NwYW4+XG4gICAgICAgIDwvdGg+XG4gICAgICAgIDx0ZCBtYXQtY2VsbCAqbWF0Q2VsbERlZj1cImxldCByb3dcIj5cbiAgICAgICAgICA8bWF0LWJvb2xlYW4tZmllbGRcbiAgICAgICAgICAgICpuZ0lmPVwiIXJlYWRPbmx5ICYmIHJvdy5lZGl0aW5nOyBlbHNlIHJlYWRPbmx5VGVtcGxhdGVcIlxuICAgICAgICAgICAgW2Zsb2F0TGFiZWxdPVwiJ25ldmVyJ1wiXG4gICAgICAgICAgICBbc3R5bGVdPVwiJ3JhZGlvJ1wiXG4gICAgICAgICAgICBbc2hvd1JhZGlvXT1cInRydWVcIlxuICAgICAgICAgICAgW2Zvcm1Db250cm9sXT1cIlxuICAgICAgICAgICAgICAocm93LnZhbGlkYXRvciB8IGZvcm1HZXRDb250cm9sOiAnYm9vbGVhbjInKSB8fCBmb3JtQnVpbGRlci5jb250cm9sKHJvdy5jdXJyZW50RGF0YVsnYm9vbGVhbjInXSlcbiAgICAgICAgICAgIFwiXG4gICAgICAgICAgPjwvbWF0LWJvb2xlYW4tZmllbGQ+XG4gICAgICAgICAgPG5nLXRlbXBsYXRlICNyZWFkT25seVRlbXBsYXRlPlxuICAgICAgICAgICAgPGlvbi1sYWJlbCBhcHBBdXRvVG9vbHRpcD5cbiAgICAgICAgICAgICAge3tcbiAgICAgICAgICAgICAgICAocm93LnZhbGlkYXRvciB8IGZvcm1HZXRWYWx1ZTogJ2Jvb2xlYW4yJykgfHwgKHJvdy5jdXJyZW50RGF0YSB8IHByb3BlcnR5R2V0OiAnYm9vbGVhbjInKVxuICAgICAgICAgICAgICAgICAgPyAoJ0NPTU1PTi5ZRVMnIHwgdHJhbnNsYXRlKVxuICAgICAgICAgICAgICAgICAgOiAoJ0NPTU1PTi5OTycgfCB0cmFuc2xhdGUpXG4gICAgICAgICAgICAgIH19XG4gICAgICAgICAgICA8L2lvbi1sYWJlbD5cbiAgICAgICAgICA8L25nLXRlbXBsYXRlPlxuICAgICAgICA8L3RkPlxuICAgICAgPC9uZy1jb250YWluZXI+XG5cbiAgICAgIDxuZy1jb250YWluZXIgbWF0Q29sdW1uRGVmPVwiYm9vbGVhbjNcIj5cbiAgICAgICAgPHRoIG1hdC1oZWFkZXItY2VsbCAqbWF0SGVhZGVyQ2VsbERlZiBjZGtEcmFnIFtyZXNpemFibGVdPVwicmVzaXphYmxlXCI+XG4gICAgICAgICAgPCEtLSBpZiBzb3J0YWJsZSwgd3JhcCB0aGUgaGVhZGVyIHdpdGggYSBtYXQtc29ydC1oZWFkZXIgLS0+XG4gICAgICAgICAgPHNwYW4gbWF0LXNvcnQtaGVhZGVyPlxuICAgICAgICAgICAgPGlvbi1sYWJlbD5Cb29sZWFuIDM8L2lvbi1sYWJlbD5cbiAgICAgICAgICA8L3NwYW4+XG4gICAgICAgIDwvdGg+XG4gICAgICAgIDx0ZCBtYXQtY2VsbCAqbWF0Q2VsbERlZj1cImxldCByb3dcIj5cbiAgICAgICAgICA8bWF0LWJvb2xlYW4tZmllbGRcbiAgICAgICAgICAgICpuZ0lmPVwiIXJlYWRPbmx5ICYmIHJvdy5lZGl0aW5nOyBlbHNlIHJlYWRPbmx5VGVtcGxhdGVcIlxuICAgICAgICAgICAgZmxvYXRMYWJlbD1cIm5ldmVyXCJcbiAgICAgICAgICAgIFtzdHlsZV09XCInYnV0dG9uJ1wiXG4gICAgICAgICAgICBbZm9ybUNvbnRyb2xdPVwiXG4gICAgICAgICAgICAgIChyb3cudmFsaWRhdG9yIHwgZm9ybUdldENvbnRyb2w6ICdib29sZWFuMicpIHx8IGZvcm1CdWlsZGVyLmNvbnRyb2wocm93LmN1cnJlbnREYXRhWydib29sZWFuMiddKVxuICAgICAgICAgICAgXCJcbiAgICAgICAgICA+PC9tYXQtYm9vbGVhbi1maWVsZD5cbiAgICAgICAgICA8bmctdGVtcGxhdGUgI3JlYWRPbmx5VGVtcGxhdGU+XG4gICAgICAgICAgICA8aW9uLWxhYmVsIGFwcEF1dG9Ub29sdGlwPlxuICAgICAgICAgICAgICB7e1xuICAgICAgICAgICAgICAgIChyb3cudmFsaWRhdG9yIHwgZm9ybUdldFZhbHVlOiAnYm9vbGVhbjInKSB8fCAocm93LmN1cnJlbnREYXRhIHwgcHJvcGVydHlHZXQ6ICdib29sZWFuMicpXG4gICAgICAgICAgICAgICAgICA/ICgnQ09NTU9OLllFUycgfCB0cmFuc2xhdGUpXG4gICAgICAgICAgICAgICAgICA6ICgnQ09NTU9OLk5PJyB8IHRyYW5zbGF0ZSlcbiAgICAgICAgICAgICAgfX1cbiAgICAgICAgICAgIDwvaW9uLWxhYmVsPlxuICAgICAgICAgIDwvbmctdGVtcGxhdGU+XG4gICAgICAgIDwvdGQ+XG4gICAgICA8L25nLWNvbnRhaW5lcj5cblxuICAgICAgPCEtLSBBY3Rpb25zIGJ1dHRvbnMgY29sdW1uIC0tPlxuICAgICAgPGFwcC1hY3Rpb25zLWNvbHVtblxuICAgICAgICBbc3RpY2t5RW5kXT1cInN0aWNreUVuZFwiXG4gICAgICAgIFtjYW5DYW5jZWxdPVwiZmFsc2VcIlxuICAgICAgICBbc3R5bGVdPVwiJ3RhYmxlJ1wiXG4gICAgICAgIChvcHRpb25zQ2xpY2spPVwib3BlblNlbGVjdENvbHVtbnNNb2RhbCgkZXZlbnQpXCJcbiAgICAgICAgKGNhbmNlbE9yRGVsZXRlQ2xpY2spPVwiY2FuY2VsT3JEZWxldGUoJGV2ZW50LmV2ZW50LCAkZXZlbnQucm93KVwiXG4gICAgICAgIChjb25maXJtQW5kQWRkQ2xpY2spPVwiY29uZmlybUFuZEFkZCgkZXZlbnQuZXZlbnQsICRldmVudC5yb3cpXCJcbiAgICAgICAgKGJhY2t3YXJkKT1cImNvbmZpcm1BbmRCYWNrd2FyZCgkZXZlbnQuZXZlbnQsICRldmVudC5yb3cpXCJcbiAgICAgICAgKGZvcndhcmQpPVwiY29uZmlybUFuZEZvcndhcmQoJGV2ZW50LmV2ZW50LCAkZXZlbnQucm93KVwiXG4gICAgICAgIFtjZWxsVGVtcGxhdGVdPVwiY2VsbEluamVjdGlvblwiXG4gICAgICA+XG4gICAgICAgIDwhLS0gY2VsbCBpbmplY3Rpb24tLT5cbiAgICAgICAgPG5nLXRlbXBsYXRlICNjZWxsSW5qZWN0aW9uIGxldC1yb3c+XG4gICAgICAgICAgPHNwYW4gKm5nSWY9XCJyb3cuZWRpdGluZyAmJiAhcm93LnZhbGlkYXRvci5kaXJ0eVwiPi08L3NwYW4+XG4gICAgICAgIDwvbmctdGVtcGxhdGU+XG4gICAgICA8L2FwcC1hY3Rpb25zLWNvbHVtbj5cblxuICAgICAgPHRyIG1hdC1oZWFkZXItcm93ICptYXRIZWFkZXJSb3dEZWY9XCJkaXNwbGF5ZWRDb2x1bW5zOyBzdGlja3k6IHRydWVcIj48L3RyPlxuICAgICAgPHRyXG4gICAgICAgIG1hdC1yb3dcbiAgICAgICAgKm1hdFJvd0RlZj1cImxldCByb3c7IGNvbHVtbnM6IGRpc3BsYXllZENvbHVtbnNcIlxuICAgICAgICBbY2xhc3MubWF0LXJvdy1zZWxlY3RlZF09XCJyb3cuZWRpdGluZ1wiXG4gICAgICAgIFtjbGFzcy5tYXQtcm93LWVycm9yXT1cInJvdy5pbnZhbGlkXCJcbiAgICAgICAgW2NsYXNzLm1hdC1yb3ctZGlzYWJsZWRdPVwiIXJvdy5lZGl0aW5nXCJcbiAgICAgICAgW2NsYXNzLm1hdC1yb3ctZGlydHldPVwicm93LmRpcnR5XCJcbiAgICAgICAgKGNsaWNrKT1cImNsaWNrUm93KCRldmVudCwgcm93KVwiXG4gICAgICAgIChrZXlkb3duLmVzY2FwZSk9XCJlc2NhcGVFZGl0aW5nUm93KCRldmVudClcIlxuICAgICAgICBbY2RrVHJhcEZvY3VzXT1cInJvdy5pbnZhbGlkXCJcbiAgICAgID48L3RyPlxuICAgIDwvdGFibGU+XG5cbiAgICA8bmctY29udGFpbmVyICpuZ0lmPVwibG9hZGluZ1N1YmplY3QgfCBhc3luYzsgZWxzZSBub1Jlc3VsdFwiPlxuICAgICAgPGlvbi1pdGVtPlxuICAgICAgICA8aW9uLXNrZWxldG9uLXRleHQgYW5pbWF0ZWQ+PC9pb24tc2tlbGV0b24tdGV4dD5cbiAgICAgIDwvaW9uLWl0ZW0+XG4gICAgPC9uZy1jb250YWluZXI+XG5cbiAgICA8bmctdGVtcGxhdGUgI25vUmVzdWx0PlxuICAgICAgPGlvbi1pdGVtICpuZ0lmPVwidG90YWxSb3dDb3VudCA9PT0gMFwiPlxuICAgICAgICA8aW9uLXRleHQgY29sb3I9XCJkYW5nZXJcIiBjbGFzcz1cInRleHQtaXRhbGljXCIgdHJhbnNsYXRlPkNPTU1PTi5OT19SRVNVTFQ8L2lvbi10ZXh0PlxuICAgICAgPC9pb24taXRlbT5cbiAgICA8L25nLXRlbXBsYXRlPlxuXG4gICAgPGlvbi1pbmZpbml0ZS1zY3JvbGxcbiAgICAgICpuZ0lmPVwiZW5hYmxlSW5maW5pdGVTY3JvbGxcIlxuICAgICAgW3RocmVzaG9sZF09XCJtb2JpbGUgPyAnMTAlJyA6ICcyJSdcIlxuICAgICAgcG9zaXRpb249XCJib3R0b21cIlxuICAgICAgKGlvbkluZmluaXRlKT1cImZldGNoTW9yZSgkZXZlbnQpXCJcbiAgICA+XG4gICAgICA8aW9uLWluZmluaXRlLXNjcm9sbC1jb250ZW50XG4gICAgICAgIGxvYWRpbmdTcGlubmVyPVwiY2lyY2xlc1wiXG4gICAgICAgIFtsb2FkaW5nVGV4dF09XCInQ09NTU9OLkxPQURJTkdfRE9UUycgfCB0cmFuc2xhdGVcIlxuICAgICAgPjwvaW9uLWluZmluaXRlLXNjcm9sbC1jb250ZW50PlxuICAgIDwvaW9uLWluZmluaXRlLXNjcm9sbD5cbiAgPC9kaXY+XG48L2lvbi1jb250ZW50PlxuXG48aW9uLWZvb3Rlcj5cbiAgPCEtLSBQYWdpbmF0b3IgIC0tPlxuICA8bWF0LXBhZ2luYXRvclxuICAgICpuZ0lmPVwiIWVuYWJsZUluZmluaXRlU2Nyb2xsXCJcbiAgICBbbGVuZ3RoXT1cInRvdGFsUm93Q291bnRcIlxuICAgIFtwYWdlU2l6ZV09XCJkZWZhdWx0UGFnZVNpemVcIlxuICAgIFtwYWdlU2l6ZU9wdGlvbnNdPVwiZGVmYXVsdFBhZ2VTaXplT3B0aW9uc1wiXG4gICAgc2hvd0ZpcnN0TGFzdEJ1dHRvbnNcbiAgPjwvbWF0LXBhZ2luYXRvcj5cblxuICA8YXBwLWZvcm0tYnV0dG9ucy1iYXJcbiAgICAqbmdJZj1cImNhbkVkaXQgJiYgIW1vYmlsZVwiXG4gICAgKG9uQ2FuY2VsKT1cImxvYWQoKVwiXG4gICAgKG9uU2F2ZSk9XCJzYXZlKClcIlxuICAgIFtkaXNhYmxlZF09XCIobG9hZGluZ1N1YmplY3QgfCBhc3luYykgfHwgIWRpcnR5XCJcbiAgPlxuICAgIDwhLS0gZXJyb3IgLS0+XG4gICAgPGlvbi1pdGVtICpuZ0lmPVwiZXJyb3JTdWJqZWN0IHwgYXN5bmNcIiBsaW5lcz1cIm5vbmVcIj5cbiAgICAgIDxpb24taWNvbiBjb2xvcj1cImRhbmdlclwiIHNsb3Q9XCJzdGFydFwiIG5hbWU9XCJhbGVydC1jaXJjbGVcIj48L2lvbi1pY29uPlxuICAgICAgPGlvbi1sYWJlbCBjb2xvcj1cImRhbmdlclwiIFtpbm5lckhUTUxdPVwiZXJyb3IgfCB0cmFuc2xhdGVcIj48L2lvbi1sYWJlbD5cbiAgICA8L2lvbi1pdGVtPlxuICA8L2FwcC1mb3JtLWJ1dHRvbnMtYmFyPlxuPC9pb24tZm9vdGVyPlxuXG48aW9uLWZhYiBzbG90PVwiZml4ZWRcIiB2ZXJ0aWNhbD1cImJvdHRvbVwiIGhvcml6b250YWw9XCJlbmRcIiAqbmdJZj1cImNhbkVkaXQgJiYgbW9iaWxlXCI+XG4gIDxpb24tZmFiLWJ1dHRvbiBjb2xvcj1cInRlcnRpYXJ5XCIgKGNsaWNrKT1cImFkZFJvdygkZXZlbnQpXCI+XG4gICAgPGlvbi1pY29uIG5hbWU9XCJhZGRcIj48L2lvbi1pY29uPlxuICA8L2lvbi1mYWItYnV0dG9uPlxuPC9pb24tZmFiPlxuIl19
|