mirror of
https://github.com/yu-i-i/overleaf-cep.git
synced 2026-05-31 04:41:32 +02:00
Tw email confirmation notification (#14088)
* Edited notification copy for user with affilation that ha commons account * edited translation key to have overleaf professional appear in bold and switched to using trans component * changed anchor tag to button and added additional check to ensure affiliation exists before accessing institution name * add tests for commons user confirmation notification * edit user email context test to facilitate test data changes * edit license in fake test data * edit test to check text of notification for non commons user GitOrigin-RevId: 6700ceaa066f099ce593283887fa81d72ad624b6
This commit is contained in:
@@ -516,6 +516,7 @@
|
||||
"institution_account": "",
|
||||
"institution_acct_successfully_linked_2": "",
|
||||
"institution_and_role": "",
|
||||
"institution_has_overleaf_subscription": "",
|
||||
"institution_templates": "",
|
||||
"institutional_leavers_survey_notification": "",
|
||||
"integrations": "",
|
||||
@@ -704,6 +705,7 @@
|
||||
"ok": "",
|
||||
"on": "",
|
||||
"on_free_plan_upgrade_to_access_features": "",
|
||||
"one_step_away_from_professional_features": "",
|
||||
"only_group_admin_or_managers_can_delete_your_account": "",
|
||||
"open_file": "",
|
||||
"open_link": "",
|
||||
@@ -866,6 +868,7 @@
|
||||
"republish": "",
|
||||
"resend": "",
|
||||
"resend_confirmation_email": "",
|
||||
"resend_email": "",
|
||||
"resending_confirmation_email": "",
|
||||
"resolve": "",
|
||||
"resolved_comments": "",
|
||||
|
||||
@@ -11,7 +11,6 @@ function ReconfirmationInfo() {
|
||||
) as UserEmailData[]
|
||||
const userEmails = getMeta('ol-userEmails', []) as UserEmailData[]
|
||||
const reconfirmedViaSAML = getMeta('ol-reconfirmedViaSAML') as string
|
||||
|
||||
return (
|
||||
<>
|
||||
{allInReconfirmNotificationPeriods.map(userEmail =>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { Trans, useTranslation } from 'react-i18next'
|
||||
import { Button } from 'react-bootstrap'
|
||||
import Notification from '../notification'
|
||||
import Icon from '../../../../../shared/components/icon'
|
||||
@@ -35,6 +35,28 @@ const ssoAvailable = ({ samlProviderId, affiliation }: UserEmailData) => {
|
||||
return false
|
||||
}
|
||||
|
||||
function emailHasLicenceAfterConfirming(emailData: UserEmailData) {
|
||||
if (emailData.confirmedAt) {
|
||||
return false
|
||||
}
|
||||
if (!emailData.affiliation) {
|
||||
return false
|
||||
}
|
||||
const affiliation = emailData.affiliation
|
||||
const institution = affiliation.institution
|
||||
if (!institution) {
|
||||
return false
|
||||
}
|
||||
if (!institution.confirmed) {
|
||||
return false
|
||||
}
|
||||
if (affiliation.pastReconfirmDate) {
|
||||
return false
|
||||
}
|
||||
|
||||
return affiliation.institution.commonsAccount
|
||||
}
|
||||
|
||||
const showConfirmEmail = (userEmail: UserEmailData) => {
|
||||
const { emailConfirmationDisabled } = getMeta(
|
||||
'ol-ExposedSettings'
|
||||
@@ -63,9 +85,48 @@ function ConfirmEmailNotification({ userEmail }: { userEmail: UserEmailData }) {
|
||||
return null
|
||||
}
|
||||
|
||||
if (emailHasLicenceAfterConfirming(userEmail)) {
|
||||
return (
|
||||
<Notification bsStyle="info">
|
||||
<Notification.Body data-testid="notification-body">
|
||||
{isLoading ? (
|
||||
<>
|
||||
<Icon type="spinner" spin /> {t('resending_confirmation_email')}
|
||||
…
|
||||
</>
|
||||
) : isError ? (
|
||||
<div aria-live="polite">{getUserFacingMessage(error)}</div>
|
||||
) : (
|
||||
<>
|
||||
<Trans
|
||||
i18nKey="one_step_away_from_professional_features"
|
||||
components={[<strong />]} // eslint-disable-line react/jsx-key
|
||||
/>
|
||||
<button
|
||||
className="pull-right btn btn-info btn-sm"
|
||||
onClick={() => handleResendConfirmationEmail(userEmail)}
|
||||
>
|
||||
{t('resend_email')}
|
||||
</button>
|
||||
<br />
|
||||
<Trans
|
||||
i18nKey="institution_has_overleaf_subscription"
|
||||
values={{
|
||||
institutionName: userEmail.affiliation?.institution.name,
|
||||
emailAddress: userEmail.email,
|
||||
}}
|
||||
components={[<strong />]} // eslint-disable-line react/jsx-key
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</Notification.Body>
|
||||
</Notification>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<Notification bsStyle="warning">
|
||||
<Notification.Body>
|
||||
<Notification.Body data-testid="pro-notification-body">
|
||||
{isLoading ? (
|
||||
<>
|
||||
<Icon type="spinner" spin /> {t('resending_confirmation_email')}
|
||||
|
||||
@@ -813,6 +813,7 @@
|
||||
"institution_acct_successfully_linked_2": "Your <0>__appName__</0> account was successfully linked to your <0>__institutionName__</0> institutional account.",
|
||||
"institution_and_role": "Institution and role",
|
||||
"institution_email_new_to_app": "Your <b>__institutionName__</b> email (<b>__email__</b>) is new to __appName__.",
|
||||
"institution_has_overleaf_subscription": "<0>__institutionName__</0> has an Overleaf subscription. Click the confirmation link sent to __emailAddress__ to upgrade to <0>Overleaf Professional</0>.",
|
||||
"institution_templates": "Institution Templates",
|
||||
"institutional": "Institutional",
|
||||
"institutional_leavers_survey_notification": "Provide some quick feedback to receive a 25% discount on an annual subscription!",
|
||||
@@ -1140,6 +1141,7 @@
|
||||
"one_collaborator": "Only one collaborator",
|
||||
"one_free_collab": "One free collaborator",
|
||||
"one_minute": "1 minute",
|
||||
"one_step_away_from_professional_features": "You are one step away from accessing <0>Overleaf Professional features</0>!",
|
||||
"one_user": "1 user",
|
||||
"online_latex_editor": "Online LaTeX Editor",
|
||||
"only_group_admin_or_managers_can_delete_your_account": "Only your group admin or group managers will be able to delete your account.",
|
||||
@@ -1402,6 +1404,7 @@
|
||||
"required": "Required",
|
||||
"resend": "Resend",
|
||||
"resend_confirmation_email": "Resend confirmation email",
|
||||
"resend_email": "Resend email",
|
||||
"resending_confirmation_email": "Resending confirmation email",
|
||||
"reset_password": "Reset Password",
|
||||
"reset_your_password": "Reset your password",
|
||||
|
||||
@@ -5,12 +5,14 @@ import {
|
||||
render,
|
||||
screen,
|
||||
waitForElementToBeRemoved,
|
||||
within,
|
||||
} from '@testing-library/react'
|
||||
import fetchMock from 'fetch-mock'
|
||||
import { merge, cloneDeep } from 'lodash'
|
||||
import {
|
||||
professionalUserData,
|
||||
unconfirmedUserData,
|
||||
unconfirmedCommonsUserData,
|
||||
} from '../../settings/fixtures/test-user-email-data'
|
||||
import {
|
||||
notification,
|
||||
@@ -508,9 +510,6 @@ describe('<UserNotifications />', function () {
|
||||
emailConfirmationDisabled: false,
|
||||
})
|
||||
window.metaAttributesCache.set('ol-userEmails', [unconfirmedUserData])
|
||||
|
||||
renderWithinProjectListProvider(ConfirmEmail)
|
||||
await fetchMock.flush(true)
|
||||
})
|
||||
|
||||
afterEach(function () {
|
||||
@@ -518,8 +517,16 @@ describe('<UserNotifications />', function () {
|
||||
})
|
||||
|
||||
it('sends successfully', async function () {
|
||||
renderWithinProjectListProvider(ConfirmEmail)
|
||||
await fetchMock.flush(true)
|
||||
fetchMock.post('/user/emails/resend_confirmation', 200)
|
||||
|
||||
const email = unconfirmedUserData.email
|
||||
const notificationBody = screen.getByTestId('pro-notification-body')
|
||||
expect(notificationBody.textContent).to.contain(
|
||||
`Please confirm your email ${email} by clicking on the link in the confirmation email`
|
||||
)
|
||||
|
||||
const resendButton = screen.getByRole('button', { name: /resend/i })
|
||||
fireEvent.click(resendButton)
|
||||
|
||||
@@ -534,6 +541,8 @@ describe('<UserNotifications />', function () {
|
||||
})
|
||||
|
||||
it('fails to send', async function () {
|
||||
renderWithinProjectListProvider(ConfirmEmail)
|
||||
await fetchMock.flush(true)
|
||||
fetchMock.post('/user/emails/resend_confirmation', 500)
|
||||
|
||||
const resendButton = screen.getByRole('button', { name: /resend/i })
|
||||
@@ -546,6 +555,25 @@ describe('<UserNotifications />', function () {
|
||||
expect(fetchMock.called()).to.be.true
|
||||
screen.getByText(/something went wrong/i)
|
||||
})
|
||||
|
||||
it('shows notification for commons account', async function () {
|
||||
window.metaAttributesCache.set('ol-userEmails', [
|
||||
unconfirmedCommonsUserData,
|
||||
])
|
||||
|
||||
renderWithinProjectListProvider(ConfirmEmail)
|
||||
await fetchMock.flush(true)
|
||||
|
||||
const alert = screen.getByRole('alert')
|
||||
const email = unconfirmedCommonsUserData.email
|
||||
const notificationBody = within(alert).getByTestId('notification-body')
|
||||
expect(notificationBody.textContent).to.contain(
|
||||
'You are one step away from accessing Overleaf Professional features'
|
||||
)
|
||||
expect(notificationBody.textContent).to.contain(
|
||||
`Overleaf has an Overleaf subscription. Click the confirmation link sent to ${email} to upgrade to Overleaf Professional`
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe('<Affiliation/>', function () {
|
||||
|
||||
@@ -12,6 +12,7 @@ import {
|
||||
professionalUserData,
|
||||
unconfirmedUserData,
|
||||
fakeUsersData,
|
||||
unconfirmedCommonsUserData,
|
||||
} from '../fixtures/test-user-email-data'
|
||||
import localStorage from '../../../../../frontend/js/infrastructure/local-storage'
|
||||
|
||||
@@ -53,6 +54,7 @@ describe('UserEmailContext', function () {
|
||||
'bar@overleaf.com': confirmedUserData,
|
||||
'baz@overleaf.com': unconfirmedUserData,
|
||||
'foo@overleaf.com': professionalUserData,
|
||||
'qux@overleaf.com': unconfirmedCommonsUserData,
|
||||
})
|
||||
expect(result.current.state.data.linkedInstitutionIds).to.have.lengthOf(0)
|
||||
|
||||
|
||||
@@ -44,6 +44,37 @@ export const professionalUserData: UserEmailData & {
|
||||
default: true,
|
||||
}
|
||||
|
||||
export const unconfirmedCommonsUserData: UserEmailData & {
|
||||
affiliation: Affiliation
|
||||
} = {
|
||||
affiliation: {
|
||||
cachedConfirmedAt: null,
|
||||
cachedEntitlement: null,
|
||||
cachedLastDayToReconfirm: null,
|
||||
cachedPastReconfirmDate: false,
|
||||
cachedReconfirmedAt: null,
|
||||
department: 'Art History',
|
||||
institution: {
|
||||
commonsAccount: true,
|
||||
confirmed: true,
|
||||
id: 1,
|
||||
isUniversity: false,
|
||||
maxConfirmationMonths: null,
|
||||
name: 'Overleaf',
|
||||
ssoEnabled: false,
|
||||
ssoBeta: false,
|
||||
},
|
||||
inReconfirmNotificationPeriod: false,
|
||||
inferred: false,
|
||||
licence: 'free',
|
||||
pastReconfirmDate: false,
|
||||
portal: { slug: '', templates_count: 1 },
|
||||
role: 'Reader',
|
||||
},
|
||||
email: 'qux@overleaf.com',
|
||||
default: true,
|
||||
}
|
||||
|
||||
export const ssoUserData: UserEmailData = {
|
||||
affiliation: {
|
||||
cachedConfirmedAt: '2022-02-03T11:46:28.249Z',
|
||||
@@ -79,4 +110,5 @@ export const fakeUsersData = [
|
||||
{ ...confirmedUserData },
|
||||
{ ...unconfirmedUserData },
|
||||
{ ...professionalUserData },
|
||||
{ ...unconfirmedCommonsUserData },
|
||||
]
|
||||
|
||||
Reference in New Issue
Block a user