O3-1409: Support for users changing passwords#43
O3-1409: Support for users changing passwords#43jnsereko wants to merge 9 commits intoopenmrs:mainfrom
Conversation
| if (passwordInput.confirmPassword !== '') { | ||
| handleValidation(passwordInput.confirmPassword, 'confirmPassword'); | ||
| } | ||
| }, [passwordInput]); |
There was a problem hiding this comment.
handleValidation is also a dependency here.
| const handlePasswordChange = (event) => { | ||
| const passwordInputValue = event.target.value.trim(); | ||
| const passwordInputFieldName = event.target.name; | ||
| const NewPasswordInput = { ...passwordInput, [passwordInputFieldName]: passwordInputValue }; | ||
| setPasswordInput(NewPasswordInput); | ||
| }; | ||
|
|
||
| const handleValidation = (passwordInputValue, passwordInputFieldName) => { |
There was a problem hiding this comment.
I would probably wrap both of these in useCallback()
| try { | ||
| setIsSavingPassword(true); | ||
| await performPasswordChange(passwordInput.oldPassword, passwordInput.confirmPassword).then(() => { | ||
| close(); | ||
| navigate({ to: `\${openmrsSpaBase}/logout` }); | ||
| showToast({ | ||
| title: t('userPassword', 'User password'), | ||
| description: t('userPasswordUpdated', 'User password updated successfully'), | ||
| kind: 'success', | ||
| }); | ||
| }); | ||
| } catch (error) { | ||
| setIsSavingPassword(false); | ||
| setErrorMessage(`${t('invalidPasswordCredentials', 'Invalid password provided')}: ${error.message}`); | ||
| } |
There was a problem hiding this comment.
This construction is weird...
performPasswordChange(passwordInput.oldPassword, passwordInput.confirmPassword).then(() => {
close();
navigate({ to: `\${openmrsSpaBase}/logout` });
showToast({
title: t('userPassword', 'User password'),
description: t('userPasswordUpdated', 'User password updated successfully'),
kind: 'success',
});
}).catch((err) => {
setIsSavingPassword(false);
setErrorMessage(`${t('invalidPasswordCredentials', 'Invalid password provided')}: ${error.message}`);
});Reads better to me. (Basically either use await and no then() or else just use it as a promise).
There was a problem hiding this comment.
The success message should be a snackbar, not a toast. Also, we should probably show a notification when it submits but fails at the backend.
| evt.preventDefault(); | ||
| evt.stopPropagation(); |
| setErrorMessage(`${t('invalidPasswordCredentials', 'Invalid password provided')}: ${error.message}`); | ||
| } | ||
|
|
||
| return false; |
There was a problem hiding this comment.
Also why are we returning false?
| onClick={handleSubmit} | ||
| disabled={isSavingPassword || isNewPasswordInvalid || isConfirmPasswordInvalid || isOldPasswordInvalid} | ||
| > | ||
| {t('apply', 'Apply')} |
There was a problem hiding this comment.
| {t('apply', 'Apply')} | |
| {t('updatePassword', 'Update Password')} |
| } | ||
|
|
||
| .errorMessage { | ||
| position: absolute; |
There was a problem hiding this comment.
Absolute positioning for an error message feels wrong.
| options, | ||
| ); | ||
|
|
||
| export const ChangePasswordModal = getAsyncLifecycle( |
There was a problem hiding this comment.
| export const ChangePasswordModal = getAsyncLifecycle( | |
| export const changePasswordModal = getAsyncLifecycle( |
| }, | ||
| { | ||
| "name": "change-password-modal", | ||
| "component": "ChangePasswordModal", |
There was a problem hiding this comment.
| "component": "ChangePasswordModal", | |
| "component": "changePasswordModal", |
| <Tile> | ||
| <form onSubmit={handleSubmit} ref={formRef}> | ||
| <div className={styles['input-group']}> | ||
| <PasswordInput |
There was a problem hiding this comment.
I think it's likely we need a Carbon Layer component in here.
packages/esm-system-admin-app/src/change-password-modal/change-password-modal.component.tsx
Outdated
Show resolved
Hide resolved
packages/esm-system-admin-app/src/change-password-modal/change-password-modal.component.tsx
Outdated
Show resolved
Hide resolved
packages/esm-system-admin-app/src/change-password-modal/change-password-modal.component.tsx
Outdated
Show resolved
Hide resolved
packages/esm-system-admin-app/src/change-password-modal/change-password-modal.component.tsx
Outdated
Show resolved
Hide resolved
packages/esm-system-admin-app/src/change-password-modal/change-password-modal.component.tsx
Outdated
Show resolved
Hide resolved
| <> | ||
| <ModalHeader closeModal={close} title={t('changePassword', 'Change Password')} /> | ||
| <ModalBody> | ||
| <Tile> |
There was a problem hiding this comment.
No need for Tile here. It adds unnecessary margin to the modal body.
packages/esm-system-admin-app/src/change-password-modal/change-password-modal.component.tsx
Outdated
Show resolved
Hide resolved
| :global(.cds--text-input) { | ||
| background-color: white; | ||
| } |
| import userEvent from '@testing-library/user-event'; | ||
|
|
||
| describe(`Change Password Modal`, () => { | ||
| it('should change user locale', async () => { |
There was a problem hiding this comment.
Shouldn't this be something about changing the password, not the locale?
| onChange={handlePasswordChange} | ||
| ref={newPasswordInputRef} | ||
| required | ||
| showPasswordLabel="Show new password" |
There was a problem hiding this comment.
Consider providing detailed helper text below the fields listing any requirements related to the data format, such as types of characters allowed per the password input usage guidelines.
| useEffect(() => { | ||
| if (passwordInput.oldPassword !== '') { | ||
| handleValidation(passwordInput.oldPassword, 'oldPassword'); | ||
| } | ||
| if (passwordInput.newPassword !== '') { | ||
| handleValidation(passwordInput.newPassword, 'newPassword'); | ||
| } | ||
| if (passwordInput.confirmPassword !== '') { | ||
| handleValidation(passwordInput.confirmPassword, 'confirmPassword'); | ||
| } | ||
| }, [handleValidation, passwordInput]); |
There was a problem hiding this comment.
For the best client-side validation experience, we should probably use RHF and Zod here similar to how we're validating the Vitals and Biometrics form (and various other vanilla React forms in O3).
…-password-modal.component.tsx Co-authored-by: Dennis Kigen <kigen.work@gmail.com>
…-password-modal.component.tsx Co-authored-by: Dennis Kigen <kigen.work@gmail.com>
…-password-modal.component.tsx Co-authored-by: Dennis Kigen <kigen.work@gmail.com>
…-password-modal.component.tsx Co-authored-by: Dennis Kigen <kigen.work@gmail.com>
…-password-modal.component.tsx Co-authored-by: Dennis Kigen <kigen.work@gmail.com>
…-password-modal.component.tsx Co-authored-by: Dennis Kigen <kigen.work@gmail.com>
Requirements
Summary
O3 screen to allow users to change their password as a follow-up for openmrs/openmrs-esm-core#902
cc @ibacher @michaelbontyes @vasharma05 @denniskigen
Screenshots
change-password.mov
None.
Issue
https://openmrs.atlassian.net/browse/O3-1409
None.
Other
None.