@sumaris-net/ngx-components 18.17.2 → 18.17.3
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/esm2022/src/app/admin/users/person.filter.mjs +4 -1
- package/esm2022/src/app/admin/users/users.mjs +37 -17
- package/esm2022/src/app/social/feed/feed.service.mjs +22 -10
- package/esm2022/src/app/social/message/message.form.mjs +7 -3
- package/esm2022/src/app/social/message/message.modal.mjs +4 -4
- package/esm2022/src/app/social/message/message.model.mjs +5 -1
- package/esm2022/src/app/social/message/message.module.mjs +7 -5
- package/esm2022/src/app/social/message/message.service.mjs +3 -1
- package/fesm2022/sumaris-net.ngx-components.mjs +60 -19
- package/fesm2022/sumaris-net.ngx-components.mjs.map +1 -1
- package/package.json +1 -1
- package/src/app/admin/users/users.d.ts +2 -0
- package/src/app/social/feed/feed.service.d.ts +4 -2
- package/src/app/social/message/message.model.d.ts +2 -0
- package/src/app/social/message/message.module.d.ts +2 -1
- package/src/assets/i18n/en-US.json +1 -0
- package/src/assets/i18n/en.json +1 -0
- package/src/assets/i18n/fr.json +1 -0
- package/src/assets/manifest.json +1 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { booleanAttribute, ChangeDetectionStrategy, Component, Inject, Input, ViewChild } from '@angular/core';
|
|
2
2
|
import { Person, PRIORITIZED_AUTHORITIES } from '../../core/services/model/person.model';
|
|
3
|
-
import { StatusById, StatusList } from '../../core/services/model/referential.model';
|
|
3
|
+
import { ReferentialRef, StatusById, StatusList } from '../../core/services/model/referential.model';
|
|
4
4
|
import { PersonValidatorService } from './person.validator';
|
|
5
5
|
import { AppTable } from '../../core/table/table.class';
|
|
6
6
|
import { ValidatorService } from '@e-is/ngx-material-table';
|
|
@@ -44,18 +44,19 @@ import * as i23 from "@angular/material/core";
|
|
|
44
44
|
import * as i24 from "@angular/material/divider";
|
|
45
45
|
import * as i25 from "@angular/material/badge";
|
|
46
46
|
import * as i26 from "@angular/cdk/a11y";
|
|
47
|
-
import * as i27 from "../../shared/
|
|
48
|
-
import * as i28 from "../../shared/directives/
|
|
49
|
-
import * as i29 from "../../shared/
|
|
50
|
-
import * as i30 from "../../shared/
|
|
51
|
-
import * as i31 from "../../
|
|
52
|
-
import * as i32 from "../../core/
|
|
53
|
-
import * as i33 from "../../
|
|
54
|
-
import * as i34 from "../../shared/
|
|
55
|
-
import * as i35 from "../../shared/pipes/
|
|
56
|
-
import * as i36 from "../../shared/pipes/
|
|
57
|
-
import * as i37 from "../../shared/pipes/
|
|
58
|
-
import * as i38 from "../../
|
|
47
|
+
import * as i27 from "../../shared/material/chips/material.chips";
|
|
48
|
+
import * as i28 from "../../shared/directives/autofocus.directive";
|
|
49
|
+
import * as i29 from "../../shared/directives/autotitle.directive";
|
|
50
|
+
import * as i30 from "../../shared/toolbar/toolbar";
|
|
51
|
+
import * as i31 from "../../shared/form/field.component";
|
|
52
|
+
import * as i32 from "../../core/form/buttons/form-buttons-bar.component";
|
|
53
|
+
import * as i33 from "../../core/table/column/actions-column.component";
|
|
54
|
+
import * as i34 from "../../shared/debug/debug.component";
|
|
55
|
+
import * as i35 from "../../shared/pipes/date-format.pipe";
|
|
56
|
+
import * as i36 from "../../shared/pipes/number-format.pipe";
|
|
57
|
+
import * as i37 from "../../shared/pipes/form.pipes";
|
|
58
|
+
import * as i38 from "../../shared/pipes/selection.pipes";
|
|
59
|
+
import * as i39 from "../../core/table/table.pipes";
|
|
59
60
|
export class UsersPage extends AppTable {
|
|
60
61
|
accountService;
|
|
61
62
|
validatorService;
|
|
@@ -69,6 +70,10 @@ export class UsersPage extends AppTable {
|
|
|
69
70
|
profiles = [...PRIORITIZED_AUTHORITIES].reverse();
|
|
70
71
|
statusList = StatusList;
|
|
71
72
|
statusById = StatusById;
|
|
73
|
+
userProfileList = PRIORITIZED_AUTHORITIES.map((label) => ReferentialRef.fromObject({
|
|
74
|
+
label,
|
|
75
|
+
name: `USER.PROFILE_ENUM.${label}`,
|
|
76
|
+
}));
|
|
72
77
|
additionalFields;
|
|
73
78
|
filterCriteriaCount = 0;
|
|
74
79
|
defaultCompact = false;
|
|
@@ -115,6 +120,7 @@ export class UsersPage extends AppTable {
|
|
|
115
120
|
this.filterForm = formBuilder.group({
|
|
116
121
|
searchText: [null],
|
|
117
122
|
statusId: [null],
|
|
123
|
+
userProfiles: [null],
|
|
118
124
|
});
|
|
119
125
|
this.additionalFields = (this.accountService.additionalFields || [])
|
|
120
126
|
.filter((field) => isNotNil(field.autocomplete))
|
|
@@ -146,6 +152,10 @@ export class UsersPage extends AppTable {
|
|
|
146
152
|
state: { animated: false },
|
|
147
153
|
});
|
|
148
154
|
}));
|
|
155
|
+
// Translate user profiles
|
|
156
|
+
this.userProfileList.forEach((profile) => {
|
|
157
|
+
profile.name = this.translate.instant(profile.name);
|
|
158
|
+
});
|
|
149
159
|
// For DEV only --
|
|
150
160
|
this.debug = !environment.production;
|
|
151
161
|
}
|
|
@@ -195,7 +205,7 @@ export class UsersPage extends AppTable {
|
|
|
195
205
|
// Save filter in settings (after a debounce time)
|
|
196
206
|
debounceTime(500), filter(() => isNotNilOrBlank(this.settingsId) && this.usePageSettings), tap((json) => this.settings.savePageSetting(this.settingsId, json, TABLE_SETTINGS_ENUM.FILTER_KEY)))
|
|
197
207
|
.subscribe());
|
|
198
|
-
if (this.canSendMessage
|
|
208
|
+
if (this.canSendMessage) {
|
|
199
209
|
await this.menuService.addSubMenuItems([
|
|
200
210
|
{
|
|
201
211
|
parentPath: '/admin/users',
|
|
@@ -235,6 +245,15 @@ export class UsersPage extends AppTable {
|
|
|
235
245
|
console.debug('[users] Restoring filter from settings...');
|
|
236
246
|
const json = this.settings.getPageSettings(this.settingsId, TABLE_SETTINGS_ENUM.FILTER_KEY) || {};
|
|
237
247
|
const filter = PersonFilter.fromObject(json);
|
|
248
|
+
json.userProfiles = Array.isArray(json.userProfiles)
|
|
249
|
+
? json.userProfiles.map((up) => {
|
|
250
|
+
const label = up.label ?? up;
|
|
251
|
+
return ReferentialRef.fromObject({
|
|
252
|
+
label,
|
|
253
|
+
name: this.translate.instant(`USER.PROFILE_ENUM.${label}`),
|
|
254
|
+
});
|
|
255
|
+
})
|
|
256
|
+
: null;
|
|
238
257
|
this.filterForm.patchValue(json);
|
|
239
258
|
this.setFilter(filter, { emitEvent: true });
|
|
240
259
|
}
|
|
@@ -264,6 +283,7 @@ export class UsersPage extends AppTable {
|
|
|
264
283
|
recipients,
|
|
265
284
|
recipientFilter,
|
|
266
285
|
}),
|
|
286
|
+
debug: this.debug,
|
|
267
287
|
});
|
|
268
288
|
}
|
|
269
289
|
async restoreCompactMode(opts) {
|
|
@@ -349,11 +369,11 @@ export class UsersPage extends AppTable {
|
|
|
349
369
|
CsvUtils.exportToFile(rows, { filename, headers, separator, encoding });
|
|
350
370
|
}
|
|
351
371
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: UsersPage, deps: [{ token: i0.Injector }, { token: i1.UntypedFormBuilder }, { token: i2.AccountService }, { token: i3.ValidatorService }, { token: i4.ConfigService }, { token: i5.PersonService }, { token: i6.MessageService }, { token: i7.MenuService }, { token: ENVIRONMENT }], target: i0.ɵɵFactoryTarget.Component });
|
|
352
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: UsersPage, selector: "app-users-table", inputs: { compact: ["compact", "compact", booleanAttribute], usePageSettings: ["usePageSettings", "usePageSettings", booleanAttribute], sticky: ["sticky", "sticky", booleanAttribute], stickyEnd: ["stickyEnd", "stickyEnd", booleanAttribute], canDownload: ["canDownload", "canDownload", booleanAttribute] }, providers: [{ provide: ValidatorService, useExisting: PersonValidatorService }], viewQueries: [{ propertyName: "filterExpansionPanel", first: true, predicate: MatExpansionPanel, descendants: true, static: true }], usesInheritance: true, ngImport: i0, template: "<app-toolbar\n [title]=\"'USER.LIST.TITLE' | translate\"\n color=\"primary\"\n [canGoBack]=\"false\"\n [hasValidate]=\"(loadingSubject | async) !== true && (dirtySubject | async) === true\"\n (onValidate)=\"save()\"\n>\n <ion-buttons slot=\"end\">\n <!-- Compose message -->\n <button\n mat-icon-button\n *ngIf=\"canSendMessage\"\n [title]=\"'USER.LIST.BTN_SEND_MESSAGE' | translate\"\n (click)=\"openComposeMessageModal($event)\"\n >\n <ion-icon name=\"mail\" slot=\"icon-only\"></ion-icon>\n </button>\n\n @if (selection | isEmptySelection) {\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 <!-- Refresh -->\n <button mat-icon-button *ngIf=\"!mobile\" [title]=\"'COMMON.BTN_REFRESH' | translate\" (click)=\"emitRefresh()\">\n <mat-icon>refresh</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 } @else {\n <!-- delete -->\n <button\n mat-icon-button\n class=\"hidden-xs hidden-sm\"\n [title]=\"'COMMON.BTN_DELETE' | translate\"\n (click)=\"deleteSelection($event)\"\n >\n <mat-icon>delete</mat-icon>\n </button>\n }\n\n @if (!mobile) {\n <button mat-icon-button [title]=\"'COMMON.BTN_OPTIONS' | translate\" [matMenuTriggerFor]=\"toolbarOptionsMenu\">\n <mat-icon>more_vert</mat-icon>\n </button>\n }\n </ion-buttons>\n</app-toolbar>\n\n<!-- Toolbar option menu -->\n<mat-menu #toolbarOptionsMenu=\"matMenu\" xPosition=\"after\">\n <!-- export button -->\n <button mat-menu-item [disabled]=\"!canDownload\" (click)=\"exportToCsv($event)\">\n <mat-icon>download</mat-icon>\n <ion-label translate>FILE.CSV.BTN_DOWNLOAD_HELP</ion-label>\n </button>\n</mat-menu>\n\n<ion-content class=\"ion-no-padding\">\n <!-- error -->\n <ion-item\n *ngIf=\"errorSubject | async; let error\"\n lines=\"none\"\n class=\"hidden-sm hidden-xs hidden-mobile\"\n @slideUpDownAnimation\n >\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 <!-- debug -->\n <app-debug *ngIf=\"debug\">\n <ion-grid class=\"ion-no-padding\">\n <ion-row>\n <ion-col>\n focusColumn: {{ focusColumn }}\n <br />\n loadingSubject: {{ loading }}\n <br />\n </ion-col>\n </ion-row>\n </ion-grid>\n </app-debug>\n\n <!-- search -->\n <mat-expansion-panel #filterExpansionPanel class=\"ion-no-padding filter-panel filter-panel-floating\">\n <form class=\"form-container ion-padding\" [formGroup]=\"filterForm\" (ngSubmit)=\"emitRefresh()\">\n <ion-grid>\n <ion-row>\n <ion-col>\n <!-- search -->\n <mat-form-field>\n <mat-label>{{ 'USER.LIST.FILTER.SEARCH' | translate }}</mat-label>\n <input matInput formControlName=\"searchText\" />\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\n <ion-col>\n <!-- status -->\n <mat-form-field>\n <mat-label>{{ 'USER.STATUS' | translate }}</mat-label>\n <mat-select formControlName=\"statusId\">\n <mat-option [value]=\"null\">\n <i><span translate>COMMON.EMPTY_OPTION</span></i>\n </mat-option>\n <mat-option *ngFor=\"let item of statusList\" [value]=\"item.id\">\n <ion-icon [name]=\"item.icon\"></ion-icon>\n {{ item.label | translate }}\n </mat-option>\n </mat-select>\n\n <button\n mat-icon-button\n matSuffix\n tabindex=\"-1\"\n type=\"button\"\n (click)=\"clearControlValue($event, filterForm.controls.statusId)\"\n [hidden]=\"filterForm.controls.statusId.disabled || !filterForm.controls.statusId.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) === true || filterForm.dirty\"\n [color]=\"empty && 'danger'\"\n class=\"ion-padding\"\n >\n {{\n (totalRowCount ? 'COMMON.RESULT_COUNT' : 'COMMON.NO_RESULT')\n | translate\n : {\n count: (totalRowCount | numberFormat),\n }\n }}\n </ion-label>\n\n <div class=\"toolbar-spacer\"></div>\n\n <!-- Close panel -->\n <ion-button\n mat-button\n fill=\"clear\"\n color=\"dark\"\n (click)=\"filterExpansionPanel.close()\"\n [disabled]=\"loadingSubject | async\"\n >\n <ion-text translate>COMMON.BTN_CLOSE</ion-text>\n </ion-button>\n\n <!-- Search button -->\n <ion-button\n mat-button\n [color]=\"filterForm.dirty ? 'tertiary' : 'dark'\"\n [fill]=\"filterForm.dirty ? 'solid' : 'clear'\"\n (click)=\"applyFilterAndClosePanel($event)\"\n [disabled]=\"loadingSubject | async\"\n >\n <ion-text translate>COMMON.BTN_APPLY</ion-text>\n </ion-button>\n </mat-action-row>\n </mat-expansion-panel>\n\n <!-- error -->\n <ion-item *ngIf=\"mobile && (errorSubject | async); let error\" lines=\"none\">\n <ion-icon color=\"danger\" slot=\"start\" name=\"alert-circle\"></ion-icon>\n <ion-label color=\"danger\" class=\"error\" [innerHTML]=\"error | translate\"></ion-label>\n </ion-item>\n\n <div class=\"table-container\">\n <table\n #table\n mat-table\n matSort\n [class.compact]=\"compact\"\n [dataSource]=\"dataSource\"\n [matSortActive]=\"defaultSortBy\"\n [matSortDirection]=\"defaultSortDirection\"\n matSortDisableClear\n [trackBy]=\"trackByFn\"\n >\n <ng-container matColumnDef=\"select\" [sticky]=\"sticky\">\n <th mat-header-cell *matHeaderCellDef [class.cdk-visually-hidden]=\"!inlineEdition\">\n <mat-checkbox\n (change)=\"$event ? masterToggle() : null\"\n [checked]=\"this | isAllSelected\"\n [indeterminate]=\"this | isNotAllSelected\"\n ></mat-checkbox>\n </th>\n <td mat-cell *matCellDef=\"let row\" [class.cdk-visually-hidden]=\"!inlineEdition\">\n <mat-checkbox (click)=\"toggleSelectRow($event, row)\" [checked]=\"selection | isSelected: row\"></mat-checkbox>\n </td>\n </ng-container>\n\n <!-- Id Column -->\n <ng-container matColumnDef=\"id\" [sticky]=\"sticky\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>\n <ion-label>#</ion-label>\n </th>\n <td mat-cell *matCellDef=\"let row\">\n <ion-label>{{ row.currentData.id }}</ion-label>\n </td>\n </ng-container>\n\n <!-- avatar Column -->\n <ng-container matColumnDef=\"avatar\" [sticky]=\"sticky\">\n <th mat-header-cell *matHeaderCellDef></th>\n <td mat-cell *matCellDef=\"let row\">\n <ion-avatar [style.background-color]=\"'white'\">\n <ion-img *ngIf=\"row.currentData.avatar; let avatarUrl; else: generateIcon\" [src]=\"avatarUrl\"></ion-img>\n <ng-template #generateIcon>\n <svg width=\"39\" height=\"39\" [data-jdenticon-value]=\"row.currentData.id\"></svg>\n </ng-template>\n </ion-avatar>\n </td>\n </ng-container>\n\n <!-- lastName -->\n <ng-container matColumnDef=\"lastName\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>\n <span translate>USER.LAST_NAME</span>\n </th>\n <td mat-cell *matCellDef=\"let row\" (click)=\"focusColumn = 'lastName'\">\n <mat-form-field *ngIf=\"row.editing; else readonlyCell\">\n <input\n matInput\n [formControl]=\"row.validator.controls['lastName']\"\n [placeholder]=\"'USER.LAST_NAME' | translate\"\n [readonly]=\"!row.editing\"\n [appAutofocus]=\"row.editing && focusColumn === 'lastName'\"\n />\n <mat-error *ngIf=\"row.validator.controls['lastName'].hasError('required')\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n <mat-error *ngIf=\"row.validator.controls['lastName'].hasError('minlength')\">\n <span>{{ 'ERROR.FIELD_MIN_LENGTH' | translate: { requiredLength: 2 } }}</span>\n </mat-error>\n </mat-form-field>\n <ng-template #readonlyCell>\n <ion-label appAutoTitle>\n {{ row.validator | formGetValue: 'lastName' }}\n </ion-label>\n </ng-template>\n </td>\n </ng-container>\n\n <!-- firstname -->\n <ng-container matColumnDef=\"firstName\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>\n <span translate>USER.FIRST_NAME</span>\n </th>\n <td mat-cell *matCellDef=\"let row\" (click)=\"focusColumn = 'firstName'\">\n <mat-form-field *ngIf=\"row.editing; else readonlyCell\">\n <input\n matInput\n [formControl]=\"row.validator.controls['firstName']\"\n [placeholder]=\"'USER.FIRST_NAME' | translate\"\n [readonly]=\"!row.editing\"\n [appAutofocus]=\"row.editing && focusColumn === 'firstName'\"\n />\n <mat-error *ngIf=\"row.validator.controls['firstName'].hasError('required')\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n <mat-error *ngIf=\"row.validator.controls['firstName'].hasError('minlength')\">\n <span>{{ 'ERROR.FIELD_MIN_LENGTH' | translate: { requiredLength: 2 } }}</span>\n </mat-error>\n </mat-form-field>\n <ng-template #readonlyCell>\n <ion-label appAutoTitle>\n {{ row.validator | formGetValue: 'firstName' }}\n </ion-label>\n </ng-template>\n </td>\n </ng-container>\n\n <!-- email -->\n <ng-container matColumnDef=\"email\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>\n <span translate>USER.EMAIL</span>\n </th>\n <td mat-cell *matCellDef=\"let row\" (click)=\"focusColumn = 'email'\">\n <mat-form-field *ngIf=\"row.editing; else readonlyCell\">\n <input\n matInput\n [formControl]=\"row.validator.controls['email']\"\n [placeholder]=\"'USER.EMAIL' | translate\"\n [readonly]=\"!row.editing\"\n [appAutofocus]=\"row.editing && focusColumn === 'email'\"\n />\n <mat-error *ngIf=\"row.validator.controls['email'].hasError('required')\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n <mat-error *ngIf=\"row.validator.controls['email'].hasError('email')\">\n <span translate>ERROR.FIELD_NOT_VALID_EMAIL</span>\n </mat-error>\n </mat-form-field>\n <ng-template #readonlyCell>\n <ion-label appAutoTitle>\n {{ row.validator | formGetValue: 'email' }}\n </ion-label>\n </ng-template>\n </td>\n </ng-container>\n\n <!-- additional fields -->\n <ng-container *ngFor=\"let definition of additionalFields\" [matColumnDef]=\"definition.key\">\n <th mat-header-cell *matHeaderCellDef>\n <span>{{ definition.label | translate }}</span>\n </th>\n <td mat-cell *matCellDef=\"let row\" (click)=\"focusColumn = definition.key\">\n <app-form-field\n floatLabel=\"never\"\n [definition]=\"definition\"\n [formControl]=\"row.validator.controls[definition.key]\"\n [required]=\"definition.extra?.account?.required\"\n [autofocus]=\"row.editing && focusColumn === definition.key\"\n ></app-form-field>\n </td>\n </ng-container>\n\n <!-- profile column -->\n <ng-container matColumnDef=\"profile\">\n <th mat-header-cell *matHeaderCellDef>\n <span translate>USER.PROFILE</span>\n </th>\n <td mat-cell *matCellDef=\"let row\" (click)=\"focusColumn = 'profile'\">\n <mat-form-field>\n <mat-select\n [formControl]=\"row.validator.controls['mainProfile']\"\n [placeholder]=\"'USER.PROFILE' | translate\"\n >\n <mat-option *ngFor=\"let item of profiles\" [value]=\"item\">\n {{ 'USER.PROFILE_ENUM.' + item | uppercase | translate }}\n </mat-option>\n </mat-select>\n <mat-error *ngIf=\"row.validator.controls['mainProfile'].hasError('required')\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n </mat-form-field>\n </td>\n </ng-container>\n\n <!-- Status column -->\n <ng-container matColumnDef=\"status\">\n <th mat-header-cell *matHeaderCellDef>\n <span translate>USER.STATUS</span>\n </th>\n <td mat-cell *matCellDef=\"let row\" (click)=\"focusColumn = 'status'\">\n <mat-form-field>\n <mat-select\n [formControl]=\"row.validator.controls['statusId']\"\n [placeholder]=\"'REFERENTIAL.STATUS' | translate\"\n >\n <mat-select-trigger>\n <span *ngIf=\"row.validator.controls['statusId'].value >=0\">\n {{ statusById[row.validator.controls['statusId'].value]?.label | translate }}\n </span>\n </mat-select-trigger>\n <mat-option *ngFor=\"let item of statusList\" [value]=\"item.id\">\n <mat-icon><ion-icon [name]=\"item.icon\"></ion-icon></mat-icon>\n {{ item.label | translate }}\n </mat-option>\n </mat-select>\n <mat-error *ngIf=\"row.validator.controls['statusId'].hasError('required')\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n </mat-form-field>\n </td>\n </ng-container>\n\n <!-- username -->\n <ng-container matColumnDef=\"username\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>\n <span translate>USER.USERNAME</span>\n </th>\n <td mat-cell *matCellDef=\"let row\" (click)=\"focusColumn = 'username'\">\n <mat-form-field *ngIf=\"row.editing; else readonlyCell\">\n <input\n matInput\n [formControl]=\"row.validator.controls.username\"\n [placeholder]=\"'USER.USERNAME' | translate\"\n [readonly]=\"!row.editing\"\n [appAutofocus]=\"row.editing && focusColumn === 'username'\"\n />\n <mat-error *ngIf=\"row.validator.controls.username.hasError('required')\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n </mat-form-field>\n <ng-template #readonlyCell>\n <ion-label appAutoTitle>\n {{ row.validator | formGetValue: 'username' }}\n </ion-label>\n </ng-template>\n </td>\n </ng-container>\n\n <!-- username extranet -->\n <ng-container matColumnDef=\"usernameExtranet\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>\n <span translate>USER.USERNAME_EXTRANET</span>\n </th>\n <td mat-cell *matCellDef=\"let row\" (click)=\"focusColumn = 'usernameExtranet'\">\n <mat-form-field *ngIf=\"row.editing; else readonlyCell\">\n <input\n matInput\n [formControl]=\"row.validator.controls.usernameExtranet\"\n [placeholder]=\"'USER.USERNAME_EXTRANET' | translate\"\n [readonly]=\"!row.editing\"\n [appAutofocus]=\"row.editing && focusColumn === 'usernameExtranet'\"\n />\n <mat-error *ngIf=\"row.validator.controls.usernameExtranet.hasError('required')\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n </mat-form-field>\n <ng-template #readonlyCell>\n <ion-label appAutoTitle>\n {{ row.validator | formGetValue: 'usernameExtranet' }}\n </ion-label>\n </ng-template>\n </td>\n </ng-container>\n\n <!-- pubkey -->\n <ng-container matColumnDef=\"pubkey\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>\n <span translate>USER.PUBKEY</span>\n </th>\n <td\n mat-cell\n *matCellDef=\"let row\"\n [title]=\"row.validator.controls.pubkey.valueChanges | async\"\n (click)=\"focusColumn = 'pubkey'\"\n >\n <mat-form-field *ngIf=\"row.editing; else readonlyCell\">\n <input\n matInput\n [formControl]=\"row.validator.controls['pubkey']\"\n [placeholder]=\"'USER.PUBKEY' | translate\"\n [readonly]=\"!row.editing\"\n autocomplete=\"off\"\n />\n <mat-error *ngIf=\"row.validator.controls.pubkey.hasError('required')\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n <mat-error *ngIf=\"row.validator.controls.pubkey.hasError('pubkey')\">\n <span translate>ERROR.FIELD_NOT_VALID_PUBKEY</span>\n </mat-error>\n </mat-form-field>\n <ng-template #readonlyCell>\n <ion-label appAutoTitle>\n {{ row.validator | formGetValue: 'pubkey' }}\n </ion-label>\n </ng-template>\n </td>\n </ng-container>\n\n <!-- Creation date column -->\n <ng-container matColumnDef=\"creationDate\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>\n <ion-label translate>USER.CREATION_DATE</ion-label>\n </th>\n <td mat-cell *matCellDef=\"let row\" class=\"mat-form-field-disabled\">\n <ion-text class=\"ion-text-end\" color=\"medium\" *ngIf=\"row.id !== -1\">\n {{ row.currentData.creationDate | dateFormat: { time: true } }}\n </ion-text>\n </td>\n </ng-container>\n\n <!-- Update date column -->\n <ng-container matColumnDef=\"updateDate\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>\n <ion-label translate>USER.UPDATE_DATE</ion-label>\n </th>\n <td mat-cell *matCellDef=\"let row\" class=\"mat-form-field-disabled\">\n <ion-text class=\"ion-text-end\" color=\"medium\" *ngIf=\"row.id !== -1\">\n {{ row.currentData.updateDate | dateFormat: { time: true } }}\n </ion-text>\n </td>\n </ng-container>\n\n <!-- Actions buttons column -->\n <app-actions-column\n [stickyEnd]=\"stickyEnd\"\n (cancelOrDeleteClick)=\"cancelOrDelete($event.event, $event.row)\"\n (confirmEditCreateClick)=\"confirmEditCreate($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 [canCancel]=\"false\"\n >\n <!-- table options menu -->\n <button\n matHeader\n mat-icon-button\n [title]=\"'COMMON.BTN_OPTIONS' | translate\"\n [matMenuTriggerFor]=\"tableOptionsMenu\"\n >\n <mat-icon>more_vert</mat-icon>\n </button>\n </app-actions-column>\n\n <tr mat-header-row *matHeaderRowDef=\"displayedColumns; sticky: true\"></tr>\n <tr\n mat-row\n *matRowDef=\"let row; columns: displayedColumns\"\n [class.mat-row-selected]=\"row.editing\"\n [class.mat-row-error]=\"row.validator.invalid\"\n [class.mat-row-dirty]=\"row.currentData.dirty\"\n [class.mat-row-disabled]=\"!row.editing\"\n (click)=\"clickRow($event, row)\"\n (keydown.escape)=\"escapeEditingRow($event)\"\n [cdkTrapFocus]=\"!row.validator?.valid\"\n ></tr>\n </table>\n\n <!-- D\u00E9clencheur invisible pour le mat-menu -->\n\n @if (loadingSubject | async) {\n <ion-item>\n <ion-skeleton-text animated></ion-skeleton-text>\n </ion-item>\n } @else if (totalRowCount === 0) {\n <ion-item>\n <ion-text color=\"danger\" class=\"text-italic\" translate>COMMON.NO_RESULT</ion-text>\n </ion-item>\n }\n </div>\n</ion-content>\n\n<!-- Table options menu -->\n<mat-menu #tableOptionsMenu=\"matMenu\" xPosition=\"after\">\n <!-- display columns -->\n <button mat-menu-item (click)=\"openSelectColumnsModal($event)\">\n <mat-icon>view_column</mat-icon>\n <ion-label translate>COMMON.DISPLAYED_COLUMNS_DOTS</ion-label>\n </button>\n\n @if (usePageSettings) {\n <mat-divider></mat-divider>\n\n <!-- Compact mode -->\n <button mat-menu-item (click)=\"toggleCompactMode()\">\n <mat-icon>{{ compact ? 'check_box' : 'check_box_outline_blank' }}</mat-icon>\n <ion-label translate>COMMON.BTN_COMPACT_ROWS</ion-label>\n </button>\n }\n</mat-menu>\n\n<ion-footer>\n <mat-paginator\n [length]=\"totalRowCount\"\n [pageSize]=\"defaultPageSize\"\n [pageSizeOptions]=\"defaultPageSizeOptions\"\n showFirstLastButtons\n ></mat-paginator>\n\n <app-form-buttons-bar\n *ngIf=\"!mobile && canEdit\"\n (onCancel)=\"cancel($event)\"\n (onSave)=\"save()\"\n [disabled]=\"(loadingSubject | async) === true || (dirtySubject | async) !== true\"\n >\n <!-- error -->\n <ion-item *ngIf=\"errorSubject | async; let error\" 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=\"mobile\">\n <ion-fab-button color=\"tertiary\" (click)=\"addRow()\">\n <ion-icon name=\"add\"></ion-icon>\n </ion-fab-button>\n</ion-fab>\n", styles: [".mat-expansion-panel{margin-bottom:5px}.mat-expansion-panel .form-container mat-form-field{width:100%}.mat-expansion-panel mat-action-row ion-label{line-height:36px}.table-container{height:100%}.mat-mdc-table .mat-column-avatar{--avatar-width: 40px;--avatar-height: 40px;width:calc(var(--avatar-width) + 10px)}.mat-mdc-table .mat-column-avatar ion-avatar{--border-radius: 5px !important;--border-width: 1px !important;--border-color: rgba(var(--ion-color-secondary-rgb), .5) !important;height:var(--avatar-height);max-height:var(--avatar-height);width:var(--avatar-width);max-width:var(--avatar-width);border:solid var(--border-width) var(--border-color);margin:0 2px}.mat-mdc-table .mat-column-avatar ion-avatar svg{max-height:calc(var(--avatar-height) - 1px);max-width:calc(var(--avatar-width) - 1px)}.mat-mdc-table.compact{--mat-row-height: 33px}.mat-mdc-table.compact .mat-column-avatar{--avatar-width: calc(var(--mat-row-height, 33px) - 4px);--avatar-height: calc(var(--mat-row-height, 33px) - 4px)}.mat-mdc-table .mat-column-id{min-width:50px;max-width:120px;padding-right:var(--mat-cell-horizontal-padding, 4px)}.mat-mdc-table .mat-column-lastName,.mat-mdc-table .mat-column-firstName{min-width:80px}.mat-mdc-table .mat-column-email,.mat-mdc-table .mat-column-pubkey,.mat-mdc-table .mat-column-department{min-width:180px}.mat-mdc-table .mat-column-profile{min-width:110px}.mat-mdc-table .mat-column-status,.mat-mdc-table .mat-column-creationDate,.mat-mdc-table .mat-column-updateDate{min-width:130px}\n"], dependencies: [{ kind: "directive", type: i8.SvgJdenticonDirective, selector: "svg[data-jdenticon-hash],svg[data-jdenticon-value]", inputs: ["data-jdenticon-hash", "data-jdenticon-value", "width", "height"] }, { kind: "directive", type: i9.TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }, { kind: "directive", type: i10.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i10.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i11.IonAvatar, selector: "ion-avatar" }, { kind: "component", type: i11.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: i11.IonButtons, selector: "ion-buttons", inputs: ["collapse"] }, { kind: "component", type: i11.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: i11.IonContent, selector: "ion-content", inputs: ["color", "forceOverscroll", "fullscreen", "scrollEvents", "scrollX", "scrollY"] }, { kind: "component", type: i11.IonFab, selector: "ion-fab", inputs: ["activated", "edge", "horizontal", "vertical"] }, { kind: "component", type: i11.IonFabButton, selector: "ion-fab-button", inputs: ["activated", "closeIcon", "color", "disabled", "download", "href", "mode", "rel", "routerAnimation", "routerDirection", "show", "size", "target", "translucent", "type"] }, { kind: "component", type: i11.IonFooter, selector: "ion-footer", inputs: ["collapse", "mode", "translucent"] }, { kind: "component", type: i11.IonGrid, selector: "ion-grid", inputs: ["fixed"] }, { kind: "component", type: i11.IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: i11.IonImg, selector: "ion-img", inputs: ["alt", "src"] }, { kind: "component", type: i11.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: i11.IonLabel, selector: "ion-label", inputs: ["color", "mode", "position"] }, { kind: "component", type: i11.IonRow, selector: "ion-row" }, { kind: "component", type: i11.IonSkeletonText, selector: "ion-skeleton-text", inputs: ["animated"] }, { kind: "component", type: i11.IonText, selector: "ion-text", inputs: ["color", "mode"] }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: i12.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i12.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i12.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i12.MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: i12.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i12.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i12.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i12.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "component", type: i12.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i12.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "directive", type: i13.MatSort, selector: "[matSort]", inputs: ["matSortActive", "matSortStart", "matSortDirection", "matSortDisableClear", "matSortDisabled"], outputs: ["matSortChange"], exportAs: ["matSort"] }, { kind: "component", type: i13.MatSortHeader, selector: "[mat-sort-header]", inputs: ["mat-sort-header", "arrowPosition", "start", "disabled", "sortActionDescription", "disableClear"], exportAs: ["matSortHeader"] }, { kind: "component", type: i14.MatPaginator, selector: "mat-paginator", inputs: ["color", "pageIndex", "length", "pageSize", "pageSizeOptions", "hidePageSize", "showFirstLastButtons", "selectConfig", "disabled"], outputs: ["page"], exportAs: ["matPaginator"] }, { kind: "component", type: i15.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i15.MatLabel, selector: "mat-label" }, { kind: "directive", type: i15.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "directive", type: i15.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "directive", type: i16.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: i17.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: i18.MatExpansionPanel, selector: "mat-expansion-panel", inputs: ["hideToggle", "togglePosition"], outputs: ["afterExpand", "afterCollapse"], exportAs: ["matExpansionPanel"] }, { kind: "directive", type: i18.MatExpansionPanelActionRow, selector: "mat-action-row" }, { kind: "component", type: i19.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i20.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "component", type: i21.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i21.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i21.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "component", type: i22.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "directive", type: i22.MatSelectTrigger, selector: "mat-select-trigger" }, { kind: "component", type: i23.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "component", type: i24.MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }, { kind: "directive", type: i25.MatBadge, selector: "[matBadge]", inputs: ["matBadgeColor", "matBadgeOverlap", "matBadgeDisabled", "matBadgePosition", "matBadge", "matBadgeDescription", "matBadgeSize", "matBadgeHidden"] }, { kind: "directive", type: i26.CdkTrapFocus, selector: "[cdkTrapFocus]", inputs: ["cdkTrapFocus", "cdkTrapFocusAutoCapture"], exportAs: ["cdkTrapFocus"] }, { kind: "directive", type: i27.AutofocusDirective, selector: "[autofocus], input[appAutofocus]", inputs: ["appAutofocus", "autofocusDelay"] }, { kind: "directive", type: i28.AutoTitleDirective, selector: "ion-label[appAutoTitle], mat-label[appAutoTitle]", inputs: ["appAutoTitle"] }, { kind: "component", type: i29.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: i30.AppFormField, selector: "app-form-field", inputs: ["definition", "readonly", "disabled", "formControl", "formControlName", "placeholder", "compact", "required", "hideRequiredMarker", "floatLabel", "label", "appearance", "subscriptSizing", "tabindex", "autofocus", "clearable", "chipColor", "class", "debug", "panelClass", "panelWidth"], outputs: ["keyup.enter"] }, { kind: "component", type: i31.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: i32.ActionsColumnComponent, selector: "app-actions-column", inputs: ["matColumnDef", "style", "stickyEnd", "canCancel", "canConfirm", "canDelete", "canBackward", "canForward", "canConfirmAndAdd", "dirtyIcon", "optionsTitle", "class", "cellTemplateStart", "cellTemplate"], outputs: ["optionsClick", "cancelOrDeleteClick", "confirmEditCreateClick", "confirmAndAddClick", "backward", "forward"] }, { kind: "component", type: i33.DebugComponent, selector: "app-debug", inputs: ["titlePrefix", "title", "enable", "expanded"] }, { kind: "pipe", type: i9.TranslatePipe, name: "translate" }, { kind: "pipe", type: i10.AsyncPipe, name: "async" }, { kind: "pipe", type: i10.UpperCasePipe, name: "uppercase" }, { kind: "pipe", type: i34.DateFormatPipe, name: "dateFormat" }, { kind: "pipe", type: i35.NumberFormatPipe, name: "numberFormat" }, { kind: "pipe", type: i36.FormGetValuePipe, name: "formGetValue" }, { kind: "pipe", type: i37.IsSelectedPipe, name: "isSelected" }, { kind: "pipe", type: i37.IsEmptySelectionPipe, name: "isEmptySelection" }, { kind: "pipe", type: i38.IsAllSelectedPipe, name: "isAllSelected" }, { kind: "pipe", type: i38.IsNotAllSelectedPipe, name: "isNotAllSelected" }], animations: [slideUpDownAnimation], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
372
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: UsersPage, selector: "app-users-table", inputs: { compact: ["compact", "compact", booleanAttribute], usePageSettings: ["usePageSettings", "usePageSettings", booleanAttribute], sticky: ["sticky", "sticky", booleanAttribute], stickyEnd: ["stickyEnd", "stickyEnd", booleanAttribute], canDownload: ["canDownload", "canDownload", booleanAttribute] }, providers: [{ provide: ValidatorService, useExisting: PersonValidatorService }], viewQueries: [{ propertyName: "filterExpansionPanel", first: true, predicate: MatExpansionPanel, descendants: true, static: true }], usesInheritance: true, ngImport: i0, template: "<app-toolbar\n [title]=\"'USER.LIST.TITLE' | translate\"\n color=\"primary\"\n [canGoBack]=\"false\"\n [hasValidate]=\"(loadingSubject | async) !== true && (dirtySubject | async) === true\"\n (onValidate)=\"save()\"\n>\n <ion-buttons slot=\"end\">\n <!-- Compose message -->\n <button\n mat-icon-button\n *ngIf=\"canSendMessage\"\n [title]=\"'USER.LIST.BTN_SEND_MESSAGE' | translate\"\n (click)=\"openComposeMessageModal($event)\"\n >\n <ion-icon name=\"mail\" slot=\"icon-only\"></ion-icon>\n </button>\n\n @if (selection | isEmptySelection) {\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 <!-- Refresh -->\n <button mat-icon-button *ngIf=\"!mobile\" [title]=\"'COMMON.BTN_REFRESH' | translate\" (click)=\"emitRefresh()\">\n <mat-icon>refresh</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 } @else {\n <!-- delete -->\n <button\n mat-icon-button\n class=\"hidden-xs hidden-sm\"\n [title]=\"'COMMON.BTN_DELETE' | translate\"\n (click)=\"deleteSelection($event)\"\n >\n <mat-icon>delete</mat-icon>\n </button>\n }\n\n @if (!mobile) {\n <button mat-icon-button [title]=\"'COMMON.BTN_OPTIONS' | translate\" [matMenuTriggerFor]=\"toolbarOptionsMenu\">\n <mat-icon>more_vert</mat-icon>\n </button>\n }\n </ion-buttons>\n</app-toolbar>\n\n<!-- Toolbar option menu -->\n<mat-menu #toolbarOptionsMenu=\"matMenu\" xPosition=\"after\">\n <!-- export button -->\n <button mat-menu-item [disabled]=\"!canDownload\" (click)=\"exportToCsv($event)\">\n <mat-icon>download</mat-icon>\n <ion-label translate>FILE.CSV.BTN_DOWNLOAD_HELP</ion-label>\n </button>\n</mat-menu>\n\n<ion-content class=\"ion-no-padding\">\n <!-- error -->\n <ion-item\n *ngIf=\"errorSubject | async; let error\"\n lines=\"none\"\n class=\"hidden-sm hidden-xs hidden-mobile\"\n @slideUpDownAnimation\n >\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 <!-- debug -->\n <app-debug *ngIf=\"debug\">\n <ion-grid class=\"ion-no-padding\">\n <ion-row>\n <ion-col>\n focusColumn: {{ focusColumn }}\n <br />\n loadingSubject: {{ loading }}\n <br />\n </ion-col>\n </ion-row>\n </ion-grid>\n </app-debug>\n\n <!-- search -->\n <mat-expansion-panel #filterExpansionPanel class=\"ion-no-padding filter-panel filter-panel-floating\">\n <form class=\"form-container ion-padding\" [formGroup]=\"filterForm\" (ngSubmit)=\"emitRefresh()\">\n <ion-grid>\n <ion-row>\n <ion-col>\n <!-- search -->\n <mat-form-field>\n <mat-label>{{ 'USER.LIST.FILTER.SEARCH' | translate }}</mat-label>\n <input matInput formControlName=\"searchText\" />\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\n <ion-col>\n <!-- status -->\n <mat-form-field>\n <mat-label>{{ 'USER.STATUS' | translate }}</mat-label>\n <mat-select formControlName=\"statusId\">\n <mat-option [value]=\"null\">\n <i><span translate>COMMON.EMPTY_OPTION</span></i>\n </mat-option>\n <mat-option *ngFor=\"let item of statusList\" [value]=\"item.id\">\n <ion-icon [name]=\"item.icon\"></ion-icon>\n {{ item.label | translate }}\n </mat-option>\n </mat-select>\n\n <button\n mat-icon-button\n matSuffix\n tabindex=\"-1\"\n type=\"button\"\n (click)=\"clearControlValue($event, filterForm.controls.statusId)\"\n [hidden]=\"filterForm.controls.statusId.disabled || !filterForm.controls.statusId.value\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n </ion-col>\n\n <ion-col>\n <!-- user profiles -->\n <mat-chips-field\n formControlName=\"userProfiles\"\n [placeholder]=\"'USER.PROFILES' | translate\"\n chipColor=\"accent\"\n [items]=\"userProfileList\"\n [displayAttributes]=\"['name']\"\n [clearable]=\"true\">\n </mat-chips-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) === true || filterForm.dirty\"\n [color]=\"empty && 'danger'\"\n class=\"ion-padding\"\n >\n {{\n (totalRowCount ? 'COMMON.RESULT_COUNT' : 'COMMON.NO_RESULT')\n | translate\n : {\n count: (totalRowCount | numberFormat),\n }\n }}\n </ion-label>\n\n <div class=\"toolbar-spacer\"></div>\n\n <!-- Close panel -->\n <ion-button\n mat-button\n fill=\"clear\"\n color=\"dark\"\n (click)=\"filterExpansionPanel.close()\"\n [disabled]=\"loadingSubject | async\"\n >\n <ion-text translate>COMMON.BTN_CLOSE</ion-text>\n </ion-button>\n\n <!-- Search button -->\n <ion-button\n mat-button\n [color]=\"filterForm.dirty ? 'tertiary' : 'dark'\"\n [fill]=\"filterForm.dirty ? 'solid' : 'clear'\"\n (click)=\"applyFilterAndClosePanel($event)\"\n [disabled]=\"loadingSubject | async\"\n >\n <ion-text translate>COMMON.BTN_APPLY</ion-text>\n </ion-button>\n </mat-action-row>\n </mat-expansion-panel>\n\n <!-- error -->\n <ion-item *ngIf=\"mobile && (errorSubject | async); let error\" lines=\"none\">\n <ion-icon color=\"danger\" slot=\"start\" name=\"alert-circle\"></ion-icon>\n <ion-label color=\"danger\" class=\"error\" [innerHTML]=\"error | translate\"></ion-label>\n </ion-item>\n\n <div class=\"table-container\">\n <table\n #table\n mat-table\n matSort\n [class.compact]=\"compact\"\n [dataSource]=\"dataSource\"\n [matSortActive]=\"defaultSortBy\"\n [matSortDirection]=\"defaultSortDirection\"\n matSortDisableClear\n [trackBy]=\"trackByFn\"\n >\n <ng-container matColumnDef=\"select\" [sticky]=\"sticky\">\n <th mat-header-cell *matHeaderCellDef [class.cdk-visually-hidden]=\"!inlineEdition\">\n <mat-checkbox\n (change)=\"$event ? masterToggle() : null\"\n [checked]=\"this | isAllSelected\"\n [indeterminate]=\"this | isNotAllSelected\"\n ></mat-checkbox>\n </th>\n <td mat-cell *matCellDef=\"let row\" [class.cdk-visually-hidden]=\"!inlineEdition\">\n <mat-checkbox (click)=\"toggleSelectRow($event, row)\" [checked]=\"selection | isSelected: row\"></mat-checkbox>\n </td>\n </ng-container>\n\n <!-- Id Column -->\n <ng-container matColumnDef=\"id\" [sticky]=\"sticky\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>\n <ion-label>#</ion-label>\n </th>\n <td mat-cell *matCellDef=\"let row\">\n <ion-label>{{ row.currentData.id }}</ion-label>\n </td>\n </ng-container>\n\n <!-- avatar Column -->\n <ng-container matColumnDef=\"avatar\" [sticky]=\"sticky\">\n <th mat-header-cell *matHeaderCellDef></th>\n <td mat-cell *matCellDef=\"let row\">\n <ion-avatar [style.background-color]=\"'white'\">\n <ion-img *ngIf=\"row.currentData.avatar; let avatarUrl; else: generateIcon\" [src]=\"avatarUrl\"></ion-img>\n <ng-template #generateIcon>\n <svg width=\"39\" height=\"39\" [data-jdenticon-value]=\"row.currentData.id\"></svg>\n </ng-template>\n </ion-avatar>\n </td>\n </ng-container>\n\n <!-- lastName -->\n <ng-container matColumnDef=\"lastName\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>\n <span translate>USER.LAST_NAME</span>\n </th>\n <td mat-cell *matCellDef=\"let row\" (click)=\"focusColumn = 'lastName'\">\n <mat-form-field *ngIf=\"row.editing; else readonlyCell\">\n <input\n matInput\n [formControl]=\"row.validator.controls['lastName']\"\n [placeholder]=\"'USER.LAST_NAME' | translate\"\n [readonly]=\"!row.editing\"\n [appAutofocus]=\"row.editing && focusColumn === 'lastName'\"\n />\n <mat-error *ngIf=\"row.validator.controls['lastName'].hasError('required')\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n <mat-error *ngIf=\"row.validator.controls['lastName'].hasError('minlength')\">\n <span>{{ 'ERROR.FIELD_MIN_LENGTH' | translate: { requiredLength: 2 } }}</span>\n </mat-error>\n </mat-form-field>\n <ng-template #readonlyCell>\n <ion-label appAutoTitle>\n {{ row.validator | formGetValue: 'lastName' }}\n </ion-label>\n </ng-template>\n </td>\n </ng-container>\n\n <!-- firstname -->\n <ng-container matColumnDef=\"firstName\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>\n <span translate>USER.FIRST_NAME</span>\n </th>\n <td mat-cell *matCellDef=\"let row\" (click)=\"focusColumn = 'firstName'\">\n <mat-form-field *ngIf=\"row.editing; else readonlyCell\">\n <input\n matInput\n [formControl]=\"row.validator.controls['firstName']\"\n [placeholder]=\"'USER.FIRST_NAME' | translate\"\n [readonly]=\"!row.editing\"\n [appAutofocus]=\"row.editing && focusColumn === 'firstName'\"\n />\n <mat-error *ngIf=\"row.validator.controls['firstName'].hasError('required')\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n <mat-error *ngIf=\"row.validator.controls['firstName'].hasError('minlength')\">\n <span>{{ 'ERROR.FIELD_MIN_LENGTH' | translate: { requiredLength: 2 } }}</span>\n </mat-error>\n </mat-form-field>\n <ng-template #readonlyCell>\n <ion-label appAutoTitle>\n {{ row.validator | formGetValue: 'firstName' }}\n </ion-label>\n </ng-template>\n </td>\n </ng-container>\n\n <!-- email -->\n <ng-container matColumnDef=\"email\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>\n <span translate>USER.EMAIL</span>\n </th>\n <td mat-cell *matCellDef=\"let row\" (click)=\"focusColumn = 'email'\">\n <mat-form-field *ngIf=\"row.editing; else readonlyCell\">\n <input\n matInput\n [formControl]=\"row.validator.controls['email']\"\n [placeholder]=\"'USER.EMAIL' | translate\"\n [readonly]=\"!row.editing\"\n [appAutofocus]=\"row.editing && focusColumn === 'email'\"\n />\n <mat-error *ngIf=\"row.validator.controls['email'].hasError('required')\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n <mat-error *ngIf=\"row.validator.controls['email'].hasError('email')\">\n <span translate>ERROR.FIELD_NOT_VALID_EMAIL</span>\n </mat-error>\n </mat-form-field>\n <ng-template #readonlyCell>\n <ion-label appAutoTitle>\n {{ row.validator | formGetValue: 'email' }}\n </ion-label>\n </ng-template>\n </td>\n </ng-container>\n\n <!-- additional fields -->\n <ng-container *ngFor=\"let definition of additionalFields\" [matColumnDef]=\"definition.key\">\n <th mat-header-cell *matHeaderCellDef>\n <span>{{ definition.label | translate }}</span>\n </th>\n <td mat-cell *matCellDef=\"let row\" (click)=\"focusColumn = definition.key\">\n <app-form-field\n floatLabel=\"never\"\n [definition]=\"definition\"\n [formControl]=\"row.validator.controls[definition.key]\"\n [required]=\"definition.extra?.account?.required\"\n [autofocus]=\"row.editing && focusColumn === definition.key\"\n ></app-form-field>\n </td>\n </ng-container>\n\n <!-- profile column -->\n <ng-container matColumnDef=\"profile\">\n <th mat-header-cell *matHeaderCellDef>\n <span translate>USER.PROFILE</span>\n </th>\n <td mat-cell *matCellDef=\"let row\" (click)=\"focusColumn = 'profile'\">\n <mat-form-field>\n <mat-select\n [formControl]=\"row.validator.controls['mainProfile']\"\n [placeholder]=\"'USER.PROFILE' | translate\"\n >\n <mat-option *ngFor=\"let item of profiles\" [value]=\"item\">\n {{ 'USER.PROFILE_ENUM.' + item | uppercase | translate }}\n </mat-option>\n </mat-select>\n <mat-error *ngIf=\"row.validator.controls['mainProfile'].hasError('required')\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n </mat-form-field>\n </td>\n </ng-container>\n\n <!-- Status column -->\n <ng-container matColumnDef=\"status\">\n <th mat-header-cell *matHeaderCellDef>\n <span translate>USER.STATUS</span>\n </th>\n <td mat-cell *matCellDef=\"let row\" (click)=\"focusColumn = 'status'\">\n <mat-form-field>\n <mat-select\n [formControl]=\"row.validator.controls['statusId']\"\n [placeholder]=\"'REFERENTIAL.STATUS' | translate\"\n >\n <mat-select-trigger>\n <span *ngIf=\"row.validator.controls['statusId'].value >= 0\">\n {{ statusById[row.validator.controls['statusId'].value]?.label | translate }}\n </span>\n </mat-select-trigger>\n <mat-option *ngFor=\"let item of statusList\" [value]=\"item.id\">\n <mat-icon><ion-icon [name]=\"item.icon\"></ion-icon></mat-icon>\n {{ item.label | translate }}\n </mat-option>\n </mat-select>\n <mat-error *ngIf=\"row.validator.controls['statusId'].hasError('required')\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n </mat-form-field>\n </td>\n </ng-container>\n\n <!-- username -->\n <ng-container matColumnDef=\"username\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>\n <span translate>USER.USERNAME</span>\n </th>\n <td mat-cell *matCellDef=\"let row\" (click)=\"focusColumn = 'username'\">\n <mat-form-field *ngIf=\"row.editing; else readonlyCell\">\n <input\n matInput\n [formControl]=\"row.validator.controls.username\"\n [placeholder]=\"'USER.USERNAME' | translate\"\n [readonly]=\"!row.editing\"\n [appAutofocus]=\"row.editing && focusColumn === 'username'\"\n />\n <mat-error *ngIf=\"row.validator.controls.username.hasError('required')\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n </mat-form-field>\n <ng-template #readonlyCell>\n <ion-label appAutoTitle>\n {{ row.validator | formGetValue: 'username' }}\n </ion-label>\n </ng-template>\n </td>\n </ng-container>\n\n <!-- username extranet -->\n <ng-container matColumnDef=\"usernameExtranet\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>\n <span translate>USER.USERNAME_EXTRANET</span>\n </th>\n <td mat-cell *matCellDef=\"let row\" (click)=\"focusColumn = 'usernameExtranet'\">\n <mat-form-field *ngIf=\"row.editing; else readonlyCell\">\n <input\n matInput\n [formControl]=\"row.validator.controls.usernameExtranet\"\n [placeholder]=\"'USER.USERNAME_EXTRANET' | translate\"\n [readonly]=\"!row.editing\"\n [appAutofocus]=\"row.editing && focusColumn === 'usernameExtranet'\"\n />\n <mat-error *ngIf=\"row.validator.controls.usernameExtranet.hasError('required')\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n </mat-form-field>\n <ng-template #readonlyCell>\n <ion-label appAutoTitle>\n {{ row.validator | formGetValue: 'usernameExtranet' }}\n </ion-label>\n </ng-template>\n </td>\n </ng-container>\n\n <!-- pubkey -->\n <ng-container matColumnDef=\"pubkey\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>\n <span translate>USER.PUBKEY</span>\n </th>\n <td\n mat-cell\n *matCellDef=\"let row\"\n [title]=\"row.validator.controls.pubkey.valueChanges | async\"\n (click)=\"focusColumn = 'pubkey'\"\n >\n <mat-form-field *ngIf=\"row.editing; else readonlyCell\">\n <input\n matInput\n [formControl]=\"row.validator.controls['pubkey']\"\n [placeholder]=\"'USER.PUBKEY' | translate\"\n [readonly]=\"!row.editing\"\n autocomplete=\"off\"\n />\n <mat-error *ngIf=\"row.validator.controls.pubkey.hasError('required')\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n <mat-error *ngIf=\"row.validator.controls.pubkey.hasError('pubkey')\">\n <span translate>ERROR.FIELD_NOT_VALID_PUBKEY</span>\n </mat-error>\n </mat-form-field>\n <ng-template #readonlyCell>\n <ion-label appAutoTitle>\n {{ row.validator | formGetValue: 'pubkey' }}\n </ion-label>\n </ng-template>\n </td>\n </ng-container>\n\n <!-- Creation date column -->\n <ng-container matColumnDef=\"creationDate\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>\n <ion-label translate>USER.CREATION_DATE</ion-label>\n </th>\n <td mat-cell *matCellDef=\"let row\" class=\"mat-form-field-disabled\">\n <ion-text class=\"ion-text-end\" color=\"medium\" *ngIf=\"row.id !== -1\">\n {{ row.currentData.creationDate | dateFormat: { time: true } }}\n </ion-text>\n </td>\n </ng-container>\n\n <!-- Update date column -->\n <ng-container matColumnDef=\"updateDate\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>\n <ion-label translate>USER.UPDATE_DATE</ion-label>\n </th>\n <td mat-cell *matCellDef=\"let row\" class=\"mat-form-field-disabled\">\n <ion-text class=\"ion-text-end\" color=\"medium\" *ngIf=\"row.id !== -1\">\n {{ row.currentData.updateDate | dateFormat: { time: true } }}\n </ion-text>\n </td>\n </ng-container>\n\n <!-- Actions buttons column -->\n <app-actions-column\n [stickyEnd]=\"stickyEnd\"\n (cancelOrDeleteClick)=\"cancelOrDelete($event.event, $event.row)\"\n (confirmEditCreateClick)=\"confirmEditCreate($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 [canCancel]=\"false\"\n >\n <!-- table options menu -->\n <button\n matHeader\n mat-icon-button\n [title]=\"'COMMON.BTN_OPTIONS' | translate\"\n [matMenuTriggerFor]=\"tableOptionsMenu\"\n >\n <mat-icon>more_vert</mat-icon>\n </button>\n </app-actions-column>\n\n <tr mat-header-row *matHeaderRowDef=\"displayedColumns; sticky: true\"></tr>\n <tr\n mat-row\n *matRowDef=\"let row; columns: displayedColumns\"\n [class.mat-row-selected]=\"row.editing\"\n [class.mat-row-error]=\"row.validator.invalid\"\n [class.mat-row-dirty]=\"row.currentData.dirty\"\n [class.mat-row-disabled]=\"!row.editing\"\n (click)=\"clickRow($event, row)\"\n (keydown.escape)=\"escapeEditingRow($event)\"\n [cdkTrapFocus]=\"!row.validator?.valid\"\n ></tr>\n </table>\n\n <!-- D\u00E9clencheur invisible pour le mat-menu -->\n\n @if (loadingSubject | async) {\n <ion-item>\n <ion-skeleton-text animated></ion-skeleton-text>\n </ion-item>\n } @else if (totalRowCount === 0) {\n <ion-item>\n <ion-text color=\"danger\" class=\"text-italic\" translate>COMMON.NO_RESULT</ion-text>\n </ion-item>\n }\n </div>\n</ion-content>\n\n<!-- Table options menu -->\n<mat-menu #tableOptionsMenu=\"matMenu\" xPosition=\"after\">\n <!-- display columns -->\n <button mat-menu-item (click)=\"openSelectColumnsModal($event)\">\n <mat-icon>view_column</mat-icon>\n <ion-label translate>COMMON.DISPLAYED_COLUMNS_DOTS</ion-label>\n </button>\n\n @if (usePageSettings) {\n <mat-divider></mat-divider>\n\n <!-- Compact mode -->\n <button mat-menu-item (click)=\"toggleCompactMode()\">\n <mat-icon>{{ compact ? 'check_box' : 'check_box_outline_blank' }}</mat-icon>\n <ion-label translate>COMMON.BTN_COMPACT_ROWS</ion-label>\n </button>\n }\n</mat-menu>\n\n<ion-footer>\n <mat-paginator\n [length]=\"totalRowCount\"\n [pageSize]=\"defaultPageSize\"\n [pageSizeOptions]=\"defaultPageSizeOptions\"\n showFirstLastButtons\n ></mat-paginator>\n\n <app-form-buttons-bar\n *ngIf=\"!mobile && canEdit\"\n (onCancel)=\"cancel($event)\"\n (onSave)=\"save()\"\n [disabled]=\"(loadingSubject | async) === true || (dirtySubject | async) !== true\"\n >\n <!-- error -->\n <ion-item *ngIf=\"errorSubject | async; let error\" 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=\"mobile\">\n <ion-fab-button color=\"tertiary\" (click)=\"addRow()\">\n <ion-icon name=\"add\"></ion-icon>\n </ion-fab-button>\n</ion-fab>\n", styles: [".mat-expansion-panel{margin-bottom:5px}.mat-expansion-panel .form-container mat-form-field{width:100%}.mat-expansion-panel mat-action-row ion-label{line-height:36px}.table-container{height:100%}.mat-mdc-table .mat-column-avatar{--avatar-width: 40px;--avatar-height: 40px;width:calc(var(--avatar-width) + 10px)}.mat-mdc-table .mat-column-avatar ion-avatar{--border-radius: 5px !important;--border-width: 1px !important;--border-color: rgba(var(--ion-color-secondary-rgb), .5) !important;height:var(--avatar-height);max-height:var(--avatar-height);width:var(--avatar-width);max-width:var(--avatar-width);border:solid var(--border-width) var(--border-color);margin:0 2px}.mat-mdc-table .mat-column-avatar ion-avatar svg{max-height:calc(var(--avatar-height) - 1px);max-width:calc(var(--avatar-width) - 1px)}.mat-mdc-table.compact{--mat-row-height: 33px}.mat-mdc-table.compact .mat-column-avatar{--avatar-width: calc(var(--mat-row-height, 33px) - 4px);--avatar-height: calc(var(--mat-row-height, 33px) - 4px)}.mat-mdc-table .mat-column-id{min-width:50px;max-width:120px;padding-right:var(--mat-cell-horizontal-padding, 4px)}.mat-mdc-table .mat-column-lastName,.mat-mdc-table .mat-column-firstName{min-width:80px}.mat-mdc-table .mat-column-email,.mat-mdc-table .mat-column-pubkey,.mat-mdc-table .mat-column-department{min-width:180px}.mat-mdc-table .mat-column-profile{min-width:110px}.mat-mdc-table .mat-column-status,.mat-mdc-table .mat-column-creationDate,.mat-mdc-table .mat-column-updateDate{min-width:130px}\n"], dependencies: [{ kind: "directive", type: i8.SvgJdenticonDirective, selector: "svg[data-jdenticon-hash],svg[data-jdenticon-value]", inputs: ["data-jdenticon-hash", "data-jdenticon-value", "width", "height"] }, { kind: "directive", type: i9.TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }, { kind: "directive", type: i10.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i10.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i11.IonAvatar, selector: "ion-avatar" }, { kind: "component", type: i11.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: i11.IonButtons, selector: "ion-buttons", inputs: ["collapse"] }, { kind: "component", type: i11.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: i11.IonContent, selector: "ion-content", inputs: ["color", "forceOverscroll", "fullscreen", "scrollEvents", "scrollX", "scrollY"] }, { kind: "component", type: i11.IonFab, selector: "ion-fab", inputs: ["activated", "edge", "horizontal", "vertical"] }, { kind: "component", type: i11.IonFabButton, selector: "ion-fab-button", inputs: ["activated", "closeIcon", "color", "disabled", "download", "href", "mode", "rel", "routerAnimation", "routerDirection", "show", "size", "target", "translucent", "type"] }, { kind: "component", type: i11.IonFooter, selector: "ion-footer", inputs: ["collapse", "mode", "translucent"] }, { kind: "component", type: i11.IonGrid, selector: "ion-grid", inputs: ["fixed"] }, { kind: "component", type: i11.IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: i11.IonImg, selector: "ion-img", inputs: ["alt", "src"] }, { kind: "component", type: i11.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: i11.IonLabel, selector: "ion-label", inputs: ["color", "mode", "position"] }, { kind: "component", type: i11.IonRow, selector: "ion-row" }, { kind: "component", type: i11.IonSkeletonText, selector: "ion-skeleton-text", inputs: ["animated"] }, { kind: "component", type: i11.IonText, selector: "ion-text", inputs: ["color", "mode"] }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: i12.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i12.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i12.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i12.MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: i12.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i12.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i12.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i12.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "component", type: i12.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i12.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "directive", type: i13.MatSort, selector: "[matSort]", inputs: ["matSortActive", "matSortStart", "matSortDirection", "matSortDisableClear", "matSortDisabled"], outputs: ["matSortChange"], exportAs: ["matSort"] }, { kind: "component", type: i13.MatSortHeader, selector: "[mat-sort-header]", inputs: ["mat-sort-header", "arrowPosition", "start", "disabled", "sortActionDescription", "disableClear"], exportAs: ["matSortHeader"] }, { kind: "component", type: i14.MatPaginator, selector: "mat-paginator", inputs: ["color", "pageIndex", "length", "pageSize", "pageSizeOptions", "hidePageSize", "showFirstLastButtons", "selectConfig", "disabled"], outputs: ["page"], exportAs: ["matPaginator"] }, { kind: "component", type: i15.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i15.MatLabel, selector: "mat-label" }, { kind: "directive", type: i15.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "directive", type: i15.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "directive", type: i16.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: i17.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: i18.MatExpansionPanel, selector: "mat-expansion-panel", inputs: ["hideToggle", "togglePosition"], outputs: ["afterExpand", "afterCollapse"], exportAs: ["matExpansionPanel"] }, { kind: "directive", type: i18.MatExpansionPanelActionRow, selector: "mat-action-row" }, { kind: "component", type: i19.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i20.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "component", type: i21.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i21.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i21.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "component", type: i22.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "directive", type: i22.MatSelectTrigger, selector: "mat-select-trigger" }, { kind: "component", type: i23.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "component", type: i24.MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }, { kind: "directive", type: i25.MatBadge, selector: "[matBadge]", inputs: ["matBadgeColor", "matBadgeOverlap", "matBadgeDisabled", "matBadgePosition", "matBadge", "matBadgeDescription", "matBadgeSize", "matBadgeHidden"] }, { kind: "directive", type: i26.CdkTrapFocus, selector: "[cdkTrapFocus]", inputs: ["cdkTrapFocus", "cdkTrapFocusAutoCapture"], exportAs: ["cdkTrapFocus"] }, { kind: "component", type: i27.MatChipsField, selector: "mat-chips-field", inputs: ["equals", "logPrefix", "formControl", "formControlName", "floatLabel", "placeholder", "suggestFn", "required", "mobile", "readonly", "clearable", "debounceTime", "displaySeparator", "displayWith", "displayAttributes", "displayColumnSizes", "displayColumnNames", "highlightAccent", "showAllOnFocus", "showPanelOnFocus", "autofocus", "config", "i18nPrefix", "noResultMessage", "panelClass", "panelWidth", "disableRipple", "matAutocompletePosition", "itemSize", "fetchMoreThreshold", "suggestLengthThreshold", "showLoadingSpinner", "chipColor", "debug", "applyImplicitValue", "dropButtonTitle", "clearButtonTitle", "trimSearchText", "hideRequiredMarker", "colSizes", "separatorKeysCodes", "appearance", "subscriptSizing", "class", "filter", "tabindex", "items"], outputs: ["click", "blur", "focus", "dropButtonClick", "keydown.escape", "keyup.enter"] }, { kind: "directive", type: i28.AutofocusDirective, selector: "[autofocus], input[appAutofocus]", inputs: ["appAutofocus", "autofocusDelay"] }, { kind: "directive", type: i29.AutoTitleDirective, selector: "ion-label[appAutoTitle], mat-label[appAutoTitle]", inputs: ["appAutoTitle"] }, { kind: "component", type: i30.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: i31.AppFormField, selector: "app-form-field", inputs: ["definition", "readonly", "disabled", "formControl", "formControlName", "placeholder", "compact", "required", "hideRequiredMarker", "floatLabel", "label", "appearance", "subscriptSizing", "tabindex", "autofocus", "clearable", "chipColor", "class", "debug", "panelClass", "panelWidth"], outputs: ["keyup.enter"] }, { kind: "component", type: i32.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: i33.ActionsColumnComponent, selector: "app-actions-column", inputs: ["matColumnDef", "style", "stickyEnd", "canCancel", "canConfirm", "canDelete", "canBackward", "canForward", "canConfirmAndAdd", "dirtyIcon", "optionsTitle", "class", "cellTemplateStart", "cellTemplate"], outputs: ["optionsClick", "cancelOrDeleteClick", "confirmEditCreateClick", "confirmAndAddClick", "backward", "forward"] }, { kind: "component", type: i34.DebugComponent, selector: "app-debug", inputs: ["titlePrefix", "title", "enable", "expanded"] }, { kind: "pipe", type: i9.TranslatePipe, name: "translate" }, { kind: "pipe", type: i10.AsyncPipe, name: "async" }, { kind: "pipe", type: i10.UpperCasePipe, name: "uppercase" }, { kind: "pipe", type: i35.DateFormatPipe, name: "dateFormat" }, { kind: "pipe", type: i36.NumberFormatPipe, name: "numberFormat" }, { kind: "pipe", type: i37.FormGetValuePipe, name: "formGetValue" }, { kind: "pipe", type: i38.IsSelectedPipe, name: "isSelected" }, { kind: "pipe", type: i38.IsEmptySelectionPipe, name: "isEmptySelection" }, { kind: "pipe", type: i39.IsAllSelectedPipe, name: "isAllSelected" }, { kind: "pipe", type: i39.IsNotAllSelectedPipe, name: "isNotAllSelected" }], animations: [slideUpDownAnimation], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
353
373
|
}
|
|
354
374
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: UsersPage, decorators: [{
|
|
355
375
|
type: Component,
|
|
356
|
-
args: [{ selector: 'app-users-table', providers: [{ provide: ValidatorService, useExisting: PersonValidatorService }], animations: [slideUpDownAnimation], changeDetection: ChangeDetectionStrategy.OnPush, template: "<app-toolbar\n [title]=\"'USER.LIST.TITLE' | translate\"\n color=\"primary\"\n [canGoBack]=\"false\"\n [hasValidate]=\"(loadingSubject | async) !== true && (dirtySubject | async) === true\"\n (onValidate)=\"save()\"\n>\n <ion-buttons slot=\"end\">\n <!-- Compose message -->\n <button\n mat-icon-button\n *ngIf=\"canSendMessage\"\n [title]=\"'USER.LIST.BTN_SEND_MESSAGE' | translate\"\n (click)=\"openComposeMessageModal($event)\"\n >\n <ion-icon name=\"mail\" slot=\"icon-only\"></ion-icon>\n </button>\n\n @if (selection | isEmptySelection) {\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 <!-- Refresh -->\n <button mat-icon-button *ngIf=\"!mobile\" [title]=\"'COMMON.BTN_REFRESH' | translate\" (click)=\"emitRefresh()\">\n <mat-icon>refresh</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 } @else {\n <!-- delete -->\n <button\n mat-icon-button\n class=\"hidden-xs hidden-sm\"\n [title]=\"'COMMON.BTN_DELETE' | translate\"\n (click)=\"deleteSelection($event)\"\n >\n <mat-icon>delete</mat-icon>\n </button>\n }\n\n @if (!mobile) {\n <button mat-icon-button [title]=\"'COMMON.BTN_OPTIONS' | translate\" [matMenuTriggerFor]=\"toolbarOptionsMenu\">\n <mat-icon>more_vert</mat-icon>\n </button>\n }\n </ion-buttons>\n</app-toolbar>\n\n<!-- Toolbar option menu -->\n<mat-menu #toolbarOptionsMenu=\"matMenu\" xPosition=\"after\">\n <!-- export button -->\n <button mat-menu-item [disabled]=\"!canDownload\" (click)=\"exportToCsv($event)\">\n <mat-icon>download</mat-icon>\n <ion-label translate>FILE.CSV.BTN_DOWNLOAD_HELP</ion-label>\n </button>\n</mat-menu>\n\n<ion-content class=\"ion-no-padding\">\n <!-- error -->\n <ion-item\n *ngIf=\"errorSubject | async; let error\"\n lines=\"none\"\n class=\"hidden-sm hidden-xs hidden-mobile\"\n @slideUpDownAnimation\n >\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 <!-- debug -->\n <app-debug *ngIf=\"debug\">\n <ion-grid class=\"ion-no-padding\">\n <ion-row>\n <ion-col>\n focusColumn: {{ focusColumn }}\n <br />\n loadingSubject: {{ loading }}\n <br />\n </ion-col>\n </ion-row>\n </ion-grid>\n </app-debug>\n\n <!-- search -->\n <mat-expansion-panel #filterExpansionPanel class=\"ion-no-padding filter-panel filter-panel-floating\">\n <form class=\"form-container ion-padding\" [formGroup]=\"filterForm\" (ngSubmit)=\"emitRefresh()\">\n <ion-grid>\n <ion-row>\n <ion-col>\n <!-- search -->\n <mat-form-field>\n <mat-label>{{ 'USER.LIST.FILTER.SEARCH' | translate }}</mat-label>\n <input matInput formControlName=\"searchText\" />\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\n <ion-col>\n <!-- status -->\n <mat-form-field>\n <mat-label>{{ 'USER.STATUS' | translate }}</mat-label>\n <mat-select formControlName=\"statusId\">\n <mat-option [value]=\"null\">\n <i><span translate>COMMON.EMPTY_OPTION</span></i>\n </mat-option>\n <mat-option *ngFor=\"let item of statusList\" [value]=\"item.id\">\n <ion-icon [name]=\"item.icon\"></ion-icon>\n {{ item.label | translate }}\n </mat-option>\n </mat-select>\n\n <button\n mat-icon-button\n matSuffix\n tabindex=\"-1\"\n type=\"button\"\n (click)=\"clearControlValue($event, filterForm.controls.statusId)\"\n [hidden]=\"filterForm.controls.statusId.disabled || !filterForm.controls.statusId.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) === true || filterForm.dirty\"\n [color]=\"empty && 'danger'\"\n class=\"ion-padding\"\n >\n {{\n (totalRowCount ? 'COMMON.RESULT_COUNT' : 'COMMON.NO_RESULT')\n | translate\n : {\n count: (totalRowCount | numberFormat),\n }\n }}\n </ion-label>\n\n <div class=\"toolbar-spacer\"></div>\n\n <!-- Close panel -->\n <ion-button\n mat-button\n fill=\"clear\"\n color=\"dark\"\n (click)=\"filterExpansionPanel.close()\"\n [disabled]=\"loadingSubject | async\"\n >\n <ion-text translate>COMMON.BTN_CLOSE</ion-text>\n </ion-button>\n\n <!-- Search button -->\n <ion-button\n mat-button\n [color]=\"filterForm.dirty ? 'tertiary' : 'dark'\"\n [fill]=\"filterForm.dirty ? 'solid' : 'clear'\"\n (click)=\"applyFilterAndClosePanel($event)\"\n [disabled]=\"loadingSubject | async\"\n >\n <ion-text translate>COMMON.BTN_APPLY</ion-text>\n </ion-button>\n </mat-action-row>\n </mat-expansion-panel>\n\n <!-- error -->\n <ion-item *ngIf=\"mobile && (errorSubject | async); let error\" lines=\"none\">\n <ion-icon color=\"danger\" slot=\"start\" name=\"alert-circle\"></ion-icon>\n <ion-label color=\"danger\" class=\"error\" [innerHTML]=\"error | translate\"></ion-label>\n </ion-item>\n\n <div class=\"table-container\">\n <table\n #table\n mat-table\n matSort\n [class.compact]=\"compact\"\n [dataSource]=\"dataSource\"\n [matSortActive]=\"defaultSortBy\"\n [matSortDirection]=\"defaultSortDirection\"\n matSortDisableClear\n [trackBy]=\"trackByFn\"\n >\n <ng-container matColumnDef=\"select\" [sticky]=\"sticky\">\n <th mat-header-cell *matHeaderCellDef [class.cdk-visually-hidden]=\"!inlineEdition\">\n <mat-checkbox\n (change)=\"$event ? masterToggle() : null\"\n [checked]=\"this | isAllSelected\"\n [indeterminate]=\"this | isNotAllSelected\"\n ></mat-checkbox>\n </th>\n <td mat-cell *matCellDef=\"let row\" [class.cdk-visually-hidden]=\"!inlineEdition\">\n <mat-checkbox (click)=\"toggleSelectRow($event, row)\" [checked]=\"selection | isSelected: row\"></mat-checkbox>\n </td>\n </ng-container>\n\n <!-- Id Column -->\n <ng-container matColumnDef=\"id\" [sticky]=\"sticky\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>\n <ion-label>#</ion-label>\n </th>\n <td mat-cell *matCellDef=\"let row\">\n <ion-label>{{ row.currentData.id }}</ion-label>\n </td>\n </ng-container>\n\n <!-- avatar Column -->\n <ng-container matColumnDef=\"avatar\" [sticky]=\"sticky\">\n <th mat-header-cell *matHeaderCellDef></th>\n <td mat-cell *matCellDef=\"let row\">\n <ion-avatar [style.background-color]=\"'white'\">\n <ion-img *ngIf=\"row.currentData.avatar; let avatarUrl; else: generateIcon\" [src]=\"avatarUrl\"></ion-img>\n <ng-template #generateIcon>\n <svg width=\"39\" height=\"39\" [data-jdenticon-value]=\"row.currentData.id\"></svg>\n </ng-template>\n </ion-avatar>\n </td>\n </ng-container>\n\n <!-- lastName -->\n <ng-container matColumnDef=\"lastName\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>\n <span translate>USER.LAST_NAME</span>\n </th>\n <td mat-cell *matCellDef=\"let row\" (click)=\"focusColumn = 'lastName'\">\n <mat-form-field *ngIf=\"row.editing; else readonlyCell\">\n <input\n matInput\n [formControl]=\"row.validator.controls['lastName']\"\n [placeholder]=\"'USER.LAST_NAME' | translate\"\n [readonly]=\"!row.editing\"\n [appAutofocus]=\"row.editing && focusColumn === 'lastName'\"\n />\n <mat-error *ngIf=\"row.validator.controls['lastName'].hasError('required')\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n <mat-error *ngIf=\"row.validator.controls['lastName'].hasError('minlength')\">\n <span>{{ 'ERROR.FIELD_MIN_LENGTH' | translate: { requiredLength: 2 } }}</span>\n </mat-error>\n </mat-form-field>\n <ng-template #readonlyCell>\n <ion-label appAutoTitle>\n {{ row.validator | formGetValue: 'lastName' }}\n </ion-label>\n </ng-template>\n </td>\n </ng-container>\n\n <!-- firstname -->\n <ng-container matColumnDef=\"firstName\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>\n <span translate>USER.FIRST_NAME</span>\n </th>\n <td mat-cell *matCellDef=\"let row\" (click)=\"focusColumn = 'firstName'\">\n <mat-form-field *ngIf=\"row.editing; else readonlyCell\">\n <input\n matInput\n [formControl]=\"row.validator.controls['firstName']\"\n [placeholder]=\"'USER.FIRST_NAME' | translate\"\n [readonly]=\"!row.editing\"\n [appAutofocus]=\"row.editing && focusColumn === 'firstName'\"\n />\n <mat-error *ngIf=\"row.validator.controls['firstName'].hasError('required')\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n <mat-error *ngIf=\"row.validator.controls['firstName'].hasError('minlength')\">\n <span>{{ 'ERROR.FIELD_MIN_LENGTH' | translate: { requiredLength: 2 } }}</span>\n </mat-error>\n </mat-form-field>\n <ng-template #readonlyCell>\n <ion-label appAutoTitle>\n {{ row.validator | formGetValue: 'firstName' }}\n </ion-label>\n </ng-template>\n </td>\n </ng-container>\n\n <!-- email -->\n <ng-container matColumnDef=\"email\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>\n <span translate>USER.EMAIL</span>\n </th>\n <td mat-cell *matCellDef=\"let row\" (click)=\"focusColumn = 'email'\">\n <mat-form-field *ngIf=\"row.editing; else readonlyCell\">\n <input\n matInput\n [formControl]=\"row.validator.controls['email']\"\n [placeholder]=\"'USER.EMAIL' | translate\"\n [readonly]=\"!row.editing\"\n [appAutofocus]=\"row.editing && focusColumn === 'email'\"\n />\n <mat-error *ngIf=\"row.validator.controls['email'].hasError('required')\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n <mat-error *ngIf=\"row.validator.controls['email'].hasError('email')\">\n <span translate>ERROR.FIELD_NOT_VALID_EMAIL</span>\n </mat-error>\n </mat-form-field>\n <ng-template #readonlyCell>\n <ion-label appAutoTitle>\n {{ row.validator | formGetValue: 'email' }}\n </ion-label>\n </ng-template>\n </td>\n </ng-container>\n\n <!-- additional fields -->\n <ng-container *ngFor=\"let definition of additionalFields\" [matColumnDef]=\"definition.key\">\n <th mat-header-cell *matHeaderCellDef>\n <span>{{ definition.label | translate }}</span>\n </th>\n <td mat-cell *matCellDef=\"let row\" (click)=\"focusColumn = definition.key\">\n <app-form-field\n floatLabel=\"never\"\n [definition]=\"definition\"\n [formControl]=\"row.validator.controls[definition.key]\"\n [required]=\"definition.extra?.account?.required\"\n [autofocus]=\"row.editing && focusColumn === definition.key\"\n ></app-form-field>\n </td>\n </ng-container>\n\n <!-- profile column -->\n <ng-container matColumnDef=\"profile\">\n <th mat-header-cell *matHeaderCellDef>\n <span translate>USER.PROFILE</span>\n </th>\n <td mat-cell *matCellDef=\"let row\" (click)=\"focusColumn = 'profile'\">\n <mat-form-field>\n <mat-select\n [formControl]=\"row.validator.controls['mainProfile']\"\n [placeholder]=\"'USER.PROFILE' | translate\"\n >\n <mat-option *ngFor=\"let item of profiles\" [value]=\"item\">\n {{ 'USER.PROFILE_ENUM.' + item | uppercase | translate }}\n </mat-option>\n </mat-select>\n <mat-error *ngIf=\"row.validator.controls['mainProfile'].hasError('required')\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n </mat-form-field>\n </td>\n </ng-container>\n\n <!-- Status column -->\n <ng-container matColumnDef=\"status\">\n <th mat-header-cell *matHeaderCellDef>\n <span translate>USER.STATUS</span>\n </th>\n <td mat-cell *matCellDef=\"let row\" (click)=\"focusColumn = 'status'\">\n <mat-form-field>\n <mat-select\n [formControl]=\"row.validator.controls['statusId']\"\n [placeholder]=\"'REFERENTIAL.STATUS' | translate\"\n >\n <mat-select-trigger>\n <span *ngIf=\"row.validator.controls['statusId'].value >=0\">\n {{ statusById[row.validator.controls['statusId'].value]?.label | translate }}\n </span>\n </mat-select-trigger>\n <mat-option *ngFor=\"let item of statusList\" [value]=\"item.id\">\n <mat-icon><ion-icon [name]=\"item.icon\"></ion-icon></mat-icon>\n {{ item.label | translate }}\n </mat-option>\n </mat-select>\n <mat-error *ngIf=\"row.validator.controls['statusId'].hasError('required')\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n </mat-form-field>\n </td>\n </ng-container>\n\n <!-- username -->\n <ng-container matColumnDef=\"username\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>\n <span translate>USER.USERNAME</span>\n </th>\n <td mat-cell *matCellDef=\"let row\" (click)=\"focusColumn = 'username'\">\n <mat-form-field *ngIf=\"row.editing; else readonlyCell\">\n <input\n matInput\n [formControl]=\"row.validator.controls.username\"\n [placeholder]=\"'USER.USERNAME' | translate\"\n [readonly]=\"!row.editing\"\n [appAutofocus]=\"row.editing && focusColumn === 'username'\"\n />\n <mat-error *ngIf=\"row.validator.controls.username.hasError('required')\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n </mat-form-field>\n <ng-template #readonlyCell>\n <ion-label appAutoTitle>\n {{ row.validator | formGetValue: 'username' }}\n </ion-label>\n </ng-template>\n </td>\n </ng-container>\n\n <!-- username extranet -->\n <ng-container matColumnDef=\"usernameExtranet\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>\n <span translate>USER.USERNAME_EXTRANET</span>\n </th>\n <td mat-cell *matCellDef=\"let row\" (click)=\"focusColumn = 'usernameExtranet'\">\n <mat-form-field *ngIf=\"row.editing; else readonlyCell\">\n <input\n matInput\n [formControl]=\"row.validator.controls.usernameExtranet\"\n [placeholder]=\"'USER.USERNAME_EXTRANET' | translate\"\n [readonly]=\"!row.editing\"\n [appAutofocus]=\"row.editing && focusColumn === 'usernameExtranet'\"\n />\n <mat-error *ngIf=\"row.validator.controls.usernameExtranet.hasError('required')\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n </mat-form-field>\n <ng-template #readonlyCell>\n <ion-label appAutoTitle>\n {{ row.validator | formGetValue: 'usernameExtranet' }}\n </ion-label>\n </ng-template>\n </td>\n </ng-container>\n\n <!-- pubkey -->\n <ng-container matColumnDef=\"pubkey\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>\n <span translate>USER.PUBKEY</span>\n </th>\n <td\n mat-cell\n *matCellDef=\"let row\"\n [title]=\"row.validator.controls.pubkey.valueChanges | async\"\n (click)=\"focusColumn = 'pubkey'\"\n >\n <mat-form-field *ngIf=\"row.editing; else readonlyCell\">\n <input\n matInput\n [formControl]=\"row.validator.controls['pubkey']\"\n [placeholder]=\"'USER.PUBKEY' | translate\"\n [readonly]=\"!row.editing\"\n autocomplete=\"off\"\n />\n <mat-error *ngIf=\"row.validator.controls.pubkey.hasError('required')\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n <mat-error *ngIf=\"row.validator.controls.pubkey.hasError('pubkey')\">\n <span translate>ERROR.FIELD_NOT_VALID_PUBKEY</span>\n </mat-error>\n </mat-form-field>\n <ng-template #readonlyCell>\n <ion-label appAutoTitle>\n {{ row.validator | formGetValue: 'pubkey' }}\n </ion-label>\n </ng-template>\n </td>\n </ng-container>\n\n <!-- Creation date column -->\n <ng-container matColumnDef=\"creationDate\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>\n <ion-label translate>USER.CREATION_DATE</ion-label>\n </th>\n <td mat-cell *matCellDef=\"let row\" class=\"mat-form-field-disabled\">\n <ion-text class=\"ion-text-end\" color=\"medium\" *ngIf=\"row.id !== -1\">\n {{ row.currentData.creationDate | dateFormat: { time: true } }}\n </ion-text>\n </td>\n </ng-container>\n\n <!-- Update date column -->\n <ng-container matColumnDef=\"updateDate\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>\n <ion-label translate>USER.UPDATE_DATE</ion-label>\n </th>\n <td mat-cell *matCellDef=\"let row\" class=\"mat-form-field-disabled\">\n <ion-text class=\"ion-text-end\" color=\"medium\" *ngIf=\"row.id !== -1\">\n {{ row.currentData.updateDate | dateFormat: { time: true } }}\n </ion-text>\n </td>\n </ng-container>\n\n <!-- Actions buttons column -->\n <app-actions-column\n [stickyEnd]=\"stickyEnd\"\n (cancelOrDeleteClick)=\"cancelOrDelete($event.event, $event.row)\"\n (confirmEditCreateClick)=\"confirmEditCreate($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 [canCancel]=\"false\"\n >\n <!-- table options menu -->\n <button\n matHeader\n mat-icon-button\n [title]=\"'COMMON.BTN_OPTIONS' | translate\"\n [matMenuTriggerFor]=\"tableOptionsMenu\"\n >\n <mat-icon>more_vert</mat-icon>\n </button>\n </app-actions-column>\n\n <tr mat-header-row *matHeaderRowDef=\"displayedColumns; sticky: true\"></tr>\n <tr\n mat-row\n *matRowDef=\"let row; columns: displayedColumns\"\n [class.mat-row-selected]=\"row.editing\"\n [class.mat-row-error]=\"row.validator.invalid\"\n [class.mat-row-dirty]=\"row.currentData.dirty\"\n [class.mat-row-disabled]=\"!row.editing\"\n (click)=\"clickRow($event, row)\"\n (keydown.escape)=\"escapeEditingRow($event)\"\n [cdkTrapFocus]=\"!row.validator?.valid\"\n ></tr>\n </table>\n\n <!-- D\u00E9clencheur invisible pour le mat-menu -->\n\n @if (loadingSubject | async) {\n <ion-item>\n <ion-skeleton-text animated></ion-skeleton-text>\n </ion-item>\n } @else if (totalRowCount === 0) {\n <ion-item>\n <ion-text color=\"danger\" class=\"text-italic\" translate>COMMON.NO_RESULT</ion-text>\n </ion-item>\n }\n </div>\n</ion-content>\n\n<!-- Table options menu -->\n<mat-menu #tableOptionsMenu=\"matMenu\" xPosition=\"after\">\n <!-- display columns -->\n <button mat-menu-item (click)=\"openSelectColumnsModal($event)\">\n <mat-icon>view_column</mat-icon>\n <ion-label translate>COMMON.DISPLAYED_COLUMNS_DOTS</ion-label>\n </button>\n\n @if (usePageSettings) {\n <mat-divider></mat-divider>\n\n <!-- Compact mode -->\n <button mat-menu-item (click)=\"toggleCompactMode()\">\n <mat-icon>{{ compact ? 'check_box' : 'check_box_outline_blank' }}</mat-icon>\n <ion-label translate>COMMON.BTN_COMPACT_ROWS</ion-label>\n </button>\n }\n</mat-menu>\n\n<ion-footer>\n <mat-paginator\n [length]=\"totalRowCount\"\n [pageSize]=\"defaultPageSize\"\n [pageSizeOptions]=\"defaultPageSizeOptions\"\n showFirstLastButtons\n ></mat-paginator>\n\n <app-form-buttons-bar\n *ngIf=\"!mobile && canEdit\"\n (onCancel)=\"cancel($event)\"\n (onSave)=\"save()\"\n [disabled]=\"(loadingSubject | async) === true || (dirtySubject | async) !== true\"\n >\n <!-- error -->\n <ion-item *ngIf=\"errorSubject | async; let error\" 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=\"mobile\">\n <ion-fab-button color=\"tertiary\" (click)=\"addRow()\">\n <ion-icon name=\"add\"></ion-icon>\n </ion-fab-button>\n</ion-fab>\n", styles: [".mat-expansion-panel{margin-bottom:5px}.mat-expansion-panel .form-container mat-form-field{width:100%}.mat-expansion-panel mat-action-row ion-label{line-height:36px}.table-container{height:100%}.mat-mdc-table .mat-column-avatar{--avatar-width: 40px;--avatar-height: 40px;width:calc(var(--avatar-width) + 10px)}.mat-mdc-table .mat-column-avatar ion-avatar{--border-radius: 5px !important;--border-width: 1px !important;--border-color: rgba(var(--ion-color-secondary-rgb), .5) !important;height:var(--avatar-height);max-height:var(--avatar-height);width:var(--avatar-width);max-width:var(--avatar-width);border:solid var(--border-width) var(--border-color);margin:0 2px}.mat-mdc-table .mat-column-avatar ion-avatar svg{max-height:calc(var(--avatar-height) - 1px);max-width:calc(var(--avatar-width) - 1px)}.mat-mdc-table.compact{--mat-row-height: 33px}.mat-mdc-table.compact .mat-column-avatar{--avatar-width: calc(var(--mat-row-height, 33px) - 4px);--avatar-height: calc(var(--mat-row-height, 33px) - 4px)}.mat-mdc-table .mat-column-id{min-width:50px;max-width:120px;padding-right:var(--mat-cell-horizontal-padding, 4px)}.mat-mdc-table .mat-column-lastName,.mat-mdc-table .mat-column-firstName{min-width:80px}.mat-mdc-table .mat-column-email,.mat-mdc-table .mat-column-pubkey,.mat-mdc-table .mat-column-department{min-width:180px}.mat-mdc-table .mat-column-profile{min-width:110px}.mat-mdc-table .mat-column-status,.mat-mdc-table .mat-column-creationDate,.mat-mdc-table .mat-column-updateDate{min-width:130px}\n"] }]
|
|
376
|
+
args: [{ selector: 'app-users-table', providers: [{ provide: ValidatorService, useExisting: PersonValidatorService }], animations: [slideUpDownAnimation], changeDetection: ChangeDetectionStrategy.OnPush, template: "<app-toolbar\n [title]=\"'USER.LIST.TITLE' | translate\"\n color=\"primary\"\n [canGoBack]=\"false\"\n [hasValidate]=\"(loadingSubject | async) !== true && (dirtySubject | async) === true\"\n (onValidate)=\"save()\"\n>\n <ion-buttons slot=\"end\">\n <!-- Compose message -->\n <button\n mat-icon-button\n *ngIf=\"canSendMessage\"\n [title]=\"'USER.LIST.BTN_SEND_MESSAGE' | translate\"\n (click)=\"openComposeMessageModal($event)\"\n >\n <ion-icon name=\"mail\" slot=\"icon-only\"></ion-icon>\n </button>\n\n @if (selection | isEmptySelection) {\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 <!-- Refresh -->\n <button mat-icon-button *ngIf=\"!mobile\" [title]=\"'COMMON.BTN_REFRESH' | translate\" (click)=\"emitRefresh()\">\n <mat-icon>refresh</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 } @else {\n <!-- delete -->\n <button\n mat-icon-button\n class=\"hidden-xs hidden-sm\"\n [title]=\"'COMMON.BTN_DELETE' | translate\"\n (click)=\"deleteSelection($event)\"\n >\n <mat-icon>delete</mat-icon>\n </button>\n }\n\n @if (!mobile) {\n <button mat-icon-button [title]=\"'COMMON.BTN_OPTIONS' | translate\" [matMenuTriggerFor]=\"toolbarOptionsMenu\">\n <mat-icon>more_vert</mat-icon>\n </button>\n }\n </ion-buttons>\n</app-toolbar>\n\n<!-- Toolbar option menu -->\n<mat-menu #toolbarOptionsMenu=\"matMenu\" xPosition=\"after\">\n <!-- export button -->\n <button mat-menu-item [disabled]=\"!canDownload\" (click)=\"exportToCsv($event)\">\n <mat-icon>download</mat-icon>\n <ion-label translate>FILE.CSV.BTN_DOWNLOAD_HELP</ion-label>\n </button>\n</mat-menu>\n\n<ion-content class=\"ion-no-padding\">\n <!-- error -->\n <ion-item\n *ngIf=\"errorSubject | async; let error\"\n lines=\"none\"\n class=\"hidden-sm hidden-xs hidden-mobile\"\n @slideUpDownAnimation\n >\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 <!-- debug -->\n <app-debug *ngIf=\"debug\">\n <ion-grid class=\"ion-no-padding\">\n <ion-row>\n <ion-col>\n focusColumn: {{ focusColumn }}\n <br />\n loadingSubject: {{ loading }}\n <br />\n </ion-col>\n </ion-row>\n </ion-grid>\n </app-debug>\n\n <!-- search -->\n <mat-expansion-panel #filterExpansionPanel class=\"ion-no-padding filter-panel filter-panel-floating\">\n <form class=\"form-container ion-padding\" [formGroup]=\"filterForm\" (ngSubmit)=\"emitRefresh()\">\n <ion-grid>\n <ion-row>\n <ion-col>\n <!-- search -->\n <mat-form-field>\n <mat-label>{{ 'USER.LIST.FILTER.SEARCH' | translate }}</mat-label>\n <input matInput formControlName=\"searchText\" />\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\n <ion-col>\n <!-- status -->\n <mat-form-field>\n <mat-label>{{ 'USER.STATUS' | translate }}</mat-label>\n <mat-select formControlName=\"statusId\">\n <mat-option [value]=\"null\">\n <i><span translate>COMMON.EMPTY_OPTION</span></i>\n </mat-option>\n <mat-option *ngFor=\"let item of statusList\" [value]=\"item.id\">\n <ion-icon [name]=\"item.icon\"></ion-icon>\n {{ item.label | translate }}\n </mat-option>\n </mat-select>\n\n <button\n mat-icon-button\n matSuffix\n tabindex=\"-1\"\n type=\"button\"\n (click)=\"clearControlValue($event, filterForm.controls.statusId)\"\n [hidden]=\"filterForm.controls.statusId.disabled || !filterForm.controls.statusId.value\"\n >\n <mat-icon>close</mat-icon>\n </button>\n </mat-form-field>\n </ion-col>\n\n <ion-col>\n <!-- user profiles -->\n <mat-chips-field\n formControlName=\"userProfiles\"\n [placeholder]=\"'USER.PROFILES' | translate\"\n chipColor=\"accent\"\n [items]=\"userProfileList\"\n [displayAttributes]=\"['name']\"\n [clearable]=\"true\">\n </mat-chips-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) === true || filterForm.dirty\"\n [color]=\"empty && 'danger'\"\n class=\"ion-padding\"\n >\n {{\n (totalRowCount ? 'COMMON.RESULT_COUNT' : 'COMMON.NO_RESULT')\n | translate\n : {\n count: (totalRowCount | numberFormat),\n }\n }}\n </ion-label>\n\n <div class=\"toolbar-spacer\"></div>\n\n <!-- Close panel -->\n <ion-button\n mat-button\n fill=\"clear\"\n color=\"dark\"\n (click)=\"filterExpansionPanel.close()\"\n [disabled]=\"loadingSubject | async\"\n >\n <ion-text translate>COMMON.BTN_CLOSE</ion-text>\n </ion-button>\n\n <!-- Search button -->\n <ion-button\n mat-button\n [color]=\"filterForm.dirty ? 'tertiary' : 'dark'\"\n [fill]=\"filterForm.dirty ? 'solid' : 'clear'\"\n (click)=\"applyFilterAndClosePanel($event)\"\n [disabled]=\"loadingSubject | async\"\n >\n <ion-text translate>COMMON.BTN_APPLY</ion-text>\n </ion-button>\n </mat-action-row>\n </mat-expansion-panel>\n\n <!-- error -->\n <ion-item *ngIf=\"mobile && (errorSubject | async); let error\" lines=\"none\">\n <ion-icon color=\"danger\" slot=\"start\" name=\"alert-circle\"></ion-icon>\n <ion-label color=\"danger\" class=\"error\" [innerHTML]=\"error | translate\"></ion-label>\n </ion-item>\n\n <div class=\"table-container\">\n <table\n #table\n mat-table\n matSort\n [class.compact]=\"compact\"\n [dataSource]=\"dataSource\"\n [matSortActive]=\"defaultSortBy\"\n [matSortDirection]=\"defaultSortDirection\"\n matSortDisableClear\n [trackBy]=\"trackByFn\"\n >\n <ng-container matColumnDef=\"select\" [sticky]=\"sticky\">\n <th mat-header-cell *matHeaderCellDef [class.cdk-visually-hidden]=\"!inlineEdition\">\n <mat-checkbox\n (change)=\"$event ? masterToggle() : null\"\n [checked]=\"this | isAllSelected\"\n [indeterminate]=\"this | isNotAllSelected\"\n ></mat-checkbox>\n </th>\n <td mat-cell *matCellDef=\"let row\" [class.cdk-visually-hidden]=\"!inlineEdition\">\n <mat-checkbox (click)=\"toggleSelectRow($event, row)\" [checked]=\"selection | isSelected: row\"></mat-checkbox>\n </td>\n </ng-container>\n\n <!-- Id Column -->\n <ng-container matColumnDef=\"id\" [sticky]=\"sticky\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>\n <ion-label>#</ion-label>\n </th>\n <td mat-cell *matCellDef=\"let row\">\n <ion-label>{{ row.currentData.id }}</ion-label>\n </td>\n </ng-container>\n\n <!-- avatar Column -->\n <ng-container matColumnDef=\"avatar\" [sticky]=\"sticky\">\n <th mat-header-cell *matHeaderCellDef></th>\n <td mat-cell *matCellDef=\"let row\">\n <ion-avatar [style.background-color]=\"'white'\">\n <ion-img *ngIf=\"row.currentData.avatar; let avatarUrl; else: generateIcon\" [src]=\"avatarUrl\"></ion-img>\n <ng-template #generateIcon>\n <svg width=\"39\" height=\"39\" [data-jdenticon-value]=\"row.currentData.id\"></svg>\n </ng-template>\n </ion-avatar>\n </td>\n </ng-container>\n\n <!-- lastName -->\n <ng-container matColumnDef=\"lastName\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>\n <span translate>USER.LAST_NAME</span>\n </th>\n <td mat-cell *matCellDef=\"let row\" (click)=\"focusColumn = 'lastName'\">\n <mat-form-field *ngIf=\"row.editing; else readonlyCell\">\n <input\n matInput\n [formControl]=\"row.validator.controls['lastName']\"\n [placeholder]=\"'USER.LAST_NAME' | translate\"\n [readonly]=\"!row.editing\"\n [appAutofocus]=\"row.editing && focusColumn === 'lastName'\"\n />\n <mat-error *ngIf=\"row.validator.controls['lastName'].hasError('required')\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n <mat-error *ngIf=\"row.validator.controls['lastName'].hasError('minlength')\">\n <span>{{ 'ERROR.FIELD_MIN_LENGTH' | translate: { requiredLength: 2 } }}</span>\n </mat-error>\n </mat-form-field>\n <ng-template #readonlyCell>\n <ion-label appAutoTitle>\n {{ row.validator | formGetValue: 'lastName' }}\n </ion-label>\n </ng-template>\n </td>\n </ng-container>\n\n <!-- firstname -->\n <ng-container matColumnDef=\"firstName\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>\n <span translate>USER.FIRST_NAME</span>\n </th>\n <td mat-cell *matCellDef=\"let row\" (click)=\"focusColumn = 'firstName'\">\n <mat-form-field *ngIf=\"row.editing; else readonlyCell\">\n <input\n matInput\n [formControl]=\"row.validator.controls['firstName']\"\n [placeholder]=\"'USER.FIRST_NAME' | translate\"\n [readonly]=\"!row.editing\"\n [appAutofocus]=\"row.editing && focusColumn === 'firstName'\"\n />\n <mat-error *ngIf=\"row.validator.controls['firstName'].hasError('required')\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n <mat-error *ngIf=\"row.validator.controls['firstName'].hasError('minlength')\">\n <span>{{ 'ERROR.FIELD_MIN_LENGTH' | translate: { requiredLength: 2 } }}</span>\n </mat-error>\n </mat-form-field>\n <ng-template #readonlyCell>\n <ion-label appAutoTitle>\n {{ row.validator | formGetValue: 'firstName' }}\n </ion-label>\n </ng-template>\n </td>\n </ng-container>\n\n <!-- email -->\n <ng-container matColumnDef=\"email\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>\n <span translate>USER.EMAIL</span>\n </th>\n <td mat-cell *matCellDef=\"let row\" (click)=\"focusColumn = 'email'\">\n <mat-form-field *ngIf=\"row.editing; else readonlyCell\">\n <input\n matInput\n [formControl]=\"row.validator.controls['email']\"\n [placeholder]=\"'USER.EMAIL' | translate\"\n [readonly]=\"!row.editing\"\n [appAutofocus]=\"row.editing && focusColumn === 'email'\"\n />\n <mat-error *ngIf=\"row.validator.controls['email'].hasError('required')\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n <mat-error *ngIf=\"row.validator.controls['email'].hasError('email')\">\n <span translate>ERROR.FIELD_NOT_VALID_EMAIL</span>\n </mat-error>\n </mat-form-field>\n <ng-template #readonlyCell>\n <ion-label appAutoTitle>\n {{ row.validator | formGetValue: 'email' }}\n </ion-label>\n </ng-template>\n </td>\n </ng-container>\n\n <!-- additional fields -->\n <ng-container *ngFor=\"let definition of additionalFields\" [matColumnDef]=\"definition.key\">\n <th mat-header-cell *matHeaderCellDef>\n <span>{{ definition.label | translate }}</span>\n </th>\n <td mat-cell *matCellDef=\"let row\" (click)=\"focusColumn = definition.key\">\n <app-form-field\n floatLabel=\"never\"\n [definition]=\"definition\"\n [formControl]=\"row.validator.controls[definition.key]\"\n [required]=\"definition.extra?.account?.required\"\n [autofocus]=\"row.editing && focusColumn === definition.key\"\n ></app-form-field>\n </td>\n </ng-container>\n\n <!-- profile column -->\n <ng-container matColumnDef=\"profile\">\n <th mat-header-cell *matHeaderCellDef>\n <span translate>USER.PROFILE</span>\n </th>\n <td mat-cell *matCellDef=\"let row\" (click)=\"focusColumn = 'profile'\">\n <mat-form-field>\n <mat-select\n [formControl]=\"row.validator.controls['mainProfile']\"\n [placeholder]=\"'USER.PROFILE' | translate\"\n >\n <mat-option *ngFor=\"let item of profiles\" [value]=\"item\">\n {{ 'USER.PROFILE_ENUM.' + item | uppercase | translate }}\n </mat-option>\n </mat-select>\n <mat-error *ngIf=\"row.validator.controls['mainProfile'].hasError('required')\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n </mat-form-field>\n </td>\n </ng-container>\n\n <!-- Status column -->\n <ng-container matColumnDef=\"status\">\n <th mat-header-cell *matHeaderCellDef>\n <span translate>USER.STATUS</span>\n </th>\n <td mat-cell *matCellDef=\"let row\" (click)=\"focusColumn = 'status'\">\n <mat-form-field>\n <mat-select\n [formControl]=\"row.validator.controls['statusId']\"\n [placeholder]=\"'REFERENTIAL.STATUS' | translate\"\n >\n <mat-select-trigger>\n <span *ngIf=\"row.validator.controls['statusId'].value >= 0\">\n {{ statusById[row.validator.controls['statusId'].value]?.label | translate }}\n </span>\n </mat-select-trigger>\n <mat-option *ngFor=\"let item of statusList\" [value]=\"item.id\">\n <mat-icon><ion-icon [name]=\"item.icon\"></ion-icon></mat-icon>\n {{ item.label | translate }}\n </mat-option>\n </mat-select>\n <mat-error *ngIf=\"row.validator.controls['statusId'].hasError('required')\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n </mat-form-field>\n </td>\n </ng-container>\n\n <!-- username -->\n <ng-container matColumnDef=\"username\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>\n <span translate>USER.USERNAME</span>\n </th>\n <td mat-cell *matCellDef=\"let row\" (click)=\"focusColumn = 'username'\">\n <mat-form-field *ngIf=\"row.editing; else readonlyCell\">\n <input\n matInput\n [formControl]=\"row.validator.controls.username\"\n [placeholder]=\"'USER.USERNAME' | translate\"\n [readonly]=\"!row.editing\"\n [appAutofocus]=\"row.editing && focusColumn === 'username'\"\n />\n <mat-error *ngIf=\"row.validator.controls.username.hasError('required')\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n </mat-form-field>\n <ng-template #readonlyCell>\n <ion-label appAutoTitle>\n {{ row.validator | formGetValue: 'username' }}\n </ion-label>\n </ng-template>\n </td>\n </ng-container>\n\n <!-- username extranet -->\n <ng-container matColumnDef=\"usernameExtranet\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>\n <span translate>USER.USERNAME_EXTRANET</span>\n </th>\n <td mat-cell *matCellDef=\"let row\" (click)=\"focusColumn = 'usernameExtranet'\">\n <mat-form-field *ngIf=\"row.editing; else readonlyCell\">\n <input\n matInput\n [formControl]=\"row.validator.controls.usernameExtranet\"\n [placeholder]=\"'USER.USERNAME_EXTRANET' | translate\"\n [readonly]=\"!row.editing\"\n [appAutofocus]=\"row.editing && focusColumn === 'usernameExtranet'\"\n />\n <mat-error *ngIf=\"row.validator.controls.usernameExtranet.hasError('required')\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n </mat-form-field>\n <ng-template #readonlyCell>\n <ion-label appAutoTitle>\n {{ row.validator | formGetValue: 'usernameExtranet' }}\n </ion-label>\n </ng-template>\n </td>\n </ng-container>\n\n <!-- pubkey -->\n <ng-container matColumnDef=\"pubkey\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>\n <span translate>USER.PUBKEY</span>\n </th>\n <td\n mat-cell\n *matCellDef=\"let row\"\n [title]=\"row.validator.controls.pubkey.valueChanges | async\"\n (click)=\"focusColumn = 'pubkey'\"\n >\n <mat-form-field *ngIf=\"row.editing; else readonlyCell\">\n <input\n matInput\n [formControl]=\"row.validator.controls['pubkey']\"\n [placeholder]=\"'USER.PUBKEY' | translate\"\n [readonly]=\"!row.editing\"\n autocomplete=\"off\"\n />\n <mat-error *ngIf=\"row.validator.controls.pubkey.hasError('required')\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n <mat-error *ngIf=\"row.validator.controls.pubkey.hasError('pubkey')\">\n <span translate>ERROR.FIELD_NOT_VALID_PUBKEY</span>\n </mat-error>\n </mat-form-field>\n <ng-template #readonlyCell>\n <ion-label appAutoTitle>\n {{ row.validator | formGetValue: 'pubkey' }}\n </ion-label>\n </ng-template>\n </td>\n </ng-container>\n\n <!-- Creation date column -->\n <ng-container matColumnDef=\"creationDate\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>\n <ion-label translate>USER.CREATION_DATE</ion-label>\n </th>\n <td mat-cell *matCellDef=\"let row\" class=\"mat-form-field-disabled\">\n <ion-text class=\"ion-text-end\" color=\"medium\" *ngIf=\"row.id !== -1\">\n {{ row.currentData.creationDate | dateFormat: { time: true } }}\n </ion-text>\n </td>\n </ng-container>\n\n <!-- Update date column -->\n <ng-container matColumnDef=\"updateDate\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header>\n <ion-label translate>USER.UPDATE_DATE</ion-label>\n </th>\n <td mat-cell *matCellDef=\"let row\" class=\"mat-form-field-disabled\">\n <ion-text class=\"ion-text-end\" color=\"medium\" *ngIf=\"row.id !== -1\">\n {{ row.currentData.updateDate | dateFormat: { time: true } }}\n </ion-text>\n </td>\n </ng-container>\n\n <!-- Actions buttons column -->\n <app-actions-column\n [stickyEnd]=\"stickyEnd\"\n (cancelOrDeleteClick)=\"cancelOrDelete($event.event, $event.row)\"\n (confirmEditCreateClick)=\"confirmEditCreate($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 [canCancel]=\"false\"\n >\n <!-- table options menu -->\n <button\n matHeader\n mat-icon-button\n [title]=\"'COMMON.BTN_OPTIONS' | translate\"\n [matMenuTriggerFor]=\"tableOptionsMenu\"\n >\n <mat-icon>more_vert</mat-icon>\n </button>\n </app-actions-column>\n\n <tr mat-header-row *matHeaderRowDef=\"displayedColumns; sticky: true\"></tr>\n <tr\n mat-row\n *matRowDef=\"let row; columns: displayedColumns\"\n [class.mat-row-selected]=\"row.editing\"\n [class.mat-row-error]=\"row.validator.invalid\"\n [class.mat-row-dirty]=\"row.currentData.dirty\"\n [class.mat-row-disabled]=\"!row.editing\"\n (click)=\"clickRow($event, row)\"\n (keydown.escape)=\"escapeEditingRow($event)\"\n [cdkTrapFocus]=\"!row.validator?.valid\"\n ></tr>\n </table>\n\n <!-- D\u00E9clencheur invisible pour le mat-menu -->\n\n @if (loadingSubject | async) {\n <ion-item>\n <ion-skeleton-text animated></ion-skeleton-text>\n </ion-item>\n } @else if (totalRowCount === 0) {\n <ion-item>\n <ion-text color=\"danger\" class=\"text-italic\" translate>COMMON.NO_RESULT</ion-text>\n </ion-item>\n }\n </div>\n</ion-content>\n\n<!-- Table options menu -->\n<mat-menu #tableOptionsMenu=\"matMenu\" xPosition=\"after\">\n <!-- display columns -->\n <button mat-menu-item (click)=\"openSelectColumnsModal($event)\">\n <mat-icon>view_column</mat-icon>\n <ion-label translate>COMMON.DISPLAYED_COLUMNS_DOTS</ion-label>\n </button>\n\n @if (usePageSettings) {\n <mat-divider></mat-divider>\n\n <!-- Compact mode -->\n <button mat-menu-item (click)=\"toggleCompactMode()\">\n <mat-icon>{{ compact ? 'check_box' : 'check_box_outline_blank' }}</mat-icon>\n <ion-label translate>COMMON.BTN_COMPACT_ROWS</ion-label>\n </button>\n }\n</mat-menu>\n\n<ion-footer>\n <mat-paginator\n [length]=\"totalRowCount\"\n [pageSize]=\"defaultPageSize\"\n [pageSizeOptions]=\"defaultPageSizeOptions\"\n showFirstLastButtons\n ></mat-paginator>\n\n <app-form-buttons-bar\n *ngIf=\"!mobile && canEdit\"\n (onCancel)=\"cancel($event)\"\n (onSave)=\"save()\"\n [disabled]=\"(loadingSubject | async) === true || (dirtySubject | async) !== true\"\n >\n <!-- error -->\n <ion-item *ngIf=\"errorSubject | async; let error\" 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=\"mobile\">\n <ion-fab-button color=\"tertiary\" (click)=\"addRow()\">\n <ion-icon name=\"add\"></ion-icon>\n </ion-fab-button>\n</ion-fab>\n", styles: [".mat-expansion-panel{margin-bottom:5px}.mat-expansion-panel .form-container mat-form-field{width:100%}.mat-expansion-panel mat-action-row ion-label{line-height:36px}.table-container{height:100%}.mat-mdc-table .mat-column-avatar{--avatar-width: 40px;--avatar-height: 40px;width:calc(var(--avatar-width) + 10px)}.mat-mdc-table .mat-column-avatar ion-avatar{--border-radius: 5px !important;--border-width: 1px !important;--border-color: rgba(var(--ion-color-secondary-rgb), .5) !important;height:var(--avatar-height);max-height:var(--avatar-height);width:var(--avatar-width);max-width:var(--avatar-width);border:solid var(--border-width) var(--border-color);margin:0 2px}.mat-mdc-table .mat-column-avatar ion-avatar svg{max-height:calc(var(--avatar-height) - 1px);max-width:calc(var(--avatar-width) - 1px)}.mat-mdc-table.compact{--mat-row-height: 33px}.mat-mdc-table.compact .mat-column-avatar{--avatar-width: calc(var(--mat-row-height, 33px) - 4px);--avatar-height: calc(var(--mat-row-height, 33px) - 4px)}.mat-mdc-table .mat-column-id{min-width:50px;max-width:120px;padding-right:var(--mat-cell-horizontal-padding, 4px)}.mat-mdc-table .mat-column-lastName,.mat-mdc-table .mat-column-firstName{min-width:80px}.mat-mdc-table .mat-column-email,.mat-mdc-table .mat-column-pubkey,.mat-mdc-table .mat-column-department{min-width:180px}.mat-mdc-table .mat-column-profile{min-width:110px}.mat-mdc-table .mat-column-status,.mat-mdc-table .mat-column-creationDate,.mat-mdc-table .mat-column-updateDate{min-width:130px}\n"] }]
|
|
357
377
|
}], ctorParameters: () => [{ type: i0.Injector }, { type: i1.UntypedFormBuilder }, { type: i2.AccountService }, { type: i3.ValidatorService }, { type: i4.ConfigService }, { type: i5.PersonService }, { type: i6.MessageService }, { type: i7.MenuService }, { type: undefined, decorators: [{
|
|
358
378
|
type: Inject,
|
|
359
379
|
args: [ENVIRONMENT]
|
|
@@ -376,4 +396,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImpo
|
|
|
376
396
|
type: ViewChild,
|
|
377
397
|
args: [MatExpansionPanel, { static: true }]
|
|
378
398
|
}] } });
|
|
379
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXNlcnMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBwL2FkbWluL3VzZXJzL3VzZXJzLnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vc3JjL2FwcC9hZG1pbi91c2Vycy91c2Vycy5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSx1QkFBdUIsRUFBRSxTQUFTLEVBQUUsTUFBTSxFQUFZLEtBQUssRUFBVSxTQUFTLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDakksT0FBTyxFQUFFLE1BQU0sRUFBRSx1QkFBdUIsRUFBRSxNQUFNLHdDQUF3QyxDQUFDO0FBQ3pGLE9BQU8sRUFBRSxVQUFVLEVBQUUsVUFBVSxFQUFFLE1BQU0sNkNBQTZDLENBQUM7QUFFckYsT0FBTyxFQUFFLHNCQUFzQixFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFHNUQsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLDhCQUE4QixDQUFDO0FBQ3hELE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBQzVELE9BQU8sRUFBdUIsd0JBQXdCLEVBQUUsTUFBTSwrQkFBK0IsQ0FBQztBQUM5RixPQUFPLEVBQUUsWUFBWSxFQUFFLHVCQUF1QixFQUFFLE1BQU0sRUFBRSxHQUFHLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUNwRixPQUFPLEVBQUUsdUJBQXVCLEVBQUUsTUFBTSxrREFBa0QsQ0FBQztBQUMzRixPQUFPLEVBQUUsaUJBQWlCLEVBQUUsWUFBWSxFQUFFLFFBQVEsRUFBRSxlQUFlLEVBQUUsU0FBUyxFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFDL0csT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLHlDQUF5QyxDQUFDO0FBQ3RFLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUUvQyxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSx3Q0FBd0MsQ0FBQztB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K0NBQ2hCLGdCQUFnQixnQkFwQ3pCLENBQUMsRUFBRSxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsV0FBVyxFQUFFLHNCQUFzQixFQUFFLENBQUMsZ0ZBbUhwRSxpQkFBaUIscUZDbEo5Qix5c3VCQXFtQkEsMjlhRHJrQmMsQ0FBQyxvQkFBb0IsQ0FBQzs7NEZBR3ZCLFNBQVM7a0JBUnJCLFNBQVM7K0JBQ0UsaUJBQWlCLGFBR2hCLENBQUMsRUFBRSxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsV0FBVyxFQUFFLHNCQUFzQixFQUFFLENBQUMsY0FDbkUsQ0FBQyxvQkFBb0IsQ0FBQyxtQkFDakIsdUJBQXVCLENBQUMsTUFBTTs7MEJBNkM1QyxNQUFNOzJCQUFDLFdBQVc7eUNBZm1CLE9BQU87c0JBQTlDLEtBQUs7dUJBQUMsRUFBRSxTQUFTLEVBQUUsZ0JBQWdCLEVBQUU7Z0JBQ0UsZUFBZTtzQkFBdEQsS0FBSzt1QkFBQyxFQUFFLFNBQVMsRUFBRSxnQkFBZ0IsRUFBRTtnQkFDRSxNQUFNO3NCQUE3QyxLQUFLO3VCQUFDLEVBQUUsU0FBUyxFQUFFLGdCQUFnQixFQUFFO2dCQUNFLFNBQVM7c0JBQWhELEtBQUs7dUJBQUMsRUFBRSxTQUFTLEVBQUUsZ0JBQWdCLEVBQUU7Z0JBQ0UsV0FBVztzQkFBbEQsS0FBSzt1QkFBQyxFQUFFLFNBQVMsRUFBRSxnQkFBZ0IsRUFBRTtnQkErRVUsb0JBQW9CO3NCQUFuRSxTQUFTO3VCQUFDLGlCQUFpQixFQUFFLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IGJvb2xlYW5BdHRyaWJ1dGUsIENoYW5nZURldGVjdGlvblN0cmF0ZWd5LCBDb21wb25lbnQsIEluamVjdCwgSW5qZWN0b3IsIElucHV0LCBPbkluaXQsIFZpZXdDaGlsZCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgUGVyc29uLCBQUklPUklUSVpFRF9BVVRIT1JJVElFUyB9IGZyb20gJy4uLy4uL2NvcmUvc2VydmljZXMvbW9kZWwvcGVyc29uLm1vZGVsJztcbmltcG9ydCB7IFN0YXR1c0J5SWQsIFN0YXR1c0xpc3QgfSBmcm9tICcuLi8uLi9jb3JlL3NlcnZpY2VzL21vZGVsL3JlZmVyZW50aWFsLm1vZGVsJztcbmltcG9ydCB7IFBlcnNvblNlcnZpY2UgfSBmcm9tICcuL3BlcnNvbi5zZXJ2aWNlJztcbmltcG9ydCB7IFBlcnNvblZhbGlkYXRvclNlcnZpY2UgfSBmcm9tICcuL3BlcnNvbi52YWxpZGF0b3InO1xuaW1wb3J0IHsgQWNjb3VudFNlcnZpY2UgfSBmcm9tICcuLi8uLi9jb3JlL3NlcnZpY2VzL2FjY291bnQuc2VydmljZSc7XG5pbXBvcnQgeyBBYnN0cmFjdENvbnRyb2wsIFVudHlwZWRGb3JtQnVpbGRlciwgVW50eXBlZEZvcm1Hcm91cCB9IGZyb20gJ0Bhbmd1bGFyL2Zvcm1zJztcbmltcG9ydCB7IEFwcFRhYmxlIH0gZnJvbSAnLi4vLi4vY29yZS90YWJsZS90YWJsZS5jbGFzcyc7XG5pbXBvcnQgeyBWYWxpZGF0b3JTZXJ2aWNlIH0gZnJvbSAnQGUtaXMvbmd4LW1hdGVyaWFsLXRhYmxlJztcbmltcG9ydCB7IEZvcm1GaWVsZERlZmluaXRpb24sIEZvcm1GaWVsZERlZmluaXRpb25VdGlscyB9IGZyb20gJy4uLy4uL3NoYXJlZC9mb3JtL2ZpZWxkLm1vZGVsJztcbmltcG9ydCB7IGRlYm91bmNlVGltZSwgZGlzdGluY3RVbnRpbEtleUNoYW5nZWQsIGZpbHRlciwgdGFwIH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuaW1wb3J0IHsgRW50aXRpZXNUYWJsZURhdGFTb3VyY2UgfSBmcm9tICcuLi8uLi9jb3JlL3RhYmxlL2VudGl0aWVzLXRhYmxlLWRhdGFzb3VyY2UuY2xhc3MnO1xuaW1wb3J0IHsgZ2V0UHJvcGVydHlCeVBhdGgsIGlzTmlsT3JCbGFuaywgaXNOb3ROaWwsIGlzTm90TmlsT3JCbGFuaywgdG9Cb29sZWFuIH0gZnJvbSAnLi4vLi4vc2hhcmVkL2Z1bmN0aW9ucyc7XG5pbXBvcnQgeyBFTlZJUk9OTUVOVCB9IGZyb20gJy4uLy4uLy4uL2Vudmlyb25tZW50cy9lbnZpcm9ubWVudC5jbGFzcyc7XG5pbXBvcnQgeyBQZXJzb25GaWx0ZXIgfSBmcm9tICcuL3BlcnNvbi5maWx0ZXInO1xuaW1wb3J0IHsgQ29uZmlnU2VydmljZSB9IGZyb20gJy4uLy4uL2NvcmUvc2VydmljZXMvY29uZmlnLnNlcnZpY2UnO1xuaW1wb3J0IHsgQ09SRV9DT05GSUdfT1BUSU9OUyB9IGZyb20gJy4uLy4uL2NvcmUvc2VydmljZXMvY29uZmlnL2NvcmUuY29uZmlnJztcbmltcG9ydCB7IEF1dGhUb2tlblR5cGUgfSBmcm9tICcuLi8uLi9jb3JlL3NlcnZpY2VzL25ldHdvcmsudHlwZXMnO1xuaW1wb3J0IHsgTWF0RXhwYW5zaW9uUGFuZWwgfSBmcm9tICdAYW5ndWxhci9tYXRlcmlhbC9leHBhbnNpb24nO1xuaW1wb3J0IHsgc2xpZGVVcERvd25BbmltYXRpb24gfSBmcm9tICcuLi8uLi9zaGFyZWQvbWF0ZXJpYWwvbWF0ZXJpYWwuYW5pbWF0aW9ucyc7XG5pbXBvcnQgeyBNZXNzYWdlIH0gZnJvbSAnLi4vLi4vc29jaWFsL21lc3NhZ2UvbWVzc2FnZS5tb2RlbCc7XG5pbXBvcnQgeyBNZXNzYWdlU2VydmljZSB9IGZyb20gJy4uLy4uL3NvY2lhbC9tZXNzYWdlL21lc3NhZ2Uuc2VydmljZSc7XG5pbXBvcnQgeyBSRVNFUlZFRF9FTkRfQ09MVU1OUywgUkVTRVJWRURfU1RBUlRfQ09MVU1OUywgVEFCTEVfU0VUVElOR1NfRU5VTSB9IGZyb20gJy4uLy4uL2NvcmUvdGFibGUvdGFibGUubW9kZWwnO1xuaW1wb3J0IHsgTWVudVNlcnZpY2UgfSBmcm9tICcuLi8uLi9jb3JlL21lbnUvbWVudS5zZXJ2aWNlJztcbmltcG9ydCB7IENzdlV0aWxzIH0gZnJvbSAnLi4vLi4vc2hhcmVkL2ZpbGUvY3N2LnV0aWxzJztcbmltcG9ydCB7IGZyb21EYXRlSVNPU3RyaW5nIH0gZnJvbSAnLi4vLi4vc2hhcmVkL2RhdGVzJztcblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnYXBwLXVzZXJzLXRhYmxlJyxcbiAgdGVtcGxhdGVVcmw6ICd1c2Vycy5odG1sJyxcbiAgc3R5bGVVcmxzOiBbJy4vdXNlcnMuc2NzcyddLFxuICBwcm92aWRlcnM6IFt7IHByb3ZpZGU6IFZhbGlkYXRvclNlcnZpY2UsIHVzZUV4aXN0aW5nOiBQZXJzb25WYWxpZGF0b3JTZXJ2aWNlIH1dLFxuICBhbmltYXRpb25zOiBbc2xpZGVVcERvd25BbmltYXRpb25dLFxuICBjaGFuZ2VEZXRlY3Rpb246IENoYW5nZURldGVjdGlvblN0cmF0ZWd5Lk9uUHVzaCxcbn0pXG5leHBvcnQgY2xhc3MgVXNlcnNQYWdlIGV4dGVuZHMgQXBwVGFibGU8UGVyc29uLCBQZXJzb25GaWx0ZXI+IGltcGxlbWVudHMgT25Jbml0IHtcbiAgcmVhZG9ubHkgY2FuRWRpdDogYm9vbGVhbjtcbiAgcmVhZG9ubHkgY2FuU2VuZE1lc3NhZ2U6IGJvb2xlYW47XG4gIHJlYWRvbmx5IGZpbHRlckZvcm06IFVudHlwZWRGb3JtR3JvdXA7XG4gIHJlYWRvbmx5IHByb2ZpbGVzID0gWy4uLlBSSU9SSVRJWkVEX0FVVEhPUklUSUVTXS5yZXZlcnNlKCk7XG4gIHJlYWRvbmx5IHN0YXR1c0xpc3QgPSBTdGF0dXNMaXN0O1xuICByZWFkb25seSBzdGF0dXNCeUlkID0gU3RhdHVzQnlJZDtcblxuICBwcm90ZWN0ZWQgYWRkaXRpb25hbEZpZWxkczogRm9ybUZpZWxkRGVmaW5pdGlvbltdO1xuICBwcm90ZWN0ZWQgZmlsdGVyQ3JpdGVyaWFDb3VudCA9IDA7XG4gIHByb3RlY3RlZCBkZWZhdWx0Q29tcGFjdCA9IGZhbHNlO1xuXG4gIHNldCBzaG93VXNlcm5hbWVDb2x1bW4odmFsdWU6IGJvb2xlYW4pIHtcbiAgICB0aGlzLnNldFNob3dDb2x1bW4oJ3VzZXJuYW1lJywgdmFsdWUpO1xuICB9XG5cbiAgZ2V0IHNob3dVc2VybmFtZUNvbHVtbigpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5nZXRTaG93Q29sdW1uKCd1c2VybmFtZScpO1xuICB9XG5cbiAgc2V0IHNob3dVc2VybmFtZUV4dHJhbmV0Q29sdW1uKHZhbHVlOiBib29sZWFuKSB7XG4gICAgdGhpcy5zZXRTaG93Q29sdW1uKCd1c2VybmFtZUV4dHJhbmV0JywgdmFsdWUpO1xuICB9XG5cbiAgZ2V0IHNob3dVc2VybmFtZUV4dHJhbmV0Q29sdW1uKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLmdldFNob3dDb2x1bW4oJ3VzZXJuYW1lRXh0cmFuZXQnKTtcbiAgfVxuXG4gIEBJbnB1dCh7IHRyYW5zZm9ybTogYm9vbGVhbkF0dHJpYnV0ZSB9KSBjb21wYWN0OiBib29sZWFuID0gbnVsbDtcbiAgQElucHV0KHsgdHJhbnNmb3JtOiBib29sZWFuQXR0cmlidXRlIH0pIHVzZVBhZ2VTZXR0aW5ncyA9IHRydWU7XG4gIEBJbnB1dCh7IHRyYW5zZm9ybTogYm9vbGVhbkF0dHJpYnV0ZSB9KSBzdGlja3kgPSBmYWxzZTtcbiAgQElucHV0KHsgdHJhbnNmb3JtOiBib29sZWFuQXR0cmlidXRlIH0pIHN0aWNreUVuZCA9IGZhbHNlO1xuICBASW5wdXQoeyB0cmFuc2Zvcm06IGJvb2xlYW5BdHRyaWJ1dGUgfSkgY2FuRG93bmxvYWQgPSB0cnVlO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIGluamVjdG9yOiBJbmplY3RvcixcbiAgICBmb3JtQnVpbGRlcjogVW50eXBlZEZvcm1CdWlsZGVyLFxuICAgIHByb3RlY3RlZCBhY2NvdW50U2VydmljZTogQWNjb3VudFNlcnZpY2UsXG4gICAgcHJvdGVjdGVkIHZhbGlkYXRvclNlcnZpY2U6IFZhbGlkYXRvclNlcnZpY2UsXG4gICAgcHJvdGVjdGVkIGNvbmZpZ1NlcnZpY2U6IENvbmZpZ1NlcnZpY2UsXG4gICAgcHJvdGVjdGVkIGRhdGFTZXJ2aWNlOiBQZXJzb25TZXJ2aWNlLFxuICAgIHByb3RlY3RlZCBtZXNzYWdlU2VydmljZTogTWVzc2FnZVNlcnZpY2UsXG4gICAgcHJvdGVjdGVkIG1lbnVTZXJ2aWNlOiBNZW51U2VydmljZSxcbiAgICBASW5qZWN0KEVOVklST05NRU5UKSBlbnZpcm9ubWVudFxuICApIHtcbiAgICBzdXBlcihcbiAgICAgIGluamVjdG9yLFxuICAgICAgUkVTRVJWRURfU1RBUlRfQ09MVU1OUy5jb25jYXQoWydhdmF0YXInLCAnbGFzdE5hbWUnLCAnZmlyc3ROYW1lJywgJ2VtYWlsJywgJ3Byb2ZpbGUnLCAnc3RhdHVzJywgJ3VzZXJuYW1lJywgJ3VzZXJuYW1lRXh0cmFuZXQnLCAncHVia2V5J10pXG4gICAgICAgIC5jb25jYXQoYWNjb3VudFNlcnZpY2UuYWRkaXRpb25hbEZpZWxkcy5tYXAoKGZpZWxkKSA9PiBmaWVsZC5rZXkpKVxuICAgICAgICAuY29uY2F0KFsnY3JlYXRpb25EYXRlJywgJ3VwZGF0ZURhdGUnXSlcbiAgICAgICAgLmNvbmNhdChSRVNFUlZFRF9FTkRfQ09MVU1OUyksXG4gICAgICBuZXcgRW50aXRpZXNUYWJsZURhdGFTb3VyY2UoUGVyc29uLCBkYXRhU2VydmljZSwgdmFsaWRhdG9yU2VydmljZSwge1xuICAgICAgICBwcmVwZW5kTmV3RWxlbWVudHM6IGZhbHNlLFxuICAgICAgICBzdXBwcmVzc0Vycm9yczogZW52aXJvbm1lbnQucHJvZHVjdGlvbixcbiAgICAgICAgc2F2ZU9ubHlEaXJ0eVJvd3M6IHRydWUsXG4gICAgICB9KSxcbiAgICAgIG51bGxcbiAgICApO1xuXG4gICAgdGhpcy5jYW5FZGl0ID0gYWNjb3VudFNlcnZpY2UuaXNBZG1pbigpO1xuICAgIHRoaXMuY2FuU2VuZE1lc3NhZ2UgPSB0aGlzLmNhbkVkaXQ7XG4gICAgdGhpcy5pbmxpbmVFZGl0aW9uID0gdGhpcy5jYW5FZGl0O1xuICAgIHRoaXMuY29uZmlybUJlZm9yZURlbGV0ZSA9IHRydWU7XG4gICAgdGhpcy5hdXRvTG9hZCA9IGZhbHNlOyAvLyBXYWl0IGNvbmZpZyBsb2FkaW5nXG4gICAgdGhpcy5pMThuQ29sdW1uUHJlZml4ID0gJ1VTRVIuJztcbiAgICB0aGlzLmRlZmF1bHRTb3J0QnkgPSAnbGFzdE5hbWUnO1xuICAgIHRoaXMuZGVmYXVsdFNvcnREaXJlY3Rpb24gPSAnYXNjJztcblxuICAgIHRoaXMuZmlsdGVyRm9ybSA9IGZvcm1CdWlsZGVyLmdyb3VwKHtcbiAgICAgIHNlYXJjaFRleHQ6IFtudWxsXSxcbiAgICAgIHN0YXR1c0lkOiBbbnVsbF0sXG4gICAgfSk7XG5cbiAgICB0aGlzLmFkZGl0aW9uYWxGaWVsZHMgPSAodGhpcy5hY2NvdW50U2VydmljZS5hZGRpdGlvbmFsRmllbGRzIHx8IFtdKVxuICAgICAgLmZpbHRlcigoZmllbGQpID0+IGlzTm90TmlsKGZpZWxkLmF1dG9jb21wbGV0ZSkpXG4gICAgICAubWFwKChmaWVsZCkgPT4ge1xuICAgICAgICAvLyBNYWtlIHN1cmUgdG8gZ2V0IHRoZSBmaW5hbCBhdXRvY29tcGxldGUgY29uZmlnIChlLmcuIHdpdGggYSBzdWdnZXN0Rm4gZnVuY3Rpb24pXG4gICAgICAgIGZpZWxkLmF1dG9jb21wbGV0ZSA9IHRoaXMucmVnaXN0ZXJBdXRvY29tcGxldGVGaWVsZChmaWVsZC5rZXksIHtcbiAgICAgICAgICAuLi5maWVsZC5hdXRvY29tcGxldGUsIC8vIENvcHksIHRvIGJlIHN1cmUgdGhlIG9yaWdpbmFsIGNvbmZpZyBpcyB1bmNoYW5nZWRcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiBmaWVsZDtcbiAgICAgIH0pO1xuXG4gICAgLy8gTGlzdGVuIHBhZ2UgYWN0aW9uIChlLmcuIGZyb20gc3ViIG1lbnUgaXRlbSlcbiAgICB0aGlzLnJlZ2lzdGVyU3Vic2NyaXB0aW9uKFxuICAgICAgdGhpcy5yb3V0ZS5xdWVyeVBhcmFtcy5waXBlKGRpc3RpbmN0VW50aWxLZXlDaGFuZ2VkKCdhY3Rpb24nKSkuc3Vic2NyaWJlKChxdWVyeVBhcmFtcykgPT4ge1xuICAgICAgICBjb25zdCBhY3Rpb24gPSBxdWVyeVBhcmFtc1snYWN0aW9uJ10gfHwgJ25vbmUnO1xuICAgICAgICBzd2l0Y2ggKGFjdGlvbikge1xuICAgICAgICAgIGNhc2UgJ3NlbmQnOlxuICAgICAgICAgICAgdGhpcy5vcGVuQ29tcG9zZU1lc3NhZ2VNb2RhbCgpO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgY2FzZSAnbm9uZSc6XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgY29uc29sZS53YXJuKCdbdXNlcnNdIFVua25vd24gYWN0aW9uPScgKyBhY3Rpb24pO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgICAgLy8gTWFyayBhcyBjb25zdW1lZFxuICAgICAgICB0aGlzLnJvdXRlci5uYXZpZ2F0ZShbJy4nXSwge1xuICAgICAgICAgIHJlbGF0aXZlVG86IHRoaXMucm91dGUsXG4gICAgICAgICAgcXVlcnlQYXJhbXM6IHsgLi4ucXVlcnlQYXJhbXMsIGFjdGlvbjogdW5kZWZpbmVkIH0sXG4gICAgICAgICAgcmVwbGFjZVVybDogdHJ1ZSxcbiAgICAgICAgICBzdGF0ZTogeyBhbmltYXRlZDogZmFsc2UgfSxcbiAgICAgICAgfSk7XG4gICAgICB9KVxuICAgICk7XG5cbiAgICAvLyBGb3IgREVWIG9ubHkgLS1cbiAgICB0aGlzLmRlYnVnID0gIWVudmlyb25tZW50LnByb2R1Y3Rpb247XG4gIH1cblxuICBAVmlld0NoaWxkKE1hdEV4cGFuc2lvblBhbmVsLCB7IHN0YXRpYzogdHJ1ZSB9KSBmaWx0ZXJFeHBhbnNpb25QYW5lbDogTWF0RXhwYW5zaW9uUGFuZWw7XG5cbiAgZ2V0IGZpcnN0VXNlckNvbHVtbigpOiBzdHJpbmcge1xuICAgIGNvbnN0IGNvbHVtbk5hbWUgPSB0aGlzLmRpc3BsYXllZENvbHVtbnNbUkVTRVJWRURfU1RBUlRfQ09MVU1OUy5sZW5ndGhdO1xuICAgIC8vIFNraXAgYXZhdGFyIGNvbHVtbiwgaWYgcHJlc2VudFxuICAgIHJldHVybiAoY29sdW1uTmFtZSA9PT0gJ2F2YXRhcicgJiYgdGhpcy5kaXNwbGF5ZWRDb2x1bW5zW1JFU0VSVkVEX1NUQVJUX0NPTFVNTlMubGVuZ3RoICsgMV0pIHx8IGNvbHVtbk5hbWU7XG4gIH1cblxuICBhc3luYyBuZ09uSW5pdCgpIHtcbiAgICBzdXBlci5uZ09uSW5pdCgpO1xuXG4gICAgdGhpcy5yZWdpc3RlclN1YnNjcmlwdGlvbihcbiAgICAgIHRoaXMuY29uZmlnU2VydmljZS5jb25maWcuc3Vic2NyaWJlKChjb25maWcpID0+IHtcbiAgICAgICAgY29uc3QgYXV0aFRva2VuVHlwZSA9IGNvbmZpZy5nZXRQcm9wZXJ0eShDT1JFX0NPTkZJR19PUFRJT05TLkFVVEhfVE9LRU5fVFlQRSkgYXMgQXV0aFRva2VuVHlwZTtcbiAgICAgICAgY29uc29sZS5kZWJ1ZygnW3VzZXJzXSBBdXRoVG9rZW5UeXBlPScgKyBhdXRoVG9rZW5UeXBlKTtcbiAgICAgICAgc3dpdGNoIChhdXRoVG9rZW5UeXBlKSB7XG4gICAgICAgICAgY2FzZSAnYmFzaWMnOlxuICAgICAgICAgICAgdGhpcy5zZXRTaG93Q29sdW1uKCdwdWJrZXknLCBmYWxzZSwgeyBlbWl0RXZlbnQ6IGZhbHNlIH0pO1xuICAgICAgICAgICAgdGhpcy5zZXRTaG93Q29sdW1uKCd1c2VybmFtZScsIHRydWUsIHsgZW1pdEV2ZW50OiBmYWxzZSB9KTtcbiAgICAgICAgICAgIHRoaXMuc2V0U2hvd0NvbHVtbigndXNlcm5hbWVFeHRyYW5ldCcsIHRydWUsIHsgZW1pdEV2ZW50OiBmYWxzZSB9KTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIGNhc2UgJ2Jhc2ljLWFuZC10b2tlbic6XG4gICAgICAgICAgICB0aGlzLnNldFNob3dDb2x1bW4oJ3B1YmtleScsIHRydWUsIHsgZW1pdEV2ZW50OiBmYWxzZSB9KTtcbiAgICAgICAgICAgIHRoaXMuc2V0U2hvd0NvbHVtbigndXNlcm5hbWUnLCB0cnVlLCB7IGVtaXRFdmVudDogZmFsc2UgfSk7XG4gICAgICAgICAgICB0aGlzLnNldFNob3dDb2x1bW4oJ3VzZXJuYW1lRXh0cmFuZXQnLCB0cnVlLCB7IGVtaXRFdmVudDogZmFsc2UgfSk7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICBjYXNlICd0b2tlbic6XG4gICAgICAgICAgICB0aGlzLnNldFNob3dDb2x1bW4oJ3B1YmtleScsIHRydWUsIHsgZW1pdEV2ZW50OiBmYWxzZSB9KTtcbiAgICAgICAgICAgIHRoaXMuc2V0U2hvd0NvbHVtbigndXNlcm5hbWUnLCBmYWxzZSwgeyBlbWl0RXZlbnQ6IGZhbHNlIH0pO1xuICAgICAgICAgICAgdGhpcy5zZXRTaG93Q29sdW1uKCd1c2VybmFtZUV4dHJhbmV0JywgZmFsc2UsIHsgZW1pdEV2ZW50OiBmYWxzZSB9KTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnVwZGF0ZUNvbHVtbnMoKTtcbiAgICAgICAgdGhpcy5lbWl0UmVmcmVzaCgpO1xuICAgICAgfSlcbiAgICApO1xuXG4gICAgdGhpcy5yZWdpc3RlclN1YnNjcmlwdGlvbihcbiAgICAgIHRoaXMub25SZWZyZXNoLnN1YnNjcmliZSgoKSA9PiB7XG4gICAgICAgIHRoaXMuZmlsdGVyRm9ybS5tYXJrQXNVbnRvdWNoZWQoKTtcbiAgICAgICAgdGhpcy5maWx0ZXJGb3JtLm1hcmtBc1ByaXN0aW5lKCk7XG4gICAgICB9KVxuICAgICk7XG5cbiAgICAvLyBVcGRhdGUgZmlsdGVyIHdoZW4gY2hhbmdlc1xuICAgIHRoaXMucmVnaXN0ZXJTdWJzY3JpcHRpb24oXG4gICAgICB0aGlzLmZpbHRlckZvcm0udmFsdWVDaGFuZ2VzXG4gICAgICAgIC5waXBlKFxuICAgICAgICAgIGRlYm91bmNlVGltZSgyNTApLFxuICAgICAgICAgIGZpbHRlcigoKSA9PiB0aGlzLmZpbHRlckZvcm0udmFsaWQpLFxuICAgICAgICAgIHRhcCgoanNvbikgPT4ge1xuICAgICAgICAgICAgY29uc3QgZmlsdGVyID0gUGVyc29uRmlsdGVyLmZyb21PYmplY3QoanNvbik7XG4gICAgICAgICAgICB0aGlzLmZpbHRlckNyaXRlcmlhQ291bnQgPSBmaWx0ZXIuY291bnROb3RFbXB0eUNyaXRlcmlhKCk7XG4gICAgICAgICAgICB0aGlzLm1hcmtGb3JDaGVjaygpO1xuICAgICAgICAgICAgLy8gVXBkYXRlIHRoZSBmaWx0ZXIsIHdpdGhvdXQgcmVsb2FkaW5nIHRoZSBjb250ZW50XG4gICAgICAgICAgICB0aGlzLnNldEZpbHRlcihmaWx0ZXIsIHsgZW1pdEV2ZW50OiBmYWxzZSB9KTtcbiAgICAgICAgICB9KSxcbiAgICAgICAgICAvLyBTYXZlIGZpbHRlciBpbiBzZXR0aW5ncyAoYWZ0ZXIgYSBkZWJvdW5jZSB0aW1lKVxuICAgICAgICAgIGRlYm91bmNlVGltZSg1MDApLFxuICAgICAgICAgIGZpbHRlcigoKSA9PiBpc05vdE5pbE9yQmxhbmsodGhpcy5zZXR0aW5nc0lkKSAmJiB0aGlzLnVzZVBhZ2VTZXR0aW5ncyksXG4gICAgICAgICAgdGFwKChqc29uKSA9PiB0aGlzLnNldHRpbmdzLnNhdmVQYWdlU2V0dGluZyh0aGlzLnNldHRpbmdzSWQsIGpzb24sIFRBQkxFX1NFVFRJTkdTX0VOVU0uRklMVEVSX0tFWSkpXG4gICAgICAgIClcbiAgICAgICAgLnN1YnNjcmliZSgpXG4gICAgKTtcblxuICAgIGlmICh0aGlzLmNhblNlbmRNZXNzYWdlICYmIHRoaXMuZGVidWcpIHtcbiAgICAgIGF3YWl0IHRoaXMubWVudVNlcnZpY2UuYWRkU3ViTWVudUl0ZW1zKFxuICAgICAgICBbXG4gICAgICAgICAge1xuICAgICAgICAgICAgcGFyZW50UGF0aDogJy9hZG1pbi91c2VycycsXG4gICAgICAgICAgICBwYXRoOiAnL2FkbWluL3VzZXJzJyxcbiAgICAgICAgICAgIHBhdGhQYXJhbXM6IHsgYWN0aW9uOiAnZXhwYW5kJyB9LFxuICAgICAgICAgICAgbWF0SWNvbjogJ2V4cGFuZF9tb3JlJyxcbiAgICAgICAgICAgIHRpdGxlOiAnVVNFUi5MSVNULkJUTl9BQ1RJT05TJyxcbiAgICAgICAgICAgIGFjdGlvbjogJ2V4cGFuZCcsXG4gICAgICAgICAgfSxcbiAgICAgICAgICB7XG4gICAgICAgICAgICBwYXJlbnRQYXRoOiAnL2FkbWluL3VzZXJzP2FjdGlvbj1leHBhbmQnLFxuICAgICAgICAgICAgcGF0aDogJy9hZG1pbi91c2Vycz9hY3Rpb249c2VuZCcsXG4gICAgICAgICAgICBpY29uOiAnbWFpbCcsXG4gICAgICAgICAgICB0aXRsZTogJ1VTRVIuTElTVC5CVE5fU0VORF9NRVNTQUdFJyxcbiAgICAgICAgICAgIGFjdGlvbjogKCkgPT4gdGhpcy5vcGVuQ29tcG9zZU1lc3NhZ2VNb2RhbCgpLFxuICAgICAgICAgIH0sXG4gICAgICAgIF0sXG4gICAgICAgIHsgc2tpcElmRXhpc3RzOiBmYWxzZSB9XG4gICAgICApO1xuICAgIH1cblxuICAgIC8vIFJlc3RvcmUgY29tcGFjdCByb3dzXG4gICAgdGhpcy5yZXN0b3JlQ29tcGFjdE1vZGUoKTtcblxuICAgIC8vIFJlc3RvcmUgZmlsdGVyIGZyb20gc2V0dGluZ3MsIG9yIGxvYWQgYWxsXG4gICAgdGhpcy5yZXN0b3JlRmlsdGVyT3JMb2FkKCk7XG4gIH1cblxuICBhcHBseUZpbHRlckFuZENsb3NlUGFuZWwoZXZlbnQ/OiBFdmVudCkge1xuICAgIHRoaXMuZW1pdFJlZnJlc2goZXZlbnQpO1xuICAgIHRoaXMuZmlsdGVyRXhwYW5zaW9uUGFuZWwuY2xvc2UoKTtcbiAgfVxuXG4gIHJlc2V0RmlsdGVyKGV2ZW50PzogRXZlbnQpIHtcbiAgICB0aGlzLnRvdGFsUm93Q291bnQgPSB1bmRlZmluZWQ7XG4gICAgdGhpcy5maWx0ZXJDcml0ZXJpYUNvdW50ID0gMDtcbiAgICB0aGlzLm1hcmtBc0xvYWRpbmcoKTtcbiAgICB0aGlzLmZpbHRlckZvcm0ucmVzZXQoKTtcbiAgICB0aGlzLnNldEZpbHRlcihudWxsKTtcbiAgfVxuXG4gIHByb3RlY3RlZCBhc3luYyByZXN0b3JlRmlsdGVyT3JMb2FkKCkge1xuICAgIHRoaXMubWFya0FzTG9hZGluZygpO1xuXG4gICAgY29uc29sZS5kZWJ1ZygnW3VzZXJzXSBSZXN0b3JpbmcgZmlsdGVyIGZyb20gc2V0dGluZ3MuLi4nKTtcblxuICAgIGNvbnN0IGpzb24gPSB0aGlzLnNldHRpbmdzLmdldFBhZ2VTZXR0aW5ncyh0aGlzLnNldHRpbmdzSWQsIFRBQkxFX1NFVFRJTkdTX0VOVU0uRklMVEVSX0tFWSkgfHwge307XG4gICAgY29uc3QgZmlsdGVyID0gUGVyc29uRmlsdGVyLmZyb21PYmplY3QoanNvbik7XG5cbiAgICB0aGlzLmZpbHRlckZvcm0ucGF0Y2hWYWx1ZShqc29uKTtcbiAgICB0aGlzLnNldEZpbHRlcihmaWx0ZXIsIHsgZW1pdEV2ZW50OiB0cnVlIH0pO1xuICB9XG5cbiAgY2xlYXJDb250cm9sVmFsdWUoZXZlbnQ6IEV2ZW50LCBmb3JtQ29udHJvbDogQWJzdHJhY3RDb250cm9sKTogYm9vbGVhbiB7XG4gICAgaWYgKGV2ZW50KSBldmVudC5zdG9wUHJvcGFnYXRpb24oKTsgLy8gQXZvaWQgdG8gZW50ZXIgaW5wdXQgdGhlIGZpZWxkXG4gICAgZm9ybUNvbnRyb2wuc2V0VmFsdWUobnVsbCk7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgYXN5bmMgb3BlbkNvbXBvc2VNZXNzYWdlTW9kYWwoZXZlbnQ/OiBFdmVudCk6IFByb21pc2U8YW55PiB7XG4gICAgLy8gQ29tcHV0ZSByZWNpcGllbnRzXG4gICAgY29uc3QgcmVjaXBpZW50cyA9ICh0aGlzLnNlbGVjdGlvbi5zZWxlY3RlZCB8fCBbXSlcbiAgICAgIC5tYXAoKHJvdykgPT4gcm93LmN1cnJlbnREYXRhKVxuICAgICAgLm1hcChQZXJzb24uZnJvbU9iamVjdClcbiAgICAgIC5tYXAoKHApID0+IHtcbiAgICAgICAgY29uc3QgdGFyZ2V0ID0gcC5hc09iamVjdCh7IG1pbmlmeTogdHJ1ZSB9KTtcbiAgICAgICAgdGFyZ2V0LmRlcGFydG1lbnQgPSBwLmRlcGFydG1lbnQ/LmFzT2JqZWN0KCk7XG4gICAgICAgIHJldHVybiB0YXJnZXQ7XG4gICAgICB9KTtcblxuICAgIGNvbnN0IHJlY2lwaWVudEZpbHRlciA9IFBlcnNvbkZpbHRlci5mcm9tT2JqZWN0KHRoaXMuZmlsdGVyKTtcbiAgICBjb25zdCBjYW5SZWNpcGllbnRGaWx0ZXIgPSAhcmVjaXBpZW50RmlsdGVyLmlzRW1wdHkoKSAmJiAodGhpcy5hY2NvdW50U2VydmljZS5pc0FkbWluKCkgfHwgdGhpcy5hY2NvdW50U2VydmljZS5pc1N1cGVydmlzb3IoKSk7XG4gICAgcmV0dXJuIHRoaXMubWVzc2FnZVNlcnZpY2Uub3BlbkNvbXBvc2VNb2RhbCh7XG4gICAgICBzdWdnZXN0Rm46ICh2YWx1ZSwgZmlsdGVyLCBzb3J0QnksIHNvcnREaXJlY3Rpb24pID0+IHRoaXMuZGF0YVNlcnZpY2Uuc3VnZ2VzdCh2YWx1ZSwgZmlsdGVyLCBzb3J0QnksIHNvcnREaXJlY3Rpb24pLFxuICAgICAgY2FuUmVjaXBpZW50RmlsdGVyLFxuICAgICAgcmVjaXBpZW50RmlsdGVyQ291bnQ6IHRoaXMudG90YWxSb3dDb3VudCxcbiAgICAgIGRhdGE6IE1lc3NhZ2UuZnJvbU9iamVjdCh7XG4gICAgICAgIHJlY2lwaWVudHMsXG4gICAgICAgIHJlY2lwaWVudEZpbHRlcixcbiAgICAgIH0pLFxuICAgIH0pO1xuICB9XG5cbiAgYXN5bmMgcmVzdG9yZUNvbXBhY3RNb2RlKG9wdHM/OiB7IGVtaXRFdmVudD86IGJvb2xlYW4gfSkge1xuICAgIGlmICghdGhpcy51c2VQYWdlU2V0dGluZ3MgfHwgaXNOaWxPckJsYW5rKHRoaXMuc2V0dGluZ3NJZCkgfHwgaXNOb3ROaWwodGhpcy5jb21wYWN0KSkgcmV0dXJuO1xuXG4gICAgY29uc3QgY29tcGFjdCA9IHRvQm9vbGVhbihcbiAgICAgIHRoaXMuc2V0dGluZ3MuZ2V0UGFnZVNldHRpbmdzKHRoaXMuc2V0dGluZ3NJZCwgVEFCTEVfU0VUVElOR1NfRU5VTS5DT01QQUNUX1JPV1NfS0VZKSxcbiAgICAgIHRvQm9vbGVhbih0aGlzLmNvbXBhY3QsIHRoaXMuZGVmYXVsdENvbXBhY3QpXG4gICAgKTtcbiAgICBpZiAodGhpcy5jb21wYWN0ICE9PSBjb21wYWN0KSB7XG4gICAgICB0aGlzLmNvbXBhY3QgPSBjb21wYWN0O1xuXG4gICAgICAvLyBFbWl0IGV2ZW50XG4gICAgICBpZiAoIW9wdHMgfHwgb3B0cy5lbWl0RXZlbnQgIT09IGZhbHNlKSB7XG4gICAgICAgIHRoaXMubWFya0ZvckNoZWNrKCk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgYXN5bmMgdG9nZ2xlQ29tcGFjdE1vZGUoKSB7XG4gICAgdGhpcy5jb21wYWN0ID0gIXRoaXMuY29tcGFjdDtcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHJ4LWFuZ3VsYXIvbm8tZXhwbGljaXQtY2hhbmdlLWRldGVjdGlvbi1hcGlzXG4gICAgdGhpcy5tYXJrRm9yQ2hlY2soKTtcbiAgICBpZiAodGhpcy51c2VQYWdlU2V0dGluZ3MgJiYgaXNOb3ROaWxPckJsYW5rKHRoaXMuc2V0dGluZ3NJZCkpIHtcbiAgICAgIGF3YWl0IHRoaXMuc2F2ZVBhZ2VTZXR0aW5ncyh0aGlzLmNvbXBhY3QsIFRBQkxFX1NFVFRJTkdTX0VOVU0uQ09NUEFDVF9ST1dTX0tFWSk7XG4gICAgfVxuICB9XG5cbiAgYXN5bmMgZXhwb3J0VG9Dc3YoZXZlbnQ6IEV2ZW50KSB7XG4gICAgLy8gUHJlcGFyZSBDU1Ygb3B0aW9uc1xuICAgIGNvbnN0IHNlcGFyYXRvciA9IENzdlV0aWxzLmdldExvY2FsaXplZFNlcGFyYXRvcih0aGlzLnRyYW5zbGF0ZSk7XG4gICAgY29uc3QgZW5jb2RpbmcgPSBDc3ZVdGlscy5nZXRMb2NhbGl6ZWRFbmNvZGluZyh0aGlzLnRyYW5zbGF0ZSk7XG4gICAgY29uc3QgdHJhbnNsYXRpb25zID0gdGhpcy50cmFuc2xhdGUuaW5zdGFudChbXG4gICAgICAnQ09NTU9OLkRBVEVfVElNRV9QQVRURVJOJyxcbiAgICAgICdVU0VSLkxJU1QuVElUTEUnLFxuICAgICAgJ1VTRVIuRU1BSUwnLFxuICAgICAgJ1VTRVIuRklSU1RfTkFNRScsXG4gICAgICAnVVNFUi5MQVNUX05BTUUnLFxuICAgICAgJ1VTRVIuVVNFUk5BTUUnLFxuICAgICAgJ1VTRVIuVVNFUk5BTUVfRVhUUkFORVQnLFxuICAgICAgJ1VTRVIuREVQQVJUTUVOVF9MQUJFTCcsXG4gICAgICAnVVNFUi5ERVBBUlRNRU5UX05BTUUnLFxuICAgICAgJ1VTRVIuUFJPRklMRScsXG4gICAgICAnVVNFUi5TVEFUVVMnLFxuICAgICAgJ1VTRVIuUFVCS0VZJyxcbiAgICAgIC4uLih0aGlzLmFkZGl0aW9uYWxGaWVsZHMgfHwgW10pLm1hcCgoZmllbGQpID0+IGZpZWxkLmxhYmVsKSxcbiAgICAgICdVU0VSLkNSRUFUSU9OX0RBVEUnLFxuICAgICAgJ1VTRVIuVVBEQVRFX0RBVEUnLFxuICAgICAgLi4udGhpcy5zdGF0dXNMaXN0Lm1hcCgoc3RhdHVzKSA9PiBzdGF0dXMubGFiZWwpLFxuICAgIF0pO1xuICAgIGNvbnN0IGRhdGVUaW1lUGF0dGVybiA9IHRyYW5zbGF0aW9uc1snQ09NTU9OLkRBVEVfVElNRV9QQVRURVJOJ107XG4gICAgY29uc3QgZmlsZW5hbWUgPSB0cmFuc2xhdGlvbnNbJ1VTRVIuTElTVC5USVRMRSddICsgJy5jc3YnO1xuICAgIGNvbnN0IGhlYWRlcnMgPSBbXG4gICAgICB0cmFuc2xhdGlvbnNbJ1VTRVIuRU1BSUwnXSxcbiAgICAgIHRyYW5zbGF0aW9uc1snVVNFUi5GSVJTVF9OQU1FJ10sXG4gICAgICB0cmFuc2xhdGlvbnNbJ1VTRVIuTEFTVF9OQU1FJ10sXG4gICAgICAuLi4odGhpcy5zaG93VXNlcm5hbWVDb2x1bW4gPyBbdHJhbnNsYXRpb25zWydVU0VSLlVTRVJOQU1FJ11dIDogW10pLFxuICAgICAgLi4uKHRoaXMuc2hvd1VzZXJuYW1lRXh0cmFuZXRDb2x1bW4gPyBbdHJhbnNsYXRpb25zWydVU0VSLlVTRVJOQU1FX0VYVFJBTkVUJ11dIDogW10pLFxuICAgICAgdHJhbnNsYXRpb25zWydVU0VSLlBST0ZJTEUnXSxcbiAgICAgIHRyYW5zbGF0aW9uc1snVVNFUi5TVEFUVVMnXSxcbiAgICAgIHRyYW5zbGF0aW9uc1snVVNFUi5QVUJLRVknXSxcbiAgICAgIC4uLih0aGlzLmFkZGl0aW9uYWxGaWVsZHMgfHwgW10pLm1hcCgoZmllbGQpID0+IHRyYW5zbGF0aW9uc1tmaWVsZC5sYWJlbF0pLFxuICAgICAgdHJhbnNsYXRpb25zWydVU0VSLkNSRUFUSU9OX0RBVEUnXSxcbiAgICAgIHRyYW5zbGF0aW9uc1snVVNFUi5VUERBVEVfREFURSddLFxuICAgIF07XG5cbiAgICBjb25zdCBhZGRpdGlvbmFsRmllbGRzRm5zID0gKHRoaXMuYWRkaXRpb25hbEZpZWxkcyB8fCBbXSkubWFwKEZvcm1GaWVsZERlZmluaXRpb25VdGlscy5nZXREaXNwbGF5VmFsdWVGbik7XG5cbiAgICBjb25zdCByb3dzID0gKHRoaXMuc2VsZWN0aW9uLmlzRW1wdHkoKSA/IHRoaXMuZGF0YVNvdXJjZS5nZXRSb3dzKCkgOiB0aGlzLnNlbGVjdGlvbi5zZWxlY3RlZClcbiAgICAgIC5tYXAoKGVsZW1lbnQpID0+IGVsZW1lbnQuY3VycmVudERhdGEpXG4gICAgICAubWFwKChwZXJzb24pID0+IHtcbiAgICAgICAgY29uc3Qgc3RhdHVzID0gdGhpcy5zdGF0dXNCeUlkW3BlcnNvbi5zdGF0dXNJZF07XG4gICAgICAgIHJldHVybiBbXG4gICAgICAgICAgcGVyc29uLmxhc3ROYW1lLFxuICAgICAgICAgIHBlcnNvbi5maXJzdE5hbWUsXG4gICAgICAgICAgcGVyc29uLmVtYWlsLFxuICAgICAgICAgIC4uLih0aGlzLnNob3dVc2VybmFtZUNvbHVtbiA/IFtwZXJzb24udXNlcm5hbWVdIDogW10pLFxuICAgICAgICAgIC4uLih0aGlzLnNob3dVc2VybmFtZUV4dHJhbmV0Q29sdW1uID8gW3BlcnNvbi51c2VybmFtZUV4dHJhbmV0XSA6IFtdKSxcbiAgICAgICAgICBwZXJzb24ubWFpblByb2ZpbGUsXG4gICAgICAgICAgc3RhdHVzID8gdHJhbnNsYXRpb25zW3N0YXR1cz8ubGFiZWxdIDogbnVsbCxcbiAgICAgICAgICBwZXJzb24ucHVia2V5LFxuICAgICAgICAgIC4uLmFkZGl0aW9uYWxGaWVsZHNGbnMubWFwKChkaXNwbGF5Rm4sIGluZGV4KSA9PiB7XG4gICAgICAgICAgICBjb25zdCB2YWx1ZSA9IGdldFByb3BlcnR5QnlQYXRoKHBlcnNvbiwgdGhpcy5hZGRpdGlvbmFsRmllbGRzW2luZGV4XS5rZXkpO1xuICAgICAgICAgICAgY29uc29sZS5kZWJ1ZygnW3VzZXJzXSBBZGRpdGlvbmFsIGZpZWxkIGRpc3BsYXlGbicsIHZhbHVlKTtcbiAgICAgICAgICAgIHJldHVybiBkaXNwbGF5Rm4odmFsdWUpO1xuICAgICAgICAgIH0pLFxuICAgICAgICAgIGZyb21EYXRlSVNPU3RyaW5nKHBlcnNvbi5jcmVhdGlvbkRhdGUpLmZvcm1hdChkYXRlVGltZVBhdHRlcm4pLFxuICAgICAgICAgIGZyb21EYXRlSVNPU3RyaW5nKHBlcnNvbi51cGRhdGVEYXRlKS5mb3JtYXQoZGF0ZVRpbWVQYXR0ZXJuKSxcbiAgICAgICAgXTtcbiAgICAgIH0pO1xuXG4gICAgQ3N2VXRpbHMuZXhwb3J0VG9GaWxlKHJvd3MsIHsgZmlsZW5hbWUsIGhlYWRlcnMsIHNlcGFyYXRvciwgZW5jb2RpbmcgfSk7XG4gIH1cbn1cbiIsIjxhcHAtdG9vbGJhclxuICBbdGl0bGVdPVwiJ1VTRVIuTElTVC5USVRMRScgfCB0cmFuc2xhdGVcIlxuICBjb2xvcj1cInByaW1hcnlcIlxuICBbY2FuR29CYWNrXT1cImZhbHNlXCJcbiAgW2hhc1ZhbGlkYXRlXT1cIihsb2FkaW5nU3ViamVjdCB8IGFzeW5jKSAhPT0gdHJ1ZSAmJiAoZGlydHlTdWJqZWN0IHwgYXN5bmMpID09PSB0cnVlXCJcbiAgKG9uVmFsaWRhdGUpPVwic2F2ZSgpXCJcbj5cbiAgPGlvbi1idXR0b25zIHNsb3Q9XCJlbmRcIj5cbiAgICA8IS0tIENvbXBvc2UgbWVzc2FnZSAtLT5cbiAgICA8YnV0dG9uXG4gICAgICBtYXQtaWNvbi1idXR0b25cbiAgICAgICpuZ0lmPVwiY2FuU2VuZE1lc3NhZ2VcIlxuICAgICAgW3RpdGxlXT1cIidVU0VSLkxJU1QuQlROX1NFTkRfTUVTU0FHRScgfCB0cmFuc2xhdGVcIlxuICAgICAgKGNsaWNrKT1cIm9wZW5Db21wb3NlTWVzc2FnZU1vZGFsKCRldmVudClcIlxuICAgID5cbiAgICAgIDxpb24taWNvbiBuYW1lPVwibWFpbFwiIHNsb3Q9XCJpY29uLW9ubHlcIj48L2lvbi1pY29uPlxuICAgIDwvYnV0dG9uPlxuXG4gICAgQGlmIChzZWxlY3Rpb24gfCBpc0VtcHR5U2VsZWN0aW9uKSB7XG4gICAgICA8IS0tIEFkZCAtLT5cbiAgICAgIDxidXR0b24gbWF0LWljb24tYnV0dG9uICpuZ0lmPVwiY2FuRWRpdCAmJiAhbW9iaWxlXCIgW3RpdGxlXT1cIidDT01NT04uQlROX0FERCcgfCB0cmFuc2xhdGVcIiAoY2xpY2spPVwiYWRkUm93KClcIj5cbiAgICAgICAgPG1hdC1pY29uPmFkZDwvbWF0LWljb24+XG4gICAgICA8L2J1dHRvbj5cblxuICAgICAgPCEtLSBSZWZyZXNoIC0tPlxuICAgICAgPGJ1dHRvbiBtYXQtaWNvbi1idXR0b24gKm5nSWY9XCIhbW9iaWxlXCIgW3RpdGxlXT1cIidDT01NT04uQlROX1JFRlJFU0gnIHwgdHJhbnNsYXRlXCIgKGNsaWNrKT1cImVtaXRSZWZyZXNoKClcIj5cbiAgICAgICAgPG1hdC1pY29uPnJlZnJlc2g8L21hdC1pY29uPlxuICAgICAgPC9idXR0b24+XG5cbiAgICAgIDwhLS0gcmVzZXQgZmlsdGVyIC0tPlxuICAgICAgPGJ1dHRvbiBtYXQtaWNvbi1idXR0b24gKGNsaWNrKT1cInJlc2V0RmlsdGVyKClcIiAqbmdJZj1cImZpbHRlckNyaXRlcmlhQ291bnRcIj5cbiAgICAgICAgPG1hdC1pY29uIGNvbG9yPVwiYWNjZW50XCI+ZmlsdGVyX2xpc3RfYWx0PC9tYXQtaWNvbj5cbiAgICAgICAgPG1hdC1pY29uIGNsYXNzPVwiaWNvbi1zZWNvbmRhcnlcIiBzdHlsZT1cImxlZnQ6IDE2cHg7IHRvcDogNXB4OyBmb250LXdlaWdodDogYm9sZFwiPmNsb3NlPC9tYXQtaWNvbj5cbiAgICAgIDwvYnV0dG9uPlxuXG4gICAgICA8IS0tIHNob3cgZmlsdGVyIC0tPlxuICAgICAgPGJ1dHRvbiBtYXQtaWNvbi1idXR0b24gKGNsaWNrKT1cImZpbHRlckV4cGFuc2lvblBhbmVsLnRvZ2dsZSgpXCI+XG4gICAgICAgIDxtYXQtaWNvblxuICAgICAgICAgICpuZ0lmPVwiZmlsdGVyQ3JpdGVyaWFDb3VudDsgZWxzZSBlbXB0eUZpbHRlclwiXG4gICAgICAgICAgW21hdEJhZGdlXT1cImZpbHRlckNyaXRlcmlhQ291bnRcIlxuICAgICAgICAgIG1hdEJhZGdlQ29sb3I9XCJhY2NlbnRcIlxuICAgICAgICAgIG1hdEJhZGdlU2l6ZT1cInNtYWxsXCJcbiAgICAgICAgICBtYXRCYWRnZVBvc2l0aW9uPVwiYWJvdmUgYWZ0ZXJcIlxuICAgICAgICAgIGFyaWEtaGlkZGVuPVwiZmFsc2VcIlxuICAgICAgICA+XG4gICAgICAgICAgZmlsdGVyX2xpc3RfYWx0XG4gICAgICAgIDwvbWF0LWljb24+XG4gICAgICAgIDxuZy10ZW1wbGF0ZSAjZW1wdHlGaWx0ZXI+XG4gICAgICAgICAgPG1hdC1pY29uPmZpbHRlcl9saXN0X2FsdDwvbWF0LWljb24+XG4gICAgICAgIDwvbmctdGVtcGxhdGU+XG4gICAgICA8L2J1dHRvbj5cbiAgICB9IEBlbHNlIHtcbiAgICAgIDwhLS0gZGVsZXRlIC0tPlxuICAgICAgPGJ1dHRvblxuICAgICAgICBtYXQtaWNvbi1idXR0b25cbiAgICAgICAgY2xhc3M9XCJoaWRkZW4teHMgaGlkZGVuLXNtXCJcbiAgICAgICAgW3RpdGxlXT1cIidDT01NT04uQlROX0RFTEVURScgfCB0cmFuc2xhdGVcIlxuICAgICAgICAoY2xpY2spPVwiZGVsZXRlU2VsZWN0aW9uKCRldmVudClcIlxuICAgICAgPlxuICAgICAgICA8bWF0LWljb24+ZGVsZXRlPC9tYXQtaWNvbj5cbiAgICAgIDwvYnV0dG9uPlxuICAgIH1cblxuICAgIEBpZiAoIW1vYmlsZSkge1xuICAgICAgPGJ1dHRvbiBtYXQtaWNvbi1idXR0b24gW3RpdGxlXT1cIidDT01NT04uQlROX09QVElPTlMnIHwgdHJhbnNsYXRlXCIgW21hdE1lbnVUcmlnZ2VyRm9yXT1cInRvb2xiYXJPcHRpb25zTWVudVwiPlxuICAgICAgICA8bWF0LWljb24+bW9yZV92ZXJ0PC9tYXQtaWNvbj5cbiAgICAgIDwvYnV0dG9uPlxuICAgIH1cbiAgPC9pb24tYnV0dG9ucz5cbjwvYXBwLXRvb2xiYXI+XG5cbjwhLS0gVG9vbGJhciBvcHRpb24gbWVudSAtLT5cbjxtYXQtbWVudSAjdG9vbGJhck9wdGlvbnNNZW51PVwibWF0TWVudVwiIHhQb3NpdGlvbj1cImFmdGVyXCI+XG4gIDwhLS0gZXhwb3J0IGJ1dHRvbiAtLT5cbiAgPGJ1dHRvbiBtYXQtbWVudS1pdGVtIFtkaXNhYmxlZF09XCIhY2FuRG93bmxvYWRcIiAoY2xpY2spPVwiZXhwb3J0VG9Dc3YoJGV2ZW50KVwiPlxuICAgIDxtYXQtaWNvbj5kb3dubG9hZDwvbWF0LWljb24+XG4gICAgPGlvbi1sYWJlbCB0cmFuc2xhdGU+RklMRS5DU1YuQlROX0RPV05MT0FEX0hFTFA8L2lvbi1sYWJlbD5cbiAgPC9idXR0b24+XG48L21hdC1tZW51PlxuXG48aW9uLWNvbnRlbnQgY2xhc3M9XCJpb24tbm8tcGFkZGluZ1wiPlxuICA8IS0tIGVycm9yIC0tPlxuICA8aW9uLWl0ZW1cbiAgICAqbmdJZj1cImVycm9yU3ViamVjdCB8IGFzeW5jOyBsZXQgZXJyb3JcIlxuICAgIGxpbmVzPVwibm9uZVwiXG4gICAgY2xhc3M9XCJoaWRkZW4tc20gaGlkZGVuLXhzIGhpZGRlbi1tb2JpbGVcIlxuICAgIEBzbGlkZVVwRG93bkFuaW1hdGlvblxuICA+XG4gICAgPGlvbi1pY29uIGNvbG9yPVwiZGFuZ2VyXCIgc2xvdD1cInN0YXJ0XCIgbmFtZT1cImFsZXJ0LWNpcmNsZVwiPjwvaW9uLWljb24+XG4gICAgPGlvbi1sYWJlbCBjb2xvcj1cImRhbmdlclwiIGNsYXNzPVwiZXJyb3JcIiBbaW5uZXJIVE1MXT1cImVycm9yIHwgdHJhbnNsYXRlXCI+PC9pb24tbGFiZWw+XG4gIDwvaW9uLWl0ZW0+XG5cbiAgPCEtLSBkZWJ1ZyAtLT5cbiAgPGFwcC1kZWJ1ZyAqbmdJZj1cImRlYnVnXCI+XG4gICAgPGlvbi1ncmlkIGNsYXNzPVwiaW9uLW5vLXBhZGRpbmdcIj5cbiAgICAgIDxpb24tcm93PlxuICAgICAgICA8aW9uLWNvbD5cbiAgICAgICAgICBmb2N1c0NvbHVtbjoge3sgZm9jdXNDb2x1bW4gfX1cbiAgICAgICAgICA8YnIgLz5cbiAgICAgICAgICBsb2FkaW5nU3ViamVjdDoge3sgbG9hZGluZyB9fVxuICAgICAgICAgIDxiciAvPlxuICAgICAgICA8L2lvbi1jb2w+XG4gICAgICA8L2lvbi1yb3c+XG4gICAgPC9pb24tZ3JpZD5cbiAgPC9hcHAtZGVidWc+XG5cbiAgPCEtLSBzZWFyY2ggLS0+XG4gIDxtYXQtZXhwYW5zaW9uLXBhbmVsICNmaWx0ZXJFeHBhbnNpb25QYW5lbCBjbGFzcz1cImlvbi1uby1wYWRkaW5nIGZpbHRlci1wYW5lbCBmaWx0ZXItcGFuZWwtZmxvYXRpbmdcIj5cbiAgICA8Zm9ybSBjbGFzcz1cImZvcm0tY29udGFpbmVyIGlvbi1wYWRkaW5nXCIgW2Zvcm1Hcm91cF09XCJmaWx0ZXJGb3JtXCIgKG5nU3VibWl0KT1cImVtaXRSZWZyZXNoKClcIj5cbiAgICAgIDxpb24tZ3JpZD5cbiAgICAgICAgPGlvbi1yb3c+XG4gICAgICAgICAgPGlvbi1jb2w+XG4gICAgICAgICAgICA8IS0tIHNlYXJjaCAtLT5cbiAgICAgICAgICAgIDxtYXQtZm9ybS1maWVsZD5cbiAgICAgICAgICAgICAgPG1hdC1sYWJlbD57eyAnVVNFUi5MSVNULkZJTFRFUi5TRUFSQ0gnIHwgdHJhbnNsYXRlIH19PC9tYXQtbGFiZWw+XG4gICAgICAgICAgICAgIDxpbnB1dCBtYXRJbnB1dCBmb3JtQ29udHJvbE5hbWU9XCJzZWFyY2hUZXh0XCIgLz5cbiAgICAgICAgICAgICAgPGJ1dHRvblxuICAgICAgICAgICAgICAgIG1hdC1pY29uLWJ1dHRvblxuICAgICAgICAgICAgICAgIG1hdFN1ZmZpeFxuICAgICAgICAgICAgICAgIHRhYmluZGV4PVwiLTFcIlxuICAgICAgICAgICAgICAgIHR5cGU9XCJidXR0b25cIlxuICAgICAgICAgICAgICAgIChjbGljayk9XCJjbGVhckNvbnRyb2xWYWx1ZSgkZXZlbnQsIGZpbHRlckZvcm0uY29udHJvbHMuc2VhcmNoVGV4dClcIlxuICAgICAgICAgICAgICAgIFtoaWRkZW5dPVwiZmlsdGVyRm9ybS5jb250cm9scy5zZWFyY2hUZXh0LmRpc2FibGVkIHx8ICFmaWx0ZXJGb3JtLmNvbnRyb2xzLnNlYXJjaFRleHQudmFsdWVcIlxuICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgPG1hdC1pY29uPmNsb3NlPC9tYXQtaWNvbj5cbiAgICAgICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgICA8L21hdC1mb3JtLWZpZWxkPlxuICAgICAgICAgIDwvaW9uLWNvbD5cblxuICAgICAgICAgIDxpb24tY29sPlxuICAgICAgICAgICAgPCEtLSBzdGF0dXMgLS0+XG4gICAgICAgICAgICA8bWF0LWZvcm0tZmllbGQ+XG4gICAgICAgICAgICAgIDxtYXQtbGFiZWw+e3sgJ1VTRVIuU1RBVFVTJyB8IHRyYW5zbGF0ZSB9fTwvbWF0LWxhYmVsPlxuICAgICAgICAgICAgICA8bWF0LXNlbGVjdCBmb3JtQ29udHJvbE5hbWU9XCJzdGF0dXNJZFwiPlxuICAgICAgICAgICAgICAgIDxtYXQtb3B0aW9uIFt2YWx1ZV09XCJudWxsXCI+XG4gICAgICAgICAgICAgICAgICA8aT48c3BhbiB0cmFuc2xhdGU+Q09NTU9OLkVNUFRZX09QVElPTjwvc3Bhbj48L2k+XG4gICAgICAgICAgICAgICAgPC9tYXQtb3B0aW9uPlxuICAgICAgICAgICAgICAgIDxtYXQtb3B0aW9uICpuZ0Zvcj1cImxldCBpdGVtIG9mIHN0YXR1c0xpc3RcIiBbdmFsdWVdPVwiaXRlbS5pZFwiPlxuICAgICAgICAgICAgICAgICAgPGlvbi1pY29uIFtuYW1lXT1cIml0ZW0uaWNvblwiPjwvaW9uLWljb24+XG4gICAgICAgICAgICAgICAgICB7eyBpdGVtLmxhYmVsIHwgdHJhbnNsYXRlIH19XG4gICAgICAgICAgICAgICAgPC9tYXQtb3B0aW9uPlxuICAgICAgICAgICAgICA8L21hdC1zZWxlY3Q+XG5cbiAgICAgICAgICAgICAgPGJ1dHRvblxuICAgICAgICAgICAgICAgIG1hdC1pY29uLWJ1dHRvblxuICAgICAgICAgICAgICAgIG1hdFN1ZmZpeFxuICAgICAgICAgICAgICAgIHRhYmluZGV4PVwiLTFcIlxuICAgICAgICAgICAgICAgIHR5cGU9XCJidXR0b25cIlxuICAgICAgICAgICAgICAgIChjbGljayk9XCJjbGVhckNvbnRyb2xWYWx1ZSgkZXZlbnQsIGZpbHRlckZvcm0uY29udHJvbHMuc3RhdHVzSWQpXCJcbiAgICAgICAgICAgICAgICBbaGlkZGVuXT1cImZpbHRlckZvcm0uY29udHJvbHMuc3RhdHVzSWQuZGlzYWJsZWQgfHwgIWZpbHRlckZvcm0uY29udHJvbHMuc3RhdHVzSWQudmFsdWVcIlxuICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgPG1hdC1pY29uPmNsb3NlPC9tYXQtaWNvbj5cbiAgICAgICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgICA8L21hdC1mb3JtLWZpZWxkPlxuICAgICAgICAgIDwvaW9uLWNvbD5cbiAgICAgICAgPC9pb24tcm93PlxuICAgICAgPC9pb24tZ3JpZD5cbiAgICA8L2Zvcm0+XG5cbiAgICA8bWF0LWFjdGlvbi1yb3c+XG4gICAgICA8IS0tIENvdW50ZXIgIC0tPlxuICAgICAgPGlvbi1sYWJlbFxuICAgICAgICBbaGlkZGVuXT1cIihsb2FkaW5nU3ViamVjdCB8IGFzeW5jKSA9PT0gdHJ1ZSB8fCBmaWx0ZXJGb3JtLmRpcnR5XCJcbiAgICAgICAgW2NvbG9yXT1cImVtcHR5ICYmICdkYW5nZXInXCJcbiAgICAgICAgY2xhc3M9XCJpb24tcGFkZGluZ1wiXG4gICAgICA+XG4gICAgICAgIHt7XG4gICAgICAgICAgKHRvdGFsUm93Q291bnQgPyAnQ09NTU9OLlJFU1VMVF9DT1VOVCcgOiAnQ09NTU9OLk5PX1JFU1VMVCcpXG4gICAgICAgICAgICB8IHRyYW5zbGF0ZVxuICAgICAgICAgICAgICA6IHtcbiAgICAgICAgICAgICAgICAgIGNvdW50OiAodG90YWxSb3dDb3VudCB8IG51bWJlckZvcm1hdCksXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICB9fVxuICAgICAgPC9pb24tbGFiZWw+XG5cbiAgICAgIDxkaXYgY2xhc3M9XCJ0b29sYmFyLXNwYWNlclwiPjwvZGl2PlxuXG4gICAgICA8IS0tIENsb3NlIHBhbmVsIC0tPlxuICAgICAgPGlvbi1idXR0b25cbiAgICAgICAgbWF0LWJ1dHRvblxuICAgICAgICBmaWxsPVwiY2xlYXJcIlxuICAgICAgICBjb2xvcj1cImRhcmtcIlxuICAgICAgICAoY2xpY2spPVwiZmlsdGVyRXhwYW5zaW9uUGFuZWwuY2xvc2UoKVwiXG4gICAgICAgIFtkaXNhYmxlZF09XCJsb2FkaW5nU3ViamVjdCB8IGFzeW5jXCJcbiAgICAgID5cbiAgICAgICAgPGlvbi10ZXh0IHRyYW5zbGF0ZT5DT01NT04uQlROX0NMT1NFPC9pb24tdGV4dD5cbiAgICAgIDwvaW9uLWJ1dHRvbj5cblxuICAgICAgPCEtLSBTZWFyY2ggYnV0dG9uIC0tPlxuICAgICAgPGlvbi1idXR0b25cbiAgICAgICAgbWF0LWJ1dHRvblxuICAgICAgICBbY29sb3JdPVwiZmlsdGVyRm9ybS5kaXJ0eSA/ICd0ZXJ0aWFyeScgOiAnZGFyaydcIlxuICAgICAgICBbZmlsbF09XCJmaWx0ZXJGb3JtLmRpcnR5ID8gJ3NvbGlkJyA6ICdjbGVhcidcIlxuICAgICAgICAoY2xpY2spPVwiYXBwbHlGaWx0ZXJBbmRDbG9zZVBhbmVsKCRldmVudClcIlxuICAgICAgICBbZGlzYWJsZWRdPVwibG9hZGluZ1N1YmplY3QgfCBhc3luY1wiXG4gICAgICA+XG4gICAgICAgIDxpb24tdGV4dCB0cmFuc2xhdGU+Q09NTU9OLkJUTl9BUFBMWTwvaW9uLXRleHQ+XG4gICAgICA8L2lvbi1idXR0b24+XG4gICAgPC9tYXQtYWN0aW9uLXJvdz5cbiAgPC9tYXQtZXhwYW5zaW9uLXBhbmVsPlxuXG4gIDwhLS0gZXJyb3IgLS0+XG4gIDxpb24taXRlbSAqbmdJZj1cIm1vYmlsZSAmJiAoZXJyb3JTdWJqZWN0IHwgYXN5bmMpOyBsZXQgZXJyb3JcIiBsaW5lcz1cIm5vbmVcIj5cbiAgICA8aW9uLWljb24gY29sb3I9XCJkYW5nZXJcIiBzbG90PVwic3RhcnRcIiBuYW1lPVwiYWxlcnQtY2lyY2xlXCI+PC9pb24taWNvbj5cbiAgICA8aW9uLWxhYmVsIGNvbG9yPVwiZGFuZ2VyXCIgY2xhc3M9XCJlcnJvclwiIFtpbm5lckhUTUxdPVwiZXJyb3IgfCB0cmFuc2xhdGVcIj48L2lvbi1sYWJlbD5cbiAgPC9pb24taXRlbT5cblxuICA8ZGl2IGNsYXNzPVwidGFibGUtY29udGFpbmVyXCI+XG4gICAgPHRhYmxlXG4gICAgICAjdGFibGVcbiAgICAgIG1hdC10YWJsZVxuICAgICAgbWF0U29ydFxuICAgICAgW2NsYXNzLmNvbXBhY3RdPVwiY29tcGFjdFwiXG4gICAgICBbZGF0YVNvdXJjZV09XCJkYXRhU291cmNlXCJcbiAgICAgIFttYXRTb3J0QWN0aXZlXT1cImRlZmF1bHRTb3J0QnlcIlxuICAgICAgW21hdFNvcnREaXJlY3Rpb25dPVwiZGVmYXVsdFNvcnREaXJlY3Rpb25cIlxuICAgICAgbWF0U29ydERpc2FibGVDbGVhclxuICAgICAgW3RyYWNrQnldPVwidHJhY2tCeUZuXCJcbiAgICA+XG4gICAgICA8bmctY29udGFpbmVyIG1hdENvbHVtbkRlZj1cInNlbGVjdFwiIFtzdGlja3ldPVwic3RpY2t5XCI+XG4gICAgICAgIDx0aCBtYXQtaGVhZGVyLWNlbGwgKm1hdEhlYWRlckNlbGxEZWYgW2NsYXNzLmNkay12aXN1YWxseS1oaWRkZW5dPVwiIWlubGluZUVkaXRpb25cIj5cbiAgICAgICAgICA8bWF0LWNoZWNrYm94XG4gICAgICAgICAgICAoY2hhbmdlKT1cIiRldmVudCA/IG1hc3RlclRvZ2dsZSgpIDogbnVsbFwiXG4gICAgICAgICAgICBbY2hlY2tlZF09XCJ0aGlzIHwgaXNBbGxTZWxlY3RlZFwiXG4gICAgICAgICAgICBbaW5kZXRlcm1pbmF0ZV09XCJ0aGlzIHwgaXNOb3RBbGxTZWxlY3RlZFwiXG4gICAgICAgICAgPjwvbWF0LWNoZWNrYm94PlxuICAgICAgICA8L3RoPlxuICAgICAgICA8dGQgbWF0LWNlbGwgKm1hdENlbGxEZWY9XCJsZXQgcm93XCIgW2NsYXNzLmNkay12aXN1YWxseS1oaWRkZW5dPVwiIWlubGluZUVkaXRpb25cIj5cbiAgICAgICAgICA8bWF0LWNoZWNrYm94IChjbGljayk9XCJ0b2dnbGVTZWxlY3RSb3coJGV2ZW50LCByb3cpXCIgW2NoZWNrZWRdPVwic2VsZWN0aW9uIHwgaXNTZWxlY3RlZDogcm93XCI+PC9tYXQtY2hlY2tib3g+XG4gICAgICAgIDwvdGQ+XG4gICAgICA8L25nLWNvbnRhaW5lcj5cblxuICAgICAgPCEtLSBJZCBDb2x1bW4gLS0+XG4gICAgICA8bmctY29udGFpbmVyIG1hdENvbHVtbkRlZj1cImlkXCIgW3N0aWNreV09XCJzdGlja3lcIj5cbiAgICAgICAgPHRoIG1hdC1oZWFkZXItY2VsbCAqbWF0SGVhZGVyQ2VsbERlZiBtYXQtc29ydC1oZWFkZXI+XG4gICAgICAgICAgPGlvbi1sYWJlbD4jPC9pb24tbGFiZWw+XG4gICAgICAgIDwvdGg+XG4gICAgICAgIDx0ZCBtYXQtY2VsbCAqbWF0Q2VsbERlZj1cImxldCByb3dcIj5cbiAgICAgICAgICA8aW9uLWxhYmVsPnt7IHJvdy5jdXJyZW50RGF0YS5pZCB9fTwvaW9uLWxhYmVsPlxuICAgICAgICA8L3RkPlxuICAgICAgPC9uZy1jb250YWluZXI+XG5cbiAgICAgIDwhLS0gYXZhdGFyIENvbHVtbiAtLT5cbiAgICAgIDxuZy1jb250YWluZXIgbWF0Q29sdW1uRGVmPVwiYXZhdGFyXCIgW3N0aWNreV09XCJzdGlja3lcIj5cbiAgICAgICAgPHRoIG1hdC1oZWFkZXItY2VsbCAqbWF0SGVhZGVyQ2VsbERlZj48L3RoPlxuICAgICAgICA8dGQgbWF0LWNlbGwgKm1hdENlbGxEZWY9XCJsZXQgcm93XCI+XG4gICAgICAgICAgPGlvbi1hdmF0YXIgW3N0eWxlLmJhY2tncm91bmQtY29sb3JdPVwiJ3doaXRlJ1wiPlxuICAgICAgICAgICAgPGlvbi1pbWcgKm5nSWY9XCJyb3cuY3VycmVudERhdGEuYXZhdGFyOyBsZXQgYXZhdGFyVXJsOyBlbHNlOiBnZW5lcmF0ZUljb25cIiBbc3JjXT1cImF2YXRhclVybFwiPjwvaW9uLWltZz5cbiAgICAgICAgICAgIDxuZy10ZW1wbGF0ZSAjZ2VuZXJhdGVJY29uPlxuICAgICAgICAgICAgICA8c3ZnIHdpZHRoPVwiMzlcIiBoZWlnaHQ9XCIzOVwiIFtkYXRhLWpkZW50aWNvbi12YWx1ZV09XCJyb3cuY3VycmVudERhdGEuaWRcIj48L3N2Zz5cbiAgICAgICAgICAgIDwvbmctdGVtcGxhdGU+XG4gICAgICAgICAgPC9pb24tYXZhdGFyPlxuICAgICAgICA8L3RkPlxuICAgICAgPC9uZy1jb250YWluZXI+XG5cbiAgICAgIDwhLS0gbGFzdE5hbWUgIC0tPlxuICAgICAgPG5nLWNvbnRhaW5lciBtYXRDb2x1bW5EZWY9XCJsYXN0TmFtZVwiPlxuICAgICAgICA8dGggbWF0LWhlYWRlci1jZWxsICptYXRIZWFkZXJDZWxsRGVmIG1hdC1zb3J0LWhlYWRlcj5cbiAgICAgICAgICA8c3BhbiB0cmFuc2xhdGU+VVNFUi5MQVNUX05BTUU8L3NwYW4+XG4gICAgICAgIDwvdGg+XG4gICAgICAgIDx0ZCBtYXQtY2VsbCAqbWF0Q2VsbERlZj1cImxldCByb3dcIiAoY2xpY2spPVwiZm9jdXNDb2x1bW4gPSAnbGFzdE5hbWUnXCI+XG4gICAgICAgICAgPG1hdC1mb3JtLWZpZWxkICpuZ0lmPVwicm93LmVkaXRpbmc7IGVsc2UgcmVhZG9ubHlDZWxsXCI+XG4gICAgICAgICAgICA8aW5wdXRcbiAgICAgICAgICAgICAgbWF0SW5wdXRcbiAgICAgICAgICAgICAgW2Zvcm1Db250cm9sXT1cInJvdy52YWxpZGF0b3IuY29udHJvbHNbJ2xhc3ROYW1lJ11cIlxuICAgICAgICAgICAgICBbcGxhY2Vob2xkZXJdPVwiJ1VTRVIuTEFTVF9OQU1FJyB8IHRyYW5zbGF0ZVwiXG4gICAgICAgICAgICAgIFtyZWFkb25seV09XCIhcm93LmVkaXRpbmdcIlxuICAgICAgICAgICAgICBbYXBwQXV0b2ZvY3VzXT1cInJvdy5lZGl0aW5nICYmIGZvY3VzQ29sdW1uID09PSAnbGFzdE5hbWUnXCJcbiAgICAgICAgICAgIC8+XG4gICAgICAgICAgICA8bWF0LWVycm9yICpuZ0lmPVwicm93LnZhbGlkYXRvci5jb250cm9sc1snbGFzdE5hbWUnXS5oYXNFcnJvcigncmVxdWlyZWQnKVwiIHRyYW5zbGF0ZT5cbiAgICAgICAgICAgICAgRVJST1IuRklFTERfUkVRVUlSRURcbiAgICAgICAgICAgIDwvbWF0LWVycm9yPlxuICAgICAgICAgICAgPG1hdC1lcnJvciAqbmdJZj1cInJvdy52YWxpZGF0b3IuY29udHJvbHNbJ2xhc3ROYW1lJ10uaGFzRXJyb3IoJ21pbmxlbmd0aCcpXCI+XG4gICAgICAgICAgICAgIDxzcGFuPnt7ICdFUlJPUi5GSUVMRF9NSU5fTEVOR1RIJyB8IHRyYW5zbGF0ZTogeyByZXF1aXJlZExlbmd0aDogMiB9IH19PC9zcGFuPlxuICAgICAgICAgICAgPC9tYXQtZXJyb3I+XG4gICAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cbiAgICAgICAgICA8bmctdGVtcGxhdGUgI3JlYWRvbmx5Q2VsbD5cbiAgICAgICAgICAgIDxpb24tbGFiZWwgYXBwQXV0b1RpdGxlPlxuICAgICAgICAgICAgICB7eyByb3cudmFsaWRhdG9yIHwgZm9ybUdldFZhbHVlOiAnbGFzdE5hbWUnIH19XG4gICAgICAgICAgICA8L2lvbi1sYWJlbD5cbiAgICAgICAgICA8L25nLXRlbXBsYXRlPlxuICAgICAgICA8L3RkPlxuICAgICAgPC9uZy1jb250YWluZXI+XG5cbiAgICAgIDwhLS0gZmlyc3RuYW1lIC0tPlxuICAgICAgPG5nLWNvbnRhaW5lciBtYXRDb2x1bW5EZWY9XCJmaXJzdE5hbWVcIj5cbiAgICAgICAgPHRoIG1hdC1oZWFkZXItY2VsbCAqbWF0SGVhZGVyQ2VsbERlZiBtYXQtc29ydC1oZWFkZXI+XG4gICAgICAgICAgPHNwYW4gdHJhbnNsYXRlPlVTRVIuRklSU1RfTkFNRTwvc3Bhbj5cbiAgICAgICAgPC90aD5cbiAgICAgICAgPHRkIG1hdC1jZWxsICptYXRDZWxsRGVmPVwibGV0IHJvd1wiIChjbGljayk9XCJmb2N1c0NvbHVtbiA9ICdmaXJzdE5hbWUnXCI+XG4gICAgICAgICAgPG1hdC1mb3JtLWZpZWxkICpuZ0lmPVwicm93LmVkaXRpbmc7IGVsc2UgcmVhZG9ubHlDZWxsXCI+XG4gICAgICAgICAgICA8aW5wdXRcbiAgICAgICAgICAgICAgbWF0SW5wdXRcbiAgICAgICAgICAgICAgW2Zvcm1Db250cm9sXT1cInJvdy52YWxpZGF0b3IuY29udHJvbHNbJ2ZpcnN0TmFtZSddXCJcbiAgICAgICAgICAgICAgW3BsYWNlaG9sZGVyXT1cIidVU0VSLkZJUlNUX05BTUUnIHwgdHJhbnNsYXRlXCJcbiAgICAgICAgICAgICAgW3JlYWRvbmx5XT1cIiFyb3cuZWRpdGluZ1wiXG4gICAgICAgICAgICAgIFthcHBBdXRvZm9jdXNdPVwicm93LmVkaXRpbmcgJiYgZm9jdXNDb2x1bW4gPT09ICdmaXJzdE5hbWUnXCJcbiAgICAgICAgICAgIC8+XG4gICAgICAgICAgICA8bWF0LWVycm9yICpuZ0lmPVwicm93LnZhbGlkYXRvci5jb250cm9sc1snZmlyc3ROYW1lJ10uaGFzRXJyb3IoJ3JlcXVpcmVkJylcIiB0cmFuc2xhdGU+XG4gICAgICAgICAgICAgIEVSUk9SLkZJRUxEX1JFUVVJUkVEXG4gICAgICAgICAgICA8L21hdC1lcnJvcj5cbiAgICAgICAgICAgIDxtYXQtZXJyb3IgKm5nSWY9XCJyb3cudmFsaWRhdG9yLmNvbnRyb2xzWydmaXJzdE5hbWUnXS5oYXNFcnJvcignbWlubGVuZ3RoJylcIj5cbiAgICAgICAgICAgICAgPHNwYW4+e3sgJ0VSUk9SLkZJRUxEX01JTl9MRU5HVEgnIHwgdHJhbnNsYXRlOiB7IHJlcXVpcmVkTGVuZ3RoOiAyIH0gfX08L3NwYW4+XG4gICAgICAgICAgICA8L21hdC1lcnJvcj5cbiAgICAgICAgICA8L21hdC1mb3JtLWZpZWxkPlxuICAgICAgICAgIDxuZy10ZW1wbGF0ZSAjcmVhZG9ubHlDZWxsPlxuICAgICAgICAgICAgPGlvbi1sYWJlbCBhcHBBdXRvVGl0bGU+XG4gICAgICAgICAgICAgIHt7IHJvdy52YWxpZGF0b3IgfCBmb3JtR2V0VmFsdWU6ICdmaXJzdE5hbWUnIH19XG4gICAgICAgICAgICA8L2lvbi1sYWJlbD5cbiAgICAgICAgICA8L25nLXRlbXBsYXRlPlxuICAgICAgICA8L3RkPlxuICAgICAgPC9uZy1jb250YWluZXI+XG5cbiAgICAgIDwhLS0gZW1haWwgIC0tPlxuICAgICAgPG5nLWNvbnRhaW5lciBtYXRDb2x1bW5EZWY9XCJlbWFpbFwiPlxuICAgICAgICA8dGggbWF0LWhlYWRlci1jZWxsICptYXRIZWFkZXJDZWxsRGVmIG1hdC1zb3J0LWhlYWRlcj5cbiAgICAgICAgICA8c3BhbiB0cmFuc2xhdGU+VVNFUi5FTUFJTDwvc3Bhbj5cbiAgICAgICAgPC90aD5cbiAgICAgICAgPHRkIG1hdC1jZWxsICptYXRDZWxsRGVmPVwibGV0IHJvd1wiIChjbGljayk9XCJmb2N1c0NvbHVtbiA9ICdlbWFpbCdcIj5cbiAgICAgICAgICA8bWF0LWZvcm0tZmllbGQgKm5nSWY9XCJyb3cuZWRpdGluZzsgZWxzZSByZWFkb25seUNlbGxcIj5cbiAgICAgICAgICAgIDxpbnB1dFxuICAgICAgICAgICAgICBtYXRJbnB1dFxuICAgICAgICAgICAgICBbZm9ybUNvbnRyb2xdPVwicm93LnZhbGlkYXRvci5jb250cm9sc1snZW1haWwnXVwiXG4gICAgICAgICAgICAgIFtwbGFjZWhvbGRlcl09XCInVVNFUi5FTUFJTCcgfCB0cmFuc2xhdGVcIlxuICAgICAgICAgICAgICBbcmVhZG9ubHldPVwiIXJvdy5lZGl0aW5nXCJcbiAgICAgICAgICAgICAgW2FwcEF1dG9mb2N1c109XCJyb3cuZWRpdGluZyAmJiBmb2N1c0NvbHVtbiA9PT0gJ2VtYWlsJ1wiXG4gICAgICAgICAgICAvPlxuICAgICAgICAgICAgPG1hdC1lcnJvciAqbmdJZj1cInJvdy52YWxpZGF0b3IuY29udHJvbHNbJ2VtYWlsJ10uaGFzRXJyb3IoJ3JlcXVpcmVkJylcIiB0cmFuc2xhdGU+XG4gICAgICAgICAgICAgIEVSUk9SLkZJRUxEX1JFUVVJUkVEXG4gICAgICAgICAgICA8L21hdC1lcnJvcj5cbiAgICAgICAgICAgIDxtYXQtZXJyb3IgKm5nSWY9XCJyb3cudmFsaWRhdG9yLmNvbnRyb2xzWydlbWFpbCddLmhhc0Vycm9yKCdlbWFpbCcpXCI+XG4gICAgICAgICAgICAgIDxzcGFuIHRyYW5zbGF0ZT5FUlJPUi5GSUVMRF9OT1RfVkFMSURfRU1BSUw8L3NwYW4+XG4gICAgICAgICAgICA8L21hdC1lcnJvcj5cbiAgICAgICAgICA8L21hdC1mb3JtLWZpZWxkPlxuICAgICAgICAgIDxuZy10ZW1wbGF0ZSAjcmVhZG9ubHlDZWxsPlxuICAgICAgICAgICAgPGlvbi1sYWJlbCBhcHBBdXRvVGl0bGU+XG4gICAgICAgICAgICAgIHt7IHJvdy52YWxpZGF0b3IgfCBmb3JtR2V0VmFsdWU6ICdlbWFpbCcgfX1cbiAgICAgICAgICAgIDwvaW9uLWxhYmVsPlxuICAgICAgICAgIDwvbmctdGVtcGxhdGU+XG4gICAgICAgIDwvdGQ+XG4gICAgICA8L25nLWNvbnRhaW5lcj5cblxuICAgICAgPCEtLSBhZGRpdGlvbmFsIGZpZWxkcyAtLT5cbiAgICAgIDxuZy1jb250YWluZXIgKm5nRm9yPVwibGV0IGRlZmluaXRpb24gb2YgYWRkaXRpb25hbEZpZWxkc1wiIFttYXRDb2x1bW5EZWZdPVwiZGVmaW5pdGlvbi5rZXlcIj5cbiAgICAgICAgPHRoIG1hdC1oZWFkZXItY2VsbCAqbWF0SGVhZGVyQ2VsbERlZj5cbiAgICAgICAgICA8c3Bhbj57eyBkZWZpbml0aW9uLmxhYmVsIHwgdHJhbnNsYXRlIH19PC9zcGFuPlxuICAgICAgICA8L3RoPlxuICAgICAgICA8dGQgbWF0LWNlbGwgKm1hdENlbGxEZWY9XCJsZXQgcm93XCIgKGNsaWNrKT1cImZvY3VzQ29sdW1uID0gZGVmaW5pdGlvbi5rZXlcIj5cbiAgICAgICAgICA8YXBwLWZvcm0tZmllbGRcbiAgICAgICAgICAgIGZsb2F0TGFiZWw9XCJuZXZlclwiXG4gICAgICAgICAgICBbZGVmaW5pdGlvbl09XCJkZWZpbml0aW9uXCJcbiAgICAgICAgICAgIFtmb3JtQ29udHJvbF09XCJyb3cudmFsaWRhdG9yLmNvbnRyb2xzW2RlZmluaXRpb24ua2V5XVwiXG4gICAgICAgICAgICBbcmVxdWlyZWRdPVwiZGVmaW5pdGlvbi5leHRyYT8uYWNjb3VudD8ucmVxdWlyZWRcIlxuICAgICAgICAgICAgW2F1dG9mb2N1c109XCJyb3cuZWRpdGluZyAmJiBmb2N1c0NvbHVtbiA9PT0gZGVmaW5pdGlvbi5rZXlcIlxuICAgICAgICAgID48L2FwcC1mb3JtLWZpZWxkPlxuICAgICAgICA8L3RkPlxuICAgICAgPC9uZy1jb250YWluZXI+XG5cbiAgICAgIDwhLS0gcHJvZmlsZSBjb2x1bW4gIC0tPlxuICAgICAgPG5nLWNvbnRhaW5lciBtYXRDb2x1bW5EZWY9XCJwcm9maWxlXCI+XG4gICAgICAgIDx0aCBtYXQtaGVhZGVyLWNlbGwgKm1hdEhlYWRlckNlbGxEZWY+XG4gICAgICAgICAgPHNwYW4gdHJhbnNsYXRlPlVTRVIuUFJPRklMRTwvc3Bhbj5cbiAgICAgICAgPC90aD5cbiAgICAgICAgPHRkIG1hdC1jZWxsICptYXRDZWxsRGVmPVwibGV0IHJvd1wiIChjbGljayk9XCJmb2N1c0NvbHVtbiA9ICdwcm9maWxlJ1wiPlxuICAgICAgICAgIDxtYXQtZm9ybS1maWVsZD5cbiAgICAgICAgICAgIDxtYXQtc2VsZWN0XG4gICAgICAgICAgICAgIFtmb3JtQ29udHJvbF09XCJyb3cudmFsaWRhdG9yLmNvbnRyb2xzWydtYWluUHJvZmlsZSddXCJcbiAgICAgICAgICAgICAgW3BsYWNlaG9sZGVyXT1cIidVU0VSLlBST0ZJTEUnIHwgdHJhbnNsYXRlXCJcbiAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgPG1hdC1vcHRpb24gKm5nRm9yPVwibGV0IGl0ZW0gb2YgcHJvZmlsZXNcIiBbdmFsdWVdPVwiaXRlbVwiPlxuICAgICAgICAgICAgICAgIHt7ICdVU0VSLlBST0ZJTEVfRU5VTS4nICsgaXRlbSB8IHVwcGVyY2FzZSB8IHRyYW5zbGF0ZSB9fVxuICAgICAgICAgICAgICA8L21hdC1vcHRpb24+XG4gICAgICAgICAgICA8L21hdC1zZWxlY3Q+XG4gICAgICAgICAgICA8bWF0LWVycm9yICpuZ0lmPVwicm93LnZhbGlkYXRvci5jb250cm9sc1snbWFpblByb2ZpbGUnXS5oYXNFcnJvcigncmVxdWlyZWQnKVwiIHRyYW5zbGF0ZT5cbiAgICAgICAgICAgICAgRVJST1IuRklFTERfUkVRVUlSRURcbiAgICAgICAgICAgIDwvbWF0LWVycm9yPlxuICAgICAgICAgIDwvbWF0LWZvcm0tZmllbGQ+XG4gICAgICAgIDwvdGQ+XG4gICAgICA8L25nLWNvbnRhaW5lcj5cblxuICAgICAgPCEtLSBTdGF0dXMgY29sdW1uICAtLT5cbiAgICAgIDxuZy1jb250YWluZXIgbWF0Q29sdW1uRGVmPVwic3RhdHVzXCI+XG4gICAgICAgIDx0aCBtYXQtaGVhZGVyLWNlbGwgKm1hdEhlYWRlckNlbGxEZWY+XG4gICAgICAgICAgPHNwYW4gdHJhbnNsYXRlPlVTRVIuU1RBVFVTPC9zcGFuPlxuICAgICAgICA8L3RoPlxuICAgICAgICA8dGQgbWF0LWNlbGwgKm1hdENlbGxEZWY9XCJsZXQgcm93XCIgKGNsaWNrKT1cImZvY3VzQ29sdW1uID0gJ3N0YXR1cydcIj5cbiAgICAgICAgICA8bWF0LWZvcm0tZmllbGQ+XG4gICAgICAgICAgICA8bWF0LXNlbGVjdFxuICAgICAgICAgICAgICBbZm9ybUNvbnRyb2xdPVwicm93LnZhbGlkYXRvci5jb250cm9sc1snc3RhdHVzSWQnXVwiXG4gICAgICAgICAgICAgIFtwbGFjZWhvbGRlcl09XCInUkVGRVJFTlRJQUwuU1RBVFVTJyB8IHRyYW5zbGF0ZVwiXG4gICAgICAgICAgICA+XG4gICAgICAgICAgICAgIDxtYXQtc2VsZWN0LXRyaWdnZXI+XG4gICAgICAgICAgICAgICAgPHNwYW4gKm5nSWY9XCJyb3cudmFsaWRhdG9yLmNvbnRyb2xzWydzdGF0dXNJZCddLnZhbHVlICZndDs9MFwiPlxuICAgICAgICAgICAgICAgICAge3sgc3RhdHVzQnlJZFtyb3cudmFsaWRhdG9yLmNvbnRyb2xzWydzdGF0dXNJZCddLnZhbHVlXT8ubGFiZWwgfCB0cmFuc2xhdGUgfX1cbiAgICAgICAgICAgICAgICA8L3NwYW4+XG4gICAgICAgICAgICAgIDwvbWF0LXNlbGVjdC10cmlnZ2VyPlxuICAgICAgICAgICAgICA8bWF0LW9wdGlvbiAqbmdGb3I9XCJsZXQgaXRlbSBvZiBzdGF0dXNMaXN0XCIgW3ZhbHVlXT1cIml0ZW0uaWRcIj5cbiAgICAgICAgICAgICAgICA8bWF0LWljb24+PGlvbi1pY29uIFtuYW1lXT1cIml0ZW0uaWNvblwiPjwvaW9uLWljb24+PC9tYXQtaWNvbj5cbiAgICAgICAgICAgICAgICB7eyBpdGVtLmxhYmVsIHwgdHJhbnNsYXRlIH19XG4gICAgICAgICAgICAgIDwvbWF0LW9wdGlvbj5cbiAgICAgICAgICAgIDwvbWF0LXNlbGVjdD5cbiAgICAgICAgICAgIDxtYXQtZXJyb3IgKm5nSWY9XCJyb3cudmFsaWRhdG9yLmNvbnRyb2xzWydzdGF0dXNJZCddLmhhc0Vycm9yKCdyZXF1aXJlZCcpXCIgdHJhbnNsYXRlPlxuICAgICAgICAgICAgICBFUlJPUi5GSUVMRF9SRVFVSVJFRFxuICAgICAgICAgICAgPC9tYXQtZXJyb3I+XG4gICAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cbiAgICAgICAgPC90ZD5cbiAgICAgIDwvbmctY29udGFpbmVyPlxuXG4gICAgICA8IS0tIHVzZXJuYW1lIC0tPlxuICAgICAgPG5nLWNvbnRhaW5lciBtYXRDb2x1bW5EZWY9XCJ1c2VybmFtZVwiPlxuICAgICAgICA8dGggbWF0LWhlYWRlci1jZWxsICptYXRIZWFkZXJDZWxsRGVmIG1hdC1zb3J0LWhlYWRlcj5cbiAgICAgICAgICA8c3BhbiB0cmFuc2xhdGU+VVNFUi5VU0VSTkFNRTwvc3Bhbj5cbiAgICAgICAgPC90aD5cbiAgICAgICAgPHRkIG1hdC1jZWxsICptYXRDZWxsRGVmPVwibGV0IHJvd1wiIChjbGljayk9XCJmb2N1c0NvbHVtbiA9ICd1c2VybmFtZSdcIj5cbiAgICAgICAgICA8bWF0LWZvcm0tZmllbGQgKm5nSWY9XCJyb3cuZWRpdGluZzsgZWxzZSByZWFkb25seUNlbGxcIj5cbiAgICAgICAgICAgIDxpbnB1dFxuICAgICAgICAgICAgICBtYXRJbnB1dFxuICAgICAgICAgICAgICBbZm9ybUNvbnRyb2xdPVwicm93LnZhbGlkYXRvci5jb250cm9scy51c2VybmFtZVwiXG4gICAgICAgICAgICAgIFtwbGFjZWhvbGRlcl09XCInVVNFUi5VU0VSTkFNRScgfCB0cmFuc2xhdGVcIlxuICAgICAgICAgICAgICBbcmVhZG9ubHldPVwiIXJvdy5lZGl0aW5nXCJcbiAgICAgICAgICAgICAgW2FwcEF1dG9mb2N1c109XCJyb3cuZWRpdGluZyAmJiBmb2N1c0NvbHVtbiA9PT0gJ3VzZXJuYW1lJ1wiXG4gICAgICAgICAgICAvPlxuICAgICAgICAgICAgPG1hdC1lcnJvciAqbmdJZj1cInJvdy52YWxpZGF0b3IuY29udHJvbHMudXNlcm5hbWUuaGFzRXJyb3IoJ3JlcXVpcmVkJylcIiB0cmFuc2xhdGU+XG4gICAgICAgICAgICAgIEVSUk9SLkZJRUxEX1JFUVVJUkVEXG4gICAgICAgICAgICA8L21hdC1lcnJvcj5cbiAgICAgICAgICA8L21hdC1mb3JtLWZpZWxkPlxuICAgICAgICAgIDxuZy10ZW1wbGF0ZSAjcmVhZG9ubHlDZWxsPlxuICAgICAgICAgICAgPGlvbi1sYWJlbCBhcHBBdXRvVGl0bGU+XG4gICAgICAgICAgICAgIHt7IHJvdy52YWxpZGF0b3IgfCBmb3JtR2V0VmFsdWU6ICd1c2VybmFtZScgfX1cbiAgICAgICAgICAgIDwvaW9uLWxhYmVsPlxuICAgICAgICAgIDwvbmctdGVtcGxhdGU+XG4gICAgICAgIDwvdGQ+XG4gICAgICA8L25nLWNvbnRhaW5lcj5cblxuICAgICAgPCEtLSB1c2VybmFtZSBleHRyYW5ldCAtLT5cbiAgICAgIDxuZy1jb250YWluZXIgbWF0Q29sdW1uRGVmPVwidXNlcm5hbWVFeHRyYW5ldFwiPlxuICAgICAgICA8dGggbWF0LWhlYWRlci1jZWxsICptYXRIZWFkZXJDZWxsRGVmIG1hdC1zb3J0LWhlYWRlcj5cbiAgICAgICAgICA8c3BhbiB0cmFuc2xhdGU+VVNFUi5VU0VSTkFNRV9FWFRSQU5FVDwvc3Bhbj5cbiAgICAgICAgPC90aD5cbiAgICAgICAgPHRkIG1hdC1jZWxsICptYXRDZWxsRGVmPVwibGV0IHJvd1wiIChjbGljayk9XCJmb2N1c0NvbHVtbiA9ICd1c2VybmFtZUV4dHJhbmV0J1wiPlxuICAgICAgICAgIDxtYXQtZm9ybS1maWVsZCAqbmdJZj1cInJvdy5lZGl0aW5nOyBlbHNlIHJlYWRvbmx5Q2VsbFwiPlxuICAgICAgICAgICAgPGlucHV0XG4gICAgICAgICAgICAgIG1hdElucHV0XG4gICAgICAgICAgICAgIFtmb3JtQ29udHJvbF09XCJyb3cudmFsaWRhdG9yLmNvbnRyb2xzLnVzZXJuYW1lRXh0cmFuZXRcIlxuICAgICAgICAgICAgICBbcGxhY2Vob2xkZXJdPVwiJ1VTRVIuVVNFUk5BTUVfRVhUUkFORVQnIHwgdHJhbnNsYXRlXCJcbiAgICAgICAgICAgICAgW3JlYWRvbmx5XT1cIiFyb3cuZWRpdGluZ1wiXG4gICAgICAgICAgICAgIFthcHBBdXRvZm9jdXNdPVwicm93LmVkaXRpbmcgJiYgZm9jdXNDb2x1bW4gPT09ICd1c2VybmFtZUV4dHJhbmV0J1wiXG4gICAgICAgICAgICAvPlxuICAgICAgICAgICAgPG1hdC1lcnJvciAqbmdJZj1cInJvdy52YWxpZGF0b3IuY29udHJvbHMudXNlcm5hbWVFeHRyYW5ldC5oYXNFcnJvcigncmVxdWlyZWQnKVwiIHRyYW5zbGF0ZT5cbiAgICAgICAgICAgICAgRVJST1IuRklFTERfUkVRVUlSRURcbiAgICAgICAgICAgIDwvbWF0LWVycm9yPlxuICAgICAgICAgIDwvbWF0LWZvcm0tZmllbGQ+XG4gICAgICAgICAgPG5nLXRlbXBsYXRlICNyZWFkb25seUNlbGw+XG4gICAgICAgICAgICA8aW9uLWxhYmVsIGFwcEF1dG9UaXRsZT5cbiAgICAgICAgICAgICAge3sgcm93LnZhbGlkYXRvciB8IGZvcm1HZXRWYWx1ZTogJ3VzZXJuYW1lRXh0cmFuZXQnIH19XG4gICAgICAgICAgICA8L2lvbi1sYWJlbD5cbiAgICAgICAgICA8L25nLXRlbXBsYXRlPlxuICAgICAgICA8L3RkPlxuICAgICAgPC9uZy1jb250YWluZXI+XG5cbiAgICAgIDwhLS0gcHVia2V5ICAtLT5cbiAgICAgIDxuZy1jb250YWluZXIgbWF0Q29sdW1uRGVmPVwicHVia2V5XCI+XG4gICAgICAgIDx0aCBtYXQtaGVhZGVyLWNlbGwgKm1hdEhlYWRlckNlbGxEZWYgbWF0LXNvcnQtaGVhZGVyPlxuICAgICAgICAgIDxzcGFuIHRyYW5zbGF0ZT5VU0VSLlBVQktFWTwvc3Bhbj5cbiAgICAgICAgPC90aD5cbiAgICAgICAgPHRkXG4gICAgICAgICAgbWF0LWNlbGxcbiAgICAgICAgICAqbWF0Q2VsbERlZj1cImxldCByb3dcIlxuICAgICAgICAgIFt0aXRsZV09XCJyb3cudmFsaWRhdG9yLmNvbnRyb2xzLnB1YmtleS52YWx1ZUNoYW5nZXMgfCBhc3luY1wiXG4gICAgICAgICAgKGNsaWNrKT1cImZvY3VzQ29sdW1uID0gJ3B1YmtleSdcIlxuICAgICAgICA+XG4gICAgICAgICAgPG1hdC1mb3JtLWZpZWxkICpuZ0lmPVwicm93LmVkaXRpbmc7IGVsc2UgcmVhZG9ubHlDZWxsXCI+XG4gICAgICAgICAgICA8aW5wdXRcbiAgICAgICAgICAgICAgbWF0SW5wdXRcbiAgICAgICAgICAgICAgW2Zvcm1Db250cm9sXT1cInJvdy52YWxpZGF0b3IuY29udHJvbHNbJ3B1YmtleSddXCJcbiAgICAgICAgICAgICAgW3BsYWNlaG9sZGVyXT1cIidVU0VSLlBVQktFWScgfCB0cmFuc2xhdGVcIlxuICAgICAgICAgICAgICBbcmVhZG9ubHldPVwiIXJvdy5lZGl0aW5nXCJcbiAgICAgICAgICAgICAgYXV0b2NvbXBsZXRlPVwib2ZmXCJcbiAgICAgICAgICAgIC8+XG4gICAgICAgICAgICA8bWF0LWVycm9yICpuZ0lmPVwicm93LnZhbGlkYXRvci5jb250cm9scy5wdWJrZXkuaGFzRXJyb3IoJ3JlcXVpcmVkJylcIiB0cmFuc2xhdGU+XG4gICAgICAgICAgICAgIEVSUk9SLkZJRUxEX1JFUVVJUkVEXG4gICAgICAgICAgICA8L21hdC1lcnJvcj5cbiAgICAgICAgICAgIDxtYXQtZXJyb3IgKm5nSWY9XCJyb3cudmFsaWRhdG9yLmNvbnRyb2xzLnB1YmtleS5oYXNFcnJvcigncHVia2V5JylcIj5cbiAgICAgICAgICAgICAgPHNwYW4gdHJhbnNsYXRlPkVSUk9SLkZJRUxEX05PVF9WQUxJRF9QVUJLRVk8L3NwYW4+XG4gICAgICAgICAgICA8L21hdC1lcnJvcj5cbiAgICAgICAgICA8L21hdC1mb3JtLWZpZWxkPlxuICAgICAgICAgIDxuZy10ZW1wbGF0ZSAjcmVhZG9ubHlDZWxsPlxuICAgICAgICAgICAgPGlvbi1sYWJlbCBhcHBBdXRvVGl0bGU+XG4gICAgICAgICAgICAgIHt7IHJvdy52YWxpZGF0b3IgfCBmb3JtR2V0VmFsdWU6ICdwdWJrZXknIH19XG4gICAgICAgICAgICA8L2lvbi1sYWJlbD5cbiAgICAgICAgICA8L25nLXRlbXBsYXRlPlxuICAgICAgICA8L3RkPlxuICAgICAgPC9uZy1jb250YWluZXI+XG5cbiAgICAgIDwhLS0gQ3JlYXRpb24gZGF0ZSBjb2x1bW4gLS0+XG4gICAgICA8bmctY29udGFpbmVyIG1hdENvbHVtbkRlZj1cImNyZWF0aW9uRGF0ZVwiPlxuICAgICAgICA8dGggbWF0LWhlYWRlci1jZWxsICptYXRIZWFkZXJDZWxsRGVmIG1hdC1zb3J0LWhlYWRlcj5cbiAgICAgICAgICA8aW9uLWxhYmVsIHRyYW5zbGF0ZT5VU0VSLkNSRUFUSU9OX0RBVEU8L2lvbi1sYWJlbD5cbiAgICAgICAgPC90aD5cbiAgICAgICAgPHRkIG1hdC1jZWxsICptYXRDZWxsRGVmPVwibGV0IHJvd1wiIGNsYXNzPVwibWF0LWZvcm0tZmllbGQtZGlzYWJsZWRcIj5cbiAgICAgICAgICA8aW9uLXRleHQgY2xhc3M9XCJpb24tdGV4dC1lbmRcIiBjb2xvcj1cIm1lZGl1bVwiICpuZ0lmPVwicm93LmlkICE9PSAtMVwiPlxuICAgICAgICAgICAge3sgcm93LmN1cnJlbnREYXRhLmNyZWF0aW9uRGF0ZSB8IGRhdGVGb3JtYXQ6IHsgdGltZTogdHJ1ZSB9IH19XG4gICAgICAgICAgPC9pb24tdGV4dD5cbiAgICAgICAgPC90ZD5cbiAgICAgIDwvbmctY29udGFpbmVyPlxuXG4gICAgICA8IS0tIFVwZGF0ZSBkYXRlIGNvbHVtbiAtLT5cbiAgICAgIDxuZy1jb250YWluZXIgbWF0Q29sdW1uRGVmPVwidXBkYXRlRGF0ZVwiPlxuICAgICAgICA8dGggbWF0LWhlYWRlci1jZWxsICptYXRIZWFkZXJDZWxsRGVmIG1hdC1zb3J0LWhlYWRlcj5cbiAgICAgICAgICA8aW9uLWxhYmVsIHRyYW5zbGF0ZT5VU0VSLlVQREFURV9EQVRFPC9pb24tbGFiZWw+XG4gICAgICAgIDwvdGg+XG4gICAgICAgIDx0ZCBtYXQtY2VsbCAqbWF0Q2VsbERlZj1cImxldCByb3dcIiBjbGFzcz1cIm1hdC1mb3JtLWZpZWxkLWRpc2FibGVkXCI+XG4gICAgICAgICAgPGlvbi10ZXh0IGNsYXNzPVwiaW9uLXRleHQtZW5kXCIgY29sb3I9XCJtZWRpdW1cIiAqbmdJZj1cInJvdy5pZCAhPT0gLTFcIj5cbiAgICAgICAgICAgIHt7IHJvdy5jdXJyZW50RGF0YS51cGRhdGVEYXRlIHwgZGF0ZUZvcm1hdDogeyB0aW1lOiB0cnVlIH0gfX1cbiAgICAgICAgICA8L2lvbi10ZXh0PlxuICAgICAgICA8L3RkPlxuICAgICAgPC9uZy1jb250YWluZXI+XG5cbiAgICAgIDwhLS0gQWN0aW9ucyBidXR0b25zIGNvbHVtbiAtLT5cbiAgICAgIDxhcHAtYWN0aW9ucy1jb2x1bW5cbiAgICAgICAgW3N0aWNreUVuZF09XCJzdGlja3lFbmRcIlxuICAgICAgICAoY2FuY2VsT3JEZWxldGVDbGljayk9XCJjYW5jZWxPckRlbGV0ZSgkZXZlbnQuZXZlbnQsICRldmVudC5yb3cpXCJcbiAgICAgICAgKGNvbmZpcm1FZGl0Q3JlYXRlQ2xpY2spPVwiY29uZmlybUVkaXRDcmVhdGUoJGV2ZW50LmV2ZW50LCAkZXZlbnQucm93KVwiXG4gICAgICAgIChjb25maXJtQW5kQWRkQ2xpY2spPVwiY29uZmlybUFuZEFkZCgkZXZlbnQuZXZlbnQsICRldmVudC5yb3cpXCJcbiAgICAgICAgKGJhY2t3YXJkKT1cImNvbmZpcm1BbmRCYWNrd2FyZCgkZXZlbnQuZXZlbnQsICRldmVudC5yb3cpXCJcbiAgICAgICAgKGZvcndhcmQpPVwiY29uZmlybUFuZEZvcndhcmQoJGV2ZW50LmV2ZW50LCAkZXZlbnQucm93KVwiXG4gICAgICAgIFtjYW5DYW5jZWxdPVwiZmFsc2VcIlxuICAgICAgPlxuICAgICAgICA8IS0tIHRhYmxlIG9wdGlvbnMgbWVudSAtLT5cbiAgICAgICAgPGJ1dHRvblxuICAgICAgICAgIG1hdEhlYWRlclxuICAgICAgICAgIG1hdC1pY29uLWJ1dHRvblxuICAgICAgICAgIFt0aXRsZV09XCInQ09NTU9OLkJUTl9PUFRJT05TJyB8IHRyYW5zbGF0ZVwiXG4gICAgICAgICAgW21hdE1lbnVUcmlnZ2VyRm9yXT1cInRhYmxlT3B0aW9uc01lbnVcIlxuICAgICAgICA+XG4gICAgICAgICAgPG1hdC1pY29uPm1vcmVfdmVydDwvbWF0LWljb24+XG4gICAgICAgIDwvYnV0dG9uPlxuICAgICAgPC9hcHAtYWN0aW9ucy1jb2x1bW4+XG5cbiAgICAgIDx0ciBtYXQtaGVhZGVyLXJvdyAqbWF0SGVhZGVyUm93RGVmPVwiZGlzcGxheWVkQ29sdW1uczsgc3RpY2t5OiB0cnVlXCI+PC90cj5cbiAgICAgIDx0clxuICAgICAgICBtYXQtcm93XG4gICAgICAgICptYXRSb3dEZWY9XCJsZXQgcm93OyBjb2x1bW5zOiBkaXNwbGF5ZWRDb2x1bW5zXCJcbiAgICAgICAgW2NsYXNzLm1hdC1yb3ctc2VsZWN0ZWRdPVwicm93LmVkaXRpbmdcIlxuICAgICAgICBbY2xhc3MubWF0LXJvdy1lcnJvcl09XCJyb3cudmFsaWRhdG9yLmludmFsaWRcIlxuICAgICAgICBbY2xhc3MubWF0LXJvdy1kaXJ0eV09XCJyb3cuY3VycmVudERhdGEuZGlydHlcIlxuICAgICAgICBbY2xhc3MubWF0LXJvdy1kaXNhYmxlZF09XCIhcm93LmVkaXRpbmdcIlxuICAgICAgICAoY2xpY2spPVwiY2xpY2tSb3coJGV2ZW50LCByb3cpXCJcbiAgICAgICAgKGtleWRvd24uZXNjYXBlKT1cImVzY2FwZUVkaXRpbmdSb3coJGV2ZW50KVwiXG4gICAgICAgIFtjZGtUcmFwRm9jdXNdPVwiIXJvdy52YWxpZGF0b3I/LnZhbGlkXCJcbiAgICAgID48L3RyPlxuICAgIDwvdGFibGU+XG5cbiAgICA8IS0tIETDqWNsZW5jaGV1ciBpbnZpc2libGUgcG91ciBsZSBtYXQtbWVudSAtLT5cblxuICAgIEBpZiAobG9hZGluZ1N1YmplY3QgfCBhc3luYykge1xuICAgICAgPGlvbi1pdGVtPlxuICAgICAgICA8aW9uLXNrZWxldG9uLXRleHQgYW5pbWF0ZWQ+PC9pb24tc2tlbGV0b24tdGV4dD5cbiAgICAgIDwvaW9uLWl0ZW0+XG4gICAgfSBAZWxzZSBpZiAodG90YWxSb3dDb3VudCA9PT0gMCkge1xuICAgICAgPGlvbi1pdGVtPlxuICAgICAgICA8aW9uLXRleHQgY29sb3I9XCJkYW5nZXJcIiBjbGFzcz1cInRleHQtaXRhbGljXCIgdHJhbnNsYXRlPkNPTU1PTi5OT19SRVNVTFQ8L2lvbi10ZXh0PlxuICAgICAgPC9pb24taXRlbT5cbiAgICB9XG4gIDwvZGl2PlxuPC9pb24tY29udGVudD5cblxuPCEtLSBUYWJsZSBvcHRpb25zIG1lbnUgLS0+XG48bWF0LW1lbnUgI3RhYmxlT3B0aW9uc01lbnU9XCJtYXRNZW51XCIgeFBvc2l0aW9uPVwiYWZ0ZXJcIj5cbiAgPCEtLSBkaXNwbGF5IGNvbHVtbnMgLS0+XG4gIDxidXR0b24gbWF0LW1lbnUtaXRlbSAoY2xpY2spPVwib3BlblNlbGVjdENvbHVtbnNNb2RhbCgkZXZlbnQpXCI+XG4gICAgPG1hdC1pY29uPnZpZXdfY29sdW1uPC9tYXQtaWNvbj5cbiAgICA8aW9uLWxhYmVsIHRyYW5zbGF0ZT5DT01NT04uRElTUExBWUVEX0NPTFVNTlNfRE9UUzwvaW9uLWxhYmVsPlxuICA8L2J1dHRvbj5cblxuICBAaWYgKHVzZVBhZ2VTZXR0aW5ncykge1xuICAgIDxtYXQtZGl2aWRlcj48L21hdC1kaXZpZGVyPlxuXG4gICAgPCEtLSBDb21wYWN0IG1vZGUgLS0+XG4gICAgPGJ1dHRvbiBtYXQtbWVudS1pdGVtIChjbGljayk9XCJ0b2dnbGVDb21wYWN0TW9kZSgpXCI+XG4gICAgICA8bWF0LWljb24+e3sgY29tcGFjdCA/ICdjaGVja19ib3gnIDogJ2NoZWNrX2JveF9vdXRsaW5lX2JsYW5rJyB9fTwvbWF0LWljb24+XG4gICAgICA8aW9uLWxhYmVsIHRyYW5zbGF0ZT5DT01NT04uQlROX0NPTVBBQ1RfUk9XUzwvaW9uLWxhYmVsPlxuICAgIDwvYnV0dG9uPlxuICB9XG48L21hdC1tZW51PlxuXG48aW9uLWZvb3Rlcj5cbiAgPG1hdC1wYWdpbmF0b3JcbiAgICBbbGVuZ3RoXT1cInRvdGFsUm93Q291bnRcIlxuICAgIFtwYWdlU2l6ZV09XCJkZWZhdWx0UGFnZVNpemVcIlxuICAgIFtwYWdlU2l6ZU9wdGlvbnNdPVwiZGVmYXVsdFBhZ2VTaXplT3B0aW9uc1wiXG4gICAgc2hvd0ZpcnN0TGFzdEJ1dHRvbnNcbiAgPjwvbWF0LXBhZ2luYXRvcj5cblxuICA8YXBwLWZvcm0tYnV0dG9ucy1iYXJcbiAgICAqbmdJZj1cIiFtb2JpbGUgJiYgY2FuRWRpdFwiXG4gICAgKG9uQ2FuY2VsKT1cImNhbmNlbCgkZXZlbnQpXCJcbiAgICAob25TYXZlKT1cInNhdmUoKVwiXG4gICAgW2Rpc2FibGVkXT1cIihsb2FkaW5nU3ViamVjdCB8IGFzeW5jKSA9PT0gdHJ1ZSB8fCAoZGlydHlTdWJqZWN0IHwgYXN5bmMpICE9PSB0cnVlXCJcbiAgPlxuICAgIDwhLS0gZXJyb3IgLS0+XG4gICAgPGlvbi1pdGVtICpuZ0lmPVwiZXJyb3JTdWJqZWN0IHwgYXN5bmM7IGxldCBlcnJvclwiIGxpbmVzPVwibm9uZVwiPlxuICAgICAgPGlvbi1pY29uIGNvbG9yPVwiZGFuZ2VyXCIgc2xvdD1cInN0YXJ0XCIgbmFtZT1cImFsZXJ0LWNpcmNsZVwiPjwvaW9uLWljb24+XG4gICAgICA8aW9uLWxhYmVsIGNvbG9yPVwiZGFuZ2VyXCIgW2lubmVySFRNTF09XCJlcnJvciB8IHRyYW5zbGF0ZVwiPjwvaW9uLWxhYmVsPlxuICAgIDwvaW9uLWl0ZW0+XG4gIDwvYXBwLWZvcm0tYnV0dG9ucy1iYXI+XG48L2lvbi1mb290ZXI+XG5cbjxpb24tZmFiIHNsb3Q9XCJmaXhlZFwiIHZlcnRpY2FsPVwiYm90dG9tXCIgaG9yaXpvbnRhbD1cImVuZFwiICpuZ0lmPVwibW9iaWxlXCI+XG4gIDxpb24tZmFiLWJ1dHRvbiBjb2xvcj1cInRlcnRpYXJ5XCIgKGNsaWNrKT1cImFkZFJvdygpXCI+XG4gICAgPGlvbi1pY29uIG5hbWU9XCJhZGRcIj48L2lvbi1pY29uPlxuICA8L2lvbi1mYWItYnV0dG9uPlxuPC9pb24tZmFiPlxuIl19
|
|
399
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXNlcnMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBwL2FkbWluL3VzZXJzL3VzZXJzLnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vc3JjL2FwcC9hZG1pbi91c2Vycy91c2Vycy5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSx1QkFBdUIsRUFBRSxTQUFTLEVBQUUsTUFBTSxFQUFZLEtBQUssRUFBVSxTQUFTLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDakksT0FBTyxFQUFFLE1BQU0sRUFBRSx1QkFBdUIsRUFBRSxNQUFNLHdDQUF3QyxDQUFDO0FBQ3pGLE9BQU8sRUFBRSxjQUFjLEVBQUUsVUFBVSxFQUFFLFVBQVUsRUFBRSxNQUFNLDZDQUE2QyxDQUFDO0FBRXJHLE9BQU8sRUFBRSxzQkFBc0IsRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBRzVELE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSw4QkFBOEIsQ0FBQztBQUN4RCxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUM1RCxPQUFPLEVBQXVCLHdCQUF3QixFQUFFLE1BQU0sK0JBQStCLENBQUM7QUFDOUYsT0FBTyxFQUFFLFlBQVksRUFBRSx1QkFBdUIsRUFBRSxNQUFNLEVBQUUsR0FBRyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDcEYsT0FBTyxFQUFFLHVCQUF1QixFQUFFLE1BQU0sa0RBQWtELENBQUM7QUFDM0YsT0FBTyxFQUFFLGlCQUFpQixFQUFFLFlBQVksRUFBRSxRQUFRLEVBQUUsZUFBZSxFQUFFLFNBQVMsRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBQy9HLE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSx5Q0FBeUMsQ0FBQztBQUN0RSxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFFL0MsT0FBTyxFQUFFLG1CQUFtQixFQUFFLE1BQU0sd0NB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LGFBR2hCLENBQUMsRUFBRSxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsV0FBVyxFQUFFLHNCQUFzQixFQUFFLENBQUMsY0FDbkUsQ0FBQyxvQkFBb0IsQ0FBQyxtQkFDakIsdUJBQXVCLENBQUMsTUFBTTs7MEJBbUQ1QyxNQUFNOzJCQUFDLFdBQVc7eUNBZm1CLE9BQU87c0JBQTlDLEtBQUs7dUJBQUMsRUFBRSxTQUFTLEVBQUUsZ0JBQWdCLEVBQUU7Z0JBQ0UsZUFBZTtzQkFBdEQsS0FBSzt1QkFBQyxFQUFFLFNBQVMsRUFBRSxnQkFBZ0IsRUFBRTtnQkFDRSxNQUFNO3NCQUE3QyxLQUFLO3VCQUFDLEVBQUUsU0FBUyxFQUFFLGdCQUFnQixFQUFFO2dCQUNFLFNBQVM7c0JBQWhELEtBQUs7dUJBQUMsRUFBRSxTQUFTLEVBQUUsZ0JBQWdCLEVBQUU7Z0JBQ0UsV0FBVztzQkFBbEQsS0FBSzt1QkFBQyxFQUFFLFNBQVMsRUFBRSxnQkFBZ0IsRUFBRTtnQkFxRlUsb0JBQW9CO3NCQUFuRSxTQUFTO3VCQUFDLGlCQUFpQixFQUFFLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IGJvb2xlYW5BdHRyaWJ1dGUsIENoYW5nZURldGVjdGlvblN0cmF0ZWd5LCBDb21wb25lbnQsIEluamVjdCwgSW5qZWN0b3IsIElucHV0LCBPbkluaXQsIFZpZXdDaGlsZCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgUGVyc29uLCBQUklPUklUSVpFRF9BVVRIT1JJVElFUyB9IGZyb20gJy4uLy4uL2NvcmUvc2VydmljZXMvbW9kZWwvcGVyc29uLm1vZGVsJztcbmltcG9ydCB7IFJlZmVyZW50aWFsUmVmLCBTdGF0dXNCeUlkLCBTdGF0dXNMaXN0IH0gZnJvbSAnLi4vLi4vY29yZS9zZXJ2aWNlcy9tb2RlbC9yZWZlcmVudGlhbC5tb2RlbCc7XG5pbXBvcnQgeyBQZXJzb25TZXJ2aWNlIH0gZnJvbSAnLi9wZXJzb24uc2VydmljZSc7XG5pbXBvcnQgeyBQZXJzb25WYWxpZGF0b3JTZXJ2aWNlIH0gZnJvbSAnLi9wZXJzb24udmFsaWRhdG9yJztcbmltcG9ydCB7IEFjY291bnRTZXJ2aWNlIH0gZnJvbSAnLi4vLi4vY29yZS9zZXJ2aWNlcy9hY2NvdW50LnNlcnZpY2UnO1xuaW1wb3J0IHsgQWJzdHJhY3RDb250cm9sLCBVbnR5cGVkRm9ybUJ1aWxkZXIsIFVudHlwZWRGb3JtR3JvdXAgfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XG5pbXBvcnQgeyBBcHBUYWJsZSB9IGZyb20gJy4uLy4uL2NvcmUvdGFibGUvdGFibGUuY2xhc3MnO1xuaW1wb3J0IHsgVmFsaWRhdG9yU2VydmljZSB9IGZyb20gJ0BlLWlzL25neC1tYXRlcmlhbC10YWJsZSc7XG5pbXBvcnQgeyBGb3JtRmllbGREZWZpbml0aW9uLCBGb3JtRmllbGREZWZpbml0aW9uVXRpbHMgfSBmcm9tICcuLi8uLi9zaGFyZWQvZm9ybS9maWVsZC5tb2RlbCc7XG5pbXBvcnQgeyBkZWJvdW5jZVRpbWUsIGRpc3RpbmN0VW50aWxLZXlDaGFuZ2VkLCBmaWx0ZXIsIHRhcCB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcbmltcG9ydCB7IEVudGl0aWVzVGFibGVEYXRhU291cmNlIH0gZnJvbSAnLi4vLi4vY29yZS90YWJsZS9lbnRpdGllcy10YWJsZS1kYXRhc291cmNlLmNsYXNzJztcbmltcG9ydCB7IGdldFByb3BlcnR5QnlQYXRoLCBpc05pbE9yQmxhbmssIGlzTm90TmlsLCBpc05vdE5pbE9yQmxhbmssIHRvQm9vbGVhbiB9IGZyb20gJy4uLy4uL3NoYXJlZC9mdW5jdGlvbnMnO1xuaW1wb3J0IHsgRU5WSVJPTk1FTlQgfSBmcm9tICcuLi8uLi8uLi9lbnZpcm9ubWVudHMvZW52aXJvbm1lbnQuY2xhc3MnO1xuaW1wb3J0IHsgUGVyc29uRmlsdGVyIH0gZnJvbSAnLi9wZXJzb24uZmlsdGVyJztcbmltcG9ydCB7IENvbmZpZ1NlcnZpY2UgfSBmcm9tICcuLi8uLi9jb3JlL3NlcnZpY2VzL2NvbmZpZy5zZXJ2aWNlJztcbmltcG9ydCB7IENPUkVfQ09ORklHX09QVElPTlMgfSBmcm9tICcuLi8uLi9jb3JlL3NlcnZpY2VzL2NvbmZpZy9jb3JlLmNvbmZpZyc7XG5pbXBvcnQgeyBBdXRoVG9rZW5UeXBlIH0gZnJvbSAnLi4vLi4vY29yZS9zZXJ2aWNlcy9uZXR3b3JrLnR5cGVzJztcbmltcG9ydCB7IE1hdEV4cGFuc2lvblBhbmVsIH0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvZXhwYW5zaW9uJztcbmltcG9ydCB7IHNsaWRlVXBEb3duQW5pbWF0aW9uIH0gZnJvbSAnLi4vLi4vc2hhcmVkL21hdGVyaWFsL21hdGVyaWFsLmFuaW1hdGlvbnMnO1xuaW1wb3J0IHsgTWVzc2FnZSB9IGZyb20gJy4uLy4uL3NvY2lhbC9tZXNzYWdlL21lc3NhZ2UubW9kZWwnO1xuaW1wb3J0IHsgTWVzc2FnZVNlcnZpY2UgfSBmcm9tICcuLi8uLi9zb2NpYWwvbWVzc2FnZS9tZXNzYWdlLnNlcnZpY2UnO1xuaW1wb3J0IHsgUkVTRVJWRURfRU5EX0NPTFVNTlMsIFJFU0VSVkVEX1NUQVJUX0NPTFVNTlMsIFRBQkxFX1NFVFRJTkdTX0VOVU0gfSBmcm9tICcuLi8uLi9jb3JlL3RhYmxlL3RhYmxlLm1vZGVsJztcbmltcG9ydCB7IE1lbnVTZXJ2aWNlIH0gZnJvbSAnLi4vLi4vY29yZS9tZW51L21lbnUuc2VydmljZSc7XG5pbXBvcnQgeyBDc3ZVdGlscyB9IGZyb20gJy4uLy4uL3NoYXJlZC9maWxlL2Nzdi51dGlscyc7XG5pbXBvcnQgeyBmcm9tRGF0ZUlTT1N0cmluZyB9IGZyb20gJy4uLy4uL3NoYXJlZC9kYXRlcyc7XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ2FwcC11c2Vycy10YWJsZScsXG4gIHRlbXBsYXRlVXJsOiAndXNlcnMuaHRtbCcsXG4gIHN0eWxlVXJsczogWycuL3VzZXJzLnNjc3MnXSxcbiAgcHJvdmlkZXJzOiBbeyBwcm92aWRlOiBWYWxpZGF0b3JTZXJ2aWNlLCB1c2VFeGlzdGluZzogUGVyc29uVmFsaWRhdG9yU2VydmljZSB9XSxcbiAgYW5pbWF0aW9uczogW3NsaWRlVXBEb3duQW5pbWF0aW9uXSxcbiAgY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2gsXG59KVxuZXhwb3J0IGNsYXNzIFVzZXJzUGFnZSBleHRlbmRzIEFwcFRhYmxlPFBlcnNvbiwgUGVyc29uRmlsdGVyPiBpbXBsZW1lbnRzIE9uSW5pdCB7XG4gIHJlYWRvbmx5IGNhbkVkaXQ6IGJvb2xlYW47XG4gIHJlYWRvbmx5IGNhblNlbmRNZXNzYWdlOiBib29sZWFuO1xuICByZWFkb25seSBmaWx0ZXJGb3JtOiBVbnR5cGVkRm9ybUdyb3VwO1xuICByZWFkb25seSBwcm9maWxlcyA9IFsuLi5QUklPUklUSVpFRF9BVVRIT1JJVElFU10ucmV2ZXJzZSgpO1xuICByZWFkb25seSBzdGF0dXNMaXN0ID0gU3RhdHVzTGlzdDtcbiAgcmVhZG9ubHkgc3RhdHVzQnlJZCA9IFN0YXR1c0J5SWQ7XG4gIHJlYWRvbmx5IHVzZXJQcm9maWxlTGlzdDogUmVmZXJlbnRpYWxSZWZbXSA9IFBSSU9SSVRJWkVEX0FVVEhPUklUSUVTLm1hcCgobGFiZWwpID0+XG4gICAgUmVmZXJlbnRpYWxSZWYuZnJvbU9iamVjdCh7XG4gICAgICBsYWJlbCxcbiAgICAgIG5hbWU6IGBVU0VSLlBST0ZJTEVfRU5VTS4ke2xhYmVsfWAsXG4gICAgfSlcbiAgKTtcblxuICBwcm90ZWN0ZWQgYWRkaXRpb25hbEZpZWxkczogRm9ybUZpZWxkRGVmaW5pdGlvbltdO1xuICBwcm90ZWN0ZWQgZmlsdGVyQ3JpdGVyaWFDb3VudCA9IDA7XG4gIHByb3RlY3RlZCBkZWZhdWx0Q29tcGFjdCA9IGZhbHNlO1xuXG4gIHNldCBzaG93VXNlcm5hbWVDb2x1bW4odmFsdWU6IGJvb2xlYW4pIHtcbiAgICB0aGlzLnNldFNob3dDb2x1bW4oJ3VzZXJuYW1lJywgdmFsdWUpO1xuICB9XG5cbiAgZ2V0IHNob3dVc2VybmFtZUNvbHVtbigpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5nZXRTaG93Q29sdW1uKCd1c2VybmFtZScpO1xuICB9XG5cbiAgc2V0IHNob3dVc2VybmFtZUV4dHJhbmV0Q29sdW1uKHZhbHVlOiBib29sZWFuKSB7XG4gICAgdGhpcy5zZXRTaG93Q29sdW1uKCd1c2VybmFtZUV4dHJhbmV0JywgdmFsdWUpO1xuICB9XG5cbiAgZ2V0IHNob3dVc2VybmFtZUV4dHJhbmV0Q29sdW1uKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLmdldFNob3dDb2x1bW4oJ3VzZXJuYW1lRXh0cmFuZXQnKTtcbiAgfVxuXG4gIEBJbnB1dCh7IHRyYW5zZm9ybTogYm9vbGVhbkF0dHJpYnV0ZSB9KSBjb21wYWN0OiBib29sZWFuID0gbnVsbDtcbiAgQElucHV0KHsgdHJhbnNmb3JtOiBib29sZWFuQXR0cmlidXRlIH0pIHVzZVBhZ2VTZXR0aW5ncyA9IHRydWU7XG4gIEBJbnB1dCh7IHRyYW5zZm9ybTogYm9vbGVhbkF0dHJpYnV0ZSB9KSBzdGlja3kgPSBmYWxzZTtcbiAgQElucHV0KHsgdHJhbnNmb3JtOiBib29sZWFuQXR0cmlidXRlIH0pIHN0aWNreUVuZCA9IGZhbHNlO1xuICBASW5wdXQoeyB0cmFuc2Zvcm06IGJvb2xlYW5BdHRyaWJ1dGUgfSkgY2FuRG93bmxvYWQgPSB0cnVlO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIGluamVjdG9yOiBJbmplY3RvcixcbiAgICBmb3JtQnVpbGRlcjogVW50eXBlZEZvcm1CdWlsZGVyLFxuICAgIHByb3RlY3RlZCBhY2NvdW50U2VydmljZTogQWNjb3VudFNlcnZpY2UsXG4gICAgcHJvdGVjdGVkIHZhbGlkYXRvclNlcnZpY2U6IFZhbGlkYXRvclNlcnZpY2UsXG4gICAgcHJvdGVjdGVkIGNvbmZpZ1NlcnZpY2U6IENvbmZpZ1NlcnZpY2UsXG4gICAgcHJvdGVjdGVkIGRhdGFTZXJ2aWNlOiBQZXJzb25TZXJ2aWNlLFxuICAgIHByb3RlY3RlZCBtZXNzYWdlU2VydmljZTogTWVzc2FnZVNlcnZpY2UsXG4gICAgcHJvdGVjdGVkIG1lbnVTZXJ2aWNlOiBNZW51U2VydmljZSxcbiAgICBASW5qZWN0KEVOVklST05NRU5UKSBlbnZpcm9ubWVudFxuICApIHtcbiAgICBzdXBlcihcbiAgICAgIGluamVjdG9yLFxuICAgICAgUkVTRVJWRURfU1RBUlRfQ09MVU1OUy5jb25jYXQoWydhdmF0YXInLCAnbGFzdE5hbWUnLCAnZmlyc3ROYW1lJywgJ2VtYWlsJywgJ3Byb2ZpbGUnLCAnc3RhdHVzJywgJ3VzZXJuYW1lJywgJ3VzZXJuYW1lRXh0cmFuZXQnLCAncHVia2V5J10pXG4gICAgICAgIC5jb25jYXQoYWNjb3VudFNlcnZpY2UuYWRkaXRpb25hbEZpZWxkcy5tYXAoKGZpZWxkKSA9PiBmaWVsZC5rZXkpKVxuICAgICAgICAuY29uY2F0KFsnY3JlYXRpb25EYXRlJywgJ3VwZGF0ZURhdGUnXSlcbiAgICAgICAgLmNvbmNhdChSRVNFUlZFRF9FTkRfQ09MVU1OUyksXG4gICAgICBuZXcgRW50aXRpZXNUYWJsZURhdGFTb3VyY2UoUGVyc29uLCBkYXRhU2VydmljZSwgdmFsaWRhdG9yU2VydmljZSwge1xuICAgICAgICBwcmVwZW5kTmV3RWxlbWVudHM6IGZhbHNlLFxuICAgICAgICBzdXBwcmVzc0Vycm9yczogZW52aXJvbm1lbnQucHJvZHVjdGlvbixcbiAgICAgICAgc2F2ZU9ubHlEaXJ0eVJvd3M6IHRydWUsXG4gICAgICB9KSxcbiAgICAgIG51bGxcbiAgICApO1xuXG4gICAgdGhpcy5jYW5FZGl0ID0gYWNjb3VudFNlcnZpY2UuaXNBZG1pbigpO1xuICAgIHRoaXMuY2FuU2VuZE1lc3NhZ2UgPSB0aGlzLmNhbkVkaXQ7XG4gICAgdGhpcy5pbmxpbmVFZGl0aW9uID0gdGhpcy5jYW5FZGl0O1xuICAgIHRoaXMuY29uZmlybUJlZm9yZURlbGV0ZSA9IHRydWU7XG4gICAgdGhpcy5hdXRvTG9hZCA9IGZhbHNlOyAvLyBXYWl0IGNvbmZpZyBsb2FkaW5nXG4gICAgdGhpcy5pMThuQ29sdW1uUHJlZml4ID0gJ1VTRVIuJztcbiAgICB0aGlzLmRlZmF1bHRTb3J0QnkgPSAnbGFzdE5hbWUnO1xuICAgIHRoaXMuZGVmYXVsdFNvcnREaXJlY3Rpb24gPSAnYXNjJztcblxuICAgIHRoaXMuZmlsdGVyRm9ybSA9IGZvcm1CdWlsZGVyLmdyb3VwKHtcbiAgICAgIHNlYXJjaFRleHQ6IFtudWxsXSxcbiAgICAgIHN0YXR1c0lkOiBbbnVsbF0sXG4gICAgICB1c2VyUHJvZmlsZXM6IFtudWxsXSxcbiAgICB9KTtcblxuICAgIHRoaXMuYWRkaXRpb25hbEZpZWxkcyA9ICh0aGlzLmFjY291bnRTZXJ2aWNlLmFkZGl0aW9uYWxGaWVsZHMgfHwgW10pXG4gICAgICAuZmlsdGVyKChmaWVsZCkgPT4gaXNOb3ROaWwoZmllbGQuYXV0b2NvbXBsZXRlKSlcbiAgICAgIC5tYXAoKGZpZWxkKSA9PiB7XG4gICAgICAgIC8vIE1ha2Ugc3VyZSB0byBnZXQgdGhlIGZpbmFsIGF1dG9jb21wbGV0ZSBjb25maWcgKGUuZy4gd2l0aCBhIHN1Z2dlc3RGbiBmdW5jdGlvbilcbiAgICAgICAgZmllbGQuYXV0b2NvbXBsZXRlID0gdGhpcy5yZWdpc3RlckF1dG9jb21wbGV0ZUZpZWxkKGZpZWxkLmtleSwge1xuICAgICAgICAgIC4uLmZpZWxkLmF1dG9jb21wbGV0ZSwgLy8gQ29weSwgdG8gYmUgc3VyZSB0aGUgb3JpZ2luYWwgY29uZmlnIGlzIHVuY2hhbmdlZFxuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIGZpZWxkO1xuICAgICAgfSk7XG5cbiAgICAvLyBMaXN0ZW4gcGFnZSBhY3Rpb24gKGUuZy4gZnJvbSBzdWIgbWVudSBpdGVtKVxuICAgIHRoaXMucmVnaXN0ZXJTdWJzY3JpcHRpb24oXG4gICAgICB0aGlzLnJvdXRlLnF1ZXJ5UGFyYW1zLnBpcGUoZGlzdGluY3RVbnRpbEtleUNoYW5nZWQoJ2FjdGlvbicpKS5zdWJzY3JpYmUoKHF1ZXJ5UGFyYW1zKSA9PiB7XG4gICAgICAgIGNvbnN0IGFjdGlvbiA9IHF1ZXJ5UGFyYW1zWydhY3Rpb24nXSB8fCAnbm9uZSc7XG4gICAgICAgIHN3aXRjaCAoYWN0aW9uKSB7XG4gICAgICAgICAgY2FzZSAnc2VuZCc6XG4gICAgICAgICAgICB0aGlzLm9wZW5Db21wb3NlTWVzc2FnZU1vZGFsKCk7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICBjYXNlICdub25lJzpcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICBjb25zb2xlLndhcm4oJ1t1c2Vyc10gVW5rbm93biBhY3Rpb249JyArIGFjdGlvbik7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgICAvLyBNYXJrIGFzIGNvbnN1bWVkXG4gICAgICAgIHRoaXMucm91dGVyLm5hdmlnYXRlKFsnLiddLCB7XG4gICAgICAgICAgcmVsYXRpdmVUbzogdGhpcy5yb3V0ZSxcbiAgICAgICAgICBxdWVyeVBhcmFtczogeyAuLi5xdWVyeVBhcmFtcywgYWN0aW9uOiB1bmRlZmluZWQgfSxcbiAgICAgICAgICByZXBsYWNlVXJsOiB0cnVlLFxuICAgICAgICAgIHN0YXRlOiB7IGFuaW1hdGVkOiBmYWxzZSB9LFxuICAgICAgICB9KTtcbiAgICAgIH0pXG4gICAgKTtcblxuICAgIC8vIFRyYW5zbGF0ZSB1c2VyIHByb2ZpbGVzXG4gICAgdGhpcy51c2VyUHJvZmlsZUxpc3QuZm9yRWFjaCgocHJvZmlsZSkgPT4ge1xuICAgICAgcHJvZmlsZS5uYW1lID0gdGhpcy50cmFuc2xhdGUuaW5zdGFudChwcm9maWxlLm5hbWUpO1xuICAgIH0pO1xuXG4gICAgLy8gRm9yIERFViBvbmx5IC0tXG4gICAgdGhpcy5kZWJ1ZyA9ICFlbnZpcm9ubWVudC5wcm9kdWN0aW9uO1xuICB9XG5cbiAgQFZpZXdDaGlsZChNYXRFeHBhbnNpb25QYW5lbCwgeyBzdGF0aWM6IHRydWUgfSkgZmlsdGVyRXhwYW5zaW9uUGFuZWw6IE1hdEV4cGFuc2lvblBhbmVsO1xuXG4gIGdldCBmaXJzdFVzZXJDb2x1bW4oKTogc3RyaW5nIHtcbiAgICBjb25zdCBjb2x1bW5OYW1lID0gdGhpcy5kaXNwbGF5ZWRDb2x1bW5zW1JFU0VSVkVEX1NUQVJUX0NPTFVNTlMubGVuZ3RoXTtcbiAgICAvLyBTa2lwIGF2YXRhciBjb2x1bW4sIGlmIHByZXNlbnRcbiAgICByZXR1cm4gKGNvbHVtbk5hbWUgPT09ICdhdmF0YXInICYmIHRoaXMuZGlzcGxheWVkQ29sdW1uc1tSRVNFUlZFRF9TVEFSVF9DT0xVTU5TLmxlbmd0aCArIDFdKSB8fCBjb2x1bW5OYW1lO1xuICB9XG5cbiAgYXN5bmMgbmdPbkluaXQoKSB7XG4gICAgc3VwZXIubmdPbkluaXQoKTtcblxuICAgIHRoaXMucmVnaXN0ZXJTdWJzY3JpcHRpb24oXG4gICAgICB0aGlzLmNvbmZpZ1NlcnZpY2UuY29uZmlnLnN1YnNjcmliZSgoY29uZmlnKSA9PiB7XG4gICAgICAgIGNvbnN0IGF1dGhUb2tlblR5cGUgPSBjb25maWcuZ2V0UHJvcGVydHkoQ09SRV9DT05GSUdfT1BUSU9OUy5BVVRIX1RPS0VOX1RZUEUpIGFzIEF1dGhUb2tlblR5cGU7XG4gICAgICAgIGNvbnNvbGUuZGVidWcoJ1t1c2Vyc10gQXV0aFRva2VuVHlwZT0nICsgYXV0aFRva2VuVHlwZSk7XG4gICAgICAgIHN3aXRjaCAoYXV0aFRva2VuVHlwZSkge1xuICAgICAgICAgIGNhc2UgJ2Jhc2ljJzpcbiAgICAgICAgICAgIHRoaXMuc2V0U2hvd0NvbHVtbigncHVia2V5JywgZmFsc2UsIHsgZW1pdEV2ZW50OiBmYWxzZSB9KTtcbiAgICAgICAgICAgIHRoaXMuc2V0U2hvd0NvbHVtbigndXNlcm5hbWUnLCB0cnVlLCB7IGVtaXRFdmVudDogZmFsc2UgfSk7XG4gICAgICAgICAgICB0aGlzLnNldFNob3dDb2x1bW4oJ3VzZXJuYW1lRXh0cmFuZXQnLCB0cnVlLCB7IGVtaXRFdmVudDogZmFsc2UgfSk7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICBjYXNlICdiYXNpYy1hbmQtdG9rZW4nOlxuICAgICAgICAgICAgdGhpcy5zZXRTaG93Q29sdW1uKCdwdWJrZXknLCB0cnVlLCB7IGVtaXRFdmVudDogZmFsc2UgfSk7XG4gICAgICAgICAgICB0aGlzLnNldFNob3dDb2x1bW4oJ3VzZXJuYW1lJywgdHJ1ZSwgeyBlbWl0RXZlbnQ6IGZhbHNlIH0pO1xuICAgICAgICAgICAgdGhpcy5zZXRTaG93Q29sdW1uKCd1c2VybmFtZUV4dHJhbmV0JywgdHJ1ZSwgeyBlbWl0RXZlbnQ6IGZhbHNlIH0pO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgY2FzZSAndG9rZW4nOlxuICAgICAgICAgICAgdGhpcy5zZXRTaG93Q29sdW1uKCdwdWJrZXknLCB0cnVlLCB7IGVtaXRFdmVudDogZmFsc2UgfSk7XG4gICAgICAgICAgICB0aGlzLnNldFNob3dDb2x1bW4oJ3VzZXJuYW1lJywgZmFsc2UsIHsgZW1pdEV2ZW50OiBmYWxzZSB9KTtcbiAgICAgICAgICAgIHRoaXMuc2V0U2hvd0NvbHVtbigndXNlcm5hbWVFeHRyYW5ldCcsIGZhbHNlLCB7IGVtaXRFdmVudDogZmFsc2UgfSk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy51cGRhdGVDb2x1bW5zKCk7XG4gICAgICAgIHRoaXMuZW1pdFJlZnJlc2goKTtcbiAgICAgIH0pXG4gICAgKTtcblxuICAgIHRoaXMucmVnaXN0ZXJTdWJzY3JpcHRpb24oXG4gICAgICB0aGlzLm9uUmVmcmVzaC5zdWJzY3JpYmUoKCkgPT4ge1xuICAgICAgICB0aGlzLmZpbHRlckZvcm0ubWFya0FzVW50b3VjaGVkKCk7XG4gICAgICAgIHRoaXMuZmlsdGVyRm9ybS5tYXJrQXNQcmlzdGluZSgpO1xuICAgICAgfSlcbiAgICApO1xuXG4gICAgLy8gVXBkYXRlIGZpbHRlciB3aGVuIGNoYW5nZXNcbiAgICB0aGlzLnJlZ2lzdGVyU3Vic2NyaXB0aW9uKFxuICAgICAgdGhpcy5maWx0ZXJGb3JtLnZhbHVlQ2hhbmdlc1xuICAgICAgICAucGlwZShcbiAgICAgICAgICBkZWJvdW5jZVRpbWUoMjUwKSxcbiAgICAgICAgICBmaWx0ZXIoKCkgPT4gdGhpcy5maWx0ZXJGb3JtLnZhbGlkKSxcbiAgICAgICAgICB0YXAoKGpzb24pID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGZpbHRlciA9IFBlcnNvbkZpbHRlci5mcm9tT2JqZWN0KGpzb24pO1xuICAgICAgICAgICAgdGhpcy5maWx0ZXJDcml0ZXJpYUNvdW50ID0gZmlsdGVyLmNvdW50Tm90RW1wdHlDcml0ZXJpYSgpO1xuICAgICAgICAgICAgdGhpcy5tYXJrRm9yQ2hlY2soKTtcbiAgICAgICAgICAgIC8vIFVwZGF0ZSB0aGUgZmlsdGVyLCB3aXRob3V0IHJlbG9hZGluZyB0aGUgY29udGVudFxuICAgICAgICAgICAgdGhpcy5zZXRGaWx0ZXIoZmlsdGVyLCB7IGVtaXRFdmVudDogZmFsc2UgfSk7XG4gICAgICAgICAgfSksXG4gICAgICAgICAgLy8gU2F2ZSBmaWx0ZXIgaW4gc2V0dGluZ3MgKGFmdGVyIGEgZGVib3VuY2UgdGltZSlcbiAgICAgICAgICBkZWJvdW5jZVRpbWUoNTAwKSxcbiAgICAgICAgICBmaWx0ZXIoKCkgPT4gaXNOb3ROaWxPckJsYW5rKHRoaXMuc2V0dGluZ3NJZCkgJiYgdGhpcy51c2VQYWdlU2V0dGluZ3MpLFxuICAgICAgICAgIHRhcCgoanNvbikgPT4gdGhpcy5zZXR0aW5ncy5zYXZlUGFnZVNldHRpbmcodGhpcy5zZXR0aW5nc0lkLCBqc29uLCBUQUJMRV9TRVRUSU5HU19FTlVNLkZJTFRFUl9LRVkpKVxuICAgICAgICApXG4gICAgICAgIC5zdWJzY3JpYmUoKVxuICAgICk7XG5cbiAgICBpZiAodGhpcy5jYW5TZW5kTWVzc2FnZSkge1xuICAgICAgYXdhaXQgdGhpcy5tZW51U2VydmljZS5hZGRTdWJNZW51SXRlbXMoXG4gICAgICAgIFtcbiAgICAgICAgICB7XG4gICAgICAgICAgICBwYXJlbnRQYXRoOiAnL2FkbWluL3VzZXJzJyxcbiAgICAgICAgICAgIHBhdGg6ICcvYWRtaW4vdXNlcnMnLFxuICAgICAgICAgICAgcGF0aFBhcmFtczogeyBhY3Rpb246ICdleHBhbmQnIH0sXG4gICAgICAgICAgICBtYXRJY29uOiAnZXhwYW5kX21vcmUnLFxuICAgICAgICAgICAgdGl0bGU6ICdVU0VSLkxJU1QuQlROX0FDVElPTlMnLFxuICAgICAgICAgICAgYWN0aW9uOiAnZXhwYW5kJyxcbiAgICAgICAgICB9LFxuICAgICAgICAgIHtcbiAgICAgICAgICAgIHBhcmVudFBhdGg6ICcvYWRtaW4vdXNlcnM/YWN0aW9uPWV4cGFuZCcsXG4gICAgICAgICAgICBwYXRoOiAnL2FkbWluL3VzZXJzP2FjdGlvbj1zZW5kJyxcbiAgICAgICAgICAgIGljb246ICdtYWlsJyxcbiAgICAgICAgICAgIHRpdGxlOiAnVVNFUi5MSVNULkJUTl9TRU5EX01FU1NBR0UnLFxuICAgICAgICAgICAgYWN0aW9uOiAoKSA9PiB0aGlzLm9wZW5Db21wb3NlTWVzc2FnZU1vZGFsKCksXG4gICAgICAgICAgfSxcbiAgICAgICAgXSxcbiAgICAgICAgeyBza2lwSWZFeGlzdHM6IGZhbHNlIH1cbiAgICAgICk7XG4gICAgfVxuXG4gICAgLy8gUmVzdG9yZSBjb21wYWN0IHJvd3NcbiAgICB0aGlzLnJlc3RvcmVDb21wYWN0TW9kZSgpO1xuXG4gICAgLy8gUmVzdG9yZSBmaWx0ZXIgZnJvbSBzZXR0aW5ncywgb3IgbG9hZCBhbGxcbiAgICB0aGlzLnJlc3RvcmVGaWx0ZXJPckxvYWQoKTtcbiAgfVxuXG4gIGFwcGx5RmlsdGVyQW5kQ2xvc2VQYW5lbChldmVudD86IEV2ZW50KSB7XG4gICAgdGhpcy5lbWl0UmVmcmVzaChldmVudCk7XG4gICAgdGhpcy5maWx0ZXJFeHBhbnNpb25QYW5lbC5jbG9zZSgpO1xuICB9XG5cbiAgcmVzZXRGaWx0ZXIoZXZlbnQ/OiBFdmVudCkge1xuICAgIHRoaXMudG90YWxSb3dDb3VudCA9IHVuZGVmaW5lZDtcbiAgICB0aGlzLmZpbHRlckNyaXRlcmlhQ291bnQgPSAwO1xuICAgIHRoaXMubWFya0FzTG9hZGluZygpO1xuICAgIHRoaXMuZmlsdGVyRm9ybS5yZXNldCgpO1xuICAgIHRoaXMuc2V0RmlsdGVyKG51bGwpO1xuICB9XG5cbiAgcHJvdGVjdGVkIGFzeW5jIHJlc3RvcmVGaWx0ZXJPckxvYWQoKSB7XG4gICAgdGhpcy5tYXJrQXNMb2FkaW5nKCk7XG5cbiAgICBjb25zb2xlLmRlYnVnKCdbdXNlcnNdIFJlc3RvcmluZyBmaWx0ZXIgZnJvbSBzZXR0aW5ncy4uLicpO1xuXG4gICAgY29uc3QganNvbiA9IHRoaXMuc2V0dGluZ3MuZ2V0UGFnZVNldHRpbmdzKHRoaXMuc2V0dGluZ3NJZCwgVEFCTEVfU0VUVElOR1NfRU5VTS5GSUxURVJfS0VZKSB8fCB7fTtcbiAgICBjb25zdCBmaWx0ZXIgPSBQZXJzb25GaWx0ZXIuZnJvbU9iamVjdChqc29uKTtcblxuICAgIGpzb24udXNlclByb2ZpbGVzID0gQXJyYXkuaXNBcnJheShqc29uLnVzZXJQcm9maWxlcylcbiAgICAgID8ganNvbi51c2VyUHJvZmlsZXMubWFwKCh1cCkgPT4ge1xuICAgICAgICAgIGNvbnN0IGxhYmVsID0gdXAubGFiZWwgPz8gdXA7XG4gICAgICAgICAgcmV0dXJuIFJlZmVyZW50aWFsUmVmLmZyb21PYmplY3Qoe1xuICAgICAgICAgICAgbGFiZWwsXG4gICAgICAgICAgICBuYW1lOiB0aGlzLnRyYW5zbGF0ZS5pbnN0YW50KGBVU0VSLlBST0ZJTEVfRU5VTS4ke2xhYmVsfWApLFxuICAgICAgICAgIH0pO1xuICAgICAgICB9KVxuICAgICAgOiBudWxsO1xuXG4gICAgdGhpcy5maWx0ZXJGb3JtLnBhdGNoVmFsdWUoanNvbik7XG4gICAgdGhpcy5zZXRGaWx0ZXIoZmlsdGVyLCB7IGVtaXRFdmVudDogdHJ1ZSB9KTtcbiAgfVxuXG4gIGNsZWFyQ29udHJvbFZhbHVlKGV2ZW50OiBFdmVudCwgZm9ybUNvbnRyb2w6IEFic3RyYWN0Q29udHJvbCk6IGJvb2xlYW4ge1xuICAgIGlmIChldmVudCkgZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7IC8vIEF2b2lkIHRvIGVudGVyIGlucHV0IHRoZSBmaWVsZFxuICAgIGZvcm1Db250cm9sLnNldFZhbHVlKG51bGwpO1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIGFzeW5jIG9wZW5Db21wb3NlTWVzc2FnZU1vZGFsKGV2ZW50PzogRXZlbnQpOiBQcm9taXNlPGFueT4ge1xuICAgIC8vIENvbXB1dGUgcmVjaXBpZW50c1xuICAgIGNvbnN0IHJlY2lwaWVudHMgPSAodGhpcy5zZWxlY3Rpb24uc2VsZWN0ZWQgfHwgW10pXG4gICAgICAubWFwKChyb3cpID0+IHJvdy5jdXJyZW50RGF0YSlcbiAgICAgIC5tYXAoUGVyc29uLmZyb21PYmplY3QpXG4gICAgICAubWFwKChwKSA9PiB7XG4gICAgICAgIGNvbnN0IHRhcmdldCA9IHAuYXNPYmplY3QoeyBtaW5pZnk6IHRydWUgfSk7XG4gICAgICAgIHRhcmdldC5kZXBhcnRtZW50ID0gcC5kZXBhcnRtZW50Py5hc09iamVjdCgpO1xuICAgICAgICByZXR1cm4gdGFyZ2V0O1xuICAgICAgfSk7XG5cbiAgICBjb25zdCByZWNpcGllbnRGaWx0ZXIgPSBQZXJzb25GaWx0ZXIuZnJvbU9iamVjdCh0aGlzLmZpbHRlcik7XG4gICAgY29uc3QgY2FuUmVjaXBpZW50RmlsdGVyID0gIXJlY2lwaWVudEZpbHRlci5pc0VtcHR5KCkgJiYgKHRoaXMuYWNjb3VudFNlcnZpY2UuaXNBZG1pbigpIHx8IHRoaXMuYWNjb3VudFNlcnZpY2UuaXNTdXBlcnZpc29yKCkpO1xuICAgIHJldHVybiB0aGlzLm1lc3NhZ2VTZXJ2aWNlLm9wZW5Db21wb3NlTW9kYWwoe1xuICAgICAgc3VnZ2VzdEZuOiAodmFsdWUsIGZpbHRlciwgc29ydEJ5LCBzb3J0RGlyZWN0aW9uKSA9PiB0aGlzLmRhdGFTZXJ2aWNlLnN1Z2dlc3QodmFsdWUsIGZpbHRlciwgc29ydEJ5LCBzb3J0RGlyZWN0aW9uKSxcbiAgICAgIGNhblJlY2lwaWVudEZpbHRlcixcbiAgICAgIHJlY2lwaWVudEZpbHRlckNvdW50OiB0aGlzLnRvdGFsUm93Q291bnQsXG4gICAgICBkYXRhOiBNZXNzYWdlLmZyb21PYmplY3Qoe1xuICAgICAgICByZWNpcGllbnRzLFxuICAgICAgICByZWNpcGllbnRGaWx0ZXIsXG4gICAgICB9KSxcbiAgICAgIGRlYnVnOiB0aGlzLmRlYnVnLFxuICAgIH0pO1xuICB9XG5cbiAgYXN5bmMgcmVzdG9yZUNvbXBhY3RNb2RlKG9wdHM/OiB7IGVtaXRFdmVudD86IGJvb2xlYW4gfSkge1xuICAgIGlmICghdGhpcy51c2VQYWdlU2V0dGluZ3MgfHwgaXNOaWxPckJsYW5rKHRoaXMuc2V0dGluZ3NJZCkgfHwgaXNOb3ROaWwodGhpcy5jb21wYWN0KSkgcmV0dXJuO1xuXG4gICAgY29uc3QgY29tcGFjdCA9IHRvQm9vbGVhbihcbiAgICAgIHRoaXMuc2V0dGluZ3MuZ2V0UGFnZVNldHRpbmdzKHRoaXMuc2V0dGluZ3NJZCwgVEFCTEVfU0VUVElOR1NfRU5VTS5DT01QQUNUX1JPV1NfS0VZKSxcbiAgICAgIHRvQm9vbGVhbih0aGlzLmNvbXBhY3QsIHRoaXMuZGVmYXVsdENvbXBhY3QpXG4gICAgKTtcbiAgICBpZiAodGhpcy5jb21wYWN0ICE9PSBjb21wYWN0KSB7XG4gICAgICB0aGlzLmNvbXBhY3QgPSBjb21wYWN0O1xuXG4gICAgICAvLyBFbWl0IGV2ZW50XG4gICAgICBpZiAoIW9wdHMgfHwgb3B0cy5lbWl0RXZlbnQgIT09IGZhbHNlKSB7XG4gICAgICAgIHRoaXMubWFya0ZvckNoZWNrKCk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgYXN5bmMgdG9nZ2xlQ29tcGFjdE1vZGUoKSB7XG4gICAgdGhpcy5jb21wYWN0ID0gIXRoaXMuY29tcGFjdDtcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHJ4LWFuZ3VsYXIvbm8tZXhwbGljaXQtY2hhbmdlLWRldGVjdGlvbi1hcGlzXG4gICAgdGhpcy5tYXJrRm9yQ2hlY2soKTtcbiAgICBpZiAodGhpcy51c2VQYWdlU2V0dGluZ3MgJiYgaXNOb3ROaWxPckJsYW5rKHRoaXMuc2V0dGluZ3NJZCkpIHtcbiAgICAgIGF3YWl0IHRoaXMuc2F2ZVBhZ2VTZXR0aW5ncyh0aGlzLmNvbXBhY3QsIFRBQkxFX1NFVFRJTkdTX0VOVU0uQ09NUEFDVF9ST1dTX0tFWSk7XG4gICAgfVxuICB9XG5cbiAgYXN5bmMgZXhwb3J0VG9Dc3YoZXZlbnQ6IEV2ZW50KSB7XG4gICAgLy8gUHJlcGFyZSBDU1Ygb3B0aW9uc1xuICAgIGNvbnN0IHNlcGFyYXRvciA9IENzdlV0aWxzLmdldExvY2FsaXplZFNlcGFyYXRvcih0aGlzLnRyYW5zbGF0ZSk7XG4gICAgY29uc3QgZW5jb2RpbmcgPSBDc3ZVdGlscy5nZXRMb2NhbGl6ZWRFbmNvZGluZyh0aGlzLnRyYW5zbGF0ZSk7XG4gICAgY29uc3QgdHJhbnNsYXRpb25zID0gdGhpcy50cmFuc2xhdGUuaW5zdGFudChbXG4gICAgICAnQ09NTU9OLkRBVEVfVElNRV9QQVRURVJOJyxcbiAgICAgICdVU0VSLkxJU1QuVElUTEUnLFxuICAgICAgJ1VTRVIuRU1BSUwnLFxuICAgICAgJ1VTRVIuRklSU1RfTkFNRScsXG4gICAgICAnVVNFUi5MQVNUX05BTUUnLFxuICAgICAgJ1VTRVIuVVNFUk5BTUUnLFxuICAgICAgJ1VTRVIuVVNFUk5BTUVfRVhUUkFORVQnLFxuICAgICAgJ1VTRVIuREVQQVJUTUVOVF9MQUJFTCcsXG4gICAgICAnVVNFUi5ERVBBUlRNRU5UX05BTUUnLFxuICAgICAgJ1VTRVIuUFJPRklMRScsXG4gICAgICAnVVNFUi5TVEFUVVMnLFxuICAgICAgJ1VTRVIuUFVCS0VZJyxcbiAgICAgIC4uLih0aGlzLmFkZGl0aW9uYWxGaWVsZHMgfHwgW10pLm1hcCgoZmllbGQpID0+IGZpZWxkLmxhYmVsKSxcbiAgICAgICdVU0VSLkNSRUFUSU9OX0RBVEUnLFxuICAgICAgJ1VTRVIuVVBEQVRFX0RBVEUnLFxuICAgICAgLi4udGhpcy5zdGF0dXNMaXN0Lm1hcCgoc3RhdHVzKSA9PiBzdGF0dXMubGFiZWwpLFxuICAgIF0pO1xuICAgIGNvbnN0IGRhdGVUaW1lUGF0dGVybiA9IHRyYW5zbGF0aW9uc1snQ09NTU9OLkRBVEVfVElNRV9QQVRURVJOJ107XG4gICAgY29uc3QgZmlsZW5hbWUgPSB0cmFuc2xhdGlvbnNbJ1VTRVIuTElTVC5USVRMRSddICsgJy5jc3YnO1xuICAgIGNvbnN0IGhlYWRlcnMgPSBbXG4gICAgICB0cmFuc2xhdGlvbnNbJ1VTRVIuRU1BSUwnXSxcbiAgICAgIHRyYW5zbGF0aW9uc1snVVNFUi5GSVJTVF9OQU1FJ10sXG4gICAgICB0cmFuc2xhdGlvbnNbJ1VTRVIuTEFTVF9OQU1FJ10sXG4gICAgICAuLi4odGhpcy5zaG93VXNlcm5hbWVDb2x1bW4gPyBbdHJhbnNsYXRpb25zWydVU0VSLlVTRVJOQU1FJ11dIDogW10pLFxuICAgICAgLi4uKHRoaXMuc2hvd1VzZXJuYW1lRXh0cmFuZXRDb2x1bW4gPyBbdHJhbnNsYXRpb25zWydVU0VSLlVTRVJOQU1FX0VYVFJBTkVUJ11dIDogW10pLFxuICAgICAgdHJhbnNsYXRpb25zWydVU0VSLlBST0ZJTEUnXSxcbiAgICAgIHRyYW5zbGF0aW9uc1snVVNFUi5TVEFUVVMnXSxcbiAgICAgIHRyYW5zbGF0aW9uc1snVVNFUi5QVUJLRVknXSxcbiAgICAgIC4uLih0aGlzLmFkZGl0aW9uYWxGaWVsZHMgfHwgW10pLm1hcCgoZmllbGQpID0+IHRyYW5zbGF0aW9uc1tmaWVsZC5sYWJlbF0pLFxuICAgICAgdHJhbnNsYXRpb25zWydVU0VSLkNSRUFUSU9OX0RBVEUnXSxcbiAgICAgIHRyYW5zbGF0aW9uc1snVVNFUi5VUERBVEVfREFURSddLFxuICAgIF07XG5cbiAgICBjb25zdCBhZGRpdGlvbmFsRmllbGRzRm5zID0gKHRoaXMuYWRkaXRpb25hbEZpZWxkcyB8fCBbXSkubWFwKEZvcm1GaWVsZERlZmluaXRpb25VdGlscy5nZXREaXNwbGF5VmFsdWVGbik7XG5cbiAgICBjb25zdCByb3dzID0gKHRoaXMuc2VsZWN0aW9uLmlzRW1wdHkoKSA/IHRoaXMuZGF0YVNvdXJjZS5nZXRSb3dzKCkgOiB0aGlzLnNlbGVjdGlvbi5zZWxlY3RlZClcbiAgICAgIC5tYXAoKGVsZW1lbnQpID0+IGVsZW1lbnQuY3VycmVudERhdGEpXG4gICAgICAubWFwKChwZXJzb24pID0+IHtcbiAgICAgICAgY29uc3Qgc3RhdHVzID0gdGhpcy5zdGF0dXNCeUlkW3BlcnNvbi5zdGF0dXNJZF07XG4gICAgICAgIHJldHVybiBbXG4gICAgICAgICAgcGVyc29uLmxhc3ROYW1lLFxuICAgICAgICAgIHBlcnNvbi5maXJzdE5hbWUsXG4gICAgICAgICAgcGVyc29uLmVtYWlsLFxuICAgICAgICAgIC4uLih0aGlzLnNob3dVc2VybmFtZUNvbHVtbiA/IFtwZXJzb24udXNlcm5hbWVdIDogW10pLFxuICAgICAgICAgIC4uLih0aGlzLnNob3dVc2VybmFtZUV4dHJhbmV0Q29sdW1uID8gW3BlcnNvbi51c2VybmFtZUV4dHJhbmV0XSA6IFtdKSxcbiAgICAgICAgICBwZXJzb24ubWFpblByb2ZpbGUsXG4gICAgICAgICAgc3RhdHVzID8gdHJhbnNsYXRpb25zW3N0YXR1cz8ubGFiZWxdIDogbnVsbCxcbiAgICAgICAgICBwZXJzb24ucHVia2V5LFxuICAgICAgICAgIC4uLmFkZGl0aW9uYWxGaWVsZHNGbnMubWFwKChkaXNwbGF5Rm4sIGluZGV4KSA9PiB7XG4gICAgICAgICAgICBjb25zdCB2YWx1ZSA9IGdldFByb3BlcnR5QnlQYXRoKHBlcnNvbiwgdGhpcy5hZGRpdGlvbmFsRmllbGRzW2luZGV4XS5rZXkpO1xuICAgICAgICAgICAgY29uc29sZS5kZWJ1ZygnW3VzZXJzXSBBZGRpdGlvbmFsIGZpZWxkIGRpc3BsYXlGbicsIHZhbHVlKTtcbiAgICAgICAgICAgIHJldHVybiBkaXNwbGF5Rm4odmFsdWUpO1xuICAgICAgICAgIH0pLFxuICAgICAgICAgIGZyb21EYXRlSVNPU3RyaW5nKHBlcnNvbi5jcmVhdGlvbkRhdGUpLmZvcm1hdChkYXRlVGltZVBhdHRlcm4pLFxuICAgICAgICAgIGZyb21EYXRlSVNPU3RyaW5nKHBlcnNvbi51cGRhdGVEYXRlKS5mb3JtYXQoZGF0ZVRpbWVQYXR0ZXJuKSxcbiAgICAgICAgXTtcbiAgICAgIH0pO1xuXG4gICAgQ3N2VXRpbHMuZXhwb3J0VG9GaWxlKHJvd3MsIHsgZmlsZW5hbWUsIGhlYWRlcnMsIHNlcGFyYXRvciwgZW5jb2RpbmcgfSk7XG4gIH1cbn1cbiIsIjxhcHAtdG9vbGJhclxuICBbdGl0bGVdPVwiJ1VTRVIuTElTVC5USVRMRScgfCB0cmFuc2xhdGVcIlxuICBjb2xvcj1cInByaW1hcnlcIlxuICBbY2FuR29CYWNrXT1cImZhbHNlXCJcbiAgW2hhc1ZhbGlkYXRlXT1cIihsb2FkaW5nU3ViamVjdCB8IGFzeW5jKSAhPT0gdHJ1ZSAmJiAoZGlydHlTdWJqZWN0IHwgYXN5bmMpID09PSB0cnVlXCJcbiAgKG9uVmFsaWRhdGUpPVwic2F2ZSgpXCJcbj5cbiAgPGlvbi1idXR0b25zIHNsb3Q9XCJlbmRcIj5cbiAgICA8IS0tIENvbXBvc2UgbWVzc2FnZSAtLT5cbiAgICA8YnV0dG9uXG4gICAgICBtYXQtaWNvbi1idXR0b25cbiAgICAgICpuZ0lmPVwiY2FuU2VuZE1lc3NhZ2VcIlxuICAgICAgW3RpdGxlXT1cIidVU0VSLkxJU1QuQlROX1NFTkRfTUVTU0FHRScgfCB0cmFuc2xhdGVcIlxuICAgICAgKGNsaWNrKT1cIm9wZW5Db21wb3NlTWVzc2FnZU1vZGFsKCRldmVudClcIlxuICAgID5cbiAgICAgIDxpb24taWNvbiBuYW1lPVwibWFpbFwiIHNsb3Q9XCJpY29uLW9ubHlcIj48L2lvbi1pY29uPlxuICAgIDwvYnV0dG9uPlxuXG4gICAgQGlmIChzZWxlY3Rpb24gfCBpc0VtcHR5U2VsZWN0aW9uKSB7XG4gICAgICA8IS0tIEFkZCAtLT5cbiAgICAgIDxidXR0b24gbWF0LWljb24tYnV0dG9uICpuZ0lmPVwiY2FuRWRpdCAmJiAhbW9iaWxlXCIgW3RpdGxlXT1cIidDT01NT04uQlROX0FERCcgfCB0cmFuc2xhdGVcIiAoY2xpY2spPVwiYWRkUm93KClcIj5cbiAgICAgICAgPG1hdC1pY29uPmFkZDwvbWF0LWljb24+XG4gICAgICA8L2J1dHRvbj5cblxuICAgICAgPCEtLSBSZWZyZXNoIC0tPlxuICAgICAgPGJ1dHRvbiBtYXQtaWNvbi1idXR0b24gKm5nSWY9XCIhbW9iaWxlXCIgW3RpdGxlXT1cIidDT01NT04uQlROX1JFRlJFU0gnIHwgdHJhbnNsYXRlXCIgKGNsaWNrKT1cImVtaXRSZWZyZXNoKClcIj5cbiAgICAgICAgPG1hdC1pY29uPnJlZnJlc2g8L21hdC1pY29uPlxuICAgICAgPC9idXR0b24+XG5cbiAgICAgIDwhLS0gcmVzZXQgZmlsdGVyIC0tPlxuICAgICAgPGJ1dHRvbiBtYXQtaWNvbi1idXR0b24gKGNsaWNrKT1cInJlc2V0RmlsdGVyKClcIiAqbmdJZj1cImZpbHRlckNyaXRlcmlhQ291bnRcIj5cbiAgICAgICAgPG1hdC1pY29uIGNvbG9yPVwiYWNjZW50XCI+ZmlsdGVyX2xpc3RfYWx0PC9tYXQtaWNvbj5cbiAgICAgICAgPG1hdC1pY29uIGNsYXNzPVwiaWNvbi1zZWNvbmRhcnlcIiBzdHlsZT1cImxlZnQ6IDE2cHg7IHRvcDogNXB4OyBmb250LXdlaWdodDogYm9sZFwiPmNsb3NlPC9tYXQtaWNvbj5cbiAgICAgIDwvYnV0dG9uPlxuXG4gICAgICA8IS0tIHNob3cgZmlsdGVyIC0tPlxuICAgICAgPGJ1dHRvbiBtYXQtaWNvbi1idXR0b24gKGNsaWNrKT1cImZpbHRlckV4cGFuc2lvblBhbmVsLnRvZ2dsZSgpXCI+XG4gICAgICAgIDxtYXQtaWNvblxuICAgICAgICAgICpuZ0lmPVwiZmlsdGVyQ3JpdGVyaWFDb3VudDsgZWxzZSBlbXB0eUZpbHRlclwiXG4gICAgICAgICAgW21hdEJhZGdlXT1cImZpbHRlckNyaXRlcmlhQ291bnRcIlxuICAgICAgICAgIG1hdEJhZGdlQ29sb3I9XCJhY2NlbnRcIlxuICAgICAgICAgIG1hdEJhZGdlU2l6ZT1cInNtYWxsXCJcbiAgICAgICAgICBtYXRCYWRnZVBvc2l0aW9uPVwiYWJvdmUgYWZ0ZXJcIlxuICAgICAgICAgIGFyaWEtaGlkZGVuPVwiZmFsc2VcIlxuICAgICAgICA+XG4gICAgICAgICAgZmlsdGVyX2xpc3RfYWx0XG4gICAgICAgIDwvbWF0LWljb24+XG4gICAgICAgIDxuZy10ZW1wbGF0ZSAjZW1wdHlGaWx0ZXI+XG4gICAgICAgICAgPG1hdC1pY29uPmZpbHRlcl9saXN0X2FsdDwvbWF0LWljb24+XG4gICAgICAgIDwvbmctdGVtcGxhdGU+XG4gICAgICA8L2J1dHRvbj5cbiAgICB9IEBlbHNlIHtcbiAgICAgIDwhLS0gZGVsZXRlIC0tPlxuICAgICAgPGJ1dHRvblxuICAgICAgICBtYXQtaWNvbi1idXR0b25cbiAgICAgICAgY2xhc3M9XCJoaWRkZW4teHMgaGlkZGVuLXNtXCJcbiAgICAgICAgW3RpdGxlXT1cIidDT01NT04uQlROX0RFTEVURScgfCB0cmFuc2xhdGVcIlxuICAgICAgICAoY2xpY2spPVwiZGVsZXRlU2VsZWN0aW9uKCRldmVudClcIlxuICAgICAgPlxuICAgICAgICA8bWF0LWljb24+ZGVsZXRlPC9tYXQtaWNvbj5cbiAgICAgIDwvYnV0dG9uPlxuICAgIH1cblxuICAgIEBpZiAoIW1vYmlsZSkge1xuICAgICAgPGJ1dHRvbiBtYXQtaWNvbi1idXR0b24gW3RpdGxlXT1cIidDT01NT04uQlROX09QVElPTlMnIHwgdHJhbnNsYXRlXCIgW21hdE1lbnVUcmlnZ2VyRm9yXT1cInRvb2xiYXJPcHRpb25zTWVudVwiPlxuICAgICAgICA8bWF0LWljb24+bW9yZV92ZXJ0PC9tYXQtaWNvbj5cbiAgICAgIDwvYnV0dG9uPlxuICAgIH1cbiAgPC9pb24tYnV0dG9ucz5cbjwvYXBwLXRvb2xiYXI+XG5cbjwhLS0gVG9vbGJhciBvcHRpb24gbWVudSAtLT5cbjxtYXQtbWVudSAjdG9vbGJhck9wdGlvbnNNZW51PVwibWF0TWVudVwiIHhQb3NpdGlvbj1cImFmdGVyXCI+XG4gIDwhLS0gZXhwb3J0IGJ1dHRvbiAtLT5cbiAgPGJ1dHRvbiBtYXQtbWVudS1pdGVtIFtkaXNhYmxlZF09XCIhY2FuRG93bmxvYWRcIiAoY2xpY2spPVwiZXhwb3J0VG9Dc3YoJGV2ZW50KVwiPlxuICAgIDxtYXQtaWNvbj5kb3dubG9hZDwvbWF0LWljb24+XG4gICAgPGlvbi1sYWJlbCB0cmFuc2xhdGU+RklMRS5DU1YuQlROX0RPV05MT0FEX0hFTFA8L2lvbi1sYWJlbD5cbiAgPC9idXR0b24+XG48L21hdC1tZW51PlxuXG48aW9uLWNvbnRlbnQgY2xhc3M9XCJpb24tbm8tcGFkZGluZ1wiPlxuICA8IS0tIGVycm9yIC0tPlxuICA8aW9uLWl0ZW1cbiAgICAqbmdJZj1cImVycm9yU3ViamVjdCB8IGFzeW5jOyBsZXQgZXJyb3JcIlxuICAgIGxpbmVzPVwibm9uZVwiXG4gICAgY2xhc3M9XCJoaWRkZW4tc20gaGlkZGVuLXhzIGhpZGRlbi1tb2JpbGVcIlxuICAgIEBzbGlkZVVwRG93bkFuaW1hdGlvblxuICA+XG4gICAgPGlvbi1pY29uIGNvbG9yPVwiZGFuZ2VyXCIgc2xvdD1cInN0YXJ0XCIgbmFtZT1cImFsZXJ0LWNpcmNsZVwiPjwvaW9uLWljb24+XG4gICAgPGlvbi1sYWJlbCBjb2xvcj1cImRhbmdlclwiIGNsYXNzPVwiZXJyb3JcIiBbaW5uZXJIVE1MXT1cImVycm9yIHwgdHJhbnNsYXRlXCI+PC9pb24tbGFiZWw+XG4gIDwvaW9uLWl0ZW0+XG5cbiAgPCEtLSBkZWJ1ZyAtLT5cbiAgPGFwcC1kZWJ1ZyAqbmdJZj1cImRlYnVnXCI+XG4gICAgPGlvbi1ncmlkIGNsYXNzPVwiaW9uLW5vLXBhZGRpbmdcIj5cbiAgICAgIDxpb24tcm93PlxuICAgICAgICA8aW9uLWNvbD5cbiAgICAgICAgICBmb2N1c0NvbHVtbjoge3sgZm9jdXNDb2x1bW4gfX1cbiAgICAgICAgICA8YnIgLz5cbiAgICAgICAgICBsb2FkaW5nU3ViamVjdDoge3sgbG9hZGluZyB9fVxuICAgICAgICAgIDxiciAvPlxuICAgICAgICA8L2lvbi1jb2w+XG4gICAgICA8L2lvbi1yb3c+XG4gICAgPC9pb24tZ3JpZD5cbiAgPC9hcHAtZGVidWc+XG5cbiAgPCEtLSBzZWFyY2ggLS0+XG4gIDxtYXQtZXhwYW5zaW9uLXBhbmVsICNmaWx0ZXJFeHBhbnNpb25QYW5lbCBjbGFzcz1cImlvbi1uby1wYWRkaW5nIGZpbHRlci1wYW5lbCBmaWx0ZXItcGFuZWwtZmxvYXRpbmdcIj5cbiAgICA8Zm9ybSBjbGFzcz1cImZvcm0tY29udGFpbmVyIGlvbi1wYWRkaW5nXCIgW2Zvcm1Hcm91cF09XCJmaWx0ZXJGb3JtXCIgKG5nU3VibWl0KT1cImVtaXRSZWZyZXNoKClcIj5cbiAgICAgIDxpb24tZ3JpZD5cbiAgICAgICAgPGlvbi1yb3c+XG4gICAgICAgICAgPGlvbi1jb2w+XG4gICAgICAgICAgICA8IS0tIHNlYXJjaCAtLT5cbiAgICAgICAgICAgIDxtYXQtZm9ybS1maWVsZD5cbiAgICAgICAgICAgICAgPG1hdC1sYWJlbD57eyAnVVNFUi5MSVNULkZJTFRFUi5TRUFSQ0gnIHwgdHJhbnNsYXRlIH19PC9tYXQtbGFiZWw+XG4gICAgICAgICAgICAgIDxpbnB1dCBtYXRJbnB1dCBmb3JtQ29udHJvbE5hbWU9XCJzZWFyY2hUZXh0XCIgLz5cbiAgICAgICAgICAgICAgPGJ1dHRvblxuICAgICAgICAgICAgICAgIG1hdC1pY29uLWJ1dHRvblxuICAgICAgICAgICAgICAgIG1hdFN1ZmZpeFxuICAgICAgICAgICAgICAgIHRhYmluZGV4PVwiLTFcIlxuICAgICAgICAgICAgICAgIHR5cGU9XCJidXR0b25cIlxuICAgICAgICAgICAgICAgIChjbGljayk9XCJjbGVhckNvbnRyb2xWYWx1ZSgkZXZlbnQsIGZpbHRlckZvcm0uY29udHJvbHMuc2VhcmNoVGV4dClcIlxuICAgICAgICAgICAgICAgIFtoaWRkZW5dPVwiZmlsdGVyRm9ybS5jb250cm9scy5zZWFyY2hUZXh0LmRpc2FibGVkIHx8ICFmaWx0ZXJGb3JtLmNvbnRyb2xzLnNlYXJjaFRleHQudmFsdWVcIlxuICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgPG1hdC1pY29uPmNsb3NlPC9tYXQtaWNvbj5cbiAgICAgICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgICA8L21hdC1mb3JtLWZpZWxkPlxuICAgICAgICAgIDwvaW9uLWNvbD5cblxuICAgICAgICAgIDxpb24tY29sPlxuICAgICAgICAgICAgPCEtLSBzdGF0dXMgLS0+XG4gICAgICAgICAgICA8bWF0LWZvcm0tZmllbGQ+XG4gICAgICAgICAgICAgIDxtYXQtbGFiZWw+e3sgJ1VTRVIuU1RBVFVTJyB8IHRyYW5zbGF0ZSB9fTwvbWF0LWxhYmVsPlxuICAgICAgICAgICAgICA8bWF0LXNlbGVjdCBmb3JtQ29udHJvbE5hbWU9XCJzdGF0dXNJZFwiPlxuICAgICAgICAgICAgICAgIDxtYXQtb3B0aW9uIFt2YWx1ZV09XCJudWxsXCI+XG4gICAgICAgICAgICAgICAgICA8aT48c3BhbiB0cmFuc2xhdGU+Q09NTU9OLkVNUFRZX09QVElPTjwvc3Bhbj48L2k+XG4gICAgICAgICAgICAgICAgPC9tYXQtb3B0aW9uPlxuICAgICAgICAgICAgICAgIDxtYXQtb3B0aW9uICpuZ0Zvcj1cImxldCBpdGVtIG9mIHN0YXR1c0xpc3RcIiBbdmFsdWVdPVwiaXRlbS5pZFwiPlxuICAgICAgICAgICAgICAgICAgPGlvbi1pY29uIFtuYW1lXT1cIml0ZW0uaWNvblwiPjwvaW9uLWljb24+XG4gICAgICAgICAgICAgICAgICB7eyBpdGVtLmxhYmVsIHwgdHJhbnNsYXRlIH19XG4gICAgICAgICAgICAgICAgPC9tYXQtb3B0aW9uPlxuICAgICAgICAgICAgICA8L21hdC1zZWxlY3Q+XG5cbiAgICAgICAgICAgICAgPGJ1dHRvblxuICAgICAgICAgICAgICAgIG1hdC1pY29uLWJ1dHRvblxuICAgICAgICAgICAgICAgIG1hdFN1ZmZpeFxuICAgICAgICAgICAgICAgIHRhYmluZGV4PVwiLTFcIlxuICAgICAgICAgICAgICAgIHR5cGU9XCJidXR0b25cIlxuICAgICAgICAgICAgICAgIChjbGljayk9XCJjbGVhckNvbnRyb2xWYWx1ZSgkZXZlbnQsIGZpbHRlckZvcm0uY29udHJvbHMuc3RhdHVzSWQpXCJcbiAgICAgICAgICAgICAgICBbaGlkZGVuXT1cImZpbHRlckZvcm0uY29udHJvbHMuc3RhdHVzSWQuZGlzYWJsZWQgfHwgIWZpbHRlckZvcm0uY29udHJvbHMuc3RhdHVzSWQudmFsdWVcIlxuICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgPG1hdC1pY29uPmNsb3NlPC9tYXQtaWNvbj5cbiAgICAgICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgICA8L21hdC1mb3JtLWZpZWxkPlxuICAgICAgICAgIDwvaW9uLWNvbD5cblxuICAgICAgICAgIDxpb24tY29sPlxuICAgICAgICAgICAgPCEtLSB1c2VyIHByb2ZpbGVzIC0tPlxuICAgICAgICAgICAgPG1hdC1jaGlwcy1maWVsZFxuICAgICAgICAgICAgICBmb3JtQ29udHJvbE5hbWU9XCJ1c2VyUHJvZmlsZXNcIlxuICAgICAgICAgICAgICBbcGxhY2Vob2xkZXJdPVwiJ1VTRVIuUFJPRklMRVMnIHwgdHJhbnNsYXRlXCJcbiAgICAgICAgICAgICAgY2hpcENvbG9yPVwiYWNjZW50XCJcbiAgICAgICAgICAgICAgW2l0ZW1zXT1cInVzZXJQcm9maWxlTGlzdFwiXG4gICAgICAgICAgICAgIFtkaXNwbGF5QXR0cmlidXRlc109XCJbJ25hbWUnXVwiXG4gICAgICAgICAgICAgIFtjbGVhcmFibGVdPVwidHJ1ZVwiPlxuICAgICAgICAgICAgPC9tYXQtY2hpcHMtZmllbGQ+XG4gICAgICAgICAgPC9pb24tY29sPlxuICAgICAgICA8L2lvbi1yb3c+XG4gICAgICA8L2lvbi1ncmlkPlxuICAgIDwvZm9ybT5cblxuICAgIDxtYXQtYWN0aW9uLXJvdz5cbiAgICAgIDwhLS0gQ291bnRlciAgLS0+XG4gICAgICA8aW9uLWxhYmVsXG4gICAgICAgIFtoaWRkZW5dPVwiKGxvYWRpbmdTdWJqZWN0IHwgYXN5bmMpID09PSB0cnVlIHx8IGZpbHRlckZvcm0uZGlydHlcIlxuICAgICAgICBbY29sb3JdPVwiZW1wdHkgJiYgJ2RhbmdlcidcIlxuICAgICAgICBjbGFzcz1cImlvbi1wYWRkaW5nXCJcbiAgICAgID5cbiAgICAgICAge3tcbiAgICAgICAgICAodG90YWxSb3dDb3VudCA/ICdDT01NT04uUkVTVUxUX0NPVU5UJyA6ICdDT01NT04uTk9fUkVTVUxUJylcbiAgICAgICAgICAgIHwgdHJhbnNsYXRlXG4gICAgICAgICAgICAgIDoge1xuICAgICAgICAgICAgICAgICAgY291bnQ6ICh0b3RhbFJvd0NvdW50IHwgbnVtYmVyRm9ybWF0KSxcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgIH19XG4gICAgICA8L2lvbi1sYWJlbD5cblxuICAgICAgPGRpdiBjbGFzcz1cInRvb2xiYXItc3BhY2VyXCI+PC9kaXY+XG5cbiAgICAgIDwhLS0gQ2xvc2UgcGFuZWwgLS0+XG4gICAgICA8aW9uLWJ1dHRvblxuICAgICAgICBtYXQtYnV0dG9uXG4gICAgICAgIGZpbGw9XCJjbGVhclwiXG4gICAgICAgIGNvbG9yPVwiZGFya1wiXG4gICAgICAgIChjbGljayk9XCJmaWx0ZXJFeHBhbnNpb25QYW5lbC5jbG9zZSgpXCJcbiAgICAgICAgW2Rpc2FibGVkXT1cImxvYWRpbmdTdWJqZWN0IHwgYXN5bmNcIlxuICAgICAgPlxuICAgICAgICA8aW9uLXRleHQgdHJhbnNsYXRlPkNPTU1PTi5CVE5fQ0xPU0U8L2lvbi10ZXh0PlxuICAgICAgPC9pb24tYnV0dG9uPlxuXG4gICAgICA8IS0tIFNlYXJjaCBidXR0b24gLS0+XG4gICAgICA8aW9uLWJ1dHRvblxuICAgICAgICBtYXQtYnV0dG9uXG4gICAgICAgIFtjb2xvcl09XCJmaWx0ZXJGb3JtLmRpcnR5ID8gJ3RlcnRpYXJ5JyA6ICdkYXJrJ1wiXG4gICAgICAgIFtmaWxsXT1cImZpbHRlckZvcm0uZGlydHkgPyAnc29saWQnIDogJ2NsZWFyJ1wiXG4gICAgICAgIChjbGljayk9XCJhcHBseUZpbHRlckFuZENsb3NlUGFuZWwoJGV2ZW50KVwiXG4gICAgICAgIFtkaXNhYmxlZF09XCJsb2FkaW5nU3ViamVjdCB8IGFzeW5jXCJcbiAgICAgID5cbiAgICAgICAgPGlvbi10ZXh0IHRyYW5zbGF0ZT5DT01NT04uQlROX0FQUExZPC9pb24tdGV4dD5cbiAgICAgIDwvaW9uLWJ1dHRvbj5cbiAgICA8L21hdC1hY3Rpb24tcm93PlxuICA8L21hdC1leHBhbnNpb24tcGFuZWw+XG5cbiAgPCEtLSBlcnJvciAtLT5cbiAgPGlvbi1pdGVtICpuZ0lmPVwibW9iaWxlICYmIChlcnJvclN1YmplY3QgfCBhc3luYyk7IGxldCBlcnJvclwiIGxpbmVzPVwibm9uZVwiPlxuICAgIDxpb24taWNvbiBjb2xvcj1cImRhbmdlclwiIHNsb3Q9XCJzdGFydFwiIG5hbWU9XCJhbGVydC1jaXJjbGVcIj48L2lvbi1pY29uPlxuICAgIDxpb24tbGFiZWwgY29sb3I9XCJkYW5nZXJcIiBjbGFzcz1cImVycm9yXCIgW2lubmVySFRNTF09XCJlcnJvciB8IHRyYW5zbGF0ZVwiPjwvaW9uLWxhYmVsPlxuICA8L2lvbi1pdGVtPlxuXG4gIDxkaXYgY2xhc3M9XCJ0YWJsZS1jb250YWluZXJcIj5cbiAgICA8dGFibGVcbiAgICAgICN0YWJsZVxuICAgICAgbWF0LXRhYmxlXG4gICAgICBtYXRTb3J0XG4gICAgICBbY2xhc3MuY29tcGFjdF09XCJjb21wYWN0XCJcbiAgICAgIFtkYXRhU291cmNlXT1cImRhdGFTb3VyY2VcIlxuICAgICAgW21hdFNvcnRBY3RpdmVdPVwiZGVmYXVsdFNvcnRCeVwiXG4gICAgICBbbWF0U29ydERpcmVjdGlvbl09XCJkZWZhdWx0U29ydERpcmVjdGlvblwiXG4gICAgICBtYXRTb3J0RGlzYWJsZUNsZWFyXG4gICAgICBbdHJhY2tCeV09XCJ0cmFja0J5Rm5cIlxuICAgID5cbiAgICAgIDxuZy1jb250YWluZXIgbWF0Q29sdW1uRGVmPVwic2VsZWN0XCIgW3N0aWNreV09XCJzdGlja3lcIj5cbiAgICAgICAgPHRoIG1hdC1oZWFkZXItY2VsbCAqbWF0SGVhZGVyQ2VsbERlZiBbY2xhc3MuY2RrLXZpc3VhbGx5LWhpZGRlbl09XCIhaW5saW5lRWRpdGlvblwiPlxuICAgICAgICAgIDxtYXQtY2hlY2tib3hcbiAgICAgICAgICAgIChjaGFuZ2UpPVwiJGV2ZW50ID8gbWFzdGVyVG9nZ2xlKCkgOiBudWxsXCJcbiAgICAgICAgICAgIFtjaGVja2VkXT1cInRoaXMgfCBpc0FsbFNlbGVjdGVkXCJcbiAgICAgICAgICAgIFtpbmRldGVybWluYXRlXT1cInRoaXMgfCBpc05vdEFsbFNlbGVjdGVkXCJcbiAgICAgICAgICA+PC9tYXQtY2hlY2tib3g+XG4gICAgICAgIDwvdGg+XG4gICAgICAgIDx0ZCBtYXQtY2VsbCAqbWF0Q2VsbERlZj1cImxldCByb3dcIiBbY2xhc3MuY2RrLXZpc3VhbGx5LWhpZGRlbl09XCIhaW5saW5lRWRpdGlvblwiPlxuICAgICAgICAgIDxtYXQtY2hlY2tib3ggKGNsaWNrKT1cInRvZ2dsZVNlbGVjdFJvdygkZXZlbnQsIHJvdylcIiBbY2hlY2tlZF09XCJzZWxlY3Rpb24gfCBpc1NlbGVjdGVkOiByb3dcIj48L21hdC1jaGVja2JveD5cbiAgICAgICAgPC90ZD5cbiAgICAgIDwvbmctY29udGFpbmVyPlxuXG4gICAgICA8IS0tIElkIENvbHVtbiAtLT5cbiAgICAgIDxuZy1jb250YWluZXIgbWF0Q29sdW1uRGVmPVwiaWRcIiBbc3RpY2t5XT1cInN0aWNreVwiPlxuICAgICAgICA8dGggbWF0LWhlYWRlci1jZWxsICptYXRIZWFkZXJDZWxsRGVmIG1hdC1zb3J0LWhlYWRlcj5cbiAgICAgICAgICA8aW9uLWxhYmVsPiM8L2lvbi1sYWJlbD5cbiAgICAgICAgPC90aD5cbiAgICAgICAgPHRkIG1hdC1jZWxsICptYXRDZWxsRGVmPVwibGV0IHJvd1wiPlxuICAgICAgICAgIDxpb24tbGFiZWw+e3sgcm93LmN1cnJlbnREYXRhLmlkIH19PC9pb24tbGFiZWw+XG4gICAgICAgIDwvdGQ+XG4gICAgICA8L25nLWNvbnRhaW5lcj5cblxuICAgICAgPCEtLSBhdmF0YXIgQ29sdW1uIC0tPlxuICAgICAgPG5nLWNvbnRhaW5lciBtYXRDb2x1bW5EZWY9XCJhdmF0YXJcIiBbc3RpY2t5XT1cInN0aWNreVwiPlxuICAgICAgICA8dGggbWF0LWhlYWRlci1jZWxsICptYXRIZWFkZXJDZWxsRGVmPjwvdGg+XG4gICAgICAgIDx0ZCBtYXQtY2VsbCAqbWF0Q2VsbERlZj1cImxldCByb3dcIj5cbiAgICAgICAgICA8aW9uLWF2YXRhciBbc3R5bGUuYmFja2dyb3VuZC1jb2xvcl09XCInd2hpdGUnXCI+XG4gICAgICAgICAgICA8aW9uLWltZyAqbmdJZj1cInJvdy5jdXJyZW50RGF0YS5hdmF0YXI7IGxldCBhdmF0YXJVcmw7IGVsc2U6IGdlbmVyYXRlSWNvblwiIFtzcmNdPVwiYXZhdGFyVXJsXCI+PC9pb24taW1nPlxuICAgICAgICAgICAgPG5nLXRlbXBsYXRlICNnZW5lcmF0ZUljb24+XG4gICAgICAgICAgICAgIDxzdmcgd2lkdGg9XCIzOVwiIGhlaWdodD1cIjM5XCIgW2RhdGEtamRlbnRpY29uLXZhbHVlXT1cInJvdy5jdXJyZW50RGF0YS5pZFwiPjwvc3ZnPlxuICAgICAgICAgICAgPC9uZy10ZW1wbGF0ZT5cbiAgICAgICAgICA8L2lvbi1hdmF0YXI+XG4gICAgICAgIDwvdGQ+XG4gICAgICA8L25nLWNvbnRhaW5lcj5cblxuICAgICAgPCEtLSBsYXN0TmFtZSAgLS0+XG4gICAgICA8bmctY29udGFpbmVyIG1hdENvbHVtbkRlZj1cImxhc3ROYW1lXCI+XG4gICAgICAgIDx0aCBtYXQtaGVhZGVyLWNlbGwgKm1hdEhlYWRlckNlbGxEZWYgbWF0LXNvcnQtaGVhZGVyPlxuICAgICAgICAgIDxzcGFuIHRyYW5zbGF0ZT5VU0VSLkxBU1RfTkFNRTwvc3Bhbj5cbiAgICAgICAgPC90aD5cbiAgICAgICAgPHRkIG1hdC1jZWxsICptYXRDZWxsRGVmPVwibGV0IHJvd1wiIChjbGljayk9XCJmb2N1c0NvbHVtbiA9ICdsYXN0TmFtZSdcIj5cbiAgICAgICAgICA8bWF0LWZvcm0tZmllbGQgKm5nSWY9XCJyb3cuZWRpdGluZzsgZWxzZSByZWFkb25seUNlbGxcIj5cbiAgICAgICAgICAgIDxpbnB1dFxuICAgICAgICAgICAgICBtYXRJbnB1dFxuICAgICAgICAgICAgICBbZm9ybUNvbnRyb2xdPVwicm93LnZhbGlkYXRvci5jb250cm9sc1snbGFzdE5hbWUnXVwiXG4gICAgICAgICAgICAgIFtwbGFjZWhvbGRlcl09XCInVVNFUi5MQVNUX05BTUUnIHwgdHJhbnNsYXRlXCJcbiAgICAgICAgICAgICAgW3JlYWRvbmx5XT1cIiFyb3cuZWRpdGluZ1wiXG4gICAgICAgICAgICAgIFthcHBBdXRvZm9jdXNdPVwicm93LmVkaXRpbmcgJiYgZm9jdXNDb2x1bW4gPT09ICdsYXN0TmFtZSdcIlxuICAgICAgICAgICAgLz5cbiAgICAgICAgICAgIDxtYXQtZXJyb3IgKm5nSWY9XCJyb3cudmFsaWRhdG9yLmNvbnRyb2xzWydsYXN0TmFtZSddLmhhc0Vycm9yKCdyZXF1aXJlZCcpXCIgdHJhbnNsYXRlPlxuICAgICAgICAgICAgICBFUlJPUi5GSUVMRF9SRVFVSVJFRFxuICAgICAgICAgICAgPC9tYXQtZXJyb3I+XG4gICAgICAgICAgICA8bWF0LWVycm9yICpuZ0lmPVwicm93LnZhbGlkYXRvci5jb250cm9sc1snbGFzdE5hbWUnXS5oYXNFcnJvcignbWlubGVuZ3RoJylcIj5cbiAgICAgICAgICAgICAgPHNwYW4+e3sgJ0VSUk9SLkZJRUxEX01JTl9MRU5HVEgnIHwgdHJhbnNsYXRlOiB7IHJlcXVpcmVkTGVuZ3RoOiAyIH0gfX08L3NwYW4+XG4gICAgICAgICAgICA8L21hdC1lcnJvcj5cbiAgICAgICAgICA8L21hdC1mb3JtLWZpZWxkPlxuICAgICAgICAgIDxuZy10ZW1wbGF0ZSAjcmVhZG9ubHlDZWxsPlxuICAgICAgICAgICAgPGlvbi1sYWJlbCBhcHBBdXRvVGl0bGU+XG4gICAgICAgICAgICAgIHt7IHJvdy52YWxpZGF0b3IgfCBmb3JtR2V0VmFsdWU6ICdsYXN0TmFtZScgfX1cbiAgICAgICAgICAgIDwvaW9uLWxhYmVsPlxuICAgICAgICAgIDwvbmctdGVtcGxhdGU+XG4gICAgICAgIDwvdGQ+XG4gICAgICA8L25nLWNvbnRhaW5lcj5cblxuICAgICAgPCEtLSBmaXJzdG5hbWUgLS0+XG4gICAgICA8bmctY29udGFpbmVyIG1hdENvbHVtbkRlZj1cImZpcnN0TmFtZVwiPlxuICAgICAgICA8dGggbWF0LWhlYWRlci1jZWxsICptYXRIZWFkZXJDZWxsRGVmIG1hdC1zb3J0LWhlYWRlcj5cbiAgICAgICAgICA8c3BhbiB0cmFuc2xhdGU+VVNFUi5GSVJTVF9OQU1FPC9zcGFuPlxuICAgICAgICA8L3RoPlxuICAgICAgICA8dGQgbWF0LWNlbGwgKm1hdENlbGxEZWY9XCJsZXQgcm93XCIgKGNsaWNrKT1cImZvY3VzQ29sdW1uID0gJ2ZpcnN0TmFtZSdcIj5cbiAgICAgICAgICA8bWF0LWZvcm0tZmllbGQgKm5nSWY9XCJyb3cuZWRpdGluZzsgZWxzZSByZWFkb25seUNlbGxcIj5cbiAgICAgICAgICAgIDxpbnB1dFxuICAgICAgICAgICAgICBtYXRJbnB1dFxuICAgICAgICAgICAgICBbZm9ybUNvbnRyb2xdPVwicm93LnZhbGlkYXRvci5jb250cm9sc1snZmlyc3ROYW1lJ11cIlxuICAgICAgICAgICAgICBbcGxhY2Vob2xkZXJdPVwiJ1VTRVIuRklSU1RfTkFNRScgfCB0cmFuc2xhdGVcIlxuICAgICAgICAgICAgICBbcmVhZG9ubHldPVwiIXJvdy5lZGl0aW5nXCJcbiAgICAgICAgICAgICAgW2FwcEF1dG9mb2N1c109XCJyb3cuZWRpdGluZyAmJiBmb2N1c0NvbHVtbiA9PT0gJ2ZpcnN0TmFtZSdcIlxuICAgICAgICAgICAgLz5cbiAgICAgICAgICAgIDxtYXQtZXJyb3IgKm5nSWY9XCJyb3cudmFsaWRhdG9yLmNvbnRyb2xzWydmaXJzdE5hbWUnXS5oYXNFcnJvcigncmVxdWlyZWQnKVwiIHRyYW5zbGF0ZT5cbiAgICAgICAgICAgICAgRVJST1IuRklFTERfUkVRVUlSRURcbiAgICAgICAgICAgIDwvbWF0LWVycm9yPlxuICAgICAgICAgICAgPG1hdC1lcnJvciAqbmdJZj1cInJvdy52YWxpZGF0b3IuY29udHJvbHNbJ2ZpcnN0TmFtZSddLmhhc0Vycm9yKCdtaW5sZW5ndGgnKVwiPlxuICAgICAgICAgICAgICA8c3Bhbj57eyAnRVJST1IuRklFTERfTUlOX0xFTkdUSCcgfCB0cmFuc2xhdGU6IHsgcmVxdWlyZWRMZW5ndGg6IDIgfSB9fTwvc3Bhbj5cbiAgICAgICAgICAgIDwvbWF0LWVycm9yPlxuICAgICAgICAgIDwvbWF0LWZvcm0tZmllbGQ+XG4gICAgICAgICAgPG5nLXRlbXBsYXRlICNyZWFkb25seUNlbGw+XG4gICAgICAgICAgICA8aW9uLWxhYmVsIGFwcEF1dG9UaXRsZT5cbiAgICAgICAgICAgICAge3sgcm93LnZhbGlkYXRvciB8IGZvcm1HZXRWYWx1ZTogJ2ZpcnN0TmFtZScgfX1cbiAgICAgICAgICAgIDwvaW9uLWxhYmVsPlxuICAgICAgICAgIDwvbmctdGVtcGxhdGU+XG4gICAgICAgIDwvdGQ+XG4gICAgICA8L25nLWNvbnRhaW5lcj5cblxuICAgICAgPCEtLSBlbWFpbCAgLS0+XG4gICAgICA8bmctY29udGFpbmVyIG1hdENvbHVtbkRlZj1cImVtYWlsXCI+XG4gICAgICAgIDx0aCBtYXQtaGVhZGVyLWNlbGwgKm1hdEhlYWRlckNlbGxEZWYgbWF0LXNvcnQtaGVhZGVyPlxuICAgICAgICAgIDxzcGFuIHRyYW5zbGF0ZT5VU0VSLkVNQUlMPC9zcGFuPlxuICAgICAgICA8L3RoPlxuICAgICAgICA8dGQgbWF0LWNlbGwgKm1hdENlbGxEZWY9XCJsZXQgcm93XCIgKGNsaWNrKT1cImZvY3VzQ29sdW1uID0gJ2VtYWlsJ1wiPlxuICAgICAgICAgIDxtYXQtZm9ybS1maWVsZCAqbmdJZj1cInJvdy5lZGl0aW5nOyBlbHNlIHJlYWRvbmx5Q2VsbFwiPlxuICAgICAgICAgICAgPGlucHV0XG4gICAgICAgICAgICAgIG1hdElucHV0XG4gICAgICAgICAgICAgIFtmb3JtQ29udHJvbF09XCJyb3cudmFsaWRhdG9yLmNvbnRyb2xzWydlbWFpbCddXCJcbiAgICAgICAgICAgICAgW3BsYWNlaG9sZGVyXT1cIidVU0VSLkVNQUlMJyB8IHRyYW5zbGF0ZVwiXG4gICAgICAgICAgICAgIFtyZWFkb25seV09XCIhcm93LmVkaXRpbmdcIlxuICAgICAgICAgICAgICBbYXBwQXV0b2ZvY3VzXT1cInJvdy5lZGl0aW5nICYmIGZvY3VzQ29sdW1uID09PSAnZW1haWwnXCJcbiAgICAgICAgICAgIC8+XG4gICAgICAgICAgICA8bWF0LWVycm9yICpuZ0lmPVwicm93LnZhbGlkYXRvci5jb250cm9sc1snZW1haWwnXS5oYXNFcnJvcigncmVxdWlyZWQnKVwiIHRyYW5zbGF0ZT5cbiAgICAgICAgICAgICAgRVJST1IuRklFTERfUkVRVUlSRURcbiAgICAgICAgICAgIDwvbWF0LWVycm9yPlxuICAgICAgICAgICAgPG1hdC1lcnJvciAqbmdJZj1cInJvdy52YWxpZGF0b3IuY29udHJvbHNbJ2VtYWlsJ10uaGFzRXJyb3IoJ2VtYWlsJylcIj5cbiAgICAgICAgICAgICAgPHNwYW4gdHJhbnNsYXRlPkVSUk9SLkZJRUxEX05PVF9WQUxJRF9FTUFJTDwvc3Bhbj5cbiAgICAgICAgICAgIDwvbWF0LWVycm9yPlxuICAgICAgICAgIDwvbWF0LWZvcm0tZmllbGQ+XG4gICAgICAgICAgPG5nLXRlbXBsYXRlICNyZWFkb25seUNlbGw+XG4gICAgICAgICAgICA8aW9uLWxhYmVsIGFwcEF1dG9UaXRsZT5cbiAgICAgICAgICAgICAge3sgcm93LnZhbGlkYXRvciB8IGZvcm1HZXRWYWx1ZTogJ2VtYWlsJyB9fVxuICAgICAgICAgICAgPC9pb24tbGFiZWw+XG4gICAgICAgICAgPC9uZy10ZW1wbGF0ZT5cbiAgICAgICAgPC90ZD5cbiAgICAgIDwvbmctY29udGFpbmVyPlxuXG4gICAgICA8IS0tIGFkZGl0aW9uYWwgZmllbGRzIC0tPlxuICAgICAgPG5nLWNvbnRhaW5lciAqbmdGb3I9XCJsZXQgZGVmaW5pdGlvbiBvZiBhZGRpdGlvbmFsRmllbGRzXCIgW21hdENvbHVtbkRlZl09XCJkZWZpbml0aW9uLmtleVwiPlxuICAgICAgICA8dGggbWF0LWhlYWRlci1jZWxsICptYXRIZWFkZXJDZWxsRGVmPlxuICAgICAgICAgIDxzcGFuPnt7IGRlZmluaXRpb24ubGFiZWwgfCB0cmFuc2xhdGUgfX08L3NwYW4+XG4gICAgICAgIDwvdGg+XG4gICAgICAgIDx0ZCBtYXQtY2VsbCAqbWF0Q2VsbERlZj1cImxldCByb3dcIiAoY2xpY2spPVwiZm9jdXNDb2x1bW4gPSBkZWZpbml0aW9uLmtleVwiPlxuICAgICAgICAgIDxhcHAtZm9ybS1maWVsZFxuICAgICAgICAgICAgZmxvYXRMYWJlbD1cIm5ldmVyXCJcbiAgICAgICAgICAgIFtkZWZpbml0aW9uXT1cImRlZmluaXRpb25cIlxuICAgICAgICAgICAgW2Zvcm1Db250cm9sXT1cInJvdy52YWxpZGF0b3IuY29udHJvbHNbZGVmaW5pdGlvbi5rZXldXCJcbiAgICAgICAgICAgIFtyZXF1aXJlZF09XCJkZWZpbml0aW9uLmV4dHJhPy5hY2NvdW50Py5yZXF1aXJlZFwiXG4gICAgICAgICAgICBbYXV0b2ZvY3VzXT1cInJvdy5lZGl0aW5nICYmIGZvY3VzQ29sdW1uID09PSBkZWZpbml0aW9uLmtleVwiXG4gICAgICAgICAgPjwvYXBwLWZvcm0tZmllbGQ+XG4gICAgICAgIDwvdGQ+XG4gICAgICA8L25nLWNvbnRhaW5lcj5cblxuICAgICAgPCEtLSBwcm9maWxlIGNvbHVtbiAgLS0+XG4gICAgICA8bmctY29udGFpbmVyIG1hdENvbHVtbkRlZj1cInByb2ZpbGVcIj5cbiAgICAgICAgPHRoIG1hdC1oZWFkZXItY2VsbCAqbWF0SGVhZGVyQ2VsbERlZj5cbiAgICAgICAgICA8c3BhbiB0cmFuc2xhdGU+VVNFUi5QUk9GSUxFPC9zcGFuPlxuICAgICAgICA8L3RoPlxuICAgICAgICA8dGQgbWF0LWNlbGwgKm1hdENlbGxEZWY9XCJsZXQgcm93XCIgKGNsaWNrKT1cImZvY3VzQ29sdW1uID0gJ3Byb2ZpbGUnXCI+XG4gICAgICAgICAgPG1hdC1mb3JtLWZpZWxkPlxuICAgICAgICAgICAgPG1hdC1zZWxlY3RcbiAgICAgICAgICAgICAgW2Zvcm1Db250cm9sXT1cInJvdy52YWxpZGF0b3IuY29udHJvbHNbJ21haW5Qcm9maWxlJ11cIlxuICAgICAgICAgICAgICBbcGxhY2Vob2xkZXJdPVwiJ1VTRVIuUFJPRklMRScgfCB0cmFuc2xhdGVcIlxuICAgICAgICAgICAgPlxuICAgICAgICAgICAgICA8bWF0LW9wdGlvbiAqbmdGb3I9XCJsZXQgaXRlbSBvZiBwcm9maWxlc1wiIFt2YWx1ZV09XCJpdGVtXCI+XG4gICAgICAgICAgICAgICAge3sgJ1VTRVIuUFJPRklMRV9FTlVNLicgKyBpdGVtIHwgdXBwZXJjYXNlIHwgdHJhbnNsYXRlIH19XG4gICAgICAgICAgICAgIDwvbWF0LW9wdGlvbj5cbiAgICAgICAgICAgIDwvbWF0LXNlbGVjdD5cbiAgICAgICAgICAgIDxtYXQtZXJyb3IgKm5nSWY9XCJyb3cudmFsaWRhdG9yLmNvbnRyb2xzWydtYWluUHJvZmlsZSddLmhhc0Vycm9yKCdyZXF1aXJlZCcpXCIgdHJhbnNsYXRlPlxuICAgICAgICAgICAgICBFUlJPUi5GSUVMRF9SRVFVSVJFRFxuICAgICAgICAgICAgPC9tYXQtZXJyb3I+XG4gICAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cbiAgICAgICAgPC90ZD5cbiAgICAgIDwvbmctY29udGFpbmVyPlxuXG4gICAgICA8IS0tIFN0YXR1cyBjb2x1bW4gIC0tPlxuICAgICAgPG5nLWNvbnRhaW5lciBtYXRDb2x1bW5EZWY9XCJzdGF0dXNcIj5cbiAgICAgICAgPHRoIG1hdC1oZWFkZXItY2VsbCAqbWF0SGVhZGVyQ2VsbERlZj5cbiAgICAgICAgICA8c3BhbiB0cmFuc2xhdGU+VVNFUi5TVEFUVVM8L3NwYW4+XG4gICAgICAgIDwvdGg+XG4gICAgICAgIDx0ZCBtYXQtY2VsbCAqbWF0Q2VsbERlZj1cImxldCByb3dcIiAoY2xpY2spPVwiZm9jdXNDb2x1bW4gPSAnc3RhdHVzJ1wiPlxuICAgICAgICAgIDxtYXQtZm9ybS1maWVsZD5cbiAgICAgICAgICAgIDxtYXQtc2VsZWN0XG4gICAgICAgICAgICAgIFtmb3JtQ29udHJvbF09XCJyb3cudmFsaWRhdG9yLmNvbnRyb2xzWydzdGF0dXNJZCddXCJcbiAgICAgICAgICAgICAgW3BsYWNlaG9sZGVyXT1cIidSRUZFUkVOVElBTC5TVEFUVVMnIHwgdHJhbnNsYXRlXCJcbiAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgPG1hdC1zZWxlY3QtdHJpZ2dlcj5cbiAgICAgICAgICAgICAgICA8c3BhbiAqbmdJZj1cInJvdy52YWxpZGF0b3IuY29udHJvbHNbJ3N0YXR1c0lkJ10udmFsdWUgPj0gMFwiPlxuICAgICAgICAgICAgICAgICAge3sgc3RhdHVzQnlJZFtyb3cudmFsaWRhdG9yLmNvbnRyb2xzWydzdGF0dXNJZCddLnZhbHVlXT8ubGFiZWwgfCB0cmFuc2xhdGUgfX1cbiAgICAgICAgICAgICAgICA8L3NwYW4+XG4gICAgICAgICAgICAgIDwvbWF0LXNlbGVjdC10cmlnZ2VyPlxuICAgICAgICAgICAgICA8bWF0LW9wdGlvbiAqbmdGb3I9XCJsZXQgaXRlbSBvZiBzdGF0dXNMaXN0XCIgW3ZhbHVlXT1cIml0ZW0uaWRcIj5cbiAgICAgICAgICAgICAgICA8bWF0LWljb24+PGlvbi1pY29uIFtuYW1lXT1cIml0ZW0uaWNvblwiPjwvaW9uLWljb24+PC9tYXQtaWNvbj5cbiAgICAgICAgICAgICAgICB7eyBpdGVtLmxhYmVsIHwgdHJhbnNsYXRlIH19XG4gICAgICAgICAgICAgIDwvbWF0LW9wdGlvbj5cbiAgICAgICAgICAgIDwvbWF0LXNlbGVjdD5cbiAgICAgICAgICAgIDxtYXQtZXJyb3IgKm5nSWY9XCJyb3cudmFsaWRhdG9yLmNvbnRyb2xzWydzdGF0dXNJZCddLmhhc0Vycm9yKCdyZXF1aXJlZCcpXCIgdHJhbnNsYXRlPlxuICAgICAgICAgICAgICBFUlJPUi5GSUVMRF9SRVFVSVJFRFxuICAgICAgICAgICAgPC9tYXQtZXJyb3I+XG4gICAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cbiAgICAgICAgPC90ZD5cbiAgICAgIDwvbmctY29udGFpbmVyPlxuXG4gICAgICA8IS0tIHVzZXJuYW1lIC0tPlxuICAgICAgPG5nLWNvbnRhaW5lciBtYXRDb2x1bW5EZWY9XCJ1c2VybmFtZVwiPlxuICAgICAgICA8dGggbWF0LWhlYWRlci1jZWxsICptYXRIZWFkZXJDZWxsRGVmIG1hdC1zb3J0LWhlYWRlcj5cbiAgICAgICAgICA8c3BhbiB0cmFuc2xhdGU+VVNFUi5VU0VSTkFNRTwvc3Bhbj5cbiAgICAgICAgPC90aD5cbiAgICAgICAgPHRkIG1hdC1jZWxsICptYXRDZWxsRGVmPVwibGV0IHJvd1wiIChjbGljayk9XCJmb2N1c0NvbHVtbiA9ICd1c2VybmFtZSdcIj5cbiAgICAgICAgICA8bWF0LWZvcm0tZmllbGQgKm5nSWY9XCJyb3cuZWRpdGluZzsgZWxzZSByZWFkb25seUNlbGxcIj5cbiAgICAgICAgICAgIDxpbnB1dFxuICAgICAgICAgICAgICBtYXRJbnB1dFxuICAgICAgICAgICAgICBbZm9ybUNvbnRyb2xdPVwicm93LnZhbGlkYXRvci5jb250cm9scy51c2VybmFtZVwiXG4gICAgICAgICAgICAgIFtwbGFjZWhvbGRlcl09XCInVVNFUi5VU0VSTkFNRScgfCB0cmFuc2xhdGVcIlxuICAgICAgICAgICAgICBbcmVhZG9ubHldPVwiIXJvdy5lZGl0aW5nXCJcbiAgICAgICAgICAgICAgW2FwcEF1dG9mb2N1c109XCJyb3cuZWRpdGluZyAmJiBmb2N1c0NvbHVtbiA9PT0gJ3VzZXJuYW1lJ1wiXG4gICAgICAgICAgICAvPlxuICAgICAgICAgICAgPG1hdC1lcnJvciAqbmdJZj1cInJvdy52YWxpZGF0b3IuY29udHJvbHMudXNlcm5hbWUuaGFzRXJyb3IoJ3JlcXVpcmVkJylcIiB0cmFuc2xhdGU+XG4gICAgICAgICAgICAgIEVSUk9SLkZJRUxEX1JFUVVJUkVEXG4gICAgICAgICAgICA8L21hdC1lcnJvcj5cbiAgICAgICAgICA8L21hdC1mb3JtLWZpZWxkPlxuICAgICAgICAgIDxuZy10ZW1wbGF0ZSAjcmVhZG9ubHlDZWxsPlxuICAgICAgICAgICAgPGlvbi1sYWJlbCBhcHBBdXRvVGl0bGU+XG4gICAgICAgICAgICAgIHt7IHJvdy52YWxpZGF0b3IgfCBmb3JtR2V0VmFsdWU6ICd1c2VybmFtZScgfX1cbiAgICAgICAgICAgIDwvaW9uLWxhYmVsPlxuICAgICAgICAgIDwvbmctdGVtcGxhdGU+XG4gICAgICAgIDwvdGQ+XG4gICAgICA8L25nLWNvbnRhaW5lcj5cblxuICAgICAgPCEtLSB1c2VybmFtZSBleHRyYW5ldCAtLT5cbiAgICAgIDxuZy1jb250YWluZXIgbWF0Q29sdW1uRGVmPVwidXNlcm5hbWVFeHRyYW5ldFwiPlxuICAgICAgICA8dGggbWF0LWhlYWRlci1jZWxsICptYXRIZWFkZXJDZWxsRGVmIG1hdC1zb3J0LWhlYWRlcj5cbiAgICAgICAgICA8c3BhbiB0cmFuc2xhdGU+VVNFUi5VU0VSTkFNRV9FWFRSQU5FVDwvc3Bhbj5cbiAgICAgICAgPC90aD5cbiAgICAgICAgPHRkIG1hdC1jZWxsICptYXRDZWxsRGVmPVwibGV0IHJvd1wiIChjbGljayk9XCJmb2N1c0NvbHVtbiA9ICd1c2VybmFtZUV4dHJhbmV0J1wiPlxuICAgICAgICAgIDxtYXQtZm9ybS1maWVsZCAqbmdJZj1cInJvdy5lZGl0aW5nOyBlbHNlIHJlYWRvbmx5Q2VsbFwiPlxuICAgICAgICAgICAgPGlucHV0XG4gICAgICAgICAgICAgIG1hdElucHV0XG4gICAgICAgICAgICAgIFtmb3JtQ29udHJvbF09XCJyb3cudmFsaWRhdG9yLmNvbnRyb2xzLnVzZXJuYW1lRXh0cmFuZXRcIlxuICAgICAgICAgICAgICBbcGxhY2Vob2xkZXJdPVwiJ1VTRVIuVVNFUk5BTUVfRVhUUkFORVQnIHwgdHJhbnNsYXRlXCJcbiAgICAgICAgICAgICAgW3JlYWRvbmx5XT1cIiFyb3cuZWRpdGluZ1wiXG4gICAgICAgICAgICAgIFthcHBBdXRvZm9jdXNdPVwicm93LmVkaXRpbmcgJiYgZm9jdXNDb2x1bW4gPT09ICd1c2VybmFtZUV4dHJhbmV0J1wiXG4gICAgICAgICAgICAvPlxuICAgICAgICAgICAgPG1hdC1lcnJvciAqbmdJZj1cInJvdy52YWxpZGF0b3IuY29udHJvbHMudXNlcm5hbWVFeHRyYW5ldC5oYXNFcnJvcigncmVxdWlyZWQnKVwiIHRyYW5zbGF0ZT5cbiAgICAgICAgICAgICAgRVJST1IuRklFTERfUkVRVUlSRURcbiAgICAgICAgICAgIDwvbWF0LWVycm9yPlxuICAgICAgICAgIDwvbWF0LWZvcm0tZmllbGQ+XG4gICAgICAgICAgPG5nLXRlbXBsYXRlICNyZWFkb25seUNlbGw+XG4gICAgICAgICAgICA8aW9uLWxhYmVsIGFwcEF1dG9UaXRsZT5cbiAgICAgICAgICAgICAge3sgcm93LnZhbGlkYXRvciB8IGZvcm1HZXRWYWx1ZTogJ3VzZXJuYW1lRXh0cmFuZXQnIH19XG4gICAgICAgICAgICA8L2lvbi1sYWJlbD5cbiAgICAgICAgICA8L25nLXRlbXBsYXRlPlxuICAgICAgICA8L3RkPlxuICAgICAgPC9uZy1jb250YWluZXI+XG5cbiAgICAgIDwhLS0gcHVia2V5ICAtLT5cbiAgICAgIDxuZy1jb250YWluZXIgbWF0Q29sdW1uRGVmPVwicHVia2V5XCI+XG4gICAgICAgIDx0aCBtYXQtaGVhZGVyLWNlbGwgKm1hdEhlYWRlckNlbGxEZWYgbWF0LXNvcnQtaGVhZGVyPlxuICAgICAgICAgIDxzcGFuIHRyYW5zbGF0ZT5VU0VSLlBVQktFWTwvc3Bhbj5cbiAgICAgICAgPC90aD5cbiAgICAgICAgPHRkXG4gICAgICAgICAgbWF0LWNlbGxcbiAgICAgICAgICAqbWF0Q2VsbERlZj1cImxldCByb3dcIlxuICAgICAgICAgIFt0aXRsZV09XCJyb3cudmFsaWRhdG9yLmNvbnRyb2xzLnB1YmtleS52YWx1ZUNoYW5nZXMgfCBhc3luY1wiXG4gICAgICAgICAgKGNsaWNrKT1cImZvY3VzQ29sdW1uID0gJ3B1YmtleSdcIlxuICAgICAgICA+XG4gICAgICAgICAgPG1hdC1mb3JtLWZpZWxkICpuZ0lmPVwicm93LmVkaXRpbmc7IGVsc2UgcmVhZG9ubHlDZWxsXCI+XG4gICAgICAgICAgICA8aW5wdXRcbiAgICAgICAgICAgICAgbWF0SW5wdXRcbiAgICAgICAgICAgICAgW2Zvcm1Db250cm9sXT1cInJvdy52YWxpZGF0b3IuY29udHJvbHNbJ3B1YmtleSddXCJcbiAgICAgICAgICAgICAgW3BsYWNlaG9sZGVyXT1cIidVU0VSLlBVQktFWScgfCB0cmFuc2xhdGVcIlxuICAgICAgICAgICAgICBbcmVhZG9ubHldPVwiIXJvdy5lZGl0aW5nXCJcbiAgICAgICAgICAgICAgYXV0b2NvbXBsZXRlPVwib2ZmXCJcbiAgICAgICAgICAgIC8+XG4gICAgICAgICAgICA8bWF0LWVycm9yICpuZ0lmPVwicm93LnZhbGlkYXRvci5jb250cm9scy5wdWJrZXkuaGFzRXJyb3IoJ3JlcXVpcmVkJylcIiB0cmFuc2xhdGU+XG4gICAgICAgICAgICAgIEVSUk9SLkZJRUxEX1JFUVVJUkVEXG4gICAgICAgICAgICA8L21hdC1lcnJvcj5cbiAgICAgICAgICAgIDxtYXQtZXJyb3IgKm5nSWY9XCJyb3cudmFsaWRhdG9yLmNvbnRyb2xzLnB1YmtleS5oYXNFcnJvcigncHVia2V5JylcIj5cbiAgICAgICAgICAgICAgPHNwYW4gdHJhbnNsYXRlPkVSUk9SLkZJRUxEX05PVF9WQUxJRF9QVUJLRVk8L3NwYW4+XG4gICAgICAgICAgICA8L21hdC1lcnJvcj5cbiAgICAgICAgICA8L21hdC1mb3JtLWZpZWxkPlxuICAgICAgICAgIDxuZy10ZW1wbGF0ZSAjcmVhZG9ubHlDZWxsPlxuICAgICAgICAgICAgPGlvbi1sYWJlbCBhcHBBdXRvVGl0bGU+XG4gICAgICAgICAgICAgIHt7IHJvdy52YWxpZGF0b3IgfCBmb3JtR2V0VmFsdWU6ICdwdWJrZXknIH19XG4gICAgICAgICAgICA8L2lvbi1sYWJlbD5cbiAgICAgICAgICA8L25nLXRlbXBsYXRlPlxuICAgICAgICA8L3RkPlxuICAgICAgPC9uZy1jb250YWluZXI+XG5cbiAgICAgIDwhLS0gQ3JlYXRpb24gZGF0ZSBjb2x1bW4gLS0+XG4gICAgICA8bmctY29udGFpbmVyIG1hdENvbHVtbkRlZj1cImNyZWF0aW9uRGF0ZVwiPlxuICAgICAgICA8dGggbWF0LWhlYWRlci1jZWxsICptYXRIZWFkZXJDZWxsRGVmIG1hdC1zb3J0LWhlYWRlcj5cbiAgICAgICAgICA8aW9uLWxhYmVsIHRyYW5zbGF0ZT5VU0VSLkNSRUFUSU9OX0RBVEU8L2lvbi1sYWJlbD5cbiAgICAgICAgPC90aD5cbiAgICAgICAgPHRkIG1hdC1jZWxsICptYXRDZWxsRGVmPVwibGV0IHJvd1wiIGNsYXNzPVwibWF0LWZvcm0tZmllbGQtZGlzYWJsZWRcIj5cbiAgICAgICAgICA8aW9uLXRleHQgY2xhc3M9XCJpb24tdGV4dC1lbmRcIiBjb2xvcj1cIm1lZGl1bVwiICpuZ0lmPVwicm93LmlkICE9PSAtMVwiPlxuICAgICAgICAgICAge3sgcm93LmN1cnJlbnREYXRhLmNyZWF0aW9uRGF0ZSB8IGRhdGVGb3JtYXQ6IHsgdGltZTogdHJ1ZSB9IH19XG4gICAgICAgICAgPC9pb24tdGV4dD5cbiAgICAgICAgPC90ZD5cbiAgICAgIDwvbmctY29udGFpbmVyPlxuXG4gICAgICA8IS0tIFVwZGF0ZSBkYXRlIGNvbHVtbiAtLT5cbiAgICAgIDxuZy1jb250YWluZXIgbWF0Q29sdW1uRGVmPVwidXBkYXRlRGF0ZVwiPlxuICAgICAgICA8dGggbWF0LWhlYWRlci1jZWxsICptYXRIZWFkZXJDZWxsRGVmIG1hdC1zb3J0LWhlYWRlcj5cbiAgICAgICAgICA8aW9uLWxhYmVsIHRyYW5zbGF0ZT5VU0VSLlVQREFURV9EQVRFPC9pb24tbGFiZWw+XG4gICAgICAgIDwvdGg+XG4gICAgICAgIDx0ZCBtYXQtY2VsbCAqbWF0Q2VsbERlZj1cImxldCByb3dcIiBjbGFzcz1cIm1hdC1mb3JtLWZpZWxkLWRpc2FibGVkXCI+XG4gICAgICAgICAgPGlvbi10ZXh0IGNsYXNzPVwiaW9uLXRleHQtZW5kXCIgY29sb3I9XCJtZWRpdW1cIiAqbmdJZj1cInJvdy5pZCAhPT0gLTFcIj5cbiAgICAgICAgICAgIHt7IHJvdy5jdXJyZW50RGF0YS51cGRhdGVEYXRlIHwgZGF0ZUZvcm1hdDogeyB0aW1lOiB0cnVlIH0gfX1cbiAgICAgICAgICA8L2lvbi10ZXh0PlxuICAgICAgICA8L3RkPlxuICAgICAgPC9uZy1jb250YWluZXI+XG5cbiAgICAgIDwhLS0gQWN0aW9ucyBidXR0b25zIGNvbHVtbiAtLT5cbiAgICAgIDxhcHAtYWN0aW9ucy1jb2x1bW5cbiAgICAgICAgW3N0aWNreUVuZF09XCJzdGlja3lFbmRcIlxuICAgICAgICAoY2FuY2VsT3JEZWxldGVDbGljayk9XCJjYW5jZWxPckRlbGV0ZSgkZXZlbnQuZXZlbnQsICRldmVudC5yb3cpXCJcbiAgICAgICAgKGNvbmZpcm1FZGl0Q3JlYXRlQ2xpY2spPVwiY29uZmlybUVkaXRDcmVhdGUoJGV2ZW50LmV2ZW50LCAkZXZlbnQucm93KVwiXG4gICAgICAgIChjb25maXJtQW5kQWRkQ2xpY2spPVwiY29uZmlybUFuZEFkZCgkZXZlbnQuZXZlbnQsICRldmVudC5yb3cpXCJcbiAgICAgICAgKGJhY2t3YXJkKT1cImNvbmZpcm1BbmRCYWNrd2FyZCgkZXZlbnQuZXZlbnQsICRldmVudC5yb3cpXCJcbiAgICAgICAgKGZvcndhcmQpPVwiY29uZmlybUFuZEZvcndhcmQoJGV2ZW50LmV2ZW50LCAkZXZlbnQucm93KVwiXG4gICAgICAgIFtjYW5DYW5jZWxdPVwiZmFsc2VcIlxuICAgICAgPlxuICAgICAgICA8IS0tIHRhYmxlIG9wdGlvbnMgbWVudSAtLT5cbiAgICAgICAgPGJ1dHRvblxuICAgICAgICAgIG1hdEhlYWRlclxuICAgICAgICAgIG1hdC1pY29uLWJ1dHRvblxuICAgICAgICAgIFt0aXRsZV09XCInQ09NTU9OLkJUTl9PUFRJT05TJyB8IHRyYW5zbGF0ZVwiXG4gICAgICAgICAgW21hdE1lbnVUcmlnZ2VyRm9yXT1cInRhYmxlT3B0aW9uc01lbnVcIlxuICAgICAgICA+XG4gICAgICAgICAgPG1hdC1pY29uPm1vcmVfdmVydDwvbWF0LWljb24+XG4gICAgICAgIDwvYnV0dG9uPlxuICAgICAgPC9hcHAtYWN0aW9ucy1jb2x1bW4+XG5cbiAgICAgIDx0ciBtYXQtaGVhZGVyLXJvdyAqbWF0SGVhZGVyUm93RGVmPVwiZGlzcGxheWVkQ29sdW1uczsgc3RpY2t5OiB0cnVlXCI+PC90cj5cbiAgICAgIDx0clxuICAgICAgICBtYXQtcm93XG4gICAgICAgICptYXRSb3dEZWY9XCJsZXQgcm93OyBjb2x1bW5zOiBkaXNwbGF5ZWRDb2x1bW5zXCJcbiAgICAgICAgW2NsYXNzLm1hdC1yb3ctc2VsZWN0ZWRdPVwicm93LmVkaXRpbmdcIlxuICAgICAgICBbY2xhc3MubWF0LXJvdy1lcnJvcl09XCJyb3cudmFsaWRhdG9yLmludmFsaWRcIlxuICAgICAgICBbY2xhc3MubWF0LXJvdy1kaXJ0eV09XCJyb3cuY3VycmVudERhdGEuZGlydHlcIlxuICAgICAgICBbY2xhc3MubWF0LXJvdy1kaXNhYmxlZF09XCIhcm93LmVkaXRpbmdcIlxuICAgICAgICAoY2xpY2spPVwiY2xpY2tSb3coJGV2ZW50LCByb3cpXCJcbiAgICAgICAgKGtleWRvd24uZXNjYXBlKT1cImVzY2FwZUVkaXRpbmdSb3coJGV2ZW50KVwiXG4gICAgICAgIFtjZGtUcmFwRm9jdXNdPVwiIXJvdy52YWxpZGF0b3I/LnZhbGlkXCJcbiAgICAgID48L3RyPlxuICAgIDwvdGFibGU+XG5cbiAgICA8IS0tIETDqWNsZW5jaGV1ciBpbnZpc2libGUgcG91ciBsZSBtYXQtbWVudSAtLT5cblxuICAgIEBpZiAobG9hZGluZ1N1YmplY3QgfCBhc3luYykge1xuICAgICAgPGlvbi1pdGVtPlxuICAgICAgICA8aW9uLXNrZWxldG9uLXRleHQgYW5pbWF0ZWQ+PC9pb24tc2tlbGV0b24tdGV4dD5cbiAgICAgIDwvaW9uLWl0ZW0+XG4gICAgfSBAZWxzZSBpZiAodG90YWxSb3dDb3VudCA9PT0gMCkge1xuICAgICAgPGlvbi1pdGVtPlxuICAgICAgICA8aW9uLXRleHQgY29sb3I9XCJkYW5nZXJcIiBjbGFzcz1cInRleHQtaXRhbGljXCIgdHJhbnNsYXRlPkNPTU1PTi5OT19SRVNVTFQ8L2lvbi10ZXh0PlxuICAgICAgPC9pb24taXRlbT5cbiAgICB9XG4gIDwvZGl2PlxuPC9pb24tY29udGVudD5cblxuPCEtLSBUYWJsZSBvcHRpb25zIG1lbnUgLS0+XG48bWF0LW1lbnUgI3RhYmxlT3B0aW9uc01lbnU9XCJtYXRNZW51XCIgeFBvc2l0aW9uPVwiYWZ0ZXJcIj5cbiAgPCEtLSBkaXNwbGF5IGNvbHVtbnMgLS0+XG4gIDxidXR0b24gbWF0LW1lbnUtaXRlbSAoY2xpY2spPVwib3BlblNlbGVjdENvbHVtbnNNb2RhbCgkZXZlbnQpXCI+XG4gICAgPG1hdC1pY29uPnZpZXdfY29sdW1uPC9tYXQtaWNvbj5cbiAgICA8aW9uLWxhYmVsIHRyYW5zbGF0ZT5DT01NT04uRElTUExBWUVEX0NPTFVNTlNfRE9UUzwvaW9uLWxhYmVsPlxuICA8L2J1dHRvbj5cblxuICBAaWYgKHVzZVBhZ2VTZXR0aW5ncykge1xuICAgIDxtYXQtZGl2aWRlcj48L21hdC1kaXZpZGVyPlxuXG4gICAgPCEtLSBDb21wYWN0IG1vZGUgLS0+XG4gICAgPGJ1dHRvbiBtYXQtbWVudS1pdGVtIChjbGljayk9XCJ0b2dnbGVDb21wYWN0TW9kZSgpXCI+XG4gICAgICA8bWF0LWljb24+e3sgY29tcGFjdCA/ICdjaGVja19ib3gnIDogJ2NoZWNrX2JveF9vdXRsaW5lX2JsYW5rJyB9fTwvbWF0LWljb24+XG4gICAgICA8aW9uLWxhYmVsIHRyYW5zbGF0ZT5DT01NT04uQlROX0NPTVBBQ1RfUk9XUzwvaW9uLWxhYmVsPlxuICAgIDwvYnV0dG9uPlxuICB9XG48L21hdC1tZW51PlxuXG48aW9uLWZvb3Rlcj5cbiAgPG1hdC1wYWdpbmF0b3JcbiAgICBbbGVuZ3RoXT1cInRvdGFsUm93Q291bnRcIlxuICAgIFtwYWdlU2l6ZV09XCJkZWZhdWx0UGFnZVNpemVcIlxuICAgIFtwYWdlU2l6ZU9wdGlvbnNdPVwiZGVmYXVsdFBhZ2VTaXplT3B0aW9uc1wiXG4gICAgc2hvd0ZpcnN0TGFzdEJ1dHRvbnNcbiAgPjwvbWF0LXBhZ2luYXRvcj5cblxuICA8YXBwLWZvcm0tYnV0dG9ucy1iYXJcbiAgICAqbmdJZj1cIiFtb2JpbGUgJiYgY2FuRWRpdFwiXG4gICAgKG9uQ2FuY2VsKT1cImNhbmNlbCgkZXZlbnQpXCJcbiAgICAob25TYXZlKT1cInNhdmUoKVwiXG4gICAgW2Rpc2FibGVkXT1cIihsb2FkaW5nU3ViamVjdCB8IGFzeW5jKSA9PT0gdHJ1ZSB8fCAoZGlydHlTdWJqZWN0IHwgYXN5bmMpICE9PSB0cnVlXCJcbiAgPlxuICAgIDwhLS0gZXJyb3IgLS0+XG4gICAgPGlvbi1pdGVtICpuZ0lmPVwiZXJyb3JTdWJqZWN0IHwgYXN5bmM7IGxldCBlcnJvclwiIGxpbmVzPVwibm9uZVwiPlxuICAgICAgPGlvbi1pY29uIGNvbG9yPVwiZGFuZ2VyXCIgc2xvdD1cInN0YXJ0XCIgbmFtZT1cImFsZXJ0LWNpcmNsZVwiPjwvaW9uLWljb24+XG4gICAgICA8aW9uLWxhYmVsIGNvbG9yPVwiZGFuZ2VyXCIgW2lubmVySFRNTF09XCJlcnJvciB8IHRyYW5zbGF0ZVwiPjwvaW9uLWxhYmVsPlxuICAgIDwvaW9uLWl0ZW0+XG4gIDwvYXBwLWZvcm0tYnV0dG9ucy1iYXI+XG48L2lvbi1mb290ZXI+XG5cbjxpb24tZmFiIHNsb3Q9XCJmaXhlZFwiIHZlcnRpY2FsPVwiYm90dG9tXCIgaG9yaXpvbnRhbD1cImVuZFwiICpuZ0lmPVwibW9iaWxlXCI+XG4gIDxpb24tZmFiLWJ1dHRvbiBjb2xvcj1cInRlcnRpYXJ5XCIgKGNsaWNrKT1cImFkZFJvdygpXCI+XG4gICAgPGlvbi1pY29uIG5hbWU9XCJhZGRcIj48L2lvbi1pY29uPlxuICA8L2lvbi1mYWItYnV0dG9uPlxuPC9pb24tZmFiPlxuIl19
|