UNPKG

@noaestudio/forms

Version:

Dynamic forms extension for Covalent

331 lines (330 loc) 34.1 kB
/** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ import { Component, Input, ChangeDetectionStrategy, ChangeDetectorRef, ContentChildren, QueryList } from '@angular/core'; import { FormBuilder } from '@angular/forms'; import { TdDynamicFormsService } from './services/dynamic-forms.service'; import { TdDynamicFormsErrorTemplate } from './dynamic-element.component'; import { timer } from 'rxjs'; import { distinctUntilChanged } from 'rxjs/operators'; var TdDynamicFormsComponent = /** @class */ (function () { function TdDynamicFormsComponent(_formBuilder, _dynamicFormsService, _changeDetectorRef) { this._formBuilder = _formBuilder; this._dynamicFormsService = _dynamicFormsService; this._changeDetectorRef = _changeDetectorRef; this._renderedElements = []; this._templateMap = new Map(); this.changeFunc = (function (data) { return {}; }); this.dynamicForm = this._formBuilder.group({}); } Object.defineProperty(TdDynamicFormsComponent.prototype, "elements", { get: /** * @return {?} */ function () { return this._renderedElements; }, set: /** * elements: ITdDynamicElementConfig[] * JS Object that will render the elements depending on its config. * [name] property is required. * @param {?} elements * @return {?} */ function (elements) { if (elements) { this._elements = elements; } else { this._elements = []; } this._rerenderElements(); }, enumerable: true, configurable: true }); Object.defineProperty(TdDynamicFormsComponent.prototype, "form", { /** * Getter property for dynamic [FormGroup]. */ get: /** * Getter property for dynamic [FormGroup]. * @return {?} */ function () { return this.dynamicForm; }, enumerable: true, configurable: true }); Object.defineProperty(TdDynamicFormsComponent.prototype, "valid", { /** * Getter property for [valid] of dynamic [FormGroup]. */ get: /** * Getter property for [valid] of dynamic [FormGroup]. * @return {?} */ function () { if (this.dynamicForm) { return this.dynamicForm.valid; } return false; }, enumerable: true, configurable: true }); Object.defineProperty(TdDynamicFormsComponent.prototype, "value", { /** * Getter property for [value] of dynamic [FormGroup]. */ get: /** * Getter property for [value] of dynamic [FormGroup]. * @return {?} */ function () { if (this.dynamicForm) { return this.dynamicForm.value; } return {}; }, enumerable: true, configurable: true }); Object.defineProperty(TdDynamicFormsComponent.prototype, "errors", { /** * Getter property for [errors] of dynamic [FormGroup]. */ get: /** * Getter property for [errors] of dynamic [FormGroup]. * @return {?} */ function () { if (this.dynamicForm) { var /** @type {?} */ errors = {}; for (var /** @type {?} */ name_1 in this.dynamicForm.controls) { errors[name_1] = this.dynamicForm.controls[name_1].errors; } return errors; } return {}; }, enumerable: true, configurable: true }); Object.defineProperty(TdDynamicFormsComponent.prototype, "controls", { /** * Getter property for [controls] of dynamic [FormGroup]. */ get: /** * Getter property for [controls] of dynamic [FormGroup]. * @return {?} */ function () { if (this.dynamicForm) { return this.dynamicForm.controls; } return {}; }, enumerable: true, configurable: true }); /** * @param {?} a * @param {?} b * @return {?} */ TdDynamicFormsComponent.prototype.jsonEqual = /** * @param {?} a * @param {?} b * @return {?} */ function (a, b) { return JSON.stringify(a) === JSON.stringify(b); }; /** * @return {?} */ TdDynamicFormsComponent.prototype.ngAfterContentInit = /** * @return {?} */ function () { this._updateErrorTemplates(); this.startChangeFunc(); }; /** * @return {?} */ TdDynamicFormsComponent.prototype.startChangeFunc = /** * @return {?} */ function () { var _this = this; this.dynamicForm.valueChanges.pipe(distinctUntilChanged(function (a, b) { return _this.jsonEqual(a, b); })).subscribe(function (data) { var /** @type {?} */ otherData = _this.changeFunc(data); var _loop_1 = function (key) { var /** @type {?} */ elem = _this.elements.find(function (elem) { return elem.name == key; }); for (var /** @type {?} */ innerKey in otherData[key]) { elem[innerKey] = otherData[key][innerKey]; } }; for (var /** @type {?} */ key in otherData) { _loop_1(key); } }); }; /** * Refreshes the form and rerenders all validator/element modifications. */ /** * Refreshes the form and rerenders all validator/element modifications. * @return {?} */ TdDynamicFormsComponent.prototype.refresh = /** * Refreshes the form and rerenders all validator/element modifications. * @return {?} */ function () { this._rerenderElements(); this._updateErrorTemplates(); }; /** * Getter method for error template references */ /** * Getter method for error template references * @param {?} name * @return {?} */ TdDynamicFormsComponent.prototype.getErrorTemplateRef = /** * Getter method for error template references * @param {?} name * @return {?} */ function (name) { return this._templateMap.get(name); }; /** * Loads error templates and sets them in a map for faster access. * @return {?} */ TdDynamicFormsComponent.prototype._updateErrorTemplates = /** * Loads error templates and sets them in a map for faster access. * @return {?} */ function () { this._templateMap = new Map(); for (var /** @type {?} */ i = 0; i < this._errorTemplates.toArray().length; i++) { this._templateMap.set(this._errorTemplates.toArray()[i].tdDynamicFormsError, this._errorTemplates.toArray()[i].templateRef); } }; /** * @return {?} */ TdDynamicFormsComponent.prototype._rerenderElements = /** * @return {?} */ function () { var _this = this; this._clearRemovedElements(); this._renderedElements = []; var /** @type {?} */ duplicates = []; this._elements.forEach(function (elem) { _this._dynamicFormsService.validateDynamicElementName(elem.name); if (duplicates.indexOf(elem.name) > -1) { throw new Error("Dynamic element name: \"" + elem.name + "\" is duplicated"); } duplicates.push(elem.name); if (!_this.dynamicForm.get(elem.name)) { _this.dynamicForm.addControl(elem.name, _this._dynamicFormsService.createFormControl(elem)); } else { _this.dynamicForm.get(elem.name).setValidators(_this._dynamicFormsService.createValidators(elem)); } // copy objects so they are only changes when calling this method // copy objects so they are only changes when calling this method _this._renderedElements.push(Object.assign({}, elem)); }); // call a change detection since the whole form might change this._changeDetectorRef.detectChanges(); timer().toPromise().then(function () { // call a markForCheck so elements are rendered correctly in OnPush // call a markForCheck so elements are rendered correctly in OnPush _this._changeDetectorRef.markForCheck(); }); }; /** * @return {?} */ TdDynamicFormsComponent.prototype._clearRemovedElements = /** * @return {?} */ function () { var _this = this; for (var /** @type {?} */ i = 0; i < this._renderedElements.length; i++) { for (var /** @type {?} */ j = 0; j < this._elements.length; j++) { // check if the name of the element is still there removed if (this._renderedElements[i].name === this._elements[j].name) { delete this._renderedElements[i]; break; } } } // remove elements that were removed from the array this._renderedElements.forEach(function (elem) { _this.dynamicForm.removeControl(elem.name); }); }; TdDynamicFormsComponent.decorators = [ { type: Component, args: [{ selector: 'td-dynamic-forms', template: "<form [formGroup]=\"dynamicForm\" novalidate>\n\t<div class=\"td-dynamic-form-wrapper\">\n\t\t<ng-template let-element ngFor [ngForOf]=\"elements\">\n\t\t\t<div class=\"td-dynamic-element-wrapper\" *ngIf=\"!element.hidden\"\n\t\t\t\t[style.max-width.%]=\"element.flex ? element.flex : 100\"\n\t\t\t\t[style.flex]=\"'1 1 ' + (element.flex ? element.flex : 100) + '%'\"\n\t\t\t\t[style.-ms-flex]=\"'1 1 ' + (element.flex ? element.flex : 100) + '%'\"\n\t\t\t\t[style.-webkit-box-flex]=\"1\">\n\t\t\t\t<td-dynamic-element #dynamicElement *ngIf=\"dynamicForm.controls[element.name]\"\n\t\t\t\t\t[formControlName]=\"element.name\"\n\t\t\t\t\t[dynamicControl]=\"dynamicForm.controls[element.name]\"\n\t\t\t\t\t[id]=\"element.name\"\n\t\t\t\t\t[label]=\"element.label || element.name\"\n\t\t\t\t\t[type]=\"element.type\"\n\t\t\t\t\t[required]=\"element.required\"\n\t\t\t\t\t[hidden]=\"element.hidden\"\n\t\t\t\t\t[min]=\"element.min\"\n\t\t\t\t\t[max]=\"element.max\"\n\t\t\t\t\t[minLength]=\"element.minLength\"\n\t\t\t\t\t[maxLength]=\"element.maxLength\"\n\t\t\t\t\t[selections]=\"element.selections\"\n\t\t\t\t\t[selectComplex]=\"element.selectComplex\"\n\t\t\t\t\t[selectMultiple]=\"element.selectMultiple\"\n\t\t\t\t\t[searchable]=\"element.searchable\"\n\t\t\t\t\t[flex]=\"element.flex\"\n\t\t\t\t\t[translate]=\"element.translate\"\n\t\t\t\t\t[step]=\"element.step\"\n\t\t\t\t\t[treeItems]=\"element.treeItems\"\n\t\t\t\t\t[action]=\"element.action\"\n\t\t\t\t\t[schema]=\"element.schema\"\n\t\t\t\t\t[draggable]=\"element.draggable\"\n\t\t\t\t\t[extras]=\"element.extras\"\n\t\t\t\t\t[extraFields]=\"element.extraFields\"\n\t\t\t\t\t[chips]=\"element.chips\"\n\t\t\t\t>\n\t\t\t\t</td-dynamic-element>\n\t\t\t\t<div class=\"tc-red-600\"\n\t\t\t\t\t[style.font-size.%]=\"'70'\"\n\t\t\t\t\t[style.position]=\"'absolute'\"\n\t\t\t\t\t[style.bottom.px]=\"'10'\"\n\t\t\t\t\t*ngIf=\"getErrorTemplateRef(element.name) && dynamicForm.controls[element.name]?.errors\">\n\t\t\t\t\t<ng-template\n\t\t\t\t\t\t[ngTemplateOutlet]=\"getErrorTemplateRef(element.name)\"\n\t\t\t\t\t\t[ngTemplateOutletContext]=\"{control: dynamicForm.controls[element.name], errors: dynamicForm.controls[element.name]?.errors}\">\n\t\t\t\t\t</ng-template>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</ng-template>\n\t</div>\n\t<ng-content></ng-content>\n</form>\n", styles: [".td-dynamic-form-wrapper{-ms-flex-wrap:wrap;flex-wrap:wrap;box-sizing:border-box;display:-ms-flexbox;display:flex;-ms-flex-direction:row;flex-direction:row;-ms-flex-align:center;align-items:center;-ms-flex-line-pack:center;align-content:center;max-width:100%;-ms-flex-pack:start;justify-content:start}.td-dynamic-form-wrapper .td-dynamic-element-wrapper{max-height:100%;box-sizing:border-box;position:relative;padding:4px 4px 8px}"], changeDetection: ChangeDetectionStrategy.OnPush, },] }, ]; /** @nocollapse */ TdDynamicFormsComponent.ctorParameters = function () { return [ { type: FormBuilder, }, { type: TdDynamicFormsService, }, { type: ChangeDetectorRef, }, ]; }; TdDynamicFormsComponent.propDecorators = { "_errorTemplates": [{ type: ContentChildren, args: [TdDynamicFormsErrorTemplate,] },], "changeFunc": [{ type: Input, args: ['changeFunc',] },], "elements": [{ type: Input, args: ['elements',] },], }; return TdDynamicFormsComponent; }()); export { TdDynamicFormsComponent }; function TdDynamicFormsComponent_tsickle_Closure_declarations() { /** @type {!Array<{type: !Function, args: (undefined|!Array<?>)}>} */ TdDynamicFormsComponent.decorators; /** * @nocollapse * @type {function(): !Array<(null|{type: ?, decorators: (undefined|!Array<{type: !Function, args: (undefined|!Array<?>)}>)})>} */ TdDynamicFormsComponent.ctorParameters; /** @type {!Object<string,!Array<{type: !Function, args: (undefined|!Array<?>)}>>} */ TdDynamicFormsComponent.propDecorators; /** @type {?} */ TdDynamicFormsComponent.prototype._renderedElements; /** @type {?} */ TdDynamicFormsComponent.prototype._elements; /** @type {?} */ TdDynamicFormsComponent.prototype._templateMap; /** @type {?} */ TdDynamicFormsComponent.prototype._errorTemplates; /** @type {?} */ TdDynamicFormsComponent.prototype.dynamicForm; /** @type {?} */ TdDynamicFormsComponent.prototype.changeFunc; /** @type {?} */ TdDynamicFormsComponent.prototype._formBuilder; /** @type {?} */ TdDynamicFormsComponent.prototype._dynamicFormsService; /** @type {?} */ TdDynamicFormsComponent.prototype._changeDetectorRef; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZHluYW1pYy1mb3Jtcy5jb21wb25lbnQuanMiLCJzb3VyY2VSb290Ijoibmc6Ly9AY292YWxlbnQvZHluYW1pYy1mb3Jtcy8iLCJzb3VyY2VzIjpbImR5bmFtaWMtZm9ybXMuY29tcG9uZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7QUFBQSxPQUFPLEVBQUUsU0FBUyxFQUFFLEtBQUssRUFBRSx1QkFBdUIsRUFBRSxpQkFBaUIsRUFBRSxlQUFlLEVBQ2hFLFNBQVMsRUFBb0IsTUFBTSxlQUFlLENBQUM7QUFDekUsT0FBTyxFQUFhLFdBQVcsRUFBbUIsTUFBTSxnQkFBZ0IsQ0FBQztBQUV6RSxPQUFPLEVBQUUscUJBQXFCLEVBQTJCLE1BQU0sa0NBQWtDLENBQUM7QUFDbEcsT0FBTyxFQUFFLDJCQUEyQixFQUFFLE1BQU0sNkJBQTZCLENBQUM7QUFFMUUsT0FBTyxFQUFFLEtBQUssRUFBYyxNQUFNLE1BQU0sQ0FBQztBQUN6QyxPQUFPLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQzs7SUErSXBELGlDQUFvQixZQUF5QixFQUFVLG9CQUEyQyxFQUFVLGtCQUFxQztRQUE3SCxpQkFBWSxHQUFaLFlBQVksQ0FBYTtRQUFVLHlCQUFvQixHQUFwQixvQkFBb0IsQ0FBdUI7UUFBVSx1QkFBa0IsR0FBbEIsa0JBQWtCLENBQW1CO2lDQWxGMUYsRUFBRTs0QkFFSCxJQUFJLEdBQUcsRUFBNEI7MEJBS3BELENBQUMsVUFBQyxJQUFVLElBQU8sTUFBTSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUM7UUE0RXBFLElBQUksQ0FBQyxXQUFXLEdBQUcsSUFBSSxDQUFDLFlBQVksQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLENBQUM7S0FDL0M7MEJBckVHLDZDQUFROzs7O1FBUVo7WUFDRSxNQUFNLENBQUMsSUFBSSxDQUFDLGlCQUFpQixDQUFDO1NBQy9COzs7Ozs7OztrQkFWWSxRQUFtQztZQUM5QyxFQUFFLENBQUMsQ0FBQyxRQUFRLENBQUMsQ0FB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bnQiOlsiaW1wb3J0IHsgQ29tcG9uZW50LCBJbnB1dCwgQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3ksIENoYW5nZURldGVjdG9yUmVmLCBDb250ZW50Q2hpbGRyZW4sXHJcbiAgICAgICAgIFRlbXBsYXRlUmVmLCBRdWVyeUxpc3QsIEFmdGVyQ29udGVudEluaXQgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuaW1wb3J0IHsgRm9ybUdyb3VwLCBGb3JtQnVpbGRlciwgQWJzdHJhY3RDb250cm9sIH0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xyXG5cclxuaW1wb3J0IHsgVGREeW5hbWljRm9ybXNTZXJ2aWNlLCBJVGREeW5hbWljRWxlbWVudENvbmZpZyB9IGZyb20gJy4vc2VydmljZXMvZHluYW1pYy1mb3Jtcy5zZXJ2aWNlJztcclxuaW1wb3J0IHsgVGREeW5hbWljRm9ybXNFcnJvclRlbXBsYXRlIH0gZnJvbSAnLi9keW5hbWljLWVsZW1lbnQuY29tcG9uZW50JztcclxuXHJcbmltcG9ydCB7IHRpbWVyLCBPYnNlcnZhYmxlIH0gZnJvbSAncnhqcyc7XHJcbmltcG9ydCB7IGRpc3RpbmN0VW50aWxDaGFuZ2VkIH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xyXG5cclxuQENvbXBvbmVudCh7XHJcbiAgc2VsZWN0b3I6ICd0ZC1keW5hbWljLWZvcm1zJyxcclxuICB0ZW1wbGF0ZTogYDxmb3JtIFtmb3JtR3JvdXBdPVwiZHluYW1pY0Zvcm1cIiBub3ZhbGlkYXRlPlxyXG5cdDxkaXYgY2xhc3M9XCJ0ZC1keW5hbWljLWZvcm0td3JhcHBlclwiPlxyXG5cdFx0PG5nLXRlbXBsYXRlIGxldC1lbGVtZW50IG5nRm9yIFtuZ0Zvck9mXT1cImVsZW1lbnRzXCI+XHJcblx0XHRcdDxkaXYgY2xhc3M9XCJ0ZC1keW5hbWljLWVsZW1lbnQtd3JhcHBlclwiICpuZ0lmPVwiIWVsZW1lbnQuaGlkZGVuXCJcclxuXHRcdFx0XHRbc3R5bGUubWF4LXdpZHRoLiVdPVwiZWxlbWVudC5mbGV4ID8gZWxlbWVudC5mbGV4IDogMTAwXCJcclxuXHRcdFx0XHRbc3R5bGUuZmxleF09XCInMSAxICcgKyAoZWxlbWVudC5mbGV4ID8gZWxlbWVudC5mbGV4IDogMTAwKSArICclJ1wiXHJcblx0XHRcdFx0W3N0eWxlLi1tcy1mbGV4XT1cIicxIDEgJyArIChlbGVtZW50LmZsZXggPyBlbGVtZW50LmZsZXggOiAxMDApICsgJyUnXCJcclxuXHRcdFx0XHRbc3R5bGUuLXdlYmtpdC1ib3gtZmxleF09XCIxXCI+XHJcblx0XHRcdFx0PHRkLWR5bmFtaWMtZWxlbWVudCAjZHluYW1pY0VsZW1lbnQgKm5nSWY9XCJkeW5hbWljRm9ybS5jb250cm9sc1tlbGVtZW50Lm5hbWVdXCJcclxuXHRcdFx0XHRcdFtmb3JtQ29udHJvbE5hbWVdPVwiZWxlbWVudC5uYW1lXCJcclxuXHRcdFx0XHRcdFtkeW5hbWljQ29udHJvbF09XCJkeW5hbWljRm9ybS5jb250cm9sc1tlbGVtZW50Lm5hbWVdXCJcclxuXHRcdFx0XHRcdFtpZF09XCJlbGVtZW50Lm5hbWVcIlxyXG5cdFx0XHRcdFx0W2xhYmVsXT1cImVsZW1lbnQubGFiZWwgfHwgZWxlbWVudC5uYW1lXCJcclxuXHRcdFx0XHRcdFt0eXBlXT1cImVsZW1lbnQudHlwZVwiXHJcblx0XHRcdFx0XHRbcmVxdWlyZWRdPVwiZWxlbWVudC5yZXF1aXJlZFwiXHJcblx0XHRcdFx0XHRbaGlkZGVuXT1cImVsZW1lbnQuaGlkZGVuXCJcclxuXHRcdFx0XHRcdFttaW5dPVwiZWxlbWVudC5taW5cIlxyXG5cdFx0XHRcdFx0W21heF09XCJlbGVtZW50Lm1heFwiXHJcblx0XHRcdFx0XHRbbWluTGVuZ3RoXT1cImVsZW1lbnQubWluTGVuZ3RoXCJcclxuXHRcdFx0XHRcdFttYXhMZW5ndGhdPVwiZWxlbWVudC5tYXhMZW5ndGhcIlxyXG5cdFx0XHRcdFx0W3NlbGVjdGlvbnNdPVwiZWxlbWVudC5zZWxlY3Rpb25zXCJcclxuXHRcdFx0XHRcdFtzZWxlY3RDb21wbGV4XT1cImVsZW1lbnQuc2VsZWN0Q29tcGxleFwiXHJcblx0XHRcdFx0XHRbc2VsZWN0TXVsdGlwbGVdPVwiZWxlbWVudC5zZWxlY3RNdWx0aXBsZVwiXHJcblx0XHRcdFx0XHRbc2VhcmNoYWJsZV09XCJlbGVtZW50LnNlYXJjaGFibGVcIlxyXG5cdFx0XHRcdFx0W2ZsZXhdPVwiZWxlbWVudC5mbGV4XCJcclxuXHRcdFx0XHRcdFt0cmFuc2xhdGVdPVwiZWxlbWVudC50cmFuc2xhdGVcIlxyXG5cdFx0XHRcdFx0W3N0ZXBdPVwiZWxlbWVudC5zdGVwXCJcclxuXHRcdFx0XHRcdFt0cmVlSXRlbXNdPVwiZWxlbWVudC50cmVlSXRlbXNcIlxyXG5cdFx0XHRcdFx0W2FjdGlvbl09XCJlbGVtZW50LmFjdGlvblwiXHJcblx0XHRcdFx0XHRbc2NoZW1hXT1cImVsZW1lbnQuc2NoZW1hXCJcclxuXHRcdFx0XHRcdFtkcmFnZ2FibGVdPVwiZWxlbWVudC5kcmFnZ2FibGVcIlxyXG5cdFx0XHRcdFx0W2V4dHJhc109XCJlbGVtZW50LmV4dHJhc1wiXHJcblx0XHRcdFx0XHRbZXh0cmFGaWVsZHNdPVwiZWxlbWVudC5leHRyYUZpZWxkc1wiXHJcblx0XHRcdFx0XHRbY2hpcHNdPVwiZWxlbWVudC5jaGlwc1wiXHJcblx0XHRcdFx0PlxyXG5cdFx0XHRcdDwvdGQtZHluYW1pYy1lbGVtZW50PlxyXG5cdFx0XHRcdDxkaXYgY2xhc3M9XCJ0Yy1yZWQtNjAwXCJcclxuXHRcdFx0XHRcdFtzdHlsZS5mb250LXNpemUuJV09XCInNzAnXCJcclxuXHRcdFx0XHRcdFtzdHlsZS5wb3NpdGlvbl09XCInYWJzb2x1dGUnXCJcclxuXHRcdFx0XHRcdFtzdHlsZS5ib3R0b20ucHhdPVwiJzEwJ1wiXHJcblx0XHRcdFx0XHQqbmdJZj1cImdldEVycm9yVGVtcGxhdGVSZWYoZWxlbWVudC5uYW1lKSAmJiBkeW5hbWljRm9ybS5jb250cm9sc1tlbGVtZW50Lm5hbWVdPy5lcnJvcnNcIj5cclxuXHRcdFx0XHRcdDxuZy10ZW1wbGF0ZVxyXG5cdFx0XHRcdFx0XHRbbmdUZW1wbGF0ZU91dGxldF09XCJnZXRFcnJvclRlbXBsYXRlUmVmKGVsZW1lbnQubmFtZSlcIlxyXG5cdFx0XHRcdFx0XHRbbmdUZW1wbGF0ZU91dGxldENvbnRleHRdPVwie2NvbnRyb2w6IGR5bmFtaWNGb3JtLmNvbnRyb2xzW2VsZW1lbnQubmFtZV0sIGVycm9yczogZHluYW1pY0Zvcm0uY29udHJvbHNbZWxlbWVudC5uYW1lXT8uZXJyb3JzfVwiPlxyXG5cdFx0XHRcdFx0PC9uZy10ZW1wbGF0ZT5cclxuXHRcdFx0XHQ8L2Rpdj5cclxuXHRcdFx0PC9kaXY+XHJcblx0XHQ8L25nLXRlbXBsYXRlPlxyXG5cdDwvZGl2PlxyXG5cdDxuZy1jb250ZW50PjwvbmctY29udGVudD5cclxuPC9mb3JtPlxyXG5gLFxyXG4gIHN0eWxlczogW2AudGQtZHluYW1pYy1mb3JtLXdyYXBwZXJ7LW1zLWZsZXgtd3JhcDp3cmFwO2ZsZXgtd3JhcDp3cmFwO2JveC1zaXppbmc6Ym9yZGVyLWJveDtkaXNwbGF5Oi1tcy1mbGV4Ym94O2Rpc3BsYXk6ZmxleDstbXMtZmxleC1kaXJlY3Rpb246cm93O2ZsZXgtZGlyZWN0aW9uOnJvdzstbXMtZmxleC1hbGlnbjpjZW50ZXI7YWxpZ24taXRlbXM6Y2VudGVyOy1tcy1mbGV4LWxpbmUtcGFjazpjZW50ZXI7YWxpZ24tY29udGVudDpjZW50ZXI7bWF4LXdpZHRoOjEwMCU7LW1zLWZsZXgtcGFjazpzdGFydDtqdXN0aWZ5LWNvbnRlbnQ6c3RhcnR9LnRkLWR5bmFtaWMtZm9ybS13cmFwcGVyIC50ZC1keW5hbWljLWVsZW1lbnQtd3JhcHBlcnttYXgtaGVpZ2h0OjEwMCU7Ym94LXNpemluZzpib3JkZXItYm94O3Bvc2l0aW9uOnJlbGF0aXZlO3BhZGRpbmc6NHB4IDRweCA4cHh9YF0sXHJcbiAgY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2gsXHJcbn0pXHJcbmV4cG9ydCBjbGFzcyBUZER5bmFtaWNGb3Jtc0NvbXBvbmVudCBpbXBsZW1lbnRzIEFmdGVyQ29udGVudEluaXQge1xyXG5cclxuICBwcml2YXRlIF9yZW5kZXJlZEVsZW1lbnRzOiBJVGREeW5hbWljRWxlbWVudENvbmZpZ1tdID0gW107XHJcbiAgcHJpdmF0ZSBfZWxlbWVudHM6IElUZER5bmFtaWNFbGVtZW50Q29uZmlnW107XHJcbiAgcHJpdmF0ZSBfdGVtcGxhdGVNYXA6IE1hcDxzdHJpbmcsIFRlbXBsYXRlUmVmPGFueT4+ID0gbmV3IE1hcDxzdHJpbmcsIFRlbXBsYXRlUmVmPGFueT4+KCk7XHJcbiAgQENvbnRlbnRDaGlsZHJlbihUZER5bmFtaWNGb3Jtc0Vycm9yVGVtcGxhdGUpIF9lcnJvclRlbXBsYXRlczogUXVlcnlMaXN0PFRkRHluYW1pY0Zvcm1zRXJyb3JUZW1wbGF0ZT47XHJcbiAgZHluYW1pY0Zvcm06IEZvcm1Hcm91cDtcclxuXHJcbiAgQElucHV0KCdjaGFuZ2VGdW5jJylcclxuICBjaGFuZ2VGdW5jIDogKGRhdGE6IGFueSkgPT4gKCBhbnkpID0gKChkYXRhIDogYW55KSA9PiB7IHJldHVybiB7fTsgfSk7XHJcblxyXG4gIC8qKlxyXG4gICAqIGVsZW1lbnRzOiBJVGREeW5hbWljRWxlbWVudENvbmZpZ1tdXHJcbiAgICogSlMgT2JqZWN0IHRoYXQgd2lsbCByZW5kZXIgdGhlIGVsZW1lbnRzIGRlcGVuZGluZyBvbiBpdHMgY29uZmlnLlxyXG4gICAqIFtuYW1lXSBwcm9wZXJ0eSBpcyByZXF1aXJlZC5cclxuICAgKi9cclxuICBASW5wdXQoJ2VsZW1lbnRzJylcclxuICBzZXQgZWxlbWVudHMoZWxlbWVudHM6IElUZER5bmFtaWNFbGVtZW50Q29uZmlnW10pIHtcclxuICAgIGlmIChlbGVtZW50cykge1xyXG4gICAgICB0aGlzLl9lbGVtZW50cyA9IGVsZW1lbnRzO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgdGhpcy5fZWxlbWVudHMgPSBbXTtcclxuICAgIH1cclxuICAgIHRoaXMuX3JlcmVuZGVyRWxlbWVudHMoKTtcclxuICB9XHJcbiAgZ2V0IGVsZW1lbnRzKCk6IElUZER5bmFtaWNFbGVtZW50Q29uZmlnW10ge1xyXG4gICAgcmV0dXJuIHRoaXMuX3JlbmRlcmVkRWxlbWVudHM7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBHZXR0ZXIgcHJvcGVydHkgZm9yIGR5bmFtaWMgW0Zvcm1Hcm91cF0uXHJcbiAgICovXHJcbiAgZ2V0IGZvcm0oKTogRm9ybUdyb3VwIHtcclxuICAgIHJldHVybiB0aGlzLmR5bmFtaWNGb3JtO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogR2V0dGVyIHByb3BlcnR5IGZvciBbdmFsaWRdIG9mIGR5bmFtaWMgW0Zvcm1Hcm91cF0uXHJcbiAgICovXHJcbiAgZ2V0IHZhbGlkKCk6IGJvb2xlYW4ge1xyXG4gICAgaWYgKHRoaXMuZHluYW1pY0Zvcm0pIHtcclxuICAgICAgcmV0dXJuIHRoaXMuZHluYW1pY0Zvcm0udmFsaWQ7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gZmFsc2U7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBHZXR0ZXIgcHJvcGVydHkgZm9yIFt2YWx1ZV0gb2YgZHluYW1pYyBbRm9ybUdyb3VwXS5cclxuICAgKi9cclxuICBnZXQgdmFsdWUoKTogYW55IHtcclxuICAgIGlmICh0aGlzLmR5bmFtaWNGb3JtKSB7XHJcbiAgICAgIHJldHVybiB0aGlzLmR5bmFtaWNGb3JtLnZhbHVlO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIHt9O1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogR2V0dGVyIHByb3BlcnR5IGZvciBbZXJyb3JzXSBvZiBkeW5hbWljIFtGb3JtR3JvdXBdLlxyXG4gICAqL1xyXG4gIGdldCBlcnJvcnMoKTogeyBbbmFtZTogc3RyaW5nXTogYW55IH0ge1xyXG4gICAgaWYgKHRoaXMuZHluYW1pY0Zvcm0pIHtcclxuICAgICAgbGV0IGVycm9yczoge1tuYW1lOiBzdHJpbmddOiBhbnl9ID0ge307XHJcbiAgICAgIGZvciAobGV0IG5hbWUgaW4gdGhpcy5keW5hbWljRm9ybS5jb250cm9scykge1xyXG4gICAgICAgIGVycm9yc1tuYW1lXSA9IHRoaXMuZHluYW1pY0Zvcm0uY29udHJvbHNbbmFtZV0uZXJyb3JzO1xyXG4gICAgICB9XHJcbiAgICAgIHJldHVybiBlcnJvcnM7XHJcbiAgICB9XHJcbiAgICByZXR1cm4ge307XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBHZXR0ZXIgcHJvcGVydHkgZm9yIFtjb250cm9sc10gb2YgZHluYW1pYyBbRm9ybUdyb3VwXS5cclxuICAgKi9cclxuICBnZXQgY29udHJvbHMoKToge1trZXk6IHN0cmluZ106IEFic3RyYWN0Q29udHJvbH0ge1xyXG4gICAgaWYgKHRoaXMuZHluYW1pY0Zvcm0pIHtcclxuICAgICAgcmV0dXJuIHRoaXMuZHluYW1pY0Zvcm0uY29udHJvbHM7XHJcbiAgICB9XHJcbiAgICByZXR1cm4ge307XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGpzb25FcXVhbChhIDogYW55LCBiIDogYW55KSB7XHJcblx0ICByZXR1cm4gSlNPTi5zdHJpbmdpZnkoYSkgPT09IEpTT04uc3RyaW5naWZ5KGIpO1xyXG4gIH1cclxuXHJcbiAgY29uc3RydWN0b3IocHJpdmF0ZSBfZm9ybUJ1aWxkZXI6IEZvcm1CdWlsZGVyLCBwcml2YXRlIF9keW5hbWljRm9ybXNTZXJ2aWNlOiBUZER5bmFtaWNGb3Jtc1NlcnZpY2UsIHByaXZhdGUgX2NoYW5nZURldGVjdG9yUmVmOiBDaGFuZ2VEZXRlY3RvclJlZikge1xyXG5cdCAgdGhpcy5keW5hbWljRm9ybSA9IHRoaXMuX2Zvcm1CdWlsZGVyLmdyb3VwKHt9KTtcclxuICB9XHJcblxyXG4gIG5nQWZ0ZXJDb250ZW50SW5pdCgpOiB2b2lkIHtcclxuICAgIHRoaXMuX3VwZGF0ZUVycm9yVGVtcGxhdGVzKCk7XHJcblxyXG5cdHRoaXMuc3RhcnRDaGFuZ2VGdW5jKCk7XHJcblxyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBzdGFydENoYW5nZUZ1bmMoKSB7XHJcblx0ICB0aGlzLmR5bmFtaWNGb3JtLnZhbHVlQ2hhbmdlcy5waXBlKGRpc3RpbmN0VW50aWxDaGFuZ2VkKCAoYSwgYikgPT4gdGhpcy5qc29uRXF1YWwoYSxiKSkpLnN1YnNjcmliZSggZGF0YSA9PiB7XHJcbiAgXHRcdGxldCBvdGhlckRhdGEgPSB0aGlzLmNoYW5nZUZ1bmMoZGF0YSk7XHJcblxyXG4gIFx0XHRmb3IgKGxldCBrZXkgaW4gb3RoZXJEYXRhKSB7XHJcbiAgXHRcdFx0bGV0IGVsZW0gPSB0aGlzLmVsZW1lbnRzLmZpbmQoIGVsZW0gPT4geyByZXR1cm4gZWxlbS5uYW1lID09IGtleX0pO1xyXG4gIFx0XHRcdGZvciAobGV0IGlubmVyS2V5IGluIG90aGVyRGF0YVtrZXldKSB7XHJcbiAgXHRcdFx0XHRlbGVtW2lubmVyS2V5XSA9IG90aGVyRGF0YVtrZXldW2lubmVyS2V5XTtcclxuICBcdFx0XHR9XHJcbiAgXHRcdH1cclxuXHJcblx0fSk7XHJcblxyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogUmVmcmVzaGVzIHRoZSBmb3JtIGFuZCByZXJlbmRlcnMgYWxsIHZhbGlkYXRvci9lbGVtZW50IG1vZGlmaWNhdGlvbnMuXHJcbiAgICovXHJcbiAgcmVmcmVzaCgpOiB2b2lkIHtcclxuICAgIHRoaXMuX3JlcmVuZGVyRWxlbWVudHMoKTtcclxuICAgIHRoaXMuX3VwZGF0ZUVycm9yVGVtcGxhdGVzKCk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBHZXR0ZXIgbWV0aG9kIGZvciBlcnJvciB0ZW1wbGF0ZSByZWZlcmVuY2VzXHJcbiAgICovXHJcbiAgZ2V0RXJyb3JUZW1wbGF0ZVJlZihuYW1lOiBzdHJpbmcpOiBUZW1wbGF0ZVJlZjxhbnk+IHtcclxuICAgIHJldHVybiB0aGlzLl90ZW1wbGF0ZU1hcC5nZXQobmFtZSk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBMb2FkcyBlcnJvciB0ZW1wbGF0ZXMgYW5kIHNldHMgdGhlbSBpbiBhIG1hcCBmb3IgZmFzdGVyIGFjY2Vzcy5cclxuICAgKi9cclxuICBwcml2YXRlIF91cGRhdGVFcnJvclRlbXBsYXRlcygpOiB2b2lkIHtcclxuICAgIHRoaXMuX3RlbXBsYXRlTWFwID0gbmV3IE1hcDxzdHJpbmcsIFRlbXBsYXRlUmVmPGFueT4+KCk7XHJcbiAgICBmb3IgKGxldCBpOiBudW1iZXIgPSAwOyBpIDwgdGhpcy5fZXJyb3JUZW1wbGF0ZXMudG9BcnJheSgpLmxlbmd0aDsgaSsrKSB7XHJcbiAgICAgIHRoaXMuX3RlbXBsYXRlTWFwLnNldChcclxuICAgICAgICB0aGlzLl9lcnJvclRlbXBsYXRlcy50b0FycmF5KClbaV0udGREeW5hbWljRm9ybXNFcnJvcixcclxuICAgICAgICB0aGlzLl9lcnJvclRlbXBsYXRlcy50b0FycmF5KClbaV0udGVtcGxhdGVSZWYsXHJcbiAgICAgICk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIF9yZXJlbmRlckVsZW1lbnRzKCk6IHZvaWQge1xyXG4gICAgdGhpcy5fY2xlYXJSZW1vdmVkRWxlbWVudHMoKTtcclxuICAgIHRoaXMuX3JlbmRlcmVkRWxlbWVudHMgPSBbXTtcclxuICAgIGxldCBkdXBsaWNhdGVzOiBzdHJpbmdbXSA9IFtdO1xyXG4gICAgdGhpcy5fZWxlbWVudHMuZm9yRWFjaCgoZWxlbTogSVRkRHluYW1pY0VsZW1lbnRDb25maWcpID0+IHtcclxuICAgICAgdGhpcy5fZHluYW1pY0Zvcm1zU2VydmljZS52YWxpZGF0ZUR5bmFtaWNFbGVtZW50TmFtZShlbGVtLm5hbWUpO1xyXG4gICAgICBpZiAoZHVwbGljYXRlcy5pbmRleE9mKGVsZW0ubmFtZSkgPiAtMSkge1xyXG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgRHluYW1pYyBlbGVtZW50IG5hbWU6IFwiJHtlbGVtLm5hbWV9XCIgaXMgZHVwbGljYXRlZGApO1xyXG4gICAgICB9XHJcbiAgICAgIGR1cGxpY2F0ZXMucHVzaChlbGVtLm5hbWUpO1xyXG4gICAgICBpZiAoIXRoaXMuZHluYW1pY0Zvcm0uZ2V0KGVsZW0ubmFtZSkpIHtcclxuICAgICAgICB0aGlzLmR5bmFtaWNGb3JtLmFkZENvbnRyb2woZWxlbS5uYW1lLCB0aGlzLl9keW5hbWljRm9ybXNTZXJ2aWNlLmNyZWF0ZUZvcm1Db250cm9sKGVsZW0pKTtcclxuICAgICAgfSBlbHNlIHtcclxuICAgICAgICB0aGlzLmR5bmFtaWNGb3JtLmdldChlbGVtLm5hbWUpLnNldFZhbGlkYXRvcnModGhpcy5fZHluYW1pY0Zvcm1zU2VydmljZS5jcmVhdGVWYWxpZGF0b3JzKGVsZW0pKTtcclxuICAgICAgfVxyXG4gICAgICAvLyBjb3B5IG9iamVjdHMgc28gdGhleSBhcmUgb25seSBjaGFuZ2VzIHdoZW4gY2FsbGluZyB0aGlzIG1ldGhvZFxyXG4gICAgICB0aGlzLl9yZW5kZXJlZEVsZW1lbnRzLnB1c2goT2JqZWN0LmFzc2lnbih7fSwgZWxlbSkpO1xyXG4gICAgfSk7XHJcbiAgICAvLyBjYWxsIGEgY2hhbmdlIGRldGVjdGlvbiBzaW5jZSB0aGUgd2hvbGUgZm9ybSBtaWdodCBjaGFuZ2VcclxuICAgIHRoaXMuX2NoYW5nZURldGVjdG9yUmVmLmRldGVjdENoYW5nZXMoKTtcclxuICAgIHRpbWVyKCkudG9Qcm9taXNlKCkudGhlbigoKSA9PiB7XHJcbiAgICAgIC8vIGNhbGwgYSBtYXJrRm9yQ2hlY2sgc28gZWxlbWVudHMgYXJlIHJlbmRlcmVkIGNvcnJlY3RseSBpbiBPblB1c2hcclxuICAgICAgdGhpcy5fY2hhbmdlRGV0ZWN0b3JSZWYubWFya0ZvckNoZWNrKCk7XHJcbiAgICB9KTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgX2NsZWFyUmVtb3ZlZEVsZW1lbnRzKCk6IHZvaWQge1xyXG4gICAgZm9yIChsZXQgaTogbnVtYmVyID0gMDsgaSA8IHRoaXMuX3JlbmRlcmVkRWxlbWVudHMubGVuZ3RoOyBpKyspIHtcclxuICAgICAgZm9yIChsZXQgajogbnVtYmVyID0gMDsgaiA8IHRoaXMuX2VsZW1lbnRzLmxlbmd0aDsgaisrKSB7XHJcbiAgICAgICAgLy8gY2hlY2sgaWYgdGhlIG5hbWUgb2YgdGhlIGVsZW1lbnQgaXMgc3RpbGwgdGhlcmUgcmVtb3ZlZFxyXG4gICAgICAgIGlmICh0aGlzLl9yZW5kZXJlZEVsZW1lbnRzW2ldLm5hbWUgPT09IHRoaXMuX2VsZW1lbnRzW2pdLm5hbWUpIHtcclxuICAgICAgICAgIGRlbGV0ZSB0aGlzLl9yZW5kZXJlZEVsZW1lbnRzW2ldO1xyXG4gICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgICAvLyByZW1vdmUgZWxlbWVudHMgdGhhdCB3ZXJlIHJlbW92ZWQgZnJvbSB0aGUgYXJyYXlcclxuICAgIHRoaXMuX3JlbmRlcmVkRWxlbWVudHMuZm9yRWFjaCgoZWxlbTogSVRkRHluYW1pY0VsZW1lbnRDb25maWcpID0+IHtcclxuICAgICAgdGhpcy5keW5hbWljRm9ybS5yZW1vdmVDb250cm9sKGVsZW0ubmFtZSk7XHJcbiAgICB9KTtcclxuICB9XHJcbn1cclxuIl19