From 69b42adfac072fdb800855d7040907bfc64894bd Mon Sep 17 00:00:00 2001 From: Saxon Fletcher Date: Thu, 29 Jan 2026 14:50:46 +1000 Subject: [PATCH] bring back old connect --- .../App/CommandMenu/CommandMenu.tsx | 2 +- .../components/interfaces/Connect/Connect.tsx | 67 ++++--------- .../Connect.Commands.tsx | 3 +- .../ConnectButton/ConnectButton.tsx | 95 +++++++++++++++++++ .../ConnectSheet/Connect.Commands.tsx | 60 ------------ .../interfaces/ConnectSheet/ConnectSheet.tsx | 77 +++------------ .../Home/NewProjectPanel/APIKeys.tsx | 4 +- .../GettingStarted/GettingStartedSection.tsx | 4 +- .../LayoutHeader/LayoutHeader.tsx | 4 +- 9 files changed, 135 insertions(+), 181 deletions(-) rename apps/studio/components/interfaces/{Connect => ConnectButton}/Connect.Commands.tsx (93%) create mode 100644 apps/studio/components/interfaces/ConnectButton/ConnectButton.tsx delete mode 100644 apps/studio/components/interfaces/ConnectSheet/Connect.Commands.tsx diff --git a/apps/studio/components/interfaces/App/CommandMenu/CommandMenu.tsx b/apps/studio/components/interfaces/App/CommandMenu/CommandMenu.tsx index a19127a67b3..c1e1daa8b65 100644 --- a/apps/studio/components/interfaces/App/CommandMenu/CommandMenu.tsx +++ b/apps/studio/components/interfaces/App/CommandMenu/CommandMenu.tsx @@ -1,4 +1,4 @@ -import { useConnectCommands } from '@/components/interfaces/ConnectSheet/Connect.Commands' +import { useConnectCommands } from '@/components/interfaces/ConnectButton/Connect.Commands' import { IS_PLATFORM } from 'common' import { useBranchCommands } from 'components/interfaces/BranchManagement/Branch.Commands' import { diff --git a/apps/studio/components/interfaces/Connect/Connect.tsx b/apps/studio/components/interfaces/Connect/Connect.tsx index 0221bbf7f09..b71285793b2 100644 --- a/apps/studio/components/interfaces/Connect/Connect.tsx +++ b/apps/studio/components/interfaces/Connect/Connect.tsx @@ -1,20 +1,18 @@ import { PermissionAction } from '@supabase/shared-types/out/constants' import { IS_PLATFORM, useParams } from 'common' -import { ExternalLink, Plug } from 'lucide-react' -import { parseAsBoolean, parseAsString, useQueryState } from 'nuqs' +import { ExternalLink } from 'lucide-react' +import { parseAsString, useQueryState } from 'nuqs' import { useEffect, useMemo, useState } from 'react' import { ApiKeysTabContent } from 'components/interfaces/Connect/ApiKeysTabContent' import { DatabaseConnectionString } from 'components/interfaces/Connect/DatabaseConnectionString' import { McpTabContent } from 'components/interfaces/Connect/McpTabContent' -import { ButtonTooltip } from 'components/ui/ButtonTooltip' import Panel from 'components/ui/Panel' import { getKeys, useAPIKeysQuery } from 'data/api-keys/api-keys-query' import { useProjectSettingsV2Query } from 'data/config/project-settings-v2-query' import { useAsyncCheckPermissions } from 'hooks/misc/useCheckPermissions' import { useIsFeatureEnabled } from 'hooks/misc/useIsFeatureEnabled' -import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' -import { BASE_PATH, PROJECT_STATUS } from 'lib/constants' +import { BASE_PATH } from 'lib/constants' import { useRouter } from 'next/router' import { Button, @@ -26,7 +24,6 @@ import { DialogHeader, DialogSectionSeparator, DialogTitle, - DialogTrigger, TabsContent_Shadcn_, TabsList_Shadcn_, TabsTrigger_Shadcn_, @@ -39,11 +36,14 @@ import { ConnectDropdown } from './ConnectDropdown' import { ConnectTabContent } from './ConnectTabContent' import Link from 'next/link' -export const Connect = () => { +interface ConnectProps { + open: boolean + onOpenChange: (open: boolean) => void +} + +export const Connect = ({ open, onOpenChange }: ConnectProps) => { const router = useRouter() const { ref: projectRef } = useParams() - const { data: selectedProject } = useSelectedProjectQuery() - const isActiveHealthy = selectedProject?.status === PROJECT_STATUS.ACTIVE_HEALTHY const { projectConnectionShowAppFrameworks: showAppFrameworks, @@ -68,11 +68,6 @@ export const Connect = () => { return true }) - const [showConnect, setShowConnect] = useQueryState( - 'showConnect', - parseAsBoolean.withDefault(false) - ) - // helper to get the connection type object function getConnectionObjectForTab(tab: string | null) { switch (tab) { @@ -106,7 +101,7 @@ export const Connect = () => { ?.children.find((child) => child.key === selectedChild)?.children[0]?.key || '' ) - const { data: settings } = useProjectSettingsV2Query({ projectRef }, { enabled: showConnect }) + const { data: settings } = useProjectSettingsV2Query({ projectRef }, { enabled: open }) const { can: canReadAPIKeys } = useAsyncCheckPermissions( PermissionAction.READ, 'service_api_keys' @@ -258,18 +253,16 @@ export const Connect = () => { setQueryMethod(null) } - const handleDialogChange = (open: boolean) => { - if (!open) { - setShowConnect(null) + const handleDialogChange = (nextOpen: boolean) => { + if (!nextOpen) { setTab(null) resetQueryStates() - } else { - setShowConnect(open) } + onOpenChange(nextOpen) } useEffect(() => { - if (!showConnect) return + if (!open) return const noConnectTabInUrl = typeof router.query.connectTab === 'undefined' const hasQuery = queryFramework || queryUsing || queryWith const inferred = inferConnectTabFromParentKey(queryFramework) @@ -280,10 +273,10 @@ export const Connect = () => { if (inferred === 'mobiles') setConnectionObject(MOBILES) if (inferred === 'orms') setConnectionObject(ORMS) } - }, [showConnect, router.query.connectTab, queryFramework, queryUsing, queryWith, setTab]) + }, [open, router.query.connectTab, queryFramework, queryUsing, queryWith, setTab]) useEffect(() => { - if (!showConnect) return + if (!open) return const newConnectionObject = getConnectionObjectForTab(tab) setConnectionObject(newConnectionObject) @@ -312,7 +305,7 @@ export const Connect = () => { if (grandchild?.key !== queryWith) setQueryWith(grandchild?.key ?? null) } }, [ - showConnect, + open, tab, queryFramework, setQueryFramework, @@ -322,32 +315,8 @@ export const Connect = () => { setQueryWith, ]) - if (!isActiveHealthy) { - return ( - } - tooltip={{ - content: { - side: 'bottom', - text: 'Project is currently not active and cannot be connected', - }, - }} - > - Connect - - ) - } - return ( - - - - + diff --git a/apps/studio/components/interfaces/Connect/Connect.Commands.tsx b/apps/studio/components/interfaces/ConnectButton/Connect.Commands.tsx similarity index 93% rename from apps/studio/components/interfaces/Connect/Connect.Commands.tsx rename to apps/studio/components/interfaces/ConnectButton/Connect.Commands.tsx index 6a370317080..d45876c90ef 100644 --- a/apps/studio/components/interfaces/Connect/Connect.Commands.tsx +++ b/apps/studio/components/interfaces/ConnectButton/Connect.Commands.tsx @@ -1,5 +1,6 @@ import { Plug } from 'lucide-react' import { useRouter } from 'next/router' + import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { PROJECT_STATUS } from 'lib/constants' import type { ICommand } from 'ui-patterns/CommandMenu' @@ -20,7 +21,6 @@ export function useConnectCommands() { id: 'connect-to-project', name: 'Connect to your project', action: () => { - // Open the Connect dialog by setting the showConnect query param router.push( { pathname: router.pathname, @@ -37,7 +37,6 @@ export function useConnectCommands() { id: 'connect-mcp', name: 'Connect via MCP', action: () => { - // Open the Connect dialog with MCP tab router.push( { pathname: router.pathname, diff --git a/apps/studio/components/interfaces/ConnectButton/ConnectButton.tsx b/apps/studio/components/interfaces/ConnectButton/ConnectButton.tsx new file mode 100644 index 00000000000..62e855b7c19 --- /dev/null +++ b/apps/studio/components/interfaces/ConnectButton/ConnectButton.tsx @@ -0,0 +1,95 @@ +import { Plug } from 'lucide-react' +import { ComponentProps, useEffect, useState } from 'react' +import { parseAsBoolean, parseAsString, useQueryState } from 'nuqs' + +import { Connect } from 'components/interfaces/Connect/Connect' +import { ConnectSheet } from 'components/interfaces/ConnectSheet/ConnectSheet' +import { ButtonTooltip } from 'components/ui/ButtonTooltip' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' +import { usePHFlag } from 'hooks/ui/useFlag' +import { PROJECT_STATUS } from 'lib/constants' +import { Button } from 'ui' + +interface ConnectButtonProps { + buttonType?: ComponentProps['type'] + renderDialog?: boolean +} + +export const ConnectButton = ({ + buttonType = 'default', + renderDialog = true, +}: ConnectButtonProps) => { + const connectSheetFlag = usePHFlag('connectSheet') + const isConnectSheetEnabled = connectSheetFlag === true || connectSheetFlag === 'variation' + + const { data: selectedProject } = useSelectedProjectQuery() + const isActiveHealthy = selectedProject?.status === PROJECT_STATUS.ACTIVE_HEALTHY + + const [showConnect, setShowConnect] = useQueryState( + 'showConnect', + parseAsBoolean.withDefault(false) + ) + const [connectTab, setConnectTab] = useQueryState('connectTab', parseAsString) + + const [connectMode, setConnectMode] = useState<'dialog' | 'sheet'>( + isConnectSheetEnabled ? 'sheet' : 'dialog' + ) + + useEffect(() => { + if (showConnect) return + setConnectMode(isConnectSheetEnabled ? 'sheet' : 'dialog') + }, [isConnectSheetEnabled, showConnect]) + + const handleOpenChange = (open: boolean) => { + if (!open) { + setShowConnect(null) + setConnectTab(null) + return + } + + setShowConnect(true) + } + + if (!isActiveHealthy) { + return ( + } + tooltip={{ + content: { + side: 'bottom', + text: 'Project is currently not active and cannot be connected', + }, + }} + > + Connect + + ) + } + + return ( + <> + + {renderDialog ? ( + connectMode === 'sheet' ? ( + + ) : ( + + ) + ) : null} + + ) +} diff --git a/apps/studio/components/interfaces/ConnectSheet/Connect.Commands.tsx b/apps/studio/components/interfaces/ConnectSheet/Connect.Commands.tsx deleted file mode 100644 index 6a370317080..00000000000 --- a/apps/studio/components/interfaces/ConnectSheet/Connect.Commands.tsx +++ /dev/null @@ -1,60 +0,0 @@ -import { Plug } from 'lucide-react' -import { useRouter } from 'next/router' -import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' -import { PROJECT_STATUS } from 'lib/constants' -import type { ICommand } from 'ui-patterns/CommandMenu' -import { useRegisterCommands, useSetCommandMenuOpen } from 'ui-patterns/CommandMenu' -import { COMMAND_MENU_SECTIONS } from 'components/interfaces/App/CommandMenu/CommandMenu.utils' -import { orderCommandSectionsByPriority } from 'components/interfaces/App/CommandMenu/ordering' - -export function useConnectCommands() { - const router = useRouter() - const setIsOpen = useSetCommandMenuOpen() - const { data: selectedProject } = useSelectedProjectQuery() - const isActiveHealthy = selectedProject?.status === PROJECT_STATUS.ACTIVE_HEALTHY - - useRegisterCommands( - COMMAND_MENU_SECTIONS.ACTIONS, - [ - { - id: 'connect-to-project', - name: 'Connect to your project', - action: () => { - // Open the Connect dialog by setting the showConnect query param - router.push( - { - pathname: router.pathname, - query: { ...router.query, showConnect: 'true' }, - }, - undefined, - { shallow: true } - ) - setIsOpen(false) - }, - icon: () => , - }, - { - id: 'connect-mcp', - name: 'Connect via MCP', - action: () => { - // Open the Connect dialog with MCP tab - router.push( - { - pathname: router.pathname, - query: { ...router.query, showConnect: 'true', connectTab: 'mcp' }, - }, - undefined, - { shallow: true } - ) - setIsOpen(false) - }, - icon: () => , - }, - ] as ICommand[], - { - enabled: !!selectedProject && isActiveHealthy, - orderSection: orderCommandSectionsByPriority, - sectionMeta: { priority: 2 }, - } - ) -} diff --git a/apps/studio/components/interfaces/ConnectSheet/ConnectSheet.tsx b/apps/studio/components/interfaces/ConnectSheet/ConnectSheet.tsx index 31a562162c4..4cd03e85fdb 100644 --- a/apps/studio/components/interfaces/ConnectSheet/ConnectSheet.tsx +++ b/apps/studio/components/interfaces/ConnectSheet/ConnectSheet.tsx @@ -1,25 +1,18 @@ import { PermissionAction } from '@supabase/shared-types/out/constants' import { useParams } from 'common' -import { Plug } from 'lucide-react' -import { useRouter } from 'next/router' -import { ComponentProps, useEffect, useMemo, useState } from 'react' +import { useEffect, useMemo } from 'react' -import { ButtonTooltip } from 'components/ui/ButtonTooltip' import { DatabaseSelector } from 'components/ui/DatabaseSelector' import { getKeys, useAPIKeysQuery } from 'data/api-keys/api-keys-query' import { useProjectSettingsV2Query } from 'data/config/project-settings-v2-query' import { useAsyncCheckPermissions } from 'hooks/misc/useCheckPermissions' import { useIsFeatureEnabled } from 'hooks/misc/useIsFeatureEnabled' -import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' -import { PROJECT_STATUS } from 'lib/constants' import { - Button, Sheet, SheetContent, SheetDescription, SheetHeader, SheetTitle, - SheetTrigger, cn } from 'ui' @@ -29,14 +22,12 @@ import { ConnectStepsSection } from './ConnectStepsSection' import { useConnectState } from './useConnectState' interface ConnectSheetProps { - buttonType?: ComponentProps['type'] + open: boolean + onOpenChange: (open: boolean) => void + connectTab?: string | null } -export const ConnectSheet = ({ buttonType = 'default' }: ConnectSheetProps) => { - const router = useRouter() - const { data: selectedProject } = useSelectedProjectQuery() - const isActiveHealthy = selectedProject?.status === PROJECT_STATUS.ACTIVE_HEALTHY - +export const ConnectSheet = ({ open, onOpenChange, connectTab }: ConnectSheetProps) => { const { projectConnectionShowAppFrameworks: showAppFrameworks, projectConnectionShowMobileFrameworks: showMobileFrameworks, @@ -60,8 +51,6 @@ export const ConnectSheet = ({ buttonType = 'default' }: ConnectSheetProps) => { return modes }, [showAppFrameworks, showMobileFrameworks, showOrms]) - const [showConnect, setShowConnect] = useState(false) - const { state, updateField, @@ -82,7 +71,7 @@ export const ConnectSheet = ({ buttonType = 'default' }: ConnectSheetProps) => { const { ref: projectRef } = useParams() const { data: settings } = useProjectSettingsV2Query( { projectRef }, - { enabled: showConnect } + { enabled: open } ) const { can: canReadAPIKeys } = useAsyncCheckPermissions( PermissionAction.READ, @@ -114,61 +103,23 @@ export const ConnectSheet = ({ buttonType = 'default' }: ConnectSheetProps) => { publishableKey?.api_key, ]) - const handleSheetChange = (open: boolean) => { - if (!open && router.query.showConnect === 'true') { - const nextQuery = { ...router.query } - delete nextQuery.showConnect - delete nextQuery.connectTab - router.replace({ pathname: router.pathname, query: nextQuery }, undefined, { shallow: true }) - } - setShowConnect(open) - } - const handleSourceChange = (databaseId: string) => { // Database selection is handled by the DatabaseSelector's internal state // We just need to trigger a re-render of connection strings } useEffect(() => { - if (!router.isReady) return - if (router.query.showConnect === 'true') { - setShowConnect(true) - const connectTab = router.query.connectTab - if (typeof connectTab === 'string') { - if (connectTab === 'mcp') setMode('mcp') - else if (connectTab === 'orms') setMode('orm') - else if (connectTab === 'direct') setMode('direct') - else if (connectTab === 'frameworks' || connectTab === 'mobiles') setMode('framework') - } + if (!open) return + if (typeof connectTab === 'string') { + if (connectTab === 'mcp') setMode('mcp') + else if (connectTab === 'orms') setMode('orm') + else if (connectTab === 'direct') setMode('direct') + else if (connectTab === 'frameworks' || connectTab === 'mobiles') setMode('framework') } - }, [router.isReady, router.query.connectTab, router.query.showConnect, setMode]) - - if (!isActiveHealthy) { - return ( - } - tooltip={{ - content: { - side: 'bottom', - text: 'Project is currently not active and cannot be connected', - }, - }} - > - Connect - - ) - } + }, [connectTab, open, setMode]) return ( - - - - +
diff --git a/apps/studio/components/interfaces/Home/NewProjectPanel/APIKeys.tsx b/apps/studio/components/interfaces/Home/NewProjectPanel/APIKeys.tsx index 3cdc75236f1..d9a2b644c76 100644 --- a/apps/studio/components/interfaces/Home/NewProjectPanel/APIKeys.tsx +++ b/apps/studio/components/interfaces/Home/NewProjectPanel/APIKeys.tsx @@ -2,7 +2,7 @@ import { PermissionAction } from '@supabase/shared-types/out/constants' import { JwtSecretUpdateStatus } from '@supabase/shared-types/out/events' import { Loader } from 'lucide-react' -import { ConnectSheet } from '@/components/interfaces/ConnectSheet/ConnectSheet' +import { ConnectButton } from '@/components/interfaces/ConnectButton/ConnectButton' import { ConnectionIcon } from '@/components/interfaces/ConnectSheet/ConnectionIcon' import { useParams } from 'common' import { AlertError } from 'components/ui/AlertError' @@ -208,7 +208,7 @@ export const APIKeys = () => { Connect to your project from a variety of frameworks, ORMs, an MCP server, or even directly via connection string.

- +
diff --git a/apps/studio/components/interfaces/HomeNew/GettingStarted/GettingStartedSection.tsx b/apps/studio/components/interfaces/HomeNew/GettingStarted/GettingStartedSection.tsx index 7f94d3fce3a..c4585d9dd36 100644 --- a/apps/studio/components/interfaces/HomeNew/GettingStarted/GettingStartedSection.tsx +++ b/apps/studio/components/interfaces/HomeNew/GettingStarted/GettingStartedSection.tsx @@ -1,7 +1,7 @@ import { Code, Table2 } from 'lucide-react' import { useCallback, useMemo, useState } from 'react' -import { ConnectSheet } from '@/components/interfaces/ConnectSheet/ConnectSheet' +import { ConnectButton } from '@/components/interfaces/ConnectButton/ConnectButton' import { useParams } from 'common' import { SIDEBAR_KEYS } from 'components/layouts/ProjectLayout/LayoutSidebar/LayoutSidebarProvider' import { useSendEventMutation } from 'data/telemetry/send-event-mutation' @@ -50,7 +50,7 @@ export function GettingStartedSection({ value, onChange }: GettingStartedSection return [ { label: 'Connect', - component: , + component: , }, ] }, []) diff --git a/apps/studio/components/layouts/ProjectLayout/LayoutHeader/LayoutHeader.tsx b/apps/studio/components/layouts/ProjectLayout/LayoutHeader/LayoutHeader.tsx index a558a4d1865..4e972e16119 100644 --- a/apps/studio/components/layouts/ProjectLayout/LayoutHeader/LayoutHeader.tsx +++ b/apps/studio/components/layouts/ProjectLayout/LayoutHeader/LayoutHeader.tsx @@ -3,7 +3,7 @@ import { ChevronLeft } from 'lucide-react' import Link from 'next/link' import { ReactNode, useMemo } from 'react' -import { ConnectSheet } from '@/components/interfaces/ConnectSheet/ConnectSheet' +import { ConnectButton } from '@/components/interfaces/ConnectButton/ConnectButton' import { LOCAL_STORAGE_KEYS, useParams } from 'common' import { useIsBranching2Enabled } from 'components/interfaces/App/FeaturePreview/FeaturePreviewContext' import { LocalDropdown } from 'components/interfaces/LocalDropdown' @@ -198,7 +198,7 @@ export const LayoutHeader = ({ }} > {IS_PLATFORM && gitlessBranching && } - + )}