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({