mirror of
https://github.com/supabase/supabase.git
synced 2026-10-07 18:35:07 +03:00
## Context Adds a feature preview banner toast for the explorer - flagged behind the configcat flag <img width="315" height="342" alt="image" src="https://github.com/user-attachments/assets/9dbd7ffd-02c6-4083-9ca0-266b862e1b5d" /> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **New Features** - Added an Explorer preview banner to project layouts when the feature is enabled. - Added an “Enable Explorer” call-to-action that opens the feature preview. - Banner dismissal is remembered and persists across sessions. - Added telemetry tracking for banner dismissal and CTA interactions. - **Bug Fixes** - Improved banner behavior and stability when displaying database connection notifications. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
124 lines
3.8 KiB
TypeScript
124 lines
3.8 KiB
TypeScript
import { LOCAL_STORAGE_KEYS, useParams } from 'common'
|
|
import { usePathname } from 'next/navigation'
|
|
import { PropsWithChildren, useEffect, useRef } from 'react'
|
|
|
|
import { ProjectLayout } from '../ProjectLayout'
|
|
import { ObservabilityMenu } from './ObservabilityMenu'
|
|
import { useIsDatabaseConnectionsEnabled } from '@/components/interfaces/App/FeaturePreview/FeaturePreviewContext'
|
|
import { useIndexAdvisorStatus } from '@/components/interfaces/QueryPerformance/hooks/useIsIndexAdvisorStatus'
|
|
import { BannerDatabaseConnections } from '@/components/ui/BannerStack/Banners/BannerDatabaseConnections'
|
|
import { BannerIndexAdvisor } from '@/components/ui/BannerStack/Banners/BannerIndexAdvisor'
|
|
import { useBannerStack } from '@/components/ui/BannerStack/BannerStackProvider'
|
|
import { UnknownInterface } from '@/components/ui/UnknownInterface'
|
|
import { useIsFeatureEnabled } from '@/hooks/misc/useIsFeatureEnabled'
|
|
import { useLocalStorageQuery } from '@/hooks/misc/useLocalStorage'
|
|
import { withAuth } from '@/hooks/misc/withAuth'
|
|
|
|
interface ObservabilityLayoutProps {
|
|
title: string
|
|
}
|
|
|
|
const ObservabilityLayoutContent = ({
|
|
title,
|
|
children,
|
|
}: PropsWithChildren<ObservabilityLayoutProps>) => {
|
|
const { ref } = useParams()
|
|
const pathname = usePathname()
|
|
const { addBanner, dismissBanner } = useBannerStack()
|
|
const { isIndexAdvisorAvailable, isIndexAdvisorEnabled } = useIndexAdvisorStatus()
|
|
|
|
const [isIndexAdvisorBannerDismissed] = useLocalStorageQuery(
|
|
LOCAL_STORAGE_KEYS.INDEX_ADVISOR_NOTICE_DISMISSED(ref ?? ''),
|
|
false
|
|
)
|
|
|
|
const { isInitialized, previouslyToggled } = useIsDatabaseConnectionsEnabled()
|
|
|
|
const [isDatabaseConnectionsBannerDismissed, , { isSuccess: isLocalStorageReady }] =
|
|
useLocalStorageQuery(LOCAL_STORAGE_KEYS.DATABASE_CONNECTIONS_BANNER_DISMISSED(ref ?? ''), false)
|
|
|
|
const prevPathnameRef = useRef(pathname)
|
|
|
|
useEffect(() => {
|
|
if (
|
|
!isInitialized ||
|
|
!isLocalStorageReady ||
|
|
isDatabaseConnectionsBannerDismissed ||
|
|
previouslyToggled
|
|
)
|
|
return
|
|
|
|
addBanner({
|
|
id: 'database-connections-banner',
|
|
priority: 2,
|
|
isDismissed: false,
|
|
content: <BannerDatabaseConnections />,
|
|
})
|
|
}, [
|
|
addBanner,
|
|
isInitialized,
|
|
isDatabaseConnectionsBannerDismissed,
|
|
previouslyToggled,
|
|
isLocalStorageReady,
|
|
])
|
|
|
|
useEffect(() => {
|
|
const isQueryPerformancePage = pathname?.includes('/query-performance')
|
|
|
|
if (
|
|
isQueryPerformancePage &&
|
|
isIndexAdvisorAvailable &&
|
|
!isIndexAdvisorEnabled &&
|
|
!isIndexAdvisorBannerDismissed
|
|
) {
|
|
addBanner({
|
|
id: 'index-advisor-banner',
|
|
isDismissed: false,
|
|
content: <BannerIndexAdvisor />,
|
|
priority: 3,
|
|
})
|
|
} else if (isIndexAdvisorBannerDismissed || !isQueryPerformancePage || isIndexAdvisorEnabled) {
|
|
dismissBanner('index-advisor-banner')
|
|
}
|
|
|
|
prevPathnameRef.current = pathname
|
|
}, [
|
|
pathname,
|
|
isIndexAdvisorAvailable,
|
|
isIndexAdvisorEnabled,
|
|
isIndexAdvisorBannerDismissed,
|
|
addBanner,
|
|
dismissBanner,
|
|
])
|
|
|
|
const { reportsAll } = useIsFeatureEnabled(['reports:all'])
|
|
|
|
if (reportsAll) {
|
|
return (
|
|
<ProjectLayout
|
|
product="Observability"
|
|
browserTitle={{ section: title }}
|
|
productMenu={<ObservabilityMenu />}
|
|
isBlocking={false}
|
|
>
|
|
{children}
|
|
</ProjectLayout>
|
|
)
|
|
} else {
|
|
return <UnknownInterface urlBack={`/project/${ref}`} />
|
|
}
|
|
}
|
|
|
|
const ObservabilityLayout = (props: PropsWithChildren<ObservabilityLayoutProps>) => {
|
|
const { ref } = useParams()
|
|
const { reportsAll } = useIsFeatureEnabled(['reports:all'])
|
|
|
|
if (reportsAll) {
|
|
return <ObservabilityLayoutContent {...props} />
|
|
} else {
|
|
return <UnknownInterface urlBack={`/project/${ref}`} />
|
|
}
|
|
}
|
|
|
|
export default withAuth(ObservabilityLayout)
|