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