UNPKG

tuain-ng-forms-lib

Version:

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

1,210 lines 194 kB
import { Component, signal } from '@angular/core'; import { Subject, takeUntil } from 'rxjs'; import { FormStructureAndData } from '../../classes/forms/form'; import { formActions, NO_ERROR } from '../../classes/forms/form.constants'; import * as i0 from "@angular/core"; import * as i1 from "../../services/form-manager.service"; import * as i2 from "../../services/event-manager.service"; import * as i3 from "../../services/file-manager.service"; const PAYLOAD_VERSION = 'TUAINEXCHANGE_1.0'; const INLINE_ACTION = 'INLINE'; const GLOBAL_ACTION = 'GLOBAL'; const GET_DATA_ACTION = 'GETDATA'; const SUBJECT = 'subject'; const TOKEN = 'token'; export class BasicFormComponent extends FormStructureAndData { formManagerService; _eventManager; fileMgmtServices; destroy$ = new Subject(); _controlToken = null; _originToken = null; _formRoute = null; _definitionObtained = false; _notifyFormActivity = true; // Eventos de acciones y campos _formChangeState = []; _formSectionsCanDeactivate = {}; _formSectionsActivate = {}; _formSectionsInactivate = {}; _formActionsStart = {}; _formActionsFinish = {}; _fieldCustomeEvent = {}; _fieldInputValidation = {}; _fieldValidationsStart = {}; _fieldValidationsFinish = {}; // Callback de acciones de tablas _tableSelectionsStart = {}; _tableSelectionsFinish = {}; _tableActionsStart = {}; _tableActionsFinish = {}; _tableGetDataStart = {}; _tableGetDataFinish = {}; // Errores en procesos _actionServerError = []; _fieldServerError = []; _tableServerError = []; // Datos complementarios del formulario inputDataFields = {}; extraData = {}; _eventEmiter; enabledSections = []; // Gestión de error _errorType = ''; errorCode = ''; errorFullCode = ''; errorName = ''; errorMessage = ''; errorDetail = ''; // Control de estado visible = false; busy = signal(false); constructor(formManagerService, _eventManager, fileMgmtServices) { super(); this.formManagerService = formManagerService; this._eventManager = _eventManager; this.fileMgmtServices = fileMgmtServices; this._eventEmiter = this._eventManager; this.cleanStart(); this.preStart(); this.customPreProcessing(); } cleanStart() { this._errorType = ''; this.errorCode = ''; this.errorFullCode = ''; this.errorName = ''; this.errorMessage = ''; this.errorDetail = ''; this.cleanForm(); this._controlToken = null; this.inputDataFields = {}; this._definitionObtained = false; // Se limpian los manejadores de eventos this.visible = false; this.busy.set(false); this._formChangeState = []; this._formSectionsCanDeactivate = {}; this._formSectionsActivate = {}; this._formSectionsInactivate = {}; this._formActionsStart = {}; this._formActionsFinish = {}; this._fieldCustomeEvent = {}; this._fieldInputValidation = {}; this._fieldValidationsStart = {}; this._fieldValidationsFinish = {}; this._tableSelectionsStart = {}; this._tableSelectionsFinish = {}; this._tableActionsStart = {}; this._tableActionsFinish = {}; this._tableGetDataStart = {}; this._tableGetDataFinish = {}; this._actionServerError = []; this._fieldServerError = []; this._tableServerError = []; this.onActionServerError(() => this.displayActionServerError()); this.onValidationServerError(() => this.displayValidationServerError()); this.onTableServerError(() => this.displayTableServerError()); } get formVisible() { return this.visible; } get form() { return this; } // Métodos virtuales preStart() { } start() { } /** * @deprecated Use preStart */ customPreProcessing() { } /** * @deprecated Overload start */ customFormStart() { } displayActionServerError() { } displayValidationServerError() { } displayTableServerError() { } showFieldInfo(code, detail) { } showModalDialog(title, body, options, callback, params) { } openUploadDialog(title, body, options, callback, params) { } subscribeAppEvent(eventName, callback) { this._eventEmiter.subscribe(eventName, callback); } openForm(name, data = null, backData = null, cleanStack = false) { let origin = null; if (!cleanStack) { origin = { ...backData, name: this.name, url: this._formRoute, token: this._controlToken }; origin.subject = origin?.subject ?? this.subject; origin.state = origin?.state ?? this.state; origin.fields = origin?.fields ?? {}; origin.extra = origin?.extra ?? {}; } const target = { ...data, name }; target.subject = target?.subject ?? null; target.state = target?.state ?? null; target.fields = target?.fields ?? {}; target.extra = target?.extra ?? {}; this.formManagerService.openForm(origin, target); } enableActivityNotification() { this._notifyFormActivity = true; } disableActivityNotification() { this._notifyFormActivity = false; } canGoBack() { return this._originToken !== null; } goBack() { return this.formManagerService.backTo(); } goBackForm() { return this.goBack(); } getOriginDetail() { return this.formManagerService?.getFormInfo(this._originToken ?? ''); } setError(errorType, errorMessage, errorDetail) { this._errorType = errorType || ''; this.errorMessage = errorMessage || ''; this.errorDetail = errorDetail || ''; } resetError() { this.errorCode = NO_ERROR; this.errorFullCode = ''; this.errorName = ''; this.errorMessage = ''; this.errorDetail = ''; } getErrorType() { return this._errorType; } getErrorMessage() { return this.errorMessage; } getErrorDetail() { return this.errorDetail; } getErrorName() { return this.errorName; } getErrorFullCode() { return this.errorFullCode; } getErrorCode() { return this.errorCode; } getFormParameter(name) { return (name) ? (this.extraData?.[name] ?? null) : null; } preocessInputParams(params) { this._controlToken = params?.[TOKEN] ?? null; this.subject = params?.[SUBJECT] ?? null; const tokenInfo = (this._controlToken) ? this.formManagerService.getFormInfo(this._controlToken) : {}; const { token, subject, state, fields, extra, originToken } = tokenInfo; if (token && this._controlToken === token) { this.subject = this.subject ?? subject ?? null; this.inputDataFields = fields; this.extraData = extra; this._originToken = originToken; return state; } return null; } subscribeSectionActivation() { const formSections = this.sections; const sectionNames = Object.keys(formSections); for (let index = 0; index < sectionNames.length; index++) { const sectionName = sectionNames[index]; const section = formSections[sectionName]; section.activation .pipe(takeUntil(this.destroy$)) .subscribe((code) => this.launchSectionActivation(code)); section.inactivation .pipe(takeUntil(this.destroy$)) .subscribe((code) => this.launchSectionInactivation(code)); // Adicionalmente se le pide a la sección se subscriba al cambio de estado del formulario section.connectWithParentForm(this, this.stateChange); } } subscribeFieldsSubjects() { const formFields = this.getFields(); if (Array.isArray(formFields)) { formFields.forEach(field => { field.customEvent .pipe(takeUntil(this.destroy$)) .subscribe(event => { const { code, eventName, eventData } = event; this.startFieldCustomEvent(code, eventName, eventData); }); field.editionFinish .pipe(takeUntil(this.destroy$)) .subscribe(event => { const { code, intrinsicValidation } = event; this.startFieldValidation(code, intrinsicValidation); }); field.editionPartial .pipe(takeUntil(this.destroy$)) .subscribe(event => { const { code, intrinsicValidation } = event; this.startFieldInputValidation(code, intrinsicValidation); }); field.detailRequest .pipe(takeUntil(this.destroy$)) .subscribe(event => this.showFieldInfo(event.code, event.detail)); // Adicionalmente se le pide al campo se subscriba al cambio de estado del formulario field.connectWithParentForm(this, this.stateChange); }); } } subscribeActionSubjects() { const formActions = this.getActions(); if (Array.isArray(formActions)) { formActions.forEach(action => { action.actionActivated .pipe(takeUntil(this.destroy$)) .subscribe(code => this.startAction(code)); // Adicionalmente se le pide a la acción se subscriba al cambio de estado del formulario action.connectWithParentForm(this, this.stateChange); }); } } subscribeTableSubjects() { const formTables = this.getTables(); if (Array.isArray(formTables)) { formTables.forEach(table => { table.inlineActionTrigger .pipe(takeUntil(this.destroy$)) .subscribe(event => this.startTableAction(event)); table.globalActionTrigger .pipe(takeUntil(this.destroy$)) .subscribe(event => this.startTableGlobalAction(event)); table.recordSelectionTrigger .pipe(takeUntil(this.destroy$)) .subscribe(event => this.startTableRecordSelection(event)); table.selectionActionTrigger .pipe(takeUntil(this.destroy$)) .subscribe(event => this.startTableSelectionAction(event)); table.getDataTrigger .pipe(takeUntil(this.destroy$)) .subscribe(event => this.startTableGetData(event)); // Adicionalmente se le pide a la tabla se subscriba al cambio de estado del formulario table.connectWithParentForm(this, this.stateChange); }); } } async formInit(params, forceReload = false) { let initialState = this.preocessInputParams(params); if (!this.name) { return; } if (forceReload || !this._definitionObtained) { this.busy.set(true); const formDefinition = await this.formManagerService.getFormDefinition(this.name); this.busy.set(false); this.loadDefinition(formDefinition); this._definitionObtained = true; } else { this.cleanData(); } if (!this.supportState(initialState ?? '')) { initialState = this.defaultState ?? null; } const inputFieldNames = Object.keys(this.inputDataFields); for (let index = 0; index < inputFieldNames.length; index++) { const code = inputFieldNames[index]; const fieldValue = this.inputDataFields[code]; this.setFieldValue(code, fieldValue); } this.subscribeSectionActivation(); this.subscribeFieldsSubjects(); this.subscribeActionSubjects(); this.subscribeTableSubjects(); // Se define el estado inicial y se solicita la acción inicial this.changeState(initialState || this.defaultState); if (this.loadInitialData) { const recordResponse = await this.requestFormAction(formActions.getData); this.checkErrorRecordReceived(recordResponse); } this.visible = true; this.enabledSections = this.visibleSections ?? []; this.start(); this.customFormStart(); } changeState(state) { const stateChanged = super.changeState(state ?? '') ?? false; if (stateChanged) { const clientActionMethods = this._formChangeState; if (clientActionMethods && clientActionMethods.length > 0) { for (const callback of clientActionMethods) { callback(state); } } } return stateChanged; } checkErrorRecordReceived(recordResponse) { const { error } = recordResponse ?? {}; if (!error) { return false; } this.errorCode = recordResponse.errorCode; this.errorFullCode = recordResponse.errorFullCode; this.errorName = recordResponse.errorName; this.errorMessage = recordResponse.errorMessage; this.errorDetail = recordResponse.errorDetail; return true; } errorOccured() { return (this.errorCode !== NO_ERROR); } /** * Soporte manejo de eventos de formulario */ async requestFormAction(actionCode, actionSubject = {}) { const actionDetail = { formCode: this.name, formSubject: this.subject, currentMode: this.state, actionCode, actionSubject, version: PAYLOAD_VERSION, formData: this.getPayload(), immutableData: this.immutableData, }; this.errorCode = NO_ERROR; this.errorFullCode = ''; this.errorName = ''; this.errorMessage = ''; this.errorDetail = ''; this.busy.set(true); const formActionResponse = await this.formManagerService.execServerAction(actionDetail); if (!formActionResponse) { return null; } this.busy.set(false); if (formActionResponse.hasError()) { const error = formActionResponse.error; this.errorCode = error.errorCode; this.errorFullCode = error.errorFullCode; this.errorName = error.errorName; this.errorMessage = error.errorMessage; this.errorDetail = error.errorDetail; } const formResponseData = formActionResponse.getData(); this.updateFormWithServerData(formResponseData); return formResponseData; } updateFormWithServerData(formContent) { const { currentMode, formSubject, actions, fields, recordTables, returnedFile, immutableData, extraInfo, } = formContent; currentMode && this.changeState(currentMode); if (formSubject) { this.subject = formSubject; } if (actions && actions.length > 0) { for (const changedAction of actions) { const actionObject = this.getAction(changedAction.actionCode); if (actionObject) { actionObject.updateFromServer(changedAction); } } } if (fields && fields.length > 0) { for (const changedField of fields) { const fieldObject = this.getField(changedField.fieldCode); if (fieldObject) { fieldObject.updateFromServer(changedField); } } } if (recordTables && recordTables.length > 0) { for (const changedTable of recordTables) { const tableObject = this.getTable(changedTable.tableCode); if (tableObject) { tableObject.updateFromServer(changedTable); } } } if (returnedFile && returnedFile.file) { this.fileMgmtServices.saveFile(returnedFile.file, returnedFile.name, returnedFile.type); } this.immutableData = immutableData; this.extraInfo = extraInfo; } /** * Manejo de event handlers para errores Server del formulario */ cleanActionServerError() { this._actionServerError = []; } cleanFieldServerError() { this._fieldServerError = []; } cleanTableServerError() { this._tableServerError = []; } onActionServerError(callback, properties = null) { this._actionServerError.push({ callback, properties }); } onValidationServerError(callback, properties = null) { this._fieldServerError.push({ callback, properties }); } onTableServerError(callback, properties = null) { this._tableServerError.push({ callback, properties }); } /** * Manejo de event handlers para acciones sobre el formulario */ onFormChange(callback) { this._formChangeState.push(callback); } onSectionCanDeactivate(codes, callback, properties = null) { const sectionSet = (Array.isArray(codes)) ? codes : (codes ? [codes] : []); sectionSet.forEach((sectionName) => { if (!this._formSectionsCanDeactivate[sectionName]) { this._formSectionsCanDeactivate[sectionName] = []; } this._formSectionsCanDeactivate[sectionName].push({ callback, properties }); }); } onSectionActivation(codes, callback, properties = null) { const sectionSet = (Array.isArray(codes)) ? codes : (codes ? [codes] : []); sectionSet.forEach((sectionName) => { if (!this._formSectionsActivate[sectionName]) { this._formSectionsActivate[sectionName] = []; } this._formSectionsActivate[sectionName].push({ callback, properties }); }); } onSectionInactivation(codes, callback, properties = null) { const sectionSet = (Array.isArray(codes)) ? codes : (codes ? [codes] : []); sectionSet.forEach((sectionName) => { if (!this._formSectionsInactivate[sectionName]) { this._formSectionsInactivate[sectionName] = []; } this._formSectionsInactivate[sectionName].push({ callback, properties }); }); } onActionStart(codes, callback, properties = null) { const actionSet = (Array.isArray(codes)) ? codes : (codes ? [codes] : []); actionSet.forEach((actionName) => { if (!this._formActionsStart[actionName]) { this._formActionsStart[actionName] = []; } this._formActionsStart[actionName].push({ callback, properties }); }); } onActionFinish(codes, callback, properties = null) { const actionSet = (Array.isArray(codes)) ? codes : (codes ? [codes] : []); actionSet.forEach((actionName) => { if (!this._formActionsFinish[actionName]) { this._formActionsFinish[actionName] = []; } this._formActionsFinish[actionName].push({ callback, properties }); }); } async verifySectionActivation(code) { const sectionObject = this.getSection(code); if (!sectionObject) { return false; } const clientSectionMethods = this._formSectionsCanDeactivate[code]; if (clientSectionMethods) { for (const clientSectionMethod of clientSectionMethods) { const { callback, properties } = clientSectionMethod; const canActivate = callback(sectionObject); if (canActivate === false) { return false; } } } return true; } async launchSectionActivation(code) { this.notifyFormActivity(); const sectionObject = this.getSection(code); if (!sectionObject) { return; } const clientSectionMethods = this._formSectionsActivate[code]; if (clientSectionMethods) { for (const clientSectionMethod of clientSectionMethods) { const { callback, properties } = clientSectionMethod; callback(sectionObject); } } } async launchSectionInactivation(code) { this.notifyFormActivity(); const sectionObject = this.getSection(code); if (!sectionObject) { return; } const clientSectionMethods = this._formSectionsInactivate[code]; if (clientSectionMethods) { for (const clientSectionMethod of clientSectionMethods) { const { callback, properties } = clientSectionMethod; callback(sectionObject); } } } async startAction(code) { this.notifyFormActivity(); const actionObject = this.getAction(code); if (!actionObject) { return; } this.resetError(); actionObject.start(); const clientActionMethods = this._formActionsStart[code]; if (clientActionMethods) { const clientActionPromises = []; for (const clientActionMethod of clientActionMethods) { const { callback, properties } = clientActionMethod; const continueActionPromise = callback(actionObject); clientActionPromises.push(continueActionPromise); } const clientActionResults = await Promise.all(clientActionPromises); const continueAction = clientActionResults.reduce((total, curr) => (total && (curr !== false)), true); if (!continueAction) { actionObject.stop(); return; } } this.startServerAction(actionObject); } async startServerAction(actionInput) { const action = (typeof actionInput === 'string') ? this.getAction(actionInput) : actionInput; if (!action) { return; } let serverError = false; let actionResult = null; if (action.backend) { actionResult = await this.requestFormAction(action.actionCode); } await this.finishAction(action, actionResult, serverError); serverError = !!this.errorOccured(); if (!serverError) { action.newState && this.changeState(action.newState); } else { for (let index = 0; index < this._actionServerError.length; index++) { const { callback, properties } = this._actionServerError[index]; callback(action); } } action.stop(); } async finishAction(action, actionResult, serverError = false) { const finishActionMethods = this._formActionsFinish[action.actionCode]; if (finishActionMethods) { const clientActionPromises = []; for (const clientActionMethod of finishActionMethods) { const { callback, properties } = clientActionMethod; const continueOnError = properties?.continueOnError ?? false; if (callback && (!serverError || continueOnError)) { clientActionPromises.push(callback(action, actionResult)); } } await Promise.all(clientActionPromises); } } completeGlobalAction(action) { return this.startServerAction(action); } /** * Manejadores de eventos para validaciones sobre campos */ onFieldInput(codes, callback, properties = null) { const fieldSet = (Array.isArray(codes)) ? codes : (codes ? [codes] : []); fieldSet.forEach((code) => { if (!this._fieldInputValidation[code]) { this._fieldInputValidation[code] = []; } this._fieldInputValidation[code].push({ callback, properties }); }); } onFieldCustomEvent(codes, callback, properties = null) { const fieldSet = (Array.isArray(codes)) ? codes : (codes ? [codes] : []); fieldSet.forEach((code) => { if (!this._fieldCustomeEvent[code]) { this._fieldCustomeEvent[code] = []; } this._fieldCustomeEvent[code].push({ callback, properties }); }); } onFieldValidationStart(codes, callback, properties = null) { const fieldSet = (Array.isArray(codes)) ? codes : (codes ? [codes] : []); fieldSet.forEach((code) => { if (!this._fieldValidationsStart[code]) { this._fieldValidationsStart[code] = []; } this._fieldValidationsStart[code].push({ callback, properties }); }); } onFieldValidationFinish(codes, callback, properties = null) { const fieldSet = (Array.isArray(codes)) ? codes : (codes ? [codes] : []); fieldSet.forEach((code) => { if (!this._fieldValidationsFinish[code]) { this._fieldValidationsFinish[code] = []; } this._fieldValidationsFinish[code].push({ callback, properties }); }); } async startFieldInputValidation(code, intrinsicValidation = true) { this.notifyFormActivity(); const fieldToValidate = this.getField(code); if (!fieldToValidate) { return false; } const validationCallbacks = this._fieldInputValidation[code]; if (validationCallbacks) { const clientValidationPromises = []; for (const validationMethod of validationCallbacks) { const { callback, properties } = validationMethod; const continueValidationPromise = callback(fieldToValidate); clientValidationPromises.push(continueValidationPromise); } await Promise.all(clientValidationPromises); } return true; } async startFieldCustomEvent(code, eventName, eventData) { this.notifyFormActivity(); const fieldToTrigger = this.getField(code); if (!fieldToTrigger) { return; } const eventHandlerCallbacks = this._fieldCustomeEvent[code]; if (eventHandlerCallbacks) { const clientEventPromises = []; for (const eventHandlerMethod of eventHandlerCallbacks) { const { callback, properties } = eventHandlerMethod; const clientEventPromise = callback(eventName, eventData, fieldToTrigger); clientEventPromises.push(clientEventPromise); } } } async startFieldValidation(code, intrinsicValidation = true) { this.notifyFormActivity(); const fieldToValidate = this.getField(code); if (!fieldToValidate) { return; } const validationCallbacks = this._fieldValidationsStart[code]; if (validationCallbacks) { const clientValidationPromises = []; for (const validationMethod of validationCallbacks) { const { callback, properties } = validationMethod; const clientValidationPromise = callback(fieldToValidate); clientValidationPromises.push(clientValidationPromise); } const clientValidationResults = await Promise.all(clientValidationPromises); const continueValidation = clientValidationResults.reduce((total, curr) => (total && (curr !== false)), true); if (!continueValidation) { return; } } if (intrinsicValidation) { this.startServerFieldValidation(fieldToValidate); } } async startServerFieldValidation(inputField) { const fieldObj = (typeof inputField === 'string') ? this.getField(inputField) : inputField; let serverError = false; let validationResult = true; if (!fieldObj) { return; } if (fieldObj.backend) { fieldObj.validating = true; validationResult = await this .requestFormAction(formActions.validate, fieldObj.code); serverError = !!this.errorOccured(); } if (serverError) { fieldObj?.setErrorCode(this.errorCode); fieldObj?.setErrorMessage(this.errorMessage); for (let index = 0; index < this._fieldServerError.length; index++) { const { callback, properties } = this._fieldServerError[index]; callback(fieldObj); } } await this.finishFieldValidation(fieldObj, validationResult, serverError); fieldObj.validating = false; } async finishFieldValidation(fieldObject, validationResult, serverError = false) { const validationCallbacks = this._fieldValidationsFinish[fieldObject.code]; if (validationCallbacks) { const clientActionPromises = []; for (const validationMethod of validationCallbacks) { const { callback, properties } = validationMethod; const continueOnError = properties?.continueOnError ?? false; if (!serverError || continueOnError) { clientActionPromises.push(callback(fieldObject, validationResult)); } } await Promise.all(clientActionPromises); } } async continueFieldValidation(code) { return this.startServerFieldValidation(code); } /** * Manejadores de eventos para acciones sobre Tablas */ onTableActionStart(code, actionCode, callback, properties = null) { const tableObject = this.getTable(code); if (!tableObject) { return; } const inlineActionObject = tableObject.getAction(actionCode); if (!inlineActionObject) { return; } let tableEventHandlers; if (this._tableActionsStart[code]) { tableEventHandlers = this._tableActionsStart[code]; } else { tableEventHandlers = {}; this._tableActionsStart[code] = tableEventHandlers; } if (!tableEventHandlers[actionCode]) { tableEventHandlers[actionCode] = []; } tableEventHandlers[actionCode].push({ callback, properties }); } onTableActionFinish(code, actionCode, callback, properties = null) { const tableObject = this.getTable(code); if (!tableObject) { return; } const inlineActionObject = tableObject.getAction(actionCode); if (!inlineActionObject) { return; } let tableEventHandlers; if (this._tableActionsFinish[code]) { tableEventHandlers = this._tableActionsFinish[code]; } else { tableEventHandlers = {}; this._tableActionsFinish[code] = tableEventHandlers; } if (!tableEventHandlers[actionCode]) { tableEventHandlers[actionCode] = []; } tableEventHandlers[actionCode].push({ callback, properties }); } onTableSelectionStart(code, callback, properties = null) { const tableObject = this.getTable(code); if (!tableObject) { return; } let tableEventHandlers; if (this._tableSelectionsStart[code]) { tableEventHandlers = this._tableSelectionsStart[code]; } else { tableEventHandlers = []; this._tableSelectionsStart[code] = tableEventHandlers; } tableEventHandlers.push({ callback, properties }); } onTableSelectionFinish(code, callback, properties = null) { const tableObject = this.getTable(code); if (!tableObject) { return; } let tableEventHandlers; if (this._tableSelectionsFinish[code]) { tableEventHandlers = this._tableSelectionsFinish[code]; } else { tableEventHandlers = []; this._tableSelectionsFinish[code] = tableEventHandlers; } tableEventHandlers.push({ callback, properties }); } onTableGetDataStart(code, callback, properties = null) { const tableObject = this.getTable(code); if (!tableObject) { return; } let tableEventHandlers; if (this._tableGetDataStart[code]) { tableEventHandlers = this._tableGetDataStart[code]; } else { tableEventHandlers = []; this._tableGetDataStart[code] = tableEventHandlers; } tableEventHandlers.push({ callback, properties }); } onTableGetDataFinish(code, callback, properties = null) { const tableObject = this.getTable(code); if (!tableObject) { return; } let tableEventHandlers; if (this._tableGetDataFinish[code]) { tableEventHandlers = this._tableGetDataFinish[code]; } else { tableEventHandlers = {}; this._tableGetDataFinish[code] = tableEventHandlers; } tableEventHandlers[GET_DATA_ACTION] = { callback, properties }; } async startTableGlobalAction(tableActionEvent) { this.notifyFormActivity(); const { tableCode, actionCode } = tableActionEvent; const tableObject = this.getTable(tableCode); if (!tableObject || !actionCode) { return; } this.resetError(); const action = tableObject.getAction(actionCode); if (!action) { return; } const tableActionDetail = { tableObject, action, tableCode, actionCode, }; const tableEventHandlers = this._tableActionsStart[tableCode]; const tableActionMethods = (tableEventHandlers) ? tableEventHandlers[actionCode] : null; if (tableActionMethods) { const clientActionPromises = []; for (const tableActionMethod of tableActionMethods) { const { callback, properties } = tableActionMethod; const clientActionPromise = callback(tableActionDetail); clientActionPromises.push(clientActionPromise); } const clientActionResults = await Promise.all(clientActionPromises); const continueAction = clientActionResults.reduce((total, curr) => (total && (curr !== false)), true); if (!continueAction) { return; } } this.startTableServerGlobalAction(tableActionDetail); } async startTableServerGlobalAction(tableActionDetail) { const { tableObject, action, tableCode, actionCode } = tableActionDetail; if (!tableObject || !action) { return; } tableObject.putOnWait(); let serverError = false; let actionResult = null; if (action.backend) { const actionSubject = { tableCode, actionType: GLOBAL_ACTION, actionCode }; actionResult = await this .requestFormAction(formActions.tableAction, actionSubject); serverError = !!this.errorOccured(); } await this.finishTableGlobalAction(tableActionDetail, actionResult, serverError); if (!serverError) { action.newState && this.changeState(action.newState); } else { for (let index = 0; index < this._tableServerError.length; index++) { const { callback, properties } = this._tableServerError[index]; callback(tableObject); } } tableObject.freeWaiting(); } async finishTableGlobalAction(tableActionDetail, actionResult, serverError = false) { const { tableCode, actionCode } = tableActionDetail; const tableEventHandlers = this._tableActionsFinish[tableCode]; const tableActionMethods = (tableEventHandlers) ? tableEventHandlers[actionCode] : null; if (tableActionMethods) { const clientActionPromises = []; for (const tableActionMethod of tableActionMethods) { const { callback, properties } = tableActionMethod; const continueOnError = properties?.continueOnError ?? false; if (!serverError || continueOnError) { clientActionPromises.push(callback(tableActionDetail, actionResult)); } } await Promise.all(clientActionPromises); } } async startTableAction(tableActionEvent) { this.notifyFormActivity(); const { tableCode, actionCode, actionDetail } = tableActionEvent; const tableObject = this.getTable(tableCode); if (!tableObject || !actionCode) { return; } this.resetError(); const { recordId, recordData } = actionDetail; const action = tableObject.getAction(actionCode); if (!action) { return; } const tableActionDetail = { tableObject, action, tableCode, actionCode, recordId, recordData }; const tableEventHandlers = this._tableActionsStart[tableCode]; const tableActionMethods = (tableEventHandlers) ? tableEventHandlers[actionCode] : null; if (tableActionMethods) { const clientActionPromises = []; for (const tableActionMethod of tableActionMethods) { const { callback, properties } = tableActionMethod; const clientActionPromise = callback(tableActionDetail); clientActionPromises.push(clientActionPromise); } const clientActionResults = await Promise.all(clientActionPromises); const continueAction = clientActionResults.reduce((total, curr) => (total && (curr !== false)), true); if (!continueAction) { return; } } this.startTableServerAction(tableActionDetail); } async startTableServerAction(tableActionDetail) { const { tableObject, action, tableCode, actionCode, recordId, recordData } = tableActionDetail; if (!tableObject || !action) { return; } tableObject.putOnWait(); let serverError = false; let actionResult = null; if (action.backend) { const actionSubject = { tableCode, actionType: this.formConfig?.tableActions.inline, actionCode, tableRecordId: recordId, tableRecordData: recordData }; actionResult = await this .requestFormAction(formActions.tableAction, actionSubject); serverError = !!this.errorOccured(); } await this.finishTableAction(tableActionDetail, actionResult, serverError); if (!serverError) { action.newState && this.changeState(action.newState); } else { this.displayTableServerError(); } tableObject.freeWaiting(); } completeInlineAction(tableAction) { return this.startTableServerAction(tableAction); } async finishTableAction(tableActionDetail, actionResult, serverError = false) { const { tableCode, actionCode } = tableActionDetail; const tableEventHandlers = this._tableActionsFinish[tableCode]; const tableActionMethods = (tableEventHandlers) ? tableEventHandlers[actionCode] : null; if (tableActionMethods) { const clientActionPromises = []; for (const tableActionMethod of tableActionMethods) { const { callback, properties } = tableActionMethod; const continueOnError = properties?.continueOnError ?? false; if (!serverError || continueOnError) { clientActionPromises.push(callback(tableActionDetail, actionResult)); } } await Promise.all(clientActionPromises); } } async startTableRecordSelection(tableActionEvent) { this.notifyFormActivity(); const { tableCode, actionDetail } = tableActionEvent; const tableObject = this.getTable(tableCode); if (!tableObject) { return; } this.resetError(); const { recordId, recordData } = actionDetail; const tableSelectionDetail = { tableObject, tableCode, recordId, recordData }; const tableEventHandlers = this._tableSelectionsStart[tableCode]; if (tableEventHandlers) { const clientActionPromises = []; for (const tableSelectionMethod of tableEventHandlers) { const { callback, properties } = tableSelectionMethod; const clientActionPromise = callback(tableSelectionDetail); clientActionPromises.push(clientActionPromise); } const clientActionResults = await Promise.all(clientActionPromises); const continueAction = clientActionResults.reduce((total, curr) => (total && (curr !== false)), true); if (!continueAction) { return; } } this.startTableServerRecordSelection(tableSelectionDetail); } async startTableServerRecordSelection(tableSelectionDetail) { const { tableObject, tableCode, recordId, recordData } = tableSelectionDetail; if (!tableObject) { return; } tableObject.putOnWait(); let serverError = false; let actionResult = null; if (tableObject.selectionBackend) { const actionSubject = { tableCode, actionType: this.formConfig?.tableActions.rowSelection, actionCode: null, tableRecordId: recordId, tableRecordData: recordData }; actionResult = await this .requestFormAction(formActions.tableAction, actionSubject); serverError = !!this.errorOccured(); } await this.finishTableRecordSelection(tableSelectionDetail, actionResult, serverError); if (serverError) { this.displayTableServerError(); } tableObject.freeWaiting(); } async finishTableRecordSelection(tableSelectionDetail, actionResult, serverError = false) { const { tableCode } = tableSelectionDetail; const tableEventHandlers = this._tableSelectionsFinish[tableCode]; if (tableEventHandlers) { const clientActionPromises = []; for (const tableSelectionMethod of tableEventHandlers) { const { callback, properties } = tableSelectionMethod; const continueOnError = properties?.continueOnError ?? false; if (!serverError || continueOnError) { clientActionPromises.push(callback(tableSelectionDetail, actionResult)); } } await Promise.all(clientActionPromises); } } async startTableSelectionAction(tableActionEvent) { this.notifyFormActivity(); const { tableCode, actionCode, actionDetail } = tableActionEvent; const tableObject = this.getTable(tableCode); if (!tableObject || !actionCode) { return; } this.resetError(); const { selectedRecords } = actionDetail; const action = tableObject.getAction(actionCode); if (!action) { return; } const tableActionDetail = { tableObject, action, tableCode, actionCode, selectedRecords }; const tableEventHandlers = this._tableActionsStart[tableCode]; const tableActionMethods = (tableEventHandlers) ? tableEventHandlers[actionCode] : null; if (tableActionMethods) { const clientActionPromises = []; for (const tableActionMethod of tableActionMethods) { const { callback, properties } = tableActionMethod; const clientActionPromise = callback(tableActionDetail); clientActionPromises.push(clientActionPromise); } const clientActionResults = await Promise.all(clientActionPromises); const continueAction = clientActionResults.reduce((total, curr) => (total && (curr !== false)), true); if (!continueAction) { return; } } this.startTableServerSelectionAction(tableActionDetail); } async startTableServerSelectionAction(tableActionDetail) { const { tableObject, action, tableCode, actionCode, selectedRecords } = tableActionDetail; if (!tableObject || !action) { return; } tableObject.putOnWait(); let serverError = false; let actionResult = null; if (action.backend) { const actionSubject = { tableCode, actionType: this.formConfig?.tableActions.selection, actionCode, selectedRecords }; actionResult = await this .requestFormAction(formActions.tableAction, actionSubject); serverError = !!this.errorOccured(); } await this.finishTableSelectionAction(tableActionDetail, actionResult, serverError); if (!serverError) { action.newState && this.changeState(action.newState); } else { this.displayTableServerError(); } tableObject.freeWaiting(); } async finishTableSelectionAction(tableActionDetail, actionResult, serverError = false) { const { tableCode, actionCode } = tableActionDetail; const tableEventHandlers = this._tableActionsFinish[tableCode]; const tableActionMethods = (tableEventHandlers) ? tableEventHandlers[actionCode] : null; if (tableActionMethods) { const clientActionPromises = []; for (const tableActionMethod of tableActionMethods) { const { callback, properties } = tableActionMethod; const continueOnError = properties?.continueOnError ?? false; if (!serverError || continueOnError) { clientActionPromises.push(callback(tableActionDetail, actionResult)); } } await Promise.all(clientActionPromises); } } async startTableGetData(tableActionEvent) { this.notifyFormActivity(); const { tableCode } = tableActionEvent; const tableObject = this.getTable(tableCode); const tableActionDetail = { tableObject, tableCode }; this.resetError(); const tableEventHandlers = this._tableGetDataStart[tableCode]; if (tableEventHandlers) { const clientActionPromises = []; for (const tableActionMethod of tableEventHandlers) { const { callback, properties } = tableActionMethod; const clientActionPromise = callback(tableActionDetail); clientActionPromises.push(clientActionPromise); } const clientActionResults = await Promise.all(clientActionPromises); const continueAction = clientActionResults.reduce((total, curr) => (total && (curr !== false)), true); if (!continueAction) { return; } } this.startTableServerGetData(tableActionDetail); } async startTableServerGetData(tableActionDetail) { const { tableObject, tableCode } = tableActionDetail; tableObject.putOnWait(); let serverError = false; const actionSubject = { tableCode }; const actionResult = await this .requestFormAction(formActions.getTableData, actionSubject); serverError = !!this.errorOccured(); await this.finishTableGetData(tableActionDetail, actionResult, serverError); if (serverError) { this.displayTableServerError(); } tableObject.freeWaiting(); } async finishTableGetData(tableActionDetail, actionResult, serverError = false) { const { tableCode, tableActionCode } = tableActionDetail; const tableEventHandlers = this._tableActionsFinish[tableCode]; const tableActionMethods = (tableEventHandlers) ? tableEventHandlers[tableActionCode] : null; if (tableActionMethods) { const clientActionPromises = []; for (const tableActionMethod of tableActionMethods) { const { callback, properties } = tableActionMethod; const continueOnError = properties?.continueOnError ?? false; if (!serverError || continueOnError) { clientActionPromises.push(callback(tableActionDetail, actionResult)); } } await Promise.all(clientActionPromises); } } checkSectionRequiredFields(sectionCode, reqFieldMessage) { this.cleanErrorFields(null, sectionCode); const requiredFieldMessage = reqFieldMessage ?? this.formConfig?.formStandardErrors.requiredField; const numErrors = this.tagFieldsWithError(requiredFieldMessage, this.getRequiredEmptyFields(null, sectionCode)); return (numErrors === 0); } validateSectionConsistency(sectionCode, reqFieldMessage) { this.resetError(); const completeFields = this.checkSectionRequiredFields(sectionCode, reqFieldMessage); if (!completeFiel