mirror of
https://github.com/supabase/supabase.git
synced 2026-10-05 17:35:10 +03:00
Joshenlim/fe 4383 consolidate tablerow no search result state (#50389)
### Context Just some housekeeping/consolidate refactors. There's a number of places where we render the same "no result" empty state for tables. So this PR just consolidates that into a reusable component `TableRowNoResults` to reduce duplication. Opting to save this under `components/ui` instead of the `ui` package as this is more of a derivation of `TableRow` than a primitive <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **UI Improvements** - Standardized empty search-result messages across database, functions, storage, and vector bucket tables. - Search terms now appear consistently when no matching records are found. - Added an accessible label to the vector bucket row actions menu. - Improved the storage explorer loading layout so content expands to use available vertical space. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
1 parent
32b1a0f492
commit
ee3fbc4e61
19 files changed
+137
-181
No files matched your search
@@ -30,6 +30,7 @@ import { AlertError } from '@/components/ui/AlertError'
|
||||
import { DocsButton } from '@/components/ui/DocsButton'
|
||||
import { SchemaSelector } from '@/components/ui/SchemaSelector'
|
||||
import { Shortcut } from '@/components/ui/Shortcut'
|
||||
import { TableRowNoResults } from '@/components/ui/TableRowNoResults'
|
||||
import { useEnumeratedTypeDeleteMutation } from '@/data/enumerated-types/enumerated-type-delete-mutation'
|
||||
import { useEnumeratedTypesQuery } from '@/data/enumerated-types/enumerated-types-query'
|
||||
import { useQuerySchemaState } from '@/hooks/misc/useSchemaQueryState'
|
||||
@@ -217,14 +218,7 @@ export const EnumeratedTypes = () => {
|
||||
</TableRow>
|
||||
)}
|
||||
{filteredEnumeratedTypes.length === 0 && search.length > 0 && (
|
||||
<TableRow>
|
||||
<TableCell colSpan={4}>
|
||||
<p className="text-sm text-foreground">No results found</p>
|
||||
<p className="text-sm text-foreground-light">
|
||||
Your search for "{search}" did not return any results
|
||||
</p>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRowNoResults colSpan={4} search={search} />
|
||||
)}
|
||||
{filteredEnumeratedTypes.length > 0 &&
|
||||
filteredEnumeratedTypes.map((type) => (
|
||||
|
||||
+2
-10
@@ -24,6 +24,7 @@ import { stripInArgModePrefixes } from '../Functions.utils'
|
||||
import { getDatabaseTriggersHref, getFilteredFunctions } from './FunctionList.utils'
|
||||
import { SIDEBAR_KEYS } from '@/components/layouts/ProjectLayout/LayoutSidebar/LayoutSidebarProvider'
|
||||
import { ButtonTooltip } from '@/components/ui/ButtonTooltip'
|
||||
import { TableRowNoResults } from '@/components/ui/TableRowNoResults'
|
||||
import {
|
||||
useDatabaseFunctionsQuery,
|
||||
type SavedDatabaseFunction,
|
||||
@@ -91,16 +92,7 @@ export const FunctionList = ({
|
||||
}
|
||||
|
||||
if (_functions.length === 0 && filterString.length > 0) {
|
||||
return (
|
||||
<TableRow key={schema}>
|
||||
<TableCell colSpan={5}>
|
||||
<p className="text-sm text-foreground">No results found</p>
|
||||
<p className="text-sm text-foreground-light">
|
||||
Your search for "{filterString}" did not return any results
|
||||
</p>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
)
|
||||
return <TableRowNoResults key={schema} colSpan={5} search={filterString} />
|
||||
}
|
||||
|
||||
return (
|
||||
|
||||
@@ -28,6 +28,7 @@ import { AlertError } from '@/components/ui/AlertError'
|
||||
import { CodeEditor } from '@/components/ui/CodeEditor/CodeEditor'
|
||||
import { SchemaSelector } from '@/components/ui/SchemaSelector'
|
||||
import { Shortcut } from '@/components/ui/Shortcut'
|
||||
import { TableRowNoResults } from '@/components/ui/TableRowNoResults'
|
||||
import { useDatabaseIndexDeleteMutation } from '@/data/database-indexes/index-delete-mutation'
|
||||
import { useIndexesQuery, type DatabaseIndex } from '@/data/database-indexes/indexes-query'
|
||||
import { useSchemasQuery } from '@/data/database/schemas-query'
|
||||
@@ -240,14 +241,7 @@ export const Indexes = () => {
|
||||
</TableRow>
|
||||
)}
|
||||
{indexes.length === 0 && search.length > 0 && (
|
||||
<TableRow>
|
||||
<TableCell colSpan={4}>
|
||||
<p className="text-sm text-foreground">No results found</p>
|
||||
<p className="text-sm text-foreground-light">
|
||||
Your search for "{search}" did not return any results
|
||||
</p>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRowNoResults colSpan={4} search={search} />
|
||||
)}
|
||||
{indexes.length > 0 &&
|
||||
indexes.map((index) => (
|
||||
|
||||
@@ -25,6 +25,7 @@ import { MigrationsEmptyState } from './MigrationsEmptyState'
|
||||
import { SupportLink } from '@/components/interfaces/Support/SupportLink'
|
||||
import { CodeEditor } from '@/components/ui/CodeEditor/CodeEditor'
|
||||
import { InlineLink } from '@/components/ui/InlineLink'
|
||||
import { TableRowNoResults } from '@/components/ui/TableRowNoResults'
|
||||
import { DatabaseMigration, useMigrationsQuery } from '@/data/database/migrations-query'
|
||||
import { useSelectedProjectQuery } from '@/hooks/misc/useSelectedProject'
|
||||
import { DOCS_URL } from '@/lib/constants'
|
||||
@@ -184,14 +185,7 @@ export const Migrations = () => {
|
||||
)
|
||||
})
|
||||
) : (
|
||||
<TableRow>
|
||||
<TableCell colSpan={3}>
|
||||
<p className="text-sm text-foreground">No results found</p>
|
||||
<p className="text-sm text-foreground-light">
|
||||
Your search for "{search}" did not return any results
|
||||
</p>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRowNoResults colSpan={3} search={search} />
|
||||
)}
|
||||
</TableBody>
|
||||
</Table>
|
||||
|
||||
@@ -15,7 +15,6 @@ import {
|
||||
DropdownMenuTrigger,
|
||||
Table,
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableHead,
|
||||
TableHeader,
|
||||
TableHeadSort,
|
||||
@@ -42,6 +41,7 @@ import {
|
||||
import { useRedirectLegacyReadReplicaDestination } from './useRedirectLegacyReadReplicaDestination'
|
||||
import { AlertError } from '@/components/ui/AlertError'
|
||||
import { Shortcut } from '@/components/ui/Shortcut'
|
||||
import { TableRowNoResults } from '@/components/ui/TableRowNoResults'
|
||||
import { useReplicationDestinationsQuery } from '@/data/replication/destinations-query'
|
||||
import { replicationKeys } from '@/data/replication/keys'
|
||||
import {
|
||||
@@ -404,16 +404,7 @@ export const Destinations = () => {
|
||||
|
||||
{!isDestinationsLoading &&
|
||||
filteredDestinations.length === 0 &&
|
||||
hasDestinations && (
|
||||
<TableRow>
|
||||
<TableCell colSpan={6}>
|
||||
<p>No results found</p>
|
||||
<p className="text-foreground-light">
|
||||
Your search for “{filterString}” did not return any results.
|
||||
</p>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
)}
|
||||
hasDestinations && <TableRowNoResults colSpan={6} search={filterString} />}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</CardContent>
|
||||
|
||||
@@ -54,6 +54,7 @@ import { DropdownMenuItemTooltip } from '@/components/ui/DropdownMenuItemTooltip
|
||||
import { EntityTypeIcon } from '@/components/ui/EntityTypeIcon'
|
||||
import { SchemaSelector } from '@/components/ui/SchemaSelector'
|
||||
import { Shortcut } from '@/components/ui/Shortcut'
|
||||
import { TableRowNoResults } from '@/components/ui/TableRowNoResults'
|
||||
import { useDatabasePublicationsQuery } from '@/data/database-publications/database-publications-query'
|
||||
import { ENTITY_TYPE } from '@/data/entity-types/entity-type-constants'
|
||||
import { useForeignTablesQuery } from '@/data/foreign-tables/foreign-tables-query'
|
||||
@@ -429,14 +430,7 @@ export const TableList = ({
|
||||
</TableRow>
|
||||
)}
|
||||
{entities.length === 0 && filterString.length > 0 && (
|
||||
<TableRow key={selectedSchema}>
|
||||
<TableCell colSpan={7}>
|
||||
<p className="text-sm text-foreground">No results found</p>
|
||||
<p className="text-sm text-foreground-light">
|
||||
Your search for "{filterString}" did not return any results
|
||||
</p>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRowNoResults key={selectedSchema} colSpan={7} search={filterString} />
|
||||
)}
|
||||
{entities.length > 0 &&
|
||||
entities.map((x) => (
|
||||
|
||||
+2
-25
@@ -19,6 +19,7 @@ import type { EventTrigger } from './EventTriggerList.utils'
|
||||
import { SUPABASE_ROLES } from '@/components/interfaces/Database/Roles/Roles.constants'
|
||||
import { getDatabaseFunctionsHref } from '@/components/interfaces/Database/Triggers/TriggersList/TriggerList.utils'
|
||||
import { ButtonTooltip } from '@/components/ui/ButtonTooltip'
|
||||
import { TableRowNoResults } from '@/components/ui/TableRowNoResults'
|
||||
|
||||
interface EventTriggerListProps {
|
||||
filterString: string
|
||||
@@ -64,32 +65,8 @@ export const EventTriggerList = ({
|
||||
return sortBy(filteredEventTriggers, (trigger) => trigger.name.toLocaleLowerCase())
|
||||
}, [eventTriggers, ownerFilter, filterString])
|
||||
|
||||
if (orderedTriggers.length === 0 && filterString.length === 0 && ownerFilter.length === 0) {
|
||||
return (
|
||||
<TableRow>
|
||||
<TableCell colSpan={6}>
|
||||
<p className="text-sm text-foreground">No event triggers created yet</p>
|
||||
<p className="text-sm text-foreground-light">
|
||||
There are no event triggers configured for this database
|
||||
</p>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
)
|
||||
}
|
||||
|
||||
if (orderedTriggers.length === 0 && (filterString.length > 0 || ownerFilter.length > 0)) {
|
||||
return (
|
||||
<TableRow>
|
||||
<TableCell colSpan={6}>
|
||||
<p className="text-sm text-foreground">No results found</p>
|
||||
<p className="text-sm text-foreground-light">
|
||||
{filterString.length > 0
|
||||
? `Your search for "${filterString}" did not return any results`
|
||||
: 'No event triggers match the current filters'}
|
||||
</p>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
)
|
||||
return <TableRowNoResults colSpan={6} search={filterString} />
|
||||
}
|
||||
|
||||
return (
|
||||
|
||||
@@ -27,6 +27,7 @@ import {
|
||||
import { selectFilterSchema } from '@/components/interfaces/Reports/v2/ReportsSelectFilter'
|
||||
import { SIDEBAR_KEYS } from '@/components/layouts/ProjectLayout/LayoutSidebar/LayoutSidebarProvider'
|
||||
import { ButtonTooltip } from '@/components/ui/ButtonTooltip'
|
||||
import { TableRowNoResults } from '@/components/ui/TableRowNoResults'
|
||||
import { useDatabaseTriggersQuery } from '@/data/database-triggers/database-triggers-query'
|
||||
import { useAsyncCheckPermissions } from '@/hooks/misc/useCheckPermissions'
|
||||
import { useQuerySchemaState } from '@/hooks/misc/useSchemaQueryState'
|
||||
@@ -92,16 +93,7 @@ export const TriggerList = ({ editTrigger, duplicateTrigger, deleteTrigger }: Tr
|
||||
}
|
||||
|
||||
if (_triggers.length === 0 && filterString.length > 0) {
|
||||
return (
|
||||
<TableRow key={schema}>
|
||||
<TableCell colSpan={7}>
|
||||
<p className="text-sm text-foreground">No results found</p>
|
||||
<p className="text-sm text-foreground-light">
|
||||
Your search for "{filterString}" did not return any results
|
||||
</p>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
)
|
||||
return <TableRowNoResults key={schema} colSpan={7} search={filterString} />
|
||||
}
|
||||
|
||||
return (
|
||||
|
||||
+6
-8
@@ -20,6 +20,7 @@ import { EditSecretSheet } from './EditSecretSheet'
|
||||
import { AlertError } from '@/components/ui/AlertError'
|
||||
import { DocsButton } from '@/components/ui/DocsButton'
|
||||
import { NoPermission } from '@/components/ui/NoPermission'
|
||||
import { TableRowNoResults } from '@/components/ui/TableRowNoResults'
|
||||
import { useSecretsDeleteMutation } from '@/data/secrets/secrets-delete-mutation'
|
||||
import { useSecretsQuery } from '@/data/secrets/secrets-query'
|
||||
import { useAsyncCheckPermissions } from '@/hooks/misc/useCheckPermissions'
|
||||
@@ -181,14 +182,11 @@ export const EdgeFunctionSecrets = () => {
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
) : (
|
||||
<TableRow className="[&>td]:hover:bg-inherit">
|
||||
<TableCell colSpan={headers.length}>
|
||||
<p className="text-sm text-foreground">No results found</p>
|
||||
<p className="text-sm text-foreground-light">
|
||||
Your search for "{searchString}" did not return any results
|
||||
</p>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRowNoResults
|
||||
className="[&>td]:hover:bg-inherit"
|
||||
colSpan={headers.length}
|
||||
search={searchString}
|
||||
/>
|
||||
)}
|
||||
</TableBody>
|
||||
</Table>
|
||||
|
||||
@@ -27,6 +27,7 @@ import { CreateBucketButton } from '../NewBucketButton'
|
||||
import { CreateAnalyticsBucketModal } from './CreateAnalyticsBucketModal'
|
||||
import { AlertError } from '@/components/ui/AlertError'
|
||||
import { AlphaNotice } from '@/components/ui/AlphaNotice'
|
||||
import { TableRowNoResults } from '@/components/ui/TableRowNoResults'
|
||||
import { useProjectStorageConfigQuery } from '@/data/config/project-storage-config-query'
|
||||
import { useAnalyticsBucketsQuery } from '@/data/storage/analytics-buckets-query'
|
||||
import { createNavigationHandler } from '@/lib/navigation'
|
||||
@@ -136,14 +137,11 @@ export const AnalyticsBuckets = () => {
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
{analyticsBuckets.length === 0 && filterString.length > 0 && (
|
||||
<TableRow className="[&>td]:hover:bg-inherit">
|
||||
<TableCell colSpan={3}>
|
||||
<p className="text-sm text-foreground">No results found</p>
|
||||
<p className="text-sm text-foreground-light">
|
||||
Your search for "{filterString}" did not return any results
|
||||
</p>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRowNoResults
|
||||
className="[&>td]:hover:bg-inherit"
|
||||
colSpan={3}
|
||||
search={filterString}
|
||||
/>
|
||||
)}
|
||||
{analyticsBuckets.map((bucket) => {
|
||||
const handleBucketNavigation = createNavigationHandler(
|
||||
|
||||
@@ -12,27 +12,6 @@ import { formatBytes } from '@/lib/helpers'
|
||||
|
||||
type BucketTableMode = 'standard' | 'virtualized'
|
||||
|
||||
type BucketTableEmptyStateProps = {
|
||||
mode: BucketTableMode
|
||||
filterString: string
|
||||
}
|
||||
|
||||
export const BucketTableEmptyState = ({ mode, filterString }: BucketTableEmptyStateProps) => {
|
||||
const BucketTableRow = mode === 'standard' ? TableRow : VirtualizedTableRow
|
||||
const BucketTableCell = mode === 'standard' ? TableCell : VirtualizedTableCell
|
||||
|
||||
return (
|
||||
<BucketTableRow className="[&>td]:hover:bg-inherit">
|
||||
<BucketTableCell colSpan={5}>
|
||||
<p className="text-sm text-foreground">No results found</p>
|
||||
<p className="text-sm text-foreground-lighter">
|
||||
Your search for “{filterString}” did not return any results
|
||||
</p>
|
||||
</BucketTableCell>
|
||||
</BucketTableRow>
|
||||
)
|
||||
}
|
||||
|
||||
type BucketTableRowProps = {
|
||||
mode: BucketTableMode
|
||||
bucket: Bucket
|
||||
|
||||
@@ -3,8 +3,9 @@ import { Table, TableBody } from 'ui'
|
||||
|
||||
import { LoadMoreRow } from './BucketsTable.LoadMoreRow'
|
||||
import { BucketTableHeader } from './BucketTableHeader'
|
||||
import { BucketTableEmptyState, BucketTableRow } from './BucketTableRow'
|
||||
import { BucketTableRow } from './BucketTableRow'
|
||||
import type { AllowedBucketType, BucketsTablePaginationProps } from './types'
|
||||
import { TableRowNoResults } from '@/components/ui/TableRowNoResults'
|
||||
import { VirtualizedTable, VirtualizedTableBody } from '@/components/ui/VirtualizedTable'
|
||||
import { type Bucket } from '@/data/storage/buckets-query'
|
||||
|
||||
@@ -47,7 +48,11 @@ const BucketsTableUnvirtualized = ({
|
||||
<BucketTableHeader mode="standard" hasBuckets={buckets.length > 0} />
|
||||
<TableBody>
|
||||
{showSearchEmptyState ? (
|
||||
<BucketTableEmptyState mode="standard" filterString={filterString} />
|
||||
<TableRowNoResults
|
||||
className="[&>td]:hover:bg-inherit"
|
||||
colSpan={5}
|
||||
search={filterString}
|
||||
/>
|
||||
) : (
|
||||
buckets.map((bucket) => (
|
||||
<BucketTableRow
|
||||
@@ -95,7 +100,11 @@ const BucketsTableVirtualized = ({
|
||||
paddingColSpan={5}
|
||||
emptyContent={
|
||||
showSearchEmptyState ? (
|
||||
<BucketTableEmptyState mode="virtualized" filterString={filterString} />
|
||||
<TableRowNoResults
|
||||
className="[&>td]:hover:bg-inherit"
|
||||
colSpan={5}
|
||||
search={filterString}
|
||||
/>
|
||||
) : undefined
|
||||
}
|
||||
trailingContent={
|
||||
|
||||
@@ -14,6 +14,7 @@ import {
|
||||
|
||||
import { PUBLIC_BUCKET_TOOLTIP } from '@/components/interfaces/Storage/Storage.constants'
|
||||
import { useBucketPolicyCount } from '@/components/interfaces/Storage/useBucketPolicyCount'
|
||||
import { TableRowNoResults } from '@/components/ui/TableRowNoResults'
|
||||
import {
|
||||
VirtualizedTableCell,
|
||||
VirtualizedTableHead,
|
||||
@@ -64,19 +65,22 @@ type BucketTableEmptyStateProps = {
|
||||
}
|
||||
|
||||
export const BucketTableEmptyState = ({ mode, filterString }: BucketTableEmptyStateProps) => {
|
||||
const BucketTableRow = mode === 'standard' ? TableRow : VirtualizedTableRow
|
||||
const BucketTableCell = mode === 'standard' ? TableCell : VirtualizedTableCell
|
||||
|
||||
return (
|
||||
<BucketTableRow className="[&>td]:hover:bg-inherit">
|
||||
<BucketTableCell colSpan={5}>
|
||||
<p className="text-sm text-foreground">No results found</p>
|
||||
<p className="text-sm text-foreground-lighter">
|
||||
Your search for “{filterString}” did not return any results
|
||||
</p>
|
||||
</BucketTableCell>
|
||||
</BucketTableRow>
|
||||
)
|
||||
if (mode === 'standard') {
|
||||
return (
|
||||
<TableRowNoResults className="[&>td]:hover:bg-inherit" colSpan={5} search={filterString} />
|
||||
)
|
||||
} else {
|
||||
return (
|
||||
<VirtualizedTableRow className="[&>td]:hover:bg-inherit">
|
||||
<VirtualizedTableCell colSpan={5}>
|
||||
<p className="text-sm text-foreground">No results found</p>
|
||||
<p className="text-sm text-foreground-lighter">
|
||||
Your search for “{filterString}” did not return any results
|
||||
</p>
|
||||
</VirtualizedTableCell>
|
||||
</VirtualizedTableRow>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
type BucketTableRowProps = {
|
||||
|
||||
@@ -3,7 +3,8 @@ import { Table, TableBody } from 'ui'
|
||||
|
||||
import { LoadMoreRow } from './BucketsTable.LoadMoreRow'
|
||||
import type { BucketsTablePaginationProps } from './BucketsTable.types'
|
||||
import { BucketTableEmptyState, BucketTableHeader, BucketTableRow } from './BucketTable'
|
||||
import { BucketTableHeader, BucketTableRow } from './BucketTable'
|
||||
import { TableRowNoResults } from '@/components/ui/TableRowNoResults'
|
||||
import { VirtualizedTable, VirtualizedTableBody } from '@/components/ui/VirtualizedTable'
|
||||
import { Bucket } from '@/data/storage/buckets-query'
|
||||
|
||||
@@ -15,8 +16,16 @@ type BucketsTableProps = {
|
||||
pagination: BucketsTablePaginationProps
|
||||
}
|
||||
|
||||
// [Joshen] To investigate: There's a lot of duplicate logic + components between
|
||||
// this FilesBuckets/BucketsTable and BucketsPickerDialog/BucketsTable. Check separately
|
||||
// if they can be cleaned up and consolidated. The latter should take precedence as it aims to
|
||||
// reduce footprint on the giant StorageExplorerState.
|
||||
|
||||
export const BucketsTable = (props: BucketsTableProps) => {
|
||||
// [Joshen] To investigate: Can't we just default to virtualized?
|
||||
// Do we need to dynamically decide whether to use a virtualized or unvirtualized one?
|
||||
const isVirtualized = props.buckets.length > 50
|
||||
|
||||
return isVirtualized ? (
|
||||
<BucketsTableVirtualized {...props} />
|
||||
) : (
|
||||
@@ -43,7 +52,11 @@ const BucketsTableUnvirtualized = ({
|
||||
<BucketTableHeader mode="standard" hasBuckets={buckets.length > 0} />
|
||||
<TableBody>
|
||||
{showSearchEmptyState ? (
|
||||
<BucketTableEmptyState mode="standard" filterString={filterString} />
|
||||
<TableRowNoResults
|
||||
className="[&>td]:hover:bg-inherit"
|
||||
colSpan={5}
|
||||
search={filterString}
|
||||
/>
|
||||
) : (
|
||||
buckets.map((bucket) => (
|
||||
<BucketTableRow
|
||||
@@ -89,7 +102,11 @@ const BucketsTableVirtualized = ({
|
||||
paddingColSpan={5}
|
||||
emptyContent={
|
||||
showSearchEmptyState ? (
|
||||
<BucketTableEmptyState mode="virtualized" filterString={filterString} />
|
||||
<TableRowNoResults
|
||||
className="[&>td]:hover:bg-inherit"
|
||||
colSpan={5}
|
||||
search={filterString}
|
||||
/>
|
||||
) : undefined
|
||||
}
|
||||
trailingContent={
|
||||
|
||||
@@ -269,7 +269,7 @@ export const FileExplorerColumn = ({
|
||||
<div
|
||||
className={`
|
||||
${fullWidth ? 'w-full' : 'w-64 border-r border-default'}
|
||||
px-2 py-1 my-1 flex shrink-0 flex-col space-y-2 overflow-auto
|
||||
px-2 py-1 my-1 flex flex-grow shrink-0 flex-col space-y-2 overflow-auto
|
||||
`}
|
||||
>
|
||||
<ShimmeringLoader />
|
||||
|
||||
+16
-19
@@ -45,6 +45,7 @@ import {
|
||||
ScaffoldSectionTitle,
|
||||
} from '@/components/layouts/Scaffold'
|
||||
import { AlertError } from '@/components/ui/AlertError'
|
||||
import { TableRowNoResults } from '@/components/ui/TableRowNoResults'
|
||||
import { useVectorBucketQuery } from '@/data/storage/vector-bucket-query'
|
||||
import { useVectorBucketsIndexesQuery } from '@/data/storage/vector-buckets-indexes-query'
|
||||
|
||||
@@ -182,25 +183,20 @@ export const VectorBucketDetails = () => {
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
{filteredList.length === 0 ? (
|
||||
<TableRow className="[&>td]:hover:bg-inherit">
|
||||
<TableCell colSpan={3}>
|
||||
{filterString.length > 0 ? (
|
||||
<>
|
||||
<p className="text-sm text-foreground">No results found</p>
|
||||
<p className="text-sm text-foreground-lighter">
|
||||
Your search for "{filterString}" did not return any results
|
||||
</p>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<p className="text-sm text-foreground">No tables yet</p>
|
||||
<p className="text-sm text-foreground-lighter">
|
||||
Create your first table to get started
|
||||
</p>
|
||||
</>
|
||||
)}
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRowNoResults
|
||||
className="[&>td]:hover:bg-inherit"
|
||||
colSpan={3}
|
||||
search={filterString}
|
||||
>
|
||||
{filterString.length === 0 ? (
|
||||
<>
|
||||
<p className="text-sm text-foreground">No tables yet</p>
|
||||
<p className="text-sm text-foreground-lighter">
|
||||
Create your first table to get started
|
||||
</p>
|
||||
</>
|
||||
) : undefined}
|
||||
</TableRowNoResults>
|
||||
) : (
|
||||
filteredList.map((index, idx: number) => {
|
||||
const id = `index-${idx}`
|
||||
@@ -225,6 +221,7 @@ export const VectorBucketDetails = () => {
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button
|
||||
aria-label="More options"
|
||||
className="w-7"
|
||||
icon={<MoreVertical />}
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
|
||||
@@ -16,6 +16,7 @@ import { CreateBucketButton } from '../NewBucketButton'
|
||||
import { CreateVectorBucketDialog } from './CreateVectorBucketDialog'
|
||||
import { VectorBucketsErrorState } from './VectorBucketsErrorState'
|
||||
import { AlphaNotice } from '@/components/ui/AlphaNotice'
|
||||
import { TableRowNoResults } from '@/components/ui/TableRowNoResults'
|
||||
import { useVectorBucketsQuery } from '@/data/storage/vector-buckets-query'
|
||||
import { createNavigationHandler } from '@/lib/navigation'
|
||||
|
||||
@@ -107,14 +108,11 @@ export const VectorsBuckets = () => {
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
{filteredBuckets.length === 0 && filterString.length > 0 && (
|
||||
<TableRow className="[&>td]:hover:bg-inherit">
|
||||
<TableCell colSpan={3}>
|
||||
<p className="text-sm text-foreground">No results found</p>
|
||||
<p className="text-sm text-foreground-lighter">
|
||||
Your search for "{filterString}" did not return any results
|
||||
</p>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRowNoResults
|
||||
className="[&>td]:hover:bg-inherit"
|
||||
colSpan={3}
|
||||
search={filterString}
|
||||
/>
|
||||
)}
|
||||
{filteredBuckets.map((bucket, idx: number) => {
|
||||
const id = `bucket-${idx}`
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
import { type PropsWithChildren } from 'react'
|
||||
import { TableCell, TableRow } from 'ui'
|
||||
|
||||
interface TableRowNoResultsProps {
|
||||
className?: string
|
||||
colSpan: number
|
||||
search?: string
|
||||
}
|
||||
|
||||
export const TableRowNoResults = ({
|
||||
className,
|
||||
colSpan,
|
||||
search,
|
||||
children,
|
||||
}: PropsWithChildren<TableRowNoResultsProps>) => {
|
||||
return (
|
||||
<TableRow className={className}>
|
||||
<TableCell colSpan={colSpan}>
|
||||
{children ?? (
|
||||
<>
|
||||
<p className="text-sm text-foreground">No results found</p>
|
||||
<p className="text-sm text-foreground-light">
|
||||
Your search for "{search}" did not return any results
|
||||
</p>
|
||||
</>
|
||||
)}
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
)
|
||||
}
|
||||
@@ -3,7 +3,7 @@ import { ExternalLink, RefreshCw, Search, X } from 'lucide-react'
|
||||
import { useRouter } from 'next/router'
|
||||
import { parseAsString, parseAsStringLiteral, useQueryState } from 'nuqs'
|
||||
import React, { useMemo, useRef, type PropsWithChildren } from 'react'
|
||||
import { Button, Card, Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from 'ui'
|
||||
import { Button, Card, Table, TableBody, TableHead, TableHeader, TableRow } from 'ui'
|
||||
import { Admonition } from 'ui-patterns/Admonition'
|
||||
import { Input } from 'ui-patterns/DataInputs/Input'
|
||||
import { PageContainer } from 'ui-patterns/PageContainer'
|
||||
@@ -35,6 +35,7 @@ import EdgeFunctionsLayout from '@/components/layouts/EdgeFunctionsLayout/EdgeFu
|
||||
import { AlertError } from '@/components/ui/AlertError'
|
||||
import { DocsButton } from '@/components/ui/DocsButton'
|
||||
import { ShortcutTooltip } from '@/components/ui/ShortcutTooltip'
|
||||
import { TableRowNoResults } from '@/components/ui/TableRowNoResults'
|
||||
import { useEdgeFunctionsQuery } from '@/data/edge-functions/edge-functions-query'
|
||||
import { useIsProjectActive } from '@/hooks/misc/useSelectedProject'
|
||||
import { DOCS_URL, IS_PLATFORM } from '@/lib/constants'
|
||||
@@ -145,6 +146,7 @@ const EdgeFunctionsPage: NextPageWithLayout = () => {
|
||||
actions={[
|
||||
search && (
|
||||
<Button
|
||||
aria-label="Clear search"
|
||||
key="clear"
|
||||
size="tiny"
|
||||
variant="text"
|
||||
@@ -200,14 +202,10 @@ const EdgeFunctionsPage: NextPageWithLayout = () => {
|
||||
<EdgeFunctionsListItem key={item.id} function={item} />
|
||||
))
|
||||
) : (
|
||||
<TableRow>
|
||||
<TableCell colSpan={showLastHourStats ? 8 : 6}>
|
||||
<p className="text-sm text-foreground">No results found</p>
|
||||
<p className="text-sm text-foreground-light">
|
||||
Your search for "{search}" did not return any results
|
||||
</p>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRowNoResults
|
||||
colSpan={showLastHourStats ? 8 : 6}
|
||||
search={search}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
</TableBody>
|
||||
|
||||
Reference in new issue
Block a user