mirror of
https://github.com/supabase/supabase.git
synced 2026-10-06 18:05:11 +03:00
## Summary - Extracts `useUserProjectRegions` (org + project region aggregation, fail-open on fetch errors) and `useEmergencyIncidentOverride` (the `ongoingIncident` flag / env var check) out of `useStatusPageBannerVisibility`, so the upcoming incident.io status-page banner can reuse both without duplicating the org/project fan-out logic. - No behavior change for the legacy banner except one intentional fix: `StatusPageBanner.utils.ts` compared the incident's affected regions (lowercased) against the user's regions (not normalized), so a mixed-case region on either side could silently fail to match. Both sides now go through the same `normalizeRegion` helper. - Part of the Linear FE-4057 stack (PR 5a of 6). Base branch is PR 4 (`charis/fe-4057-pr4-project-creation-status-admonition`), not master. Linear: FE-4057 ## Test plan - [x] `pnpm --filter studio run typecheck` - [x] `pnpm --filter studio run lint:ratchet` - [x] `pnpm knip --workspace apps/studio` - [x] `pnpm test:prettier` - [x] `pnpm --filter studio exec vitest run` on the touched test files and the `hooks/misc/` and `components/layouts/AppLayout/` directories (all passing, no regressions) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Improved status banner targeting by matching incidents against normalized regions across the user’s projects. * Updated banner visibility checks to handle incomplete project or region data, including when project information fails to load. * Improved loading behavior so the banner can be evaluated based on user-region data rather than waiting for separate organization and project requests. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
75 lines
2.7 KiB
TypeScript
75 lines
2.7 KiB
TypeScript
import { useQuery } from '@tanstack/react-query'
|
|
import { LOCAL_STORAGE_KEYS } from 'common'
|
|
import { useCallback } from 'react'
|
|
|
|
import { getRelevantIncidentIds, shouldShowBanner } from './StatusPageBanner.utils'
|
|
import { incidentBannerQueryOptions } from '@/data/platform/incident-banner-query'
|
|
import { useEmergencyIncidentOverride } from '@/hooks/misc/useEmergencyIncidentOverride'
|
|
import { useLocalStorageQuery } from '@/hooks/misc/useLocalStorage'
|
|
import { useUserProjectRegions } from '@/hooks/misc/useUserProjectRegions'
|
|
|
|
export type StatusPageBannerData = { title: string; dismiss?: () => void }
|
|
|
|
const EMPTY_REGIONS: ReadonlySet<string> = new Set()
|
|
|
|
export function useStatusPageBannerVisibility(): StatusPageBannerData | null {
|
|
const showIncidentBannerOverride = useEmergencyIncidentOverride()
|
|
|
|
const { data: incidentBannerData } = useQuery(incidentBannerQueryOptions())
|
|
|
|
const bannerItems = incidentBannerData?.incidents ?? []
|
|
const incidents = bannerItems.map((i) => ({ id: i.id, cache: i.metadata }))
|
|
const hasActiveIncidents = incidents.length > 0
|
|
|
|
const userProjectRegions = useUserProjectRegions({
|
|
enabled: !showIncidentBannerOverride && hasActiveIncidents,
|
|
})
|
|
|
|
const userContext =
|
|
userProjectRegions.status === 'resolved' ? userProjectRegions.context : undefined
|
|
const hasProjects = userContext?.hasProjects ?? false
|
|
const userRegions = userContext?.regions ?? EMPTY_REGIONS
|
|
const hasUnknownRegions = userContext !== undefined && !userContext.isComplete
|
|
|
|
const [dismissedIds, setDismissedIds, { isSuccess: isDismissedLoaded }] = useLocalStorageQuery<
|
|
Array<string>
|
|
>(LOCAL_STORAGE_KEYS.INCIDENT_BANNER_DISMISSED_IDS, [])
|
|
|
|
const dismiss = useCallback(() => {
|
|
const activeIncidentIds = new Set(incidents.map((i) => i.id))
|
|
const relevantIds = getRelevantIncidentIds({
|
|
incidents,
|
|
hasProjects,
|
|
userRegions,
|
|
hasUnknownRegions,
|
|
})
|
|
setDismissedIds((prev) => [
|
|
...new Set([...prev.filter((id) => activeIncidentIds.has(id)), ...relevantIds]),
|
|
])
|
|
}, [incidents, hasProjects, userRegions, hasUnknownRegions, setDismissedIds])
|
|
|
|
if (showIncidentBannerOverride) return { title: 'We are investigating a technical issue' }
|
|
|
|
if (!hasActiveIncidents || userProjectRegions.status === 'loading') return null
|
|
|
|
const dismissedIdSet = new Set(dismissedIds)
|
|
const undismissedIncidents = incidents.filter((i) => !dismissedIdSet.has(i.id))
|
|
|
|
if (
|
|
!isDismissedLoaded ||
|
|
!shouldShowBanner({
|
|
incidents: undismissedIncidents,
|
|
hasProjects,
|
|
userRegions,
|
|
hasUnknownRegions,
|
|
})
|
|
)
|
|
return null
|
|
|
|
const title = hasProjects
|
|
? 'We are investigating a technical issue'
|
|
: 'Project creation may be impacted in some regions'
|
|
|
|
return { title, dismiss }
|
|
}
|