fix(FR-2228): add email input field to password change modal#5777
fix(FR-2228): add email input field to password change modal#5777ironAiken2 wants to merge 1 commit intographite-base/5777from
Conversation
How to use the Graphite Merge QueueAdd either label to this PR to merge it via the merge queue:
You must have a Graphite account in order to use the merge queue. Sign up using this link. An organization admin has required the Graphite Merge Queue in this repository. Please do not merge from GitHub as this will restart CI on PRs being processed by the merge queue. This stack of pull requests is managed by Graphite. Learn more about stacking. |
Coverage report for
|
St.❔ |
Category | Percentage | Covered / Total |
|---|---|---|---|
| 🔴 | Statements | 7.55% (-0.01% 🔻) |
1189/15742 |
| 🔴 | Branches | 6.36% (-0% 🔻) |
695/10923 |
| 🔴 | Functions | 5.04% (-0.01% 🔻) |
226/4480 |
| 🔴 | Lines | 7.39% (-0.01% 🔻) |
1136/15365 |
Test suite run success
624 tests passing in 32 suites.
Report generated by 🧪jest coverage report action from 302c82c
180cb24 to
4a8efd7
Compare
682c631 to
302c82c
Compare
There was a problem hiding this comment.
Pull request overview
Fixes the broken “forgot/change password” flow in the login UI by replacing the help-panel-only behavior with a modal that collects an email address and triggers the password-change email endpoint.
Changes:
- Adds a new
SendChangePasswordEmailModalUI with an email input + submit action. - Updates the “Change Password” link to open the modal instead of populating the help side panel.
- Wires the modal submit to
POST /cloud/send-password-change-emailusing the anonymous client.
You can also share your feedback on Copilot code review. Take the survey.
| <Form.Item name="email" rules={[{ required: true, type: 'email' }]}> | ||
| <Input | ||
| prefix={<MailOutlined />} | ||
| placeholder={t('login.E-mailOrUsername')} |
There was a problem hiding this comment.
The field is validated as type: 'email' but the placeholder uses t('login.E-mailOrUsername'), which suggests usernames are accepted even though they will be rejected by validation (and the API wrapper docs for /cloud/send-password-change-email indicate it expects an email). Consider using an email-only placeholder/label (and optionally type="email"/autoComplete="email") so the UI matches the actual accepted input.
| placeholder={t('login.E-mailOrUsername')} | |
| type="email" | |
| autoComplete="email" | |
| placeholder={t('login.E-mail')} |
| <Form.Item name="email" rules={[{ required: true, type: 'email' }]}> | ||
| <Input | ||
| prefix={<MailOutlined />} | ||
| placeholder={t('login.E-mailOrUsername')} |
There was a problem hiding this comment.
The email input in this modal is missing an accessible label (aria-label or a visible Form.Item label). In the same file, the login identifier field sets aria-label="Email or Username"; adding a similar label here will improve screen reader support.
| placeholder={t('login.E-mailOrUsername')} | |
| placeholder={t('login.E-mailOrUsername')} | |
| aria-label={t('login.E-mailOrUsername')} |
| content: t('login.DescChangePasswordEmail'), | ||
| }) | ||
| } | ||
| onClick={() => setShowChangePasswordEmail(true)} |
There was a problem hiding this comment.
Clicking “Change Password” only opens the modal, but it doesn’t clear/hide an already-open help side panel. Since the help panel uses a higher z-index (1060) than the modal (1002), the panel can visually overlap the modal and block interaction. Consider closing the help panel when opening this modal (e.g., setHelpPanel(null)) or adjust the visibility/z-index relationship so the modal always stays on top.
| onClick={() => setShowChangePasswordEmail(true)} | |
| onClick={() => { | |
| setShowChangePasswordEmail(true); | |
| setHelpPanel(null); | |
| }} |
| const onSubmit = () => { | ||
| form.validateFields().then((values) => { | ||
| mutation.mutate( | ||
| { email: values.email }, | ||
| { | ||
| onSuccess() { | ||
| message.success(t('login.EmailSent')); | ||
| onCancel(); | ||
| }, | ||
| }, | ||
| ); | ||
| }); |
There was a problem hiding this comment.
onSubmit calls form.validateFields().then(...) without handling the rejection path, which can result in an unhandled promise rejection when validation fails. Also, the mutation only defines onSuccess—errors (network/server) will fail silently with no user feedback. Please handle validation failures (catch/early return) and surface mutation errors (e.g., onError with message.error(...) or mutateAsync in a try/catch) similar to the pattern used in SignupModal.
| const onSubmit = () => { | |
| form.validateFields().then((values) => { | |
| mutation.mutate( | |
| { email: values.email }, | |
| { | |
| onSuccess() { | |
| message.success(t('login.EmailSent')); | |
| onCancel(); | |
| }, | |
| }, | |
| ); | |
| }); | |
| const onSubmit = async () => { | |
| let values: { email: string }; | |
| try { | |
| values = await form.validateFields(); | |
| } catch { | |
| // Validation failed; do not proceed with mutation. | |
| return; | |
| } | |
| mutation.mutate( | |
| { email: values.email }, | |
| { | |
| onSuccess() { | |
| message.success(t('login.EmailSent')); | |
| onCancel(); | |
| }, | |
| onError(error) { | |
| const errorMessage = | |
| (error as { message?: string })?.message || | |
| t('login.EmailSendFailed'); | |
| message.error(errorMessage); | |
| }, | |
| }, | |
| ); |
agatha197
left a comment
There was a problem hiding this comment.
please check copilot reviews
|
duplicated by #6033 |

Resolves #5776 (FR-2228, FR-2264)
The 'Change Password' link in the login form previously opened a help panel (sidebar) instead of a proper input UI. This meant users had no way to actually enter their email address to receive a password change link.
This PR extracts the forgot-password flow into a standalone
SendChangePasswordEmailModalcomponent with a proper email form input, fixing the broken user flow.Changes:
SendChangePasswordEmailModalas a dedicated React modal componentChecklist: (if applicable)