mirror of
https://github.com/simstudioai/sim.git
synced 2026-04-06 03:00:16 -04:00
update table-selector
This commit is contained in:
@@ -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,
|
||||
|
||||
@@ -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...'
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user