angular-google-charts
Version:
A wrapper for the Google Charts library written with Angular
209 lines • 30.9 kB
JavaScript
import { ChangeDetectionStrategy, Component, ElementRef, EventEmitter, Input, Optional, Output } from '@angular/core';
import { fromEvent, ReplaySubject } from 'rxjs';
import { debounceTime } from 'rxjs/operators';
import { getPackageForChart } from '../../helpers/chart.helper';
import { DataTableService } from '../../services/data-table.service';
import { ScriptLoaderService } from '../../services/script-loader.service';
import { ChartType } from '../../types/chart-type';
import { DashboardComponent } from '../dashboard/dashboard.component';
import * as i0 from "@angular/core";
import * as i1 from "../../services/script-loader.service";
import * as i2 from "../../services/data-table.service";
import * as i3 from "../dashboard/dashboard.component";
export class GoogleChartComponent {
constructor(element, scriptLoaderService, dataTableService, dashboard) {
this.element = element;
this.scriptLoaderService = scriptLoaderService;
this.dataTableService = dataTableService;
this.dashboard = dashboard;
/**
* The chart-specific options. All options listen in the Google Charts documentation applying
* to the chart type specified can be used here.
*/
this.options = {};
/**
* If this is set to `true`, the chart will be redrawn if the browser window is resized.
* Defaults to `false` and should only be used when specifying the width or height of the chart
* in percent.
*
* Note that this can impact performance.
*/
this.dynamicResize = false;
this.ready = new EventEmitter();
this.error = new EventEmitter();
this.select = new EventEmitter();
this.mouseover = new EventEmitter();
this.mouseleave = new EventEmitter();
this.wrapperReadySubject = new ReplaySubject(1);
this.initialized = false;
this.eventListeners = new Map();
}
get chart() {
return this.chartWrapper.getChart();
}
get wrapperReady$() {
return this.wrapperReadySubject.asObservable();
}
get chartWrapper() {
if (!this.wrapper) {
throw new Error('Trying to access the chart wrapper before it was fully initialized');
}
return this.wrapper;
}
set chartWrapper(wrapper) {
this.wrapper = wrapper;
this.drawChart();
}
ngOnInit() {
// We don't need to load any chart packages, the chart wrapper will handle this for us
this.scriptLoaderService.loadChartPackages(getPackageForChart(this.type)).subscribe(() => {
this.dataTable = this.dataTableService.create(this.data, this.columns, this.formatters);
// Only ever create the wrapper once to allow animations to happen when something changes.
this.wrapper = new google.visualization.ChartWrapper({
container: this.element.nativeElement,
chartType: this.type,
dataTable: this.dataTable,
options: this.mergeOptions()
});
this.registerChartEvents();
this.wrapperReadySubject.next(this.wrapper);
this.initialized = true;
this.drawChart();
});
}
ngOnChanges(changes) {
if (changes.dynamicResize) {
this.updateResizeListener();
}
if (this.initialized) {
let shouldRedraw = false;
if (changes.data || changes.columns || changes.formatters) {
this.dataTable = this.dataTableService.create(this.data, this.columns, this.formatters);
this.wrapper.setDataTable(this.dataTable);
shouldRedraw = true;
}
if (changes.type) {
this.wrapper.setChartType(this.type);
shouldRedraw = true;
}
if (changes.options || changes.width || changes.height || changes.title) {
this.wrapper.setOptions(this.mergeOptions());
shouldRedraw = true;
}
if (shouldRedraw) {
this.drawChart();
}
}
}
ngOnDestroy() {
this.unsubscribeToResizeIfSubscribed();
}
/**
* For listening to events other than the most common ones (available via Output properties).
*
* Can be called after the chart emits that it's "ready".
*
* Returns a handle that can be used for `removeEventListener`.
*/
addEventListener(eventName, callback) {
const handle = this.registerChartEvent(this.chart, eventName, callback);
this.eventListeners.set(handle, { eventName, callback, handle });
return handle;
}
removeEventListener(handle) {
const entry = this.eventListeners.get(handle);
if (entry) {
google.visualization.events.removeListener(entry.handle);
this.eventListeners.delete(handle);
}
}
updateResizeListener() {
this.unsubscribeToResizeIfSubscribed();
if (this.dynamicResize) {
this.resizeSubscription = fromEvent(window, 'resize', { passive: true })
.pipe(debounceTime(100))
.subscribe(() => {
if (this.initialized) {
this.drawChart();
}
});
}
}
unsubscribeToResizeIfSubscribed() {
if (this.resizeSubscription != null) {
this.resizeSubscription.unsubscribe();
this.resizeSubscription = undefined;
}
}
mergeOptions() {
return {
title: this.title,
width: this.width,
height: this.height,
...this.options
};
}
registerChartEvents() {
google.visualization.events.removeAllListeners(this.wrapper);
this.registerChartEvent(this.wrapper, 'ready', () => {
// This could also be done by checking if we already subscribed to the events
google.visualization.events.removeAllListeners(this.chart);
this.registerChartEvent(this.chart, 'onmouseover', (event) => this.mouseover.emit(event));
this.registerChartEvent(this.chart, 'onmouseout', (event) => this.mouseleave.emit(event));
this.registerChartEvent(this.chart, 'select', () => {
const selection = this.chart.getSelection();
this.select.emit({ selection });
});
this.eventListeners.forEach(x => (x.handle = this.registerChartEvent(this.chart, x.eventName, x.callback)));
this.ready.emit({ chart: this.chart });
});
this.registerChartEvent(this.wrapper, 'error', (error) => this.error.emit(error));
}
registerChartEvent(object, eventName, callback) {
return google.visualization.events.addListener(object, eventName, callback);
}
drawChart() {
if (this.dashboard != null) {
// If this chart is part of a dashboard, the dashboard takes care of drawing
return;
}
this.wrapper.draw();
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: GoogleChartComponent, deps: [{ token: i0.ElementRef }, { token: i1.ScriptLoaderService }, { token: i2.DataTableService }, { token: i3.DashboardComponent, optional: true }], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: GoogleChartComponent, selector: "google-chart", inputs: { type: "type", data: "data", columns: "columns", title: "title", width: "width", height: "height", options: "options", formatters: "formatters", dynamicResize: "dynamicResize" }, outputs: { ready: "ready", error: "error", select: "select", mouseover: "mouseover", mouseleave: "mouseleave" }, host: { classAttribute: "google-chart" }, exportAs: ["googleChart"], usesOnChanges: true, ngImport: i0, template: '', isInline: true, styles: [":host{width:-moz-fit-content;width:fit-content;display:block}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: GoogleChartComponent, decorators: [{
type: Component,
args: [{ selector: 'google-chart', template: '', host: { class: 'google-chart' }, exportAs: 'googleChart', changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{width:-moz-fit-content;width:fit-content;display:block}\n"] }]
}], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: i1.ScriptLoaderService }, { type: i2.DataTableService }, { type: i3.DashboardComponent, decorators: [{
type: Optional
}] }]; }, propDecorators: { type: [{
type: Input
}], data: [{
type: Input
}], columns: [{
type: Input
}], title: [{
type: Input
}], width: [{
type: Input
}], height: [{
type: Input
}], options: [{
type: Input
}], formatters: [{
type: Input
}], dynamicResize: [{
type: Input
}], ready: [{
type: Output
}], error: [{
type: Output
}], select: [{
type: Output
}], mouseover: [{
type: Output
}], mouseleave: [{
type: Output
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ29vZ2xlLWNoYXJ0LmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL2FuZ3VsYXItZ29vZ2xlLWNoYXJ0cy9zcmMvbGliL2NvbXBvbmVudHMvZ29vZ2xlLWNoYXJ0L2dvb2dsZS1jaGFydC5jb21wb25lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUNMLHVCQUF1QixFQUN2QixTQUFTLEVBQ1QsVUFBVSxFQUNWLFlBQVksRUFDWixLQUFLLEVBSUwsUUFBUSxFQUNSLE1BQU0sRUFFUCxNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQUUsU0FBUyxFQUFjLGFBQWEsRUFBZ0IsTUFBTSxNQUFNLENBQUM7QUFDMUUsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBRTlDLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBQ2hFLE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLG1DQUFtQyxDQUFDO0FBQ3JFLE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxNQUFNLHNDQUFzQyxDQUFDO0FBQzNFLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQVVuRCxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSxrQ0FBa0MsQ0FBQzs7Ozs7QUFVdEUsTUFBTSxPQUFPLG9CQUFvQjtJQWlHL0IsWUFDVSxPQUFtQixFQUNuQixtQkFBd0MsRUFDeEMsZ0JBQWtDLEVBQ3RCLFNBQThCO1FBSDFDLFlBQU8sR0FBUCxPQUFPLENBQVk7UUFDbkIsd0JBQW1CLEdBQW5CLG1CQUFtQixDQUFxQjtRQUN4QyxxQkFBZ0IsR0FBaEIsZ0JBQWdCLENBQWtCO1FBQ3RCLGNBQVMsR0FBVCxTQUFTLENBQXFCO1FBckRwRDs7O1dBR0c7UUFFSSxZQUFPLEdBQVcsRUFBRSxDQUFDO1FBVzVCOzs7Ozs7V0FNRztRQUVJLGtCQUFhLEdBQUcs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SUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQztJQUNyRyxDQUFDO0lBRU8sa0JBQWtCLENBQUMsTUFBVyxFQUFFLFNBQWlCLEVBQUUsUUFBa0I7UUFDM0UsT0FBTyxNQUFNLENBQUMsYUFBYSxDQUFDLE1BQU0sQ0FBQyxXQUFXLENBQUMsTUFBTSxFQUFFLFNBQVMsRUFBRSxRQUFRLENBQUMsQ0FBQztJQUM5RSxDQUFDO0lBRU8sU0FBUztRQUNmLElBQUksSUFBSSxDQUFDLFNBQVMsSUFBSSxJQUFJLEVBQUU7WUFDMUIsNEVBQTRFO1lBQzVFLE9BQU87U0FDUjtRQUVELElBQUksQ0FBQyxPQUFRLENBQUMsSUFBSSxFQUFFLENBQUM7SUFDdkIsQ0FBQzsrR0F0UVUsb0JBQW9CO21HQUFwQixvQkFBb0IsMmJBTnJCLEVBQUU7OzRGQU1ELG9CQUFvQjtrQkFSaEMsU0FBUzsrQkFDRSxjQUFjLFlBQ2QsRUFBRSxRQUVOLEVBQUUsS0FBSyxFQUFFLGNBQWMsRUFBRSxZQUNyQixhQUFhLG1CQUNOLHVCQUF1QixDQUFDLE1BQU07OzBCQXVHNUMsUUFBUTs0Q0FoR0osSUFBSTtzQkFEVixLQUFLO2dCQVNDLElBQUk7c0JBRFYsS0FBSztnQkFVQyxPQUFPO3NCQURiLEtBQUs7Z0JBU0MsS0FBSztzQkFEWCxLQUFLO2dCQVNDLEtBQUs7c0JBRFgsS0FBSztnQkFTQyxNQUFNO3NCQURaLEtBQUs7Z0JBUUMsT0FBTztzQkFEYixLQUFLO2dCQVVDLFVBQVU7c0JBRGhCLEtBQUs7Z0JBV0MsYUFBYTtzQkFEbkIsS0FBSztnQkFJQyxLQUFLO3NCQURYLE1BQU07Z0JBSUEsS0FBSztzQkFEWCxNQUFNO2dCQUlBLE1BQU07c0JBRFosTUFBTTtnQkFJQSxTQUFTO3NCQURmLE1BQU07Z0JBSUEsVUFBVTtzQkFEaEIsTUFBTSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIENoYW5nZURldGVjdGlvblN0cmF0ZWd5LFxuICBDb21wb25lbnQsXG4gIEVsZW1lbnRSZWYsXG4gIEV2ZW50RW1pdHRlcixcbiAgSW5wdXQsXG4gIE9uQ2hhbmdlcyxcbiAgT25EZXN0cm95LFxuICBPbkluaXQsXG4gIE9wdGlvbmFsLFxuICBPdXRwdXQsXG4gIFNpbXBsZUNoYW5nZXNcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBmcm9tRXZlbnQsIE9ic2VydmFibGUsIFJlcGxheVN1YmplY3QsIFN1YnNjcmlwdGlvbiB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgZGVib3VuY2VUaW1lIH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuXG5pbXBvcnQgeyBnZXRQYWNrYWdlRm9yQ2hhcnQgfSBmcm9tICcuLi8uLi9oZWxwZXJzL2NoYXJ0LmhlbHBlcic7XG5pbXBvcnQgeyBEYXRhVGFibGVTZXJ2aWNlIH0gZnJvbSAnLi4vLi4vc2VydmljZXMvZGF0YS10YWJsZS5zZXJ2aWNlJztcbmltcG9ydCB7IFNjcmlwdExvYWRlclNlcnZpY2UgfSBmcm9tICcuLi8uLi9zZXJ2aWNlcy9zY3JpcHQtbG9hZGVyLnNlcnZpY2UnO1xuaW1wb3J0IHsgQ2hhcnRUeXBlIH0gZnJvbSAnLi4vLi4vdHlwZXMvY2hhcnQtdHlwZSc7XG5pbXBvcnQge1xuICBDaGFydEVycm9yRXZlbnQsXG4gIENoYXJ0TW91c2VMZWF2ZUV2ZW50LFxuICBDaGFydE1vdXNlT3ZlckV2ZW50LFxuICBDaGFydFJlYWR5RXZlbnQsXG4gIENoYXJ0U2VsZWN0aW9uQ2hhbmdlZEV2ZW50XG59IGZyb20gJy4uLy4uL3R5cGVzL2V2ZW50cyc7XG5pbXBvcnQgeyBGb3JtYXR0ZXIgfSBmcm9tICcuLi8uLi90eXBlcy9mb3JtYXR0ZXInO1xuaW1wb3J0IHsgQ2hhcnRCYXNlLCBDb2x1bW4sIFJvdyB9IGZyb20gJy4uL2NoYXJ0LWJhc2UvY2hhcnQtYmFzZS5jb21wb25lbnQnO1xuaW1wb3J0IHsgRGFzaGJvYXJkQ29tcG9uZW50IH0gZnJvbSAnLi4vZGFzaGJvYXJkL2Rhc2hib2FyZC5jb21wb25lbnQnO1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdnb29nbGUtY2hhcnQnLFxuICB0ZW1wbGF0ZTogJycsXG4gIHN0eWxlczogWyc6aG9zdCB7IHdpZHRoOiBmaXQtY29udGVudDsgZGlzcGxheTogYmxvY2s7IH0nXSxcbiAgaG9zdDogeyBjbGFzczogJ2dvb2dsZS1jaGFydCcgfSxcbiAgZXhwb3J0QXM6ICdnb29nbGVDaGFydCcsXG4gIGNoYW5nZURldGVjdGlvbjogQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3kuT25QdXNoXG59KVxuZXhwb3J0IGNsYXNzIEdvb2dsZUNoYXJ0Q29tcG9uZW50IGltcGxlbWVudHMgQ2hhcnRCYXNlLCBPbkluaXQsIE9uQ2hhbmdlcywgT25EZXN0cm95IHtcbiAgLyoqXG4gICAqIFRoZSB0eXBlIG9mIHRoZSBjaGFydCB0byBjcmVhdGUuXG4gICAqL1xuICBASW5wdXQoKVxuICBwdWJsaWMgdHlwZSE6IENoYXJ0VHlwZTtcblxuICAvKipcbiAgICogRGF0YSB1c2VkIHRvIGluaXRpYWxpemUgdGhlIHRhYmxlLlxuICAgKlxuICAgKiBUaGlzIG11c3QgYWxzbyBjb250YWluIGFsbCByb2xlcyB0aGF0IGFyZSBzZXQgaW4gdGhlIGBjb2x1bW5zYCBwcm9wZXJ0eS5cbiAgICovXG4gIEBJbnB1dCgpXG4gIHB1YmxpYyBkYXRhITogUm93W107XG5cbiAgLyoqXG4gICAqIFRoZSBjb2x1bW5zIHRoZSBgZGF0YWAgY29uc2lzdHMgb2YuXG4gICAqIFRoZSBsZW5ndGggb2YgdGhpcyBhcnJheSBtdXN0IG1hdGNoIHRoZSBsZW5ndGggb2YgZWFjaCByb3cgaW4gdGhlIGBkYXRhYCBvYmplY3QuXG4gICAqXG4gICAqIElmIHtAbGluayBodHRwczovL2RldmVsb3BlcnMuZ29vZ2xlLmNvbS9jaGFydC9pbnRlcmFjdGl2ZS9kb2NzL3JvbGVzIHJvbGVzfSBzaG91bGQgYmUgYXBwbGllZCwgdGhleSBtdXN0IGJlIGluY2x1ZGVkIGluIHRoaXMgYXJyYXkgYXMgd2VsbC5cbiAgICovXG4gIEBJbnB1dCgpXG4gIHB1YmxpYyBjb2x1bW5zPzogQ29sdW1uW107XG5cbiAgLyoqXG4gICAqIEEgY29udmVuaWVuY2UgcHJvcGVydHkgdXNlZCB0byBzZXQgdGhlIHRpdGxlIG9mIHRoZSBjaGFydC5cbiAgICpcbiAgICogVGhpcyBjYW4gYWxzbyBiZSBzZXQgdXNpbmcgYG9wdGlvbnMudGl0bGVgLCB3aGljaCwgaWYgZXhpc3RhbnQsIHdpbGwgb3ZlcndyaXRlIHRoaXMgdmFsdWUuXG4gICAqL1xuICBASW5wdXQoKVxuICBwdWJsaWMgdGl0bGU/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIEEgY29udmVuaWVuY2UgcHJvcGVydHkgdXNlZCB0byBzZXQgdGhlIHdpZHRoIG9mIHRoZSBjaGFydCBpbiBwaXhlbHMuXG4gICAqXG4gICAqIFRoaXMgY2FuIGFsc28gYmUgc2V0IHVzaW5nIGBvcHRpb25zLndpZHRoYCwgd2hpY2gsIGlmIGV4aXN0YW50LCB3aWxsIG92ZXJ3cml0ZSB0aGlzIHZhbHVlLlxuICAgKi9cbiAgQElucHV0KClcbiAgcHVibGljIHdpZHRoPzogbnVtYmVyO1xuXG4gIC8qKlxuICAgKiBBIGNvbnZlbmllbmNlIHByb3BlcnR5IHVzZWQgdG8gc2V0IHRoZSBoZWlnaHQgb2YgdGhlIGNoYXJ0IGluIHBpeGVscy5cbiAgICpcbiAgICogVGhpcyBjYW4gYWxzbyBiZSBzZXQgdXNpbmcgYG9wdGlvbnMuaGVpZ2h0YCwgd2hpY2gsIGlmIGV4aXN0YW50LCB3aWxsIG92ZXJ3cml0ZSB0aGlzIHZhbHVlLlxuICAgKi9cbiAgQElucHV0KClcbiAgcHVibGljIGhlaWdodD86IG51bWJlcjtcblxuICAvKipcbiAgICogVGhlIGNoYXJ0LXNwZWNpZmljIG9wdGlvbnMuIEFsbCBvcHRpb25zIGxpc3RlbiBpbiB0aGUgR29vZ2xlIENoYXJ0cyBkb2N1bWVudGF0aW9uIGFwcGx5aW5nXG4gICAqIHRvIHRoZSBjaGFydCB0eXBlIHNwZWNpZmllZCBjYW4gYmUgdXNlZCBoZXJlLlxuICAgKi9cbiAgQElucHV0KClcbiAgcHVibGljIG9wdGlvbnM6IG9iamVjdCA9IHt9O1xuXG4gIC8qKlxuICAgKiBVc2VkIHRvIGNoYW5nZSB0aGUgZGlzcGxheWVkIHZhbHVlIG9mIHRoZSBzcGVjaWZpZWQgY29sdW1uIGluIGFsbCByb3dzLlxuICAgKlxuICAgKiBFYWNoIGFycmF5IGVsZW1lbnQgbXVzdCBjb25zaXN0IG9mIGFuIGluc3RhbmNlIG9mIGEgW2Bmb3JtYXR0ZXJgXShodHRwczovL2RldmVsb3BlcnMuZ29vZ2xlLmNvbS9jaGFydC9pbnRlcmFjdGl2ZS9kb2NzL3JlZmVyZW5jZSNmb3JtYXR0ZXJzKVxuICAgKiBhbmQgdGhlIGluZGV4IG9mIHRoZSBjb2x1bW4geW91IHdhbnQgdGhlIGZvcm1hdHRlciB0byBnZXQgYXBwbGllZCB0by5cbiAgICovXG4gIEBJbnB1dCgpXG4gIHB1YmxpYyBmb3JtYXR0ZXJzPzogRm9ybWF0dGVyW107XG5cbiAgLyoqXG4gICAqIElmIHRoaXMgaXMgc2V0IHRvIGB0cnVlYCwgdGhlIGNoYXJ0IHdpbGwgYmUgcmVkcmF3biBpZiB0aGUgYnJvd3NlciB3aW5kb3cgaXMgcmVzaXplZC5cbiAgICogRGVmYXVsdHMgdG8gYGZhbHNlYCBhbmQgc2hvdWxkIG9ubHkgYmUgdXNlZCB3aGVuIHNwZWNpZnlpbmcgdGhlIHdpZHRoIG9yIGhlaWdodCBvZiB0aGUgY2hhcnRcbiAgICogaW4gcGVyY2VudC5cbiAgICpcbiAgICogTm90ZSB0aGF0IHRoaXMgY2FuIGltcGFjdCBwZXJmb3JtYW5jZS5cbiAgICovXG4gIEBJbnB1dCgpXG4gIHB1YmxpYyBkeW5hbWljUmVzaXplID0gZmFsc2U7XG5cbiAgQE91dHB1dCgpXG4gIHB1YmxpYyByZWFkeSA9IG5ldyBFdmVudEVtaXR0ZXI8Q2hhcnRSZWFkeUV2ZW50PigpO1xuXG4gIEBPdXRwdXQoKVxuICBwdWJsaWMgZXJyb3IgPSBuZXcgRXZlbnRFbWl0dGVyPENoYXJ0RXJyb3JFdmVudD4oKTtcblxuICBAT3V0cHV0KClcbiAgcHVibGljIHNlbGVjdCA9IG5ldyBFdmVudEVtaXR0ZXI8Q2hhcnRTZWxlY3Rpb25DaGFuZ2VkRXZlbnQ+KCk7XG5cbiAgQE91dHB1dCgpXG4gIHB1YmxpYyBtb3VzZW92ZXIgPSBuZXcgRXZlbnRFbWl0dGVyPENoYXJ0TW91c2VPdmVyRXZlbnQ+KCk7XG5cbiAgQE91dHB1dCgpXG4gIHB1YmxpYyBtb3VzZWxlYXZlID0gbmV3IEV2ZW50RW1pdHRlcjxDaGFydE1vdXNlTGVhdmVFdmVudD4oKTtcblxuICBwcml2YXRlIHJlc2l6ZVN1YnNjcmlwdGlvbj86IFN1YnNjcmlwdGlvbjtcblxuICBwcml2YXRlIGRhdGFUYWJsZTogZ29vZ2xlLnZpc3VhbGl6YXRpb24uRGF0YVRhYmxlIHwgdW5kZWZpbmVkO1xuICBwcml2YXRlIHdyYXBwZXI6IGdvb2dsZS52aXN1YWxpemF0aW9uLkNoYXJ0V3JhcHBlciB8IHVuZGVmaW5lZDtcbiAgcHJpdmF0ZSB3cmFwcGVyUmVhZHlTdWJqZWN0ID0gbmV3IFJlcGxheVN1YmplY3Q8Z29vZ2xlLnZpc3VhbGl6YXRpb24uQ2hhcnRXcmFwcGVyPigxKTtcbiAgcHJpdmF0ZSBpbml0aWFsaXplZCA9IGZhbHNlO1xuICBwcml2YXRlIGV2ZW50TGlzdGVuZXJzID0gbmV3IE1hcDxhbnksIHsgZXZlbnROYW1lOiBzdHJpbmc7IGNhbGxiYWNrOiBGdW5jdGlvbjsgaGFuZGxlOiBhbnkgfT4oKTtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIGVsZW1lbnQ6IEVsZW1lbnRSZWYsXG4gICAgcHJpdmF0ZSBzY3JpcHRMb2FkZXJTZXJ2aWNlOiBTY3JpcHRMb2FkZXJTZXJ2aWNlLFxuICAgIHByaXZhdGUgZGF0YVRhYmxlU2VydmljZTogRGF0YVRhYmxlU2VydmljZSxcbiAgICBAT3B0aW9uYWwoKSBwcml2YXRlIGRhc2hib2FyZD86IERhc2hib2FyZENvbXBvbmVudFxuICApIHt9XG5cbiAgcHVibGljIGdldCBjaGFydCgpOiBnb29nbGUudmlzdWFsaXphdGlvbi5DaGFydEJhc2UgfCBudWxsIHtcbiAgICByZXR1cm4gdGhpcy5jaGFydFdyYXBwZXIuZ2V0Q2hhcnQoKTtcbiAgfVxuXG4gIHB1YmxpYyBnZXQgd3JhcHBlclJlYWR5JCgpOiBPYnNlcnZhYmxlPGdvb2dsZS52aXN1YWxpemF0aW9uLkNoYXJ0V3JhcHBlcj4ge1xuICAgIHJldHVybiB0aGlzLndyYXBwZXJSZWFkeVN1YmplY3QuYXNPYnNlcnZhYmxlKCk7XG4gIH1cblxuICBwdWJsaWMgZ2V0IGNoYXJ0V3JhcHBlcigpOiBnb29nbGUudmlzdWFsaXphdGlvbi5DaGFydFdyYXBwZXIge1xuICAgIGlmICghdGhpcy53cmFwcGVyKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ1RyeWluZyB0byBhY2Nlc3MgdGhlIGNoYXJ0IHdyYXBwZXIgYmVmb3JlIGl0IHdhcyBmdWxseSBpbml0aWFsaXplZCcpO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzLndyYXBwZXI7XG4gIH1cblxuICBwdWJsaWMgc2V0IGNoYXJ0V3JhcHBlcih3cmFwcGVyOiBnb29nbGUudmlzdWFsaXphdGlvbi5DaGFydFdyYXBwZXIpIHtcbiAgICB0aGlzLndyYXBwZXIgPSB3cmFwcGVyO1xuICAgIHRoaXMuZHJhd0NoYXJ0KCk7XG4gIH1cblxuICBwdWJsaWMgbmdPbkluaXQoKSB7XG4gICAgLy8gV2UgZG9uJ3QgbmVlZCB0byBsb2FkIGFueSBjaGFydCBwYWNrYWdlcywgdGhlIGNoYXJ0IHdyYXBwZXIgd2lsbCBoYW5kbGUgdGhpcyBmb3IgdXNcbiAgICB0aGlzLnNjcmlwdExvYWRlclNlcnZpY2UubG9hZENoYXJ0UGFja2FnZXMoZ2V0UGFja2FnZUZvckNoYXJ0KHRoaXMudHlwZSkpLnN1YnNjcmliZSgoKSA9PiB7XG4gICAgICB0aGlzLmRhdGFUYWJsZSA9IHRoaXMuZGF0YVRhYmxlU2VydmljZS5jcmVhdGUodGhpcy5kYXRhLCB0aGlzLmNvbHVtbnMsIHRoaXMuZm9ybWF0dGVycyk7XG5cbiAgICAgIC8vIE9ubHkgZXZlciBjcmVhdGUgdGhlIHdyYXBwZXIgb25jZSB0byBhbGxvdyBhbmltYXRpb25zIHRvIGhhcHBlbiB3aGVuIHNvbWV0aGluZyBjaGFuZ2VzLlxuICAgICAgdGhpcy53cmFwcGVyID0gbmV3IGdvb2dsZS52aXN1YWxpemF0aW9uLkNoYXJ0V3JhcHBlcih7XG4gICAgICAgIGNvbnRhaW5lcjogdGhpcy5lbGVtZW50Lm5hdGl2ZUVsZW1lbnQsXG4gICAgICAgIGNoYXJ0VHlwZTogdGhpcy50eXBlLFxuICAgICAgICBkYXRhVGFibGU6IHRoaXMuZGF0YVRhYmxlLFxuICAgICAgICBvcHRpb25zOiB0aGlzLm1lcmdlT3B0aW9ucygpXG4gICAgICB9KTtcblxuICAgICAgdGhpcy5yZWdpc3RlckNoYXJ0RXZlbnRzKCk7XG5cbiAgICAgIHRoaXMud3JhcHBlclJlYWR5U3ViamVjdC5uZXh0KHRoaXMud3JhcHBlcik7XG4gICAgICB0aGlzLmluaXRpYWxpemVkID0gdHJ1ZTtcblxuICAgICAgdGhpcy5kcmF3Q2hhcnQoKTtcbiAgICB9KTtcbiAgfVxuXG4gIHB1YmxpYyBuZ09uQ2hhbmdlcyhjaGFuZ2VzOiBTaW1wbGVDaGFuZ2VzKSB7XG4gICAgaWYgKGNoYW5nZXMuZHluYW1pY1Jlc2l6ZSkge1xuICAgICAgdGhpcy51cGRhdGVSZXNpemVMaXN0ZW5lcigpO1xuICAgIH1cblxuICAgIGlmICh0aGlzLmluaXRpYWxpemVkKSB7XG4gICAgICBsZXQgc2hvdWxkUmVkcmF3ID0gZmFsc2U7XG4gICAgICBpZiAoY2hhbmdlcy5kYXRhIHx8IGNoYW5nZXMuY29sdW1ucyB8fCBjaGFuZ2VzLmZvcm1hdHRlcnMpIHtcbiAgICAgICAgdGhpcy5kYXRhVGFibGUgPSB0aGlzLmRhdGFUYWJsZVNlcnZpY2UuY3JlYXRlKHRoaXMuZGF0YSwgdGhpcy5jb2x1bW5zLCB0aGlzLmZvcm1hdHRlcnMpO1xuICAgICAgICB0aGlzLndyYXBwZXIhLnNldERhdGFUYWJsZSh0aGlzLmRhdGFUYWJsZSEpO1xuICAgICAgICBzaG91bGRSZWRyYXcgPSB0cnVlO1xuICAgICAgfVxuXG4gICAgICBpZiAoY2hhbmdlcy50eXBlKSB7XG4gICAgICAgIHRoaXMud3JhcHBlciEuc2V0Q2hhcnRUeXBlKHRoaXMudHlwZSk7XG4gICAgICAgIHNob3VsZFJlZHJhdyA9IHRydWU7XG4gICAgICB9XG5cbiAgICAgIGlmIChjaGFuZ2VzLm9wdGlvbnMgfHwgY2hhbmdlcy53aWR0aCB8fCBjaGFuZ2VzLmhlaWdodCB8fCBjaGFuZ2VzLnRpdGxlKSB7XG4gICAgICAgIHRoaXMud3JhcHBlciEuc2V0T3B0aW9ucyh0aGlzLm1lcmdlT3B0aW9ucygpKTtcbiAgICAgICAgc2hvdWxkUmVkcmF3ID0gdHJ1ZTtcbiAgICAgIH1cblxuICAgICAgaWYgKHNob3VsZFJlZHJhdykge1xuICAgICAgICB0aGlzLmRyYXdDaGFydCgpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHB1YmxpYyBuZ09uRGVzdHJveSgpOiB2b2lkIHtcbiAgICB0aGlzLnVuc3Vic2NyaWJlVG9SZXNpemVJZlN1YnNjcmliZWQoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBGb3IgbGlzdGVuaW5nIHRvIGV2ZW50cyBvdGhlciB0aGFuIHRoZSBtb3N0IGNvbW1vbiBvbmVzIChhdmFpbGFibGUgdmlhIE91dHB1dCBwcm9wZXJ0aWVzKS5cbiAgICpcbiAgICogQ2FuIGJlIGNhbGxlZCBhZnRlciB0aGUgY2hhcnQgZW1pdHMgdGhhdCBpdCdzIFwicmVhZHlcIi5cbiAgICpcbiAgICogUmV0dXJucyBhIGhhbmRsZSB0aGF0IGNhbiBiZSB1c2VkIGZvciBgcmVtb3ZlRXZlbnRMaXN0ZW5lcmAuXG4gICAqL1xuICBwdWJsaWMgYWRkRXZlbnRMaXN0ZW5lcihldmVudE5hbWU6IHN0cmluZywgY2FsbGJhY2s6IEZ1bmN0aW9uKTogYW55IHtcbiAgICBjb25zdCBoYW5kbGUgPSB0aGlzLnJlZ2lzdGVyQ2hhcnRFdmVudCh0aGlzLmNoYXJ0LCBldmVudE5hbWUsIGNhbGxiYWNrKTtcbiAgICB0aGlzLmV2ZW50TGlzdGVuZXJzLnNldChoYW5kbGUsIHsgZXZlbnROYW1lLCBjYWxsYmFjaywgaGFuZGxlIH0pO1xuICAgIHJldHVybiBoYW5kbGU7XG4gIH1cblxuICBwdWJsaWMgcmVtb3ZlRXZlbnRMaXN0ZW5lcihoYW5kbGU6IGFueSk6IHZvaWQge1xuICAgIGNvbnN0IGVudHJ5ID0gdGhpcy5ldmVudExpc3RlbmVycy5nZXQoaGFuZGxlKTtcbiAgICBpZiAoZW50cnkpIHtcbiAgICAgIGdvb2dsZS52aXN1YWxpemF0aW9uLmV2ZW50cy5yZW1vdmVMaXN0ZW5lcihlbnRyeS5oYW5kbGUpO1xuICAgICAgdGhpcy5ldmVudExpc3RlbmVycy5kZWxldGUoaGFuZGxlKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIHVwZGF0ZVJlc2l6ZUxpc3RlbmVyKCkge1xuICAgIHRoaXMudW5zdWJzY3JpYmVUb1Jlc2l6ZUlmU3Vic2NyaWJlZCgpO1xuXG4gICAgaWYgKHRoaXMuZHluYW1pY1Jlc2l6ZSkge1xuICAgICAgdGhpcy5yZXNpemVTdWJzY3JpcHRpb24gPSBmcm9tRXZlbnQod2luZG93LCAncmVzaXplJywgeyBwYXNzaXZlOiB0cnVlIH0pXG4gICAgICAgIC5waXBlKGRlYm91bmNlVGltZSgxMDApKVxuICAgICAgICAuc3Vic2NyaWJlKCgpID0+IHtcbiAgICAgICAgICBpZiAodGhpcy5pbml0aWFsaXplZCkge1xuICAgICAgICAgICAgdGhpcy5kcmF3Q2hhcnQoKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgdW5zdWJzY3JpYmVUb1Jlc2l6ZUlmU3Vic2NyaWJlZCgpIHtcbiAgICBpZiAodGhpcy5yZXNpemVTdWJzY3JpcHRpb24gIT0gbnVsbCkge1xuICAgICAgdGhpcy5yZXNpemVTdWJzY3JpcHRpb24udW5zdWJzY3JpYmUoKTtcbiAgICAgIHRoaXMucmVzaXplU3Vic2NyaXB0aW9uID0gdW5kZWZpbmVkO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgbWVyZ2VPcHRpb25zKCk6IG9iamVjdCB7XG4gICAgcmV0dXJuIHtcbiAgICAgIHRpdGxlOiB0aGlzLnRpdGxlLFxuICAgICAgd2lkdGg6IHRoaXMud2lkdGgsXG4gICAgICBoZWlnaHQ6IHRoaXMuaGVpZ2h0LFxuICAgICAgLi4udGhpcy5vcHRpb25zXG4gICAgfTtcbiAgfVxuXG4gIHByaXZhdGUgcmVnaXN0ZXJDaGFydEV2ZW50cygpIHtcbiAgICBnb29nbGUudmlzdWFsaXphdGlvbi5ldmVudHMucmVtb3ZlQWxsTGlzdGVuZXJzKHRoaXMud3JhcHBlcik7XG5cbiAgICB0aGlzLnJlZ2lzdGVyQ2hhcnRFdmVudCh0aGlzLndyYXBwZXIsICdyZWFkeScsICgpID0+IHtcbiAgICAgIC8vIFRoaXMgY291bGQgYWxzbyBiZSBkb25lIGJ5IGNoZWNraW5nIGlmIHdlIGFscmVhZHkgc3Vic2NyaWJlZCB0byB0aGUgZXZlbnRzXG4gICAgICBnb29nbGUudmlzdWFsaXphdGlvbi5ldmVudHMucmVtb3ZlQWxsTGlzdGVuZXJzKHRoaXMuY2hhcnQpO1xuICAgICAgdGhpcy5yZWdpc3RlckNoYXJ0RXZlbnQodGhpcy5jaGFydCwgJ29ubW91c2VvdmVyJywgKGV2ZW50OiBDaGFydE1vdXNlT3ZlckV2ZW50KSA9PiB0aGlzLm1vdXNlb3Zlci5lbWl0KGV2ZW50KSk7XG4gICAgICB0aGlzLnJlZ2lzdGVyQ2hhcnRFdmVudCh0aGlzLmNoYXJ0LCAnb25tb3VzZW91dCcsIChldmVudDogQ2hhcnRNb3VzZUxlYXZlRXZlbnQpID0+IHRoaXMubW91c2VsZWF2ZS5lbWl0KGV2ZW50KSk7XG4gICAgICB0aGlzLnJlZ2lzdGVyQ2hhcnRFdmVudCh0aGlzLmNoYXJ0LCAnc2VsZWN0JywgKCkgPT4ge1xuICAgICAgICBjb25zdCBzZWxlY3Rpb24gPSB0aGlzLmNoYXJ0IS5nZXRTZWxlY3Rpb24oKTtcbiAgICAgICAgdGhpcy5zZWxlY3QuZW1pdCh7IHNlbGVjdGlvbiB9KTtcbiAgICAgIH0pO1xuICAgICAgdGhpcy5ldmVudExpc3RlbmVycy5mb3JFYWNoKHggPT4gKHguaGFuZGxlID0gdGhpcy5yZWdpc3RlckNoYXJ0RXZlbnQodGhpcy5jaGFydCwgeC5ldmVudE5hbWUsIHguY2FsbGJhY2spKSk7XG5cbiAgICAgIHRoaXMucmVhZHkuZW1pdCh7IGNoYXJ0OiB0aGlzLmNoYXJ0ISB9KTtcbiAgICB9KTtcblxuICAgIHRoaXMucmVnaXN0ZXJDaGFydEV2ZW50KHRoaXMud3JhcHBlciwgJ2Vycm9yJywgKGVycm9yOiBDaGFydEVycm9yRXZlbnQpID0+IHRoaXMuZXJyb3IuZW1pdChlcnJvcikpO1xuICB9XG5cbiAgcHJpdmF0ZSByZWdpc3RlckNoYXJ0RXZlbnQob2JqZWN0OiBhbnksIGV2ZW50TmFtZTogc3RyaW5nLCBjYWxsYmFjazogRnVuY3Rpb24pOiBhbnkge1xuICAgIHJldHVybiBnb29nbGUudmlzdWFsaXphdGlvbi5ldmVudHMuYWRkTGlzdGVuZXIob2JqZWN0LCBldmVudE5hbWUsIGNhbGxiYWNrKTtcbiAgfVxuXG4gIHByaXZhdGUgZHJhd0NoYXJ0KCkge1xuICAgIGlmICh0aGlzLmRhc2hib2FyZCAhPSBudWxsKSB7XG4gICAgICAvLyBJZiB0aGlzIGNoYXJ0IGlzIHBhcnQgb2YgYSBkYXNoYm9hcmQsIHRoZSBkYXNoYm9hcmQgdGFrZXMgY2FyZSBvZiBkcmF3aW5nXG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdGhpcy53cmFwcGVyIS5kcmF3KCk7XG4gIH1cbn1cbiJdfQ==