diff --git a/services/web/frontend/js/features/settings/components/misc-section.tsx b/services/web/frontend/js/features/settings/components/beta-program-section.tsx
similarity index 62%
rename from services/web/frontend/js/features/settings/components/misc-section.tsx
rename to services/web/frontend/js/features/settings/components/beta-program-section.tsx
index 052e2d8010..027e1209b3 100644
--- a/services/web/frontend/js/features/settings/components/misc-section.tsx
+++ b/services/web/frontend/js/features/settings/components/beta-program-section.tsx
@@ -1,27 +1,21 @@
import { useTranslation } from 'react-i18next'
import { useUserContext } from '../../../shared/context/user-context'
-function MiscSection() {
+function BetaProgramSection() {
const { t } = useTranslation()
const { betaProgram } = useUserContext()
return (
<>
{t('sharelatex_beta_program')}
-
+
{betaProgram
? t('beta_program_already_participating')
: t('beta_program_benefits')}
{t('manage_beta_program_membership')}
-
- {t('sessions')}
- {t('manage_sessions')}
-
- {t('newsletter')}
- {t('manage_newsletter')}
>
)
}
-export default MiscSection
+export default BetaProgramSection
diff --git a/services/web/frontend/js/features/settings/components/newsletter-section.tsx b/services/web/frontend/js/features/settings/components/newsletter-section.tsx
new file mode 100644
index 0000000000..630cd7c8bf
--- /dev/null
+++ b/services/web/frontend/js/features/settings/components/newsletter-section.tsx
@@ -0,0 +1,14 @@
+import { useTranslation } from 'react-i18next'
+
+function NewsletterSection() {
+ const { t } = useTranslation()
+
+ return (
+ <>
+ {t('newsletter')}
+ {t('manage_newsletter')}
+ >
+ )
+}
+
+export default NewsletterSection
diff --git a/services/web/frontend/js/features/settings/components/root.tsx b/services/web/frontend/js/features/settings/components/root.tsx
index c188415a44..5481033963 100644
--- a/services/web/frontend/js/features/settings/components/root.tsx
+++ b/services/web/frontend/js/features/settings/components/root.tsx
@@ -6,12 +6,15 @@ import EmailsSection from './emails-section'
import AccountInfoSection from './account-info-section'
import PasswordSection from './password-section'
import LinkingSection from './linking-section'
-import MiscSection from './misc-section'
+import BetaProgramSection from './beta-program-section'
+import SessionsSection from './sessions-section'
+import NewsletterSection from './newsletter-section'
import LeaveSection from './leave-section'
import * as eventTracking from '../../../infrastructure/event-tracking'
import { UserProvider } from '../../../shared/context/user-context'
import { SSOProvider } from '../context/sso-context'
import useWaitForI18n from '../../../shared/hooks/use-wait-for-i18n'
+import { ExposedSettings } from '../../../../../types/exposed-settings'
function SettingsPageRoot() {
const { isReady } = useWaitForI18n()
@@ -34,6 +37,7 @@ function SettingsPageRoot() {
function SettingsPageContent() {
const { t } = useTranslation()
const ssoError = getMeta('ol-ssoError') as string
+ const { isOverleaf } = getMeta('ol-ExposedSettings') as ExposedSettings
return (
@@ -60,9 +64,17 @@ function SettingsPageContent() {
-
+ {isOverleaf ? : null}
-
+
+
+ {isOverleaf ? (
+ <>
+
+
+
+ >
+ ) : null}
diff --git a/services/web/frontend/js/features/settings/components/sessions-section.tsx b/services/web/frontend/js/features/settings/components/sessions-section.tsx
new file mode 100644
index 0000000000..73fbd01425
--- /dev/null
+++ b/services/web/frontend/js/features/settings/components/sessions-section.tsx
@@ -0,0 +1,14 @@
+import { useTranslation } from 'react-i18next'
+
+function SessionsSection() {
+ const { t } = useTranslation()
+
+ return (
+ <>
+ {t('sessions')}
+ {t('manage_sessions')}
+ >
+ )
+}
+
+export default SessionsSection
diff --git a/services/web/frontend/stories/settings/beta-program.stories.js b/services/web/frontend/stories/settings/beta-program.stories.js
new file mode 100644
index 0000000000..7097af424e
--- /dev/null
+++ b/services/web/frontend/stories/settings/beta-program.stories.js
@@ -0,0 +1,27 @@
+import BetaProgramSection from '../../js/features/settings/components/beta-program-section'
+import { UserProvider } from '../../js/shared/context/user-context'
+
+export const SectionNotEnrolled = args => {
+ window.metaAttributesCache.set('ol-user', { betaProgram: false })
+
+ return (
+
+
+
+ )
+}
+
+export const SectionEnrolled = args => {
+ window.metaAttributesCache.set('ol-user', { betaProgram: true })
+
+ return (
+
+
+
+ )
+}
+
+export default {
+ title: 'Account Settings / Beta Program',
+ component: BetaProgramSection,
+}
diff --git a/services/web/frontend/stories/settings/misc.stories.js b/services/web/frontend/stories/settings/misc.stories.js
deleted file mode 100644
index 89ec5b25dd..0000000000
--- a/services/web/frontend/stories/settings/misc.stories.js
+++ /dev/null
@@ -1,17 +0,0 @@
-import MiscSection from '../../js/features/settings/components/misc-section'
-import { UserProvider } from '../../js/shared/context/user-context'
-
-export const Section = args => {
- window.metaAttributesCache.set('ol-user', { betaProgram: true })
-
- return (
-
-
-
- )
-}
-
-export default {
- title: 'Account Settings / Misc / Section',
- component: MiscSection,
-}
diff --git a/services/web/frontend/stories/settings/newsletter.stories.js b/services/web/frontend/stories/settings/newsletter.stories.js
new file mode 100644
index 0000000000..f0fffb6a35
--- /dev/null
+++ b/services/web/frontend/stories/settings/newsletter.stories.js
@@ -0,0 +1,10 @@
+import NewsletterSection from '../../js/features/settings/components/newsletter-section'
+
+export const Section = args => {
+ return
+}
+
+export default {
+ title: 'Account Settings / Newsletter',
+ component: NewsletterSection,
+}
diff --git a/services/web/frontend/stories/settings/sessions.stories.js b/services/web/frontend/stories/settings/sessions.stories.js
new file mode 100644
index 0000000000..668ed08b6a
--- /dev/null
+++ b/services/web/frontend/stories/settings/sessions.stories.js
@@ -0,0 +1,10 @@
+import SessionsSection from '../../js/features/settings/components/sessions-section'
+
+export const Section = args => {
+ return
+}
+
+export default {
+ title: 'Account Settings / Sessions',
+ component: SessionsSection,
+}
diff --git a/services/web/test/frontend/features/settings/components/beta-program-section.test.tsx b/services/web/test/frontend/features/settings/components/beta-program-section.test.tsx
new file mode 100644
index 0000000000..09da06967b
--- /dev/null
+++ b/services/web/test/frontend/features/settings/components/beta-program-section.test.tsx
@@ -0,0 +1,45 @@
+import { expect } from 'chai'
+import { screen, render } from '@testing-library/react'
+import BetaProgramSection from '../../../../../frontend/js/features/settings/components/beta-program-section'
+import { UserProvider } from '../../../../../frontend/js/shared/context/user-context'
+
+function renderSectionWithUserProvider() {
+ render(, {
+ wrapper: ({ children }) => {children},
+ })
+}
+
+describe('', function () {
+ beforeEach(function () {
+ window.metaAttributesCache.set('ol-user', {
+ betaProgram: true,
+ })
+ })
+
+ afterEach(function () {
+ window.metaAttributesCache = new Map()
+ })
+
+ it('shows link to sessions', async function () {
+ renderSectionWithUserProvider()
+
+ const link = screen.getByRole('link', {
+ name: 'Manage Beta Program Membership',
+ })
+
+ expect(link.getAttribute('href')).to.equal('/beta/participate')
+ })
+
+ it('shows enrolled status', async function () {
+ renderSectionWithUserProvider()
+ screen.getByText('You are enrolled in the Beta Program')
+ })
+
+ it('shows not enrolled status', async function () {
+ window.metaAttributesCache.set('ol-user', {
+ betaProgram: false,
+ })
+ renderSectionWithUserProvider()
+ screen.getByText(/By joining our Beta program you can have early access/)
+ })
+})
diff --git a/services/web/test/frontend/features/settings/components/newsletter-section.test.tsx b/services/web/test/frontend/features/settings/components/newsletter-section.test.tsx
new file mode 100644
index 0000000000..a1fdeee81f
--- /dev/null
+++ b/services/web/test/frontend/features/settings/components/newsletter-section.test.tsx
@@ -0,0 +1,16 @@
+import { expect } from 'chai'
+import { screen, render } from '@testing-library/react'
+
+import NewsletterSection from '../../../../../frontend/js/features/settings/components/newsletter-section'
+
+describe('', function () {
+ it('shows link to sessions', async function () {
+ render()
+
+ const link = screen.getByRole('link', {
+ name: 'Manage Your Newsletter Preferences',
+ })
+
+ expect(link.getAttribute('href')).to.equal('/user/email-preferences')
+ })
+})
diff --git a/services/web/test/frontend/features/settings/components/root.test.tsx b/services/web/test/frontend/features/settings/components/root.test.tsx
index 826fea8107..39c83d4478 100644
--- a/services/web/test/frontend/features/settings/components/root.test.tsx
+++ b/services/web/test/frontend/features/settings/components/root.test.tsx
@@ -1,3 +1,4 @@
+import { expect } from 'chai'
import sinon from 'sinon'
import { screen, render, waitFor } from '@testing-library/react'
import * as eventTracking from '../../../../../frontend/js/infrastructure/event-tracking'
@@ -11,7 +12,8 @@ describe('', function () {
window.metaAttributesCache.set('ol-ExposedSettings', { isOverleaf: true })
window.metaAttributesCache.set('ol-hasPassword', true)
window.metaAttributesCache.set('ol-ExposedSettings', {
- hasAffiliationsFeature: false,
+ hasAffiliationsFeature: true,
+ isOverleaf: true,
})
window.metaAttributesCache.set('ol-user', {
features: { github: true, dropbox: true, mendeley: true, zotero: true },
@@ -31,18 +33,48 @@ describe('', function () {
sendMBSpy.restore()
})
- it('displays page', async function () {
+ it('displays page for Overleaf', async function () {
render()
await waitFor(() => {
screen.getByText('Account Settings')
})
-
+ screen.getByText('Emails and Affiliations')
+ screen.getByText('Update Account Info')
+ screen.getByText('Change Password')
+ screen.getByText('Integrations')
+ screen.getByText('Overleaf Beta Program')
+ screen.getByText('Sessions')
+ screen.getByText('Newsletter')
screen.getByRole('button', {
name: 'Delete your account',
})
})
+ it('displays page for non-Overleaf', async function () {
+ window.metaAttributesCache.set('ol-ExposedSettings', {
+ hasAffiliationsFeature: false,
+ isOverleaf: false,
+ })
+ render()
+
+ await waitFor(() => {
+ screen.getByText('Account Settings')
+ })
+ expect(screen.queryByText('Emails and Affiliations')).to.not.exist
+ screen.getByText('Update Account Info')
+ screen.getByText('Change Password')
+ screen.getByText('Integrations')
+ expect(screen.queryByText('Overleaf Beta Program')).to.not.exist
+ screen.getByText('Sessions')
+ expect(screen.queryByText('Newsletter')).to.not.exist
+ expect(
+ screen.queryByRole('button', {
+ name: 'Delete your account',
+ })
+ ).to.not.exist
+ })
+
it('sends tracking event on load', async function () {
render()
diff --git a/services/web/test/frontend/features/settings/components/sessions-section.test.tsx b/services/web/test/frontend/features/settings/components/sessions-section.test.tsx
new file mode 100644
index 0000000000..9dc84b1f3c
--- /dev/null
+++ b/services/web/test/frontend/features/settings/components/sessions-section.test.tsx
@@ -0,0 +1,16 @@
+import { expect } from 'chai'
+import { screen, render } from '@testing-library/react'
+
+import SessionsSection from '../../../../../frontend/js/features/settings/components/sessions-section'
+
+describe('', function () {
+ it('shows link to sessions', async function () {
+ render()
+
+ const link = screen.getByRole('link', {
+ name: 'Manage Your Sessions',
+ })
+
+ expect(link.getAttribute('href')).to.equal('/user/sessions')
+ })
+})