diff --git a/apps/studio/components/interfaces/App/FeaturePreview/FeaturePreviewContext.tsx b/apps/studio/components/interfaces/App/FeaturePreview/FeaturePreviewContext.tsx index 557c0e1327e..03691172a71 100644 --- a/apps/studio/components/interfaces/App/FeaturePreview/FeaturePreviewContext.tsx +++ b/apps/studio/components/interfaces/App/FeaturePreview/FeaturePreviewContext.tsx @@ -13,6 +13,7 @@ import { } from 'react' import { useFeaturePreviews } from './useFeaturePreviews' +import { useLocalStorageQuery } from '@/hooks/misc/useLocalStorage' import { IS_PLATFORM } from '@/lib/constants' import { EMPTY_OBJ } from '@/lib/void' @@ -152,9 +153,18 @@ export const useIsMarketplaceEnabled = () => { } export const useIsDatabaseConnectionsEnabled = () => { - const { flags } = useFeaturePreviewContext() - const isDatabaseConnectionsEnabled = useFlag('topForPostgres') - return isDatabaseConnectionsEnabled && flags[LOCAL_STORAGE_KEYS.UI_PREVIEW_DATABASE_CONNECTIONS] + const { flags, isInitialized } = useFeaturePreviewContext() + const [localStorageFlag] = useLocalStorageQuery( + LOCAL_STORAGE_KEYS.UI_PREVIEW_DATABASE_CONNECTIONS, + null + ) + const previouslyToggled = localStorageFlag !== null + + return { + enabled: flags[LOCAL_STORAGE_KEYS.UI_PREVIEW_DATABASE_CONNECTIONS], + isInitialized, + previouslyToggled, + } } export const useFeaturePreviewModal = () => { diff --git a/apps/studio/components/interfaces/App/FeaturePreview/useFeaturePreviews.ts b/apps/studio/components/interfaces/App/FeaturePreview/useFeaturePreviews.ts index 3587e6b175b..a30be45c941 100644 --- a/apps/studio/components/interfaces/App/FeaturePreview/useFeaturePreviews.ts +++ b/apps/studio/components/interfaces/App/FeaturePreview/useFeaturePreviews.ts @@ -133,8 +133,8 @@ export const useFeaturePreviews = (): FeaturePreview[] => { discussionsUrl: 'https://github.com/orgs/supabase/discussions/48639', isNew: true, isPlatformOnly: false, - isDefaultOptIn: false, - enabled: isDatabaseConnectionsEnabled, + isDefaultOptIn: isDatabaseConnectionsEnabled, + enabled: true, getRoute: (ref?: string) => `/project/${ref}/observability/connections`, bannerId: 'database-connections-banner', }, diff --git a/apps/studio/components/layouts/ObservabilityLayout/ObservabilityLayout.tsx b/apps/studio/components/layouts/ObservabilityLayout/ObservabilityLayout.tsx index c350faa2332..acdd6ac0b98 100644 --- a/apps/studio/components/layouts/ObservabilityLayout/ObservabilityLayout.tsx +++ b/apps/studio/components/layouts/ObservabilityLayout/ObservabilityLayout.tsx @@ -1,4 +1,4 @@ -import { LOCAL_STORAGE_KEYS, useFeatureFlags, useParams } from 'common' +import { LOCAL_STORAGE_KEYS, useParams } from 'common' import { usePathname } from 'next/navigation' import { PropsWithChildren, useEffect, useRef } from 'react' @@ -24,7 +24,6 @@ const ObservabilityLayoutContent = ({ }: PropsWithChildren) => { const { ref } = useParams() const pathname = usePathname() - const { hasLoaded } = useFeatureFlags() const { addBanner, dismissBanner } = useBannerStack() const { isIndexAdvisorAvailable, isIndexAdvisorEnabled } = useIndexAdvisorStatus() @@ -33,7 +32,7 @@ const ObservabilityLayoutContent = ({ false ) - const isDatabaseConnectionsEnabled = useIsDatabaseConnectionsEnabled() + const { isInitialized, previouslyToggled } = useIsDatabaseConnectionsEnabled() const [isDatabaseConnectionsBannerDismissed, , { isSuccess: isLocalStorageReady }] = useLocalStorageQuery(LOCAL_STORAGE_KEYS.DATABASE_CONNECTIONS_BANNER_DISMISSED(ref ?? ''), false) @@ -42,10 +41,10 @@ const ObservabilityLayoutContent = ({ useEffect(() => { if ( - !hasLoaded || + !isInitialized || !isLocalStorageReady || isDatabaseConnectionsBannerDismissed || - isDatabaseConnectionsEnabled + previouslyToggled ) return @@ -56,11 +55,11 @@ const ObservabilityLayoutContent = ({ content: , }) }, [ - hasLoaded, addBanner, dismissBanner, + isInitialized, isDatabaseConnectionsBannerDismissed, - isDatabaseConnectionsEnabled, + previouslyToggled, isLocalStorageReady, ]) diff --git a/apps/studio/components/layouts/ObservabilityLayout/ObservabilityMenu.utils.test.tsx b/apps/studio/components/layouts/ObservabilityLayout/ObservabilityMenu.utils.test.tsx index f63bdd9f116..a61aa7a3b8e 100644 --- a/apps/studio/components/layouts/ObservabilityLayout/ObservabilityMenu.utils.test.tsx +++ b/apps/studio/components/layouts/ObservabilityLayout/ObservabilityMenu.utils.test.tsx @@ -1,4 +1,3 @@ -import { renderHook } from '@testing-library/react' import { useFlag, useParams } from 'common' import { beforeEach, describe, expect, it, vi } from 'vitest' @@ -9,6 +8,7 @@ import { import { useSupamonitorStatus } from '@/components/interfaces/QueryPerformance/hooks/useSupamonitorStatus' import { useContentQuery } from '@/data/content/content-query' import { useIsFeatureEnabled } from '@/hooks/misc/useIsFeatureEnabled' +import { customRenderHook as renderHook } from '@/tests/lib/custom-render' import { routerMock } from '@/tests/lib/route-mock' const { REF, mockIsPlatform } = vi.hoisted(() => ({ diff --git a/apps/studio/components/layouts/ObservabilityLayout/ObservabilityMenu.utils.tsx b/apps/studio/components/layouts/ObservabilityLayout/ObservabilityMenu.utils.tsx index 44ff90b6442..7301943bd0a 100644 --- a/apps/studio/components/layouts/ObservabilityLayout/ObservabilityMenu.utils.tsx +++ b/apps/studio/components/layouts/ObservabilityLayout/ObservabilityMenu.utils.tsx @@ -49,7 +49,7 @@ export const useGenerateObservabilityMenu = () => { const { isSupamonitorEnabled } = useSupamonitorStatus() const showOverview = useFlag('observabilityOverview') - const isDatabaseConnectionsEnabled = useIsDatabaseConnectionsEnabled() + const { enabled: isDatabaseConnectionsEnabled } = useIsDatabaseConnectionsEnabled() const storageSupported = useIsFeatureEnabled('project_storage:all') const baseUrl = `/project/${ref}/observability` diff --git a/apps/studio/components/layouts/SQLEditorLayout/SQLEditorMenu.tsx b/apps/studio/components/layouts/SQLEditorLayout/SQLEditorMenu.tsx index 3c3d66e8355..6938b6ce9f8 100644 --- a/apps/studio/components/layouts/SQLEditorLayout/SQLEditorMenu.tsx +++ b/apps/studio/components/layouts/SQLEditorLayout/SQLEditorMenu.tsx @@ -41,7 +41,7 @@ export const SQLEditorMenu = () => { const { data: project } = useSelectedProjectQuery() const snapV2 = useSqlEditorV2StateSnapshot() - const isDatabaseConnectionsEnabled = useIsDatabaseConnectionsEnabled() + const { enabled: isDatabaseConnectionsEnabled } = useIsDatabaseConnectionsEnabled() const sqlEditorLogsSource = useFlag('sqlEditorLogsSource') const otelLegacyLogs = useFlag('otelLegacyLogs') const canCreateLogsSnippet = sqlEditorLogsSource && otelLegacyLogs diff --git a/apps/studio/components/ui/BannerStack/Banners/BannerDatabaseConnections.tsx b/apps/studio/components/ui/BannerStack/Banners/BannerDatabaseConnections.tsx index 4ca36cb90f9..c80f67615ea 100644 --- a/apps/studio/components/ui/BannerStack/Banners/BannerDatabaseConnections.tsx +++ b/apps/studio/components/ui/BannerStack/Banners/BannerDatabaseConnections.tsx @@ -1,10 +1,14 @@ import { LOCAL_STORAGE_KEYS } from 'common' import { useParams } from 'common/hooks' +import Link from 'next/link' import { Badge, Button, WarningIcon } from 'ui' import { BannerCard } from '../BannerCard' import { useBannerStack } from '../BannerStackProvider' -import { useFeaturePreviewModal } from '@/components/interfaces/App/FeaturePreview/FeaturePreviewContext' +import { + useFeaturePreviewModal, + useIsDatabaseConnectionsEnabled, +} from '@/components/interfaces/App/FeaturePreview/FeaturePreviewContext' import { useLocalStorageQuery } from '@/hooks/misc/useLocalStorage' import { useTrack } from '@/lib/telemetry/track' @@ -19,6 +23,8 @@ export const BannerDatabaseConnections = () => { false ) + const { enabled: isEnabled } = useIsDatabaseConnectionsEnabled() + return ( { @@ -72,16 +78,33 @@ export const BannerDatabaseConnections = () => {

- + {isEnabled ? ( + + ) : ( + + )}
diff --git a/apps/studio/pages/project/[ref]/observability/connections.tsx b/apps/studio/pages/project/[ref]/observability/connections.tsx index a49cb5178cc..10cc40a4caf 100644 --- a/apps/studio/pages/project/[ref]/observability/connections.tsx +++ b/apps/studio/pages/project/[ref]/observability/connections.tsx @@ -33,7 +33,7 @@ export const DatabaseConnections: NextPageWithLayout = () => { const { data: project } = useSelectedProjectQuery() const { openSidebar } = useSidebarManagerSnapshot() const aiSnap = useAiAssistantStateSnapshot() - const isDatabaseConnectionsEnabled = useIsDatabaseConnectionsEnabled() + const { enabled: isDatabaseConnectionsEnabled } = useIsDatabaseConnectionsEnabled() const { selectFeaturePreview } = useFeaturePreviewModal() const [live, setLive] = useState(true) diff --git a/apps/studio/tests/lib/custom-render.tsx b/apps/studio/tests/lib/custom-render.tsx index f182c109a3e..d23ace9f00c 100644 --- a/apps/studio/tests/lib/custom-render.tsx +++ b/apps/studio/tests/lib/custom-render.tsx @@ -66,7 +66,7 @@ export const customRender = (component: React.ReactElement, renderOptions?: Cust }) } -export const customRenderHook = (hook: () => any, renderOptions?: CustomRenderOpts) => { +export const customRenderHook = (hook: () => T, renderOptions?: CustomRenderOpts) => { return renderHook(hook, { wrapper: ({ children }) => CustomWrapper({