@progress/telerik-angular-native-report-viewer
Version:
Progress® Telerik® Native Report Viewer for Angular
394 lines (388 loc) • 47.6 kB
JavaScript
import { Component, Input, ViewChild, ViewEncapsulation } from '@angular/core';
import { chevronDownIcon, chevronUpIcon, convertLowercaseIcon, regularExpressionIcon, wholeWordIcon } from '@progress/kendo-svg-icons';
import { Subscription, take } from 'rxjs';
import * as i0 from "@angular/core";
import * as i1 from "../reporting-angular-viewer.service";
import * as i2 from "@angular/common";
import * as i3 from "@progress/kendo-angular-dialog";
import * as i4 from "@progress/kendo-angular-dropdowns";
import * as i5 from "@progress/kendo-angular-listbox";
import * as i6 from "@progress/kendo-angular-buttons";
import * as i7 from "../directives/after-filter-changed.directive";
export class SearchComponent {
constructor(ngZone, service) {
this.ngZone = ngZone;
this.service = service;
this.chevronUpIcon = chevronUpIcon;
this.wholeWordIcon = wholeWordIcon;
this.chevronDownIcon = chevronDownIcon;
this.convertToLowerCaseIcon = convertLowercaseIcon;
this.regularExpressionIcon = regularExpressionIcon;
this.windowTop = 30;
this.searchResults = [];
this.isComboboxOpen = false;
this.searchText = '';
this.opened = true;
this.selectedIndex = 0;
this.searchInfo = {
searchToken: '',
matchCase: false,
matchWholeWord: false,
useRegularExpressions: false
};
this.subs = new Subscription();
}
ngOnInit() {
const reportElemWidth = this.service.reportWidth;
this.windowHeight = this.service.windowHeight;
this.windowWidth = this.service.windowWidth;
this.windowLeft = reportElemWidth - (this.windowWidth + 40);
}
ngAfterViewInit() {
this.service.searchManager?.on('searchComplete', (results) => this.onSearchComplete(results));
this.ngZone.onStable.pipe(take(1)).subscribe(_ => this.comboBox?.focus());
const combobox = this.comboBox?.wrapper?.nativeElement;
this.subs.add(combobox.addEventListener('keydown', (event) => this.onArrowEvent(event), true));
}
ngOnDestroy() {
this.subs.unsubscribe();
}
toggle(isOpened) {
this.service.isSearchWindowOpen = isOpened;
this.searchResults = [];
this.service.searchManager.closeSearch();
}
handleFilter(value) {
if (value === "") {
return;
}
this.searchText = value;
this.search(value, true);
}
onWidthChange(width) {
this.service.windowWidth = width;
}
onHeightChange(height) {
this.service.windowHeight = height;
}
onBlur() {
this.searchText = this.comboBox.text = this.comboBox?.searchbar.value;
}
search(text, isTextFilter = false) {
if (typeof text !== 'string' && !isTextFilter)
return;
if (text && this.searchTerms.indexOf(text) === -1) {
this.searchTerms.push(text);
}
if (this.searchInfo.searchToken !== text) {
this.selectedIndex = 0;
}
this.comboBox.value = text;
this.comboBox.searchBarChange(text);
this.searchInfo.searchToken = text;
this.service.searchManager?.search(this.searchInfo);
this.ngZone.onStable.pipe(take(1)).subscribe(_ => this.comboBox?.focus());
}
onSearchFilter(filterName) {
this.selectedIndex = 0;
this.searchInfo[filterName] = !this.searchInfo[filterName];
this.search(this.searchInfo.searchToken);
}
onSelectionChange(item) {
const searchResultItem = this.searchResults[item.index];
this.service.searchManager?.highlightSearchItem(searchResultItem);
}
open(event, comboBox) {
if (event.target.closest('button') && !this.isComboboxOpen) {
this.isComboboxOpen = true;
comboBox.toggle(true);
}
}
onClose() {
setTimeout(() => this.isComboboxOpen = false);
}
onNavigateButtons(direction, sourceTarget = 'listboxNav') {
const topReached = direction === 'up' && this.selectedIndex <= 0;
const bottomReached = direction === 'down' && this.selectedIndex >= this.searchResults.length - 1;
if (topReached || bottomReached) {
return;
}
this.selectedIndex = this.selectedIndex + (direction === 'up' ? -1 : 1);
this.listbox?.selectionService.select(this.selectedIndex);
}
getLocaleMessage(message) {
return this.service.options.messages[`ReportViewer_SearchDialog${message}`];
}
onArrowEvent(event) {
event.stopImmediatePropagation();
const searchResultItems = this.searchResults.length;
if (searchResultItems > 0) {
const isArrowUp = event.key === 'ArrowUp';
const isArrowDown = event.key === 'ArrowDown';
if (isArrowUp || isArrowDown) {
event.preventDefault();
const dir = isArrowUp ? 'up' : 'down';
this.onNavigateButtons(dir, 'comboboxNav');
}
const currentListboxItem = this.listbox.listboxItems.toArray()[this.selectedIndex].nativeElement;
currentListboxItem?.focus();
this.ngZone.onStable.pipe(take(1)).subscribe(() => this.comboBox?.focus());
}
}
onSearchComplete(results) {
let totalCount = results.length;
if (totalCount > 250) {
results = results.slice(0, 250);
}
this.searchResults = results;
if (results) {
this.listbox?.selectItem(0);
}
if (totalCount > 0) {
this.service.searchManager?.navigateToPage(results[0]);
}
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: SearchComponent, deps: [{ token: i0.NgZone }, { token: i1.ReportingAngularViewerService }], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: SearchComponent, selector: "search-window", inputs: { searchTerms: "searchTerms" }, viewQueries: [{ propertyName: "listbox", first: true, predicate: ["listBox"], descendants: true }, { propertyName: "comboBox", first: true, predicate: ["comboBox"], descendants: true }], ngImport: i0, template: `
<kendo-window
(close)="toggle(false)"
class="trv-search trv-search-dialog"
[height]="390"
[(top)]="windowTop"
[(left)]="windowLeft"
(widthChange)="onWidthChange($event)"
(heightChange)="onHeightChange($event)"
[width]="windowWidth"
[height]="windowHeight"
[minHeight]="390"
[minWidth]="330"
>
<kendo-window-titlebar>
<span class="k-window-title"> {{ getLocaleMessage('Title') }} </span>
<button kendoWindowMinimizeAction></button>
<button kendoWindowRestoreAction></button>
<button kendoWindowCloseAction></button>
</kendo-window-titlebar>
<div class="trv-search-window trv-window k-window-content">
<div class="search-dialog-wrapper">
<kendo-combobox
#comboBox
[data]="searchTerms"
[value]="searchText"
[allowCustom]="true"
[filterable]="true"
[placeholder]="getLocaleMessage('ComboBoxPlaceholderText')"
(afterFilterChanged)="handleFilter($event)"
(click)="open($event, comboBox)"
(close)="onClose()"
(blur)="onBlur()"
(valueChange)="search($event)"
(open)="$event.preventDefault()"
></kendo-combobox>
<div class="k-hstack k-gap-2 k-ml-2">
<button
kendoButton
fillMode="flat"
icon="convert-lowercase"
[svgIcon]="convertToLowerCaseIcon"
[title]="getLocaleMessage('MatchCaseTitle')"
[selected]="searchInfo.matchCase"
(click)="onSearchFilter('matchCase')">
</button>
<button
kendoButton
fillMode="flat"
icon="whole-word"
[svgIcon]="wholeWordIcon"
[title]="getLocaleMessage('MatchWholeWordTitle')"
[selected]="searchInfo.matchWholeWord"
(click)="onSearchFilter('matchWholeWord')">
</button>
<button
kendoButton
fillMode="flat"
icon="regular-expression"
[svgIcon]="regularExpressionIcon"
[title]="getLocaleMessage('UseRegexTitle')"
[selected]="searchInfo.useRegularExpressions"
(click)="onSearchFilter('useRegularExpressions')">
</button>
</div>
</div>
<div class="trv-search-dialog-results k-hstack k-gap-3 k-align-items-center k-mt-3 k-mb-2">
<span *ngIf="searchResults.length > 0" class="trv-search-dialog-results-label">
Result {{ listBox.selectedIndex + 1}} of {{searchResults.length }}
</span>
<span *ngIf="searchResults.length === 0" class="trv-search-dialog-results-label">
{{ getLocaleMessage('NoResultsLabel') }}
</span>
<kendo-buttongroup>
<button
kendoButton
fillMode="flat"
icon="chevron-up"
[svgIcon]="chevronUpIcon"
[title]="getLocaleMessage('NavigateUpTitle')"
(click)="onNavigateButtons('up')"
[disabled]="selectedIndex <= 0">
</button>
<button
kendoButton
fillMode="flat"
icon="chevron-down"
[svgIcon]="chevronDownIcon"
[title]="getLocaleMessage('NavigateDownTitle')"
(click)="onNavigateButtons('down');"
[disabled]="selectedIndex + 1 >= searchResults.length">
</button>
</kendo-buttongroup>
</div>
<kendo-listbox
#listBox
[style.width.%]="100"
[data]="searchResults"
[toolbar]="false"
(selectionChange)="onSelectionChange($event)"
>
<ng-template kendoListBoxItemTemplate let-dataItem>
<div
[attr.data-uid]="dataItem.id"
class="trv-search-dialog-results-row k-listview-item k-selected"
role="option"
>
<span class="k-search-dialog-result-desc">{{dataItem.description}}</span>
<span class="trv-search-dialog-results-pageSpan">page {{dataItem.page}}</span>
</div>
</ng-template>
</kendo-listbox>
</div>
</kendo-window>
`, isInline: true, styles: [".k-window-content .k-listbox{overflow:hidden;position:relative;flex-grow:1;height:auto}.k-window-content .k-list{max-height:100%}.trv-search{max-height:700px}.k-listview-item .k-search-dialog-result-desc{flex:1;margin-right:1em}.k-listview-item.trv-search-dialog-results-row{width:100%;display:flex;justify-content:space-between}\n"], dependencies: [{ kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i3.WindowComponent, selector: "kendo-window", inputs: ["autoFocusedElement", "title", "draggable", "resizable", "themeColor", "keepContent", "state", "minWidth", "minHeight", "width", "height", "top", "left"], outputs: ["dragStart", "dragEnd", "resizeStart", "resizeEnd", "close", "widthChange", "heightChange", "topChange", "leftChange", "stateChange"], exportAs: ["kendoWindow"] }, { kind: "component", type: i3.WindowCloseActionDirective, selector: "button[kendoWindowCloseAction]", inputs: ["window"], exportAs: ["kendoWindowCloseAction"] }, { kind: "component", type: i3.WindowMinimizeActionDirective, selector: "button[kendoWindowMinimizeAction]", inputs: ["window"], exportAs: ["kendoWindowMinimizeAction"] }, { kind: "component", type: i3.WindowRestoreActionDirective, selector: "button[kendoWindowRestoreAction]", inputs: ["window"], exportAs: ["kendoWindowRestoreAction"] }, { kind: "component", type: i3.WindowTitleBarComponent, selector: "kendo-window-titlebar", inputs: ["template", "id"] }, { kind: "component", type: i4.ComboBoxComponent, selector: "kendo-combobox", inputs: ["icon", "svgIcon", "inputAttributes", "showStickyHeader", "focusableId", "allowCustom", "data", "value", "textField", "valueField", "valuePrimitive", "valueNormalizer", "placeholder", "adaptiveMode", "title", "subtitle", "popupSettings", "listHeight", "loading", "suggest", "clearButton", "disabled", "itemDisabled", "readonly", "tabindex", "tabIndex", "filterable", "virtual", "size", "rounded", "fillMode"], outputs: ["valueChange", "selectionChange", "filterChange", "open", "opened", "close", "closed", "focus", "blur", "inputFocus", "inputBlur", "escape"], exportAs: ["kendoComboBox"] }, { kind: "component", type: i5.ListBoxComponent, selector: "kendo-listbox", inputs: ["textField", "data", "size", "toolbar", "listboxLabel", "listboxToolbarLabel", "itemDisabled"], outputs: ["selectionChange", "actionClick", "getChildListbox"] }, { kind: "directive", type: i5.ItemTemplateDirective, selector: "[kendoListBoxItemTemplate]" }, { kind: "component", type: i6.ButtonComponent, selector: "button[kendoButton]", inputs: ["arrowIcon", "toggleable", "togglable", "selected", "tabIndex", "imageUrl", "iconClass", "icon", "disabled", "size", "rounded", "fillMode", "themeColor", "svgIcon", "primary", "look"], outputs: ["selectedChange", "click"], exportAs: ["kendoButton"] }, { kind: "component", type: i6.ButtonGroupComponent, selector: "kendo-buttongroup", inputs: ["disabled", "selection", "width", "tabIndex", "navigable"], outputs: ["navigate"], exportAs: ["kendoButtonGroup"] }, { kind: "directive", type: i7.afterFilterChangedDirective, selector: "[afterFilterChanged]", inputs: ["filterChangeDelay"], outputs: ["afterFilterChanged"] }], encapsulation: i0.ViewEncapsulation.None }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: SearchComponent, decorators: [{
type: Component,
args: [{ selector: 'search-window', template: `
<kendo-window
(close)="toggle(false)"
class="trv-search trv-search-dialog"
[height]="390"
[(top)]="windowTop"
[(left)]="windowLeft"
(widthChange)="onWidthChange($event)"
(heightChange)="onHeightChange($event)"
[width]="windowWidth"
[height]="windowHeight"
[minHeight]="390"
[minWidth]="330"
>
<kendo-window-titlebar>
<span class="k-window-title"> {{ getLocaleMessage('Title') }} </span>
<button kendoWindowMinimizeAction></button>
<button kendoWindowRestoreAction></button>
<button kendoWindowCloseAction></button>
</kendo-window-titlebar>
<div class="trv-search-window trv-window k-window-content">
<div class="search-dialog-wrapper">
<kendo-combobox
#comboBox
[data]="searchTerms"
[value]="searchText"
[allowCustom]="true"
[filterable]="true"
[placeholder]="getLocaleMessage('ComboBoxPlaceholderText')"
(afterFilterChanged)="handleFilter($event)"
(click)="open($event, comboBox)"
(close)="onClose()"
(blur)="onBlur()"
(valueChange)="search($event)"
(open)="$event.preventDefault()"
></kendo-combobox>
<div class="k-hstack k-gap-2 k-ml-2">
<button
kendoButton
fillMode="flat"
icon="convert-lowercase"
[svgIcon]="convertToLowerCaseIcon"
[title]="getLocaleMessage('MatchCaseTitle')"
[selected]="searchInfo.matchCase"
(click)="onSearchFilter('matchCase')">
</button>
<button
kendoButton
fillMode="flat"
icon="whole-word"
[svgIcon]="wholeWordIcon"
[title]="getLocaleMessage('MatchWholeWordTitle')"
[selected]="searchInfo.matchWholeWord"
(click)="onSearchFilter('matchWholeWord')">
</button>
<button
kendoButton
fillMode="flat"
icon="regular-expression"
[svgIcon]="regularExpressionIcon"
[title]="getLocaleMessage('UseRegexTitle')"
[selected]="searchInfo.useRegularExpressions"
(click)="onSearchFilter('useRegularExpressions')">
</button>
</div>
</div>
<div class="trv-search-dialog-results k-hstack k-gap-3 k-align-items-center k-mt-3 k-mb-2">
<span *ngIf="searchResults.length > 0" class="trv-search-dialog-results-label">
Result {{ listBox.selectedIndex + 1}} of {{searchResults.length }}
</span>
<span *ngIf="searchResults.length === 0" class="trv-search-dialog-results-label">
{{ getLocaleMessage('NoResultsLabel') }}
</span>
<kendo-buttongroup>
<button
kendoButton
fillMode="flat"
icon="chevron-up"
[svgIcon]="chevronUpIcon"
[title]="getLocaleMessage('NavigateUpTitle')"
(click)="onNavigateButtons('up')"
[disabled]="selectedIndex <= 0">
</button>
<button
kendoButton
fillMode="flat"
icon="chevron-down"
[svgIcon]="chevronDownIcon"
[title]="getLocaleMessage('NavigateDownTitle')"
(click)="onNavigateButtons('down');"
[disabled]="selectedIndex + 1 >= searchResults.length">
</button>
</kendo-buttongroup>
</div>
<kendo-listbox
#listBox
[style.width.%]="100"
[data]="searchResults"
[toolbar]="false"
(selectionChange)="onSelectionChange($event)"
>
<ng-template kendoListBoxItemTemplate let-dataItem>
<div
[attr.data-uid]="dataItem.id"
class="trv-search-dialog-results-row k-listview-item k-selected"
role="option"
>
<span class="k-search-dialog-result-desc">{{dataItem.description}}</span>
<span class="trv-search-dialog-results-pageSpan">page {{dataItem.page}}</span>
</div>
</ng-template>
</kendo-listbox>
</div>
</kendo-window>
`, encapsulation: ViewEncapsulation.None, styles: [".k-window-content .k-listbox{overflow:hidden;position:relative;flex-grow:1;height:auto}.k-window-content .k-list{max-height:100%}.trv-search{max-height:700px}.k-listview-item .k-search-dialog-result-desc{flex:1;margin-right:1em}.k-listview-item.trv-search-dialog-results-row{width:100%;display:flex;justify-content:space-between}\n"] }]
}], ctorParameters: function () { return [{ type: i0.NgZone }, { type: i1.ReportingAngularViewerService }]; }, propDecorators: { searchTerms: [{
type: Input
}], listbox: [{
type: ViewChild,
args: ['listBox']
}], comboBox: [{
type: ViewChild,
args: ['comboBox']
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VhcmNoLXdpbmRvdy5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvbGliL3NlYXJjaC9zZWFyY2gtd2luZG93LmNvbXBvbmVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQWlCLFNBQVMsRUFBRSxLQUFLLEVBQTZCLFNBQVMsRUFBRSxpQkFBaUIsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUl6SCxPQUFPLEVBRUgsZUFBZSxFQUNmLGFBQWEsRUFDYixvQkFBb0IsRUFDcEIscUJBQXFCLEVBQ3JCLGFBQWEsRUFDaEIsTUFBTSwyQkFBMkIsQ0FBQztBQUVuQyxPQUFPLEVBQUUsWUFBWSxFQUFFLElBQUksRUFBRSxNQUFNLE1BQU0sQ0FBQzs7Ozs7Ozs7O0FBdUoxQyxNQUFNLE9BQU8sZUFBZTtJQWdDeEIsWUFDWSxNQUFjLEVBQ2YsT0FBc0M7UUFEckMsV0FBTSxHQUFOLE1BQU0sQ0FBUTtRQUNmLFlBQU8sR0FBUCxPQUFPLENBQStCO1FBNUIxQyxrQkFBYSxHQUFZLGFBQWEsQ0FBQztRQUN2QyxrQkFBYSxHQUFZLGFBQWEsQ0FBQztRQUN2QyxvQkFBZSxHQUFZLGVBQWUsQ0FBQztRQUMzQywyQkFBc0IsR0FBWSxvQkFBb0IsQ0FBQztRQUN2RCwwQkFBcUIsR0FBWSxxQkFBcUIsQ0FBQztRQUV2RCxjQUFTLEdBQVcsRUFBRSxDQUFDO1FBS3ZCLGtCQUFhLEdBQW1CLEVBQUUsQ0FBQztRQUNuQyxtQkFBYyxHQUFZLEtBQUssQ0FBQztRQUNoQyxlQUFVLEdBQVcsRUFBRSxDQUFDO1FBQ3hCLFdBQU0sR0FBRyxJQUFJLENBQUM7UUFDZCxrQkFBYSxHQUFXLENBQUMsQ0FBQztRQUUxQixlQUFVLEdBQWU7WUFDNUIsV0FBVyxFQUFFLEVBQUU7WUFDZixTQUFTLEVBQUUsS0FBSztZQUNoQixjQUFjLEVBQUUsS0FBSztZQUNyQixxQkFBcUIsRUFBRSxLQUFLO1NBQy9CLENBQUE7UUFFTyxT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LENBQUM7U0FDMUQ7SUFDTCxDQUFDOytHQXRMUSxlQUFlO21HQUFmLGVBQWUsd1JBbkpkOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7S0FxSFQ7OzRGQThCUSxlQUFlO2tCQXJKM0IsU0FBUzsrQkFDSSxlQUFlLFlBQ2Y7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztLQXFIVCxpQkE0QmMsaUJBQWlCLENBQUMsSUFBSTt5SUFHNUIsV0FBVztzQkFBbkIsS0FBSztnQkFFdUIsT0FBTztzQkFBbkMsU0FBUzt1QkFBQyxTQUFTO2dCQUNVLFFBQVE7c0JBQXJDLFNBQVM7dUJBQUMsVUFBVSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEFmdGVyVmlld0luaXQsIENvbXBvbmVudCwgSW5wdXQsIE5nWm9uZSwgT25EZXN0cm95LCBPbkluaXQsIFZpZXdDaGlsZCwgVmlld0VuY2Fwc3VsYXRpb24gfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IFJlcG9ydGluZ0FuZ3VsYXJWaWV3ZXJTZXJ2aWNlIH0gZnJvbSAnLi4vcmVwb3J0aW5nLWFuZ3VsYXItdmlld2VyLnNlcnZpY2UnO1xuaW1wb3J0IHsgU2VhcmNoSW5mbywgU2VhcmNoUmVzdWx0IH0gZnJvbSAnQHByb2dyZXNzL3RlbGVyaWstY29tbW9uLXJlcG9ydC12aWV3ZXInO1xuaW1wb3J0IHsgTGlzdEJveENvbXBvbmVudCwgTGlzdEJveFNlbGVjdGlvbkV2ZW50IH0gZnJvbSAnQHByb2dyZXNzL2tlbmRvLWFuZ3VsYXItbGlzdGJveCc7XG5pbXBvcnQge1xuICAgIFNWR0ljb24sXG4gICAgY2hldnJvbkRvd25JY29uLFxuICAgIGNoZXZyb25VcEljb24sXG4gICAgY29udmVydExvd2VyY2FzZUljb24sXG4gICAgcmVndWxhckV4cHJlc3Npb25JY29uLFxuICAgIHdob2xlV29yZEljb25cbn0gZnJvbSAnQHByb2dyZXNzL2tlbmRvLXN2Zy1pY29ucyc7XG5pbXBvcnQgeyBDb21ib0JveENvbXBvbmVudCB9IGZyb20gJ0Bwcm9ncmVzcy9rZW5kby1hbmd1bGFyLWRyb3Bkb3ducyc7XG5pbXBvcnQgeyBTdWJzY3JpcHRpb24sIHRha2UgfSBmcm9tICdyeGpzJztcblxuQENvbXBvbmVudCh7XG4gICAgc2VsZWN0b3I6ICdzZWFyY2gtd2luZG93JyxcbiAgICB0ZW1wbGF0ZTogYFxuICAgICAgICA8a2VuZG8td2luZG93XG4gICAgICAgICAgICAoY2xvc2UpPVwidG9nZ2xlKGZhbHNlKVwiXG4gICAgICAgICAgICBjbGFzcz1cInRydi1zZWFyY2ggdHJ2LXNlYXJjaC1kaWFsb2dcIlxuICAgICAgICAgICAgW2hlaWdodF09XCIzOTBcIlxuICAgICAgICAgICAgWyh0b3ApXT1cIndpbmRvd1RvcFwiXG4gICAgICAgICAgICBbKGxlZnQpXT1cIndpbmRvd0xlZnRcIlxuICAgICAgICAgICAgKHdpZHRoQ2hhbmdlKT1cIm9uV2lkdGhDaGFuZ2UoJGV2ZW50KVwiXG4gICAgICAgICAgICAoaGVpZ2h0Q2hhbmdlKT1cIm9uSGVpZ2h0Q2hhbmdlKCRldmVudClcIlxuICAgICAgICAgICAgW3dpZHRoXT1cIndpbmRvd1dpZHRoXCJcbiAgICAgICAgICAgIFtoZWlnaHRdPVwid2luZG93SGVpZ2h0XCJcbiAgICAgICAgICAgIFttaW5IZWlnaHRdPVwiMzkwXCJcbiAgICAgICAgICAgIFttaW5XaWR0aF09XCIzMzBcIlxuICAgICAgICA+XG4gICAgICAgICAgICA8a2VuZG8td2luZG93LXRpdGxlYmFyPlxuICAgICAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwiay13aW5kb3ctdGl0bGVcIj4ge3sgZ2V0TG9jYWxlTWVzc2FnZSgnVGl0bGUnKSB9fSA8L3NwYW4+XG4gICAgICAgICAgICAgICAgPGJ1dHRvbiBrZW5kb1dpbmRvd01pbmltaXplQWN0aW9uPjwvYnV0dG9uPlxuICAgICAgICAgICAgICAgIDxidXR0b24ga2VuZG9XaW5kb3dSZXN0b3JlQWN0aW9uPjwvYnV0dG9uPlxuICAgICAgICAgICAgICAgIDxidXR0b24ga2VuZG9XaW5kb3dDbG9zZUFjdGlvbj48L2J1dHRvbj5cbiAgICAgICAgICAgIDwva2VuZG8td2luZG93LXRpdGxlYmFyPlxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cInRydi1zZWFyY2gtd2luZG93IHRydi13aW5kb3cgay13aW5kb3ctY29udGVudFwiPlxuICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJzZWFyY2gtZGlhbG9nLXdyYXBwZXJcIj5cbiAgICAgICAgICAgICAgICAgICAgPGtlbmRvLWNvbWJvYm94XG4gICAgICAgICAgICAgICAgICAgICAgICAjY29tYm9Cb3hcbiAgICAgICAgICAgICAgICAgICAgICAgIFtkYXRhXT1cInNlYXJjaFRlcm1zXCJcbiAgICAgICAgICAgICAgICAgICAgICAgIFt2YWx1ZV09XCJzZWFyY2hUZXh0XCJcbiAgICAgICAgICAgICAgICAgICAgICAgIFthbGxvd0N1c3RvbV09XCJ0cnVlXCJcbiAgICAgICAgICAgICAgICAgICAgICAgIFtmaWx0ZXJhYmxlXT1cInRydWVcIlxuICAgICAgICAgICAgICAgICAgICAgICAgW3BsYWNlaG9sZGVyXT1cImdldExvY2FsZU1lc3NhZ2UoJ0NvbWJvQm94UGxhY2Vob2xkZXJUZXh0JylcIlxuICAgICAgICAgICAgICAgICAgICAgICAgKGFmdGVyRmlsdGVyQ2hhbmdlZCk9XCJoYW5kbGVGaWx0ZXIoJGV2ZW50KVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAoY2xpY2spPVwib3BlbigkZXZlbnQsIGNvbWJvQm94KVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAoY2xvc2UpPVwib25DbG9zZSgpXCJcbiAgICAgICAgICAgICAgICAgICAgICAgIChibHVyKT1cIm9uQmx1cigpXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICh2YWx1ZUNoYW5nZSk9XCJzZWFyY2goJGV2ZW50KVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAob3Blbik9XCIkZXZlbnQucHJldmVudERlZmF1bHQoKVwiXG4gICAgICAgICAgICAgICAgICAgID48L2tlbmRvLWNvbWJvYm94PlxuXG4gICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJrLWhzdGFjayBrLWdhcC0yIGstbWwtMlwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgPGJ1dHRvbiBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBrZW5kb0J1dHRvblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbGxNb2RlPVwiZmxhdFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWNvbj1cImNvbnZlcnQtbG93ZXJjYXNlXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBbc3ZnSWNvbl09XCJjb252ZXJ0VG9Mb3dlckNhc2VJY29uXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBbdGl0bGVdPVwiZ2V0TG9jYWxlTWVzc2FnZSgnTWF0Y2hDYXNlVGl0bGUnKVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgW3NlbGVjdGVkXT1cInNlYXJjaEluZm8ubWF0Y2hDYXNlXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAoY2xpY2spPVwib25TZWFyY2hGaWx0ZXIoJ21hdGNoQ2FzZScpXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgICAgICAgICAgICAgICAgIDxidXR0b25cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBrZW5kb0J1dHRvblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbGxNb2RlPVwiZmxhdFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWNvbj1cIndob2xlLXdvcmRcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtzdmdJY29uXT1cIndob2xlV29yZEljb25cIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFt0aXRsZV09XCJnZXRMb2NhbGVNZXNzYWdlKCdNYXRjaFdob2xlV29yZFRpdGxlJylcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtzZWxlY3RlZF09XCJzZWFyY2hJbmZvLm1hdGNoV2hvbGVXb3JkXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAoY2xpY2spPVwib25TZWFyY2hGaWx0ZXIoJ21hdGNoV2hvbGVXb3JkJylcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICAgICAgICAgICAgICAgICAgPGJ1dHRvblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGtlbmRvQnV0dG9uXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsbE1vZGU9XCJmbGF0XCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpY29uPVwicmVndWxhci1leHByZXNzaW9uXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBbc3ZnSWNvbl09XCJyZWd1bGFyRXhwcmVzc2lvbkljb25cIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFt0aXRsZV09XCJnZXRMb2NhbGVNZXNzYWdlKCdVc2VSZWdleFRpdGxlJylcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtzZWxlY3RlZF09XCJzZWFyY2hJbmZvLnVzZVJlZ3VsYXJFeHByZXNzaW9uc1wiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKGNsaWNrKT1cIm9uU2VhcmNoRmlsdGVyKCd1c2VSZWd1bGFyRXhwcmVzc2lvbnMnKVwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgIDwvZGl2PlxuXG4gICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cInRydi1zZWFyY2gtZGlhbG9nLXJlc3VsdHMgay1oc3RhY2sgay1nYXAtMyBrLWFsaWduLWl0ZW1zLWNlbnRlciBrLW10LTMgay1tYi0yXCI+XG4gICAgICAgICAgICAgICAgICAgIDxzcGFuICpuZ0lmPVwic2VhcmNoUmVzdWx0cy5sZW5ndGggPiAwXCIgY2xhc3M9XCJ0cnYtc2VhcmNoLWRpYWxvZy1yZXN1bHRzLWxhYmVsXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICBSZXN1bHQge3sgbGlzdEJveC5zZWxlY3RlZEluZGV4ICsgMX19IG9mIHt7c2VhcmNoUmVzdWx0cy5sZW5ndGggfX1cbiAgICAgICAgICAgICAgICAgICAgPC9zcGFuPlxuICAgICAgICAgICAgICAgICAgICA8c3BhbiAqbmdJZj1cInNlYXJjaFJlc3VsdHMubGVuZ3RoID09PSAwXCIgY2xhc3M9XCJ0cnYtc2VhcmNoLWRpYWxvZy1yZXN1bHRzLWxhYmVsXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICB7eyBnZXRMb2NhbGVNZXNzYWdlKCdOb1Jlc3VsdHNMYWJlbCcpIH19XG4gICAgICAgICAgICAgICAgICAgIDwvc3Bhbj5cbiAgICAgICAgICAgICAgICAgICAgPGtlbmRvLWJ1dHRvbmdyb3VwPlxuICAgICAgICAgICAgICAgICAgICAgICAgPGJ1dHRvblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGtlbmRvQnV0dG9uXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsbE1vZGU9XCJmbGF0XCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpY29uPVwiY2hldnJvbi11cFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgW3N2Z0ljb25dPVwiY2hldnJvblVwSWNvblwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgW3RpdGxlXT1cImdldExvY2FsZU1lc3NhZ2UoJ05hdmlnYXRlVXBUaXRsZScpXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAoY2xpY2spPVwib25OYXZpZ2F0ZUJ1dHRvbnMoJ3VwJylcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtkaXNhYmxlZF09XCJzZWxlY3RlZEluZGV4IDw9IDBcIj5cbiAgICAgICAgICAgICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgICAgICAgICAgIDxidXR0b25cbiAgICAgICAgICAgICAgICAgICAgICAgIGtlbmRvQnV0dG9uXG4gICAgICAgICAgICAgICAgICAgICAgICBmaWxsTW9kZT1cImZsYXRcIlxuICAgICAgICAgICAgICAgICAgICAgICAgaWNvbj1cImNoZXZyb24tZG93blwiXG4gICAgICAgICAgICAgICAgICAgICAgICBbc3ZnSWNvbl09XCJjaGV2cm9uRG93bkljb25cIlxuICAgICAgICAgICAgICAgICAgICAgICAgW3RpdGxlXT1cImdldExvY2FsZU1lc3NhZ2UoJ05hdmlnYXRlRG93blRpdGxlJylcIlxuICAgICAgICAgICAgICAgICAgICAgICAgKGNsaWNrKT1cIm9uTmF2aWdhdGVCdXR0b25zKCdkb3duJyk7XCJcbiAgICAgICAgICAgICAgICAgICAgICAgIFtkaXNhYmxlZF09XCJzZWxlY3RlZEluZGV4ICsgMSA+PSBzZWFyY2hSZXN1bHRzLmxlbmd0aFwiPlxuICAgICAgICAgICAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgICAgICAgICAgICAgPC9rZW5kby1idXR0b25ncm91cD5cbiAgICAgICAgICAgICAgICA8L2Rpdj5cblxuICAgICAgICAgICAgICAgIDxrZW5kby1saXN0Ym94XG4gICAgICAgICAgICAgICAgICAgICNsaXN0Qm94XG4gICAgICAgICAgICAgICAgICAgIFtzdHlsZS53aWR0aC4lXT1cIjEwMFwiXG4gICAgICAgICAgICAgICAgICAgIFtkYXRhXT1cInNlYXJjaFJlc3VsdHNcIlxuICAgICAgICAgICAgICAgICAgICBbdG9vbGJhcl09XCJmYWxzZVwiXG4gICAgICAgICAgICAgICAgICAgIChzZWxlY3Rpb25DaGFuZ2UpPVwib25TZWxlY3Rpb25DaGFuZ2UoJGV2ZW50KVwiXG4gICAgICAgICAgICAgICAgPlxuICAgICAgICAgICAgICAgICAgICA8bmctdGVtcGxhdGUga2VuZG9MaXN0Qm94SXRlbVRlbXBsYXRlIGxldC1kYXRhSXRlbT5cbiAgICAgICAgICAgICAgICAgICAgICAgIDxkaXZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBbYXR0ci5kYXRhLXVpZF09XCJkYXRhSXRlbS5pZFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3M9XCJ0cnYtc2VhcmNoLWRpYWxvZy1yZXN1bHRzLXJvdyBrLWxpc3R2aWV3LWl0ZW0gay1zZWxlY3RlZFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcm9sZT1cIm9wdGlvblwiXG4gICAgICAgICAgICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJrLXNlYXJjaC1kaWFsb2ctcmVzdWx0LWRlc2NcIj57e2RhdGFJdGVtLmRlc2NyaXB0aW9ufX08L3NwYW4+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJ0cnYtc2VhcmNoLWRpYWxvZy1yZXN1bHRzLXBhZ2VTcGFuXCI+cGFnZSB7e2RhdGFJdGVtLnBhZ2V9fTwvc3Bhbj5cbiAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgICAgICA8L25nLXRlbXBsYXRlPlxuICAgICAgICAgICAgICAgIDwva2VuZG8tbGlzdGJveD5cbiAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICA8L2tlbmRvLXdpbmRvdz5cbiAgICBgLFxuICAgIHN0eWxlczogW2BcbiAgICAgICAgIC5rLXdpbmRvdy1jb250ZW50IC5rLWxpc3Rib3gge1xuICAgICAgICAgICAgb3ZlcmZsb3c6IGhpZGRlbjtcbiAgICAgICAgICAgIHBvc2l0aW9uOiByZWxhdGl2ZTtcbiAgICAgICAgICAgIGZsZXgtZ3JvdzogMTtcbiAgICAgICAgICAgIGhlaWdodDogYXV0bztcbiAgICAgICAgfVxuXG4gICAgICAgIC5rLXdpbmRvdy1jb250ZW50IC5rLWxpc3Qge1xuICAgICAgICAgICAgbWF4LWhlaWdodDogMTAwJTtcbiAgICAgICAgfVxuXG4gICAgICAgIC50cnYtc2VhcmNoIHtcbiAgICAgICAgICAgIG1heC1oZWlnaHQ6IDcwMHB4O1xuICAgICAgICB9XG5cbiAgICAgICAgLmstbGlzdHZpZXctaXRlbSAuay1zZWFyY2gtZGlhbG9nLXJlc3VsdC1kZXNjIHtcbiAgICAgICAgICAgIGZsZXg6IDE7XG4gICAgICAgICAgICBtYXJnaW4tcmlnaHQ6IDFlbTtcbiAgICAgICAgfVxuXG4gICAgICAgIC5rLWxpc3R2aWV3LWl0ZW0udHJ2LXNlYXJjaC1kaWFsb2ctcmVzdWx0cy1yb3cge1xuICAgICAgICAgICAgd2lkdGg6IDEwMCU7XG4gICAgICAgICAgICBkaXNwbGF5OiBmbGV4O1xuICAgICAgICAgICAganVzdGlmeS1jb250ZW50OiBzcGFjZS1iZXR3ZWVuO1xuICAgICAgICB9XG4gICAgYF0sXG4gICAgZW5jYXBzdWxhdGlvbjogVmlld0VuY2Fwc3VsYXRpb24uTm9uZVxufSlcbmV4cG9ydCBjbGFzcyBTZWFyY2hDb21wb25lbnQgaW1wbGVtZW50cyBPbkluaXQsIEFmdGVyVmlld0luaXQsIE9uRGVzdHJveSB7XG4gICAgQElucHV0KCkgc2VhcmNoVGVybXM6IHN0cmluZ1tdO1xuXG4gICAgQFZpZXdDaGlsZCgnbGlzdEJveCcpIHB1YmxpYyBsaXN0Ym94ITogTGlzdEJveENvbXBvbmVudDtcbiAgICBAVmlld0NoaWxkKCdjb21ib0JveCcpIHB1YmxpYyBjb21ib0JveCE6IENvbWJvQm94Q29tcG9uZW50O1xuXG4gICAgcHVibGljIGNoZXZyb25VcEljb246IFNWR0ljb24gPSBjaGV2cm9uVXBJY29uO1xuICAgIHB1YmxpYyB3aG9sZVdvcmRJY29uOiBTVkdJY29uID0gd2hvbGVXb3JkSWNvbjtcbiAgICBwdWJsaWMgY2hldnJvbkRvd25JY29uOiBTVkdJY29uID0gY2hldnJvbkRvd25JY29uO1xuICAgIHB1YmxpYyBjb252ZXJ0VG9Mb3dlckNhc2VJY29uOiBTVkdJY29uID0gY29udmVydExvd2VyY2FzZUljb247XG4gICAgcHVibGljIHJlZ3VsYXJFeHByZXNzaW9uSWNvbjogU1ZHSWNvbiA9IHJlZ3VsYXJFeHByZXNzaW9uSWNvbjtcblxuICAgIHB1YmxpYyB3aW5kb3dUb3A6IG51bWJlciA9IDMwO1xuICAgIHB1YmxpYyB3aW5kb3dMZWZ0ITogbnVtYmVyO1xuICAgIHB1YmxpYyB3aW5kb3dXaWR0aCE6IG51bWJlcjtcbiAgICBwdWJsaWMgd2luZG93SGVpZ2h0ITogbnVtYmVyO1xuXG4gICAgcHVibGljIHNlYXJjaFJlc3VsdHM6IFNlYXJjaFJlc3VsdFtdID0gW107XG4gICAgcHVibGljIGlzQ29tYm9ib3hPcGVuOiBib29sZWFuID0gZmFsc2U7XG4gICAgcHVibGljIHNlYXJjaFRleHQ6IHN0cmluZyA9ICcnO1xuICAgIHB1YmxpYyBvcGVuZWQgPSB0cnVlO1xuICAgIHB1YmxpYyBzZWxlY3RlZEluZGV4OiBudW1iZXIgPSAwO1xuXG4gICAgcHVibGljIHNlYXJjaEluZm86IFNlYXJjaEluZm8gPSB7XG4gICAgICAgIHNlYXJjaFRva2VuOiAnJyxcbiAgICAgICAgbWF0Y2hDYXNlOiBmYWxzZSxcbiAgICAgICAgbWF0Y2hXaG9sZVdvcmQ6IGZhbHNlLFxuICAgICAgICB1c2VSZWd1bGFyRXhwcmVzc2lvbnM6IGZhbHNlXG4gICAgfVxuXG4gICAgcHJpdmF0ZSBzdWJzOiBTdWJzY3JpcHRpb24gPSBuZXcgU3Vic2NyaXB0aW9uKCk7XG5cbiAgICBwdWJsaWMgY29uc3RydWN0b3IoXG4gICAgICAgIHByaXZhdGUgbmdab25lOiBOZ1pvbmUsXG4gICAgICAgIHB1YmxpYyBzZXJ2aWNlOiBSZXBvcnRpbmdBbmd1bGFyVmlld2VyU2VydmljZSkge31cblxuICAgIHB1YmxpYyBuZ09uSW5pdCgpOiB2b2lkIHtcbiAgICAgICAgY29uc3QgcmVwb3J0RWxlbVdpZHRoID0gdGhpcy5zZXJ2aWNlLnJlcG9ydFdpZHRoO1xuXG4gICAgICAgIHRoaXMud2luZG93SGVpZ2h0ID0gdGhpcy5zZXJ2aWNlLndpbmRvd0hlaWdodDtcbiAgICAgICAgdGhpcy53aW5kb3dXaWR0aCA9IHRoaXMuc2VydmljZS53aW5kb3dXaWR0aDtcbiAgICAgICAgdGhpcy53aW5kb3dMZWZ0ID0gcmVwb3J0RWxlbVdpZHRoIC0gKHRoaXMud2luZG93V2lkdGggKyA0MCk7XG4gICAgfVxuXG4gICAgcHVibGljIG5nQWZ0ZXJWaWV3SW5pdCgpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5zZXJ2aWNlLnNlYXJjaE1hbmFnZXI/Lm9uKCdzZWFyY2hDb21wbGV0ZScsIChyZXN1bHRzOiBTZWFyY2hSZXN1bHRbXSkgPT4gdGhpcy5vblNlYXJjaENvbXBsZXRlKHJlc3VsdHMpKTtcblxuICAgICAgICB0aGlzLm5nWm9uZS5vblN0YWJsZS5waXBlKHRha2UoMSkpLnN1YnNjcmliZShfID0+IHRoaXMuY29tYm9Cb3g/LmZvY3VzKCkpO1xuXG4gICAgICAgIGNvbnN0IGNvbWJvYm94ID0gdGhpcy5jb21ib0JveD8ud3JhcHBlcj8ubmF0aXZlRWxlbWVudDtcbiAgICAgICAgdGhpcy5zdWJzLmFkZChjb21ib2JveC5hZGRFdmVudExpc3RlbmVyKCdrZXlkb3duJywgKGV2ZW50OiBhbnkpID0+IHRoaXMub25BcnJvd0V2ZW50KGV2ZW50KSwgdHJ1ZSkpO1xuICAgIH1cblxuICAgIHB1YmxpYyBuZ09uRGVzdHJveSgpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5zdWJzLnVuc3Vic2NyaWJlKCk7XG4gICAgfVxuXG4gICAgcHVibGljIHRvZ2dsZShpc09wZW5lZDogYm9vbGVhbik6IHZvaWQge1xuICAgICAgICB0aGlzLnNlcnZpY2UuaXNTZWFyY2hXaW5kb3dPcGVuID0gaXNPcGVuZWQ7XG4gICAgICAgIHRoaXMuc2VhcmNoUmVzdWx0cyA9IFtdO1xuICAgICAgICB0aGlzLnNlcnZpY2Uuc2VhcmNoTWFuYWdlci5jbG9zZVNlYXJjaCgpO1xuICAgIH1cblxuICAgIHB1YmxpYyBoYW5kbGVGaWx0ZXIodmFsdWU6IGFueSkge1xuICAgICAgICAgaWYodmFsdWUgPT09IFwiXCIpIHtcbiAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5zZWFyY2hUZXh0ID0gdmFsdWU7XG4gICAgICAgIHRoaXMuc2VhcmNoKHZhbHVlLCB0cnVlKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgb25XaWR0aENoYW5nZSh3aWR0aDogbnVtYmVyKTogdm9pZCB7XG4gICAgICAgIHRoaXMuc2VydmljZS53aW5kb3dXaWR0aCA9IHdpZHRoO1xuICAgIH1cblxuICAgIHB1YmxpYyBvbkhlaWdodENoYW5nZShoZWlnaHQ6IG51bWJlcik6IHZvaWQge1xuICAgICAgICB0aGlzLnNlcnZpY2Uud2luZG93SGVpZ2h0ID0gaGVpZ2h0O1xuICAgIH1cblxuICAgIHB1YmxpYyBvbkJsdXIoKSB7XG4gICAgICAgIHRoaXMuc2VhcmNoVGV4dCA9IHRoaXMuY29tYm9Cb3gudGV4dCA9IHRoaXMuY29tYm9Cb3g/LnNlYXJjaGJhci52YWx1ZTtcbiAgICB9XG5cbiAgICBwdWJsaWMgc2VhcmNoKHRleHQ6IHN0cmluZywgaXNUZXh0RmlsdGVyOiBib29sZWFuID0gZmFsc2UpOiB2b2lkIHtcbiAgICAgICAgaWYgKHR5cGVvZiB0ZXh0ICE9PSAnc3RyaW5nJyAmJiAhaXNUZXh0RmlsdGVyKSByZXR1cm47XG5cbiAgICAgICAgaWYgKHRleHQgJiYgdGhpcy5zZWFyY2hUZXJtcy5pbmRleE9mKHRleHQpID09PSAtMSkge1xuICAgICAgICAgICAgdGhpcy5zZWFyY2hUZXJtcy5wdXNoKHRleHQpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHRoaXMuc2VhcmNoSW5mby5zZWFyY2hUb2tlbiAhPT0gdGV4dCkge1xuICAgICAgICAgICAgdGhpcy5zZWxlY3RlZEluZGV4ID0gMDtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuY29tYm9Cb3gudmFsdWUgPSB0ZXh0O1xuICAgICAgICB0aGlzLmNvbWJvQm94LnNlYXJjaEJhckNoYW5nZSh0ZXh0KTtcbiAgICAgICAgdGhpcy5zZWFyY2hJbmZvLnNlYXJjaFRva2VuID0gdGV4dDtcblxuICAgICAgICB0aGlzLnNlcnZpY2Uuc2VhcmNoTWFuYWdlcj8uc2VhcmNoKHRoaXMuc2VhcmNoSW5mbyk7XG5cbiAgICAgICAgdGhpcy5uZ1pvbmUub25TdGFibGUucGlwZSh0YWtlKDEpKS5zdWJzY3JpYmUoXyA9PiB0aGlzLmNvbWJvQm94Py5mb2N1cygpKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgb25TZWFyY2hGaWx0ZXIoZmlsdGVyTmFtZTogJ21hdGNoQ2FzZScgfCAnbWF0Y2hXaG9sZVdvcmQnIHwgJ3VzZVJlZ3VsYXJFeHByZXNzaW9ucycpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5zZWxlY3RlZEluZGV4ID0gMDtcbiAgICAgICAgdGhpcy5zZWFyY2hJbmZvW2ZpbHRlck5hbWVdID0gIXRoaXMuc2VhcmNoSW5mb1tmaWx0ZXJOYW1lXTtcblxuICAgICAgICB0aGlzLnNlYXJjaCh0aGlzLnNlYXJjaEluZm8uc2VhcmNoVG9rZW4pO1xuICAgIH1cblxuICAgIHB1YmxpYyBvblNlbGVjdGlvbkNoYW5nZShpdGVtOiBMaXN0Qm94U2VsZWN0aW9uRXZlbnQpOiB2b2lkIHtcbiAgICAgICAgY29uc3Qgc2VhcmNoUmVzdWx0SXRlbTogU2VhcmNoUmVzdWx0ID0gdGhpcy5zZWFyY2hSZXN1bHRzW2l0ZW0uaW5kZXhdO1xuICAgICAgICB0aGlzLnNlcnZpY2Uuc2VhcmNoTWFuYWdlcj8uaGlnaGxpZ2h0U2VhcmNoSXRlbShzZWFyY2hSZXN1bHRJdGVtKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgb3BlbihldmVudDogYW55LCBjb21ib0JveDogQ29tYm9Cb3hDb21wb25lbnQpOiB2b2lkIHtcbiAgICAgICAgaWYgKGV2ZW50LnRhcmdldC5jbG9zZXN0KCdidXR0b24nKSAmJiAhdGhpcy5pc0NvbWJvYm94T3Blbikge1xuICAgICAgICAgICAgdGhpcy5pc0NvbWJvYm94T3BlbiA9IHRydWU7XG4gICAgICAgICAgICBjb21ib0JveC50b2dnbGUodHJ1ZSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwdWJsaWMgb25DbG9zZSgpOiB2b2lkIHtcbiAgICAgICAgc2V0VGltZW91dCgoKSA9PiB0aGlzLmlzQ29tYm9ib3hPcGVuID0gZmFsc2UgKVxuICAgIH1cblxuICAgIHB1YmxpYyBvbk5hdmlnYXRlQnV0dG9ucyhkaXJlY3Rpb246ICd1cCcgfCAnZG93bicsIHNvdXJjZVRhcmdldDogJ2NvbWJvYm94TmF2JyB8ICdsaXN0Ym94TmF2JyA9ICdsaXN0Ym94TmF2Jyk6IHZvaWQge1xuICAgICAgICBjb25zdCB0b3BSZWFjaGVkID0gZGlyZWN0aW9uID09PSAndXAnICYmIHRoaXMuc2VsZWN0ZWRJbmRleCA8PSAwO1xuICAgICAgICBjb25zdCBib3R0b21SZWFjaGVkID0gZGlyZWN0aW9uID09PSAnZG93bicgJiYgdGhpcy5zZWxlY3RlZEluZGV4ID49IHRoaXMuc2VhcmNoUmVzdWx0cy5sZW5ndGggLSAxO1xuXG4gICAgICAgIGlmICh0b3BSZWFjaGVkIHx8IGJvdHRvbVJlYWNoZWQpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuc2VsZWN0ZWRJbmRleCA9IHRoaXMuc2VsZWN0ZWRJbmRleCArIChkaXJlY3Rpb24gPT09ICd1cCcgPyAtMSA6IDEpO1xuXG4gICAgICAgIHRoaXMubGlzdGJveD8uc2VsZWN0aW9uU2VydmljZS5zZWxlY3QodGhpcy5zZWxlY3RlZEluZGV4KTtcbiAgICB9XG5cbiAgICBwdWJsaWMgZ2V0TG9jYWxlTWVzc2FnZShtZXNzYWdlOiBzdHJpbmcpOiBzdHJpbmcge1xuICAgICAgICByZXR1cm4gdGhpcy5zZXJ2aWNlLm9wdGlvbnMubWVzc2FnZXNbYFJlcG9ydFZpZXdlcl9TZWFyY2hEaWFsb2cke21lc3NhZ2V9YF07XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBvbkFycm93RXZlbnQoZXZlbnQ6IGFueSk6IHZvaWQge1xuICAgICAgICBldmVudC5zdG9wSW1tZWRpYXRlUHJvcGFnYXRpb24oKTtcbiAgICAgICAgY29uc3Qgc2VhcmNoUmVzdWx0SXRlbXMgPSB0aGlzLnNlYXJjaFJlc3VsdHMubGVuZ3RoO1xuXG4gICAgICAgIGlmIChzZWFyY2hSZXN1bHRJdGVtcyA+IDApIHtcbiAgICAgICAgICAgIGNvbnN0IGlzQXJyb3dVcCA9IGV2ZW50LmtleSA9PT0gJ0Fycm93VXAnO1xuICAgICAgICAgICAgY29uc3QgaXNBcnJvd0Rvd24gPSBldmVudC5rZXkgPT09ICdBcnJvd0Rvd24nXG5cbiAgICAgICAgICAgIGlmIChpc0Fycm93VXAgfHwgaXNBcnJvd0Rvd24pIHtcbiAgICAgICAgICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXG4gICAgICAgICAgICAgICAgY29uc3QgZGlyOiAndXAnIHwgJ2Rvd24nID0gaXNBcnJvd1VwID8gJ3VwJyA6ICdkb3duJztcbiAgICAgICAgICAgICAgICB0aGlzLm9uTmF2aWdhdGVCdXR0b25zKGRpciwgJ2NvbWJvYm94TmF2Jyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGNvbnN0IGN1cnJlbnRMaXN0Ym94SXRlbSA9IHRoaXMubGlzdGJveC5saXN0Ym94SXRlbXMudG9BcnJheSgpW3RoaXMuc2VsZWN0ZWRJbmRleF0ubmF0aXZlRWxlbWVudDtcbiAgICAgICAgICAgIGN1cnJlbnRMaXN0Ym94SXRlbT8uZm9jdXMoKTtcblxuICAgICAgICAgICAgdGhpcy5uZ1pvbmUub25TdGFibGUucGlwZSh0YWtlKDEpKS5zdWJzY3JpYmUoKCkgPT4gdGhpcy5jb21ib0JveD8uZm9jdXMoKSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIG9uU2VhcmNoQ29tcGxldGUocmVzdWx0czogU2VhcmNoUmVzdWx0W10pOiB2b2lkIHtcbiAgICAgICAgbGV0IHRvdGFsQ291bnQgPSByZXN1bHRzLmxlbmd0aDtcblxuICAgICAgICBpZiAodG90YWxDb3VudCA+IDI1MCkge1xuICAgICAgICAgICAgcmVzdWx0cyA9IHJlc3VsdHMuc2xpY2UoMCwgMjUwKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuc2VhcmNoUmVzdWx0cyA9IHJlc3VsdHM7XG5cbiAgICAgICAgaWYgKHJlc3VsdHMpIHtcbiAgICAgICAgICAgIHRoaXMubGlzdGJveD8uc2VsZWN0SXRlbSgwKTtcbiAgICAgICAgfVxuICAgICAgICBcbiAgICAgICAgaWYgKHRvdGFsQ291bnQgPiAwKSB7XG4gICAgICAgICAgICB0aGlzLnNlcnZpY2Uuc2VhcmNoTWFuYWdlcj8ubmF2aWdhdGVUb1BhZ2UocmVzdWx0c1swXSk7XG4gICAgICAgIH1cbiAgICB9XG59XG4iXX0=