ngx-easy-table
Version:
Angular easy table
541 lines • 146 kB
JavaScript
import { moveItemInArray } from '@angular/cdk/drag-drop';
import { ChangeDetectionStrategy, Component, ContentChild, EventEmitter, HostListener, Input, Output, TemplateRef, ViewChild, } from '@angular/core';
import { API, Event } from '../..';
import { DefaultConfigService } from '../../services/config-service';
import { GroupRowsService } from '../../services/group-rows.service';
import { StyleService } from '../../services/style.service';
import { Subject } from 'rxjs';
import { CdkVirtualScrollViewport } from '@angular/cdk/scrolling';
import { filter, takeUntil, throttleTime } from 'rxjs/operators';
import * as i0 from "@angular/core";
import * as i1 from "@angular/cdk/scrolling";
import * as i2 from "../../services/style.service";
import * as i3 from "@angular/common";
import * as i4 from "@angular/cdk/drag-drop";
import * as i5 from "../pagination/pagination.component";
import * as i6 from "../thead/thead.component";
import * as i7 from "ngx-pagination";
import * as i8 from "../../pipes/search-pipe";
import * as i9 from "../../pipes/render-pipe";
import * as i10 from "../../pipes/global-search-pipe";
import * as i11 from "../../pipes/sort.pipe";
export class BaseComponent {
onContextMenuClick(targetElement) {
if (this.contextMenu && !this.contextMenu.nativeElement.contains(targetElement)) {
this.rowContextMenuPosition = {
top: null,
left: null,
value: null,
};
}
}
constructor(cdr, scrollDispatcher, styleService) {
this.cdr = cdr;
this.scrollDispatcher = scrollDispatcher;
this.styleService = styleService;
this.unsubscribe = new Subject();
this.filterCount = -1;
this.filteredCountSubject = new Subject();
this.tableClass = null;
this.grouped = [];
this.isSelected = false;
this.page = 1;
this.count = 0;
this.sortState = new Map();
this.sortKey = null;
this.rowContextMenuPosition = {
top: null,
left: null,
value: null,
};
this.sortBy = {
key: '',
order: 'asc',
};
this.selectedDetailsTemplateRowId = new Set();
this.selectedCheckboxes = new Set();
this.id = 'table';
this.event = new EventEmitter();
this.filteredCountSubject.pipe(takeUntil(this.unsubscribe)).subscribe((count) => {
setTimeout(() => {
this.filterCount = count;
this.cdr.detectChanges();
});
});
}
ngOnInit() {
if (!this.columns) {
console.error('[columns] property required!');
}
if (this.configuration) {
this.config = this.configuration;
}
else {
this.config = DefaultConfigService.config;
}
this.limit = this.config.rows;
if (this.groupRowsBy) {
this.grouped = GroupRowsService.doGroupRows(this.data, this.groupRowsBy);
}
this.doDecodePersistedState();
}
ngOnDestroy() {
this.unsubscribe.next();
this.unsubscribe.complete();
}
ngAfterViewInit() {
const throttleValue = this.config.infiniteScrollThrottleTime
? this.config.infiniteScrollThrottleTime
: 200;
this.scrollDispatcher
.scrolled()
.pipe(throttleTime(throttleValue), filter((event) => {
return (!!event &&
this.viewPort &&
this.viewPort.getRenderedRange().end === this.viewPort.getDataLength());
}), takeUntil(this.unsubscribe))
.subscribe(() => {
this.emitEvent(Event.onInfiniteScrollEnd, null);
});
}
ngOnChanges(changes) {
const { configuration, data, pagination, groupRowsBy } = changes;
this.toggleRowIndex = changes.toggleRowIndex;
if (configuration && configuration.currentValue) {
this.config = configuration.currentValue;
}
if (data && data.currentValue) {
this.doApplyData(data);
}
if (pagination && pagination.currentValue) {
const { count, limit, offset } = pagination.currentValue;
this.count = count;
this.limit = limit;
this.page = offset;
}
if (groupRowsBy && groupRowsBy.currentValue) {
this.grouped = GroupRowsService.doGroupRows(this.data, this.groupRowsBy);
}
if (this.toggleRowIndex && this.toggleRowIndex.currentValue) {
const row = this.toggleRowIndex.currentValue;
this.collapseRow(row.index);
}
}
orderBy(column) {
if (typeof column.orderEnabled !== 'undefined' && !column.orderEnabled) {
return;
}
this.sortKey = column.key;
if (!this.config.orderEnabled || this.sortKey === '') {
return;
}
this.setColumnOrder(column);
if (!this.config.orderEventOnly && !column.orderEventOnly) {
this.sortBy.key = this.sortKey;
this.sortBy.order = this.sortState.get(this.sortKey);
}
else {
this.sortBy.key = '';
this.sortBy.order = '';
}
if (!this.config.serverPagination) {
this.data = [...this.data];
this.sortBy = { ...this.sortBy };
}
const value = {
key: this.sortKey,
order: this.sortState.get(this.sortKey),
};
this.emitEvent(Event.onOrder, value);
}
onClick($event, row, key, colIndex, rowIndex) {
if (this.config.selectRow) {
this.selectedRow = rowIndex;
}
if (this.config.selectCol && `${colIndex}`) {
this.selectedCol = colIndex;
}
if (this.config.selectCell && `${colIndex}`) {
this.selectedRow = rowIndex;
this.selectedCol = colIndex;
}
if (this.config.clickEvent) {
const value = {
event: $event,
row,
key,
rowId: rowIndex,
colId: colIndex,
};
this.emitEvent(Event.onClick, value);
}
}
onDoubleClick($event, row, key, colIndex, rowIndex) {
const value = {
event: $event,
row,
key,
rowId: rowIndex,
colId: colIndex,
};
this.emitEvent(Event.onDoubleClick, value);
}
onCheckboxSelect($event, row, rowIndex) {
const value = {
event: $event,
row,
rowId: rowIndex,
};
this.emitEvent(Event.onCheckboxSelect, value);
}
onRadioSelect($event, row, rowIndex) {
const value = {
event: $event,
row,
rowId: rowIndex,
};
this.emitEvent(Event.onRadioSelect, value);
}
onSelectAll() {
this.isSelected = !this.isSelected;
this.emitEvent(Event.onSelectAll, this.isSelected);
}
onSearch($event) {
if (!this.config.serverPagination) {
this.term = $event;
}
this.emitEvent(Event.onSearch, $event);
}
onGlobalSearch(value) {
if (!this.config.serverPagination) {
this.globalSearchTerm = value;
}
this.emitEvent(Event.onGlobalSearch, value);
}
onPagination(pagination) {
this.page = pagination.page;
this.limit = pagination.limit;
this.config.rows = pagination.limit;
this.emitEvent(Event.onPagination, pagination);
}
toggleCheckbox(rowIndex) {
this.selectedCheckboxes.has(rowIndex)
? this.selectedCheckboxes.delete(rowIndex)
: this.selectedCheckboxes.add(rowIndex);
}
collapseRow(rowIndex) {
if (this.selectedDetailsTemplateRowId.has(rowIndex)) {
this.selectedDetailsTemplateRowId.delete(rowIndex);
this.emitEvent(Event.onRowCollapsedHide, rowIndex);
}
else {
this.selectedDetailsTemplateRowId.add(rowIndex);
this.emitEvent(Event.onRowCollapsedShow, rowIndex);
}
}
doDecodePersistedState() {
if (!this.config.persistState) {
return;
}
const pagination = localStorage.getItem(Event.onPagination);
const sort = localStorage.getItem(Event.onOrder);
const search = localStorage.getItem(Event.onSearch);
if (pagination) {
this.onPagination(JSON.parse(pagination));
}
if (sort) {
const { key, order } = JSON.parse(sort);
this.bindApi({
type: API.sortBy,
value: { column: key, order },
});
}
if (search) {
this.bindApi({
type: API.setInputValue,
value: JSON.parse(search),
});
}
}
isRowCollapsed(rowIndex) {
if (this.config.collapseAllRows) {
return true;
}
return this.selectedDetailsTemplateRowId.has(rowIndex);
}
get loadingHeight() {
const table = document.getElementById(this.id);
if (table && table.rows && table.rows.length > 3) {
const searchEnabled = this.config.searchEnabled ? 1 : 0;
const headerEnabled = this.config.headerEnabled ? 1 : 0;
const borderTrHeight = 1;
const borderDivHeight = 2;
return ((table.rows.length - searchEnabled - headerEnabled) *
(table.rows[3].offsetHeight - borderTrHeight) -
borderDivHeight);
}
return 30;
}
get arrowDefinition() {
return this.config.showDetailsArrow || typeof this.config.showDetailsArrow === 'undefined';
}
onRowContextMenu($event, row, key, colIndex, rowIndex) {
if (!this.config.showContextMenu) {
return;
}
$event.preventDefault();
const value = {
event: $event,
row,
key,
rowId: rowIndex,
colId: colIndex,
};
this.rowContextMenuPosition = {
top: `${$event.pageY - 10}px`,
left: `${$event.pageX - 10}px`,
value,
};
this.emitEvent(Event.onRowContextMenu, value);
}
doApplyData(data) {
const order = this.columns.find((c) => !!c.orderBy);
if (order) {
this.sortState.set(this.sortKey, order.orderBy === 'asc' ? 'desc' : 'asc');
this.orderBy(order);
}
else {
this.data = [...data.currentValue];
}
}
onDragStart(event) {
this.emitEvent(Event.onReorderStart, event);
}
onDrop(event) {
this.emitEvent(Event.onRowDrop, event);
moveItemInArray(this.data, event.previousIndex, event.currentIndex);
}
// DO NOT REMOVE. It is called from parent component. See src/app/demo/api-doc/api-doc.component.ts
apiEvent(event) {
return this.bindApi(event);
}
/* eslint-disable */
bindApi(event) {
switch (event.type) {
case API.rowContextMenuClicked:
this.rowContextMenuPosition = {
top: null,
left: null,
value: null,
};
break;
case API.toggleRowIndex:
this.collapseRow(event.value);
break;
case API.toggleCheckbox:
this.toggleCheckbox(event.value);
break;
case API.setInputValue:
if (this.config.searchEnabled) {
event.value.forEach((input) => {
const element = document.getElementById(`search_${input.key}`);
if (!element) {
console.error(`Column '${input.key}' not available in the DOM. Have you misspelled a name?`);
}
else {
element.value = input.value;
}
});
}
this.onSearch(event.value);
this.cdr.markForCheck();
break;
case API.onGlobalSearch:
this.onGlobalSearch(event.value);
this.cdr.markForCheck();
break;
case API.setRowClass:
if (Array.isArray(event.value)) {
event.value.forEach((val) => this.styleService.setRowClass(val));
break;
}
this.styleService.setRowClass(event.value);
this.cdr.markForCheck();
break;
case API.setCellClass:
if (Array.isArray(event.value)) {
event.value.forEach((val) => this.styleService.setCellClass(val));
break;
}
this.styleService.setCellClass(event.value);
break;
case API.setRowStyle:
if (Array.isArray(event.value)) {
event.value.forEach((val) => this.styleService.setRowStyle(val));
break;
}
this.styleService.setRowStyle(event.value);
break;
case API.setCellStyle:
if (Array.isArray(event.value)) {
event.value.forEach((val) => this.styleService.setCellStyle(val));
break;
}
this.styleService.setCellStyle(event.value);
break;
case API.setTableClass:
this.tableClass = event.value;
this.cdr.markForCheck();
break;
case API.getPaginationTotalItems:
return this.paginationComponent.paginationDirective.getTotalItems();
case API.getPaginationCurrentPage:
return this.paginationComponent.paginationDirective.getCurrent();
case API.getPaginationLastPage:
return this.paginationComponent.paginationDirective.getLastPage();
case API.getNumberOfRowsPerPage:
return this.paginationComponent.paginationDirective.isLastPage()
? this.paginationComponent.paginationDirective.getTotalItems() % this.limit
: this.limit;
case API.setPaginationCurrentPage:
this.paginationComponent.paginationDirective.setCurrent(event.value);
break;
case API.setPaginationRange:
this.paginationComponent.ranges = event.value;
break;
case API.setPaginationPreviousLabel:
this.paginationComponent.previousLabel = event.value;
break;
case API.setPaginationNextLabel:
this.paginationComponent.nextLabel = event.value;
break;
case API.setPaginationDisplayLimit:
this.paginationComponent.changeLimit(event.value, true);
break;
case API.sortBy:
const column = { title: '', key: event.value.column, orderBy: event.value.order };
this.orderBy(column);
this.cdr.detectChanges();
break;
default:
break;
}
}
setColumnOrder(column) {
const key = column.key;
switch (this.sortState.get(key)) {
case '':
case undefined:
this.sortState.set(key, column.orderBy || 'desc');
break;
case 'asc':
this.config.threeWaySort ? this.sortState.set(key, '') : this.sortState.set(key, 'desc');
break;
case 'desc':
this.sortState.set(key, 'asc');
break;
}
if (this.sortState.size > 1) {
const temp = this.sortState.get(key);
this.sortState.clear();
this.sortState.set(key, temp);
}
}
emitEvent(event, value) {
this.event.emit({ event, value });
if (this.config.persistState) {
localStorage.setItem(event, JSON.stringify(value));
}
if (this.config.logger) {
// eslint-disable-next-line no-console
console.log({ event, value });
}
}
dragEnter($event) {
$event.preventDefault();
$event.stopPropagation();
}
dragOver($event) {
$event.preventDefault();
$event.stopPropagation();
}
dragLeave($event) {
$event.preventDefault();
$event.stopPropagation();
}
drop($event) {
$event.preventDefault();
$event.stopPropagation();
const file = $event.dataTransfer?.files?.[0];
if (file?.type !== 'application/json') {
// eslint-disable-next-line no-console
console.log('File not allowed');
return;
}
const fileReader = new FileReader();
fileReader.onload = (event) => {
this.data = JSON.parse(event?.target?.result);
this.cdr.markForCheck();
};
fileReader.readAsText(file);
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.11", ngImport: i0, type: BaseComponent, deps: [{ token: i0.ChangeDetectorRef }, { token: i1.ScrollDispatcher }, { token: i2.StyleService }], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.11", type: BaseComponent, selector: "ngx-table", inputs: { configuration: "configuration", data: "data", pagination: "pagination", groupRowsBy: "groupRowsBy", id: "id", toggleRowIndex: "toggleRowIndex", detailsTemplate: "detailsTemplate", summaryTemplate: "summaryTemplate", groupRowsHeaderTemplate: "groupRowsHeaderTemplate", filtersTemplate: "filtersTemplate", selectAllTemplate: "selectAllTemplate", noResultsTemplate: "noResultsTemplate", loadingTemplate: "loadingTemplate", additionalActionsTemplate: "additionalActionsTemplate", rowContextMenu: "rowContextMenu", columns: "columns" }, outputs: { event: "event" }, host: { listeners: { "document:click": "onContextMenuClick($event.target)" } }, providers: [DefaultConfigService, GroupRowsService, StyleService], queries: [{ propertyName: "rowTemplate", first: true, predicate: TemplateRef, descendants: true }], viewQueries: [{ propertyName: "paginationComponent", first: true, predicate: ["paginationComponent"], descendants: true }, { propertyName: "contextMenu", first: true, predicate: ["contextMenu"], descendants: true }, { propertyName: "table", first: true, predicate: ["table"], descendants: true }, { propertyName: "viewPort", first: true, predicate: CdkVirtualScrollViewport, descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div\n class=\"ngx-container\"\n [class.ngx-container--dark]=\"config.tableLayout.theme === 'dark'\"\n (dragenter)=\"dragEnter($event)\"\n (dragover)=\"dragOver($event)\"\n (dragleave)=\"dragLeave($event)\"\n (drop)=\"drop($event)\"\n>\n <table\n [id]=\"id\"\n #table\n [ngClass]=\"tableClass === null || tableClass === '' ? 'ngx-table' : tableClass\"\n [class.ngx-table__table--tiny]=\"config.tableLayout.style === 'tiny'\"\n [class.ngx-table__table--normal]=\"config.tableLayout.style === 'normal'\"\n [class.ngx-table__table--big]=\"config.tableLayout.style === 'big'\"\n [class.ngx-table__table--borderless]=\"config.tableLayout.borderless\"\n [class.ngx-table__table--dark]=\"config.tableLayout.theme === 'dark'\"\n [class.ngx-table__table--hoverable]=\"config.tableLayout.hover\"\n [class.ngx-table__table--striped]=\"config.tableLayout.striped\"\n [class.ngx-table__horizontal-scroll]=\"config.horizontalScroll && !config.isLoading\"\n >\n <thead\n [class.ngx-infinite-scroll-viewport-thead]=\"config.infiniteScroll\"\n table-thead\n [config]=\"config\"\n [sortKey]=\"sortKey\"\n [sortState]=\"sortState\"\n [selectAllTemplate]=\"selectAllTemplate\"\n [filtersTemplate]=\"filtersTemplate\"\n [additionalActionsTemplate]=\"additionalActionsTemplate\"\n [columns]=\"columns\"\n (selectAll)=\"onSelectAll()\"\n (filter)=\"onSearch($event)\"\n (order)=\"orderBy($event)\"\n (event)=\"emitEvent($event.event, $event.value)\"\n ></thead>\n <tbody *ngIf=\"data && !config.isLoading && !config.rowReorder\">\n <ng-container *ngIf=\"rowTemplate\">\n <ul\n class=\"ngx-table__table-row-context-menu\"\n [ngStyle]=\"{\n position: 'absolute',\n top: rowContextMenuPosition.top,\n left: rowContextMenuPosition.left\n }\"\n *ngIf=\"rowContextMenuPosition.top\"\n >\n <ng-container\n [ngTemplateOutlet]=\"rowContextMenu\"\n [ngTemplateOutletContext]=\"{ $implicit: rowContextMenuPosition.value }\"\n >\n </ng-container>\n </ul>\n <ng-container *ngIf=\"!config.infiniteScroll\">\n <ng-container\n *ngFor=\"\n let row of data\n | sort: sortBy\n | search: term:filteredCountSubject\n | global: globalSearchTerm:filteredCountSubject\n | paginate: { itemsPerPage: limit, currentPage: page, totalItems: count, id: id }\n \"\n >\n <tr\n (click)=\"onClick($event, row, '', null, data.indexOf(row))\"\n #contextMenu\n (contextmenu)=\"onRowContextMenu($event, row, '', null, data.indexOf(row))\"\n (dblclick)=\"onDoubleClick($event, row, '', null, data.indexOf(row))\"\n [class.ngx-table__table-row--selected]=\"\n data.indexOf(row) === selectedRow && !config.selectCell\n \"\n >\n <ng-container\n [ngTemplateOutlet]=\"rowTemplate\"\n [ngTemplateOutletContext]=\"{ $implicit: row, index: data.indexOf(row) }\"\n >\n </ng-container>\n <td *ngIf=\"config.detailsTemplate\">\n <span\n class=\"ngx-icon\"\n *ngIf=\"arrowDefinition\"\n [ngClass]=\"\n isRowCollapsed(data.indexOf(row))\n ? 'ngx-icon-arrow-down'\n : 'ngx-icon-arrow-right'\n \"\n (click)=\"collapseRow(data.indexOf(row))\"\n >\n </span>\n </td>\n </tr>\n <tr\n *ngIf=\"\n (config.detailsTemplate && selectedDetailsTemplateRowId.has(data.indexOf(row))) ||\n config.collapseAllRows\n \"\n >\n <td [attr.colspan]=\"columns.length + 1\">\n <ng-container\n [ngTemplateOutlet]=\"detailsTemplate\"\n [ngTemplateOutletContext]=\"{ $implicit: row, index: data.indexOf(row) }\"\n >\n </ng-container>\n </td>\n </tr>\n </ng-container>\n </ng-container>\n <cdk-virtual-scroll-viewport\n itemSize=\"50\"\n *ngIf=\"config.infiniteScroll\"\n class=\"ngx-infinite-scroll-viewport\"\n >\n <ng-container\n *cdkVirtualFor=\"\n let row of data\n | sort: sortBy\n | search: term:filteredCountSubject\n | global: globalSearchTerm:filteredCountSubject;\n let rowIndex = index\n \"\n >\n <tr\n (click)=\"onClick($event, row, '', null, rowIndex)\"\n #contextMenu\n (contextmenu)=\"onRowContextMenu($event, row, '', null, rowIndex)\"\n (dblclick)=\"onDoubleClick($event, row, '', null, rowIndex)\"\n [class.ngx-table__table-row--selected]=\"\n rowIndex === selectedRow && !config.selectCell\n \"\n >\n <ng-container\n [ngTemplateOutlet]=\"rowTemplate\"\n [ngTemplateOutletContext]=\"{ $implicit: row, index: rowIndex }\"\n >\n </ng-container>\n <td *ngIf=\"config.detailsTemplate\">\n <span\n class=\"ngx-icon\"\n *ngIf=\"arrowDefinition\"\n [ngClass]=\"\n isRowCollapsed(rowIndex) ? 'ngx-icon-arrow-down' : 'ngx-icon-arrow-right'\n \"\n (click)=\"collapseRow(rowIndex)\"\n >\n </span>\n </td>\n </tr>\n <tr\n *ngIf=\"\n (config.detailsTemplate && selectedDetailsTemplateRowId.has(rowIndex)) ||\n config.collapseAllRows\n \"\n >\n <td [attr.colspan]=\"columns.length + 1\">\n <ng-container\n [ngTemplateOutlet]=\"detailsTemplate\"\n [ngTemplateOutletContext]=\"{ $implicit: row, index: rowIndex }\"\n >\n </ng-container>\n </td>\n </tr>\n </ng-container>\n </cdk-virtual-scroll-viewport>\n </ng-container>\n <ng-container *ngIf=\"!rowTemplate && !config.groupRows\">\n <ul\n class=\"ngx-table__table-row-context-menu\"\n [ngStyle]=\"{\n position: 'absolute',\n top: rowContextMenuPosition.top,\n left: rowContextMenuPosition.left\n }\"\n *ngIf=\"rowContextMenuPosition.top\"\n >\n <ng-container\n [ngTemplateOutlet]=\"rowContextMenu\"\n [ngTemplateOutletContext]=\"{ $implicit: rowContextMenuPosition.value }\"\n >\n </ng-container>\n </ul>\n <ng-container *ngIf=\"!config.infiniteScroll\">\n <ng-container\n *ngFor=\"\n let row of data\n | sort: sortBy\n | search: term:filteredCountSubject\n | global: globalSearchTerm:filteredCountSubject\n | paginate: { itemsPerPage: limit, currentPage: page, totalItems: count, id: id }\n \"\n >\n <tr\n [class.ngx-table__table-row--selected]=\"\n data.indexOf(row) === selectedRow && !config.selectCell\n \"\n >\n <td *ngIf=\"config.checkboxes\">\n <label class=\"ngx-form-checkbox\">\n <input\n type=\"checkbox\"\n id=\"checkbox-{{ data.indexOf(row) }}\"\n [checked]=\"isSelected || selectedCheckboxes.has(data.indexOf(row))\"\n (change)=\"onCheckboxSelect($event, row, data.indexOf(row))\"\n />\n <em class=\"ngx-form-icon\"></em>\n </label>\n </td>\n <td *ngIf=\"config.radio\">\n <label>\n <input\n type=\"radio\"\n id=\"radio-{{ data.indexOf(row) }}\"\n name=\"radio\"\n (change)=\"onRadioSelect($event, row, data.indexOf(row))\"\n />\n </label>\n </td>\n <ng-container *ngFor=\"let column of columns; let colIndex = index\">\n <td\n (click)=\"onClick($event, row, column.key, colIndex, data.indexOf(row))\"\n #contextMenu\n (contextmenu)=\"\n onRowContextMenu($event, row, column.key, colIndex, data.indexOf(row))\n \"\n (dblclick)=\"onDoubleClick($event, row, column.key, colIndex, data.indexOf(row))\"\n [class.pinned-left]=\"column.pinned\"\n [ngClass]=\"column.cssClass ? column.cssClass.name : ''\"\n [style.left]=\"styleService.pinnedWidth(column.pinned, colIndex)\"\n [class.ngx-table__table-col--selected]=\"\n colIndex === selectedCol && !config.selectCell\n \"\n [class.ngx-table__table-cell--selected]=\"\n colIndex === selectedCol &&\n data.indexOf(row) === selectedRow &&\n !config.selectCol &&\n !config.selectRow\n \"\n >\n <div *ngIf=\"!column.cellTemplate\">{{ row | render: column.key }}</div>\n <ng-container\n *ngIf=\"column.cellTemplate\"\n [ngTemplateOutlet]=\"column.cellTemplate\"\n [ngTemplateOutletContext]=\"{\n $implicit: row,\n rowIndex: data.indexOf(row),\n column: column\n }\"\n >\n </ng-container>\n </td>\n </ng-container>\n <td *ngIf=\"config.additionalActions || config.detailsTemplate\">\n <span\n class=\"ngx-icon\"\n *ngIf=\"arrowDefinition\"\n [ngClass]=\"\n isRowCollapsed(data.indexOf(row))\n ? 'ngx-icon-arrow-down'\n : 'ngx-icon-arrow-right'\n \"\n (click)=\"collapseRow(data.indexOf(row))\"\n >\n </span>\n </td>\n </tr>\n <tr\n *ngIf=\"\n (config.detailsTemplate && selectedDetailsTemplateRowId.has(data.indexOf(row))) ||\n config.collapseAllRows\n \"\n >\n <td *ngIf=\"config.checkboxes || config.radio\"></td>\n <td [attr.colspan]=\"columns.length + 1\">\n <ng-container\n [ngTemplateOutlet]=\"detailsTemplate\"\n [ngTemplateOutletContext]=\"{ $implicit: row, index: data.indexOf(row) }\"\n >\n </ng-container>\n </td>\n </tr>\n </ng-container>\n </ng-container>\n <!-- infinite scroll -->\n <cdk-virtual-scroll-viewport\n itemSize=\"50\"\n *ngIf=\"config.infiniteScroll\"\n class=\"ngx-infinite-scroll-viewport\"\n >\n <ng-container\n *cdkVirtualFor=\"\n let row of data\n | sort: sortBy\n | search: term:filteredCountSubject\n | global: globalSearchTerm:filteredCountSubject;\n let rowIndex = index\n \"\n >\n <tr\n [class.ngx-table__table-row--selected]=\"\n rowIndex === selectedRow && !config.selectCell\n \"\n >\n <td *ngIf=\"config.checkboxes\" width=\"3%\">\n <label class=\"ngx-form-checkbox\">\n <input\n type=\"checkbox\"\n id=\"checkbox-infinite-scroll-{{ rowIndex }}\"\n [checked]=\"isSelected || selectedCheckboxes.has(rowIndex)\"\n (change)=\"onCheckboxSelect($event, row, rowIndex)\"\n />\n <em class=\"ngx-form-icon\"></em>\n </label>\n </td>\n <td *ngIf=\"config.radio\" width=\"3%\">\n <label>\n <input\n type=\"radio\"\n id=\"radio-infinite-scroll-{{ rowIndex }}\"\n name=\"radio\"\n (change)=\"onRadioSelect($event, row, rowIndex)\"\n />\n </label>\n </td>\n <ng-container *ngFor=\"let column of columns; let colIndex = index\">\n <td\n (click)=\"onClick($event, row, column.key, colIndex, rowIndex)\"\n #contextMenu\n (contextmenu)=\"onRowContextMenu($event, row, column.key, colIndex, rowIndex)\"\n (dblclick)=\"onDoubleClick($event, row, column.key, colIndex, rowIndex)\"\n [class.pinned-left]=\"column.pinned\"\n [ngClass]=\"column.cssClass ? column.cssClass.name : ''\"\n [style.left]=\"styleService.pinnedWidth(column.pinned, colIndex)\"\n [class.ngx-table__table-col--selected]=\"\n colIndex === selectedCol && !config.selectCell\n \"\n [class.ngx-table__table-cell--selected]=\"\n colIndex === selectedCol &&\n rowIndex === selectedRow &&\n !config.selectCol &&\n !config.selectRow\n \"\n >\n <div *ngIf=\"!column.cellTemplate\">{{ row | render: column.key }}</div>\n <ng-container\n *ngIf=\"column.cellTemplate\"\n [ngTemplateOutlet]=\"column.cellTemplate\"\n [ngTemplateOutletContext]=\"{\n $implicit: row,\n rowIndex: rowIndex,\n column: column\n }\"\n >\n </ng-container>\n </td>\n </ng-container>\n <td *ngIf=\"config.additionalActions || config.detailsTemplate\">\n <span\n class=\"ngx-icon\"\n *ngIf=\"arrowDefinition\"\n [ngClass]=\"\n isRowCollapsed(rowIndex) ? 'ngx-icon-arrow-down' : 'ngx-icon-arrow-right'\n \"\n (click)=\"collapseRow(rowIndex)\"\n >\n </span>\n </td>\n </tr>\n <tr\n *ngIf=\"\n (config.detailsTemplate && selectedDetailsTemplateRowId.has(rowIndex)) ||\n config.collapseAllRows\n \"\n >\n <td *ngIf=\"config.checkboxes || config.radio\"></td>\n <td [attr.colspan]=\"columns.length + 1\">\n <ng-container\n [ngTemplateOutlet]=\"detailsTemplate\"\n [ngTemplateOutletContext]=\"{ $implicit: row, index: rowIndex }\"\n >\n </ng-container>\n </td>\n </tr>\n </ng-container>\n </cdk-virtual-scroll-viewport>\n </ng-container>\n <ng-container *ngIf=\"!rowTemplate && config.groupRows\">\n <ng-container\n *ngFor=\"\n let group of grouped\n | sort: sortBy:config\n | search: term:filteredCountSubject:config\n | global: globalSearchTerm:filteredCountSubject\n | paginate: { itemsPerPage: limit, currentPage: page, totalItems: count, id: id };\n let rowIndex = index\n \"\n >\n <tr>\n <ng-container *ngIf=\"!groupRowsHeaderTemplate\">\n <td [attr.colspan]=\"columns.length\">\n <div>{{ group[0][groupRowsBy] }} ({{ group.length }})</div>\n </td>\n </ng-container>\n <ng-container\n *ngIf=\"groupRowsHeaderTemplate\"\n [ngTemplateOutlet]=\"groupRowsHeaderTemplate\"\n [ngTemplateOutletContext]=\"{\n total: group.length,\n key: groupRowsBy,\n value: group[0] ? group[0][groupRowsBy] : '',\n group: group,\n index: rowIndex\n }\"\n >\n </ng-container>\n <td>\n <span\n class=\"ngx-icon\"\n *ngIf=\"arrowDefinition\"\n [ngClass]=\"\n isRowCollapsed(rowIndex) ? 'ngx-icon-arrow-down' : 'ngx-icon-arrow-right'\n \"\n (click)=\"collapseRow(rowIndex)\"\n >\n </span>\n </td>\n </tr>\n <ng-container *ngIf=\"selectedDetailsTemplateRowId.has(rowIndex)\">\n <tr *ngFor=\"let row of group\">\n <td *ngFor=\"let column of columns\">\n {{ row | render: column.key }}\n <!-- TODO allow users to add groupRowsTemplateRef -->\n </td>\n <td></td>\n </tr>\n </ng-container>\n </ng-container>\n </ng-container>\n </tbody>\n <tbody\n *ngIf=\"data && !config.isLoading && config.rowReorder\"\n class=\"ngx-draggable-row-area\"\n cdkDropList\n (cdkDropListDropped)=\"onDrop($event)\"\n >\n <ng-container *ngIf=\"!rowTemplate && !config.groupRows\">\n <ng-container\n *ngFor=\"\n let row of data\n | sort: sortBy\n | search: term:filteredCountSubject\n | global: globalSearchTerm:filteredCountSubject\n | paginate: { itemsPerPage: limit, currentPage: page, totalItems: count, id: id }\n \"\n >\n <tr\n class=\"ngx-draggable-row\"\n cdkDrag\n (cdkDragStarted)=\"onDragStart($event)\"\n [cdkDragStartDelay]=\"config.reorderDelay || 0\"\n cdkDragLockAxis=\"y\"\n >\n <td *ngIf=\"config.checkboxes\">\n <label class=\"ngx-form-checkbox\">\n <input\n type=\"checkbox\"\n id=\"checkbox-draggable-{{ data.indexOf(row) }}\"\n [checked]=\"isSelected || selectedCheckboxes.has(data.indexOf(row))\"\n (change)=\"onCheckboxSelect($event, row, data.indexOf(row))\"\n />\n <em class=\"ngx-form-icon\"></em>\n </label>\n </td>\n <td *ngIf=\"config.radio\">\n <label>\n <input\n type=\"radio\"\n id=\"radio-draggable-{{ data.indexOf(row) }}\"\n name=\"radio\"\n (change)=\"onRadioSelect($event, row, data.indexOf(row))\"\n />\n </label>\n </td>\n <ng-container *ngFor=\"let column of columns; let colIndex = index\">\n <td\n (click)=\"onClick($event, row, column.key, colIndex, data.indexOf(row))\"\n (dblclick)=\"onDoubleClick($event, row, column.key, colIndex, data.indexOf(row))\"\n [class.ngx-table__table-col--selected]=\"\n colIndex === selectedCol && !config.selectCell\n \"\n [class.ngx-table__table-cell--selected]=\"\n colIndex === selectedCol &&\n data.indexOf(row) === selectedRow &&\n !config.selectCol &&\n !config.selectRow\n \"\n >\n <div *ngIf=\"!column.cellTemplate\">{{ row | render: column.key }}</div>\n <ng-container\n *ngIf=\"column.cellTemplate\"\n [ngTemplateOutlet]=\"column.cellTemplate\"\n [ngTemplateOutletContext]=\"{\n $implicit: row,\n rowIndex: data.indexOf(row),\n column: column\n }\"\n >\n </ng-container>\n </td>\n </ng-container>\n </tr>\n </ng-container>\n </ng-container>\n </tbody>\n <tbody *ngIf=\"filterCount === 0\">\n <tr class=\"ngx-table__body-empty\">\n <ng-container *ngIf=\"noResultsTemplate\" [ngTemplateOutlet]=\"noResultsTemplate\">\n </ng-container>\n <td [attr.colspan]=\"columns && columns.length + 1\" *ngIf=\"!noResultsTemplate\">\n <div class=\"ngx-table__table-no-results\">No results</div>\n </td>\n </tr>\n </tbody>\n <tbody *ngIf=\"config.isLoading\">\n <tr class=\"ngx-table__body-loading\">\n <ng-container *ngIf=\"loadingTemplate\" [ngTemplateOutlet]=\"loadingTemplate\"> </ng-container>\n <td [attr.colspan]=\"columns && columns.length + 1\" *ngIf=\"!loadingTemplate\">\n <div [style.height.px]=\"loadingHeight\" class=\"ngx-table__table-loader-wrapper\">\n <div class=\"ngx-table__table-loader\"></div>\n </div>\n </td>\n </tr>\n </tbody>\n <tfoot *ngIf=\"summaryTemplate\">\n <tr>\n <ng-container\n [ngTemplateOutlet]=\"summaryTemplate\"\n [ngTemplateOutletContext]=\"{ total: data.length, limit: limit, page: page }\"\n >\n </ng-container>\n </tr>\n </tfoot>\n </table>\n <pagination\n [attr.id]=\"'pagination' + id\"\n [id]=\"id\"\n #paginationComponent\n [config]=\"config\"\n [pagination]=\"pagination\"\n (updateRange)=\"onPagination($event)\"\n >\n </pagination>\n</div>\n", dependencies: [{ kind: "directive", type: i3.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i3.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i3.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i3.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: i4.CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "directive", type: i4.CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "directive", type: i1.CdkFixedSizeVirtualScroll, selector: "cdk-virtual-scroll-viewport[itemSize]", inputs: ["itemSize", "minBufferPx", "maxBufferPx"] }, { kind: "directive", type: i1.CdkVirtualForOf, selector: "[cdkVirtualFor][cdkVirtualForOf]", inputs: ["cdkVirtualForOf", "cdkVirtualForTrackBy", "cdkVirtualForTemplate", "cdkVirtualForTemplateCacheSize"] }, { kind: "component", type: i1.CdkVirtualScrollViewport, selector: "cdk-virtual-scroll-viewport", inputs: ["orientation", "appendOnly"], outputs: ["scrolledIndexChange"] }, { kind: "component", type: i5.PaginationComponent, selector: "pagination", inputs: ["pagination", "config", "id"], outputs: ["updateRange"] }, { kind: "component", type: i6.TableTHeadComponent, selector: "[table-thead]", inputs: ["config", "columns", "sortKey", "sortState", "selectAllTemplate", "filtersTemplate", "additionalActionsTemplate"], outputs: ["filter", "order", "selectAll", "event"] }, { kind: "pipe", type: i7.PaginatePipe, name: "paginate" }, { kind: "pipe", type: i8.SearchPipe, name: "search" }, { kind: "pipe", type: i9.RenderPipe, name: "render" }, { kind: "pipe", type: i10.GlobalSearchPipe, name: "global" }, { kind: "pipe", type: i11.SortPipe, name: "sort" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.11", ngImport: i0, type: BaseComponent, decorators: [{
type: Component,
args: [{ selector: 'ngx-table', providers: [DefaultConfigService, GroupRowsService, StyleService], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div\n class=\"ngx-container\"\n [class.ngx-container--dark]=\"config.tableLayout.theme === 'dark'\"\n (dragenter)=\"dragEnter($event)\"\n (dragover)=\"dragOver($event)\"\n (dragleave)=\"dragLeave($event)\"\n (drop)=\"drop($event)\"\n>\n <table\n [id]=\"id\"\n #table\n [ngClass]=\"tableClass === null || tableClass === '' ? 'ngx-table' : tableClass\"\n [class.ngx-table__table--tiny]=\"config.tableLayout.style === 'tiny'\"\n [class.ngx-table__table--normal]=\"config.tableLayout.style === 'normal'\"\n [class.ngx-table__table--big]=\"config.tableLayout.style === 'big'\"\n [class.ngx-table__table--borderless]=\"config.tableLayout.borderless\"\n [class.ngx-table__table--dark]=\"config.tableLayout.theme === 'dark'\"\n [class.ngx-table__table--hoverable]=\"config.tableLayout.hover\"\n [class.ngx-table__table--striped]=\"config.tableLayout.striped\"\n [class.ngx-table__horizontal-scroll]=\"config.horizontalScroll && !config.isLoading\"\n >\n <thead\n [class.ngx-infinite-scroll-viewport-thead]=\"config.infiniteScroll\"\n table-thead\n [config]=\"config\"\n [sortKey]=\"sortKey\"\n [sortState]=\"sortState\"\n [selectAllTemplate]=\"selectAllTemplate\"\n [filtersTemplate]=\"filtersTemplate\"\n [additionalActionsTemplate]=\"additionalActionsTemplate\"\n [columns]=\"columns\"\n (selectAll)=\"onSelectAll()\"\n (filter)=\"onSearch($event)\"\n (order)=\"orderBy($event)\"\n (event)=\"emitEvent($event.event, $event.value)\"\n ></thead>\n <tbody *ngIf=\"data && !config.isLoading && !config.rowReorder\">\n <ng-container *ngIf=\"rowTemplate\">\n <ul\n class=\"ngx-table__table-row-context-menu\"\n [ngStyle]=\"{\n position: 'absolute',\n top: rowContextMenuPosition.top,\n left: rowContextMenuPosition.left\n }\"\n *ngIf=\"rowContextMenuPosition.top\"\n >\n <ng-container\n [ngTemplateOutlet]=\"rowContextMenu\"\n [ngTemplateOutletContext]=\"{ $implicit: rowContextMenuPosition.value }\"\n >\n </ng-container>\n </ul>\n <ng-container *ngIf=\"!config.infiniteScroll\">\n <ng-container\n *ngFor=\"\n let row of data\n | sort: sortBy\n | search: term:filteredCountSubject\n | global: globalSearchTerm:filteredCountSubject\n | paginate: { itemsPerPage: limit, currentPage: page, totalItems: count, id: id }\n \"\n >\n <tr\n (click)=\"onClick($event, row, '', null, data.indexOf(row))\"\n #contextMenu\n (contextmenu)=\"onRowContextMenu($event, row, '', null, data.indexOf(row))\"\n (dblclick)=\"onDoubleClick($event, row, '', null, data.indexOf(row))\"\n [class.ngx-table__table-row--selected]=\"\n data.indexOf(row) === selectedRow && !config.selectCell\n \"\n >\n <ng-container\n [ngTemplateOutlet]=\"rowTemplate\"\n [ngTemplateOutletContext]=\"{ $implicit: row, index: data.indexOf(row) }\"\n >\n </ng-container>\n <td *ngIf=\"config.detailsTemplate\">\n <span\n class=\"ngx-icon\"\n *ngIf=\"arrowDefinition\"\n [ngClass]=\"\n isRowCollapsed(data.indexOf(row))\n ? 'ngx-icon-arrow-down'\n : 'ngx-icon-arrow-right'\n \"\n (click)=\"collapseRow(data.indexOf(row))\"\n >\n </span>\n </td>\n </tr>\n <tr\n *ngIf=\"\n (config.detailsTemplate && selectedDetailsTemplateRowId.has(data.indexOf(row))) ||\n config.collapseAllRows\n \"\n >\n <td [attr.colspan]=\"columns.length + 1\">\n <ng-container\n [ngTemplateOutlet]=\"detailsTemplate\"\n [ngTemplateOutletContext]=\"{ $implicit: row, index: data.indexOf(row) }\"\n >\n </ng-container>\n </td>\n </tr>\n </ng-container>\n </ng-container>\n <cdk-virtual-scroll-viewport\n itemSize=\"50\"\n *ngIf=\"config.infiniteScroll\"\n class=\"ngx-infinite-scroll-viewport\"\n >\n <ng-container\n *cdkVirtualFor=\"\n let row of data\n | sort: sortBy\n | search: term:filteredCountSubject\n | global: globalSearchTerm:filteredCountSubject;\n let rowIndex = index\n \"\n >\n <tr\n (click)=\"onClick($event, row, '', null, rowIndex)\"\n #contextMenu\n (contextmenu)=\"onRowContextMenu($event, row, '', null, rowIndex)\"\n (dblclick)=\"onDoubleClick($event, row, '', null, rowIndex)\"\n [class.ngx-table__table-row--selected]=\"\n rowIndex === selectedRow && !config.selectCell\n \"\n >\n <ng-container\n [ngTemplateOutlet]=\"rowTemplate\"\n [ngTemplateOutletContext]=\"{ $implicit: row, index: rowIndex }\"\n >\n </ng-container>\n <td *ngIf=\"config.detailsTemplate\">\n <span\n class=\"ngx-icon\"\n *ngIf=\"arrowDefinition\"\n [ngClass]=\"\n isRowCollapsed(rowIndex) ? 'ngx-icon-arrow-down' : 'ngx-icon-arrow-right'\n \"\n (click)=\"collapseRow(rowIndex)\"\n >\n </span>\n </td>\n </tr>\n <tr\n *ngIf=\"\n (config.detailsTemplate && selectedDetailsTemplateRowId.has(rowIndex)) ||\n config.collapseAllRows\n \"\n >\n <td [attr.colspan]=\"columns.length + 1\">\n <ng-container\n [ngTemplateOutlet]=\"detailsTemplate\"\n [ngTemplateOutletContext]=\"{ $implicit: row, index: rowIndex }\"\n >\n </ng-container>\n </td>\n </tr>\n </ng-container>\n </cdk-virtual-scroll-viewport>\n </ng-container>\n <ng-container *ngIf=\"!rowTemplate && !config.groupRows\">\n <ul\n class=\"ngx-table__table-row-context-menu\"\n [ngStyle]=\"{\n position: 'absolute',\n top: rowContextMenuPosition.top,\n left: rowContextMenuPosition.left\n }\"\n *ngIf=\"rowContextMenuPosition.top\"\n >\n <ng-container\n [ngTemplateOutlet]=\"rowContextMenu\"\n [ngTemplateOutletContext]=\"{ $implicit: rowContextMenuPosition.value }\"\n >\n </ng-container>\n </ul>\n <ng-container *ngIf=\"!config.infiniteScroll\">\n <ng-container\n *ngFor=\"\n let row of data\n | sort: sortBy\n | search: term:filteredCountSubject\n | global: globalSearchTerm:filteredCountSubject\n | paginate: { itemsPerPage: limit, currentPage: page, totalItems: count, id: id }\n \"\n >\n <tr\n [class.ngx-table__table-row--selected]=\"\n data.indexOf(row) === selectedRow && !config.selectCell\n \"\n >\n <td *ngIf=\"config.checkboxes\">\n <label class=\"ngx-form-checkbox\">\n <input\n type=\"checkbox\"\n id=\"checkbox-{{ data.indexOf(row) }}\"\n [checked]=\"isSelected || selectedCheckboxes.has(data.indexOf(row))\"\n (change)=\"onCheckboxSelect($event, row, data.indexOf(row))\"\n />\n <em class=\"ngx-form-icon\"></em>\n </label>\n </td>\n <td *ngIf=\"config.radio\">\n <label>\n <input\n type=\"radio\"\n id=\"radio-{{ data.indexOf(row) }}\"\n name=\"radio\"\n (change)=\"onRadioSelect($event, row, data.indexOf(row))\"\n />\n </label>\n </td>\n <ng-container *ngFor=\"let column of columns; let colIndex = index\">\n <td\n (click)=\"onClick($event, row, column.key, colIndex, data.indexOf(row))\"\n #contextMenu\n (contextmenu)=\"\n onRowContextMenu($event, row, column.key, colIndex, data.indexOf(row))\n \"\n (dblclick)=\"onDoubleClick($event, row, column.key, colIndex, data.indexOf(row))\"\n [class.pinned-left]=\"column.pinned\"\n [ngClass]=\"column.cssClass ? column.cssClass.name : ''\"\n [style.left]=\"styleService.pinnedWidth(column.pinned, colIndex)\"\n [class.ngx-table__table-col--selected]=\"\n colIndex === selectedCol && !config.selectCell\n \"\n [class.ngx-table__table-cell--selected]=\"\n colIndex === selectedCol &&\n data.indexOf(row) === selectedRow &&\n !config.selectCol &&\n !config.selectRow\n \"\n >\n <div *ngIf=\"!column.cellTemplate\">{{ row | render: column.key }}</div>\n <ng-container\n *ngIf=\"column.cellTemplate\"\n [ngTemplateOutlet]=\"column.cellTemplate\"\n [ngTemplateOutletContext]=\"{\n $implicit: row,\n rowIndex: data.indexOf(row),\n column: column\n }\"\n >\n </ng-container>\n </td>\n </ng-container>\n <td *ngIf=\"config.additionalActions || config.detailsTemplate\">\n <span\n class=\"ngx-icon\"\n *ngIf=\"arrowDefinition\"\n [ngClass]=\"\n isRowCollapsed(data.indexOf(row))\n ? 'ngx-icon-arrow-down'\n : 'ngx-icon-arrow-right'\n \"\n (click)=\"collapseRow(data.indexOf(row))\"\n >\n </span>\n </td>\n </tr>\n <tr\n *ngIf=\"\n (config.detailsTemplate && selectedDetailsTemplateRowId.has(data.indexOf(row))) ||\n config.collapseAllRows\n \"\n >\n <td *ngIf=\"config.checkboxes || config.radio\"></td>\n <td [attr.colspan]=\"columns.length + 1\">\n <ng-container\n [ngTemplateOutlet]=\"detailsTemplate\"\n [ngTemplateOutletContext]=\"{ $implicit: row, index: data.indexOf(row) }\"\n >\n </ng-container>\n </td>\n </tr>\n </ng-container>\n </ng-container>\n <!-- infinite scroll -->\n <cdk-virtual-scroll-viewport\n itemSize=\"50\"\n *ngIf=\"config.infiniteScroll\"\n class=\"ngx-infinite-scroll-viewport\"\n >\n <ng-container\n *cdkVirtualFor=\"\n let row of data\n | sort: sortBy\n | search: term:filteredCountSubject\n | global: globalSearchTerm:filteredCountSubject;\n let rowIndex = index\n \"\n >\n <tr\n [class.ngx-table__table-row--selected]=\"\n rowIndex === selectedRow && !config.selectCell\n \"\n >\n <td *ngIf=\"config.checkboxes\" width=\"3%\">\n <label class=\"ngx-form-checkbox\">\n <input\n type=\"checkbox\"\n id=\"checkbox-infinite-scroll-{{ rowIndex }}\"\n [checked]=\"isSelected || selectedCheckboxes.has(rowIndex)\"\n (change)=\"onCheckboxSelect($event, row, rowIndex)\"\n />\n <em class=\"ngx-form-icon\"></em>\n </label>\n </td>\n <td *ngIf=\"config.radio\" width=\"3%\">\n <label>\n <input\n type=\"radio\"\n id=\"radio-infinite-scroll-{{ rowIndex }}\"\n name=\"radio\"\n (change)=\"onRadioSelect($event, row, rowIndex)\"\n />\n </label>\n </td>\n <ng-container *ngFor=\"let column of columns; let colIndex = index\">\n <td\n (click)=\"onClick($event, row, column.key, colIndex, rowIndex)\"\n #contextMenu\n (contextmenu)=\"onRowContextMenu($event, row, column.key, colIndex, rowIndex)\"\n (dblclick)=\"onDoubleClick($event, row, column.key, colIndex, rowIndex)\"\n [class.pinned-left]=\"column.pinned\"\n [ngClass]=\"column.cssClass ? column.cssClass.name : ''\"\n [style.left]=\"styleService.pinnedWidth(column.pinned, colIndex)\"\n [class.ngx-table__table-col--selected]=\"\n colIndex === selectedCol && !config.selectCell\n \"\n [class.ngx-table__table-cell--selected]=\"\n colIndex === selectedCol &&\n rowIndex === selectedRow &&\n !config.selectCol &&\n !config.selectRow\n \"\n >\n <div *ngIf=\"!column.cellTemplate\">{{ row | render: column.key }}</div>\n <ng-container\n *ngIf=\"column.cellTemplate\"\n [ngTemplateOutlet]=\"column.cellTemplate\"\n [ngTemplateOutletContext]=\"{\n $implicit: row,\n rowIndex: rowIndex,\n column: column\n }\"\n >\n </ng-container>\n </td>\n </ng-container>\n <td *ngIf=\"config.additionalActions || config.detailsTemplate\">\n <span\n class=\"ngx-icon\"\n *ngIf=\"arrowDefinition\"\n [ngClass]=\"\n isRowCollapsed(rowIndex) ? 'ngx-icon-arrow-down' : 'ngx-icon-arrow-right'\n \"\n (click)=\"collapseRow(rowIndex)\"\n >\n </span>\n </td>\n </tr>\n <tr\n *ngIf=\"\n (config.detailsTemplate && selectedDetailsTemplateRowId.has(rowIndex)) ||\n config.collapseAllRows\n \"\n >\n <td *ngIf=\"config.checkboxes || config.radio\"></td>\n <td [attr.colspan]=\"columns.length + 1\">\n <ng-container\n [ngTemplateOutlet]=\"detailsTemplate\"\n [ngTemplateOutletContext]=\"{ $implicit: row, index: rowIndex }\"\n >\n </ng-container>\n </td>\n </tr>\n </ng-container>\n </cdk-virtual-scroll-viewport>\n </ng-container>\n <ng-container *ngIf=\"!rowTemplate && config.groupRows\">\n <ng-container\n *ngFor=\"\n let group of grouped\n | sort: sortBy:config\n | search: term:filteredCountSubject:config\n | global: globalSearchTerm:filteredCountSubject\n | paginate: { itemsPerPage: limit, currentPage: page, totalItems: count, id: id };\n let rowIndex = index\n \"\n >\n <tr>\n <ng-container *ngIf=\"!groupRowsHeaderTemplate\">\n <td [attr.colspan]=\"columns.length\">\n <div>{{ group[0][groupRowsBy] }} ({{ group.length }})</div>\n </td>\n </ng-container>\n <ng-container\n *ngIf=\"groupRowsHeaderTemplate\"\n [ngTemplateOutlet]=\"groupRowsHeaderTemplate\"\n [ngTemplateOutletContext]=\"{\n total: group.length,\n key: groupRowsBy,\n value: group[0] ? group[0][groupRowsBy] : '',\n group: group,\n index: rowIndex\n }\"\n >\n </ng-container>\n <td>\n <span\n class=\"ngx-icon\"\n *ngIf=\"arrowDefinition\"\n [ngClass]=\"\n isRowCollapsed(rowIndex) ? 'ngx-icon-arrow-down' : 'ngx-icon-arrow-right'\n \"\n (click)=\"collapseRow(rowIndex)\"\n >\n </span>\n </td>\n </tr>\n <ng-container *ngIf=\"selectedDetailsTemplateRowId.has(rowIndex)\">\n <tr *ngFor=\"let row of group\">\n <td *ngFor=\"let column of columns\">\n {{ row | render: column.key }}\n <!-- TODO allow users to add groupRowsTemplateRef -->\n </td>\n <td></td>\n </tr>\n </ng-container>\n </ng-container>\n </ng-container>\n </tbody>\n <tbody\n *ngIf=\"data && !config.isLoading && config.rowReorder\"\n class=\"ngx-draggable-row-area\"\n cdkDropList\n (cdkDropListDropped)=\"onDrop($event)\"\n >\n <ng-container *ngIf=\"!rowTemplate && !config.groupRows\">\n <ng-container\n *ngFor=\"\n let row of data\n | sort: sortBy\n | search: term:filteredCountSubject\n | global: globalSearchTerm:filteredCountSubject\n | paginate: { itemsPerPage: limit, currentPage: page, totalItems: count, id: id }\n \"\n >\n <tr\n class=\"ngx-draggable-row\"\n cdkDrag\n (cdkDragStarted)=\"onDragStart($event)\"\n [cdkDragStartDelay]=\"config.reorderDelay || 0\"\n cdkDragLockAxis=\"y\"\n >\n <td *ngIf=\"config.checkboxes\">\n <label class=\"ngx-form-checkbox\">\n <input\n type=\"checkbox\"\n id=\"checkbox-draggable-{{ data.indexOf(row) }}\"\n [checked]=\"isSelected || selectedCheckboxes.has(data.indexOf(row))\"\n (change)=\"onCheckboxSelect($event, row, data.indexOf(row))\"\n />\n <em class=\"ngx-form-icon\"></em>\n </label>\n </td>\n <td *ngIf=\"config.radio\">\n <label>\n <input\n type=\"radio\"\n id=\"radio-draggable-{{ data.indexOf(row) }}\"\n name=\"radio\"\n (change)=\"onRadioSelect($event, row, data.indexOf(row))\"\n />\n </label>\n </td>\n <ng-container *ngFor=\"let column of columns; let colIndex = index\">\n <td\n (click)=\"onClick($event, row, column.key, colIndex, data.indexOf(row))\"\n (dblclick)=\"onDoubleClick($event, row, column.key, colIndex, data.indexOf(row))\"\n [class.ngx-table__table-col--selected]=\"\n colIndex === selectedCol && !config.selectCell\n \"\n [class.ngx-table__table-cell--selected]=\"\n colIndex === selectedCol &&\n data.indexOf(row) === selectedRow &&\n !config.selectCol &&\n !config.selectRow\n \"\n >\n <div *ngIf=\"!column.cellTemplate\">{{ row | render: column.key }}</div>\n <ng-container\n *ngIf=\"column.cellTemplate\"\n [ngTemplateOutlet]=\"column.cellTemplate\"\n [ngTemplateOutletContext]=\"{\n $implicit: row,\n rowIndex: data.indexOf(row),\n column: column\n }\"\n >\n </ng-container>\n </td>\n </ng-container>\n </tr>\n </ng-container>\n </ng-container>\n </tbody>\n <tbody *ngIf=\"filterCount === 0\">\n <tr class=\"ngx-table__body-empty\">\n <ng-container *ngIf=\"noResultsTemplate\" [ngTemplateOutlet]=\"noResultsTemplate\">\n </ng-container>\n <td [attr.colspan]=\"columns && columns.length + 1\" *ngIf=\"!noResultsTemplate\">\n <div class=\"ngx-table__table-no-results\">No results</div>\n </td>\n </tr>\n </tbody>\n <tbody *ngIf=\"config.isLoading\">\n <tr class=\"ngx-table__body-loading\">\n <ng-container *ngIf=\"loadingTemplate\" [ngTemplateOutlet]=\"loadingTemplate\"> </ng-container>\n <td [attr.colspan]=\"columns && columns.length + 1\" *ngIf=\"!loadingTemplate\">\n <div [style.height.px]=\"loadingHeight\" class=\"ngx-table__table-loader-wrapper\">\n <div class=\"ngx-table__table-loader\"></div>\n </div>\n </td>\n </tr>\n </tbody>\n <tfoot *ngIf=\"summaryTemplate\">\n <tr>\n <ng-container\n [ngTemplateOutlet]=\"summaryTemplate\"\n [ngTemplateOutletContext]=\"{ total: data.length, limit: limit, page: page }\"\n >\n </ng-container>\n </tr>\n </tfoot>\n </table>\n <pagination\n [attr.id]=\"'pagination' + id\"\n [id]=\"id\"\n #paginationComponent\n [config]=\"config\"\n [pagination]=\"pagination\"\n (updateRange)=\"onPagination($event)\"\n >\n </pagination>\n</div>\n" }]
}], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: i1.ScrollDispatcher }, { type: i2.StyleService }], propDecorators: { configuration: [{
type: Input
}], data: [{
type: Input
}], pagination: [{
type: Input
}], groupRowsBy: [{
type: Input
}], id: [{
type: Input
}], toggleRowIndex: [{
type: Input
}], detailsTemplate: [{
type: Input
}], summaryTemplate: [{
type: Input
}], groupRowsHeaderTemplate: [{
type: Input
}], filtersTemplate: [{
type: Input
}], selectAllTemplate: [{
type: Input
}], noResultsTemplate: [{
type: Input
}], loadingTemplate: [{
type: Input
}], additionalActionsTemplate: [{
type: Input
}], rowContextMenu: [{
type: Input
}], columns: [{
type: Input
}], event: [{
type: Output
}], rowTemplate: [{
type: ContentChild,
args: [TemplateRef]
}], paginationComponent: [{
type: ViewChild,
args: ['paginationComponent']
}], contextMenu: [{
type: ViewChild,
args: ['contextMenu']
}], table: [{
type: ViewChild,
args: ['table']
}], viewPort: [{
type: ViewChild,
args: [CdkVirtualScrollViewport]
}], onContextMenuClick: [{
type: HostListener,
args: ['document:click', ['$event.target']]
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmFzZS5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9uZ3gtZWFzeS10YWJsZS9zcmMvbGliL2NvbXBvbmVudHMvYmFzZS9iYXNlLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL25neC1lYXN5LXRhYmxlL3NyYy9saWIvY29tcG9uZW50cy9iYXNlL2Jhc2UuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUE2QixlQUFlLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUNwRixPQUFPLEVBRUwsdUJBQXVCLEVBRXZCLFNBQVMsRUFDVCxZQUFZLEVBQ1osWUFBWSxFQUNaLFlBQVksRUFDWixLQUFLLEVBSUwsTUFBTSxFQUdOLFdBQVcsRUFDWCxTQUFTLEdBQ1YsTUFBTSxlQUFlLENBQUM7QUFFdkIsT0FBTyxFQUFFLEdBQUcsRUFBNEIsS0FBSyxFQUFjLE1BQU0sT0FBTyxDQUFDO0FBQ3pFLE9BQU8sRUFBRSxvQkFBb0IsRUFBRSxNQUFNLCtCQUErQixDQUFDO0FBRXJFLE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLG1DQUFtQyxDQUFDO0FBQ3JFLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSw4QkFBOEIsQ0FBQztBQUM1RCxPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBQy9CLE9BQU8sRUFBRSx3QkFBd0IsRUFBb0IsTUFBTSx3QkFBd0IsQ0FBQztBQUNwRixPQUFPLEVBQUUsTUFBTSxFQUFFLFNBQVMsRUFBRSxZQUFZLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQzs7Ozs7Ozs7Ozs7OztBQWdCakUsTUFBTSxPQUFPLGFBQWE7SUFxRGpCLGtCQUFrQixDQUFDLGFBQWtCO1FBQzFDLElBQUksSUFBSSxDQUFDLFdBQVcsSUFBSSxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsYUFBYSxDQUFDLFFBQVEsQ0FB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Uzt1QkFBQyxhQUFhO2dCQUNKLEtBQUs7c0JBQXhCLFNBQVM7dUJBQUMsT0FBTztnQkFDbUIsUUFBUTtzQkFBNUMsU0FBUzt1QkFBQyx3QkFBd0I7Z0JBRzVCLGtCQUFrQjtzQkFEeEIsWUFBWTt1QkFBQyxnQkFBZ0IsRUFBRSxDQUFDLGVBQWUsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENka0RyYWdEcm9wLCBDZGtEcmFnU3RhcnQsIG1vdmVJdGVtSW5BcnJheSB9IGZyb20gJ0Bhbmd1bGFyL2Nkay9kcmFnLWRyb3AnO1xuaW1wb3J0IHtcbiAgQWZ0ZXJWaWV3SW5pdCxcbiAgQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3ksXG4gIENoYW5nZURldGVjdG9yUmVmLFxuICBDb21wb25lbnQsXG4gIENvbnRlbnRDaGlsZCxcbiAgRXZlbnRFbWl0dGVyLFxuICBIb3N0TGlzdGVuZXIsXG4gIElucHV0LFxuICBPbkNoYW5nZXMsXG4gIE9uRGVzdHJveSxcbiAgT25Jbml0LFxuICBPdXRwdXQsXG4gIFNpbXBsZUNoYW5nZSxcbiAgU2ltcGxlQ2hhbmdlcyxcbiAgVGVtcGxhdGVSZWYsXG4gIFZpZXdDaGlsZCxcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5cbmltcG9ydCB7IEFQSSwgQXBpVHlwZSwgQ29sdW1ucywgQ29uZmlnLCBFdmVudCwgUGFnaW5hdGlvbiB9IGZyb20gJy4uLy4uJztcbmltcG9ydCB7IERlZmF1bHRDb25maWdTZXJ2aWNlIH0gZnJvbSAnLi4vLi4vc2VydmljZXMvY29uZmlnLXNlcnZpY2UnO1xuaW1wb3J0IHsgUGFnaW5hdGlvbkNvbXBvbmVudCwgUGFnaW5hdGlvblJhbmdlIH0gZnJvbSAnLi4vcGFnaW5hdGlvbi9wYWdpbmF0aW9uLmNvbXBvbmVudCc7XG5pbXBvcnQgeyBHcm91cFJvd3NTZXJ2aWNlIH0gZnJvbSAnLi4vLi4vc2VydmljZXMvZ3JvdXAtcm93cy5zZXJ2aWNlJztcbmltcG9ydCB7IFN0eWxlU2VydmljZSB9IGZyb20gJy4uLy4uL3NlcnZpY2VzL3N0eWxlLnNlcnZpY2UnO1xuaW1wb3J0IHsgU3ViamVjdCB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgQ2RrVmlydHVhbFNjcm9sbFZpZXdwb3J0LCBTY3JvbGxEaXNwYXRjaGVyIH0gZnJvbSAnQGFuZ3VsYXIvY2RrL3Njcm9sbGluZyc7XG5pbXBvcnQgeyBmaWx0ZXIsIHRha2VVbnRpbCwgdGhyb3R0bGVUaW1lIH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuXG50eXBlIENvbHVtbktleVR5cGUgPSBzdHJpbmcgfCBudW1iZXIgfCBib29sZWFuO1xuXG5pbnRlcmZhY2UgUm93Q29udGV4dE1lbnVQb3NpdGlvbiB7XG4gIHRvcDogc3RyaW5nIHwgbnVsbDtcbiAgbGVmdDogc3RyaW5nIHwgbnVsbDtcbiAgdmFsdWU6IGFueSB8IG51bGw7XG59XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ25neC10YWJsZScsXG4gIHByb3ZpZGVyczogW0RlZmF1bHRDb25maWdTZXJ2aWNlLCBHcm91cFJvd3NTZXJ2aWNlLCBTdHlsZVNlcnZpY2VdLFxuICB0ZW1wbGF0ZVVybDogJy4vYmFzZS5jb21wb25lbnQuaHRtbCcsXG4gIGNoYW5nZURldGVjdGlvbjogQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3kuT25QdXNoLFxufSlcbmV4cG9ydCBjbGFzcyBCYXNlQ29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0LCBPbkNoYW5nZXMsIEFmdGVyVmlld0luaXQsIE9uRGVzdHJveSB7XG4gIHByaXZhdGUgdW5zdWJzY3JpYmUgPSBuZXcgU3ViamVjdDx2b2lkPigpO1xuICBwdWJsaWMgc2VsZWN0ZWRSb3c6IG51bWJlcjtcbiAgcHVibGljIHNlbGVjdGVkQ29sOiBudW1iZXI7XG4gIHB1YmxpYyB0ZXJtOiBhbnk7XG4gIHB1YmxpYyBmaWx0ZXJDb3VudCA9IC0xO1xuICBwdWJsaWMgZmlsdGVyZWRDb3VudFN1YmplY3QgPSBuZXcgU3ViamVjdDxudW1iZXI+KCk7XG4gIHB1YmxpYyB0YWJsZUNsYXNzOiBzdHJpbmcgfCBudWxsID0gbnVsbDtcbiAgcHVibGljIGdsb2JhbFNlYXJjaFRlcm06IHN0cmluZztcbiAgcHVibGljIGdyb3VwZWQ6IGFueSA9IFtdO1xuICBwdWJsaWMgaXNTZWxlY3RlZCA9IGZhbHNlO1xuICBwdWJsaWMgcGFnZSA9IDE7XG4gIHB1YmxpYyBjb3VudCA9IDA7XG4gIHB1YmxpYyBzb3J0U3RhdGUgPSBuZXcgTWFwKCk7XG4gIHB1YmxpYyBzb3J0S2V5OiBzdHJpbmcgfCBudWxsID0gbnVsbDtcbiAgcHVibGljIHJvd0NvbnRleHRNZW51UG9zaXRpb246IFJvd0NvbnRleHRNZW51UG9zaXRpb24gPSB7XG4gICAgdG9wOiBudWxsLFxuICAgIGxlZnQ6IG51bGwsXG4gICAgdmFsdWU6IG51bGwsXG4gIH07XG4gIHB1YmxpYyBsaW1pdDtcbiAgcHVibGljIHNvcnRCeTogeyBrZXk6IHN0cmluZyB9ICYgeyBvcmRlcjogc3RyaW5nIH0gPSB7XG4gICAga2V5OiAnJyxcbiAgICBvcmRlcjogJ2FzYycsXG4gIH07XG4gIHB1YmxpYyBzZWxlY3RlZERldGFpbHNUZW1wbGF0ZVJvd0lkID0gbmV3IFNldDxudW1iZXI+KCk7XG4gIHB1YmxpYyBzZWxlY3RlZENoZWNrYm94ZXMgPSBuZXcgU2V0PG51bWJlcj4oKTtcbiAgcHVibGljIGNvbmZpZzogQ29uZmlnO1xuXG4gIEBJbnB1dCgpIGNvbmZpZ3VyYXRpb246IENvbmZpZztcbiAgQElucHV0KCkgZGF0YTogYW55W107XG4gIEBJbnB1dCgpIHBhZ2luYXRpb246IFBhZ2luYXRpb247XG4gIEBJbnB1dCgpIGdyb3VwUm93c0J5OiBzdHJpbmc7XG4gIEBJbnB1dCgpIGlkID0gJ3RhYmxlJztcbiAgQElucHV0KCkgdG9nZ2xlUm93SW5kZXg7XG4gIEBJbnB1dCgpIGRldGFpbHNUZW1wbGF0ZTogVGVtcGxhdGVSZWY8YW55PjtcbiAgQElucHV0KCkgc3VtbWFyeVRlbXBsYXRlOiBUZW1wbGF0ZVJlZjx7IHRvdGFsOiBudW1iZXI7IGxpbWl0OiBudW1iZXI7IHBhZ2U6IG51bWJlciB9PjtcbiAgQElucHV0KCkgZ3JvdXBSb3dzSGVhZGVyVGVtcGxhdGU6IFRlbXBsYXRlUmVmPGFueT47XG4gIEBJbnB1dCgpIGZpbHRlcnNUZW1wbGF0ZTogVGVtcGxhdGVSZWY8YW55PjtcbiAgQElucHV0KCkgc2VsZWN0QWxsVGVtcGxhdGU6IFRlbXBsYXRlUmVmPGFueT47XG4gIEBJbnB1dCgpIG5vUmVzdWx0c1RlbXBsYXRlOiBUZW1wbGF0ZVJlZjx2b2lkPjtcbiAgQElucHV0KCkgbG9hZGluZ1RlbXBsYXRlOiBUZW1wbGF0ZVJlZjx2b2lkPjtcbiAgQElucHV0KCkgYWRkaXRpb25hbEFjdGlvbnNUZW1wbGF0ZTogVGVtcGxhdGVSZWY8dm9pZD47XG4gIEBJbnB1dCgpIHJvd0NvbnRleHRNZW51OiBUZW1wbGF0ZVJlZjxhbnk+O1xuICBASW5wdXQoKSBjb2x1bW5zOiBDb2x1bW5zW107XG4gIEBPdXRwdXQoKSByZWFkb25seSBldmVudCA9IG5ldyBFdmVudEVtaXR0ZXI8eyBldmVudDogc3RyaW5nOyB2YWx1ZTogYW55IH0+KCk7XG4gIEBDb250ZW50Q2hpbGQoVGVtcGxhdGVSZWYpIHB1YmxpYyByb3dUZW1wbGF0ZTogVGVtcGxhdGVSZWY8YW55PjtcbiAgQFZpZXdDaGlsZCgncGFnaW5hdGlvbkNvbXBvbmVudCcpIHByaXZhdGUgcGFnaW5hdGlvbkNvbXBvbmVudDogUGFnaW5hdGlvbkNvbXBvbmVudDtcbiAgQFZpZXdDaGlsZCgnY29udGV4dE1lbnUnKSBjb250ZXh0TWVudTtcbiAgQFZpZXdDaGlsZCgndGFibGUnKSB0YWJsZTtcbiAgQFZpZXdDaGlsZChDZGtWaXJ0dWFsU2Nyb2xsVmlld3BvcnQpIHZpZXdQb3J0OiBDZGtWaXJ0dWFsU2Nyb2xsVmlld3BvcnQ7XG5cbiAgQEhvc3RMaXN0ZW5lcignZG9jdW1lbnQ6Y2xpY2snLCBbJyRldmVudC50YXJnZXQnXSlcbiAgcHVibGljIG9uQ29udGV4dE1lbnVDbGljayh0YXJnZXRFbGVtZW50OiBhbnkpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5jb250ZXh0TWVudSAmJiAhdGhpcy5jb250ZXh0TWVudS5uYXRpdmVFbGVtZW50LmNvbnRhaW5zKHRhcmdldEVsZW1lbnQpKSB7XG4gICAgICB0aGlzLnJvd0NvbnRleHRNZW51UG9zaXRpb24gPSB7XG4gICAgICAgIHRvcDogbnVsbCxcbiAgICAgICAgbGVmdDogbnVsbCxcbiAgICAgICAgdmFsdWU6IG51bGwsXG4gICAgICB9O1xuICAgIH1cbiAgfVxuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgcmVhZG9ubHkgY2RyOiBDaGFuZ2VEZXRlY3RvclJlZixcbiAgICBwcml2YXRlIHJlYWRvbmx5IHNjcm9sbERpc3BhdGNoZXI6IFNjcm9sbERpc3BhdGNoZXIsXG4gICAgcHVibGljIHJlYWRvbmx5IHN0eWxlU2VydmljZTogU3R5bGVTZXJ2aWNlXG4gICkge1xuICAgIHRoaXMuZmlsdGVyZWRDb3VudFN1YmplY3QucGlwZSh0YWtlVW50aWwodGhpcy51bnN1YnNjcmliZSkpLnN1YnNjcmliZSgoY291bnQpID0+IHtcbiAgICAgIHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICB0aGlzLmZpbHRlckNvdW50ID0gY291bnQ7XG4gICAgICAgIHRoaXMuY2RyLmRldGVjdENoYW5nZXMoKTtcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG5cbiAgbmdPbkluaXQoKTogdm9pZCB7XG4gICAgaWYgKCF0aGlzLmNvbHVtbnMpIHtcbiAgICAgIGNvbnNvbGUuZXJyb3IoJ1tjb2x1bW5zXSBwcm9wZXJ0eSByZXF1aXJlZCEnKTtcbiAgICB9XG4gICAgaWYgKHRoaXMuY29uZmlndXJhdGlvbikge1xuICAgICAgdGhpcy5jb25maWcgPSB0aGlzLmNvbmZpZ3VyYXRpb247XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuY29uZmlnID0gRGVmYXVsdENvbmZpZ1NlcnZpY2UuY29uZmlnO1xuICAgIH1cbiAgICB0aGlzLmxpbWl0ID0gdGhpcy5jb25maWcucm93cztcbiAgICBpZiAodGhpcy5ncm91cFJvd3NCeSkge1xuICAgICAgdGhpcy5ncm91cGVkID0gR3JvdXBSb3dzU2VydmljZS5kb0dyb3VwUm93cyh0aGlzLmRhdGEsIHRoaXMuZ3JvdXBSb3dzQnkpO1xuICAgIH1cbiAgICB0aGlzLmRvRGVjb2RlUGVyc2lzdGVkU3RhdGUoKTtcbiAgfVxuXG4gIG5nT25EZXN0cm95KCk6IHZvaWQge1xuICAgIHRoaXMudW5zdWJzY3JpYmUubmV4dCgpO1xuICAgIHRoaXMudW5zdWJzY3JpYmUuY29tcGxldGUoKTtcbiAgfVxuXG4gIG5nQWZ0ZXJWaWV3SW5pdCgpOiB2b2lkIHtcbiAgICBjb25zdCB0aHJvdHRsZVZhbHVlID0gdGhpcy5jb25maWcuaW5maW5pdGVTY3JvbGxUaHJvdHRsZVRpbWVcbiAgICAgID8gdGhpcy5jb25maWcuaW5maW5pdGVTY3JvbGxUaHJvdHRsZVRpbWVcbiAgICAgIDogMjAwO1xuICAgIHRoaXMuc2Nyb2xsRGlzcGF0Y2hlclxuICAgICAgLnNjcm9sbGVkKClcbiAgICAgIC5waXBlKFxuICAgICAgICB0aHJvdHRsZVRpbWUodGhyb3R0bGVWYWx1ZSksXG4gICAgICAgIGZpbHRlcigoZXZlbnQpID0+IHtcbiAgICAgICAgICByZXR1cm4gKFxuICAgICAgICAgICAgISFldmVudCAmJlxuICAgICAgICAgICAgdGhpcy52aWV3UG9ydCAmJlxuICAgICAgICAgICAgdGhpcy52aWV3UG9ydC5nZXRSZW5kZXJlZFJhbmdlKCkuZW5kID09PSB0aGlzLnZpZXdQb3J0LmdldERhdGFMZW5ndGgoKVxuICAgICAgICAgICk7XG4gICAgICAgIH0pLFxuICAgICAgICB0YWtlVW50aWwodGhpcy51bnN1YnNjcmliZSlcbiAgICAgIClcbiAgICAgIC5zdWJzY3JpYmUoKCkgPT4ge1xuICAgICAgICB0aGlzLmVtaXRFdmVudChFdmVudC5vbkluZmluaXRlU2Nyb2xsRW5kLCBudWxsKTtcbiAgICAgIH0pO1xuICB9XG5cbiAgbmdPbkNoYW5nZXMoY2hhbmdlczogU2ltcGxlQ2hhbmdlcyk6IHZvaWQge1xuICAgIGNvbnN0IHsgY29uZmlndXJhdGlvbiwgZGF0YSwgcGFnaW5hdGlvbiwgZ3JvdXBSb3dzQnkgfSA9IGNoYW5nZXM7XG4gICAgdGhpcy50b2dnbGVSb3dJbmRleCA9IGNoYW5nZXMudG9nZ2xlUm93SW5kZXg7XG4gICAgaWYgKGNvbmZpZ3VyYXRpb24gJiYgY29uZmlndXJhdGlvbi5jdXJyZW50VmFsdWUpIHtcbiAgICAgIHRoaXMuY29uZmlnID0gY29uZmlndXJhdGlvbi5jdXJyZW50VmFsdWU7XG4gICAgfVxuICAgIGlmIChkYXRhICYmIGRhdGEuY3VycmVudFZhbHVlKSB7XG4gICAgICB0aGlzLmRvQXBwbHlEYXRhKGRhdGEpO1xuICAgIH1cbiAgICBpZiAocGFnaW5hdGlvbiAmJiBwYWdpbmF0aW9uLmN1cnJlbnRWYWx1ZSkge1xuICAgICAgY29uc3QgeyBjb3VudCwgbGltaXQsIG9mZnNldCB9ID0gcGFnaW5hdGlvbi5jdXJyZW50VmFsdWUgYXMgUGFnaW5hdGlvbjtcbiAgICAgIHRoaXMuY291bnQgPSBjb3VudDtcbiAgICAgIHRoaXMubGltaXQgPSBsaW1pdDtcbiAgICAgIHRoaXMucGFnZSA9IG9mZnNldDtcbiAgICB9XG4gICAgaWYgKGdyb3VwUm93c0J5ICYmIGdyb3VwUm93c0J5LmN1cnJlbnRWYWx1ZSkge1xuICAgICAgdGhpcy5ncm91cGVkID0gR3JvdXBSb3dzU2VydmljZS5kb0dyb3VwUm93cyh0aGlzLmRhdGEsIHRoaXMuZ3JvdXBSb3dzQnkpO1xuICAgIH1cbiAgICBpZiAodGhpcy50b2dnbGVSb3dJbmRleCAmJiB0aGlzLnRvZ2dsZVJvd0luZGV4LmN1cnJlbnRWYWx1ZSkge1xuICAgICAgY29uc3Qgcm93ID0gdGhpcy50b2dnbGVSb3dJbmRleC5jdXJyZW50VmFsdWU7XG4gICAgICB0aGlzLmNvbGxhcHNlUm93KHJvdy5pbmRleCk7XG4gICAgfVxuICB9XG5cbiAgb3JkZXJCeShjb2x1bW46IENvbHVtbnMpOiB2b2lkIHtcbiAgICBpZiAodHlwZW9mIGNvbHVtbi5vcmRlckVuYWJsZWQgIT09ICd1bmRlZmluZWQnICYmICFjb2x1bW4ub3JkZXJFbmFibGVkKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHRoaXMuc29ydEtleSA9IGNvbHVtbi5rZXk7XG4gICAgaWYgKCF0aGlzLmNvbmZpZy5vcmRlckVuYWJsZWQgfHwgdGhpcy5zb3J0S2V5ID09PSAnJykge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHRoaXMuc2V0Q29sdW1uT3JkZXIoY29sdW1uKTtcbiAgICBpZiAoIXRoaXMuY29uZmlnLm9yZGVyRXZlbnRPbmx5ICYmICFjb2x1bW4ub3JkZXJFdmVudE9ubHkpIHtcbiAgICAgIHRoaXMuc29ydEJ5LmtleSA9IHRoaXMuc29ydEtleTtcbiAgICAgIHRoaXMuc29ydEJ5Lm9yZGVyID0gdGhpcy5zb3J0U3RhdGUuZ2V0KHRoaXMuc29ydEtleSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuc29ydEJ5LmtleSA9ICcnO1xuICAgICAgdGhpcy5zb3J0Qnkub3JkZXIgPSAnJztcbiAgICB9XG4gICAgaWYgKCF0aGlzLmNvbmZpZy5zZXJ2ZXJQYWdpbmF0aW9uKSB7XG4gICAgICB0aGlzLmRhdGEgPSBbLi4udGhpcy5kYXRhXTtcbiAgICAgIHRoaXMuc29ydEJ5ID0geyAuLi50aGlzLnNvcnRCeSB9O1xuICAgIH1cblxuICAgIGNvbnN0IHZhbHVlID0ge1xuICAgICAga2V5OiB0aGlzLnNvcnRLZXksXG4gICAgICBvcmRlcjogdGhpcy5zb3J0U3RhdGUuZ2V0KHRoaXMuc29ydEtleSksXG4gICAgfTtcbiAgICB0aGlzLmVtaXRFdmVudChFdmVudC5vbk9yZGVyLCB2YWx1ZSk7XG4gIH1cblxuICBvbkNsaWNrKCRldmVudDogTW91c2VFdmVudCwgcm93OiBhbnksIGtleTogQ29sdW1uS2V5VHlwZSwgY29sSW5kZXg6IGFueSwgcm93SW5kZXg6IG51bWJlcik6IHZvaWQge1xuICAgIGlmICh0aGlzLmNvbmZpZy5zZWxlY3RSb3cpIHtcbiAgICAgIHRoaXMuc2VsZWN0ZWRSb3cgPSByb3dJbmRleDtcbiAgICB9XG4gICAgaWYgKHRoaXMuY29uZmlnLnNlbGVjdENvbCAmJiBgJHtjb2xJbmRleH1gKSB7XG4gICAgICB0aGlzLnNlbGVjdGVkQ29sID0gY29sSW5kZXg7XG4gICAgfVxuICAgIGlmICh0aGlzLmNvbmZpZy5zZWxlY3RDZWxsICYmIGAke2NvbEluZGV4fWApIHtcbiAgICAgIHRoaXMuc2VsZWN0ZWRSb3cgPSByb3dJbmRleDtcbiAgICAgIHRoaXMuc2VsZWN0ZWRDb2wgPSBjb2xJbmRleDtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5jb25maWcuY2xpY2tFdmVudCkge1xuICAgICAgY29uc3QgdmFsdWUgPSB7XG4gICAgICAgIGV2ZW50OiAkZXZlbnQsXG4gICAgICAgIHJvdyxcbiAgICAgICAga2V5LFxuICAgICAgICByb3dJZDogcm93SW5kZXgsXG4gICAgICAgIGNvbElkOiBjb2xJbmRleCxcbiAgICAgIH07XG4gICAgICB0aGlzLmVtaXRFdmVudChFdmVudC5vbkNsaWNrLCB2YWx1ZSk7XG4gICAgfVxuICB9XG5cbiAgb25Eb3VibGVDbGljayhcbiAgICAkZXZlbnQ6IE1vdXNlRXZlbnQsXG4gICAgcm93OiBhbnksXG4gICAga2V5OiBDb2x1bW5LZXlUeXBlLFxuICAgIGNvbEluZGV4OiBhbnksXG4gICAgcm93SW5kZXg6IG51bWJlclxuICApOiB2b2lkIHtcbiAgICBjb25zdCB2YWx1ZSA9IHtcbiAgICAgIGV2ZW50OiAkZXZlbnQsXG4gICAgICByb3csXG4gICAgICBrZXksXG4gICAgICByb3dJZDogcm93SW5kZXgsXG4gICAgICBjb2xJZDogY29sSW5kZXgsXG4gICAgfTtcbiAgICB0aGlzLmVtaXRFdmVudChFdmVudC5vbkRvdWJsZUNsaWNrLCB2YWx1ZSk7XG4gIH1cblxuICBvbkNoZWNrYm94U2VsZWN0KCRldmVudDogYW55LCByb3c6IGFueSwgcm93SW5kZXg6IG51bWJlcik6IHZvaWQge1xuICAgIGNvbnN0IHZhbHVlID0ge1xuICAgICAgZXZlbnQ6ICRldmVudCxcbiAgICAgIHJvdyxcbiAgICAgIHJvd0lkOiByb3dJbmRleCxcbiAgICB9O1xuICAgIHRoaXMuZW1pdEV2ZW50KEV2ZW50Lm9uQ2hlY2tib3hTZWxlY3QsIHZhbHVlKTtcbiAgfVxuXG4gIG9uUmFkaW9TZWxlY3QoJGV2ZW50OiBhbnksIHJvdzogYW55LCByb3dJbmRleDogbnVtYmVyKTogdm9pZCB7XG4gICAgY29uc3QgdmFsdWUgPSB7XG4gICAgICBldmVudDogJGV2ZW50LFxuICAgICAgcm93LFxuICAgICAgcm93SWQ6IHJvd0luZGV4LFxuICAgIH07XG4gICAgdGhpcy5lbWl0RXZlbnQoRXZlbnQub25SYWRpb1NlbGVjdCwgdmFsdWUpO1xuICB9XG5cbiAgb25TZWxlY3RBbGwoKTogdm9pZCB7XG4gICAgdGhpcy5pc1NlbGVjdGVkID0gIXRoaXMuaXNTZWxlY3RlZDtcbiAgICB0aGlzLmVtaXRFdmVudChFdmVudC5vblNlbGVjdEFsbCwgdGhpcy5pc1NlbGVjdGVkKTtcbiAgfVxuXG4gIG9uU2VhcmNoKCRldmVudDogQXJyYXk8eyBrZXk6IHN0cmluZzsgdmFsdWU6IHN0cmluZyB9Pik6IHZvaWQge1xuICAgIGlmICghdGhpcy5jb25maWcuc2VydmVyUGFnaW5hdGlvbikge1xuICAgICAgdGhpcy50ZXJtID0gJGV2ZW50O1xuICAgIH1cbiAgICB0aGlzLmVtaXRFdmVudChFdmVudC5vblNlYXJjaCwgJGV2ZW50KTtcbiAgfVxuXG4gIG9uR2xvYmFsU2VhcmNoKHZhbHVlOiBzdHJpbmcpOiB2b2lkIHtcbiAgICBpZiAoIXRoaXMuY29uZmlnLnNlcnZlclBhZ2luYXRpb24pIHtcbiAgICAgIHRoaXMuZ2xvYmFsU2VhcmNoVGVybSA9IHZhbHVlO1xuICAgIH1cbiAgICB0aGlzLmVtaXRFdmVudChFdmVudC5vbkdsb2JhbFNlYXJjaCwgdmFsdWUpO1xuICB9XG5cbiAgb25QYWdpbmF0aW9uKHBhZ2luYXRpb246IFBhZ2luYXRpb25SYW5nZSk6IHZvaWQge1xuICAgIHRoaXMucGFnZSA9IHBhZ2luYXRpb24ucGFnZTtcbiAgICB0aGlzLmxpbWl0ID0gcGFnaW5hdGlvbi5saW1pdDtcbiAgICB0aGlzLmNvbmZpZy5yb3dzID0gcGFnaW5hdGlvbi5saW1pdDtcbiAgICB0aGlzLmVtaXRFdmVudChFdmVudC5vblBhZ2luYXRpb24sIHBhZ2luYXRpb24pO1xuICB9XG5cbiAgdG9nZ2xlQ2hlY2tib3gocm93SW5kZXg6IG51bWJlcik6IHZvaWQge1xuICAgIHRoaXMuc2VsZWN0ZWRDaGVja2JveGVzLmhhcyhyb3dJbmRleClcbiAgICAgID8gdGhpcy5zZWxlY3RlZENoZWNrYm94ZXMuZGVsZXRlKHJvd0luZGV4KVxuICAgICAgOiB0aGlzLnNlbGVjdGVkQ2hlY2tib3hlcy5hZGQocm93SW5kZXgpO1xuICB9XG5cbiAgY29sbGFwc2VSb3cocm93SW5kZXg6IG51bWJlcik6IHZvaWQge1xuICAgIGlmICh0aGlzLnNlbGVjdGVkRGV0YWlsc1RlbXBsYXRlUm93SWQuaGFzKHJvd0luZGV4KSkge1xuICAgICAgdGhpcy5zZWxlY3RlZERldGFpbHNUZW1wbGF0ZVJvd0lkLmRlbGV0ZShyb3dJbmRleCk7XG4gICAgICB0aGlzLmVtaXRFdmVudChFdmVudC5vblJvd0NvbGxhcHNlZEhpZGUsIHJvd0luZGV4KTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5zZWxlY3RlZERldGFpbHNUZW1wbGF0ZVJvd0lkLmFkZChyb3dJbmRleCk7XG4gICAgICB0aGlzLmVtaXRFdmVudChFdmVudC5vblJvd0NvbGxhcHNlZFNob3csIHJvd0luZGV4KTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGRvRGVjb2RlUGVyc2lzdGVkU3RhdGUoKTogdm9pZCB7XG4gICAgaWYgKCF0aGlzLmNvbmZpZy5wZXJzaXN0U3RhdGUpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgY29uc3QgcGFnaW5hdGlvbiA9IGxvY2FsU3RvcmFnZS5nZXRJdGVtKEV2ZW50Lm9uUGFnaW5hdGlvbik7XG4gICAgY29uc3Qgc29ydCA9IGxvY2FsU3RvcmFnZS5nZXRJdGVtKEV2ZW50Lm9uT3JkZXIpO1xuICAgIGNvbnN0IHNlYXJjaCA9IGxvY2FsU3RvcmFnZS5nZXRJdGVtKEV2ZW50Lm9uU2VhcmNoKTtcbiAgICBpZiAocGFnaW5hdGlvbikge1xuICAgICAgdGhpcy5vblBhZ2luYXRpb24oSlNPTi5wYXJzZShwYWdpbmF0aW9uKSk7XG4gICAgfVxuICAgIGlmIChzb3J0KSB7XG4gICAgICBjb25zdCB7IGtleSwgb3JkZXIgfSA9IEpTT04ucGFyc2Uoc29ydCk7XG4gICAgICB0aGlzLmJpbmRBcGkoe1xuICAgICAgICB0eXBlOiBBUEkuc29ydEJ5LFxuICAgICAgICB2YWx1ZTogeyBjb2x1bW46IGtleSwgb3JkZXIgfSxcbiAgICAgIH0pO1xuICAgIH1cbiAgICBpZiAoc2VhcmNoKSB7XG4gICAgICB0aGlzLmJpbmRBcGkoe1xuICAgICAgICB0eXBlOiBBUEkuc2V0SW5wdXRWYWx1ZSxcbiAgICAgICAgdmFsdWU6IEpTT04ucGFyc2Uoc2VhcmNoKSxcbiAgICAgIH0pO1xuICAgIH1cbiAgfVxuXG4gIGlzUm93Q29sbGFwc2VkKHJvd0luZGV4OiBudW1iZXIpOiBib29sZWFuIHtcbiAgICBpZiAodGhpcy5jb25maWcuY29sbGFwc2VBbGxSb3dzKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuc2VsZWN0ZWREZXRhaWxzVGVtcGxhdGVSb3dJZC5oYXMocm93SW5kZXgpO1xuICB9XG5cbiAgZ2V0IGxvYWRpbmdIZWlnaHQoKTogbnVtYmVyIHtcbiAgICBjb25zdCB0YWJsZSA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKHRoaXMuaWQpIGFzIEhUTUxUYWJsZUVsZW1lbnQ7XG4gICAgaWYgKHRhYmxlICYmIHRhYmxlLnJvd3MgJiYgdGFibGUucm93cy5sZW5ndGggPiAzKSB7XG4gICAgICBjb25zdCBzZWFyY2hFbmFibGVkID0gdGhpcy5jb25maWcuc2VhcmNoRW5hYmxlZCA/IDEgOiAwO1xuICAgICAgY29uc3QgaGVhZGVyRW5hYmxlZCA9IHRoaXMuY29uZmlnLmhlYWRlckVuYWJsZWQgPyAxIDogMDtcbiAgICAgIGNvbnN0IGJvcmRlclRySGVpZ2h0ID0gMTtcbiAgICAgIGNvbnN0IGJvcmRlckRpdkhlaWdodCA9IDI7XG4gICAgICByZXR1cm4gKFxuICAgICAgICAodGFibGUucm93cy5sZW5ndGggLSBzZWFyY2hFbmFibGVkIC0gaGVhZGVyRW5hYmxlZCkgKlxuICAgICAgICAgICh0YWJsZS5yb3dzWzNdLm9mZnNldEhlaWdodCAtIGJvcmRlclRySGVpZ2h0KSAtXG4gICAgICAgIGJvcmRlckRpdkhlaWdodFxuICAgICAgKTtcbiAgICB9XG5cbiAgICByZXR1cm4gMzA7XG4gIH1cblxuICBnZXQgYXJyb3dEZWZpbml0aW9uKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLmNvbmZpZy5zaG93RGV0YWlsc0Fycm93IHx8IHR5cGVvZiB0aGlzLmNvbmZpZy5zaG93RGV0YWlsc0Fycm93ID09PSAndW5kZWZpbmVkJztcbiAgfVxuXG4gIG9uUm93Q29udGV4dE1lbnUoXG4gICAgJGV2ZW50OiBNb3VzZUV2ZW50LFxuICAgIHJvdzogYW55LFxuICAgIGtleTogQ29sdW1uS2V5VHlwZSxcbiAgICBjb2xJbmRleDogYW55LFxuICAgIHJvd0luZGV4OiBudW1iZXJcbiAgKTogdm9pZCB7XG4gICAgaWYgKCF0aGlzLmNvbmZpZy5zaG93Q29udGV4dE1lbnUpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgJGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgY29uc3QgdmFsdWUgPSB7XG4gICAgICBldmVudDogJGV2ZW50LFxuICAgICAgcm93LFxuICAgICAga2V5LFxuICAgICAgcm93SWQ6IHJvd0luZGV4LFxuICAgICAgY29sSWQ6IGNvbEluZGV4LFxuICAgIH07XG4gICAgdGhpcy5yb3dDb250ZXh0TWVudVBvc2l0aW9uID0ge1xuICAgICAgdG9wOiBgJHskZXZlbnQucGFnZVkgLSAxMH1weGAsXG4gICAgICBsZWZ0OiBgJHskZXZlbnQucGFnZVggLSAxMH1weGAsXG4gICAgICB2YWx1ZSxcbiAgICB9O1xuXG4gICAgdGhpcy5lbWl0RXZlbnQoRXZlbnQub25Sb3dDb250ZXh0TWVudSwgdmFsdWUpO1xuICB9XG5cbiAgcHJpdmF0ZSBkb0FwcGx5RGF0YShkYXRhOiBTaW1wbGVDaGFuZ2UpOiB2b2lkIHtcbiAgICBjb25zdCBvcmRlciA9IHRoaXMuY29sdW1ucy5maW5kKChjKSA9PiAhIWMub3JkZXJCeSk7XG4gICAgaWYgKG9yZGVyKSB7XG4gICAgICB0aGlzLnNvcnRTdGF0ZS5zZXQodGhpcy5zb3J0S2V5LCBvcmRlci5vcmRlckJ5ID09PSAnYXNjJyA/ICdkZXNjJyA6ICdhc2MnKTtcbiAgICAgIHRoaXMub3JkZXJCeShvcmRlcik7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuZGF0YSA9IFsuLi5kYXRhLmN1cnJlbnRWYWx1ZV07XG4gICAgfVxuICB9XG5cbiAgb25EcmFnU3RhcnQoZXZlbnQ6IENka0RyYWdTdGFydCk6IHZvaWQge1xuICAgIHRoaXMuZW1pdEV2ZW50KEV2ZW50Lm9uUmVvcmRlclN0YXJ0LCBldmVudCk7XG4gIH1cblxuICBvbkRyb3AoZXZlbnQ6IENka0RyYWdEcm9wPHN0cmluZ1tdPik6IHZvaWQge1xuICAgIHRoaXMuZW1pdEV2ZW50KEV2ZW50Lm9uUm93RHJvcCwgZXZlbnQpO1xuICAgIG1vdmVJdGVtSW5BcnJheSh0aGlzLmRhdGEsIGV2ZW50LnByZXZpb3VzSW5kZXgsIGV2ZW50LmN1cnJlbnRJbmRleCk7XG4gIH1cblxuICAvLyBETyBOT1QgUkVNT1ZFLiBJdCBpcyBjYWxsZWQgZnJvbSBwYXJlbnQgY29tcG9uZW50LiBTZWUgc3JjL2FwcC9kZW1vL2FwaS1kb2MvYXBpLWRvYy5jb21wb25lbnQudHNcbiAgYXBpRXZlbnQoZXZlbnQ6IEFwaVR5cGUpOiB2b2lkIHwgbnVtYmVyIHtcbiAgICByZXR1cm4gdGhpcy5iaW5kQXBpKGV2ZW50KTtcbiAgfVxuXG4gIC8qIGVzbGludC1kaXNhYmxlICovXG4gIHByaXZhdGUgYmluZEFwaShldmVudDogQXBpVHlwZSk6IHZvaWQgfCBudW1iZXIge1xuICAgIHN3aXRjaCAoZXZlbnQudHlwZSkge1xuICAgICAgY2FzZSBBUEkucm93Q29udGV4dE1lbnVDbGlja2VkOlxuICAgICAgICB0aGlzLnJvd0NvbnRleHRNZW51UG9zaXRpb24gPSB7XG4gICAgICAgICAgdG9wOiBudWxsLFxuICAgICAgICAgIGxlZnQ6IG51bGwsXG4gICAgICAgICAgdmFsdWU6IG51bGwsXG4gICAgICAgIH07XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSBBUEkudG9nZ2xlUm93SW5kZXg6XG4gICAgICAgIHRoaXMuY29sbGFwc2VSb3coZXZlbnQudmFsdWUpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgQVBJLnRvZ2dsZUNoZWNrYm94OlxuICAgICAgICB0aGlzLnRvZ2dsZUNoZWNrYm94KGV2ZW50LnZhbHVlKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIEFQSS5zZXRJbnB1dFZhbHVlOlxuICAgICAgICBpZiAodGhpcy5jb25maWcuc2VhcmNoRW5hYmxlZCkge1xuICAgICAgICAgIGV2ZW50LnZhbHVlLmZvckVhY2goKGlucHV0KSA9PiB7XG4gICAgICAgICAgICBjb25zdCBlbGVtZW50ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoYHNlYXJjaF8ke2lucHV0LmtleX1gKSBhcyBIVE1MSW5wdXRFbGVtZW50O1xuICAgICAgICAgICAgaWYgKCFlbGVtZW50KSB7XG4gICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoXG4gICAgICAgICAgICAgICAgYENvbHVtbiAnJHtpbnB1dC5rZXl9JyBub3QgYXZhaWxhYmxlIGluIHRoZSBET00uIEhhdmUgeW91IG1pc3NwZWxsZWQgYSBuYW1lP2BcbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIGVsZW1lbnQudmFsdWUgPSBpbnB1dC52YWx1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLm9uU2VhcmNoKGV2ZW50LnZhbHVlKTtcbiAgICAgICAgdGhpcy5jZHIubWFya0ZvckNoZWNrKCk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSBBUEkub25HbG9iYWxTZWFyY2g6XG4gICAgICAgIHRoaXMub25HbG9iYWxTZWFyY2goZXZlbnQudmFsdWUpO1xuICAgICAgICB0aGlzLmNkci5tYXJrRm9yQ2hlY2soKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIEFQSS5zZXRSb3dDbGFzczpcbiAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkoZXZlbnQudmFsdWUpKSB7XG4gICAgICAgICAgZXZlbnQudmFsdWUuZm9yRWFjaCgodmFsKSA9PiB0aGlzLnN0eWxlU2VydmljZS5zZXRSb3dDbGFzcyh2YWwpKTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnN0eWxlU2VydmljZS5zZXRSb3dDbGFzcyhldmVudC52YWx1ZSk7XG4gICAgICAgIHRoaXMuY2RyLm1hcmtGb3JDaGVjaygpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgQVBJLnNldENlbGxDbGFzczpcbiAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkoZXZlbnQudmFsdWUpKSB7XG4gICAgICAgICAgZXZlbnQudmFsdWUuZm9yRWFjaCgodmFsKSA9PiB0aGlzLnN0eWxlU2VydmljZS5zZXRDZWxsQ2xhc3ModmFsKSk7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5zdHlsZVNlcnZpY2Uuc2V0Q2VsbENsYXNzKGV2ZW50LnZhbHVlKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIEFQSS5zZXRSb3dTdHlsZTpcbiAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkoZXZlbnQudmFsdWUpKSB7XG4gICAgICAgICAgZXZlbnQudmFsdWUuZm9yRWFjaCgodmFsKSA9PiB0aGlzLnN0eWxlU2VydmljZS5zZXRSb3dTdHlsZSh2YWwpKTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnN0eWxlU2VydmljZS5zZXRSb3dTdHlsZShldmVudC52YWx1ZSk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSBBUEkuc2V0Q2VsbFN0eWxlOlxuICAgICAgICBpZiAoQXJyYXkuaXNBcnJheShldmVudC52YWx1ZSkpIHtcbiAgICAgICAgICBldmVudC52YWx1ZS5mb3JFYWNoKCh2YWwpID0+IHRoaXMuc3R5bGVTZXJ2aWNlLnNldENlbGxTdHlsZSh2YWwpKTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnN0eWxlU2VydmljZS5zZXRDZWxsU3R5bGUoZXZlbnQudmFsdWUpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgQVBJLnNldFRhYmxlQ2xhc3M6XG4gICAgICAgIHRoaXMudGFibGVDbGFzcyA9IGV2ZW50LnZhbHVlO1xuICAgICAgICB0aGlzLmNkci5tYXJrRm9yQ2hlY2soKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIEFQSS5nZXRQYWdpbmF0aW9uVG90YWxJdGVtczpcbiAgICAgICAgcmV0dXJuIHRoaXMucGFnaW5hdGlvbkNvbXBvbmVudC5wYWdpbmF0aW9uRGlyZWN0aXZlLmdldFRvdGFsSXRlbXMoKTtcbiAgICAgIGNhc2UgQVBJLmdldFBhZ2luYXRpb25DdXJyZW50UGFnZTpcbiAgICAgICAgcmV0dXJuIHRoaXMucGFnaW5hdGlvbkNvbXBvbmVudC5wYWdpbmF0aW9uRGlyZWN0aXZlLmdldEN1cnJlbnQoKTtcbiAgICAgIGNhc2UgQVBJLmdldFBhZ2luYXRpb25MYXN0UGFnZTpcbiAgICAgICAgcmV0dXJuIHRoaXMucGFnaW5hdGlvbkNvbXBvbmVudC5wYWdpbmF0aW9uRGlyZWN0aXZlLmdldExhc3RQYWdlKCk7XG4gICAgICBjYXNlIEFQSS5nZXROdW1iZXJPZlJvd3NQZXJQYWdlOlxuICAgICAgICByZXR1cm4gdGhpcy5wYWdpbmF0aW9uQ29tcG9uZW50LnBhZ2luYXRpb25EaXJlY3RpdmUuaXNMYXN0UGFnZSgpXG4gICAgICAgICAgPyB0aGlzLnBhZ2luYXRpb25Db21wb25lbnQucGFnaW5hdGlvbkRpcmVjdGl2ZS5nZXRUb3RhbEl0ZW1zKCkgJSB0aGlzLmxpbWl0XG4gICAgICAgICAgOiB0aGlzLmxpbWl0O1xuICAgICAgY2FzZSBBUEkuc2V0UGFnaW5hdGlvbkN1cnJlbnRQYWdlOlxuICAgICAgICB0aGlzLnBhZ2luYXRpb25Db21wb25lbnQucGFnaW5hdGlvbkRpcmVjdGl2ZS5zZXRDdXJyZW50KGV2ZW50LnZhbHVlKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIEFQSS5zZXRQYWdpbmF0aW9uUmFuZ2U6XG4gICAgICAgIHRoaXMucGFnaW5hdGlvbkNvbXBvbmVudC5yYW5nZXMgPSBldmVudC52YWx1ZTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIEFQSS5zZXRQYWdpbmF0aW9uUHJldmlvdXNMYWJlbDpcbiAgICAgICAgdGhpcy5wYWdpbmF0aW9uQ29tcG9uZW50LnByZXZpb3VzTGFiZWwgPSBldmVudC52YWx1ZTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIEFQSS5zZXRQYWdpbmF0aW9uTmV4dExhYmVsOlxuICAgICAgICB0aGlzLnBhZ2luYXRpb25Db21wb25lbnQubmV4dExhYmVsID0gZXZlbnQudmFsdWU7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSBBUEkuc2V0UGFnaW5hdGlvbkRpc3BsYXlMaW1pdDpcbiAgICAgICAgdGhpcy5wYWdpbmF0aW9uQ29tcG9uZW50LmNoYW5nZUxpbWl0KGV2ZW50LnZhbHVlLCB0cnVlKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIEFQSS5zb3J0Qnk6XG4gICAgICAgIGNvbnN0IGNvbHVtbjogQ29sdW1ucyA9IHsgdGl0bGU6ICcnLCBrZXk6IGV2ZW50LnZhbHVlLmNvbHVtbiwgb3JkZXJCeTogZXZlbnQudmFsdWUub3JkZXIgfTtcbiAgICAgICAgdGhpcy5vcmRlckJ5KGNvbHVtbik7XG4gICAgICAgIHRoaXMuY2RyLmRldGVjdENoYW5nZXMoKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICBicmVhaztcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIHNldENvbHVtbk9yZGVyKGNvbHVtbjogQ29sdW1ucyk6IHZvaWQge1xuICAgIGNvbnN0IGtleTogc3RyaW5nID0gY29sdW1uLmtleTtcblxuICAgIHN3aXRjaCAodGhpcy5zb3J0U3RhdGUuZ2V0KGtleSkpIHtcbiAgICAgIGNhc2UgJyc6XG4gICAgICBjYXNlIHVuZGVmaW5lZDpcbiAgICAgICAgdGhpcy5zb3J0U3RhdGUuc2V0KGtleSwgY29sdW1uLm9yZGVyQnkgfHwgJ2Rlc2MnKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICdhc2MnOlxuICAgICAgICB0aGlzLmNvbmZpZy50aHJlZVdheVNvcnQgPyB0aGlzLnNvcnRTdGF0ZS5zZXQoa2V5LCAnJykgOiB0aGlzLnNvcnRTdGF0ZS5zZXQoa2V5LCAnZGVzYycpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ2Rlc2MnOlxuICAgICAgICB0aGlzLnNvcnRTdGF0ZS5zZXQoa2V5LCAnYXNjJyk7XG4gICAgICAgIGJyZWFrO1xuICAgIH1cbiAgICBpZiAodGhpcy5zb3J0U3RhdGUuc2l6ZSA+IDEpIHtcbiAgICAgIGNvbnN0IHRlbXAgPSB0aGlzLnNvcnRTdGF0ZS5nZXQoa2V5KTtcbiAgICAgIHRoaXMuc29ydFN0YXRlLmNsZWFyKCk7XG4gICAgICB0aGlzLnNvcnRTdGF0ZS5zZXQoa2V5LCB0ZW1wKTtcbiAgICB9XG4gIH1cblxuICBwdWJsaWMgZW1pdEV2ZW50KGV2ZW50OiBzdHJpbmcsIHZhbHVlOiBhbnkpOiB2b2lkIHtcbiAgICB0aGlzLmV2ZW50LmVtaXQoeyBldmVudCwgdmFsdWUgfSk7XG4gICAgaWYgKHRoaXMuY29uZmlnLnBlcnNpc3RTdGF0ZSkge1xuICAgICAgbG9jYWxTdG9yYWdlLnNldEl0ZW0oZXZlbnQsIEpTT04uc3RyaW5naWZ5KHZhbHVlKSk7XG4gICAgfVxuICAgIGlmICh0aGlzLmNvbmZpZy5sb2dnZXIpIHtcbiAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1jb25zb2xlXG4gICAgICBjb25zb2xlLmxvZyh7IGV2ZW50LCB2YWx1ZSB9KTtcbiAgICB9XG4gIH1cblxuICBkcmFnRW50ZXIoJGV2ZW50OiBEcmFnRXZlbnQpOiB2b2lkIHtcbiAgICAkZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAkZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG4gIH1cblxuICBkcmFnT3ZlcigkZXZlbnQ6IERyYWdFdmVudCk6IHZvaWQge1xuICAgICRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICRldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcbiAgfVxuXG4gIGRyYWdMZWF2ZSgkZXZlbnQ6IERyYWdFdmVudCk6IHZvaWQge1xuICAgICRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICRldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcbiAgfVxuXG4gIGRyb3AoJGV2ZW50OiBEcmFnRXZlbnQpOiB2b2lkIHtcbiAgICAkZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAkZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgY29uc3QgZmlsZSA9ICRldmVudC5kYXRhVHJhbnNmZXI/LmZpbGVzPy5bMF07XG4gICAgaWYgKGZpbGU/LnR5cGUgIT09ICdhcHBsaWNhdGlvbi9qc29uJykge1xuICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWNvbnNvbGVcbiAgICAgIGNvbnNvbGUubG9nKCdGaWxlIG5vdCBhbGxvd2VkJyk7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGNvbnN0IGZpbGVSZWFkZXIgPSBuZXcgRmlsZVJlYWRlcigpO1xuICAgIGZpbGVSZWFkZXIub25sb2FkID0gKGV2ZW50KSA9PiB7XG4gICAgICB0aGlzLmRhdGEgPSBKU09OLnBhcnNlKGV2ZW50Py50YXJnZXQ/LnJlc3VsdCBhcyBzdHJpbmcpO1xuICAgICAgdGhpcy5jZHIubWFya0ZvckNoZWNrKCk7XG4gICAgfTtcbiAgICBmaWxlUmVhZGVyLnJlYWRBc1RleHQoZmlsZSk7XG4gIH1cbn1cbiIsIjxkaXZcbiAgY2xhc3M9XCJuZ3gtY29udGFpbmVyXCJcbiAgW2NsYXNzLm5neC1jb250YWluZXItLWRhcmtdPVwiY29uZmlnLnRhYmxlTGF5b3V0LnRoZW1lID09PSAnZGFyaydcIlxuICAoZHJhZ2VudGVyKT1cImRyYWdFbnRlcigkZXZlbnQpXCJcbiAgKGRyYWdvdmVyKT1cImRyYWdPdmVyKCRldmVudClcIlxuICAoZHJhZ2xlYXZlKT1cImRyYWdMZWF2ZSgkZXZlbnQpXCJcbiAgKGRyb3ApPVwiZHJvcCgkZXZlbnQpXCJcbj5cbiAgPHRhYmxlXG4gICAgW2lkXT1cImlkXCJcbiAgICAjdGFibGVcbiAgICBbbmdDbGFzc109XCJ0YWJsZUNsYXNzID09PSBudWxsIHx8IHRhYmxlQ2xhc3MgPT09ICcnID8gJ25neC10YWJsZScgOiB0YWJsZUNsYXNzXCJcbiAgICBbY2xhc3Mubmd4LXRhYmxlX190YWJsZS0tdGlueV09XCJjb25maWcudGFibGVMYXlvdXQuc3R5bGUgPT09ICd0aW55J1wiXG4gICAgW2NsYXNzLm5neC10YWJsZV9fdGFibGUtLW5vcm1hbF09XCJjb25maWcudGFibGVMYXlvdXQuc3R5bGUgPT09ICdub3JtYWwnXCJcbiAgICBbY2xhc3Mubmd4LXRhYmxlX190YWJsZS0tYmlnXT1cImNvbmZpZy50YWJsZUxheW91dC5zdHlsZSA9PT0gJ2JpZydcIlxuICAgIFtjbGFzcy5uZ3gtdGFibGVfX3RhYmxlLS1ib3JkZXJsZXNzXT1cImNvbmZpZy50YWJsZUxheW91dC5ib3JkZXJsZXNzXCJcbiAgICBbY2xhc3Mubmd4LXRhYmxlX190YWJsZS0tZGFya109XCJjb25maWcudGFibGVMYXlvdXQudGhlbWUgPT09ICdkYXJrJ1wiXG4gICAgW2NsYXNzLm5neC10YWJsZV9fdGFibGUtLWhvdmVyYWJsZV09XCJjb25maWcudGFibGVMYXlvdXQuaG92ZXJcIlxuICAgIFtjbGFzcy5uZ3gtdGFibGVfX3RhYmxlLS1zdHJpcGVkXT1cImNvbmZpZy50YWJsZUxheW91dC5zdHJpcGVkXCJcbiAgICBbY2xhc3Mubmd4LXRhYmxlX19ob3Jpem9udGFsLXNjcm9sbF09XCJjb25maWcuaG9yaXpvbnRhbFNjcm9sbCAmJiAhY29uZmlnLmlzTG9hZGluZ1wiXG4gID5cbiAgICA8dGhlYWRcbiAgICAgIFtjbGFzcy5uZ3gtaW5maW5pdGUtc2Nyb2xsLXZpZXdwb3J0LXRoZWFkXT1cImNvbmZpZy5pbmZpbml0ZVNjcm9sbFwiXG4gICAgICB0YWJsZS10aGVhZFxuICAgICAgW2NvbmZpZ109XCJjb25maWdcIlxuICAgICAgW3NvcnRLZXldPVwic29ydEtleVwiXG4gICAgICBbc29ydFN0YXRlXT1cInNvcnRTdGF0ZVwiXG4gICAgICBbc2VsZWN0QWxsVGVtcGxhdGVdPVwic2VsZWN0QWxsVGVtcGxhdGVcIlxuICAgICAgW2ZpbHRlcnNUZW1wbGF0ZV09XCJmaWx0ZXJzVGVtcGxhdGVcIlxuICAgICAgW2FkZGl0aW9uYWxBY3Rpb25zVGVtcGxhdGVdPVwiYWRkaXRpb25hbEFjdGlvbnNUZW1wbGF0ZVwiXG4gICAgICBbY29sdW1uc109XCJjb2x1bW5zXCJcbiAgICAgIChzZWxlY3RBbGwpPVwib25TZWxlY3RBbGwoKVwiXG4gICAgICAoZmlsdGVyKT1cIm9uU2VhcmNoKCRldmVudClcIlxuICAgICAgKG9yZGVyKT1cIm9yZGVyQnkoJGV2ZW50KVwiXG4gICAgICAoZXZlbnQpPVwiZW1pdEV2ZW50KCRldmVudC5ldmVudCwgJGV2ZW50LnZhbHVlKVwiXG4gICAgPjwvdGhlYWQ+XG4gICAgPHRib2R5ICpuZ0lmPVwiZGF0YSAmJiAhY29uZmlnLmlzTG9hZGluZyAmJiAhY29uZmlnLnJvd1Jlb3JkZXJcIj5cbiAgICAgIDxuZy1jb250YWluZXIgKm5nSWY9XCJyb3dUZW1wbGF0ZVwiPlxuICAgICAgICA8dWxcbiAgICAgICAgICBjbGFzcz1cIm5neC10YWJsZV9fdGFibGUtcm93LWNvbnRleHQtbWVudVwiXG4gICAgICAgICAgW25nU3R5bGVdPVwie1xuICAgICAgICAgICAgcG9zaXRpb246ICdhYnNvbHV0ZScsXG4gICAgICAgICAgICB0b3A6IHJvd0NvbnRleHRNZW51UG9zaXRpb24udG9wLFxuICAgICAgICAgICAgbGVmdDogcm93Q29udGV4dE1lbnVQb3NpdGlvbi5sZWZ0XG4gICAgICAgICAgfVwiXG4gICAgICAgICAgKm5nSWY9XCJyb3dDb250ZXh0TWVudVBvc2l0aW9uLnRvcFwiXG4gICAgICAgID5cbiAgICAgICAgICA8bmctY29udGFpbmVyXG4gICAgICAgICAgICBbbmdUZW1wbGF0ZU91dGxldF09XCJyb3dDb250ZXh0TWVudVwiXG4gICAgICAgICAgICBbbmdUZW1wbGF0ZU91dGxldENvbnRleHRdPVwieyAkaW1wbGljaXQ6IHJvd0NvbnRleHRNZW51UG9zaXRpb24udmFsdWUgfVwiXG4gICAgICAgICAgPlxuICAgICAgICAgIDwvbmctY29udGFpbmVyPlxuICAgICAgICA8L3VsPlxuICAgICAgICA8bmctY29udGFpbmVyICpuZ0lmPVwiIWNvbmZpZy5pbmZpbml0ZVNjcm9sbFwiPlxuICAgICAgICAgIDxuZy1jb250YWluZXJcbiAgICAgICAgICAgICpuZ0Zvcj1cIlxuICAgICAgICAgICAgICBsZXQgcm93IG9mIGRhdGFcbiAgICAgICAgICAgICAgICB8IHNvcnQ6IHNvcnRCeVxuICAgICAgICAgICAgICAgIHwgc2VhcmNoOiB0ZXJtOmZpbHRlcmVkQ291bnRTdWJqZWN0XG4gICAgICAgICAgICAgICAgfCBnbG9iYWw6IGdsb2JhbFNlYXJjaFRlcm06ZmlsdGVyZWRDb3VudFN1YmplY3RcbiAgICAgICAgICAgICAgICB8IHBhZ2luYXRlOiB7IGl0ZW1zUGVyUGFnZTogbGltaXQsIGN1cnJlbnRQYWdlOiBwYWdlLCB0b3RhbEl0ZW1zOiBjb3VudCwgaWQ6IGlkIH1cbiAgICAgICAgICAgIFwiXG4gICAgICAgICAgPlxuICAgICAgICAgICAgPHRyXG4gICAgICAgICAgICAgIChjbGljayk9XCJvbkNsaWNrKCRldmVudCwgcm93LCAnJywgbnVsbCwgZGF0YS5pbmRleE9mKHJvdykpXCJcbiAgICAgICAgICAgICAgI2NvbnRleHRNZW51XG4gICAgICAgICAgICAgIChjb250ZXh0bWVudSk9XCJvblJvd0NvbnRleHRNZW51KCRldmVudCwgcm93LCAnJywgbnVsbCwgZGF0YS5pbmRleE9mKHJvdykpXCJcbiAgICAgICAgICAgICAgKGRibGNsaWNrKT1cIm9uRG91YmxlQ2xpY2soJGV2ZW50LCByb3csICcnLCBudWxsLCBkYXRhLmluZGV4T2Yocm93KSlcIlxuICAgICAgICAgICAgICBbY2xhc3Mubmd4LXRhYmxlX190YWJsZS1yb3ctLXNlbGVjdGVkXT1cIlxuICAgICAgICAgICAgICAgIGRhdGEuaW5kZXhPZihyb3cpID09PSBzZWxlY3RlZFJvdyAmJiAhY29uZmlnLnNlbGVjdENlbGxcbiAgICAgICAgICAgICAgXCJcbiAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgPG5nLWNvbnRhaW5lclxuICAgICAgICAgICAgICAgIFtuZ1RlbXBsYXRlT3V0bGV0XT1cInJvd1RlbXBsYXRlXCJcbiAgICAgICAgICAgICAgICBbbmdUZW1wbGF0ZU91dGxldENvbnRleHRdPVwieyAkaW1wbGljaXQ6IHJvdywgaW5kZXg6IGRhdGEuaW5kZXhPZihyb3cpIH1cIlxuICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgIDwvbmctY29udGFpbmVyPlxuICAgICAgICAgICAgICA8dGQgKm5nSWY9XCJjb25maWcuZGV0YWlsc1RlbXBsYXRlXCI+XG4gICAgICAgICAgICAgICAgPHNwYW5cbiAgICAgICAgICAgICAgICAgIGNsYXNzPVwibmd4LWljb25cIlxuICAgICAgICAgICAgICAgICAgKm5nSWY9XCJhcnJvd0RlZmluaXRpb25cIlxuICAgICAgICAgICAgICAgICAgW25nQ2xhc3NdPVwiXG4gICAgICAgICAgICAgICAgICAgIGlzUm93Q29sbGFwc2VkKGRhdGEuaW5kZXhPZihyb3cpKVxuICAgICAgICAgICAgICAgICAgICAgID8gJ25neC1pY29uLWFycm93LWRvd24nXG4gICAgICAgICAgICAgICAgICAgICAgOiAnbmd4LWljb24tYXJyb3ctcmlnaHQnXG4gICAgICAgICAgICAgICAgICBcIlxuICAgICAgICAgICAgICAgICAgKGNsaWNrKT1cImNvbGxhcHNlUm93KGRhdGEuaW5kZXhPZihyb3cpKVwiXG4gICAgICAgICAgICAgICAgPlxuICAgICAgICAgICAgICAgIDwvc3Bhbj5cbiAgICAgICAgICAgICAgPC90ZD5cbiAgICAgICAgICAgIDwvdHI+XG4gICAgICAgICAgICA8dHJcbiAgICAgICAgICAgICAgKm5nSWY9XCJcbiAgICAgICAgICAgICAgICAoY29uZmlnLmRldGFpbHNUZW1wbGF0ZSAmJiBzZWxlY3RlZERldGFpbHNUZW1wbGF0ZVJvd0lkLmhhcyhkYXRhLmluZGV4T2Yocm93KSkpIHx8XG4gICAgICAgICAgICAgICAgY29uZmlnLmNvbGxhcHNlQWxsUm93c1xuICAgICAgICAgICAgICBcIlxuICAgICAgICAgICAgPlxuICAgICAgICAgICAgICA8dGQgW2F0dHIuY29sc3Bhbl09XCJjb2x1bW5zLmxlbmd0aCArIDFcIj5cbiAgICAgICAgICAgICAgICA8bmctY29udGFpbmVyXG4gICAgICAgICAgICAgICAgICBbbmdUZW1wbGF0ZU91dGxldF09XCJkZXRhaWxzVGVtcGxhdGVcIlxuICAgICAgICAgICAgICAgICAgW25nVGVtcGxhdGVPdXRsZXRDb250ZXh0XT1cInsgJGltcGxpY2l0OiByb3csIGluZGV4OiBkYXRhLmluZGV4T2Yocm93KSB9XCJcbiAgICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgPC9uZy1jb250YWluZXI+XG4gICAgICAgICAgICAgIDwvdGQ+XG4gICAgICAgICAgICA8L3RyPlxuICAgICAgICAgIDwvbmctY29udGFpbmVyPlxuICAgICAgICA8L25nLWNvbnRhaW5lcj5cbiAgICAgICAgPGNkay12aXJ0dWFsLXNjcm9sbC12aWV3cG9ydFxuICAgICAgICAgIGl0ZW1TaXplPVwiNTBcIlxuICAgICAgICAgICpuZ0lmPVwiY29uZmlnLmluZmluaXRlU2Nyb2xsXCJcbiAgICAgICAgICBjbGFzcz1cIm5neC1pbmZpbml0ZS1zY3JvbGwtdmlld3BvcnRcIlxuICAgICAgICA+XG4gICAgICAgICAgPG5nLWNvbnRhaW5lclxuICAgICAgICAgICAgKmNka1ZpcnR1YWxGb3I9XCJcbiAgICAgICAgICAgICAgbGV0IHJvdyBvZiBkYXRhXG4gICAgICAgICAgICAgICAgfCBzb3J0OiBzb3J0QnlcbiAgICAgICAgICAgICAgICB8IHNlYXJjaDogdGVybTpmaWx0ZXJlZENvdW50U3ViamVjdFxuICAgICAgICAgICAgICAgIHwgZ2xvYmFsOiBnbG9iYWxTZWFyY2hUZXJtOmZpbHRlcmVkQ291bnRTdWJqZWN0O1xuICAgICAgICAgICAgICBsZXQgcm93SW5kZXggPSBpbmRleFxuICAgICAgICAgICAgXCJcbiAgICAgICAgICA+XG4gICAgICAgICAgICA8dHJcbiAgICAgICAgICAgICAgKGNsaWNrKT1cIm9uQ2xpY2soJGV2ZW50LCByb3csICcnLCBudWxsLCByb3dJbmRleClcIlxuICAgICAgICAgICAgICAjY29udGV4dE1lbnVcbiAgICAgICAgICAgICAgKGNvbnRleHRtZW51KT1cIm9uUm93Q29udGV4dE1lbnUoJGV2ZW50LCByb3csICcnLCBudWxsLCByb3dJbmRleClcIlxuICAgICAgICAgICAgICAoZGJsY2xpY2spPVwib25Eb3VibGVDbGljaygkZXZlbnQsIHJvdywgJycsIG51bGwsIHJvd0luZGV4KVwiXG4gICAgICAgICAgICAgIFtjbGFzcy5uZ3gtdGFibGVfX3RhYmxlLXJvdy0tc2VsZWN0ZWRdPVwiXG4gICAgICAgICAgICAgICAgcm93SW5kZXggPT09IHNlbGVjdGVkUm93ICYmICFjb25maWcuc2VsZWN0Q2VsbFxuICAgICAgICAgICAgICBcIlxuICAgICAgICAgICAgPlxuICAgICAgICAgICAgICA8bmctY29udGFpbmVyXG4gICAgICAgICAgICAgICAgW25nVGVtcGxhdGVPdXRsZXRdPVwicm93VGVtcGxhdGVcIlxuICAgICAgICAgICAgICAgIFtuZ1RlbXBsYXRlT3V0bGV0Q29udGV4dF09XCJ7ICRpbXBsaWNpdDogcm93LCBpbmRleDogcm93SW5kZXggfVwiXG4gICAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgPC9uZy1jb250YWluZXI+XG4gICAgICAgICAgICAgIDx0ZCAqbmdJZj1cImNvbmZpZy5kZXRhaWxzVGVtcGxhdGVcIj5cbiAgICAgICAgICAgICAgICA8c3BhblxuICAgICAgICAgICAgICAgICAgY2xhc3M9XCJuZ3gtaWNvblwiXG4gICAgICAgICAgICAgICAgICAqbmdJZj1cImFycm93RGVmaW5pdGlvblwiXG4gICAgICAgICAgICAgICAgICBbbmdDbGFzc109XCJcbiAgICAgICAgICAgICAgICAgICAgaXNSb3dDb2xsYXBzZWQocm93SW5kZXgpID8gJ25neC1pY29uLWFycm93LWRvd24nIDogJ25neC1pY29uLWFycm93LXJpZ2h0J1xuICAgICAgICAgICAgICAgICAgXCJcbiAgICAgICAgICAgICAgICAgIChjbGljayk9XCJjb2xsYXBzZVJvdyhyb3dJbmRleClcIlxuICAgICAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICA8L3NwYW4+XG4gICAgICAgICAgICAgIDwvdGQ+XG4gICAgICAgICAgICA8L3RyPlxuICAgICAgICAgICAgPHRyXG4gICAgICAgICAgICAgICpuZ0lmPVwiXG4gICAgICAgICAgICAgICAgKGNvbmZpZy5kZXRhaWxzVGVtcGxhdGUgJiYgc2VsZWN0ZWREZXRhaWxzVGVtcGxhdGVSb3dJZC5oYXMocm93SW5kZXgpKSB8fFxuICAgICAgICAgICAgICAgIGNvbmZpZy5jb2xsYXBzZUFsbFJvd3NcbiAgICAgICAgICAgICAgXCJcbiAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgPHRkIFthdHRyLmNvbHNwYW5dPVwiY29sdW1ucy5sZW5ndGggKyAxXCI+XG4gICAgICAgICAgICAgICAgPG5nLWNvbnRhaW5lclxuICAgICAgICAgICAgICAgICAgW25nVGVtcGxhdGVPdXRsZXRdPVwiZGV0YWlsc1RlbXBsYXRlXCJcbiAgICAgICAgICAgICAgICAgIFtuZ1RlbXBsYXRlT3V0bGV0Q29udGV4dF09XCJ7ICRpbXBsaWNpdDogcm93LCBpbmRleDogcm93SW5kZXggfVwiXG4gICAgICAgICAgICAgICAgPlxuICAgICAgICAgICAgICAgIDwvbmctY29udGFpbmVyPlxuICAgICAgICAgICAgICA8L3RkPlxuICAgICAgICAgICAgPC90cj5cbiAgICAgICAgICA8L25nLWNvbnRhaW5lcj5cbiAgICAgICAgPC9jZGstdmlydHVhbC1zY3JvbGwtdmlld3BvcnQ+XG4gICAgICA8L25nLWNvbnRhaW5lcj5cbiAgICAgIDxuZy1jb250YWluZXIgKm5nSWY9XCIhcm93VGVtcGxhdGUgJiYgIWNvbmZpZy5ncm91cFJvd3NcIj5cbiAgICAgICAgPHVsXG4gICAgICAgICAgY2xhc3M9XCJuZ3gtdGFibGVfX3RhYmxlLXJvdy1jb250ZXh0LW1lbnVcIlxuICAgICAgICAgIFtuZ1N0eWxlXT1cIntcbiAgICAgICAgICAgIHBvc2l0aW9uOiAnYWJzb2x1dGUnLFxuICAgICAgICAgICAgdG9wOiByb3dDb250ZXh0TWVudVBvc2l0aW9uLnRvcCxcbiAgICAgICAgICAgIGxlZnQ6IHJvd0NvbnRleHRNZW51UG9zaXRpb24ubGVmdFxuICAgICAgICAgIH1cIlxuICAgICAgICAgICpuZ0lmPVwicm93Q29udGV4dE1lbnVQb3NpdGlvbi50b3BcIlxuICAgICAgICA+XG4gICAgICAgICAgPG5nLWNvbnRhaW5lclxuICAgICAgICAgICAgW25nVGVtcGxhdGVPdXRsZXRdPVwicm93Q29udGV4dE1lbnVcIlxuICAgICAgICAgICAgW25nVGVtcGxhdGVPdXRsZXRDb250ZXh0XT1cInsgJGltcGxpY2l0OiByb3dDb250ZXh0TWVudVBvc2l0aW9uLnZhbHVlIH1cIlxuICAgICAgICAgID5cbiAgICAgICAgICA8L25nLWNvbnRhaW5lcj5cbiAgICAgICAgPC91bD5cbiAgICAgICAgPG5nLWNvbnRhaW5lciAqbmdJZj1cIiFjb25maWcuaW5maW5pdGVTY3JvbGxcIj5cbiAgICAgICAgICA8bmctY29udGFpbmVyXG4gICAgICAgICAgICAqbmdGb3I9XCJcbiAgICAgICAgICAgICAgbGV0IHJvdyBvZiBkYXRhXG4gICAgICAgICAgICAgICAgfCBzb3J0OiBzb3J0QnlcbiAgICAgICAgICAgICAgICB8IHNlYXJjaDogdGVybTpmaWx0ZXJlZENvdW50U3ViamVjdFxuICAgICAgICAgICAgICAgIHwgZ2xvYmFsOiBnbG9iYWxTZWFyY2hUZXJtOmZpbHRlcmVkQ291bnRTdWJqZWN0XG4gICAgICAgICAgICAgICAgfCBwYWdpbmF0ZTogeyBpdGVtc1BlclBhZ2U6IGxpbWl0LCBjdXJyZW50UGFnZTogcGFnZSwgdG90YWxJdGVtczogY291bnQsIGlkOiBpZCB9XG4gICAgICAgICAgICBcIlxuICAgICAgICAgID5cbiAgICAgICAgICAgIDx0clxuICAgICAgICAgICAgICBbY2xhc3Mubmd4LXRhYmxlX190YWJsZS1yb3ctLXNlbGVjdGVkXT1cIlxuICAgICAgICAgICAgICAgIGRhdGEuaW5kZXhPZihyb3cpID09PSBzZWxlY3RlZFJvdyAmJiAhY29uZmlnLnNlbGVjdENlbGxcbiAgICAgICAgICAgICAgXCJcbiAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgPHRkICpuZ0lmPVwiY29uZmlnLmNoZWNrYm94ZXNcIj5cbiAgICAgICAgICAgICAgICA8bGFiZWwgY2xhc3M9XCJuZ3gtZm9ybS1jaGVja2JveFwiPlxuICAgICAgICAgICAgICAgICAgPGlucHV0XG4gICAgICAgICAgICAgICAgICAgIHR5cGU9XCJjaGVja2JveFwiXG4gICAgICAgICAgICAgICAgICAgIGlkPVwiY2hlY2tib3gte3sgZGF0YS5pbmRleE9mKHJvdykgfX1cIlxuICAgICAgICAgICAgICAgICAgICBbY2hlY2tlZF09XCJpc1NlbGVjdGVkIHx8IHNlbGVjdGVkQ2hlY2tib3hlcy5oYXMoZGF0YS5pbmRleE9mKHJvdykpXCJcbiAgICAgICAgICAgICAgICAgICAgKGNoYW5nZSk9XCJvbkNoZWNrYm94U2VsZWN0KCRldmVudCwgcm93LCBkYXRhLmluZGV4T2Yocm93KSlcIlxuICAgICAgICAgICAgICAgICAgLz5cbiAgICAgICAgICAgICAgICAgIDxlbSBjbGFzcz1cIm5neC1mb3JtLWljb25cIj48L2VtPlxuICAgICAgICAgICAgICAgIDwvbGFiZWw+XG4gICAgICAgICAgICAgIDwvdGQ+XG4gICAgICAgICAgICAgIDx0ZCAqbmdJZj1cImNvbmZpZy5yYWRpb1wiPlxuICAgICAgICAgICAgICAgIDxsYWJlbD5cbiAgICAgICAgICAgICAgICAgIDxpbnB1dFxuICAgICAgICAgICAgICAgICAgICB0eXBlPVwicmFkaW9cIlxuICAgICAgICAgICAgICAgICAgICBpZD1cInJhZGlvLXt7IGRhdGEuaW5kZXhPZihyb3cpIH19XCJcbiAgICAgICAgICAgICAgICAgICAgbmFtZT1cInJhZGlvXCJcbiAgICAgICAgICAgICAgICAgICAgKGNoYW5nZSk9XCJvblJhZGlvU2VsZWN0KCRldmVudCwgcm93LCBkYXRhLmluZGV4T2Yocm93KSlcIlxuICAgICAgICAgICAgICAgICAgLz5cbiAgICAgICAgICAgICAgICA8L2xhYmVsPlxuICAgICAgICAgICAgICA8L3RkPlxuICAgICAgICAgICAgICA8bmctY29udGFpbmVyICpuZ0Zvcj1cImxldCBjb2x1bW4gb2YgY29sdW1uczsgbGV0IGNvbEluZGV4ID0gaW5kZXhcIj5cbiAgICAgICAgICAgICAgICA8dGRcbiAgICAgICAgICAgICAgICAgIChjbGljayk9XCJvbkNsaWNrKCRldmVudCwgcm93LCBjb2x1bW4ua2V5LCBjb2xJbmRleCwgZGF0YS5pbmRleE9mKHJvdykpXCJcbiAgICAgICAgICAgICAgICAgICNjb250ZXh0TWVudVxuICAgICAgICAgICAgICAgICAgKGNvbnRleHRtZW51KT1cIlxuICAgICAgICAgICAgICAgICAgICBvblJvd0NvbnRleHRNZW51KCRldmVudCwgcm93LCBjb2x1bW4ua2V5LCBjb2xJbmRleCwgZGF0YS5pbmRleE9mKHJvdykpXG4gICAgICAgICAgICAgICAgICBcIlxuICAgICAgICAgICAgICAgICAgKGRibGNsaWNrKT1cIm9uRG91YmxlQ2xpY2soJGV2ZW50LCByb3csIGNvbHVtbi5rZXksIGNvbEluZGV4LCBkYXRhLmluZGV4T2Yocm93KSlcIlxuICAgICAgICAgICAgICAgICAgW2NsYXNzLnBpbm5lZC1sZWZ0XT1cImNvbHVtbi5waW5uZWRcIlxuICAgICAgICAgICAgICAgICAgW25nQ2xhc3NdPVwiY29sdW1uLmNzc0NsYXNzID8gY29sdW1uLmNzc0NsYXNzLm5hbWUgOiAnJ1wiXG4gICAgICAgICAgICAgICAgICBbc3R5bGUubGVmdF09XCJzdHlsZVNlcnZpY2UucGlubmVkV2lkdGgoY29sdW1uLnBpbm5lZCwgY29sSW5kZXgpXCJcbiAgICAgICAgICAgICAgICAgIFtjbGFzcy5uZ3gtdGFibGVfX3RhYmxlLWNvbC0tc2VsZWN0ZWRdPVwiXG4gICAgICAgICAgICAgICAgICAgIGNvbEluZGV4ID09PSBzZWxlY3RlZENvbCAmJiAhY29uZmlnLnNlbGVjdENlbGxcbiAgICAgICAgICAgICAgICAgIFwiXG4gICAgICAgICAgICAgICAgICBbY2xhc3Mubmd4LXRhYmxlX190YWJsZS1jZWxsLS1zZWxlY3RlZF09XCJcbiAgICAgICAgICAgICAgICAgICAgY29sSW5kZXggPT09IHNlbGVjdGVkQ29sICYmXG4gICAgICAgICAgICAgICAgICAgIGRhdGEuaW5kZXhPZihyb3cpID09PSBzZWxlY3RlZFJvdyAmJlxuICAgICAgICAgICAgICAgICAgICAhY29uZmlnLnNlbGVjdENvbCAmJlxuICAgICAgICAgICAgICAgICAgICAhY29uZmlnLnNlbGVjdFJvd1xuICAgICAgICAgICAgICAgICAgXCJcbiAgICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgICA8ZGl2ICpuZ0lmPVwiIWNvbHVtbi5jZWxsVGVtcGxhdGVcIj57eyByb3cgfCByZW5kZXI6IGNvbHVtbi5rZXkgfX08L2Rpdj5cbiAgICAgICAgICAgICAgICAgIDxuZy1jb250YWluZXJcbiAgICAgICAgICAgICAgICAgICAgKm5nSWY9XCJjb2x1bW4uY2VsbFRlbXBsYXRlXCJcbiAgICAgICAgICAgICAgICAgICAgW25nVGVtcGxhdGVPdXRsZXRdPVwiY29sdW1uLmNlbGxUZW1wbGF0ZVwiXG4gICAgICAgICAgICAgICAgICAgIFtuZ1RlbXBsYXRlT3V0bGV0Q29udGV4dF09XCJ7XG4gICAgICAgICAgICAgICAgICAgICAgJGltcGxpY2l0OiByb3csXG4gICAgICAgICAgICAgICAgICAgICAgcm93SW5kZXg6IGRhdGEuaW5kZXhPZihyb3cpLFxuICAgICAgICAgICAgICAgICAgICAgIGNvbHVtbjogY29sdW1uXG4gICAgICAgICAgICAgICAgICAgIH1cIlxuICAgICAgICAgICAgICAgICAgPlxuICAgICAgICAgICAgICAgICAgPC9uZy1jb250YWluZXI+XG4gICAgICAgICAgICAgICAgPC90ZD5cbiAgICAgICAgICAgICAgPC9uZy1jb250YWluZXI+XG4gICAgICAgICAgICAgIDx0ZCAqbmdJZj1cImNvbmZpZy5hZGRpdGlvbmFsQWN0aW9ucyB8fCBjb25maWcuZGV0YWlsc1RlbXBsYXRlXCI+XG4gICAgICAgICAgICAgICAgPHNwYW5cbiAgICAgICAgICAgICAgICAgIGNsYXNzPVwibmd4LWljb25cIlxuICAgICAgICAgICAgICAgICAgKm5nSWY9XCJhcnJvd0RlZmluaXRpb25cIlxuICAgICAgICAgICAgICAgICAgW25nQ2xhc3NdPVwiXG4gICAgICAgICAgICAgICAgICAgIGlzUm93Q29sbGFwc2VkKGRhdGEuaW5kZXhPZihyb3cpKVxuICAgICAgICAgICAgICAgICAgICAgID8gJ25neC1pY29uLWFycm93LWRvd24nXG4gICAgICAgICAgICAgICAgICAgICAgOiAnbmd4LWljb24tYXJyb3ctcmlnaHQnXG4gICAgICAgICAgICAgICAgICBcIlxuICAgICAgICAgICAgICAgICAgKGNsaWNrKT1cImNvbGxhcHNlUm93KGRhdGEuaW5kZXhPZihyb3cpKVwiXG4gICAgICAgICAgICAgICAgPlxuICAgICAgICAgICAgICAgIDwvc3Bhbj5cbiAgICAgICAgICAgICAgPC90ZD5cbiAgICAgICAgICAgIDwvdHI+XG4gICAgICAgICAgICA8dHJcbiAgICAgICAgICAgICAgKm5nSWY9XCJcbiAgICAgICAgICAgICAgICAoY29uZmlnLmRldGFpbHNUZW1wbGF0ZSAmJiBzZWxlY3RlZERldGFpbHNUZW1wbGF0ZVJvd0lkLmhhcyhkYXRhLmluZGV4T2Yocm93KSkpIHx8XG4gICAgICAgICAgICAgICAgY29uZmlnLmNvbGxhcHNlQWxsUm93c1xuICAgICAgICAgICAgICBcIlxuICAgICAgICAgICAgPlxuICAgICAgICAgICAgICA8dGQgKm5nSWY9XCJjb25maWcuY2hlY2tib3hlcyB8fCBjb25maWcucmFkaW9cIj48L3RkPlxuICAgICAgICAgICAgICA8dGQgW2F0dHIuY29sc3Bhbl09XCJjb2x1bW5zLmxlbmd0aCArIDFcIj5cbiAgICAgICAgICAgICAgICA8bmctY29udGFpbmVyXG4gICAgICAgICAgICAgICAgICBbbmdUZW1wbGF0ZU91dGxldF09XCJkZXRhaWxzVGVtcGxhdGVcIlxuICAgICAgICAgICAgICAgICAgW25nVGVtcGxhdGVPdXRsZXRDb250ZXh0XT1cInsgJGltcGxpY2l0OiByb3csIGluZGV4OiBkYXRhLmluZGV4T2Yocm93KSB9XCJcbiAgICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgPC9uZy1jb250YWluZXI+XG4gICAgICAgICAgICAgIDwvdGQ+XG4gICAgICAgICAgICA8L3RyPlxuICAgICAgICAgIDwvbmctY29udGFpbmVyPlxuICAgICAgICA8L25nLWNvbnRhaW5lcj5cbiAgICAgICAgPCEtLSBpbmZpbml0ZSBzY3JvbGwgLS0+XG4gICAgICAgIDxjZGstdmlydHVhbC1zY3JvbGwtdmlld3BvcnRcbiAgICAgICAgICBpdGVtU2l6ZT1cIjUwXCJcbiAgICAgICAgICAqbmdJZj1cImNvbmZpZy5pbmZpbml0ZVNjcm9sbFwiXG4gICAgICAgICAgY2xhc3M9XCJuZ3gtaW5maW5pdGUtc2Nyb2xsLXZpZXdwb3J0XCJcbiAgICAgICAgPlxuICAgICAgICAgIDxuZy1jb250YWluZXJcbiAgICAgICAgICAgICpjZGtWaXJ0dWFsRm9yPVwiXG4gICAgICAgICAgICAgIGxldCByb3cgb2YgZGF0YVxuICAgICAgICAgICAgICAgIHwgc29ydDogc29ydEJ5XG4gICAgICAgICAgICAgICAgfCBzZWFyY2g6IHRlcm06ZmlsdGVyZWRDb3VudFN1YmplY3RcbiAgICAgICAgICAgICAgICB8IGdsb2JhbDogZ2xvYmFsU2VhcmNoVGVybTpmaWx0ZXJlZENvdW50U3ViamVjdDtcbiAgICAgICAgICAgICAgbGV0IHJvd0luZGV4ID0gaW5kZXhcbiAgICAgICAgICAgIFwiXG4gICAgICAgICAgPlxuICAgICAgICAgICAgPHRyXG4gICAgICAgICAgICAgIFtjbGFzcy5uZ3gtdGFibGVfX3RhYmxlLXJvdy0tc2VsZWN0ZWRdPVwiXG4gICAgICAgICAgICAgICAgcm93SW5kZXggPT09IHNlbGVjdGVkUm93ICYmICFjb25maWcuc2VsZWN0Q2VsbFxuICAgICAgICAgICAgICBcIlxuICAgICAgICAgICAgPlxuICAgICAgICAgICAgICA8dGQgKm5nSWY9XCJjb25maWcuY2hlY2tib3hlc1wiIHdpZHRoPVwiMyVcIj5cbiAgICAgICAgICAgICAgICA8bGFiZWwgY2xhc3M9XCJuZ3gtZm9ybS1jaGVja2JveFwiPlxuICAgICAgICAgICAgICAgICAgPGlucHV0XG4gICAgICAgICAgICAgICAgICAgIHR5cGU9XCJjaGVja2JveFwiXG4gICAgICAgICAgICAgICAgICAgIGlkPVwiY2hlY2tib3gtaW5maW5pdGUtc2Nyb2xsLXt7IHJvd0luZGV4IH19XCJcbiAgICAgICAgICAgICAgICAgICAgW2NoZWNrZWRdPVwiaXNTZWxlY3RlZCB8fCBzZWxlY3RlZENoZWNrYm94ZXMuaGFzKHJvd0luZGV4KVwiXG4gICAgICAgICAgICAgICAgICAgIChjaGFuZ2UpPVwib25DaGVja2JveFNlbGVjdCgkZXZlbnQsIHJvdywgcm93SW5kZXgpXCJcbiAgICAgICAgICAgICAgICAgIC8+XG4gICAgICAgICAgICAgICAgICA8ZW0gY2xhc3M9XCJuZ3gtZm9ybS1pY29uXCI+PC9lbT5cbiAgICAgICAgICAgICAgICA8L2xhYmVsPlxuICAgICAgICAgICAgICA8L3RkPlxuICAgICAgICAgICAgICA8dGQgKm5nSWY9XCJjb25maWcucmFkaW9cIiB3aWR0aD1cIjMlXCI+XG4gICAgICAgICAgICAgICAgPGxhYmVsPlxuICAgICAgICAgICAgICAgICAgPGlucHV0XG4gICAgICAgICAgICAgICAgICAgIHR5cGU9XCJyYWRpb1wiXG4gICAgICAgICAgICAgICAgICAgIGlkPVwicmFkaW8taW5maW5pdGUtc2Nyb2xsLXt7IHJvd0luZGV4IH19XCJcbiAgICAgICAgICAgICAgICAgICAgbmFtZT1cInJhZGlvXCJcbiAgICAgICAgICAgICAgICAgICAgKGNoYW5nZSk9XCJvblJhZGlvU2VsZWN0KCRldmVudCwgcm93LCByb3dJbmRleClcIlxuICAgICAgICAgICAgICAgICAgLz5cbiAgICAgICAgICAgICAgICA8L2xhYmVsPlxuICAgICAgICAgICAgICA8L3RkPlxuICAgICAgICAgICAgICA8bmctY29udGFpbmVyICpuZ0Zvcj1cImxldCBjb2x1bW4gb2YgY29sdW1uczsgbGV0IGNvbEluZGV4ID0gaW5kZXhcIj5cbiAgICAgICAgICAgICAgICA8dGRcbiAgICAgICAgICAgICAgICAgIChjbGljayk9XCJvbkNsaWNrKCRldmVudCwgcm93LCBjb2x1bW4ua2V5LCBjb2xJbmRleCwgcm93SW5kZXgpXCJcbiAgICAgICAgICAgICAgICAgICNjb250ZXh0TWVudVxuICAgICAgICAgICAgICAgICAgKGNvbnRleHRtZW51KT1cIm9uUm93Q29udGV4dE1lbnUoJGV2ZW50LCByb3csIGNvbHVtbi5rZXksIGNvbEluZGV4LCByb3dJbmRleClcIlxuICAgICAgICAgICAgICAgICAgKGRibGNsaWNrKT1cIm9uRG91YmxlQ2xpY2soJGV2ZW50LCByb3csIGNvbHVtbi5rZXksIGNvbEluZGV4LCByb3dJbmRleClcIlxuICAgICAgICAgICAgICAgICAgW2NsYXNzLnBpbm5lZC1sZWZ0XT1cImNvbHVtbi5waW5uZWRcIlxuICAgICAgICAgICAgICAgICAgW25nQ2xhc3NdPVwiY29sdW1uLmNzc0NsYXNzID8gY29sdW1uLmNzc0NsYXNzLm5hbWUgOiAnJ1wiXG4gICAgICAgICAgICAgICAgICBbc3R5bGUubGVmdF09XCJzdHlsZVNlcnZpY2UucGlubmVkV2lkdGgoY29sdW1uLnBpbm5lZCwgY29sSW5kZXgpXCJcbiAgICAgICAgICAgICAgICAgIFtjbGFzcy5uZ3gtdGFibGVfX3RhYmxlLWNvbC0tc2VsZWN0ZWRdPVwiXG4gICAgICAgICAgICAgICAgICAgIGNvbEluZGV4ID09PSBzZWxlY3RlZENvbCAmJiAhY29uZmlnLnNlbGVjdENlbGxcbiAgICAgICAgICAgICAgICAgIFwiXG4gICAgICAgICAgICAgICAgICBbY2xhc3Mubmd4LXRhYmxlX190YWJsZS1jZWxsLS1zZWxlY3RlZF09XCJcbiAgICAgICAgICAgICAgICAgICAgY29sSW5kZXggPT09IHNlbGVjdGVkQ29sICYmXG4gICAgICAgICAgICAgICAgICAgIHJvd0luZGV4ID09PSBzZWxlY3RlZFJvdyAmJlxuICAgICAgICAgICAgICAgICAgICAhY29uZmlnLnNlbGVjdENvbCAmJlxuICAgICAgICAgICAgICAgICAgICAhY29uZmlnLnNlbGVjdFJvd1xuICAgICAgICAgICAgICAgICAgXCJcbiAgICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgICA8ZGl2ICpuZ0lmPVwiIWNvbHVtbi5jZWxsVGVtcGxhdGVcIj57eyByb3cgfCByZW5kZXI6IGNvbHVtbi5rZXkgfX08L2Rpdj5cbiAgICAgICAgICAgICAgICAgIDxuZy1jb250YWluZXJcbiAgICAgICAgICAgICAgICAgICAgKm5nSWY9XCJjb2x1bW4uY2VsbFRlbXBsYXRlXCJcbiAgICAgICAgICAgICAgICAgICAgW25nVGVtcGxhdGVPdXRsZXRdPVwiY29sdW1uLmNlbGxUZW1wbGF0ZVwiXG4gICAgICAgICAgICAgICAgICAgIFtuZ1RlbXBsYXRlT3V0bGV0Q29udGV4dF09XCJ7XG4gICAgICAgICAgICAgICAgICAgICAgJGltcGxpY2l0OiByb3csXG4gICAgICAgICAgICAgICAgICAgICAgcm93SW5kZXg6IHJvd0luZGV4LFxuICAgICAgICAgICAgICAgICAgICAgIGNvbHVtbjogY29sdW1uXG4gICAgICAgICAgICAgICAgICAgIH1cIlxuICAgICAgICAgICAgICAgICAgPlxuICAgICAgICAgICAgICAgICAgPC9uZy1jb250YWluZXI+XG4gICAgICAgICAgICAgICAgPC90ZD5cbiAgICAgICAgICAgICAgPC9uZy1jb250YWluZXI+XG4gICAgICAgICAgICAgIDx0ZCAqbmdJZj1cImNvbmZpZy5hZGRpdGlvbmFsQWN0aW9ucyB8fCBjb25maWcuZGV0YWlsc1RlbXBsYXRlXCI+XG4gICAgICAgICAgICAgICAgPHNwYW5cbiAgICAgICAgICAgICAgICAgIGNsYXNzPVwibmd4LWljb25cIlxuICAgICAgICAgICAgICAgICAgKm5nSWY9XCJhcnJvd0RlZmluaXRpb25cIlxuICAgICAgICAgICAgICAgICAgW25nQ2xhc3NdPVwiXG4gICAgICAgICAgICAgICAgICAgIGlzUm93Q29sbGFwc2VkKHJvd0luZGV4KSA/ICduZ3gtaWNvbi1hcnJvdy1kb3duJyA6ICduZ3gtaWNvbi1hcnJvdy1yaWdodCdcbiAgICAgICAgICAgICAgICAgIFwiXG4gICAgICAgICAgICAgICAgICAoY2xpY2spPVwiY29sbGFwc2VSb3cocm93SW5kZXgpXCJcbiAgICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgPC9zcGFuPlxuICAgICAgICAgICAgICA8L3RkPlxuICAgICAgICAgICAgPC90cj5cbiAgICAgICAgICAgIDx0clxuICAgICAgICAgICAgICAqbmdJZj1cIlxuICAgICAgICAgICAgICAgIChjb25maWcuZGV0YWlsc1RlbXBsYXRlICYmIHNlbGVjdGVkRGV0YWlsc1RlbXBsYXRlUm93SWQuaGFzKHJvd0luZGV4KSkgfHxcbiAgICAgICAgICAgICAgICBjb25maWcuY29sbGFwc2VBbGxSb3dzXG4gICAgICAgICAgICAgIFwiXG4gICAgICAgICAgICA+XG4gICAgICAgICAgICAgIDx0ZCAqbmdJZj1cImNvbmZpZy5jaGVja2JveGVzIHx8IGNvbmZpZy5yYWRpb1wiPjwvdGQ+XG4gICAgICAgICAgICAgIDx0ZCBbYXR0ci5jb2xzcGFuXT1cImNvbHVtbnMubGVuZ3RoICsgMVwiPlxuICAgICAgICAgICAgICAgIDxuZy1jb250YWluZXJcbiAgICAgICAgICAgICAgICAgIFtuZ1RlbXBsYXRlT3V0bGV0XT1cImRldGFpbHNUZW1wbGF0ZVwiXG4gICAgICAgICAgICAgICAgICBbbmdUZW1wbGF0ZU91dGxldENvbnRleHRdPVwieyAkaW1wbGljaXQ6IHJvdywgaW5kZXg6IHJvd0luZGV4IH1cIlxuICAgICAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICA8L25nLWNvbnRhaW5lcj5cbiAgICAgICAgICAgICAgPC90ZD5cbiAgICAgICAgICAgIDwvdHI+XG4gICAgICAgICAgPC9uZy1jb250YWluZXI+XG4gICAgICAgIDwvY2RrLXZpcnR1YWwtc2Nyb2xsLXZpZXdwb3J0PlxuICAgICAgPC9uZy1jb250YWluZXI+XG4gICAgICA8bmctY29udGFpbmVyICpuZ0lmPVwiIXJvd1RlbXBsYXRlICYmIGNvbmZpZy5ncm91cFJvd3NcIj5cbiAgICAgICAgPG5nLWNvbnRhaW5lclxuICAgICAgICAgICpuZ0Zvcj1cIlxuICAgICAgICAgICAgbGV0IGdyb3VwIG9mIGdyb3VwZWRcbiAgICAgICAgICAgICAgfCBzb3J0OiBzb3J0Qnk6Y29uZmlnXG4gICAgICAgICAgICAgIHwgc2VhcmNoOiB0ZXJtOmZpbHRlcmVkQ291bnRTdWJqZWN0OmNvbmZpZ1xuICAgICAgICAgICAgICB8IGdsb2JhbDogZ2xvYmFsU2VhcmNoVGVybTpmaWx0ZXJlZENvdW50U3ViamVjdFxuICAgICAgICAgICAgICB8IHBhZ2luYXRlOiB7IGl0ZW1zUGVyUGFnZTogbGltaXQsIGN1cnJlbnRQYWdlOiBwYWdlLCB0b3RhbEl0ZW1zOiBjb3VudCwgaWQ6IGlkIH07XG4gICAgICAgICAgICBsZXQgcm93SW5kZXggPSBpbmRleFxuICAgICAgICAgIFwiXG4gICAgICAgID5cbiAgICAgICAgICA8dHI+XG4gICAgICAgICAgICA8bmctY29udGFpbmVyICpuZ0lmPVwiIWdyb3VwUm93c0hlYWRlclRlbXBsYXRlXCI+XG4gICAgICAgICAgICAgIDx0ZCBbYXR0ci5jb2xzcGFuXT1cImNvbHVtbnMubGVuZ3RoXCI+XG4gICAgICAgICAgICAgICAgPGRpdj57eyBncm91cFswXVtncm91cFJvd3NCeV0gfX0gKHt7IGdyb3VwLmxlbmd0aCB9fSk8L2Rpdj5cbiAgICAgICAgICAgICAgPC90ZD5cbiAgICAgICAgICAgIDwvbmctY29udGFpbmVyPlxuICAgICAgICAgICAgPG5nLWNvbnRhaW5lclxuICAgICAgICAgICAgICAqbmdJZj1cImdyb3VwUm93c0hlYWRlclRlbXBsYXRlXCJcbiAgICAgICAgICAgICAgW25nVGVtcGxhdGVPdXRsZXRdPVwiZ3JvdXBSb3dzSGVhZGVyVGVtcGxhdGVcIlxuICAgICAgICAgICAgICBbbmdUZW1wbGF0ZU91dGxldENvbnRleHRdPVwie1xuICAgICAgICAgICAgICAgIHRvdGFsOiBncm91cC5sZW5ndGgsXG4gICAgICAgICAgICAgICAga2V5OiBncm91cFJvd3NCeSxcbiAgICAgICAgICAgICAgICB2YWx1ZTogZ3JvdXBbMF0gPyBncm91cFswXVtncm91cFJvd3NCeV0gOiAnJyxcbiAgICAgICAgICAgICAgICBncm91cDogZ3JvdXAsXG4gICAgICAgICAgICAgICAgaW5kZXg6IHJvd0luZGV4XG4gICAgICAgICAgICAgIH1cIlxuICAgICAgICAgICAgPlxuICAgICAgICAgICAgPC9uZy1jb250YWluZXI+XG4gICAgICAgICAgICA8dGQ+XG4gICAgICAgICAgICAgIDxzcGFuXG4gICAgICAgICAgICAgICAgY2xhc3M9XCJuZ3gtaWNvblwiXG4gICAgICAgICAgICAgICAgKm5nSWY9XCJhcnJvd0RlZmluaXRpb25cIlxuICAgICAgICAgICAgICAgIFtuZ0NsYXNzXT1cIlxuICAgICAgICAgICAgICAgICAgaXNSb3dDb2xsYXBzZWQocm93SW5kZXgpID8gJ25neC1pY29uLWFycm93LWRvd24nIDogJ25neC1pY29uLWFycm93LXJpZ2h0J1xuICAgICAgICAgICAgICAgIFwiXG4gICAgICAgICAgICAgICAgKGNsaWNrKT1cImNvbGxhcHNlUm93KHJvd0luZGV4KVwiXG4gICAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgPC9zcGFuPlxuICAgICAgICAgICAgPC90ZD5cbiAgICAgICAgICA8L3RyPlxuICAgICAgICAgIDxuZy1jb250YWluZXIgKm5nSWY9XCJzZWxlY3RlZERldGFpbHNUZW1wbGF0ZVJvd0lkLmhhcyhyb3dJbmRleClcIj5cbiAgICAgICAgICAgIDx0ciAqbmdGb3I9XCJsZXQgcm93IG9mIGdyb3VwXCI+XG4gICAgICAgICAgICAgIDx0ZCAqbmdGb3I9XCJsZXQgY29sdW1uIG9mIGNvbHVtbnNcIj5cbiAgICAgICAgICAgICAgICB7eyByb3cgfCByZW5kZXI6IGNvbHVtbi5rZXkgfX1cbiAgICAgICAgICAgICAgICA8IS0tIFRPRE8gYWxsb3cgdXNlcnMgdG8gYWRkIGdyb3VwUm93c1RlbXBsYXRlUmVmIC0tPlxuICAgICAgICAgICAgICA8L3RkPlxuICAgICAgICAgICAgICA8dGQ+PC90ZD5cbiAgICAgICAgICAgIDwvdHI+XG4gICAgICAgICAgPC9uZy1jb250YWluZXI+XG4gICAgICAgIDwvbmctY29udGFpbmVyPlxuICAgICAgPC9uZy1jb250YWluZXI+XG4gICAgPC90Ym9keT5cbiAgICA8dGJvZHlcbiAgICAgICpuZ0lmPVwiZGF0YSAmJiAhY29uZmlnLmlzTG9hZGluZyAmJiBjb25maWcucm93UmVvcmRlclwiXG4gICAgICBjbGFzcz1cIm5neC1kcmFnZ2FibGUtcm93LWFyZWFcIlxuICAgICAgY2RrRHJvcExpc3RcbiAgICAgIChjZGtEcm9wTGlzdERyb3BwZWQpPVwib25Ecm9wKCRldmVudClcIlxuICAgID5cbiAgICAgIDxuZy1jb250YWluZXIgKm5nSWY9XCIhcm93VGVtcGxhdGUgJiYgIWNvbmZpZy5ncm91cFJvd3NcIj5cbiAgICAgICAgPG5nLWNvbnRhaW5lclxuICAgICAgICAgICpuZ0Zvcj1cIlxuICAgICAgICAgICAgbGV0IHJvdyBvZiBkYXRhXG4gICAgICAgICAgICAgIHwgc29ydDogc29ydEJ5XG4gICAgICAgICAgICAgIHwgc2VhcmNoOiB0ZXJtOmZpbHRlcmVkQ291bnRTdWJqZWN0XG4gICAgICAgICAgICAgIHwgZ2xvYmFsOiBnbG9iYWxTZWFyY2hUZXJtOmZpbHRlcmVkQ291bnRTdWJqZWN0XG4gICAgICAgICAgICAgIHwgcGFnaW5hdGU6IHsgaXRlbXNQZXJQYWdlOiBsaW1pdCwgY3VycmVudFBhZ2U6IHBhZ2UsIHRvdGFsSXRlbXM6IGNvdW50LCBpZDogaWQgfVxuICAgICAgICAgIFwiXG4gICAgICAgID5cbiAgICAgICAgICA8dHJcbiAgICAgICAgICAgIGNsYXNzPVwibmd4LWRyYWdnYWJsZS1yb3dcIlxuICAgICAgICAgICAgY2RrRHJhZ1xuICAgICAgICAgICAgKGNka0RyYWdTdGFydGVkKT1cIm9uRHJhZ1N0YXJ0KCRldmVudClcIlxuICAgICAgICAgICAgW2Nka0RyYWdTdGFydERlbGF5XT1cImNvbmZpZy5yZW9yZGVyRGVsYXkgfHwgMFwiXG4gICAgICAgICAgICBjZGtEcmFnTG9ja0F4aXM9XCJ5XCJcbiAgICAgICAgICA+XG4gICAgICAgICAgICA8dGQgKm5nSWY9XCJjb25maWcuY2hlY2tib3hlc1wiPlxuICAgICAgICAgICAgICA8bGFiZWwgY2xhc3M9XCJuZ3gtZm9ybS1jaGVja2JveFwiPlxuICAgICAgICAgICAgICAgIDxpbnB1dFxuICAgICAgICAgICAgICAgICAgdHlwZT1cImNoZWNrYm94XCJcbiAgICAgICAgICAgICAgICAgIGlkPVwiY2hlY2tib3gtZHJhZ2dhYmxlLXt7IGRhdGEuaW5kZXhPZihyb3cpIH19XCJcbiAgICAgICAgICAgICAgICAgIFtjaGVja2VkXT1cImlzU2VsZWN0ZWQgfHwgc2VsZWN0ZWRDaGVja2JveGVzLmhhcyhkYXRhLmluZGV4T2Yocm93KSlcIlxuICAgICAgICAgICAgICAgICAgKGNoYW5nZSk9XCJvbkNoZWNrYm94U2VsZWN0KCRldmVudCwgcm93LCBkYXRhLmluZGV4T2Yocm93KSlcIlxuICAgICAgICAgICAgICAgIC8+XG4gICAgICAgICAgICAgICAgPGVtIGNsYXNzPVwibmd4LWZvcm0taWNvblwiPjwvZW0+XG4gICAgICAgICAgICAgIDwvbGFiZWw+XG4gICAgICAgICAgICA8L3RkPlxuICAgICAgICAgICAgPHRkICpuZ0lmPVwiY29uZmlnLnJhZGlvXCI+XG4gICAgICAgICAgICAgIDxsYWJlbD5cbiAgICAgICAgICAgICAgICA8aW5wdXRcbiAgICAgICAgICAgICAgICAgIHR5cGU9XCJyYWRpb1wiXG4gICAgICAgICAgICAgICAgICBpZD1cInJhZGlvLWRyYWdnYWJsZS17eyBkYXRhLmluZGV4T2Yocm93KSB9fVwiXG4gICAgICAgICAgICAgICAgICBuYW1lPVwicmFkaW9cIlxuICAgICAgICAgICAgICAgICAgKGNoYW5nZSk9XCJvblJhZGlvU2VsZWN0KCRldmVudCwgcm93LCBkYXRhLmluZGV4T2Yocm93KSlcIlxuICAgICAgICAgICAgICAgIC8+XG4gICAgICAgICAgICAgIDwvbGFiZWw+XG4gICAgICAgICAgICA8L3RkPlxuICAgICAgICAgICAgPG5nLWNvbnRhaW5lciAqbmdGb3I9XCJsZXQgY29sdW1uIG9mIGNvbHVtbnM7IGxldCBjb2xJbmRleCA9IGluZGV4XCI+XG4gICAgICAgICAgICAgIDx0ZFxuICAgICAgICAgICAgICAgIChjbGljayk9XCJvbkNsaWNrKCRldmVudCwgcm93LCBjb2x1bW4ua2V5LCBjb2xJbmRleCwgZGF0YS5pbmRleE9mKHJvdykpXCJcbiAgICAgICAgICAgICAgICAoZGJsY2xpY2spPVwib25Eb3VibGVDbGljaygkZXZlbnQsIHJvdywgY29sdW1uLmtleSwgY29sSW5kZXgsIGRhdGEuaW5kZXhPZihyb3cpKVwiXG4gICAgICAgICAgICAgICAgW2NsYXNzLm5neC10YWJsZV9fdGFibGUtY29sLS1zZWxlY3RlZF09XCJcbiAgICAgICAgICAgICAgICAgIGNvbEluZGV4ID09PSBzZWxlY3RlZENvbCAmJiAhY29uZmlnLnNlbGVjdENlbGxcbiAgICAgICAgICAgICAgICBcIlxuICAgICAgICAgICAgICAgIFtjbGFzcy5uZ3gtdGFibGVfX3RhYmxlLWNlbGwtLXNlbGVjdGVkXT1cIlxuICAgICAgICAgICAgICAgICAgY29sSW5kZXggPT09IHNlbGVjdGVkQ29sICYmXG4gICAgICAgICAgICAgICAgICBkYXRhLmluZGV4T2Yocm93KSA9PT0gc2VsZWN0ZWRSb3cgJiZcbiAgICAgICAgICAgICAgICAgICFjb25maWcuc2VsZWN0Q29sICYmXG4gICAgICAgICAgICAgICAgICAhY29uZmlnLnNlbGVjdFJvd1xuICAgICAgICAgICAgICAgIFwiXG4gICAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICA8ZGl2ICpuZ0lmPVwiIWNvbHVtbi5jZWxsVGVtcGxhdGVcIj57eyByb3cgfCByZW5kZXI6IGNvbHVtbi5rZXkgfX08L2Rpdj5cbiAgICAgICAgICAgICAgICA8bmctY29udGFpbmVyXG4gICAgICAgICAgICAgICAgICAqbmdJZj1cImNvbHVtbi5jZWxsVGVtcGxhdGVcIlxuICAgICAgICAgICAgICAgICAgW25nVGVtcGxhdGVPdXRsZXRdPVwiY29sdW1uLmNlbGxUZW1wbGF0ZVwiXG4gICAgICAgICAgICAgICAgICBbbmdUZW1wbGF0ZU91dGxldENvbnRleHRdPVwie1xuICAgICAgICAgICAgICAgICAgICAkaW1wbGljaXQ6IHJvdyxcbiAgICAgICAgICAgICAgICAgICAgcm93SW5kZXg6IGRhdGEuaW5kZXhPZihyb3cpLFxuICAgICAgICAgICAgICAgICAgICBjb2x1bW46IGNvbHVtblxuICAgICAgICAgICAgICAgICAgfVwiXG4gICAgICAgICAgICAgICAgPlxuICAgICAgICAgICAgICAgIDwvbmctY29udGFpbmVyPlxuICAgICAgICAgICAgICA8L3RkPlxuICAgICAgICAgICAgPC9uZy1jb250YWluZXI+XG4gICAgICAgICAgPC90cj5cbiAgICAgICAgPC9uZy1jb250YWluZXI+XG4gICAgICA8L25nLWNvbnRhaW5lcj5cbiAgICA8L3Rib2R5PlxuICAgIDx0Ym9keSAqbmdJZj1cImZpbHRlckNvdW50ID09PSAwXCI+XG4gICAgICA8dHIgY2xhc3M9XCJuZ3gtdGFibGVfX2JvZHktZW1wdHlcIj5cbiAgICAgICAgPG5nLWNvbnRhaW5lciAqbmdJZj1cIm5vUmVzdWx0c1RlbXBsYXRlXCIgW25nVGVtcGxhdGVPdXRsZXRdPVwibm9SZXN1bHRzVGVtcGxhdGVcIj5cbiAgICAgICAgPC9uZy1jb250YWluZXI+XG4gICAgICAgIDx0ZCBbYXR0ci5jb2xzcGFuXT1cImNvbHVtbnMgJiYgY29sdW1ucy5sZW5ndGggKyAxXCIgKm5nSWY9XCIhbm9SZXN1bHRzVGVtcGxhdGVcIj5cbiAgICAgICAgICA8ZGl2IGNsYXNzPVwibmd4LXRhYmxlX190YWJsZS1uby1yZXN1bHRzXCI+Tm8gcmVzdWx0czwvZGl2PlxuICAgICAgICA8L3RkPlxuICAgICAgPC90cj5cbiAgICA8L3Rib2R5PlxuICAgIDx0Ym9keSAqbmdJZj1cImNvbmZpZy5pc0xvYWRpbmdcIj5cbiAgICAgIDx0ciBjbGFzcz1cIm5neC10YWJsZV9fYm9keS1sb2FkaW5nXCI+XG4gICAgICAgIDxuZy1jb250YWluZXIgKm5nSWY9XCJsb2FkaW5nVGVtcGxhdGVcIiBbbmdUZW1wbGF0ZU91dGxldF09XCJsb2FkaW5nVGVtcGxhdGVcIj4gPC9uZy1jb250YWluZXI+XG4gICAgICAgIDx0ZCBbYXR0ci5jb2xzcGFuXT1cImNvbHVtbnMgJiYgY29sdW1ucy5sZW5ndGggKyAxXCIgKm5nSWY9XCIhbG9hZGluZ1RlbXBsYXRlXCI+XG4gICAgICAgICAgPGRpdiBbc3R5bGUuaGVpZ2h0LnB4XT1cImxvYWRpbmdIZWlnaHRcIiBjbGFzcz1cIm5neC10YWJsZV9fdGFibGUtbG9hZGVyLXdyYXBwZXJcIj5cbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJuZ3gtdGFibGVfX3RhYmxlLWxvYWRlclwiPjwvZGl2PlxuICAgICAgICAgIDwvZGl2PlxuICAgICAgICA8L3RkPlxuICAgICAgPC90cj5cbiAgICA8L3Rib2R5PlxuICAgIDx0Zm9vdCAqbmdJZj1cInN1bW1hcnlUZW1wbGF0ZVwiPlxuICAgICAgPHRyPlxuICAgICAgICA8bmctY29udGFpbmVyXG4gICAgICAgICAgW25nVGVtcGxhdGVPdXRsZXRdPVwic3VtbWFyeVRlbXBsYXRlXCJcbiAgICAgICAgICBbbmdUZW1wbGF0ZU91dGxldENvbnRleHRdPVwieyB0b3RhbDogZGF0YS5sZW5ndGgsIGxpbWl0OiBsaW1pdCwgcGFnZTogcGFnZSB9XCJcbiAgICAgICAgPlxuICAgICAgICA8L25nLWNvbnRhaW5lcj5cbiAgICAgIDwvdHI+XG4gICAgPC90Zm9vdD5cbiAgPC90YWJsZT5cbiAgPHBhZ2luYXRpb25cbiAgICBbYXR0ci5pZF09XCIncGFnaW5hdGlvbicgKyBpZFwiXG4gICAgW2lkXT1cImlkXCJcbiAgICAjcGFnaW5hdGlvbkNvbXBvbmVudFxuICAgIFtjb25maWddPVwiY29uZmlnXCJcbiAgICBbcGFnaW5hdGlvbl09XCJwYWdpbmF0aW9uXCJcbiAgICAodXBkYXRlUmFuZ2UpPVwib25QYWdpbmF0aW9uKCRldmVudClcIlxuICA+XG4gIDwvcGFnaW5hdGlvbj5cbjwvZGl2PlxuIl19