Files
supabase/apps/studio/components/interfaces/Settings/Database/UsePoolerCheckbox.tsx
Wen Bo Xie cd930f5a2f feat: add IPv4 add on direct conn notice (#26903)
* feat: add IPv4 add on direct conn notice

* feat: add session mode warning

* fix: remove statement from Supavisor-related types

* Revert change in api types file

* Revert change in api types file

* Update API types file via codegen

* Smol feex

* Temp lint fix

* Fix

* fix: include serverless mention

---------

Co-authored-by: Joshen Lim <joshenlimek@gmail.com>
2024-05-31 17:07:25 +00:00

191 lines
8.0 KiB
TypeScript

import { ChevronDown } from 'lucide-react'
import Link from 'next/link'
import { useRouter } from 'next/router'
import { useState } from 'react'
import { useParams } from 'common'
import ShimmeringLoader from 'components/ui/ShimmeringLoader'
import { usePgBouncerStatus } from 'data/config/pgbouncer-enabled-query'
import { useProjectSettingsQuery } from 'data/config/project-settings-query'
import { usePoolingConfigurationQuery } from 'data/database/pooling-configuration-query'
import { useDatabaseSelectorStateSnapshot } from 'state/database-selector'
import { useDatabaseSettingsStateSnapshot } from 'state/database-settings'
import {
Badge,
Button,
Checkbox_Shadcn_,
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuSeparator,
DropdownMenuTrigger,
Label_Shadcn_,
Separator,
} from 'ui'
import {
DropdownMenuRadioGroup,
DropdownMenuRadioItem,
} from 'ui/src/components/shadcn/ui/dropdown-menu'
interface UsePoolerCheckboxInterface {
id: string
checked: boolean
poolingMode: 'transaction' | 'session'
onCheckedChange: (value: boolean) => void
onSelectPoolingMode: (mode: 'transaction' | 'session') => void
}
export const UsePoolerCheckbox = ({
id,
checked,
poolingMode = 'transaction',
onCheckedChange,
onSelectPoolingMode,
}: UsePoolerCheckboxInterface) => {
const router = useRouter()
const [open, setOpen] = useState(false)
const { ref: projectRef } = useParams()
const snap = useDatabaseSettingsStateSnapshot()
const state = useDatabaseSelectorStateSnapshot()
const { data, isLoading, isSuccess } = usePoolingConfigurationQuery({ projectRef })
const { data: settings, isSuccess: isSuccessSettings } = useProjectSettingsQuery({ projectRef })
const { data: pgBouncerStatus } = usePgBouncerStatus({ projectRef: projectRef })
const isDatabaseSettingsPage = router.pathname.endsWith('/settings/database')
const poolingConfiguration = data?.find((x) => x.identifier === state.selectedDatabaseId)
const resolvesToIpV6 = settings?.project.db_ip_addr_config === 'ipv6'
const onSelectOption = (value: 'session' | 'transaction') => {
onSelectPoolingMode(value)
setOpen(false)
}
return (
<div className="flex flex-col gap-y-1">
<div className="flex gap-x-3 items-center">
<Checkbox_Shadcn_
id={`use-pooler-${id}`}
checked={checked}
onCheckedChange={() => onCheckedChange(!checked)}
/>
<div className="-mt-[2px] flex flex-col gap-y-1 w-full">
<div className="flex items-center gap-x-4">
<div className="flex items-center gap-x-2">
<Label_Shadcn_ htmlFor={`use-pooler-${id}`} className="text-sm cursor-pointer">
Display connection pooler
</Label_Shadcn_>
{checked && (
<>
<div className="flex items-center gap-x-2">
{isLoading && <ShimmeringLoader className="w-[100px] py-2.5" />}
{isSuccess && (
<div className="flex items-center gap-x-1">
<DropdownMenu open={open} onOpenChange={setOpen}>
<DropdownMenuTrigger asChild>
<Button
type="outline"
className="py-0.5 pr-1.5 capitalize"
iconRight={<ChevronDown strokeWidth={1} />}
>
Mode: {poolingMode}
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent side="bottom" align="start" className="w-[280px]">
<DropdownMenuRadioGroup
value={poolingMode}
onValueChange={(value) =>
onSelectOption(value as 'session' | 'transaction')
}
>
<DropdownMenuRadioItem value="session">
Session mode
</DropdownMenuRadioItem>
{poolingConfiguration?.pool_mode === 'transaction' && (
<DropdownMenuRadioItem value="transaction">
Transaction mode
</DropdownMenuRadioItem>
)}
</DropdownMenuRadioGroup>
{poolingConfiguration?.pool_mode === 'session' && (
<>
<DropdownMenuSeparator className="my-1" />
<div className="px-2 text-xs flex flex-col gap-y-2">
<p>
To use transaction mode, change the pool mode in the{' '}
{isDatabaseSettingsPage ? (
<span
tabIndex={0}
className="underline hover:text-foreground cursor-pointer transition"
onClick={() => {
const el = document.getElementById('connection-pooler')
if (el) {
setOpen(false)
el.scrollIntoView({
behavior: 'smooth',
block: 'center',
})
}
}}
>
pooling configuration settings
</span>
) : (
<Link
href={`/project/${projectRef}/settings/database#connection-pooler`}
className="underline hover:text-foreground"
>
pooling configuration settings
</Link>
)}{' '}
to use transaction mode first.
</p>
<p>
You can then connect to session mode on port 5432 and
transaction mode on port 6543.
</p>
</div>
</>
)}
<Separator className="my-1" />
<DropdownMenuItem
key="more-info"
onClick={() => {
setOpen(false)
snap.setShowPoolingModeHelper(true)
}}
>
How to choose pooling modes?
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</div>
)}
</div>
</>
)}
</div>
<div className="flex items-center gap-x-1">
{isSuccess && checked && <Badge>Supavisor</Badge>}
{isSuccessSettings && (
<Badge>
{checked
? 'Resolves to IPv4'
: resolvesToIpV6
? 'Resolves to IPv6'
: 'Will resolve to IPv6'}
</Badge>
)}
{pgBouncerStatus?.active && (
<Badge variant="warning">PgBouncer pending removal</Badge>
)}
</div>
</div>
</div>
</div>
</div>
)
}