update table-selector

This commit is contained in:
waleed
2026-02-19 12:16:57 -08:00
parent 592dd46dd8
commit f1938f008a
3 changed files with 79 additions and 55 deletions

View File

@@ -118,7 +118,6 @@ import {
StagehandIcon,
StripeIcon,
SupabaseIcon,
TableIcon,
TavilyIcon,
TelegramIcon,
TextractIcon,
@@ -258,7 +257,6 @@ export const blockTypeToIconMap: Record<string, IconComponent> = {
stripe: StripeIcon,
stt_v2: STTIcon,
supabase: SupabaseIcon,
table: TableIcon,
tavily: TavilyIcon,
telegram: TelegramIcon,
textract_v2: TextractIcon,

View File

@@ -1,10 +1,8 @@
'use client'
import { useCallback, useMemo } from 'react'
import { ExternalLink } from 'lucide-react'
import { useParams } from 'next/navigation'
import { Combobox, type ComboboxOption, Tooltip } from '@/components/emcn'
import { Button } from '@/components/ui/button'
import { Combobox, type ComboboxOption } from '@/components/emcn'
import { useSubBlockValue } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-sub-block-value'
import type { SubBlockConfig } from '@/blocks/types'
import { useTablesList } from '@/hooks/queries/tables'
@@ -18,12 +16,12 @@ interface TableSelectorProps {
}
/**
* Table selector component with dropdown and link to view table
* Table selector component with dropdown for selecting workspace tables
*
* @remarks
* Provides a dropdown to select workspace tables and an external link
* to navigate directly to the table page view when a table is selected.
* Provides a dropdown to select workspace tables.
* Uses React Query for efficient data fetching and caching.
* The external link to view the table is rendered in the label row by the parent SubBlock.
*/
export function TableSelector({
blockId,
@@ -37,7 +35,6 @@ export function TableSelector({
const [storeValue, setStoreValue] = useSubBlockValue<string>(blockId, subBlock.id)
// Use React Query hook for table data - it handles caching, loading, and error states
const {
data: tables = [],
isLoading,
@@ -62,50 +59,20 @@ export function TableSelector({
[isPreview, disabled, setStoreValue]
)
const handleNavigateToTable = useCallback(() => {
if (tableId && workspaceId) {
window.open(`/workspace/${workspaceId}/tables/${tableId}`, '_blank')
}
}, [workspaceId, tableId])
const hasSelectedTable = tableId && !tableId.startsWith('<')
// Convert error object to string if needed
const errorMessage = error instanceof Error ? error.message : error ? String(error) : undefined
return (
<div className='flex items-center gap-[6px]'>
<div className='flex-1'>
<Combobox
options={options}
value={tableId ?? undefined}
onChange={handleChange}
placeholder={subBlock.placeholder || 'Select a table'}
disabled={disabled || isPreview}
editable={false}
isLoading={isLoading}
error={errorMessage}
searchable={options.length > 5}
searchPlaceholder='Search...'
/>
</div>
{hasSelectedTable && !isPreview && (
<Tooltip.Root>
<Tooltip.Trigger asChild>
<Button
variant='ghost'
size='sm'
className='h-[30px] w-[30px] flex-shrink-0 p-0'
onClick={handleNavigateToTable}
>
<ExternalLink className='h-[14px] w-[14px] text-[var(--text-secondary)]' />
</Button>
</Tooltip.Trigger>
<Tooltip.Content side='top'>
<p>View table</p>
</Tooltip.Content>
</Tooltip.Root>
)}
</div>
<Combobox
options={options}
value={tableId ?? undefined}
onChange={handleChange}
placeholder={subBlock.placeholder || 'Select a table'}
disabled={disabled || isPreview}
editable={false}
isLoading={isLoading}
error={errorMessage}
searchable={options.length > 5}
searchPlaceholder='Search...'
/>
)
}

View File

@@ -1,6 +1,14 @@
import { type JSX, type MouseEvent, memo, useCallback, useRef, useState } from 'react'
import { type JSX, type MouseEvent, memo, useCallback, useMemo, useRef, useState } from 'react'
import isEqual from 'lodash/isEqual'
import { AlertTriangle, ArrowLeftRight, ArrowUp, Check, Clipboard } from 'lucide-react'
import {
AlertTriangle,
ArrowLeftRight,
ArrowUp,
Check,
Clipboard,
ExternalLink,
} from 'lucide-react'
import { useParams } from 'next/navigation'
import { Button, Input, Label, Tooltip } from '@/components/emcn/components'
import { cn } from '@/lib/core/utils/cn'
import type { FilterRule, SortRule } from '@/lib/table/query-builder/constants'
@@ -206,7 +214,12 @@ const renderLabel = (
copied: boolean
onCopy: () => void
},
labelSuffix?: React.ReactNode
labelSuffix?: React.ReactNode,
externalLink?: {
show: boolean
onClick: () => void
tooltip: string
}
): JSX.Element | null => {
if (config.type === 'switch') return null
if (!config.title) return null
@@ -215,6 +228,7 @@ const renderLabel = (
const showWand = wandState?.isWandEnabled && !wandState.isPreview && !wandState.disabled
const showCanonicalToggle = !!canonicalToggle && !wandState?.isPreview
const showCopy = copyState?.showCopyButton && !wandState?.isPreview
const showExternalLink = externalLink?.show && !wandState?.isPreview
const canonicalToggleDisabledResolved = canonicalToggleIsDisabled ?? canonicalToggle?.disabled
return (
@@ -355,6 +369,23 @@ const renderLabel = (
</Tooltip.Content>
</Tooltip.Root>
)}
{showExternalLink && (
<Tooltip.Root>
<Tooltip.Trigger asChild>
<button
type='button'
className='flex h-[12px] w-[12px] flex-shrink-0 items-center justify-center bg-transparent p-0'
onClick={externalLink?.onClick}
aria-label={externalLink?.tooltip}
>
<ExternalLink className='!h-[12px] !w-[12px] text-[var(--text-secondary)]' />
</button>
</Tooltip.Trigger>
<Tooltip.Content side='top'>
<p>{externalLink?.tooltip}</p>
</Tooltip.Content>
</Tooltip.Root>
)}
</div>
</div>
)
@@ -419,6 +450,9 @@ function SubBlockComponent({
labelSuffix,
dependencyContext,
}: SubBlockProps): JSX.Element {
const params = useParams()
const workspaceId = params.workspaceId as string
const [isValidJson, setIsValidJson] = useState(true)
const [isSearchActive, setIsSearchActive] = useState(false)
const [searchQuery, setSearchQuery] = useState('')
@@ -455,6 +489,30 @@ function SubBlockComponent({
}
}, [webhookManagement?.webhookUrl])
const tableId =
config.type === 'table-selector' && subBlockValues
? (subBlockValues[config.id]?.value as string | null)
: null
const hasSelectedTable = tableId && !tableId.startsWith('<')
const handleNavigateToTable = useCallback(() => {
if (tableId && workspaceId) {
window.open(`/workspace/${workspaceId}/tables/${tableId}`, '_blank')
}
}, [workspaceId, tableId])
const externalLink = useMemo(
() =>
config.type === 'table-selector' && hasSelectedTable
? {
show: true,
onClick: handleNavigateToTable,
tooltip: 'View table',
}
: undefined,
[config.type, hasSelectedTable, handleNavigateToTable]
)
/**
* Handles wand icon click to activate inline prompt mode.
* Focuses the input after a brief delay to ensure DOM is ready.
@@ -1099,7 +1157,8 @@ function SubBlockComponent({
copied,
onCopy: handleCopy,
},
labelSuffix
labelSuffix,
externalLink
)}
{renderInput()}
</div>