@c8y/ngx-components
Version:
Angular modules for Cumulocity IoT applications
105 lines • 29.7 kB
JavaScript
import { Component, Input } from '@angular/core';
import { ControlContainer, FormBuilder, NgForm, Validators } from '@angular/forms';
import { CoreModule } from '@c8y/ngx-components';
import { WidgetConfigComponent } from '@c8y/ngx-components/context-dashboard';
import { DatapointSelectorModule } from '@c8y/ngx-components/datapoint-selector';
import { IconSelectorModule } from '@c8y/ngx-components/icon-selector';
import { PopoverModule } from 'ngx-bootstrap/popover';
import * as i0 from "@angular/core";
import * as i1 from "@angular/forms";
import * as i2 from "@c8y/ngx-components/context-dashboard";
import * as i3 from "@c8y/ngx-components";
import * as i4 from "@c8y/ngx-components/datapoint-selector";
import * as i5 from "@c8y/ngx-components/icon-selector";
import * as i6 from "ngx-bootstrap/popover";
export function exactlyASingleDatapointActive() {
return (control) => {
const datapoints = control.value;
if (!datapoints || !datapoints.length) {
return null;
}
const activeDatapoints = datapoints.filter(datapoint => datapoint.__active);
if (activeDatapoints.length === 1) {
return null;
}
return { exactlyOneDatapointNeedsToBeActive: true };
};
}
export class KpiWidgetConfigComponent {
constructor(formBuilder, form, widgetConfig) {
this.formBuilder = formBuilder;
this.form = form;
this.widgetConfig = widgetConfig;
this.datapointSelectionConfig = {};
this.defaultFormOptions = {
showRedRange: true,
showYellowRange: true
};
this.availableIcons = [];
this.limits = {
fontSizeMax: 72,
fontSizeMin: 18,
numberOfDecimalPlacesMax: 10,
numberOfDecimalPlacesMin: 0
};
}
onBeforeSave(config) {
if (this.formGroup.valid) {
Object.assign(config, this.formGroup.value);
return true;
}
return false;
}
async ngOnInit() {
if (this.widgetConfig.context?.id) {
this.datapointSelectionConfig.contextAsset = this.widgetConfig?.context;
}
this.initForm();
if (this.config?.datapoints) {
this.formGroup.patchValue({ datapoints: this.config.datapoints });
}
}
initForm() {
this.formGroup = this.createForm();
this.form.form.addControl('config', this.formGroup);
this.formGroup.patchValue(this.config);
}
createForm() {
return this.formBuilder.group({
numberOfDecimalPlaces: [
2,
[
Validators.required,
Validators.min(this.limits.numberOfDecimalPlacesMin),
Validators.max(this.limits.numberOfDecimalPlacesMax)
]
],
showTimestamp: [true, []],
showTrend: [true, []],
showIcon: [true, []],
icon: ['water', [Validators.required, Validators.minLength(1)]],
fontSize: [
36,
[
Validators.required,
Validators.min(this.limits.fontSizeMin),
Validators.max(this.limits.fontSizeMax)
]
],
datapoints: this.formBuilder.control(new Array(), [
Validators.required,
Validators.minLength(1),
exactlyASingleDatapointActive()
])
});
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: KpiWidgetConfigComponent, deps: [{ token: i1.FormBuilder }, { token: i1.NgForm }, { token: i2.WidgetConfigComponent }], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: KpiWidgetConfigComponent, isStandalone: true, selector: "c8y-kpi-widget-config", inputs: { config: "config" }, ngImport: i0, template: "<div class=\"p-l-24 p-r-24\">\n <form [formGroup]=\"formGroup\" class=\"row no-card-context\">\n <div class=\"col-sm-6 bg-level-0\">\n <c8y-datapoint-selection-list\n [defaultFormOptions]=\"defaultFormOptions\"\n [config]=\"datapointSelectionConfig\"\n [minActiveCount]=\"1\"\n [maxActiveCount]=\"1\"\n formControlName=\"datapoints\"\n name=\"datapoints\"\n class=\"bg-inherit\"\n ></c8y-datapoint-selection-list>\n </div>\n <div class=\"col-sm-6\">\n <div class=\"card-header separator\">\n <div class=\"card-title h4\">{{ 'Layout' | translate }}</div>\n </div>\n <label translate>Icon</label>\n <div class=\"d-flex a-i-center\">\n <c8y-icon-selector-wrapper name=\"icon\" formControlName=\"icon\"></c8y-icon-selector-wrapper>\n </div>\n <c8y-form-group>\n <label [title]=\"'Number of decimal places' | translate\" translate>\n Number of decimal places\n </label>\n <input\n class=\"form-control\"\n formControlName=\"numberOfDecimalPlaces\"\n name=\"numberOfDecimalPlaces\"\n type=\"number\"\n [placeholder]=\"'e.g. {{ example }}' | translate: { example: 1 }\"\n />\n <c8y-messages\n [show]=\"\n formGroup.controls?.numberOfDecimalPlaces?.touched &&\n formGroup?.controls?.numberOfDecimalPlaces?.errors\n \"\n ></c8y-messages>\n </c8y-form-group>\n <div>\n <label>{{ 'Display' | translate }}</label>\n <div class=\"d-flex gap-16 flex-wrap\">\n <c8y-form-group>\n <label [title]=\"'Show timestamp' | translate\" class=\"c8y-checkbox\">\n <input type=\"checkbox\" formControlName=\"showTimestamp\" name=\"showTimestamp\" />\n <span></span>\n <span translate>Show timestamp</span>\n </label>\n </c8y-form-group>\n\n <c8y-form-group>\n <label [title]=\"'Show icon' | translate\" class=\"c8y-checkbox\">\n <input type=\"checkbox\" formControlName=\"showIcon\" name=\"showIcon\" />\n <span></span>\n <span translate>Show icon</span>\n </label>\n </c8y-form-group>\n\n <c8y-form-group>\n <label [title]=\"'Show trend icon' | translate\" class=\"c8y-checkbox\">\n <input type=\"checkbox\" formControlName=\"showTrend\" name=\"showTrend\" />\n <span></span>\n <span translate>Show trend icon</span>\n <button\n class=\"btn-help btn-help--sm\"\n type=\"button\"\n [attr.aria-label]=\"'Help' | translate\"\n popover=\"{{\n 'Indicates the trend between the last two measurement values.' | translate\n }}\"\n placement=\"right\"\n triggers=\"focus\"\n container=\"body\"\n ></button>\n </label>\n </c8y-form-group>\n </div>\n\n <c8y-form-group>\n <label [title]=\"'Font size of measurement value (px)' | translate\" translate>\n Font size of measurement value (px)\n </label>\n <input\n class=\"form-control\"\n formControlName=\"fontSize\"\n name=\"fontSize\"\n type=\"number\"\n [placeholder]=\"'e.g. {{ example }}' | translate: { example: 36 }\"\n />\n <c8y-messages\n [show]=\"formGroup.controls?.fontSize?.touched && formGroup?.controls?.fontSize?.errors\"\n ></c8y-messages>\n </c8y-form-group>\n </div>\n </div>\n </form>\n</div>\n", dependencies: [{ kind: "ngmodule", type: CoreModule }, { kind: "pipe", type: i3.C8yTranslatePipe, name: "translate" }, { kind: "directive", type: i3.C8yTranslateDirective, selector: "[translate],[ngx-translate]" }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "component", type: i3.FormGroupComponent, selector: "c8y-form-group", inputs: ["hasError", "hasWarning", "hasSuccess", "novalidation", "status"] }, { kind: "component", type: i3.MessagesComponent, selector: "c8y-messages", inputs: ["show", "defaults", "helpMessage"] }, { kind: "directive", type: i3.RequiredInputPlaceholderDirective, selector: "input[required], input[formControlName]" }, { 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: "ngmodule", type: DatapointSelectorModule }, { kind: "component", type: i4.DatapointSelectionListComponent, selector: "c8y-datapoint-selection-list", inputs: ["actions", "allowDragAndDrop", "config", "defaultFormOptions", "maxActiveCount", "minActiveCount", "resolveContext", "listTitle"], outputs: ["isValid", "change"] }, { kind: "ngmodule", type: IconSelectorModule }, { kind: "component", type: i5.IconSelectorWrapperComponent, selector: "c8y-icon-selector-wrapper", inputs: ["canRemoveIcon", "selectedIcon", "iconSize"], outputs: ["onSelect"] }, { kind: "ngmodule", type: PopoverModule }, { kind: "directive", type: i6.PopoverDirective, selector: "[popover]", inputs: ["adaptivePosition", "boundariesElement", "popover", "popoverContext", "popoverTitle", "placement", "outsideClick", "triggers", "container", "containerClass", "isOpen", "delay"], outputs: ["onShown", "onHidden"], exportAs: ["bs-popover"] }], viewProviders: [{ provide: ControlContainer, useExisting: NgForm }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: KpiWidgetConfigComponent, decorators: [{
type: Component,
args: [{ selector: 'c8y-kpi-widget-config', standalone: true, imports: [CoreModule, DatapointSelectorModule, IconSelectorModule, PopoverModule], viewProviders: [{ provide: ControlContainer, useExisting: NgForm }], template: "<div class=\"p-l-24 p-r-24\">\n <form [formGroup]=\"formGroup\" class=\"row no-card-context\">\n <div class=\"col-sm-6 bg-level-0\">\n <c8y-datapoint-selection-list\n [defaultFormOptions]=\"defaultFormOptions\"\n [config]=\"datapointSelectionConfig\"\n [minActiveCount]=\"1\"\n [maxActiveCount]=\"1\"\n formControlName=\"datapoints\"\n name=\"datapoints\"\n class=\"bg-inherit\"\n ></c8y-datapoint-selection-list>\n </div>\n <div class=\"col-sm-6\">\n <div class=\"card-header separator\">\n <div class=\"card-title h4\">{{ 'Layout' | translate }}</div>\n </div>\n <label translate>Icon</label>\n <div class=\"d-flex a-i-center\">\n <c8y-icon-selector-wrapper name=\"icon\" formControlName=\"icon\"></c8y-icon-selector-wrapper>\n </div>\n <c8y-form-group>\n <label [title]=\"'Number of decimal places' | translate\" translate>\n Number of decimal places\n </label>\n <input\n class=\"form-control\"\n formControlName=\"numberOfDecimalPlaces\"\n name=\"numberOfDecimalPlaces\"\n type=\"number\"\n [placeholder]=\"'e.g. {{ example }}' | translate: { example: 1 }\"\n />\n <c8y-messages\n [show]=\"\n formGroup.controls?.numberOfDecimalPlaces?.touched &&\n formGroup?.controls?.numberOfDecimalPlaces?.errors\n \"\n ></c8y-messages>\n </c8y-form-group>\n <div>\n <label>{{ 'Display' | translate }}</label>\n <div class=\"d-flex gap-16 flex-wrap\">\n <c8y-form-group>\n <label [title]=\"'Show timestamp' | translate\" class=\"c8y-checkbox\">\n <input type=\"checkbox\" formControlName=\"showTimestamp\" name=\"showTimestamp\" />\n <span></span>\n <span translate>Show timestamp</span>\n </label>\n </c8y-form-group>\n\n <c8y-form-group>\n <label [title]=\"'Show icon' | translate\" class=\"c8y-checkbox\">\n <input type=\"checkbox\" formControlName=\"showIcon\" name=\"showIcon\" />\n <span></span>\n <span translate>Show icon</span>\n </label>\n </c8y-form-group>\n\n <c8y-form-group>\n <label [title]=\"'Show trend icon' | translate\" class=\"c8y-checkbox\">\n <input type=\"checkbox\" formControlName=\"showTrend\" name=\"showTrend\" />\n <span></span>\n <span translate>Show trend icon</span>\n <button\n class=\"btn-help btn-help--sm\"\n type=\"button\"\n [attr.aria-label]=\"'Help' | translate\"\n popover=\"{{\n 'Indicates the trend between the last two measurement values.' | translate\n }}\"\n placement=\"right\"\n triggers=\"focus\"\n container=\"body\"\n ></button>\n </label>\n </c8y-form-group>\n </div>\n\n <c8y-form-group>\n <label [title]=\"'Font size of measurement value (px)' | translate\" translate>\n Font size of measurement value (px)\n </label>\n <input\n class=\"form-control\"\n formControlName=\"fontSize\"\n name=\"fontSize\"\n type=\"number\"\n [placeholder]=\"'e.g. {{ example }}' | translate: { example: 36 }\"\n />\n <c8y-messages\n [show]=\"formGroup.controls?.fontSize?.touched && formGroup?.controls?.fontSize?.errors\"\n ></c8y-messages>\n </c8y-form-group>\n </div>\n </div>\n </form>\n</div>\n" }]
}], ctorParameters: () => [{ type: i1.FormBuilder }, { type: i1.NgForm }, { type: i2.WidgetConfigComponent }], propDecorators: { config: [{
type: Input
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoia3BpLXdpZGdldC1jb25maWcuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vd2lkZ2V0cy9pbXBsZW1lbnRhdGlvbnMva3BpL2twaS13aWRnZXQtY29uZmlnL2twaS13aWRnZXQtY29uZmlnLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uLy4uL3dpZGdldHMvaW1wbGVtZW50YXRpb25zL2twaS9rcGktd2lkZ2V0LWNvbmZpZy9rcGktd2lkZ2V0LWNvbmZpZy5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsU0FBUyxFQUFFLEtBQUssRUFBVSxNQUFNLGVBQWUsQ0FBQztBQUN6RCxPQUFPLEVBRUwsZ0JBQWdCLEVBQ2hCLFdBQVcsRUFDWCxNQUFNLEVBR04sVUFBVSxFQUNYLE1BQU0sZ0JBQWdCLENBQUM7QUFDeEIsT0FBTyxFQUFFLFVBQVUsRUFBZ0IsTUFBTSxxQkFBcUIsQ0FBQztBQUMvRCxPQUFPLEVBQUUscUJBQXFCLEVBQUUsTUFBTSx1Q0FBdUMsQ0FBQztBQUM5RSxPQUFPLEVBR0wsdUJBQXVCLEVBRXhCLE1BQU0sd0NBQXdDLENBQUM7QUFHaEQsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sbUNBQW1DLENBQUM7QUFDdkUsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLHVCQUF1QixDQUFDOzs7Ozs7OztBQUV0RCxNQUFNLFVBQVUsNkJBQTZCO0lBQzNDLE9BQU8sQ0FBQyxPQUF3QixFQUEyQixFQUFFO1FBQzNELE1BQU0sVUFBVSxHQUFpQixPQUFPLENBQUMsS0FBSyxDQUFDO1FBRS9DLElBQUksQ0FBQyxVQUFVLElBQUksQ0FBQyxVQUFVLENBQUMsTUFBTSxFQUFFLENBQUM7WUFDdEMsT0FBTyxJQUFJLENBQUM7UUFDZCxDQUFDO1FBRUQsTUFBTSxnQkFBZ0IsR0FBRyxVQUFVLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxFQUFFLENB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QUFFO2dCQUNGO29CQUNFLFVBQVUsQ0FBQyxRQUFRO29CQUNuQixVQUFVLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsV0FBVyxDQUFDO29CQUN2QyxVQUFVLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsV0FBVyxDQUFDO2lCQUN4QzthQUNGO1lBQ0QsVUFBVSxFQUFFLElBQUksQ0FBQyxXQUFXLENBQUMsT0FBTyxDQUFDLElBQUksS0FBSyxFQUFjLEVBQUU7Z0JBQzVELFVBQVUsQ0FBQyxRQUFRO2dCQUNuQixVQUFVLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQztnQkFDdkIsNkJBQTZCLEVBQUU7YUFDaEMsQ0FBQztTQUNILENBQUMsQ0FBQztJQUNMLENBQUM7K0dBMUVVLHdCQUF3QjttR0FBeEIsd0JBQXdCLCtHQ2hEckMsbXJIQWlHQSwyQ0RwRFksVUFBVSw2MERBQUUsdUJBQXVCLHFUQUFFLGtCQUFrQixpTkFBRSxhQUFhLG9WQUNqRSxDQUFDLEVBQUUsT0FBTyxFQUFFLGdCQUFnQixFQUFFLFdBQVcsRUFBRSxNQUFNLEVBQUUsQ0FBQzs7NEZBRXhELHdCQUF3QjtrQkFQcEMsU0FBUzsrQkFDRSx1QkFBdUIsY0FFckIsSUFBSSxXQUNQLENBQUMsVUFBVSxFQUFFLHVCQUF1QixFQUFFLGtCQUFrQixFQUFFLGFBQWEsQ0FBQyxpQkFDbEUsQ0FBQyxFQUFFLE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxXQUFXLEVBQUUsTUFBTSxFQUFFLENBQUM7eUlBRzFELE1BQU07c0JBQWQsS0FBSyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENvbXBvbmVudCwgSW5wdXQsIE9uSW5pdCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHtcbiAgQWJzdHJhY3RDb250cm9sLFxuICBDb250cm9sQ29udGFpbmVyLFxuICBGb3JtQnVpbGRlcixcbiAgTmdGb3JtLFxuICBWYWxpZGF0aW9uRXJyb3JzLFxuICBWYWxpZGF0b3JGbixcbiAgVmFsaWRhdG9yc1xufSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XG5pbXBvcnQgeyBDb3JlTW9kdWxlLCBPbkJlZm9yZVNhdmUgfSBmcm9tICdAYzh5L25neC1jb21wb25lbnRzJztcbmltcG9ydCB7IFdpZGdldENvbmZpZ0NvbXBvbmVudCB9IGZyb20gJ0BjOHkvbmd4LWNvbXBvbmVudHMvY29udGV4dC1kYXNoYm9hcmQnO1xuaW1wb3J0IHtcbiAgRGF0YXBvaW50QXR0cmlidXRlc0Zvcm1Db25maWcsXG4gIERhdGFwb2ludFNlbGVjdG9yTW9kYWxPcHRpb25zLFxuICBEYXRhcG9pbnRTZWxlY3Rvck1vZHVsZSxcbiAgS1BJRGV0YWlsc1xufSBmcm9tICdAYzh5L25neC1jb21wb25lbnRzL2RhdGFwb2ludC1zZWxlY3Rvcic7XG5pbXBvcnQgeyBPYnNlcnZhYmxlIH0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyBLcGlXaWRnZXRDb25maWcgfSBmcm9tICcuLi9rcGktd2lkZ2V0Lm1vZGVsJztcbmltcG9ydCB7IEljb25TZWxlY3Rvck1vZHVsZSB9IGZyb20gJ0BjOHkvbmd4LWNvbXBvbmVudHMvaWNvbi1zZWxlY3Rvcic7XG5pbXBvcnQgeyBQb3BvdmVyTW9kdWxlIH0gZnJvbSAnbmd4LWJvb3RzdHJhcC9wb3BvdmVyJztcblxuZXhwb3J0IGZ1bmN0aW9uIGV4YWN0bHlBU2luZ2xlRGF0YXBvaW50QWN0aXZlKCk6IFZhbGlkYXRvckZuIHtcbiAgcmV0dXJuIChjb250cm9sOiBBYnN0cmFjdENvbnRyb2wpOiBWYWxpZGF0aW9uRXJyb3JzIHwgbnVsbCA9PiB7XG4gICAgY29uc3QgZGF0YXBvaW50czogS1BJRGV0YWlsc1tdID0gY29udHJvbC52YWx1ZTtcblxuICAgIGlmICghZGF0YXBvaW50cyB8fCAhZGF0YXBvaW50cy5sZW5ndGgpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIGNvbnN0IGFjdGl2ZURhdGFwb2ludHMgPSBkYXRhcG9pbnRzLmZpbHRlcihkYXRhcG9pbnQgPT4gZGF0YXBvaW50Ll9fYWN0aXZlKTtcblxuICAgIGlmIChhY3RpdmVEYXRhcG9pbnRzLmxlbmd0aCA9PT0gMSkge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgcmV0dXJuIHsgZXhhY3RseU9uZURhdGFwb2ludE5lZWRzVG9CZUFjdGl2ZTogdHJ1ZSB9O1xuICB9O1xufVxuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdjOHkta3BpLXdpZGdldC1jb25maWcnLFxuICB0ZW1wbGF0ZVVybDogJy4va3BpLXdpZGdldC1jb25maWcuY29tcG9uZW50Lmh0bWwnLFxuICBzdGFuZGFsb25lOiB0cnVlLFxuICBpbXBvcnRzOiBbQ29yZU1vZHVsZSwgRGF0YXBvaW50U2VsZWN0b3JNb2R1bGUsIEljb25TZWxlY3Rvck1vZHVsZSwgUG9wb3Zlck1vZHVsZV0sXG4gIHZpZXdQcm92aWRlcnM6IFt7IHByb3ZpZGU6IENvbnRyb2xDb250YWluZXIsIHVzZUV4aXN0aW5nOiBOZ0Zvcm0gfV1cbn0pXG5leHBvcnQgY2xhc3MgS3BpV2lkZ2V0Q29uZmlnQ29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0LCBPbkJlZm9yZVNhdmUge1xuICBASW5wdXQoKSBjb25maWc6IEtwaVdpZGdldENvbmZpZztcbiAgZGF0YXBvaW50U2VsZWN0aW9uQ29uZmlnOiBQYXJ0aWFsPERhdGFwb2ludFNlbGVjdG9yTW9kYWxPcHRpb25zPiA9IHt9O1xuICBkZWZhdWx0Rm9ybU9wdGlvbnM6IFBhcnRpYWw8RGF0YXBvaW50QXR0cmlidXRlc0Zvcm1Db25maWc+ID0ge1xuICAgIHNob3dSZWRSYW5nZTogdHJ1ZSxcbiAgICBzaG93WWVsbG93UmFuZ2U6IHRydWVcbiAgfTtcbiAgZm9ybUdyb3VwOiBSZXR1cm5UeXBlPEtwaVdpZGdldENvbmZpZ0NvbXBvbmVudFsnY3JlYXRlRm9ybSddPjtcbiAgYXZhaWxhYmxlSWNvbnM6IHN0cmluZ1tdID0gW107XG4gIHByaXZhdGUgbGltaXRzID0ge1xuICAgIGZvbnRTaXplTWF4OiA3MixcbiAgICBmb250U2l6ZU1pbjogMTgsXG4gICAgbnVtYmVyT2ZEZWNpbWFsUGxhY2VzTWF4OiAxMCxcbiAgICBudW1iZXJPZkRlY2ltYWxQbGFjZXNNaW46IDBcbiAgfSBhcyBjb25zdDtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIGZvcm1CdWlsZGVyOiBGb3JtQnVpbGRlcixcbiAgICBwcml2YXRlIGZvcm06IE5nRm9ybSxcbiAgICBwcml2YXRlIHdpZGdldENvbmZpZzogV2lkZ2V0Q29uZmlnQ29tcG9uZW50XG4gICkge31cblxuICBvbkJlZm9yZVNhdmUoY29uZmlnPzogS3BpV2lkZ2V0Q29uZmlnKTogYm9vbGVhbiB8IFByb21pc2U8Ym9vbGVhbj4gfCBPYnNlcnZhYmxlPGJvb2xlYW4+IHtcbiAgICBpZiAodGhpcy5mb3JtR3JvdXAudmFsaWQpIHtcbiAgICAgIE9iamVjdC5hc3NpZ24oY29uZmlnLCB0aGlzLmZvcm1Hcm91cC52YWx1ZSk7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgYXN5bmMgbmdPbkluaXQoKSB7XG4gICAgaWYgKHRoaXMud2lkZ2V0Q29uZmlnLmNvbnRleHQ/LmlkKSB7XG4gICAgICB0aGlzLmRhdGFwb2ludFNlbGVjdGlvbkNvbmZpZy5jb250ZXh0QXNzZXQgPSB0aGlzLndpZGdldENvbmZpZz8uY29udGV4dDtcbiAgICB9XG4gICAgdGhpcy5pbml0Rm9ybSgpO1xuICAgIGlmICh0aGlzLmNvbmZpZz8uZGF0YXBvaW50cykge1xuICAgICAgdGhpcy5mb3JtR3JvdXAucGF0Y2hWYWx1ZSh7IGRhdGFwb2ludHM6IHRoaXMuY29uZmlnLmRhdGFwb2ludHMgfSk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBpbml0Rm9ybSgpOiB2b2lkIHtcbiAgICB0aGlzLmZvcm1Hcm91cCA9IHRoaXMuY3JlYXRlRm9ybSgpO1xuICAgIHRoaXMuZm9ybS5mb3JtLmFkZENvbnRyb2woJ2NvbmZpZycsIHRoaXMuZm9ybUdyb3VwKTtcbiAgICB0aGlzLmZvcm1Hcm91cC5wYXRjaFZhbHVlKHRoaXMuY29uZmlnKTtcbiAgfVxuXG4gIHByaXZhdGUgY3JlYXRlRm9ybSgpIHtcbiAgICByZXR1cm4gdGhpcy5mb3JtQnVpbGRlci5ncm91cCh7XG4gICAgICBudW1iZXJPZkRlY2ltYWxQbGFjZXM6IFtcbiAgICAgICAgMixcbiAgICAgICAgW1xuICAgICAgICAgIFZhbGlkYXRvcnMucmVxdWlyZWQsXG4gICAgICAgICAgVmFsaWRhdG9ycy5taW4odGhpcy5saW1pdHMubnVtYmVyT2ZEZWNpbWFsUGxhY2VzTWluKSxcbiAgICAgICAgICBWYWxpZGF0b3JzLm1heCh0aGlzLmxpbWl0cy5udW1iZXJPZkRlY2ltYWxQbGFjZXNNYXgpXG4gICAgICAgIF1cbiAgICAgIF0sXG4gICAgICBzaG93VGltZXN0YW1wOiBbdHJ1ZSwgW11dLFxuICAgICAgc2hvd1RyZW5kOiBbdHJ1ZSwgW11dLFxuICAgICAgc2hvd0ljb246IFt0cnVlLCBbXV0sXG4gICAgICBpY29uOiBbJ3dhdGVyJywgW1ZhbGlkYXRvcnMucmVxdWlyZWQsIFZhbGlkYXRvcnMubWluTGVuZ3RoKDEpXV0sXG4gICAgICBmb250U2l6ZTogW1xuICAgICAgICAzNixcbiAgICAgICAgW1xuICAgICAgICAgIFZhbGlkYXRvcnMucmVxdWlyZWQsXG4gICAgICAgICAgVmFsaWRhdG9ycy5taW4odGhpcy5saW1pdHMuZm9udFNpemVNaW4pLFxuICAgICAgICAgIFZhbGlkYXRvcnMubWF4KHRoaXMubGltaXRzLmZvbnRTaXplTWF4KVxuICAgICAgICBdXG4gICAgICBdLFxuICAgICAgZGF0YXBvaW50czogdGhpcy5mb3JtQnVpbGRlci5jb250cm9sKG5ldyBBcnJheTxLUElEZXRhaWxzPigpLCBbXG4gICAgICAgIFZhbGlkYXRvcnMucmVxdWlyZWQsXG4gICAgICAgIFZhbGlkYXRvcnMubWluTGVuZ3RoKDEpLFxuICAgICAgICBleGFjdGx5QVNpbmdsZURhdGFwb2ludEFjdGl2ZSgpXG4gICAgICBdKVxuICAgIH0pO1xuICB9XG59XG4iLCI8ZGl2IGNsYXNzPVwicC1sLTI0IHAtci0yNFwiPlxuICA8Zm9ybSBbZm9ybUdyb3VwXT1cImZvcm1Hcm91cFwiIGNsYXNzPVwicm93IG5vLWNhcmQtY29udGV4dFwiPlxuICAgIDxkaXYgY2xhc3M9XCJjb2wtc20tNiBiZy1sZXZlbC0wXCI+XG4gICAgICA8Yzh5LWRhdGFwb2ludC1zZWxlY3Rpb24tbGlzdFxuICAgICAgICBbZGVmYXVsdEZvcm1PcHRpb25zXT1cImRlZmF1bHRGb3JtT3B0aW9uc1wiXG4gICAgICAgIFtjb25maWddPVwiZGF0YXBvaW50U2VsZWN0aW9uQ29uZmlnXCJcbiAgICAgICAgW21pbkFjdGl2ZUNvdW50XT1cIjFcIlxuICAgICAgICBbbWF4QWN0aXZlQ291bnRdPVwiMVwiXG4gICAgICAgIGZvcm1Db250cm9sTmFtZT1cImRhdGFwb2ludHNcIlxuICAgICAgICBuYW1lPVwiZGF0YXBvaW50c1wiXG4gICAgICAgIGNsYXNzPVwiYmctaW5oZXJpdFwiXG4gICAgICA+PC9jOHktZGF0YXBvaW50LXNlbGVjdGlvbi1saXN0PlxuICAgIDwvZGl2PlxuICAgIDxkaXYgY2xhc3M9XCJjb2wtc20tNlwiPlxuICAgICAgPGRpdiBjbGFzcz1cImNhcmQtaGVhZGVyIHNlcGFyYXRvclwiPlxuICAgICAgICA8ZGl2IGNsYXNzPVwiY2FyZC10aXRsZSBoNFwiPnt7ICdMYXlvdXQnIHwgdHJhbnNsYXRlIH19PC9kaXY+XG4gICAgICA8L2Rpdj5cbiAgICAgIDxsYWJlbCB0cmFuc2xhdGU+SWNvbjwvbGFiZWw+XG4gICAgICA8ZGl2IGNsYXNzPVwiZC1mbGV4IGEtaS1jZW50ZXJcIj5cbiAgICAgICAgPGM4eS1pY29uLXNlbGVjdG9yLXdyYXBwZXIgbmFtZT1cImljb25cIiBmb3JtQ29udHJvbE5hbWU9XCJpY29uXCI+PC9jOHktaWNvbi1zZWxlY3Rvci13cmFwcGVyPlxuICAgICAgPC9kaXY+XG4gICAgICA8Yzh5LWZvcm0tZ3JvdXA+XG4gICAgICAgIDxsYWJlbCBbdGl0bGVdPVwiJ051bWJlciBvZiBkZWNpbWFsIHBsYWNlcycgfCB0cmFuc2xhdGVcIiB0cmFuc2xhdGU+XG4gICAgICAgICAgTnVtYmVyIG9mIGRlY2ltYWwgcGxhY2VzXG4gICAgICAgIDwvbGFiZWw+XG4gICAgICAgIDxpbnB1dFxuICAgICAgICAgIGNsYXNzPVwiZm9ybS1jb250cm9sXCJcbiAgICAgICAgICBmb3JtQ29udHJvbE5hbWU9XCJudW1iZXJPZkRlY2ltYWxQbGFjZXNcIlxuICAgICAgICAgIG5hbWU9XCJudW1iZXJPZkRlY2ltYWxQbGFjZXNcIlxuICAgICAgICAgIHR5cGU9XCJudW1iZXJcIlxuICAgICAgICAgIFtwbGFjZWhvbGRlcl09XCInZS5nLiB7eyBleGFtcGxlIH19JyB8IHRyYW5zbGF0ZTogeyBleGFtcGxlOiAxIH1cIlxuICAgICAgICAvPlxuICAgICAgICA8Yzh5LW1lc3NhZ2VzXG4gICAgICAgICAgW3Nob3ddPVwiXG4gICAgICAgICAgICBmb3JtR3JvdXAuY29udHJvbHM/Lm51bWJlck9mRGVjaW1hbFBsYWNlcz8udG91Y2hlZCAmJlxuICAgICAgICAgICAgZm9ybUdyb3VwPy5jb250cm9scz8ubnVtYmVyT2ZEZWNpbWFsUGxhY2VzPy5lcnJvcnNcbiAgICAgICAgICBcIlxuICAgICAgICA+PC9jOHktbWVzc2FnZXM+XG4gICAgICA8L2M4eS1mb3JtLWdyb3VwPlxuICAgICAgPGRpdj5cbiAgICAgICAgPGxhYmVsPnt7ICdEaXNwbGF5JyB8IHRyYW5zbGF0ZSB9fTwvbGFiZWw+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJkLWZsZXggZ2FwLTE2IGZsZXgtd3JhcFwiPlxuICAgICAgICAgIDxjOHktZm9ybS1ncm91cD5cbiAgICAgICAgICAgIDxsYWJlbCBbdGl0bGVdPVwiJ1Nob3cgdGltZXN0YW1wJyB8IHRyYW5zbGF0ZVwiIGNsYXNzPVwiYzh5LWNoZWNrYm94XCI+XG4gICAgICAgICAgICAgIDxpbnB1dCB0eXBlPVwiY2hlY2tib3hcIiBmb3JtQ29udHJvbE5hbWU9XCJzaG93VGltZXN0YW1wXCIgbmFtZT1cInNob3dUaW1lc3RhbXBcIiAvPlxuICAgICAgICAgICAgICA8c3Bhbj48L3NwYW4+XG4gICAgICAgICAgICAgIDxzcGFuIHRyYW5zbGF0ZT5TaG93IHRpbWVzdGFtcDwvc3Bhbj5cbiAgICAgICAgICAgIDwvbGFiZWw+XG4gICAgICAgICAgPC9jOHktZm9ybS1ncm91cD5cblxuICAgICAgICAgIDxjOHktZm9ybS1ncm91cD5cbiAgICAgICAgICAgIDxsYWJlbCBbdGl0bGVdPVwiJ1Nob3cgaWNvbicgfCB0cmFuc2xhdGVcIiBjbGFzcz1cImM4eS1jaGVja2JveFwiPlxuICAgICAgICAgICAgICA8aW5wdXQgdHlwZT1cImNoZWNrYm94XCIgZm9ybUNvbnRyb2xOYW1lPVwic2hvd0ljb25cIiBuYW1lPVwic2hvd0ljb25cIiAvPlxuICAgICAgICAgICAgICA8c3Bhbj48L3NwYW4+XG4gICAgICAgICAgICAgIDxzcGFuIHRyYW5zbGF0ZT5TaG93IGljb248L3NwYW4+XG4gICAgICAgICAgICA8L2xhYmVsPlxuICAgICAgICAgIDwvYzh5LWZvcm0tZ3JvdXA+XG5cbiAgICAgICAgICA8Yzh5LWZvcm0tZ3JvdXA+XG4gICAgICAgICAgICA8bGFiZWwgW3RpdGxlXT1cIidTaG93IHRyZW5kIGljb24nIHwgdHJhbnNsYXRlXCIgY2xhc3M9XCJjOHktY2hlY2tib3hcIj5cbiAgICAgICAgICAgICAgPGlucHV0IHR5cGU9XCJjaGVja2JveFwiIGZvcm1Db250cm9sTmFtZT1cInNob3dUcmVuZFwiIG5hbWU9XCJzaG93VHJlbmRcIiAvPlxuICAgICAgICAgICAgICA8c3Bhbj48L3NwYW4+XG4gICAgICAgICAgICAgIDxzcGFuIHRyYW5zbGF0ZT5TaG93IHRyZW5kIGljb248L3NwYW4+XG4gICAgICAgICAgICAgIDxidXR0b25cbiAgICAgICAgICAgICAgICBjbGFzcz1cImJ0bi1oZWxwIGJ0bi1oZWxwLS1zbVwiXG4gICAgICAgICAgICAgICAgdHlwZT1cImJ1dHRvblwiXG4gICAgICAgICAgICAgICAgW2F0dHIuYXJpYS1sYWJlbF09XCInSGVscCcgfCB0cmFuc2xhdGVcIlxuICAgICAgICAgICAgICAgIHBvcG92ZXI9XCJ7e1xuICAgICAgICAgICAgICAgICAgJ0luZGljYXRlcyB0aGUgdHJlbmQgYmV0d2VlbiB0aGUgbGFzdCB0d28gbWVhc3VyZW1lbnQgdmFsdWVzLicgfCB0cmFuc2xhdGVcbiAgICAgICAgICAgICAgICB9fVwiXG4gICAgICAgICAgICAgICAgcGxhY2VtZW50PVwicmlnaHRcIlxuICAgICAgICAgICAgICAgIHRyaWdnZXJzPVwiZm9jdXNcIlxuICAgICAgICAgICAgICAgIGNvbnRhaW5lcj1cImJvZHlcIlxuICAgICAgICAgICAgICA+PC9idXR0b24+XG4gICAgICAgICAgICA8L2xhYmVsPlxuICAgICAgICAgIDwvYzh5LWZvcm0tZ3JvdXA+XG4gICAgICAgIDwvZGl2PlxuXG4gICAgICAgIDxjOHktZm9ybS1ncm91cD5cbiAgICAgICAgICA8bGFiZWwgW3RpdGxlXT1cIidGb250IHNpemUgb2YgbWVhc3VyZW1lbnQgdmFsdWUgKHB4KScgfCB0cmFuc2xhdGVcIiB0cmFuc2xhdGU+XG4gICAgICAgICAgICBGb250IHNpemUgb2YgbWVhc3VyZW1lbnQgdmFsdWUgKHB4KVxuICAgICAgICAgIDwvbGFiZWw+XG4gICAgICAgICAgPGlucHV0XG4gICAgICAgICAgICBjbGFzcz1cImZvcm0tY29udHJvbFwiXG4gICAgICAgICAgICBmb3JtQ29udHJvbE5hbWU9XCJmb250U2l6ZVwiXG4gICAgICAgICAgICBuYW1lPVwiZm9udFNpemVcIlxuICAgICAgICAgICAgdHlwZT1cIm51bWJlclwiXG4gICAgICAgICAgICBbcGxhY2Vob2xkZXJdPVwiJ2UuZy4ge3sgZXhhbXBsZSB9fScgfCB0cmFuc2xhdGU6IHsgZXhhbXBsZTogMzYgfVwiXG4gICAgICAgICAgLz5cbiAgICAgICAgICA8Yzh5LW1lc3NhZ2VzXG4gICAgICAgICAgICBbc2hvd109XCJmb3JtR3JvdXAuY29udHJvbHM/LmZvbnRTaXplPy50b3VjaGVkICYmIGZvcm1Hcm91cD8uY29udHJvbHM/LmZvbnRTaXplPy5lcnJvcnNcIlxuICAgICAgICAgID48L2M4eS1tZXNzYWdlcz5cbiAgICAgICAgPC9jOHktZm9ybS1ncm91cD5cbiAgICAgIDwvZGl2PlxuICAgIDwvZGl2PlxuICA8L2Zvcm0+XG48L2Rpdj5cbiJdfQ==