@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
156 lines • 24.7 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 cloneDeep from "lodash/cloneDeep";
import { INTERACTION_DATA_POINTS_EVENT, MOUSE_ACTIVE_EVENT, } from "../../constants";
import { XYGridConfig } from "../../core/grid/config/xy-grid-config";
import { Chart } from "../chart";
import { ChartAssist } from "./chart-assist";
import { ChartPalette } from "../common/palette/chart-palette";
import { CHART_MARKERS, CHART_PALETTE_CS1 } from "../common/palette/palettes";
import { SequentialChartMarkerProvider } from "../common/palette/sequential-chart-marker-provider";
import { InteractionType, } from "../common/types";
import { UtilityService } from "../common/utility.service";
import { sparkChartGridConfig } from "../grid/config/spark-chart-grid-config";
import { XYGrid } from "../grid/xy-grid";
import { InteractionLabelPlugin } from "../plugins/interaction/interaction-label-plugin";
import { InteractionLinePlugin } from "../plugins/interaction/interaction-line-plugin";
/**
* Chart assist implementation to be used with spark charts
*/
export class SparkChartAssist {
showBottomAxis;
showTopBorder;
palette;
markers;
/** Collection of ISpark objects */
sparks = [];
/** Used for keeping tabs on the legend's active state */
isLegendActive = false;
/** Grid config for all sparks except the last (bottom) one */
gridConfig;
/** Grid config for the last (bottom) spark */
lastGridConfig;
highlightedDataPoints = {};
constructor(showBottomAxis = true, showTopBorder = true, palette = new ChartPalette(CHART_PALETTE_CS1), markers = new SequentialChartMarkerProvider(CHART_MARKERS)) {
this.showBottomAxis = showBottomAxis;
this.showTopBorder = showTopBorder;
this.palette = palette;
this.markers = markers;
this.gridConfig = sparkChartGridConfig(new XYGridConfig(), false, showTopBorder);
this.gridConfig.interactionPlugins = false;
this.lastGridConfig = sparkChartGridConfig(new XYGridConfig(), showBottomAxis, showTopBorder);
this.lastGridConfig.interactionPlugins = false;
}
/**
* Use this method to update the set of sparks if they all consist of only one series.
* If one or more sparks has multiple series use the updateSparks method instead.
*
* See {@link IChartAssist#update}
*/
update(inputSeriesSet) {
const sparks = inputSeriesSet.map((chartSeries) => ({
id: chartSeries.id,
chartSeriesSet: [chartSeries],
}));
this.updateSparks(sparks);
}
/**
* Use this method to update the set of sparks if any of them consist of more than one series.
*
* @param {ISpark<IAccessors>[]} sparks The collection of sparks to update
*/
updateSparks(sparks) {
const inputSparks = cloneDeep(sparks);
this.sparks = inputSparks.map((spark, index) => {
const lastSpark = index === inputSparks.length - 1;
const existingSparkIndex = spark.id
? this.sparks.findIndex((existingSpark) => existingSpark.id === spark.id)
: -1;
if (existingSparkIndex !== -1) {
spark.chart = this.reconfigureChart(this.sparks[existingSparkIndex].chart, lastSpark);
}
else {
spark.chart = spark.chart || this.createChart(lastSpark);
spark.id = spark.id || UtilityService.uuid();
}
spark.chart.update(spark.chartSeriesSet);
return spark;
});
}
/** See {@link IChartAssist#getHighlightedValue} */
getHighlightedValue(chartSeries, scaleKey, formatterName) {
return ChartAssist.getLabel(chartSeries, this.highlightedDataPoints[chartSeries.id], scaleKey, formatterName);
}
/**
* To use the for-cycle trackBy, set the id value on each spark
* and assign this function to the ngFor trackBy property
*/
trackByFn(_index, spark) {
return spark?.id;
}
setRenderState(_seriesId, _state) {
// not used
}
getVisibleSeriesWithLegend() {
return [];
}
createChart(lastSpark) {
const grid = new XYGrid(lastSpark ? this.lastGridConfig : this.gridConfig);
const chart = new Chart(grid);
if (this.showTopBorder || this.showBottomAxis) {
chart.addPlugin(new InteractionLinePlugin());
}
if (lastSpark && this.showBottomAxis) {
chart.addPlugin(new InteractionLabelPlugin());
}
this.configureEventSubscriptions(chart.getEventBus());
return chart;
}
configureEventSubscriptions(eventBus) {
eventBus.getStream(INTERACTION_DATA_POINTS_EVENT).subscribe((event) => {
if (event.data.interactionType === InteractionType.MouseMove) {
const dataPoints = event.data.dataPoints;
Object.keys(dataPoints).forEach((seriesId) => {
this.highlightedDataPoints[seriesId] = Object.assign({}, dataPoints[seriesId]);
});
}
});
eventBus.getStream(MOUSE_ACTIVE_EVENT).subscribe((event) => {
this.isLegendActive = event.data;
});
}
reconfigureChart(chart, lastSpark) {
chart
.getGrid()
.config(lastSpark ? this.lastGridConfig : this.gridConfig);
chart.updateDimensions();
const hasInteractionLabel = chart.hasPlugin(InteractionLabelPlugin);
if (lastSpark && !hasInteractionLabel && this.showBottomAxis) {
const labelPlugin = new InteractionLabelPlugin();
chart.addPlugin(labelPlugin);
labelPlugin.initialize();
}
else if (!lastSpark && hasInteractionLabel) {
chart.removePlugin(InteractionLabelPlugin);
}
return chart;
}
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3BhcmstY2hhcnQtYXNzaXN0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL2NvcmUvY2hhcnQtYXNzaXN0cy9zcGFyay1jaGFydC1hc3Npc3QudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEseURBQXlEO0FBQ3pELEVBQUU7QUFDRiwrRUFBK0U7QUFDL0UsNEVBQTRFO0FBQzVFLDhFQUE4RTtBQUM5RSwrRUFBK0U7QUFDL0UsOEVBQThFO0FBQzlFLDREQUE0RDtBQUM1RCxFQUFFO0FBQ0YsNkVBQTZFO0FBQzdFLHVEQUF1RDtBQUN2RCxFQUFFO0FBQ0YsNkVBQTZFO0FBQzdFLDRFQUE0RTtBQUM1RSwrRUFBK0U7QUFDL0UsMEVBQTBFO0FBQzFFLGlGQUFpRjtBQUNqRiw2RUFBNkU7QUFDN0UsaUJBQWlCO0FBRWpCLE9BQU8sU0FBUyxNQUFNLGtCQUFrQixDQUFDO0FBRXpDLE9BQU8sRUFDSCw2QkFBNkIsRUFDN0Isa0JBQWtCLEdBQ3JCLE1BQU0saUJBQWlCLENBQUM7QUFDekIsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLHVDQUF1QyxDQUFDO0FBRXJFLE9BQU8sRUFBRSxLQUFLLEVBQUUsTUFBTSxVQUFVLENBQUM7QUFDakMsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBRzdDLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQztBQUMvRCxPQUFPLEVBQUUsYUFBYSxFQUFFLGlCQUFpQixFQUFFLE1BQU0sNEJBQTRCLENBQUM7QUFDOUUsT0FBTyxFQUFFLDZCQUE2QixFQUFFLE1BQU0sb0RBQW9ELENBQUM7QUFDbkcsT0FBTyxFQVFILGVBQWUsR0FFbEIsTUFBTSxpQkFBaUIsQ0FBQztBQUN6QixPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFDM0QsT0FBTyxFQUFFLG9CQUFvQixFQUFFLE1BQU0sd0NBQXdDLENBQUM7QUFDOUUsT0FBTyxFQUFF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U0FBUyxJQUFJLENBQUMsbUJBQW1CLElBQUksSUFBSSxDQUFDLGNBQWMsRUFBRTtZQUMxRCxNQUFNLFdBQVcsR0FBRyxJQUFJLHNCQUFzQixFQUFFLENBQUM7WUFDakQsS0FBSyxDQUFDLFNBQVMsQ0FBQyxXQUFXLENBQUMsQ0FBQztZQUM3QixXQUFXLENBQUMsVUFBVSxFQUFFLENBQUM7U0FDNUI7YUFBTSxJQUFJLENBQUMsU0FBUyxJQUFJLG1CQUFtQixFQUFFO1lBQzFDLEtBQUssQ0FBQyxZQUFZLENBQUMsc0JBQXNCLENBQUMsQ0FBQztTQUM5QztRQUVELE9BQU8sS0FBSyxDQUFDO0lBQ2pCLENBQUM7Q0FDSiIsInNvdXJjZXNDb250ZW50IjpbIi8vIMKpIDIwMjIgU29sYXJXaW5kcyBXb3JsZHdpZGUsIExMQy4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vXG4vLyBQZXJtaXNzaW9uIGlzIGhlcmVieSBncmFudGVkLCBmcmVlIG9mIGNoYXJnZSwgdG8gYW55IHBlcnNvbiBvYnRhaW5pbmcgYSBjb3B5XG4vLyAgb2YgdGhpcyBzb2Z0d2FyZSBhbmQgYXNzb2NpYXRlZCBkb2N1bWVudGF0aW9uIGZpbGVzICh0aGUgXCJTb2Z0d2FyZVwiKSwgdG9cbi8vICBkZWFsIGluIHRoZSBTb2Z0d2FyZSB3aXRob3V0IHJlc3RyaWN0aW9uLCBpbmNsdWRpbmcgd2l0aG91dCBsaW1pdGF0aW9uIHRoZVxuLy8gIHJpZ2h0cyB0byB1c2UsIGNvcHksIG1vZGlmeSwgbWVyZ2UsIHB1Ymxpc2gsIGRpc3RyaWJ1dGUsIHN1YmxpY2Vuc2UsIGFuZC9vclxuLy8gIHNlbGwgY29waWVzIG9mIHRoZSBTb2Z0d2FyZSwgYW5kIHRvIHBlcm1pdCBwZXJzb25zIHRvIHdob20gdGhlIFNvZnR3YXJlIGlzXG4vLyAgZnVybmlzaGVkIHRvIGRvIHNvLCBzdWJqZWN0IHRvIHRoZSBmb2xsb3dpbmcgY29uZGl0aW9uczpcbi8vXG4vLyBUaGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSBhbmQgdGhpcyBwZXJtaXNzaW9uIG5vdGljZSBzaGFsbCBiZSBpbmNsdWRlZCBpblxuLy8gIGFsbCBjb3BpZXMgb3Igc3Vic3RhbnRpYWwgcG9ydGlvbnMgb2YgdGhlIFNvZnR3YXJlLlxuLy9cbi8vIFRIRSBTT0ZUV0FSRSBJUyBQUk9WSURFRCBcIkFTIElTXCIsIFdJVEhPVVQgV0FSUkFOVFkgT0YgQU5ZIEtJTkQsIEVYUFJFU1MgT1Jcbi8vICBJTVBMSUVELCBJTkNMVURJTkcgQlVUIE5PVCBMSU1JVEVEIFRPIFRIRSBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWSxcbi8vICBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBTkQgTk9OSU5GUklOR0VNRU5ULiBJTiBOTyBFVkVOVCBTSEFMTCBUSEVcbi8vICBBVVRIT1JTIE9SIENPUFlSSUdIVCBIT0xERVJTIEJFIExJQUJMRSBGT1IgQU5ZIENMQUlNLCBEQU1BR0VTIE9SIE9USEVSXG4vLyAgTElBQklMSVRZLCBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgVE9SVCBPUiBPVEhFUldJU0UsIEFSSVNJTkcgRlJPTSxcbi8vICBPVVQgT0YgT1IgSU4gQ09OTkVDVElPTiBXSVRIIFRIRSBTT0ZUV0FSRSBPUiBUSEUgVVNFIE9SIE9USEVSIERFQUxJTkdTIElOXG4vLyAgVEhFIFNPRlRXQVJFLlxuXG5pbXBvcnQgY2xvbmVEZWVwIGZyb20gXCJsb2Rhc2gvY2xvbmVEZWVwXCI7XG5cbmltcG9ydCB7XG4gICAgSU5URVJBQ1RJT05fREFUQV9QT0lOVFNfRVZFTlQsXG4gICAgTU9VU0VfQUNUSVZFX0VWRU5ULFxufSBmcm9tIFwiLi4vLi4vY29uc3RhbnRzXCI7XG5pbXBvcnQgeyBYWUdyaWRDb25maWcgfSBmcm9tIFwiLi4vLi4vY29yZS9ncmlkL2NvbmZpZy94eS1ncmlkLWNvbmZpZ1wiO1xuaW1wb3J0IHsgUmVuZGVyU3RhdGUgfSBmcm9tIFwiLi4vLi4vcmVuZGVyZXJzL3R5cGVzXCI7XG5pbXBvcnQgeyBDaGFydCB9IGZyb20gXCIuLi9jaGFydFwiO1xuaW1wb3J0IHsgQ2hhcnRBc3Npc3QgfSBmcm9tIFwiLi9jaGFydC1hc3Npc3RcIjtcbmltcG9ydCB7IElDaGFydEFzc2lzdCwgSVNwYXJrIH0gZnJvbSBcIi4vdHlwZXNcIjtcbmltcG9ydCB7IEV2ZW50QnVzIH0gZnJvbSBcIi4uL2NvbW1vbi9ldmVudC1idXNcIjtcbmltcG9ydCB7IENoYXJ0UGFsZXR0ZSB9IGZyb20gXCIuLi9jb21tb24vcGFsZXR0ZS9jaGFydC1wYWxldHRlXCI7XG5pbXBvcnQgeyBDSEFSVF9NQVJLRVJTLCBDSEFSVF9QQUxFVFRFX0NTMSB9IGZyb20gXCIuLi9jb21tb24vcGFsZXR0ZS9wYWxldHRlc1wiO1xuaW1wb3J0IHsgU2VxdWVudGlhbENoYXJ0TWFya2VyUHJvdmlkZXIgfSBmcm9tIFwiLi4vY29tbW9uL3BhbGV0dGUvc2VxdWVudGlhbC1jaGFydC1tYXJrZXItcHJvdmlkZXJcIjtcbmltcG9ydCB7XG4gICAgSUFjY2Vzc29ycyxcbiAgICBJQ2hhcnRBc3Npc3RTZXJpZXMsXG4gICAgSUNoYXJ0RXZlbnQsXG4gICAgSUNoYXJ0TWFya2VyLFxuICAgIElDaGFydFBhbGV0dGUsXG4gICAgSUNoYXJ0U2VyaWVzLFxuICAgIElEYXRhUG9pbnRzUGF5bG9hZCxcbiAgICBJbnRlcmFjdGlvblR5cGUsXG4gICAgSVZhbHVlUHJvdmlkZXIsXG59IGZyb20gXCIuLi9jb21tb24vdHlwZXNcIjtcbmltcG9ydCB7IFV0aWxpdHlTZXJ2aWNlIH0gZnJvbSBcIi4uL2NvbW1vbi91dGlsaXR5LnNlcnZpY2VcIjtcbmltcG9ydCB7IHNwYXJrQ2hhcnRHcmlkQ29uZmlnIH0gZnJvbSBcIi4uL2dyaWQvY29uZmlnL3NwYXJrLWNoYXJ0LWdyaWQtY29uZmlnXCI7XG5pbXBvcnQgeyBYWUdyaWQgfSBmcm9tIFwiLi4vZ3JpZC94eS1ncmlkXCI7XG5pbXBvcnQgeyBJbnRlcmFjdGlvbkxhYmVsUGx1Z2luIH0gZnJvbSBcIi4uL3BsdWdpbnMvaW50ZXJhY3Rpb24vaW50ZXJhY3Rpb24tbGFiZWwtcGx1Z2luXCI7XG5pbXBvcnQgeyBJbnRlcmFjdGlvbkxpbmVQbHVnaW4gfSBmcm9tIFwiLi4vcGx1Z2lucy9pbnRlcmFjdGlvbi9pbnRlcmFjdGlvbi1saW5lLXBsdWdpblwiO1xuXG4vKipcbiAqIENoYXJ0IGFzc2lzdCBpbXBsZW1lbnRhdGlvbiB0byBiZSB1c2VkIHdpdGggc3BhcmsgY2hhcnRzXG4gKi9cbmV4cG9ydCBjbGFzcyBTcGFya0NoYXJ0QXNzaXN0IGltcGxlbWVudHMgSUNoYXJ0QXNzaXN0IHtcbiAgICAvKiogQ29sbGVjdGlvbiBvZiBJU3Bhcmsgb2JqZWN0cyAqL1xuICAgIHB1YmxpYyBzcGFya3M6IElTcGFyazxJQWNjZXNzb3JzPltdID0gW107XG4gICAgLyoqIFVzZWQgZm9yIGtlZXBpbmcgdGFicyBvbiB0aGUgbGVnZW5kJ3MgYWN0aXZlIHN0YXRlICovXG4gICAgcHVibGljIGlzTGVnZW5kQWN0aXZlID0gZmFsc2U7XG4gICAgLyoqIEdyaWQgY29uZmlnIGZvciBhbGwgc3BhcmtzIGV4Y2VwdCB0aGUgbGFzdCAoYm90dG9tKSBvbmUgKi9cbiAgICBwdWJsaWMgcmVhZG9ubHkgZ3JpZENvbmZpZzogWFlHcmlkQ29uZmlnO1xuICAgIC8qKiBHcmlkIGNvbmZpZyBmb3IgdGhlIGxhc3QgKGJvdHRvbSkgc3BhcmsgKi9cbiAgICBwdWJsaWMgcmVhZG9ubHkgbGFzdEdyaWRDb25maWc6IFhZR3JpZENvbmZpZztcblxuICAgIHB1YmxpYyBoaWdobGlnaHRlZERhdGFQb2ludHM6IElEYXRhUG9pbnRzUGF5bG9hZCA9IHt9O1xuXG4gICAgY29uc3RydWN0b3IoXG4gICAgICAgIHB1YmxpYyByZWFkb25seSBzaG93Qm90dG9tQXhpcyA9IHRydWUsXG4gICAgICAgIHB1YmxpYyByZWFkb25seSBzaG93VG9wQm9yZGVyID0gdHJ1ZSxcbiAgICAgICAgcHVibGljIHBhbGV0dGU6IElDaGFydFBhbGV0dGUgPSBuZXcgQ2hhcnRQYWxldHRlKENIQVJUX1BBTEVUVEVfQ1MxKSxcbiAgICAgICAgcHVibGljIG1hcmtlcnM6IElWYWx1ZVByb3ZpZGVyPElDaGFydE1hcmtlcj4gPSBuZXcgU2VxdWVudGlhbENoYXJ0TWFya2VyUHJvdmlkZXIoXG4gICAgICAgICAgICBDSEFSVF9NQVJLRVJTXG4gICAgICAgIClcbiAgICApIHtcbiAgICAgICAgdGhpcy5ncmlkQ29uZmlnID0gc3BhcmtDaGFydEdyaWRDb25maWcoXG4gICAgICAgICAgICBuZXcgWFlHcmlkQ29uZmlnKCksXG4gICAgICAgICAgICBmYWxzZSxcbiAgICAgICAgICAgIHNob3dUb3BCb3JkZXJcbiAgICAgICAgKTtcbiAgICAgICAgdGhpcy5ncmlkQ29uZmlnLmludGVyYWN0aW9uUGx1Z2lucyA9IGZhbHNlO1xuXG4gICAgICAgIHRoaXMubGFzdEdyaWRDb25maWcgPSBzcGFya0NoYXJ0R3JpZENvbmZpZyhcbiAgICAgICAgICAgIG5ldyBYWUdyaWRDb25maWcoKSxcbiAgICAgICAgICAgIHNob3dCb3R0b21BeGlzLFxuICAgICAgICAgICAgc2hvd1RvcEJvcmRlclxuICAgICAgICApO1xuICAgICAgICB0aGlzLmxhc3RHcmlkQ29uZmlnLmludGVyYWN0aW9uUGx1Z2lucyA9IGZhbHNlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFVzZSB0aGlzIG1ldGhvZCB0byB1cGRhdGUgdGhlIHNldCBvZiBzcGFya3MgaWYgdGhleSBhbGwgY29uc2lzdCBvZiBvbmx5IG9uZSBzZXJpZXMuXG4gICAgICogSWYgb25lIG9yIG1vcmUgc3BhcmtzIGhhcyBtdWx0aXBsZSBzZXJpZXMgdXNlIHRoZSB1cGRhdGVTcGFya3MgbWV0aG9kIGluc3RlYWQuXG4gICAgICpcbiAgICAgKiBTZWUge0BsaW5rIElDaGFydEFzc2lzdCN1cGRhdGV9XG4gICAgICovXG4gICAgcHVibGljIHVwZGF0ZShpbnB1dFNlcmllc1NldDogSUNoYXJ0QXNzaXN0U2VyaWVzPElBY2Nlc3NvcnM+W10pOiB2b2lkIHtcbiAgICAgICAgY29uc3Qgc3BhcmtzID0gaW5wdXRTZXJpZXNTZXQubWFwKChjaGFydFNlcmllcykgPT4gKHtcbiAgICAgICAgICAgIGlkOiBjaGFydFNlcmllcy5pZCxcbiAgICAgICAgICAgIGNoYXJ0U2VyaWVzU2V0OiBbY2hhcnRTZXJpZXNdLFxuICAgICAgICB9KSk7XG4gICAgICAgIHRoaXMudXBkYXRlU3BhcmtzKHNwYXJrcyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVXNlIHRoaXMgbWV0aG9kIHRvIHVwZGF0ZSB0aGUgc2V0IG9mIHNwYXJrcyBpZiBhbnkgb2YgdGhlbSBjb25zaXN0IG9mIG1vcmUgdGhhbiBvbmUgc2VyaWVzLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtJU3Bhcms8SUFjY2Vzc29ycz5bXX0gc3BhcmtzIFRoZSBjb2xsZWN0aW9uIG9mIHNwYXJrcyB0byB1cGRhdGVcbiAgICAgKi9cbiAgICBwdWJsaWMgdXBkYXRlU3BhcmtzKHNwYXJrczogSVNwYXJrPElBY2Nlc3NvcnM+W10pOiB2b2lkIHtcbiAgICAgICAgY29uc3QgaW5wdXRTcGFya3MgPSBjbG9uZURlZXAoc3BhcmtzKTtcbiAgICAgICAgdGhpcy5zcGFya3MgPSBpbnB1dFNwYXJrcy5tYXAoKHNwYXJrLCBpbmRleCk6IElTcGFyazxJQWNjZXNzb3JzPiA9PiB7XG4gICAgICAgICAgICBjb25zdCBsYXN0U3BhcmsgPSBpbmRleCA9PT0gaW5wdXRTcGFya3MubGVuZ3RoIC0gMTtcbiAgICAgICAgICAgIGNvbnN0IGV4aXN0aW5nU3BhcmtJbmRleCA9IHNwYXJrLmlkXG4gICAgICAgICAgICAgICAgPyB0aGlzLnNwYXJrcy5maW5kSW5kZXgoXG4gICAgICAgICAgICAgICAgICAgICAgKGV4aXN0aW5nU3BhcmspID0+IGV4aXN0aW5nU3BhcmsuaWQgPT09IHNwYXJrLmlkXG4gICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgOiAtMTtcbiAgICAgICAgICAgIGlmIChleGlzdGluZ1NwYXJrSW5kZXggIT09IC0xKSB7XG4gICAgICAgICAgICAgICAgc3BhcmsuY2hhcnQgPSB0aGlzLnJlY29uZmlndXJlQ2hhcnQoXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc3BhcmtzW2V4aXN0aW5nU3BhcmtJbmRleF0uY2hhcnQgYXMgQ2hhcnQsXG4gICAgICAgICAgICAgICAgICAgIGxhc3RTcGFya1xuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHNwYXJrLmNoYXJ0ID0gc3BhcmsuY2hhcnQgfHwgdGhpcy5jcmVhdGVDaGFydChsYXN0U3BhcmspO1xuICAgICAgICAgICAgICAgIHNwYXJrLmlkID0gc3BhcmsuaWQgfHwgVXRpbGl0eVNlcnZpY2UudXVpZCgpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBzcGFyay5jaGFydC51cGRhdGUoc3BhcmsuY2hhcnRTZXJpZXNTZXQpO1xuXG4gICAgICAgICAgICByZXR1cm4gc3Bhcms7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKiBTZWUge0BsaW5rIElDaGFydEFzc2lzdCNnZXRIaWdobGlnaHRlZFZhbHVlfSAqL1xuICAgIHB1YmxpYyBnZXRIaWdobGlnaHRlZFZhbHVlKFxuICAgICAgICBjaGFydFNlcmllczogSUNoYXJ0U2VyaWVzPElBY2Nlc3NvcnM+LFxuICAgICAgICBzY2FsZUtleTogc3RyaW5nLFxuICAgICAgICBmb3JtYXR0ZXJOYW1lPzogc3RyaW5nXG4gICAgKTogc3RyaW5nIHwgbnVtYmVyIHtcbiAgICAgICAgcmV0dXJuIENoYXJ0QXNzaXN0LmdldExhYmVsKFxuICAgICAgICAgICAgY2hhcnRTZXJpZXMsXG4gICAgICAgICAgICB0aGlzLmhpZ2hsaWdodGVkRGF0YVBvaW50c1tjaGFydFNlcmllcy5pZF0sXG4gICAgICAgICAgICBzY2FsZUtleSxcbiAgICAgICAgICAgIGZvcm1hdHRlck5hbWVcbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUbyB1c2UgdGhlIGZvci1jeWNsZSB0cmFja0J5LCBzZXQgdGhlIGlkIHZhbHVlIG9uIGVhY2ggc3BhcmtcbiAgICAgKiBhbmQgYXNzaWduIHRoaXMgZnVuY3Rpb24gdG8gdGhlIG5nRm9yIHRyYWNrQnkgcHJvcGVydHlcbiAgICAgKi9cbiAgICBwdWJsaWMgdHJhY2tCeUZuKFxuICAgICAgICBfaW5kZXg6IG51bWJlcixcbiAgICAgICAgc3Bhcms6IElTcGFyazxJQWNjZXNzb3JzPlxuICAgICk6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gICAgICAgIHJldHVybiBzcGFyaz8uaWQ7XG4gICAgfVxuXG4gICAgcHVibGljIHNldFJlbmRlclN0YXRlKF9zZXJpZXNJZDogc3RyaW5nLCBfc3RhdGU6IFJlbmRlclN0YXRlKTogdm9pZCB7XG4gICAgICAgIC8vIG5vdCB1c2VkXG4gICAgfVxuXG4gICAgcHVibGljIGdldFZpc2libGVTZXJpZXNXaXRoTGVnZW5kKCk6IElDaGFydEFzc2lzdFNlcmllczxJQWNjZXNzb3JzPltdIHtcbiAgICAgICAgcmV0dXJuIFtdO1xuICAgIH1cblxuICAgIHByb3RlY3RlZCBjcmVhdGVDaGFydChsYXN0U3Bhcms6IGJvb2xlYW4pOiBDaGFydCB7XG4gICAgICAgIGNvbnN0IGdyaWQgPSBuZXcgWFlHcmlkKFxuICAgICAgICAgICAgbGFzdFNwYXJrID8gdGhpcy5sYXN0R3JpZENvbmZpZyA6IHRoaXMuZ3JpZENvbmZpZ1xuICAgICAgICApO1xuICAgICAgICBjb25zdCBjaGFydCA9IG5ldyBDaGFydChncmlkKTtcblxuICAgICAgICBpZiAodGhpcy5zaG93VG9wQm9yZGVyIHx8IHRoaXMuc2hvd0JvdHRvbUF4aXMpIHtcbiAgICAgICAgICAgIGNoYXJ0LmFkZFBsdWdpbihuZXcgSW50ZXJhY3Rpb25MaW5lUGx1Z2luKCkpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChsYXN0U3BhcmsgJiYgdGhpcy5zaG93Qm90dG9tQXhpcykge1xuICAgICAgICAgICAgY2hhcnQuYWRkUGx1Z2luKG5ldyBJbnRlcmFjdGlvbkxhYmVsUGx1Z2luKCkpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5jb25maWd1cmVFdmVudFN1YnNjcmlwdGlvbnMoY2hhcnQuZ2V0RXZlbnRCdXMoKSk7XG5cbiAgICAgICAgcmV0dXJuIGNoYXJ0O1xuICAgIH1cblxuICAgIHByaXZhdGUgY29uZmlndXJlRXZlbnRTdWJzY3JpcHRpb25zKGV2ZW50QnVzOiBFdmVudEJ1czxJQ2hhcnRFdmVudD4pOiB2b2lkIHtcbiAgICAgICAgZXZlbnRCdXMuZ2V0U3RyZWFtKElOVEVSQUNUSU9OX0RBVEFfUE9JTlRTX0VWRU5UKS5zdWJzY3JpYmUoKGV2ZW50KSA9PiB7XG4gICAgICAgICAgICBpZiAoZXZlbnQuZGF0YS5pbnRlcmFjdGlvblR5cGUgPT09IEludGVyYWN0aW9uVHlwZS5Nb3VzZU1vdmUpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBkYXRhUG9pbnRzID0gPElEYXRhUG9pbnRzUGF5bG9hZD5ldmVudC5kYXRhLmRhdGFQb2ludHM7XG4gICAgICAgICAgICAgICAgT2JqZWN0LmtleXMoZGF0YVBvaW50cykuZm9yRWFjaCgoc2VyaWVzSWQpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5oaWdobGlnaHRlZERhdGFQb2ludHNbc2VyaWVzSWRdID0gT2JqZWN0LmFzc2lnbihcbiAgICAgICAgICAgICAgICAgICAgICAgIHt9LFxuICAgICAgICAgICAgICAgICAgICAgICAgZGF0YVBvaW50c1tzZXJpZXNJZF1cbiAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIGV2ZW50QnVzLmdldFN0cmVhbShNT1VTRV9BQ1RJVkVfRVZFTlQpLnN1YnNjcmliZSgoZXZlbnQpID0+IHtcbiAgICAgICAgICAgIHRoaXMuaXNMZWdlbmRBY3RpdmUgPSBldmVudC5kYXRhO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHJlY29uZmlndXJlQ2hhcnQoY2hhcnQ6IENoYXJ0LCBsYXN0U3Bhcms6IGJvb2xlYW4pOiBDaGFydCB7XG4gICAgICAgIGNoYXJ0XG4gICAgICAgICAgICAuZ2V0R3JpZCgpXG4gICAgICAgICAgICAuY29uZmlnKGxhc3RTcGFyayA/IHRoaXMubGFzdEdyaWRDb25maWcgOiB0aGlzLmdyaWRDb25maWcpO1xuICAgICAgICBjaGFydC51cGRhdGVEaW1lbnNpb25zKCk7XG5cbiAgICAgICAgY29uc3QgaGFzSW50ZXJhY3Rpb25MYWJlbCA9IGNoYXJ0Lmhhc1BsdWdpbihJbnRlcmFjdGlvbkxhYmVsUGx1Z2luKTtcbiAgICAgICAgaWYgKGxhc3RTcGFyayAmJiAhaGFzSW50ZXJhY3Rpb25MYWJlbCAmJiB0aGlzLnNob3dCb3R0b21BeGlzKSB7XG4gICAgICAgICAgICBjb25zdCBsYWJlbFBsdWdpbiA9IG5ldyBJbnRlcmFjdGlvbkxhYmVsUGx1Z2luKCk7XG4gICAgICAgICAgICBjaGFydC5hZGRQbHVnaW4obGFiZWxQbHVnaW4pO1xuICAgICAgICAgICAgbGFiZWxQbHVnaW4uaW5pdGlhbGl6ZSgpO1xuICAgICAgICB9IGVsc2UgaWYgKCFsYXN0U3BhcmsgJiYgaGFzSW50ZXJhY3Rpb25MYWJlbCkge1xuICAgICAgICAgICAgY2hhcnQucmVtb3ZlUGx1Z2luKEludGVyYWN0aW9uTGFiZWxQbHVnaW4pO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGNoYXJ0O1xuICAgIH1cbn1cbiJdfQ==