@c8y/ngx-components
Version:
Angular modules for Cumulocity IoT applications
153 lines • 31.5 kB
JavaScript
import { Component, EventEmitter } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { AlertService, BuiltInActionType, DataGridService, ModalService, Status, gettext } from '@c8y/ngx-components';
import { DescriptionGridColumn, DeviceTypeGridColumn, PRODUCT_EXPERIENCE_REPOSITORY_SHARED, RepositoryItemNameGridColumn, RepositoryService, RepositoryType, TypeGridColumn, VersionsGridColumn } from '@c8y/ngx-components/repository/shared';
import { TranslateService } from '@ngx-translate/core';
import { BsModalService } from 'ngx-bootstrap/modal';
import { AddSoftwareModalComponent } from './add-software-modal.component';
import * as i0 from "@angular/core";
import * as i1 from "@c8y/ngx-components/repository/shared";
import * as i2 from "@c8y/ngx-components";
import * as i3 from "ngx-bootstrap/modal";
import * as i4 from "@ngx-translate/core";
import * as i5 from "@angular/router";
import * as i6 from "@angular/common";
export class SoftwareListComponent {
constructor(repositoryService, gridService, modalService, bsModalService, translateService, alertService, router, activatedRoute) {
this.repositoryService = repositoryService;
this.gridService = gridService;
this.modalService = modalService;
this.bsModalService = bsModalService;
this.translateService = translateService;
this.alertService = alertService;
this.router = router;
this.activatedRoute = activatedRoute;
this.sizeRequestDone = false;
this.refresh$ = new EventEmitter();
this.columns = [
new RepositoryItemNameGridColumn({
filterLabel: gettext('Filter software by name')
}),
new DescriptionGridColumn({
filterLabel: gettext('Filter software by description'),
placeholder: gettext('Cloud connectivity software')
}),
new DeviceTypeGridColumn({ filterLabel: gettext('Filter software by device type') }),
new TypeGridColumn({
header: gettext('Software type'),
filterLabel: gettext('Filter by software type'),
example: 'yum',
path: 'softwareType',
repositoryType: RepositoryType.SOFTWARE
}),
new VersionsGridColumn()
];
this.actionControls = [];
this.pagination = {
pageSize: 50,
currentPage: 1
};
this.noResultsMessage = gettext('No results to display.');
this.noDataMessage = gettext('No software to display.');
this.noResultsSubtitle = gettext('Refine your search terms or check your spelling.');
this.noDataSubtitle = gettext('Add a new software by clicking below.');
this.serverSideDataCallback = this.onDataSourceModifier.bind(this);
}
ngOnInit() {
this.actionControls.push({
type: BuiltInActionType.Edit,
callback: this.editSoftware.bind(this)
});
this.actionControls.push({
type: BuiltInActionType.Delete,
callback: this.deleteSoftware.bind(this)
});
}
async onDataSourceModifier(dataSourceModifier) {
const dataRequest = this.repositoryService.listRepositoryEntries(RepositoryType.SOFTWARE, {
query: this.gridService.getQueryObj(dataSourceModifier.columns),
skipDefaultOrder: true,
params: {
pageSize: dataSourceModifier.pagination.pageSize,
currentPage: dataSourceModifier.pagination.currentPage
}
});
const filtererdSizeRequest = this.repositoryService
.listRepositoryEntries(RepositoryType.SOFTWARE, {
skipDefaultOrder: true,
query: this.gridService.getQueryObj(dataSourceModifier.columns),
params: { pageSize: 1 }
})
.then(response => response?.paging?.totalPages);
this.sizeRequest = this.repositoryService
.listRepositoryEntries(RepositoryType.SOFTWARE, {
skipDefaultOrder: true,
params: { pageSize: 1 }
})
.then(response => {
this.sizeRequestDone = true;
return response?.paging?.totalPages;
});
const [dataResponse, size, filteredSize] = await Promise.all([
dataRequest,
this.sizeRequest,
filtererdSizeRequest
]);
const { res, data, paging } = dataResponse;
const serverSideDataResult = {
res,
data,
paging,
filteredSize,
size
};
return serverSideDataResult;
}
addSoftware() {
const config = {
class: 'modal-sm',
ariaDescribedby: 'addSoftwareModalDescription',
ariaLabelledBy: 'addSoftwareModalTitle',
ignoreBackdropClick: true,
keyboard: false
};
const modalRef = this.bsModalService.show(AddSoftwareModalComponent, config);
modalRef.content.saved.subscribe(savedSoftware => this.editSoftware(savedSoftware));
}
editSoftware(software) {
this.router.navigate([software.id], { relativeTo: this.activatedRoute });
}
async deleteSoftware(software) {
try {
const title = gettext('Delete software');
const body = `
${this.translateService.instant(gettext('You are about to delete software "{{ name }}" with all its versions.'), { name: software.name })}
${this.translateService.instant(gettext('This operation is irreversible.'))}
${this.translateService.instant(gettext('Do you want to proceed?'))}
`;
const labels = {
ok: gettext('Delete')
};
await this.modalService.confirm(title, body, Status.DANGER, labels, {}, { eventName: PRODUCT_EXPERIENCE_REPOSITORY_SHARED.SOFTWARE.EVENTS.REPOSITORY });
await this.repositoryService.delete(software);
this.alertService.success(gettext('Software deleted.'));
this.refresh$.next();
}
catch (ex) {
// only if not cancel from modal
if (ex) {
this.alertService.addServerFailure(ex);
}
}
}
trackByName(_index, column) {
return column.name;
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: SoftwareListComponent, deps: [{ token: i1.RepositoryService }, { token: i2.DataGridService }, { token: i2.ModalService }, { token: i3.BsModalService }, { token: i4.TranslateService }, { token: i2.AlertService }, { token: i5.Router }, { token: i5.ActivatedRoute }], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: SoftwareListComponent, selector: "c8y-software-list", ngImport: i0, template: "<c8y-title>\n {{ 'Software repository' | translate }}\n</c8y-title>\n<c8y-breadcrumb>\n <c8y-breadcrumb-item\n icon=\"c8y-management\"\n label=\"{{ 'Management' | translate }}\"\n ></c8y-breadcrumb-item>\n <c8y-breadcrumb-item\n icon=\"c8y-tools\"\n label=\"{{ 'Software repository' | translate }}\"\n ></c8y-breadcrumb-item>\n</c8y-breadcrumb>\n\n<c8y-action-bar-item [placement]=\"'right'\">\n <button\n class=\"btn btn-link\"\n title=\"{{ 'Add software' | translate }}\"\n type=\"button\"\n (click)=\"addSoftware()\"\n >\n <i c8yIcon=\"plus-circle\"></i>\n {{ 'Add software' | translate }}\n </button>\n</c8y-action-bar-item>\n\n<c8y-help\n src=\"/docs/device-management-application/managing-device-data/#managing-software\"\n></c8y-help>\n\n<div class=\"content-fullpage border-top border-bottom\">\n <c8y-data-grid\n [title]=\"'Software' | translate\"\n [refresh]=\"refresh$\"\n [pagination]=\"pagination\"\n [columns]=\"columns\"\n [actionControls]=\"actionControls\"\n [infiniteScroll]=\"'auto'\"\n [serverSideDataCallback]=\"serverSideDataCallback\"\n >\n <c8y-ui-empty-state\n [icon]=\"stats?.size > 0 ? 'search' : 'c8y-tools'\"\n [title]=\"stats?.size > 0 ? (noResultsMessage | translate) : (noDataMessage | translate)\"\n [subtitle]=\"stats?.size > 0 ? (noResultsSubtitle | translate) : (noDataSubtitle | translate)\"\n *emptyStateContext=\"let stats\"\n [horizontal]=\"stats?.size > 0\"\n >\n <p *ngIf=\"stats?.size === 0\">\n <button\n class=\"btn btn-primary\"\n [title]=\"'Add software' | translate\"\n type=\"button\"\n (click)=\"addSoftware()\"\n >\n {{ 'Add software' | translate }}\n </button>\n </p>\n </c8y-ui-empty-state>\n <ng-container *ngFor=\"let column of columns; trackBy: trackByName\">\n <c8y-column [name]=\"column.name\"></c8y-column>\n </ng-container>\n </c8y-data-grid>\n</div>\n", dependencies: [{ kind: "directive", type: i6.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i6.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i2.ActionBarItemComponent, selector: "c8y-action-bar-item", inputs: ["placement", "priority", "itemClass", "injector", "groupId", "inGroupPriority"] }, { kind: "component", type: i2.BreadcrumbComponent, selector: "c8y-breadcrumb" }, { kind: "component", type: i2.BreadcrumbItemComponent, selector: "c8y-breadcrumb-item", inputs: ["icon", "translate", "label", "path", "injector"] }, { kind: "component", type: i2.EmptyStateComponent, selector: "c8y-ui-empty-state", inputs: ["icon", "title", "subtitle", "horizontal"] }, { kind: "directive", type: i2.EmptyStateContextDirective, selector: "[emptyStateContext]" }, { kind: "directive", type: i2.IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "directive", type: i2.ColumnDirective, selector: "c8y-column", inputs: ["name"] }, { kind: "component", type: i2.DataGridComponent, selector: "c8y-data-grid", inputs: ["title", "loadMoreItemsLabel", "loadingItemsLabel", "showSearch", "refresh", "columns", "rows", "pagination", "infiniteScroll", "serverSideDataCallback", "selectable", "singleSelection", "selectionPrimaryKey", "displayOptions", "actionControls", "bulkActionControls", "headerActionControls", "searchText", "configureColumnsEnabled", "showCounterWarning", "activeClassName", "expandableRows"], outputs: ["rowMouseOver", "rowMouseLeave", "rowClick", "onConfigChange", "onBeforeFilter", "onBeforeSearch", "onFilter", "itemsSelect", "onReload", "onAddCustomColumn", "onRemoveCustomColumn", "onColumnFilterReset", "onSort", "onPageSizeChange", "onColumnReordered", "onColumnVisibilityChange"] }, { kind: "component", type: i2.TitleComponent, selector: "c8y-title", inputs: ["pageTitleUpdate"] }, { kind: "component", type: i2.HelpComponent, selector: "c8y-help", inputs: ["src", "isCollapsed", "priority", "icon"] }, { kind: "pipe", type: i2.C8yTranslatePipe, name: "translate" }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: SoftwareListComponent, decorators: [{
type: Component,
args: [{ selector: 'c8y-software-list', template: "<c8y-title>\n {{ 'Software repository' | translate }}\n</c8y-title>\n<c8y-breadcrumb>\n <c8y-breadcrumb-item\n icon=\"c8y-management\"\n label=\"{{ 'Management' | translate }}\"\n ></c8y-breadcrumb-item>\n <c8y-breadcrumb-item\n icon=\"c8y-tools\"\n label=\"{{ 'Software repository' | translate }}\"\n ></c8y-breadcrumb-item>\n</c8y-breadcrumb>\n\n<c8y-action-bar-item [placement]=\"'right'\">\n <button\n class=\"btn btn-link\"\n title=\"{{ 'Add software' | translate }}\"\n type=\"button\"\n (click)=\"addSoftware()\"\n >\n <i c8yIcon=\"plus-circle\"></i>\n {{ 'Add software' | translate }}\n </button>\n</c8y-action-bar-item>\n\n<c8y-help\n src=\"/docs/device-management-application/managing-device-data/#managing-software\"\n></c8y-help>\n\n<div class=\"content-fullpage border-top border-bottom\">\n <c8y-data-grid\n [title]=\"'Software' | translate\"\n [refresh]=\"refresh$\"\n [pagination]=\"pagination\"\n [columns]=\"columns\"\n [actionControls]=\"actionControls\"\n [infiniteScroll]=\"'auto'\"\n [serverSideDataCallback]=\"serverSideDataCallback\"\n >\n <c8y-ui-empty-state\n [icon]=\"stats?.size > 0 ? 'search' : 'c8y-tools'\"\n [title]=\"stats?.size > 0 ? (noResultsMessage | translate) : (noDataMessage | translate)\"\n [subtitle]=\"stats?.size > 0 ? (noResultsSubtitle | translate) : (noDataSubtitle | translate)\"\n *emptyStateContext=\"let stats\"\n [horizontal]=\"stats?.size > 0\"\n >\n <p *ngIf=\"stats?.size === 0\">\n <button\n class=\"btn btn-primary\"\n [title]=\"'Add software' | translate\"\n type=\"button\"\n (click)=\"addSoftware()\"\n >\n {{ 'Add software' | translate }}\n </button>\n </p>\n </c8y-ui-empty-state>\n <ng-container *ngFor=\"let column of columns; trackBy: trackByName\">\n <c8y-column [name]=\"column.name\"></c8y-column>\n </ng-container>\n </c8y-data-grid>\n</div>\n" }]
}], ctorParameters: () => [{ type: i1.RepositoryService }, { type: i2.DataGridService }, { type: i2.ModalService }, { type: i3.BsModalService }, { type: i4.TranslateService }, { type: i2.AlertService }, { type: i5.Router }, { type: i5.ActivatedRoute }] });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic29mdHdhcmUtbGlzdC5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9yZXBvc2l0b3J5L3NvZnR3YXJlL2xpc3Qvc29mdHdhcmUtbGlzdC5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi8uLi9yZXBvc2l0b3J5L3NvZnR3YXJlL2xpc3Qvc29mdHdhcmUtbGlzdC5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsU0FBUyxFQUFFLFlBQVksRUFBVSxNQUFNLGVBQWUsQ0FBQztBQUNoRSxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0sRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBRXpELE9BQU8sRUFFTCxZQUFZLEVBQ1osaUJBQWlCLEVBRWpCLGVBQWUsRUFFZixZQUFZLEVBR1osTUFBTSxFQUNOLE9BQU8sRUFDUixNQUFNLHFCQUFxQixDQUFDO0FBQzdCLE9BQU8sRUFDTCxxQkFBcUIsRUFDckIsb0JBQW9CLEVBQ3BCLG9DQUFvQyxFQUNwQyw0QkFBNEIsRUFDNUIsaUJBQWlCLEVBQ2pCLGNBQWMsRUFDZCxjQUFjLEVBQ2Qsa0JBQWtCLEVBQ25CLE1BQU0sdUNBQXVDLENBQUM7QUFDL0MsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFDdkQsT0FBTyxFQUFFLGNBQWMsRUFBZ0IsTUFBTSxxQkFBcUIsQ0FBQztBQUNuRSxPQUFPLEVBQUUseUJBQXlCLEVBQUUsTUFBTSxnQ0FBZ0MsQ0FBQzs7Ozs7Ozs7QUFNM0UsTUFBTSxPQUFPLHFCQUFxQjtJQW1DaEMsWUFDVSxpQkFBb0MsRUFDcEMsV0FBNEIsRUFDNUIsWUFBMEIsRUFDMUIsY0FBOEIsRUFDOUIsZ0JBQWtDLEVBQ2xDLFlBQTBCLEVBQzFCLE1BQWMsRUFDZCxjQUE4QjtRQVA5QixzQkFBaUIsR0FBakIsaUJBQWlCLENBQW1CO1FBQ3BDLGdCQUFXLEdBQVgsV0FBVyxDQUFpQjtRQUM1QixpQkFBWSxHQUFaLFlBQVksQ0FBYztRQUMxQixtQkFBYyxHQUFkLGNBQWMsQ0FBZ0I7UUFDOUIscUJBQWdCLEdBQWhCLGdCQUFnQixDQUFrQjtRQUNsQyxpQkFBWSxHQUFaLFlBQVksQ0FBYztRQUMxQixXQUFNLEdBQU4sTUFBTSxDQUFRO1FBQ2QsbUJBQWMsR0FBZCxjQUFjLENBQWdCO1FBekN4QyxvQkFBZSxHQUFHLEtBQUssQ0FBQztRQUN4QixhQUFRLEdBQXVCLElBQUksWUFBWSxFQUFFLENBQUM7UUFFbEQsWUFBTyxHQUFhO1lBQ2xCLElBQUksNEJBQTRCLENBQUM7Z0JBQy9CLFdBQVcsRUFBRSxPQUFPLENBQUMseUJBQXlCLENBQUM7YUFDaEQsQ0FBQztZQUNGLElBQUkscUJBQXFCLENBQUM7Z0JBQ3hCLFdBQVcsRUFBRSxPQUFPLENBQUMsZ0NBQWdDLENBQUM7Z0JBQ3RELFdBQVcsRUFBRSxPQUFPLENBQUMsNkJBQTZCLENBQUM7YUFDcEQsQ0FBQztZQUNGLElBQUksb0JBQW9CLENBQUMsRUFBRSxXQUFXLEVBQUUsT0FBTyxDQUFDLGdDQUFnQyxDQUFDLEVBQUUsQ0FBQztZQUNwRixJQUFJLGNBQWMsQ0FBQztnQkFDakIsTUFBTSxFQUFFLE9BQU8sQ0FBQyxlQUFlLENBQUM7Z0JBQ2hDLFdBQVcsRUFBRSxPQUFPLENBQUMseUJBQXlCLENBQUM7Z0JBQy9DLE9BQU8sRUFBRSxLQUFLO2dCQUNkLElBQUksRUFBRSxjQUFjO2dCQUNwQixjQUFjLEVBQUUsY0FBYyxDQUFDLFFBQVE7YUFDeEMsQ0FBQztZQUNGLElBQUksa0JBQWtCLEVBQUU7U0FDekIsQ0FBQztRQUNGLG1CQUFjLEdBQW9CLEVBQUUsQ0FBQztRQUVyQyxlQUFVLEdBQUc7WUFDWCxRQUFRLEVBQUUsRUFBRTtZQUNaLFdBQVcsRUFBRSxDQUFDO1NBQ2YsQ0FBQztRQUVGLHFCQUFnQixHQUFHLE9BQU8sQ0FBQyx3QkFBd0IsQ0FBQyxDQUFDO1FBQ3JELGtCQUFhLEdBQUcsT0FBTyxDQUFDLHlCQUF5QixDQUFDLENBQUM7UUFDbkQsc0JBQWlCLEdBQUcsT0FBTyxDQUFDLGtEQUFrRCxDQUFDLENBQUM7UUFDaEYsbUJBQWMsR0FBRyxPQUFPLENBQUMsdUNBQXVDLENBQUMsQ0FBQztRQVloRSxJQUFJLENBQUMsc0JBQXNCLEdBQUcsSUFBSSxDQUFDLG9CQUFvQixDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUNyRSxDQUFDO0lBRUQsUUFBUTtRQUNOLElBQUksQ0FBQyxjQUFjLENBQUMsSUFBSSxDQUFDO1lBQ3ZCLElBQUksRUFBRSxpQkFBaUIsQ0FBQyxJQUFJO1lBQzVCLFFBQVEsRUFBRSxJQUFJLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUM7U0FDdkMsQ0FBQyxDQUFDO1FBQ0gsSUFBSSxDQUFDLGNBQWMsQ0FBQyxJQUFJLENBQUM7WUFDdkIsSUFBSSxFQUFFLGlCQUFpQixDQUFDLE1BQU07WUFDOUIsUUFBUSxFQUFFLElBQUksQ0FBQyxjQUFjLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQztTQUN6QyxDQUFDLENBQUM7SUFDTCxDQUFDO0lBRUQsS0FBSyxDQUFDLG9CQUFvQixDQUN4QixrQkFBc0M7UUFFdEMsTUFBTSxXQUFXLEdBQ2YsSUFBSSxDQUFDLGlCQUFpQixDQUFDLHFCQUFxQixDQUFDLGNBQWMsQ0FBQyxRQUFRLEVBQUU7WUFDcEUsS0FBSyxFQUFFLElBQUksQ0FBQyxXQUFXLENBQUMsV0FBVyxDQUFDLGtCQUFrQixDQUFDLE9BQU8sQ0FBQztZQUMvRCxnQkFBZ0IsRUFBRSxJQUFJO1lBQ3RCLE1BQU0sRUFBRTtnQkFDTixRQUFRLEVBQUUsa0JBQWtCLENBQUMsVUFBVSxDQUFDLFFBQVE7Z0JBQ2hELFdBQVcsRUFBRSxrQkFBa0IsQ0FBQyxVQUFVLENBQUMsV0FBVzthQUN2RDtTQUNGLENBQUMsQ0FBQztRQUVMLE1BQU0sb0JBQW9CLEdBQW9CLElBQUksQ0FBQyxpQkFBaUI7YUFDakUscUJBQXFCLENBQUMsY0FBYyxDQUFDLFFBQVEsRUFBRTtZQUM5QyxnQkFBZ0IsRUFBRSxJQUFJO1lBQ3RCLEtBQUssRUFBRSxJQUFJLENBQUMsV0FBVyxDQUFDLFdBQVcsQ0FBQyxrQkFBa0IsQ0FBQyxPQUFPLENBQUM7WUFDL0QsTUFBTSxFQUFFLEVBQUUsUUFBUSxFQUFFLENBQUMsRUFBRTtTQUN4QixDQUFDO2FBQ0QsSUFBSSxDQUFDLFFBQVEsQ0FBQyxFQUFFLENBQUMsUUFBUSxFQUFFLE1BQU0sRUFBRSxVQUFVLENBQUMsQ0FBQztRQUVsRCxJQUFJLENBQUMsV0FBVyxHQUFHLElBQUksQ0FBQyxpQkFBaUI7YUFDdEMscUJBQXFCLENBQUMsY0FBYyxDQUFDLFFBQVEsRUFBRTtZQUM5QyxnQkFBZ0IsRUFBRSxJQUFJO1lBQ3RCLE1BQU0sRUFBRSxFQUFFLFFBQVEsRUFBRSxDQUFDLEVBQUU7U0FDeEIsQ0FBQzthQUNELElBQUksQ0FBQyxRQUFRLENBQUMsRUFBRTtZQUNmLElBQUksQ0FBQyxlQUFlLEdBQUcsSUFBSSxDQUFDO1lBQzVCLE9BQU8sUUFBUSxFQUFFLE1BQU0sRUFBRSxVQUFVLENBQUM7UUFDdEMsQ0FBQyxDQUFDLENBQUM7UUFFTCxNQUFNLENBQUMsWUFBWSxFQUFFLElBQUksRUFBRSxZQUFZLENBQUMsR0FBRyxNQUFNLE9BQU8sQ0FBQyxHQUFHLENBQUM7WUFDM0QsV0FBVztZQUNYLElBQUksQ0FBQyxXQUFXO1lBQ2hCLG9CQUFvQjtTQUNyQixDQUFDLENBQUM7UUFFSCxNQUFNLEVBQUUsR0FBRyxFQUFFLElBQUksRUFBRSxNQUFNLEVBQUUsR0FBRyxZQUFZLENBQUM7UUFFM0MsTUFBTSxvQkFBb0IsR0FBeUI7WUFDakQsR0FBRztZQUNILElBQUk7WUFDSixNQUFNO1lBQ04sWUFBWTtZQUNaLElBQUk7U0FDTCxDQUFDO1FBRUYsT0FBTyxvQkFBb0IsQ0FBQztJQUM5QixDQUFDO0lBRUQsV0FBVztRQUNULE1BQU0sTUFBTSxHQUE0QztZQUN0RCxLQUFLLEVBQUUsVUFBVTtZQUNqQixlQUFlLEVBQUUsNkJBQTZCO1lBQzlDLGNBQWMsRUFBRSx1QkFBdUI7WUFDdkMsbUJBQW1CLEVBQUUsSUFBSTtZQUN6QixRQUFRLEVBQUUsS0FBSztTQUNoQixDQUFDO1FBQ0YsTUFBTSxRQUFRLEdBQUcsSUFBSSxDQUFDLGNBQWMsQ0FBQyxJQUFJLENBQUMseUJBQXlCLEVBQUUsTUFBTSxDQUFDLENBQUM7UUFDN0UsUUFBUSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsU0FBUyxDQUFDLGFBQWEsQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxhQUFhLENBQUMsQ0FBQyxDQUFDO0lBQ3RGLENBQUM7SUFFRCxZQUFZLENBQUMsUUFBaUM7UUFDNUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsQ0FBQyxRQUFRLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRSxVQUFVLEVBQUUsSUFBSSxDQUFDLGNBQWMsRUFBRSxDQUFDLENBQUM7SUFDM0UsQ0FBQztJQUVELEtBQUssQ0FBQyxjQUFjLENBQUMsUUFBd0I7UUFDM0MsSUFBSSxDQUFDO1lBQ0gsTUFBTSxLQUFLLEdBQUcsT0FBTyxDQUFDLGlCQUFpQixDQUFDLENBQUM7WUFDekMsTUFBTSxJQUFJLEdBQUc7VUFDVCxJQUFJLENBQUMsZ0JBQWdCLENBQUMsT0FBTyxDQUM3QixPQUFPLENBQUMsc0VBQXNFLENBQUMsRUFDL0UsRUFBRSxJQUFJLEVBQUUsUUFBUSxDQUFDLElBQUksRUFBRSxDQUN4QjtVQUNDLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLGlDQUFpQyxDQUFDLENBQUM7VUFDekUsSUFBSSxDQUFDLGdCQUFnQixDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMseUJBQXlCLENBQUMsQ0FBQztPQUNwRSxDQUFDO1lBQ0YsTUFBTSxNQUFNLEdBQUc7Z0JBQ2IsRUFBRSxFQUFFLE9BQU8sQ0FBQyxRQUFRLENBQUM7YUFDdEIsQ0FBQztZQUNGLE1BQU0sSUFBSSxDQUFDLFlBQVksQ0FBQyxPQUFPLENBQzdCLEtBQUssRUFDTCxJQUFJLEVBQ0osTUFBTSxDQUFDLE1BQU0sRUFDYixNQUFNLEVBQ04sRUFBRSxFQUNGLEVBQUUsU0FBUyxFQUFFLG9DQUFvQyxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsVUFBVSxFQUFFLENBQy9FLENBQUM7WUFDRixNQUFNLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLENBQUM7WUFDOUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLG1CQUFtQixDQUFDLENBQUMsQ0FBQztZQUN4RCxJQUFJLENBQUMsUUFBUSxDQUFDLElBQUksRUFBRSxDQUFDO1FBQ3ZCLENBQUM7UUFBQyxPQUFPLEVBQUUsRUFBRSxDQUFDO1lBQ1osZ0NBQWdDO1lBQ2hDLElBQUksRUFBRSxFQUFFLENBQUM7Z0JBQ1AsSUFBSSxDQUFDLFlBQVksQ0FBQyxnQkFBZ0IsQ0FBQyxFQUFFLENBQUMsQ0FBQztZQUN6QyxDQUFDO1FBQ0gsQ0FBQztJQUNILENBQUM7SUFFRCxXQUFXLENBQUMsTUFBTSxFQUFFLE1BQWM7UUFDaEMsT0FBTyxNQUFNLENBQUMsSUFBSSxDQUFDO0lBQ3JCLENBQUM7K0dBaEtVLHFCQUFxQjttR0FBckIscUJBQXFCLHlEQ2xDbEMsKzhEQStEQTs7NEZEN0JhLHFCQUFxQjtrQkFKakMsU0FBUzsrQkFDRSxtQkFBbUIiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDb21wb25lbnQsIEV2ZW50RW1pdHRlciwgT25Jbml0IH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBBY3RpdmF0ZWRSb3V0ZSwgUm91dGVyIH0gZnJvbSAnQGFuZ3VsYXIvcm91dGVyJztcbmltcG9ydCB7IElNYW5hZ2VkT2JqZWN0LCBJUmVzdWx0TGlzdCB9IGZyb20gJ0BjOHkvY2xpZW50JztcbmltcG9ydCB7XG4gIEFjdGlvbkNvbnRyb2wsXG4gIEFsZXJ0U2VydmljZSxcbiAgQnVpbHRJbkFjdGlvblR5cGUsXG4gIENvbHVtbixcbiAgRGF0YUdyaWRTZXJ2aWNlLFxuICBEYXRhU291cmNlTW9kaWZpZXIsXG4gIE1vZGFsU2VydmljZSxcbiAgU2VydmVyU2lkZURhdGFDYWxsYmFjayxcbiAgU2VydmVyU2lkZURhdGFSZXN1bHQsXG4gIFN0YXR1cyxcbiAgZ2V0dGV4dFxufSBmcm9tICdAYzh5L25neC1jb21wb25lbnRzJztcbmltcG9ydCB7XG4gIERlc2NyaXB0aW9uR3JpZENvbHVtbixcbiAgRGV2aWNlVHlwZUdyaWRDb2x1bW4sXG4gIFBST0RVQ1RfRVhQRVJJRU5DRV9SRVBPU0lUT1JZX1NIQVJFRCxcbiAgUmVwb3NpdG9yeUl0ZW1OYW1lR3JpZENvbHVtbixcbiAgUmVwb3NpdG9yeVNlcnZpY2UsXG4gIFJlcG9zaXRvcnlUeXBlLFxuICBUeXBlR3JpZENvbHVtbixcbiAgVmVyc2lvbnNHcmlkQ29sdW1uXG59IGZyb20gJ0BjOHkvbmd4LWNvbXBvbmVudHMvcmVwb3NpdG9yeS9zaGFyZWQnO1xuaW1wb3J0IHsgVHJhbnNsYXRlU2VydmljZSB9IGZyb20gJ0BuZ3gtdHJhbnNsYXRlL2NvcmUnO1xuaW1wb3J0IHsgQnNNb2RhbFNlcnZpY2UsIE1vZGFsT3B0aW9ucyB9IGZyb20gJ25neC1ib290c3RyYXAvbW9kYWwnO1xuaW1wb3J0IHsgQWRkU29mdHdhcmVNb2RhbENvbXBvbmVudCB9IGZyb20gJy4vYWRkLXNvZnR3YXJlLW1vZGFsLmNvbXBvbmVudCc7XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ2M4eS1zb2Z0d2FyZS1saXN0JyxcbiAgdGVtcGxhdGVVcmw6ICdzb2Z0d2FyZS1saXN0LmNvbXBvbmVudC5odG1sJ1xufSlcbmV4cG9ydCBjbGFzcyBTb2Z0d2FyZUxpc3RDb21wb25lbnQgaW1wbGVtZW50cyBPbkluaXQge1xuICBzaXplUmVxdWVzdDogUHJvbWlzZTxudW1iZXI+O1xuICBzaXplUmVxdWVzdERvbmUgPSBmYWxzZTtcbiAgcmVmcmVzaCQ6IEV2ZW50RW1pdHRlcjx2b2lkPiA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcblxuICBjb2x1bW5zOiBDb2x1bW5bXSA9IFtcbiAgICBuZXcgUmVwb3NpdG9yeUl0ZW1OYW1lR3JpZENvbHVtbih7XG4gICAgICBmaWx0ZXJMYWJlbDogZ2V0dGV4dCgnRmlsdGVyIHNvZnR3YXJlIGJ5IG5hbWUnKVxuICAgIH0pLFxuICAgIG5ldyBEZXNjcmlwdGlvbkdyaWRDb2x1bW4oe1xuICAgICAgZmlsdGVyTGFiZWw6IGdldHRleHQoJ0ZpbHRlciBzb2Z0d2FyZSBieSBkZXNjcmlwdGlvbicpLFxuICAgICAgcGxhY2Vob2xkZXI6IGdldHRleHQoJ0Nsb3VkIGNvbm5lY3Rpdml0eSBzb2Z0d2FyZScpXG4gICAgfSksXG4gICAgbmV3IERldmljZVR5cGVHcmlkQ29sdW1uKHsgZmlsdGVyTGFiZWw6IGdldHRleHQoJ0ZpbHRlciBzb2Z0d2FyZSBieSBkZXZpY2UgdHlwZScpIH0pLFxuICAgIG5ldyBUeXBlR3JpZENvbHVtbih7XG4gICAgICBoZWFkZXI6IGdldHRleHQoJ1NvZnR3YXJlIHR5cGUnKSxcbiAgICAgIGZpbHRlckxhYmVsOiBnZXR0ZXh0KCdGaWx0ZXIgYnkgc29mdHdhcmUgdHlwZScpLFxuICAgICAgZXhhbXBsZTogJ3l1bScsXG4gICAgICBwYXRoOiAnc29mdHdhcmVUeXBlJyxcbiAgICAgIHJlcG9zaXRvcnlUeXBlOiBSZXBvc2l0b3J5VHlwZS5TT0ZUV0FSRVxuICAgIH0pLFxuICAgIG5ldyBWZXJzaW9uc0dyaWRDb2x1bW4oKVxuICBdO1xuICBhY3Rpb25Db250cm9sczogQWN0aW9uQ29udHJvbFtdID0gW107XG4gIHNlcnZlclNpZGVEYXRhQ2FsbGJhY2s6IFNlcnZlclNpZGVEYXRhQ2FsbGJhY2s7XG4gIHBhZ2luYXRpb24gPSB7XG4gICAgcGFnZVNpemU6IDUwLFxuICAgIGN1cnJlbnRQYWdlOiAxXG4gIH07XG5cbiAgbm9SZXN1bHRzTWVzc2FnZSA9IGdldHRleHQoJ05vIHJlc3VsdHMgdG8gZGlzcGxheS4nKTtcbiAgbm9EYXRhTWVzc2FnZSA9IGdldHRleHQoJ05vIHNvZnR3YXJlIHRvIGRpc3BsYXkuJyk7XG4gIG5vUmVzdWx0c1N1YnRpdGxlID0gZ2V0dGV4dCgnUmVmaW5lIHlvdXIgc2VhcmNoIHRlcm1zIG9yIGNoZWNrIHlvdXIgc3BlbGxpbmcuJyk7XG4gIG5vRGF0YVN1YnRpdGxlID0gZ2V0dGV4dCgnQWRkIGEgbmV3IHNvZnR3YXJlIGJ5IGNsaWNraW5nIGJlbG93LicpO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgcmVwb3NpdG9yeVNlcnZpY2U6IFJlcG9zaXRvcnlTZXJ2aWNlLFxuICAgIHByaXZhdGUgZ3JpZFNlcnZpY2U6IERhdGFHcmlkU2VydmljZSxcbiAgICBwcml2YXRlIG1vZGFsU2VydmljZTogTW9kYWxTZXJ2aWNlLFxuICAgIHByaXZhdGUgYnNNb2RhbFNlcnZpY2U6IEJzTW9kYWxTZXJ2aWNlLFxuICAgIHByaXZhdGUgdHJhbnNsYXRlU2VydmljZTogVHJhbnNsYXRlU2VydmljZSxcbiAgICBwcml2YXRlIGFsZXJ0U2VydmljZTogQWxlcnRTZXJ2aWNlLFxuICAgIHByaXZhdGUgcm91dGVyOiBSb3V0ZXIsXG4gICAgcHJpdmF0ZSBhY3RpdmF0ZWRSb3V0ZTogQWN0aXZhdGVkUm91dGVcbiAgKSB7XG4gICAgdGhpcy5zZXJ2ZXJTaWRlRGF0YUNhbGxiYWNrID0gdGhpcy5vbkRhdGFTb3VyY2VNb2RpZmllci5iaW5kKHRoaXMpO1xuICB9XG5cbiAgbmdPbkluaXQoKTogdm9pZCB7XG4gICAgdGhpcy5hY3Rpb25Db250cm9scy5wdXNoKHtcbiAgICAgIHR5cGU6IEJ1aWx0SW5BY3Rpb25UeXBlLkVkaXQsXG4gICAgICBjYWxsYmFjazogdGhpcy5lZGl0U29mdHdhcmUuYmluZCh0aGlzKVxuICAgIH0pO1xuICAgIHRoaXMuYWN0aW9uQ29udHJvbHMucHVzaCh7XG4gICAgICB0eXBlOiBCdWlsdEluQWN0aW9uVHlwZS5EZWxldGUsXG4gICAgICBjYWxsYmFjazogdGhpcy5kZWxldGVTb2Z0d2FyZS5iaW5kKHRoaXMpXG4gICAgfSk7XG4gIH1cblxuICBhc3luYyBvbkRhdGFTb3VyY2VNb2RpZmllcihcbiAgICBkYXRhU291cmNlTW9kaWZpZXI6IERhdGFTb3VyY2VNb2RpZmllclxuICApOiBQcm9taXNlPFNlcnZlclNpZGVEYXRhUmVzdWx0PiB7XG4gICAgY29uc3QgZGF0YVJlcXVlc3Q6IFByb21pc2U8SVJlc3VsdExpc3Q8SU1hbmFnZWRPYmplY3Q+PiA9XG4gICAgICB0aGlzLnJlcG9zaXRvcnlTZXJ2aWNlLmxpc3RSZXBvc2l0b3J5RW50cmllcyhSZXBvc2l0b3J5VHlwZS5TT0ZUV0FSRSwge1xuICAgICAgICBxdWVyeTogdGhpcy5ncmlkU2VydmljZS5nZXRRdWVyeU9iaihkYXRhU291cmNlTW9kaWZpZXIuY29sdW1ucyksXG4gICAgICAgIHNraXBEZWZhdWx0T3JkZXI6IHRydWUsXG4gICAgICAgIHBhcmFtczoge1xuICAgICAgICAgIHBhZ2VTaXplOiBkYXRhU291cmNlTW9kaWZpZXIucGFnaW5hdGlvbi5wYWdlU2l6ZSxcbiAgICAgICAgICBjdXJyZW50UGFnZTogZGF0YVNvdXJjZU1vZGlmaWVyLnBhZ2luYXRpb24uY3VycmVudFBhZ2VcbiAgICAgICAgfVxuICAgICAgfSk7XG5cbiAgICBjb25zdCBmaWx0ZXJlcmRTaXplUmVxdWVzdDogUHJvbWlzZTxudW1iZXI+ID0gdGhpcy5yZXBvc2l0b3J5U2VydmljZVxuICAgICAgLmxpc3RSZXBvc2l0b3J5RW50cmllcyhSZXBvc2l0b3J5VHlwZS5TT0ZUV0FSRSwge1xuICAgICAgICBza2lwRGVmYXVsdE9yZGVyOiB0cnVlLFxuICAgICAgICBxdWVyeTogdGhpcy5ncmlkU2VydmljZS5nZXRRdWVyeU9iaihkYXRhU291cmNlTW9kaWZpZXIuY29sdW1ucyksXG4gICAgICAgIHBhcmFtczogeyBwYWdlU2l6ZTogMSB9XG4gICAgICB9KVxuICAgICAgLnRoZW4ocmVzcG9uc2UgPT4gcmVzcG9uc2U/LnBhZ2luZz8udG90YWxQYWdlcyk7XG5cbiAgICB0aGlzLnNpemVSZXF1ZXN0ID0gdGhpcy5yZXBvc2l0b3J5U2VydmljZVxuICAgICAgLmxpc3RSZXBvc2l0b3J5RW50cmllcyhSZXBvc2l0b3J5VHlwZS5TT0ZUV0FSRSwge1xuICAgICAgICBza2lwRGVmYXVsdE9yZGVyOiB0cnVlLFxuICAgICAgICBwYXJhbXM6IHsgcGFnZVNpemU6IDEgfVxuICAgICAgfSlcbiAgICAgIC50aGVuKHJlc3BvbnNlID0+IHtcbiAgICAgICAgdGhpcy5zaXplUmVxdWVzdERvbmUgPSB0cnVlO1xuICAgICAgICByZXR1cm4gcmVzcG9uc2U/LnBhZ2luZz8udG90YWxQYWdlcztcbiAgICAgIH0pO1xuXG4gICAgY29uc3QgW2RhdGFSZXNwb25zZSwgc2l6ZSwgZmlsdGVyZWRTaXplXSA9IGF3YWl0IFByb21pc2UuYWxsKFtcbiAgICAgIGRhdGFSZXF1ZXN0LFxuICAgICAgdGhpcy5zaXplUmVxdWVzdCxcbiAgICAgIGZpbHRlcmVyZFNpemVSZXF1ZXN0XG4gICAgXSk7XG5cbiAgICBjb25zdCB7IHJlcywgZGF0YSwgcGFnaW5nIH0gPSBkYXRhUmVzcG9uc2U7XG5cbiAgICBjb25zdCBzZXJ2ZXJTaWRlRGF0YVJlc3VsdDogU2VydmVyU2lkZURhdGFSZXN1bHQgPSB7XG4gICAgICByZXMsXG4gICAgICBkYXRhLFxuICAgICAgcGFnaW5nLFxuICAgICAgZmlsdGVyZWRTaXplLFxuICAgICAgc2l6ZVxuICAgIH07XG5cbiAgICByZXR1cm4gc2VydmVyU2lkZURhdGFSZXN1bHQ7XG4gIH1cblxuICBhZGRTb2Z0d2FyZSgpIHtcbiAgICBjb25zdCBjb25maWc6IE1vZGFsT3B0aW9uczxBZGRTb2Z0d2FyZU1vZGFsQ29tcG9uZW50PiA9IHtcbiAgICAgIGNsYXNzOiAnbW9kYWwtc20nLFxuICAgICAgYXJpYURlc2NyaWJlZGJ5OiAnYWRkU29mdHdhcmVNb2RhbERlc2NyaXB0aW9uJyxcbiAgICAgIGFyaWFMYWJlbGxlZEJ5OiAnYWRkU29mdHdhcmVNb2RhbFRpdGxlJyxcbiAgICAgIGlnbm9yZUJhY2tkcm9wQ2xpY2s6IHRydWUsXG4gICAgICBrZXlib2FyZDogZmFsc2VcbiAgICB9O1xuICAgIGNvbnN0IG1vZGFsUmVmID0gdGhpcy5ic01vZGFsU2VydmljZS5zaG93KEFkZFNvZnR3YXJlTW9kYWxDb21wb25lbnQsIGNvbmZpZyk7XG4gICAgbW9kYWxSZWYuY29udGVudC5zYXZlZC5zdWJzY3JpYmUoc2F2ZWRTb2Z0d2FyZSA9PiB0aGlzLmVkaXRTb2Z0d2FyZShzYXZlZFNvZnR3YXJlKSk7XG4gIH1cblxuICBlZGl0U29mdHdhcmUoc29mdHdhcmU6IFBhcnRpYWw8SU1hbmFnZWRPYmplY3Q+KSB7XG4gICAgdGhpcy5yb3V0ZXIubmF2aWdhdGUoW3NvZnR3YXJlLmlkXSwgeyByZWxhdGl2ZVRvOiB0aGlzLmFjdGl2YXRlZFJvdXRlIH0pO1xuICB9XG5cbiAgYXN5bmMgZGVsZXRlU29mdHdhcmUoc29mdHdhcmU6IElNYW5hZ2VkT2JqZWN0KSB7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHRpdGxlID0gZ2V0dGV4dCgnRGVsZXRlIHNvZnR3YXJlJyk7XG4gICAgICBjb25zdCBib2R5ID0gYFxuICAgICAgICAke3RoaXMudHJhbnNsYXRlU2VydmljZS5pbnN0YW50KFxuICAgICAgICAgIGdldHRleHQoJ1lvdSBhcmUgYWJvdXQgdG8gZGVsZXRlIHNvZnR3YXJlIFwie3sgbmFtZSB9fVwiIHdpdGggYWxsIGl0cyB2ZXJzaW9ucy4nKSxcbiAgICAgICAgICB7IG5hbWU6IHNvZnR3YXJlLm5hbWUgfVxuICAgICAgICApfVxuICAgICAgICAke3RoaXMudHJhbnNsYXRlU2VydmljZS5pbnN0YW50KGdldHRleHQoJ1RoaXMgb3BlcmF0aW9uIGlzIGlycmV2ZXJzaWJsZS4nKSl9XG4gICAgICAgICR7dGhpcy50cmFuc2xhdGVTZXJ2aWNlLmluc3RhbnQoZ2V0dGV4dCgnRG8geW91IHdhbnQgdG8gcHJvY2VlZD8nKSl9XG4gICAgICBgO1xuICAgICAgY29uc3QgbGFiZWxzID0ge1xuICAgICAgICBvazogZ2V0dGV4dCgnRGVsZXRlJylcbiAgICAgIH07XG4gICAgICBhd2FpdCB0aGlzLm1vZGFsU2VydmljZS5jb25maXJtKFxuICAgICAgICB0aXRsZSxcbiAgICAgICAgYm9keSxcbiAgICAgICAgU3RhdHVzLkRBTkdFUixcbiAgICAgICAgbGFiZWxzLFxuICAgICAgICB7fSxcbiAgICAgICAgeyBldmVudE5hbWU6IFBST0RVQ1RfRVhQRVJJRU5DRV9SRVBPU0lUT1JZX1NIQVJFRC5TT0ZUV0FSRS5FVkVOVFMuUkVQT1NJVE9SWSB9XG4gICAgICApO1xuICAgICAgYXdhaXQgdGhpcy5yZXBvc2l0b3J5U2VydmljZS5kZWxldGUoc29mdHdhcmUpO1xuICAgICAgdGhpcy5hbGVydFNlcnZpY2Uuc3VjY2VzcyhnZXR0ZXh0KCdTb2Z0d2FyZSBkZWxldGVkLicpKTtcbiAgICAgIHRoaXMucmVmcmVzaCQubmV4dCgpO1xuICAgIH0gY2F0Y2ggKGV4KSB7XG4gICAgICAvLyBvbmx5IGlmIG5vdCBjYW5jZWwgZnJvbSBtb2RhbFxuICAgICAgaWYgKGV4KSB7XG4gICAgICAgIHRoaXMuYWxlcnRTZXJ2aWNlLmFkZFNlcnZlckZhaWx1cmUoZXgpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHRyYWNrQnlOYW1lKF9pbmRleCwgY29sdW1uOiBDb2x1bW4pOiBzdHJpbmcge1xuICAgIHJldHVybiBjb2x1bW4ubmFtZTtcbiAgfVxufVxuIiwiPGM4eS10aXRsZT5cbiAge3sgJ1NvZnR3YXJlIHJlcG9zaXRvcnknIHwgdHJhbnNsYXRlIH19XG48L2M4eS10aXRsZT5cbjxjOHktYnJlYWRjcnVtYj5cbiAgPGM4eS1icmVhZGNydW1iLWl0ZW1cbiAgICBpY29uPVwiYzh5LW1hbmFnZW1lbnRcIlxuICAgIGxhYmVsPVwie3sgJ01hbmFnZW1lbnQnIHwgdHJhbnNsYXRlIH19XCJcbiAgPjwvYzh5LWJyZWFkY3J1bWItaXRlbT5cbiAgPGM4eS1icmVhZGNydW1iLWl0ZW1cbiAgICBpY29uPVwiYzh5LXRvb2xzXCJcbiAgICBsYWJlbD1cInt7ICdTb2Z0d2FyZSByZXBvc2l0b3J5JyB8IHRyYW5zbGF0ZSB9fVwiXG4gID48L2M4eS1icmVhZGNydW1iLWl0ZW0+XG48L2M4eS1icmVhZGNydW1iPlxuXG48Yzh5LWFjdGlvbi1iYXItaXRlbSBbcGxhY2VtZW50XT1cIidyaWdodCdcIj5cbiAgPGJ1dHRvblxuICAgIGNsYXNzPVwiYnRuIGJ0bi1saW5rXCJcbiAgICB0aXRsZT1cInt7ICdBZGQgc29mdHdhcmUnIHwgdHJhbnNsYXRlIH19XCJcbiAgICB0eXBlPVwiYnV0dG9uXCJcbiAgICAoY2xpY2spPVwiYWRkU29mdHdhcmUoKVwiXG4gID5cbiAgICA8aSBjOHlJY29uPVwicGx1cy1jaXJjbGVcIj48L2k+XG4gICAge3sgJ0FkZCBzb2Z0d2FyZScgfCB0cmFuc2xhdGUgfX1cbiAgPC9idXR0b24+XG48L2M4eS1hY3Rpb24tYmFyLWl0ZW0+XG5cbjxjOHktaGVscFxuICBzcmM9XCIvZG9jcy9kZXZpY2UtbWFuYWdlbWVudC1hcHBsaWNhdGlvbi9tYW5hZ2luZy1kZXZpY2UtZGF0YS8jbWFuYWdpbmctc29mdHdhcmVcIlxuPjwvYzh5LWhlbHA+XG5cbjxkaXYgY2xhc3M9XCJjb250ZW50LWZ1bGxwYWdlIGJvcmRlci10b3AgYm9yZGVyLWJvdHRvbVwiPlxuICA8Yzh5LWRhdGEtZ3JpZFxuICAgIFt0aXRsZV09XCInU29mdHdhcmUnIHwgdHJhbnNsYXRlXCJcbiAgICBbcmVmcmVzaF09XCJyZWZyZXNoJFwiXG4gICAgW3BhZ2luYXRpb25dPVwicGFnaW5hdGlvblwiXG4gICAgW2NvbHVtbnNdPVwiY29sdW1uc1wiXG4gICAgW2FjdGlvbkNvbnRyb2xzXT1cImFjdGlvbkNvbnRyb2xzXCJcbiAgICBbaW5maW5pdGVTY3JvbGxdPVwiJ2F1dG8nXCJcbiAgICBbc2VydmVyU2lkZURhdGFDYWxsYmFja109XCJzZXJ2ZXJTaWRlRGF0YUNhbGxiYWNrXCJcbiAgPlxuICAgIDxjOHktdWktZW1wdHktc3RhdGVcbiAgICAgIFtpY29uXT1cInN0YXRzPy5zaXplID4gMCA/ICdzZWFyY2gnIDogJ2M4eS10b29scydcIlxuICAgICAgW3RpdGxlXT1cInN0YXRzPy5zaXplID4gMCA/IChub1Jlc3VsdHNNZXNzYWdlIHwgdHJhbnNsYXRlKSA6IChub0RhdGFNZXNzYWdlIHwgdHJhbnNsYXRlKVwiXG4gICAgICBbc3VidGl0bGVdPVwic3RhdHM/LnNpemUgPiAwID8gKG5vUmVzdWx0c1N1YnRpdGxlIHwgdHJhbnNsYXRlKSA6IChub0RhdGFTdWJ0aXRsZSB8IHRyYW5zbGF0ZSlcIlxuICAgICAgKmVtcHR5U3RhdGVDb250ZXh0PVwibGV0IHN0YXRzXCJcbiAgICAgIFtob3Jpem9udGFsXT1cInN0YXRzPy5zaXplID4gMFwiXG4gICAgPlxuICAgICAgPHAgKm5nSWY9XCJzdGF0cz8uc2l6ZSA9PT0gMFwiPlxuICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgY2xhc3M9XCJidG4gYnRuLXByaW1hcnlcIlxuICAgICAgICAgIFt0aXRsZV09XCInQWRkIHNvZnR3YXJlJyB8IHRyYW5zbGF0ZVwiXG4gICAgICAgICAgdHlwZT1cImJ1dHRvblwiXG4gICAgICAgICAgKGNsaWNrKT1cImFkZFNvZnR3YXJlKClcIlxuICAgICAgICA+XG4gICAgICAgICAge3sgJ0FkZCBzb2Z0d2FyZScgfCB0cmFuc2xhdGUgfX1cbiAgICAgICAgPC9idXR0b24+XG4gICAgICA8L3A+XG4gICAgPC9jOHktdWktZW1wdHktc3RhdGU+XG4gICAgPG5nLWNvbnRhaW5lciAqbmdGb3I9XCJsZXQgY29sdW1uIG9mIGNvbHVtbnM7IHRyYWNrQnk6IHRyYWNrQnlOYW1lXCI+XG4gICAgICA8Yzh5LWNvbHVtbiBbbmFtZV09XCJjb2x1bW4ubmFtZVwiPjwvYzh5LWNvbHVtbj5cbiAgICA8L25nLWNvbnRhaW5lcj5cbiAgPC9jOHktZGF0YS1ncmlkPlxuPC9kaXY+XG4iXX0=