UNPKG

@nova-ui/dashboards

Version:

Nova Dashboards is a framework designed to provide feature developers with a common solution for presenting data coming from various sources within a single view, as well as a set of predefined widget visualizations that are 100% configuration-driven and

154 lines 33.7 kB
// © 2022 SolarWinds Worldwide, LLC. All rights reserved. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to // deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. import { ChangeDetectionStrategy, ChangeDetectorRef, Component, EventEmitter, Inject, Input, Output, } from "@angular/core"; import { FormBuilder, Validators, } from "@angular/forms"; import _difference from "lodash/difference"; import { Subject } from "rxjs"; import { takeUntil } from "rxjs/operators"; import { EventBus } from "@nova-ui/bits"; import { PIZZAGNA_EVENT_BUS, } from "../../../../../types"; import { DATA_SOURCE_CREATED } from "../../../../types"; import * as i0 from "@angular/core"; import * as i1 from "@angular/forms"; import * as i2 from "@angular/common"; import * as i3 from "@nova-ui/bits"; import * as i4 from "../../../widget-editor-accordion/widget-editor-accordion.component"; import * as i5 from "../../../widget-editor-accordion/widget-editor-accordion-header/widget-editor-accordion-header.component"; import * as i6 from "../../../../pipe/widget-editor-accordion-form-state.pipe"; // Remember to declare this class in the parent module export class GroupingConfigurationComponent { static { this.lateLoadKey = "DrilldownConfiguratorComponent"; } constructor(changeDetector, formBuilder, eventBus) { this.changeDetector = changeDetector; this.formBuilder = formBuilder; this.eventBus = eventBus; this.formReady = new EventEmitter(); this.form = this.formBuilder.group({ groups: [], groupBy: this.formBuilder.array([]), drillstate: [undefined], }); this.destroy$ = new Subject(); } get getGroupByControl() { return this.form.get("groupBy"); } get getDrillStateControl() { return this.form.get("drillstate"); } get getGroupsControl() { return this.form.get("groups"); } ngOnInit() { this.eventBus .getStream(DATA_SOURCE_CREATED) .pipe(takeUntil(this.destroy$)) .subscribe((provider) => this.onDataSourceCreated(provider)); this.getGroupByControl.valueChanges .pipe(takeUntil(this.destroy$)) .subscribe(() => this.fillGroupsOptions()); this.fillGroupsOptions(); this.formReady.emit(this.form); } ngOnChanges(changes) { if (changes.groups) { this.getGroupsControl.setValue(changes.groups.currentValue); } if (changes.groupBy && !changes.groupBy.firstChange) { this.getGroupByControl.clear(); this.groupBy.forEach((group) => this.getGroupByControl.push(this.createControl(group))); this.fillGroupsOptions(); } } createControl(value) { return this.formBuilder.control(value || "", Validators.required); } addGrouping() { const control = this.createControl(); this.getGroupByControl.push(control); this.fillGroupsOptions(); const lastControlIndex = this.getGroupByControl.controls.length - 1; control.setValue(this.selectData[lastControlIndex][0]); } removeRule(index) { this.getGroupByControl.removeAt(index); this.fillGroupsOptions(); } isAddRestricted() { return this.selectData.some((i) => i.length === 1); } getSubtitle() { const subtitle = this.getGroupByControl.controls .map((control, index) => `${index === 0 ? "By" : "then"} ${control.value}`) .join(", "); return this.getGroupByControl?.value.length === 0 ? $localize `No groups` : $localize `${subtitle}`; } ngOnDestroy() { this.destroy$.next(); this.destroy$.complete(); } onDataSourceCreated(provider) { provider?.payload?.dataFieldsConfig?.dataFields$ ?.pipe(takeUntil(this.destroy$)) .subscribe((dataFields) => { if (dataFields) { const dataFieldIds = dataFields.map((field) => field.id); const dataDiff = _difference(this.groups, dataFieldIds); if (dataDiff.length || !this.groups?.length) { this.groups = dataFieldIds; this.getGroupsControl.setValue(dataFieldIds); this.getGroupByControl.clear(); this.getDrillStateControl.setValue([]); this.fillGroupsOptions(); } } }); } fillGroupsOptions() { this.selectData = []; const controlValue = this.getGroupByControl.value; this.getGroupByControl.controls.forEach((value, index) => { this.selectData[index] = []; const diff = _difference(this.groups, controlValue); if (controlValue[index]) { this.selectData[index].push(controlValue[index]); } this.selectData[index] = [...this.selectData[index], ...diff]; }); } /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: GroupingConfigurationComponent, deps: [{ token: i0.ChangeDetectorRef }, { token: i1.FormBuilder }, { token: PIZZAGNA_EVENT_BUS }], target: i0.ɵɵFactoryTarget.Component }); } /** @nocollapse */ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: GroupingConfigurationComponent, selector: "nui-grouping-configuration", inputs: { groups: "groups", groupBy: "groupBy" }, outputs: { formReady: "formReady" }, usesOnChanges: true, ngImport: i0, template: "<nui-widget-editor-accordion\n [formGroup]=\"form\"\n [state]=\"form | nuiWidgetEditorAccordionFormState | async\"\n>\n <nui-widget-editor-accordion-header\n [headerIcon]=\"'tag'\"\n [subtitle]=\"getSubtitle()\"\n headerTitle=\"Grouping\"\n />\n <div\n class=\"grouping-configuration__accordion-content\"\n formArrayName=\"groupBy\"\n >\n <ng-container\n *ngFor=\"let group of getGroupByControl.controls; index as i\"\n >\n <label *ngIf=\"i !== 0\" class=\"d-flex nui-text-secondary mb-1\" i18n\n >Then</label\n >\n <label *ngIf=\"i === 0\" class=\"d-flex nui-text-panel mb-2\" i18n\n >Group by</label\n >\n <div class=\"d-flex flex-row flex-grow-1 mb-4\">\n <nui-form-field [control]=\"group\" class=\"d-flex flex-grow-1\">\n <nui-select-v2\n placeholder=\"Select Item\"\n i18n-placeholder\n [formControlName]=\"i\"\n >\n <nui-select-v2-option\n *ngFor=\"let item of selectData[i]\"\n [value]=\"item\"\n >\n {{ item }}\n </nui-select-v2-option>\n </nui-select-v2>\n </nui-form-field>\n <div class=\"justify-content-center\">\n <button\n nui-button\n icon=\"delete\"\n displayStyle=\"action\"\n type=\"button\"\n (click)=\"removeRule(i)\"\n ></button>\n </div>\n </div>\n </ng-container>\n <button\n nui-button\n icon=\"add\"\n displayStyle=\"action\"\n type=\"button\"\n i18n\n *ngIf=\"!this.isAddRestricted()\"\n (click)=\"addGrouping()\"\n >\n Add another level\n </button>\n </div>\n</nui-widget-editor-accordion>\n", styles: [".grouping-configuration__accordion-content{padding:15px 15px 15px 46px}\n"], dependencies: [{ kind: "directive", type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i1.FormArrayName, selector: "[formArrayName]", inputs: ["formArrayName"] }, { kind: "component", type: i3.FormFieldComponent, selector: "nui-form-field", inputs: ["control", "caption", "info", "infoTemplate", "hint", "hintTemplate", "customBoxWidth", "showOptionalText"] }, { kind: "component", type: i3.ButtonComponent, selector: "[nui-button]", inputs: ["displayStyle", "icon", "iconColor", "iconRight", "isBusy", "isEmpty", "ariaLabel", "isRepeat", "size"] }, { kind: "component", type: i3.SelectV2Component, selector: "nui-select-v2", inputs: ["displayValueTemplate"] }, { kind: "component", type: i3.SelectV2OptionComponent, selector: "nui-select-v2-option", inputs: ["value", "index", "displayValueContext", "outfiltered"] }, { kind: "component", type: i4.WidgetEditorAccordionComponent, selector: "nui-widget-editor-accordion", inputs: ["showOpenStateIcon", "state"], outputs: ["openToggle"] }, { kind: "component", type: i5.WidgetEditorAccordionHeaderComponent, selector: "nui-widget-editor-accordion-header", inputs: ["headerIcon", "iconColor", "subtitle", "headerTitle"] }, { kind: "pipe", type: i2.AsyncPipe, name: "async" }, { kind: "pipe", type: i6.WidgetEditorAccordionFormStatePipe, name: "nuiWidgetEditorAccordionFormState" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: GroupingConfigurationComponent, decorators: [{ type: Component, args: [{ selector: "nui-grouping-configuration", changeDetection: ChangeDetectionStrategy.OnPush, template: "<nui-widget-editor-accordion\n [formGroup]=\"form\"\n [state]=\"form | nuiWidgetEditorAccordionFormState | async\"\n>\n <nui-widget-editor-accordion-header\n [headerIcon]=\"'tag'\"\n [subtitle]=\"getSubtitle()\"\n headerTitle=\"Grouping\"\n />\n <div\n class=\"grouping-configuration__accordion-content\"\n formArrayName=\"groupBy\"\n >\n <ng-container\n *ngFor=\"let group of getGroupByControl.controls; index as i\"\n >\n <label *ngIf=\"i !== 0\" class=\"d-flex nui-text-secondary mb-1\" i18n\n >Then</label\n >\n <label *ngIf=\"i === 0\" class=\"d-flex nui-text-panel mb-2\" i18n\n >Group by</label\n >\n <div class=\"d-flex flex-row flex-grow-1 mb-4\">\n <nui-form-field [control]=\"group\" class=\"d-flex flex-grow-1\">\n <nui-select-v2\n placeholder=\"Select Item\"\n i18n-placeholder\n [formControlName]=\"i\"\n >\n <nui-select-v2-option\n *ngFor=\"let item of selectData[i]\"\n [value]=\"item\"\n >\n {{ item }}\n </nui-select-v2-option>\n </nui-select-v2>\n </nui-form-field>\n <div class=\"justify-content-center\">\n <button\n nui-button\n icon=\"delete\"\n displayStyle=\"action\"\n type=\"button\"\n (click)=\"removeRule(i)\"\n ></button>\n </div>\n </div>\n </ng-container>\n <button\n nui-button\n icon=\"add\"\n displayStyle=\"action\"\n type=\"button\"\n i18n\n *ngIf=\"!this.isAddRestricted()\"\n (click)=\"addGrouping()\"\n >\n Add another level\n </button>\n </div>\n</nui-widget-editor-accordion>\n", styles: [".grouping-configuration__accordion-content{padding:15px 15px 15px 46px}\n"] }] }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: i1.FormBuilder }, { type: i3.EventBus, decorators: [{ type: Inject, args: [PIZZAGNA_EVENT_BUS] }] }], propDecorators: { groups: [{ type: Input }], groupBy: [{ type: Input }], formReady: [{ type: Output }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ3JvdXBpbmctY29uZmlndXJhdGlvbi5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi8uLi9zcmMvbGliL2NvbmZpZ3VyYXRvci9jb21wb25lbnRzL3dpZGdldHMvZHJpbGxkb3duL2dyb3VwaW5nLWNvbmZpZ3VyYXRpb24vZ3JvdXBpbmctY29uZmlndXJhdGlvbi5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi8uLi8uLi8uLi8uLi9zcmMvbGliL2NvbmZpZ3VyYXRvci9jb21wb25lbnRzL3dpZGdldHMvZHJpbGxkb3duL2dyb3VwaW5nLWNvbmZpZ3VyYXRpb24vZ3JvdXBpbmctY29uZmlndXJhdGlvbi5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSx5REFBeUQ7QUFDekQsRUFBRTtBQUNGLCtFQUErRTtBQUMvRSw0RUFBNEU7QUFDNUUsOEVBQThFO0FBQzlFLCtFQUErRTtBQUMvRSw4RUFBOEU7QUFDOUUsNERBQTREO0FBQzVELEVBQUU7QUFDRiw2RUFBNkU7QUFDN0UsdURBQXVEO0FBQ3ZELEVBQUU7QUFDRiw2RUFBNkU7QUFDN0UsNEVBQTRFO0FBQzVFLCtFQUErRTtBQUMvRSwwRUFBMEU7QUFDMUUsaUZBQWlGO0FBQ2pGLDZFQUE2RTtBQUM3RSxpQkFBaUI7QUFFakIsT0FBTyxFQUNILHVCQUF1QixFQUN2QixpQkFBaUIsRUFDakIsU0FBUyxFQUNULFlBQVksRUFDWixNQUFNLEVBQ04sS0FBSyxFQUlMLE1BQU0sR0FFVCxNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBR0gsV0FBVyxFQUdYLFVBQVUsR0FDYixNQUFNLGdCQUFnQixDQUFDO0FBQ3hCLE9BQU8sV0FBVyxNQUFNLG1CQUFtQixDQUFDO0FBQzVDLE9BQU8sRUFBRSxPQUFPLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDL0IsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBRTNDLE9BQU8sRUFBRSxRQUFRLEVBQW1DLE1BQU0sZUFBZSxDQUFDO0FBRTFFLE9BQU8sRUFHSCxrQkFBa0IsR0FDckIsTUFBTSxzQkFBc0IsQ0FBQztBQUM5QixPQUFPLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSxtQkFBbUIsQ0FBQzs7Ozs7Ozs7QUFjeEQsc0RBQXNEO0FBQ3RELE1BQU0sT0FBTyw4QkFBOEI7YUFHekIsZ0JBQVcsR0FBRyxnQ0FBZ0MsQUFBbkMsQ0FBb0M7SUFnQjdELFlBQ1csY0FBaUMsRUFDaEMsV0FBd0IsRUFDSSxRQUEwQjtRQUZ2RCxtQkFBYyxHQUFkLGNBQWMsQ0FBbUI7UUFDaEMsZ0JBQVcsR0FBWCxXQUFXLENBQWE7UUFDSSxhQUFRLEdBQVIsUUFBUSxDQUFrQjtRQWZ4RCxjQUFTLEdBQUcsSUFBSSxZQUFZLEVBQWEsQ0FBQztRQUU3QyxTQUFJLEdBQWMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxLQUFLLENBQUM7WUFDNUMsTUFBTSxFQUFFLEVBQUU7WUFDVixPQUFPLEVBQUUsSUFBSSxDQUFDLFdBQVcsQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDO1lBQ25DLFVBQVUsRUFBRSxDQUFDLFNBQVMsQ0FBQztTQUMxQixDQUFDLENBQUM7UUFJYyxhQUFRLEdBQUcsSUFBSSxPQUFPLEVBQVEsQ0FBQztJQU03QyxDQUFDO0lBRUosSUFBVyxpQkFBaUI7UUFDeEIsT0FBTyxJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxTQUFTLENBQWMsQ0FBQztJQUNqRCxDQUFDO0lBRUQsSUFBVyxvQkFBb0I7UUFDM0IsT0FBTyxJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxZQUFZLENBQWMsQ0FBQztJQUNwRCxDQUFDO0lBRUQsSUFBVyxnQkFBZ0I7UUFDdkIsT0FBTyxJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxRQUFRLENBQWdCLENBQUM7SUFDbEQsQ0FBQztJQUVNLFFBQVE7UUFDWCxJQUFJLENBQUMsUUFBUTthQUNSLFNBQVMsQ0FBQyxtQkFBbUIsQ0FBQzthQUM5QixJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQzthQUM5QixTQUFTLENBQUMsQ0FBQyxRQUE2QixFQUFFLEVBQUUsQ0FDekMsSUFBSSxDQUFDLG1CQUFtQixDQUFDLFFBQVEsQ0FBQyxDQUNyQyxDQUFDO1FBRU4sSUFBSSxDQUFDLGlCQUFpQixDQUFDLFlBQVk7YUFDOUIsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUM7YUFDOUIsU0FBUyxDQUFDLEdBQUcsRUFBRSxDQUFDLElBQUksQ0FBQyxpQkFBaUIsRUFBRSxDQUFDLENBQUM7UUFFL0MsSUFBSSxDQUFDLGlCQUFpQixFQUFFLENBQUM7UUFFekIsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ25DLENBQUM7SUFFTSxXQUFXLENBQUMsT0FBc0I7UUFDckMsSUFBSSxPQUFPLENBQUMsTUFBTSxFQUFFO1lBQ2hCLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxZQUFZLENBQUMsQ0FBQztTQUMvRDtRQUNELElBQUksT0FBTyxDQUFDLE9BQU8sSUFBSSxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsV0FBVyxFQUFFO1lBQ2pELElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxLQUFLLEVBQUUsQ0FBQztZQUMvQixJQUFJLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQzNCLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUN6RCxDQUFDO1lBQ0YsSUFBSSxDQUFDLGlCQUFpQixFQUFFLENBQUM7U0FDNUI7SUFDTCxDQUFDO0lBRU0sYUFBYSxDQUFDLEtBQWM7UUFDL0IsT0FBTyxJQUFJLENBQUMsV0FBVyxDQUFDLE9BQU8sQ0FBQyxLQUFLLElBQUksRUFBRSxFQUFFLFVBQVUsQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUN0RSxDQUFDO0lBRU0sV0FBVztRQUNkLE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxhQUFhLEVBQUUsQ0FBQztRQUNyQyxJQUFJLENBQUMsaUJBQWlCLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQ3JDLElBQUksQ0FBQyxpQkFBaUIsRUFBRSxDQUFDO1FBQ3pCLE1BQU0sZ0JBQWdCLEdBQUcsSUFBSSxDQUFDLGlCQUFpQixDQUFDLFFBQVEsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDO1FBQ3BFLE9BQU8sQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDM0QsQ0FBQztJQUVNLFVBQVUsQ0FBQyxLQUFhO1FBQzNCLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDdkMsSUFBSSxDQUFDLGlCQUFpQixFQUFFLENBQUM7SUFDN0IsQ0FBQztJQUVNLGVBQWU7UUFDbEIsT0FBTyxJQUFJLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLE1BQU0sS0FBSyxDQUFDLENBQUMsQ0FBQztJQUN2RCxDQUFDO0lBRU0sV0FBVztRQUNkLE1BQU0sUUFBUSxHQUFHLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxRQUFRO2FBQzNDLEdBQUcsQ0FDQSxDQUFDLE9BQXdCLEVBQUUsS0FBYSxFQUFFLEVBQUUsQ0FDeEMsR0FBRyxLQUFLLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLE1BQU0sSUFBSSxPQUFPLENBQUMsS0FBSyxFQUFFLENBQ3hEO2FBQ0EsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO1FBRWhCLE9BQU8sSUFBSSxDQUFDLGlCQUFpQixFQUFFLEtBQUssQ0FBQyxNQUFNLEtBQUssQ0FBQztZQUM3QyxDQUFDLENBQUMsU0FBUyxDQUFBLFdBQVc7WUFDdEIsQ0FBQyxDQUFDLFNBQVMsQ0FBQSxHQUFHLFFBQVEsRUFBRSxDQUFDO0lBQ2pDLENBQUM7SUFFTSxXQUFXO1FBQ2QsSUFBSSxDQUFDLFFBQVEsQ0FBQyxJQUFJLEVBQUUsQ0FBQztRQUNyQixJQUFJLENBQUMsUUFBUSxDQUFDLFFBQVEsRUFBRSxDQUFDO0lBQzdCLENBQUM7SUFFTyxtQkFBbUIsQ0FBQyxRQUE2QjtRQUNyRCxRQUFRLEVBQUUsT0FBTyxFQUFFLGdCQUFnQixFQUFFLFdBQVc7WUFDNUMsRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQzthQUMvQixTQUFTLENBQUMsQ0FBQyxVQUF3QixFQUFFLEVBQUU7WUFDcEMsSUFBSSxVQUFVLEVBQUU7Z0JBQ1osTUFBTSxZQUFZLEdBQUcsVUFBVSxDQUFDLEdBQUcsQ0FDL0IsQ0FBQyxLQUFpQixFQUFFLEVBQUUsQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUNsQyxDQUFDO2dCQUNGLE1BQU0sUUFBUSxHQUFHLFdBQVcsQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLFlBQVksQ0FBQyxDQUFDO2dCQUN4RCxJQUFJLFFBQVEsQ0FBQyxNQUFNLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLE1BQU0sRUFBRTtvQkFDekMsSUFBSSxDQUFDLE1BQU0sR0FBRyxZQUFZLENBQUM7b0JBQzNCLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxRQUFRLENBQUMsWUFBWSxDQUFDLENBQUM7b0JBQzdDLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxLQUFLLEVBQUUsQ0FBQztvQkFDL0IsSUFBSSxDQUFDLG9CQUFvQixDQUFDLFFBQVEsQ0FBQyxFQUFFLENBQUMsQ0FBQztvQkFDdkMsSUFBSSxDQUFDLGlCQUFpQixFQUFFLENBQUM7aUJBQzVCO2FBQ0o7UUFDTCxDQUFDLENBQUMsQ0FBQztJQUNYLENBQUM7SUFFTyxpQkFBaUI7UUFDckIsSUFBSSxDQUFDLFVBQVUsR0FBRyxFQUFFLENBQUM7UUFDckIsTUFBTSxZQUFZLEdBQUcsSUFBSSxDQUFDLGlCQUFpQixDQUFDLEtBQWlCLENBQUM7UUFDOUQsSUFBSSxDQUFDLGlCQUFpQixDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQ25DLENBQUMsS0FBc0IsRUFBRSxLQUFhLEVBQUUsRUFBRTtZQUN0QyxJQUFJLENBQUMsVUFBVSxDQUFDLEtBQUssQ0FBQyxHQUFHLEVBQUUsQ0FBQztZQUM1QixNQUFNLElBQUksR0FBRyxXQUFXLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRSxZQUFZLENBQUMsQ0FBQztZQUNwRCxJQUFJLFlBQVksQ0FBQyxLQUFLLENBQUMsRUFBRTtnQkFDckIsSUFBSSxDQUFDLFVBQVUsQ0FBQyxLQUFLLENBQUMsQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUM7YUFDcEQ7WUFDRCxJQUFJLENBQUMsVUFBVSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsR0FBRyxJQUFJLENBQUMsVUFBVSxDQUFDLEtBQUssQ0FBQyxFQUFFLEdBQUcsSUFBSSxDQUFDLENBQUM7UUFDbEUsQ0FBQyxDQUNKLENBQUM7SUFDTixDQUFDO2tJQTNJUSw4QkFBOEIsOEVBc0IzQixrQkFBa0I7c0hBdEJyQiw4QkFBOEIsOEtDbkUzQywycEVBNkRBOzs0RkRNYSw4QkFBOEI7a0JBYjFDLFNBQVM7K0JBQ0ksNEJBQTRCLG1CQUVyQix1QkFBdUIsQ0FBQyxNQUFNOzswQkFnQzFDLE1BQU07MkJBQUMsa0JBQWtCO3lDQWpCckIsTUFBTTtzQkFBZCxLQUFLO2dCQUNHLE9BQU87c0JBQWYsS0FBSztnQkFDSSxTQUFTO3NCQUFsQixNQUFNIiwic291cmNlc0NvbnRlbnQiOlsiLy8gwqkgMjAyMiBTb2xhcldpbmRzIFdvcmxkd2lkZSwgTExDLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy9cbi8vIFBlcm1pc3Npb24gaXMgaGVyZWJ5IGdyYW50ZWQsIGZyZWUgb2YgY2hhcmdlLCB0byBhbnkgcGVyc29uIG9idGFpbmluZyBhIGNvcHlcbi8vICBvZiB0aGlzIHNvZnR3YXJlIGFuZCBhc3NvY2lhdGVkIGRvY3VtZW50YXRpb24gZmlsZXMgKHRoZSBcIlNvZnR3YXJlXCIpLCB0b1xuLy8gIGRlYWwgaW4gdGhlIFNvZnR3YXJlIHdpdGhvdXQgcmVzdHJpY3Rpb24sIGluY2x1ZGluZyB3aXRob3V0IGxpbWl0YXRpb24gdGhlXG4vLyAgcmlnaHRzIHRvIHVzZSwgY29weSwgbW9kaWZ5LCBtZXJnZSwgcHVibGlzaCwgZGlzdHJpYnV0ZSwgc3VibGljZW5zZSwgYW5kL29yXG4vLyAgc2VsbCBjb3BpZXMgb2YgdGhlIFNvZnR3YXJlLCBhbmQgdG8gcGVybWl0IHBlcnNvbnMgdG8gd2hvbSB0aGUgU29mdHdhcmUgaXNcbi8vICBmdXJuaXNoZWQgdG8gZG8gc28sIHN1YmplY3QgdG8gdGhlIGZvbGxvd2luZyBjb25kaXRpb25zOlxuLy9cbi8vIFRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBlcm1pc3Npb24gbm90aWNlIHNoYWxsIGJlIGluY2x1ZGVkIGluXG4vLyAgYWxsIGNvcGllcyBvciBzdWJzdGFudGlhbCBwb3J0aW9ucyBvZiB0aGUgU29mdHdhcmUuXG4vL1xuLy8gVEhFIFNPRlRXQVJFIElTIFBST1ZJREVEIFwiQVMgSVNcIiwgV0lUSE9VVCBXQVJSQU5UWSBPRiBBTlkgS0lORCwgRVhQUkVTUyBPUlxuLy8gIElNUExJRUQsIElOQ0xVRElORyBCVVQgTk9UIExJTUlURUQgVE8gVEhFIFdBUlJBTlRJRVMgT0YgTUVSQ0hBTlRBQklMSVRZLFxuLy8gIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFORCBOT05JTkZSSU5HRU1FTlQuIElOIE5PIEVWRU5UIFNIQUxMIFRIRVxuLy8gIEFVVEhPUlMgT1IgQ09QWVJJR0hUIEhPTERFUlMgQkUgTElBQkxFIEZPUiBBTlkgQ0xBSU0sIERBTUFHRVMgT1IgT1RIRVJcbi8vICBMSUFCSUxJVFksIFdIRVRIRVIgSU4gQU4gQUNUSU9OIE9GIENPTlRSQUNULCBUT1JUIE9SIE9USEVSV0lTRSwgQVJJU0lORyBGUk9NLFxuLy8gIE9VVCBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhFIFNPRlRXQVJFIE9SIFRIRSBVU0UgT1IgT1RIRVIgREVBTElOR1MgSU5cbi8vICBUSEUgU09GVFdBUkUuXG5cbmltcG9ydCB7XG4gICAgQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3ksXG4gICAgQ2hhbmdlRGV0ZWN0b3JSZWYsXG4gICAgQ29tcG9uZW50LFxuICAgIEV2ZW50RW1pdHRlcixcbiAgICBJbmplY3QsXG4gICAgSW5wdXQsXG4gICAgT25DaGFuZ2VzLFxuICAgIE9uRGVzdHJveSxcbiAgICBPbkluaXQsXG4gICAgT3V0cHV0LFxuICAgIFNpbXBsZUNoYW5nZXMsXG59IGZyb20gXCJAYW5ndWxhci9jb3JlXCI7XG5pbXBvcnQge1xuICAgIEFic3RyYWN0Q29udHJvbCxcbiAgICBGb3JtQXJyYXksXG4gICAgRm9ybUJ1aWxkZXIsXG4gICAgRm9ybUNvbnRyb2wsXG4gICAgRm9ybUdyb3VwLFxuICAgIFZhbGlkYXRvcnMsXG59IGZyb20gXCJAYW5ndWxhci9mb3Jtc1wiO1xuaW1wb3J0IF9kaWZmZXJlbmNlIGZyb20gXCJsb2Rhc2gvZGlmZmVyZW5jZVwiO1xuaW1wb3J0IHsgU3ViamVjdCB9IGZyb20gXCJyeGpzXCI7XG5pbXBvcnQgeyB0YWtlVW50aWwgfSBmcm9tIFwicnhqcy9vcGVyYXRvcnNcIjtcblxuaW1wb3J0IHsgRXZlbnRCdXMsIElEYXRhRmllbGQsIElEYXRhU291cmNlLCBJRXZlbnQgfSBmcm9tIFwiQG5vdmEtdWkvYml0c1wiO1xuXG5pbXBvcnQge1xuICAgIElIYXNDaGFuZ2VEZXRlY3RvcixcbiAgICBJSGFzRm9ybSxcbiAgICBQSVpaQUdOQV9FVkVOVF9CVVMsXG59IGZyb20gXCIuLi8uLi8uLi8uLi8uLi90eXBlc1wiO1xuaW1wb3J0IHsgREFUQV9TT1VSQ0VfQ1JFQVRFRCB9IGZyb20gXCIuLi8uLi8uLi8uLi90eXBlc1wiO1xuXG5AQ29tcG9uZW50KHtcbiAgICBzZWxlY3RvcjogXCJudWktZ3JvdXBpbmctY29uZmlndXJhdGlvblwiLFxuICAgIHRlbXBsYXRlVXJsOiBcIi4vZ3JvdXBpbmctY29uZmlndXJhdGlvbi5jb21wb25lbnQuaHRtbFwiLFxuICAgIGNoYW5nZURldGVjdGlvbjogQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3kuT25QdXNoLFxuICAgIHN0eWxlczogW1xuICAgICAgICBgXG4gICAgICAgICAgICAuZ3JvdXBpbmctY29uZmlndXJhdGlvbl9fYWNjb3JkaW9uLWNvbnRlbnQge1xuICAgICAgICAgICAgICAgIHBhZGRpbmc6IDE1cHggMTVweCAxNXB4IDQ2cHg7XG4gICAgICAgICAgICB9XG4gICAgICAgIGAsXG4gICAgXSxcbn0pXG4vLyBSZW1lbWJlciB0byBkZWNsYXJlIHRoaXMgY2xhc3MgaW4gdGhlIHBhcmVudCBtb2R1bGVcbmV4cG9ydCBjbGFzcyBHcm91cGluZ0NvbmZpZ3VyYXRpb25Db21wb25lbnRcbiAgICBpbXBsZW1lbnRzIE9uSW5pdCwgT25DaGFuZ2VzLCBJSGFzQ2hhbmdlRGV0ZWN0b3IsIElIYXNGb3JtLCBPbkRlc3Ryb3lcbntcbiAgICBwdWJsaWMgc3RhdGljIGxhdGVMb2FkS2V5ID0gXCJEcmlsbGRvd25Db25maWd1cmF0b3JDb21wb25lbnRcIjtcblxuICAgIEBJbnB1dCgpIGdyb3Vwczogc3RyaW5nW107XG4gICAgQElucHV0KCkgZ3JvdXBCeTogc3RyaW5nW107XG4gICAgQE91dHB1dCgpIGZvcm1SZWFkeSA9IG5ldyBFdmVudEVtaXR0ZXI8Rm9ybUdyb3VwPigpO1xuXG4gICAgcHVibGljIGZvcm06IEZvcm1Hcm91cCA9IHRoaXMuZm9ybUJ1aWxkZXIuZ3JvdXAoe1xuICAgICAgICBncm91cHM6IFtdLFxuICAgICAgICBncm91cEJ5OiB0aGlzLmZvcm1CdWlsZGVyLmFycmF5KFtdKSxcbiAgICAgICAgZHJpbGxzdGF0ZTogW3VuZGVmaW5lZF0sXG4gICAgfSk7XG5cbiAgICBwdWJsaWMgc2VsZWN0RGF0YTogQXJyYXk8QXJyYXk8c3RyaW5nPj47XG5cbiAgICBwcml2YXRlIHJlYWRvbmx5IGRlc3Ryb3kkID0gbmV3IFN1YmplY3Q8dm9pZD4oKTtcblxuICAgIGNvbnN0cnVjdG9yKFxuICAgICAgICBwdWJsaWMgY2hhbmdlRGV0ZWN0b3I6IENoYW5nZURldGVjdG9yUmVmLFxuICAgICAgICBwcml2YXRlIGZvcm1CdWlsZGVyOiBGb3JtQnVpbGRlcixcbiAgICAgICAgQEluamVjdChQSVpaQUdOQV9FVkVOVF9CVVMpIHByaXZhdGUgZXZlbnRCdXM6IEV2ZW50QnVzPElFdmVudD5cbiAgICApIHt9XG5cbiAgICBwdWJsaWMgZ2V0IGdldEdyb3VwQnlDb250cm9sKCk6IEZvcm1BcnJheSB7XG4gICAgICAgIHJldHVybiB0aGlzLmZvcm0uZ2V0KFwiZ3JvdXBCeVwiKSBhcyBGb3JtQXJyYXk7XG4gICAgfVxuXG4gICAgcHVibGljIGdldCBnZXREcmlsbFN0YXRlQ29udHJvbCgpOiBGb3JtQXJyYXkge1xuICAgICAgICByZXR1cm4gdGhpcy5mb3JtLmdldChcImRyaWxsc3RhdGVcIikgYXMgRm9ybUFycmF5O1xuICAgIH1cblxuICAgIHB1YmxpYyBnZXQgZ2V0R3JvdXBzQ29udHJvbCgpOiBGb3JtQ29udHJvbCB7XG4gICAgICAgIHJldHVybiB0aGlzLmZvcm0uZ2V0KFwiZ3JvdXBzXCIpIGFzIEZvcm1Db250cm9sO1xuICAgIH1cblxuICAgIHB1YmxpYyBuZ09uSW5pdCgpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5ldmVudEJ1c1xuICAgICAgICAgICAgLmdldFN0cmVhbShEQVRBX1NPVVJDRV9DUkVBVEVEKVxuICAgICAgICAgICAgLnBpcGUodGFrZVVudGlsKHRoaXMuZGVzdHJveSQpKVxuICAgICAgICAgICAgLnN1YnNjcmliZSgocHJvdmlkZXI6IElFdmVudDxJRGF0YVNvdXJjZT4pID0+XG4gICAgICAgICAgICAgICAgdGhpcy5vbkRhdGFTb3VyY2VDcmVhdGVkKHByb3ZpZGVyKVxuICAgICAgICAgICAgKTtcblxuICAgICAgICB0aGlzLmdldEdyb3VwQnlDb250cm9sLnZhbHVlQ2hhbmdlc1xuICAgICAgICAgICAgLnBpcGUodGFrZVVudGlsKHRoaXMuZGVzdHJveSQpKVxuICAgICAgICAgICAgLnN1YnNjcmliZSgoKSA9PiB0aGlzLmZpbGxHcm91cHNPcHRpb25zKCkpO1xuXG4gICAgICAgIHRoaXMuZmlsbEdyb3Vwc09wdGlvbnMoKTtcblxuICAgICAgICB0aGlzLmZvcm1SZWFkeS5lbWl0KHRoaXMuZm9ybSk7XG4gICAgfVxuXG4gICAgcHVibGljIG5nT25DaGFuZ2VzKGNoYW5nZXM6IFNpbXBsZUNoYW5nZXMpOiB2b2lkIHtcbiAgICAgICAgaWYgKGNoYW5nZXMuZ3JvdXBzKSB7XG4gICAgICAgICAgICB0aGlzLmdldEdyb3Vwc0NvbnRyb2wuc2V0VmFsdWUoY2hhbmdlcy5ncm91cHMuY3VycmVudFZhbHVlKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoY2hhbmdlcy5ncm91cEJ5ICYmICFjaGFuZ2VzLmdyb3VwQnkuZmlyc3RDaGFuZ2UpIHtcbiAgICAgICAgICAgIHRoaXMuZ2V0R3JvdXBCeUNvbnRyb2wuY2xlYXIoKTtcbiAgICAgICAgICAgIHRoaXMuZ3JvdXBCeS5mb3JFYWNoKChncm91cCkgPT5cbiAgICAgICAgICAgICAgICB0aGlzLmdldEdyb3VwQnlDb250cm9sLnB1c2godGhpcy5jcmVhdGVDb250cm9sKGdyb3VwKSlcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICB0aGlzLmZpbGxHcm91cHNPcHRpb25zKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwdWJsaWMgY3JlYXRlQ29udHJvbCh2YWx1ZT86IHN0cmluZyk6IEZvcm1Db250cm9sIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZm9ybUJ1aWxkZXIuY29udHJvbCh2YWx1ZSB8fCBcIlwiLCBWYWxpZGF0b3JzLnJlcXVpcmVkKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgYWRkR3JvdXBpbmcoKTogdm9pZCB7XG4gICAgICAgIGNvbnN0IGNvbnRyb2wgPSB0aGlzLmNyZWF0ZUNvbnRyb2woKTtcbiAgICAgICAgdGhpcy5nZXRHcm91cEJ5Q29udHJvbC5wdXNoKGNvbnRyb2wpO1xuICAgICAgICB0aGlzLmZpbGxHcm91cHNPcHRpb25zKCk7XG4gICAgICAgIGNvbnN0IGxhc3RDb250cm9sSW5kZXggPSB0aGlzLmdldEdyb3VwQnlDb250cm9sLmNvbnRyb2xzLmxlbmd0aCAtIDE7XG4gICAgICAgIGNvbnRyb2wuc2V0VmFsdWUodGhpcy5zZWxlY3REYXRhW2xhc3RDb250cm9sSW5kZXhdWzBdKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgcmVtb3ZlUnVsZShpbmRleDogbnVtYmVyKTogdm9pZCB7XG4gICAgICAgIHRoaXMuZ2V0R3JvdXBCeUNvbnRyb2wucmVtb3ZlQXQoaW5kZXgpO1xuICAgICAgICB0aGlzLmZpbGxHcm91cHNPcHRpb25zKCk7XG4gICAgfVxuXG4gICAgcHVibGljIGlzQWRkUmVzdHJpY3RlZCgpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuc2VsZWN0RGF0YS5zb21lKChpKSA9PiBpLmxlbmd0aCA9PT0gMSk7XG4gICAgfVxuXG4gICAgcHVibGljIGdldFN1YnRpdGxlKCk6IHN0cmluZyB7XG4gICAgICAgIGNvbnN0IHN1YnRpdGxlID0gdGhpcy5nZXRHcm91cEJ5Q29udHJvbC5jb250cm9sc1xuICAgICAgICAgICAgLm1hcChcbiAgICAgICAgICAgICAgICAoY29udHJvbDogQWJzdHJhY3RDb250cm9sLCBpbmRleDogbnVtYmVyKSA9PlxuICAgICAgICAgICAgICAgICAgICBgJHtpbmRleCA9PT0gMCA/IFwiQnlcIiA6IFwidGhlblwifSAke2NvbnRyb2wudmFsdWV9YFxuICAgICAgICAgICAgKVxuICAgICAgICAgICAgLmpvaW4oXCIsIFwiKTtcblxuICAgICAgICByZXR1cm4gdGhpcy5nZXRHcm91cEJ5Q29udHJvbD8udmFsdWUubGVuZ3RoID09PSAwXG4gICAgICAgICAgICA/ICRsb2NhbGl6ZWBObyBncm91cHNgXG4gICAgICAgICAgICA6ICRsb2NhbGl6ZWAke3N1YnRpdGxlfWA7XG4gICAgfVxuXG4gICAgcHVibGljIG5nT25EZXN0cm95KCk6IHZvaWQge1xuICAgICAgICB0aGlzLmRlc3Ryb3kkLm5leHQoKTtcbiAgICAgICAgdGhpcy5kZXN0cm95JC5jb21wbGV0ZSgpO1xuICAgIH1cblxuICAgIHByaXZhdGUgb25EYXRhU291cmNlQ3JlYXRlZChwcm92aWRlcjogSUV2ZW50PElEYXRhU291cmNlPikge1xuICAgICAgICBwcm92aWRlcj8ucGF5bG9hZD8uZGF0YUZpZWxkc0NvbmZpZz8uZGF0YUZpZWxkcyRcbiAgICAgICAgICAgID8ucGlwZSh0YWtlVW50aWwodGhpcy5kZXN0cm95JCkpXG4gICAgICAgICAgICAuc3Vic2NyaWJlKChkYXRhRmllbGRzOiBJRGF0YUZpZWxkW10pID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoZGF0YUZpZWxkcykge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBkYXRhRmllbGRJZHMgPSBkYXRhRmllbGRzLm1hcChcbiAgICAgICAgICAgICAgICAgICAgICAgIChmaWVsZDogSURhdGFGaWVsZCkgPT4gZmllbGQuaWRcbiAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgZGF0YURpZmYgPSBfZGlmZmVyZW5jZSh0aGlzLmdyb3VwcywgZGF0YUZpZWxkSWRzKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGRhdGFEaWZmLmxlbmd0aCB8fCAhdGhpcy5ncm91cHM/Lmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5ncm91cHMgPSBkYXRhRmllbGRJZHM7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmdldEdyb3Vwc0NvbnRyb2wuc2V0VmFsdWUoZGF0YUZpZWxkSWRzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZ2V0R3JvdXBCeUNvbnRyb2wuY2xlYXIoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZ2V0RHJpbGxTdGF0ZUNvbnRyb2wuc2V0VmFsdWUoW10pO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5maWxsR3JvdXBzT3B0aW9ucygpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBmaWxsR3JvdXBzT3B0aW9ucygpIHtcbiAgICAgICAgdGhpcy5zZWxlY3REYXRhID0gW107XG4gICAgICAgIGNvbnN0IGNvbnRyb2xWYWx1ZSA9IHRoaXMuZ2V0R3JvdXBCeUNvbnRyb2wudmFsdWUgYXMgc3RyaW5nW107XG4gICAgICAgIHRoaXMuZ2V0R3JvdXBCeUNvbnRyb2wuY29udHJvbHMuZm9yRWFjaChcbiAgICAgICAgICAgICh2YWx1ZTogQWJzdHJhY3RDb250cm9sLCBpbmRleDogbnVtYmVyKSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5zZWxlY3REYXRhW2luZGV4XSA9IFtdO1xuICAgICAgICAgICAgICAgIGNvbnN0IGRpZmYgPSBfZGlmZmVyZW5jZSh0aGlzLmdyb3VwcywgY29udHJvbFZhbHVlKTtcbiAgICAgICAgICAgICAgICBpZiAoY29udHJvbFZhbHVlW2luZGV4XSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnNlbGVjdERhdGFbaW5kZXhdLnB1c2goY29udHJvbFZhbHVlW2luZGV4XSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMuc2VsZWN0RGF0YVtpbmRleF0gPSBbLi4udGhpcy5zZWxlY3REYXRhW2luZGV4XSwgLi4uZGlmZl07XG4gICAgICAgICAgICB9XG4gICAgICAgICk7XG4gICAgfVxufVxuIiwiPG51aS13aWRnZXQtZWRpdG9yLWFjY29yZGlvblxuICAgIFtmb3JtR3JvdXBdPVwiZm9ybVwiXG4gICAgW3N0YXRlXT1cImZvcm0gfCBudWlXaWRnZXRFZGl0b3JBY2NvcmRpb25Gb3JtU3RhdGUgfCBhc3luY1wiXG4+XG4gICAgPG51aS13aWRnZXQtZWRpdG9yLWFjY29yZGlvbi1oZWFkZXJcbiAgICAgICAgW2hlYWRlckljb25dPVwiJ3RhZydcIlxuICAgICAgICBbc3VidGl0bGVdPVwiZ2V0U3VidGl0bGUoKVwiXG4gICAgICAgIGhlYWRlclRpdGxlPVwiR3JvdXBpbmdcIlxuICAgIC8+XG4gICAgPGRpdlxuICAgICAgICBjbGFzcz1cImdyb3VwaW5nLWNvbmZpZ3VyYXRpb25fX2FjY29yZGlvbi1jb250ZW50XCJcbiAgICAgICAgZm9ybUFycmF5TmFtZT1cImdyb3VwQnlcIlxuICAgID5cbiAgICAgICAgPG5nLWNvbnRhaW5lclxuICAgICAgICAgICAgKm5nRm9yPVwibGV0IGdyb3VwIG9mIGdldEdyb3VwQnlDb250cm9sLmNvbnRyb2xzOyBpbmRleCBhcyBpXCJcbiAgICAgICAgPlxuICAgICAgICAgICAgPGxhYmVsICpuZ0lmPVwiaSAhPT0gMFwiIGNsYXNzPVwiZC1mbGV4IG51aS10ZXh0LXNlY29uZGFyeSBtYi0xXCIgaTE4blxuICAgICAgICAgICAgICAgID5UaGVuPC9sYWJlbFxuICAgICAgICAgICAgPlxuICAgICAgICAgICAgPGxhYmVsICpuZ0lmPVwiaSA9PT0gMFwiIGNsYXNzPVwiZC1mbGV4IG51aS10ZXh0LXBhbmVsIG1iLTJcIiBpMThuXG4gICAgICAgICAgICAgICAgPkdyb3VwIGJ5PC9sYWJlbFxuICAgICAgICAgICAgPlxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cImQtZmxleCBmbGV4LXJvdyBmbGV4LWdyb3ctMSBtYi00XCI+XG4gICAgICAgICAgICAgICAgPG51aS1mb3JtLWZpZWxkIFtjb250cm9sXT1cImdyb3VwXCIgY2xhc3M9XCJkLWZsZXggZmxleC1ncm93LTFcIj5cbiAgICAgICAgICAgICAgICAgICAgPG51aS1zZWxlY3QtdjJcbiAgICAgICAgICAgICAgICAgICAgICAgIHBsYWNlaG9sZGVyPVwiU2VsZWN0IEl0ZW1cIlxuICAgICAgICAgICAgICAgICAgICAgICAgaTE4bi1wbGFjZWhvbGRlclxuICAgICAgICAgICAgICAgICAgICAgICAgW2Zvcm1Db250cm9sTmFtZV09XCJpXCJcbiAgICAgICAgICAgICAgICAgICAgPlxuICAgICAgICAgICAgICAgICAgICAgICAgPG51aS1zZWxlY3QtdjItb3B0aW9uXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKm5nRm9yPVwibGV0IGl0ZW0gb2Ygc2VsZWN0RGF0YVtpXVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgW3ZhbHVlXT1cIml0ZW1cIlxuICAgICAgICAgICAgICAgICAgICAgICAgPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHt7IGl0ZW0gfX1cbiAgICAgICAgICAgICAgICAgICAgICAgIDwvbnVpLXNlbGVjdC12Mi1vcHRpb24+XG4gICAgICAgICAgICAgICAgICAgIDwvbnVpLXNlbGVjdC12Mj5cbiAgICAgICAgICAgICAgICA8L251aS1mb3JtLWZpZWxkPlxuICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJqdXN0aWZ5LWNvbnRlbnQtY2VudGVyXCI+XG4gICAgICAgICAgICAgICAgICAgIDxidXR0b25cbiAgICAgICAgICAgICAgICAgICAgICAgIG51aS1idXR0b25cbiAgICAgICAgICAgICAgICAgICAgICAgIGljb249XCJkZWxldGVcIlxuICAgICAgICAgICAgICAgICAgICAgICAgZGlzcGxheVN0eWxlPVwiYWN0aW9uXCJcbiAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU9XCJidXR0b25cIlxuICAgICAgICAgICAgICAgICAgICAgICAgKGNsaWNrKT1cInJlbW92ZVJ1bGUoaSlcIlxuICAgICAgICAgICAgICAgICAgICA+PC9idXR0b24+XG4gICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgPC9uZy1jb250YWluZXI+XG4gICAgICAgIDxidXR0b25cbiAgICAgICAgICAgIG51aS1idXR0b25cbiAgICAgICAgICAgIGljb249XCJhZGRcIlxuICAgICAgICAgICAgZGlzcGxheVN0eWxlPVwiYWN0aW9uXCJcbiAgICAgICAgICAgIHR5cGU9XCJidXR0b25cIlxuICAgICAgICAgICAgaTE4blxuICAgICAgICAgICAgKm5nSWY9XCIhdGhpcy5pc0FkZFJlc3RyaWN0ZWQoKVwiXG4gICAgICAgICAgICAoY2xpY2spPVwiYWRkR3JvdXBpbmcoKVwiXG4gICAgICAgID5cbiAgICAgICAgICAgIEFkZCBhbm90aGVyIGxldmVsXG4gICAgICAgIDwvYnV0dG9uPlxuICAgIDwvZGl2PlxuPC9udWktd2lkZ2V0LWVkaXRvci1hY2NvcmRpb24+XG4iXX0=