Browse Source

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

Sort user emails by primary>confirmed>alphabetical

GitOrigin-RevId: 1d166e424e3848b83110c1a87adfff7790c1a01f
roo hutton 1 year ago
parent
commit
d680544b69

+ 15 - 1
services/web/frontend/js/features/settings/components/emails-section.tsx

@@ -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" />

+ 1 - 1
services/web/frontend/js/features/settings/components/emails/row.tsx

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

+ 52 - 0
services/web/test/frontend/features/settings/components/emails/emails-section.test.tsx

@@ -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
+  })
 })