UNPKG

tuain-ng-forms-lib

Version:

Componentes y Clases Angular para la gestión de formularios TUAIN

1,133 lines (1,123 loc) 210 kB
import * as i0 from '@angular/core'; import { InjectionToken, signal, computed, Component, ChangeDetectionStrategy, Input, EventEmitter, Output, inject, DestroyRef, model, Injectable, NgModule } from '@angular/core'; import { Subject, takeUntil, BehaviorSubject, ReplaySubject } from 'rxjs'; import yn from 'yn'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { nanoid } from 'nanoid'; const ICON_RESOLVER = new InjectionToken('ICON_RESOLVER'); class FormPiece { destroy$ = new Subject(); _formState = ''; _visibleForced; _isForced; _absoluteVisible = true; _absoluteDisabled = false; _widget = null; visibleStates = []; enabledStates = []; _form = null; _formConfig; _visible = true; _disabled = false; customAttributes = {}; constructor(pieceDefinition, formConfig) { this._formConfig = formConfig; this._isForced = false; this._visibleForced = false; this.setVisibleStates(pieceDefinition.visibleStates); this.setEnabledStates(pieceDefinition.enabledStates); this.enabled = !pieceDefinition?.disabled; this.setVisibility(pieceDefinition?.visible ?? true); this.customAttributes = pieceDefinition?.customAttributes ?? {}; if (pieceDefinition?.customAttributes) { Object.keys(pieceDefinition?.customAttributes) ?.forEach(attr => this.customAttributes[attr] = pieceDefinition?.customAttributes?.[attr]); } } getCustomAttribute(name) { return this.customAttributes?.[name] ?? null; } setCustomAttribute(name, value) { if (name) { this.customAttributes[name] = value; } } setCustomAttributes(attributes) { Object.entries(attributes).forEach(([name, value]) => { this.setCustomAttribute(name, value); }); return this; } matchAttribute(name, value) { return this.customAttributes?.[name] === value; } setVisibleStates(newStates) { const visibleStates = (!Array.isArray(newStates) && typeof newStates === 'string') ? newStates.split(',').map(state => state.trim()).filter(state => state.length > 0) : newStates; this.visibleStates = (Array.isArray(visibleStates)) ? [...(new Set(visibleStates))] : []; } addVisibleState(state) { if (!this.visibleStates.includes(state)) { this.visibleStates.push(state); } } removeVisibleState(state) { const existStateIdx = this.visibleStates.findIndex(st => st === state); if (existStateIdx >= 0) { this.visibleStates.splice(existStateIdx, 1); } } setEnabledStates(newStates) { const enabledStates = (!Array.isArray(newStates) && typeof newStates === 'string') ? newStates.split(',').map(state => state.trim()).filter(state => state.length > 0) : newStates; this.enabledStates = (Array.isArray(enabledStates)) ? [...(new Set(enabledStates))] : []; } addEnabledState(state) { if (!this.enabledStates.includes(state)) { this.enabledStates.push(state); } } removeEnabledState(state) { const existStateIdx = this.enabledStates.findIndex(st => st === state); if (existStateIdx >= 0) { this.enabledStates.splice(existStateIdx, 1); } } viewOnState(state) { return (this.visibleStates && state) ? this.visibleStates.includes(state) : false; } enabledOnState(state) { return (this.enabledStates && state) ? this.enabledStates.includes(state) : false; } get absoluteVisible() { return this._absoluteVisible; } get absoluteDisabled() { return this._absoluteDisabled; } get visible() { return this._visible; } set visible(visible) { this.setVisibility(visible); } visibleOn(state) { return this._absoluteVisible && this.viewOnState(state); } enabledOn(state) { return !this._absoluteDisabled && this.enabledOnState(state); } setVisibility(visible, forced = null) { this._absoluteVisible = !!visible; if (forced !== null) { this._isForced = forced; this._visibleForced = visible; } this._visible = this._absoluteVisible && this.viewOnState(this._formState); } show(forced = null) { this.setVisibility(true, forced); } hide(forced = null) { this.setVisibility(false, forced); } get enabled() { return !this._disabled; } set enabled(enabled) { this._absoluteDisabled = !enabled; this._disabled = this._absoluteDisabled || !this.enabledOnState(this._formState); } get editable() { return !this._disabled; } get disabled() { return this._disabled; } set disabled(disabled) { this.enabled = !disabled; } enable() { this.enabled = true; } disable() { this.enabled = false; } formStateChangeCustomSubscribe(form, formChangeSubject) { } formStateChange(state) { if (state) { this._formState = state; this._visible = this._absoluteVisible && this.viewOnState(state); this._disabled = this._absoluteDisabled || !this.enabledOnState(state); } } connectWithParentForm(form, formChangeSubject) { this._form = form; this.formStateChangeCustomSubscribe(form, formChangeSubject); formChangeSubject .pipe(takeUntil(this.destroy$)) .subscribe({ next: (event) => this.formStateChange(event?.state), error: (err) => console.error(`Error en formStateChange subscription: ${err}`) }); } get form() { return this._form; } get formConfig() { return this._formConfig; } set widget(widget) { this._widget = widget; } get widget() { return this._widget; } destroy() { this.destroy$.next(); this.destroy$.complete(); } } const VISIBLE = 'visible'; const DISABLED = 'disabled'; class FormPiecePropagate extends FormPiece { _attributeChange; constructor(pieceDefinition, formConfig) { super(pieceDefinition, formConfig); this._attributeChange = new BehaviorSubject(null); } get attributeChange() { return this._attributeChange.asObservable(); } propagateAttribute(name, value) { this._attributeChange?.next({ name, value }); } setCustomAttribute(name, value) { super.setCustomAttribute(name, value); const fullName = `customAttributes.${name}`; this.propagateAttribute(fullName, value); } setVisibility(visible, forced = null) { super.setVisibility(visible, forced); this.propagateAttribute(VISIBLE, this._visible); } set enabled(enabled) { super.enabled = enabled; this.propagateAttribute(DISABLED, this._disabled); } formStateChange(state) { super.formStateChange(state); if (state) { this.propagateAttribute(VISIBLE, this._visible); this.propagateAttribute(DISABLED, this._disabled); } } } const NO_ERROR = '00'; const HEADER = 'HEADER'; var ElementType; (function (ElementType) { ElementType["Action"] = "ACTION"; ElementType["Field"] = "FIELD"; ElementType["Table"] = "TABLE"; })(ElementType || (ElementType = {})); var FormActionType; (function (FormActionType) { FormActionType["TableAction"] = "TABLEACTION"; FormActionType["GetData"] = "GETDATA"; FormActionType["GetTableData"] = "GETTABLEDATA"; FormActionType["Validate"] = "VALIDATE"; })(FormActionType || (FormActionType = {})); var ComparisonOperator; (function (ComparisonOperator) { ComparisonOperator["G"] = "G"; ComparisonOperator["L"] = "L"; ComparisonOperator["GE"] = "GE"; ComparisonOperator["LE"] = "LE"; ComparisonOperator["EQ"] = "EQ"; ComparisonOperator["NEQ"] = "NEQ"; ComparisonOperator["HAS"] = "HAS"; ComparisonOperator["NOTHAS"] = "NOTHAS"; ComparisonOperator["BETWEEN"] = "BETWEEN"; ComparisonOperator["IN"] = "IN"; })(ComparisonOperator || (ComparisonOperator = {})); /** @deprecated Since v17. Use ElementType enum instead. Will be removed in v19. */ const elementTypes = { action: ElementType.Action, field: ElementType.Field, table: ElementType.Table, }; /** @deprecated Since v17. Use FormActionType enum instead. Will be removed in v19. */ const formActions = { tableAction: FormActionType.TableAction, getData: FormActionType.GetData, getTableData: FormActionType.GetTableData, validate: FormActionType.Validate, }; /** @deprecated Since v17. Use ComparisonOperator enum instead. Will be removed in v19. */ const operators = { G: ComparisonOperator.G, L: ComparisonOperator.L, GE: ComparisonOperator.GE, LE: ComparisonOperator.LE, EQ: ComparisonOperator.EQ, NEQ: ComparisonOperator.NEQ, HAS: ComparisonOperator.HAS, NOTHAS: ComparisonOperator.NOTHAS, BETWEEN: ComparisonOperator.BETWEEN, IN: ComparisonOperator.IN, }; class FormElement extends FormPiecePropagate { elementType = null; constructor(elementDefinition, formConfig) { super(elementDefinition, formConfig); } setAttr(attr, value) { const { name: attrName, propagate: name } = attr; try { const currentValue = this[attrName]; if (currentValue !== value) { this[attrName] = value; name && this.propagateAttribute(name, value); } } catch (e) { console.log(`Atributo ${attrName} no presente o valor ${value} inconsistente. ${e}`); } } isField() { return this.elementType === ElementType.Field; } isAction() { return this.elementType === ElementType.Action; } isTable() { return this.elementType === ElementType.Table; } } const UNDEFINED = 'undefined'; const DEFAULT_ERROR_TYPE = 'error'; const DEFAULT_CAPTURE_TYPE = 'INPUT'; const DEFAULT_ALIGNMENT = 'left'; const STD_MAX_LENGTH = 50; const BIG_MAX_LENGTH = 500; const directChanges = [ 'defaultEditable', 'defaultValue', 'alignment', 'required', 'errorCode', 'errorMessage', 'errorType', 'tooltip', 'info', 'format', 'intrinsicErrorMessage', 'outputOnly', 'captureType', 'title', 'type', 'maxLength', 'maxValue', 'minLength', 'minValue', 'validateOnServer', 'serverAction', 'visibleLabel', 'options', 'placeholder', ]; const attrs$2 = { captureType: { name: '_captureType', propagate: 'captureType' }, errorCode: { name: '_errorCode', propagate: 'errorCode' }, errorMessage: { name: '_errorMessage', propagate: 'errorMessage' }, errorType: { name: '_errorType', propagate: 'errorType' }, defaultValue: { name: '_defaultValue', propagate: 'defaultValue' }, defaultEditable: { name: '_defaultEditable', propagate: 'defaultEditable' }, fieldAlignment: { name: '_fieldAlignment', propagate: 'alignment' }, fieldCode: { name: '_fieldCode', propagate: 'code' }, fieldInfo: { name: '_fieldInfo', propagate: 'info' }, fieldRequired: { name: '_fieldRequired', propagate: 'required' }, fieldTitle: { name: '_fieldTitle', propagate: 'title' }, fieldType: { name: '_fieldType', propagate: 'type' }, fieldFormat: { name: '_fieldFormat', propagate: 'format' }, fieldOptions: { name: '_fieldOptions', propagate: 'options' }, focus: { name: '_focus', propagate: 'focus' }, hasChanged: { name: '_hasChanged', propagate: 'hasChanged' }, intrinsicErrorMessage: { name: '_intrinsicErrorMessage', propagate: null }, maxLength: { name: '_maxLength', propagate: 'maxLength' }, maxValue: { name: '_maxValue', propagate: 'maxValue' }, minLength: { name: '_minLength', propagate: 'minLength' }, minValue: { name: '_minValue', propagate: 'minValue' }, onValidation: { name: '_onValidation', propagate: 'onValidation' }, outputOnly: { name: '_outputOnly', propagate: 'outputOnly' }, placeholder: { name: '_placeholder', propagate: 'placeholder' }, tooltipText: { name: '_tooltipText', propagate: 'tooltip' }, validateOnServer: { name: '_validateOnServer', propagate: 'validateOnServer' }, value: { name: '_value', propagate: 'value' }, visibleLabel: { name: '_visibleLabel', propagate: 'visibleLabel' }, }; class FieldDescriptor extends FormElement { _customEvent = new Subject(); _editionFinish = new Subject(); _editionPartial = new Subject(); _detailRequest = new Subject(); _errorType = ''; _errorCode = ''; _errorMessage = ''; _intrinsicErrorMessage = ''; _minValue; _maxValue; _maxLength = 0; _minLength = 0; _focus = false; _onValidation = false; _validateOnServer = false; _value; _visibleLabel = false; _captureType = ''; _defaultValue = ''; _defaultEditable = false; _externalValue; _fieldAlignment = ''; _fieldInfo = ''; _fieldRequired = false; _fieldTitle = ''; _fieldType = ''; _fieldFormat = null; _hasChanged = false; _outputOnly = false; _tooltipText = ''; _placeholder = ''; _fieldCode = ''; _fieldOptions = null; _customEmpty = null; constructor(inputFieldReceived, formConfig) { super(inputFieldReceived, formConfig); this.elementType = ElementType.Field; const fld = (inputFieldReceived) ? inputFieldReceived : {}; this.setAttr(attrs$2.fieldCode, fld.fieldCode); this.title = fld.fieldTitle ?? this._fieldCode; this.placeholder = fld.placeholder ?? this.title; this.type = fld.fieldTypeCode; this.captureType = fld.captureType ?? DEFAULT_CAPTURE_TYPE; const defaultValue = fld.defaultValue ?? null; if (this._fieldType === this._formConfig.fieldTypes.boolean) { this.defaultValue = defaultValue ?? false; } else { this.defaultValue = defaultValue; } const defaultTypeAlignment = (this._formConfig.tableFieldStyles[this._fieldType] != null) ? this._formConfig.tableFieldStyles[this._fieldType]['text-align'] : DEFAULT_ALIGNMENT; const fieldAlignment = (fld.alignment != null) ? fld.alignment.toLowerCase() : defaultTypeAlignment; this.alignment = fieldAlignment; this.info = fld.info || ''; let fieldFormat; try { if (fld.format && typeof fld.format === 'string') { fieldFormat = new RegExp(fld.format); } else if (fld.format?.regExp) { fieldFormat = new RegExp(fld.format?.regExp); } } catch (e) { fieldFormat = null; } this.format = fieldFormat; this.validateOnServer = fld.serverAction ?? false; this.tooltip = fld.tooltip || ''; this.defaultEditable = this.enabled; this.required = fld.required ?? false; this.outputOnly = fld.outputOnly ?? false; this.minValue = fld.minValue; this.maxValue = fld.maxValue; this.minLength = fld.minLength ?? 0; this.maxLength = fld.maxLength || (this._captureType === 'TEXTAREA' ? BIG_MAX_LENGTH : STD_MAX_LENGTH); this.intrinsicErrorMessage = this._formConfig?.fieldValidations?.[this._fieldType]?.message ?? this._formConfig?.fieldValidations?.DEFAULT?.message ?? ''; this.setError(fld.errorCode, fld.errorMessage, fld.errorType ?? DEFAULT_ERROR_TYPE); this.setEditable(fld.editable ?? true); this.visibleLabel = fld.visibleLabel ?? true; this.setVisibility(fld.visible); this.options = fld.fieldOptions; this._setValue(fld.fieldValue ?? this._defaultValue ?? ''); } get alignment() { return this._fieldAlignment; } set alignment(alignment) { this.setAttr(attrs$2.fieldAlignment, alignment); } get backend() { return this._validateOnServer; } get captureType() { return this._captureType; } set captureType(captureType) { this.setAttr(attrs$2.captureType, captureType); } get placeholder() { return this._placeholder; } set placeholder(placeholder) { this.setAttr(attrs$2.placeholder, placeholder); } get code() { return this._fieldCode; } get defaultValue() { return this._defaultValue; } set defaultValue(defaultValue) { this.setAttr(attrs$2.defaultValue, defaultValue); } get defaultEditable() { return this._defaultEditable; } set defaultEditable(editable) { this.setAttr(attrs$2.defaultEditable, editable); } get detailRequest() { return this._detailRequest.asObservable(); } get customEvent() { return this._customEvent.asObservable(); } get editionFinish() { return this._editionFinish.asObservable(); } get editionPartial() { return this._editionPartial.asObservable(); } get empty() { return this._customEmpty ? this._customEmpty.call(this) : this.defaultEmpty(); } get error() { return { type: this._errorType, code: this._errorCode, message: this._errorMessage }; } set error(errorObj) { this.setError(errorObj.code, errorObj.message, errorObj.type ?? DEFAULT_ERROR_TYPE); } get errorCode() { return this._errorCode; } set errorCode(code) { this.setError(code, this._errorMessage); } get errorMessage() { return this._errorMessage; } set errorMessage(msg) { this.setError(this._errorCode, msg); } get errorType() { return this._errorType; } get externalValue() { return this._externalValue; } get format() { return this._fieldFormat; } set format(format) { this.setAttr(attrs$2.fieldFormat, format); } get hasChanged() { return this._hasChanged; } set hasChanged(hasChanged) { this.setAttr(attrs$2.hasChanged, hasChanged); } get info() { return this._fieldInfo; } set info(newInfo) { this.setAttr(attrs$2.fieldInfo, newInfo); } set intrinsicErrorMessage(message) { this.setAttr(attrs$2.intrinsicErrorMessage, message); } get maxLength() { return (this._maxLength > 0) ? this._maxLength.toString() : ''; } set maxLength(requiredMaxLength) { this.setAttr(attrs$2.maxLength, requiredMaxLength ? +requiredMaxLength : null); } get maxValue() { return this._maxValue; } set maxValue(inputMaxValue) { let maxValue = inputMaxValue; if (this._fieldType === this._formConfig.fieldTypes.date) { maxValue = new Date(maxValue); } this.setAttr(attrs$2.maxValue, maxValue); } get minLength() { return this._minLength; } set minLength(requiredMinLength) { this.setAttr(attrs$2.minLength, requiredMinLength ? +requiredMinLength : null); } get minValue() { return this._minValue; } set minValue(inputMinValue) { let minValue = inputMinValue; if (this._fieldType === this._formConfig.fieldTypes.date) { minValue = new Date(minValue); } this.setAttr(attrs$2.minValue, minValue); } get name() { return this._fieldCode; } get options() { return this._fieldOptions?.map(option => { const optionCopy = { ...option }; return optionCopy; }) ?? []; } set options(newOptions) { if ((!this._formConfig.captureTypesWithOptions.includes(this._captureType)) || typeof newOptions === UNDEFINED || !newOptions || !Array.isArray(newOptions)) { return; } let fieldOptions = newOptions.map((option) => { if (option.text !== undefined && option.text !== null && option.value !== undefined && option.value !== null) { return { fieldOptionValue: option.text, fieldOptionId: option.value }; } return option; }); fieldOptions = (fieldOptions && Array.isArray(fieldOptions) && fieldOptions.length > 0) ? fieldOptions : []; this.setAttr(attrs$2.fieldOptions, fieldOptions); if (this._value) { if (this._fieldType === this._formConfig.fieldTypes.array && Array.isArray(this._value)) { const fieldValue = this._value?.filter(item => this._fieldOptions?.find(opt => opt.fieldOptionId === item)); this.setAttr(attrs$2.value, fieldValue); } else { const valInOptions = this._fieldOptions?.find(item => item.fieldOptionId === this._value); if (!valInOptions) { this._setValue(''); } } } if (this._fieldRequired && this._fieldOptions?.length === 1 && this._value !== this._fieldOptions?.[0].fieldOptionId) { this._setValue(this._fieldOptions?.[0].fieldOptionId); this.notifyEditionFinish(); } } get optionText() { return this._fieldOptions?.find(item => item.fieldOptionId === this._value)?.fieldOptionValue ?? null; } get outputOnly() { return this._outputOnly; } set outputOnly(outputOnly) { this.setAttr(attrs$2.outputOnly, outputOnly); } get required() { return this._fieldRequired; } set required(required) { this.setAttr(attrs$2.fieldRequired, required ?? false); } get title() { return this._fieldTitle; } set title(title) { this.setAttr(attrs$2.fieldTitle, title?.toString() ?? ''); } get tooltip() { return this._tooltipText; } set tooltip(tooltip) { this.setAttr(attrs$2.tooltipText, tooltip); } get type() { return this._fieldType; } set type(fieldType) { this.setAttr(attrs$2.fieldType, fieldType); } get onValidation() { return this._onValidation; } get validating() { return this._onValidation; } set validating(isValidating) { this.setAttr(attrs$2.onValidation, isValidating); } get value() { return (this._fieldType === this._formConfig.fieldTypes.boolean || this._fieldType === this._formConfig.fieldTypes.check) ? yn(this._value) : this._value; } get validateOnServer() { return this._validateOnServer; } set validateOnServer(validateOnServer) { this.setAttr(attrs$2.validateOnServer, validateOnServer); } get serverAction() { return this._validateOnServer; } set serverAction(validateOnServer) { this.validateOnServer = validateOnServer; } set value(newValue) { this._setValue(newValue); } get visibleLabel() { return this._visibleLabel; } set visibleLabel(visibleLabel) { this.setAttr(attrs$2.visibleLabel, visibleLabel); } /** * @deprecated Since v17. Use value instead. Will be removed in v19. */ get fieldValue() { return this.value; } /** * @deprecated Since v17. Use hasChanged instead. Will be removed in v19. */ changed(hasChanged = true) { this.hasChanged = hasChanged; } clean() { this._setValue(this._defaultValue || ''); this.resetError(); } setCustomEmpty(fn) { this._customEmpty = fn; } focus() { this.setAttr(attrs$2.focus, true); } getErrorCode() { return this.error.code; } setErrorCode(code) { this.setError(code, this._errorMessage); } getErrorMessage() { return this.error.message; } setErrorMessage(msg) { this.setError(this._errorCode, msg); } getRequired() { return this.required; } hasError() { return this._errorCode !== NO_ERROR; } hideLabel() { this.visibleLabel = false; } resetError() { (this._errorCode !== NO_ERROR) && this.setError(NO_ERROR, null); } setEditable(editable = true) { (editable) ? this.enable() : this.disable(); } setValue(newValue, widgetUpdate = true) { this._setValue(newValue, widgetUpdate); } showLabel() { this.visibleLabel = true; } /** * @deprecated Since v17. Use code instead. Will be removed in v19. */ get fieldCode() { return this._fieldCode; } /** * @deprecated Since v17. Use title instead. Will be removed in v19. */ setLabel(label) { this.title = label; } /** * @deprecated Since v17. Use required instead. Will be removed in v19. */ setRequired(required) { this.required = required; } /** * @deprecated Since v17. Use changed instead. Will be removed in v19. */ setChanged(hasChanged) { this.changed(hasChanged); } /** * @deprecated Since v17. Use value instead. Will be removed in v19. */ getValue() { return this.value; } /** * @deprecated Since v17. Use empty instead. Will be removed in v19. */ isEmpty() { return this.empty; } /** * @deprecated Since v17. Use error instead. Will be removed in v19. */ getError() { return this.error; } /** * @deprecated Since v17. Use optionText instead. Will be removed in v19. */ getOptionText() { return this.optionText; } /** * @deprecated Since v17. Use options instead. Will be removed in v19. */ getFieldOptions() { return this.options; } /** * @deprecated Since v17. Use options instead. Will be removed in v19. */ setFieldOptions(newOptions) { return this.options = newOptions; } /** * @deprecated Since v17. Use intrinsicErrorMessage instead. Will be removed in v19. */ setIntrinsicErrorMessage(message) { this.intrinsicErrorMessage = message; } /** * @deprecated Since v17. Use maxValue instead. Will be removed in v19. */ setMaxValue(inputMaxValue) { this.maxValue = inputMaxValue; } /** * @deprecated Since v17. Use minValue instead. Will be removed in v19. */ setMinValue(inputMinValue) { this.minValue = inputMinValue; } /** * @deprecated Since v17. Use showLabel instead. Will be removed in v19. */ setVisibleLabel(visibleLabel) { this.visibleLabel = visibleLabel; } defaultEmpty() { const fieldCurrentValue = this.value; if (fieldCurrentValue === undefined || fieldCurrentValue === null) { return true; } if (this._fieldType === this._formConfig.fieldTypes.array && Array.isArray(fieldCurrentValue) && fieldCurrentValue.length === 0) { return true; } ; if (this._fieldType === this._formConfig.fieldTypes.phone) { if (!Array.isArray(fieldCurrentValue)) { return true; } if (fieldCurrentValue.length !== 2 || !fieldCurrentValue[0] || !fieldCurrentValue[1]) { return true; } return false; } ; const arrayFieldTypes = this._formConfig.arrayFieldTypes ?? null; if (arrayFieldTypes && Object.keys(arrayFieldTypes).includes(this._fieldType)) { let arraySize = arrayFieldTypes[this._fieldType]; arraySize = !Number.isNaN(+arraySize) ? +arraySize : 0; if (arraySize === 0) { return (Array.isArray(fieldCurrentValue) && fieldCurrentValue.length === 0); } return (Array.isArray(fieldCurrentValue) && fieldCurrentValue.length < arraySize); } ; return fieldCurrentValue === ''; } notifyEditionPartial() { this.resetError(); this._editionPartial.next({ code: this._fieldCode, intrinsicValidation: true }); } triggerCustomEvent(eventName, eventData) { this._customEvent.next({ code: this._fieldCode, eventName, eventData }); } notifyEditionFinish() { const fieldValue = this.value; this.resetError(); const validationConfig = this._formConfig.fieldValidations?.[this._fieldType] ?? {}; const { type, validation } = validationConfig; let message = validationConfig?.message; let intrinsicValidation = true; if (fieldValue && (validation || this._fieldFormat)) { if (type === 'regexp') { intrinsicValidation = (validation?.test(fieldValue) ?? true) && (this._fieldFormat?.test(fieldValue) ?? true); } else if (type === 'function' && typeof validation === 'function') { const { valid, message: customMessage } = validation(fieldValue, this); intrinsicValidation = valid; message = customMessage; } if (!intrinsicValidation) { this.setError('99', message ?? this._intrinsicErrorMessage); } } if (intrinsicValidation && fieldValue && this._minValue && fieldValue < this._minValue) { intrinsicValidation = false; const formatedMinValue = !isNaN(+this._minValue) ? Number(this._minValue).toLocaleString('es-CO') : this._minValue; this.setError('99', `El valor de ${this.title} no puede ser inferior a ${formatedMinValue}`); } if (intrinsicValidation && fieldValue && this._maxValue && fieldValue > this._maxValue) { intrinsicValidation = false; const formatedMaxValue = !isNaN(+this._maxValue) ? Number(this._maxValue).toLocaleString('es-CO') : this._maxValue; this.setError('99', `El valor de ${this.title} no puede ser superior a ${formatedMaxValue}`); } if (intrinsicValidation && fieldValue && typeof fieldValue === 'string' && this._minLength && fieldValue?.length < this._minLength) { intrinsicValidation = false; this.setError('99', `Longitud de ${this._fieldTitle} debe ser de al menos ${this._minLength}`); } this._editionFinish.next({ code: this._fieldCode, intrinsicValidation }); } notifyEditionDetailRequest(detail) { const detailEvent = { code: this._fieldCode, detail }; this._detailRequest.next(detailEvent); } setError(code, message, type = DEFAULT_ERROR_TYPE) { this.setAttr(attrs$2.errorCode, code ?? NO_ERROR); this.setAttr(attrs$2.errorType, (this._errorCode === NO_ERROR) ? '' : type); this.setAttr(attrs$2.errorMessage, message ?? ''); } updateFromServer(fld) { const fieldKeys = Object.keys(fld); for (let index = 0; index < fieldKeys.length; index++) { const attrName = fieldKeys[index]; const attrValue = fld[attrName]; if (directChanges.includes(attrName)) { this[attrName] = attrValue; } else { (attrName === 'label') && (this.title = attrValue); (attrName === 'labelVisible') && (this.visibleLabel = attrValue); (attrName === 'editable') && this.setEditable(attrValue); (attrName === 'visible') && this.setVisibility(attrValue); (attrName === 'value') && (this._setValue(attrValue) && (this.hasChanged = false)); (attrName === 'fieldValue') && (this._setValue(attrValue) && (this.hasChanged = false)); (attrName === 'fieldOptions') && (this.options = attrValue); (attrName === 'fieldTitle') && (this.title = attrValue); (attrName === 'fieldTypeCode') && (this.type = attrValue); (attrName === 'fieldType') && (this.type = attrValue); (attrName === 'tooltipText') && (this.tooltip = attrValue); (attrName === 'customAttributes') && (this.setCustomAttributes(attrValue)); } } } _setValue(newValue, widgetUpdate = true) { if (typeof newValue === UNDEFINED) { return true; } if (newValue === null && this.required) { return true; } let newFinalValue; if (this._fieldType === this._formConfig.fieldTypes.boolean || this._fieldType === this._formConfig.fieldTypes.check) { newFinalValue = yn(newValue) ?? false; } else if (this._fieldType === this._formConfig.fieldTypes.array || this._fieldType === this._formConfig.fieldTypes.map) { if (newValue === null || newValue === '') { newFinalValue = []; } else if (Array.isArray(newValue)) { newFinalValue = newValue; } else { newFinalValue = newValue.toString().split(','); } } else { newFinalValue = newValue; } if (this._value !== newFinalValue) { this._hasChanged = true; if (widgetUpdate) { this.setAttr(attrs$2.value, newFinalValue); } else { this._value = newFinalValue; } } return true; } } const attrs$1 = { actionCode: { name: '_actionCode', propagate: 'actionCode' }, actionName: { name: '_actionName', propagate: 'actionName' }, iconName: { name: '_iconName', propagate: 'iconName' }, inProgress: { name: '_inProgress', propagate: 'inProgress' }, restrictedOnField: { name: '_restrictedOnField', propagate: 'restrictedOnField' }, restrictedOnOperator: { name: '_restrictedOnOperator', propagate: 'restrictedOnOperator' }, restrictedOnValue: { name: '_restrictedOnValue', propagate: 'restrictedOnValue' }, }; class FormAction extends FormElement { _actionActivated = new Subject(); _actionCode = ''; _actionName = ''; _iconName = ''; _inProgress = false; _newState; _backend; _restrictedOnField = null; _restrictedOnOperator = null; _restrictedOnValue = null; constructor(actionDefinition, formConfig) { super(actionDefinition, formConfig); this.elementType = ElementType.Action; this.setAttr(attrs$1.actionCode, actionDefinition.actionCode ? actionDefinition.actionCode.toString() : ''); this.setAttr(attrs$1.actionName, actionDefinition.actionTitle); this.setAttr(attrs$1.iconName, actionDefinition.iconName || ''); this.setAttr(attrs$1.restrictedOnField, actionDefinition.fieldRestrictedCode?.toString() ?? null); if (this._restrictedOnField) { this.setAttr(attrs$1.restrictedOnOperator, actionDefinition.operatorRestricted || ''); this.setAttr(attrs$1.restrictedOnValue, actionDefinition.valueRestricted ?? ''); } this._backend = actionDefinition?.serverAction ?? false; this._newState = actionDefinition?.newState; this.setCustomAttribute('location', actionDefinition.position || HEADER); } get actionCode() { return this._actionCode; } get actionName() { return this._actionName; } get iconName() { return this._iconName; } get inProgress() { return this._inProgress; } get newState() { return this._newState; } get backend() { return this._backend; } get restrictedOnField() { return this._restrictedOnField; } get restrictedOnOperator() { return this._restrictedOnOperator; } get restrictedOnValue() { return this._restrictedOnValue; } set actionCode(actionCode) { this.setAttr(attrs$1.actionCode, actionCode); } set actionName(actionName) { this.setAttr(attrs$1.actionName, actionName); } set iconName(iconName) { this.setAttr(attrs$1.iconName, iconName); } set inProgress(inProgress) { this.setAttr(attrs$1.inProgress, inProgress); } set newState(newState) { this._newState = newState; } set backend(backend) { this._backend = backend; } set restrictedOnField(restrictedOnField) { this.setAttr(attrs$1.restrictedOnField, restrictedOnField); } set restrictedOnOperator(restrictedOnOperator) { this.setAttr(attrs$1.restrictedOnOperator, restrictedOnOperator); } set restrictedOnValue(restrictedOnValue) { this.setAttr(attrs$1.restrictedOnValue, restrictedOnValue); } start() { this.inProgress = true; } stop() { this.inProgress = false; } connectWithParentForm(form, formChangeSubject) { super.connectWithParentForm(form, formChangeSubject); if (this._restrictedOnField) { const relatedField = this._form.fields?.[this._restrictedOnField]; if (relatedField) { relatedField.editionFinish .pipe(takeUntil(this.destroy$)) .subscribe({ next: (event) => this.updateRestrictedVisibility(event), error: (err) => console.error(`Error en restricted visibility subscription: ${err}`) }); relatedField.editionPartial .pipe(takeUntil(this.destroy$)) .subscribe({ next: (event) => this.updateRestrictedVisibility(event), error: (err) => console.error(`Error en restricted visibility subscription: ${err}`) }); } } } updateRestrictedVisibility(event) { const newVisible = this._absoluteVisible && this.viewOnState(this._formState); (this._visible !== newVisible) && this.setVisibility(newVisible); } viewOnState(state) { const actionVisible = (this.visibleStates && state) ? this.visibleStates.includes(state) : false; if (actionVisible && this._form && this._restrictedOnField) { const relatedField = this._form.fields?.[this._restrictedOnField]; if (relatedField) { const fieldValue = relatedField.value; if ((this._restrictedOnOperator === '==' && fieldValue !== this._restrictedOnValue) || (this._restrictedOnOperator === '!=' && fieldValue === this._restrictedOnValue)) { return false; } } } return actionVisible; } get actionActivated() { return this._actionActivated.asObservable(); } notifyActivation() { this._actionActivated.next(this._actionCode); } updateFromServer(receivedAction) { for (const propertyName in receivedAction) { if (propertyName !== 'actionCode' && propertyName !== 'actionId') { try { this[propertyName] = receivedAction[propertyName]; } catch (e) { console.log(`Error actualizando la propiedad ${propertyName} de la acción ${this.actionCode}. ${e}`); } } } } } class RecordFormSubSection extends FormPiecePropagate { _customRender = null; _subsectionId = null; _subsectionCode = null; _subsectionTitle = null; _subSectionElements = []; _subSectionFields = []; _subSectionTables = []; _subSectionActions = []; _elementsArray = {}; _active = false; constructor(subsectionReceived, formObject, formConfig) { super(subsectionReceived, formConfig); if (!subsectionReceived) { return; } this._subsectionId = (subsectionReceived.subsectionId) ? subsectionReceived.subsectionId.toString() : ''; this._subsectionCode = (subsectionReceived.subsectionCode) ? subsectionReceived.subsectionCode : ''; this._subsectionTitle = (subsectionReceived.subsectionTitle) ? subsectionReceived.subsectionTitle : ''; if (subsectionReceived.elements) { for (const receivedElement of subsectionReceived.elements) { let elementObject = null; let arrayToAdd = []; const { type, code } = receivedElement; switch (type) { case ElementType.Field: elementObject = formObject.getField(code); arrayToAdd = this._subSectionFields; break; case ElementType.Table: elementObject = formObject.getTable(code); arrayToAdd = this._subSectionTables; break; case ElementType.Action: elementObject = formObject.getAction(code); arrayToAdd = this._subSectionActions; break; } if (elementObject) { elementObject.elementType = type; arrayToAdd.push(elementObject); this._subSectionElements.push(elementObject); this._elementsArray[code] = elementObject; } } } } get customRender() { return this._customRender; } set customRender(customRenderName) { this._customRender = customRenderName; } get subsectionId() { return this._subsectionId; } get subsectionCode() { return this._subsectionCode; } get subsectionTitle() { return this._subsectionTitle; } get subSectionElements() { return this._subSectionElements; } get subSectionFields() { return this._subSectionFields; } get subSectionTables() { return this._subSectionTables; } get subSectionActions() { return this._subSectionActions; } get elementsArray() { return this._elementsArray; } get active() { return this._active; } set subsectionId(subsectionId) { this._subsectionId = subsectionId; } set subsectionCode(subsectionCode) { this._subsectionCode = subsectionCode; } set subsectionTitle(subsectionTitle) { this._subsectionTitle = subsectionTitle; } set subSectionElements(subSectionElements) { this._subSectionElements = subSectionElements; } set subSectionFields(subSectionFields) { this._subSectionFields = subSectionFields; } set subSectionTables(subSectionTables) { this._subSectionTables = subSectionTables; } set subSectionActions(subSectionActions) { this._subSectionActions = subSectionActions; } set elementsArray(elementsArray) { this._elementsArray = elementsArray; } set active(active) { this._active = active; } getField(name) { return this._subSectionFields.find(fld => fld.name === name); } getFields() { return this._subSectionFields; } getFieldNames() { return this._subSectionFields.map(field => field.code); } getActions() { return this._subSectionActions; } getActionNames() { return this._subSectionActions.map(action => action.actionCode); } activate() { if (!this._active) { this._active = true; } } inactivate() { if (this._active) { this._active = false; } } } const ACTIVE$1 = 'active'; class RecordFormSection extends FormPiecePropagate { _activation = new Subject(); _inactivation = new Subject(); _active = false; _sectionId = null; _sectionCode = null; _sectionTitle = null; _subSections = []; _subSectionsObj = {}; _exclusiveSubSectionsByAttr = {}; constructor(sectionReceived, formObject, formConfig) { super(sectionReceived, formConfig); if (!sectionReceived) { return; } this._sectionId = (sectionReceived.sectionId) ? sectionReceived.sectionId.toString() : ''; this._sectionCode = (sectionReceived.sectionCode) ? sectionReceived.sectionCode : ''; this._sectionTitle = (sectionReceived.sectionTitle) ? sectionReceived.sectionTitle : ''; this._subSections = []; this._subSectionsObj = {}; if (sectionReceived.subsections) { const subsections = sectionReceived.subsections.map(subSecDef => { const visibleStates = subSecDef.visibleStates ?? []; if (subSecDef.elements && Array.isArray(subSecDef.elements)) { subSecDef.elements = subSecDef.elements.map((elm) => ({ code: elm.elementCode, type: elm.elementTypeName })); } return { ...subSecDef, visibleStates }; }); for (const subsectionReceived of subsections) { const subSectionToAdd = new RecordFormSubSection(subsectionReceived, formObject, formConfig); const subsectionCode = subSectionToAdd.subsectionCode; if (subsectionCode) { this._subSections.push(subSectionToAdd); this._subSectionsObj[subsectionCode] = subSectionToAdd; } } } } get code() { return this._sectionCode; } get activation() { return this._activation.asObservable(); } get inactivation() { return this._inactivation.asObservable(); } get active() { return this._active; } get sectionId() { return this._sectionId; } get sectionCode() { return this._sectionCode; } get sectionTitle() { return this._sectionTitle; } get subSections() { return this._subSections; } get subSectionsObj() { return this._subSectionsObj; } set active(active) { this._active = active; } set sectionId(sectionId) { this._sectionId = sectionId; } set sectionCode(sectionCode) { this._sectionCode = sectionCode; } set sectionTitle(sectionTitle) { this._sectionTitle = sectionTitle; } set subSections(subSections) { this._subSections = subSections; } set subSectionsObj(subSectionsObj) { this._subSectionsObj = subSectionsObj; } activate() { if (!this._active) { this._active = true; this._sectionCode && this._activation.next(this._sectionCode); } } inactivate() { if (this._active) { this._active = false; this._sectionCode && this._inactivation.next(this._sectionCode); } } get title() { return this._sectionTitle; } set title(title) { this._sectionTitle = title; } getVisibleSubsections(state) { return this._subSections.filter(subSection => subSection.visible); } getSubsection(subSectionCode) { return (this._subSectionsObj && this._subSectionsObj[subSectionCode]) ? this._subSectionsObj[subSectionCode] : null; } activateSubSection(subSectionCode) { if (subSectionCode === this._exclusiveSubSectionsByAttr[ACTIVE$1]) { return; } const subSection = (this._subSectionsObj && this._subSectionsObj[subSectionCode]) ? this._subSectionsObj[subSectionCode] : null; if (subSection) { subSection?.activate(); this._exclusiveSubSectionsByAttr[ACTIVE$1] = subSectionCode; } } getFields() { let fieldsArray = []; if (this._subSections && this._subSections.length > 0) { for (const subSection of this._subSections) { const subsectionFields = subSection.getFields() ?? []; if (subsectionFields?.length > 0) { fieldsArray = fieldsArray.concat(subsectionFields); } } } return fieldsArray; } getActions() { let actionArray = []; if (this._subSections && this._subSections.length > 0) { for (const subSection of this._subSections) { const subSectionActions = subSection.getActions() ?? []; if (subSectionActions?.length > 0) { actionArray = actionArray.concat(subSectionActions); } } } return actionArray; } getActionNames() { let actionArray = []; if (this._subSections && this._subSections.length > 0) { for (const subSection of this._subSections) { actionArray = actionArray.concat(subSection.getActionNames()); } } return actionArray; } getFieldNames() { let fieldsArray = []; if (this._subSections && this._subSections.length > 0) { for (const subSection of this._subSections) { fieldsArray = fieldsArray.concat(subSection.getFieldNames()); } } return fieldsArray; } getField(name) { let field = null; if (this._subSections && this._subSections.length > 0) { for (const subSection of this._subSections) { field = subSection.getField(name); if (field) { return field; } } } return null; } formStateChangeCustomSubscribe(form, formChangeSubject) { this._subSections?.forEach(subsection => { subsection?.connectWithParentForm(form, formChangeSubject); }); } } class RecordTableColumn extends FormPiece { fieldCode = ''; fieldTitle = ''; fieldType = ''; fieldAlignment = ''; fieldFormat = ''; sortable = true; searchable = true; sortDirections = []; // Filtros filterVisible = false; filterDef = null; filterSetup = null; constructor(recTableColReceived, formConfig) { super(recTableColReceived, formConfig); this.filterDef = null; if (recTableColReceived) { this.fieldCode = recTableColReceived.fieldCode; this.fieldTitle = recTableColReceived.fieldTitle ?? ''; this.fieldType = recTableColReceived.fieldTypeCode || this._formConfig.fieldTypes.text; const defaultTypeAlignment = (this._formConfig.tableFieldStyles[this.fieldType] != null) ? this._formConfig.tableFieldStyles[this.fieldType]['text-align'] : 'left'; this.fieldAlignment = (recTableColReceived.alignment != null) ? recTableColReceived.alignment.toLowerCase() : defaultTypeAlignment; this._absoluteVisible = recTableColReceived?.visible ?? true; this.sortable = recTableColReceived?.sortable ?? false; this.searchable = recTableColReceived?.searchable ?? true; this.sortDirections = (this.sortable) ? ['ascend', 'descend'] : []; this.fieldFormat = recTableColReceived.format || ''; this.customAttributes = recTableColReceived?.customAttributes ?? {}; } } setSearchable(searchable = true) { this.searchable = searchable; } hideFilter() { this.filterVisible = false; } addFilterDefinition(filterDefinition) { this.filterDef = { operators: filterDefinition.operators, options: filterDefinition.options ?? null, }; } get filterDefinition() { return this.filterDef; } addFilter(columnValues, operato