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

fix: handle compulsory data element operands [DHIS2-17647] #426

Merged
merged 3 commits into from
Dec 10, 2024

Conversation

tomzemp
Copy link
Member

@tomzemp tomzemp commented Nov 29, 2024

This PR addresses the referenced ticket (DHIS2-17647) and in general

(Note when I was testing this, I just made a couple of new data elements and assigned them to a new data set and then marked some as compulsory data element operands)

Before:

  • no handling of compulsory data element operands

After:

  • compulsory data element operands are marked with an * when they are empty. They then will get other applicable styling as values are entered (e.g. synced, error, warning)
image
  • if the data set has compulsoryFieldsCompleteOnly: true ("Complete allowed only if compulsory fields are filled in" in the maintenance app), a snack bar message will appear saying that the form cannot be completed due to compulsory data element operands and the styling on the cells will be set to red/invalid/not saved (this styling will update as values are entered)
image

Testing

  • I've added automated tests on the complete-button to test that the checks preventing the completion based on the values/compulsoryDataElementOperands is working (i.e. this an integration level test which tests useHasCompulsoryDataElementOperandsToFillOut hook and logic preventing completion in useOnCompleteCallback)
  • I have not added any automated tests for the styling (and hence implicit test of useIsCompulsoryDataElementOperand hook) partly because we didn't have existing tests and more because the InnerWrapper component where this can be tested is being refactored due to the performance PR (fix: remove FinalForm dependency in main form [DHIS2-18373] #425) so the mocking would have to be redone if I added some now. I find these tests less crucial in any case because the styling doesn't block user from entering data.

I've also done some manual testing (see note above).

@dhis2-bot
Copy link
Contributor

dhis2-bot commented Nov 29, 2024

🚀 Deployed on https://pr-426--dhis2-data-entry.netlify.app

@dhis2-bot dhis2-bot temporarily deployed to netlify November 29, 2024 16:25 Inactive
@@ -453,6 +464,7 @@ const metadata = {

describe('<CategoryComboTableBody />', () => {
useMetadata.mockReturnValue({ data: metadata })
useDataSetId.mockReturnValue(['dataSet1'])
Copy link
Member Author

Choose a reason for hiding this comment

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

(FYI: edit was necessary because of thenew call to the useIsCompulsoryDataElementOperand hook


return () => {
let promise

if (isLoading && offline) {
if (hasCompulsoryDataElementOperandsToFillOut) {
setCompleteAttempted(true)
Copy link
Member Author

Choose a reason for hiding this comment

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

this is only set if there is a compulsory data element operand to fill out, so that invalid styling only gets applied if the compulsory data element operands need to be filled out (otherwise, they remain with just the *)

@@ -4,6 +4,7 @@ import create from 'zustand'
const inititalState = {
errors: {},
warnings: {},
completeAttempted: false,
Copy link
Member Author

Choose a reason for hiding this comment

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

I couldn't totally decide where to put this, but thought that since it was going to apply error styling to cells, I would put it in the store with the errors information.

import { useDataSetId } from './use-context-selection/use-context-selection.js'
import { useDataValueSet } from './use-data-value-set/use-data-value-set.js'

export const useIsCompulsoryDataElementOperand = ({
Copy link
Member Author

Choose a reason for hiding this comment

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

I colocated these hooks because I didn't really want to create a new folder in src/shared directory. I'd also vote for moving the miscellaneous hooks in src/shared into src/shared/hooks, and then I could create a folder and two separate hooks for these, but I didn't want to create two separate files with the the existing file structure.

@@ -12,7 +12,7 @@ import {
* @params {Object} options
* @params {Boolean} options.enabled - Defaults to `true`
**/
export default function useImperativeValidate() {
export const useImperativeValidate = () => {
Copy link
Member Author

Choose a reason for hiding this comment

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

this is not necessary FYI, but I was having some trouble with jest mocking when it was a default, so I changed to be a named export.

@tomzemp tomzemp marked this pull request as ready for review December 2, 2024 08:46
@tomzemp tomzemp requested a review from a team December 2, 2024 08:46
if (isLoading && offline) {
if (hasCompulsoryDataElementOperandsToFillOut) {
setCompleteAttempted(true)
cancelCompletionMutation()
Copy link
Contributor

Choose a reason for hiding this comment

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

I think that doing completeStatus: { ...previousDataValueSet.completeStatus, complete: !completed, }, in cancelCompletionMutation messes up the complete status a bit. In you try to mark as complete successfully, then mark as incomplete successfully and then finally mark as complete unsuccessfully you will see the complete status = true even if the completion did fail. maybe we just want to set it as completeStatus: { ...previousDataValueSet.completeStatus, complete: false, }, ?

Copy link
Member Author

Choose a reason for hiding this comment

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

Thanks! Fixed this. I did't pay enough attention to what the cancelCompletionMutation function was doing before. I guess as it's used for cancelling incomplete functions as well, I've modified the hook to return a function to which you can pass the desired complete status (i.e. false here).

This works as far as I can tell though I have not gone through in total detail to review all of the logic with the completion.

Copy link
Contributor

@flaminic flaminic left a comment

Choose a reason for hiding this comment

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

Look good thanks @tomzemp . Just one comment on a weird behaviour i found for the complete status

@dhis2-bot dhis2-bot temporarily deployed to netlify December 10, 2024 13:05 Inactive
@tomzemp tomzemp merged commit 1d6c667 into master Dec 10, 2024
8 checks passed
dhis2-bot added a commit that referenced this pull request Dec 10, 2024
## [100.11.4](v100.11.3...v100.11.4) (2024-12-10)

### Bug Fixes

* handle compulsory data element operands [DHIS2-17647] ([#426](#426)) ([1d6c667](1d6c667))
@dhis2-bot
Copy link
Contributor

🎉 This PR is included in version 100.11.4 🎉

The release is available on:

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants