Files
supabase/apps/studio/components/layouts/AppLayout/StatusPageBanner.utils.ts
2026-04-01 10:22:37 +02:00

73 lines
2.6 KiB
TypeScript

import type { IncidentCache } from '@/lib/api/incident-status'
type BannerIncident = { id: string; cache?: IncidentCache | null }
/**
* Determines whether the incident status banner should be shown to a given user,
* given all active incidents and the user's project state.
*
* Returns true if any incident matches the user's context.
*
* @param incidents - Active incidents from the incident-status endpoint
* @param hasProjects - Whether the user has any projects at all
* @param userRegions - Deduplicated set of regions of all databases (primary and read replicas) owned by the user
* @param hasUnknownRegions - True when region data is incomplete (org has >100 projects).
* When true, the region check is skipped and a match is assumed.
*/
export function shouldShowBanner({
incidents,
hasProjects,
userRegions,
hasUnknownRegions = false,
}: {
incidents: Array<BannerIncident>
hasProjects: boolean
userRegions: Set<string>
hasUnknownRegions?: boolean
}): boolean {
return incidents.some((incident) => {
// Forced incidents are shown unconditionally, regardless of regions or project state
if (incident.cache?.force) return true
const affectedRegions = incident.cache?.affected_regions ?? []
const affectsProjectCreation = incident.cache?.affects_project_creation ?? false
// Users with no projects only see the banner if the incident affects project creation
// and has no specific region targeting (inline notice in RegionSelector handles region-specific incidents)
if (!hasProjects) return affectsProjectCreation && affectedRegions.length === 0
// User has projects: if no region restriction, always show
if (affectedRegions.length === 0) return true
// Region data is incomplete — assume the user has a database in an affected region
if (hasUnknownRegions) return true
// Region restriction: only show if the user has a database in an affected region
return affectedRegions.some((region) => userRegions.has(region.toLowerCase()))
})
}
/**
* Returns the IDs of incidents that are relevant to the given user.
*
* An incident is considered relevant if it would trigger banner visibility for
* the user, per the same logic as shouldShowBanner.
*/
export function getRelevantIncidentIds({
incidents,
hasProjects,
userRegions,
hasUnknownRegions = false,
}: {
incidents: Array<BannerIncident>
hasProjects: boolean
userRegions: Set<string>
hasUnknownRegions?: boolean
}): Array<string> {
return incidents
.filter((incident) =>
shouldShowBanner({ incidents: [incident], hasProjects, userRegions, hasUnknownRegions })
)
.map((incident) => incident.id)
}