sb-dashlets
Version:
A Simple extensible angular library to render JSON data into different chart formats
222 lines • 29.8 kB
JavaScript
import * as tslib_1 from "tslib";
import { Component, Inject, ViewChild } from '@angular/core';
import { DataService } from '../../services/index';
import { BaseChartDirective, ThemeService } from 'ng2-charts';
import { IReportType, ReportState } from '../../types/index';
import { BaseComponent } from '../base/base.component';
import { get, groupBy, mapValues, sumBy, remove } from 'lodash-es';
import { DEFAULT_CONFIG, DASHLET_CONSTANTS } from '../../tokens/index';
import { CHART_DEFAULT_CONFIG } from './defaultConfiguration';
const ɵ0 = CHART_DEFAULT_CONFIG;
/**
* @dynamic
*/
let ChartJsComponent = class ChartJsComponent extends BaseComponent {
constructor(dataService, defaultConfig, CONSTANTS) {
super(dataService);
this.dataService = dataService;
this.CONSTANTS = CONSTANTS;
this.reportType = IReportType.CHART;
this.inputParameters = {};
this.exportOptions = ['png', 'csv', 'jpg'];
this._defaultConfig = defaultConfig;
}
/**
* @description initializes the component with the passed config and data
* @param {InputParams} { config, type, data }
* @return {*} {Promise<any>}
* @memberof ChartJsComponent
*/
initialize({ config, type, data }) {
return tslib_1.__awaiter(this, void 0, void 0, function* () {
if (!(config && type && data))
throw new SyntaxError(this.CONSTANTS.INVALID_INPUT);
this.config = config = Object.assign({}, config, { type });
const fetchedJSON = this.data = yield this.fetchData(data).toPromise().catch(err => []);
this.builder(config, fetchedJSON);
this._isInitialized = true;
this.state.emit(ReportState.DONE);
});
}
/**
* @description It's a high order function responsible for getting labels and datasets, addition and removal of data.
* @private
* @param {string} labelExpr
* @param {IDataset[]} datasets
* @return {*}
* @memberof ChartJsComponent
*/
getLabelsAndDatasetsClosure(labelExpr, datasets) {
return (data) => {
const getDataGroupedByLabelExpr = data => groupBy(data, val => {
const value = get(val, labelExpr);
return value && typeof value === 'string' ? value.toLowerCase().trim() : '';
});
const getLabels = (data) => Object.keys(data);
const getDatasets = (data) => datasets.map(dataset => {
return Object.assign({}, dataset, (dataset.dataExpr && {
data: Object.values(mapValues(data, rows => sumBy(rows, row => +(row[dataset.dataExpr] || 0))))
}));
});
const findDataByLabelPredicate = (label) => (row) => row[labelExpr] === label;
return {
addData(newData) {
data = data.concat(newData);
return this.getData(data);
},
getData(overriddenData) {
data = overriddenData || data;
const groupedData = getDataGroupedByLabelExpr(data);
return {
labels: getLabels(groupedData),
datasets: getDatasets(groupedData)
};
},
removeData(label) {
remove(data, findDataByLabelPredicate(label));
return this.getData(data);
}
};
};
}
/**
* @description prepared the chart data using the configuration passed
* @param {Partial<IChartOptions>} config
* @param {*} data
* @memberof ChartJsComponent
*/
builder(config, data) {
let { labels = [], labelExpr = null, type = null, legend = true, colors = [], datasets = [], options = {} } = config, others = tslib_1.__rest(config, ["labels", "labelExpr", "type", "legend", "colors", "datasets", "options"]);
options = Object.assign({}, others, options);
if (labelExpr) {
this._labelsAndDatasetsClosure = this.getLabelsAndDatasetsClosure(labelExpr, datasets)(data);
const { getData } = this._labelsAndDatasetsClosure;
({ labels, datasets } = getData());
}
this.setChartData({ labels, datasets, options, type, legend, colors });
}
setChartData(config = {}) {
this.inputParameters = Object.assign({}, this._defaultConfig, this.inputParameters, config);
this.$context = { data: this.data, config: this.config, inputParameters: this.inputParameters, exportOptions: this.exportOptions };
}
reset() {
// throw new Error('Method not implemented.');
}
destroy() {
this.baseChartDirective.chart.destroy();
}
ngOnDestroy() {
this.destroy();
}
/**
* @description updates the type, data or Dashlet configuration
* @param {InputParams} input
* @memberof ChartJsComponent
*/
update(input) {
this.checkIfInitialized();
if (!input)
throw new Error(this.CONSTANTS.INVALID_INPUT);
const { type = null, config = {}, data = null } = input;
let labels, datasets;
if (data) {
const { labelExpr, datasets: datasetsConfig } = config;
if (labelExpr || datasets) {
this._labelsAndDatasetsClosure = this.getLabelsAndDatasetsClosure(labelExpr || this.getConfigValue(labelExpr), datasetsConfig || this.getConfigValue(datasets))(data);
}
({ labels, datasets } = this._labelsAndDatasetsClosure.getData(data));
}
this.setChartData(Object.assign({}, config, (type && { type }), (labels && datasets && { labels, datasets })));
this.baseChartDirective.update();
}
addData(data) {
this.checkIfInitialized();
if (!data)
throw new Error(this.CONSTANTS.INVALID_INPUT);
if (this._labelsAndDatasetsClosure) {
data = Array.isArray(data) ? data : [data];
const { labels, datasets } = this._labelsAndDatasetsClosure.addData(data);
this.setChartData({ labels, datasets });
}
}
refreshChart() {
throw new Error(this.CONSTANTS.METHOD_NOT_IMPLEMENTED);
}
/**
* @description Removes data associated with a label
* @param {string} label
* @memberof ChartJsComponent
*/
removeData(label) {
this.checkIfInitialized();
const { labels, datasets } = this._labelsAndDatasetsClosure.removeData(label);
this.setChartData({ labels, datasets });
}
getTelemetry() {
throw new Error(this.CONSTANTS.METHOD_NOT_IMPLEMENTED);
}
getCurrentSelection() {
throw new Error(this.CONSTANTS.METHOD_NOT_IMPLEMENTED);
}
getDatasetAtIndex(index) {
throw new Error(this.CONSTANTS.METHOD_NOT_IMPLEMENTED);
}
onChartClicked(event) {
this.events.emit({
type: 'CLICK',
event
});
}
onChartHovered(event) {
this.events.emit({
type: 'HOVER',
event
});
}
exportAsImage(format = 'jpg') {
const dataUrl = document.getElementById(this.id).toDataURL(`image/${format}`, 1);
const fileName = `image.${format}`;
this._downloadFile(dataUrl, fileName);
}
exportAs(format) {
if (!this.exportOptions.includes(format)) {
throw new Error('given type not supported');
}
switch (format) {
case 'csv': {
this.exportAsCsv();
break;
}
default: {
this.exportAsImage(format);
break;
}
}
}
};
ChartJsComponent.ctorParameters = () => [
{ type: DataService },
{ type: Object, decorators: [{ type: Inject, args: [DEFAULT_CONFIG,] }] },
{ type: undefined, decorators: [{ type: Inject, args: [DASHLET_CONSTANTS,] }] }
];
tslib_1.__decorate([
ViewChild(BaseChartDirective, { static: false })
], ChartJsComponent.prototype, "baseChartDirective", void 0);
ChartJsComponent = tslib_1.__decorate([
Component({
selector: 'sb-chart-js',
template: "<ng-template #defaultFilterTemplate let-context>\n <sb-dashlets-filters [data]=\"context?.data\" [config]=\"context?.config?.filters\"\n (filteredData)=\"update({data: $event})\">\n </sb-dashlets-filters>\n</ng-template>\n\n<ng-container *ngIf=\"$context?.config?.filters\" [ngTemplateOutlet]=\"templateRefs?.filter || defaultFilterTemplate\"\n [ngTemplateOutletContext]=\"{'$implicit': $context}\">\n</ng-container>\n\n<ng-container *ngIf=\"templateRefs?.header && $context\" [ngTemplateOutlet]=\"templateRefs?.header\"\n [ngTemplateOutletContext]=\"{'$implicit': $context}\">\n</ng-container>\n\n<div *ngIf=\"$context?.inputParameters as data\">\n <canvas [id]=\"id\" baseChart width=\"400\" height=\"400\" [datasets]=\"data?.datasets\" [labels]=\"data?.labels\"\n [options]=\"data?.options\" [colors]=\"data?.colors\" [legend]=\"data?.legend\" [chartType]=\"data?.type\"\n (chartClick)=\"onChartClicked($event)\" (chartHover)=\"onChartHovered($event)\"></canvas>\n</div>\n\n<ng-container *ngIf=\"templateRefs?.footer && $context\" [ngTemplateOutlet]=\"templateRefs?.footer\"\n [ngTemplateOutletContext]=\"{'$implicit': $context}\">\n</ng-container>",
providers: [
ThemeService,
{
provide: DEFAULT_CONFIG,
useValue: ɵ0
}
],
styles: [""]
}),
tslib_1.__param(1, Inject(DEFAULT_CONFIG)), tslib_1.__param(2, Inject(DASHLET_CONSTANTS))
], ChartJsComponent);
export { ChartJsComponent };
export { ɵ0 };
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2hhcnQtanMuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6Im5nOi8vc2ItZGFzaGxldHMvIiwic291cmNlcyI6WyJsaWIvY29tcG9uZW50cy9jaGFydC1qcy9jaGFydC1qcy5jb21wb25lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxFQUFhLFNBQVMsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUN4RSxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFDbkQsT0FBTyxFQUFFLGtCQUFrQixFQUFFLFlBQVksRUFBRSxNQUFNLFlBQVksQ0FBQztBQUM5RCxPQUFPLEVBQWUsV0FBVyxFQUFrQyxXQUFXLEVBQUUsTUFBTSxtQkFBbUIsQ0FBQztBQUMxRyxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFFdkQsT0FBTyxFQUFFLEdBQUcsRUFBRSxPQUFPLEVBQUUsU0FBUyxFQUFFLEtBQUssRUFBRSxNQUFNLEVBQUUsTUFBTSxXQUFXLENBQUM7QUFDbkUsT0FBTyxFQUFFLGNBQWMsRUFBRSxpQkFBaUIsRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBQ3ZFLE9BQU8sRUFBRSxvQkFBb0IsRUFBRSxNQUFNLHdCQUF3QixDQUFBO1dBYTdDLG9CQUFvQjtBQVhwQzs7R0FFRztBQWFILElBQWEsZ0JBQWdCLEdBQTdCLE1BQWEsZ0JBQWlCLFNBQVEsYUFBYTtJQVlqRCxZQUFzQixXQUF3QixFQUEwQixhQUFxQixFQUFxQyxTQUF1QjtRQUN2SixLQUFLLENBQUMsV0FBVyxDQUFDLENBQUM7UUFEQyxnQkFBVyxHQUFYLFdBQVcsQ0FBYTtRQUFvRixjQUFTLEdBQVQsU0FBUyxDQUFjO1FBVGhKLGVBQVUsR0FBZ0IsV0FBVyxDQUFDLEtBQUssQ0FBQztRQUs5QyxvQkFBZSxHQUEyQixFQUFFLENBQUM7UUFFN0Msa0JBQWEsR0FBRyxDQUFDLEtBQUssRUFBRSxLQUFLLEVBQUUsS0FB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QUMsTUFBYztRQUNyQixJQUFJLENBQUMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLEVBQUU7WUFDeEMsTUFBTSxJQUFJLEtBQUssQ0FBQywwQkFBMEIsQ0FBQyxDQUFDO1NBQzdDO1FBQ0QsUUFBUSxNQUFNLEVBQUU7WUFDZCxLQUFLLEtBQUssQ0FBQyxDQUFDO2dCQUNWLElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQztnQkFDbkIsTUFBTTthQUNQO1lBQ0QsT0FBTyxDQUFDLENBQUM7Z0JBQ1AsSUFBSSxDQUFDLGFBQWEsQ0FBQyxNQUFNLENBQUMsQ0FBQztnQkFDM0IsTUFBTTthQUNQO1NBQ0Y7SUFDSCxDQUFDO0NBQ0YsQ0FBQTs7WUFoTW9DLFdBQVc7eUNBQUcsTUFBTSxTQUFDLGNBQWM7NENBQTBCLE1BQU0sU0FBQyxpQkFBaUI7O0FBVnRFO0lBQWpELFNBQVMsQ0FBQyxrQkFBa0IsRUFBRSxFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQUUsQ0FBQzs0REFBd0M7QUFGOUUsZ0JBQWdCO0lBWjVCLFNBQVMsQ0FBQztRQUNULFFBQVEsRUFBRSxhQUFhO1FBQ3ZCLDBwQ0FBd0M7UUFFeEMsU0FBUyxFQUFFO1lBQ1QsWUFBWTtZQUNaO2dCQUNFLE9BQU8sRUFBRSxjQUFjO2dCQUN2QixRQUFRLElBQXNCO2FBQy9CO1NBQ0Y7O0tBQ0YsQ0FBQztJQWFpRCxtQkFBQSxNQUFNLENBQUMsY0FBYyxDQUFDLENBQUEsRUFBeUIsbUJBQUEsTUFBTSxDQUFDLGlCQUFpQixDQUFDLENBQUE7R0FaOUcsZ0JBQWdCLENBNE01QjtTQTVNWSxnQkFBZ0IiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDb21wb25lbnQsIEluamVjdCwgT25EZXN0cm95LCBWaWV3Q2hpbGQgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IERhdGFTZXJ2aWNlIH0gZnJvbSAnLi4vLi4vc2VydmljZXMvaW5kZXgnO1xuaW1wb3J0IHsgQmFzZUNoYXJ0RGlyZWN0aXZlLCBUaGVtZVNlcnZpY2UgfSBmcm9tICduZzItY2hhcnRzJztcbmltcG9ydCB7IElucHV0UGFyYW1zLCBJUmVwb3J0VHlwZSwgSURhdGFzZXQsIElDaGFydCwgU3RyaW5nT2JqZWN0LCBSZXBvcnRTdGF0ZSB9IGZyb20gJy4uLy4uL3R5cGVzL2luZGV4JztcbmltcG9ydCB7IEJhc2VDb21wb25lbnQgfSBmcm9tICcuLi9iYXNlL2Jhc2UuY29tcG9uZW50JztcbmltcG9ydCB7IElDaGFydE9wdGlvbnMsIENoYXJ0VHlwZSwgVXBkYXRlSW5wdXRQYXJhbXMgfSBmcm9tICcuLi8uLi90eXBlcy9pbmRleCc7XG5pbXBvcnQgeyBnZXQsIGdyb3VwQnksIG1hcFZhbHVlcywgc3VtQnksIHJlbW92ZSB9IGZyb20gJ2xvZGFzaC1lcyc7XG5pbXBvcnQgeyBERUZBVUxUX0NPTkZJRywgREFTSExFVF9DT05TVEFOVFMgfSBmcm9tICcuLi8uLi90b2tlbnMvaW5kZXgnO1xuaW1wb3J0IHsgQ0hBUlRfREVGQVVMVF9DT05GSUcgfSBmcm9tICcuL2RlZmF1bHRDb25maWd1cmF0aW9uJ1xuXG4vKipcbiAqIEBkeW5hbWljXG4gKi9cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ3NiLWNoYXJ0LWpzJyxcbiAgdGVtcGxhdGVVcmw6ICcuL2NoYXJ0LWpzLmNvbXBvbmVudC5odG1sJyxcbiAgc3R5bGVVcmxzOiBbJy4vY2hhcnQtanMuY29tcG9uZW50LmNzcyddLFxuICBwcm92aWRlcnM6IFtcbiAgICBUaGVtZVNlcnZpY2UsXG4gICAge1xuICAgICAgcHJvdmlkZTogREVGQVVMVF9DT05GSUcsXG4gICAgICB1c2VWYWx1ZTogQ0hBUlRfREVGQVVMVF9DT05GSUdcbiAgICB9XG4gIF1cbn0pXG5leHBvcnQgY2xhc3MgQ2hhcnRKc0NvbXBvbmVudCBleHRlbmRzIEJhc2VDb21wb25lbnQgaW1wbGVtZW50cyBJQ2hhcnQsIE9uRGVzdHJveSB7XG5cbiAgQFZpZXdDaGlsZChCYXNlQ2hhcnREaXJlY3RpdmUsIHsgc3RhdGljOiBmYWxzZSB9KSBiYXNlQ2hhcnREaXJlY3RpdmU6IEJhc2VDaGFydERpcmVjdGl2ZTtcbiAgcmVhZG9ubHkgcmVwb3J0VHlwZTogSVJlcG9ydFR5cGUgPSBJUmVwb3J0VHlwZS5DSEFSVDtcblxuICBwdWJsaWMgX2RlZmF1bHRDb25maWc6IFBhcnRpYWw8SUNoYXJ0T3B0aW9ucz47XG4gIHB1YmxpYyBjb25maWc6IFBhcnRpYWw8SUNoYXJ0T3B0aW9ucz47XG4gIHB1YmxpYyB0eXBlOiBDaGFydFR5cGU7XG4gIHB1YmxpYyBpbnB1dFBhcmFtZXRlcnM6IFBhcnRpYWw8SUNoYXJ0T3B0aW9ucz4gPSB7fTtcbiAgcHVibGljIF9sYWJlbHNBbmREYXRhc2V0c0Nsb3N1cmU6IGFueTtcbiAgcHVibGljIGV4cG9ydE9wdGlvbnMgPSBbJ3BuZycsICdjc3YnLCAnanBnJ107XG5cbiAgY29uc3RydWN0b3IocHJvdGVjdGVkIGRhdGFTZXJ2aWNlOiBEYXRhU2VydmljZSwgQEluamVjdChERUZBVUxUX0NPTkZJRykgZGVmYXVsdENvbmZpZzogb2JqZWN0LCBASW5qZWN0KERBU0hMRVRfQ09OU1RBTlRTKSBwcml2YXRlIENPTlNUQU5UUzogU3RyaW5nT2JqZWN0KSB7XG4gICAgc3VwZXIoZGF0YVNlcnZpY2UpO1xuICAgIHRoaXMuX2RlZmF1bHRDb25maWcgPSBkZWZhdWx0Q29uZmlnO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBpbml0aWFsaXplcyB0aGUgY29tcG9uZW50IHdpdGggdGhlIHBhc3NlZCBjb25maWcgYW5kIGRhdGFcbiAgICogQHBhcmFtIHtJbnB1dFBhcmFtc30geyBjb25maWcsIHR5cGUsIGRhdGEgfVxuICAgKiBAcmV0dXJuIHsqfSAge1Byb21pc2U8YW55Pn1cbiAgICogQG1lbWJlcm9mIENoYXJ0SnNDb21wb25lbnRcbiAgICovXG4gIGFzeW5jIGluaXRpYWxpemUoeyBjb25maWcsIHR5cGUsIGRhdGEgfTogSW5wdXRQYXJhbXMpOiBQcm9taXNlPGFueT4ge1xuICAgIGlmICghKGNvbmZpZyAmJiB0eXBlICYmIGRhdGEpKSB0aHJvdyBuZXcgU3ludGF4RXJyb3IodGhpcy5DT05TVEFOVFMuSU5WQUxJRF9JTlBVVCk7XG4gICAgdGhpcy5jb25maWcgPSBjb25maWcgPSB7IC4uLmNvbmZpZywgdHlwZSB9O1xuICAgIGNvbnN0IGZldGNoZWRKU09OID0gdGhpcy5kYXRhID0gYXdhaXQgdGhpcy5mZXRjaERhdGEoZGF0YSkudG9Qcm9taXNlKCkuY2F0Y2goZXJyID0+IFtdKTtcbiAgICB0aGlzLmJ1aWxkZXIoY29uZmlnLCBmZXRjaGVkSlNPTik7XG4gICAgdGhpcy5faXNJbml0aWFsaXplZCA9IHRydWU7XG4gICAgdGhpcy5zdGF0ZS5lbWl0KFJlcG9ydFN0YXRlLkRPTkUpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBJdCdzIGEgaGlnaCBvcmRlciBmdW5jdGlvbiByZXNwb25zaWJsZSBmb3IgZ2V0dGluZyBsYWJlbHMgYW5kIGRhdGFzZXRzLCBhZGRpdGlvbiBhbmQgcmVtb3ZhbCBvZiBkYXRhLlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gbGFiZWxFeHByXG4gICAqIEBwYXJhbSB7SURhdGFzZXRbXX0gZGF0YXNldHNcbiAgICogQHJldHVybiB7Kn1cbiAgICogQG1lbWJlcm9mIENoYXJ0SnNDb21wb25lbnRcbiAgICovXG4gIHByaXZhdGUgZ2V0TGFiZWxzQW5kRGF0YXNldHNDbG9zdXJlKGxhYmVsRXhwcjogc3RyaW5nLCBkYXRhc2V0czogSURhdGFzZXRbXSkge1xuICAgIHJldHVybiAoZGF0YTogb2JqZWN0W10pID0+IHtcbiAgICAgIGNvbnN0IGdldERhdGFHcm91cGVkQnlMYWJlbEV4cHIgPSBkYXRhID0+IGdyb3VwQnkoZGF0YSwgdmFsID0+IHtcbiAgICAgICAgY29uc3QgdmFsdWUgPSBnZXQodmFsLCBsYWJlbEV4cHIpO1xuICAgICAgICByZXR1cm4gdmFsdWUgJiYgdHlwZW9mIHZhbHVlID09PSAnc3RyaW5nJyA/IHZhbHVlLnRvTG93ZXJDYXNlKCkudHJpbSgpIDogJyc7XG4gICAgICB9KTtcbiAgICAgIGNvbnN0IGdldExhYmVscyA9IChkYXRhOiBvYmplY3QpID0+IE9iamVjdC5rZXlzKGRhdGEpO1xuICAgICAgY29uc3QgZ2V0RGF0YXNldHMgPSAoZGF0YTogb2JqZWN0KSA9PiBkYXRhc2V0cy5tYXAoZGF0YXNldCA9PiB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgLi4uZGF0YXNldCxcbiAgICAgICAgICAuLi4oZGF0YXNldC5kYXRhRXhwciAmJiB7XG4gICAgICAgICAgICBkYXRhOiBPYmplY3QudmFsdWVzKG1hcFZhbHVlcyhkYXRhLCByb3dzID0+IHN1bUJ5KHJvd3MsIHJvdyA9PiArKHJvd1tkYXRhc2V0LmRhdGFFeHByXSB8fCAwKSkpKVxuICAgICAgICAgIH0pXG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgICAgY29uc3QgZmluZERhdGFCeUxhYmVsUHJlZGljYXRlID0gKGxhYmVsOiBzdHJpbmcpID0+IChyb3c6IG9iamVjdCkgPT4gcm93W2xhYmVsRXhwcl0gPT09IGxhYmVsO1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgYWRkRGF0YShuZXdEYXRhOiBvYmplY3RbXSkge1xuICAgICAgICAgIGRhdGEgPSBkYXRhLmNvbmNhdChuZXdEYXRhKTtcbiAgICAgICAgICByZXR1cm4gdGhpcy5nZXREYXRhKGRhdGEpO1xuICAgICAgICB9LFxuICAgICAgICBnZXREYXRhKG92ZXJyaWRkZW5EYXRhPzogb2JqZWN0W10pIHtcbiAgICAgICAgICBkYXRhID0gb3ZlcnJpZGRlbkRhdGEgfHwgZGF0YTtcbiAgICAgICAgICBjb25zdCBncm91cGVkRGF0YSA9IGdldERhdGFHcm91cGVkQnlMYWJlbEV4cHIoZGF0YSk7XG4gICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIGxhYmVsczogZ2V0TGFiZWxzKGdyb3VwZWREYXRhKSxcbiAgICAgICAgICAgIGRhdGFzZXRzOiBnZXREYXRhc2V0cyhncm91cGVkRGF0YSlcbiAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIHJlbW92ZURhdGEobGFiZWw6IHN0cmluZykge1xuICAgICAgICAgIHJlbW92ZShkYXRhLCBmaW5kRGF0YUJ5TGFiZWxQcmVkaWNhdGUobGFiZWwpKTtcbiAgICAgICAgICByZXR1cm4gdGhpcy5nZXREYXRhKGRhdGEpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBwcmVwYXJlZCB0aGUgY2hhcnQgZGF0YSB1c2luZyB0aGUgY29uZmlndXJhdGlvbiBwYXNzZWRcbiAgICogQHBhcmFtIHtQYXJ0aWFsPElDaGFydE9wdGlvbnM+fSBjb25maWdcbiAgICogQHBhcmFtIHsqfSBkYXRhXG4gICAqIEBtZW1iZXJvZiBDaGFydEpzQ29tcG9uZW50XG4gICAqL1xuICBidWlsZGVyKGNvbmZpZzogUGFydGlhbDxJQ2hhcnRPcHRpb25zPiwgZGF0YSkge1xuICAgIGxldCB7IGxhYmVscyA9IFtdLCBsYWJlbEV4cHIgPSBudWxsLCB0eXBlID0gbnVsbCwgbGVnZW5kID0gdHJ1ZSwgY29sb3JzID0gW10sIGRhdGFzZXRzID0gW10sIG9wdGlvbnMgPSB7fSwgLi4ub3RoZXJzIH0gPSBjb25maWc7XG4gICAgb3B0aW9ucyA9IHsgLi4ub3RoZXJzLCAuLi5vcHRpb25zIH07XG4gICAgaWYgKGxhYmVsRXhwcikge1xuICAgICAgdGhpcy5fbGFiZWxzQW5kRGF0YXNldHNDbG9zdXJlID0gdGhpcy5nZXRMYWJlbHNBbmREYXRhc2V0c0Nsb3N1cmUobGFiZWxFeHByLCBkYXRhc2V0cykoZGF0YSk7XG4gICAgICBjb25zdCB7IGdldERhdGEgfSA9IHRoaXMuX2xhYmVsc0FuZERhdGFzZXRzQ2xvc3VyZTtcbiAgICAgICh7IGxhYmVscywgZGF0YXNldHMgfSA9IGdldERhdGEoKSk7XG4gICAgfVxuICAgIHRoaXMuc2V0Q2hhcnREYXRhKHsgbGFiZWxzLCBkYXRhc2V0cywgb3B0aW9ucywgdHlwZSwgbGVnZW5kLCBjb2xvcnMgfSk7XG4gIH1cblxuICBwcml2YXRlIHNldENoYXJ0RGF0YShjb25maWc6IFBhcnRpYWw8SUNoYXJ0T3B0aW9ucz4gPSB7fSkge1xuICAgIHRoaXMuaW5wdXRQYXJhbWV0ZXJzID0geyAuLi50aGlzLl9kZWZhdWx0Q29uZmlnLCAuLi50aGlzLmlucHV0UGFyYW1ldGVycywgLi4uY29uZmlnIH07XG4gICAgdGhpcy4kY29udGV4dCA9IHsgZGF0YTogdGhpcy5kYXRhLCBjb25maWc6IHRoaXMuY29uZmlnLCBpbnB1dFBhcmFtZXRlcnM6IHRoaXMuaW5wdXRQYXJhbWV0ZXJzLCBleHBvcnRPcHRpb25zOiB0aGlzLmV4cG9ydE9wdGlvbnMgfTtcbiAgfVxuXG4gIHJlc2V0KCk6IHZvaWQge1xuICAgIC8vIHRocm93IG5ldyBFcnJvcignTWV0aG9kIG5vdCBpbXBsZW1lbnRlZC4nKTtcbiAgfVxuXG4gIGRlc3Ryb3koKTogdm9pZCB7XG4gICAgdGhpcy5iYXNlQ2hhcnREaXJlY3RpdmUuY2hhcnQuZGVzdHJveSgpO1xuICB9XG5cbiAgbmdPbkRlc3Ryb3koKSB7XG4gICAgdGhpcy5kZXN0cm95KCk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIHVwZGF0ZXMgdGhlIHR5cGUsIGRhdGEgb3IgRGFzaGxldCBjb25maWd1cmF0aW9uXG4gICAqIEBwYXJhbSB7SW5wdXRQYXJhbXN9IGlucHV0XG4gICAqIEBtZW1iZXJvZiBDaGFydEpzQ29tcG9uZW50XG4gICAqL1xuICB1cGRhdGUoaW5wdXQ6IFBhcnRpYWw8VXBkYXRlSW5wdXRQYXJhbXM+KSB7XG4gICAgdGhpcy5jaGVja0lmSW5pdGlhbGl6ZWQoKTtcbiAgICBpZiAoIWlucHV0KSB0aHJvdyBuZXcgRXJyb3IodGhpcy5DT05TVEFOVFMuSU5WQUxJRF9JTlBVVCk7XG4gICAgY29uc3QgeyB0eXBlID0gbnVsbCwgY29uZmlnID0ge30sIGRhdGEgPSBudWxsIH0gPSBpbnB1dDtcbiAgICBsZXQgbGFiZWxzLCBkYXRhc2V0cztcbiAgICBpZiAoZGF0YSkge1xuICAgICAgY29uc3QgeyBsYWJlbEV4cHIsIGRhdGFzZXRzOiBkYXRhc2V0c0NvbmZpZyB9ID0gY29uZmlnIGFzIHsgbGFiZWxFeHByOiBzdHJpbmcsIGRhdGFzZXRzOiBJRGF0YXNldFtdIH07XG4gICAgICBpZiAobGFiZWxFeHByIHx8IGRhdGFzZXRzKSB7XG4gICAgICAgIHRoaXMuX2xhYmVsc0FuZERhdGFzZXRzQ2xvc3VyZSA9IHRoaXMuZ2V0TGFiZWxzQW5kRGF0YXNldHNDbG9zdXJlKGxhYmVsRXhwciB8fCB0aGlzLmdldENvbmZpZ1ZhbHVlKGxhYmVsRXhwciksIGRhdGFzZXRzQ29uZmlnIHx8IHRoaXMuZ2V0Q29uZmlnVmFsdWUoZGF0YXNldHMpKShkYXRhKTtcbiAgICAgIH1cbiAgICAgICh7IGxhYmVscywgZGF0YXNldHMgfSA9IHRoaXMuX2xhYmVsc0FuZERhdGFzZXRzQ2xvc3VyZS5nZXREYXRhKGRhdGEpKTtcbiAgICB9XG4gICAgdGhpcy5zZXRDaGFydERhdGEoeyAuLi5jb25maWcsIC4uLih0eXBlICYmIHsgdHlwZSB9KSwgLi4uKGxhYmVscyAmJiBkYXRhc2V0cyAmJiB7IGxhYmVscywgZGF0YXNldHMgfSkgfSk7XG4gICAgdGhpcy5iYXNlQ2hhcnREaXJlY3RpdmUudXBkYXRlKCk7XG4gIH1cblxuICBhZGREYXRhKGRhdGE6IG9iamVjdFtdIHwgb2JqZWN0KSB7XG4gICAgdGhpcy5jaGVja0lmSW5pdGlhbGl6ZWQoKTtcbiAgICBpZiAoIWRhdGEpIHRocm93IG5ldyBFcnJvcih0aGlzLkNPTlNUQU5UUy5JTlZBTElEX0lOUFVUKTtcbiAgICBpZiAodGhpcy5fbGFiZWxzQW5kRGF0YXNldHNDbG9zdXJlKSB7XG4gICAgICBkYXRhID0gQXJyYXkuaXNBcnJheShkYXRhKSA/IGRhdGEgOiBbZGF0YV07XG4gICAgICBjb25zdCB7IGxhYmVscywgZGF0YXNldHMgfSA9IHRoaXMuX2xhYmVsc0FuZERhdGFzZXRzQ2xvc3VyZS5hZGREYXRhKGRhdGEpO1xuICAgICAgdGhpcy5zZXRDaGFydERhdGEoeyBsYWJlbHMsIGRhdGFzZXRzIH0pO1xuICAgIH1cbiAgfVxuXG4gIHJlZnJlc2hDaGFydCgpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IodGhpcy5DT05TVEFOVFMuTUVUSE9EX05PVF9JTVBMRU1FTlRFRCk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFJlbW92ZXMgZGF0YSBhc3NvY2lhdGVkIHdpdGggYSBsYWJlbFxuICAgKiBAcGFyYW0ge3N0cmluZ30gbGFiZWxcbiAgICogQG1lbWJlcm9mIENoYXJ0SnNDb21wb25lbnRcbiAgICovXG4gIHJlbW92ZURhdGEobGFiZWw6IHN0cmluZykge1xuICAgIHRoaXMuY2hlY2tJZkluaXRpYWxpemVkKCk7XG4gICAgY29uc3QgeyBsYWJlbHMsIGRhdGFzZXRzIH0gPSB0aGlzLl9sYWJlbHNBbmREYXRhc2V0c0Nsb3N1cmUucmVtb3ZlRGF0YShsYWJlbCk7XG4gICAgdGhpcy5zZXRDaGFydERhdGEoeyBsYWJlbHMsIGRhdGFzZXRzIH0pO1xuICB9XG5cbiAgZ2V0VGVsZW1ldHJ5KCkge1xuICAgIHRocm93IG5ldyBFcnJvcih0aGlzLkNPTlNUQU5UUy5NRVRIT0RfTk9UX0lNUExFTUVOVEVEKTtcbiAgfVxuXG4gIGdldEN1cnJlbnRTZWxlY3Rpb24oKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKHRoaXMuQ09OU1RBTlRTLk1FVEhPRF9OT1RfSU1QTEVNRU5URUQpO1xuICB9XG5cbiAgZ2V0RGF0YXNldEF0SW5kZXgoaW5kZXg6IG51bWJlcikge1xuICAgIHRocm93IG5ldyBFcnJvcih0aGlzLkNPTlNUQU5UUy5NRVRIT0RfTk9UX0lNUExFTUVOVEVEKTtcbiAgfVxuXG4gIG9uQ2hhcnRDbGlja2VkKGV2ZW50KSB7XG4gICAgdGhpcy5ldmVudHMuZW1pdCh7XG4gICAgICB0eXBlOiAnQ0xJQ0snLFxuICAgICAgZXZlbnRcbiAgICB9KVxuICB9XG5cbiAgb25DaGFydEhvdmVyZWQoZXZlbnQpIHtcbiAgICB0aGlzLmV2ZW50cy5lbWl0KHtcbiAgICAgIHR5cGU6ICdIT1ZFUicsXG4gICAgICBldmVudFxuICAgIH0pXG4gIH1cblxuICBleHBvcnRBc0ltYWdlKGZvcm1hdCA9ICdqcGcnKSB7XG4gICAgY29uc3QgZGF0YVVybCA9IChkb2N1bWVudC5nZXRFbGVtZW50QnlJZCh0aGlzLmlkKSBhcyBhbnkpLnRvRGF0YVVSTChgaW1hZ2UvJHtmb3JtYXR9YCwgMSk7XG4gICAgY29uc3QgZmlsZU5hbWUgPSBgaW1hZ2UuJHtmb3JtYXR9YDtcbiAgICB0aGlzLl9kb3dubG9hZEZpbGUoZGF0YVVybCwgZmlsZU5hbWUpO1xuICB9XG5cbiAgZXhwb3J0QXMoZm9ybWF0OiBzdHJpbmcpIHtcbiAgICBpZiAoIXRoaXMuZXhwb3J0T3B0aW9ucy5pbmNsdWRlcyhmb3JtYXQpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ2dpdmVuIHR5cGUgbm90IHN1cHBvcnRlZCcpO1xuICAgIH1cbiAgICBzd2l0Y2ggKGZvcm1hdCkge1xuICAgICAgY2FzZSAnY3N2Jzoge1xuICAgICAgICB0aGlzLmV4cG9ydEFzQ3N2KCk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgICAgZGVmYXVsdDoge1xuICAgICAgICB0aGlzLmV4cG9ydEFzSW1hZ2UoZm9ybWF0KTtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuICB9XG59XG4iXX0=