@ohri/openmrs-esm-ohri-form-render-app
Version:
A Forms Rendering microfrontend for OpenMRS HIV Reference Implementation (OHRI)
139 lines (122 loc) • 5.04 kB
text/typescript
import { openmrsFetch } from '@openmrs/esm-framework';
import { async } from 'rxjs';
export const handleFormValidation = async (schema, configObject) => {
const errors = [];
const warnings = [];
if (schema) {
const parsedForm = typeof schema == 'string' ? JSON.parse(schema) : schema;
const asyncTasks = [];
parsedForm.pages?.forEach((page) =>
page.sections?.forEach((section) =>
section.questions?.forEach((question) => {
asyncTasks.push(
handleQuestionValidation(question, errors, configObject, warnings),
handleAnswerValidation(question, errors, warnings),
);
question.type === 'obsGroup' &&
question.questions?.forEach((obsGrpQuestion) =>
asyncTasks.push(
handleQuestionValidation(obsGrpQuestion, errors, configObject, warnings),
handleAnswerValidation(question, errors, warnings),
),
);
}),
),
);
await Promise.all(asyncTasks);
return [errors, warnings];
}
};
const handleQuestionValidation = async (conceptObject, errorsArray, configObject, warningsArray) => {
const conceptRepresentation =
'custom:(uuid,display,datatype,answers,conceptMappings:(conceptReferenceTerm:(conceptSource:(name),code)))';
const searchRef = conceptObject.questionOptions.concept
? conceptObject.questionOptions.concept
: conceptObject.questionOptions.conceptMappings?.length
? conceptObject.questionOptions.conceptMappings
?.map((mapping) => {
return `${mapping.type}:${mapping.value}`;
})
.join(',')
: '';
if (searchRef) {
try {
const { data } = await openmrsFetch(`/ws/rest/v1/concept?references=${searchRef}&v=${conceptRepresentation}`);
if (data.results.length) {
const [resObject] = data.results;
resObject.datatype.name === 'Boolean' &&
conceptObject.questionOptions.answers.forEach((answer) => {
if (
answer.concept !== 'cf82933b-3f3f-45e7-a5ab-5d31aaee3da3' &&
answer.concept !== '488b58ff-64f5-4f8a-8979-fa79940b1594'
) {
errorsArray.push({
errorMessage: `❌ concept "${conceptObject.questionOptions.concept}" of type "boolean" has a non-boolean answer "${answer.label}"`,
field: conceptObject,
});
}
});
resObject.datatype.name === 'Coded' &&
conceptObject.questionOptions.answers.forEach((answer) => {
if (!resObject.answers.some((answerObject) => answerObject.uuid === answer.concept)) {
warningsArray.push({
warningMessage: `⚠️ answer: "${answer.label}" - "${answer.concept}" does not exist in the response answers but exists in the form`,
field: conceptObject,
});
}
});
dataTypeChecker(conceptObject, resObject, errorsArray, configObject);
} else {
errorsArray.push({
errorMessage: `❓ Concept "${conceptObject.questionOptions.concept}" not found`,
field: conceptObject,
});
}
} catch (error) {
console.error(error);
}
} else {
errorsArray.push({
errorMessage: `❓ No UUID`,
field: conceptObject,
});
}
};
const dataTypeChecker = (conceptObject, responseObject, array, dataTypeToRenderingMap) => {
dataTypeToRenderingMap.hasOwnProperty(responseObject.datatype.name) &&
!dataTypeToRenderingMap[responseObject.datatype.name].includes(conceptObject.questionOptions.rendering) &&
array.push({
errorMessage: `❓ ${conceptObject.questionOptions.concept}: datatype "${responseObject.datatype.name}" doesn't match control type "${conceptObject.questionOptions.rendering}"`,
field: conceptObject,
});
!dataTypeToRenderingMap.hasOwnProperty(responseObject.datatype.name) &&
array.push({
errorMessage: `❓ Untracked datatype "${responseObject.datatype.name}"`,
field: conceptObject,
});
};
const handleAnswerValidation = (questionObject, array, warningsArray) => {
const answerArray = questionObject.questionOptions.answers;
const conceptRepresentation =
'custom:(uuid,display,datatype,conceptMappings:(conceptReferenceTerm:(conceptSource:(name),code)))';
answerArray?.length &&
answerArray.forEach((answer) => {
const searchRef = answer.concept
? answer.concept
: answer.conceptMappings?.length
? answer.conceptMappings
.map((eachMapping) => {
return `${eachMapping.type}:${eachMapping.value}`;
})
.join(',')
: '';
openmrsFetch(`/ws/rest/v1/concept?references=${searchRef}&v=${conceptRepresentation}`).then((response) => {
if (!response.data.results.length) {
array.push({
errorMessage: `❌ concept "${answer.concept}" not found`,
field: answer,
});
}
});
});
};