Skip to content

Commit

Permalink
feat: reset questions which are hidden, reset question on hidden section
Browse files Browse the repository at this point in the history
  • Loading branch information
9sneha-n committed Nov 10, 2024
1 parent 8bbb990 commit 9159682
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 54 deletions.
5 changes: 1 addition & 4 deletions src/data/entities/D2ExpressionParser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,17 +28,13 @@ export class D2ExpressionParser {
xp.ExpressionMode.RULE_ENGINE_CONDITION
);

//Mapper function for program rule variables
const variables = expressionParser.collectProgramRuleVariableNames();

const variablesValueMap = this.mapProgramVariables(variables, ruleVariables);

const variablesMap = new Map(
variablesValueMap.map(variable => [variable.programRuleVariable, variable.value])
);

const programVariables = expressionParser.collectProgramVariablesNames();

programVariables.forEach(programVariable => {
switch (programVariable) {
case "current_date": {
Expand Down Expand Up @@ -70,6 +66,7 @@ export class D2ExpressionParser {
() => console.debug(""),
expressionData
);

return Either.success(parsedResult);
} catch (error) {
return Either.error(
Expand Down
64 changes: 25 additions & 39 deletions src/domain/entities/Questionnaire/QuestionnaireQuestion.ts
Original file line number Diff line number Diff line change
Expand Up @@ -156,8 +156,7 @@ export class QuestionnaireQuestion {
questions: Question[],
updatedQuestion: Question,
rules: QuestionnaireRule[],
questionnaire: Questionnaire,
_parentSectionHidden?: boolean
questionnaire: Questionnaire
): Question[] {
//1. Update the question value before anything else, the updated value needs to be used to parse rule conditions
const updatedQuestions = questions.map(question => {
Expand All @@ -169,50 +168,24 @@ export class QuestionnaireQuestion {
});

const parsedAndUpdatedQuestions = updatedQuestions.map(question => {
//If the question is part of any of the rule actions, update the section
const parsedAndUpdatedQuestion =
question.id === updatedQuestion.id
? this.updateQuestion(question, rules)
: question;

return parsedAndUpdatedQuestion;
});
processedQuestions.push(updatedQuestion);
//If any of the updated question has been changed to hidden, then reset its value
//When it is shown again, the user can enter a "fresh" value
const hiddenQuestions = parsedAndUpdatedQuestions.filter(
q =>
q.isVisible === true &&
updatedQuestions.find(uq => uq.id === q.id)?.isVisible === false
);

const sortedUpdatedQuestions = _(parsedAndUpdatedQuestions)
.sortBy(question => question.sortOrder)
.value();
processedQuestions.push(updatedQuestion);

const resetQuestions = hiddenQuestions.reduce((acc, hiddenQuestion) => {
return this.updateQuestions(
processedQuestions,
acc,
{ ...hiddenQuestion, value: undefined },
rules,
questionnaire
);
}, parsedAndUpdatedQuestions);

const sortedResetUpdatedQuestions = _(resetQuestions)
.sortBy(question => question.sortOrder)
.value();

const finalUpdatedQuestions =
hiddenQuestions.length === 0 ? sortedUpdatedQuestions : sortedResetUpdatedQuestions;

//3. Get all questions that need to be updated as a side effect of the current question update
const allQuestionIdsRequiringUpdate = _(
questionnaire.rules.flatMap(rule => {
if (
rule.dataElementIds.includes(updatedQuestion.id) ||
rule.teAttributeIds.includes(updatedQuestion.id)
//sneha : check that the rule is "applicable"also i.e. the condition is true
) {
const actionUpdates = rule.actions.flatMap(
action => action?.dataElement?.id || action.trackedEntityAttribute?.id
Expand All @@ -227,18 +200,21 @@ export class QuestionnaireQuestion {
.uniq()
.value();

const allQuestionsRequiringUpdate = finalUpdatedQuestions.filter(question =>
const allQuestionsRequiringUpdate = sortedUpdatedQuestions.filter(question =>
allQuestionIdsRequiringUpdate.includes(question.id)
);
if (allQuestionsRequiringUpdate.length === 0) return finalUpdatedQuestions;
if (allQuestionsRequiringUpdate.length === 0) return sortedUpdatedQuestions;

//4. Recursively update all questions that need to be updated as a side effect of the current question update
const finalUpdatesWithSideEffects = allQuestionsRequiringUpdate.reduce(
(acc, questionRequiringUpdate) => {
const currentApplicableRules = getApplicableRules(
questionRequiringUpdate,
questionnaire.rules,
acc
);
//5. Maintain a dependency graph to avoid infinite recursive calls,
// once a question has been processed, it should not be processed again
processedQuestions.push(questionRequiringUpdate);
const updates = this.updateQuestions(
processedQuestions,
Expand All @@ -247,23 +223,33 @@ export class QuestionnaireQuestion {
currentApplicableRules,
questionnaire
);
//6. If "side-effect" question is hidden, reset its value
// const updatedQuestion = updates.find(q => q.id === questionRequiringUpdate.id);

return updates;
},
finalUpdatedQuestions
sortedUpdatedQuestions
);

return finalUpdatesWithSideEffects;
}

private static updateQuestion(question: Question, rules: QuestionnaireRule[]): Question {
const updatedIsVisible = this.isQuestionVisible(question, rules);
const updatedErrors = this.getQuestionWarningsAndErrors(question, rules);

return {
...question,
isVisible: updatedIsVisible,
errors: updatedErrors,
};
if (question.isVisible !== updatedIsVisible) {
return {
...question,
isVisible: updatedIsVisible,
errors: updatedErrors,
value: undefined,
};
} else
return {
...question,
isVisible: updatedIsVisible,
errors: updatedErrors,
};
}

private static isQuestionVisible(question: Question, rules: QuestionnaireRule[]): boolean {
Expand Down
39 changes: 28 additions & 11 deletions src/domain/entities/Questionnaire/QuestionnaireSection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,17 +56,34 @@ export class QuestionnaireSectionM {
? this.updateSection(section, rules)
: section;

return {
...updatedSection,
questions: QuestionnaireQuestion.updateQuestions(
[],
updatedSection.questions,
updatedQuestion,
rules,
questionnaire,
updatedSection.isVisible === false && section.isVisible === true
),
};
if (section.isVisible === false && updatedSection.isVisible === true) {
//reset all questions in the section

const resetQuestions = section.questions.reduce((acc, hiddenQuestion) => {
return QuestionnaireQuestion.updateQuestions(
section.questions,
acc,
{ ...hiddenQuestion, value: undefined },
rules,
questionnaire
);
}, section.questions);

return {
...updatedSection,
questions: resetQuestions,
};
} else
return {
...updatedSection,
questions: QuestionnaireQuestion.updateQuestions(
[],
updatedSection.questions,
updatedQuestion,
rules,
questionnaire
),
};
});

return updatedSections;
Expand Down

0 comments on commit 9159682

Please sign in to comment.