@nuarch/dynamic-forms
Version:
Teradata UI Platform Dynamic Forms Module
359 lines • 37.6 kB
JavaScript
/**
* @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==