Skip to content

(feat) O3-4171 : Validate concept answers and show error for non-existing answers #445

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

Open
wants to merge 31 commits into
base: main
Choose a base branch
from

Conversation

Bharath-K-Shetty
Copy link
Contributor

Requirements

  • This PR has a title that briefly describes the work done including the ticket number. If there is a ticket, make sure your PR title includes a conventional commit label. See existing PR titles for inspiration.
  • My work conforms to the OpenMRS 3.0 Styleguide and design documentation.
  • My work includes tests or is validated by existing tests.

Summary

  • Checks each answer concept against the original concept's answer list
  • Performs a concept lookup only for non-original answers
  • Shows an inline notification when one or more answers are invalid.

Screenshots

Screen.Recording.2025-04-08.190713.mp4

Related Issue

https://openmrs.atlassian.net/browse/O3-4171

Other

@Bharath-K-Shetty
Copy link
Contributor Author

Bharath-K-Shetty commented Apr 8, 2025

Hey @NethmiRodrigo should i stick with this endpoint ${restBaseUrl}/concept?q=${conceptId}&v=full for additional concept answers validation or current end point is good?
Also, I'm planning to extend the validation to check for invalid concept answer names as well. I haven’t implemented that part yet since there are a few existing issues with editing concept answer names that I want to avoid interfering with for now.Thanks..!

setInvalidAnswerFound(!allValid);
};

validateAnswers();
Copy link
Collaborator

Choose a reason for hiding this comment

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

Since you are calling this function inside useEffect, the function should be defined outside the useEffect hook.

if (originalAnswerIds.has(answer.id)) {
continue;
} else {
const url = `${restBaseUrl}/concept/${answer.id}?v=full`;
Copy link
Collaborator

Choose a reason for hiding this comment

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

Please use the useConceptId hook.
For future reference, we don't usually do API calls within the component like this. We make hooks - https://o3-docs.openmrs.org/docs/coding-conventions/data-fetching.

Copy link
Contributor Author

@Bharath-K-Shetty Bharath-K-Shetty Apr 10, 2025

Choose a reason for hiding this comment

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

@NethmiRodrigo But we can't directly use the hook inside the loop right??Can you please elaborate how exactly i can do that..!

Comment on lines 198 to 206
{invalidAnswerFound && (
<InlineNotification
kind="error"
lowContrast
className={styles.error}
title={t('invalidAnswerConcept', 'Invalid Answer Concept Detected')}
subtitle={t('answerConceptValidation', 'One or more selected answer concepts do not exist in the system. ')}
/>
)}
Copy link
Collaborator

Choose a reason for hiding this comment

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

This is good, maybe we can show a not found icon within the blue tag of the answer that is invalid. Otherwise we'd have to guess which ones are invalid.

@Bharath-K-Shetty
Copy link
Contributor Author

Screenshot 2025-04-15 175423
Added Warning icon for invalid concept answers..!

@Bharath-K-Shetty
Copy link
Contributor Author

Screenshot 2025-04-17 180620

Updated one..!

Comment on lines +148 to +151
const expectedName = originalAnswersMap.get(answer.id);
if (answer.text !== expectedName) {
invalidIds.push(answer.id);
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

Hey @Bharath-K-Shetty, does this mean that if the label of the answer is not the same as the label of the original answer from the concept, it will be flagged as invalid?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Copy link
Collaborator

@NethmiRodrigo NethmiRodrigo Apr 21, 2025

Choose a reason for hiding this comment

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

Is there a reason behind that? If the concept UUID is correct, that is sufficient, no? Since we fetch concepts using the UUID only.

Copy link
Contributor Author

@Bharath-K-Shetty Bharath-K-Shetty Apr 21, 2025

Choose a reason for hiding this comment

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

Here, I added validation for labels as well, because in the schema, it's possible to edit a concept answer to a name that isn't present in the system (even if the UUID is valid), which technically isn't incorrect, right? Also, since label validation is already used for validating concepts, I thought it would be better to validate concept answers through labels too. Regarding the fetching part—it also returns the labels of the valid concepts, which we can use to identify and validate any invalid ones.

Copy link
Collaborator

Choose a reason for hiding this comment

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

How I was thinking about it is, if changing the label of a concept doesn't cause a failure when saving the form, then the form builder shouldn't flag an error saying concept not found.

Also, since label validation is already used for validating concepts

Mind pointing me to where we're doing that?

Regarding the fetching part—it also returns the labels of the valid concepts, which we can use to identify and validate any invalid ones.

Yes, but we aren't using the label to fetch concepts, so it feels wrong to invalidate saying concept not found, when it can be found.

Copy link
Contributor Author

@Bharath-K-Shetty Bharath-K-Shetty Apr 22, 2025

Choose a reason for hiding this comment

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

How I was thinking about it is, if changing the label of a concept doesn't cause a failure when saving the form, then the form builder shouldn't flag an error saying concept not found.

Then is it correct to add a concept answer that has invalid label but with a valid UUID..?

Yes, but we aren't using the label to fetch concepts, so it feels wrong to invalidate saying concept not found, when it can be found.

If it feels wrong.We can add a different notification saying that concept answer label is invalid.Is this be good enough or should removing it be better..?

Mind pointing me to where we're doing that?

Sorry i guess i misunderstood what conceptNameLookupError means..!

Copy link
Collaborator

Choose a reason for hiding this comment

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

Then is it correct to add a concept answer that has invalid label but with a valid UUID..?

Can you test this out and see? Change just the label of an answer in the form, and submit the form in the patient chart for a patient, and see if it causes an error? If it doesn't then we shouldn't show any error for it.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Sorry i guess i misunderstood what conceptNameLookupError means..!

If you are referring to

yeah that variable should be named differently to something like conceptIdLookupError because that hook, as defined here -
export function useConceptId(conceptId: string | undefined): UseConceptNameReturnType {
const url = `${restBaseUrl}/concept/${conceptId}?v=full`;
const { data, error } = useSWR<{ data: Concept }, Error>(conceptId ? url : null, openmrsFetch);
return {
concept: data?.data ?? null,
conceptName: data?.data?.display ?? null,
conceptNameLookupError: error,
isLoadingConcept: (conceptId && !data && !error) || false,
};
}
actually searches for the concept using the concept id and not the concept name.

Copy link
Contributor Author

@Bharath-K-Shetty Bharath-K-Shetty Apr 23, 2025

Choose a reason for hiding this comment

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

Can you test this out and see? Change just the label of an answer in the form, and submit the form in the patient chart for a patient, and see if it causes an error? If it doesn't then we shouldn't show any error for it.

but in the patient chart it is not showing error for both invalid id and label of concept answer..?(It is showing error if main selected concept answer has invalid id)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@NethmiRodrigo should i remove the validation done on labels..?

Copy link
Collaborator

@NethmiRodrigo NethmiRodrigo left a comment

Choose a reason for hiding this comment

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

Any progress on fixing the test?

@Bharath-K-Shetty
Copy link
Contributor Author

Bharath-K-Shetty commented Apr 18, 2025

Hey @NethmiRodrigo Dennis mentioned like without adding warning icon inside the Tag component he will have some better approach so that we don't need to change that robust test case..!

He also mentioned like adding a icon inside the Tag component is not a good approach because previously the Tag element had the single child which it was considering it as a title.But now it is changed and we don't have any attribute by which we can add a title to it and make the test case work..!

@Bharath-K-Shetty
Copy link
Contributor Author

Hey @NethmiRodrigo & @denniskigen i think i got the solution instead of explicitly adding the icon.In <Tag> we have a prop called decorator where we can add a warning icon..!

@denniskigen
Copy link
Member

denniskigen commented Apr 18, 2025

Isn't that experimental though? It looks like you can use the renderIcon prop to achieve the same goal.

@Bharath-K-Shetty
Copy link
Contributor Author

Hey @denniskigen Yeah i understand that it is experimental.But if i use renderIcon prop instead of decorator then the icon will be rendered first before the child..!

@NethmiRodrigo
Copy link
Collaborator

But if i use renderIcon prop instead of decorator then the icon will be rendered first before the child..!

@Bharath-K-Shetty that's actually fine

@Bharath-K-Shetty
Copy link
Contributor Author

Bharath-K-Shetty commented Apr 18, 2025

@NethmiRodrigo it is updated now..!

@gracepotma
Copy link
Contributor

Discussed on today's design call with myself, Bharath, and Veronica. We decided on this approach:
image

Sketches file:
https://docs.google.com/presentation/d/1h7O5OAyBrS8YEeE_KXntEqB8HVZ9XofNFolWEMXqIPk/edit?usp=sharing

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.

4 participants