tuain-form-manager
Version:
Component library to perform operations on Tuain Development Framework forms to interchange information on web or mobile applications based on the data interchange of abstract forms making trnasformation on the data upon actions required on both sides (fr
1,111 lines (976 loc) • 33.6 kB
JavaScript
const crypto = require('crypto');
const { importExchange, exportExchange } = require('./process-exchange');
const modErrs = require('./module-errors');
const DEFAULT_VERSION = 'TUAINEXCHANGE_1.0';
const START = 'start';
const START_OPERATION = 'startOperation';
const GETDATA = 'GETDATA';
const VALIDATE_FIELD = 'VALIDATE';
const TABLE_ACCION = 'TABLEACTION';
const TABLE_GET_DATA = 'GETTABLEDATA';
const EDITABLE = 'editable';
const FIELDVALUE = 'fieldValue';
const INFO = 'info';
const VISIBLE = 'visible';
const DISABLED = 'disabled';
const REQUIRED = 'required';
const INLINE = 'INLINE';
const ROWSELECTION = 'ROWSELECTION';
const DEFAULT_RECORDS_PAGE = 10;
const RESTRICTED_ATTRIBUTES = ['actions', 'fields', 'recordTables', 'cookiesToSet', 'immutableData', 'returnedFile'];
const FIELD_ASSIGN_ATTRIBUTES = [
'defaultEditable',
'defaultValue',
'alignment',
'required',
'errorCode',
'errorMessage',
'errorType',
'tooltip',
'info',
'format',
'intrinsicErrorMessage',
'outputOnly',
'captureType',
'title',
'type',
'maxLength',
'maxValue',
'minLength',
'minValue',
'validateOnServer',
'serverAction',
'visibleLabel',
'options',
'editable',
'visible',
'placeholder',
];
const TABLE_CONSTRAINTS = [
'visible',
'currentPage',
'requestedPage',
'recordsPerPage',
'sortingColumn',
'sortingDirection',
'totalRecordsNumber',
'recordsNumber',
'currentFilter',
'tableRecords',
];
const SESSION_ATTRIBUTES = {
sessionCode: 'sessionCode',
profileCode: 'profileCode',
};
class Form {
constructor(logger, errMgr, requestContext, formDefinition, requestData) {
this.logger = logger;
this.errMgr = errMgr;
this._errorObject = null;
this._formDefinition = formDefinition;
this._formActions = {};
this._fieldValidations = {};
this._tableActions = {};
this._tablePopulate = {};
this._requestData = {
formCode: '',
state: '',
formSubject: '',
actionCode: '',
actionSubject: '',
requestVersion: DEFAULT_VERSION,
formData: {
fields: {},
tables: {},
},
};
this._responseData = {
actions: [],
cookiesToSet: [],
fields: {},
recordTables: {},
immutableData: {},
extraInfo: {},
returnedFile: null,
};
if (requestContext) {
this._requestContext = requestContext;
this._enabledFunctions = requestContext.enabledFunctions;
this._session = requestContext.currentSession;
this._sessionDetail = this._session?.sessionDetail;
this._requestRef = requestContext.requestReference;
}
importExchange(requestData, this);
this.onAction(START, () => this.start());
this.onAction(START_OPERATION, () => this.startOperation());
this.onAction(GETDATA, () => this.getData());
this.onAction(VALIDATE_FIELD, () => this.executeFieldValidation());
this.onAction(TABLE_ACCION, () => this.executeTableAction());
this.onAction(TABLE_GET_DATA, () => this.executeTablePopulate());
}
startOperation() {}
getData() {}
async start() {
const customizeDef = await this.startOperation();
if (customizeDef) {
return customizeDef;
}
return this.getData();
}
setCookie(name, value) {
this._responseData.cookiesToSet.push({ [name]: value });
}
getSessionAttribute(name) {
return this._session?.[name] ?? null;
}
sessionDetailAttribute(name) {
return this._sessionDetail?.[name] ?? null;
}
addExtraInfo(name, value) {
this._responseData.extraInfo[name] = { value };
}
getExtraInfo(name) {
return this._responseData.extraInfo[name]?.value ?? null;
}
getAttribute(name) {
return this._responseData[name] ?? null;
}
setAttribute(name, value) {
if (!RESTRICTED_ATTRIBUTES.includes(name)) {
this._responseData[name] = value;
}
}
setFormRequestAttributes(formCode, state, formSubject, actionCode, actionSubject, requestVersion) {
Object.assign(this._requestData, { formCode, state, formSubject, actionCode, actionSubject, requestVersion });
this.state = state;
}
setImmutableElement(name, value, inputSignature = null) {
let signature = inputSignature;
if (!signature) {
const content = JSON.stringify({ name, value });
const signatureKey = this._requestContext.signatureKey ?? this._requestContext.deviceKey ?? '1234567890';
signature = crypto.createHmac('sha256', signatureKey).update(content).digest('hex');
}
this._responseData.immutableData[name] = JSON.parse(JSON.stringify({ value, signature }));
}
getImmutableElement(name) {
if (!this._responseData?.immutableData) {
return null;
}
const { value, signature } = this._responseData?.immutableData?.[name] ?? {};
const content = JSON.stringify({ name, value });
const signatureKey = this._requestContext.signatureKey ?? this._requestContext.deviceKey ?? '1234567890';
const checkSignature = crypto.createHmac('sha256', signatureKey).update(content).digest('hex');
let requiredData = value;
try {
requiredData = typeof value === 'object' ? JSON.parse(JSON.stringify(value)) : value;
} catch (e) {
requiredData = value;
}
return signature === checkSignature ? requiredData : null;
}
get requestVersion() {
return this._requestData.requestVersion;
}
get actionSubject() {
return this._responseData.actionSubject ?? this._requestData.actionSubject;
}
set actionSubject(actionSubject) {
this._responseData.actionSubject = actionSubject;
}
get formSubject() {
return this._responseData.formSubject ?? this._requestData.formSubject;
}
set formSubject(formSubject) {
this._responseData.formSubject = formSubject;
}
getSubject() {
return this.formSubject;
}
getformSubject() {
return this.formSubject;
}
get state() {
return this._responseData.state ?? this._requestData.state;
}
set state(newState) {
this._responseData.state = newState;
}
get currentState() {
return this.state;
}
set currentState(state) {
this.state = state;
}
get mode() {
return this.state;
}
set mode(state) {
this.state = state;
}
get currentMode() {
return this.state;
}
set currentMode(state) {
this.state = state;
}
get formCode() {
return this._formDefinition.form.formCode;
}
get requireSession() {
return this._formDefinition.form.requireSession ?? false;
}
get globalFunctions() {
return this._formDefinition?.bussinesFunctionsRequired ?? [];
}
get responseData() {
return this._responseData;
}
set returnedFile(fileContent) {
this._responseData.returnedFile = fileContent;
}
get requestRef() {
return this._requestRef;
}
get requestContext() {
return this._requestContext;
}
get sessionCode() {
return this.getSessionAttribute(SESSION_ATTRIBUTES.sessionCode);
}
get profileCode() {
return this.getSessionAttribute(SESSION_ATTRIBUTES.profileCode);
}
get sessionDetail() {
return this._sessionDetail;
}
set error(errorObject) {
this._errorObject = errorObject;
}
get error() {
return this._errorObject;
}
getExportData() {
return exportExchange(this);
}
supportState(state) {
return this._formDefinition.states.findIndex((st) => st.name === state) >= 0;
}
supportMode(state) {
return this.supportState(state);
}
getStates() {
return this._formDefinition.states.map((stateDef) => stateDef.name);
}
changeState(newState) {
if (!newState || !this.supportState(newState)) {
return false;
}
if (!this.state) {
this.state = newState;
} else {
const transitionToChange = this._formDefinition.transitions.find(
(trns) => trns.source === this.state && trns.destination === newState,
);
if (transitionToChange) {
this.state = newState;
}
}
return this.state === newState;
}
/**
* @deprecated Use changeState
*/
changeFormMode(newState) {
return this.changeState(newState);
}
getActionDefinition(code) {
return this._formDefinition?.actions?.find((act) => act.actionCode === code) ?? null;
}
getAction(code) {
return this._responseData?.actions?.find((act) => act.actionCode === code) ?? null;
}
showAction(code) {
this.setActionAttribute(code, VISIBLE, true);
}
hideAction(code) {
this.setActionAttribute(code, VISIBLE, false);
}
enableAction(code) {
this.setActionAttribute(code, DISABLED, false);
}
disableAction(code) {
this.setActionAttribute(code, DISABLED, true);
}
onAction(code, callback) {
this._formActions[code] = callback;
}
showActions(actionArray) {
const actionNames = Array.isArray(actionArray) ? actionArray : [actionArray];
actionNames.forEach((code) => this.showAction(code));
}
hideActions(actionArray) {
const actionNames = Array.isArray(actionArray) ? actionArray : [actionArray];
actionNames.forEach((code) => this.hideAction(code));
}
enableActions(actionArray) {
const actionNames = Array.isArray(actionArray) ? actionArray : [actionArray];
actionNames.forEach((code) => this.enableAction(code));
}
disableActions(actionArray) {
const actionNames = Array.isArray(actionArray) ? actionArray : [actionArray];
actionNames.forEach((code) => this.disableAction(code));
}
addInputField(fieldObj) {
const { fieldCode } = fieldObj;
this._requestData.formData.fields[fieldCode] = fieldObj;
}
addTableRequest(tableRequest) {
const { tableCode, visible, currentPage, requestedPage, currentFilter, recordsPerPage, sortingColumn, sortingDirection } =
tableRequest;
this._requestData.formData.tables[tableCode] = tableRequest;
const constraints = {
visible,
currentPage,
requestedPage,
recordsPerPage,
sortingColumn,
sortingDirection,
currentFilter,
};
this.setTableConstraints(tableCode, constraints);
}
touchField(code) {
const actuallyAdded = this._responseData.fields[code];
if (actuallyAdded) {
return actuallyAdded;
}
const inputField = this._requestData.formData.fields[code];
if (inputField) {
this._responseData.fields[code] = inputField;
}
return inputField;
}
setFieldAttributes(code, attrObj) {
const field = this.getField(code);
if (field) {
Object.entries(attrObj ?? {}).forEach(([attr, value]) => {
if (FIELD_ASSIGN_ATTRIBUTES.includes(attr)) {
field[attr] = value;
}
});
}
}
setFieldAttribute(fieldCode, attr, value) {
const fieldObject = this.getField(fieldCode);
if (fieldObject) {
fieldObject[attr] = value;
}
}
getField(code) {
return this.touchField(code);
}
setFieldValue(code, value) {
this.setFieldAttribute(code, FIELDVALUE, value);
}
setFieldInfo(code, info) {
this.setFieldAttribute(code, INFO, info);
}
showField(code) {
this.setFieldAttribute(code, VISIBLE, true);
}
hideField(code) {
this.setFieldAttribute(code, VISIBLE, false);
}
enableField(code) {
this.setFieldAttribute(code, EDITABLE, true);
}
disableField(code) {
this.setFieldAttribute(code, EDITABLE, false);
}
getFieldValue(code) {
return this.getField(code)?.fieldValue ?? null;
}
demandField(code) {
this.setFieldAttribute(code, REQUIRED, true);
}
giveUpField(code) {
this.setFieldAttribute(code, REQUIRED, false);
}
onFieldValidation(code, callback) {
this._fieldValidations[code] = callback;
}
onFieldsValidation(fields, callback) {
if (!Array.isArray(fields) || fields?.length === 0 || !callback) {
return;
}
fields?.forEach((code) => {
this.onFieldValidation(code, callback);
});
}
setFieldsValues(fieldValues) {
Object.keys(fieldValues).forEach((code) => {
this.setFieldValue(code, fieldValues[code]);
});
}
getFieldNames() {
const names = new Set();
Object.keys(this._requestData.formData.fields).forEach((name) => names.add(name));
Object.keys(this._responseData.fields).forEach((name) => names.add(name));
return [...names];
}
applyProcessToFieldSet(callback, fieldArray) {
if (!fieldArray || !Array.isArray(fieldArray) || fieldArray?.length === 0 || !callback) {
return;
}
for (let index = 0; index < fieldArray.length; index++) {
callback(fieldArray[index]);
}
}
cleanFields(fieldArray) {
// return this.applyProcessToFieldSet(code => this.setFieldValue(code, ''), fieldArray);
const codes = Array.isArray(fieldArray) ? fieldArray : [fieldArray];
codes.forEach((code) => this.setFieldValue(code, ''));
}
enableFields(fieldArray) {
const codes = Array.isArray(fieldArray) ? fieldArray : [fieldArray];
codes.forEach((code) => this.enableField(code));
}
disableFields(fieldArray) {
const codes = Array.isArray(fieldArray) ? fieldArray : [fieldArray];
codes.forEach((code) => this.disableField(code));
}
showFields(fieldArray) {
const codes = Array.isArray(fieldArray) ? fieldArray : [fieldArray];
codes.forEach((code) => this.showField(code));
}
hideFields(fieldArray) {
const codes = Array.isArray(fieldArray) ? fieldArray : [fieldArray];
codes.forEach((code) => this.hideField(code));
}
showTable(code) {
const responseTable = this.getResponseTable(code);
if (responseTable) {
responseTable.visible = true;
}
}
hideTable(code) {
const responseTable = this.getResponseTable(code);
if (responseTable) {
responseTable.visible = false;
}
}
showTables(tableArray) {
const codes = Array.isArray(tableArray) ? tableArray : [tableArray];
codes.forEach((code) => this.showTable(code));
}
hideTables(tableArray) {
const codes = Array.isArray(tableArray) ? tableArray : [tableArray];
codes.forEach((code) => this.hideTable(code));
}
getTableDefinition(code) {
return this._formDefinition?.tables.find((tbl) => tbl.tableCode === code) ?? null;
}
getTableConstraints(tableCode) {
return this._requestData.formData.tables[tableCode];
}
onTableRowSelection(code, callback) {
this.onTableAction(code, ROWSELECTION, callback);
}
onTablePopulate(code, callback) {
this._tablePopulate[code] = callback;
}
onTableAction(tableCode, actionCode, callback) {
if (!this._tableActions[tableCode]) {
this._tableActions[tableCode] = {};
}
this._tableActions[tableCode][actionCode] = callback;
}
/**
* Funciones de secciones por implementar
* getSections();
* getSection(sectionCode);
* activateSection(sectionCode);
* getSubSection(sectionCode, subsectionCode);
* numSections();
* getSectionsTitles();
* getSectionObject(elementId);
* showSection(sectionCode);
* hideSection(sectionCode);
* showSections(sectionArray);
* hideSections(sectionArray);
* showSubSection(sectionCode, subSectionCode);
* hideSubSection(sectionCode, subSectionCode);
* showSubSections(sectionCode, subSectionArray);
* hideSubSections(sectionCode, subSectionArray);
*/
setTableConstraints(tableCode, constraints) {
const responseTable = this.getResponseTable(tableCode);
if (!responseTable || !constraints) {
return;
}
Object.keys(constraints)?.forEach((constraint) => {
switch (constraint) {
case 'visible':
responseTable.visible = constraints[constraint];
break;
case 'currentPage':
responseTable.currentPage = constraints[constraint];
break;
case 'requestedPage':
responseTable.requestedPage = constraints[constraint];
break;
case 'recordsPerPage':
responseTable.recordsPerPage = constraints[constraint];
break;
case 'sortingColumn':
responseTable.sortingColumn = constraints[constraint];
break;
case 'sortingDirection':
responseTable.sortingDirection = constraints[constraint];
break;
case 'totalRecordsNumber':
responseTable.totalRecordsNumber = constraints[constraint];
break;
default:
break;
}
});
}
async actionAllowed(actionCode) {
const generalFunctions = this.globalFunctions;
for (let index = 0; index < generalFunctions.length; index++) {
const functionRequired = generalFunctions[index];
const locatedFunction = this._enabledFunctions.find((fnc) => fnc.functionName === functionRequired.functionName);
if (!locatedFunction) {
return false;
}
}
const actionDefinition = this.getActionDefinition(actionCode);
const actionFunctions = actionDefinition?.bussinesFunctionsRequired?.split(',') ?? [];
for (let index = 0; index < actionFunctions?.length; index++) {
const functionRequired = actionFunctions[index];
const locatedFunction = this._enabledFunctions.find((fnc) => fnc.functionName === functionRequired);
if (!locatedFunction) {
return false;
}
}
return true;
}
setActionAttribute(actionCode, attributeId, value) {
const actionDefinition = this.getActionDefinition(actionCode);
if (!actionDefinition) {
return null;
}
const actionObject = this.getAction(actionCode);
if (!actionObject) {
this._responseData.actions.push({ actionCode: actionDefinition.actionCode, [attributeId]: value });
} else {
actionObject[attributeId] = value;
}
}
getFieldsValues(fieldCodeArray) {
const fieldValues = {};
fieldCodeArray.forEach((fieldCode) => {
fieldValues[fieldCode] = this.getFieldValue(fieldCode);
});
return fieldValues;
}
fillFieldValues(dataObject, mapTable = null) {
const attributes = Object.keys(dataObject);
for (let index = 0; index < attributes.length; index++) {
const dataFieldName = attributes[index];
const objectFieldValue = dataObject[dataFieldName];
const formFieldCode = mapTable ? mapTable[dataFieldName] : dataFieldName;
this.setFieldValue(formFieldCode, objectFieldValue);
}
}
setFieldOptions(code, options, idField, valueField, saparator = '-') {
const fieldObject = this.getField(code);
if (!fieldObject) {
return;
}
fieldObject.fieldOptions = [];
const numSeparators = Array.isArray(valueField) ? valueField.length - 1 : 0;
for (let i = 0; i < options?.length; i++) {
const optionObj = options[i];
const fieldOptionId = optionObj?.[idField];
let fieldOptionValue = '';
if (Array.isArray(valueField)) {
for (let index = 0; index < valueField.length; index++) {
const textPart = valueField[index];
fieldOptionValue += index < numSeparators ? `${optionObj?.[textPart]} ${saparator} ` : optionObj?.[textPart];
}
} else {
fieldOptionValue = optionObj?.[valueField];
}
if (fieldOptionId !== undefined && fieldOptionId !== null && fieldOptionValue !== undefined && fieldOptionValue !== null) {
fieldObject.fieldOptions.push({ fieldOptionId, fieldOptionValue });
}
}
}
async executeFieldValidation() {
let message;
const fieldCode = this.actionSubject;
const fieldValue = this.getFieldValue(fieldCode);
const callback = this._fieldValidations[fieldCode];
if (!callback) {
message = `No existe función de validación de ${fieldCode}`;
this.logger.log({ level: 'debug', label: 'fieldValidation', action: fieldCode, message });
return this.errMgr.get(modErrs.fieldValidation.NoValidationCallback);
}
let errorObj = null;
try {
errorObj = await callback(fieldCode, fieldValue);
} catch (err) {
message = `Excepción en validación de ${fieldCode}: ${err.message} / ${err.stack}`;
this.logger.log({ level: 'error', label: 'fieldValidation', action: fieldCode, message });
errorObj = this.errMgr.get(modErrs.fieldValidation.exceptionNotHandled, message);
}
return errorObj;
}
async executeFormAction(actionCode) {
let errorObj = null;
let message;
const callback = this._formActions[actionCode];
if (!callback) {
message = `No existe función de atención de ${actionCode} para ${this.formCode}`;
this.logger.log({ level: 'debug', label: 'executeFormAction', message });
errorObj = this.errMgr.get(modErrs.formActionExec.actionNotDefined, message);
return [errorObj, this.getExportData()];
}
if (!this.actionAllowed(actionCode)) {
message = `Usuario sin privilegios para la acción ${actionCode} en ${this.formCode}`;
this.logger.log({ level: 'debug', label: 'executeFormAction', message });
errorObj = this.errMgr.get(modErrs.formActionExec.actionNotDefined, message);
return [errorObj, this.getExportData()];
}
message = `START FORM ACTION ${actionCode} / ${this.formCode}/${this.formSubject ?? ''}`;
this.logger.log({ level: 'debug', label: 'executeFormAction', message });
try {
errorObj = await callback(actionCode);
} catch (err) {
message = `Excepción en acción de ${actionCode}: ${err.message} / ${err.stack}`;
this.logger.log({ level: 'error', label: 'executeFormAction', action: actionCode, message });
errorObj = this.errMgr.get(modErrs.formActionExec.exceptionNotHandled, message);
}
return [errorObj, this.getExportData()];
}
getResponseTable(tableCode) {
let message;
let responseTable = this._responseData.recordTables[tableCode];
if (!responseTable) {
const tableDefinition = this.getTableDefinition(tableCode);
if (!tableDefinition) {
message = `La tabla a ${tableCode} no está en la definición del formulario`;
this.logger.log({ level: 'error', message });
return null;
}
const {
visible = true,
currentPage = 1,
requestedPage = 1,
totalRecordsNumber = 0,
recordsNumber = 0,
recordsPerPage = 10,
sortingColumn = null,
sortingDirection = null,
} = tableDefinition?.constraints ?? {};
responseTable = {
tableCode,
visible,
currentPage,
requestedPage,
totalRecordsNumber,
recordsNumber,
recordsPerPage,
sortingColumn,
sortingDirection,
};
this._responseData.recordTables[tableCode] = responseTable;
}
return responseTable;
}
getResponseTableAction(tableCode, actionCode) {
const responseTable = this.getResponseTable(tableCode);
if (!responseTable) {
return null;
}
if (!responseTable?.actions) {
responseTable.actions = { [actionCode]: {} };
}
return responseTable.actions[actionCode];
}
getResponseTableField(tableCode, fieldCode) {
const responseTable = this.getResponseTable(tableCode);
if (!responseTable) {
return null;
}
if (!responseTable?.fields) {
responseTable.fields = { [fieldCode]: {} };
}
return responseTable.fields[fieldCode];
}
fillTable(records, mapping) {
const { tableCode, recordIdField, recordColumnsNames, recordItemAttributes } = mapping;
const responseTable = this.getResponseTable(tableCode);
if (!responseTable) {
return;
}
const tableRecords = [];
for (let recordIndex = 0; recordIndex < records?.length; recordIndex++) {
const recordToAdd = records[recordIndex];
const tableRecord = {
tableRecordId: recordToAdd[recordIdField] ?? 0,
recordData: [],
};
for (let colIndex = 0; colIndex < recordColumnsNames?.length; colIndex++) {
const fieldCode = recordColumnsNames[colIndex];
const attrName = recordItemAttributes[colIndex];
const fieldValue = recordToAdd[attrName] ?? '';
tableRecord.recordData.push({ fieldCode, fieldValue });
}
tableRecords.push(tableRecord);
}
Object.assign(responseTable, { tableRecords });
}
showTableField(tableCode, fieldCode) {
const tableField = this.getResponseTableField(tableCode, fieldCode);
if (tableField) {
Object.assign(tableField, { visible: true });
}
}
hideTableField(tableCode, fieldCode) {
const tableField = this.getResponseTableField(tableCode, fieldCode);
if (tableField) {
Object.assign(tableField, { visible: false });
}
}
enableTableAction(tableCode, actionCode) {
const tableAction = this.getResponseTableAction(tableCode, actionCode);
if (tableAction) {
Object.assign(tableAction, { enabled: true });
}
}
disableTableAction(tableCode, actionCode) {
const tableAction = this.getResponseTableAction(tableCode, actionCode);
if (tableAction) {
Object.assign(tableAction, { enabled: false });
}
}
showTableAction(tableCode, actionCode) {
const tableAction = this.getResponseTableAction(tableCode, actionCode);
if (tableAction) {
Object.assign(tableAction, { visible: true });
}
}
hideTableAction(tableCode, actionCode) {
const tableAction = this.getResponseTableAction(tableCode, actionCode);
if (tableAction) {
Object.assign(tableAction, { visible: false });
}
}
showOnStateTableAction(tableCode, actionCode, state) {
const tableAction = this.getResponseTableAction(tableCode, actionCode);
if (tableAction) {
if (!tableAction.showOnStates) {
tableAction.showOnStates = [];
}
const currentlyVisible = tableAction.showOnStates.findIndex((item) => item === state);
const correntlyHidden = tableAction.hideOnStates?.findIndex((item) => item === state);
if (currentlyVisible < 0) {
tableAction.showOnStates.push(state);
}
if (correntlyHidden >= 0) {
tableAction.hideOnStates.splice(correntlyHidden, 1);
if (tableAction.hideOnStates.length === 0) {
delete tableAction.hideOnStates;
}
}
}
}
hideOnStateTableAction(tableCode, actionCode, state) {
const tableAction = this.getResponseTableAction(tableCode, actionCode);
if (tableAction) {
if (!tableAction.hideOnStates) {
tableAction.hideOnStates = [];
}
const currentlyVisible = tableAction.showOnStates.findIndex((item) => item === state);
const correntlyHidden = tableAction.hideOnStates?.findIndex((item) => item === state);
if (correntlyHidden < 0) {
tableAction.hideOnStates.push(state);
}
if (currentlyVisible >= 0) {
tableAction.showOnStates.splice(currentlyVisible, 1);
if (tableAction.showOnStates.length === 0) {
delete tableAction.showOnStates;
}
}
}
}
enableOnStateTableAction(tableCode, actionCode, state) {
const tableAction = this.getResponseTableAction(tableCode, actionCode);
if (tableAction) {
if (!tableAction.enableOnStates) {
tableAction.enableOnStates = [];
}
const currentlyEnabled = tableAction.enableOnStates.findIndex((item) => item === state);
const correntlyDisabled = tableAction.disableOnStates?.findIndex((item) => item === state);
if (currentlyEnabled < 0) {
tableAction.enableOnStates.push(state);
}
if (correntlyDisabled >= 0) {
tableAction.disableOnStates.splice(correntlyDisabled, 1);
if (tableAction.disableOnStates.length === 0) {
delete tableAction.disableOnStates;
}
}
}
}
disableOnStateTableAction(tableCode, actionCode, state) {
const tableAction = this.getResponseTableAction(tableCode, actionCode);
if (tableAction) {
if (!tableAction.disableOnStates) {
tableAction.disableOnStates = [];
}
const currentlyEnabled = tableAction.enableOnStates.findIndex((item) => item === state);
const correntlyDisabled = tableAction.disableOnStates?.findIndex((item) => item === state);
if (correntlyDisabled < 0) {
tableAction.disableOnStates.push(state);
}
if (currentlyEnabled >= 0) {
tableAction.enableOnStates.splice(currentlyEnabled, 1);
if (tableAction.enableOnStates.length === 0) {
delete tableAction.enableOnStates;
}
}
}
}
async executeTableAction() {
let message = '';
if (!this.actionSubject || typeof this.actionSubject !== 'object') {
message = 'Acción de tabla requiere actionSubject';
this.logger.log({ level: 'error', label: 'executeTableAction', message });
return this.errMgr.get(modErrs.tableActionExec.subjectIncomplete, message);
}
const { tableCode, actionType = INLINE, tableRecordId, tableRecordData } = this.actionSubject;
if (!tableCode) {
message = 'Acción de tabla requiere tableCode';
this.logger.log({ level: 'error', label: 'executeTableAction', message });
return this.errMgr.get(modErrs.tableActionExec.subjectIncomplete, message);
}
let { actionCode } = this.actionSubject;
if (actionType === INLINE) {
if (!actionCode) {
message = 'Acción inline requiere actionCode';
return this.errMgr.get(modErrs.tableActionExec.subjectIncomplete, message);
}
if (!tableRecordId) {
message = 'Acción inline requiere identificador del registro tableRecordId';
return this.errMgr.get(modErrs.tableActionExec.noRecordId, message);
}
} else if (actionType === ROWSELECTION) {
actionCode = ROWSELECTION;
if (!tableRecordId) {
message = 'Acción sobre tabla requiere identificador del registro tableRecordId';
return this.errMgr.get(modErrs.tableActionExec.noRecordId, message);
}
} else {
// Cualquier otro tipo de acción sobre tabla no involucra tableRecordId!!!
actionCode = actionType;
}
let errorObject = null;
try {
const tableActionCallback = this._tableActions?.[tableCode]?.[actionCode] ?? null;
if (!tableActionCallback) {
this.logger.log({
level: 'error',
label: 'executeTableAction',
message: `No existe función callback para la acción ${actionCode} sobre la tabla ${tableCode} en ${this.formCode}`,
});
return this.errMgr.get(modErrs.tableActionExec.noCallback);
}
this.logger.log({
level: 'debug',
label: 'tableAction',
action: actionCode,
message: `Se inicia ejecución de la acción ${actionCode} sobre la tabla ${tableCode} en ${this.formCode}`,
});
errorObject = await tableActionCallback(tableCode, actionCode, tableRecordId, tableRecordData ?? {});
} catch (err) {
message = `Excepción no soportada en acción ${actionCode} sobre la tabla ${tableCode} : ${err.message} / ${err.stack}`;
this.logger.log({ level: 'error', label: 'tableAction', action: actionCode, message });
errorObject = this.errMgr.get(modErrs.tableActionExec.noCallback, message);
}
return errorObject;
}
async executeTablePopulate() {
let message = '';
if (!this.actionSubject || typeof this.actionSubject !== 'object') {
message = 'Acción de poblamiento de tabla requiere actionSubject';
this.logger.log({ level: 'error', label: 'executeTablePopulate', message });
return this.errMgr.get(modErrs.tableActionExec.subjectIncomplete, message);
}
const { tableCode } = this.actionSubject;
if (!tableCode) {
message = 'Acción de poblamiento de tabla requiere tableCode';
this.logger.log({ level: 'error', label: 'executeTablePopulate', message });
return this.errMgr.get(modErrs.tableActionExec.subjectIncomplete, message);
}
let errorObject = null;
try {
const tablePopulateCallback = this._tablePopulate?.[tableCode] ?? null;
if (!tablePopulateCallback) {
this.logger.log({
level: 'error',
label: 'executeTablePopulate',
message: `No existe función callback para el poblamiento de la tabla ${tableCode} en ${this.formCode}`,
});
return this.errMgr.get(modErrs.tableActionExec.noCallback);
}
errorObject = await tablePopulateCallback(tableCode, this.actionSubject);
} catch (err) {
message = `Excepción no soportada en el poblamiento de la tabla ${tableCode} en ${this.formCode}: ${err} / ${err.stack}`;
this.logger.log({ level: 'error', label: 'executeTablePopulate', action: tableCode, message });
errorObject = this.errMgr.get(modErrs.tablePopulate.exceptionNotHandled, message);
}
return errorObject;
}
/**
* @deprecated Use onAction
*/
addActionMethod(code, callback) {
return this.onAction(code, callback);
}
/**
* @deprecated Use onFieldValidation
*/
addFieldValidation(code, callback) {
return this.onFieldValidation(code, callback);
}
/**
* @deprecated Use onFieldsValidation
*/
addFieldsValidation(fields, callback) {
return this.onFieldsValidation(fields, callback);
}
/**
* @deprecated Use onTableRowSelection
*/
addTableRowSelection(code, callback) {
return this.onTableRowSelection(code, callback);
}
/**
* @deprecated Use onTablePopulate
*/
addTablePopulate(code, callback) {
return this.onTablePopulate(code, callback);
}
/**
* @deprecated Use onTableAction
*/
addTableAction(tableCode, actionCode, callback) {
return this.onTableAction(tableCode, actionCode, callback);
}
}
module.exports = Form;