@grptx/ng-canvas-gauges
Version:
Angular 14+ component wrapper for the canvas-gauges lib written by @Mikhus
230 lines • 28.4 kB
JavaScript
/*!
* The MIT License (MIT)
*
* Copyright (c) 2017 Vlad Martynenko <vladimir.martynenko.work@gmail.com>
*
* 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 { ViewChild, Input, NgZone, ElementRef, Directive } from '@angular/core';
import * as CanvasGauges from 'canvas-gauges';
import * as Rx from 'rx-dom-html';
import * as i0 from "@angular/core";
const _c0 = ["gauge"];
// String utils
const toCamelCase = (str) => str.replace(/(\-\w)/g, (matches) => matches[1].toUpperCase());
const toKebabCase = (str) => str.replace(/([a-z0-9])([A-Z])/g, '$1-$2').toLowerCase();
const attributeName2PropertyName = (attrName) => toCamelCase(attrName);
/**
* Base gauge component for the Gauges rendering
* T - Type of the Gauge to be rendered (Currently RadialGauge, LinearGauge from the original library)
* T2 - Type of config options used by the particular gauge (RadialGaugeOptions, LinearGaugeOptions)
*/
export class BaseGauge {
/**
*
* @param el - reference to the element of the whole component, used to scrape options declared on the component itself
* @param zone - required to redraw gauge outside of Angular, due to animation lags caused by the ovewritten function of the ngZone
*/
constructor(el, zone) {
this.el = el;
this.zone = zone;
/**
* Flag indicating that OnViewInit life-cycle has completed
*/
this.isInited = false;
}
/**
* Returns gauges properties as an options object.
* Option properties consist of the attribute-based properties and those
* explicitly set.
* @returns <T2>
*/
get options() {
const options = {};
options.renderTo = this.canvas.nativeElement;
// Map attribute-based options onto options.
// Requries converting kebab style attribute names to camelCase property names
for (const attr of this.el.nativeElement.attributes) {
const prop = attributeName2PropertyName(attr.name);
options[prop] = CanvasGauges.DomObserver.parse(attr.value);
}
// merge preOptons with attribute-based properties
// tslint:disable-next-line:forin
for (const prop in this.preInitOptions) {
options[prop] = this.preInitOptions[prop];
}
// clear the preInitOptions as they have already been merged
// with the attribute-based properties
if (this.isInited) {
this.preInitOptions = null;
}
return options;
}
/**
* Assign gauge options at anytime in the lifecycle.
* @param newOptions - assign the style and size properties
*/
set options(newOptions) {
// cache newOptions as preInitOptions until gauge is ready
if (!this.isInited) {
this.preInitOptions = newOptions;
return;
}
this.update(newOptions);
}
/**
* Assign the value of the gauge visual indicator such as a needle or pointer
* @param newValue the guage new value
*/
set value(newValue) {
// case new gauge value as preInitValue until the gauge is ready
if (!this.isInited) {
this.preInitValue = newValue;
return;
}
this.zone.runOutsideAngular(() => {
this.gauge.value = newValue;
});
}
/**
* Update the gauge options. Do not use until after OnViewInit() before using.
*
* Special implementation note - options.properties are maintained as
* attribute name->value on this component's elementRef. Thus this method
* maps each newOptions property onto the property's corresponding attribute.
* The attribute update triggers a DOM mutation event which "this" listens for.
* See #listenForDOMEvents()
*
* @param newOptions - the options to update the gauge
*/
update(newOptions) {
// map all options onto this element's attributes
// Then attribute changes will be detected and pushed to the gauge.update()
if (!newOptions) {
return;
}
// tslint:disable-next-line:forin
for (const prop in newOptions) {
const val = newOptions[prop].toString();
if (prop === 'value') {
// short circuit the value property update by calling
// the gauge.value api directly for efficient animated update
this.value = CanvasGauges.DomObserver.parse(val);
}
else {
const attrName = toKebabCase(prop);
this.el.nativeElement.setAttribute(attrName, val);
}
}
}
/**
* Perform gauge initialization.
* Subclasses that override this method must this super version
* for proper operation.
*/
ngAfterViewInit() {
// initial update of gauge properties
this.initGauge();
this.listenForDOMEvents();
this.isInited = true;
}
/**
* Listen for attribute-change events that are created when updating
* the options of this gauge.
*/
listenForDOMEvents() {
// Listen to gauge element for attribute changes
// Convert all changed attribtues into a GenericOptions or subclass
// Update the gauge with the new options.
this.domListener =
Rx.DOM.fromMutationObserver(this.el.nativeElement, { attributes: true }).
subscribe(changes => {
const newOptions = {};
changes.forEach(change => {
if ('attributes' === change.type) {
// console.log('DOM, change', change.attributeName);
newOptions[attributeName2PropertyName(change.attributeName)] =
CanvasGauges.DomObserver.parse(this.el.nativeElement.getAttribute(change.attributeName));
}
});
this.basicUpdate(newOptions);
});
}
/**
* Discontinue listening for attribute change events.
*/
stopListeningForDOMEvents() {
if (this.domListener) {
this.domListener.disconnect();
this.domListener = null;
}
}
/**
* Initalize the gauge with all options defined by attributes and
* parent component options.
*/
initGauge() {
const options = this.options;
if (this.preInitValue) {
options.value = this.preInitValue;
}
// init options.renderTo if needed
if (!options.hasOwnProperty('renderTo') || !options.renderTo) {
options.renderTo = this.canvas.nativeElement;
}
this.basicUpdate(options);
}
/**
* Performs the gauge update using the current options
* @param options The options for the guage
*/
basicUpdate(options) {
// treat the value property special and update it through the
// value getter.
if (typeof options.value === 'number') {
// use gauge api directly for most efficient update method
this.value = options.value;
// filter value property from options to avoid redundant
// processing by gauge
delete options.value;
}
// do nothing if no option properties to update
if (Object.keys(options).length) {
this.gauge.update(options);
}
}
}
BaseGauge.ɵfac = function BaseGauge_Factory(t) { return new (t || BaseGauge)(i0.ɵɵdirectiveInject(i0.ElementRef), i0.ɵɵdirectiveInject(i0.NgZone)); };
BaseGauge.ɵdir = /*@__PURE__*/ i0.ɵɵdefineDirective({ type: BaseGauge, viewQuery: function BaseGauge_Query(rf, ctx) { if (rf & 1) {
i0.ɵɵviewQuery(_c0, 7);
} if (rf & 2) {
let _t;
i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.canvas = _t.first);
} }, inputs: { options: "options", value: "value" } });
(function () { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(BaseGauge, [{
type: Directive
}], function () { return [{ type: i0.ElementRef }, { type: i0.NgZone }]; }, { canvas: [{
type: ViewChild,
args: ['gauge', { static: true }]
}], options: [{
type: Input
}], value: [{
type: Input
}] }); })();
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmFzZS1nYXVnZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3Byb2plY3RzL25nLWNhbnZhcy1nYXVnZXMvc3JjL2xpYi9iYXNlLWdhdWdlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBc0JHO0FBRUgsT0FBTyxFQUFFLFNBQVMsRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFFLFVBQVUsRUFBeUIsU0FBUyxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ3ZHLE9BQU8sS0FBSyxZQUFZLE1BQU0sZUFBZSxDQUFDO0FBQzlDLE9BQU8sS0FBSyxFQUFFLE1BQU0sYUFBYSxDQUFDOzs7QUFJbEMsZUFBZTtBQUNmLE1BQU0sV0FBVyxHQUFHLENBQUMsR0FBVyxFQUFFLEVBQUUsQ0FBQyxHQUFHLENBQUMsT0FBTyxDQUFDLFNBQVMsRUFBRSxDQUFDLE9BQU8sRUFBRSxFQUFFLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDLFdBQVcsRUFBRSxDQUFDLENBQUM7QUFFbkcsTUFBTSxXQUFXLEdBQUcsQ0FBQyxHQUFXLEVBQUUsRUFBRSxDQUFDLEdBQUcsQ0FBQyxPQUFPLENBQUMsb0JBQW9CLEVBQUUsT0FBTyxDQUFDLENBQUMsV0FBVyxFQUFFLENBQUM7QUFFOUYsTUFBTSwwQkFBMEIsR0FBRyxDQUFDLFFBQWdCLEVBQUUsRUFBRSxDQUFDLFdBQVcsQ0FBQyxRQUFRLENBQUMsQ0FBQztBQUsvRTs7OztHQUlHO0FBRUgsTUFBTSxPQUFnQixTQUFTO0lBdUMzQjs7OztPQUlHO0lBQ0gsWUFBb0IsRUFBYyxFQUFTLElBQVk7UUFBbkMsT0FBRSxHQUFGLEVBQUUsQ0FBWTtRQUFTLFNBQUksR0FBSixJQUFJLENBQVE7UUE1QnZEOztXQUVHO1FBQ0ssYUFBUSxHQUFHLEtBQUssQ0FBQztJQTBCekIsQ0FBQztJQVNEOzs7OztPQUtHO0lBQ0gsSUFBVyxPQUFPO1FBRWQsTUFBTSxPQUFPLEdBQUcs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QU0sQ0FBQyxhQUFhLENBQUM7U0FDaEQ7UUFFRCxJQUFJLENBQUMsV0FBVyxDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQzlCLENBQUM7SUFHRDs7O09BR0c7SUFDTyxXQUFXLENBQUMsT0FBVztRQUU3Qiw2REFBNkQ7UUFDN0QsZ0JBQWdCO1FBQ2hCLElBQUksT0FBTyxPQUFPLENBQUMsS0FBSyxLQUFLLFFBQVEsRUFBRTtZQUVuQywwREFBMEQ7WUFDMUQsSUFBSSxDQUFDLEtBQUssR0FBRyxPQUFPLENBQUMsS0FBSyxDQUFDO1lBRTNCLHdEQUF3RDtZQUN4RCxzQkFBc0I7WUFDdEIsT0FBTyxPQUFPLENBQUMsS0FBSyxDQUFDO1NBQ3hCO1FBRUQsK0NBQStDO1FBQy9DLElBQUksTUFBTSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQyxNQUFNLEVBQUU7WUFDN0IsSUFBSSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLENBQUM7U0FDOUI7SUFDTCxDQUFDOztrRUEzUGlCLFNBQVM7NERBQVQsU0FBUzs7Ozs7O3VGQUFULFNBQVM7Y0FEOUIsU0FBUztrRkFRSSxNQUFNO2tCQURmLFNBQVM7bUJBQUMsT0FBTyxFQUFFLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRTtZQXVGekIsT0FBTztrQkFEakIsS0FBSztZQWtCSyxLQUFLO2tCQURmLEtBQUsiLCJzb3VyY2VzQ29udGVudCI6WyIvKiFcbiAqIFRoZSBNSVQgTGljZW5zZSAoTUlUKVxuICpcbiAqIENvcHlyaWdodCAoYykgMjAxNyBWbGFkIE1hcnR5bmVua28gPHZsYWRpbWlyLm1hcnR5bmVua28ud29ya0BnbWFpbC5jb20+XG4gKlxuICogUGVybWlzc2lvbiBpcyBoZXJlYnkgZ3JhbnRlZCwgZnJlZSBvZiBjaGFyZ2UsIHRvIGFueSBwZXJzb24gb2J0YWluaW5nIGEgY29weVxuICogb2YgdGhpcyBzb2Z0d2FyZSBhbmQgYXNzb2NpYXRlZCBkb2N1bWVudGF0aW9uIGZpbGVzICh0aGUgXCJTb2Z0d2FyZVwiKSwgdG8gZGVhbFxuICogaW4gdGhlIFNvZnR3YXJlIHdpdGhvdXQgcmVzdHJpY3Rpb24sIGluY2x1ZGluZyB3aXRob3V0IGxpbWl0YXRpb24gdGhlIHJpZ2h0c1xuICogdG8gdXNlLCBjb3B5LCBtb2RpZnksIG1lcmdlLCBwdWJsaXNoLCBkaXN0cmlidXRlLCBzdWJsaWNlbnNlLCBhbmQvb3Igc2VsbFxuICogY29waWVzIG9mIHRoZSBTb2Z0d2FyZSwgYW5kIHRvIHBlcm1pdCBwZXJzb25zIHRvIHdob20gdGhlIFNvZnR3YXJlIGlzXG4gKiBmdXJuaXNoZWQgdG8gZG8gc28sIHN1YmplY3QgdG8gdGhlIGZvbGxvd2luZyBjb25kaXRpb25zOlxuICpcbiAqIFRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBlcm1pc3Npb24gbm90aWNlIHNoYWxsIGJlIGluY2x1ZGVkIGluXG4gKiBhbGwgY29waWVzIG9yIHN1YnN0YW50aWFsIHBvcnRpb25zIG9mIHRoZSBTb2Z0d2FyZS5cbiAqXG4gKiBUSEUgU09GVFdBUkUgSVMgUFJPVklERUQgXCJBUyBJU1wiLCBXSVRIT1VUIFdBUlJBTlRZIE9GIEFOWSBLSU5ELCBFWFBSRVNTIE9SXG4gKiBJTVBMSUVELCBJTkNMVURJTkcgQlVUIE5PVCBMSU1JVEVEIFRPIFRIRSBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWSxcbiAqIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFORCBOT05JTkZSSU5HRU1FTlQuIElOIE5PIEVWRU5UIFNIQUxMIFRIRVxuICogQVVUSE9SUyBPUiBDT1BZUklHSFQgSE9MREVSUyBCRSBMSUFCTEUgRk9SIEFOWSBDTEFJTSwgREFNQUdFUyBPUiBPVEhFUlxuICogTElBQklMSVRZLCBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgVE9SVCBPUiBPVEhFUldJU0UsIEFSSVNJTkcgRlJPTSxcbiAqIE9VVCBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhFIFNPRlRXQVJFIE9SIFRIRSBVU0UgT1IgT1RIRVIgREVBTElOR1MgSU4gVEhFXG4gKiBTT0ZUV0FSRS5cbiAqL1xuXG5pbXBvcnQgeyBWaWV3Q2hpbGQsIElucHV0LCBOZ1pvbmUsIEVsZW1lbnRSZWYsIE9uSW5pdCwgQWZ0ZXJWaWV3SW5pdCwgRGlyZWN0aXZlIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgKiBhcyBDYW52YXNHYXVnZXMgZnJvbSAnY2FudmFzLWdhdWdlcyc7XG5pbXBvcnQgKiBhcyBSeCBmcm9tICdyeC1kb20taHRtbCc7XG5cblxuXG4vLyBTdHJpbmcgdXRpbHNcbmNvbnN0IHRvQ2FtZWxDYXNlID0gKHN0cjogc3RyaW5nKSA9PiBzdHIucmVwbGFjZSgvKFxcLVxcdykvZywgKG1hdGNoZXMpID0+IG1hdGNoZXNbMV0udG9VcHBlckNhc2UoKSk7XG5cbmNvbnN0IHRvS2ViYWJDYXNlID0gKHN0cjogc3RyaW5nKSA9PiBzdHIucmVwbGFjZSgvKFthLXowLTldKShbQS1aXSkvZywgJyQxLSQyJykudG9Mb3dlckNhc2UoKTtcblxuY29uc3QgYXR0cmlidXRlTmFtZTJQcm9wZXJ0eU5hbWUgPSAoYXR0ck5hbWU6IHN0cmluZykgPT4gdG9DYW1lbENhc2UoYXR0ck5hbWUpO1xuXG5cblxuXG4vKipcbiAqIEJhc2UgZ2F1Z2UgY29tcG9uZW50IGZvciB0aGUgR2F1Z2VzIHJlbmRlcmluZ1xuICogVCAtIFR5cGUgb2YgdGhlIEdhdWdlIHRvIGJlIHJlbmRlcmVkIChDdXJyZW50bHkgUmFkaWFsR2F1Z2UsIExpbmVhckdhdWdlIGZyb20gdGhlIG9yaWdpbmFsIGxpYnJhcnkpXG4gKiBUMiAtIFR5cGUgb2YgY29uZmlnIG9wdGlvbnMgdXNlZCBieSB0aGUgcGFydGljdWxhciBnYXVnZSAoUmFkaWFsR2F1Z2VPcHRpb25zLCBMaW5lYXJHYXVnZU9wdGlvbnMpXG4gKi9cbkBEaXJlY3RpdmUoKVxuZXhwb3J0IGFic3RyYWN0IGNsYXNzIEJhc2VHYXVnZTxUIGV4dGVuZHMgQ2FudmFzR2F1Z2VzLkJhc2VHYXVnZSwgVDIgZXh0ZW5kcyBDYW52YXNHYXVnZXMuR2VuZXJpY09wdGlvbnM+XG4gICAgaW1wbGVtZW50cyBPbkluaXQsIEFmdGVyVmlld0luaXQge1xuXG4gICAgLyoqXG4gICAgICogQ2FudmFzIGVsZW1lbnQgb24gdGhlIHRlbXBsYXRlIHVzZWQgYnkgdGhlIGxpYnJhcnkgdG8gZHJhdyBnYXVnZSBlbGVtZW50XG4gICAgICovXG4gICAgQFZpZXdDaGlsZCgnZ2F1Z2UnLCB7IHN0YXRpYzogdHJ1ZSB9KVxuICAgIHByb3RlY3RlZCBjYW52YXM6IEVsZW1lbnRSZWY7XG5cbiAgICAvKipcbiAgICAgKiBBIGdhdWdlIGluc3RhbmNlIHJlc3BvbnNpYmxlIGZvciByZW5kZXJpbmcgYW5kIHVwZGF0ZXMgb24gdGhlIGNhbnZhcy5cbiAgICAgKiBTdWJjbGFzc2VzIHNob3VsZCBpbml0aWFsaXplIGluIHRoZWlyIG5nT25Jbml0IGltcGxlbWVudGF0aW9uLlxuICAgICAqL1xuICAgIHByb3RlY3RlZCBnYXVnZTogVDtcblxuXG4gICAgLyoqXG4gICAgICogRmxhZyBpbmRpY2F0aW5nIHRoYXQgT25WaWV3SW5pdCBsaWZlLWN5Y2xlIGhhcyBjb21wbGV0ZWRcbiAgICAgKi9cbiAgICBwcml2YXRlIGlzSW5pdGVkID0gZmFsc2U7XG5cbiAgICAvKipcbiAgICAgKiB2YWx1ZSBwcm9wZXJ0eSBvZiBnYXVnZSBwcmlvciB0byBjb21wb25lbnQgdmlldyBpbml0aWFsaXphdGlvblxuICAgICAqL1xuICAgIHByaXZhdGUgcHJlSW5pdFZhbHVlOiBudW1iZXI7XG5cbiAgICAvKipcbiAgICAgKiBvcHRpb25zIHByb3BlcnR5IG9mIGdhdWdlIHByaW9yIHRvIGNvbXBvbmVudCB2aWV3IGluaXRpYWxpemF0aW9uXG4gICAgICovXG4gICAgcHJpdmF0ZSBwcmVJbml0T3B0aW9uczogVDI7XG5cblxuICAgIC8qKlxuICAgICAqIExpc3RlbiBmb3IgYXR0cmlidXRlIGNoYW5nZXMsIGkuZS4sIG9wdGlvbnMgcHJvcGVydGllcyB0aGF0IGFyZSBzdG9yZWRcbiAgICAgKiBhcyBhdHRyaWJ1dGVzIG9uIHRoaXMgRWxlbWVudFJlZlxuICAgICAqL1xuICAgIHByaXZhdGUgZG9tTGlzdGVuZXI6IE11dGF0aW9uT2JzZXJ2ZXI7XG5cblxuICAgIC8qKlxuICAgICAqXG4gICAgICogQHBhcmFtIGVsIC0gcmVmZXJlbmNlIHRvIHRoZSBlbGVtZW50IG9mIHRoZSB3aG9sZSBjb21wb25lbnQsIHVzZWQgdG8gc2NyYXBlIG9wdGlvbnMgZGVjbGFyZWQgb24gdGhlIGNvbXBvbmVudCBpdHNlbGZcbiAgICAgKiBAcGFyYW0gem9uZSAtIHJlcXVpcmVkIHRvIHJlZHJhdyBnYXVnZSBvdXRzaWRlIG9mIEFuZ3VsYXIsIGR1ZSB0byBhbmltYXRpb24gbGFncyBjYXVzZWQgYnkgdGhlIG92ZXdyaXR0ZW4gZnVuY3Rpb24gb2YgdGhlIG5nWm9uZVxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHByaXZhdGUgZWw6IEVsZW1lbnRSZWYsIHB1YmxpYyB6b25lOiBOZ1pvbmUpIHtcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFN1YmNsYXNzZXMgc2hvdWxkIGluc3RhbnRpYXRlIHRoZSBDYW52YXNHYXVnZSBvYmplY3QgaW4gdGhlIGNoaWxkIGNvbXBvbmVudFxuICAgICAqL1xuICAgIGFic3RyYWN0IG5nT25Jbml0KCk6IHZvaWQ7XG5cblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgZ2F1Z2VzIHByb3BlcnRpZXMgYXMgYW4gb3B0aW9ucyBvYmplY3QuXG4gICAgICogT3B0aW9uIHByb3BlcnRpZXMgY29uc2lzdCBvZiB0aGUgYXR0cmlidXRlLWJhc2VkIHByb3BlcnRpZXMgYW5kIHRob3NlXG4gICAgICogZXhwbGljaXRseSBzZXQuXG4gICAgICogQHJldHVybnMgPFQyPlxuICAgICAqL1xuICAgIHB1YmxpYyBnZXQgb3B0aW9ucygpOiBUMiB7XG5cbiAgICAgICAgY29uc3Qgb3B0aW9ucyA9IHt9IGFzIFQyO1xuICAgICAgICBvcHRpb25zLnJlbmRlclRvID0gdGhpcy5jYW52YXMubmF0aXZlRWxlbWVudDtcblxuICAgICAgICAvLyBNYXAgYXR0cmlidXRlLWJhc2VkIG9wdGlvbnMgb250byBvcHRpb25zLlxuICAgICAgICAvLyBSZXF1cmllcyBjb252ZXJ0aW5nIGtlYmFiIHN0eWxlIGF0dHJpYnV0ZSBuYW1lcyB0byBjYW1lbENhc2UgcHJvcGVydHkgbmFtZXNcbiAgICAgICAgZm9yIChjb25zdCBhdHRyIG9mIHRoaXMuZWwubmF0aXZlRWxlbWVudC5hdHRyaWJ1dGVzKSB7XG4gICAgICAgICAgICBjb25zdCBwcm9wID0gYXR0cmlidXRlTmFtZTJQcm9wZXJ0eU5hbWUoYXR0ci5uYW1lKTtcbiAgICAgICAgICAgIG9wdGlvbnNbcHJvcF0gPSBDYW52YXNHYXVnZXMuRG9tT2JzZXJ2ZXIucGFyc2UoYXR0ci52YWx1ZSk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBtZXJnZSBwcmVPcHRvbnMgd2l0aCBhdHRyaWJ1dGUtYmFzZWQgcHJvcGVydGllc1xuICAgICAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6Zm9yaW5cbiAgICAgICAgZm9yIChjb25zdCBwcm9wIGluIHRoaXMucHJlSW5pdE9wdGlvbnMpIHtcbiAgICAgICAgICAgIG9wdGlvbnNbcHJvcF0gPSB0aGlzLnByZUluaXRPcHRpb25zW3Byb3BdO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gY2xlYXIgdGhlIHByZUluaXRPcHRpb25zIGFzIHRoZXkgaGF2ZSBhbHJlYWR5IGJlZW4gbWVyZ2VkXG4gICAgICAgIC8vIHdpdGggdGhlIGF0dHJpYnV0ZS1iYXNlZCBwcm9wZXJ0aWVzXG4gICAgICAgIGlmICh0aGlzLmlzSW5pdGVkKSB7XG4gICAgICAgICAgICB0aGlzLnByZUluaXRPcHRpb25zID0gbnVsbDtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBvcHRpb25zO1xuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogQXNzaWduIGdhdWdlIG9wdGlvbnMgYXQgYW55dGltZSBpbiB0aGUgbGlmZWN5Y2xlLlxuICAgICAqIEBwYXJhbSBuZXdPcHRpb25zIC0gYXNzaWduIHRoZSBzdHlsZSBhbmQgc2l6ZSBwcm9wZXJ0aWVzXG4gICAgICovXG4gICAgQElucHV0KClcbiAgICBwdWJsaWMgc2V0IG9wdGlvbnMobmV3T3B0aW9uczogVDIpIHtcblxuICAgICAgICAvLyBjYWNoZSBuZXdPcHRpb25zIGFzIHByZUluaXRPcHRpb25zIHVudGlsIGdhdWdlIGlzIHJlYWR5XG4gICAgICAgIGlmICghdGhpcy5pc0luaXRlZCkge1xuICAgICAgICAgICAgdGhpcy5wcmVJbml0T3B0aW9ucyA9IG5ld09wdGlvbnM7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLnVwZGF0ZShuZXdPcHRpb25zKTtcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIEFzc2lnbiB0aGUgdmFsdWUgb2YgdGhlIGdhdWdlIHZpc3VhbCBpbmRpY2F0b3Igc3VjaCBhcyBhIG5lZWRsZSBvciBwb2ludGVyXG4gICAgICogQHBhcmFtIG5ld1ZhbHVlICB0aGUgZ3VhZ2UgbmV3IHZhbHVlXG4gICAgICovXG4gICAgQElucHV0KClcbiAgICBwdWJsaWMgc2V0IHZhbHVlKG5ld1ZhbHVlOiBudW1iZXIpIHtcblxuICAgICAgICAvLyBjYXNlIG5ldyBnYXVnZSB2YWx1ZSBhcyBwcmVJbml0VmFsdWUgdW50aWwgdGhlIGdhdWdlIGlzIHJlYWR5XG4gICAgICAgIGlmICghdGhpcy5pc0luaXRlZCkge1xuICAgICAgICAgICAgdGhpcy5wcmVJbml0VmFsdWUgPSBuZXdWYWx1ZTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuem9uZS5ydW5PdXRzaWRlQW5ndWxhcigoKSA9PiB7XG4gICAgICAgICAgICB0aGlzLmdhdWdlLnZhbHVlID0gbmV3VmFsdWU7XG4gICAgICAgIH0pO1xuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogVXBkYXRlIHRoZSBnYXVnZSBvcHRpb25zLiBEbyBub3QgdXNlIHVudGlsIGFmdGVyIE9uVmlld0luaXQoKSBiZWZvcmUgdXNpbmcuXG4gICAgICpcbiAgICAgKiBTcGVjaWFsIGltcGxlbWVudGF0aW9uIG5vdGUgLSBvcHRpb25zLnByb3BlcnRpZXMgYXJlIG1haW50YWluZWQgYXNcbiAgICAgKiBhdHRyaWJ1dGUgbmFtZS0+dmFsdWUgb24gdGhpcyBjb21wb25lbnQncyBlbGVtZW50UmVmLiAgVGh1cyB0aGlzIG1ldGhvZFxuICAgICAqIG1hcHMgZWFjaCBuZXdPcHRpb25zIHByb3BlcnR5IG9udG8gdGhlIHByb3BlcnR5J3MgY29ycmVzcG9uZGluZyBhdHRyaWJ1dGUuXG4gICAgICogVGhlIGF0dHJpYnV0ZSB1cGRhdGUgdHJpZ2dlcnMgYSBET00gbXV0YXRpb24gZXZlbnQgd2hpY2ggIFwidGhpc1wiIGxpc3RlbnMgZm9yLlxuICAgICAqIFNlZSAjbGlzdGVuRm9yRE9NRXZlbnRzKClcbiAgICAgKlxuICAgICAqIEBwYXJhbSBuZXdPcHRpb25zICAtIHRoZSBvcHRpb25zIHRvIHVwZGF0ZSB0aGUgZ2F1Z2VcbiAgICAgKi9cbiAgICBwdWJsaWMgdXBkYXRlKG5ld09wdGlvbnM6IFQyIHwge30pIHtcblxuICAgICAgICAvLyBtYXAgYWxsIG9wdGlvbnMgb250byB0aGlzIGVsZW1lbnQncyBhdHRyaWJ1dGVzXG4gICAgICAgIC8vIFRoZW4gYXR0cmlidXRlIGNoYW5nZXMgd2lsbCBiZSBkZXRlY3RlZCBhbmQgcHVzaGVkIHRvIHRoZSBnYXVnZS51cGRhdGUoKVxuICAgICAgICBpZiAoIW5ld09wdGlvbnMpIHsgcmV0dXJuOyB9XG5cbiAgICAgICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOmZvcmluXG4gICAgICAgIGZvciAoY29uc3QgcHJvcCBpbiBuZXdPcHRpb25zKSB7XG4gICAgICAgICAgICBjb25zdCB2YWwgPSBuZXdPcHRpb25zW3Byb3BdLnRvU3RyaW5nKCk7XG5cbiAgICAgICAgICAgIGlmIChwcm9wID09PSAndmFsdWUnKSB7XG4gICAgICAgICAgICAgICAgLy8gc2hvcnQgY2lyY3VpdCB0aGUgdmFsdWUgcHJvcGVydHkgdXBkYXRlIGJ5IGNhbGxpbmdcbiAgICAgICAgICAgICAgICAvLyB0aGUgZ2F1Z2UudmFsdWUgYXBpIGRpcmVjdGx5IGZvciBlZmZpY2llbnQgYW5pbWF0ZWQgdXBkYXRlXG4gICAgICAgICAgICAgICAgdGhpcy52YWx1ZSA9IENhbnZhc0dhdWdlcy5Eb21PYnNlcnZlci5wYXJzZSh2YWwpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBjb25zdCBhdHRyTmFtZSA9IHRvS2ViYWJDYXNlKHByb3ApO1xuICAgICAgICAgICAgICAgIHRoaXMuZWwubmF0aXZlRWxlbWVudC5zZXRBdHRyaWJ1dGUoYXR0ck5hbWUsIHZhbCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFBlcmZvcm0gZ2F1Z2UgaW5pdGlhbGl6YXRpb24uXG4gICAgICogU3ViY2xhc3NlcyB0aGF0IG92ZXJyaWRlIHRoaXMgbWV0aG9kIG11c3QgdGhpcyBzdXBlciB2ZXJzaW9uXG4gICAgICogZm9yIHByb3BlciBvcGVyYXRpb24uXG4gICAgICovXG4gICAgcHVibGljIG5nQWZ0ZXJWaWV3SW5pdCgpIHtcblxuICAgICAgICAvLyBpbml0aWFsIHVwZGF0ZSBvZiBnYXVnZSBwcm9wZXJ0aWVzXG4gICAgICAgIHRoaXMuaW5pdEdhdWdlKCk7XG5cbiAgICAgICAgdGhpcy5saXN0ZW5Gb3JET01FdmVudHMoKTtcblxuICAgICAgICB0aGlzLmlzSW5pdGVkID0gdHJ1ZTtcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIExpc3RlbiBmb3IgYXR0cmlidXRlLWNoYW5nZSBldmVudHMgdGhhdCBhcmUgY3JlYXRlZCB3aGVuIHVwZGF0aW5nXG4gICAgICogdGhlIG9wdGlvbnMgb2YgdGhpcyBnYXVnZS5cbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgbGlzdGVuRm9yRE9NRXZlbnRzKCkge1xuICAgICAgICAvLyBMaXN0ZW4gdG8gZ2F1Z2UgZWxlbWVudCBmb3IgYXR0cmlidXRlIGNoYW5nZXNcbiAgICAgICAgLy8gQ29udmVydCBhbGwgY2hhbmdlZCBhdHRyaWJ0dWVzIGludG8gYSBHZW5lcmljT3B0aW9ucyBvciBzdWJjbGFzc1xuICAgICAgICAvLyBVcGRhdGUgdGhlIGdhdWdlIHdpdGggdGhlIG5ldyBvcHRpb25zLlxuICAgICAgICB0aGlzLmRvbUxpc3RlbmVyID1cbiAgICAgICAgICAgIFJ4LkRPTS5mcm9tTXV0YXRpb25PYnNlcnZlcih0aGlzLmVsLm5hdGl2ZUVsZW1lbnQsIHsgYXR0cmlidXRlczogdHJ1ZSB9KS5cbiAgICAgICAgICAgICAgICBzdWJzY3JpYmUoY2hhbmdlcyA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IG5ld09wdGlvbnMgPSB7fSBhcyBUMjtcbiAgICAgICAgICAgICAgICAgICAgY2hhbmdlcy5mb3JFYWNoKGNoYW5nZSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoJ2F0dHJpYnV0ZXMnID09PSBjaGFuZ2UudHlwZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGNvbnNvbGUubG9nKCdET00sIGNoYW5nZScsIGNoYW5nZS5hdHRyaWJ1dGVOYW1lKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdPcHRpb25zW2F0dHJpYnV0ZU5hbWUyUHJvcGVydHlOYW1lKGNoYW5nZS5hdHRyaWJ1dGVOYW1lKV0gPVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBDYW52YXNHYXVnZXMuRG9tT2JzZXJ2ZXIucGFyc2UoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmVsLm5hdGl2ZUVsZW1lbnQuZ2V0QXR0cmlidXRlKGNoYW5nZS5hdHRyaWJ1dGVOYW1lKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuYmFzaWNVcGRhdGUobmV3T3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBEaXNjb250aW51ZSBsaXN0ZW5pbmcgZm9yIGF0dHJpYnV0ZSBjaGFuZ2UgZXZlbnRzLlxuICAgICAqL1xuICAgIHByb3RlY3RlZCBzdG9wTGlzdGVuaW5nRm9yRE9NRXZlbnRzKCkge1xuICAgICAgICBpZiAodGhpcy5kb21MaXN0ZW5lcikge1xuICAgICAgICAgICAgdGhpcy5kb21MaXN0ZW5lci5kaXNjb25uZWN0KCk7XG4gICAgICAgICAgICB0aGlzLmRvbUxpc3RlbmVyID0gbnVsbDtcbiAgICAgICAgfVxuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogSW5pdGFsaXplIHRoZSBnYXVnZSB3aXRoIGFsbCBvcHRpb25zIGRlZmluZWQgYnkgYXR0cmlidXRlcyBhbmRcbiAgICAgKiBwYXJlbnQgY29tcG9uZW50IG9wdGlvbnMuXG4gICAgICovXG4gICAgcHJvdGVjdGVkIGluaXRHYXVnZSgpIHtcbiAgICAgICAgY29uc3Qgb3B0aW9ucyA9IHRoaXMub3B0aW9ucztcbiAgICAgICAgaWYgKHRoaXMucHJlSW5pdFZhbHVlKSB7XG4gICAgICAgICAgICBvcHRpb25zLnZhbHVlID0gdGhpcy5wcmVJbml0VmFsdWU7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBpbml0IG9wdGlvbnMucmVuZGVyVG8gaWYgbmVlZGVkXG4gICAgICAgIGlmICghb3B0aW9ucy5oYXNPd25Qcm9wZXJ0eSgncmVuZGVyVG8nKSB8fCAhb3B0aW9ucy5yZW5kZXJUbykge1xuICAgICAgICAgICAgb3B0aW9ucy5yZW5kZXJUbyA9IHRoaXMuY2FudmFzLm5hdGl2ZUVsZW1lbnQ7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLmJhc2ljVXBkYXRlKG9wdGlvbnMpO1xuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogUGVyZm9ybXMgdGhlIGdhdWdlIHVwZGF0ZSB1c2luZyB0aGUgY3VycmVudCBvcHRpb25zXG4gICAgICogQHBhcmFtIG9wdGlvbnMgIFRoZSBvcHRpb25zIGZvciB0aGUgZ3VhZ2VcbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgYmFzaWNVcGRhdGUob3B0aW9uczogVDIpIHtcblxuICAgICAgICAvLyB0cmVhdCB0aGUgdmFsdWUgcHJvcGVydHkgc3BlY2lhbCBhbmQgdXBkYXRlIGl0IHRocm91Z2ggdGhlXG4gICAgICAgIC8vIHZhbHVlIGdldHRlci5cbiAgICAgICAgaWYgKHR5cGVvZiBvcHRpb25zLnZhbHVlID09PSAnbnVtYmVyJykge1xuXG4gICAgICAgICAgICAvLyB1c2UgZ2F1Z2UgYXBpIGRpcmVjdGx5IGZvciBtb3N0IGVmZmljaWVudCB1cGRhdGUgbWV0aG9kXG4gICAgICAgICAgICB0aGlzLnZhbHVlID0gb3B0aW9ucy52YWx1ZTtcblxuICAgICAgICAgICAgLy8gZmlsdGVyIHZhbHVlIHByb3BlcnR5IGZyb20gb3B0aW9ucyB0byBhdm9pZCByZWR1bmRhbnRcbiAgICAgICAgICAgIC8vIHByb2Nlc3NpbmcgYnkgZ2F1Z2VcbiAgICAgICAgICAgIGRlbGV0ZSBvcHRpb25zLnZhbHVlO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gZG8gbm90aGluZyBpZiBubyBvcHRpb24gcHJvcGVydGllcyB0byB1cGRhdGVcbiAgICAgICAgaWYgKE9iamVjdC5rZXlzKG9wdGlvbnMpLmxlbmd0aCkge1xuICAgICAgICAgICAgdGhpcy5nYXVnZS51cGRhdGUob3B0aW9ucyk7XG4gICAgICAgIH1cbiAgICB9XG5cbn1cblxuXG5cbiJdfQ==