Merge pull request #24787 from overleaf/rh-sort-account-emails

Sort user emails by primary>confirmed>alphabetical

GitOrigin-RevId: 1d166e424e3848b83110c1a87adfff7790c1a01f
This commit is contained in:
roo hutton
2025-05-19 15:07:08 +01:00
committed by Copybot
parent ab37e18bc3
commit d680544b69
3 changed files with 68 additions and 2 deletions

View File

@@ -26,6 +26,20 @@ function EmailsSectionContent() {
// Only show the "add email" button if the user has permission to add a secondary email
const hideAddSecondaryEmail = getMeta('ol-cannot-add-secondary-email')
// Sort emails: primary first, then confirmed secondary emails, then unconfirmed secondary emails
const sortedUserEmails = [...userEmails].sort((a, b) => {
// Primary email comes first
if (a.default) return -1
if (b.default) return 1
// Then sort by confirmation status
if (a.confirmedAt && !b.confirmedAt) return -1
if (!a.confirmedAt && b.confirmedAt) return 1
// If both have the same status, sort by email string
return a.email.localeCompare(b.email)
})
return (
<>
<h2 className="h3">{t('emails_and_affiliations_title')}</h2>
@@ -54,7 +68,7 @@ function EmailsSectionContent() {
</div>
) : (
<>
{userEmails?.map(userEmail => (
{sortedUserEmails.map(userEmail => (
<Fragment key={userEmail.email}>
<EmailsRow userEmailData={userEmail} primary={primary} />
<div className="horizontal-divider" />

View File

@@ -28,7 +28,7 @@ function EmailsRow({ userEmailData, primary }: EmailsRowProps) {
return (
<>
<OLRow>
<OLRow data-testid="email-row">
<OLCol lg={4}>
<EmailCell>
<Email userEmailData={userEmailData} />

View File

@@ -163,4 +163,56 @@ describe('<EmailsSection />', function () {
screen.getByText(/sorry, something went wrong/i)
screen.getByRole('button', { name: /resend confirmation code/i })
})
it('sorts emails with primary first, then confirmed, then unconfirmed', async function () {
const unconfirmedEmail = { ...unconfirmedUserData, email: 'b@example.com' }
const unconfirmedEmailTwo = {
...unconfirmedUserData,
email: 'd@example.com',
}
const confirmedEmail = {
...confirmedUserData,
email: 'a@example.com',
confirmedAt: new Date().toISOString(),
}
const confirmedEmailTwo = {
...confirmedUserData,
email: 'e@example.com',
confirmedAt: new Date().toISOString(),
}
const primaryEmail = {
...professionalUserData,
email: 'c@example.com',
default: true,
}
const emails = [
confirmedEmailTwo,
unconfirmedEmailTwo,
unconfirmedEmail,
confirmedEmail,
primaryEmail,
]
fetchMock.get('/user/emails?ensureAffiliation=true', emails)
render(<EmailsSection />)
await waitForElementToBeRemoved(() => screen.getByText(/loading/i))
const emailElements = screen.getAllByTestId(/email-row/i)
// Primary should be first regardless of alphabetical order
expect(within(emailElements[0]).getByText('c@example.com')).to.exist
expect(within(emailElements[0]).getByText('Primary')).to.exist
// Confirmed should be second in alphabetical order
expect(within(emailElements[1]).getByText('a@example.com')).to.exist
expect(within(emailElements[2]).getByText('e@example.com')).to.exist
// Unconfirmed should be last in alphabetical order
expect(within(emailElements[3]).getByText('b@example.com')).to.exist
expect(within(emailElements[3]).getByText(/unconfirmed/i)).to.exist
expect(within(emailElements[4]).getByText('d@example.com')).to.exist
expect(within(emailElements[4]).getByText(/unconfirmed/i)).to.exist
})
})