@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
99 lines • 19 kB
JavaScript
// © 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, Input, NgZone, ViewChild, } from "@angular/core";
import { LoggerService } from "@nova-ui/bits";
import { PizzagnaService } from "../../../pizzagna/services/pizzagna.service";
import { BaseLayout } from "../base-layout";
import * as i0 from "@angular/core";
import * as i1 from "../../../pizzagna/services/pizzagna.service";
import * as i2 from "@nova-ui/bits";
import * as i3 from "@angular/common";
import * as i4 from "@angular/cdk/portal";
import * as i5 from "../../../pizzagna/directives/component-portal/component-portal.directive";
export class TilesComponent extends BaseLayout {
static { this.lateLoadKey = "TilesComponent"; }
constructor(changeDetector, pizzagnaService, logger, ngZone) {
super(changeDetector, pizzagnaService, logger);
this.ngZone = ngZone;
this.nodes = [];
this.direction = "column";
this.prioritizeGridRows = false;
}
ngAfterViewInit() {
this.handleGridFlowOnResize();
}
ngOnDestroy() {
this.tilesResizeObserver?.disconnect();
// Ensures that any base class observables are unsubscribed.
super.ngOnDestroy();
}
getNodes() {
return this.nodes;
}
handleGridFlowOnResize() {
this.tilesResizeObserver = new ResizeObserver(() => this.onResize());
this.ngZone.runOutsideAngular(() => {
this.tilesResizeObserver.observe(this.gridItemsContainer.nativeElement);
});
}
onResize() {
if (this.nodes?.length < 2) {
return;
}
const cssAttributes = this.gridItemsContainer.nativeElement.getBoundingClientRect();
const { height, width } = cssAttributes;
const h2WRatio = height / width;
const allowedH2WRatio = getHeightToWidthRatioFor(this.nodes.length);
const gap = 0.05; // height/width gap used in transitions to avoid widget lagging
if (h2WRatio - gap > allowedH2WRatio && !this.prioritizeGridRows) {
this.prioritizeGridRows = true;
this.changeDetector.detectChanges();
return;
}
if (h2WRatio + gap < allowedH2WRatio && this.prioritizeGridRows) {
this.prioritizeGridRows = false;
this.changeDetector.detectChanges();
return;
}
}
/** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: TilesComponent, deps: [{ token: i0.ChangeDetectorRef }, { token: i1.PizzagnaService }, { token: i2.LoggerService }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Component }); }
/** @nocollapse */ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: TilesComponent, selector: "nui-tiles", inputs: { nodes: "nodes", direction: "direction" }, host: { properties: { "class": "this.elementClass" } }, viewQueries: [{ propertyName: "gridItemsContainer", first: true, predicate: ["gridItemsContainer"], descendants: true, static: true }], usesInheritance: true, ngImport: i0, template: "<div\n #gridItemsContainer\n class=\"nui-grid-layout\"\n [ngClass]=\"{ 'prioritize-rows': prioritizeGridRows }\"\n>\n <ng-container *ngFor=\"let node of nodeConfigs; trackBy: trackByFn\">\n <ng-container\n nuiComponentPortal\n #componentPortal=\"nuiComponentPortal\"\n [componentId]=\"node.id\"\n [componentType]=\"node.componentType\"\n [properties]=\"node.properties\"\n [providers]=\"node.providers\"\n >\n <ng-template\n [cdkPortalOutlet]=\"componentPortal.portal\"\n (attached)=\"componentPortal.attached($event)\"\n ></ng-template>\n </ng-container>\n </ng-container>\n <div *ngIf=\"nodeConfigs.length === 0\" class=\"is-empty\">\n <nui-image image=\"no-data-to-show\"></nui-image>\n </div>\n</div>\n", styles: [".nui-grid-layout{display:grid;height:100%;gap:10px;grid-template-columns:repeat(auto-fit,minmax(94.8px,1fr));grid-template-rows:repeat(auto-fit,minmax(15px,1fr));line-height:1.2}.nui-grid-layout.prioritize-rows{grid-auto-flow:column;grid-template-columns:minmax(1px,1fr)}:host-context(.mobile){min-height:160px}.is-empty{display:grid;place-content:center;height:100%}\n"], dependencies: [{ kind: "directive", type: i3.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i3.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i3.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: i4.CdkPortalOutlet, selector: "[cdkPortalOutlet]", inputs: ["cdkPortalOutlet"], outputs: ["attached"], exportAs: ["cdkPortalOutlet"] }, { kind: "directive", type: i5.ComponentPortalDirective, selector: "[nuiComponentPortal]", inputs: ["componentId", "componentType", "properties", "providers", "outputs"], outputs: ["output"], exportAs: ["nuiComponentPortal"] }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: TilesComponent, decorators: [{
type: Component,
args: [{ selector: "nui-tiles", template: "<div\n #gridItemsContainer\n class=\"nui-grid-layout\"\n [ngClass]=\"{ 'prioritize-rows': prioritizeGridRows }\"\n>\n <ng-container *ngFor=\"let node of nodeConfigs; trackBy: trackByFn\">\n <ng-container\n nuiComponentPortal\n #componentPortal=\"nuiComponentPortal\"\n [componentId]=\"node.id\"\n [componentType]=\"node.componentType\"\n [properties]=\"node.properties\"\n [providers]=\"node.providers\"\n >\n <ng-template\n [cdkPortalOutlet]=\"componentPortal.portal\"\n (attached)=\"componentPortal.attached($event)\"\n ></ng-template>\n </ng-container>\n </ng-container>\n <div *ngIf=\"nodeConfigs.length === 0\" class=\"is-empty\">\n <nui-image image=\"no-data-to-show\"></nui-image>\n </div>\n</div>\n", styles: [".nui-grid-layout{display:grid;height:100%;gap:10px;grid-template-columns:repeat(auto-fit,minmax(94.8px,1fr));grid-template-rows:repeat(auto-fit,minmax(15px,1fr));line-height:1.2}.nui-grid-layout.prioritize-rows{grid-auto-flow:column;grid-template-columns:minmax(1px,1fr)}:host-context(.mobile){min-height:160px}.is-empty{display:grid;place-content:center;height:100%}\n"] }]
}], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: i1.PizzagnaService }, { type: i2.LoggerService }, { type: i0.NgZone }], propDecorators: { nodes: [{
type: Input
}], direction: [{
type: Input
}], elementClass: [{
type: HostBinding,
args: ["class"]
}], gridItemsContainer: [{
type: ViewChild,
args: ["gridItemsContainer", { static: true }]
}] } });
/**
* Height to Width container ratio varies per tiles amount.
* Experimentally was determined valid h/w ratio for 2...8 tiles and
* This function represents the linear dependency (approximately).
*/
const getHeightToWidthRatioFor = (tilesAmount) => 0.25 * tilesAmount + 0.7;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGlsZXMuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vc3JjL2xpYi9jb21wb25lbnRzL2xheW91dHMvdGlsZXMvdGlsZXMuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vc3JjL2xpYi9jb21wb25lbnRzL2xheW91dHMvdGlsZXMvdGlsZXMuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEseURBQXlEO0FBQ3pELEVBQUU7QUFDRiwrRUFBK0U7QUFDL0UsNEVBQTRFO0FBQzVFLDhFQUE4RTtBQUM5RSwrRUFBK0U7QUFDL0UsOEVBQThFO0FBQzlFLDREQUE0RDtBQUM1RCxFQUFFO0FBQ0YsNkVBQTZFO0FBQzdFLHVEQUF1RDtBQUN2RCxFQUFFO0FBQ0YsNkVBQTZFO0FBQzdFLDRFQUE0RTtBQUM1RSwrRUFBK0U7QUFDL0UsMEVBQTBFO0FBQzFFLGlGQUFpRjtBQUNqRiw2RUFBNkU7QUFDN0UsaUJBQWlCO0FBRWpCLE9BQU8sRUFFSCxpQkFBaUIsRUFDakIsU0FBUyxFQUNULFVBQVUsRUFDVixXQUFXLEVBQ1gsS0FBSyxFQUNMLE1BQU0sRUFFTixTQUFTLEdBQ1osTUFBTSxlQUFlLENBQUM7QUFFdkIsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUU5QyxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sNkNBQTZDLENBQUM7QUFDOUUsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLGdCQUFnQixDQUFDOzs7Ozs7O0FBTzVDLE1BQU0sT0FBTyxjQUNULFNBQVEsVUFBVTthQUdKLGdCQUFXLEdBQUcsZ0JBQWdCLEFBQW5CLENBQW9CO0lBYTdDLFlBQ0ksY0FBaUMsRUFDakMsZUFBZ0MsRUFDaEMsTUFBcUIsRUFDYixNQUFjO1FBRXRCLEtBQUssQ0FBQyxjQUFjLEVBQUUsZUFBZSxFQUFFLE1BQU0sQ0FBQyxDQUFDO1FBRnZDLFdBQU0sR0FBTixNQUFNLENBQVE7UUFmVixVQUFLLEdBQWEsRUFBRSxDQUFDO1FBQ3JCLGNBQVMsR0FBRyxRQUFRLENBQUM7UUFHOUIsdUJBQWtCLEdBQVksS0FBSyxDQUFDO0lBYzNDLENBQUM7SUFFTSxlQUFlO1FBQ2xCLElBQUksQ0FBQyxzQkFBc0IsRUFBRSxDQUFDO0lBQ2xDLENBQUM7SUFFTSxXQUFXO1FBQ2QsSUFBSSxDQUFDLG1CQUFtQixFQUFFLFVBQVUsRUFBRSxDQUFDO1FBQ3ZDLDREQUE0RDtRQUM1RCxLQUFLLENBQUMsV0FBVyxFQUFFLENBQUM7SUFDeEIsQ0FBQztJQUVNLFFBQVE7UUFDWCxPQUFPLElBQUksQ0FBQyxLQUFLLENBQUM7SUFDdEIsQ0FBQztJQUVPLHNCQUFzQjtRQUMxQixJQUFJLENBQUMsbUJBQW1CLEdBQUcsSUFBSSxjQUFjLENBQUMsR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDLENBQUM7UUFDckUsSUFBSSxDQUFDLE1BQU0sQ0FBQyxpQkFBaUIsQ0FBQyxHQUFHLEVBQUU7WUFDL0IsSUFBSSxDQUFDLG1CQUFtQixDQUFDLE9BQU8sQ0FDNUIsSUFBSSxDQUFDLGtCQUFrQixDQUFDLGFBQWEsQ0FDeEMsQ0FBQztRQUNOLENBQUMsQ0FBQyxDQUFDO0lBQ1AsQ0FBQztJQUVPLFFBQVE7UUFDWixJQUFJLElBQUksQ0FBQyxLQUFLLEVBQUUsTUFBTSxHQUFHLENBQUMsRUFBRTtZQUN4QixPQUFPO1NBQ1Y7UUFFRCxNQUFNLGFBQWEsR0FDZixJQUFJLENBQUMsa0JBQWtCLENBQUMsYUFBYSxDQUFDLHFCQUFxQixFQUFFLENBQUM7UUFDbEUsTUFBTSxFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQUUsR0FBRyxhQUFhLENBQUM7UUFFeEMsTUFBTSxRQUFRLEdBQUcsTUFBTSxHQUFHLEtBQUssQ0FBQztRQUNoQyxNQUFNLGVBQWUsR0FBRyx3QkFBd0IsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBRXBFLE1BQU0sR0FBRyxHQUFHLElBQUksQ0FBQyxDQUFDLCtEQUErRDtRQUVqRixJQUFJLFFBQVEsR0FBRyxHQUFHLEdBQUcsZUFBZSxJQUFJLENBQUMsSUFBSSxDQUFDLGtCQUFrQixFQUFFO1lBQzlELElBQUksQ0FBQyxrQkFBa0IsR0FBRyxJQUFJLENBQUM7WUFDL0IsSUFBSSxDQUFDLGNBQWMsQ0FBQyxhQUFhLEVBQUUsQ0FBQztZQUNwQyxPQUFPO1NBQ1Y7UUFFRCxJQUFJLFFBQVEsR0FBRyxHQUFHLEdBQUcsZUFBZSxJQUFJLElBQUksQ0FBQyxrQkFBa0IsRUFBRTtZQUM3RCxJQUFJLENBQUMsa0JBQWtCLEdBQUcsS0FBSyxDQUFDO1lBQ2hDLElBQUksQ0FBQyxjQUFjLENBQUMsYUFBYSxFQUFFLENBQUM7WUFDcEMsT0FBTztTQUNWO0lBQ0wsQ0FBQztrSUExRVEsY0FBYztzSEFBZCxjQUFjLDRUQzFDM0IsMjJCQXdCQTs7NEZEa0JhLGNBQWM7a0JBTDFCLFNBQVM7K0JBQ0ksV0FBVztxS0FVTCxLQUFLO3NCQUFwQixLQUFLO2dCQUNVLFNBQVM7c0JBQXhCLEtBQUs7Z0JBRXVCLFlBQVk7c0JBQXhDLFdBQVc7dUJBQUMsT0FBTztnQkFJWixrQkFBa0I7c0JBRHpCLFNBQVM7dUJBQUMsb0JBQW9CLEVBQUUsRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFOztBQWlFckQ7Ozs7R0FJRztBQUNILE1BQU0sd0JBQXdCLEdBQUcsQ0FBQyxXQUFtQixFQUFFLEVBQUUsQ0FDckQsSUFBSSxHQUFHLFdBQVcsR0FBRyxHQUFHLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyDCqSAyMDIyIFNvbGFyV2luZHMgV29ybGR3aWRlLCBMTEMuIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vL1xuLy8gUGVybWlzc2lvbiBpcyBoZXJlYnkgZ3JhbnRlZCwgZnJlZSBvZiBjaGFyZ2UsIHRvIGFueSBwZXJzb24gb2J0YWluaW5nIGEgY29weVxuLy8gIG9mIHRoaXMgc29mdHdhcmUgYW5kIGFzc29jaWF0ZWQgZG9jdW1lbnRhdGlvbiBmaWxlcyAodGhlIFwiU29mdHdhcmVcIiksIHRvXG4vLyAgZGVhbCBpbiB0aGUgU29mdHdhcmUgd2l0aG91dCByZXN0cmljdGlvbiwgaW5jbHVkaW5nIHdpdGhvdXQgbGltaXRhdGlvbiB0aGVcbi8vICByaWdodHMgdG8gdXNlLCBjb3B5LCBtb2RpZnksIG1lcmdlLCBwdWJsaXNoLCBkaXN0cmlidXRlLCBzdWJsaWNlbnNlLCBhbmQvb3Jcbi8vICBzZWxsIGNvcGllcyBvZiB0aGUgU29mdHdhcmUsIGFuZCB0byBwZXJtaXQgcGVyc29ucyB0byB3aG9tIHRoZSBTb2Z0d2FyZSBpc1xuLy8gIGZ1cm5pc2hlZCB0byBkbyBzbywgc3ViamVjdCB0byB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbnM6XG4vL1xuLy8gVGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UgYW5kIHRoaXMgcGVybWlzc2lvbiBub3RpY2Ugc2hhbGwgYmUgaW5jbHVkZWQgaW5cbi8vICBhbGwgY29waWVzIG9yIHN1YnN0YW50aWFsIHBvcnRpb25zIG9mIHRoZSBTb2Z0d2FyZS5cbi8vXG4vLyBUSEUgU09GVFdBUkUgSVMgUFJPVklERUQgXCJBUyBJU1wiLCBXSVRIT1VUIFdBUlJBTlRZIE9GIEFOWSBLSU5ELCBFWFBSRVNTIE9SXG4vLyAgSU1QTElFRCwgSU5DTFVESU5HIEJVVCBOT1QgTElNSVRFRCBUTyBUSEUgV0FSUkFOVElFUyBPRiBNRVJDSEFOVEFCSUxJVFksXG4vLyAgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQU5EIE5PTklORlJJTkdFTUVOVC4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFXG4vLyAgQVVUSE9SUyBPUiBDT1BZUklHSFQgSE9MREVSUyBCRSBMSUFCTEUgRk9SIEFOWSBDTEFJTSwgREFNQUdFUyBPUiBPVEhFUlxuLy8gIExJQUJJTElUWSwgV0hFVEhFUiBJTiBBTiBBQ1RJT04gT0YgQ09OVFJBQ1QsIFRPUlQgT1IgT1RIRVJXSVNFLCBBUklTSU5HIEZST00sXG4vLyAgT1VUIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgU09GVFdBUkUgT1IgVEhFIFVTRSBPUiBPVEhFUiBERUFMSU5HUyBJTlxuLy8gIFRIRSBTT0ZUV0FSRS5cblxuaW1wb3J0IHtcbiAgICBBZnRlclZpZXdJbml0LFxuICAgIENoYW5nZURldGVjdG9yUmVmLFxuICAgIENvbXBvbmVudCxcbiAgICBFbGVtZW50UmVmLFxuICAgIEhvc3RCaW5kaW5nLFxuICAgIElucHV0LFxuICAgIE5nWm9uZSxcbiAgICBPbkRlc3Ryb3ksXG4gICAgVmlld0NoaWxkLFxufSBmcm9tIFwiQGFuZ3VsYXIvY29yZVwiO1xuXG5pbXBvcnQgeyBMb2dnZXJTZXJ2aWNlIH0gZnJvbSBcIkBub3ZhLXVpL2JpdHNcIjtcblxuaW1wb3J0IHsgUGl6emFnbmFTZXJ2aWNlIH0gZnJvbSBcIi4uLy4uLy4uL3BpenphZ25hL3NlcnZpY2VzL3BpenphZ25hLnNlcnZpY2VcIjtcbmltcG9ydCB7IEJhc2VMYXlvdXQgfSBmcm9tIFwiLi4vYmFzZS1sYXlvdXRcIjtcblxuQENvbXBvbmVudCh7XG4gICAgc2VsZWN0b3I6IFwibnVpLXRpbGVzXCIsXG4gICAgc3R5bGVVcmxzOiBbXCIuL3RpbGVzLmNvbXBvbmVudC5sZXNzXCJdLFxuICAgIHRlbXBsYXRlVXJsOiBcIi4vdGlsZXMuY29tcG9uZW50Lmh0bWxcIixcbn0pXG5leHBvcnQgY2xhc3MgVGlsZXNDb21wb25lbnRcbiAgICBleHRlbmRzIEJhc2VMYXlvdXRcbiAgICBpbXBsZW1lbnRzIE9uRGVzdHJveSwgQWZ0ZXJWaWV3SW5pdFxue1xuICAgIHB1YmxpYyBzdGF0aWMgbGF0ZUxvYWRLZXkgPSBcIlRpbGVzQ29tcG9uZW50XCI7XG5cbiAgICBASW5wdXQoKSBwdWJsaWMgbm9kZXM6IHN0cmluZ1tdID0gW107XG4gICAgQElucHV0KCkgcHVibGljIGRpcmVjdGlvbiA9IFwiY29sdW1uXCI7XG5cbiAgICBASG9zdEJpbmRpbmcoXCJjbGFzc1wiKSBwdWJsaWMgZWxlbWVudENsYXNzOiBzdHJpbmc7XG4gICAgcHVibGljIHByaW9yaXRpemVHcmlkUm93czogYm9vbGVhbiA9IGZhbHNlO1xuXG4gICAgQFZpZXdDaGlsZChcImdyaWRJdGVtc0NvbnRhaW5lclwiLCB7IHN0YXRpYzogdHJ1ZSB9KVxuICAgIHByaXZhdGUgZ3JpZEl0ZW1zQ29udGFpbmVyOiBFbGVtZW50UmVmPEhUTUxFbGVtZW50PjtcblxuICAgIHByaXZhdGUgdGlsZXNSZXNpemVPYnNlcnZlcjogUmVzaXplT2JzZXJ2ZXI7XG5cbiAgICBjb25zdHJ1Y3RvcihcbiAgICAgICAgY2hhbmdlRGV0ZWN0b3I6IENoYW5nZURldGVjdG9yUmVmLFxuICAgICAgICBwaXp6YWduYVNlcnZpY2U6IFBpenphZ25hU2VydmljZSxcbiAgICAgICAgbG9nZ2VyOiBMb2dnZXJTZXJ2aWNlLFxuICAgICAgICBwcml2YXRlIG5nWm9uZTogTmdab25lXG4gICAgKSB7XG4gICAgICAgIHN1cGVyKGNoYW5nZURldGVjdG9yLCBwaXp6YWduYVNlcnZpY2UsIGxvZ2dlcik7XG4gICAgfVxuXG4gICAgcHVibGljIG5nQWZ0ZXJWaWV3SW5pdCgpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5oYW5kbGVHcmlkRmxvd09uUmVzaXplKCk7XG4gICAgfVxuXG4gICAgcHVibGljIG5nT25EZXN0cm95KCk6IHZvaWQge1xuICAgICAgICB0aGlzLnRpbGVzUmVzaXplT2JzZXJ2ZXI/LmRpc2Nvbm5lY3QoKTtcbiAgICAgICAgLy8gRW5zdXJlcyB0aGF0IGFueSBiYXNlIGNsYXNzIG9ic2VydmFibGVzIGFyZSB1bnN1YnNjcmliZWQuXG4gICAgICAgIHN1cGVyLm5nT25EZXN0cm95KCk7XG4gICAgfVxuXG4gICAgcHVibGljIGdldE5vZGVzKCk6IHN0cmluZ1tdIHtcbiAgICAgICAgcmV0dXJuIHRoaXMubm9kZXM7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBoYW5kbGVHcmlkRmxvd09uUmVzaXplKCkge1xuICAgICAgICB0aGlzLnRpbGVzUmVzaXplT2JzZXJ2ZXIgPSBuZXcgUmVzaXplT2JzZXJ2ZXIoKCkgPT4gdGhpcy5vblJlc2l6ZSgpKTtcbiAgICAgICAgdGhpcy5uZ1pvbmUucnVuT3V0c2lkZUFuZ3VsYXIoKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy50aWxlc1Jlc2l6ZU9ic2VydmVyLm9ic2VydmUoXG4gICAgICAgICAgICAgICAgdGhpcy5ncmlkSXRlbXNDb250YWluZXIubmF0aXZlRWxlbWVudFxuICAgICAgICAgICAgKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBvblJlc2l6ZSgpIHtcbiAgICAgICAgaWYgKHRoaXMubm9kZXM/Lmxlbmd0aCA8IDIpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGNzc0F0dHJpYnV0ZXMgPVxuICAgICAgICAgICAgdGhpcy5ncmlkSXRlbXNDb250YWluZXIubmF0aXZlRWxlbWVudC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICAgICAgY29uc3QgeyBoZWlnaHQsIHdpZHRoIH0gPSBjc3NBdHRyaWJ1dGVzO1xuXG4gICAgICAgIGNvbnN0IGgyV1JhdGlvID0gaGVpZ2h0IC8gd2lkdGg7XG4gICAgICAgIGNvbnN0IGFsbG93ZWRIMldSYXRpbyA9IGdldEhlaWdodFRvV2lkdGhSYXRpb0Zvcih0aGlzLm5vZGVzLmxlbmd0aCk7XG5cbiAgICAgICAgY29uc3QgZ2FwID0gMC4wNTsgLy8gaGVpZ2h0L3dpZHRoIGdhcCB1c2VkIGluIHRyYW5zaXRpb25zIHRvIGF2b2lkIHdpZGdldCBsYWdnaW5nXG5cbiAgICAgICAgaWYgKGgyV1JhdGlvIC0gZ2FwID4gYWxsb3dlZEgyV1JhdGlvICYmICF0aGlzLnByaW9yaXRpemVHcmlkUm93cykge1xuICAgICAgICAgICAgdGhpcy5wcmlvcml0aXplR3JpZFJvd3MgPSB0cnVlO1xuICAgICAgICAgICAgdGhpcy5jaGFuZ2VEZXRlY3Rvci5kZXRlY3RDaGFuZ2VzKCk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoaDJXUmF0aW8gKyBnYXAgPCBhbGxvd2VkSDJXUmF0aW8gJiYgdGhpcy5wcmlvcml0aXplR3JpZFJvd3MpIHtcbiAgICAgICAgICAgIHRoaXMucHJpb3JpdGl6ZUdyaWRSb3dzID0gZmFsc2U7XG4gICAgICAgICAgICB0aGlzLmNoYW5nZURldGVjdG9yLmRldGVjdENoYW5nZXMoKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgIH1cbn1cblxuLyoqXG4gKiBIZWlnaHQgdG8gV2lkdGggY29udGFpbmVyIHJhdGlvIHZhcmllcyBwZXIgdGlsZXMgYW1vdW50LlxuICogRXhwZXJpbWVudGFsbHkgd2FzIGRldGVybWluZWQgdmFsaWQgaC93IHJhdGlvIGZvciAyLi4uOCB0aWxlcyBhbmRcbiAqIFRoaXMgZnVuY3Rpb24gcmVwcmVzZW50cyB0aGUgbGluZWFyIGRlcGVuZGVuY3kgKGFwcHJveGltYXRlbHkpLlxuICovXG5jb25zdCBnZXRIZWlnaHRUb1dpZHRoUmF0aW9Gb3IgPSAodGlsZXNBbW91bnQ6IG51bWJlcikgPT5cbiAgICAwLjI1ICogdGlsZXNBbW91bnQgKyAwLjc7XG4iLCI8ZGl2XG4gICAgI2dyaWRJdGVtc0NvbnRhaW5lclxuICAgIGNsYXNzPVwibnVpLWdyaWQtbGF5b3V0XCJcbiAgICBbbmdDbGFzc109XCJ7ICdwcmlvcml0aXplLXJvd3MnOiBwcmlvcml0aXplR3JpZFJvd3MgfVwiXG4+XG4gICAgPG5nLWNvbnRhaW5lciAqbmdGb3I9XCJsZXQgbm9kZSBvZiBub2RlQ29uZmlnczsgdHJhY2tCeTogdHJhY2tCeUZuXCI+XG4gICAgICAgIDxuZy1jb250YWluZXJcbiAgICAgICAgICAgIG51aUNvbXBvbmVudFBvcnRhbFxuICAgICAgICAgICAgI2NvbXBvbmVudFBvcnRhbD1cIm51aUNvbXBvbmVudFBvcnRhbFwiXG4gICAgICAgICAgICBbY29tcG9uZW50SWRdPVwibm9kZS5pZFwiXG4gICAgICAgICAgICBbY29tcG9uZW50VHlwZV09XCJub2RlLmNvbXBvbmVudFR5cGVcIlxuICAgICAgICAgICAgW3Byb3BlcnRpZXNdPVwibm9kZS5wcm9wZXJ0aWVzXCJcbiAgICAgICAgICAgIFtwcm92aWRlcnNdPVwibm9kZS5wcm92aWRlcnNcIlxuICAgICAgICA+XG4gICAgICAgICAgICA8bmctdGVtcGxhdGVcbiAgICAgICAgICAgICAgICBbY2RrUG9ydGFsT3V0bGV0XT1cImNvbXBvbmVudFBvcnRhbC5wb3J0YWxcIlxuICAgICAgICAgICAgICAgIChhdHRhY2hlZCk9XCJjb21wb25lbnRQb3J0YWwuYXR0YWNoZWQoJGV2ZW50KVwiXG4gICAgICAgICAgICA+PC9uZy10ZW1wbGF0ZT5cbiAgICAgICAgPC9uZy1jb250YWluZXI+XG4gICAgPC9uZy1jb250YWluZXI+XG4gICAgPGRpdiAqbmdJZj1cIm5vZGVDb25maWdzLmxlbmd0aCA9PT0gMFwiIGNsYXNzPVwiaXMtZW1wdHlcIj5cbiAgICAgICAgPG51aS1pbWFnZSBpbWFnZT1cIm5vLWRhdGEtdG8tc2hvd1wiPjwvbnVpLWltYWdlPlxuICAgIDwvZGl2PlxuPC9kaXY+XG4iXX0=