@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
111 lines • 23.3 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, HostBinding, Input, } from "@angular/core";
import { TimeseriesZoomPlugin, TimeseriesZoomPluginsSyncService, ZoomPlugin, } from "@nova-ui/charts";
import { TimeseriesChartPresetService } from "./timeseries-chart-preset.service";
import { TimeseriesChartPreset, TimeseriesChartTypes, TimeseriesWidgetProjectType, } from "./types";
import * as i0 from "@angular/core";
import * as i1 from "./timeseries-chart-preset.service";
import * as i2 from "@nova-ui/charts";
import * as i3 from "@angular/common";
import * as i4 from "@nova-ui/bits";
import * as i5 from "@angular/cdk/portal";
import * as i6 from "../../pizzagna/directives/component-portal/component-portal.directive";
import * as i7 from "./timeseries-inspection-menu/timeseries-inspection-menu.component";
/** @ignore */
export class TimeseriesWidgetComponent {
static { this.lateLoadKey = "TimeseriesWidgetComponent"; }
constructor(timeseriesChartPresetService, changeDetector, zoomPluginsSyncService) {
this.timeseriesChartPresetService = timeseriesChartPresetService;
this.changeDetector = changeDetector;
this.zoomPluginsSyncService = zoomPluginsSyncService;
this.elementClass = "";
this.zoomPlugins = [];
this.allowPopover = false;
this.timeseriesWidgetProjectType = TimeseriesWidgetProjectType;
}
ngOnInit() {
if (this.configuration?.projectType ===
TimeseriesWidgetProjectType.PerfstackApp) {
if (this.configuration.type === TimeseriesChartTypes.alert) {
// adds timeseries zoom plugin for each subcharts to make the synchronization working for the alert chart
this.widgetData?.series.forEach(() => this.zoomPlugins.push(this.getTimeseriesZoomPlugin()));
// doesn't add zoom plugin for a summary serie when there are no sub charts and only sumary serie will be displayed
if (!(this.widgetData?.series.length === 1 &&
this.widgetData.series[0].id ===
this.widgetData.summarySerie?.id)) {
this.zoomPlugins.push(this.getTimeseriesZoomPlugin());
}
}
else {
this.zoomPlugins.push(this.getTimeseriesZoomPlugin());
}
}
else {
this.zoomPlugins.push(new ZoomPlugin());
}
}
getTimeseriesZoomPlugin() {
return new TimeseriesZoomPlugin({ collectionId: this.collectionId }, this.zoomPluginsSyncService);
}
ngOnChanges(changes) {
if (changes.configuration) {
const configurationCurrent = changes.configuration.currentValue;
const configurationPrevious = changes.configuration.previousValue;
if (configurationCurrent?.preset !== configurationPrevious?.preset) {
this.chartPreset =
this.timeseriesChartPresetService.presets[this.configuration?.preset ?? TimeseriesChartPreset.Line];
}
}
}
/** Checks if chart should be shown. */
shouldShowChart() {
return (this.widgetData?.series?.length ?? 0) > 0;
}
toggleLeave() {
this.allowPopover = false;
}
toggleEnter() {
this.allowPopover = true;
}
isExploringEnabled() {
return (this.configuration?.type !== TimeseriesChartTypes.line &&
this.configuration?.type !== TimeseriesChartTypes.multi &&
this.configuration?.type !== TimeseriesChartTypes.status);
}
/** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: TimeseriesWidgetComponent, deps: [{ token: i1.TimeseriesChartPresetService }, { token: i0.ChangeDetectorRef }, { token: i2.TimeseriesZoomPluginsSyncService }], target: i0.ɵɵFactoryTarget.Component }); }
/** @nocollapse */ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: TimeseriesWidgetComponent, selector: "nui-timeseries-widget", inputs: { widgetData: "widgetData", configuration: "configuration", collectionId: "collectionId", elementClass: "elementClass" }, host: { properties: { "class": "this.elementClass" } }, usesOnChanges: true, ngImport: i0, template: "<div\n class=\"h-100 timeseries-widget-content\"\n *ngIf=\"shouldShowChart()\"\n (mouseleave)=\"toggleLeave()\"\n (mouseenter)=\"toggleEnter()\"\n>\n <ng-container\n nuiComponentPortal\n componentId=\"timeseriesWidgetChart\"\n [componentType]=\"chartPreset.componentType\"\n [properties]=\"{\n widgetData: widgetData,\n configuration: configuration,\n collectionId: collectionId || configuration?.collectionId,\n zoomPlugins: zoomPlugins\n }\"\n #componentPortal=\"nuiComponentPortal\"\n >\n <ng-template\n [cdkPortalOutlet]=\"componentPortal.portal\"\n (attached)=\"componentPortal.attached($event)\"\n >\n </ng-template>\n </ng-container>\n <nui-timeseries-inspection-menu\n *ngIf=\"\n configuration?.enableZoom &&\n configuration?.projectType ===\n timeseriesWidgetProjectType.PerfstackApp &&\n zoomPlugins.length\n \"\n [allowed]=\"allowPopover\"\n [plugin]=\"zoomPlugins[0]\"\n [collectionId]=\"collectionId\"\n [exploringEnabled]=\"isExploringEnabled()\"\n [metricIds]=\"configuration?.metricIds\"\n ></nui-timeseries-inspection-menu>\n</div>\n<div *ngIf=\"!shouldShowChart()\">\n <nui-image image=\"no-data-to-show\"></nui-image>\n</div>\n", styles: [".timeseries-widget-content{padding:10px;position:relative}\n"], dependencies: [{ kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i4.ImageComponent, selector: "nui-image", inputs: ["image", "description", "float", "margin", "isWatermark", "width", "height", "autoFill"] }, { kind: "directive", type: i5.CdkPortalOutlet, selector: "[cdkPortalOutlet]", inputs: ["cdkPortalOutlet"], outputs: ["attached"], exportAs: ["cdkPortalOutlet"] }, { kind: "directive", type: i6.ComponentPortalDirective, selector: "[nuiComponentPortal]", inputs: ["componentId", "componentType", "properties", "providers", "outputs"], outputs: ["output"], exportAs: ["nuiComponentPortal"] }, { kind: "component", type: i7.TimeseriesInspectionMenuComponent, selector: "nui-timeseries-inspection-menu", inputs: ["plugin", "exploringEnabled", "metricIds", "collectionId", "allowed"] }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: TimeseriesWidgetComponent, decorators: [{
type: Component,
args: [{ selector: "nui-timeseries-widget", template: "<div\n class=\"h-100 timeseries-widget-content\"\n *ngIf=\"shouldShowChart()\"\n (mouseleave)=\"toggleLeave()\"\n (mouseenter)=\"toggleEnter()\"\n>\n <ng-container\n nuiComponentPortal\n componentId=\"timeseriesWidgetChart\"\n [componentType]=\"chartPreset.componentType\"\n [properties]=\"{\n widgetData: widgetData,\n configuration: configuration,\n collectionId: collectionId || configuration?.collectionId,\n zoomPlugins: zoomPlugins\n }\"\n #componentPortal=\"nuiComponentPortal\"\n >\n <ng-template\n [cdkPortalOutlet]=\"componentPortal.portal\"\n (attached)=\"componentPortal.attached($event)\"\n >\n </ng-template>\n </ng-container>\n <nui-timeseries-inspection-menu\n *ngIf=\"\n configuration?.enableZoom &&\n configuration?.projectType ===\n timeseriesWidgetProjectType.PerfstackApp &&\n zoomPlugins.length\n \"\n [allowed]=\"allowPopover\"\n [plugin]=\"zoomPlugins[0]\"\n [collectionId]=\"collectionId\"\n [exploringEnabled]=\"isExploringEnabled()\"\n [metricIds]=\"configuration?.metricIds\"\n ></nui-timeseries-inspection-menu>\n</div>\n<div *ngIf=\"!shouldShowChart()\">\n <nui-image image=\"no-data-to-show\"></nui-image>\n</div>\n", styles: [".timeseries-widget-content{padding:10px;position:relative}\n"] }]
}], ctorParameters: () => [{ type: i1.TimeseriesChartPresetService }, { type: i0.ChangeDetectorRef }, { type: i2.TimeseriesZoomPluginsSyncService }], propDecorators: { widgetData: [{
type: Input
}], configuration: [{
type: Input
}], collectionId: [{
type: Input
}], elementClass: [{
type: Input
}, {
type: HostBinding,
args: ["class"]
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGltZXNlcmllcy13aWRnZXQuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vc3JjL2xpYi9jb21wb25lbnRzL3RpbWVzZXJpZXMtd2lkZ2V0L3RpbWVzZXJpZXMtd2lkZ2V0LmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uL3NyYy9saWIvY29tcG9uZW50cy90aW1lc2VyaWVzLXdpZGdldC90aW1lc2VyaWVzLXdpZGdldC5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSx5REFBeUQ7QUFDekQsRUFBRTtBQUNGLCtFQUErRTtBQUMvRSw0RUFBNEU7QUFDNUUsOEVBQThFO0FBQzlFLCtFQUErRTtBQUMvRSw4RUFBOEU7QUFDOUUsNERBQTREO0FBQzVELEVBQUU7QUFDRiw2RUFBNkU7QUFDN0UsdURBQXVEO0FBQ3ZELEVBQUU7QUFDRiw2RUFBNkU7QUFDN0UsNEVBQTRFO0FBQzVFLCtFQUErRTtBQUMvRSwwRUFBMEU7QUFDMUUsaUZBQWlGO0FBQ2pGLDZFQUE2RTtBQUM3RSxpQkFBaUI7QUFFakIsT0FBTyxFQUNILGlCQUFpQixFQUNqQixTQUFTLEVBQ1QsV0FBVyxFQUNYLEtBQUssR0FJUixNQUFNLGVBQWUsQ0FBQztBQUV2QixPQUFPLEVBQ0gsb0JBQW9CLEVBQ3BCLGdDQUFnQyxFQUNoQyxVQUFVLEdBQ2IsTUFBTSxpQkFBaUIsQ0FBQztBQUV6QixPQUFPLEVBQUUsNEJBQTRCLEVBQUUsTUFBTSxtQ0FBbUMsQ0FBQztBQUNqRixPQUFPLEVBSUgscUJBQXFCLEVBQ3JCLG9CQUFvQixFQUNwQiwyQkFBMkIsR0FFOUIsTUFBTSxTQUFTLENBQUM7Ozs7Ozs7OztBQUdqQixjQUFjO0FBTWQsTUFBTSxPQUFPLHlCQUF5QjthQUdwQixnQkFBVyxHQUFHLDJCQUEyQixBQUE5QixDQUErQjtJQWN4RCxZQUNXLDRCQUEwRCxFQUMxRCxjQUFpQyxFQUNqQyxzQkFBd0Q7UUFGeEQsaUNB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TUFBTSxDQUMzRCxDQUFDO0lBQ04sQ0FBQztrSUEvRlEseUJBQXlCO3NIQUF6Qix5QkFBeUIsNFFDdER0Qyw0M0NBeUNBOzs0RkRhYSx5QkFBeUI7a0JBTHJDLFNBQVM7K0JBQ0ksdUJBQXVCO2dMQVNqQixVQUFVO3NCQUF6QixLQUFLO2dCQUNVLGFBQWE7c0JBQTVCLEtBQUs7Z0JBQ1UsWUFBWTtzQkFBM0IsS0FBSztnQkFFZ0MsWUFBWTtzQkFBakQsS0FBSzs7c0JBQUksV0FBVzt1QkFBQyxPQUFPIiwic291cmNlc0NvbnRlbnQiOlsiLy8gwqkgMjAyMiBTb2xhcldpbmRzIFdvcmxkd2lkZSwgTExDLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy9cbi8vIFBlcm1pc3Npb24gaXMgaGVyZWJ5IGdyYW50ZWQsIGZyZWUgb2YgY2hhcmdlLCB0byBhbnkgcGVyc29uIG9idGFpbmluZyBhIGNvcHlcbi8vICBvZiB0aGlzIHNvZnR3YXJlIGFuZCBhc3NvY2lhdGVkIGRvY3VtZW50YXRpb24gZmlsZXMgKHRoZSBcIlNvZnR3YXJlXCIpLCB0b1xuLy8gIGRlYWwgaW4gdGhlIFNvZnR3YXJlIHdpdGhvdXQgcmVzdHJpY3Rpb24sIGluY2x1ZGluZyB3aXRob3V0IGxpbWl0YXRpb24gdGhlXG4vLyAgcmlnaHRzIHRvIHVzZSwgY29weSwgbW9kaWZ5LCBtZXJnZSwgcHVibGlzaCwgZGlzdHJpYnV0ZSwgc3VibGljZW5zZSwgYW5kL29yXG4vLyAgc2VsbCBjb3BpZXMgb2YgdGhlIFNvZnR3YXJlLCBhbmQgdG8gcGVybWl0IHBlcnNvbnMgdG8gd2hvbSB0aGUgU29mdHdhcmUgaXNcbi8vICBmdXJuaXNoZWQgdG8gZG8gc28sIHN1YmplY3QgdG8gdGhlIGZvbGxvd2luZyBjb25kaXRpb25zOlxuLy9cbi8vIFRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBlcm1pc3Npb24gbm90aWNlIHNoYWxsIGJlIGluY2x1ZGVkIGluXG4vLyAgYWxsIGNvcGllcyBvciBzdWJzdGFudGlhbCBwb3J0aW9ucyBvZiB0aGUgU29mdHdhcmUuXG4vL1xuLy8gVEhFIFNPRlRXQVJFIElTIFBST1ZJREVEIFwiQVMgSVNcIiwgV0lUSE9VVCBXQVJSQU5UWSBPRiBBTlkgS0lORCwgRVhQUkVTUyBPUlxuLy8gIElNUExJRUQsIElOQ0xVRElORyBCVVQgTk9UIExJTUlURUQgVE8gVEhFIFdBUlJBTlRJRVMgT0YgTUVSQ0hBTlRBQklMSVRZLFxuLy8gIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFORCBOT05JTkZSSU5HRU1FTlQuIElOIE5PIEVWRU5UIFNIQUxMIFRIRVxuLy8gIEFVVEhPUlMgT1IgQ09QWVJJR0hUIEhPTERFUlMgQkUgTElBQkxFIEZPUiBBTlkgQ0xBSU0sIERBTUFHRVMgT1IgT1RIRVJcbi8vICBMSUFCSUxJVFksIFdIRVRIRVIgSU4gQU4gQUNUSU9OIE9GIENPTlRSQUNULCBUT1JUIE9SIE9USEVSV0lTRSwgQVJJU0lORyBGUk9NLFxuLy8gIE9VVCBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhFIFNPRlRXQVJFIE9SIFRIRSBVU0UgT1IgT1RIRVIgREVBTElOR1MgSU5cbi8vICBUSEUgU09GVFdBUkUuXG5cbmltcG9ydCB7XG4gICAgQ2hhbmdlRGV0ZWN0b3JSZWYsXG4gICAgQ29tcG9uZW50LFxuICAgIEhvc3RCaW5kaW5nLFxuICAgIElucHV0LFxuICAgIE9uSW5pdCxcbiAgICBPbkNoYW5nZXMsXG4gICAgU2ltcGxlQ2hhbmdlcyxcbn0gZnJvbSBcIkBhbmd1bGFyL2NvcmVcIjtcblxuaW1wb3J0IHtcbiAgICBUaW1lc2VyaWVzWm9vbVBsdWdpbixcbiAgICBUaW1lc2VyaWVzWm9vbVBsdWdpbnNTeW5jU2VydmljZSxcbiAgICBab29tUGx1Z2luLFxufSBmcm9tIFwiQG5vdmEtdWkvY2hhcnRzXCI7XG5cbmltcG9ydCB7IFRpbWVzZXJpZXNDaGFydFByZXNldFNlcnZpY2UgfSBmcm9tIFwiLi90aW1lc2VyaWVzLWNoYXJ0LXByZXNldC5zZXJ2aWNlXCI7XG5pbXBvcnQge1xuICAgIElDaGFydFByZXNldCxcbiAgICBJVGltZXNlcmllc091dHB1dCxcbiAgICBJVGltZXNlcmllc1dpZGdldENvbmZpZyxcbiAgICBUaW1lc2VyaWVzQ2hhcnRQcmVzZXQsXG4gICAgVGltZXNlcmllc0NoYXJ0VHlwZXMsXG4gICAgVGltZXNlcmllc1dpZGdldFByb2plY3RUeXBlLFxuICAgIFRpbWVzZXJpZXNXaWRnZXRab29tUGx1Z2luLFxufSBmcm9tIFwiLi90eXBlc1wiO1xuaW1wb3J0IHsgSUhhc0NoYW5nZURldGVjdG9yIH0gZnJvbSBcIi4uLy4uL3R5cGVzXCI7XG5cbi8qKiBAaWdub3JlICovXG5AQ29tcG9uZW50KHtcbiAgICBzZWxlY3RvcjogXCJudWktdGltZXNlcmllcy13aWRnZXRcIixcbiAgICBzdHlsZVVybHM6IFtcIi4vdGltZXNlcmllcy13aWRnZXQuY29tcG9uZW50Lmxlc3NcIl0sXG4gICAgdGVtcGxhdGVVcmw6IFwiLi90aW1lc2VyaWVzLXdpZGdldC5jb21wb25lbnQuaHRtbFwiLFxufSlcbmV4cG9ydCBjbGFzcyBUaW1lc2VyaWVzV2lkZ2V0Q29tcG9uZW50XG4gICAgaW1wbGVtZW50cyBPbkluaXQsIE9uQ2hhbmdlcywgSUhhc0NoYW5nZURldGVjdG9yXG57XG4gICAgcHVibGljIHN0YXRpYyBsYXRlTG9hZEtleSA9IFwiVGltZXNlcmllc1dpZGdldENvbXBvbmVudFwiO1xuXG4gICAgQElucHV0KCkgcHVibGljIHdpZGdldERhdGE/OiBJVGltZXNlcmllc091dHB1dDtcbiAgICBASW5wdXQoKSBwdWJsaWMgY29uZmlndXJhdGlvbj86IElUaW1lc2VyaWVzV2lkZ2V0Q29uZmlnO1xuICAgIEBJbnB1dCgpIHB1YmxpYyBjb2xsZWN0aW9uSWQ/OiBzdHJpbmc7XG5cbiAgICBASW5wdXQoKSBASG9zdEJpbmRpbmcoXCJjbGFzc1wiKSBwdWJsaWMgZWxlbWVudENsYXNzID0gXCJcIjtcblxuICAgIHB1YmxpYyBjaGFydFByZXNldDogSUNoYXJ0UHJlc2V0O1xuXG4gICAgcHVibGljIHpvb21QbHVnaW5zOiBUaW1lc2VyaWVzV2lkZ2V0Wm9vbVBsdWdpbltdID0gW107XG4gICAgcHVibGljIGFsbG93UG9wb3ZlciA9IGZhbHNlO1xuICAgIHB1YmxpYyB0aW1lc2VyaWVzV2lkZ2V0UHJvamVjdFR5cGUgPSBUaW1lc2VyaWVzV2lkZ2V0UHJvamVjdFR5cGU7XG5cbiAgICBjb25zdHJ1Y3RvcihcbiAgICAgICAgcHVibGljIHRpbWVzZXJpZXNDaGFydFByZXNldFNlcnZpY2U6IFRpbWVzZXJpZXNDaGFydFByZXNldFNlcnZpY2UsXG4gICAgICAgIHB1YmxpYyBjaGFuZ2VEZXRlY3RvcjogQ2hhbmdlRGV0ZWN0b3JSZWYsXG4gICAgICAgIHB1YmxpYyB6b29tUGx1Z2luc1N5bmNTZXJ2aWNlOiBUaW1lc2VyaWVzWm9vbVBsdWdpbnNTeW5jU2VydmljZVxuICAgICkge31cblxuICAgIHB1YmxpYyBuZ09uSW5pdCgpOiB2b2lkIHtcbiAgICAgICAgaWYgKFxuICAgICAgICAgICAgdGhpcy5jb25maWd1cmF0aW9uPy5wcm9qZWN0VHlwZSA9PT1cbiAgICAgICAgICAgIFRpbWVzZXJpZXNXaWRnZXRQcm9qZWN0VHlwZS5QZXJmc3RhY2tBcHBcbiAgICAgICAgKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5jb25maWd1cmF0aW9uLnR5cGUgPT09IFRpbWVzZXJpZXNDaGFydFR5cGVzLmFsZXJ0KSB7XG4gICAgICAgICAgICAgICAgLy8gYWRkcyB0aW1lc2VyaWVzIHpvb20gcGx1Z2luIGZvciBlYWNoIHN1YmNoYXJ0cyB0byBtYWtlIHRoZSBzeW5jaHJvbml6YXRpb24gd29ya2luZyBmb3IgdGhlIGFsZXJ0IGNoYXJ0XG4gICAgICAgICAgICAgICAgdGhpcy53aWRnZXREYXRhPy5zZXJpZXMuZm9yRWFjaCgoKSA9PlxuICAgICAgICAgICAgICAgICAgICB0aGlzLnpvb21QbHVnaW5zLnB1c2godGhpcy5nZXRUaW1lc2VyaWVzWm9vbVBsdWdpbigpKVxuICAgICAgICAgICAgICAgICk7XG5cbiAgICAgICAgICAgICAgICAvLyBkb2Vzbid0IGFkZCB6b29tIHBsdWdpbiBmb3IgYSBzdW1tYXJ5IHNlcmllIHdoZW4gdGhlcmUgYXJlIG5vIHN1YiBjaGFydHMgYW5kIG9ubHkgc3VtYXJ5IHNlcmllIHdpbGwgYmUgZGlzcGxheWVkXG4gICAgICAgICAgICAgICAgaWYgKFxuICAgICAgICAgICAgICAgICAgICAhKFxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy53aWRnZXREYXRhPy5zZXJpZXMubGVuZ3RoID09PSAxICYmXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLndpZGdldERhdGEuc2VyaWVzWzBdLmlkID09PVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMud2lkZ2V0RGF0YS5zdW1tYXJ5U2VyaWU/LmlkXG4gICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy56b29tUGx1Z2lucy5wdXNoKHRoaXMuZ2V0VGltZXNlcmllc1pvb21QbHVnaW4oKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLnpvb21QbHVnaW5zLnB1c2godGhpcy5nZXRUaW1lc2VyaWVzWm9vbVBsdWdpbigpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuem9vbVBsdWdpbnMucHVzaChuZXcgWm9vbVBsdWdpbigpKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgZ2V0VGltZXNlcmllc1pvb21QbHVnaW4oKTogVGltZXNlcmllc1pvb21QbHVnaW4ge1xuICAgICAgICByZXR1cm4gbmV3IFRpbWVzZXJpZXNab29tUGx1Z2luKFxuICAgICAgICAgICAgeyBjb2xsZWN0aW9uSWQ6IHRoaXMuY29sbGVjdGlvbklkIH0sXG4gICAgICAgICAgICB0aGlzLnpvb21QbHVnaW5zU3luY1NlcnZpY2VcbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgbmdPbkNoYW5nZXMoY2hhbmdlczogU2ltcGxlQ2hhbmdlcyk6IHZvaWQge1xuICAgICAgICBpZiAoY2hhbmdlcy5jb25maWd1cmF0aW9uKSB7XG4gICAgICAgICAgICBjb25zdCBjb25maWd1cmF0aW9uQ3VycmVudDogSVRpbWVzZXJpZXNXaWRnZXRDb25maWcgPVxuICAgICAgICAgICAgICAgIGNoYW5nZXMuY29uZmlndXJhdGlvbi5jdXJyZW50VmFsdWU7XG4gICAgICAgICAgICBjb25zdCBjb25maWd1cmF0aW9uUHJldmlvdXM6IElUaW1lc2VyaWVzV2lkZ2V0Q29uZmlnID1cbiAgICAgICAgICAgICAgICBjaGFuZ2VzLmNvbmZpZ3VyYXRpb24ucHJldmlvdXNWYWx1ZTtcblxuICAgICAgICAgICAgaWYgKFxuICAgICAgICAgICAgICAgIGNvbmZpZ3VyYXRpb25DdXJyZW50Py5wcmVzZXQgIT09IGNvbmZpZ3VyYXRpb25QcmV2aW91cz8ucHJlc2V0XG4gICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgICB0aGlzLmNoYXJ0UHJlc2V0ID1cbiAgICAgICAgICAgICAgICAgICAgdGhpcy50aW1lc2VyaWVzQ2hhcnRQcmVzZXRTZXJ2aWNlLnByZXNldHNbXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbmZpZ3VyYXRpb24/LnByZXNldCA/PyBUaW1lc2VyaWVzQ2hhcnRQcmVzZXQuTGluZVxuICAgICAgICAgICAgICAgICAgICBdO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqIENoZWNrcyBpZiBjaGFydCBzaG91bGQgYmUgc2hvd24uICovXG4gICAgcHVibGljIHNob3VsZFNob3dDaGFydCgpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuICh0aGlzLndpZGdldERhdGE/LnNlcmllcz8ubGVuZ3RoID8/IDApID4gMDtcbiAgICB9XG5cbiAgICBwdWJsaWMgdG9nZ2xlTGVhdmUoKTogdm9pZCB7XG4gICAgICAgIHRoaXMuYWxsb3dQb3BvdmVyID0gZmFsc2U7XG4gICAgfVxuICAgIHB1YmxpYyB0b2dnbGVFbnRlcigpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5hbGxvd1BvcG92ZXIgPSB0cnVlO1xuICAgIH1cblxuICAgIHB1YmxpYyBpc0V4cGxvcmluZ0VuYWJsZWQoKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICB0aGlzLmNvbmZpZ3VyYXRpb24/LnR5cGUgIT09IFRpbWVzZXJpZXNDaGFydFR5cGVzLmxpbmUgJiZcbiAgICAgICAgICAgIHRoaXMuY29uZmlndXJhdGlvbj8udHlwZSAhPT0gVGltZXNlcmllc0NoYXJ0VHlwZXMubXVsdGkgJiZcbiAgICAgICAgICAgIHRoaXMuY29uZmlndXJhdGlvbj8udHlwZSAhPT0gVGltZXNlcmllc0NoYXJ0VHlwZXMuc3RhdHVzXG4gICAgICAgICk7XG4gICAgfVxufVxuIiwiPGRpdlxuICAgIGNsYXNzPVwiaC0xMDAgdGltZXNlcmllcy13aWRnZXQtY29udGVudFwiXG4gICAgKm5nSWY9XCJzaG91bGRTaG93Q2hhcnQoKVwiXG4gICAgKG1vdXNlbGVhdmUpPVwidG9nZ2xlTGVhdmUoKVwiXG4gICAgKG1vdXNlZW50ZXIpPVwidG9nZ2xlRW50ZXIoKVwiXG4+XG4gICAgPG5nLWNvbnRhaW5lclxuICAgICAgICBudWlDb21wb25lbnRQb3J0YWxcbiAgICAgICAgY29tcG9uZW50SWQ9XCJ0aW1lc2VyaWVzV2lkZ2V0Q2hhcnRcIlxuICAgICAgICBbY29tcG9uZW50VHlwZV09XCJjaGFydFByZXNldC5jb21wb25lbnRUeXBlXCJcbiAgICAgICAgW3Byb3BlcnRpZXNdPVwie1xuICAgICAgICAgICAgd2lkZ2V0RGF0YTogd2lkZ2V0RGF0YSxcbiAgICAgICAgICAgIGNvbmZpZ3VyYXRpb246IGNvbmZpZ3VyYXRpb24sXG4gICAgICAgICAgICBjb2xsZWN0aW9uSWQ6IGNvbGxlY3Rpb25JZCB8fCBjb25maWd1cmF0aW9uPy5jb2xsZWN0aW9uSWQsXG4gICAgICAgICAgICB6b29tUGx1Z2luczogem9vbVBsdWdpbnNcbiAgICAgICAgfVwiXG4gICAgICAgICNjb21wb25lbnRQb3J0YWw9XCJudWlDb21wb25lbnRQb3J0YWxcIlxuICAgID5cbiAgICAgICAgPG5nLXRlbXBsYXRlXG4gICAgICAgICAgICBbY2RrUG9ydGFsT3V0bGV0XT1cImNvbXBvbmVudFBvcnRhbC5wb3J0YWxcIlxuICAgICAgICAgICAgKGF0dGFjaGVkKT1cImNvbXBvbmVudFBvcnRhbC5hdHRhY2hlZCgkZXZlbnQpXCJcbiAgICAgICAgPlxuICAgICAgICA8L25nLXRlbXBsYXRlPlxuICAgIDwvbmctY29udGFpbmVyPlxuICAgIDxudWktdGltZXNlcmllcy1pbnNwZWN0aW9uLW1lbnVcbiAgICAgICAgKm5nSWY9XCJcbiAgICAgICAgICAgIGNvbmZpZ3VyYXRpb24/LmVuYWJsZVpvb20gJiZcbiAgICAgICAgICAgIGNvbmZpZ3VyYXRpb24/LnByb2plY3RUeXBlID09PVxuICAgICAgICAgICAgICAgIHRpbWVzZXJpZXNXaWRnZXRQcm9qZWN0VHlwZS5QZXJmc3RhY2tBcHAgJiZcbiAgICAgICAgICAgIHpvb21QbHVnaW5zLmxlbmd0aFxuICAgICAgICBcIlxuICAgICAgICBbYWxsb3dlZF09XCJhbGxvd1BvcG92ZXJcIlxuICAgICAgICBbcGx1Z2luXT1cInpvb21QbHVnaW5zWzBdXCJcbiAgICAgICAgW2NvbGxlY3Rpb25JZF09XCJjb2xsZWN0aW9uSWRcIlxuICAgICAgICBbZXhwbG9yaW5nRW5hYmxlZF09XCJpc0V4cGxvcmluZ0VuYWJsZWQoKVwiXG4gICAgICAgIFttZXRyaWNJZHNdPVwiY29uZmlndXJhdGlvbj8ubWV0cmljSWRzXCJcbiAgICA+PC9udWktdGltZXNlcmllcy1pbnNwZWN0aW9uLW1lbnU+XG48L2Rpdj5cbjxkaXYgKm5nSWY9XCIhc2hvdWxkU2hvd0NoYXJ0KClcIj5cbiAgICA8bnVpLWltYWdlIGltYWdlPVwibm8tZGF0YS10by1zaG93XCI+PC9udWktaW1hZ2U+XG48L2Rpdj5cbiJdfQ==