import { PermissionAction } from '@supabase/shared-types/out/constants' import { AlertTriangle, Book, Github, Loader2 } from 'lucide-react' import Link from 'next/link' import { useState } from 'react' import { toast } from 'sonner' import { ButtonTooltip } from 'components/ui/ButtonTooltip' import { useDatabaseExtensionDisableMutation } from 'data/database-extensions/database-extension-disable-mutation' import { DatabaseExtension } from 'data/database-extensions/database-extensions-query' import { useAsyncCheckPermissions } from 'hooks/misc/useCheckPermissions' import { useIsOrioleDb, useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { DOCS_URL } from 'lib/constants' import { extensions } from 'shared-data' import { Button, Switch, TableCell, TableRow, Tooltip, TooltipContent, TooltipTrigger } from 'ui' import { Admonition } from 'ui-patterns' import ConfirmationModal from 'ui-patterns/Dialogs/ConfirmationModal' import EnableExtensionModal from './EnableExtensionModal' import { EXTENSION_DISABLE_WARNINGS } from './Extensions.constants' interface ExtensionRowProps { extension: DatabaseExtension } export const ExtensionRow = ({ extension }: ExtensionRowProps) => { const { data: project } = useSelectedProjectQuery() const isOn = extension.installed_version !== null const isOrioleDb = useIsOrioleDb() const [isDisableModalOpen, setIsDisableModalOpen] = useState(false) const [showConfirmEnableModal, setShowConfirmEnableModal] = useState(false) const { can: canUpdateExtensions } = useAsyncCheckPermissions( PermissionAction.TENANT_SQL_ADMIN_WRITE, 'extensions' ) const orioleDbCheck = isOrioleDb && extension.name === 'orioledb' const disabled = !canUpdateExtensions || orioleDbCheck const extensionMeta = extensions.find((item) => item.name === extension.name) const docsUrl = extensionMeta?.link.startsWith('/guides') ? `${DOCS_URL}${extensionMeta?.link}` : extensionMeta?.link ?? undefined const { mutate: disableExtension, isLoading: isDisabling } = useDatabaseExtensionDisableMutation({ onSuccess: () => { toast.success(`${extension.name} is off.`) setIsDisableModalOpen(false) }, }) const onConfirmDisable = () => { if (project === undefined) return console.error('Project is required') disableExtension({ projectRef: project.ref, connectionString: project.connectionString, id: extension.name, }) } return ( <>
{extension.name} {extensionMeta?.deprecated && extensionMeta?.deprecated.length > 0 && ( } className="rounded-full" tooltip={{ content: { text: `The extension is deprecated and will be removed in ${extensionMeta.deprecated.join(', ')}.`, }, }} > Deprecated )}
{extension?.installed_version ?? extension.default_version} {isOn ? extension.schema : '-'}

{extension.comment}

{extensionMeta?.product ? (
{extensionMeta.product_url ? ( {extensionMeta.product} ) : ( {extensionMeta.product} )} {!isOn && ( Install extension to use {extensionMeta.product} )}
) : ( - )}
{extensionMeta?.github_url && ( )} {docsUrl !== undefined && ( )}
{/* [Joshen] The div child here and all these classes is to properly add a left border to make the sticky column more distinct */}
{isDisabling ? ( ) : ( isOn ? setIsDisableModalOpen(true) : setShowConfirmEnableModal(true) } /> {disabled && ( {!canUpdateExtensions ? 'You need additional permissions to toggle extensions' : orioleDbCheck ? 'Project is using OrioleDB and cannot be disabled' : null} )} )}
setShowConfirmEnableModal(false)} /> setIsDisableModalOpen(false)} onConfirm={() => onConfirmDisable()} >

Are you sure you want to turn OFF the "{extension.name}" extension?

{EXTENSION_DISABLE_WARNINGS[extension.name] && ( {EXTENSION_DISABLE_WARNINGS[extension.name]} )}
) }