import { FC, useEffect, useState } from 'react' import { useRouter } from 'next/router' import Link from 'next/link' import { partition } from 'lodash' import { Alert, Button, Dropdown, IconChevronDown, IconCopy, IconEdit, IconLoader, IconRefreshCw, IconSearch, IconTrash, IconX, Input, Listbox, Menu, Typography, } from '@supabase/ui' import { PostgresSchema, PostgresTable } from '@supabase/postgres-meta' import Base64 from 'lib/base64' import { checkPermissions, useStore } from 'hooks' import { SchemaView } from './TableEditorLayout.types' import ProductMenuItem from 'components/ui/ProductMenu/ProductMenuItem' import { PermissionAction } from '@supabase/shared-types/out/constants' interface Props { selectedSchema?: string onSelectSchema: (schema: string) => void onAddTable: () => void onEditTable: (table: PostgresTable) => void onDeleteTable: (table: PostgresTable) => void onDuplicateTable: (table: PostgresTable) => void } const TableEditorMenu: FC = ({ selectedSchema, onSelectSchema = () => {}, onAddTable = () => {}, onEditTable = () => {}, onDeleteTable = () => {}, onDuplicateTable = () => {}, }) => { const { meta, ui } = useStore() const router = useRouter() const { id } = router.query const projectRef = ui.selectedProject?.ref const schemas: PostgresSchema[] = meta.schemas.list() const tables: PostgresTable[] = meta.tables.list( (table: PostgresTable) => table.schema === selectedSchema ) // @ts-ignore const schema = schemas.find((schema) => schema.name === selectedSchema) const [searchText, setSearchText] = useState('') const [schemaViews, setSchemaViews] = useState([]) const [isRefreshing, setIsRefreshing] = useState(false) // We may need to shift this to the schema store and do something like meta.schema.loadViews() // I don't need we need a separate store for views useEffect(() => { let cancel = false const fetchViews = async (selectedSchema: string) => { const views: SchemaView[] = await meta.schemas.getViews(selectedSchema) if (!cancel) setSchemaViews(views) } if (selectedSchema) { fetchViews(selectedSchema) } return () => { cancel = true } }, [selectedSchema]) const refreshTables = async () => { setIsRefreshing(true) await meta.tables.load() setIsRefreshing(false) } const schemaTables = searchText.length === 0 ? tables : // @ts-ignore tables.filter((table) => table.name.toLowerCase().includes(searchText.toLowerCase())) const filteredSchemaViews = searchText.length === 0 ? schemaViews : schemaViews.filter((view) => view.name.includes(searchText)) const [protectedSchemas, openSchemas] = partition(schemas, (schema) => meta.excludedSchemas.includes(schema?.name ?? '') ) const isLocked = protectedSchemas.some((s) => s.id === schema?.id) return (
{/* Schema selection dropdown */}
{meta.schemas.isLoading ? (
Loading schemas...
) : ( { setSearchText('') setSchemaViews([]) onSelectSchema(name) }} >

Schemas

{openSchemas.map((schema) => ( schema} > {schema.name} ))}

Protected schemas

{protectedSchemas.map((schema) => ( schema} > {schema.name} ))}
)}
{!isLocked && (
{/* Add new table button */}
} type="default" style={{ justifyContent: 'start' }} onClick={onAddTable} > New table
)} {/* Table search input */}
} placeholder="Search tables" onChange={(e) => setSearchText(e.target.value)} value={searchText} size="tiny" actions={ searchText && ( ) } />
{/* List of tables belonging to selected schema */} {schemaTables.length > 0 && (
All tables
} />
{schemaTables.map((table) => { const isActive = Number(id) === table.id return ( } onClick={() => onEditTable(table)} > Edit Table , } onClick={() => onDuplicateTable(table)} > Duplicate Table , , } onClick={() => onDeleteTable(table)} > Delete Table , ]} >
) } /> ) })}
)} {/* List of views belonging to selected schema */} {filteredSchemaViews.length > 0 && (
All views
} /> {schemaViews.map((view: SchemaView) => { const viewId = Base64.encode(JSON.stringify(view)) const isActive = id === viewId return (
{view.name}
) })}
)} {searchText.length > 0 && schemaTables.length === 0 && filteredSchemaViews.length === 0 && (
This schema has no tables or views
)} {searchText.length === 0 && schemaTables.length === 0 && filteredSchemaViews.length === 0 && (
There are no tables in this schema
)} ) } export default TableEditorMenu