Files
supabase/apps/studio/components/interfaces/QuerySources/DatabaseParametersSubMenu.tsx
Joshen Lim 0b5be1fada Disable read replica creation CTAs for HA projects (#49629)
## Context

As per PR title - disables creation of read replicas for HA projects.
This involves:
- Hiding new replica CTA in `DatabaseSelector`
  - Used in pages like reports
- Hiding new replica CTA in `DatabaseParametersSubMenu`
  - Used in SQL Editor + Explorer
- Disabling new replica CTA in settings/infrastructure under Read
Replicas
<img width="1065" height="401" alt="image"
src="https://github.com/user-attachments/assets/18c59cee-2f47-4874-9861-8211684282ab"
/>
<img width="418" height="366" alt="image"
src="https://github.com/user-attachments/assets/553cf75b-ff95-41c0-beca-357430a7e888"
/>



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

## Bug Fixes

- Updated read replica controls to accurately reflect project
availability.
- Hid read replica creation options for high-availability projects.
- Prevented read replica deployment for high-availability projects.
- Added an explanatory notice and guidance when read replicas are
unavailable due to high-availability settings.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-27 22:13:29 +08:00

88 lines
3.3 KiB
TypeScript

import { IS_PLATFORM, useParams } from 'common'
import { Check, Plus } from 'lucide-react'
import Link from 'next/link'
import {
DropdownMenuItem,
DropdownMenuSeparator,
DropdownMenuSub,
DropdownMenuSubContent,
DropdownMenuSubTrigger,
} from 'ui'
import { getAddReadReplicaPath } from '@/components/interfaces/Settings/Infrastructure/Infrastructure.utils'
import { useReadReplicasQuery } from '@/data/read-replicas/replicas-query'
import { formatDatabaseID, formatDatabaseRegion } from '@/data/read-replicas/replicas.utils'
import { useIsFeatureEnabled } from '@/hooks/misc/useIsFeatureEnabled'
import { useIsHighAvailability } from '@/hooks/misc/useSelectedProject'
/** The label a database row/summary shows: the primary, or a replica by region + id. */
function databaseLabel(identifier: string, region: string, projectRef: string | undefined) {
if (identifier === projectRef) return 'Primary database'
return `Read replica (${formatDatabaseRegion(region)} - ${formatDatabaseID(identifier)})`
}
export const DatabaseParametersSubMenu = ({
identifier,
onIdentifierChange,
}: {
identifier?: string
onIdentifierChange: (identifier: string) => void
}) => {
const { ref: projectRef } = useParams()
const isHighAvailability = useIsHighAvailability()
const { infrastructureReadReplicas } = useIsFeatureEnabled(['infrastructure:read_replicas'])
const { data } = useReadReplicasQuery({ projectRef })
const databases = (data ?? [])
.slice()
.sort((a, b) => (a.inserted_at > b.inserted_at ? 1 : 0))
.sort((database) => (database.identifier === projectRef ? -1 : 0))
const selectedDatabaseId = identifier ?? projectRef
const selectedDatabase = databases.find((db) => db.identifier === selectedDatabaseId)
const newReplicaURL = getAddReadReplicaPath(projectRef)
return (
<DropdownMenuSub>
<DropdownMenuSubTrigger>
<div className="flex flex-col">
<span>Database</span>
<span className="text-foreground-lighter text-xs">
{selectedDatabase
? databaseLabel(selectedDatabase.identifier, selectedDatabase.region, projectRef)
: 'Primary database'}
</span>
</div>
</DropdownMenuSubTrigger>
<DropdownMenuSubContent className="w-64">
{databases.map((database) => {
const isUnhealthy = database.status !== 'ACTIVE_HEALTHY'
return (
<DropdownMenuItem
key={database.identifier}
className="justify-between"
disabled={isUnhealthy}
onClick={() => onIdentifierChange(database.identifier)}
>
<span>{databaseLabel(database.identifier, database.region, projectRef)}</span>
{database.identifier === selectedDatabaseId && <Check size={14} />}
</DropdownMenuItem>
)
})}
{IS_PLATFORM && infrastructureReadReplicas && !isHighAvailability && (
<>
<DropdownMenuSeparator />
<DropdownMenuItem asChild className="gap-x-2">
<Link href={newReplicaURL}>
<Plus size={14} strokeWidth={1.5} />
Create a new read replica
</Link>
</DropdownMenuItem>
</>
)}
</DropdownMenuSubContent>
</DropdownMenuSub>
)
}