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: [DHIS2-14334] edit enrollment date #3350

Merged
merged 44 commits into from
Sep 6, 2023
Merged

feat: [DHIS2-14334] edit enrollment date #3350

merged 44 commits into from
Sep 6, 2023

Conversation

superskip
Copy link
Contributor

@superskip superskip commented Jun 26, 2023

DHIS2-14334

Don't be scared by the large number of line changes, a lot of them comes from yarn.lock.

@cooper-joe Could you please have a look at the style-object in EnrollmentDate.component? I think the units of measurement might be wrong.

@superskip superskip requested a review from cooper-joe June 26, 2023 16:31
@superskip superskip requested a review from a team as a code owner June 26, 2023 16:31
Copy link
Member

@cooper-joe cooper-joe left a comment

Choose a reason for hiding this comment

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

LGTM

const onUpdateTeiAttributeValues = useCallback((updatedAttributeValues, teiDisplayName) => {
dispatch(updateEnrollmentAttributeValues(updatedAttributeValues
.map(({ attribute, value }) => ({ id: attribute, value })),
));
dispatch(updateTeiDisplayName(teiDisplayName));
}, [dispatch]);

const onUpdateEnrollmentDate = useCallback(enrollmentDate =>
dispatch(updateEnrollmentDate(enrollmentDate)), [dispatch]);
Copy link
Contributor

Choose a reason for hiding this comment

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

Hey @superskip,
IMHO the enrollment date in the top ScopeSelector should be updated without requiring a page refresh. The WidgetProfile currently handles it inonUpdateTeiAttributeValues and updateTeiDisplayName(teiDisplayName). Does it make sense to implement something similar for the enrollment date?

Screen.Recording.2023-06-28.at.10.15.11.mov

Thanks you!

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good observation! Will fix :)

@github-actions
Copy link

github-actions bot commented Jul 18, 2023

Copy link
Member

@JoakimSM JoakimSM left a comment

Choose a reason for hiding this comment

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

Thanks @superskip.

Some comments in the code, but in addition we should implement the same for "incident date" (you might have mentioned that you wanted a review first). The incident date should have the same information regarding auto-generated events.

dense
className={classes.calendar}
label={enrollmentDateLabel}
inputWidth="50%"
Copy link
Member

Choose a reason for hiding this comment

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

Can we do a maxWidth of 200 instead of this? Not sure what styles we can send to the CalendarInput component, but an option is to wrap the CalendarInput in a div and set maxWidth on this.

Copy link
Contributor Author

@superskip superskip Aug 7, 2023

Choose a reason for hiding this comment

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

There is no maxWidth prop, but there is already lower bound on how narrow the enrollment widget can get. If we use inputWidth="200px" then this lower bound will increase by a little. If we instead say inputWidth="180px" then the lower bound will increase even less (if at all) while at the same time we will get a width matching better with the width shown in the pictures in the jira ticket.

Copy link
Member

Choose a reason for hiding this comment

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

I think a maxWidth of 200 would be best. Let's go for a wrapping div with a maxWidth of 200.

onUpdateDate,
classes,
}: Props) => {
const [updateMutation] = useDataMutation(enrollmentUpdate);
Copy link
Member

@JoakimSM JoakimSM Jul 19, 2023

Choose a reason for hiding this comment

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

Let's implement a simple UI-rollback if the request fails. Simple as in; let's not consider that the user can do simultaneous requests for changing the enrollment date. The useDataMutation takes an onError callback that we can utilise.

const saveHandler = (selectedDate: string) => {
enrollment.enrolledAt = convertValueClientToServer(selectedDate, dataElementTypes.DATE);
updateMutation(enrollment);
onUpdateDate && onUpdateDate(enrollment.enrolledAt);
Copy link
Member

Choose a reason for hiding this comment

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

(Putting this comment here, even though it is not directly related to the code line)

At the moment we update enrolledAt by mutating the enrollment object, but we don't actually set the state (to trigger a re-render). The UI currently updates because of some side-effects in the useDataMutation hook. We should follow best practice here and update the enrollment by setting the state.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Which part of the UI are you thinking of here? The date in the enrollment widget is rendered when the states editMode and selectedDate (in enrollmentDate.compontent) changes. Anyway, I think perhaps the change you had in mind got implemented in the error handling commit 🙂

Copy link
Member

Choose a reason for hiding this comment

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

Not exactly what I was looking for.

We should use optimistic UI and update the enrollment date instantly when the user changes it. Meaning; Before we get confirmation from the api, the enrollment date in the Widget UI should update and we should invoke the external onUpdate callback. If the request fails, we should revert the value to the original one. Also, in your saveHandler (EnrollmentDate.container) it is fine to invoke updateMutation directly, don't need to use an useEffect.

I think it makes most sense to update the enrollment object from useEnrollment (EnrollmentDate.container) instead of using a local component state.

program={program}
refetchEnrollment={refetchEnrollment}
refetchTEI={refetchTEI}
ownerOrgUnit={{ id: ownerOrgUnit, displayName }}
loading={!(enrollment && program && displayName)}
onDelete={onDelete}
onAddNew={onAddNew}
onUpdateEnrollmentDate={onUpdateEnrollmentDate}
onUpdateIncidentDate={onUpdateIncidentDate}
error={error}
Copy link
Member

Choose a reason for hiding this comment

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

can we change this to initError? (hard to keep track of the errors now when we also have error callbacks when updating)

@@ -0,0 +1,151 @@
// @flow
Copy link
Member

Choose a reason for hiding this comment

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

NIT: Can we change the name of this file since we are using it for both enrollment date and incident date? A bit hard since it is the enrollment Widget (so EnrollmentDate makes some sense). EnrollmentWidgetDate maybe? (feel free to come up with something better)

@superskip
Copy link
Contributor Author

superskip commented Aug 31, 2023

Renamed EnrollmentDate -> Date.

@JoakimSM - I didn't like how the code turned out after doing the thing we discussed (exposing setEnrollment).
Instead I made it so that enrollment gets refetched once the update request succeeds. As a consequence, the enrolledAt and occurredAt values are not up to date while the request is being processed. Therefore, to display the new date value while the request gets processed I had to introduce a state variable (in Date.container.js).

Copy link
Member

@JoakimSM JoakimSM left a comment

Choose a reason for hiding this comment

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

Good job 👍

@superskip superskip added testing and removed testing labels Sep 5, 2023
@superskip superskip added testing and removed testing labels Sep 5, 2023
Copy link

@geethaalwan geethaalwan left a comment

Choose a reason for hiding this comment

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

Tested successfully on 2.41,2.40.2,2.38.5,2.39.3 versions

@superskip superskip merged commit 9dd1b6a into master Sep 6, 2023
@superskip superskip deleted the DHIS2-14334 branch September 6, 2023 08:59
dhis2-bot added a commit that referenced this pull request Sep 6, 2023
# [100.38.0](v100.37.0...v100.38.0) (2023-09-06)

### Features

* [DHIS2-14334] edit enrollment date ([#3350](#3350)) ([9dd1b6a](9dd1b6a))
@dhis2-bot
Copy link
Contributor

🎉 This PR is included in version 100.38.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

superskip pushed a commit that referenced this pull request Oct 27, 2023
# [100.38.0](v100.37.0...v100.38.0) (2023-09-06)

### Features

* [DHIS2-14334] edit enrollment date ([#3350](#3350)) ([9dd1b6a](9dd1b6a))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants