mirror of
https://github.com/supabase/supabase.git
synced 2026-10-05 17:35:10 +03:00
## Context There's certain areas in the dashboard where we're calling `useTablesQuery` without a schema filter, in which case the dashboard then fires a query against the project's database to fetch _all_ tables across _all_ schemas - this could easily be a heavy query if there's a large number of relations in the project's database. Am hence opting to either add a schema filter if appropriate, or otherwise opt to use the infinite loading behaviour ## Changes involved - Add schema filter to `useTablesQuery` in database triggers and publications - Use infinite loading for tables in Cmd K for "Run query on table" and "Search database tables" ## To test - [x] Verify that database triggers + publications still function as expected - [x] Verify that CMD K "Run query on table" and "Search database tables" still function as expected (including search) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Implemented debounced infinite-scrolling table search in the command menu and SQL editor command flow. * Added a schema selector dropdown to publications management for easier navigation. * **Improvements** * Removed the “Schema” column from the publications tables UI. * Updated search guidance and table-picker status (counts/loading) during infinite browsing. * Trigger table listings now follow the selected schema context. * Refined command menu list height and improved the database-tables placeholder text. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
126 lines
2.8 KiB
TypeScript
126 lines
2.8 KiB
TypeScript
'use client'
|
|
|
|
import { Auth, EdgeFunctions, Storage } from 'icons'
|
|
import { Database } from 'lucide-react'
|
|
import dynamic from 'next/dynamic'
|
|
|
|
import { EmptyState, SkeletonResults } from './ContextSearchResults.shared'
|
|
import type { SearchContextValue } from './SearchContext.types'
|
|
|
|
const TableSearchResults = dynamic(
|
|
() => import('./TableSearchResults').then((mod) => ({ default: mod.TableSearchResults })),
|
|
{
|
|
loading: () => <SkeletonResults />,
|
|
ssr: false,
|
|
}
|
|
)
|
|
|
|
const PolicySearchResults = dynamic(
|
|
() => import('./PolicySearchResults').then((mod) => ({ default: mod.PolicySearchResults })),
|
|
{
|
|
loading: () => <SkeletonResults />,
|
|
ssr: false,
|
|
}
|
|
)
|
|
|
|
const EdgeFunctionSearchResults = dynamic(
|
|
() =>
|
|
import('./EdgeFunctionSearchResults').then((mod) => ({
|
|
default: mod.EdgeFunctionSearchResults,
|
|
})),
|
|
{
|
|
loading: () => <SkeletonResults />,
|
|
ssr: false,
|
|
}
|
|
)
|
|
|
|
const StorageSearchResults = dynamic(
|
|
() => import('./StorageSearchResults').then((mod) => ({ default: mod.StorageSearchResults })),
|
|
{
|
|
loading: () => <SkeletonResults />,
|
|
ssr: false,
|
|
}
|
|
)
|
|
|
|
interface ContextSearchResultsProps {
|
|
context: SearchContextValue
|
|
query: string
|
|
debouncedFilterString: string
|
|
}
|
|
|
|
const CONTEXT_CONFIG: Record<
|
|
SearchContextValue,
|
|
{
|
|
icon: React.ComponentType<React.SVGProps<SVGSVGElement>>
|
|
label: string
|
|
requiresInput?: boolean // requires user input before showing results
|
|
}
|
|
> = {
|
|
'database-tables': {
|
|
icon: Database,
|
|
label: 'Database Tables',
|
|
requiresInput: false,
|
|
},
|
|
'auth-policies': {
|
|
icon: Auth,
|
|
label: 'RLS Policies',
|
|
requiresInput: false,
|
|
},
|
|
'edge-functions': {
|
|
icon: EdgeFunctions,
|
|
label: 'Edge Functions',
|
|
requiresInput: false,
|
|
},
|
|
storage: {
|
|
icon: Storage,
|
|
label: 'Storage',
|
|
requiresInput: false,
|
|
},
|
|
}
|
|
|
|
export function ContextSearchResults({
|
|
context,
|
|
query,
|
|
debouncedFilterString,
|
|
}: ContextSearchResultsProps) {
|
|
const config = CONTEXT_CONFIG[context]
|
|
|
|
if (context === 'database-tables') {
|
|
return (
|
|
<div className="flex-1 min-h-0 flex flex-col">
|
|
<TableSearchResults debouncedFilterString={debouncedFilterString} />
|
|
</div>
|
|
)
|
|
}
|
|
|
|
if (context === 'auth-policies') {
|
|
return (
|
|
<div className="flex-1 min-h-0 flex flex-col">
|
|
<PolicySearchResults query={query} />
|
|
</div>
|
|
)
|
|
}
|
|
|
|
if (context === 'edge-functions') {
|
|
return (
|
|
<div className="flex-1 min-h-0 flex flex-col">
|
|
<EdgeFunctionSearchResults query={query} />
|
|
</div>
|
|
)
|
|
}
|
|
|
|
if (context === 'storage') {
|
|
return (
|
|
<div className="flex-1 min-h-0 flex flex-col">
|
|
<StorageSearchResults query={query} />
|
|
</div>
|
|
)
|
|
}
|
|
|
|
return (
|
|
<div className="flex-1 min-h-0 flex flex-col">
|
|
<EmptyState icon={config.icon} label={config.label} query={query} />
|
|
</div>
|
|
)
|
|
}
|