@c8y/ngx-components
Version:
Angular modules for Cumulocity IoT applications
74 lines • 39 kB
JavaScript
import { Component } from '@angular/core';
import { Router, RouterModule } from '@angular/router';
import { InventoryService } from '@c8y/client';
import { AlertService, CoreModule, gettext, ModalService } from '@c8y/ngx-components';
import { TranslateService } from '@ngx-translate/core';
import { BehaviorSubject, pipe } from 'rxjs';
import { map, shareReplay, switchMap, tap } from 'rxjs/operators';
import { pathToDatapointLibrary } from '@c8y/ngx-components/datapoint-library/model';
import { A11yModule } from '@angular/cdk/a11y';
import { BsDropdownModule } from 'ngx-bootstrap/dropdown';
import { DatapointParserService } from '@c8y/ngx-components/datapoint-library/services';
import * as i0 from "@angular/core";
import * as i1 from "@c8y/client";
import * as i2 from "@angular/router";
import * as i3 from "@c8y/ngx-components";
import * as i4 from "@ngx-translate/core";
import * as i5 from "@c8y/ngx-components/datapoint-library/services";
import * as i6 from "@angular/cdk/a11y";
import * as i7 from "@angular/common";
import * as i8 from "ngx-bootstrap/dropdown";
export class DatapointLibraryListComponent {
constructor(inventory, router, modalService, translateService, alertService, parser) {
this.inventory = inventory;
this.router = router;
this.modalService = modalService;
this.translateService = translateService;
this.alertService = alertService;
this.parser = parser;
this.title = gettext('Data point library');
this.listClass = '';
this.isLoading = true;
this.reload$ = new BehaviorSubject(null);
this.datapoints$ = this.reload$.pipe(tap(() => {
this.isLoading = true;
}), switchMap(() => this.getDatapoints()), tap(() => {
this.isLoading = false;
}), shareReplay());
this.parsePipe = pipe(map((data) => this.parser.parseDatapoints(data)));
}
getDatapoints() {
return this.inventory.list({ pageSize: 20, fragmentType: 'c8y_Kpi', withTotalPages: true });
}
addDatapointEntry() {
this.router.navigate([pathToDatapointLibrary, 'new']);
}
editDatapointEntry(entry) {
this.router.navigate([pathToDatapointLibrary, entry.id]);
}
async removeDatapointEntry(entry) {
try {
await this.modalService.confirm(gettext('Delete data point'), this.translateService.instant(gettext('You are about to delete data point "{{ dpLabel }}". Do you want to proceed?'), { dpLabel: entry.c8y_Kpi.label }), 'danger');
}
catch (e) {
return;
}
try {
await this.inventory.delete(entry.id);
this.reload$.next();
}
catch (e) {
this.alertService.addServerFailure(e);
}
}
reload() {
this.reload$.next();
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DatapointLibraryListComponent, deps: [{ token: i1.InventoryService }, { token: i2.Router }, { token: i3.ModalService }, { token: i4.TranslateService }, { token: i3.AlertService }, { token: i5.DatapointParserService }], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: DatapointLibraryListComponent, isStandalone: true, selector: "c8y-datapoint-library-list", ngImport: i0, template: "<c8y-title>{{ title | translate }}</c8y-title>\n<c8y-breadcrumb>\n <c8y-breadcrumb-item\n [icon]=\"'c8y-tools'\"\n [label]=\"'Configuration' | translate\"\n ></c8y-breadcrumb-item>\n <c8y-breadcrumb-item\n [icon]=\"'c8y-tools'\"\n [label]=\"title | translate\"\n ></c8y-breadcrumb-item>\n</c8y-breadcrumb>\n<c8y-action-bar-item\n [placement]=\"'right'\"\n *c8yIfAllowed=\"['ROLE_INVENTORY_ADMIN']\"\n [priority]=\"1\"\n>\n <button\n class=\"btn btn-link\"\n [title]=\"'Add data point' | translate\"\n type=\"button\"\n (click)=\"addDatapointEntry()\"\n data-cy=\"c8y-datapoint-library-list--add-data-point\"\n >\n <i c8yIcon=\"plus-circle\"></i>\n {{ 'Add data point' | translate }}\n </button>\n</c8y-action-bar-item>\n\n<c8y-action-bar-item\n [placement]=\"'right'\"\n [priority]=\"0\"\n>\n <button\n class=\"btn btn-link\"\n [title]=\"'Reload' | translate\"\n type=\"button\"\n [disabled]=\"isLoading\"\n (click)=\"reload()\"\n >\n <i\n c8yIcon=\"refresh\"\n [ngClass]=\"{ 'icon-spin': isLoading }\"\n ></i>\n {{ 'Reload' | translate }}\n </button>\n</c8y-action-bar-item>\n\n<c8y-action-bar-item\n [placement]=\"'left'\"\n itemClass=\"navbar-form hidden-xs\"\n>\n <c8y-list-display-switch\n (onListClassChange)=\"listClass = $event\"\n [listLength]=\"(datapoints$ | async)?.data?.length\"\n ></c8y-list-display-switch>\n</c8y-action-bar-item>\n\n<c8y-help src=\"/docs/cockpit/data-point-library/#data-point-library\"></c8y-help>\n\n<!-- empty state\n-->\n<c8y-ui-empty-state\n [icon]=\"'c8y-data-points'\"\n [title]=\"'No data points to display.' | translate\"\n [subtitle]=\"'Add a data point using the button below.' | translate\"\n *ngIf=\"(datapoints$ | async)?.data?.length === 0\"\n>\n <p>\n <button\n class=\"btn btn-primary\"\n [title]=\"'Add data point' | translate\"\n type=\"button\"\n (click)=\"addDatapointEntry()\"\n >\n <i c8yIcon=\"plus-circle\"></i>\n {{ 'Add data point' | translate }}\n </button>\n </p>\n</c8y-ui-empty-state>\n\n<!-- loading indicator -->\n<div\n class=\"d-flex j-c-center\"\n *ngIf=\"isLoading\"\n>\n <c8y-loading></c8y-loading>\n</div>\n\n<div\n class=\"card-group\"\n [ngClass]=\"listClass\"\n *ngIf=\"!isLoading && (datapoints$ | async) as datapoints\"\n>\n <div\n class=\"page-sticky-header hidden-xs\"\n *ngIf=\"datapoints.data.length\"\n >\n <div class=\"d-flex\">\n <div class=\"card-header\">\n <div class=\"card-icon\"></div>\n <p translate>Label</p>\n </div>\n <div class=\"card-actions\"></div>\n <div class=\"card-block p-l-0\">\n <div class=\"col-sm-3 p-l-16\">\n <p translate>Fragment</p>\n </div>\n <div class=\"col-sm-2\">\n <p translate>Series</p>\n </div>\n <div class=\"col-sm-1\">\n <span translate>Unit</span>\n </div>\n <div class=\"col-sm-2\">\n <span translate>Target</span>\n </div>\n <div class=\"col-sm-4\">\n <span translate>Range</span>\n </div>\n </div>\n </div>\n </div>\n <div\n class=\"col-sm-6 col-md-4 col-lg-3 col-xs-12\"\n *c8yFor=\"let datapoint of datapoints; loadMore: 'hidden'; pipe: parsePipe\"\n >\n <div\n class=\"card pointer\"\n (click)=\"editDatapointEntry(datapoint)\"\n >\n <div\n class=\"card-actions\"\n (click)=\"$event.stopPropagation()\"\n >\n <div\n class=\"dropdown settings pull-right\"\n dropdown\n #datapointOptionsDropdown=\"bs-dropdown\"\n [cdkTrapFocus]=\"datapointOptionsDropdown.isOpen\"\n >\n <button\n class=\"dropdown-toggle c8y-dropdown\"\n [title]=\"'Actions' | translate\"\n type=\"button\"\n dropdownToggle\n >\n <i c8yIcon=\"ellipsis-v\"></i>\n </button>\n <ul\n class=\"dropdown-menu\"\n *dropdownMenu\n >\n <li>\n <button\n [title]=\"'Edit' | translate\"\n type=\"button\"\n (click)=\"editDatapointEntry(datapoint)\"\n >\n <i c8yIcon=\"pencil\"></i>\n {{ 'Edit' | translate }}\n </button>\n </li>\n <li>\n <button\n [title]=\"'Remove' | translate\"\n type=\"button\"\n (click)=\"removeDatapointEntry(datapoint)\"\n >\n <i c8yIcon=\"delete\"></i>\n {{ 'Remove' | translate }}\n </button>\n </li>\n </ul>\n </div>\n </div>\n\n <div class=\"card-header separator\">\n <div class=\"card-icon\">\n <i\n c8yIcon=\"circle\"\n [style.color]=\"datapoint.c8y_Kpi?.color\"\n ></i>\n </div>\n <div\n class=\"card-title text-truncate\"\n [title]=\"datapoint.c8y_Kpi?.label\"\n >\n {{ datapoint.c8y_Kpi?.label }}\n </div>\n </div>\n <div class=\"card-block bg-level-1 p-b-24 card-hidden-list\">\n <div class=\"col-sm-3 col-md-2\">\n <c8y-range-display\n [config]=\"datapoint.c8y_Kpi\"\n [display]=\"'compact'\"\n ></c8y-range-display>\n </div>\n </div>\n <div class=\"card-block\">\n <div class=\"col-sm-3 text-truncate\">\n <span>\n <label\n class=\"text-label-small m-r-4\"\n translate\n >\n Fragment\n </label>\n <span [title]=\"datapoint.c8y_Kpi?.fragment\">\n {{ datapoint.c8y_Kpi?.fragment }}\n </span>\n </span>\n </div>\n <div class=\"col-sm-2 text-truncate\">\n <label\n class=\"text-label-small m-r-4\"\n translate\n >\n Series\n </label>\n <span [title]=\"datapoint.c8y_Kpi?.series\">\n {{ datapoint.c8y_Kpi?.series }}\n </span>\n </div>\n <div class=\"col-sm-1 text-truncate card-hidden-grid\">\n <span *ngIf=\"datapoint.c8y_Kpi?.unit\">\n <label\n class=\"text-label-small m-r-4\"\n translate\n >\n Unit\n </label>\n <span [title]=\"datapoint.c8y_Kpi?.unit\">\n {{ datapoint.c8y_Kpi?.unit }}\n </span>\n </span>\n </div>\n <div class=\"col-sm-2 text-truncate\">\n <span *ngIf=\"datapoint.c8y_Kpi?.target\">\n <label\n class=\"text-label-small m-r-4\"\n translate\n >\n Target\n </label>\n <span [title]=\"datapoint.c8y_Kpi?.target\">\n {{ datapoint.c8y_Kpi?.target }}\n </span>\n </span>\n </div>\n <div class=\"col-sm-4 card-hidden-grid\">\n <c8y-range-display\n [config]=\"datapoint.c8y_Kpi\"\n [display]=\"'inline'\"\n ></c8y-range-display>\n </div>\n </div>\n </div>\n </div>\n</div>\n", dependencies: [{ kind: "ngmodule", type: A11yModule }, { kind: "directive", type: i6.CdkTrapFocus, selector: "[cdkTrapFocus]", inputs: ["cdkTrapFocus", "cdkTrapFocusAutoCapture"], exportAs: ["cdkTrapFocus"] }, { kind: "ngmodule", type: CoreModule }, { kind: "component", type: i3.ActionBarItemComponent, selector: "c8y-action-bar-item", inputs: ["placement", "priority", "itemClass", "injector", "groupId", "inGroupPriority"] }, { kind: "component", type: i3.BreadcrumbComponent, selector: "c8y-breadcrumb" }, { kind: "component", type: i3.BreadcrumbItemComponent, selector: "c8y-breadcrumb-item", inputs: ["icon", "translate", "label", "path", "injector"] }, { kind: "component", type: i3.EmptyStateComponent, selector: "c8y-ui-empty-state", inputs: ["icon", "title", "subtitle", "horizontal"] }, { kind: "directive", type: i3.IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "pipe", type: i3.C8yTranslatePipe, name: "translate" }, { kind: "directive", type: i3.C8yTranslateDirective, selector: "[translate],[ngx-translate]" }, { kind: "directive", type: i7.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i7.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "pipe", type: i7.AsyncPipe, name: "async" }, { kind: "directive", type: i3.IfAllowedDirective, selector: "[c8yIfAllowed]", inputs: ["c8yIfAllowed", "c8yIfAllowedAllowAny"] }, { kind: "directive", type: i3.ForOfDirective, selector: "[c8yFor]", inputs: ["c8yForOf", "c8yForLoadMore", "c8yForPipe", "c8yForNotFound", "c8yForMaxIterations", "c8yForLoadingTemplate", "c8yForLoadNextLabel", "c8yForLoadingLabel", "c8yForRealtime", "c8yForRealtimeOptions", "c8yForComparator", "c8yForEnableVirtualScroll", "c8yForVirtualScrollElementSize", "c8yForVirtualScrollStrategy", "c8yForVirtualScrollContainerHeight"], outputs: ["c8yForCount", "c8yForChange", "c8yForLoadMoreComponent"] }, { kind: "component", type: i3.LoadingComponent, selector: "c8y-loading", inputs: ["layout", "progress", "message"] }, { kind: "component", type: i3.TitleComponent, selector: "c8y-title", inputs: ["pageTitleUpdate"] }, { kind: "component", type: i3.HelpComponent, selector: "c8y-help", inputs: ["src", "isCollapsed", "priority", "icon"] }, { kind: "component", type: i3.RangeDisplayComponent, selector: "c8y-range-display", inputs: ["config", "display"] }, { kind: "component", type: i3.ListDisplaySwitchComponent, selector: "c8y-list-display-switch", inputs: ["listKey", "listLength", "filterPipe"], outputs: ["onListClassChange"] }, { kind: "ngmodule", type: BsDropdownModule }, { kind: "directive", type: i8.BsDropdownMenuDirective, selector: "[bsDropdownMenu],[dropdownMenu]", exportAs: ["bs-dropdown-menu"] }, { kind: "directive", type: i8.BsDropdownToggleDirective, selector: "[bsDropdownToggle],[dropdownToggle]", exportAs: ["bs-dropdown-toggle"] }, { kind: "directive", type: i8.BsDropdownDirective, selector: "[bsDropdown], [dropdown]", inputs: ["placement", "triggers", "container", "dropup", "autoClose", "isAnimated", "insideClick", "isDisabled", "isOpen"], outputs: ["isOpenChange", "onShown", "onHidden"], exportAs: ["bs-dropdown"] }, { kind: "ngmodule", type: RouterModule }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DatapointLibraryListComponent, decorators: [{
type: Component,
args: [{ selector: 'c8y-datapoint-library-list', standalone: true, imports: [A11yModule, CoreModule, BsDropdownModule, RouterModule], template: "<c8y-title>{{ title | translate }}</c8y-title>\n<c8y-breadcrumb>\n <c8y-breadcrumb-item\n [icon]=\"'c8y-tools'\"\n [label]=\"'Configuration' | translate\"\n ></c8y-breadcrumb-item>\n <c8y-breadcrumb-item\n [icon]=\"'c8y-tools'\"\n [label]=\"title | translate\"\n ></c8y-breadcrumb-item>\n</c8y-breadcrumb>\n<c8y-action-bar-item\n [placement]=\"'right'\"\n *c8yIfAllowed=\"['ROLE_INVENTORY_ADMIN']\"\n [priority]=\"1\"\n>\n <button\n class=\"btn btn-link\"\n [title]=\"'Add data point' | translate\"\n type=\"button\"\n (click)=\"addDatapointEntry()\"\n data-cy=\"c8y-datapoint-library-list--add-data-point\"\n >\n <i c8yIcon=\"plus-circle\"></i>\n {{ 'Add data point' | translate }}\n </button>\n</c8y-action-bar-item>\n\n<c8y-action-bar-item\n [placement]=\"'right'\"\n [priority]=\"0\"\n>\n <button\n class=\"btn btn-link\"\n [title]=\"'Reload' | translate\"\n type=\"button\"\n [disabled]=\"isLoading\"\n (click)=\"reload()\"\n >\n <i\n c8yIcon=\"refresh\"\n [ngClass]=\"{ 'icon-spin': isLoading }\"\n ></i>\n {{ 'Reload' | translate }}\n </button>\n</c8y-action-bar-item>\n\n<c8y-action-bar-item\n [placement]=\"'left'\"\n itemClass=\"navbar-form hidden-xs\"\n>\n <c8y-list-display-switch\n (onListClassChange)=\"listClass = $event\"\n [listLength]=\"(datapoints$ | async)?.data?.length\"\n ></c8y-list-display-switch>\n</c8y-action-bar-item>\n\n<c8y-help src=\"/docs/cockpit/data-point-library/#data-point-library\"></c8y-help>\n\n<!-- empty state\n-->\n<c8y-ui-empty-state\n [icon]=\"'c8y-data-points'\"\n [title]=\"'No data points to display.' | translate\"\n [subtitle]=\"'Add a data point using the button below.' | translate\"\n *ngIf=\"(datapoints$ | async)?.data?.length === 0\"\n>\n <p>\n <button\n class=\"btn btn-primary\"\n [title]=\"'Add data point' | translate\"\n type=\"button\"\n (click)=\"addDatapointEntry()\"\n >\n <i c8yIcon=\"plus-circle\"></i>\n {{ 'Add data point' | translate }}\n </button>\n </p>\n</c8y-ui-empty-state>\n\n<!-- loading indicator -->\n<div\n class=\"d-flex j-c-center\"\n *ngIf=\"isLoading\"\n>\n <c8y-loading></c8y-loading>\n</div>\n\n<div\n class=\"card-group\"\n [ngClass]=\"listClass\"\n *ngIf=\"!isLoading && (datapoints$ | async) as datapoints\"\n>\n <div\n class=\"page-sticky-header hidden-xs\"\n *ngIf=\"datapoints.data.length\"\n >\n <div class=\"d-flex\">\n <div class=\"card-header\">\n <div class=\"card-icon\"></div>\n <p translate>Label</p>\n </div>\n <div class=\"card-actions\"></div>\n <div class=\"card-block p-l-0\">\n <div class=\"col-sm-3 p-l-16\">\n <p translate>Fragment</p>\n </div>\n <div class=\"col-sm-2\">\n <p translate>Series</p>\n </div>\n <div class=\"col-sm-1\">\n <span translate>Unit</span>\n </div>\n <div class=\"col-sm-2\">\n <span translate>Target</span>\n </div>\n <div class=\"col-sm-4\">\n <span translate>Range</span>\n </div>\n </div>\n </div>\n </div>\n <div\n class=\"col-sm-6 col-md-4 col-lg-3 col-xs-12\"\n *c8yFor=\"let datapoint of datapoints; loadMore: 'hidden'; pipe: parsePipe\"\n >\n <div\n class=\"card pointer\"\n (click)=\"editDatapointEntry(datapoint)\"\n >\n <div\n class=\"card-actions\"\n (click)=\"$event.stopPropagation()\"\n >\n <div\n class=\"dropdown settings pull-right\"\n dropdown\n #datapointOptionsDropdown=\"bs-dropdown\"\n [cdkTrapFocus]=\"datapointOptionsDropdown.isOpen\"\n >\n <button\n class=\"dropdown-toggle c8y-dropdown\"\n [title]=\"'Actions' | translate\"\n type=\"button\"\n dropdownToggle\n >\n <i c8yIcon=\"ellipsis-v\"></i>\n </button>\n <ul\n class=\"dropdown-menu\"\n *dropdownMenu\n >\n <li>\n <button\n [title]=\"'Edit' | translate\"\n type=\"button\"\n (click)=\"editDatapointEntry(datapoint)\"\n >\n <i c8yIcon=\"pencil\"></i>\n {{ 'Edit' | translate }}\n </button>\n </li>\n <li>\n <button\n [title]=\"'Remove' | translate\"\n type=\"button\"\n (click)=\"removeDatapointEntry(datapoint)\"\n >\n <i c8yIcon=\"delete\"></i>\n {{ 'Remove' | translate }}\n </button>\n </li>\n </ul>\n </div>\n </div>\n\n <div class=\"card-header separator\">\n <div class=\"card-icon\">\n <i\n c8yIcon=\"circle\"\n [style.color]=\"datapoint.c8y_Kpi?.color\"\n ></i>\n </div>\n <div\n class=\"card-title text-truncate\"\n [title]=\"datapoint.c8y_Kpi?.label\"\n >\n {{ datapoint.c8y_Kpi?.label }}\n </div>\n </div>\n <div class=\"card-block bg-level-1 p-b-24 card-hidden-list\">\n <div class=\"col-sm-3 col-md-2\">\n <c8y-range-display\n [config]=\"datapoint.c8y_Kpi\"\n [display]=\"'compact'\"\n ></c8y-range-display>\n </div>\n </div>\n <div class=\"card-block\">\n <div class=\"col-sm-3 text-truncate\">\n <span>\n <label\n class=\"text-label-small m-r-4\"\n translate\n >\n Fragment\n </label>\n <span [title]=\"datapoint.c8y_Kpi?.fragment\">\n {{ datapoint.c8y_Kpi?.fragment }}\n </span>\n </span>\n </div>\n <div class=\"col-sm-2 text-truncate\">\n <label\n class=\"text-label-small m-r-4\"\n translate\n >\n Series\n </label>\n <span [title]=\"datapoint.c8y_Kpi?.series\">\n {{ datapoint.c8y_Kpi?.series }}\n </span>\n </div>\n <div class=\"col-sm-1 text-truncate card-hidden-grid\">\n <span *ngIf=\"datapoint.c8y_Kpi?.unit\">\n <label\n class=\"text-label-small m-r-4\"\n translate\n >\n Unit\n </label>\n <span [title]=\"datapoint.c8y_Kpi?.unit\">\n {{ datapoint.c8y_Kpi?.unit }}\n </span>\n </span>\n </div>\n <div class=\"col-sm-2 text-truncate\">\n <span *ngIf=\"datapoint.c8y_Kpi?.target\">\n <label\n class=\"text-label-small m-r-4\"\n translate\n >\n Target\n </label>\n <span [title]=\"datapoint.c8y_Kpi?.target\">\n {{ datapoint.c8y_Kpi?.target }}\n </span>\n </span>\n </div>\n <div class=\"col-sm-4 card-hidden-grid\">\n <c8y-range-display\n [config]=\"datapoint.c8y_Kpi\"\n [display]=\"'inline'\"\n ></c8y-range-display>\n </div>\n </div>\n </div>\n </div>\n</div>\n" }]
}], ctorParameters: () => [{ type: i1.InventoryService }, { type: i2.Router }, { type: i3.ModalService }, { type: i4.TranslateService }, { type: i3.AlertService }, { type: i5.DatapointParserService }] });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGF0YXBvaW50LWxpYnJhcnktbGlzdC5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9kYXRhcG9pbnQtbGlicmFyeS9saXN0L2RhdGFwb2ludC1saWJyYXJ5LWxpc3QuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vZGF0YXBvaW50LWxpYnJhcnkvbGlzdC9kYXRhcG9pbnQtbGlicmFyeS1saXN0LmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDMUMsT0FBTyxFQUFFLE1BQU0sRUFBRSxZQUFZLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUN2RCxPQUFPLEVBQWtCLGdCQUFnQixFQUFlLE1BQU0sYUFBYSxDQUFDO0FBQzVFLE9BQU8sRUFBRSxZQUFZLEVBQUUsVUFBVSxFQUFFLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUN0RixPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUN2RCxPQUFPLEVBQUUsZUFBZSxFQUFjLElBQUksRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUN6RCxPQUFPLEVBQUUsR0FBRyxFQUFFLFdBQVcsRUFBRSxTQUFTLEVBQUUsR0FBRyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDbEUsT0FBTyxFQUFFLHNCQUFzQixFQUFFLE1BQU0sNkNBQTZDLENBQUM7QUFDckYsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLG1CQUFtQixDQUFDO0FBQy9DLE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBQzFELE9BQU8sRUFBRSxzQkFBc0IsRUFBRSxNQUFNLGdEQUFnRCxDQUFDOzs7Ozs7Ozs7O0FBUXhGLE1BQU0sT0FBTyw2QkFBNkI7SUFrQnhDLFlBQ1UsU0FBMkIsRUFDM0IsTUFBYyxFQUNkLFlBQTBCLEVBQzFCLGdCQUFrQyxF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QUNFLDRCQUE0QixjQUUxQixJQUFJLFdBQ1AsQ0FBQyxVQUFVLEVBQUUsVUFBVSxFQUFFLGdCQUFnQixFQUFFLFlBQVksQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENvbXBvbmVudCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgUm91dGVyLCBSb3V0ZXJNb2R1bGUgfSBmcm9tICdAYW5ndWxhci9yb3V0ZXInO1xuaW1wb3J0IHsgSU1hbmFnZWRPYmplY3QsIEludmVudG9yeVNlcnZpY2UsIElSZXN1bHRMaXN0IH0gZnJvbSAnQGM4eS9jbGllbnQnO1xuaW1wb3J0IHsgQWxlcnRTZXJ2aWNlLCBDb3JlTW9kdWxlLCBnZXR0ZXh0LCBNb2RhbFNlcnZpY2UgfSBmcm9tICdAYzh5L25neC1jb21wb25lbnRzJztcbmltcG9ydCB7IFRyYW5zbGF0ZVNlcnZpY2UgfSBmcm9tICdAbmd4LXRyYW5zbGF0ZS9jb3JlJztcbmltcG9ydCB7IEJlaGF2aW9yU3ViamVjdCwgT2JzZXJ2YWJsZSwgcGlwZSB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgbWFwLCBzaGFyZVJlcGxheSwgc3dpdGNoTWFwLCB0YXAgfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XG5pbXBvcnQgeyBwYXRoVG9EYXRhcG9pbnRMaWJyYXJ5IH0gZnJvbSAnQGM4eS9uZ3gtY29tcG9uZW50cy9kYXRhcG9pbnQtbGlicmFyeS9tb2RlbCc7XG5pbXBvcnQgeyBBMTF5TW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvY2RrL2ExMXknO1xuaW1wb3J0IHsgQnNEcm9wZG93bk1vZHVsZSB9IGZyb20gJ25neC1ib290c3RyYXAvZHJvcGRvd24nO1xuaW1wb3J0IHsgRGF0YXBvaW50UGFyc2VyU2VydmljZSB9IGZyb20gJ0BjOHkvbmd4LWNvbXBvbmVudHMvZGF0YXBvaW50LWxpYnJhcnkvc2VydmljZXMnO1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdjOHktZGF0YXBvaW50LWxpYnJhcnktbGlzdCcsXG4gIHRlbXBsYXRlVXJsOiAnLi9kYXRhcG9pbnQtbGlicmFyeS1saXN0LmNvbXBvbmVudC5odG1sJyxcbiAgc3RhbmRhbG9uZTogdHJ1ZSxcbiAgaW1wb3J0czogW0ExMXlNb2R1bGUsIENvcmVNb2R1bGUsIEJzRHJvcGRvd25Nb2R1bGUsIFJvdXRlck1vZHVsZV1cbn0pXG5leHBvcnQgY2xhc3MgRGF0YXBvaW50TGlicmFyeUxpc3RDb21wb25lbnQge1xuICByZWFkb25seSB0aXRsZSA9IGdldHRleHQoJ0RhdGEgcG9pbnQgbGlicmFyeScpO1xuICBsaXN0Q2xhc3MgPSAnJztcbiAgaXNMb2FkaW5nID0gdHJ1ZTtcbiAgcmVsb2FkJDogQmVoYXZpb3JTdWJqZWN0PHZvaWQ+ID0gbmV3IEJlaGF2aW9yU3ViamVjdChudWxsKTtcbiAgZGF0YXBvaW50cyQ6IE9ic2VydmFibGU8SVJlc3VsdExpc3Q8SU1hbmFnZWRPYmplY3Q+PiA9IHRoaXMucmVsb2FkJC5waXBlKFxuICAgIHRhcCgoKSA9PiB7XG4gICAgICB0aGlzLmlzTG9hZGluZyA9IHRydWU7XG4gICAgfSksXG4gICAgc3dpdGNoTWFwKCgpID0+IHRoaXMuZ2V0RGF0YXBvaW50cygpKSxcbiAgICB0YXAoKCkgPT4ge1xuICAgICAgdGhpcy5pc0xvYWRpbmcgPSBmYWxzZTtcbiAgICB9KSxcbiAgICBzaGFyZVJlcGxheSgpXG4gICk7XG5cbiAgcGFyc2VQaXBlID0gcGlwZShtYXAoKGRhdGE6IElNYW5hZ2VkT2JqZWN0W10pID0+IHRoaXMucGFyc2VyLnBhcnNlRGF0YXBvaW50cyhkYXRhKSkpO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgaW52ZW50b3J5OiBJbnZlbnRvcnlTZXJ2aWNlLFxuICAgIHByaXZhdGUgcm91dGVyOiBSb3V0ZXIsXG4gICAgcHJpdmF0ZSBtb2RhbFNlcnZpY2U6IE1vZGFsU2VydmljZSxcbiAgICBwcml2YXRlIHRyYW5zbGF0ZVNlcnZpY2U6IFRyYW5zbGF0ZVNlcnZpY2UsXG4gICAgcHJpdmF0ZSBhbGVydFNlcnZpY2U6IEFsZXJ0U2VydmljZSxcbiAgICBwcml2YXRlIHBhcnNlcjogRGF0YXBvaW50UGFyc2VyU2VydmljZVxuICApIHt9XG5cbiAgZ2V0RGF0YXBvaW50cygpOiBQcm9taXNlPElSZXN1bHRMaXN0PElNYW5hZ2VkT2JqZWN0Pj4ge1xuICAgIHJldHVybiB0aGlzLmludmVudG9yeS5saXN0KHsgcGFnZVNpemU6IDIwLCBmcmFnbWVudFR5cGU6ICdjOHlfS3BpJywgd2l0aFRvdGFsUGFnZXM6IHRydWUgfSk7XG4gIH1cblxuICBhZGREYXRhcG9pbnRFbnRyeSgpIHtcbiAgICB0aGlzLnJvdXRlci5uYXZpZ2F0ZShbcGF0aFRvRGF0YXBvaW50TGlicmFyeSwgJ25ldyddKTtcbiAgfVxuXG4gIGVkaXREYXRhcG9pbnRFbnRyeShlbnRyeTogSU1hbmFnZWRPYmplY3QpIHtcbiAgICB0aGlzLnJvdXRlci5uYXZpZ2F0ZShbcGF0aFRvRGF0YXBvaW50TGlicmFyeSwgZW50cnkuaWRdKTtcbiAgfVxuXG4gIGFzeW5jIHJlbW92ZURhdGFwb2ludEVudHJ5KGVudHJ5OiBJTWFuYWdlZE9iamVjdCkge1xuICAgIHRyeSB7XG4gICAgICBhd2FpdCB0aGlzLm1vZGFsU2VydmljZS5jb25maXJtKFxuICAgICAgICBnZXR0ZXh0KCdEZWxldGUgZGF0YSBwb2ludCcpLFxuICAgICAgICB0aGlzLnRyYW5zbGF0ZVNlcnZpY2UuaW5zdGFudChcbiAgICAgICAgICBnZXR0ZXh0KCdZb3UgYXJlIGFib3V0IHRvIGRlbGV0ZSBkYXRhIHBvaW50IFwie3sgZHBMYWJlbCB9fVwiLiBEbyB5b3Ugd2FudCB0byBwcm9jZWVkPycpLFxuICAgICAgICAgIHsgZHBMYWJlbDogZW50cnkuYzh5X0twaS5sYWJlbCB9XG4gICAgICAgICksXG4gICAgICAgICdkYW5nZXInXG4gICAgICApO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdHJ5IHtcbiAgICAgIGF3YWl0IHRoaXMuaW52ZW50b3J5LmRlbGV0ZShlbnRyeS5pZCk7XG4gICAgICB0aGlzLnJlbG9hZCQubmV4dCgpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIHRoaXMuYWxlcnRTZXJ2aWNlLmFkZFNlcnZlckZhaWx1cmUoZSk7XG4gICAgfVxuICB9XG5cbiAgcmVsb2FkKCkge1xuICAgIHRoaXMucmVsb2FkJC5uZXh0KCk7XG4gIH1cbn1cbiIsIjxjOHktdGl0bGU+e3sgdGl0bGUgfCB0cmFuc2xhdGUgfX08L2M4eS10aXRsZT5cbjxjOHktYnJlYWRjcnVtYj5cbiAgPGM4eS1icmVhZGNydW1iLWl0ZW1cbiAgICBbaWNvbl09XCInYzh5LXRvb2xzJ1wiXG4gICAgW2xhYmVsXT1cIidDb25maWd1cmF0aW9uJyB8IHRyYW5zbGF0ZVwiXG4gID48L2M4eS1icmVhZGNydW1iLWl0ZW0+XG4gIDxjOHktYnJlYWRjcnVtYi1pdGVtXG4gICAgW2ljb25dPVwiJ2M4eS10b29scydcIlxuICAgIFtsYWJlbF09XCJ0aXRsZSB8IHRyYW5zbGF0ZVwiXG4gID48L2M4eS1icmVhZGNydW1iLWl0ZW0+XG48L2M4eS1icmVhZGNydW1iPlxuPGM4eS1hY3Rpb24tYmFyLWl0ZW1cbiAgW3BsYWNlbWVudF09XCIncmlnaHQnXCJcbiAgKmM4eUlmQWxsb3dlZD1cIlsnUk9MRV9JTlZFTlRPUllfQURNSU4nXVwiXG4gIFtwcmlvcml0eV09XCIxXCJcbj5cbiAgPGJ1dHRvblxuICAgIGNsYXNzPVwiYnRuIGJ0bi1saW5rXCJcbiAgICBbdGl0bGVdPVwiJ0FkZCBkYXRhIHBvaW50JyB8IHRyYW5zbGF0ZVwiXG4gICAgdHlwZT1cImJ1dHRvblwiXG4gICAgKGNsaWNrKT1cImFkZERhdGFwb2ludEVudHJ5KClcIlxuICAgIGRhdGEtY3k9XCJjOHktZGF0YXBvaW50LWxpYnJhcnktbGlzdC0tYWRkLWRhdGEtcG9pbnRcIlxuICA+XG4gICAgPGkgYzh5SWNvbj1cInBsdXMtY2lyY2xlXCI+PC9pPlxuICAgIHt7ICdBZGQgZGF0YSBwb2ludCcgfCB0cmFuc2xhdGUgfX1cbiAgPC9idXR0b24+XG48L2M4eS1hY3Rpb24tYmFyLWl0ZW0+XG5cbjxjOHktYWN0aW9uLWJhci1pdGVtXG4gIFtwbGFjZW1lbnRdPVwiJ3JpZ2h0J1wiXG4gIFtwcmlvcml0eV09XCIwXCJcbj5cbiAgPGJ1dHRvblxuICAgIGNsYXNzPVwiYnRuIGJ0bi1saW5rXCJcbiAgICBbdGl0bGVdPVwiJ1JlbG9hZCcgfCB0cmFuc2xhdGVcIlxuICAgIHR5cGU9XCJidXR0b25cIlxuICAgIFtkaXNhYmxlZF09XCJpc0xvYWRpbmdcIlxuICAgIChjbGljayk9XCJyZWxvYWQoKVwiXG4gID5cbiAgICA8aVxuICAgICAgYzh5SWNvbj1cInJlZnJlc2hcIlxuICAgICAgW25nQ2xhc3NdPVwieyAnaWNvbi1zcGluJzogaXNMb2FkaW5nIH1cIlxuICAgID48L2k+XG4gICAge3sgJ1JlbG9hZCcgfCB0cmFuc2xhdGUgfX1cbiAgPC9idXR0b24+XG48L2M4eS1hY3Rpb24tYmFyLWl0ZW0+XG5cbjxjOHktYWN0aW9uLWJhci1pdGVtXG4gIFtwbGFjZW1lbnRdPVwiJ2xlZnQnXCJcbiAgaXRlbUNsYXNzPVwibmF2YmFyLWZvcm0gaGlkZGVuLXhzXCJcbj5cbiAgPGM4eS1saXN0LWRpc3BsYXktc3dpdGNoXG4gICAgKG9uTGlzdENsYXNzQ2hhbmdlKT1cImxpc3RDbGFzcyA9ICRldmVudFwiXG4gICAgW2xpc3RMZW5ndGhdPVwiKGRhdGFwb2ludHMkIHwgYXN5bmMpPy5kYXRhPy5sZW5ndGhcIlxuICA+PC9jOHktbGlzdC1kaXNwbGF5LXN3aXRjaD5cbjwvYzh5LWFjdGlvbi1iYXItaXRlbT5cblxuPGM4eS1oZWxwIHNyYz1cIi9kb2NzL2NvY2twaXQvZGF0YS1wb2ludC1saWJyYXJ5LyNkYXRhLXBvaW50LWxpYnJhcnlcIj48L2M4eS1oZWxwPlxuXG48IS0tIGVtcHR5IHN0YXRlXG4tLT5cbjxjOHktdWktZW1wdHktc3RhdGVcbiAgW2ljb25dPVwiJ2M4eS1kYXRhLXBvaW50cydcIlxuICBbdGl0bGVdPVwiJ05vIGRhdGEgcG9pbnRzIHRvIGRpc3BsYXkuJyB8IHRyYW5zbGF0ZVwiXG4gIFtzdWJ0aXRsZV09XCInQWRkIGEgZGF0YSBwb2ludCB1c2luZyB0aGUgYnV0dG9uIGJlbG93LicgfCB0cmFuc2xhdGVcIlxuICAqbmdJZj1cIihkYXRhcG9pbnRzJCB8IGFzeW5jKT8uZGF0YT8ubGVuZ3RoID09PSAwXCJcbj5cbiAgPHA+XG4gICAgPGJ1dHRvblxuICAgICAgY2xhc3M9XCJidG4gYnRuLXByaW1hcnlcIlxuICAgICAgW3RpdGxlXT1cIidBZGQgZGF0YSBwb2ludCcgfCB0cmFuc2xhdGVcIlxuICAgICAgdHlwZT1cImJ1dHRvblwiXG4gICAgICAoY2xpY2spPVwiYWRkRGF0YXBvaW50RW50cnkoKVwiXG4gICAgPlxuICAgICAgPGkgYzh5SWNvbj1cInBsdXMtY2lyY2xlXCI+PC9pPlxuICAgICAge3sgJ0FkZCBkYXRhIHBvaW50JyB8IHRyYW5zbGF0ZSB9fVxuICAgIDwvYnV0dG9uPlxuICA8L3A+XG48L2M4eS11aS1lbXB0eS1zdGF0ZT5cblxuPCEtLSBsb2FkaW5nIGluZGljYXRvciAtLT5cbjxkaXZcbiAgY2xhc3M9XCJkLWZsZXggai1jLWNlbnRlclwiXG4gICpuZ0lmPVwiaXNMb2FkaW5nXCJcbj5cbiAgPGM4eS1sb2FkaW5nPjwvYzh5LWxvYWRpbmc+XG48L2Rpdj5cblxuPGRpdlxuICBjbGFzcz1cImNhcmQtZ3JvdXBcIlxuICBbbmdDbGFzc109XCJsaXN0Q2xhc3NcIlxuICAqbmdJZj1cIiFpc0xvYWRpbmcgJiYgKGRhdGFwb2ludHMkIHwgYXN5bmMpIGFzIGRhdGFwb2ludHNcIlxuPlxuICA8ZGl2XG4gICAgY2xhc3M9XCJwYWdlLXN0aWNreS1oZWFkZXIgaGlkZGVuLXhzXCJcbiAgICAqbmdJZj1cImRhdGFwb2ludHMuZGF0YS5sZW5ndGhcIlxuICA+XG4gICAgPGRpdiBjbGFzcz1cImQtZmxleFwiPlxuICAgICAgPGRpdiBjbGFzcz1cImNhcmQtaGVhZGVyXCI+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJjYXJkLWljb25cIj48L2Rpdj5cbiAgICAgICAgPHAgdHJhbnNsYXRlPkxhYmVsPC9wPlxuICAgICAgPC9kaXY+XG4gICAgICA8ZGl2IGNsYXNzPVwiY2FyZC1hY3Rpb25zXCI+PC9kaXY+XG4gICAgICA8ZGl2IGNsYXNzPVwiY2FyZC1ibG9jayBwLWwtMFwiPlxuICAgICAgICA8ZGl2IGNsYXNzPVwiY29sLXNtLTMgcC1sLTE2XCI+XG4gICAgICAgICAgPHAgdHJhbnNsYXRlPkZyYWdtZW50PC9wPlxuICAgICAgICA8L2Rpdj5cbiAgICAgICAgPGRpdiBjbGFzcz1cImNvbC1zbS0yXCI+XG4gICAgICAgICAgPHAgdHJhbnNsYXRlPlNlcmllczwvcD5cbiAgICAgICAgPC9kaXY+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJjb2wtc20tMVwiPlxuICAgICAgICAgIDxzcGFuIHRyYW5zbGF0ZT5Vbml0PC9zcGFuPlxuICAgICAgICA8L2Rpdj5cbiAgICAgICAgPGRpdiBjbGFzcz1cImNvbC1zbS0yXCI+XG4gICAgICAgICAgPHNwYW4gdHJhbnNsYXRlPlRhcmdldDwvc3Bhbj5cbiAgICAgICAgPC9kaXY+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJjb2wtc20tNFwiPlxuICAgICAgICAgIDxzcGFuIHRyYW5zbGF0ZT5SYW5nZTwvc3Bhbj5cbiAgICAgICAgPC9kaXY+XG4gICAgICA8L2Rpdj5cbiAgICA8L2Rpdj5cbiAgPC9kaXY+XG4gIDxkaXZcbiAgICBjbGFzcz1cImNvbC1zbS02IGNvbC1tZC00IGNvbC1sZy0zIGNvbC14cy0xMlwiXG4gICAgKmM4eUZvcj1cImxldCBkYXRhcG9pbnQgb2YgZGF0YXBvaW50czsgbG9hZE1vcmU6ICdoaWRkZW4nOyBwaXBlOiBwYXJzZVBpcGVcIlxuICA+XG4gICAgPGRpdlxuICAgICAgY2xhc3M9XCJjYXJkIHBvaW50ZXJcIlxuICAgICAgKGNsaWNrKT1cImVkaXREYXRhcG9pbnRFbnRyeShkYXRhcG9pbnQpXCJcbiAgICA+XG4gICAgICA8ZGl2XG4gICAgICAgIGNsYXNzPVwiY2FyZC1hY3Rpb25zXCJcbiAgICAgICAgKGNsaWNrKT1cIiRldmVudC5zdG9wUHJvcGFnYXRpb24oKVwiXG4gICAgICA+XG4gICAgICAgIDxkaXZcbiAgICAgICAgICBjbGFzcz1cImRyb3Bkb3duIHNldHRpbmdzIHB1bGwtcmlnaHRcIlxuICAgICAgICAgIGRyb3Bkb3duXG4gICAgICAgICAgI2RhdGFwb2ludE9wdGlvbnNEcm9wZG93bj1cImJzLWRyb3Bkb3duXCJcbiAgICAgICAgICBbY2RrVHJhcEZvY3VzXT1cImRhdGFwb2ludE9wdGlvbnNEcm9wZG93bi5pc09wZW5cIlxuICAgICAgICA+XG4gICAgICAgICAgPGJ1dHRvblxuICAgICAgICAgICAgY2xhc3M9XCJkcm9wZG93bi10b2dnbGUgYzh5LWRyb3Bkb3duXCJcbiAgICAgICAgICAgIFt0aXRsZV09XCInQWN0aW9ucycgfCB0cmFuc2xhdGVcIlxuICAgICAgICAgICAgdHlwZT1cImJ1dHRvblwiXG4gICAgICAgICAgICBkcm9wZG93blRvZ2dsZVxuICAgICAgICAgID5cbiAgICAgICAgICAgIDxpIGM4eUljb249XCJlbGxpcHNpcy12XCI+PC9pPlxuICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICAgIDx1bFxuICAgICAgICAgICAgY2xhc3M9XCJkcm9wZG93bi1tZW51XCJcbiAgICAgICAgICAgICpkcm9wZG93bk1lbnVcbiAgICAgICAgICA+XG4gICAgICAgICAgICA8bGk+XG4gICAgICAgICAgICAgIDxidXR0b25cbiAgICAgICAgICAgICAgICBbdGl0bGVdPVwiJ0VkaXQnIHwgdHJhbnNsYXRlXCJcbiAgICAgICAgICAgICAgICB0eXBlPVwiYnV0dG9uXCJcbiAgICAgICAgICAgICAgICAoY2xpY2spPVwiZWRpdERhdGFwb2ludEVudHJ5KGRhdGFwb2ludClcIlxuICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgPGkgYzh5SWNvbj1cInBlbmNpbFwiPjwvaT5cbiAgICAgICAgICAgICAgICB7eyAnRWRpdCcgfCB0cmFuc2xhdGUgfX1cbiAgICAgICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgICA8L2xpPlxuICAgICAgICAgICAgPGxpPlxuICAgICAgICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgICAgICAgW3RpdGxlXT1cIidSZW1vdmUnIHwgdHJhbnNsYXRlXCJcbiAgICAgICAgICAgICAgICB0eXBlPVwiYnV0dG9uXCJcbiAgICAgICAgICAgICAgICAoY2xpY2spPVwicmVtb3ZlRGF0YXBvaW50RW50cnkoZGF0YXBvaW50KVwiXG4gICAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICA8aSBjOHlJY29uPVwiZGVsZXRlXCI+PC9pPlxuICAgICAgICAgICAgICAgIHt7ICdSZW1vdmUnIHwgdHJhbnNsYXRlIH19XG4gICAgICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICAgICAgPC9saT5cbiAgICAgICAgICA8L3VsPlxuICAgICAgICA8L2Rpdj5cbiAgICAgIDwvZGl2PlxuXG4gICAgICA8ZGl2IGNsYXNzPVwiY2FyZC1oZWFkZXIgc2VwYXJhdG9yXCI+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJjYXJkLWljb25cIj5cbiAgICAgICAgICA8aVxuICAgICAgICAgICAgYzh5SWNvbj1cImNpcmNsZVwiXG4gICAgICAgICAgICBbc3R5bGUuY29sb3JdPVwiZGF0YXBvaW50LmM4eV9LcGk/LmNvbG9yXCJcbiAgICAgICAgICA+PC9pPlxuICAgICAgICA8L2Rpdj5cbiAgICAgICAgPGRpdlxuICAgICAgICAgIGNsYXNzPVwiY2FyZC10aXRsZSB0ZXh0LXRydW5jYXRlXCJcbiAgICAgICAgICBbdGl0bGVdPVwiZGF0YXBvaW50LmM4eV9LcGk/LmxhYmVsXCJcbiAgICAgICAgPlxuICAgICAgICAgIHt7IGRhdGFwb2ludC5jOHlfS3BpPy5sYWJlbCB9fVxuICAgICAgICA8L2Rpdj5cbiAgICAgIDwvZGl2PlxuICAgICAgPGRpdiBjbGFzcz1cImNhcmQtYmxvY2sgYmctbGV2ZWwtMSBwLWItMjQgY2FyZC1oaWRkZW4tbGlzdFwiPlxuICAgICAgICA8ZGl2IGNsYXNzPVwiY29sLXNtLTMgY29sLW1kLTJcIj5cbiAgICAgICAgICA8Yzh5LXJhbmdlLWRpc3BsYXlcbiAgICAgICAgICAgIFtjb25maWddPVwiZGF0YXBvaW50LmM4eV9LcGlcIlxuICAgICAgICAgICAgW2Rpc3BsYXldPVwiJ2NvbXBhY3QnXCJcbiAgICAgICAgICA+PC9jOHktcmFuZ2UtZGlzcGxheT5cbiAgICAgICAgPC9kaXY+XG4gICAgICA8L2Rpdj5cbiAgICAgIDxkaXYgY2xhc3M9XCJjYXJkLWJsb2NrXCI+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJjb2wtc20tMyB0ZXh0LXRydW5jYXRlXCI+XG4gICAgICAgICAgPHNwYW4+XG4gICAgICAgICAgICA8bGFiZWxcbiAgICAgICAgICAgICAgY2xhc3M9XCJ0ZXh0LWxhYmVsLXNtYWxsIG0tci00XCJcbiAgICAgICAgICAgICAgdHJhbnNsYXRlXG4gICAgICAgICAgICA+XG4gICAgICAgICAgICAgIEZyYWdtZW50XG4gICAgICAgICAgICA8L2xhYmVsPlxuICAgICAgICAgICAgPHNwYW4gW3RpdGxlXT1cImRhdGFwb2ludC5jOHlfS3BpPy5mcmFnbWVudFwiPlxuICAgICAgICAgICAgICB7eyBkYXRhcG9pbnQuYzh5X0twaT8uZnJhZ21lbnQgfX1cbiAgICAgICAgICAgIDwvc3Bhbj5cbiAgICAgICAgICA8L3NwYW4+XG4gICAgICAgIDwvZGl2PlxuICAgICAgICA8ZGl2IGNsYXNzPVwiY29sLXNtLTIgdGV4dC10cnVuY2F0ZVwiPlxuICAgICAgICAgIDxsYWJlbFxuICAgICAgICAgICAgY2xhc3M9XCJ0ZXh0LWxhYmVsLXNtYWxsIG0tci00XCJcbiAgICAgICAgICAgIHRyYW5zbGF0ZVxuICAgICAgICAgID5cbiAgICAgICAgICAgIFNlcmllc1xuICAgICAgICAgIDwvbGFiZWw+XG4gICAgICAgICAgPHNwYW4gW3RpdGxlXT1cImRhdGFwb2ludC5jOHlfS3BpPy5zZXJpZXNcIj5cbiAgICAgICAgICAgIHt7IGRhdGFwb2ludC5jOHlfS3BpPy5zZXJpZXMgfX1cbiAgICAgICAgICA8L3NwYW4+XG4gICAgICAgIDwvZGl2PlxuICAgICAgICA8ZGl2IGNsYXNzPVwiY29sLXNtLTEgdGV4dC10cnVuY2F0ZSBjYXJkLWhpZGRlbi1ncmlkXCI+XG4gICAgICAgICAgPHNwYW4gKm5nSWY9XCJkYXRhcG9pbnQuYzh5X0twaT8udW5pdFwiPlxuICAgICAgICAgICAgPGxhYmVsXG4gICAgICAgICAgICAgIGNsYXNzPVwidGV4dC1sYWJlbC1zbWFsbCBtLXItNFwiXG4gICAgICAgICAgICAgIHRyYW5zbGF0ZVxuICAgICAgICAgICAgPlxuICAgICAgICAgICAgICBVbml0XG4gICAgICAgICAgICA8L2xhYmVsPlxuICAgICAgICAgICAgPHNwYW4gW3RpdGxlXT1cImRhdGFwb2ludC5jOHlfS3BpPy51bml0XCI+XG4gICAgICAgICAgICAgIHt7IGRhdGFwb2ludC5jOHlfS3BpPy51bml0IH19XG4gICAgICAgICAgICA8L3NwYW4+XG4gICAgICAgICAgPC9zcGFuPlxuICAgICAgICA8L2Rpdj5cbiAgICAgICAgPGRpdiBjbGFzcz1cImNvbC1zbS0yIHRleHQtdHJ1bmNhdGVcIj5cbiAgICAgICAgICA8c3BhbiAqbmdJZj1cImRhdGFwb2ludC5jOHlfS3BpPy50YXJnZXRcIj5cbiAgICAgICAgICAgIDxsYWJlbFxuICAgICAgICAgICAgICBjbGFzcz1cInRleHQtbGFiZWwtc21hbGwgbS1yLTRcIlxuICAgICAgICAgICAgICB0cmFuc2xhdGVcbiAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgVGFyZ2V0XG4gICAgICAgICAgICA8L2xhYmVsPlxuICAgICAgICAgICAgPHNwYW4gW3RpdGxlXT1cImRhdGFwb2ludC5jOHlfS3BpPy50YXJnZXRcIj5cbiAgICAgICAgICAgICAge3sgZGF0YXBvaW50LmM4eV9LcGk/LnRhcmdldCB9fVxuICAgICAgICAgICAgPC9zcGFuPlxuICAgICAgICAgIDwvc3Bhbj5cbiAgICAgICAgPC9kaXY+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJjb2wtc20tNCBjYXJkLWhpZGRlbi1ncmlkXCI+XG4gICAgICAgICAgPGM4eS1yYW5nZS1kaXNwbGF5XG4gICAgICAgICAgICBbY29uZmlnXT1cImRhdGFwb2ludC5jOHlfS3BpXCJcbiAgICAgICAgICAgIFtkaXNwbGF5XT1cIidpbmxpbmUnXCJcbiAgICAgICAgICA+PC9jOHktcmFuZ2UtZGlzcGxheT5cbiAgICAgICAgPC9kaXY+XG4gICAgICA8L2Rpdj5cbiAgICA8L2Rpdj5cbiAgPC9kaXY+XG48L2Rpdj5cbiJdfQ==