Files
supabase/apps/studio/components/layouts/ObservabilityLayout/ObservabilityMenu.utils.tsx
Joshen Lim dfb0603a36 Joshenlim/fe 4063 set up incremental default opt in for database connections (#49132)
## Context

As per PR title - sets up incremental default opt in for the Database
Connections feature preview

Database Connections preview banner should still only show up if it's
never been dismissed before, but the CTA's changed to "Explore" rather
than "Enable" if the user's default opted in

Related discussion here:
https://github.com/orgs/supabase/discussions/48639

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
  * Database Connections preview is now enabled by default.
  * Added clearer handling for preview state and initialization.
* Banner actions open Database Connections when enabled, or the feature
preview when disabled.
* **Bug Fixes**
* Improved banner and menu visibility while preview settings initialize.
* Preserved banner dismissal behavior after a previous preference
change.
* Improved navigation consistency across Database Connections entry
points.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-17 16:11:07 +08:00

216 lines
6.0 KiB
TypeScript

import { useFlag, useParams } from 'common'
import { useRouter } from 'next/router'
import { useMemo } from 'react'
import { useIsDatabaseConnectionsEnabled } from '@/components/interfaces/App/FeaturePreview/FeaturePreviewContext'
import { useSupamonitorStatus } from '@/components/interfaces/QueryPerformance/hooks/useSupamonitorStatus'
import { useContentQuery, type Content, type ContentBase } from '@/data/content/content-query'
import { useIsFeatureEnabled } from '@/hooks/misc/useIsFeatureEnabled'
import { IS_PLATFORM } from '@/lib/constants'
import { SHORTCUT_IDS, type ShortcutId } from '@/state/shortcuts/registry'
import { type Dashboards } from '@/types'
interface ObservabilityMenuItem {
name: string
key: string
url: string
shortcutId?: ShortcutId
}
export interface ObservabilityMenuSection {
title: string
key: string
items: ObservabilityMenuItem[]
}
const usePreservedQueryParams = () => {
const router = useRouter()
// Preserve date range query parameters when navigating
const preservedQueryParams = useMemo(() => {
const { its, ite, isHelper, helperText } = router.query
const params = new URLSearchParams()
if (its && typeof its === 'string') params.set('its', its)
if (ite && typeof ite === 'string') params.set('ite', ite)
if (isHelper && typeof isHelper === 'string') params.set('isHelper', isHelper)
if (helperText && typeof helperText === 'string') params.set('helperText', helperText)
const queryString = params.toString()
return queryString ? `?${queryString}` : ''
}, [router.query])
return preservedQueryParams
}
export const useGenerateObservabilityMenu = () => {
const { ref } = useParams()
const preservedQueryParams = usePreservedQueryParams()
const { isSupamonitorEnabled } = useSupamonitorStatus()
const showOverview = useFlag('observabilityOverview')
const { enabled: isDatabaseConnectionsEnabled } = useIsDatabaseConnectionsEnabled()
const storageSupported = useIsFeatureEnabled('project_storage:all')
const baseUrl = `/project/${ref}/observability`
const generalItems: ObservabilityMenuItem[] = [
...(showOverview
? [
{
name: 'Overview',
key: 'observability',
url: `${baseUrl}${preservedQueryParams}`,
shortcutId: SHORTCUT_IDS.NAV_OBSERVABILITY_OVERVIEW,
},
]
: []),
...(isSupamonitorEnabled
? [
{
name: 'Query Insights',
key: 'query-insights',
url: `${baseUrl}/query-insights${preservedQueryParams}`,
shortcutId: SHORTCUT_IDS.NAV_OBSERVABILITY_QUERY_PERFORMANCE,
},
]
: [
{
name: 'Query Performance',
key: 'query-performance',
url: `${baseUrl}/query-performance${preservedQueryParams}`,
shortcutId: SHORTCUT_IDS.NAV_OBSERVABILITY_QUERY_PERFORMANCE,
},
]),
...(IS_PLATFORM
? [
{
name: 'API Gateway',
key: 'api-overview',
url: `${baseUrl}/api-overview${preservedQueryParams}`,
shortcutId: SHORTCUT_IDS.NAV_OBSERVABILITY_API_GATEWAY,
},
]
: []),
...(isDatabaseConnectionsEnabled
? [
{
name: 'Database Connections',
key: 'connections',
url: `${baseUrl}/connections`,
shortcutId: SHORTCUT_IDS.NAV_OBSERVABILITY_API_GATEWAY,
},
]
: []),
]
const productItems: ObservabilityMenuItem[] = [
{
name: 'Database',
key: 'database',
url: `${baseUrl}/database${preservedQueryParams}`,
shortcutId: SHORTCUT_IDS.NAV_OBSERVABILITY_DATABASE,
},
{
name: 'Data API',
key: 'postgrest',
url: `${baseUrl}/postgrest${preservedQueryParams}`,
shortcutId: SHORTCUT_IDS.NAV_OBSERVABILITY_DATA_API,
},
{
name: 'Auth',
key: 'auth',
url: `${baseUrl}/auth${preservedQueryParams}`,
shortcutId: SHORTCUT_IDS.NAV_OBSERVABILITY_AUTH,
},
{
name: 'Edge Functions',
key: 'edge-functions',
url: `${baseUrl}/edge-functions${preservedQueryParams}`,
shortcutId: SHORTCUT_IDS.NAV_OBSERVABILITY_FUNCTIONS,
},
...(storageSupported
? [
{
name: 'Storage',
key: 'storage',
url: `${baseUrl}/storage${preservedQueryParams}`,
shortcutId: SHORTCUT_IDS.NAV_OBSERVABILITY_STORAGE,
},
]
: []),
{
name: 'Realtime',
key: 'realtime',
url: `${baseUrl}/realtime${preservedQueryParams}`,
shortcutId: SHORTCUT_IDS.NAV_OBSERVABILITY_REALTIME,
},
]
const sections: ObservabilityMenuSection[] = [
{
title: 'GENERAL',
key: 'general-section',
items: generalItems,
},
]
if (IS_PLATFORM) {
sections.push({
title: 'PRODUCT',
key: 'product-section',
items: productItems,
})
}
return sections
}
function isReportContent(c: Content): c is ContentBase & {
type: 'report'
content: Dashboards.Content
} {
return c.type === 'report'
}
export const useGenerateCustomReportsMenu = () => {
const { ref } = useParams()
const preservedQueryParams = usePreservedQueryParams()
const { data: content, isPending: isLoading } = useContentQuery({
projectRef: ref,
type: 'report',
})
function getReportMenuItems() {
if (!content) return []
const reports = content?.content.filter(isReportContent)
const sortedReports = reports?.sort((a, b) => {
if (a.name < b.name) {
return -1
}
if (a.name > b.name) {
return 1
}
return 0
})
const reportMenuItems = sortedReports.map((r, idx) => ({
id: r.id,
name: r.name,
description: r.description || '',
key: r.id || idx + '-report',
url: `/project/${ref}/observability/${r.id}${preservedQueryParams}`,
hasDropdownActions: true,
report: r,
}))
return reportMenuItems
}
const data = getReportMenuItems()
return { data, isLoading }
}