UNPKG

@nuarch/dynamic-forms

Version:

Teradata UI Platform Dynamic Forms Module

359 lines 37.6 kB
/** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingReturn,uselessCode} checked by tsc */ import { ChangeDetectionStrategy, ChangeDetectorRef, Component, ContentChildren, EventEmitter, Input, Output, QueryList, TemplateRef, ViewChildren, } from '@angular/core'; import { FormBuilder } from '@angular/forms'; import { TdMediaService } from '@covalent/core/media'; import { BehaviorSubject, Subject, timer } from 'rxjs'; import { distinctUntilChanged, takeUntil } from 'rxjs/operators'; import { TdDynamicFormsErrorTemplate } from './dynamic-element.component'; import { TdDynamicFormsService } from './services/dynamic-forms.service'; export class TdDynamicFormsComponent { /** * @param {?} _formBuilder * @param {?} _dynamicFormsService * @param {?} media * @param {?} _changeDetectorRef */ constructor(_formBuilder, _dynamicFormsService, media, _changeDetectorRef) { this._formBuilder = _formBuilder; this._dynamicFormsService = _dynamicFormsService; this.media = media; this._changeDetectorRef = _changeDetectorRef; this._renderedElements = []; this._templateMap = new Map(); this.destroySubscriptions = new Subject(); this.isSingleInGroupedForm = false; this.remove = new EventEmitter(); this.change = new EventEmitter(); this.smallScreen = false; this.dynamicForm = this._formBuilder.group({}); this.media.registerQuery('gt-sm') .pipe(distinctUntilChanged(), takeUntil(this.destroySubscriptions)) .subscribe((largeScreen) => { this.smallScreen = !largeScreen; this._changeDetectorRef.markForCheck(); }); } /** * @return {?} */ ngAfterViewInit() { if (!!this.nestedGroups) { this.nestedGroups.forEach((innerGroup) => { innerGroup.forms.changes.pipe(takeUntil(this.destroySubscriptions)).subscribe(() => { this.change.emit(); }); }); } } /** * 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) { /** @type {?} */ let nestedGroupsValid = !this.nestedGroups.some((nestedGroup) => { return !nestedGroup.valid; }); return this.dynamicForm.valid && nestedGroupsValid; } return false; } /** * @return {?} */ get touched() { if (this.dynamicForm) { /** @type {?} */ let nestedGroupsTouched = this.nestedGroups.some((nestedGroup) => { return nestedGroup.touched; }); return this.dynamicForm.touched || nestedGroupsTouched; } return false; } /** * @return {?} */ get dirty() { if (!!this.dynamicForm) { /** @type {?} */ let nestedGroupsDirty = !!this.nestedGroups ? this.nestedGroups.some((nestedGroup) => { return nestedGroup.dirty; }) : false; return this.dynamicForm.dirty || nestedGroupsDirty; } 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) { /** @type {?} */ let errors = {}; for (let 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 {}; } /** * @return {?} */ ngAfterContentInit() { this._updateErrorTemplates(); } /** * 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) { if (!this.templateRef) { return this._templateMap.get(name); } return this.templateRef; } /** * @param {?} element * @return {?} */ getStyle(element) { /** @type {?} */ const width = !this.smallScreen && element && element.flex && !this.isSingleInGroupedForm ? `${element.flex}%` : '100%'; return { 'max-width': width, 'flex': `1 1 ${width}`, '-ms-flex': `1 1 ${width}`, '-webkit-box-flex': 1, }; } /** * Render elements are the elements actually rendered. * Elements in different group may have different selections, so should update selections of render elements. * @param {?} elementName * @param {?} selections * @return {?} */ updateRenderElementSelections(elementName, selections) { /** @type {?} */ const elementToUpdate = this._renderedElements.find((renderElement) => { return renderElement.name === elementName; }); if (!!elementToUpdate) { if (elementToUpdate.selections instanceof BehaviorSubject) { elementToUpdate.selections.next(selections); } else { elementToUpdate.selections = selections; } } else { throw new Error(`Error: element of name ${elementName} does not exist`); } } /** * @return {?} */ removeGroup() { this.remove.emit(); } /** * @return {?} */ ngOnDestroy() { this.destroySubscriptions.next(); } /** * Loads error templates and sets them in a map for faster access. * @return {?} */ _updateErrorTemplates() { this._templateMap = new Map(); for (let 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 = []; /** @type {?} */ let 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); /** @type {?} */ let dynamicElement = this.dynamicForm.get(elem.name); if (!dynamicElement) { this.dynamicForm.addControl(elem.name, this._dynamicFormsService.createFormControl(elem)); } else { dynamicElement.setValue(elem.default); dynamicElement.markAsPristine(); dynamicElement.markAsUntouched(); if (elem.disabled) { dynamicElement.disable(); } else { dynamicElement.enable(); } dynamicElement.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 i = 0; i < this._renderedElements.length; i++) { for (let 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>\r\n <div class=\"td-dynamic-form-wrapper\">\r\n <ng-template let-element ngFor [ngForOf]=\"elements\">\r\n <div class=\"td-dynamic-element-wrapper\"\r\n [ngClass]=\"{'hidden': element.hidden}\"\r\n [ngStyle]=\"getStyle(element)\">\r\n <nu-dynamic-forms\r\n #nestedGroup\r\n *ngIf=\"element.type==='group'\"\r\n [elements]=\"[element]\"\r\n [templateRef]=\"templateRef\"\r\n (remove)=\"removeGroup()\">\r\n </nu-dynamic-forms>\r\n <td-dynamic-element\r\n #dynamicElement\r\n *ngIf=\"element.type!=='group' && dynamicForm.controls[element.name]\"\r\n [formControlName]=\"element.name\"\r\n [dynamicControl]=\"dynamicForm.controls[element.name]\"\r\n [id]=\"element.name\"\r\n [name]=\"element.name\"\r\n [label]=\"element.label || element.name\"\r\n [hint]=\"element.hint\"\r\n [type]=\"element.type\"\r\n [required]=\"element.required\"\r\n [min]=\"element.min\"\r\n [max]=\"element.max\"\r\n [minLength]=\"element.minLength\"\r\n [maxLength]=\"element.maxLength\"\r\n [selections]=\"element.selections\"\r\n [multiple]=\"element.multiple\"\r\n [errorMessageTemplate]=\"getErrorTemplateRef(element.name)\">\r\n </td-dynamic-element>\r\n </div>\r\n </ng-template>\r\n </div>\r\n <ng-content></ng-content>\r\n</form>\r\n", changeDetection: ChangeDetectionStrategy.OnPush, styles: [".td-dynamic-form-wrapper{-ms-flex-wrap:wrap;flex-wrap:wrap;box-sizing:border-box;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-ms-flex-line-pack:center;align-content:center;max-width:100%;-webkit-box-pack:start;-ms-flex-pack:start;justify-content:start}.td-dynamic-form-wrapper ::ng-deep .mat-form-field-infix{width:auto}.td-dynamic-form-wrapper ::ng-deep .td-dynamic-element-hint{font-size:75%;display:block}.td-dynamic-form-wrapper .td-dynamic-element-wrapper{max-height:100%;box-sizing:border-box;position:relative;padding:4px 4px 8px}.td-dynamic-form-wrapper .hidden{display:none}"] }] } ]; /** @nocollapse */ TdDynamicFormsComponent.ctorParameters = () => [ { type: FormBuilder }, { type: TdDynamicFormsService }, { type: TdMediaService }, { type: ChangeDetectorRef } ]; TdDynamicFormsComponent.propDecorators = { templateRef: [{ type: Input }], isSingleInGroupedForm: [{ type: Input }], _errorTemplates: [{ type: ContentChildren, args: [TdDynamicFormsErrorTemplate,] }], nestedGroups: [{ type: ViewChildren, args: ['nestedGroup',] }], remove: [{ type: Output }], change: [{ type: Output }], elements: [{ type: Input, args: ['elements',] }] }; if (false) { /** @type {?} */ TdDynamicFormsComponent.prototype._renderedElements; /** @type {?} */ TdDynamicFormsComponent.prototype._elements; /** @type {?} */ TdDynamicFormsComponent.prototype._templateMap; /** @type {?} */ TdDynamicFormsComponent.prototype.destroySubscriptions; /** @type {?} */ TdDynamicFormsComponent.prototype.templateRef; /** @type {?} */ TdDynamicFormsComponent.prototype.isSingleInGroupedForm; /** @type {?} */ TdDynamicFormsComponent.prototype._errorTemplates; /** @type {?} */ TdDynamicFormsComponent.prototype.nestedGroups; /** @type {?} */ TdDynamicFormsComponent.prototype.remove; /** @type {?} */ TdDynamicFormsComponent.prototype.change; /** @type {?} */ TdDynamicFormsComponent.prototype.dynamicForm; /** @type {?} */ TdDynamicFormsComponent.prototype.smallScreen; /** @type {?} */ TdDynamicFormsComponent.prototype._formBuilder; /** @type {?} */ TdDynamicFormsComponent.prototype._dynamicFormsService; /** @type {?} */ TdDynamicFormsComponent.prototype.media; /** @type {?} */ TdDynamicFormsComponent.prototype._changeDetectorRef; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZHluYW1pYy1mb3Jtcy5jb21wb25lbnQuanMiLCJzb3VyY2VSb290Ijoibmc6Ly9AbnVhcmNoL2R5bmFtaWMtZm9ybXMvIiwic291cmNlcyI6WyJkeW5hbWljLWZvcm1zLmNvbXBvbmVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7O0FBQUEsT0FBTyxFQUVMLHVCQUF1QixFQUN2QixpQkFBaUIsRUFDakIsU0FBUyxFQUNULGVBQWUsRUFBRSxZQUFZLEVBQzdCLEtBQUssRUFDTSxNQUFNLEVBQ2pCLFNBQVMsRUFDVCxXQUFXLEVBQ1gsWUFBWSxHQUNiLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFBbUIsV0FBVyxFQUFhLE1BQU0sZ0JBQWdCLENBQUM7QUFDekUsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBQ3RELE9BQU8sRUFBRSxlQUFlLEVBQWMsT0FBTyxFQUFFLEtBQUssRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUNuRSxPQUFPLEVBQUUsb0JBQW9CLEVBQUUsU0FBUyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDakUsT0FBTyxFQUFFLDJCQUEyQixFQUFFLE1BQU0sNkJBQTZCLENBQUM7QUFHMUUsT0FBTyxFQUEyQixxQkFBcUIsRUFBRSxNQUFNLGtDQUFrQyxDQUFDO0FBUWxHLE1BQU0sT0FBTyx1QkFBdUI7Ozs7Ozs7SUF5SGxDLFlBQW9CLFlBQXlCLEVBQ3pCLG9CQUEyQyxFQUMzQyxLQUFxQixFQUNyQixrQkFBcUM7UUFIckMsaUJBQVksR0FBWixZQUFZLENBQWE7UUFDekIseUJBQW9CLEdBQXBCLG9CQUFvQixDQUF1QjtRQUMzQyxVQUFLLEdBQUwsS0FBSyxDQUFnQjtRQUNyQix1QkFBa0IsR0FBbEIsa0JBQWtCLENBQW1CO1FBMUhqRCxzQkFBaUIsR0FBOEIsRUFBRSxDQUFDO1FBRWxELGlCQUFZLEdBQWtDLElBQUksR0FBRyxFQUE0QixDQUFDO1FBQ2xGLHlCQUFvQixHQUFrQixJQUFJLE9BQU8sRUFBUSxD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akMsdURBQW1EOztJQUNuRCx3Q0FBNkI7O0lBQzdCLHFEQUE2QyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XHJcbiAgQWZ0ZXJDb250ZW50SW5pdCwgQWZ0ZXJWaWV3SW5pdCxcclxuICBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneSxcclxuICBDaGFuZ2VEZXRlY3RvclJlZixcclxuICBDb21wb25lbnQsXHJcbiAgQ29udGVudENoaWxkcmVuLCBFdmVudEVtaXR0ZXIsXHJcbiAgSW5wdXQsXHJcbiAgT25EZXN0cm95LCBPdXRwdXQsXHJcbiAgUXVlcnlMaXN0LFxyXG4gIFRlbXBsYXRlUmVmLFxyXG4gIFZpZXdDaGlsZHJlbixcclxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuaW1wb3J0IHsgQWJzdHJhY3RDb250cm9sLCBGb3JtQnVpbGRlciwgRm9ybUdyb3VwIH0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xyXG5pbXBvcnQgeyBUZE1lZGlhU2VydmljZSB9IGZyb20gJ0Bjb3ZhbGVudC9jb3JlL21lZGlhJztcclxuaW1wb3J0IHsgQmVoYXZpb3JTdWJqZWN0LCBPYnNlcnZhYmxlLCBTdWJqZWN0LCB0aW1lciB9IGZyb20gJ3J4anMnO1xyXG5pbXBvcnQgeyBkaXN0aW5jdFVudGlsQ2hhbmdlZCwgdGFrZVVudGlsIH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xyXG5pbXBvcnQgeyBUZER5bmFtaWNGb3Jtc0Vycm9yVGVtcGxhdGUgfSBmcm9tICcuL2R5bmFtaWMtZWxlbWVudC5jb21wb25lbnQnO1xyXG5pbXBvcnQgeyBOdUR5bmFtaWNGb3Jtc0NvbXBvbmVudCB9IGZyb20gJy4vbnUtZHluYW1pYy1mb3Jtcy5jb21wb25lbnQnO1xyXG5cclxuaW1wb3J0IHsgSVRkRHluYW1pY0VsZW1lbnRDb25maWcsIFRkRHluYW1pY0Zvcm1zU2VydmljZSB9IGZyb20gJy4vc2VydmljZXMvZHluYW1pYy1mb3Jtcy5zZXJ2aWNlJztcclxuXHJcbkBDb21wb25lbnQoe1xyXG4gIHNlbGVjdG9yOiAndGQtZHluYW1pYy1mb3JtcycsXHJcbiAgdGVtcGxhdGVVcmw6ICcuL2R5bmFtaWMtZm9ybXMuY29tcG9uZW50Lmh0bWwnLFxyXG4gIHN0eWxlVXJsczogWycuL2R5bmFtaWMtZm9ybXMuY29tcG9uZW50LnNjc3MnXSxcclxuICBjaGFuZ2VEZXRlY3Rpb246IENoYW5nZURldGVjdGlvblN0cmF0ZWd5Lk9uUHVzaCxcclxufSlcclxuZXhwb3J0IGNsYXNzIFRkRHluYW1pY0Zvcm1zQ29tcG9uZW50IGltcGxlbWVudHMgQWZ0ZXJWaWV3SW5pdCwgQWZ0ZXJDb250ZW50SW5pdCwgT25EZXN0cm95IHtcclxuXHJcbiAgcHJpdmF0ZSBfcmVuZGVyZWRFbGVtZW50czogSVRkRHluYW1pY0VsZW1lbnRDb25maWdbXSA9IFtdO1xyXG4gIHByaXZhdGUgX2VsZW1lbnRzOiBJVGREeW5hbWljRWxlbWVudENvbmZpZ1tdO1xyXG4gIHByaXZhdGUgX3RlbXBsYXRlTWFwOiBNYXA8c3RyaW5nLCBUZW1wbGF0ZVJlZjxhbnk+PiA9IG5ldyBNYXA8c3RyaW5nLCBUZW1wbGF0ZVJlZjxhbnk+PigpO1xyXG4gIHByaXZhdGUgZGVzdHJveVN1YnNjcmlwdGlvbnM6IFN1YmplY3Q8dm9pZD4gPSBuZXcgU3ViamVjdDx2b2lkPigpO1xyXG5cclxuICBASW5wdXQoKSB0ZW1wbGF0ZVJlZjogVGVtcGxhdGVSZWY8VGREeW5hbWljRm9ybXNFcnJvclRlbXBsYXRlPjtcclxuICBASW5wdXQoKSBpc1NpbmdsZUluR3JvdXBlZEZvcm06IGJvb2xlYW4gPSBmYWxzZTtcclxuICBAQ29udGVudENoaWxkcmVuKFRkRHluYW1pY0Zvcm1zRXJyb3JUZW1wbGF0ZSkgX2Vycm9yVGVtcGxhdGVzOiBRdWVyeUxpc3Q8VGREeW5hbWljRm9ybXNFcnJvclRlbXBsYXRlPjtcclxuICBAVmlld0NoaWxkcmVuKCduZXN0ZWRHcm91cCcpIG5lc3RlZEdyb3VwczogUXVlcnlMaXN0PE51RHluYW1pY0Zvcm1zQ29tcG9uZW50PjtcclxuICBAT3V0cHV0KCkgcmVtb3ZlOiBFdmVudEVtaXR0ZXI8dm9pZD4gPSBuZXcgRXZlbnRFbWl0dGVyPHZvaWQ+KCk7XHJcbiAgQE91dHB1dCgpIGNoYW5nZTogRXZlbnRFbWl0dGVyPHZvaWQ+ID0gbmV3IEV2ZW50RW1pdHRlcjx2b2lkPigpO1xyXG4gIGR5bmFtaWNGb3JtOiBGb3JtR3JvdXA7XHJcbiAgc21hbGxTY3JlZW46IGJvb2xlYW4gPSBmYWxzZTtcclxuXHJcbiAgbmdBZnRlclZpZXdJbml0KCk6IHZvaWQge1xyXG4gICAgaWYgKCEhdGhpcy5uZXN0ZWRHcm91cHMpIHtcclxuICAgICAgdGhpcy5uZXN0ZWRHcm91cHMuZm9yRWFjaCgoaW5uZXJHcm91cDogTnVEeW5hbWljRm9ybXNDb21wb25lbnQpID0+IHtcclxuICAgICAgICBpbm5lckdyb3VwLmZvcm1zLmNoYW5nZXMucGlwZShcclxuICAgICAgICAgIHRha2VVbnRpbCh0aGlzLmRlc3Ryb3lTdWJzY3JpcHRpb25zKSxcclxuICAgICAgICApLnN1YnNjcmliZSgoKSA9PiB7XHJcbiAgICAgICAgICB0aGlzLmNoYW5nZS5lbWl0KCk7XHJcbiAgICAgICAgfSk7XHJcbiAgICAgIH0pO1xyXG4gICAgfVxyXG4gIH1cclxuICAvKipcclxuICAgKiBlbGVtZW50czogSVRkRHluYW1pY0VsZW1lbnRDb25maWdbXVxyXG4gICAqIEpTIE9iamVjdCB0aGF0IHdpbGwgcmVuZGVyIHRoZSBlbGVtZW50cyBkZXBlbmRpbmcgb24gaXRzIGNvbmZpZy5cclxuICAgKiBbbmFtZV0gcHJvcGVydHkgaXMgcmVxdWlyZWQuXHJcbiAgICovXHJcbiAgQElucHV0KCdlbGVtZW50cycpXHJcbiAgc2V0IGVsZW1lbnRzKGVsZW1lbnRzOiBJVGREeW5hbWljRWxlbWVudENvbmZpZ1tdKSB7XHJcbiAgICBpZiAoZWxlbWVudHMpIHtcclxuICAgICAgdGhpcy5fZWxlbWVudHMgPSBlbGVtZW50cztcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIHRoaXMuX2VsZW1lbnRzID0gW107XHJcbiAgICB9XHJcbiAgICB0aGlzLl9yZXJlbmRlckVsZW1lbnRzKCk7XHJcbiAgfVxyXG5cclxuICBnZXQgZWxlbWVudHMoKTogSVRkRHluYW1pY0VsZW1lbnRDb25maWdbXSB7XHJcbiAgICByZXR1cm4gdGhpcy5fcmVuZGVyZWRFbGVtZW50cztcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIEdldHRlciBwcm9wZXJ0eSBmb3IgZHluYW1pYyBbRm9ybUdyb3VwXS5cclxuICAgKi9cclxuICBnZXQgZm9ybSgpOiBGb3JtR3JvdXAge1xyXG4gICAgcmV0dXJuIHRoaXMuZHluYW1pY0Zvcm07XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBHZXR0ZXIgcHJvcGVydHkgZm9yIFt2YWxpZF0gb2YgZHluYW1pYyBbRm9ybUdyb3VwXS5cclxuICAgKi9cclxuICBnZXQgdmFsaWQoKTogYm9vbGVhbiB7XHJcbiAgICBpZiAodGhpcy5keW5hbWljRm9ybSkge1xyXG4gICAgICBsZXQgbmVzdGVkR3JvdXBzVmFsaWQ6IGJvb2xlYW4gPSAhdGhpcy5uZXN0ZWRHcm91cHMuc29tZSgobmVzdGVkR3JvdXA6IE51RHluYW1pY0Zvcm1zQ29tcG9uZW50KSA9PiB7XHJcbiAgICAgICAgcmV0dXJuICFuZXN0ZWRHcm91cC52YWxpZDtcclxuICAgICAgfSk7XHJcbiAgICAgIHJldHVybiB0aGlzLmR5bmFtaWNGb3JtLnZhbGlkICYmIG5lc3RlZEdyb3Vwc1ZhbGlkO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIGZhbHNlO1xyXG4gIH1cclxuXHJcbiAgZ2V0IHRvdWNoZWQoKTogYm9vbGVhbiB7XHJcbiAgICBpZih0aGlzLmR5bmFtaWNGb3JtKSB7XHJcbiAgICAgIGxldCBuZXN0ZWRHcm91cHNUb3VjaGVkOiBib29sZWFuID0gdGhpcy5uZXN0ZWRHcm91cHMuc29tZSgobmVzdGVkR3JvdXA6IE51RHluYW1pY0Zvcm1zQ29tcG9uZW50KSA9PiB7XHJcbiAgICAgICAgcmV0dXJuIG5lc3RlZEdyb3VwLnRvdWNoZWQ7XHJcbiAgICAgIH0pO1xyXG4gICAgICByZXR1cm4gdGhpcy5keW5hbWljRm9ybS50b3VjaGVkIHx8IG5lc3RlZEdyb3Vwc1RvdWNoZWQ7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gZmFsc2U7XHJcbiAgfVxyXG5cclxuICBnZXQgZGlydHkoKTogYm9vbGVhbiB7XHJcbiAgICBpZiAoISF0aGlzLmR5bmFtaWNGb3JtKSB7XHJcbiAgICAgIGxldCBuZXN0ZWRHcm91cHNEaXJ0eTogYm9vbGVhbiA9ICEhdGhpcy5uZXN0ZWRHcm91cHMgP1xyXG4gICAgICAgIHRoaXMubmVzdGVkR3JvdXBzLnNvbWUoKG5lc3RlZEdyb3VwOiBOdUR5bmFtaWNGb3Jtc0NvbXBvbmVudCkgPT4ge1xyXG4gICAgICAgICAgcmV0dXJuIG5lc3RlZEdyb3VwLmRpcnR5O1xyXG4gICAgICAgIH0pIDogZmFsc2U7XHJcbiAgICAgIHJldHVybiB0aGlzLmR5bmFtaWNGb3JtLmRpcnR5IHx8IG5lc3RlZEdyb3Vwc0RpcnR5O1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIGZhbHNlO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogR2V0dGVyIHByb3BlcnR5IGZvciBbdmFsdWVdIG9mIGR5bmFtaWMgW0Zvcm1Hcm91cF0uXHJcbiAgICovXHJcbiAgZ2V0IHZhbHVlKCk6IGFueSB7XHJcbiAgICBpZiAodGhpcy5keW5hbWljRm9ybSkge1xyXG4gICAgICByZXR1cm4gdGhpcy5keW5hbWljRm9ybS52YWx1ZTtcclxuICAgIH1cclxuICAgIHJldHVybiB7fTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIEdldHRlciBwcm9wZXJ0eSBmb3IgW2Vycm9yc10gb2YgZHluYW1pYyBbRm9ybUdyb3VwXS5cclxuICAgKi9cclxuICBnZXQgZXJyb3JzKCk6IHsgW25hbWU6IHN0cmluZ106IGFueSB9IHtcclxuICAgIGlmICh0aGlzLmR5bmFtaWNGb3JtKSB7XHJcbiAgICAgIGxldCBlcnJvcnM6IHsgW25hbWU6IHN0cmluZ106IGFueSB9ID0ge307XHJcbiAgICAgIGZvciAobGV0IG5hbWUgaW4gdGhpcy5keW5hbWljRm9ybS5jb250cm9scykge1xyXG4gICAgICAgIGVycm9yc1tuYW1lXSA9IHRoaXMuZHluYW1pY0Zvcm0uY29udHJvbHNbbmFtZV0uZXJyb3JzO1xyXG4gICAgICB9XHJcbiAgICAgIHJldHVybiBlcnJvcnM7XHJcbiAgICB9XHJcbiAgICByZXR1cm4ge307XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBHZXR0ZXIgcHJvcGVydHkgZm9yIFtjb250cm9sc10gb2YgZHluYW1pYyBbRm9ybUdyb3VwXS5cclxuICAgKi9cclxuICBnZXQgY29udHJvbHMoKTogeyBba2V5OiBzdHJpbmddOiBBYnN0cmFjdENvbnRyb2wgfSB7XHJcbiAgICBpZiAodGhpcy5keW5hbWljRm9ybSkge1xyXG4gICAgICByZXR1cm4gdGhpcy5keW5hbWljRm9ybS5jb250cm9scztcclxuICAgIH1cclxuICAgIHJldHVybiB7fTtcclxuICB9XHJcblxyXG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgX2Zvcm1CdWlsZGVyOiBGb3JtQnVpbGRlcixcclxuICAgICAgICAgICAgICBwcml2YXRlIF9keW5hbWljRm9ybXNTZXJ2aWNlOiBUZER5bmFtaWNGb3Jtc1NlcnZpY2UsXHJcbiAgICAgICAgICAgICAgcHJpdmF0ZSBtZWRpYTogVGRNZWRpYVNlcnZpY2UsXHJcbiAgICAgICAgICAgICAgcHJpdmF0ZSBfY2hhbmdlRGV0ZWN0b3JSZWY6IENoYW5nZURldGVjdG9yUmVmKSB7XHJcbiAgICB0aGlzLmR5bmFtaWNGb3JtID0gdGhpcy5fZm9ybUJ1aWxkZXIuZ3JvdXAoe30pO1xyXG5cclxuICAgIHRoaXMubWVkaWEucmVnaXN0ZXJRdWVyeSgnZ3Qtc20nKVxyXG4gICAgLnBpcGUoZGlzdGluY3RVbnRpbENoYW5nZWQoKSwgdGFrZVVudGlsKHRoaXMuZGVzdHJveVN1YnNjcmlwdGlvbnMpKVxyXG4gICAgLnN1YnNjcmliZSgobGFyZ2VTY3JlZW46IGJvb2xlYW4pID0+IHtcclxuICAgICAgdGhpcy5zbWFsbFNjcmVlbiA9ICFsYXJnZVNjcmVlbjtcclxuICAgICAgdGhpcy5fY2hhbmdlRGV0ZWN0b3JSZWYubWFya0ZvckNoZWNrKCk7XHJcbiAgICB9KTtcclxuICB9XHJcblxyXG4gIG5nQWZ0ZXJDb250ZW50SW5pdCgpOiB2b2lkIHtcclxuICAgIHRoaXMuX3VwZGF0ZUVycm9yVGVtcGxhdGVzKCk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBSZWZyZXNoZXMgdGhlIGZvcm0gYW5kIHJlcmVuZGVycyBhbGwgdmFsaWRhdG9yL2VsZW1lbnQgbW9kaWZpY2F0aW9ucy5cclxuICAgKi9cclxuICByZWZyZXNoKCk6IHZvaWQge1xyXG4gICAgdGhpcy5fcmVyZW5kZXJFbGVtZW50cygpO1xyXG4gICAgdGhpcy5fdXBkYXRlRXJyb3JUZW1wbGF0ZXMoKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIEdldHRlciBtZXRob2QgZm9yIGVycm9yIHRlbXBsYXRlIHJlZmVyZW5jZXNcclxuICAgKi9cclxuICBnZXRFcnJvclRlbXBsYXRlUmVmKG5hbWU6IHN0cmluZyk6IFRlbXBsYXRlUmVmPGFueT4ge1xyXG4gICAgaWYgKCF0aGlzLnRlbXBsYXRlUmVmKSB7XHJcbiAgICAgIHJldHVybiB0aGlzLl90ZW1wbGF0ZU1hcC5nZXQobmFtZSk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gdGhpcy50ZW1wbGF0ZVJlZjtcclxuICB9XHJcblxyXG4gIGdldFN0eWxlKGVsZW1lbnQ6IElUZER5bmFtaWNFbGVtZW50Q29uZmlnKTogYW55IHtcclxuICAgIGNvbnN0IHdpZHRoOiBzdHJpbmcgPSAhdGhpcy5zbWFsbFNjcmVlbiAmJiBlbGVtZW50ICYmIGVsZW1lbnQuZmxleCAmJiAhdGhpcy5pc1NpbmdsZUluR3JvdXBlZEZvcm0gPyBgJHtlbGVtZW50LmZsZXh9JWAgOiAnMTAwJSc7XHJcblxyXG4gICAgcmV0dXJuIHtcclxuICAgICAgJ21heC13aWR0aCc6IHdpZHRoLFxyXG4gICAgICAnZmxleCc6IGAxIDEgJHt3aWR0aH1gLFxyXG4gICAgICAnLW1zLWZsZXgnOiBgMSAxICR7d2lkdGh9YCxcclxuICAgICAgJy13ZWJraXQtYm94LWZsZXgnOiAxLFxyXG4gICAgfTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIFJlbmRlciBlbGVtZW50cyBhcmUgdGhlIGVsZW1lbnRzIGFjdHVhbGx5IHJlbmRlcmVkLlxyXG4gICAqIEVsZW1lbnRzIGluIGRpZmZlcmVudCBncm91cCBtYXkgaGF2ZSBkaWZmZXJlbnQgc2VsZWN0aW9ucywgc28gc2hvdWxkIHVwZGF0ZSBzZWxlY3Rpb25zIG9mIHJlbmRlciBlbGVtZW50cy5cclxuICAgKiBAcGFyYW0gZWxlbWVudE5hbWVcclxuICAgKiBAcGFyYW0gc2VsZWN0aW9uc1xyXG4gICAqL1xyXG4gIHVwZGF0ZVJlbmRlckVsZW1lbnRTZWxlY3Rpb25zKGVsZW1lbnROYW1lOiBzdHJpbmcsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VsZWN0aW9uczogc3RyaW5nW10gfCB7IHZhbHVlOiBhbnksIGxhYmVsOiBzdHJpbmcsIGRlbGV0ZWQ/OiBib29sZWFuIH1bXSk6IHZvaWQge1xyXG4gICAgY29uc3QgZWxlbWVudFRvVXBkYXRlOiBJVGREeW5hbWljRWxlbWVudENvbmZpZyA9IHRoaXMuX3JlbmRlcmVkRWxlbWVudHMuZmluZCgocmVuZGVyRWxlbWVudDogSVRkRHluYW1pY0VsZW1lbnRDb25maWcpID0+IHtcclxuICAgICAgcmV0dXJuIHJlbmRlckVsZW1lbnQubmFtZSA9PT0gZWxlbWVudE5hbWU7XHJcbiAgICB9KTtcclxuXHJcbiAgICBpZiAoISFlbGVtZW50VG9VcGRhdGUpIHtcclxuICAgICAgaWYgKGVsZW1lbnRUb1VwZGF0ZS5zZWxlY3Rpb25zIGluc3RhbmNlb2YgQmVoYXZpb3JTdWJqZWN0KSB7XHJcbiAgICAgICAgZWxlbWVudFRvVXBkYXRlLnNlbGVjdGlvbnMubmV4dChzZWxlY3Rpb25zKTtcclxuICAgICAgfSBlbHNlIHtcclxuICAgICAgICBlbGVtZW50VG9VcGRhdGUuc2VsZWN0aW9ucyA9IHNlbGVjdGlvbnM7XHJcbiAgICAgIH1cclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIHRocm93IG5ldyBFcnJvcihgRXJyb3I6IGVsZW1lbnQgb2YgbmFtZSAke2VsZW1lbnROYW1lfSBkb2VzIG5vdCBleGlzdGApO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgcmVtb3ZlR3JvdXAoKTogdm9pZCB7XHJcbiAgICB0aGlzLnJlbW92ZS5lbWl0KCk7XHJcbiAgfVxyXG5cclxuICBuZ09uRGVzdHJveSgpOiB2b2lkIHtcclxuICAgIHRoaXMuZGVzdHJveVN1YnNjcmlwdGlvbnMubmV4dCgpO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogTG9hZHMgZXJyb3IgdGVtcGxhdGVzIGFuZCBzZXRzIHRoZW0gaW4gYSBtYXAgZm9yIGZhc3RlciBhY2Nlc3MuXHJcbiAgICovXHJcbiAgcHJpdmF0ZSBfdXBkYXRlRXJyb3JUZW1wbGF0ZXMoKTogdm9pZCB7XHJcbiAgICB0aGlzLl90ZW1wbGF0ZU1hcCA9IG5ldyBNYXA8c3RyaW5nLCBUZW1wbGF0ZVJlZjxhbnk+PigpO1xyXG4gICAgZm9yIChsZXQgaTogbnVtYmVyID0gMDsgaSA8IHRoaXMuX2Vycm9yVGVtcGxhdGVzLnRvQXJyYXkoKS5sZW5ndGg7IGkrKykge1xyXG4gICAgICB0aGlzLl90ZW1wbGF0ZU1hcC5zZXQoXHJcbiAgICAgICAgdGhpcy5fZXJyb3JUZW1wbGF0ZXMudG9BcnJheSgpW2ldLnRkRHluYW1pY0Zvcm1zRXJyb3IsXHJcbiAgICAgICAgdGhpcy5fZXJyb3JUZW1wbGF0ZXMudG9BcnJheSgpW2ldLnRlbXBsYXRlUmVmLFxyXG4gICAgICApO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBfcmVyZW5kZXJFbGVtZW50cygpOiB2b2lkIHtcclxuICAgIHRoaXMuX2NsZWFyUmVtb3ZlZEVsZW1lbnRzKCk7XHJcbiAgICB0aGlzLl9yZW5kZXJlZEVsZW1lbnRzID0gW107XHJcbiAgICBsZXQgZHVwbGljYXRlczogc3RyaW5nW10gPSBbXTtcclxuICAgIHRoaXMuX2VsZW1lbnRzLmZvckVhY2goKGVsZW06IElUZER5bmFtaWNFbGVtZW50Q29uZmlnKSA9PiB7XHJcbiAgICAgIHRoaXMuX2R5bmFtaWNGb3Jtc1NlcnZpY2UudmFsaWRhdGVEeW5hbWljRWxlbWVudE5hbWUoZWxlbS5uYW1lKTtcclxuICAgICAgaWYgKGR1cGxpY2F0ZXMuaW5kZXhPZihlbGVtLm5hbWUpID4gLTEpIHtcclxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYER5bmFtaWMgZWxlbWVudCBuYW1lOiBcIiR7ZWxlbS5uYW1lfVwiIGlzIGR1cGxpY2F0ZWRgKTtcclxuICAgICAgfVxyXG4gICAgICBkdXBsaWNhdGVzLnB1c2goZWxlbS5uYW1lKTtcclxuICAgICAgbGV0IGR5bmFtaWNFbGVtZW50OiBBYnN0cmFjdENvbnRyb2wgPSB0aGlzLmR5bmFtaWNGb3JtLmdldChlbGVtLm5hbWUpO1xyXG4gICAgICBpZiAoIWR5bmFtaWNFbGVtZW50KSB7XHJcbiAgICAgICAgdGhpcy5keW5hbWljRm9ybS5hZGRDb250cm9sKGVsZW0ubmFtZSwgdGhpcy5fZHluYW1pY0Zvcm1zU2VydmljZS5jcmVhdGVGb3JtQ29udHJvbChlbGVtKSk7XHJcbiAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgZHluYW1pY0VsZW1lbnQuc2V0VmFsdWUoZWxlbS5kZWZhdWx0KTtcclxuICAgICAgICBkeW5hbWljRWxlbWVudC5tYXJrQXNQcmlzdGluZSgpO1xyXG4gICAgICAgIGR5bmFtaWNFbGVtZW50Lm1hcmtBc1VudG91Y2hlZCgpO1xyXG4gICAgICAgIGlmIChlbGVtLmRpc2FibGVkKSB7XHJcbiAgICAgICAgICBkeW5hbWljRWxlbWVudC5kaXNhYmxlKCk7XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgIGR5bmFtaWNFbGVtZW50LmVuYWJsZSgpO1xyXG4gICAgICAgIH1cclxuICAgICAgICBkeW5hbWljRWxlbWVudC5zZXRWYWxpZGF0b3JzKHRoaXMuX2R5bmFtaWNGb3Jtc1NlcnZpY2UuY3JlYXRlVmFsaWRhdG9ycyhlbGVtKSk7XHJcbiAgICAgIH1cclxuICAgICAgLy8gY29weSBvYmplY3RzIHNvIHRoZXkgYXJlIG9ubHkgY2hhbmdlcyB3aGVuIGNhbGxpbmcgdGhpcyBtZXRob2RcclxuICAgICAgdGhpcy5fcmVuZGVyZWRFbGVtZW50cy5wdXNoKE9iamVjdC5hc3NpZ24oe30sIGVsZW0pKTtcclxuICAgIH0pO1xyXG4gICAgLy8gY2FsbCBhIGNoYW5nZSBkZXRlY3Rpb24gc2luY2UgdGhlIHdob2xlIGZvcm0gbWlnaHQgY2hhbmdlXHJcbiAgICB0aGlzLl9jaGFuZ2VEZXRlY3RvclJlZi5kZXRlY3RDaGFuZ2VzKCk7XHJcbiAgICB0aW1lcigpLnRvUHJvbWlzZSgpLnRoZW4oKCkgPT4ge1xyXG4gICAgICAvLyBjYWxsIGEgbWFya0ZvckNoZWNrIHNvIGVsZW1lbnRzIGFyZSByZW5kZXJlZCBjb3JyZWN0bHkgaW4gT25QdXNoXHJcbiAgICAgIHRoaXMuX2NoYW5nZURldGVjdG9yUmVmLm1hcmtGb3JDaGVjaygpO1xyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIF9jbGVhclJlbW92ZWRFbGVtZW50cygpOiB2b2lkIHtcclxuICAgIGZvciAobGV0IGk6IG51bWJlciA9IDA7IGkgPCB0aGlzLl9yZW5kZXJlZEVsZW1lbnRzLmxlbmd0aDsgaSsrKSB7XHJcbiAgICAgIGZvciAobGV0IGo6IG51bWJlciA9IDA7IGogPCB0aGlzLl9lbGVtZW50cy5sZW5ndGg7IGorKykge1xyXG4gICAgICAgIC8vIGNoZWNrIGlmIHRoZSBuYW1lIG9mIHRoZSBlbGVtZW50IGlzIHN0aWxsIHRoZXJlIHJlbW92ZWRcclxuICAgICAgICBpZiAodGhpcy5fcmVuZGVyZWRFbGVtZW50c1tpXS5uYW1lID09PSB0aGlzLl9lbGVtZW50c1tqXS5uYW1lKSB7XHJcbiAgICAgICAgICBkZWxldGUgdGhpcy5fcmVuZGVyZWRFbGVtZW50c1tpXTtcclxuICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgfVxyXG4gICAgLy8gcmVtb3ZlIGVsZW1lbnRzIHRoYXQgd2VyZSByZW1vdmVkIGZyb20gdGhlIGFycmF5XHJcbiAgICB0aGlzLl9yZW5kZXJlZEVsZW1lbnRzLmZvckVhY2goKGVsZW06IElUZER5bmFtaWNFbGVtZW50Q29uZmlnKSA9PiB7XHJcbiAgICAgIHRoaXMuZHluYW1pY0Zvcm0ucmVtb3ZlQ29udHJvbChlbGVtLm5hbWUpO1xyXG4gICAgfSk7XHJcbiAgfVxyXG59XHJcbiJdfQ==