-
Notifications
You must be signed in to change notification settings - Fork 10
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: change email updating workflow [DHIS2-18493] #1470
Changes from 1 commit
abcac63
17a281d
38b79c9
4087c37
705528c
7c54a40
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -15,6 +15,7 @@ import TextField from 'd2-ui/lib/form-fields/TextField' | |
import PropTypes from 'prop-types' | ||
import React, { useMemo, useState } from 'react' | ||
import styles from './ModalField.component.module.css' | ||
import { VerifyEmail } from './VerifyEmail.component.js' | ||
|
||
const TooltipWrapper = ({ disabled, content, children }) => { | ||
if (!disabled) { | ||
|
@@ -39,16 +40,67 @@ const getSaveDisabledContent = ({ newEmail, emailValidationMessage }) => { | |
return i18n.t('Emails must match') | ||
} | ||
|
||
const RemoveModal = ({ | ||
removeModalOpen, | ||
closeModal, | ||
userEmailVerified, | ||
setUserEmail, | ||
onUpdate, | ||
}) => ( | ||
<Modal hide={!removeModalOpen} onClose={closeModal}> | ||
<ModalTitle>{i18n.t('Remove email')}</ModalTitle> | ||
|
||
<ModalContent> | ||
{userEmailVerified && ( | ||
<NoticeBox | ||
className={styles.emailModalItem} | ||
title={i18n.t('Your email is currently verified')} | ||
warning | ||
></NoticeBox> | ||
)} | ||
<div>{i18n.t('Are you sure you want to remove your email?')}</div> | ||
</ModalContent> | ||
|
||
<ModalActions> | ||
<ButtonStrip end> | ||
<Button onClick={() => closeModal()} secondary> | ||
{i18n.t('Cancel')} | ||
</Button> | ||
|
||
<Button | ||
onClick={() => { | ||
setUserEmail(null) | ||
onUpdate('email', '') | ||
closeModal() | ||
}} | ||
destructive | ||
> | ||
{i18n.t('Remove email')} | ||
</Button> | ||
</ButtonStrip> | ||
</ModalActions> | ||
</Modal> | ||
) | ||
|
||
RemoveModal.propTypes = { | ||
closeModal: PropTypes.func, | ||
removeModalOpen: PropTypes.bool, | ||
setUserEmail: PropTypes.bool, | ||
userEmailVerified: PropTypes.bool, | ||
onUpdate: PropTypes.func, | ||
} | ||
|
||
export function ModalField({ | ||
userEmail, | ||
userEmailVerified, | ||
setUserEmail, | ||
onUpdate, | ||
}) { | ||
const [modalOpen, setModalOpen] = useState() | ||
const [removeModalOpen, setRemoveModalOpen] = useState() | ||
const [newEmail, setNewEmail] = useState() | ||
const [newEmailConfirm, setNewEmailConfirm] = useState() | ||
const [newEmailTouched, setNewEmailTouched] = useState(false) | ||
const [newEmailConfirmTouched, setNewEmailConfirmTouched] = useState(false) | ||
const emailValidationMessage = useMemo( | ||
() => emailValidator(newEmail), | ||
[newEmail] | ||
|
@@ -63,9 +115,10 @@ export function ModalField({ | |
|
||
const closeModal = () => { | ||
setModalOpen(false) | ||
setRemoveModalOpen(false) | ||
setNewEmail() | ||
setNewEmailConfirm() | ||
setNewEmailTouched(false) | ||
setNewEmailConfirmTouched(false) | ||
} | ||
return ( | ||
<div className={styles.emailModalContainer}> | ||
|
@@ -75,13 +128,26 @@ export function ModalField({ | |
floatingLabelText={i18n.t('Email')} | ||
style={{ width: '100%' }} | ||
/> | ||
<div> | ||
<div className={styles.buttonContainer}> | ||
<VerifyEmail userEmail={userEmail} /> | ||
<Button secondary onClick={() => setModalOpen(true)}> | ||
{i18n.t('Update email')} | ||
{i18n.t('Change email')} | ||
</Button> | ||
<TooltipWrapper | ||
disabled={!userEmail} | ||
content={i18n.t('There is no email to remove')} | ||
> | ||
<Button | ||
destructive | ||
onClick={() => setRemoveModalOpen(true)} | ||
disabled={!userEmail} | ||
> | ||
{i18n.t('Remove email')} | ||
</Button> | ||
</TooltipWrapper> | ||
</div> | ||
<Modal hide={!modalOpen} onClose={closeModal}> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Kind of minor. But I think I would've preferred this (The modal with the contents) to be it's own component. Not just for the sake of extracting this out - but it would also mean that we don't have to manually reset the state of this modal during There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think that's fair. We just started writing it this way and then it was easier to continue on with what we had and do a manual reset of the component state. But it became a bit longer than what we had originally, so seems fair to also break it up into a separate component. I've updated to put it in its own component but within the EmailField.js file as I think it's functionally easier to read the code when this is in one file. |
||
<ModalTitle>{i18n.t('Update email')}</ModalTitle> | ||
<ModalTitle>{i18n.t('Change email')}</ModalTitle> | ||
|
||
<ModalContent> | ||
{userEmailVerified && ( | ||
|
@@ -98,7 +164,11 @@ export function ModalField({ | |
|
||
<InputField | ||
label={i18n.t('Current email')} | ||
value={userEmail} | ||
value={ | ||
userEmail !== '' | ||
? userEmail | ||
: i18n.t('no current email') | ||
} | ||
type="email" | ||
disabled | ||
className={styles.emailModalItem} | ||
|
@@ -117,14 +187,14 @@ export function ModalField({ | |
label={i18n.t('Confirm new email')} | ||
value={newEmailConfirm} | ||
type="email" | ||
error={newEmailTouched && !emailsMatch} | ||
error={newEmailConfirmTouched && !emailsMatch} | ||
validationText={ | ||
emailsMatch || !newEmailTouched | ||
emailsMatch || !newEmailConfirmTouched | ||
? undefined | ||
: i18n.t('Emails must match') | ||
} | ||
onChange={(newValue) => { | ||
setNewEmailTouched(true) | ||
setNewEmailConfirmTouched(true) | ||
setNewEmailConfirm(newValue.value) | ||
}} | ||
className={styles.emailModalItem} | ||
|
@@ -156,6 +226,13 @@ export function ModalField({ | |
</ButtonStrip> | ||
</ModalActions> | ||
</Modal> | ||
<RemoveModal | ||
removeModalOpen={removeModalOpen} | ||
closeModal={closeModal} | ||
userEmailVerified={userEmailVerified} | ||
setUserEmail={setUserEmail} | ||
onUpdate={onUpdate} | ||
/> | ||
</div> | ||
) | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,4 +8,9 @@ | |
|
||
.emailModalItem { | ||
margin-block-end: 16px; | ||
} | ||
|
||
.buttonContainer { | ||
display: flex; | ||
gap: 8px; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm a bit confused about the naming of this component (and file). When I read "ModalField" I would expect this to be a generic field that somehow opens a modal. I would expect this to be called
EmailField
.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've updated to use EmailField, and to make some of the related functions/props correspond to this update