UNPKG

material-dynamic-forms

Version:

¡Crea formularios dinámicos, potentes y configurables en Angular usando Material Design! 🚀

398 lines 62.4 kB
import { Injectable } from '@angular/core'; import { Validators, } from '@angular/forms'; import { HttpParams } from '@angular/common/http'; import { eDataType, eTypeMOdel, } from './interfaces'; import { getValueFromProperty, transformToObject } from './functions/functions'; import * as i0 from "@angular/core"; import * as i1 from "@angular/forms"; import * as i2 from "@angular/common/http"; export class DynamicFormService { constructor(fb, http) { this.fb = fb; this.http = http; this.baseUrl = ''; // Agregamos esta variable para almacenar los valores externos this.externalDependenciesValues = {}; // Declarar formGroupControls como propiedad this.formGroupControls = {}; // Variable para manejar el modo de edición this.isEditMode = false; this.isReadonly = false; // Add readonly flag this.rangeValidator = (group) => { const desde = Number(group.get('desde')?.value); const hasta = Number(group.get('hasta')?.value); return desde <= hasta ? null : { rangeError: true }; }; } setBaseUrl(url) { this.baseUrl = url; } // Método para establecer el modo de edición setEditMode(isEdit) { this.isEditMode = isEdit; } // Add method to set readonly setReadonly(isReadonly) { this.isReadonly = isReadonly; } // Permite setear/actualizar los valores externos desde el componente setExternalDependenciesValues(values) { this.externalDependenciesValues = { ...this.externalDependenciesValues, ...values, }; } removeExternalDependency(key) { if (this.externalDependenciesValues.hasOwnProperty(key)) { delete this.externalDependenciesValues[key]; } } functionInitComponent(fieldGroupsDynamicForm, form) { this.formGroupControls = {}; let isRangeValidator = false; const initializeControl = (field) => { const initialValue = field.value !== undefined ? field.value : field.type === eDataType.select_chips ? [] : ''; const validators = this.isReadonly ? [] : field.validation || []; const isDisabled = this.isReadonly || !!field.dependency || field.disabled; return this.fb.control({ value: initialValue, disabled: isDisabled }, validators); }; const handleDependenciesValue = (field, control) => { if (!field.valueDependency && !field.valueExcludeDependency) { return; } const updateField = () => { const depValue = field.valueDependency ? this.formGroupControls[field.valueDependency.dependency] && this.formGroupControls[field.valueDependency.dependency].value : field.valueExcludeDependency ? this.formGroupControls[field.valueExcludeDependency.dependency] && this.formGroupControls[field.valueExcludeDependency.dependency] .value : undefined; const valueComparar = field.valueDependency ? field.valueDependency.valueDep : field.valueExcludeDependency ? field.valueExcludeDependency.valueDep : undefined; if (field.valueDependency && depValue === valueComparar) { control.enable(); control.clearValidators(); control.setValidators(field.valueDependency.validation ?? []); control.updateValueAndValidity(); } else if (field.valueExcludeDependency && depValue !== valueComparar) { control.enable(); control.clearValidators(); control.setValidators(field.valueExcludeDependency.validation ?? []); control.updateValueAndValidity(); } else { control.disable(); control.reset(); control.clearValidators(); control.updateValueAndValidity(); } }; if (field.valueDependency) { this.formGroupControls[field.valueDependency.dependency].valueChanges.subscribe(updateField); } else if (field.valueExcludeDependency) { this.formGroupControls[field.valueExcludeDependency.dependency].valueChanges.subscribe(updateField); } updateField(); }; const handleDependencies = (field, control) => { if (!field.dependency) { return; } const dependencyFields = field.dependency.split(','); dependencyFields.forEach((depField) => { if (!this.formGroupControls[depField]) { this.formGroupControls[depField] = this.fb.control('', Validators.required); } }); const updateField = () => { if ((field.valueDependency || field.valueExcludeDependency) && control.disabled) { return; } const allDependenciesFilled = dependencyFields.every((depField) => this.formGroupControls[depField] && this.formGroupControls[depField]?.value); if (allDependenciesFilled) { const dependencyValue = this.formGroupControls[dependencyFields[0]].value; if (!field.valueDependency && !field.valueExcludeDependency && field.disabled) { control.disable(); } else { control.enable(); } if (!this.isEditMode) control.reset(); // Verificar si hay dependencias externas const hasExternalDeps = field.externalDependencies && field.externalDependencies.length > 0; // Aquí se unifica la lógica de obtención de datos if (field.apiUrl && dependencyValue) { this.fetchOptions(field, dependencyValue, hasExternalDeps); } } else { control.reset(); field.options = []; if (!field.valueDependency && !field.valueExcludeDependency) { control.disable(); } } }; dependencyFields.forEach((depField) => { this.formGroupControls[depField].valueChanges.subscribe(updateField); }); updateField(); }; const handleDynamicDateConstraints = (field, control) => { if (!field.dateDependency || (!field.minDateFn && !field.maxDateFn)) { return; } const dependencyField = this.formGroupControls[field.dateDependency]; if (!dependencyField) { console.error(`El campo de dependencia ${field.dateDependency} no existe.`); return; } const updateConstraints = () => { const dependencyValue = dependencyField.value ? new Date(dependencyField.value) : null; if (dependencyValue) { // Asegurarse de que la hora sea 00:00:00 dependencyValue.setHours(0, 0, 0, 0); } if (field.minDateFn && dependencyValue) { const calculatedMinDate = field.minDateFn(dependencyValue); field.minDate = calculatedMinDate; control.setValidators([ ...(control.validator ? [control.validator] : []), Validators.min(calculatedMinDate.getTime()), ]); } if (field.maxDateFn && dependencyValue) { const calculatedMaxDate = field.maxDateFn(dependencyValue); field.maxDate = calculatedMaxDate; control.setValidators([ ...(control.validator ? [control.validator] : []), Validators.max(calculatedMaxDate.getTime()), ]); } control.updateValueAndValidity(); }; dependencyField.valueChanges.subscribe(updateConstraints); updateConstraints(); // Aplicar al inicializar // Forzar una actualización manual del valor del campo dependiente setTimeout(() => { dependencyField.updateValueAndValidity(); }, 0); }; fieldGroupsDynamicForm.forEach((group) => { group.fields.forEach((field) => { if (field.visible) { // Inicializar control const control = initializeControl(field); // Agregar control al objeto de controles if (field.name) this.formGroupControls[field.name] = control; // Agregar opciones al campo select sin dependencias if (field.apiUrl && !field.urlParamDependency && !field.urlQueryParam && !field.urlEndParam) { this.fetchOptions(field, null, false); } if (!this.isReadonly) { // Manejar dependencias de values de campos internas if (field.valueDependency || field.valueExcludeDependency) handleDependenciesValue(field, control); // Manejar dependencias de campos if (field.dependency) handleDependencies(field, control); // Manejar dependencias de fechas if (field.type === eDataType.date) handleDynamicDateConstraints(field, control); } } }); isRangeValidator = group.isRangeValidator ?? false; }); form = this.fb.group(this.formGroupControls); if (isRangeValidator) form.setValidators(this.rangeValidator); if (this.isEditMode) { this.markControlsAsTouched(form); } if (this.isReadonly) { form.disable(); // Disable the entire form if readonly } return form; } markControlsAsTouched(form) { Object.keys(form.controls).forEach((key) => { const control = form.get(key); if (control) { control.markAsTouched(); control.updateValueAndValidity(); // Actualiza los errores y validaciones } }); } handleExternalDependenciesService(field, control) { if (!control) { console.warn(`Control no encontrado para el campo ${field.name}`); return () => { }; } const checkDependencies = () => { // 1) Verificar dependencias externas const depsExtOk = field.externalDependencies?.every((dep) => this.externalDependenciesValues?.[dep] !== undefined); // 2) Verificar dependencias de formulario (field.dependency) let depsFormOk = true; if (field.dependency) { const dependencyFields = field.dependency.split(','); // Chequea que todos esos campos tengan algún valor depsFormOk = dependencyFields.every((depField) => !!this.formGroupControls[depField]?.value); } // Si todo está OK, habilitar campo y llamar a la API if (depsExtOk && depsFormOk) { control.enable(); if (field.apiUrl) { // Verificar si hay dependencias externas const hasExternalDeps = field.externalDependencies && field.externalDependencies.length > 0; // fetchOptions con "useExternalDeps = true" si hay dependencias externas this.fetchOptions(field, undefined, hasExternalDeps); } } else if (!this.isEditMode || !control.value) { // Si no está en modo edición o el control no tiene valor, deshabilita control.disable(); control.reset(); field.options = []; } // En modo edición y tiene valor, no hacer nada para mantener el valor }; // Ejecuta inicialmente checkDependencies(); // Retorna la función para que el componente la invoque cuando cambien las dependencias return checkDependencies; } functionGetFormValue(form, fieldGroupsDynamicForm) { let dataFilterSend = {}; fieldGroupsDynamicForm.forEach((group) => { group.fields.forEach((fieldDynamicForm) => { const control = form.get(fieldDynamicForm.name); if (control) { if (control.value !== '' && control.value !== null) { fieldDynamicForm.active = true; switch (fieldDynamicForm.type) { case eDataType.select: fieldDynamicForm.value = control.value; if (control.value === -1) { fieldDynamicForm.options = [ { key: -1, value: 'TODOS' }, ...fieldDynamicForm.options, ]; } fieldDynamicForm.selectedOption = fieldDynamicForm.options?.find((option) => option.key === control.value); fieldDynamicForm.filterParam ? (dataFilterSend[fieldDynamicForm.filterParam] = fieldDynamicForm.selectedOption ? fieldDynamicForm.selectedOption['key'] : null) : (dataFilterSend[fieldDynamicForm.name] = fieldDynamicForm.selectedOption ? transformToObject(fieldDynamicForm.selectedOption) : null); break; case eDataType.date: fieldDynamicForm.value = control.value || null; dataFilterSend[fieldDynamicForm.name] = fieldDynamicForm.value; break; default: fieldDynamicForm.value = fieldDynamicForm.typeModel === eTypeMOdel.number ? Number(control.value) : control.value; //fieldDynamicForm.value = control.value; dataFilterSend[fieldDynamicForm.name] = fieldDynamicForm.value; break; } } else { fieldDynamicForm.active = false; fieldDynamicForm.value = null; dataFilterSend[fieldDynamicForm.name] = null; } } }); }); return dataFilterSend; } buildUrlAndParams(field, dependencyValue, useExternalDeps = false) { let url = `${this.baseUrl}${field.apiUrl}`; let params = new HttpParams(); // 1. urlParamDependency (ej: /api/{id}) if (field.urlParamDependency && dependencyValue) { url = url.replace(/\{.*?\}/g, dependencyValue); } // 2. urlQueryParam (ej: ?depField=value) else if (field.urlQueryParam && field.dependency) { const dependencyFields = field.dependency.split(','); dependencyFields.forEach((depField) => { params = params.set(depField, this.formGroupControls[depField].value); }); } // 3. urlEndParam (ej: /api/id) else if (field.urlEndParam && dependencyValue) { url = `${url}/${dependencyValue}`; } // 4. Agregar dependencias externas si se indica if (useExternalDeps && field.externalDependencies) { field.externalDependencies.forEach((dep) => { if (this.externalDependenciesValues[dep] !== undefined) { params = params.append(dep, this.externalDependenciesValues[dep]); } }); } return { url, params }; } fetchOptions(field, dependencyValue, useExternalDeps = false) { if (!field.apiUrl) { return; } const { url, params } = this.buildUrlAndParams(field, dependencyValue, useExternalDeps); this.http.get(url, { params }).subscribe((res) => { field.options = field.subscribeMap ? field.subscribeMap(res).map((item) => ({ key: item.id, value: field.valueTOShow ? getValueFromProperty(item, field.valueTOShow) : item.nombre || item.name, data: item.data, })) : res.data.map((item) => ({ key: item.id, value: field.valueTOShow ? item[field.valueTOShow] : item.nombre || item.name, data: item, })); field.options?.sort((a, b) => (a.value || '').localeCompare(b.value || '')); }); } } DynamicFormService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: DynamicFormService, deps: [{ token: i1.FormBuilder }, { token: i2.HttpClient }], target: i0.ɵɵFactoryTarget.Injectable }); DynamicFormService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: DynamicFormService }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: DynamicFormService, decorators: [{ type: Injectable }], ctorParameters: function () { return [{ type: i1.FormBuilder }, { type: i2.HttpClient }]; } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZHluYW1pYy1mb3JtLnNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9wcm9qZWN0cy9keW5hbWljLWZvcm0vc3JjL2xpYi9keW5hbWljLWZvcm0uc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQzNDLE9BQU8sRUFHTCxVQUFVLEdBR1gsTUFBTSxnQkFBZ0IsQ0FBQztBQUN4QixPQUFPLEVBQWMsVUFBVSxFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFDOUQsT0FBTyxFQUdMLFNBQVMsRUFHVCxVQUFVLEdBQ1gsTUFBTSxjQUFjLENBQUM7QUFDdEIsT0FBTyxFQUFFLG9CQUFvQixFQUFFLGlCQUFpQixFQUFFLE1BQU0sdUJBQXVCLENBQUM7Ozs7QUFHaEYsTUFBTSxPQUFPLGtCQUFrQjtJQWM3QixZQUFvQixFQUFlLEVBQVUsSUFBZ0I7UUFBekMsT0FBRSxHQUFGLEVBQUUsQ0FBYTtRQUFVLFNBQUksR0FBSixJQUFJLENBQVk7UUFickQsWUFBTyxHQUFXLEVBQUUsQ0FBQztRQUU3Qiw4REFBOEQ7UUFDdEQsK0JBQTBCLEdBQTJCLEVBQUUsQ0FBQztRQUVoRSw0Q0FBNEM7UUFDcEMsc0JBQWlCLEdBQXVDLEVBQUUsQ0FBQztRQUVuRSwyQ0FBMkM7UUFDbkMsZUFBVSxHQUFZLEtBQUssQ0FBQztRQUU1QixlQUFVLEdBQVksS0FBSyxDQUFDLENBQUMsb0JBQW9CO1FBc1Z6RCxtQkFBYyxHQUFnQixDQUM1QixLQUFzQixFQUNTLEVBQUU7WUFDakMsTUFBTSxLQUFLLEdBQUcsTUFBTSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsT0FBTyxDQUFDLEVBQUUsS0FBSyxDQUFDLENBQUM7WUFDaEQsTUFBTSxLQUFLLEdBQUcsTUFBTSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsT0FBTyxDQUFDLEVBQUUsS0FBSyxDQUFDLENBQUM7WUFDaEQs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QUFJLENBQUMsTUFBTSxJQUFJLElBQUksQ0FBQyxJQUFJO29CQUM1QixJQUFJLEVBQUUsSUFBSTtpQkFDWCxDQUFDLENBQUMsQ0FBQztZQUNOLEtBQUssQ0FBQyxPQUFPLEVBQUUsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFLENBQzNCLENBQUMsQ0FBQyxDQUFDLEtBQUssSUFBSSxFQUFFLENBQUMsQ0FBQyxhQUFhLENBQUMsQ0FBQyxDQUFDLEtBQUssSUFBSSxFQUFFLENBQUMsQ0FDN0MsQ0FBQztRQUNKLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQzs7K0dBbmZVLGtCQUFrQjttSEFBbEIsa0JBQWtCOzJGQUFsQixrQkFBa0I7a0JBRDlCLFVBQVUiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBJbmplY3RhYmxlIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XHJcbmltcG9ydCB7XHJcbiAgRm9ybUJ1aWxkZXIsXHJcbiAgRm9ybUdyb3VwLFxyXG4gIFZhbGlkYXRvcnMsXHJcbiAgQWJzdHJhY3RDb250cm9sLFxyXG4gIFZhbGlkYXRvckZuLFxyXG59IGZyb20gJ0Bhbmd1bGFyL2Zvcm1zJztcclxuaW1wb3J0IHsgSHR0cENsaWVudCwgSHR0cFBhcmFtcyB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbi9odHRwJztcclxuaW1wb3J0IHtcclxuICBJRmllbGRHcm91cCxcclxuICBJRmllbGREeW5hbWljRm9ybSxcclxuICBlRGF0YVR5cGUsXHJcbiAgS2V5VmFsdWUsXHJcbiAgT2JqZWN0S2V5VmFsdWUsXHJcbiAgZVR5cGVNT2RlbCxcclxufSBmcm9tICcuL2ludGVyZmFjZXMnO1xyXG5pbXBvcnQgeyBnZXRWYWx1ZUZyb21Qcm9wZXJ0eSwgdHJhbnNmb3JtVG9PYmplY3QgfSBmcm9tICcuL2Z1bmN0aW9ucy9mdW5jdGlvbnMnO1xyXG5cclxuQEluamVjdGFibGUoKVxyXG5leHBvcnQgY2xhc3MgRHluYW1pY0Zvcm1TZXJ2aWNlIHtcclxuICBwcml2YXRlIGJhc2VVcmw6IHN0cmluZyA9ICcnO1xyXG5cclxuICAvLyBBZ3JlZ2Ftb3MgZXN0YSB2YXJpYWJsZSBwYXJhIGFsbWFjZW5hciBsb3MgdmFsb3JlcyBleHRlcm5vc1xyXG4gIHByaXZhdGUgZXh0ZXJuYWxEZXBlbmRlbmNpZXNWYWx1ZXM6IHsgW2tleTogc3RyaW5nXTogYW55IH0gPSB7fTtcclxuXHJcbiAgLy8gRGVjbGFyYXIgZm9ybUdyb3VwQ29udHJvbHMgY29tbyBwcm9waWVkYWRcclxuICBwcml2YXRlIGZvcm1Hcm91cENvbnRyb2xzOiB7IFtrZXk6IHN0cmluZ106IEFic3RyYWN0Q29udHJvbCB9ID0ge307XHJcblxyXG4gIC8vIFZhcmlhYmxlIHBhcmEgbWFuZWphciBlbCBtb2RvIGRlIGVkaWNpw7NuXHJcbiAgcHJpdmF0ZSBpc0VkaXRNb2RlOiBib29sZWFuID0gZmFsc2U7XHJcblxyXG4gIHByaXZhdGUgaXNSZWFkb25seTogYm9vbGVhbiA9IGZhbHNlOyAvLyBBZGQgcmVhZG9ubHkgZmxhZ1xyXG5cclxuICBjb25zdHJ1Y3Rvcihwcml2YXRlIGZiOiBGb3JtQnVpbGRlciwgcHJpdmF0ZSBodHRwOiBIdHRwQ2xpZW50KSB7IH1cclxuXHJcbiAgcHVibGljIHNldEJhc2VVcmwodXJsOiBzdHJpbmcpOiB2b2lkIHtcclxuICAgIHRoaXMuYmFzZVVybCA9IHVybDtcclxuICB9XHJcblxyXG4gIC8vIE3DqXRvZG8gcGFyYSBlc3RhYmxlY2VyIGVsIG1vZG8gZGUgZWRpY2nDs25cclxuICBwdWJsaWMgc2V0RWRpdE1vZGUoaXNFZGl0OiBib29sZWFuKTogdm9pZCB7XHJcbiAgICB0aGlzLmlzRWRpdE1vZGUgPSBpc0VkaXQ7XHJcbiAgfVxyXG5cclxuICAvLyBBZGQgbWV0aG9kIHRvIHNldCByZWFkb25seVxyXG4gIHB1YmxpYyBzZXRSZWFkb25seShpc1JlYWRvbmx5OiBib29sZWFuKTogdm9pZCB7XHJcbiAgICB0aGlzLmlzUmVhZG9ubHkgPSBpc1JlYWRvbmx5O1xyXG4gIH1cclxuXHJcbiAgLy8gUGVybWl0ZSBzZXRlYXIvYWN0dWFsaXphciBsb3MgdmFsb3JlcyBleHRlcm5vcyBkZXNkZSBlbCBjb21wb25lbnRlXHJcbiAgcHVibGljIHNldEV4dGVybmFsRGVwZW5kZW5jaWVzVmFsdWVzKHZhbHVlczogeyBba2V5OiBzdHJpbmddOiBhbnkgfSk6IHZvaWQge1xyXG4gICAgdGhpcy5leHRlcm5hbERlcGVuZGVuY2llc1ZhbHVlcyA9IHtcclxuICAgICAgLi4udGhpcy5leHRlcm5hbERlcGVuZGVuY2llc1ZhbHVlcyxcclxuICAgICAgLi4udmFsdWVzLFxyXG4gICAgfTtcclxuICB9XHJcblxyXG4gIHB1YmxpYyByZW1vdmVFeHRlcm5hbERlcGVuZGVuY3koa2V5OiBzdHJpbmcpOiB2b2lkIHtcclxuICAgIGlmICh0aGlzLmV4dGVybmFsRGVwZW5kZW5jaWVzVmFsdWVzLmhhc093blByb3BlcnR5KGtleSkpIHtcclxuICAgICAgZGVsZXRlIHRoaXMuZXh0ZXJuYWxEZXBlbmRlbmNpZXNWYWx1ZXNba2V5XTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIGZ1bmN0aW9uSW5pdENvbXBvbmVudChcclxuICAgIGZpZWxkR3JvdXBzRHluYW1pY0Zvcm06IElGaWVsZEdyb3VwW10sXHJcbiAgICBmb3JtOiBGb3JtR3JvdXBcclxuICApOiBGb3JtR3JvdXAge1xyXG4gICAgdGhpcy5mb3JtR3JvdXBDb250cm9scyA9IHt9O1xyXG4gICAgbGV0IGlzUmFuZ2VWYWxpZGF0b3I6IGJvb2xlYW4gPSBmYWxzZTtcclxuXHJcbiAgICBjb25zdCBpbml0aWFsaXplQ29udHJvbCA9IChmaWVsZDogSUZpZWxkRHluYW1pY0Zvcm0pID0+IHtcclxuICAgICAgY29uc3QgaW5pdGlhbFZhbHVlID1cclxuICAgICAgICBmaWVsZC52YWx1ZSAhPT0gdW5kZWZpbmVkXHJcbiAgICAgICAgICA/IGZpZWxkLnZhbHVlXHJcbiAgICAgICAgICA6IGZpZWxkLnR5cGUgPT09IGVEYXRhVHlwZS5zZWxlY3RfY2hpcHNcclxuICAgICAgICAgICAgPyBbXVxyXG4gICAgICAgICAgICA6ICcnO1xyXG4gICAgICBjb25zdCB2YWxpZGF0b3JzID0gdGhpcy5pc1JlYWRvbmx5ID8gW10gOiBmaWVsZC52YWxpZGF0aW9uIHx8IFtdO1xyXG4gICAgICBjb25zdCBpc0Rpc2FibGVkID1cclxuICAgICAgICB0aGlzLmlzUmVhZG9ubHkgfHwgISFmaWVsZC5kZXBlbmRlbmN5IHx8IGZpZWxkLmRpc2FibGVkO1xyXG4gICAgICByZXR1cm4gdGhpcy5mYi5jb250cm9sKFxyXG4gICAgICAgIHsgdmFsdWU6IGluaXRpYWxWYWx1ZSwgZGlzYWJsZWQ6IGlzRGlzYWJsZWQgfSxcclxuICAgICAgICB2YWxpZGF0b3JzXHJcbiAgICAgICk7XHJcbiAgICB9O1xyXG5cclxuICAgIGNvbnN0IGhhbmRsZURlcGVuZGVuY2llc1ZhbHVlID0gKFxyXG4gICAgICBmaWVsZDogSUZpZWxkRHluYW1pY0Zvcm0sXHJcbiAgICAgIGNvbnRyb2w6IGFueVxyXG4gICAgKSA9PiB7XHJcbiAgICAgIGlmICghZmllbGQudmFsdWVEZXBlbmRlbmN5ICYmICFmaWVsZC52YWx1ZUV4Y2x1ZGVEZXBlbmRlbmN5KSB7XHJcbiAgICAgICAgcmV0dXJuO1xyXG4gICAgICB9XHJcblxyXG4gICAgICBjb25zdCB1cGRhdGVGaWVsZCA9ICgpID0+IHtcclxuICAgICAgICBjb25zdCBkZXBWYWx1ZSA9IGZpZWxkLnZhbHVlRGVwZW5kZW5jeVxyXG4gICAgICAgICAgPyB0aGlzLmZvcm1Hcm91cENvbnRyb2xzW2ZpZWxkLnZhbHVlRGVwZW5kZW5jeS5kZXBlbmRlbmN5XSAmJlxyXG4gICAgICAgICAgdGhpcy5mb3JtR3JvdXBDb250cm9sc1tmaWVsZC52YWx1ZURlcGVuZGVuY3kuZGVwZW5kZW5jeV0udmFsdWVcclxuICAgICAgICAgIDogZmllbGQudmFsdWVFeGNsdWRlRGVwZW5kZW5jeVxyXG4gICAgICAgICAgICA/IHRoaXMuZm9ybUdyb3VwQ29udHJvbHNbZmllbGQudmFsdWVFeGNsdWRlRGVwZW5kZW5jeS5kZXBlbmRlbmN5XSAmJlxyXG4gICAgICAgICAgICB0aGlzLmZvcm1Hcm91cENvbnRyb2xzW2ZpZWxkLnZhbHVlRXhjbHVkZURlcGVuZGVuY3kuZGVwZW5kZW5jeV1cclxuICAgICAgICAgICAgICAudmFsdWVcclxuICAgICAgICAgICAgOiB1bmRlZmluZWQ7XHJcbiAgICAgICAgY29uc3QgdmFsdWVDb21wYXJhciA9IGZpZWxkLnZhbHVlRGVwZW5kZW5jeVxyXG4gICAgICAgICAgPyBmaWVsZC52YWx1ZURlcGVuZGVuY3kudmFsdWVEZXBcclxuICAgICAgICAgIDogZmllbGQudmFsdWVFeGNsdWRlRGVwZW5kZW5jeVxyXG4gICAgICAgICAgICA/IGZpZWxkLnZhbHVlRXhjbHVkZURlcGVuZGVuY3kudmFsdWVEZXBcclxuICAgICAgICAgICAgOiB1bmRlZmluZWQ7XHJcblxyXG4gICAgICAgIGlmIChmaWVsZC52YWx1ZURlcGVuZGVuY3kgJiYgZGVwVmFsdWUgPT09IHZhbHVlQ29tcGFyYXIpIHtcclxuICAgICAgICAgIGNvbnRyb2wuZW5hYmxlKCk7XHJcbiAgICAgICAgICBjb250cm9sLmNsZWFyVmFsaWRhdG9ycygpO1xyXG4gICAgICAgICAgY29udHJvbC5zZXRWYWxpZGF0b3JzKGZpZWxkLnZhbHVlRGVwZW5kZW5jeS52YWxpZGF0aW9uID8/IFtdKTtcclxuICAgICAgICAgIGNvbnRyb2wudXBkYXRlVmFsdWVBbmRWYWxpZGl0eSgpO1xyXG4gICAgICAgIH0gZWxzZSBpZiAoZmllbGQudmFsdWVFeGNsdWRlRGVwZW5kZW5jeSAmJiBkZXBWYWx1ZSAhPT0gdmFsdWVDb21wYXJhcikge1xyXG4gICAgICAgICAgY29udHJvbC5lbmFibGUoKTtcclxuICAgICAgICAgIGNvbnRyb2wuY2xlYXJWYWxpZGF0b3JzKCk7XHJcbiAgICAgICAgICBjb250cm9sLnNldFZhbGlkYXRvcnMoZmllbGQudmFsdWVFeGNsdWRlRGVwZW5kZW5jeS52YWxpZGF0aW9uID8/IFtdKTtcclxuICAgICAgICAgIGNvbnRyb2wudXBkYXRlVmFsdWVBbmRWYWxpZGl0eSgpO1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICBjb250cm9sLmRpc2FibGUoKTtcclxuICAgICAgICAgIGNvbnRyb2wucmVzZXQoKTtcclxuICAgICAgICAgIGNvbnRyb2wuY2xlYXJWYWxpZGF0b3JzKCk7XHJcbiAgICAgICAgICBjb250cm9sLnVwZGF0ZVZhbHVlQW5kVmFsaWRpdHkoKTtcclxuICAgICAgICB9XHJcbiAgICAgIH07XHJcblxyXG4gICAgICBpZiAoZmllbGQudmFsdWVEZXBlbmRlbmN5KSB7XHJcbiAgICAgICAgdGhpcy5mb3JtR3JvdXBDb250cm9sc1tcclxuICAgICAgICAgIGZpZWxkLnZhbHVlRGVwZW5kZW5jeS5kZXBlbmRlbmN5XHJcbiAgICAgICAgXS52YWx1ZUNoYW5nZXMuc3Vic2NyaWJlKHVwZGF0ZUZpZWxkKTtcclxuICAgICAgfSBlbHNlIGlmIChmaWVsZC52YWx1ZUV4Y2x1ZGVEZXBlbmRlbmN5KSB7XHJcbiAgICAgICAgdGhpcy5mb3JtR3JvdXBDb250cm9sc1tcclxuICAgICAgICAgIGZpZWxkLnZhbHVlRXhjbHVkZURlcGVuZGVuY3kuZGVwZW5kZW5jeVxyXG4gICAgICAgIF0udmFsdWVDaGFuZ2VzLnN1YnNjcmliZSh1cGRhdGVGaWVsZCk7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIHVwZGF0ZUZpZWxkKCk7XHJcbiAgICB9O1xyXG5cclxuICAgIGNvbnN0IGhhbmRsZURlcGVuZGVuY2llcyA9IChmaWVsZDogSUZpZWxkRHluYW1pY0Zvcm0sIGNvbnRyb2w6IGFueSkgPT4ge1xyXG4gICAgICBpZiAoIWZpZWxkLmRlcGVuZGVuY3kpIHtcclxuICAgICAgICByZXR1cm47XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIGNvbnN0IGRlcGVuZGVuY3lGaWVsZHMgPSBmaWVsZC5kZXBlbmRlbmN5LnNwbGl0KCcsJyk7XHJcbiAgICAgIGRlcGVuZGVuY3lGaWVsZHMuZm9yRWFjaCgoZGVwRmllbGQpID0+IHtcclxuICAgICAgICBpZiAoIXRoaXMuZm9ybUdyb3VwQ29udHJvbHNbZGVwRmllbGRdKSB7XHJcbiAgICAgICAgICB0aGlzLmZvcm1Hcm91cENvbnRyb2xzW2RlcEZpZWxkXSA9IHRoaXMuZmIuY29udHJvbChcclxuICAgICAgICAgICAgJycsXHJcbiAgICAgICAgICAgIFZhbGlkYXRvcnMucmVxdWlyZWRcclxuICAgICAgICAgICk7XHJcbiAgICAgICAgfVxyXG4gICAgICB9KTtcclxuXHJcbiAgICAgIGNvbnN0IHVwZGF0ZUZpZWxkID0gKCkgPT4ge1xyXG4gICAgICAgIGlmIChcclxuICAgICAgICAgIChmaWVsZC52YWx1ZURlcGVuZGVuY3kgfHwgZmllbGQudmFsdWVFeGNsdWRlRGVwZW5kZW5jeSkgJiZcclxuICAgICAgICAgIGNvbnRyb2wuZGlzYWJsZWRcclxuICAgICAgICApIHtcclxuICAgICAgICAgIHJldHVybjtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGNvbnN0IGFsbERlcGVuZGVuY2llc0ZpbGxlZCA9IGRlcGVuZGVuY3lGaWVsZHMuZXZlcnkoXHJcbiAgICAgICAgICAoZGVwRmllbGQpID0+XHJcbiAgICAgICAgICAgIHRoaXMuZm9ybUdyb3VwQ29udHJvbHNbZGVwRmllbGRdICYmXHJcbiAgICAgICAgICAgIHRoaXMuZm9ybUdyb3VwQ29udHJvbHNbZGVwRmllbGRdPy52YWx1ZVxyXG4gICAgICAgICk7XHJcblxyXG4gICAgICAgIGlmIChhbGxEZXBlbmRlbmNpZXNGaWxsZWQpIHtcclxuICAgICAgICAgIGNvbnN0IGRlcGVuZGVuY3lWYWx1ZSA9XHJcbiAgICAgICAgICAgIHRoaXMuZm9ybUdyb3VwQ29udHJvbHNbZGVwZW5kZW5jeUZpZWxkc1swXV0udmFsdWU7XHJcblxyXG4gICAgICAgICAgaWYgKFxyXG4gICAgICAgICAgICAhZmllbGQudmFsdWVEZXBlbmRlbmN5ICYmXHJcbiAgICAgICAgICAgICFmaWVsZC52YWx1ZUV4Y2x1ZGVEZXBlbmRlbmN5ICYmXHJcbiAgICAgICAgICAgIGZpZWxkLmRpc2FibGVkXHJcbiAgICAgICAgICApIHtcclxuICAgICAgICAgICAgY29udHJvbC5kaXNhYmxlKCk7XHJcbiAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICBjb250cm9sLmVuYWJsZSgpO1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgICAgaWYgKCF0aGlzLmlzRWRpdE1vZGUpIGNvbnRyb2wucmVzZXQoKTtcclxuXHJcbiAgICAgICAgICAvLyBWZXJpZmljYXIgc2kgaGF5IGRlcGVuZGVuY2lhcyBleHRlcm5hc1xyXG4gICAgICAgICAgY29uc3QgaGFzRXh0ZXJuYWxEZXBzID1cclxuICAgICAgICAgICAgZmllbGQuZXh0ZXJuYWxEZXBlbmRlbmNpZXMgJiYgZmllbGQuZXh0ZXJuYWxEZXBlbmRlbmNpZXMubGVuZ3RoID4gMDtcclxuXHJcbiAgICAgICAgICAvLyBBcXXDrSBzZSB1bmlmaWNhIGxhIGzDs2dpY2EgZGUgb2J0ZW5jacOzbiBkZSBkYXRvc1xyXG4gICAgICAgICAgaWYgKGZpZWxkLmFwaVVybCAmJiBkZXBlbmRlbmN5VmFsdWUpIHtcclxuICAgICAgICAgICAgdGhpcy5mZXRjaE9wdGlvbnMoZmllbGQsIGRlcGVuZGVuY3lWYWx1ZSwgaGFzRXh0ZXJuYWxEZXBzKTtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgY29udHJvbC5yZXNldCgpO1xyXG4gICAgICAgICAgZmllbGQub3B0aW9ucyA9IFtdO1xyXG4gICAgICAgICAgaWYgKCFmaWVsZC52YWx1ZURlcGVuZGVuY3kgJiYgIWZpZWxkLnZhbHVlRXhjbHVkZURlcGVuZGVuY3kpIHtcclxuICAgICAgICAgICAgY29udHJvbC5kaXNhYmxlKCk7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICB9O1xyXG5cclxuICAgICAgZGVwZW5kZW5jeUZpZWxkcy5mb3JFYWNoKChkZXBGaWVsZCkgPT4ge1xyXG4gICAgICAgIHRoaXMuZm9ybUdyb3VwQ29udHJvbHNbZGVwRmllbGRdLnZhbHVlQ2hhbmdlcy5zdWJzY3JpYmUodXBkYXRlRmllbGQpO1xyXG4gICAgICB9KTtcclxuXHJcbiAgICAgIHVwZGF0ZUZpZWxkKCk7XHJcbiAgICB9O1xyXG5cclxuICAgIGNvbnN0IGhhbmRsZUR5bmFtaWNEYXRlQ29uc3RyYWludHMgPSAoXHJcbiAgICAgIGZpZWxkOiBJRmllbGREeW5hbWljRm9ybSxcclxuICAgICAgY29udHJvbDogYW55XHJcbiAgICApID0+IHtcclxuICAgICAgaWYgKCFmaWVsZC5kYXRlRGVwZW5kZW5jeSB8fCAoIWZpZWxkLm1pbkRhdGVGbiAmJiAhZmllbGQubWF4RGF0ZUZuKSkge1xyXG4gICAgICAgIHJldHVybjtcclxuICAgICAgfVxyXG5cclxuICAgICAgY29uc3QgZGVwZW5kZW5jeUZpZWxkID0gdGhpcy5mb3JtR3JvdXBDb250cm9sc1tmaWVsZC5kYXRlRGVwZW5kZW5jeV07XHJcbiAgICAgIGlmICghZGVwZW5kZW5jeUZpZWxkKSB7XHJcbiAgICAgICAgY29uc29sZS5lcnJvcihcclxuICAgICAgICAgIGBFbCBjYW1wbyBkZSBkZXBlbmRlbmNpYSAke2ZpZWxkLmRhdGVEZXBlbmRlbmN5fSBubyBleGlzdGUuYFxyXG4gICAgICAgICk7XHJcbiAgICAgICAgcmV0dXJuO1xyXG4gICAgICB9XHJcblxyXG4gICAgICBjb25zdCB1cGRhdGVDb25zdHJhaW50cyA9ICgpID0+IHtcclxuICAgICAgICBjb25zdCBkZXBlbmRlbmN5VmFsdWU6IERhdGUgfCBudWxsID0gZGVwZW5kZW5jeUZpZWxkLnZhbHVlXHJcbiAgICAgICAgICA/IG5ldyBEYXRlKGRlcGVuZGVuY3lGaWVsZC52YWx1ZSlcclxuICAgICAgICAgIDogbnVsbDtcclxuXHJcbiAgICAgICAgaWYgKGRlcGVuZGVuY3lWYWx1ZSkge1xyXG4gICAgICAgICAgLy8gQXNlZ3VyYXJzZSBkZSBxdWUgbGEgaG9yYSBzZWEgMDA6MDA6MDBcclxuICAgICAgICAgIGRlcGVuZGVuY3lWYWx1ZS5zZXRIb3VycygwLCAwLCAwLCAwKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGlmIChmaWVsZC5taW5EYXRlRm4gJiYgZGVwZW5kZW5jeVZhbHVlKSB7XHJcbiAgICAgICAgICBjb25zdCBjYWxjdWxhdGVkTWluRGF0ZSA9IGZpZWxkLm1pbkRhdGVGbihkZXBlbmRlbmN5VmFsdWUpO1xyXG4gICAgICAgICAgZmllbGQubWluRGF0ZSA9IGNhbGN1bGF0ZWRNaW5EYXRlO1xyXG4gICAgICAgICAgY29udHJvbC5zZXRWYWxpZGF0b3JzKFtcclxuICAgICAgICAgICAgLi4uKGNvbnRyb2wudmFsaWRhdG9yID8gW2NvbnRyb2wudmFsaWRhdG9yXSA6IFtdKSxcclxuICAgICAgICAgICAgVmFsaWRhdG9ycy5taW4oY2FsY3VsYXRlZE1pbkRhdGUuZ2V0VGltZSgpKSxcclxuICAgICAgICAgIF0pO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgaWYgKGZpZWxkLm1heERhdGVGbiAmJiBkZXBlbmRlbmN5VmFsdWUpIHtcclxuICAgICAgICAgIGNvbnN0IGNhbGN1bGF0ZWRNYXhEYXRlID0gZmllbGQubWF4RGF0ZUZuKGRlcGVuZGVuY3lWYWx1ZSk7XHJcbiAgICAgICAgICBmaWVsZC5tYXhEYXRlID0gY2FsY3VsYXRlZE1heERhdGU7XHJcbiAgICAgICAgICBjb250cm9sLnNldFZhbGlkYXRvcnMoW1xyXG4gICAgICAgICAgICAuLi4oY29udHJvbC52YWxpZGF0b3IgPyBbY29udHJvbC52YWxpZGF0b3JdIDogW10pLFxyXG4gICAgICAgICAgICBWYWxpZGF0b3JzLm1heChjYWxjdWxhdGVkTWF4RGF0ZS5nZXRUaW1lKCkpLFxyXG4gICAgICAgICAgXSk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBjb250cm9sLnVwZGF0ZVZhbHVlQW5kVmFsaWRpdHkoKTtcclxuICAgICAgfTtcclxuXHJcbiAgICAgIGRlcGVuZGVuY3lGaWVsZC52YWx1ZUNoYW5nZXMuc3Vic2NyaWJlKHVwZGF0ZUNvbnN0cmFpbnRzKTtcclxuICAgICAgdXBkYXRlQ29uc3RyYWludHMoKTsgLy8gQXBsaWNhciBhbCBpbmljaWFsaXphclxyXG5cclxuICAgICAgLy8gRm9yemFyIHVuYSBhY3R1YWxpemFjacOzbiBtYW51YWwgZGVsIHZhbG9yIGRlbCBjYW1wbyBkZXBlbmRpZW50ZVxyXG4gICAgICBzZXRUaW1lb3V0KCgpID0+IHtcclxuICAgICAgICBkZXBlbmRlbmN5RmllbGQudXBkYXRlVmFsdWVBbmRWYWxpZGl0eSgpO1xyXG4gICAgICB9LCAwKTtcclxuICAgIH07XHJcblxyXG4gICAgZmllbGRHcm91cHNEeW5hbWljRm9ybS5mb3JFYWNoKChncm91cDogSUZpZWxkR3JvdXApID0+IHtcclxuICAgICAgZ3JvdXAuZmllbGRzLmZvckVhY