UNPKG

@nova-ui/charts

Version:

Nova Charts is a library created to provide potential consumers with solutions for various data visualizations that conform with the Nova Design Language. It's designed to solve common patterns identified by UX designers, but also be very flexible so that

171 lines 26.6 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 cloneDeep from "lodash/cloneDeep"; import defaultsDeep from "lodash/defaultsDeep"; import isUndefined from "lodash/isUndefined"; import { Subject } from "rxjs"; import { takeUntil } from "rxjs/operators"; import { GAUGE_LABELS_CONTAINER_CLASS, GAUGE_LABEL_FORMATTER_NAME_DEFAULT, GAUGE_THRESHOLD_LABEL_CLASS, } from "./constants"; import { MOUSE_ACTIVE_EVENT, STANDARD_RENDER_LAYERS } from "../../../constants"; import { GAUGE_THRESHOLD_MARKERS_SERIES_ID } from "../../../gauge/constants"; import { RenderLayerName } from "../../../renderers/types"; import { ChartPlugin } from "../../common/chart-plugin"; import { LinearScale } from "../../common/scales/linear-scale"; /** * A chart plugin that handles the rendering of labels for a donut gauge */ export class LinearGaugeLabelsPlugin extends ChartPlugin { config; /** The default plugin configuration */ DEFAULT_CONFIG = { padding: 5, formatterName: GAUGE_LABEL_FORMATTER_NAME_DEFAULT, disableThresholdLabels: false, flippedLabels: false, }; destroy$ = new Subject(); lasagnaLayer; isHorizontal = true; thresholdsSeries; constructor(config = {}) { super(); this.config = config; this.config = defaultsDeep(this.config, this.DEFAULT_CONFIG); } initialize() { this.lasagnaLayer = this.chart.getGrid().getLasagna().addLayer({ name: GAUGE_LABELS_CONTAINER_CLASS, order: STANDARD_RENDER_LAYERS[RenderLayerName.data].order, clipped: false, }); this.chart .getEventBus() .getStream(MOUSE_ACTIVE_EVENT) .pipe(takeUntil(this.destroy$)) .subscribe((event) => { const gaugeThresholdLabelsGroup = this.lasagnaLayer.select(`.${GAUGE_LABELS_CONTAINER_CLASS}`); if (!gaugeThresholdLabelsGroup.empty()) { gaugeThresholdLabelsGroup.style("opacity", event.data ? 1 : 0); } }); } update() { this.updateData(); this.drawThresholdLabels(); } updateDimensions() { this.updateData(); this.drawThresholdLabels(); } destroy() { if (this.destroy$) { this.destroy$.next(); this.destroy$.complete(); } } updateData() { this.thresholdsSeries = this.chart .getDataManager() .chartSeriesSet.find((series) => series.id === GAUGE_THRESHOLD_MARKERS_SERIES_ID); this.isHorizontal = this.thresholdsSeries?.scales.x instanceof LinearScale; } drawThresholdLabels() { if (isUndefined(this.thresholdsSeries)) { console.warn("Threshold series is undefined. As a result, threshold labels for the linear gauge will not be rendered."); return; } let gaugeThresholdsLabelsGroup = this.lasagnaLayer.select(`.${GAUGE_LABELS_CONTAINER_CLASS}`); if (gaugeThresholdsLabelsGroup.empty()) { gaugeThresholdsLabelsGroup = this.lasagnaLayer .append("svg:g") .attr("class", GAUGE_LABELS_CONTAINER_CLASS) .style("opacity", 0); } const data = cloneDeep(this.config.disableThresholdLabels ? [] : this.thresholdsSeries?.data); if (isUndefined(data)) { throw new Error("Gauge threshold series data is undefined"); } // last value in the thresholds series is the max value of the gauge (needed by RadialGaugeThresholdsRenderer). // removing this value to avoid rendering a label for it data.pop(); const formatter = this.thresholdsSeries?.scales[this.isHorizontal ? "x" : "y"] .formatters[this.config.formatterName] ?? ((d) => d); const labelSelection = gaugeThresholdsLabelsGroup .selectAll(`text.${GAUGE_THRESHOLD_LABEL_CLASS}`) .data(data); labelSelection.exit().remove(); labelSelection .enter() .append("text") .attr("class", GAUGE_THRESHOLD_LABEL_CLASS) .merge(labelSelection) .attr("transform", (d, i) => `translate(${this.xTranslate(d, i)}, ${this.yTranslate(d, i)})`) .attr("title", (d, i) => formatter(data[i].value)) .style("text-anchor", (d) => this.getTextAnchor()) .style("dominant-baseline", (d) => this.getAlignmentBaseline()) .text((d, i) => formatter(data[i].value)); } xTranslate = (d, i) => { if (this.isHorizontal) { const thresholdsSeries = this .thresholdsSeries; const value = this.thresholdsSeries?.accessors?.data?.value?.(d, i, thresholdsSeries?.data, thresholdsSeries); return this.thresholdsSeries?.scales.x.convert(value); } return this.getLabelOffset(); }; yTranslate = (d, i) => { if (this.isHorizontal) { return this.getLabelOffset(); } const thresholdsSeries = this .thresholdsSeries; const value = this.thresholdsSeries?.accessors?.data?.value?.(d, i, thresholdsSeries?.data, thresholdsSeries); return this.thresholdsSeries?.scales.y.convert(value); }; getLabelOffset() { let labelStart = 0; if (!this.config.flippedLabels) { const gridDimensions = this.chart.getGrid().config().dimension; labelStart = this.isHorizontal ? gridDimensions.height() : gridDimensions.width(); } let padding = this.config.padding; padding = this.config.flippedLabels ? -padding : padding; return labelStart + padding; } getTextAnchor() { if (this.isHorizontal) { return "middle"; } return this.config.flippedLabels ? "end" : "start"; } getAlignmentBaseline() { if (this.isHorizontal) { return this.config.flippedLabels ? "text-after-edge" : "hanging"; } return "central"; } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibGluZWFyLWdhdWdlLWxhYmVscy1wbHVnaW4uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9zcmMvY29yZS9wbHVnaW5zL2dhdWdlL2xpbmVhci1nYXVnZS1sYWJlbHMtcGx1Z2luLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLHlEQUF5RDtBQUN6RCxFQUFFO0FBQ0YsK0VBQStFO0FBQy9FLDRFQUE0RTtBQUM1RSw4RUFBOEU7QUFDOUUsK0VBQStFO0FBQy9FLDhFQUE4RTtBQUM5RSw0REFBNEQ7QUFDNUQsRUFBRTtBQUNGLDZFQUE2RTtBQUM3RSx1REFBdUQ7QUFDdkQsRUFBRTtBQUNGLDZFQUE2RTtBQUM3RSw0RUFBNEU7QUFDNUUsK0VBQStFO0FBQy9FLDBFQUEwRTtBQUMxRSxpRkFBaUY7QUFDakYsNkVBQTZFO0FBQzdFLGlCQUFpQjtBQUVqQixPQUFPLFNBQVMsTUFBTSxrQkFBa0IsQ0FBQztBQUN6QyxPQUFPLFlBQVksTUFBTSxxQkFBcUIsQ0FBQztBQUMvQyxPQUFPLFdBQVcsTUFBTSxvQkFBb0IsQ0FBQztBQUM3QyxPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBQy9CLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUUzQyxPQUFPLEVBQ0gsNEJBQTRCLEVBQzVCLGtDQUFrQyxFQUNsQywyQkFBMkIsR0FDOUIsTUFBTSxhQUFhLENBQUM7QUFFckIsT0FBTyxFQUFFLGtCQUFrQixFQUFFLHNCQUFzQixFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFDaEYsT0FBTyxFQUFFLGlDQUFpQyxFQUFFLE1BQU0sMEJBQTBCLENBQUM7QUFDN0UsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBQzNELE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQztBQUN4RCxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sa0NBQWtDLENBQUM7QUFTL0Q7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O1FBQ3pELE9BQU8sVUFBVSxHQUFHLE9BQU8sQ0FBQztJQUNoQyxDQUFDO0lBRU8sYUFBYTtRQUNqQixJQUFJLElBQUksQ0FBQyxZQUFZLEVBQUU7WUFDbkIsT0FBTyxRQUFRLENBQUM7U0FDbkI7UUFFRCxPQUFPLElBQUksQ0FBQyxNQUFNLENBQUMsYUFBYSxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQztJQUN2RCxDQUFDO0lBRU8sb0JBQW9CO1FBQ3hCLElBQUksSUFBSSxDQUFDLFlBQVksRUFBRTtZQUNuQixPQUFPLElBQUksQ0FBQyxNQUFNLENBQUMsYUFBYSxDQUFDLENBQUMsQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDO1NBQ3BFO1FBRUQsT0FBTyxTQUFTLENBQUM7SUFDckIsQ0FBQztDQUNKIiwic291cmNlc0NvbnRlbnQiOlsiLy8gwqkgMjAyMiBTb2xhcldpbmRzIFdvcmxkd2lkZSwgTExDLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy9cbi8vIFBlcm1pc3Npb24gaXMgaGVyZWJ5IGdyYW50ZWQsIGZyZWUgb2YgY2hhcmdlLCB0byBhbnkgcGVyc29uIG9idGFpbmluZyBhIGNvcHlcbi8vICBvZiB0aGlzIHNvZnR3YXJlIGFuZCBhc3NvY2lhdGVkIGRvY3VtZW50YXRpb24gZmlsZXMgKHRoZSBcIlNvZnR3YXJlXCIpLCB0b1xuLy8gIGRlYWwgaW4gdGhlIFNvZnR3YXJlIHdpdGhvdXQgcmVzdHJpY3Rpb24sIGluY2x1ZGluZyB3aXRob3V0IGxpbWl0YXRpb24gdGhlXG4vLyAgcmlnaHRzIHRvIHVzZSwgY29weSwgbW9kaWZ5LCBtZXJnZSwgcHVibGlzaCwgZGlzdHJpYnV0ZSwgc3VibGljZW5zZSwgYW5kL29yXG4vLyAgc2VsbCBjb3BpZXMgb2YgdGhlIFNvZnR3YXJlLCBhbmQgdG8gcGVybWl0IHBlcnNvbnMgdG8gd2hvbSB0aGUgU29mdHdhcmUgaXNcbi8vICBmdXJuaXNoZWQgdG8gZG8gc28sIHN1YmplY3QgdG8gdGhlIGZvbGxvd2luZyBjb25kaXRpb25zOlxuLy9cbi8vIFRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBlcm1pc3Npb24gbm90aWNlIHNoYWxsIGJlIGluY2x1ZGVkIGluXG4vLyAgYWxsIGNvcGllcyBvciBzdWJzdGFudGlhbCBwb3J0aW9ucyBvZiB0aGUgU29mdHdhcmUuXG4vL1xuLy8gVEhFIFNPRlRXQVJFIElTIFBST1ZJREVEIFwiQVMgSVNcIiwgV0lUSE9VVCBXQVJSQU5UWSBPRiBBTlkgS0lORCwgRVhQUkVTUyBPUlxuLy8gIElNUExJRUQsIElOQ0xVRElORyBCVVQgTk9UIExJTUlURUQgVE8gVEhFIFdBUlJBTlRJRVMgT0YgTUVSQ0hBTlRBQklMSVRZLFxuLy8gIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFORCBOT05JTkZSSU5HRU1FTlQuIElOIE5PIEVWRU5UIFNIQUxMIFRIRVxuLy8gIEFVVEhPUlMgT1IgQ09QWVJJR0hUIEhPTERFUlMgQkUgTElBQkxFIEZPUiBBTlkgQ0xBSU0sIERBTUFHRVMgT1IgT1RIRVJcbi8vICBMSUFCSUxJVFksIFdIRVRIRVIgSU4gQU4gQUNUSU9OIE9GIENPTlRSQUNULCBUT1JUIE9SIE9USEVSV0lTRSwgQVJJU0lORyBGUk9NLFxuLy8gIE9VVCBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhFIFNPRlRXQVJFIE9SIFRIRSBVU0UgT1IgT1RIRVIgREVBTElOR1MgSU5cbi8vICBUSEUgU09GVFdBUkUuXG5cbmltcG9ydCBjbG9uZURlZXAgZnJvbSBcImxvZGFzaC9jbG9uZURlZXBcIjtcbmltcG9ydCBkZWZhdWx0c0RlZXAgZnJvbSBcImxvZGFzaC9kZWZhdWx0c0RlZXBcIjtcbmltcG9ydCBpc1VuZGVmaW5lZCBmcm9tIFwibG9kYXNoL2lzVW5kZWZpbmVkXCI7XG5pbXBvcnQgeyBTdWJqZWN0IH0gZnJvbSBcInJ4anNcIjtcbmltcG9ydCB7IHRha2VVbnRpbCB9IGZyb20gXCJyeGpzL29wZXJhdG9yc1wiO1xuXG5pbXBvcnQge1xuICAgIEdBVUdFX0xBQkVMU19DT05UQUlORVJfQ0xBU1MsXG4gICAgR0FVR0VfTEFCRUxfRk9STUFUVEVSX05BTUVfREVGQVVMVCxcbiAgICBHQVVHRV9USFJFU0hPTERfTEFCRUxfQ0xBU1MsXG59IGZyb20gXCIuL2NvbnN0YW50c1wiO1xuaW1wb3J0IHsgSUdhdWdlTGFiZWxzUGx1Z2luQ29uZmlnIH0gZnJvbSBcIi4vdHlwZXNcIjtcbmltcG9ydCB7IE1PVVNFX0FDVElWRV9FVkVOVCwgU1RBTkRBUkRfUkVOREVSX0xBWUVSUyB9IGZyb20gXCIuLi8uLi8uLi9jb25zdGFudHNcIjtcbmltcG9ydCB7IEdBVUdFX1RIUkVTSE9MRF9NQVJLRVJTX1NFUklFU19JRCB9IGZyb20gXCIuLi8uLi8uLi9nYXVnZS9jb25zdGFudHNcIjtcbmltcG9ydCB7IFJlbmRlckxheWVyTmFtZSB9IGZyb20gXCIuLi8uLi8uLi9yZW5kZXJlcnMvdHlwZXNcIjtcbmltcG9ydCB7IENoYXJ0UGx1Z2luIH0gZnJvbSBcIi4uLy4uL2NvbW1vbi9jaGFydC1wbHVnaW5cIjtcbmltcG9ydCB7IExpbmVhclNjYWxlIH0gZnJvbSBcIi4uLy4uL2NvbW1vbi9zY2FsZXMvbGluZWFyLXNjYWxlXCI7XG5pbXBvcnQge1xuICAgIEQzU2VsZWN0aW9uLFxuICAgIElBY2Nlc3NvcnMsXG4gICAgSUNoYXJ0RXZlbnQsXG4gICAgSUNoYXJ0U2VyaWVzLFxuICAgIElEYXRhU2VyaWVzLFxufSBmcm9tIFwiLi4vLi4vY29tbW9uL3R5cGVzXCI7XG5cbi8qKlxuICogQSBjaGFydCBwbHVnaW4gdGhhdCBoYW5kbGVzIHRoZSByZW5kZXJpbmcgb2YgbGFiZWxzIGZvciBhIGRvbnV0IGdhdWdlXG4gKi9cbmV4cG9ydCBjbGFzcyBMaW5lYXJHYXVnZUxhYmVsc1BsdWdpbiBleHRlbmRzIENoYXJ0UGx1Z2luIHtcbiAgICAvKiogVGhlIGRlZmF1bHQgcGx1Z2luIGNvbmZpZ3VyYXRpb24gKi9cbiAgICBwdWJsaWMgREVGQVVMVF9DT05GSUc6IElHYXVnZUxhYmVsc1BsdWdpbkNvbmZpZyA9IHtcbiAgICAgICAgcGFkZGluZzogNSxcbiAgICAgICAgZm9ybWF0dGVyTmFtZTogR0FVR0VfTEFCRUxfRk9STUFUVEVSX05BTUVfREVGQVVMVCxcbiAgICAgICAgZGlzYWJsZVRocmVzaG9sZExhYmVsczogZmFsc2UsXG4gICAgICAgIGZsaXBwZWRMYWJlbHM6IGZhbHNlLFxuICAgIH07XG5cbiAgICBwcml2YXRlIHJlYWRvbmx5IGRlc3Ryb3kkID0gbmV3IFN1YmplY3Q8dm9pZD4oKTtcbiAgICBwcml2YXRlIGxhc2FnbmFMYXllcjogRDNTZWxlY3Rpb248U1ZHRWxlbWVudD47XG4gICAgcHJpdmF0ZSBpc0hvcml6b250YWwgPSB0cnVlO1xuICAgIHByaXZhdGUgdGhyZXNob2xkc1NlcmllczogSUNoYXJ0U2VyaWVzPElBY2Nlc3NvcnM8YW55Pj4gfCB1bmRlZmluZWQ7XG5cbiAgICBjb25zdHJ1Y3RvcihwdWJsaWMgY29uZmlnOiBJR2F1Z2VMYWJlbHNQbHVnaW5Db25maWcgPSB7fSkge1xuICAgICAgICBzdXBlcigpO1xuICAgICAgICB0aGlzLmNvbmZpZyA9IGRlZmF1bHRzRGVlcCh0aGlzLmNvbmZpZywgdGhpcy5ERUZBVUxUX0NPTkZJRyk7XG4gICAgfVxuXG4gICAgcHVibGljIGluaXRpYWxpemUoKTogdm9pZCB7XG4gICAgICAgIHRoaXMubGFzYWduYUxheWVyID0gdGhpcy5jaGFydC5nZXRHcmlkKCkuZ2V0TGFzYWduYSgpLmFkZExheWVyKHtcbiAgICAgICAgICAgIG5hbWU6IEdBVUdFX0xBQkVMU19DT05UQUlORVJfQ0xBU1MsXG4gICAgICAgICAgICBvcmRlcjogU1RBTkRBUkRfUkVOREVSX0xBWUVSU1tSZW5kZXJMYXllck5hbWUuZGF0YV0ub3JkZXIsXG4gICAgICAgICAgICBjbGlwcGVkOiBmYWxzZSxcbiAgICAgICAgfSk7XG5cbiAgICAgICAgdGhpcy5jaGFydFxuICAgICAgICAgICAgLmdldEV2ZW50QnVzKClcbiAgICAgICAgICAgIC5nZXRTdHJlYW0oTU9VU0VfQUNUSVZFX0VWRU5UIGFzIHN0cmluZylcbiAgICAgICAgICAgIC5waXBlKHRha2VVbnRpbCh0aGlzLmRlc3Ryb3kkKSlcbiAgICAgICAgICAgIC5zdWJzY3JpYmUoKGV2ZW50OiBJQ2hhcnRFdmVudCkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IGdhdWdlVGhyZXNob2xkTGFiZWxzR3JvdXAgPSB0aGlzLmxhc2FnbmFMYXllci5zZWxlY3QoXG4gICAgICAgICAgICAgICAgICAgIGAuJHtHQVVHRV9MQUJFTFNfQ09OVEFJTkVSX0NMQVNTfWBcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgIGlmICghZ2F1Z2VUaHJlc2hvbGRMYWJlbHNHcm91cC5lbXB0eSgpKSB7XG4gICAgICAgICAgICAgICAgICAgIGdhdWdlVGhyZXNob2xkTGFiZWxzR3JvdXAuc3R5bGUoXG4gICAgICAgICAgICAgICAgICAgICAgICBcIm9wYWNpdHlcIixcbiAgICAgICAgICAgICAgICAgICAgICAgIGV2ZW50LmRhdGEgPyAxIDogMFxuICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgIH1cblxuICAgIHB1YmxpYyB1cGRhdGUoKTogdm9pZCB7XG4gICAgICAgIHRoaXMudXBkYXRlRGF0YSgpO1xuICAgICAgICB0aGlzLmRyYXdUaHJlc2hvbGRMYWJlbHMoKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgdXBkYXRlRGltZW5zaW9ucygpOiB2b2lkIHtcbiAgICAgICAgdGhpcy51cGRhdGVEYXRhKCk7XG4gICAgICAgIHRoaXMuZHJhd1RocmVzaG9sZExhYmVscygpO1xuICAgIH1cblxuICAgIHB1YmxpYyBkZXN0cm95KCk6IHZvaWQge1xuICAgICAgICBpZiAodGhpcy5kZXN0cm95JCkge1xuICAgICAgICAgICAgdGhpcy5kZXN0cm95JC5uZXh0KCk7XG4gICAgICAgICAgICB0aGlzLmRlc3Ryb3kkLmNvbXBsZXRlKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIHVwZGF0ZURhdGEoKSB7XG4gICAgICAgIHRoaXMudGhyZXNob2xkc1NlcmllcyA9IHRoaXMuY2hhcnRcbiAgICAgICAgICAgIC5nZXREYXRhTWFuYWdlcigpXG4gICAgICAgICAgICAuY2hhcnRTZXJpZXNTZXQuZmluZChcbiAgICAgICAgICAgICAgICAoc2VyaWVzOiBJQ2hhcnRTZXJpZXM8SUFjY2Vzc29yczxhbnk+PikgPT5cbiAgICAgICAgICAgICAgICAgICAgc2VyaWVzLmlkID09PSBHQVVHRV9USFJFU0hPTERfTUFSS0VSU19TRVJJRVNfSURcbiAgICAgICAgICAgICk7XG4gICAgICAgIHRoaXMuaXNIb3Jpem9udGFsID1cbiAgICAgICAgICAgIHRoaXMudGhyZXNob2xkc1Nlcmllcz8uc2NhbGVzLnggaW5zdGFuY2VvZiBMaW5lYXJTY2FsZTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGRyYXdUaHJlc2hvbGRMYWJlbHMoKSB7XG4gICAgICAgIGlmIChpc1VuZGVmaW5lZCh0aGlzLnRocmVzaG9sZHNTZXJpZXMpKSB7XG4gICAgICAgICAgICBjb25zb2xlLndhcm4oXG4gICAgICAgICAgICAgICAgXCJUaHJlc2hvbGQgc2VyaWVzIGlzIHVuZGVmaW5lZC4gQXMgYSByZXN1bHQsIHRocmVzaG9sZCBsYWJlbHMgZm9yIHRoZSBsaW5lYXIgZ2F1Z2Ugd2lsbCBub3QgYmUgcmVuZGVyZWQuXCJcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBsZXQgZ2F1Z2VUaHJlc2hvbGRzTGFiZWxzR3JvdXAgPSB0aGlzLmxhc2FnbmFMYXllci5zZWxlY3QoXG4gICAgICAgICAgICBgLiR7R0FVR0VfTEFCRUxTX0NPTlRBSU5FUl9DTEFTU31gXG4gICAgICAgICk7XG4gICAgICAgIGlmIChnYXVnZVRocmVzaG9sZHNMYWJlbHNHcm91cC5lbXB0eSgpKSB7XG4gICAgICAgICAgICBnYXVnZVRocmVzaG9sZHNMYWJlbHNHcm91cCA9IHRoaXMubGFzYWduYUxheWVyXG4gICAgICAgICAgICAgICAgLmFwcGVuZChcInN2ZzpnXCIpXG4gICAgICAgICAgICAgICAgLmF0dHIoXCJjbGFzc1wiLCBHQVVHRV9MQUJFTFNfQ09OVEFJTkVSX0NMQVNTKVxuICAgICAgICAgICAgICAgIC5zdHlsZShcIm9wYWNpdHlcIiwgMCk7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBkYXRhID0gY2xvbmVEZWVwKFxuICAgICAgICAgICAgdGhpcy5jb25maWcuZGlzYWJsZVRocmVzaG9sZExhYmVsc1xuICAgICAgICAgICAgICAgID8gW11cbiAgICAgICAgICAgICAgICA6IHRoaXMudGhyZXNob2xkc1Nlcmllcz8uZGF0YVxuICAgICAgICApO1xuICAgICAgICBpZiAoaXNVbmRlZmluZWQoZGF0YSkpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIkdhdWdlIHRocmVzaG9sZCBzZXJpZXMgZGF0YSBpcyB1bmRlZmluZWRcIik7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBsYXN0IHZhbHVlIGluIHRoZSB0aHJlc2hvbGRzIHNlcmllcyBpcyB0aGUgbWF4IHZhbHVlIG9mIHRoZSBnYXVnZSAobmVlZGVkIGJ5IFJhZGlhbEdhdWdlVGhyZXNob2xkc1JlbmRlcmVyKS5cbiAgICAgICAgLy8gcmVtb3ZpbmcgdGhpcyB2YWx1ZSB0byBhdm9pZCByZW5kZXJpbmcgYSBsYWJlbCBmb3IgaXRcbiAgICAgICAgZGF0YS5wb3AoKTtcblxuICAgICAgICBjb25zdCBmb3JtYXR0ZXIgPVxuICAgICAgICAgICAgdGhpcy50aHJlc2hvbGRzU2VyaWVzPy5zY2FsZXNbdGhpcy5pc0hvcml6b250YWwgPyBcInhcIiA6IFwieVwiXVxuICAgICAgICAgICAgICAgIC5mb3JtYXR0ZXJzW3RoaXMuY29uZmlnLmZvcm1hdHRlck5hbWUgYXMgc3RyaW5nXSA/PyAoKGQpID0+IGQpO1xuICAgICAgICBjb25zdCBsYWJlbFNlbGVjdGlvbiA9IGdhdWdlVGhyZXNob2xkc0xhYmVsc0dyb3VwXG4gICAgICAgICAgICAuc2VsZWN0QWxsKGB0ZXh0LiR7R0FVR0VfVEhSRVNIT0xEX0xBQkVMX0NMQVNTfWApXG4gICAgICAgICAgICAuZGF0YShkYXRhKTtcblxuICAgICAgICBsYWJlbFNlbGVjdGlvbi5leGl0KCkucmVtb3ZlKCk7XG4gICAgICAgIGxhYmVsU2VsZWN0aW9uXG4gICAgICAgICAgICAuZW50ZXIoKVxuICAgICAgICAgICAgLmFwcGVuZChcInRleHRcIilcbiAgICAgICAgICAgIC5hdHRyKFwiY2xhc3NcIiwgR0FVR0VfVEhSRVNIT0xEX0xBQkVMX0NMQVNTKVxuICAgICAgICAgICAgLm1lcmdlKGxhYmVsU2VsZWN0aW9uIGFzIGFueSlcbiAgICAgICAgICAgIC5hdHRyKFxuICAgICAgICAgICAgICAgIFwidHJhbnNmb3JtXCIsXG4gICAgICAgICAgICAgICAgKGQsIGkpID0+XG4gICAgICAgICAgICAgICAgICAgIGB0cmFuc2xhdGUoJHt0aGlzLnhUcmFuc2xhdGUoZCwgaSl9LCAke3RoaXMueVRyYW5zbGF0ZShcbiAgICAgICAgICAgICAgICAgICAgICAgIGQsXG4gICAgICAgICAgICAgICAgICAgICAgICBpXG4gICAgICAgICAgICAgICAgICAgICl9KWBcbiAgICAgICAgICAgIClcbiAgICAgICAgICAgIC5hdHRyKFwidGl0bGVcIiwgKGQsIGkpID0+IGZvcm1hdHRlcihkYXRhW2ldLnZhbHVlKSlcbiAgICAgICAgICAgIC5zdHlsZShcInRleHQtYW5jaG9yXCIsIChkKSA9PiB0aGlzLmdldFRleHRBbmNob3IoKSlcbiAgICAgICAgICAgIC5zdHlsZShcImRvbWluYW50LWJhc2VsaW5lXCIsIChkKSA9PiB0aGlzLmdldEFsaWdubWVudEJhc2VsaW5lKCkpXG4gICAgICAgICAgICAudGV4dCgoZCwgaSkgPT4gZm9ybWF0dGVyKGRhdGFbaV0udmFsdWUpKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHhUcmFuc2xhdGUgPSAoZDogYW55LCBpOiBudW1iZXIpID0+IHtcbiAgICAgICAgaWYgKHRoaXMuaXNIb3Jpem9udGFsKSB7XG4gICAgICAgICAgICBjb25zdCB0aHJlc2hvbGRzU2VyaWVzID0gdGhpc1xuICAgICAgICAgICAgICAgIC50aHJlc2hvbGRzU2VyaWVzIGFzIElEYXRhU2VyaWVzPElBY2Nlc3NvcnM+O1xuICAgICAgICAgICAgY29uc3QgdmFsdWUgPSB0aGlzLnRocmVzaG9sZHNTZXJpZXM/LmFjY2Vzc29ycz8uZGF0YT8udmFsdWU/LihcbiAgICAgICAgICAgICAgICBkLFxuICAgICAgICAgICAgICAgIGksXG4gICAgICAgICAgICAgICAgdGhyZXNob2xkc1Nlcmllcz8uZGF0YSBhcyBhbnlbXSxcbiAgICAgICAgICAgICAgICB0aHJlc2hvbGRzU2VyaWVzXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMudGhyZXNob2xkc1Nlcmllcz8uc2NhbGVzLnguY29udmVydCh2YWx1ZSk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcy5nZXRMYWJlbE9mZnNldCgpO1xuICAgIH07XG5cbiAgICBwcml2YXRlIHlUcmFuc2xhdGUgPSAoZDogYW55LCBpOiBudW1iZXIpID0+IHtcbiAgICAgICAgaWYgKHRoaXMuaXNIb3Jpem9udGFsKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5nZXRMYWJlbE9mZnNldCgpO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgdGhyZXNob2xkc1NlcmllcyA9IHRoaXNcbiAgICAgICAgICAgIC50aHJlc2hvbGRzU2VyaWVzIGFzIElEYXRhU2VyaWVzPElBY2Nlc3NvcnM+O1xuICAgICAgICBjb25zdCB2YWx1ZSA9IHRoaXMudGhyZXNob2xkc1Nlcmllcz8uYWNjZXNzb3JzPy5kYXRhPy52YWx1ZT8uKFxuICAgICAgICAgICAgZCxcbiAgICAgICAgICAgIGksXG4gICAgICAgICAgICB0aHJlc2hvbGRzU2VyaWVzPy5kYXRhIGFzIGFueVtdLFxuICAgICAgICAgICAgdGhyZXNob2xkc1Nlcmllc1xuICAgICAgICApO1xuICAgICAgICByZXR1cm4gdGhpcy50aHJlc2hvbGRzU2VyaWVzPy5zY2FsZXMueS5jb252ZXJ0KHZhbHVlKTtcbiAgICB9O1xuXG4gICAgcHJpdmF0ZSBnZXRMYWJlbE9mZnNldCgpIHtcbiAgICAgICAgbGV0IGxhYmVsU3RhcnQgPSAwO1xuICAgICAgICBpZiAoIXRoaXMuY29uZmlnLmZsaXBwZWRMYWJlbHMpIHtcbiAgICAgICAgICAgIGNvbnN0IGdyaWREaW1lbnNpb25zID0gdGhpcy5jaGFydC5nZXRHcmlkKCkuY29uZmlnKCkuZGltZW5zaW9uO1xuICAgICAgICAgICAgbGFiZWxTdGFydCA9IHRoaXMuaXNIb3Jpem9udGFsXG4gICAgICAgICAgICAgICAgPyBncmlkRGltZW5zaW9ucy5oZWlnaHQoKVxuICAgICAgICAgICAgICAgIDogZ3JpZERpbWVuc2lvbnMud2lkdGgoKTtcbiAgICAgICAgfVxuICAgICAgICBsZXQgcGFkZGluZyA9IHRoaXMuY29uZmlnLnBhZGRpbmcgYXMgbnVtYmVyO1xuICAgICAgICBwYWRkaW5nID0gdGhpcy5jb25maWcuZmxpcHBlZExhYmVscyA/IC1wYWRkaW5nIDogcGFkZGluZztcbiAgICAgICAgcmV0dXJuIGxhYmVsU3RhcnQgKyBwYWRkaW5nO1xuICAgIH1cblxuICAgIHByaXZhdGUgZ2V0VGV4dEFuY2hvcigpOiBzdHJpbmcge1xuICAgICAgICBpZiAodGhpcy5pc0hvcml6b250YWwpIHtcbiAgICAgICAgICAgIHJldHVybiBcIm1pZGRsZVwiO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXMuY29uZmlnLmZsaXBwZWRMYWJlbHMgPyBcImVuZFwiIDogXCJzdGFydFwiO1xuICAgIH1cblxuICAgIHByaXZhdGUgZ2V0QWxpZ25tZW50QmFzZWxpbmUoKTogc3RyaW5nIHtcbiAgICAgICAgaWYgKHRoaXMuaXNIb3Jpem9udGFsKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5jb25maWcuZmxpcHBlZExhYmVscyA/IFwidGV4dC1hZnRlci1lZGdlXCIgOiBcImhhbmdpbmdcIjtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBcImNlbnRyYWxcIjtcbiAgICB9XG59XG4iXX0=