@noaestudio/forms
Version:
Dynamic forms extension for Covalent
302 lines (301 loc) • 30.4 kB
JavaScript
/**
* @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';
export class TdDynamicFormsComponent {
/**
* @param {?} _formBuilder
* @param {?} _dynamicFormsService
* @param {?} _changeDetectorRef
*/
constructor(_formBuilder, _dynamicFormsService, _changeDetectorRef) {
this._formBuilder = _formBuilder;
this._dynamicFormsService = _dynamicFormsService;
this._changeDetectorRef = _changeDetectorRef;
this._renderedElements = [];
this._templateMap = new Map();
this.changeFunc = ((data) => { return {}; });
this.dynamicForm = this._formBuilder.group({});
}
/**
* elements: ITdDynamicElementConfig[]
* JS Object that will render the elements depending on its config.
* [name] property is required.
* @param {?} elements
* @return {?}
*/
set elements(elements) {
if (elements) {
this._elements = elements;
}
else {
this._elements = [];
}
this._rerenderElements();
}
/**
* @return {?}
*/
get elements() {
return this._renderedElements;
}
/**
* Getter property for dynamic [FormGroup].
* @return {?}
*/
get form() {
return this.dynamicForm;
}
/**
* Getter property for [valid] of dynamic [FormGroup].
* @return {?}
*/
get valid() {
if (this.dynamicForm) {
return this.dynamicForm.valid;
}
return false;
}
/**
* Getter property for [value] of dynamic [FormGroup].
* @return {?}
*/
get value() {
if (this.dynamicForm) {
return this.dynamicForm.value;
}
return {};
}
/**
* Getter property for [errors] of dynamic [FormGroup].
* @return {?}
*/
get errors() {
if (this.dynamicForm) {
let /** @type {?} */ errors = {};
for (let /** @type {?} */ name in this.dynamicForm.controls) {
errors[name] = this.dynamicForm.controls[name].errors;
}
return errors;
}
return {};
}
/**
* Getter property for [controls] of dynamic [FormGroup].
* @return {?}
*/
get controls() {
if (this.dynamicForm) {
return this.dynamicForm.controls;
}
return {};
}
/**
* @param {?} a
* @param {?} b
* @return {?}
*/
jsonEqual(a, b) {
return JSON.stringify(a) === JSON.stringify(b);
}
/**
* @return {?}
*/
ngAfterContentInit() {
this._updateErrorTemplates();
this.startChangeFunc();
}
/**
* @return {?}
*/
startChangeFunc() {
this.dynamicForm.valueChanges.pipe(distinctUntilChanged((a, b) => this.jsonEqual(a, b))).subscribe(data => {
let /** @type {?} */ otherData = this.changeFunc(data);
for (let /** @type {?} */ key in otherData) {
let /** @type {?} */ elem = this.elements.find(elem => { return elem.name == key; });
for (let /** @type {?} */ innerKey in otherData[key]) {
elem[innerKey] = otherData[key][innerKey];
}
}
});
}
/**
* Refreshes the form and rerenders all validator/element modifications.
* @return {?}
*/
refresh() {
this._rerenderElements();
this._updateErrorTemplates();
}
/**
* Getter method for error template references
* @param {?} name
* @return {?}
*/
getErrorTemplateRef(name) {
return this._templateMap.get(name);
}
/**
* Loads error templates and sets them in a map for faster access.
* @return {?}
*/
_updateErrorTemplates() {
this._templateMap = new Map();
for (let /** @type {?} */ i = 0; i < this._errorTemplates.toArray().length; i++) {
this._templateMap.set(this._errorTemplates.toArray()[i].tdDynamicFormsError, this._errorTemplates.toArray()[i].templateRef);
}
}
/**
* @return {?}
*/
_rerenderElements() {
this._clearRemovedElements();
this._renderedElements = [];
let /** @type {?} */ duplicates = [];
this._elements.forEach((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
this._renderedElements.push(Object.assign({}, elem));
});
// call a change detection since the whole form might change
this._changeDetectorRef.detectChanges();
timer().toPromise().then(() => {
// call a markForCheck so elements are rendered correctly in OnPush
this._changeDetectorRef.markForCheck();
});
}
/**
* @return {?}
*/
_clearRemovedElements() {
for (let /** @type {?} */ i = 0; i < this._renderedElements.length; i++) {
for (let /** @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((elem) => {
this.dynamicForm.removeControl(elem.name);
});
}
}
TdDynamicFormsComponent.decorators = [
{ type: Component, args: [{
selector: 'td-dynamic-forms',
template: `<form [formGroup]="dynamicForm" novalidate>
<div class="td-dynamic-form-wrapper">
<ng-template let-element ngFor [ngForOf]="elements">
<div class="td-dynamic-element-wrapper" *ngIf="!element.hidden"
[style.max-width.%]="element.flex ? element.flex : 100"
[style.flex]="'1 1 ' + (element.flex ? element.flex : 100) + '%'"
[style.-ms-flex]="'1 1 ' + (element.flex ? element.flex : 100) + '%'"
[style.-webkit-box-flex]="1">
<td-dynamic-element #dynamicElement *ngIf="dynamicForm.controls[element.name]"
[formControlName]="element.name"
[dynamicControl]="dynamicForm.controls[element.name]"
[id]="element.name"
[label]="element.label || element.name"
[type]="element.type"
[required]="element.required"
[hidden]="element.hidden"
[min]="element.min"
[max]="element.max"
[minLength]="element.minLength"
[maxLength]="element.maxLength"
[selections]="element.selections"
[selectComplex]="element.selectComplex"
[selectMultiple]="element.selectMultiple"
[searchable]="element.searchable"
[flex]="element.flex"
[translate]="element.translate"
[step]="element.step"
[treeItems]="element.treeItems"
[action]="element.action"
[schema]="element.schema"
[draggable]="element.draggable"
[extras]="element.extras"
[extraFields]="element.extraFields"
[chips]="element.chips"
>
</td-dynamic-element>
<div class="tc-red-600"
[style.font-size.%]="'70'"
[style.position]="'absolute'"
[style.bottom.px]="'10'"
*ngIf="getErrorTemplateRef(element.name) && dynamicForm.controls[element.name]?.errors">
<ng-template
[ngTemplateOutlet]="getErrorTemplateRef(element.name)"
[ngTemplateOutletContext]="{control: dynamicForm.controls[element.name], errors: dynamicForm.controls[element.name]?.errors}">
</ng-template>
</div>
</div>
</ng-template>
</div>
<ng-content></ng-content>
</form>
`,
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 = () => [
{ type: FormBuilder, },
{ type: TdDynamicFormsService, },
{ type: ChangeDetectorRef, },
];
TdDynamicFormsComponent.propDecorators = {
"_errorTemplates": [{ type: ContentChildren, args: [TdDynamicFormsErrorTemplate,] },],
"changeFunc": [{ type: Input, args: ['changeFunc',] },],
"elements": [{ type: Input, args: ['elements',] },],
};
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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZHluYW1pYy1mb3Jtcy5jb21wb25lbnQuanMiLCJzb3VyY2VSb290Ijoibmc6Ly9AY292YWxlbnQvZHluYW1pYy1mb3Jtcy8iLCJzb3VyY2VzIjpbImR5bmFtaWMtZm9ybXMuY29tcG9uZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7QUFBQSxPQUFPLEVBQUUsU0FBUyxFQUFFLEtBQUssRUFBRSx1QkFBdUIsRUFBRSxpQkFBaUIsRUFBRSxlQUFlLEVBQ2hFLFNBQVMsRUFBb0IsTUFBTSxlQUFlLENBQUM7QUFDekUsT0FBTyxFQUFhLFdBQVcsRUFBbUIsTUFBTSxnQkFBZ0IsQ0FBQztBQUV6RSxPQUFPLEVBQUUscUJBQXFCLEVBQTJCLE1BQU0sa0NBQWtDLENBQUM7QUFDbEcsT0FBTyxFQUFFLDJCQUEyQixFQUFFLE1BQU0sNkJBQTZCLENBQUM7QUFFMUUsT0FBTyxFQUFFLEtBQUssRUFBYyxNQUFNLE1BQU0sQ0FBQztBQUN6QyxPQUFPLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQTJEdEQsTUFBTTs7Ozs7O0lBb0ZKLFlBQW9CLFlBQXlCLEVBQVUsb0JBQTJDLEVBQVUsa0JBQXFDO1FBQTdILGlCQUFZLEdBQVosWUFBWSxDQUFhO1FBQVUseUJBQW9CLEdBQXBCLG9CQUFvQixDQUF1QjtRQUFVLHVCQUFrQixHQUFsQixrQkFBa0IsQ0FBbUI7aUNBbEYxRixFQUFFOzRCQUVILElBQUksR0FBRyxFQUE0QjswQkFLcEQsQ0FBQyxDQUFDLElBQVUsRUFBRSxFQUFFLEdBQUcsTUFBTSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUM7UUE0RXBFLElBQUksQ0FBQyxXQUFXLEdBQUcsSUFBSSxDQUFDLFlBQVksQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLENBQUM7S0FDL0M7Ozs7Ozs7O1FBckVHLFFBQVEsQ0FBQyxRQUFtQztRQUM5QyxFQUFFLENBQUMsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDO1lBQ2IsSUFBSSxDQUFDLFNBQVMsR0FB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LENBQUMsRUFBRSxDQUFDLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQzs7Z0JBRXZELEVBQUUsQ0FBQyxDQUFDLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLEtBQUssSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO29CQUM5RCxPQUFPLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDLENBQUMsQ0FBQztvQkFDakMsS0FBSyxDQUFDO2lCQUNQO2FBQ0Y7U0FDRjs7UUFFRCxJQUFJLENBQUMsaUJBQWlCLENBQUMsT0FBTyxDQUFDLENBQUMsSUFBNkIsRUFBRSxFQUFFO1lBQy9ELElBQUksQ0FBQyxXQUFXLENBQUMsYUFBYSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztTQUMzQyxDQUFDLENBQUM7Ozs7WUExT04sU0FBUyxTQUFDO2dCQUNULFFBQVEsRUFBRSxrQkFBa0I7Z0JBQzVCLFFBQVEsRUFBRTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0NBbURYO2dCQUNDLE1BQU0sRUFBRSxDQUFDLGdiQUFnYixDQUFDO2dCQUMxYixlQUFlLEVBQUUsdUJBQXVCLENBQUMsTUFBTTthQUNoRDs7OztZQWhFbUIsV0FBVztZQUV0QixxQkFBcUI7WUFKc0IsaUJBQWlCOzs7Z0NBd0VsRSxlQUFlLFNBQUMsMkJBQTJCOzJCQUczQyxLQUFLLFNBQUMsWUFBWTt5QkFRbEIsS0FBSyxTQUFDLFVBQVUiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDb21wb25lbnQsIElucHV0LCBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneSwgQ2hhbmdlRGV0ZWN0b3JSZWYsIENvbnRlbnRDaGlsZHJlbixcclxuICAgICAgICAgVGVtcGxhdGVSZWYsIFF1ZXJ5TGlzdCwgQWZ0ZXJDb250ZW50SW5pdCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xyXG5pbXBvcnQgeyBGb3JtR3JvdXAsIEZvcm1CdWlsZGVyLCBBYnN0cmFjdENvbnRyb2wgfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XHJcblxyXG5pbXBvcnQgeyBUZER5bmFtaWNGb3Jtc1NlcnZpY2UsIElUZER5bmFtaWNFbGVtZW50Q29uZmlnIH0gZnJvbSAnLi9zZXJ2aWNlcy9keW5hbWljLWZvcm1zLnNlcnZpY2UnO1xyXG5pbXBvcnQgeyBUZER5bmFtaWNGb3Jtc0Vycm9yVGVtcGxhdGUgfSBmcm9tICcuL2R5bmFtaWMtZWxlbWVudC5jb21wb25lbnQnO1xyXG5cclxuaW1wb3J0IHsgdGltZXIsIE9ic2VydmFibGUgfSBmcm9tICdyeGpzJztcclxuaW1wb3J0IHsgZGlzdGluY3RVbnRpbENoYW5nZWQgfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XHJcblxyXG5AQ29tcG9uZW50KHtcclxuICBzZWxlY3RvcjogJ3RkLWR5bmFtaWMtZm9ybXMnLFxyXG4gIHRlbXBsYXRlOiBgPGZvcm0gW2Zvcm1Hcm91cF09XCJkeW5hbWljRm9ybVwiIG5vdmFsaWRhdGU+XHJcblx0PGRpdiBjbGFzcz1cInRkLWR5bmFtaWMtZm9ybS13cmFwcGVyXCI+XHJcblx0XHQ8bmctdGVtcGxhdGUgbGV0LWVsZW1lbnQgbmdGb3IgW25nRm9yT2ZdPVwiZWxlbWVudHNcIj5cclxuXHRcdFx0PGRpdiBjbGFzcz1cInRkLWR5bmFtaWMtZWxlbWVudC13cmFwcGVyXCIgKm5nSWY9XCIhZWxlbWVudC5oaWRkZW5cIlxyXG5cdFx0XHRcdFtzdHlsZS5tYXgtd2lkdGguJV09XCJlbGVtZW50LmZsZXggPyBlbGVtZW50LmZsZXggOiAxMDBcIlxyXG5cdFx0XHRcdFtzdHlsZS5mbGV4XT1cIicxIDEgJyArIChlbGVtZW50LmZsZXggPyBlbGVtZW50LmZsZXggOiAxMDApICsgJyUnXCJcclxuXHRcdFx0XHRbc3R5bGUuLW1zLWZsZXhdPVwiJzEgMSAnICsgKGVsZW1lbnQuZmxleCA/IGVsZW1lbnQuZmxleCA6IDEwMCkgKyAnJSdcIlxyXG5cdFx0XHRcdFtzdHlsZS4td2Via2l0LWJveC1mbGV4XT1cIjFcIj5cclxuXHRcdFx0XHQ8dGQtZHluYW1pYy1lbGVtZW50ICNkeW5hbWljRWxlbWVudCAqbmdJZj1cImR5bmFtaWNGb3JtLmNvbnRyb2xzW2VsZW1lbnQubmFtZV1cIlxyXG5cdFx0XHRcdFx0W2Zvcm1Db250cm9sTmFtZV09XCJlbGVtZW50Lm5hbWVcIlxyXG5cdFx0XHRcdFx0W2R5bmFtaWNDb250cm9sXT1cImR5bmFtaWNGb3JtLmNvbnRyb2xzW2VsZW1lbnQubmFtZV1cIlxyXG5cdFx0XHRcdFx0W2lkXT1cImVsZW1lbnQubmFtZVwiXHJcblx0XHRcdFx0XHRbbGFiZWxdPVwiZWxlbWVudC5sYWJlbCB8fCBlbGVtZW50Lm5hbWVcIlxyXG5cdFx0XHRcdFx0W3R5cGVdPVwiZWxlbWVudC50eXBlXCJcclxuXHRcdFx0XHRcdFtyZXF1aXJlZF09XCJlbGVtZW50LnJlcXVpcmVkXCJcclxuXHRcdFx0XHRcdFtoaWRkZW5dPVwiZWxlbWVudC5oaWRkZW5cIlxyXG5cdFx0XHRcdFx0W21pbl09XCJlbGVtZW50Lm1pblwiXHJcblx0XHRcdFx0XHRbbWF4XT1cImVsZW1lbnQubWF4XCJcclxuXHRcdFx0XHRcdFttaW5MZW5ndGhdPVwiZWxlbWVudC5taW5MZW5ndGhcIlxyXG5cdFx0XHRcdFx0W21heExlbmd0aF09XCJlbGVtZW50Lm1heExlbmd0aFwiXHJcblx0XHRcdFx0XHRbc2VsZWN0aW9uc109XCJlbGVtZW50LnNlbGVjdGlvbnNcIlxyXG5cdFx0XHRcdFx0W3NlbGVjdENvbXBsZXhdPVwiZWxlbWVudC5zZWxlY3RDb21wbGV4XCJcclxuXHRcdFx0XHRcdFtzZWxlY3RNdWx0aXBsZV09XCJlbGVtZW50LnNlbGVjdE11bHRpcGxlXCJcclxuXHRcdFx0XHRcdFtzZWFyY2hhYmxlXT1cImVsZW1lbnQuc2VhcmNoYWJsZVwiXHJcblx0XHRcdFx0XHRbZmxleF09XCJlbGVtZW50LmZsZXhcIlxyXG5cdFx0XHRcdFx0W3RyYW5zbGF0ZV09XCJlbGVtZW50LnRyYW5zbGF0ZVwiXHJcblx0XHRcdFx0XHRbc3RlcF09XCJlbGVtZW50LnN0ZXBcIlxyXG5cdFx0XHRcdFx0W3RyZWVJdGVtc109XCJlbGVtZW50LnRyZWVJdGVtc1wiXHJcblx0XHRcdFx0XHRbYWN0aW9uXT1cImVsZW1lbnQuYWN0aW9uXCJcclxuXHRcdFx0XHRcdFtzY2hlbWFdPVwiZWxlbWVudC5zY2hlbWFcIlxyXG5cdFx0XHRcdFx0W2RyYWdnYWJsZV09XCJlbGVtZW50LmRyYWdnYWJsZVwiXHJcblx0XHRcdFx0XHRbZXh0cmFzXT1cImVsZW1lbnQuZXh0cmFzXCJcclxuXHRcdFx0XHRcdFtleHRyYUZpZWxkc109XCJlbGVtZW50LmV4dHJhRmllbGRzXCJcclxuXHRcdFx0XHRcdFtjaGlwc109XCJlbGVtZW50LmNoaXBzXCJcclxuXHRcdFx0XHQ+XHJcblx0XHRcdFx0PC90ZC1keW5hbWljLWVsZW1lbnQ+XHJcblx0XHRcdFx0PGRpdiBjbGFzcz1cInRjLXJlZC02MDBcIlxyXG5cdFx0XHRcdFx0W3N0eWxlLmZvbnQtc2l6ZS4lXT1cIic3MCdcIlxyXG5cdFx0XHRcdFx0W3N0eWxlLnBvc2l0aW9uXT1cIidhYnNvbHV0ZSdcIlxyXG5cdFx0XHRcdFx0W3N0eWxlLmJvdHRvbS5weF09XCInMTAnXCJcclxuXHRcdFx0XHRcdCpuZ0lmPVwiZ2V0RXJyb3JUZW1wbGF0ZVJlZihlbGVtZW50Lm5hbWUpICYmIGR5bmFtaWNGb3JtLmNvbnRyb2xzW2VsZW1lbnQubmFtZV0/LmVycm9yc1wiPlxyXG5cdFx0XHRcdFx0PG5nLXRlbXBsYXRlXHJcblx0XHRcdFx0XHRcdFtuZ1RlbXBsYXRlT3V0bGV0XT1cImdldEVycm9yVGVtcGxhdGVSZWYoZWxlbWVudC5uYW1lKVwiXHJcblx0XHRcdFx0XHRcdFtuZ1RlbXBsYXRlT3V0bGV0Q29udGV4dF09XCJ7Y29udHJvbDogZHluYW1pY0Zvcm0uY29udHJvbHNbZWxlbWVudC5uYW1lXSwgZXJyb3JzOiBkeW5hbWljRm9ybS5jb250cm9sc1tlbGVtZW50Lm5hbWVdPy5lcnJvcnN9XCI+XHJcblx0XHRcdFx0XHQ8L25nLXRlbXBsYXRlPlxyXG5cdFx0XHRcdDwvZGl2PlxyXG5cdFx0XHQ8L2Rpdj5cclxuXHRcdDwvbmctdGVtcGxhdGU+XHJcblx0PC9kaXY+XHJcblx0PG5nLWNvbnRlbnQ+PC9uZy1jb250ZW50PlxyXG48L2Zvcm0+XHJcbmAsXHJcbiAgc3R5bGVzOiBbYC50ZC1keW5hbWljLWZvcm0td3JhcHBlcnstbXMtZmxleC13cmFwOndyYXA7ZmxleC13cmFwOndyYXA7Ym94LXNpemluZzpib3JkZXItYm94O2Rpc3BsYXk6LW1zLWZsZXhib3g7ZGlzcGxheTpmbGV4Oy1tcy1mbGV4LWRpcmVjdGlvbjpyb3c7ZmxleC1kaXJlY3Rpb246cm93Oy1tcy1mbGV4LWFsaWduOmNlbnRlcjthbGlnbi1pdGVtczpjZW50ZXI7LW1zLWZsZXgtbGluZS1wYWNrOmNlbnRlcjthbGlnbi1jb250ZW50OmNlbnRlcjttYXgtd2lkdGg6MTAwJTstbXMtZmxleC1wYWNrOnN0YXJ0O2p1c3RpZnktY29udGVudDpzdGFydH0udGQtZHluYW1pYy1mb3JtLXdyYXBwZXIgLnRkLWR5bmFtaWMtZWxlbWVudC13cmFwcGVye21heC1oZWlnaHQ6MTAwJTtib3gtc2l6aW5nOmJvcmRlci1ib3g7cG9zaXRpb246cmVsYXRpdmU7cGFkZGluZzo0cHggNHB4IDhweH1gXSxcclxuICBjaGFuZ2VEZXRlY3Rpb246IENoYW5nZURldGVjdGlvblN0cmF0ZWd5Lk9uUHVzaCxcclxufSlcclxuZXhwb3J0IGNsYXNzIFRkRHluYW1pY0Zvcm1zQ29tcG9uZW50IGltcGxlbWVudHMgQWZ0ZXJDb250ZW50SW5pdCB7XHJcblxyXG4gIHByaXZhdGUgX3JlbmRlcmVkRWxlbWVudHM6IElUZER5bmFtaWNFbGVtZW50Q29uZmlnW10gPSBbXTtcclxuICBwcml2YXRlIF9lbGVtZW50czogSVRkRHluYW1pY0VsZW1lbnRDb25maWdbXTtcclxuICBwcml2YXRlIF90ZW1wbGF0ZU1hcDogTWFwPHN0cmluZywgVGVtcGxhdGVSZWY8YW55Pj4gPSBuZXcgTWFwPHN0cmluZywgVGVtcGxhdGVSZWY8YW55Pj4oKTtcclxuICBAQ29udGVudENoaWxkcmVuKFRkRHluYW1pY0Zvcm1zRXJyb3JUZW1wbGF0ZSkgX2Vycm9yVGVtcGxhdGVzOiBRdWVyeUxpc3Q8VGREeW5hbWljRm9ybXNFcnJvclRlbXBsYXRlPjtcclxuICBkeW5hbWljRm9ybTogRm9ybUdyb3VwO1xyXG5cclxuICBASW5wdXQoJ2NoYW5nZUZ1bmMnKVxyXG4gIGNoYW5nZUZ1bmMgOiAoZGF0YTogYW55KSA9PiAoIGFueSkgPSAoKGRhdGEgOiBhbnkpID0+IHsgcmV0dXJuIHt9OyB9KTtcclxuXHJcbiAgLyoqXHJcbiAgICogZWxlbWVudHM6IElUZER5bmFtaWNFbGVtZW50Q29uZmlnW11cclxuICAgKiBKUyBPYmplY3QgdGhhdCB3aWxsIHJlbmRlciB0aGUgZWxlbWVudHMgZGVwZW5kaW5nIG9uIGl0cyBjb25maWcuXHJcbiAgICogW25hbWVdIHByb3BlcnR5IGlzIHJlcXVpcmVkLlxyXG4gICAqL1xyXG4gIEBJbnB1dCgnZWxlbWVudHMnKVxyXG4gIHNldCBlbGVtZW50cyhlbGVtZW50czogSVRkRHluYW1pY0VsZW1lbnRDb25maWdbXSkge1xyXG4gICAgaWYgKGVsZW1lbnRzKSB7XHJcbiAgICAgIHRoaXMuX2VsZW1lbnRzID0gZWxlbWVudHM7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICB0aGlzLl9lbGVtZW50cyA9IFtdO1xyXG4gICAgfVxyXG4gICAgdGhpcy5fcmVyZW5kZXJFbGVtZW50cygpO1xyXG4gIH1cclxuICBnZXQgZWxlbWVudHMoKTogSVRkRHluYW1pY0VsZW1lbnRDb25maWdbXSB7XHJcbiAgICByZXR1cm4gdGhpcy5fcmVuZGVyZWRFbGVtZW50cztcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIEdldHRlciBwcm9wZXJ0eSBmb3IgZHluYW1pYyBbRm9ybUdyb3VwXS5cclxuICAgKi9cclxuICBnZXQgZm9ybSgpOiBGb3JtR3JvdXAge1xyXG4gICAgcmV0dXJuIHRoaXMuZHluYW1pY0Zvcm07XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBHZXR0ZXIgcHJvcGVydHkgZm9yIFt2YWxpZF0gb2YgZHluYW1pYyBbRm9ybUdyb3VwXS5cclxuICAgKi9cclxuICBnZXQgdmFsaWQoKTogYm9vbGVhbiB7XHJcbiAgICBpZiAodGhpcy5keW5hbWljRm9ybSkge1xyXG4gICAgICByZXR1cm4gdGhpcy5keW5hbWljRm9ybS52YWxpZDtcclxuICAgIH1cclxuICAgIHJldHVybiBmYWxzZTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIEdldHRlciBwcm9wZXJ0eSBmb3IgW3ZhbHVlXSBvZiBkeW5hbWljIFtGb3JtR3JvdXBdLlxyXG4gICAqL1xyXG4gIGdldCB2YWx1ZSgpOiBhbnkge1xyXG4gICAgaWYgKHRoaXMuZHluYW1pY0Zvcm0pIHtcclxuICAgICAgcmV0dXJuIHRoaXMuZHluYW1pY0Zvcm0udmFsdWU7XHJcbiAgICB9XHJcbiAgICByZXR1cm4ge307XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBHZXR0ZXIgcHJvcGVydHkgZm9yIFtlcnJvcnNdIG9mIGR5bmFtaWMgW0Zvcm1Hcm91cF0uXHJcbiAgICovXHJcbiAgZ2V0IGVycm9ycygpOiB7IFtuYW1lOiBzdHJpbmddOiBhbnkgfSB7XHJcbiAgICBpZiAodGhpcy5keW5hbWljRm9ybSkge1xyXG4gICAgICBsZXQgZXJyb3JzOiB7W25hbWU6IHN0cmluZ106IGFueX0gPSB7fTtcclxuICAgICAgZm9yIChsZXQgbmFtZSBpbiB0aGlzLmR5bmFtaWNGb3JtLmNvbnRyb2xzKSB7XHJcbiAgICAgICAgZXJyb3JzW25hbWVdID0gdGhpcy5keW5hbWljRm9ybS5jb250cm9sc1tuYW1lXS5lcnJvcnM7XHJcbiAgICAgIH1cclxuICAgICAgcmV0dXJuIGVycm9ycztcclxuICAgIH1cclxuICAgIHJldHVybiB7fTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIEdldHRlciBwcm9wZXJ0eSBmb3IgW2NvbnRyb2xzXSBvZiBkeW5hbWljIFtGb3JtR3JvdXBdLlxyXG4gICAqL1xyXG4gIGdldCBjb250cm9scygpOiB7W2tleTogc3RyaW5nXTogQWJzdHJhY3RDb250cm9sfSB7XHJcbiAgICBpZiAodGhpcy5keW5hbWljRm9ybSkge1xyXG4gICAgICByZXR1cm4gdGhpcy5keW5hbWljRm9ybS5jb250cm9scztcclxuICAgIH1cclxuICAgIHJldHVybiB7fTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUganNvbkVxdWFsKGEgOiBhbnksIGIgOiBhbnkpIHtcclxuXHQgIHJldHVybiBKU09OLnN0cmluZ2lmeShhKSA9PT0gSlNPTi5zdHJpbmdpZnkoYik7XHJcbiAgfVxyXG5cclxuICBjb25zdHJ1Y3Rvcihwcml2YXRlIF9mb3JtQnVpbGRlcjogRm9ybUJ1aWxkZXIsIHByaXZhdGUgX2R5bmFtaWNGb3Jtc1NlcnZpY2U6IFRkRHluYW1pY0Zvcm1zU2VydmljZSwgcHJpdmF0ZSBfY2hhbmdlRGV0ZWN0b3JSZWY6IENoYW5nZURldGVjdG9yUmVmKSB7XHJcblx0ICB0aGlzLmR5bmFtaWNGb3JtID0gdGhpcy5fZm9ybUJ1aWxkZXIuZ3JvdXAoe30pO1xyXG4gIH1cclxuXHJcbiAgbmdBZnRlckNvbnRlbnRJbml0KCk6IHZvaWQge1xyXG4gICAgdGhpcy5fdXBkYXRlRXJyb3JUZW1wbGF0ZXMoKTtcclxuXHJcblx0dGhpcy5zdGFydENoYW5nZUZ1bmMoKTtcclxuXHJcbiAgfVxyXG5cclxuICBwcml2YXRlIHN0YXJ0Q2hhbmdlRnVuYygpIHtcclxuXHQgIHRoaXMuZHluYW1pY0Zvcm0udmFsdWVDaGFuZ2VzLnBpcGUoZGlzdGluY3RVbnRpbENoYW5nZWQoIChhLCBiKSA9PiB0aGlzLmpzb25FcXVhbChhLGIpKSkuc3Vic2NyaWJlKCBkYXRhID0+IHtcclxuICBcdFx0bGV0IG90aGVyRGF0YSA9IHRoaXMuY2hhbmdlRnVuYyhkYXRhKTtcclxuXHJcbiAgXHRcdGZvciAobGV0IGtleSBpbiBvdGhlckRhdGEpIHtcclxuICBcdFx0XHRsZXQgZWxlbSA9IHRoaXMuZWxlbWVudHMuZmluZCggZWxlbSA9PiB7IHJldHVybiBlbGVtLm5hbWUgPT0ga2V5fSk7XHJcbiAgXHRcdFx0Zm9yIChsZXQgaW5uZXJLZXkgaW4gb3RoZXJEYXRhW2tleV0pIHtcclxuICBcdFx0XHRcdGVsZW1baW5uZXJLZXldID0gb3RoZXJEYXRhW2tleV1baW5uZXJLZXldO1xyXG4gIFx0XHRcdH1cclxuICBcdFx0fVxyXG5cclxuXHR9KTtcclxuXHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBSZWZyZXNoZXMgdGhlIGZvcm0gYW5kIHJlcmVuZGVycyBhbGwgdmFsaWRhdG9yL2VsZW1lbnQgbW9kaWZpY2F0aW9ucy5cclxuICAgKi9cclxuICByZWZyZXNoKCk6IHZvaWQge1xyXG4gICAgdGhpcy5fcmVyZW5kZXJFbGVtZW50cygpO1xyXG4gICAgdGhpcy5fdXBkYXRlRXJyb3JUZW1wbGF0ZXMoKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIEdldHRlciBtZXRob2QgZm9yIGVycm9yIHRlbXBsYXRlIHJlZmVyZW5jZXNcclxuICAgKi9cclxuICBnZXRFcnJvclRlbXBsYXRlUmVmKG5hbWU6IHN0cmluZyk6IFRlbXBsYXRlUmVmPGFueT4ge1xyXG4gICAgcmV0dXJuIHRoaXMuX3RlbXBsYXRlTWFwLmdldChuYW1lKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIExvYWRzIGVycm9yIHRlbXBsYXRlcyBhbmQgc2V0cyB0aGVtIGluIGEgbWFwIGZvciBmYXN0ZXIgYWNjZXNzLlxyXG4gICAqL1xyXG4gIHByaXZhdGUgX3VwZGF0ZUVycm9yVGVtcGxhdGVzKCk6IHZvaWQge1xyXG4gICAgdGhpcy5fdGVtcGxhdGVNYXAgPSBuZXcgTWFwPHN0cmluZywgVGVtcGxhdGVSZWY8YW55Pj4oKTtcclxuICAgIGZvciAobGV0IGk6IG51bWJlciA9IDA7IGkgPCB0aGlzLl9lcnJvclRlbXBsYXRlcy50b0FycmF5KCkubGVuZ3RoOyBpKyspIHtcclxuICAgICAgdGhpcy5fdGVtcGxhdGVNYXAuc2V0KFxyXG4gICAgICAgIHRoaXMuX2Vycm9yVGVtcGxhdGVzLnRvQXJyYXkoKVtpXS50ZER5bmFtaWNGb3Jtc0Vycm9yLFxyXG4gICAgICAgIHRoaXMuX2Vycm9yVGVtcGxhdGVzLnRvQXJyYXkoKVtpXS50ZW1wbGF0ZVJlZixcclxuICAgICAgKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIHByaXZhdGUgX3JlcmVuZGVyRWxlbWVudHMoKTogdm9pZCB7XHJcbiAgICB0aGlzLl9jbGVhclJlbW92ZWRFbGVtZW50cygpO1xyXG4gICAgdGhpcy5fcmVuZGVyZWRFbGVtZW50cyA9IFtdO1xyXG4gICAgbGV0IGR1cGxpY2F0ZXM6IHN0cmluZ1tdID0gW107XHJcbiAgICB0aGlzLl9lbGVtZW50cy5mb3JFYWNoKChlbGVtOiBJVGREeW5hbWljRWxlbWVudENvbmZpZykgPT4ge1xyXG4gICAgICB0aGlzLl9keW5hbWljRm9ybXNTZXJ2aWNlLnZhbGlkYXRlRHluYW1pY0VsZW1lbnROYW1lKGVsZW0ubmFtZSk7XHJcbiAgICAgIGlmIChkdXBsaWNhdGVzLmluZGV4T2YoZWxlbS5uYW1lKSA+IC0xKSB7XHJcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBEeW5hbWljIGVsZW1lbnQgbmFtZTogXCIke2VsZW0ubmFtZX1cIiBpcyBkdXBsaWNhdGVkYCk7XHJcbiAgICAgIH1cclxuICAgICAgZHVwbGljYXRlcy5wdXNoKGVsZW0ubmFtZSk7XHJcbiAgICAgIGlmICghdGhpcy5keW5hbWljRm9ybS5nZXQoZWxlbS5uYW1lKSkge1xyXG4gICAgICAgIHRoaXMuZHluYW1pY0Zvcm0uYWRkQ29udHJvbChlbGVtLm5hbWUsIHRoaXMuX2R5bmFtaWNGb3Jtc1NlcnZpY2UuY3JlYXRlRm9ybUNvbnRyb2woZWxlbSkpO1xyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIHRoaXMuZHluYW1pY0Zvcm0uZ2V0KGVsZW0ubmFtZSkuc2V0VmFsaWRhdG9ycyh0aGlzLl9keW5hbWljRm9ybXNTZXJ2aWNlLmNyZWF0ZVZhbGlkYXRvcnMoZWxlbSkpO1xyXG4gICAgICB9XHJcbiAgICAgIC8vIGNvcHkgb2JqZWN0cyBzbyB0aGV5IGFyZSBvbmx5IGNoYW5nZXMgd2hlbiBjYWxsaW5nIHRoaXMgbWV0aG9kXHJcbiAgICAgIHRoaXMuX3JlbmRlcmVkRWxlbWVudHMucHVzaChPYmplY3QuYXNzaWduKHt9LCBlbGVtKSk7XHJcbiAgICB9KTtcclxuICAgIC8vIGNhbGwgYSBjaGFuZ2UgZGV0ZWN0aW9uIHNpbmNlIHRoZSB3aG9sZSBmb3JtIG1pZ2h0IGNoYW5nZVxyXG4gICAgdGhpcy5fY2hhbmdlRGV0ZWN0b3JSZWYuZGV0ZWN0Q2hhbmdlcygpO1xyXG4gICAgdGltZXIoKS50b1Byb21pc2UoKS50aGVuKCgpID0+IHtcclxuICAgICAgLy8gY2FsbCBhIG1hcmtGb3JDaGVjayBzbyBlbGVtZW50cyBhcmUgcmVuZGVyZWQgY29ycmVjdGx5IGluIE9uUHVzaFxyXG4gICAgICB0aGlzLl9jaGFuZ2VEZXRlY3RvclJlZi5tYXJrRm9yQ2hlY2soKTtcclxuICAgIH0pO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBfY2xlYXJSZW1vdmVkRWxlbWVudHMoKTogdm9pZCB7XHJcbiAgICBmb3IgKGxldCBpOiBudW1iZXIgPSAwOyBpIDwgdGhpcy5fcmVuZGVyZWRFbGVtZW50cy5sZW5ndGg7IGkrKykge1xyXG4gICAgICBmb3IgKGxldCBqOiBudW1iZXIgPSAwOyBqIDwgdGhpcy5fZWxlbWVudHMubGVuZ3RoOyBqKyspIHtcclxuICAgICAgICAvLyBjaGVjayBpZiB0aGUgbmFtZSBvZiB0aGUgZWxlbWVudCBpcyBzdGlsbCB0aGVyZSByZW1vdmVkXHJcbiAgICAgICAgaWYgKHRoaXMuX3JlbmRlcmVkRWxlbWVudHNbaV0ubmFtZSA9PT0gdGhpcy5fZWxlbWVudHNbal0ubmFtZSkge1xyXG4gICAgICAgICAgZGVsZXRlIHRoaXMuX3JlbmRlcmVkRWxlbWVudHNbaV07XHJcbiAgICAgICAgICBicmVhaztcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgIH1cclxuICAgIC8vIHJlbW92ZSBlbGVtZW50cyB0aGF0IHdlcmUgcmVtb3ZlZCBmcm9tIHRoZSBhcnJheVxyXG4gICAgdGhpcy5fcmVuZGVyZWRFbGVtZW50cy5mb3JFYWNoKChlbGVtOiBJVGREeW5hbWljRWxlbWVudENvbmZpZykgPT4ge1xyXG4gICAgICB0aGlzLmR5bmFtaWNGb3JtLnJlbW92ZUNvbnRyb2woZWxlbS5uYW1lKTtcclxuICAgIH0pO1xyXG4gIH1cclxufVxyXG4iXX0=