@c8y/ngx-components
Version:
Angular modules for Cumulocity IoT applications
76 lines • 32.9 kB
JavaScript
import { Component, Input } from '@angular/core';
import { BsModalRef } from 'ngx-bootstrap/modal';
import { Subject, from, merge } from 'rxjs';
import { StaticAssetsService } from '@c8y/ngx-components/static-assets/data';
import { first, shareReplay, map, tap } from 'rxjs/operators';
import { AsyncPipe, DatePipe, NgFor, NgIf } from '@angular/common';
import { CoreModule, gettext } from '@c8y/ngx-components';
import { PopoverModule } from 'ngx-bootstrap/popover';
import { CollapseModule } from 'ngx-bootstrap/collapse';
import * as i0 from "@angular/core";
import * as i1 from "ngx-bootstrap/modal";
import * as i2 from "@c8y/ngx-components/static-assets/data";
import * as i3 from "@c8y/ngx-components";
import * as i4 from "ngx-bootstrap/popover";
import * as i5 from "ngx-bootstrap/collapse";
export class StaticAssetsModalComponent {
constructor(modalRef, staticAssets) {
this.modalRef = modalRef;
this.staticAssets = staticAssets;
this.assetType = 'branding';
this.supportedFileExtensions = [];
this.modalTitle = gettext('Select asset');
this.layout = 'grid';
this.accept = '';
this.isExpanded = false;
this._filesUpdate$ = new Subject();
this.result = new Promise((resolve, reject) => {
this.resolve = resolve;
this.reject = reject;
});
}
ngOnInit() {
this._unfilteredFiles$ = merge(this._filesUpdate$, from(this.staticAssets.listFiles(this.assetType))).pipe(shareReplay(1));
this.files$ = this._unfilteredFiles$.pipe(map(files => this.supportedFileExtensions
? files.filter(tmp => this.supportedFileExtensions.includes(tmp.extension.toLowerCase()))
: files), map(files => files.sort((a, b) => (a.addedAt < b.addedAt ? 1 : a.addedAt > b.addedAt ? -1 : 0))), tap(files => {
if (!files.length) {
this.isExpanded = true;
}
}));
if (this.supportedFileExtensions) {
this.accept = this.supportedFileExtensions.join(',');
}
}
async addFiles(files) {
if (!files?.length) {
return;
}
const existingFiles = await this._unfilteredFiles$.pipe(first()).toPromise();
const newFiles = await this.staticAssets.addFilesToStaticAssets(this.assetType, files, existingFiles);
this._filesUpdate$.next(newFiles);
}
select(asset) {
this.modalRef.hide();
this.resolve(asset);
}
cancel() {
this.modalRef.hide();
this.reject();
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: StaticAssetsModalComponent, deps: [{ token: i1.BsModalRef }, { token: i2.StaticAssetsService }], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: StaticAssetsModalComponent, isStandalone: true, selector: "c8y-static-assets-modal", inputs: { assetType: "assetType", supportedFileExtensions: "supportedFileExtensions", modalTitle: "modalTitle", layout: "layout" }, ngImport: i0, template: "<c8y-modal\n [title]=\"modalTitle\"\n (onDismiss)=\"cancel()\"\n [headerClasses]=\"'dialog-header'\"\n [labels]=\"{ cancel: 'Cancel' }\"\n>\n <ng-container c8y-modal-title>\n <span [c8yIcon]=\"'select-all'\"></span>\n </ng-container>\n <ng-container *ngIf=\"files$ | async as assets; else loading\">\n <div class=\"text-center sticky-top separator-bottom bg-component\" style=\"z-index: 1001;\">\n <p *ngIf=\"assets.length\" class=\"m-0 p-16\">\n {{ 'Select from the list below or`first part, followed by upload a new asset`' | translate }}\n <button\n class=\"btn-link\"\n aria-controls=\"collapseUpload\"\n [attr.aria-expanded]=\"isExpanded\"\n (click)=\"isExpanded = !isExpanded\"\n >\n {{ 'upload a new asset' | translate }}\n </button>\n </p>\n <div\n class=\"collapse\"\n id=\"collapseUpload\"\n [isAnimated]=\"true\"\n [collapse]=\"!isExpanded\"\n >\n <div class=\"p-t-24 p-l-24 p-r-24 bg-level-1 separator-top-bottom p-b-32\">\n <c8y-drop-area\n class=\"drop-area-sm m-b-8\"\n [icon]=\"'upload'\"\n [accept]=\"accept\"\n (dropped)=\"addFiles($event)\"\n ></c8y-drop-area>\n <c8y-messages\n [helpMessage]=\"\n 'After uploading, the asset will be visible in the list below.' | translate\n \"\n ></c8y-messages>\n </div>\n </div>\n </div>\n <div *ngIf=\"assets.length\">\n <c8y-list-group\n class=\"m-b-0\"\n *ngIf=\"layout != 'grid'\"\n >\n <c8y-list-item *ngFor=\"let asset of assets\">\n <c8y-list-item-icon icon=\"file\"></c8y-list-item-icon>\n\n <c8y-list-item-body>\n <div class=\"row\">\n <div class=\"col-md-3 col-xs-12 d-flex a-i-center\">\n <div\n class=\"text-truncate\"\n title=\"{{ asset.fileName }}\"\n >\n {{ asset.fileName }}\n </div>\n <button\n class=\"btn-dot m-l-4\"\n [title]=\"'Preview' | translate\"\n [popover]=\"preview\"\n placement=\"end\"\n triggers=\"focus\"\n container=\"body\"\n [adaptivePosition]=\"false\"\n >\n <i c8yIcon=\"eye\"></i>\n </button>\n <ng-template #preview>\n <div class=\"bg-checkered\">\n <img\n class=\"fit-w\"\n [alt]=\"asset.fileName\"\n [src]=\"asset.path\"\n />\n </div>\n </ng-template>\n </div>\n <div class=\"col-md-3 col-xs-12 text-muted\">\n <code class=\"text-10\">{{ asset.type }}</code>\n </div>\n <div class=\"col-md-2 col-xs-12 text-muted\">\n <span class=\"small\">{{ asset.size | bytes }}</span>\n </div>\n <div\n class=\"col-md-2 col-xs-12 text-muted\"\n [title]=\"asset.addedAt | date\"\n >\n <div class=\"icon-flex small\">\n <i\n class=\"m-r-4\"\n c8yIcon=\"calendar\"\n ></i>\n <span>{{ asset.addedAt | date }}</span>\n </div>\n </div>\n <div class=\"col-md-2 col-xs-12 d-flex\">\n <button\n class=\"btn btn-default btn-sm m-l-auto showOnHover\"\n (click)=\"select(asset)\"\n translate\n >\n Select\n </button>\n </div>\n </div>\n </c8y-list-item-body>\n </c8y-list-item>\n </c8y-list-group>\n <div\n class=\"card-group-block interact-grid\"\n *ngIf=\"layout === 'grid'\"\n >\n <button\n class=\"col-md-3 col-sm-4 col-xs-12 card btn-clean interact pointer\"\n *ngFor=\"let asset of assets\"\n (click)=\"select(asset)\"\n >\n <div class=\"card-block\">\n <div class=\"bg-checkered\">\n <img\n class=\"img-responsive m-auto img-square\"\n [alt]=\"asset.fileName\"\n [src]=\"asset.path\"\n />\n </div>\n <p\n class=\"text-medium text-truncate-wrap m-t-8\"\n title=\"{{ asset.fileName }}\"\n >\n {{ asset.fileName }}\n </p>\n <p class=\"m-b-4\">\n <code class=\"text-10\">{{ asset.type }}</code>\n </p>\n <p class=\"small text-muted d-flex a-i-center\">\n {{ asset.size | bytes }}\n <span class=\"m-l-auto\">\n <i\n class=\"m-r-4\"\n c8yIcon=\"calendar\"\n ></i>\n <span>{{ asset.addedAt | date }}</span>\n </span>\n </p>\n </div>\n </button>\n </div>\n </div>\n </ng-container>\n\n <ng-template #loading>\n <div class=\"p-24\">\n <c8y-loading></c8y-loading>\n </div>\n </ng-template>\n</c8y-modal>\n", dependencies: [{ kind: "directive", type: NgFor, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "pipe", type: DatePipe, name: "date" }, { kind: "ngmodule", type: CoreModule }, { 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: "component", type: i3.LoadingComponent, selector: "c8y-loading", inputs: ["layout", "progress", "message"] }, { kind: "pipe", type: i3.BytesPipe, name: "bytes" }, { kind: "component", type: i3.DropAreaComponent, selector: "c8y-drop-area", inputs: ["formControl", "title", "message", "icon", "loadingMessage", "forceHideList", "alwaysShow", "clickToOpen", "loading", "progress", "maxAllowedFiles", "files", "maxFileSizeInMegaBytes", "accept"], outputs: ["dropped"] }, { kind: "component", type: i3.ModalComponent, selector: "c8y-modal", inputs: ["disabled", "close", "dismiss", "title", "body", "customFooter", "headerClasses", "labels"], outputs: ["onDismiss", "onClose"] }, { kind: "component", type: i3.MessagesComponent, selector: "c8y-messages", inputs: ["show", "defaults", "helpMessage"] }, { kind: "component", type: i3.ListGroupComponent, selector: "c8y-list-group" }, { kind: "component", type: i3.ListItemComponent, selector: "c8y-list-item, c8y-li", inputs: ["active", "highlighted", "emptyActions", "dense", "collapsed", "selectable"], outputs: ["collapsedChange"] }, { kind: "component", type: i3.ListItemIconComponent, selector: "c8y-list-item-icon, c8y-li-icon", inputs: ["icon", "status"] }, { kind: "component", type: i3.ListItemBodyComponent, selector: "c8y-list-item-body, c8y-li-body", inputs: ["body"] }, { kind: "ngmodule", type: PopoverModule }, { kind: "directive", type: i4.PopoverDirective, selector: "[popover]", inputs: ["adaptivePosition", "boundariesElement", "popover", "popoverContext", "popoverTitle", "placement", "outsideClick", "triggers", "container", "containerClass", "isOpen", "delay"], outputs: ["onShown", "onHidden"], exportAs: ["bs-popover"] }, { kind: "ngmodule", type: CollapseModule }, { kind: "directive", type: i5.CollapseDirective, selector: "[collapse]", inputs: ["display", "isAnimated", "collapse"], outputs: ["collapsed", "collapses", "expanded", "expands"], exportAs: ["bs-collapse"] }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: StaticAssetsModalComponent, decorators: [{
type: Component,
args: [{ selector: 'c8y-static-assets-modal', imports: [NgFor, NgIf, AsyncPipe, DatePipe, CoreModule, PopoverModule, CollapseModule], standalone: true, template: "<c8y-modal\n [title]=\"modalTitle\"\n (onDismiss)=\"cancel()\"\n [headerClasses]=\"'dialog-header'\"\n [labels]=\"{ cancel: 'Cancel' }\"\n>\n <ng-container c8y-modal-title>\n <span [c8yIcon]=\"'select-all'\"></span>\n </ng-container>\n <ng-container *ngIf=\"files$ | async as assets; else loading\">\n <div class=\"text-center sticky-top separator-bottom bg-component\" style=\"z-index: 1001;\">\n <p *ngIf=\"assets.length\" class=\"m-0 p-16\">\n {{ 'Select from the list below or`first part, followed by upload a new asset`' | translate }}\n <button\n class=\"btn-link\"\n aria-controls=\"collapseUpload\"\n [attr.aria-expanded]=\"isExpanded\"\n (click)=\"isExpanded = !isExpanded\"\n >\n {{ 'upload a new asset' | translate }}\n </button>\n </p>\n <div\n class=\"collapse\"\n id=\"collapseUpload\"\n [isAnimated]=\"true\"\n [collapse]=\"!isExpanded\"\n >\n <div class=\"p-t-24 p-l-24 p-r-24 bg-level-1 separator-top-bottom p-b-32\">\n <c8y-drop-area\n class=\"drop-area-sm m-b-8\"\n [icon]=\"'upload'\"\n [accept]=\"accept\"\n (dropped)=\"addFiles($event)\"\n ></c8y-drop-area>\n <c8y-messages\n [helpMessage]=\"\n 'After uploading, the asset will be visible in the list below.' | translate\n \"\n ></c8y-messages>\n </div>\n </div>\n </div>\n <div *ngIf=\"assets.length\">\n <c8y-list-group\n class=\"m-b-0\"\n *ngIf=\"layout != 'grid'\"\n >\n <c8y-list-item *ngFor=\"let asset of assets\">\n <c8y-list-item-icon icon=\"file\"></c8y-list-item-icon>\n\n <c8y-list-item-body>\n <div class=\"row\">\n <div class=\"col-md-3 col-xs-12 d-flex a-i-center\">\n <div\n class=\"text-truncate\"\n title=\"{{ asset.fileName }}\"\n >\n {{ asset.fileName }}\n </div>\n <button\n class=\"btn-dot m-l-4\"\n [title]=\"'Preview' | translate\"\n [popover]=\"preview\"\n placement=\"end\"\n triggers=\"focus\"\n container=\"body\"\n [adaptivePosition]=\"false\"\n >\n <i c8yIcon=\"eye\"></i>\n </button>\n <ng-template #preview>\n <div class=\"bg-checkered\">\n <img\n class=\"fit-w\"\n [alt]=\"asset.fileName\"\n [src]=\"asset.path\"\n />\n </div>\n </ng-template>\n </div>\n <div class=\"col-md-3 col-xs-12 text-muted\">\n <code class=\"text-10\">{{ asset.type }}</code>\n </div>\n <div class=\"col-md-2 col-xs-12 text-muted\">\n <span class=\"small\">{{ asset.size | bytes }}</span>\n </div>\n <div\n class=\"col-md-2 col-xs-12 text-muted\"\n [title]=\"asset.addedAt | date\"\n >\n <div class=\"icon-flex small\">\n <i\n class=\"m-r-4\"\n c8yIcon=\"calendar\"\n ></i>\n <span>{{ asset.addedAt | date }}</span>\n </div>\n </div>\n <div class=\"col-md-2 col-xs-12 d-flex\">\n <button\n class=\"btn btn-default btn-sm m-l-auto showOnHover\"\n (click)=\"select(asset)\"\n translate\n >\n Select\n </button>\n </div>\n </div>\n </c8y-list-item-body>\n </c8y-list-item>\n </c8y-list-group>\n <div\n class=\"card-group-block interact-grid\"\n *ngIf=\"layout === 'grid'\"\n >\n <button\n class=\"col-md-3 col-sm-4 col-xs-12 card btn-clean interact pointer\"\n *ngFor=\"let asset of assets\"\n (click)=\"select(asset)\"\n >\n <div class=\"card-block\">\n <div class=\"bg-checkered\">\n <img\n class=\"img-responsive m-auto img-square\"\n [alt]=\"asset.fileName\"\n [src]=\"asset.path\"\n />\n </div>\n <p\n class=\"text-medium text-truncate-wrap m-t-8\"\n title=\"{{ asset.fileName }}\"\n >\n {{ asset.fileName }}\n </p>\n <p class=\"m-b-4\">\n <code class=\"text-10\">{{ asset.type }}</code>\n </p>\n <p class=\"small text-muted d-flex a-i-center\">\n {{ asset.size | bytes }}\n <span class=\"m-l-auto\">\n <i\n class=\"m-r-4\"\n c8yIcon=\"calendar\"\n ></i>\n <span>{{ asset.addedAt | date }}</span>\n </span>\n </p>\n </div>\n </button>\n </div>\n </div>\n </ng-container>\n\n <ng-template #loading>\n <div class=\"p-24\">\n <c8y-loading></c8y-loading>\n </div>\n </ng-template>\n</c8y-modal>\n" }]
}], ctorParameters: () => [{ type: i1.BsModalRef }, { type: i2.StaticAssetsService }], propDecorators: { assetType: [{
type: Input
}], supportedFileExtensions: [{
type: Input
}], modalTitle: [{
type: Input
}], layout: [{
type: Input
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RhdGljLWFzc2V0cy1tb2RhbC5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zdGF0aWMtYXNzZXRzL21vZGFsL3N0YXRpYy1hc3NldHMtbW9kYWwuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vc3RhdGljLWFzc2V0cy9tb2RhbC9zdGF0aWMtYXNzZXRzLW1vZGFsLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxTQUFTLEVBQUUsS0FBSyxFQUFVLE1BQU0sZUFBZSxDQUFDO0FBRXpELE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUNqRCxPQUFPLEVBQWMsT0FBTyxFQUFFLElBQUksRUFBRSxLQUFLLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDeEQsT0FBTyxFQUFFLG1CQUFtQixFQUFFLE1BQU0sd0NBQXdDLENBQUM7QUFDN0UsT0FBTyxFQUFFLEtBQUssRUFBRSxXQUFXLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQzlELE9BQU8sRUFBRSxTQUFTLEVBQUUsUUFBUSxFQUFFLEtBQUssRUFBRSxJQUFJLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUNuRSxPQUFPLEVBQUUsVUFBVSxFQUFlLE9BQU8sRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQ3ZFLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQztBQUN0RCxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0sd0JBQXdCLENBQUM7Ozs7Ozs7QUFReEQsTUFBTSxPQUFPLDBCQUEwQjtJQWNyQyxZQUNVLFFBQW9CLEVBQ3BCLFlBQWlDO1FBRGpDLGFBQVEsR0FBUixRQUFRLENBQVk7UUFDcEIsaUJBQVksR0FBWixZQUFZLENBQXFCO1FBZmxDLGNBQVMsR0FBb0IsVUFBVSxDQUFDO1FBQ3hDLDRCQUF1QixHQUFhLEVBQUUsQ0FBQztRQUN2Qyxl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QyxJQUFJLEVBQUUsQ0FBQztRQUNyQixJQUFJLENBQUMsTUFBTSxFQUFFLENBQUM7SUFDaEIsQ0FBQzsrR0F0RVUsMEJBQTBCO21HQUExQiwwQkFBMEIsdU5DakJ2QywrMUtBZ0tBLDRDRGxKWSxLQUFLLG1IQUFFLElBQUksd0ZBQUUsU0FBUyx5Q0FBRSxRQUFRLDRDQUFFLFVBQVUsK2tEQUFFLGFBQWEsOFZBQUUsY0FBYzs7NEZBRzFFLDBCQUEwQjtrQkFOdEMsU0FBUzsrQkFDRSx5QkFBeUIsV0FFMUIsQ0FBQyxLQUFLLEVBQUUsSUFBSSxFQUFFLFNBQVMsRUFBRSxRQUFRLEVBQUUsVUFBVSxFQUFFLGFBQWEsRUFBRSxjQUFjLENBQUMsY0FDMUUsSUFBSTtpSEFHUCxTQUFTO3NCQUFqQixLQUFLO2dCQUNHLHVCQUF1QjtzQkFBL0IsS0FBSztnQkFDRyxVQUFVO3NCQUFsQixLQUFLO2dCQUNHLE1BQU07c0JBQWQsS0FBSyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENvbXBvbmVudCwgSW5wdXQsIE9uSW5pdCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHR5cGUgeyBTdGF0aWNBc3NldCwgU3RhdGljQXNzZXRUeXBlIH0gZnJvbSAnQGM4eS9uZ3gtY29tcG9uZW50cy9zdGF0aWMtYXNzZXRzL2RhdGEnO1xuaW1wb3J0IHsgQnNNb2RhbFJlZiB9IGZyb20gJ25neC1ib290c3RyYXAvbW9kYWwnO1xuaW1wb3J0IHsgT2JzZXJ2YWJsZSwgU3ViamVjdCwgZnJvbSwgbWVyZ2UgfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IFN0YXRpY0Fzc2V0c1NlcnZpY2UgfSBmcm9tICdAYzh5L25neC1jb21wb25lbnRzL3N0YXRpYy1hc3NldHMvZGF0YSc7XG5pbXBvcnQgeyBmaXJzdCwgc2hhcmVSZXBsYXksIG1hcCwgdGFwIH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuaW1wb3J0IHsgQXN5bmNQaXBlLCBEYXRlUGlwZSwgTmdGb3IsIE5nSWYgfSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xuaW1wb3J0IHsgQ29yZU1vZHVsZSwgRHJvcHBlZEZpbGUsIGdldHRleHQgfSBmcm9tICdAYzh5L25neC1jb21wb25lbnRzJztcbmltcG9ydCB7IFBvcG92ZXJNb2R1bGUgfSBmcm9tICduZ3gtYm9vdHN0cmFwL3BvcG92ZXInO1xuaW1wb3J0IHsgQ29sbGFwc2VNb2R1bGUgfSBmcm9tICduZ3gtYm9vdHN0cmFwL2NvbGxhcHNlJztcblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnYzh5LXN0YXRpYy1hc3NldHMtbW9kYWwnLFxuICB0ZW1wbGF0ZVVybDogJy4vc3RhdGljLWFzc2V0cy1tb2RhbC5jb21wb25lbnQuaHRtbCcsXG4gIGltcG9ydHM6IFtOZ0ZvciwgTmdJZiwgQXN5bmNQaXBlLCBEYXRlUGlwZSwgQ29yZU1vZHVsZSwgUG9wb3Zlck1vZHVsZSwgQ29sbGFwc2VNb2R1bGVdLFxuICBzdGFuZGFsb25lOiB0cnVlXG59KVxuZXhwb3J0IGNsYXNzIFN0YXRpY0Fzc2V0c01vZGFsQ29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0IHtcbiAgQElucHV0KCkgYXNzZXRUeXBlOiBTdGF0aWNBc3NldFR5cGUgPSAnYnJhbmRpbmcnO1xuICBASW5wdXQoKSBzdXBwb3J0ZWRGaWxlRXh0ZW5zaW9uczogc3RyaW5nW10gPSBbXTtcbiAgQElucHV0KCkgbW9kYWxUaXRsZTogc3RyaW5nID0gZ2V0dGV4dCgnU2VsZWN0IGFzc2V0Jyk7XG4gIEBJbnB1dCgpIGxheW91dDogJ2xpc3QnIHwgJ2dyaWQnID0gJ2dyaWQnO1xuICByZXN1bHQ6IFByb21pc2U8U3RhdGljQXNzZXQ+O1xuICBmaWxlcyQ6IE9ic2VydmFibGU8U3RhdGljQXNzZXRbXT47XG4gIGFjY2VwdCA9ICcnO1xuICBpc0V4cGFuZGVkID0gZmFsc2U7XG4gIHByaXZhdGUgX3VuZmlsdGVyZWRGaWxlcyQ6IE9ic2VydmFibGU8U3RhdGljQXNzZXRbXT47XG4gIHByaXZhdGUgX2ZpbGVzVXBkYXRlJCA9IG5ldyBTdWJqZWN0PFN0YXRpY0Fzc2V0W10+KCk7XG4gIHByaXZhdGUgcmVzb2x2ZTogKHJlczogU3RhdGljQXNzZXQpID0+IHZvaWQ7XG4gIHByaXZhdGUgcmVqZWN0OiAoZXJyPzogdW5rbm93bikgPT4gdm9pZDtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIG1vZGFsUmVmOiBCc01vZGFsUmVmLFxuICAgIHByaXZhdGUgc3RhdGljQXNzZXRzOiBTdGF0aWNBc3NldHNTZXJ2aWNlXG4gICkge1xuICAgIHRoaXMucmVzdWx0ID0gbmV3IFByb21pc2U8U3RhdGljQXNzZXQ+KChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIHRoaXMucmVzb2x2ZSA9IHJlc29sdmU7XG4gICAgICB0aGlzLnJlamVjdCA9IHJlamVjdDtcbiAgICB9KTtcbiAgfVxuXG4gIG5nT25Jbml0KCkge1xuICAgIHRoaXMuX3VuZmlsdGVyZWRGaWxlcyQgPSBtZXJnZShcbiAgICAgIHRoaXMuX2ZpbGVzVXBkYXRlJCxcbiAgICAgIGZyb20odGhpcy5zdGF0aWNBc3NldHMubGlzdEZpbGVzKHRoaXMuYXNzZXRUeXBlKSlcbiAgICApLnBpcGUoc2hhcmVSZXBsYXkoMSkpO1xuICAgIHRoaXMuZmlsZXMkID0gdGhpcy5fdW5maWx0ZXJlZEZpbGVzJC5waXBlKFxuICAgICAgbWFwKGZpbGVzID0+XG4gICAgICAgIHRoaXMuc3VwcG9ydGVkRmlsZUV4dGVuc2lvbnNcbiAgICAgICAgICA/IGZpbGVzLmZpbHRlcih0bXAgPT4gdGhpcy5zdXBwb3J0ZWRGaWxlRXh0ZW5zaW9ucy5pbmNsdWRlcyh0bXAuZXh0ZW5zaW9uLnRvTG93ZXJDYXNlKCkpKVxuICAgICAgICAgIDogZmlsZXNcbiAgICAgICksXG4gICAgICBtYXAoZmlsZXMgPT5cbiAgICAgICAgZmlsZXMuc29ydCgoYSwgYikgPT4gKGEuYWRkZWRBdCA8IGIuYWRkZWRBdCA/IDEgOiBhLmFkZGVkQXQgPiBiLmFkZGVkQXQgPyAtMSA6IDApKVxuICAgICAgKSxcbiAgICAgIHRhcChmaWxlcyA9PiB7XG4gICAgICAgIGlmICghZmlsZXMubGVuZ3RoKSB7XG4gICAgICAgICAgdGhpcy5pc0V4cGFuZGVkID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgfSlcbiAgICApO1xuICAgIGlmICh0aGlzLnN1cHBvcnRlZEZpbGVFeHRlbnNpb25zKSB7XG4gICAgICB0aGlzLmFjY2VwdCA9IHRoaXMuc3VwcG9ydGVkRmlsZUV4dGVuc2lvbnMuam9pbignLCcpO1xuICAgIH1cbiAgfVxuXG4gIGFzeW5jIGFkZEZpbGVzKGZpbGVzOiBEcm9wcGVkRmlsZVtdKSB7XG4gICAgaWYgKCFmaWxlcz8ubGVuZ3RoKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGNvbnN0IGV4aXN0aW5nRmlsZXMgPSBhd2FpdCB0aGlzLl91bmZpbHRlcmVkRmlsZXMkLnBpcGUoZmlyc3QoKSkudG9Qcm9taXNlKCk7XG4gICAgY29uc3QgbmV3RmlsZXMgPSBhd2FpdCB0aGlzLnN0YXRpY0Fzc2V0cy5hZGRGaWxlc1RvU3RhdGljQXNzZXRzKFxuICAgICAgdGhpcy5hc3NldFR5cGUsXG4gICAgICBmaWxlcyxcbiAgICAgIGV4aXN0aW5nRmlsZXNcbiAgICApO1xuICAgIHRoaXMuX2ZpbGVzVXBkYXRlJC5uZXh0KG5ld0ZpbGVzKTtcbiAgfVxuXG4gIHNlbGVjdChhc3NldDogU3RhdGljQXNzZXQpIHtcbiAgICB0aGlzLm1vZGFsUmVmLmhpZGUoKTtcbiAgICB0aGlzLnJlc29sdmUoYXNzZXQpO1xuICB9XG5cbiAgY2FuY2VsKCkge1xuICAgIHRoaXMubW9kYWxSZWYuaGlkZSgpO1xuICAgIHRoaXMucmVqZWN0KCk7XG4gIH1cbn1cbiIsIjxjOHktbW9kYWxcbiAgW3RpdGxlXT1cIm1vZGFsVGl0bGVcIlxuICAob25EaXNtaXNzKT1cImNhbmNlbCgpXCJcbiAgW2hlYWRlckNsYXNzZXNdPVwiJ2RpYWxvZy1oZWFkZXInXCJcbiAgW2xhYmVsc109XCJ7IGNhbmNlbDogJ0NhbmNlbCcgfVwiXG4+XG4gIDxuZy1jb250YWluZXIgYzh5LW1vZGFsLXRpdGxlPlxuICAgIDxzcGFuIFtjOHlJY29uXT1cIidzZWxlY3QtYWxsJ1wiPjwvc3Bhbj5cbiAgPC9uZy1jb250YWluZXI+XG4gIDxuZy1jb250YWluZXIgKm5nSWY9XCJmaWxlcyQgfCBhc3luYyBhcyBhc3NldHM7IGVsc2UgbG9hZGluZ1wiPlxuICAgIDxkaXYgY2xhc3M9XCJ0ZXh0LWNlbnRlciBzdGlja3ktdG9wIHNlcGFyYXRvci1ib3R0b20gYmctY29tcG9uZW50XCIgc3R5bGU9XCJ6LWluZGV4OiAxMDAxO1wiPlxuICAgICAgPHAgKm5nSWY9XCJhc3NldHMubGVuZ3RoXCIgY2xhc3M9XCJtLTAgcC0xNlwiPlxuICAgICAgICB7eyAnU2VsZWN0IGZyb20gdGhlIGxpc3QgYmVsb3cgb3JgZmlyc3QgcGFydCwgZm9sbG93ZWQgYnkgdXBsb2FkIGEgbmV3IGFzc2V0YCcgfCB0cmFuc2xhdGUgfX1cbiAgICAgICAgPGJ1dHRvblxuICAgICAgICAgIGNsYXNzPVwiYnRuLWxpbmtcIlxuICAgICAgICAgIGFyaWEtY29udHJvbHM9XCJjb2xsYXBzZVVwbG9hZFwiXG4gICAgICAgICAgW2F0dHIuYXJpYS1leHBhbmRlZF09XCJpc0V4cGFuZGVkXCJcbiAgICAgICAgICAoY2xpY2spPVwiaXNFeHBhbmRlZCA9ICFpc0V4cGFuZGVkXCJcbiAgICAgICAgPlxuICAgICAgICAgIHt7ICd1cGxvYWQgYSBuZXcgYXNzZXQnIHwgdHJhbnNsYXRlIH19XG4gICAgICAgIDwvYnV0dG9uPlxuICAgICAgPC9wPlxuICAgICAgPGRpdlxuICAgICAgICBjbGFzcz1cImNvbGxhcHNlXCJcbiAgICAgICAgaWQ9XCJjb2xsYXBzZVVwbG9hZFwiXG4gICAgICAgIFtpc0FuaW1hdGVkXT1cInRydWVcIlxuICAgICAgICBbY29sbGFwc2VdPVwiIWlzRXhwYW5kZWRcIlxuICAgICAgPlxuICAgICAgICA8ZGl2IGNsYXNzPVwicC10LTI0IHAtbC0yNCBwLXItMjQgYmctbGV2ZWwtMSBzZXBhcmF0b3ItdG9wLWJvdHRvbSBwLWItMzJcIj5cbiAgICAgICAgICA8Yzh5LWRyb3AtYXJlYVxuICAgICAgICAgICAgY2xhc3M9XCJkcm9wLWFyZWEtc20gbS1iLThcIlxuICAgICAgICAgICAgW2ljb25dPVwiJ3VwbG9hZCdcIlxuICAgICAgICAgICAgW2FjY2VwdF09XCJhY2NlcHRcIlxuICAgICAgICAgICAgKGRyb3BwZWQpPVwiYWRkRmlsZXMoJGV2ZW50KVwiXG4gICAgICAgICAgPjwvYzh5LWRyb3AtYXJlYT5cbiAgICAgICAgICA8Yzh5LW1lc3NhZ2VzXG4gICAgICAgICAgICBbaGVscE1lc3NhZ2VdPVwiXG4gICAgICAgICAgICAgICdBZnRlciB1cGxvYWRpbmcsIHRoZSBhc3NldCB3aWxsIGJlIHZpc2libGUgaW4gdGhlIGxpc3QgYmVsb3cuJyB8IHRyYW5zbGF0ZVxuICAgICAgICAgICAgXCJcbiAgICAgICAgICA+PC9jOHktbWVzc2FnZXM+XG4gICAgICAgIDwvZGl2PlxuICAgICAgPC9kaXY+XG4gICAgPC9kaXY+XG4gICAgPGRpdiAqbmdJZj1cImFzc2V0cy5sZW5ndGhcIj5cbiAgICAgIDxjOHktbGlzdC1ncm91cFxuICAgICAgICBjbGFzcz1cIm0tYi0wXCJcbiAgICAgICAgKm5nSWY9XCJsYXlvdXQgIT0gJ2dyaWQnXCJcbiAgICAgID5cbiAgICAgICAgPGM4eS1saXN0LWl0ZW0gKm5nRm9yPVwibGV0IGFzc2V0IG9mIGFzc2V0c1wiPlxuICAgICAgICAgIDxjOHktbGlzdC1pdGVtLWljb24gaWNvbj1cImZpbGVcIj48L2M4eS1saXN0LWl0ZW0taWNvbj5cblxuICAgICAgICAgIDxjOHktbGlzdC1pdGVtLWJvZHk+XG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwicm93XCI+XG4gICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJjb2wtbWQtMyBjb2wteHMtMTIgZC1mbGV4IGEtaS1jZW50ZXJcIj5cbiAgICAgICAgICAgICAgICA8ZGl2XG4gICAgICAgICAgICAgICAgICBjbGFzcz1cInRleHQtdHJ1bmNhdGVcIlxuICAgICAgICAgICAgICAgICAgdGl0bGU9XCJ7eyBhc3NldC5maWxlTmFtZSB9fVwiXG4gICAgICAgICAgICAgICAgPlxuICAgICAgICAgICAgICAgICAge3sgYXNzZXQuZmlsZU5hbWUgfX1cbiAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgICAgICAgICBjbGFzcz1cImJ0bi1kb3QgbS1sLTRcIlxuICAgICAgICAgICAgICAgICAgW3RpdGxlXT1cIidQcmV2aWV3JyB8IHRyYW5zbGF0ZVwiXG4gICAgICAgICAgICAgICAgICBbcG9wb3Zlcl09XCJwcmV2aWV3XCJcbiAgICAgICAgICAgICAgICAgIHBsYWNlbWVudD1cImVuZFwiXG4gICAgICAgICAgICAgICAgICB0cmlnZ2Vycz1cImZvY3VzXCJcbiAgICAgICAgICAgICAgICAgIGNvbnRhaW5lcj1cImJvZHlcIlxuICAgICAgICAgICAgICAgICAgW2FkYXB0aXZlUG9zaXRpb25dPVwiZmFsc2VcIlxuICAgICAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICAgIDxpIGM4eUljb249XCJleWVcIj48L2k+XG4gICAgICAgICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgICAgICAgPG5nLXRlbXBsYXRlICNwcmV2aWV3PlxuICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImJnLWNoZWNrZXJlZFwiPlxuICAgICAgICAgICAgICAgICAgICA8aW1nXG4gICAgICAgICAgICAgICAgICAgICAgY2xhc3M9XCJmaXQtd1wiXG4gICAgICAgICAgICAgICAgICAgICAgW2FsdF09XCJhc3NldC5maWxlTmFtZVwiXG4gICAgICAgICAgICAgICAgICAgICAgW3NyY109XCJhc3NldC5wYXRoXCJcbiAgICAgICAgICAgICAgICAgICAgLz5cbiAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgIDwvbmctdGVtcGxhdGU+XG4gICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiY29sLW1kLTMgY29sLXhzLTEyIHRleHQtbXV0ZWRcIj5cbiAgICAgICAgICAgICAgICA8Y29kZSBjbGFzcz1cInRleHQtMTBcIj57eyBhc3NldC50eXBlIH19PC9jb2RlPlxuICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImNvbC1tZC0yIGNvbC14cy0xMiB0ZXh0LW11dGVkXCI+XG4gICAgICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJzbWFsbFwiPnt7IGFzc2V0LnNpemUgfCBieXRlcyB9fTwvc3Bhbj5cbiAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgIDxkaXZcbiAgICAgICAgICAgICAgICBjbGFzcz1cImNvbC1tZC0yIGNvbC14cy0xMiB0ZXh0LW11dGVkXCJcbiAgICAgICAgICAgICAgICBbdGl0bGVdPVwiYXNzZXQuYWRkZWRBdCB8IGRhdGVcIlxuICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImljb24tZmxleCBzbWFsbFwiPlxuICAgICAgICAgICAgICAgICAgPGlcbiAgICAgICAgICAgICAgICAgICAgY2xhc3M9XCJtLXItNFwiXG4gICAgICAgICAgICAgICAgICAgIGM4eUljb249XCJjYWxlbmRhclwiXG4gICAgICAgICAgICAgICAgICA+PC9pPlxuICAgICAgICAgICAgICAgICAgPHNwYW4+e3sgYXNzZXQuYWRkZWRBdCB8IGRhdGUgfX08L3NwYW4+XG4gICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiY29sLW1kLTIgY29sLXhzLTEyIGQtZmxleFwiPlxuICAgICAgICAgICAgICAgIDxidXR0b25cbiAgICAgICAgICAgICAgICAgIGNsYXNzPVwiYnRuIGJ0bi1kZWZhdWx0IGJ0bi1zbSBtLWwtYXV0byBzaG93T25Ib3ZlclwiXG4gICAgICAgICAgICAgICAgICAoY2xpY2spPVwic2VsZWN0KGFzc2V0KVwiXG4gICAgICAgICAgICAgICAgICB0cmFuc2xhdGVcbiAgICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgICBTZWxlY3RcbiAgICAgICAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICA8L2M4eS1saXN0LWl0ZW0tYm9keT5cbiAgICAgICAgPC9jOHktbGlzdC1pdGVtPlxuICAgICAgPC9jOHktbGlzdC1ncm91cD5cbiAgICAgIDxkaXZcbiAgICAgICAgY2xhc3M9XCJjYXJkLWdyb3VwLWJsb2NrIGludGVyYWN0LWdyaWRcIlxuICAgICAgICAqbmdJZj1cImxheW91dCA9PT0gJ2dyaWQnXCJcbiAgICAgID5cbiAgICAgICAgPGJ1dHRvblxuICAgICAgICAgIGNsYXNzPVwiY29sLW1kLTMgY29sLXNtLTQgY29sLXhzLTEyIGNhcmQgYnRuLWNsZWFuIGludGVyYWN0IHBvaW50ZXJcIlxuICAgICAgICAgICpuZ0Zvcj1cImxldCBhc3NldCBvZiBhc3NldHNcIlxuICAgICAgICAgIChjbGljayk9XCJzZWxlY3QoYXNzZXQpXCJcbiAgICAgICAgPlxuICAgICAgICAgIDxkaXYgY2xhc3M9XCJjYXJkLWJsb2NrXCI+XG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwiYmctY2hlY2tlcmVkXCI+XG4gICAgICAgICAgICAgIDxpbWdcbiAgICAgICAgICAgICAgICBjbGFzcz1cImltZy1yZXNwb25zaXZlIG0tYXV0byBpbWctc3F1YXJlXCJcbiAgICAgICAgICAgICAgICBbYWx0XT1cImFzc2V0LmZpbGVOYW1lXCJcbiAgICAgICAgICAgICAgICBbc3JjXT1cImFzc2V0LnBhdGhcIlxuICAgICAgICAgICAgICAvPlxuICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICA8cFxuICAgICAgICAgICAgICBjbGFzcz1cInRleHQtbWVkaXVtIHRleHQtdHJ1bmNhdGUtd3JhcCBtLXQtOFwiXG4gICAgICAgICAgICAgIHRpdGxlPVwie3sgYXNzZXQuZmlsZU5hbWUgfX1cIlxuICAgICAgICAgICAgPlxuICAgICAgICAgICAgICB7eyBhc3NldC5maWxlTmFtZSB9fVxuICAgICAgICAgICAgPC9wPlxuICAgICAgICAgICAgPHAgY2xhc3M9XCJtLWItNFwiPlxuICAgICAgICAgICAgICA8Y29kZSBjbGFzcz1cInRleHQtMTBcIj57eyBhc3NldC50eXBlIH19PC9jb2RlPlxuICAgICAgICAgICAgPC9wPlxuICAgICAgICAgICAgPHAgY2xhc3M9XCJzbWFsbCB0ZXh0LW11dGVkIGQtZmxleCBhLWktY2VudGVyXCI+XG4gICAgICAgICAgICAgIHt7IGFzc2V0LnNpemUgfCBieXRlcyB9fVxuICAgICAgICAgICAgICA8c3BhbiBjbGFzcz1cIm0tbC1hdXRvXCI+XG4gICAgICAgICAgICAgICAgPGlcbiAgICAgICAgICAgICAgICAgIGNsYXNzPVwibS1yLTRcIlxuICAgICAgICAgICAgICAgICAgYzh5SWNvbj1cImNhbGVuZGFyXCJcbiAgICAgICAgICAgICAgICA+PC9pPlxuICAgICAgICAgICAgICAgIDxzcGFuPnt7IGFzc2V0LmFkZGVkQXQgfCBkYXRlIH19PC9zcGFuPlxuICAgICAgICAgICAgICA8L3NwYW4+XG4gICAgICAgICAgICA8L3A+XG4gICAgICAgICAgPC9kaXY+XG4gICAgICAgIDwvYnV0dG9uPlxuICAgICAgPC9kaXY+XG4gICAgPC9kaXY+XG4gIDwvbmctY29udGFpbmVyPlxuXG4gIDxuZy10ZW1wbGF0ZSAjbG9hZGluZz5cbiAgICA8ZGl2IGNsYXNzPVwicC0yNFwiPlxuICAgICAgPGM4eS1sb2FkaW5nPjwvYzh5LWxvYWRpbmc+XG4gICAgPC9kaXY+XG4gIDwvbmctdGVtcGxhdGU+XG48L2M4eS1tb2RhbD5cbiJdfQ==