From 146a207fd1df45b276bc5c1652aeb7cbb15a6f83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Alby?= Date: Mon, 25 Apr 2022 13:04:44 +0200 Subject: [PATCH] Merge pull request #7723 from overleaf/ta-settings-refactor [SettingsPage] Refactor Linking Section GitOrigin-RevId: 49aa27cdcb3669c59c9a9c46edd3249cee876dd0 --- services/web/config/settings.defaults.js | 1 + .../settings/components/emails-section.tsx | 9 +- .../integration-linking-section.tsx | 46 ------ .../settings/components/linking-section.tsx | 135 ++++++++++++++++++ .../integration-widget.tsx} | 0 .../widget.tsx => linking/sso-widget.tsx} | 0 .../js/features/settings/components/root.tsx | 13 +- .../components/sso-linking-section.tsx | 68 --------- .../settings/helpers/integration-linking.js | 21 --- .../helpers/{sso-linking.js => linking.js} | 17 ++- .../settings/integration-linking.stories.js | 23 --- .../stories/settings/linking.stories.js | 46 ++++++ .../frontend/stories/settings/page.stories.js | 16 +-- .../stories/settings/sso-linking.stories.js | 23 --- .../integration-widget.test.tsx} | 2 +- .../sso-widget.test.tsx} | 2 +- 16 files changed, 217 insertions(+), 205 deletions(-) delete mode 100644 services/web/frontend/js/features/settings/components/integration-linking-section.tsx create mode 100644 services/web/frontend/js/features/settings/components/linking-section.tsx rename services/web/frontend/js/features/settings/components/{integration-linking/widget.tsx => linking/integration-widget.tsx} (100%) rename services/web/frontend/js/features/settings/components/{sso-linking/widget.tsx => linking/sso-widget.tsx} (100%) delete mode 100644 services/web/frontend/js/features/settings/components/sso-linking-section.tsx delete mode 100644 services/web/frontend/stories/settings/helpers/integration-linking.js rename services/web/frontend/stories/settings/helpers/{sso-linking.js => linking.js} (66%) delete mode 100644 services/web/frontend/stories/settings/integration-linking.stories.js create mode 100644 services/web/frontend/stories/settings/linking.stories.js delete mode 100644 services/web/frontend/stories/settings/sso-linking.stories.js rename services/web/test/frontend/features/settings/components/{integration-linking/widget.test.tsx => linking/integration-widget.test.tsx} (98%) rename services/web/test/frontend/features/settings/components/{sso-linking/widget.test.tsx => linking/sso-widget.test.tsx} (98%) diff --git a/services/web/config/settings.defaults.js b/services/web/config/settings.defaults.js index a7fd72673a..decdbd4af6 100644 --- a/services/web/config/settings.defaults.js +++ b/services/web/config/settings.defaults.js @@ -774,6 +774,7 @@ module.exports = { sourceEditorExtensions: [], sourceEditorComponents: [], integrationLinkingWidgets: [], + referenceLinkingWidgets: [], }, moduleImportSequence: ['launchpad', 'server-ce-scripts', 'user-activate'], diff --git a/services/web/frontend/js/features/settings/components/emails-section.tsx b/services/web/frontend/js/features/settings/components/emails-section.tsx index b01c87fbb9..e42b69f56a 100644 --- a/services/web/frontend/js/features/settings/components/emails-section.tsx +++ b/services/web/frontend/js/features/settings/components/emails-section.tsx @@ -69,9 +69,12 @@ function EmailsSection() { } return ( - - - + <> + + + +
+ ) } diff --git a/services/web/frontend/js/features/settings/components/integration-linking-section.tsx b/services/web/frontend/js/features/settings/components/integration-linking-section.tsx deleted file mode 100644 index 4ce5f1456a..0000000000 --- a/services/web/frontend/js/features/settings/components/integration-linking-section.tsx +++ /dev/null @@ -1,46 +0,0 @@ -import { useTranslation } from 'react-i18next' -import importOverleafModules from '../../../../macros/import-overleaf-module.macro' -const integrationLinkingWidgets = importOverleafModules( - 'integrationLinkingWidgets' -) - -function IntegrationLinkingSection() { - const { t } = useTranslation() - - return ( - <> -

{t('integrations')}

-

{t('linked_accounts_explained')}

-
- {integrationLinkingWidgets.map( - ({ import: importObject, path }, widgetIndex) => ( - - ) - )} -
- - ) -} - -type IntegrationLinkingWidgetProps = { - ModuleComponent: any - isLast: boolean -} - -function IntegrationLinkingWidget({ - ModuleComponent, - isLast, -}: IntegrationLinkingWidgetProps) { - return ( - <> - - {isLast ? null :
} - - ) -} - -export default IntegrationLinkingSection diff --git a/services/web/frontend/js/features/settings/components/linking-section.tsx b/services/web/frontend/js/features/settings/components/linking-section.tsx new file mode 100644 index 0000000000..607b2c6538 --- /dev/null +++ b/services/web/frontend/js/features/settings/components/linking-section.tsx @@ -0,0 +1,135 @@ +import { useTranslation } from 'react-i18next' +import importOverleafModules from '../../../../macros/import-overleaf-module.macro' +import { useSSOContext, SSOSubscription } from '../context/sso-context' +import { SSOLinkingWidget } from './linking/sso-widget' + +const integrationLinkingWidgets = importOverleafModules( + 'integrationLinkingWidgets' +) +const referenceLinkingWidgets = importOverleafModules('referenceLinkingWidgets') + +function LinkingSection() { + const { t } = useTranslation() + const { subscriptions } = useSSOContext() + + const hasIntegrationLinkingSection = integrationLinkingWidgets.length + const hasReferencesLinkingSection = referenceLinkingWidgets.length + const hasSSOLinkingSection = Object.keys(subscriptions).length > 0 + + if ( + !hasIntegrationLinkingSection && + !hasReferencesLinkingSection && + !hasSSOLinkingSection + ) { + return null + } + + return ( + <> +

{t('integrations')}

+

{t('linked_accounts_explained')}

+ {hasIntegrationLinkingSection ? ( + <> +

{t('sync_dropbox_github')}

+
+ {integrationLinkingWidgets.map( + ({ import: importObject, path }, widgetIndex) => ( + + ) + )} +
+ + ) : null} + {hasReferencesLinkingSection ? ( + <> +

{t('reference_sync')}

+
+ {referenceLinkingWidgets.map( + ({ import: importObject, path }, widgetIndex) => ( + + ) + )} +
+ + ) : null} + {hasSSOLinkingSection ? ( + <> +

{t('linked_accounts')}

+
+ {Object.values(subscriptions).map( + (subscription, subscriptionIndex) => ( + + ) + )} +
+ + ) : null} + {hasIntegrationLinkingSection || + hasReferencesLinkingSection || + hasSSOLinkingSection ? ( +
+ ) : null} + + ) +} + +type LinkingWidgetProps = { + ModuleComponent: any + isLast: boolean +} + +function ModuleLinkingWidget({ ModuleComponent, isLast }: LinkingWidgetProps) { + return ( + <> + + {isLast ? null :
} + + ) +} + +type SSOLinkingWidgetContainerProps = { + subscription: SSOSubscription + isLast: boolean +} + +function SSOLinkingWidgetContainer({ + subscription, + isLast, +}: SSOLinkingWidgetContainerProps) { + const { t } = useTranslation() + const { unlink } = useSSOContext() + + return ( + <> + unlink(subscription.providerId)} + /> + {isLast ? null :
} + + ) +} + +export default LinkingSection diff --git a/services/web/frontend/js/features/settings/components/integration-linking/widget.tsx b/services/web/frontend/js/features/settings/components/linking/integration-widget.tsx similarity index 100% rename from services/web/frontend/js/features/settings/components/integration-linking/widget.tsx rename to services/web/frontend/js/features/settings/components/linking/integration-widget.tsx diff --git a/services/web/frontend/js/features/settings/components/sso-linking/widget.tsx b/services/web/frontend/js/features/settings/components/linking/sso-widget.tsx similarity index 100% rename from services/web/frontend/js/features/settings/components/sso-linking/widget.tsx rename to services/web/frontend/js/features/settings/components/linking/sso-widget.tsx diff --git a/services/web/frontend/js/features/settings/components/root.tsx b/services/web/frontend/js/features/settings/components/root.tsx index f181838b03..27b6f2f464 100644 --- a/services/web/frontend/js/features/settings/components/root.tsx +++ b/services/web/frontend/js/features/settings/components/root.tsx @@ -5,12 +5,12 @@ import getMeta from '../../../utils/meta' import EmailsSection from './emails-section' import AccountInfoSection from './account-info-section' import PasswordSection from './password-section' -import IntegrationLinkingSection from './integration-linking-section' -import SSOLinkingSection from './sso-linking-section' +import LinkingSection from './linking-section' import MiscSection from './misc-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' function SettingsPageRoot() { const { t } = useTranslation() @@ -34,7 +34,7 @@ function SettingsPageRoot() {

{t('account_settings')}

-
+
@@ -45,10 +45,9 @@ function SettingsPageRoot() {

- -
- -
+ + +
diff --git a/services/web/frontend/js/features/settings/components/sso-linking-section.tsx b/services/web/frontend/js/features/settings/components/sso-linking-section.tsx deleted file mode 100644 index b8a216f20f..0000000000 --- a/services/web/frontend/js/features/settings/components/sso-linking-section.tsx +++ /dev/null @@ -1,68 +0,0 @@ -import { useTranslation } from 'react-i18next' -import { - SSOProvider, - useSSOContext, - SSOSubscription, -} from '../context/sso-context' -import { SSOLinkingWidget } from './sso-linking/widget' - -function SSOLinkingSection() { - const { t } = useTranslation() - - return ( - -

{t('linked_accounts')}

-

{t('linked_accounts_explained')}

- -
- ) -} - -function SSOLinkingWidgets() { - const { subscriptions } = useSSOContext() - - return ( -
- {Object.values(subscriptions).map((subscription, subscriptionIndex) => ( - - ))} -
- ) -} - -type SSOLinkingWidgetContainerProps = { - subscription: SSOSubscription - isLast: boolean -} - -function SSOLinkingWidgetContainer({ - subscription, - isLast, -}: SSOLinkingWidgetContainerProps) { - const { t } = useTranslation() - const { unlink } = useSSOContext() - - return ( - <> - unlink(subscription.providerId)} - /> - {isLast ? null :
} - - ) -} - -export default SSOLinkingSection diff --git a/services/web/frontend/stories/settings/helpers/integration-linking.js b/services/web/frontend/stories/settings/helpers/integration-linking.js deleted file mode 100644 index cf7df7cc7f..0000000000 --- a/services/web/frontend/stories/settings/helpers/integration-linking.js +++ /dev/null @@ -1,21 +0,0 @@ -const MOCK_DELAY = 1000 - -export function defaultSetupMocks(fetchMock) { - fetchMock.get( - 'express:/user/tpds/queues', - { tpdsToWeb: 0, webToTpds: 0 }, - { delay: MOCK_DELAY } - ) -} - -export function setDefaultMeta() { - window.metaAttributesCache.set('ol-user', { - features: { github: true, dropbox: true, mendeley: false, zotero: false }, - refProviders: { - mendeley: true, - zotero: true, - }, - }) - window.metaAttributesCache.set('ol-github', { enabled: false }) - window.metaAttributesCache.set('ol-dropbox', { registered: true }) -} diff --git a/services/web/frontend/stories/settings/helpers/sso-linking.js b/services/web/frontend/stories/settings/helpers/linking.js similarity index 66% rename from services/web/frontend/stories/settings/helpers/sso-linking.js rename to services/web/frontend/stories/settings/helpers/linking.js index 3cdc6cf6dc..647fcb0427 100644 --- a/services/web/frontend/stories/settings/helpers/sso-linking.js +++ b/services/web/frontend/stories/settings/helpers/linking.js @@ -1,10 +1,25 @@ const MOCK_DELAY = 1000 export function defaultSetupMocks(fetchMock) { - fetchMock.post('/user/oauth-unlink', 200, { delay: MOCK_DELAY }) + fetchMock + .post('/user/oauth-unlink', 200, { delay: MOCK_DELAY }) + .get( + 'express:/user/tpds/queues', + { tpdsToWeb: 0, webToTpds: 0 }, + { delay: MOCK_DELAY } + ) } export function setDefaultMeta() { + window.metaAttributesCache.set('ol-user', { + features: { github: true, dropbox: true, mendeley: false, zotero: false }, + refProviders: { + mendeley: true, + zotero: true, + }, + }) + window.metaAttributesCache.set('ol-github', { enabled: false }) + window.metaAttributesCache.set('ol-dropbox', { registered: true }) window.metaAttributesCache.set('ol-thirdPartyIds', { collabratec: 'collabratec-id', google: 'google-id', diff --git a/services/web/frontend/stories/settings/integration-linking.stories.js b/services/web/frontend/stories/settings/integration-linking.stories.js deleted file mode 100644 index 774e9d03f2..0000000000 --- a/services/web/frontend/stories/settings/integration-linking.stories.js +++ /dev/null @@ -1,23 +0,0 @@ -import useFetchMock from '../hooks/use-fetch-mock' -import IntegrationLinkingSection from '../../js/features/settings/components/integration-linking-section' -import { - setDefaultMeta, - defaultSetupMocks, -} from './helpers/integration-linking' -import { UserProvider } from '../../js/shared/context/user-context' - -export const Section = args => { - useFetchMock(defaultSetupMocks) - setDefaultMeta() - - return ( - - - - ) -} - -export default { - title: 'Account Settings / Integration Linking / Section', - component: IntegrationLinkingSection, -} diff --git a/services/web/frontend/stories/settings/linking.stories.js b/services/web/frontend/stories/settings/linking.stories.js new file mode 100644 index 0000000000..6c45a33e91 --- /dev/null +++ b/services/web/frontend/stories/settings/linking.stories.js @@ -0,0 +1,46 @@ +import useFetchMock from '../hooks/use-fetch-mock' +import LinkingSection from '../../js/features/settings/components/linking-section' +import { setDefaultMeta, defaultSetupMocks } from './helpers/linking' +import { UserProvider } from '../../js/shared/context/user-context' +import { SSOProvider } from '../../js/features/settings/context/sso-context' + +export const Section = args => { + useFetchMock(defaultSetupMocks) + setDefaultMeta() + + return ( + + + + + + ) +} + +export const SectionAllUnlinked = args => { + useFetchMock(defaultSetupMocks) + setDefaultMeta() + window.metaAttributesCache.set('ol-thirdPartyIds', {}) + window.metaAttributesCache.set('ol-user', { + features: { github: true, dropbox: true, mendeley: true, zotero: true }, + refProviders: { + mendeley: false, + zotero: false, + }, + }) + window.metaAttributesCache.set('ol-github', { enabled: false }) + window.metaAttributesCache.set('ol-dropbox', { registered: false }) + + return ( + + + + + + ) +} + +export default { + title: 'Account Settings / Linking', + component: LinkingSection, +} diff --git a/services/web/frontend/stories/settings/page.stories.js b/services/web/frontend/stories/settings/page.stories.js index 9a28ac1dd9..5e07a7e71f 100644 --- a/services/web/frontend/stories/settings/page.stories.js +++ b/services/web/frontend/stories/settings/page.stories.js @@ -17,13 +17,9 @@ import { defaultSetupMocks as defaultSetupEmailsMocks, } from './helpers/emails' import { - setDefaultMeta as setDefaultIntegrationLinkingMeta, - defaultSetupMocks as defaultSetupIntegrationLinkingMocks, -} from './helpers/integration-linking' -import { - setDefaultMeta as setDefaultSSOMeta, - defaultSetupMocks as defaultSetupSSOMocks, -} from './helpers/sso-linking' + setDefaultMeta as setDefaultLinkingMeta, + defaultSetupMocks as defaultSetupLinkingMocks, +} from './helpers/linking' import { UserProvider } from '../../js/shared/context/user-context' export const Root = args => { @@ -31,14 +27,12 @@ export const Root = args => { setDefaultAccountInfoMeta() setDefaultPasswordMeta() setDefaultEmailsMeta() - setDefaultIntegrationLinkingMeta() - setDefaultSSOMeta() + setDefaultLinkingMeta() useFetchMock(defaultSetupLeaveMocks) useFetchMock(defaultSetupAccountInfoMocks) useFetchMock(defaultSetupPasswordMocks) useFetchMock(defaultSetupEmailsMocks) - useFetchMock(defaultSetupIntegrationLinkingMocks) - useFetchMock(defaultSetupSSOMocks) + useFetchMock(defaultSetupLinkingMocks) return ( diff --git a/services/web/frontend/stories/settings/sso-linking.stories.js b/services/web/frontend/stories/settings/sso-linking.stories.js deleted file mode 100644 index 84ffa29553..0000000000 --- a/services/web/frontend/stories/settings/sso-linking.stories.js +++ /dev/null @@ -1,23 +0,0 @@ -import useFetchMock from '../hooks/use-fetch-mock' -import SSOLinkingSection from '../../js/features/settings/components/sso-linking-section' -import { setDefaultMeta, defaultSetupMocks } from './helpers/sso-linking' - -export const Section = args => { - useFetchMock(defaultSetupMocks) - setDefaultMeta() - - return -} - -export const SectionAllUnlinked = args => { - useFetchMock(defaultSetupMocks) - setDefaultMeta() - window.metaAttributesCache.set('ol-thirdPartyIds', {}) - - return -} - -export default { - title: 'Account Settings / SSO Linking / Section', - component: SSOLinkingSection, -} diff --git a/services/web/test/frontend/features/settings/components/integration-linking/widget.test.tsx b/services/web/test/frontend/features/settings/components/linking/integration-widget.test.tsx similarity index 98% rename from services/web/test/frontend/features/settings/components/integration-linking/widget.test.tsx rename to services/web/test/frontend/features/settings/components/linking/integration-widget.test.tsx index 1c9bdc06e2..faf9cdaae6 100644 --- a/services/web/test/frontend/features/settings/components/integration-linking/widget.test.tsx +++ b/services/web/test/frontend/features/settings/components/linking/integration-widget.test.tsx @@ -1,6 +1,6 @@ import { expect } from 'chai' import { screen, fireEvent, render, waitFor } from '@testing-library/react' -import { IntegrationLinkingWidget } from '../../../../../../frontend/js/features/settings/components/integration-linking/widget' +import { IntegrationLinkingWidget } from '../../../../../../frontend/js/features/settings/components/linking/integration-widget' describe('', function () { const defaultProps = { diff --git a/services/web/test/frontend/features/settings/components/sso-linking/widget.test.tsx b/services/web/test/frontend/features/settings/components/linking/sso-widget.test.tsx similarity index 98% rename from services/web/test/frontend/features/settings/components/sso-linking/widget.test.tsx rename to services/web/test/frontend/features/settings/components/linking/sso-widget.test.tsx index e8dd9d6478..13a95fe5ce 100644 --- a/services/web/test/frontend/features/settings/components/sso-linking/widget.test.tsx +++ b/services/web/test/frontend/features/settings/components/linking/sso-widget.test.tsx @@ -1,7 +1,7 @@ import { expect } from 'chai' import sinon from 'sinon' import { screen, fireEvent, render, waitFor } from '@testing-library/react' -import { SSOLinkingWidget } from '../../../../../../frontend/js/features/settings/components/sso-linking/widget' +import { SSOLinkingWidget } from '../../../../../../frontend/js/features/settings/components/linking/sso-widget' describe('', function () { const defaultProps = {