diff --git a/packages/web/lib/networking/queries/useGetIntegrationsQuery.tsx b/packages/web/lib/networking/queries/useGetIntegrationsQuery.tsx index 9c28e2505..9b2623414 100644 --- a/packages/web/lib/networking/queries/useGetIntegrationsQuery.tsx +++ b/packages/web/lib/networking/queries/useGetIntegrationsQuery.tsx @@ -11,6 +11,7 @@ export interface Integration { createdAt: Date updatedAt: Date taskName?: string + settings?: unknown } export type IntegrationType = 'EXPORT' | 'IMPORT' @@ -43,6 +44,7 @@ export function useGetIntegrationsQuery(): IntegrationsQueryResponse { createdAt updatedAt taskName + settings } } ... on IntegrationsError { diff --git a/packages/web/pages/settings/integrations.tsx b/packages/web/pages/settings/integrations.tsx index 4d549b217..14c019ab7 100644 --- a/packages/web/pages/settings/integrations.tsx +++ b/packages/web/pages/settings/integrations.tsx @@ -110,11 +110,14 @@ export default function Integrations(): JSX.Element { } } - const redirectToPocket = (importItemState: ImportItemState) => { + const redirectToIntegration = ( + name: string, + importItemState: ImportItemState + ) => { // create a form and submit it to the backend const form = document.createElement('form') form.method = 'POST' - form.action = `${fetchEndpoint}/integration/pocket/auth` + form.action = `${fetchEndpoint}/integration/${name.toLowerCase()}/auth` const input = document.createElement('input') input.type = 'hidden' input.name = 'state' @@ -158,10 +161,39 @@ export default function Integrations(): JSX.Element { router.replace('/settings/integrations') } } + + const connectWithNotion = async () => { + try { + // get the token from query string + const token = router.query.code as string + const result = await setIntegrationMutation({ + token, + name: 'NOTION', + type: 'EXPORT', + enabled: true, + }) + if (result) { + revalidate() + showSuccessToast('Connected with Notion.') + } else { + showErrorToast('There was an error connecting to Notion.') + } + } catch (err) { + showErrorToast( + 'There was an error connecting to Notion. Please try again.', + { duration: 5000 } + ) + } finally { + router.replace('/settings/integrations') + } + } if (!router.isReady) return if (router.query.pocketToken && router.query.state && !pocketConnected) { connectToPocket() } + if (router.query.code) { + connectWithNotion() + } }, [router]) useEffect(() => { @@ -210,7 +242,7 @@ export default function Integrations(): JSX.Element { action: () => { pocketConnected ? deleteIntegration(pocketConnected.id) - : redirectToPocket(ImportItemState.Unarchived) + : redirectToIntegration('pocket', ImportItemState.Unarchived) }, disabled: isImporting(pocketConnected), isDropdown: !pocketConnected, @@ -218,18 +250,33 @@ export default function Integrations(): JSX.Element { { text: 'Import All', action: () => { - redirectToPocket(ImportItemState.All) + redirectToIntegration('pocket', ImportItemState.All) }, }, { text: 'Import Unarchived', action: () => { - redirectToPocket(ImportItemState.Unarchived) + redirectToIntegration('pocket', ImportItemState.Unarchived) }, }, ], }, }, + { + icon: '/static/icons/notion.png', + title: 'Notion', + subText: + 'Notion is an all-in-one workspace. Use our Notion integration to sync your Omnivore items to Notion.', + button: { + text: 'Settings', + icon: , + style: 'ctaWhite', + action: () => + router.push( + '/settings/integrations/notion' + ), + }, + }, { icon: '/static/icons/webhooks.svg', title: 'Webhooks', diff --git a/packages/web/pages/settings/integrations/notion.tsx b/packages/web/pages/settings/integrations/notion.tsx new file mode 100644 index 000000000..4b956065e --- /dev/null +++ b/packages/web/pages/settings/integrations/notion.tsx @@ -0,0 +1,97 @@ +import { styled } from '@stitches/react' +import { Button, Checkbox, Form, Input, Switch } from 'antd' +import 'antd/dist/antd.compact.css' +import Image from 'next/image' +import { useMemo } from 'react' +import { + Box, + HStack, + VStack, +} from '../../../components/elements/LayoutPrimitives' +import { PageMetaData } from '../../../components/patterns/PageMetaData' +import { SettingsLayout } from '../../../components/templates/SettingsLayout' +import { useGetIntegrationsQuery } from '../../../lib/networking/queries/useGetIntegrationsQuery' + +// Styles +const Header = styled(Box, { + color: '$utilityTextDefault', + fontSize: 'x-large', + margin: '20px', +}) + +export default function Notion(): JSX.Element { + const { integrations, revalidate } = useGetIntegrationsQuery() + const notion = useMemo(() => { + return integrations.find((i) => i.name == 'NOTION' && i.type == 'EXPORT') + }, [integrations]) + + return ( + <> + + + + + Integration Image +
Notion integration settings
+
+ + {notion && ( +
+ + + + + + + + + + + + + + + + + + + + Highlights + Labels + Notes + + + + + +
+ )} +
+
+ + ) +} diff --git a/packages/web/public/static/icons/notion.png b/packages/web/public/static/icons/notion.png new file mode 100644 index 000000000..391051679 Binary files /dev/null and b/packages/web/public/static/icons/notion.png differ