From 4e239854809c280d0d8bea8427e1daeb7fcb3272 Mon Sep 17 00:00:00 2001 From: Saxon Fletcher Date: Tue, 18 Feb 2025 16:07:37 +1000 Subject: [PATCH] updated scaffolding --- .../Auth/AuthProvidersForm/AuthAlert.tsx | 6 +- .../AuthProvidersForm/AuthProvidersForm.tsx | 17 +++-- .../Auth/AuthProvidersForm/ProviderForm.tsx | 2 +- .../BasicAuthSettingsForm.tsx | 8 +- .../Auth/ThirdPartyAuthForm/index.tsx | 46 +++++++----- .../AuthLayout/AuthProvidersLayout.tsx | 38 ++++++++++ .../layouts/PageLayout/Breadcrumbs.tsx | 39 ---------- .../layouts/PageLayout/PageContainer.tsx | 16 ---- .../layouts/PageLayout/PageHeader.tsx | 12 ++- .../layouts/PageLayout/PageLayout.tsx | 30 +++++--- .../layouts/PageLayout/PageNavigation.tsx | 33 --------- .../layouts/PageLayout/SectionHeader.tsx | 23 ------ .../components/layouts/PageLayout/index.ts | 5 -- apps/studio/components/layouts/Scaffold.tsx | 33 ++++++++- .../pages/project/[ref]/auth/providers.tsx | 37 ++-------- .../pages/project/[ref]/auth/third-party.tsx | 74 ++++--------------- 16 files changed, 160 insertions(+), 259 deletions(-) create mode 100644 apps/studio/components/layouts/AuthLayout/AuthProvidersLayout.tsx delete mode 100644 apps/studio/components/layouts/PageLayout/Breadcrumbs.tsx delete mode 100644 apps/studio/components/layouts/PageLayout/PageContainer.tsx delete mode 100644 apps/studio/components/layouts/PageLayout/PageNavigation.tsx delete mode 100644 apps/studio/components/layouts/PageLayout/SectionHeader.tsx diff --git a/apps/studio/components/interfaces/Auth/AuthProvidersForm/AuthAlert.tsx b/apps/studio/components/interfaces/Auth/AuthProvidersForm/AuthAlert.tsx index 992f35bc210..98192c9133b 100644 --- a/apps/studio/components/interfaces/Auth/AuthProvidersForm/AuthAlert.tsx +++ b/apps/studio/components/interfaces/Auth/AuthProvidersForm/AuthAlert.tsx @@ -10,11 +10,11 @@ import { } from 'ui' export const AuthAlert = ({ - ref, + projectRef, title, isHookSendSMSEnabled, }: { - ref?: string + projectRef: string title: string isHookSendSMSEnabled: boolean }) => { @@ -51,7 +51,7 @@ export const AuthAlert = ({

The SMS hook will be used in place of the SMS provider configured

diff --git a/apps/studio/components/interfaces/Auth/AuthProvidersForm/AuthProvidersForm.tsx b/apps/studio/components/interfaces/Auth/AuthProvidersForm/AuthProvidersForm.tsx index b37189354c7..02f6803c577 100644 --- a/apps/studio/components/interfaces/Auth/AuthProvidersForm/AuthProvidersForm.tsx +++ b/apps/studio/components/interfaces/Auth/AuthProvidersForm/AuthProvidersForm.tsx @@ -16,6 +16,11 @@ import { import { getPhoneProviderValidationSchema, PROVIDERS_SCHEMAS } from '../AuthProvidersFormValidation' import type { Provider } from './AuthProvidersForm.types' import ProviderForm from './ProviderForm' +import { + ScaffoldSection, + ScaffoldSectionDescription, + ScaffoldSectionTitle, +} from 'components/layouts/Scaffold' export const AuthProvidersForm = () => { const { ref: projectRef } = useParams() @@ -28,11 +33,11 @@ export const AuthProvidersForm = () => { } = useAuthConfigQuery({ projectRef }) return ( -
- + + Auth Providers + + Authenticate your users through a suite of providers and login methods +
{authConfig?.EXTERNAL_EMAIL_ENABLED && authConfig?.MAILER_OTP_EXP > 3600 && ( @@ -102,6 +107,6 @@ export const AuthProvidersForm = () => { )}
-
+ ) } diff --git a/apps/studio/components/interfaces/Auth/AuthProvidersForm/ProviderForm.tsx b/apps/studio/components/interfaces/Auth/AuthProvidersForm/ProviderForm.tsx index c58b20afca2..2873b1efa70 100644 --- a/apps/studio/components/interfaces/Auth/AuthProvidersForm/ProviderForm.tsx +++ b/apps/studio/components/interfaces/Auth/AuthProvidersForm/ProviderForm.tsx @@ -169,7 +169,7 @@ const ProviderForm = ({ config, provider, isActive }: ProviderFormProps) => {
diff --git a/apps/studio/components/interfaces/Auth/BasicAuthSettingsForm/BasicAuthSettingsForm.tsx b/apps/studio/components/interfaces/Auth/BasicAuthSettingsForm/BasicAuthSettingsForm.tsx index dc81505171f..774b8787cd7 100644 --- a/apps/studio/components/interfaces/Auth/BasicAuthSettingsForm/BasicAuthSettingsForm.tsx +++ b/apps/studio/components/interfaces/Auth/BasicAuthSettingsForm/BasicAuthSettingsForm.tsx @@ -26,9 +26,9 @@ import { Switch, WarningIcon, } from 'ui' -import { SectionHeader } from 'components/layouts/PageLayout' import { NO_REQUIRED_CHARACTERS } from '../Auth.constants' +import { ScaffoldSection, ScaffoldSectionTitle } from 'components/layouts/Scaffold' const schema = object({ DISABLE_SIGNUP: boolean().required(), @@ -106,8 +106,8 @@ const BasicAuthSettingsForm = () => { } return ( -
- + + User Signups
@@ -252,7 +252,7 @@ const BasicAuthSettingsForm = () => {
-
+ ) } diff --git a/apps/studio/components/interfaces/Auth/ThirdPartyAuthForm/index.tsx b/apps/studio/components/interfaces/Auth/ThirdPartyAuthForm/index.tsx index 39e81d3c9d7..9398391bbef 100644 --- a/apps/studio/components/interfaces/Auth/ThirdPartyAuthForm/index.tsx +++ b/apps/studio/components/interfaces/Auth/ThirdPartyAuthForm/index.tsx @@ -24,7 +24,12 @@ import { getIntegrationTypeLabel, INTEGRATION_TYPES, } from './ThirdPartyAuthForm.utils' - +import { + ScaffoldSection, + ScaffoldSectionDescription, + ScaffoldSectionTitle, +} from 'components/layouts/Scaffold' +import { DocsButton } from 'components/ui/DocsButton' export const ThirdPartyAuthForm = () => { const { ref: projectRef } = useParams() const { @@ -53,26 +58,27 @@ export const ThirdPartyAuthForm = () => { } return ( -
- +
+
+ Third Party Auth + + Use third-party authentication (TPA) systems based on JWTs to access your project. +
+ Billing is based on the number of monthly active users (MAUs) requesting your API + throughout the billing period (50 included then you'll be charged{' '} + $0.00325 + per MAU). +
+
+
+ + {integrations.length !== 0 && ( - ) : null - } - docsUrl="https://supabase.com/docs/guides/auth/third-party/overview" - /> -
- - Billing is based on the number of monthly active users (MAUs) requesting your API - throughout the billing period (50 included then you'll be charged{' '} - - $0.00325 - per MAU). + )} +
+ {isLoading && (
{ {`Are you sure you want to delete the ${getIntegrationTypeLabel(getIntegrationType(selectedIntegrationForDeletion))} integration?`}

-
+ ) } diff --git a/apps/studio/components/layouts/AuthLayout/AuthProvidersLayout.tsx b/apps/studio/components/layouts/AuthLayout/AuthProvidersLayout.tsx new file mode 100644 index 00000000000..2f68a3181ce --- /dev/null +++ b/apps/studio/components/layouts/AuthLayout/AuthProvidersLayout.tsx @@ -0,0 +1,38 @@ +import { ReactNode } from 'react' +import DefaultLayout from 'components/layouts/DefaultLayout' +import AuthLayout from './AuthLayout' +import { PageLayout } from 'components/layouts/PageLayout' + +interface AuthProvidersLayoutProps { + children: ReactNode + projectRef: string +} + +const AuthProvidersLayout = ({ children, projectRef }: AuthProvidersLayoutProps) => { + const navItems = [ + { + label: 'Supabase Auth', + href: `/project/${projectRef}/auth/providers`, + }, + { + label: 'Third Party Auth', + href: `/project/${projectRef}/auth/third-party`, + }, + ] + + return ( + + + + {children} + + + + ) +} + +export default AuthProvidersLayout diff --git a/apps/studio/components/layouts/PageLayout/Breadcrumbs.tsx b/apps/studio/components/layouts/PageLayout/Breadcrumbs.tsx deleted file mode 100644 index 7570d4c9963..00000000000 --- a/apps/studio/components/layouts/PageLayout/Breadcrumbs.tsx +++ /dev/null @@ -1,39 +0,0 @@ -import Link from 'next/link' -import { ChevronRight } from 'lucide-react' -import { cn } from 'ui' - -export interface BreadcrumbItem { - label: string - href?: string - onClick?: () => void -} - -interface BreadcrumbsProps { - items: BreadcrumbItem[] - className?: string -} - -const Breadcrumbs = ({ items, className }: BreadcrumbsProps) => { - return ( -
- {items.map((item, index) => ( -
- {index > 0 && } - {item.href ? ( - - {item.label} - - ) : item.onClick ? ( - - ) : ( - {item.label} - )} -
- ))} -
- ) -} - -export default Breadcrumbs diff --git a/apps/studio/components/layouts/PageLayout/PageContainer.tsx b/apps/studio/components/layouts/PageLayout/PageContainer.tsx deleted file mode 100644 index 6612061f8d0..00000000000 --- a/apps/studio/components/layouts/PageLayout/PageContainer.tsx +++ /dev/null @@ -1,16 +0,0 @@ -import { ReactNode } from 'react' - -import { cn } from 'ui' -import { PAGE_SIZE_CLASSES, type PageSize } from 'ui/src/lib/constants' - -interface PageContainerProps { - children?: ReactNode - className?: string - size?: PageSize -} - -const PageContainer = ({ children, className, size = 'default' }: PageContainerProps) => { - return
{children}
-} - -export default PageContainer diff --git a/apps/studio/components/layouts/PageLayout/PageHeader.tsx b/apps/studio/components/layouts/PageLayout/PageHeader.tsx index 706f106d578..63d5ecbccc0 100644 --- a/apps/studio/components/layouts/PageLayout/PageHeader.tsx +++ b/apps/studio/components/layouts/PageLayout/PageHeader.tsx @@ -1,4 +1,5 @@ import { useParams } from 'common' +import { useRouter } from 'next/router' import { Fragment, ReactNode } from 'react' import { cn } from 'ui' import { @@ -36,14 +37,17 @@ export const PageHeader = ({ }: PageHeaderProps) => { const { ref } = useParams() + const displayBreadcrumbs = isCompact && title ? [...breadcrumbs, { label: title }] : breadcrumbs + return (
- {(breadcrumbs.length > 0 || (isCompact && (title || primaryActions || secondaryActions))) && ( + {(displayBreadcrumbs.length > 0 || + (isCompact && (title || primaryActions || secondaryActions))) && (
- {breadcrumbs.length > 0 ? ( + {displayBreadcrumbs.length > 0 ? ( - {breadcrumbs.map((item, index) => ( + {displayBreadcrumbs.map((item, index) => ( {item.href ? ( @@ -54,7 +58,7 @@ export const PageHeader = ({ {item.label} )} - {index < breadcrumbs.length - 1 && } + {index < displayBreadcrumbs.length - 1 && } ))} diff --git a/apps/studio/components/layouts/PageLayout/PageLayout.tsx b/apps/studio/components/layouts/PageLayout/PageLayout.tsx index 21348d4a0cf..fdde379ab95 100644 --- a/apps/studio/components/layouts/PageLayout/PageLayout.tsx +++ b/apps/studio/components/layouts/PageLayout/PageLayout.tsx @@ -4,8 +4,8 @@ import { ReactNode } from 'react' import { useParams } from 'common' import { Button, cn, NavMenu, NavMenuItem } from 'ui' -import { PAGE_SIZE_CLASSES, type PageSize } from 'ui/src/lib/constants' import { PageHeader } from '.' +import { ScaffoldContainer } from '../Scaffold' export interface NavigationItem { id?: string @@ -28,7 +28,7 @@ interface PageLayoutProps { secondaryActions?: ReactNode navigationItems?: NavigationItem[] className?: string - size?: PageSize + size?: 'default' | 'full' isCompact?: boolean } @@ -69,15 +69,14 @@ const PageLayout = ({ isCompact = false, }: PageLayoutProps) => { const router = useRouter() - const { ref } = useParams() return (
-
0 && ( {navigationItems.map((item) => ( - + {item.href ? ( {item.icon && {item.icon}} {item.label} ) : ( - @@ -120,10 +126,10 @@ const PageLayout = ({ ))} )} -
+ {/* Content section */} -
{children}
+ {children}
) } diff --git a/apps/studio/components/layouts/PageLayout/PageNavigation.tsx b/apps/studio/components/layouts/PageLayout/PageNavigation.tsx deleted file mode 100644 index ce8b64aff93..00000000000 --- a/apps/studio/components/layouts/PageLayout/PageNavigation.tsx +++ /dev/null @@ -1,33 +0,0 @@ -import Link from 'next/link' -import { useCurrentPath } from 'hooks/misc/useCurrentPath' -import { cn } from 'ui' -import { NavMenu, NavMenuItem } from 'ui' - -export interface NavigationItem { - label: string - href: string -} - -interface PageNavigationProps { - items: NavigationItem[] - className?: string -} - -const PageNavigation = ({ items, className }: PageNavigationProps) => { - const currentPath = useCurrentPath() - - return ( - - {items.map((item) => ( - - {item.label} - - ))} - - ) -} - -export default PageNavigation diff --git a/apps/studio/components/layouts/PageLayout/SectionHeader.tsx b/apps/studio/components/layouts/PageLayout/SectionHeader.tsx deleted file mode 100644 index 372f46198be..00000000000 --- a/apps/studio/components/layouts/PageLayout/SectionHeader.tsx +++ /dev/null @@ -1,23 +0,0 @@ -import React from 'react' -import { cn } from 'ui' - -interface SectionHeaderProps { - title?: string - subtitle?: string - actions?: React.ReactNode - className?: string -} - -const SectionHeader = ({ title, subtitle, actions, className }: SectionHeaderProps) => { - return ( -
-
- {title &&

{title}

} - {subtitle &&

{subtitle}

} -
- {actions &&
{actions}
} -
- ) -} - -export default SectionHeader diff --git a/apps/studio/components/layouts/PageLayout/index.ts b/apps/studio/components/layouts/PageLayout/index.ts index 2b8a403917d..f88a3a8bc48 100644 --- a/apps/studio/components/layouts/PageLayout/index.ts +++ b/apps/studio/components/layouts/PageLayout/index.ts @@ -1,9 +1,4 @@ export { default as PageLayout } from './PageLayout' export { default as PageHeader } from './PageHeader' -export { default as PageContainer } from './PageContainer' -export { default as SectionHeader } from './SectionHeader' -export { default as PageNavigation } from './PageNavigation' -export { default as Breadcrumbs } from './Breadcrumbs' export type { NavigationItem } from './PageLayout' -export type { BreadcrumbItem } from './Breadcrumbs' diff --git a/apps/studio/components/layouts/Scaffold.tsx b/apps/studio/components/layouts/Scaffold.tsx index 61a11f361c6..1215a3be0fe 100644 --- a/apps/studio/components/layouts/Scaffold.tsx +++ b/apps/studio/components/layouts/Scaffold.tsx @@ -59,13 +59,22 @@ const ScaffoldDivider = React.forwardRef>( - ({ className, ...props }, ref) => { +interface ScaffoldSectionProps extends React.HTMLAttributes { + isFullWidth?: boolean + topPadding?: boolean +} + +const ScaffoldSection = React.forwardRef( + ({ className, isFullWidth, topPadding, ...props }, ref) => { return (
) } @@ -145,6 +154,20 @@ const ScaffoldContainerLegacy = React.forwardRef< ) }) +const ScaffoldSectionTitle = React.forwardRef< + HTMLHeadingElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => { + return

+}) + +const ScaffoldSectionDescription = React.forwardRef< + HTMLParagraphElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => { + return

+}) + ScaffoldHeader.displayName = 'ScaffoldHeader' ScaffoldTitle.displayName = 'ScaffoldTitle' ScaffoldDescription.displayName = 'ScaffoldDescription' @@ -158,6 +181,8 @@ ScaffoldFilterAndContent.displayName = 'ScaffoldFilterAndContent' ScaffoldActionsContainer.displayName = 'ScaffoldActionsContainer' ScaffoldActionsGroup.displayName = 'ScaffoldActionsGroup' ScaffoldContainerLegacy.displayName = 'ScaffoldContainerLegacy' +ScaffoldSectionTitle.displayName = 'ScaffoldSectionTitle' +ScaffoldSectionDescription.displayName = 'ScaffoldSectionDescription' export { ScaffoldHeader, @@ -169,6 +194,8 @@ export { ScaffoldColumn, ScaffoldSectionDetail, ScaffoldSectionContent, + ScaffoldSectionTitle, + ScaffoldSectionDescription, ScaffoldFilterAndContent, ScaffoldActionsContainer, ScaffoldActionsGroup, diff --git a/apps/studio/pages/project/[ref]/auth/providers.tsx b/apps/studio/pages/project/[ref]/auth/providers.tsx index c80eaffb7a9..8f384f66b41 100644 --- a/apps/studio/pages/project/[ref]/auth/providers.tsx +++ b/apps/studio/pages/project/[ref]/auth/providers.tsx @@ -1,12 +1,13 @@ import { PermissionAction } from '@supabase/shared-types/out/constants' import { AuthProvidersForm, BasicAuthSettingsForm } from 'components/interfaces/Auth' -import AuthLayout from 'components/layouts/AuthLayout/AuthLayout' -import DefaultLayout from 'components/layouts/DefaultLayout' -import { PageContainer, PageLayout } from 'components/layouts/PageLayout' +import AuthProvidersLayout from 'components/layouts/AuthLayout/AuthProvidersLayout' import NoPermission from 'components/ui/NoPermission' import { useCheckPermissions, usePermissionsLoaded } from 'hooks/misc/useCheckPermissions' +import { useParams } from 'common' import type { NextPageWithLayout } from 'types' +import { ScaffoldContainer } from 'components/layouts/Scaffold' +import { useRouter } from 'next/router' const ProvidersPage: NextPageWithLayout = () => { const canReadAuthSettings = useCheckPermissions(PermissionAction.READ, 'custom_config_gotrue') @@ -17,38 +18,16 @@ const ProvidersPage: NextPageWithLayout = () => { } return ( - + - + ) } ProvidersPage.getLayout = (page) => { - const navigationItems = [ - { - label: 'Supabase Auth', - href: `/project/[ref]/auth/providers`, - }, - { - label: 'Third Party Auth', - href: `/project/[ref]/auth/third-party`, - }, - ] - - return ( - - - - {page} - - - - ) + const { ref: projectRef } = useRouter().query + return {page} } export default ProvidersPage diff --git a/apps/studio/pages/project/[ref]/auth/third-party.tsx b/apps/studio/pages/project/[ref]/auth/third-party.tsx index f48b3eabf6a..9feadf08af7 100644 --- a/apps/studio/pages/project/[ref]/auth/third-party.tsx +++ b/apps/studio/pages/project/[ref]/auth/third-party.tsx @@ -1,79 +1,31 @@ import { PermissionAction } from '@supabase/shared-types/out/constants' import { ThirdPartyAuthForm } from 'components/interfaces/Auth' -import AuthLayout from 'components/layouts/AuthLayout/AuthLayout' -import { useCheckPermissions, usePermissionsLoaded } from 'hooks/misc/useCheckPermissions' -import { useParams } from 'common' -import { useCurrentPath } from 'hooks/misc/useCurrentPath' -import Link from 'next/link' -import { NavMenu, NavMenuItem } from 'ui' -import { - ScaffoldContainer, - ScaffoldDescription, - ScaffoldDivider, - ScaffoldHeader, - ScaffoldTitle, -} from 'components/layouts/Scaffold' +import AuthProvidersLayout from 'components/layouts/AuthLayout/AuthProvidersLayout' import NoPermission from 'components/ui/NoPermission' +import { useCheckPermissions, usePermissionsLoaded } from 'hooks/misc/useCheckPermissions' import type { NextPageWithLayout } from 'types' -import DefaultLayout from 'components/layouts/DefaultLayout' +import { ScaffoldContainer } from 'components/layouts/Scaffold' +import { useRouter } from 'next/router' -const PageLayout: NextPageWithLayout = () => { +const ThirdPartyPage: NextPageWithLayout = () => { const canReadAuthSettings = useCheckPermissions(PermissionAction.READ, 'custom_config_gotrue') const isPermissionsLoaded = usePermissionsLoaded() - const { ref } = useParams() - const currentPath = useCurrentPath() - - const navMenuItems = [ - { - label: 'Supabase auth', - href: `/project/${ref}/auth/providers`, - }, - { - label: 'Third Party auth', - href: `/project/${ref}/auth/third-party`, - }, - ] if (isPermissionsLoaded && !canReadAuthSettings) { return } return ( - <> - - - Sign in / up - - Configure authentication providers and login methods for your users - - - {navMenuItems.map((item) => ( - - {item.label} - - ))} - - - - - - - - - - + + + ) } -PageLayout.getLayout = (page) => { - return ( - - {page} - - ) +ThirdPartyPage.getLayout = (page) => { + const { ref: projectRef } = useRouter().query + return {page} } -export default PageLayout + +export default ThirdPartyPage