UNPKG

@nova-ui/dashboards

Version:

Nova Dashboards is a framework designed to provide feature developers with a common solution for presenting data coming from various sources within a single view, as well as a set of predefined widget visualizations that are 100% configuration-driven and

109 lines 19.9 kB
// © 2022 SolarWinds Worldwide, LLC. All rights reserved. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to // deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. import { ChangeDetectorRef, Component, ElementRef, HostBinding, Inject, Input, NgZone, } from "@angular/core"; import { Subject } from "rxjs"; import { takeUntil } from "rxjs/operators"; import { EventBus, ResizeObserverDirective } from "@nova-ui/bits"; import { mapDataToFormatterProperties } from "../../functions/map-data-to-formatter-properties"; import { DRILLDOWN } from "../../services/types"; import { PIZZAGNA_EVENT_BUS } from "../../types"; import * as i0 from "@angular/core"; import * as i1 from "@angular/common"; import * as i2 from "@nova-ui/bits"; import * as i3 from "@angular/cdk/portal"; import * as i4 from "../../pizzagna/directives/component-portal/component-portal.directive"; const RESIZE_DEBOUNCE_TIME = 10; export class ListWidgetComponent { static { this.lateLoadKey = "ListWidgetComponent"; } constructor(changeDetector, zone, host, eventBus) { this.changeDetector = changeDetector; this.zone = zone; this.host = host; this.eventBus = eventBus; this.itemFormatterProps = new Map(); this.destroy$ = new Subject(); } ngOnInit() { this.initResizeObserver(); } ngOnChanges(changes) { if (changes.data?.currentValue) { changes.data.currentValue.forEach((v) => this.itemFormatterProps.set(v, this.calcItemProps(v))); } } // TODO: think of how to get rid of this logic on listWidget // since it's very specific for drilldown and appstack onListItemEvent(item) { this.eventBus.getStream(DRILLDOWN).next({ payload: item }); } ngOnDestroy() { this.destroy$.next(); this.destroy$.complete(); this.itemFormatterProps.clear(); } getPropsFor(item) { return { ...this.itemFormatterProps.get(item), widgetWidth: this.widgetWidth, }; } shouldDisplayRepeat() { return this.data?.length > 0; } calcItemProps(item) { if (!this.configuration) { return item; } return { ...mapDataToFormatterProperties(this.configuration, item), ...this.configuration.itemProperties, }; } // think of using eventBus to let widget entities know about it's width. - mb some formatters for widget doesn't care about it's width. initResizeObserver() { const resizeDirective = new ResizeObserverDirective(this.host, this.zone); resizeDirective.debounceTime = RESIZE_DEBOUNCE_TIME; resizeDirective.ngAfterViewInit(); resizeDirective.containerResize .pipe(takeUntil(this.destroy$)) .subscribe(() => { this.widgetWidth = this.host.nativeElement.offsetWidth; }); } /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ListWidgetComponent, deps: [{ token: i0.ChangeDetectorRef }, { token: i0.NgZone }, { token: i0.ElementRef }, { token: PIZZAGNA_EVENT_BUS }], target: i0.ɵɵFactoryTarget.Component }); } /** @nocollapse */ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: ListWidgetComponent, selector: "nui-list-widget", inputs: { data: "data", configuration: "configuration", elementClass: "elementClass" }, host: { properties: { "class": "this.elementClass" } }, usesOnChanges: true, ngImport: i0, template: "<nui-repeat\n *ngIf=\"shouldDisplayRepeat()\"\n [itemsSource]=\"data\"\n [repeatItemTemplateRef]=\"repeatItemTemplate\"\n>\n</nui-repeat>\n\n<div class=\"empty\" *ngIf=\"!shouldDisplayRepeat()\">\n <nui-image image=\"no-data-to-show\"></nui-image>\n</div>\n\n<ng-template #repeatItemTemplate let-item=\"item\">\n <div class=\"empty\" *ngIf=\"!item\">\n <nui-image image=\"no-data-to-show\"></nui-image>\n </div>\n <ng-container\n nuiComponentPortal\n #componentPortal=\"nuiComponentPortal\"\n [componentId]=\"configuration.componentType\"\n [componentType]=\"configuration.componentType\"\n [properties]=\"getPropsFor(item)\"\n [outputs]=\"['navigated']\"\n (output)=\"onListItemEvent(item)\"\n >\n <ng-template\n [cdkPortalOutlet]=\"componentPortal.portal\"\n (attached)=\"componentPortal.attached($event)\"\n ></ng-template>\n </ng-container>\n</ng-template>\n", styles: [":host{height:100%;overflow:auto}.empty{height:100%;display:grid;place-content:center}\n"], dependencies: [{ kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i2.ImageComponent, selector: "nui-image", inputs: ["image", "description", "float", "margin", "isWatermark", "width", "height", "autoFill"] }, { kind: "directive", type: i3.CdkPortalOutlet, selector: "[cdkPortalOutlet]", inputs: ["cdkPortalOutlet"], outputs: ["attached"], exportAs: ["cdkPortalOutlet"] }, { kind: "directive", type: i4.ComponentPortalDirective, selector: "[nuiComponentPortal]", inputs: ["componentId", "componentType", "properties", "providers", "outputs"], outputs: ["output"], exportAs: ["nuiComponentPortal"] }, { kind: "component", type: i2.RepeatComponent, selector: "nui-repeat", inputs: ["draggable", "reorderable", "preventRowClick", "repeatItemTemplateRef", "dragHandleTemplateRef", "dragPreviewClass", "dragPreviewTemplateRef", "actionsTemplateRef", "selectionMode", "paddingSize", "virtualScroll", "itemSize", "selection", "itemConfig", "itemsSource", "highlightSelectedItem"], outputs: ["draggableChange", "reorderableChange", "itemsReordered", "selectionChange"] }] }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ListWidgetComponent, decorators: [{ type: Component, args: [{ selector: "nui-list-widget", template: "<nui-repeat\n *ngIf=\"shouldDisplayRepeat()\"\n [itemsSource]=\"data\"\n [repeatItemTemplateRef]=\"repeatItemTemplate\"\n>\n</nui-repeat>\n\n<div class=\"empty\" *ngIf=\"!shouldDisplayRepeat()\">\n <nui-image image=\"no-data-to-show\"></nui-image>\n</div>\n\n<ng-template #repeatItemTemplate let-item=\"item\">\n <div class=\"empty\" *ngIf=\"!item\">\n <nui-image image=\"no-data-to-show\"></nui-image>\n </div>\n <ng-container\n nuiComponentPortal\n #componentPortal=\"nuiComponentPortal\"\n [componentId]=\"configuration.componentType\"\n [componentType]=\"configuration.componentType\"\n [properties]=\"getPropsFor(item)\"\n [outputs]=\"['navigated']\"\n (output)=\"onListItemEvent(item)\"\n >\n <ng-template\n [cdkPortalOutlet]=\"componentPortal.portal\"\n (attached)=\"componentPortal.attached($event)\"\n ></ng-template>\n </ng-container>\n</ng-template>\n", styles: [":host{height:100%;overflow:auto}.empty{height:100%;display:grid;place-content:center}\n"] }] }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: i0.NgZone }, { type: i0.ElementRef }, { type: i2.EventBus, decorators: [{ type: Inject, args: [PIZZAGNA_EVENT_BUS] }] }], propDecorators: { data: [{ type: Input }], configuration: [{ type: Input }], elementClass: [{ type: Input }, { type: HostBinding, args: ["class"] }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibGlzdC13aWRnZXQuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vc3JjL2xpYi9jb21wb25lbnRzL2xpc3Qtd2lkZ2V0L2xpc3Qtd2lkZ2V0LmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uL3NyYy9saWIvY29tcG9uZW50cy9saXN0LXdpZGdldC9saXN0LXdpZGdldC5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSx5REFBeUQ7QUFDekQsRUFBRTtBQUNGLCtFQUErRTtBQUMvRSw0RUFBNEU7QUFDNUUsOEVBQThFO0FBQzlFLCtFQUErRTtBQUMvRSw4RUFBOEU7QUFDOUUsNERBQTREO0FBQzVELEVBQUU7QUFDRiw2RUFBNkU7QUFDN0UsdURBQXVEO0FBQ3ZELEVBQUU7QUFDRiw2RUFBNkU7QUFDN0UsNEVBQTRFO0FBQzVFLCtFQUErRTtBQUMvRSwwRUFBMEU7QUFDMUUsaUZBQWlGO0FBQ2pGLDZFQUE2RTtBQUM3RSxpQkFBaUI7QUFFakIsT0FBTyxFQUNILGlCQUFpQixFQUNqQixTQUFTLEVBQ1QsVUFBVSxFQUNWLFdBQVcsRUFDWCxNQUFNLEVBQ04sS0FBSyxFQUNMLE1BQU0sR0FLVCxNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBQy9CLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUUzQyxPQUFPLEVBQUUsUUFBUSxFQUFVLHVCQUF1QixFQUFFLE1BQU0sZUFBZSxDQUFDO0FBRzFFLE9BQU8sRUFBRSw0QkFBNEIsRUFBRSxNQUFNLGtEQUFrRCxDQUFDO0FBQ2hHLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQztBQUNqRCxPQUFPLEVBQXNCLGtCQUFrQixFQUFFLE1BQU0sYUFBYSxDQUFDOzs7Ozs7QUFFckUsTUFBTSxvQkFBb0IsR0FBRyxFQUFFLENBQUM7QUFPaEMs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c0JBQW5CLEtBQUs7Z0JBQ1UsYUFBYTtzQkFBNUIsS0FBSztnQkFDZ0MsWUFBWTtzQkFBakQsS0FBSzs7c0JBQUksV0FBVzt1QkFBQyxPQUFPIiwic291cmNlc0NvbnRlbnQiOlsiLy8gwqkgMjAyMiBTb2xhcldpbmRzIFdvcmxkd2lkZSwgTExDLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy9cbi8vIFBlcm1pc3Npb24gaXMgaGVyZWJ5IGdyYW50ZWQsIGZyZWUgb2YgY2hhcmdlLCB0byBhbnkgcGVyc29uIG9idGFpbmluZyBhIGNvcHlcbi8vICBvZiB0aGlzIHNvZnR3YXJlIGFuZCBhc3NvY2lhdGVkIGRvY3VtZW50YXRpb24gZmlsZXMgKHRoZSBcIlNvZnR3YXJlXCIpLCB0b1xuLy8gIGRlYWwgaW4gdGhlIFNvZnR3YXJlIHdpdGhvdXQgcmVzdHJpY3Rpb24sIGluY2x1ZGluZyB3aXRob3V0IGxpbWl0YXRpb24gdGhlXG4vLyAgcmlnaHRzIHRvIHVzZSwgY29weSwgbW9kaWZ5LCBtZXJnZSwgcHVibGlzaCwgZGlzdHJpYnV0ZSwgc3VibGljZW5zZSwgYW5kL29yXG4vLyAgc2VsbCBjb3BpZXMgb2YgdGhlIFNvZnR3YXJlLCBhbmQgdG8gcGVybWl0IHBlcnNvbnMgdG8gd2hvbSB0aGUgU29mdHdhcmUgaXNcbi8vICBmdXJuaXNoZWQgdG8gZG8gc28sIHN1YmplY3QgdG8gdGhlIGZvbGxvd2luZyBjb25kaXRpb25zOlxuLy9cbi8vIFRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBlcm1pc3Npb24gbm90aWNlIHNoYWxsIGJlIGluY2x1ZGVkIGluXG4vLyAgYWxsIGNvcGllcyBvciBzdWJzdGFudGlhbCBwb3J0aW9ucyBvZiB0aGUgU29mdHdhcmUuXG4vL1xuLy8gVEhFIFNPRlRXQVJFIElTIFBST1ZJREVEIFwiQVMgSVNcIiwgV0lUSE9VVCBXQVJSQU5UWSBPRiBBTlkgS0lORCwgRVhQUkVTUyBPUlxuLy8gIElNUExJRUQsIElOQ0xVRElORyBCVVQgTk9UIExJTUlURUQgVE8gVEhFIFdBUlJBTlRJRVMgT0YgTUVSQ0hBTlRBQklMSVRZLFxuLy8gIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFORCBOT05JTkZSSU5HRU1FTlQuIElOIE5PIEVWRU5UIFNIQUxMIFRIRVxuLy8gIEFVVEhPUlMgT1IgQ09QWVJJR0hUIEhPTERFUlMgQkUgTElBQkxFIEZPUiBBTlkgQ0xBSU0sIERBTUFHRVMgT1IgT1RIRVJcbi8vICBMSUFCSUxJVFksIFdIRVRIRVIgSU4gQU4gQUNUSU9OIE9GIENPTlRSQUNULCBUT1JUIE9SIE9USEVSV0lTRSwgQVJJU0lORyBGUk9NLFxuLy8gIE9VVCBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhFIFNPRlRXQVJFIE9SIFRIRSBVU0UgT1IgT1RIRVIgREVBTElOR1MgSU5cbi8vICBUSEUgU09GVFdBUkUuXG5cbmltcG9ydCB7XG4gICAgQ2hhbmdlRGV0ZWN0b3JSZWYsXG4gICAgQ29tcG9uZW50LFxuICAgIEVsZW1lbnRSZWYsXG4gICAgSG9zdEJpbmRpbmcsXG4gICAgSW5qZWN0LFxuICAgIElucHV0LFxuICAgIE5nWm9uZSxcbiAgICBPbkNoYW5nZXMsXG4gICAgT25EZXN0cm95LFxuICAgIE9uSW5pdCxcbiAgICBTaW1wbGVDaGFuZ2VzLFxufSBmcm9tIFwiQGFuZ3VsYXIvY29yZVwiO1xuaW1wb3J0IHsgU3ViamVjdCB9IGZyb20gXCJyeGpzXCI7XG5pbXBvcnQgeyB0YWtlVW50aWwgfSBmcm9tIFwicnhqcy9vcGVyYXRvcnNcIjtcblxuaW1wb3J0IHsgRXZlbnRCdXMsIElFdmVudCwgUmVzaXplT2JzZXJ2ZXJEaXJlY3RpdmUgfSBmcm9tIFwiQG5vdmEtdWkvYml0c1wiO1xuXG5pbXBvcnQgeyBJTGlzdFdpZGdldENvbmZpZ3VyYXRpb24gfSBmcm9tIFwiLi90eXBlc1wiO1xuaW1wb3J0IHsgbWFwRGF0YVRvRm9ybWF0dGVyUHJvcGVydGllcyB9IGZyb20gXCIuLi8uLi9mdW5jdGlvbnMvbWFwLWRhdGEtdG8tZm9ybWF0dGVyLXByb3BlcnRpZXNcIjtcbmltcG9ydCB7IERSSUxMRE9XTiB9IGZyb20gXCIuLi8uLi9zZXJ2aWNlcy90eXBlc1wiO1xuaW1wb3J0IHsgSUhhc0NoYW5nZURldGVjdG9yLCBQSVpaQUdOQV9FVkVOVF9CVVMgfSBmcm9tIFwiLi4vLi4vdHlwZXNcIjtcblxuY29uc3QgUkVTSVpFX0RFQk9VTkNFX1RJTUUgPSAxMDtcblxuQENvbXBvbmVudCh7XG4gICAgc2VsZWN0b3I6IFwibnVpLWxpc3Qtd2lkZ2V0XCIsXG4gICAgdGVtcGxhdGVVcmw6IFwiLi9saXN0LXdpZGdldC5jb21wb25lbnQuaHRtbFwiLFxuICAgIHN0eWxlVXJsczogW1wiLi9saXN0LXdpZGdldC5jb21wb25lbnQubGVzc1wiXSxcbn0pXG5leHBvcnQgY2xhc3MgTGlzdFdpZGdldENvbXBvbmVudFxuICAgIGltcGxlbWVudHMgT25EZXN0cm95LCBPbkluaXQsIElIYXNDaGFuZ2VEZXRlY3RvciwgT25DaGFuZ2VzXG57XG4gICAgc3RhdGljIGxhdGVMb2FkS2V5ID0gXCJMaXN0V2lkZ2V0Q29tcG9uZW50XCI7XG5cbiAgICBASW5wdXQoKSBwdWJsaWMgZGF0YTogYW55W107XG4gICAgQElucHV0KCkgcHVibGljIGNvbmZpZ3VyYXRpb246IElMaXN0V2lkZ2V0Q29uZmlndXJhdGlvbjtcbiAgICBASW5wdXQoKSBASG9zdEJpbmRpbmcoXCJjbGFzc1wiKSBwdWJsaWMgZWxlbWVudENsYXNzOiBzdHJpbmc7XG5cbiAgICBwcml2YXRlIGl0ZW1Gb3JtYXR0ZXJQcm9wcyA9IG5ldyBNYXAoKTtcbiAgICBwcml2YXRlIHJlYWRvbmx5IGRlc3Ryb3kkID0gbmV3IFN1YmplY3Q8dm9pZD4oKTtcbiAgICBwcml2YXRlIHdpZGdldFdpZHRoOiBudW1iZXI7XG5cbiAgICBjb25zdHJ1Y3RvcihcbiAgICAgICAgcHVibGljIGNoYW5nZURldGVjdG9yOiBDaGFuZ2VEZXRlY3RvclJlZixcbiAgICAgICAgcHJpdmF0ZSB6b25lOiBOZ1pvbmUsXG4gICAgICAgIHByaXZhdGUgaG9zdDogRWxlbWVudFJlZixcbiAgICAgICAgQEluamVjdChQSVpaQUdOQV9FVkVOVF9CVVMpIHByaXZhdGUgZXZlbnRCdXM6IEV2ZW50QnVzPElFdmVudD5cbiAgICApIHt9XG5cbiAgICBwdWJsaWMgbmdPbkluaXQoKTogdm9pZCB7XG4gICAgICAgIHRoaXMuaW5pdFJlc2l6ZU9ic2VydmVyKCk7XG4gICAgfVxuXG4gICAgcHVibGljIG5nT25DaGFuZ2VzKGNoYW5nZXM6IFNpbXBsZUNoYW5nZXMpOiB2b2lkIHtcbiAgICAgICAgaWYgKGNoYW5nZXMuZGF0YT8uY3VycmVudFZhbHVlKSB7XG4gICAgICAgICAgICBjaGFuZ2VzLmRhdGEuY3VycmVudFZhbHVlLmZvckVhY2goKHY6IGFueSkgPT5cbiAgICAgICAgICAgICAgICB0aGlzLml0ZW1Gb3JtYXR0ZXJQcm9wcy5zZXQodiwgdGhpcy5jYWxjSXRlbVByb3BzKHYpKVxuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIFRPRE86IHRoaW5rIG9mIGhvdyB0byBnZXQgcmlkIG9mIHRoaXMgbG9naWMgb24gbGlzdFdpZGdldFxuICAgIC8vIHNpbmNlIGl0J3MgdmVyeSBzcGVjaWZpYyBmb3IgZHJpbGxkb3duIGFuZCBhcHBzdGFja1xuICAgIHB1YmxpYyBvbkxpc3RJdGVtRXZlbnQoaXRlbTogYW55KTogdm9pZCB7XG4gICAgICAgIHRoaXMuZXZlbnRCdXMuZ2V0U3RyZWFtKERSSUxMRE9XTikubmV4dCh7IHBheWxvYWQ6IGl0ZW0gfSk7XG4gICAgfVxuXG4gICAgcHVibGljIG5nT25EZXN0cm95KCk6IHZvaWQge1xuICAgICAgICB0aGlzLmRlc3Ryb3kkLm5leHQoKTtcbiAgICAgICAgdGhpcy5kZXN0cm95JC5jb21wbGV0ZSgpO1xuICAgICAgICB0aGlzLml0ZW1Gb3JtYXR0ZXJQcm9wcy5jbGVhcigpO1xuICAgIH1cblxuICAgIHB1YmxpYyBnZXRQcm9wc0ZvcihpdGVtOiBhbnkpOiBhbnkge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgLi4udGhpcy5pdGVtRm9ybWF0dGVyUHJvcHMuZ2V0KGl0ZW0pLFxuICAgICAgICAgICAgd2lkZ2V0V2lkdGg6IHRoaXMud2lkZ2V0V2lkdGgsXG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgcHVibGljIHNob3VsZERpc3BsYXlSZXBlYXQoKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiB0aGlzLmRhdGE/Lmxlbmd0aCA+IDA7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBjYWxjSXRlbVByb3BzKGl0ZW06IGFueSkge1xuICAgICAgICBpZiAoIXRoaXMuY29uZmlndXJhdGlvbikge1xuICAgICAgICAgICAgcmV0dXJuIGl0ZW07XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIC4uLm1hcERhdGFUb0Zvcm1hdHRlclByb3BlcnRpZXModGhpcy5jb25maWd1cmF0aW9uLCBpdGVtKSxcbiAgICAgICAgICAgIC4uLnRoaXMuY29uZmlndXJhdGlvbi5pdGVtUHJvcGVydGllcyxcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICAvLyB0aGluayBvZiB1c2luZyBldmVudEJ1cyB0byBsZXQgd2lkZ2V0IGVudGl0aWVzIGtub3cgYWJvdXQgaXQncyB3aWR0aC4gLSBtYiBzb21lIGZvcm1hdHRlcnMgZm9yIHdpZGdldCBkb2Vzbid0IGNhcmUgYWJvdXQgaXQncyB3aWR0aC5cbiAgICBwcml2YXRlIGluaXRSZXNpemVPYnNlcnZlcigpIHtcbiAgICAgICAgY29uc3QgcmVzaXplRGlyZWN0aXZlID0gbmV3IFJlc2l6ZU9ic2VydmVyRGlyZWN0aXZlKFxuICAgICAgICAgICAgdGhpcy5ob3N0LFxuICAgICAgICAgICAgdGhpcy56b25lXG4gICAgICAgICk7XG4gICAgICAgIHJlc2l6ZURpcmVjdGl2ZS5kZWJvdW5jZVRpbWUgPSBSRVNJWkVfREVCT1VOQ0VfVElNRTtcbiAgICAgICAgcmVzaXplRGlyZWN0aXZlLm5nQWZ0ZXJWaWV3SW5pdCgpO1xuXG4gICAgICAgIHJlc2l6ZURpcmVjdGl2ZS5jb250YWluZXJSZXNpemVcbiAgICAgICAgICAgIC5waXBlKHRha2VVbnRpbCh0aGlzLmRlc3Ryb3kkKSlcbiAgICAgICAgICAgIC5zdWJzY3JpYmUoKCkgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMud2lkZ2V0V2lkdGggPSB0aGlzLmhvc3QubmF0aXZlRWxlbWVudC5vZmZzZXRXaWR0aDtcbiAgICAgICAgICAgIH0pO1xuICAgIH1cbn1cbiIsIjxudWktcmVwZWF0XG4gICAgKm5nSWY9XCJzaG91bGREaXNwbGF5UmVwZWF0KClcIlxuICAgIFtpdGVtc1NvdXJjZV09XCJkYXRhXCJcbiAgICBbcmVwZWF0SXRlbVRlbXBsYXRlUmVmXT1cInJlcGVhdEl0ZW1UZW1wbGF0ZVwiXG4+XG48L251aS1yZXBlYXQ+XG5cbjxkaXYgY2xhc3M9XCJlbXB0eVwiICpuZ0lmPVwiIXNob3VsZERpc3BsYXlSZXBlYXQoKVwiPlxuICAgIDxudWktaW1hZ2UgaW1hZ2U9XCJuby1kYXRhLXRvLXNob3dcIj48L251aS1pbWFnZT5cbjwvZGl2PlxuXG48bmctdGVtcGxhdGUgI3JlcGVhdEl0ZW1UZW1wbGF0ZSBsZXQtaXRlbT1cIml0ZW1cIj5cbiAgICA8ZGl2IGNsYXNzPVwiZW1wdHlcIiAqbmdJZj1cIiFpdGVtXCI+XG4gICAgICAgIDxudWktaW1hZ2UgaW1hZ2U9XCJuby1kYXRhLXRvLXNob3dcIj48L251aS1pbWFnZT5cbiAgICA8L2Rpdj5cbiAgICA8bmctY29udGFpbmVyXG4gICAgICAgIG51aUNvbXBvbmVudFBvcnRhbFxuICAgICAgICAjY29tcG9uZW50UG9ydGFsPVwibnVpQ29tcG9uZW50UG9ydGFsXCJcbiAgICAgICAgW2NvbXBvbmVudElkXT1cImNvbmZpZ3VyYXRpb24uY29tcG9uZW50VHlwZVwiXG4gICAgICAgIFtjb21wb25lbnRUeXBlXT1cImNvbmZpZ3VyYXRpb24uY29tcG9uZW50VHlwZVwiXG4gICAgICAgIFtwcm9wZXJ0aWVzXT1cImdldFByb3BzRm9yKGl0ZW0pXCJcbiAgICAgICAgW291dHB1dHNdPVwiWyduYXZpZ2F0ZWQnXVwiXG4gICAgICAgIChvdXRwdXQpPVwib25MaXN0SXRlbUV2ZW50KGl0ZW0pXCJcbiAgICA+XG4gICAgICAgIDxuZy10ZW1wbGF0ZVxuICAgICAgICAgICAgW2Nka1BvcnRhbE91dGxldF09XCJjb21wb25lbnRQb3J0YWwucG9ydGFsXCJcbiAgICAgICAgICAgIChhdHRhY2hlZCk9XCJjb21wb25lbnRQb3J0YWwuYXR0YWNoZWQoJGV2ZW50KVwiXG4gICAgICAgID48L25nLXRlbXBsYXRlPlxuICAgIDwvbmctY29udGFpbmVyPlxuPC9uZy10ZW1wbGF0ZT5cbiJdfQ==