Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat:use dhis2 expression parser #69

Merged
merged 15 commits into from
Nov 19, 2024
Merged

Conversation

9sneha-n
Copy link

@9sneha-n 9sneha-n commented Sep 25, 2024

📌 References

📝 Implementation

  1. Use dhis2 expression parser for parsing program rule conditions
  2. Recursively update all survey questions (form field) that need to be updated as a side effect of the current question update

📹 Screenshots/Screen capture

testing videos : https://drive.google.com/drive/folders/1BQkuP6o0fi0GxY-cqbTJzlCAj9Ivk7bu?usp=sharing

🔥 Notes to the tester

@9sneha-n 9sneha-n marked this pull request as ready for review November 10, 2024 10:06
Copy link

@tokland tokland left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some inline comments:

boolean: xp.ValueType.BOOLEAN,
date: xp.ValueType.DATE,
number: xp.ValueType.NUMBER,
};
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's move auxiliar/helper methods down, so the first we see when opening the file is the class and its public methods.


export class D2ExpressionParser {
public evaluateRuleEngineCondition(
ruleCondtion: string,
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo: ruleCondtion

);

const programVariables = expressionParser.collectProgramVariablesNames();
programVariables.forEach(programVariable => {
Copy link

@tokland tokland Nov 11, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[functional programming / immutability] let's refactor this block to avoid the forEach. We can for example build some from programVariables and concat to the previous ones to build the final variablesMap in one go.

"date",
new Date().toISOString().split("T")[0]
)
);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Multi-line expressions like this one are hard to read. Create local variables for intermediate values.

undefined,
undefined,
undefined
);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can remove the undefined args, is not adding too much value.

...question,
isVisible: updatedIsVisible,
errors: updatedErrors,
};
Copy link

@tokland tokland Nov 11, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[subjective] The return value is the same except for the value: undefined. This does not seem accidental repetition, to keep it DRY, move the condition inside.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have faced this issue before as well, typescript cannot resolve the type unless the condition is an if else. Is there any other way to resolve this?
Screenshot 2024-11-14 at 3 42 24 PM

Copy link

@tokland tokland Nov 14, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have faced this issue before as well, typescript cannot resolve the type unless the condition is an if else. Is there any other way to resolve this?

I see, things like this happen for union types, not TS's fault, it's normal. Try this approach:

...(question.isVisible !== updatedIsVisible ? { value: undefined } : {})

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wow, nice one! It works 👍

@@ -152,100 +152,102 @@ export class QuestionnaireQuestion {
}

static updateQuestions(
Copy link

@tokland tokland Nov 11, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only if we have time (probably not...). This is the kind of logic that really benefits from having some tests, as it's not trivial at all and extremely easy to introduce a bug. No need to cover all cases, just a subset that are used in the app and we know to be tricky.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Noted, will do this if i have time remaining after creation of ppt for meeting.

@@ -45,11 +42,12 @@ export interface QuestionnaireRuleAction {
}
export interface QuestionnaireRule {
id: Id;
condition: string; //condition is parsed with dataelementId e.g: #{dataElementId} == 'Yes'
condition: string;
dataElementIds: Id[]; // all dataElements in condition (there could be mutiple conditions)
teAttributeIds: Id[]; // all trackedEntityAttributes in condition (there could be mutiple conditions)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo: mutiple

@@ -45,11 +42,12 @@ export interface QuestionnaireRuleAction {
}
export interface QuestionnaireRule {
id: Id;
condition: string; //condition is parsed with dataelementId e.g: #{dataElementId} == 'Yes'
condition: string;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here we need some kind of documentation to know that kind of things we can do in a condition.

updatedSection.isVisible === false && section.isVisible === true
),
};
if (section.isVisible === false && updatedSection.isVisible === true) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When working with boolean, it's more declarative just a / !a


export class D2ExpressionParser {
public evaluateRuleEngineCondition(
ruleCondtion: string,
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add some docs somewhere (probably the easiest is a link to DHIS2 documentation) so we know what kind of conditions we can do.

@9sneha-n
Copy link
Author

@tokland Ready for re-review.

Copy link

@tokland tokland left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code-wise, all good by me.

@MiquelAdell MiquelAdell merged commit b892c5a into development Nov 19, 2024
1 check passed
@MiquelAdell MiquelAdell deleted the feature/coding-dojo branch November 19, 2024 08:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants