import { PermissionAction } from '@supabase/shared-types/out/constants' import { isNull, partition } from 'lodash' import { AlertCircle, Search } from 'lucide-react' import { useEffect, useState } from 'react' import { useParams } from 'common' import InformationBox from 'components/ui/InformationBox' import { NoSearchResults } from 'components/ui/NoSearchResults' import { GenericSkeletonLoader } from 'components/ui/ShimmeringLoader' import { useDatabaseExtensionsQuery } from 'data/database-extensions/database-extensions-query' import { useAsyncCheckPermissions } from 'hooks/misc/useCheckPermissions' import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { DOCS_URL } from 'lib/constants' import { Card, Input, ShadowScrollArea, Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from 'ui' import { ExtensionRow } from './ExtensionRow' import { HIDDEN_EXTENSIONS, SEARCH_TERMS } from './Extensions.constants' export const Extensions = () => { const { filter } = useParams() const { data: project } = useSelectedProjectQuery() const [filterString, setFilterString] = useState('') const { data, isLoading } = useDatabaseExtensionsQuery({ projectRef: project?.ref, connectionString: project?.connectionString, }) const extensions = filterString.length === 0 ? data ?? [] : (data ?? []).filter((ext) => { const nameMatchesSearch = ext.name.toLowerCase().includes(filterString.toLowerCase()) const searchTermsMatchesSearch = (SEARCH_TERMS[ext.name] || []).some((x) => x.includes(filterString.toLowerCase()) ) return nameMatchesSearch || searchTermsMatchesSearch }) const extensionsWithoutHidden = extensions.filter((ext) => !HIDDEN_EXTENSIONS.includes(ext.name)) const [enabledExtensions, disabledExtensions] = partition( extensionsWithoutHidden, (ext) => !isNull(ext.installed_version) ) const { can: canUpdateExtensions, isSuccess: isPermissionsLoaded } = useAsyncCheckPermissions( PermissionAction.TENANT_SQL_ADMIN_WRITE, 'extensions' ) useEffect(() => { if (filter !== undefined) setFilterString(filter as string) }, [filter]) return ( <>
setFilterString(e.target.value)} className="w-52" icon={} />
{isPermissionsLoaded && !canUpdateExtensions && ( } title="You need additional permissions to update database extensions" /> )} {isLoading ? ( ) : ( Name Version Schema Description Used by Links {/* [Joshen] All these classes are just to make the last column sticky I reckon we can pull these out into the Table component where we can declare sticky columns via props, but we can do that if we start to have more tables in the dashboard with sticky columns */}
Enabled
{[...enabledExtensions, ...disabledExtensions].map((extension) => ( ))} {extensions.length === 0 && ( setFilterString('')} /> )}
)} ) }