@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
107 lines • 27.4 kB
JavaScript
// © 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, Input, Output, } from "@angular/core";
import { FormBuilder, Validators } from "@angular/forms";
// eslint-disable-next-line import/no-deprecated
import { combineLatest } from "rxjs";
// eslint-disable-next-line import/no-deprecated
import { map, startWith } from "rxjs/operators";
import { chartPaletteColorMap, DEFAULT_KPI_TILE_COLOR, } from "../../../../../constants/default-palette";
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 "../../../color-picker/color-picker.component";
import * as i6 from "../../../../pipe/widget-editor-accordion-form-state.pipe";
import * as i7 from "../../../../pipe/widget-editor-accordion-header-icon.pipe";
export class KpiDescriptionConfigurationComponent {
static { this.lateLoadKey = "KpiDescriptionConfigurationComponent"; }
constructor(changeDetector, formBuilder) {
this.changeDetector = changeDetector;
this.formBuilder = formBuilder;
this.defaultColor = {
label: $localize `Default color`,
color: DEFAULT_KPI_TILE_COLOR,
};
this.label = "";
this.backgroundColor = this.defaultColor.color;
this.units = "";
this.formReady = new EventEmitter();
}
ngOnInit() {
this.backgroundColors = [...this.backgroundColors];
this.backgroundColors.unshift(this.defaultColor);
this.form = this.formBuilder.group({
label: [this.label, [Validators.required]],
backgroundColor: [this.backgroundColor, [Validators.required]],
});
if (this.configurableUnits) {
this.form.addControl("units", this.formBuilder.control(this.units));
}
const label = this.form.get("label");
// eslint-disable-next-line import/no-deprecated
const labelValue = label?.valueChanges.pipe(startWith(label.value));
const backgroundColor = this.form.get("backgroundColor");
const backgroundColorValue = backgroundColor?.valueChanges.pipe(
// eslint-disable-next-line import/no-deprecated
startWith(backgroundColor?.value));
// eslint-disable-next-line import/no-deprecated
this.subtitle$ = combineLatest([
labelValue?.pipe(map((t) => t || $localize `no label`)),
backgroundColorValue?.pipe(map((t) => chartPaletteColorMap[t] || $localize `Default Color`)),
]).pipe(map((labels) => labels.join(", ")));
this.formReady.emit(this.form);
}
ngOnChanges(changes) {
if (changes.label) {
this.form?.patchValue({ label: changes.label.currentValue });
}
if (changes.backgroundColor) {
this.form?.patchValue({
backgroundColor: changes.backgroundColor.currentValue,
});
}
if (changes.units) {
this.form?.patchValue({ units: changes.units.currentValue });
}
}
/** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: KpiDescriptionConfigurationComponent, deps: [{ token: i0.ChangeDetectorRef }, { token: i1.FormBuilder }], target: i0.ɵɵFactoryTarget.Component }); }
/** @nocollapse */ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: KpiDescriptionConfigurationComponent, selector: "nui-kpi-description-configuration", inputs: { componentId: "componentId", configurableUnits: "configurableUnits", label: "label", backgroundColor: "backgroundColor", units: "units", backgroundColors: "backgroundColors" }, outputs: { formReady: "formReady" }, usesOnChanges: true, ngImport: i0, template: "<nui-widget-editor-accordion\n [formGroup]=\"form\"\n [state]=\"form | nuiWidgetEditorAccordionFormState | async\"\n>\n <div accordionHeader class=\"d-flex align-items-center px-4 py-2\">\n <nui-icon\n class=\"align-self-start pt-2\"\n [icon]=\"form | nuiFormHeaderIconPipe : 'widget_list' | async\"\n ></nui-icon>\n <div class=\"d-flex flex-column ml-4 pt-1\">\n <span class=\"nui-text-label\" i18n>Description</span>\n <div class=\"nui-text-secondary\" [title]=\"subtitle$ | async\">\n {{ subtitle$ | async }}\n </div>\n </div>\n </div>\n <div class=\"kpi-description-configuration__accordion-content\">\n <div class=\"mb-4\">\n <nui-form-field\n caption=\"Label\"\n i18n-caption\n [control]=\"form.get('label')\"\n class=\"form-group\"\n >\n <nui-textbox\n formControlName=\"label\"\n placeholder=\"Set label\"\n i18n-placeholder\n ></nui-textbox>\n </nui-form-field>\n </div>\n\n <nui-form-field\n caption=\"Background Color\"\n i18n-caption\n [control]=\"form.get('backgroundColor')\"\n class=\"form-group\"\n >\n <nui-color-picker\n class=\"kpi-description-configuration__accordion-content__color-picker\"\n formControlName=\"backgroundColor\"\n [colorPalette]=\"backgroundColors\"\n >\n </nui-color-picker>\n </nui-form-field>\n\n <div class=\"mt-4\" *ngIf=\"configurableUnits\">\n <nui-form-field\n caption=\"Units\"\n i18n-caption\n [control]=\"form.get('units')\"\n class=\"form-group\"\n >\n <nui-textbox\n formControlName=\"units\"\n placeholder=\"Units\"\n i18n-placeholder\n ></nui-textbox>\n </nui-form-field>\n </div>\n </div>\n</nui-widget-editor-accordion>\n", styles: [".kpi-description-configuration__accordion-content{padding:15px 15px 15px 46px}.kpi-description-configuration__color-select{display:flex;align-items:center}.kpi-description-configuration__color-preview{width:100%;height:20px;border-radius:3px}.kpi-description-configuration__color-preview.with-arrow{width:calc(100% - 40px);margin-left:10px}.kpi-description-configuration__selector-arrow{display:flex;align-items:center;justify-content:center;width:30px;height:30px;border-left:1px solid;border-left-color:var(--nui-color-line-default,#d9d9d9);margin-left:10px}\n"], dependencies: [{ 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: "component", type: i3.IconComponent, selector: "nui-icon", inputs: ["iconColor", "brushType", "iconHoverColor", "iconSize", "cssClass", "fillContainer", "status", "childStatus", "icon", "counter"] }, { kind: "component", type: i3.TextboxComponent, selector: "nui-textbox", inputs: ["caption", "autocomplete", "info", "customBoxWidth", "disabled", "hint", "name", "placeholder", "readonly", "rows", "type", "value", "isInErrorState", "ariaLabel", "isBusy"], outputs: ["textChange", "blurred"] }, { kind: "component", type: i3.FormFieldComponent, selector: "nui-form-field", inputs: ["control", "caption", "info", "infoTemplate", "hint", "hintTemplate", "customBoxWidth", "showOptionalText"] }, { kind: "component", type: i4.WidgetEditorAccordionComponent, selector: "nui-widget-editor-accordion", inputs: ["showOpenStateIcon", "state"], outputs: ["openToggle"] }, { kind: "component", type: i5.ColorPickerComponent, selector: "nui-color-picker", inputs: ["colors", "colorPalette", "cols"] }, { kind: "pipe", type: i2.AsyncPipe, name: "async" }, { kind: "pipe", type: i6.WidgetEditorAccordionFormStatePipe, name: "nuiWidgetEditorAccordionFormState" }, { kind: "pipe", type: i7.FormHeaderIconPipePipe, name: "nuiFormHeaderIconPipe" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: KpiDescriptionConfigurationComponent, decorators: [{
type: Component,
args: [{ selector: "nui-kpi-description-configuration", changeDetection: ChangeDetectionStrategy.OnPush, template: "<nui-widget-editor-accordion\n [formGroup]=\"form\"\n [state]=\"form | nuiWidgetEditorAccordionFormState | async\"\n>\n <div accordionHeader class=\"d-flex align-items-center px-4 py-2\">\n <nui-icon\n class=\"align-self-start pt-2\"\n [icon]=\"form | nuiFormHeaderIconPipe : 'widget_list' | async\"\n ></nui-icon>\n <div class=\"d-flex flex-column ml-4 pt-1\">\n <span class=\"nui-text-label\" i18n>Description</span>\n <div class=\"nui-text-secondary\" [title]=\"subtitle$ | async\">\n {{ subtitle$ | async }}\n </div>\n </div>\n </div>\n <div class=\"kpi-description-configuration__accordion-content\">\n <div class=\"mb-4\">\n <nui-form-field\n caption=\"Label\"\n i18n-caption\n [control]=\"form.get('label')\"\n class=\"form-group\"\n >\n <nui-textbox\n formControlName=\"label\"\n placeholder=\"Set label\"\n i18n-placeholder\n ></nui-textbox>\n </nui-form-field>\n </div>\n\n <nui-form-field\n caption=\"Background Color\"\n i18n-caption\n [control]=\"form.get('backgroundColor')\"\n class=\"form-group\"\n >\n <nui-color-picker\n class=\"kpi-description-configuration__accordion-content__color-picker\"\n formControlName=\"backgroundColor\"\n [colorPalette]=\"backgroundColors\"\n >\n </nui-color-picker>\n </nui-form-field>\n\n <div class=\"mt-4\" *ngIf=\"configurableUnits\">\n <nui-form-field\n caption=\"Units\"\n i18n-caption\n [control]=\"form.get('units')\"\n class=\"form-group\"\n >\n <nui-textbox\n formControlName=\"units\"\n placeholder=\"Units\"\n i18n-placeholder\n ></nui-textbox>\n </nui-form-field>\n </div>\n </div>\n</nui-widget-editor-accordion>\n", styles: [".kpi-description-configuration__accordion-content{padding:15px 15px 15px 46px}.kpi-description-configuration__color-select{display:flex;align-items:center}.kpi-description-configuration__color-preview{width:100%;height:20px;border-radius:3px}.kpi-description-configuration__color-preview.with-arrow{width:calc(100% - 40px);margin-left:10px}.kpi-description-configuration__selector-arrow{display:flex;align-items:center;justify-content:center;width:30px;height:30px;border-left:1px solid;border-left-color:var(--nui-color-line-default,#d9d9d9);margin-left:10px}\n"] }]
}], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: i1.FormBuilder }], propDecorators: { componentId: [{
type: Input
}], configurableUnits: [{
type: Input
}], label: [{
type: Input
}], backgroundColor: [{
type: Input
}], units: [{
type: Input
}], backgroundColors: [{
type: Input
}], formReady: [{
type: Output
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoia3BpLWRlc2NyaXB0aW9uLWNvbmZpZ3VyYXRpb24uY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vc3JjL2xpYi9jb25maWd1cmF0b3IvY29tcG9uZW50cy93aWRnZXRzL2NvbmZpZ3VyYXRvci1pdGVtcy9rcGktZGVzY3JpcHRpb24tY29uZmlndXJhdGlvbi9rcGktZGVzY3JpcHRpb24tY29uZmlndXJhdGlvbi5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi8uLi8uLi8uLi8uLi9zcmMvbGliL2NvbmZpZ3VyYXRvci9jb21wb25lbnRzL3dpZGdldHMvY29uZmlndXJhdG9yLWl0ZW1zL2twaS1kZXNjcmlwdGlvbi1jb25maWd1cmF0aW9uL2twaS1kZXNjcmlwdGlvbi1jb25maWd1cmF0aW9uLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLHlEQUF5RDtBQUN6RCxFQUFFO0FBQ0YsK0VBQStFO0FBQy9FLDRFQUE0RTtBQUM1RSw4RUFBOEU7QUFDOUUsK0VBQStFO0FBQy9FLDhFQUE4RTtBQUM5RSw0REFBNEQ7QUFDNUQsRUFBRTtBQUNGLDZFQUE2RTtBQUM3RSx1REFBdUQ7QUFDdkQsRUFBRTtBQUNGLDZFQUE2RTtBQUM3RSw0RUFBNEU7QUFDNUUsK0VBQStFO0FBQy9FLDBFQUEwRTtBQUMxRSxpRkFBaUY7QUFDakYsNkVBQTZFO0FBQzdFLGlCQUFpQjtBQUVqQixPQUFPLEVBQ0gsdUJBQXVCLEVBQ3ZCLGlCQUFpQixFQUNqQixTQUFTLEVBQ1QsWUFBWSxFQUNaLEtBQUssRUFHTCxNQUFNLEdBRVQsTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUFFLFdBQVcsRUFBYSxVQUFVLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUNwRSxnREFBZ0Q7QUFDaEQsT0FBTyxFQUFFLGFBQWEsRUFBYyxNQUFNLE1BQU0sQ0FBQztBQUNqRCxnREFBZ0Q7QUFDaEQsT0FBTyxF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S0FBSyxFQUFFO1lBQ2YsSUFBSSxDQUFDLElBQUksRUFBRSxVQUFVLENBQUMsRUFBRSxLQUFLLEVBQUUsT0FBTyxDQUFDLEtBQUssQ0FBQyxZQUFZLEVBQUUsQ0FBQyxDQUFDO1NBQ2hFO1FBQ0QsSUFBSSxPQUFPLENBQUMsZUFBZSxFQUFFO1lBQ3pCLElBQUksQ0FBQyxJQUFJLEVBQUUsVUFBVSxDQUFDO2dCQUNsQixlQUFlLEVBQUUsT0FBTyxDQUFDLGVBQWUsQ0FBQyxZQUFZO2FBQ3hELENBQUMsQ0FBQztTQUNOO1FBQ0QsSUFBSSxPQUFPLENBQUMsS0FBSyxFQUFFO1lBQ2YsSUFBSSxDQUFDLElBQUksRUFBRSxVQUFVLENBQUMsRUFBRSxLQUFLLEVBQUUsT0FBTyxDQUFDLEtBQUssQ0FBQyxZQUFZLEVBQUUsQ0FBQyxDQUFDO1NBQ2hFO0lBQ0wsQ0FBQztrSUF4RVEsb0NBQW9DO3NIQUFwQyxvQ0FBb0MsNlRDckRqRCxpckVBOERBOzs0RkRUYSxvQ0FBb0M7a0JBTmhELFNBQVM7K0JBQ0ksbUNBQW1DLG1CQUc1Qix1QkFBdUIsQ0FBQyxNQUFNO2dIQVd0QyxXQUFXO3NCQUFuQixLQUFLO2dCQUNHLGlCQUFpQjtzQkFBekIsS0FBSztnQkFFRyxLQUFLO3NCQUFiLEtBQUs7Z0JBQ0csZUFBZTtzQkFBdkIsS0FBSztnQkFDRyxLQUFLO3NCQUFiLEtBQUs7Z0JBQ0csZ0JBQWdCO3NCQUF4QixLQUFLO2dCQUVJLFNBQVM7c0JBQWxCLE1BQU0iLCJzb3VyY2VzQ29udGVudCI6WyIvLyDCqSAyMDIyIFNvbGFyV2luZHMgV29ybGR3aWRlLCBMTEMuIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vL1xuLy8gUGVybWlzc2lvbiBpcyBoZXJlYnkgZ3JhbnRlZCwgZnJlZSBvZiBjaGFyZ2UsIHRvIGFueSBwZXJzb24gb2J0YWluaW5nIGEgY29weVxuLy8gIG9mIHRoaXMgc29mdHdhcmUgYW5kIGFzc29jaWF0ZWQgZG9jdW1lbnRhdGlvbiBmaWxlcyAodGhlIFwiU29mdHdhcmVcIiksIHRvXG4vLyAgZGVhbCBpbiB0aGUgU29mdHdhcmUgd2l0aG91dCByZXN0cmljdGlvbiwgaW5jbHVkaW5nIHdpdGhvdXQgbGltaXRhdGlvbiB0aGVcbi8vICByaWdodHMgdG8gdXNlLCBjb3B5LCBtb2RpZnksIG1lcmdlLCBwdWJsaXNoLCBkaXN0cmlidXRlLCBzdWJsaWNlbnNlLCBhbmQvb3Jcbi8vICBzZWxsIGNvcGllcyBvZiB0aGUgU29mdHdhcmUsIGFuZCB0byBwZXJtaXQgcGVyc29ucyB0byB3aG9tIHRoZSBTb2Z0d2FyZSBpc1xuLy8gIGZ1cm5pc2hlZCB0byBkbyBzbywgc3ViamVjdCB0byB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbnM6XG4vL1xuLy8gVGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UgYW5kIHRoaXMgcGVybWlzc2lvbiBub3RpY2Ugc2hhbGwgYmUgaW5jbHVkZWQgaW5cbi8vICBhbGwgY29waWVzIG9yIHN1YnN0YW50aWFsIHBvcnRpb25zIG9mIHRoZSBTb2Z0d2FyZS5cbi8vXG4vLyBUSEUgU09GVFdBUkUgSVMgUFJPVklERUQgXCJBUyBJU1wiLCBXSVRIT1VUIFdBUlJBTlRZIE9GIEFOWSBLSU5ELCBFWFBSRVNTIE9SXG4vLyAgSU1QTElFRCwgSU5DTFVESU5HIEJVVCBOT1QgTElNSVRFRCBUTyBUSEUgV0FSUkFOVElFUyBPRiBNRVJDSEFOVEFCSUxJVFksXG4vLyAgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQU5EIE5PTklORlJJTkdFTUVOVC4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFXG4vLyAgQVVUSE9SUyBPUiBDT1BZUklHSFQgSE9MREVSUyBCRSBMSUFCTEUgRk9SIEFOWSBDTEFJTSwgREFNQUdFUyBPUiBPVEhFUlxuLy8gIExJQUJJTElUWSwgV0hFVEhFUiBJTiBBTiBBQ1RJT04gT0YgQ09OVFJBQ1QsIFRPUlQgT1IgT1RIRVJXSVNFLCBBUklTSU5HIEZST00sXG4vLyAgT1VUIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgU09GVFdBUkUgT1IgVEhFIFVTRSBPUiBPVEhFUiBERUFMSU5HUyBJTlxuLy8gIFRIRSBTT0ZUV0FSRS5cblxuaW1wb3J0IHtcbiAgICBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneSxcbiAgICBDaGFuZ2VEZXRlY3RvclJlZixcbiAgICBDb21wb25lbnQsXG4gICAgRXZlbnRFbWl0dGVyLFxuICAgIElucHV0LFxuICAgIE9uQ2hhbmdlcyxcbiAgICBPbkluaXQsXG4gICAgT3V0cHV0LFxuICAgIFNpbXBsZUNoYW5nZXMsXG59IGZyb20gXCJAYW5ndWxhci9jb3JlXCI7XG5pbXBvcnQgeyBGb3JtQnVpbGRlciwgRm9ybUdyb3VwLCBWYWxpZGF0b3JzIH0gZnJvbSBcIkBhbmd1bGFyL2Zvcm1zXCI7XG4vLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgaW1wb3J0L25vLWRlcHJlY2F0ZWRcbmltcG9ydCB7IGNvbWJpbmVMYXRlc3QsIE9ic2VydmFibGUgfSBmcm9tIFwicnhqc1wiO1xuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1kZXByZWNhdGVkXG5pbXBvcnQgeyBtYXAsIHN0YXJ0V2l0aCB9IGZyb20gXCJyeGpzL29wZXJhdG9yc1wiO1xuXG5pbXBvcnQge1xuICAgIGNoYXJ0UGFsZXR0ZUNvbG9yTWFwLFxuICAgIERFRkFVTFRfS1BJX1RJTEVfQ09MT1IsXG59IGZyb20gXCIuLi8uLi8uLi8uLi8uLi9jb25zdGFudHMvZGVmYXVsdC1wYWxldHRlXCI7XG5pbXBvcnQge1xuICAgIElIYXNDaGFuZ2VEZXRlY3RvcixcbiAgICBJSGFzRm9ybSxcbiAgICBJUGFsZXR0ZUNvbG9yLFxufSBmcm9tIFwiLi4vLi4vLi4vLi4vLi4vdHlwZXNcIjtcblxuQENvbXBvbmVudCh7XG4gICAgc2VsZWN0b3I6IFwibnVpLWtwaS1kZXNjcmlwdGlvbi1jb25maWd1cmF0aW9uXCIsXG4gICAgdGVtcGxhdGVVcmw6IFwiLi9rcGktZGVzY3JpcHRpb24tY29uZmlndXJhdGlvbi5jb21wb25lbnQuaHRtbFwiLFxuICAgIHN0eWxlVXJsczogW1wiLi9rcGktZGVzY3JpcHRpb24tY29uZmlndXJhdGlvbi5jb21wb25lbnQubGVzc1wiXSxcbiAgICBjaGFuZ2VEZXRlY3Rpb246IENoYW5nZURldGVjdGlvblN0cmF0ZWd5Lk9uUHVzaCxcbn0pXG5leHBvcnQgY2xhc3MgS3BpRGVzY3JpcHRpb25Db25maWd1cmF0aW9uQ29tcG9uZW50XG4gICAgaW1wbGVtZW50cyBPbkluaXQsIE9uQ2hhbmdlcywgSUhhc0NoYW5nZURldGVjdG9yLCBJSGFzRm9ybVxue1xuICAgIHB1YmxpYyBzdGF0aWMgbGF0ZUxvYWRLZXkgPSBcIktwaURlc2NyaXB0aW9uQ29uZmlndXJhdGlvbkNvbXBvbmVudFwiO1xuICAgIHB1YmxpYyBkZWZhdWx0Q29sb3IgPSB7XG4gICAgICAgIGxhYmVsOiAkbG9jYWxpemVgRGVmYXVsdCBjb2xvcmAsXG4gICAgICAgIGNvbG9yOiBERUZBVUxUX0tQSV9USUxFX0NPTE9SLFxuICAgIH07XG5cbiAgICBASW5wdXQoKSBjb21wb25lbnRJZDogc3RyaW5nO1xuICAgIEBJbnB1dCgpIGNvbmZpZ3VyYWJsZVVuaXRzOiBib29sZWFuO1xuXG4gICAgQElucHV0KCkgbGFiZWw6IHN0cmluZyA9IFwiXCI7XG4gICAgQElucHV0KCkgYmFja2dyb3VuZENvbG9yOiBzdHJpbmcgPSB0aGlzLmRlZmF1bHRDb2xvci5jb2xvcjtcbiAgICBASW5wdXQoKSB1bml0czogc3RyaW5nID0gXCJcIjtcbiAgICBASW5wdXQoKSBiYWNrZ3JvdW5kQ29sb3JzOiBJUGFsZXR0ZUNvbG9yW107XG5cbiAgICBAT3V0cHV0KCkgZm9ybVJlYWR5ID0gbmV3IEV2ZW50RW1pdHRlcjxGb3JtR3JvdXA+KCk7XG5cbiAgICBwdWJsaWMgZm9ybTogRm9ybUdyb3VwO1xuICAgIHB1YmxpYyBzdWJ0aXRsZSQ6IE9ic2VydmFibGU8c3RyaW5nPjtcblxuICAgIGNvbnN0cnVjdG9yKFxuICAgICAgICBwdWJsaWMgY2hhbmdlRGV0ZWN0b3I6IENoYW5nZURldGVjdG9yUmVmLFxuICAgICAgICBwcml2YXRlIGZvcm1CdWlsZGVyOiBGb3JtQnVpbGRlclxuICAgICkge31cblxuICAgIHB1YmxpYyBuZ09uSW5pdCgpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5iYWNrZ3JvdW5kQ29sb3JzID0gWy4uLnRoaXMuYmFja2dyb3VuZENvbG9yc107XG4gICAgICAgIHRoaXMuYmFja2dyb3VuZENvbG9ycy51bnNoaWZ0KHRoaXMuZGVmYXVsdENvbG9yKTtcblxuICAgICAgICB0aGlzLmZvcm0gPSB0aGlzLmZvcm1CdWlsZGVyLmdyb3VwKHtcbiAgICAgICAgICAgIGxhYmVsOiBbdGhpcy5sYWJlbCwgW1ZhbGlkYXRvcnMucmVxdWlyZWRdXSxcbiAgICAgICAgICAgIGJhY2tncm91bmRDb2xvcjogW3RoaXMuYmFja2dyb3VuZENvbG9yLCBbVmFsaWRhdG9ycy5yZXF1aXJlZF1dLFxuICAgICAgICB9KTtcblxuICAgICAgICBpZiAodGhpcy5jb25maWd1cmFibGVVbml0cykge1xuICAgICAgICAgICAgdGhpcy5mb3JtLmFkZENvbnRyb2woXCJ1bml0c1wiLCB0aGlzLmZvcm1CdWlsZGVyLmNvbnRyb2wodGhpcy51bml0cykpO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgbGFiZWwgPSB0aGlzLmZvcm0uZ2V0KFwibGFiZWxcIik7XG4gICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBpbXBvcnQvbm8tZGVwcmVjYXRlZFxuICAgICAgICBjb25zdCBsYWJlbFZhbHVlID0gbGFiZWw/LnZhbHVlQ2hhbmdlcy5waXBlKHN0YXJ0V2l0aChsYWJlbC52YWx1ZSkpO1xuXG4gICAgICAgIGNvbnN0IGJhY2tncm91bmRDb2xvciA9IHRoaXMuZm9ybS5nZXQoXCJiYWNrZ3JvdW5kQ29sb3JcIik7XG4gICAgICAgIGNvbnN0IGJhY2tncm91bmRDb2xvclZhbHVlID0gYmFja2dyb3VuZENvbG9yPy52YWx1ZUNoYW5nZXMucGlwZShcbiAgICAgICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBpbXBvcnQvbm8tZGVwcmVjYXRlZFxuICAgICAgICAgICAgc3RhcnRXaXRoKGJhY2tncm91bmRDb2xvcj8udmFsdWUpXG4gICAgICAgICk7XG4gICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBpbXBvcnQvbm8tZGVwcmVjYXRlZFxuICAgICAgICB0aGlzLnN1YnRpdGxlJCA9IGNvbWJpbmVMYXRlc3QoW1xuICAgICAgICAgICAgbGFiZWxWYWx1ZT8ucGlwZShtYXAoKHQpID0+IHQgfHwgJGxvY2FsaXplYG5vIGxhYmVsYCkpLFxuICAgICAgICAgICAgYmFja2dyb3VuZENvbG9yVmFsdWU/LnBpcGUoXG4gICAgICAgICAgICAgICAgbWFwKCh0KSA9PiBjaGFydFBhbGV0dGVDb2xvck1hcFt0XSB8fCAkbG9jYWxpemVgRGVmYXVsdCBDb2xvcmApXG4gICAgICAgICAgICApLFxuICAgICAgICBdKS5waXBlKG1hcCgobGFiZWxzKSA9PiBsYWJlbHMuam9pbihcIiwgXCIpKSk7XG5cbiAgICAgICAgdGhpcy5mb3JtUmVhZHkuZW1pdCh0aGlzLmZvcm0pO1xuICAgIH1cblxuICAgIHB1YmxpYyBuZ09uQ2hhbmdlcyhjaGFuZ2VzOiBTaW1wbGVDaGFuZ2VzKTogdm9pZCB7XG4gICAgICAgIGlmIChjaGFuZ2VzLmxhYmVsKSB7XG4gICAgICAgICAgICB0aGlzLmZvcm0/LnBhdGNoVmFsdWUoeyBsYWJlbDogY2hhbmdlcy5sYWJlbC5jdXJyZW50VmFsdWUgfSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGNoYW5nZXMuYmFja2dyb3VuZENvbG9yKSB7XG4gICAgICAgICAgICB0aGlzLmZvcm0/LnBhdGNoVmFsdWUoe1xuICAgICAgICAgICAgICAgIGJhY2tncm91bmRDb2xvcjogY2hhbmdlcy5iYWNrZ3JvdW5kQ29sb3IuY3VycmVudFZhbHVlLFxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGNoYW5nZXMudW5pdHMpIHtcbiAgICAgICAgICAgIHRoaXMuZm9ybT8ucGF0Y2hWYWx1ZSh7IHVuaXRzOiBjaGFuZ2VzLnVuaXRzLmN1cnJlbnRWYWx1ZSB9KTtcbiAgICAgICAgfVxuICAgIH1cbn1cbiIsIjxudWktd2lkZ2V0LWVkaXRvci1hY2NvcmRpb25cbiAgICBbZm9ybUdyb3VwXT1cImZvcm1cIlxuICAgIFtzdGF0ZV09XCJmb3JtIHwgbnVpV2lkZ2V0RWRpdG9yQWNjb3JkaW9uRm9ybVN0YXRlIHwgYXN5bmNcIlxuPlxuICAgIDxkaXYgYWNjb3JkaW9uSGVhZGVyIGNsYXNzPVwiZC1mbGV4IGFsaWduLWl0ZW1zLWNlbnRlciBweC00IHB5LTJcIj5cbiAgICAgICAgPG51aS1pY29uXG4gICAgICAgICAgICBjbGFzcz1cImFsaWduLXNlbGYtc3RhcnQgcHQtMlwiXG4gICAgICAgICAgICBbaWNvbl09XCJmb3JtIHwgbnVpRm9ybUhlYWRlckljb25QaXBlIDogJ3dpZGdldF9saXN0JyB8IGFzeW5jXCJcbiAgICAgICAgPjwvbnVpLWljb24+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJkLWZsZXggZmxleC1jb2x1bW4gbWwtNCBwdC0xXCI+XG4gICAgICAgICAgICA8c3BhbiBjbGFzcz1cIm51aS10ZXh0LWxhYmVsXCIgaTE4bj5EZXNjcmlwdGlvbjwvc3Bhbj5cbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJudWktdGV4dC1zZWNvbmRhcnlcIiBbdGl0bGVdPVwic3VidGl0bGUkIHwgYXN5bmNcIj5cbiAgICAgICAgICAgICAgICB7eyBzdWJ0aXRsZSQgfCBhc3luYyB9fVxuICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgIDwvZGl2PlxuICAgIDwvZGl2PlxuICAgIDxkaXYgY2xhc3M9XCJrcGktZGVzY3JpcHRpb24tY29uZmlndXJhdGlvbl9fYWNjb3JkaW9uLWNvbnRlbnRcIj5cbiAgICAgICAgPGRpdiBjbGFzcz1cIm1iLTRcIj5cbiAgICAgICAgICAgIDxudWktZm9ybS1maWVsZFxuICAgICAgICAgICAgICAgIGNhcHRpb249XCJMYWJlbFwiXG4gICAgICAgICAgICAgICAgaTE4bi1jYXB0aW9uXG4gICAgICAgICAgICAgICAgW2NvbnRyb2xdPVwiZm9ybS5nZXQoJ2xhYmVsJylcIlxuICAgICAgICAgICAgICAgIGNsYXNzPVwiZm9ybS1ncm91cFwiXG4gICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgPG51aS10ZXh0Ym94XG4gICAgICAgICAgICAgICAgICAgIGZvcm1Db250cm9sTmFtZT1cImxhYmVsXCJcbiAgICAgICAgICAgICAgICAgICAgcGxhY2Vob2xkZXI9XCJTZXQgbGFiZWxcIlxuICAgICAgICAgICAgICAgICAgICBpMThuLXBsYWNlaG9sZGVyXG4gICAgICAgICAgICAgICAgPjwvbnVpLXRleHRib3g+XG4gICAgICAgICAgICA8L251aS1mb3JtLWZpZWxkPlxuICAgICAgICA8L2Rpdj5cblxuICAgICAgICA8bnVpLWZvcm0tZmllbGRcbiAgICAgICAgICAgIGNhcHRpb249XCJCYWNrZ3JvdW5kIENvbG9yXCJcbiAgICAgICAgICAgIGkxOG4tY2FwdGlvblxuICAgICAgICAgICAgW2NvbnRyb2xdPVwiZm9ybS5nZXQoJ2JhY2tncm91bmRDb2xvcicpXCJcbiAgICAgICAgICAgIGNsYXNzPVwiZm9ybS1ncm91cFwiXG4gICAgICAgID5cbiAgICAgICAgICAgIDxudWktY29sb3ItcGlja2VyXG4gICAgICAgICAgICAgICAgY2xhc3M9XCJrcGktZGVzY3JpcHRpb24tY29uZmlndXJhdGlvbl9fYWNjb3JkaW9uLWNvbnRlbnRfX2NvbG9yLXBpY2tlclwiXG4gICAgICAgICAgICAgICAgZm9ybUNvbnRyb2xOYW1lPVwiYmFja2dyb3VuZENvbG9yXCJcbiAgICAgICAgICAgICAgICBbY29sb3JQYWxldHRlXT1cImJhY2tncm91bmRDb2xvcnNcIlxuICAgICAgICAgICAgPlxuICAgICAgICAgICAgPC9udWktY29sb3ItcGlja2VyPlxuICAgICAgICA8L251aS1mb3JtLWZpZWxkPlxuXG4gICAgICAgIDxkaXYgY2xhc3M9XCJtdC00XCIgKm5nSWY9XCJjb25maWd1cmFibGVVbml0c1wiPlxuICAgICAgICAgICAgPG51aS1mb3JtLWZpZWxkXG4gICAgICAgICAgICAgICAgY2FwdGlvbj1cIlVuaXRzXCJcbiAgICAgICAgICAgICAgICBpMThuLWNhcHRpb25cbiAgICAgICAgICAgICAgICBbY29udHJvbF09XCJmb3JtLmdldCgndW5pdHMnKVwiXG4gICAgICAgICAgICAgICAgY2xhc3M9XCJmb3JtLWdyb3VwXCJcbiAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICA8bnVpLXRleHRib3hcbiAgICAgICAgICAgICAgICAgICAgZm9ybUNvbnRyb2xOYW1lPVwidW5pdHNcIlxuICAgICAgICAgICAgICAgICAgICBwbGFjZWhvbGRlcj1cIlVuaXRzXCJcbiAgICAgICAgICAgICAgICAgICAgaTE4bi1wbGFjZWhvbGRlclxuICAgICAgICAgICAgICAgID48L251aS10ZXh0Ym94PlxuICAgICAgICAgICAgPC9udWktZm9ybS1maWVsZD5cbiAgICAgICAgPC9kaXY+XG4gICAgPC9kaXY+XG48L251aS13aWRnZXQtZWRpdG9yLWFjY29yZGlvbj5cbiJdfQ==