import * as Tooltip from '@radix-ui/react-tooltip' import { PermissionAction } from '@supabase/shared-types/out/constants' import { useParams } from 'common' import { partition } from 'lodash' import { useMemo, useState } from 'react' import { ProtectedSchemaModal } from 'components/interfaces/Database/ProtectedSchemaWarning' import AlertError from 'components/ui/AlertError' import InfiniteList from 'components/ui/InfiniteList' import SchemaSelector from 'components/ui/SchemaSelector' import ShimmeringLoader from 'components/ui/ShimmeringLoader' import { useSchemasQuery } from 'data/database/schemas-query' import { useEntityTypesQuery } from 'data/entity-types/entity-types-infinite-query' import { useCheckPermissions, useLocalStorage } from 'hooks' import { EXCLUDED_SCHEMAS } from 'lib/constants/schemas' import { useTableEditorStateSnapshot } from 'state/table-editor' import { AlertDescription_Shadcn_, AlertTitle_Shadcn_, Alert_Shadcn_, Button, DropdownMenu, DropdownMenuContent, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuTrigger, IconChevronsDown, IconEdit, IconLoader, IconRefreshCw, IconSearch, IconX, Input, } from 'ui' import { useProjectContext } from '../ProjectLayout/ProjectContext' import EntityListItem from './EntityListItem' import { useRouter } from 'next/router' const TableEditorMenu = () => { const router = useRouter() const { id } = useParams() const snap = useTableEditorStateSnapshot() const [showModal, setShowModal] = useState(false) const [searchText, setSearchText] = useState('') const [sort, setSort] = useLocalStorage<'alphabetical' | 'grouped-alphabetical'>( 'table-editor-sort', 'alphabetical' ) const { project } = useProjectContext() const { data, isLoading, isSuccess, isError, error, refetch, isRefetching, hasNextPage, isFetchingNextPage, fetchNextPage, isPreviousData: isSearching, } = useEntityTypesQuery( { projectRef: project?.ref, connectionString: project?.connectionString, schema: snap.selectedSchemaName, search: searchText || undefined, sort, }, { keepPreviousData: Boolean(searchText), } ) const totalCount = data?.pages?.[0].data.count const entityTypes = useMemo( () => data?.pages.flatMap((page) => page.data.entities), [data?.pages] ) const { data: schemas } = useSchemasQuery({ projectRef: project?.ref, connectionString: project?.connectionString, }) const schema = schemas?.find((schema) => schema.name === snap.selectedSchemaName) const canCreateTables = useCheckPermissions(PermissionAction.TENANT_SQL_ADMIN_WRITE, 'tables') const refreshTables = async () => { await refetch() } const [protectedSchemas] = partition( (schemas ?? []).sort((a, b) => a.name.localeCompare(b.name)), (schema) => EXCLUDED_SCHEMAS.includes(schema?.name ?? '') ) const isLocked = protectedSchemas.some((s) => s.id === schema?.id) return ( <>
{ setSearchText('') snap.setSelectedSchemaName(name) router.push(`/project/${project?.ref}/editor`) }} onSelectCreateSchema={() => snap.onAddSchema()} />
{!isLocked ? (
} type="default" style={{ justifyContent: 'start' }} onClick={snap.onAddTable} > New table {!canCreateTables && (
You need additional permissions to create tables
)} ) : ( Viewing protected schema

This schema is managed by Supabase and is read-only through the table editor

)} {/* Table search input */}
) : ( ) } placeholder="Search tables" onChange={(e) => setSearchText(e.target.value.trim())} value={searchText} size="tiny" actions={ searchText && ( ) } />
setShowModal(false)} /> ) } export default TableEditorMenu