From 487ffc230919475988d5465f1aed1f68f17cc6c8 Mon Sep 17 00:00:00 2001 From: Jessica Lawshe <5312836+lawshe@users.noreply.github.com> Date: Thu, 5 Feb 2026 08:38:50 -0600 Subject: [PATCH] Merge pull request #31099 from overleaf/ii-domain-capture-member-limit-email [web] Members limit email template changes GitOrigin-RevId: 8c26adda9f748a22a2c99787a3166be706293de3 --- .../app/src/Features/Email/EmailBuilder.mjs | 24 ++++++++++--------- .../test/unit/src/Email/EmailBuilder.test.mjs | 23 +++++++++--------- 2 files changed, 25 insertions(+), 22 deletions(-) diff --git a/services/web/app/src/Features/Email/EmailBuilder.mjs b/services/web/app/src/Features/Email/EmailBuilder.mjs index 3cececcfcb..4d00a96745 100644 --- a/services/web/app/src/Features/Email/EmailBuilder.mjs +++ b/services/web/app/src/Features/Email/EmailBuilder.mjs @@ -1025,24 +1025,26 @@ templates.taxExemptCertificateRequired = NoCTAEmailTemplate({ templates.groupMemberLimitWarning = ctaTemplate({ subject(opts) { - return `${opts.groupName || 'Your group'} is approaching its member limit` + return `Action needed: Your Overleaf group is nearly out of licenses` }, title(opts) { - return `${opts.groupName || 'Your group'} is approaching its member limit` + return `Action needed: Your Overleaf group is nearly out of licenses` }, greeting(opts) { - return opts.firstName ? `Hi ${opts.firstName},` : 'Hi,' + return opts.firstName ? `Hi ${opts.firstName},` : 'Hi there,' }, message(opts) { return [ - `Your group "${opts.groupName}" is approaching its member limit.`, - `Current usage: ${opts.currentMembers} of ${opts.membersLimit} licenses used (${opts.remainingSeats} remaining)`, - 'With domain capture enabled, users with verified email addresses from your domain can automatically join the group via SSO. Once the member limit is reached, new users will be blocked from joining.', - ] - }, - secondaryMessage() { - return [ - 'To ensure uninterrupted access for your users, consider adding more licenses or removing inactive members.', + `Your Overleaf group ${opts.groupName} is close to its license limit.`, + `${opts.currentMembers} of ${opts.membersLimit} licenses are in use (${opts.remainingSeats} remaining).`, + 'Because domain capture is enabled, users from your domain can join automatically via SSO.' + + '
' + + 'Once all licenses are used, new users won’t be able to join.', + 'What you can do now:', + '', ] }, ctaText() { diff --git a/services/web/test/unit/src/Email/EmailBuilder.test.mjs b/services/web/test/unit/src/Email/EmailBuilder.test.mjs index 9e010f57b9..6fa32ccf6b 100644 --- a/services/web/test/unit/src/Email/EmailBuilder.test.mjs +++ b/services/web/test/unit/src/Email/EmailBuilder.test.mjs @@ -1005,26 +1005,27 @@ describe('EmailBuilder', function () { const dom = cheerio.load(ctx.email.html) const plainText = dom.text() expect(ctx.email.subject).to.equal( - `${ctx.opts.groupName} is approaching its member limit` + 'Action needed: Your Overleaf group is nearly out of licenses' ) expect(ctx.email.html).to.exist expect(ctx.email.html).to.contain( - `Your group "${ctx.opts.groupName}" is approaching its member limit.` + `Your Overleaf group ${ctx.opts.groupName} is close to its license limit.` ) expect(plainText).to.contain( - `Current usage: ${ctx.opts.currentMembers} of ` + - `${ctx.opts.membersLimit} licenses used ` + - `(${ctx.opts.remainingSeats} remaining)` + `${ctx.opts.currentMembers} of ${ctx.opts.membersLimit} ` + + `licenses are in use (${ctx.opts.remainingSeats} remaining).` ) expect(ctx.email.html).to.contain( - 'With domain capture enabled, users with verified email ' + - 'addresses from your domain can automatically join the group ' + - 'via SSO. Once the member limit is reached, new users will ' + - 'be blocked from joining.' + 'Because domain capture is enabled, users from your domain ' + + 'can join automatically via SSO.' ) expect(ctx.email.html).to.contain( - 'To ensure uninterrupted access for your users, consider ' + - 'adding more licenses or removing inactive members.' + 'Once all licenses are used, new users won’t be able to join.' + ) + expect(ctx.email.html).to.contain('What you can do now:') + expect(ctx.email.html).to.contain('Add more licenses, or') + expect(ctx.email.html).to.contain( + 'Remove inactive users to free up licenses' ) const buttonLink = dom('td a') expect(buttonLink).to.exist