diff --git a/apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/index.ts b/apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/index.ts
index f3df3db82..e4594de05 100644
--- a/apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/index.ts
+++ b/apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/index.ts
@@ -1,3 +1,11 @@
-export * from './table-action-bar'
-export * from './table-query-builder'
-export * from './table-row-modal'
+export * from './action-bar'
+export * from './body-states'
+export * from './cell-renderer'
+export * from './cell-viewer-modal'
+export * from './context-menu'
+export * from './header-bar'
+export * from './pagination'
+export * from './query-builder'
+export * from './row-modal'
+export * from './schema-modal'
+export * from './table-viewer'
diff --git a/apps/sim/app/workspace/[workspaceId]/tables/[tableId]/table-data-viewer/components/table-pagination.tsx b/apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/pagination.tsx
similarity index 91%
rename from apps/sim/app/workspace/[workspaceId]/tables/[tableId]/table-data-viewer/components/table-pagination.tsx
rename to apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/pagination.tsx
index 2c2f7aa1d..e73256a63 100644
--- a/apps/sim/app/workspace/[workspaceId]/tables/[tableId]/table-data-viewer/components/table-pagination.tsx
+++ b/apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/pagination.tsx
@@ -1,6 +1,6 @@
import { Button } from '@/components/emcn'
-interface TablePaginationProps {
+interface PaginationProps {
currentPage: number
totalPages: number
totalCount: number
@@ -8,13 +8,13 @@ interface TablePaginationProps {
onNextPage: () => void
}
-export function TablePagination({
+export function Pagination({
currentPage,
totalPages,
totalCount,
onPreviousPage,
onNextPage,
-}: TablePaginationProps) {
+}: PaginationProps) {
if (totalPages <= 1) return null
return (
diff --git a/apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/query-builder/filter-row.tsx b/apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/query-builder/filter-row.tsx
new file mode 100644
index 000000000..8667494bc
--- /dev/null
+++ b/apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/query-builder/filter-row.tsx
@@ -0,0 +1,89 @@
+'use client'
+
+import { X } from 'lucide-react'
+import { Button, Combobox, Input } from '@/components/emcn'
+import type { FilterRule } from '@/lib/table/filters/constants'
+
+interface FilterRowProps {
+ rule: FilterRule
+ index: number
+ columnOptions: Array<{ value: string; label: string }>
+ comparisonOptions: Array<{ value: string; label: string }>
+ logicalOptions: Array<{ value: string; label: string }>
+ onUpdate: (id: string, field: keyof FilterRule, value: string) => void
+ onRemove: (id: string) => void
+ onApply: () => void
+}
+
+export function FilterRow({
+ rule,
+ index,
+ columnOptions,
+ comparisonOptions,
+ logicalOptions,
+ onUpdate,
+ onRemove,
+ onApply,
+}: FilterRowProps) {
+ return (
+
+
+
+
+ {index === 0 ? (
+
+ ) : (
+ onUpdate(rule.id, 'logicalOperator', value as 'and' | 'or')}
+ />
+ )}
+
+
+
+ onUpdate(rule.id, 'column', value)}
+ placeholder='Column'
+ />
+
+
+
+ onUpdate(rule.id, 'operator', value)}
+ />
+
+
+
onUpdate(rule.id, 'value', e.target.value)}
+ placeholder='Value'
+ onKeyDown={(e) => {
+ if (e.key === 'Enter') {
+ onApply()
+ }
+ }}
+ />
+
+ )
+}
diff --git a/apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/query-builder/index.tsx b/apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/query-builder/index.tsx
new file mode 100644
index 000000000..52ed542e9
--- /dev/null
+++ b/apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/query-builder/index.tsx
@@ -0,0 +1,137 @@
+'use client'
+
+import { useCallback, useMemo, useState } from 'react'
+import { ArrowUpAZ, Loader2, Plus } from 'lucide-react'
+import { nanoid } from 'nanoid'
+import { Button } from '@/components/emcn'
+import type { FilterRule, SortRule } from '@/lib/table/filters/constants'
+import { useFilterBuilder } from '@/lib/table/filters/use-builder'
+import { filterRulesToFilter, sortRuleToSort } from '@/lib/table/filters/utils'
+import type { ColumnDefinition } from '@/lib/table/types'
+import type { QueryOptions } from '../../lib/types'
+import { FilterRow } from './filter-row'
+import { SortRow } from './sort-row'
+
+type Column = Pick
+
+interface QueryBuilderProps {
+ columns: Column[]
+ onApply: (options: QueryOptions) => void
+ onAddRow: () => void
+ isLoading?: boolean
+}
+
+export function QueryBuilder({ columns, onApply, onAddRow, isLoading = false }: QueryBuilderProps) {
+ const [rules, setRules] = useState([])
+ const [sortRule, setSortRule] = useState(null)
+
+ const columnOptions = useMemo(
+ () => columns.map((col) => ({ value: col.name, label: col.name })),
+ [columns]
+ )
+
+ const {
+ comparisonOptions,
+ logicalOptions,
+ sortDirectionOptions,
+ addRule: handleAddRule,
+ removeRule: handleRemoveRule,
+ updateRule: handleUpdateRule,
+ } = useFilterBuilder({
+ columns: columnOptions,
+ rules,
+ setRules,
+ })
+
+ const handleAddSort = useCallback(() => {
+ setSortRule({
+ id: nanoid(),
+ column: columns[0]?.name || '',
+ direction: 'asc',
+ })
+ }, [columns])
+
+ const handleRemoveSort = useCallback(() => {
+ setSortRule(null)
+ }, [])
+
+ const handleApply = useCallback(() => {
+ const filter = filterRulesToFilter(rules)
+ const sort = sortRuleToSort(sortRule)
+ onApply({ filter, sort })
+ }, [rules, sortRule, onApply])
+
+ const handleClear = useCallback(() => {
+ setRules([])
+ setSortRule(null)
+ onApply({
+ filter: null,
+ sort: null,
+ })
+ }, [onApply])
+
+ const hasChanges = rules.length > 0 || sortRule !== null
+
+ return (
+
+ {rules.map((rule, index) => (
+
+ ))}
+
+ {sortRule && (
+
+ )}
+
+
+
+
+
+
+ {!sortRule && (
+
+ )}
+
+ {hasChanges && (
+ <>
+
+
+
+ >
+ )}
+
+
+ )
+}
diff --git a/apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/query-builder/sort-row.tsx b/apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/query-builder/sort-row.tsx
new file mode 100644
index 000000000..578567119
--- /dev/null
+++ b/apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/query-builder/sort-row.tsx
@@ -0,0 +1,65 @@
+'use client'
+
+import { ArrowDownAZ, ArrowUpAZ, X } from 'lucide-react'
+import { Button, Combobox } from '@/components/emcn'
+import type { SortRule } from '@/lib/table/filters/constants'
+
+interface SortRowProps {
+ sortRule: SortRule
+ columnOptions: Array<{ value: string; label: string }>
+ sortDirectionOptions: Array<{ value: string; label: string }>
+ onChange: (rule: SortRule | null) => void
+ onRemove: () => void
+}
+
+export function SortRow({
+ sortRule,
+ columnOptions,
+ sortDirectionOptions,
+ onChange,
+ onRemove,
+}: SortRowProps) {
+ return (
+
+
+
+
+
+
+
+
+ onChange({ ...sortRule, column: value })}
+ placeholder='Column'
+ />
+
+
+
+ onChange({ ...sortRule, direction: value as 'asc' | 'desc' })}
+ />
+
+
+
+ {sortRule.direction === 'asc' ? (
+
+ ) : (
+
+ )}
+
+
+ )
+}
diff --git a/apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/table-row-modal.tsx b/apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/row-modal.tsx
similarity index 98%
rename from apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/table-row-modal.tsx
rename to apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/row-modal.tsx
index 9c3ee999b..c5614c1a8 100644
--- a/apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/table-row-modal.tsx
+++ b/apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/row-modal.tsx
@@ -18,9 +18,9 @@ import {
import { Input } from '@/components/ui/input'
import type { ColumnDefinition, TableInfo, TableRow } from '@/lib/table'
-const logger = createLogger('TableRowModal')
+const logger = createLogger('RowModal')
-export interface TableRowModalProps {
+export interface RowModalProps {
mode: 'add' | 'edit' | 'delete'
isOpen: boolean
onClose: () => void
@@ -92,15 +92,7 @@ function formatValueForInput(value: unknown, type: string): string {
return String(value)
}
-export function TableRowModal({
- mode,
- isOpen,
- onClose,
- table,
- row,
- rowIds,
- onSuccess,
-}: TableRowModalProps) {
+export function RowModal({ mode, isOpen, onClose, table, row, rowIds, onSuccess }: RowModalProps) {
const params = useParams()
const workspaceId = params.workspaceId as string
diff --git a/apps/sim/app/workspace/[workspaceId]/tables/[tableId]/table-data-viewer/components/schema-viewer-modal.tsx b/apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/schema-modal.tsx
similarity index 94%
rename from apps/sim/app/workspace/[workspaceId]/tables/[tableId]/table-data-viewer/components/schema-viewer-modal.tsx
rename to apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/schema-modal.tsx
index 697930ff4..9963ada0a 100644
--- a/apps/sim/app/workspace/[workspaceId]/tables/[tableId]/table-data-viewer/components/schema-viewer-modal.tsx
+++ b/apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/schema-modal.tsx
@@ -13,15 +13,15 @@ import {
TableRow,
} from '@/components/emcn'
import type { ColumnDefinition } from '@/lib/table'
-import { getTypeBadgeVariant } from '../utils'
+import { getTypeBadgeVariant } from '../lib/utils'
-interface SchemaViewerModalProps {
+interface SchemaModalProps {
isOpen: boolean
onClose: () => void
columns: ColumnDefinition[]
}
-export function SchemaViewerModal({ isOpen, onClose, columns }: SchemaViewerModalProps) {
+export function SchemaModal({ isOpen, onClose, columns }: SchemaModalProps) {
return (
diff --git a/apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/table-query-builder.tsx b/apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/table-query-builder.tsx
deleted file mode 100644
index 499a2e271..000000000
--- a/apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/table-query-builder.tsx
+++ /dev/null
@@ -1,288 +0,0 @@
-'use client'
-
-import { useCallback, useMemo, useState } from 'react'
-import { ArrowDownAZ, ArrowUpAZ, Loader2, Plus, X } from 'lucide-react'
-import { nanoid } from 'nanoid'
-import { Button, Combobox, Input } from '@/components/emcn'
-import type { FilterRule, SortRule } from '@/lib/table/filters/constants'
-import { useFilterBuilder } from '@/lib/table/filters/use-builder'
-import { filterRulesToFilter, sortRuleToSort } from '@/lib/table/filters/utils'
-import type { ColumnDefinition, Filter, Sort } from '@/lib/table/types'
-
-export interface BuilderQueryResult {
- filter: Filter | null
- sort: Sort | null
-}
-
-type Column = Pick
-
-interface TableQueryBuilderProps {
- columns: Column[]
- onApply: (options: BuilderQueryResult) => void
- onAddRow: () => void
- isLoading?: boolean
-}
-
-export function TableQueryBuilder({
- columns,
- onApply,
- onAddRow,
- isLoading = false,
-}: TableQueryBuilderProps) {
- const [rules, setRules] = useState([])
- const [sortRule, setSortRule] = useState(null)
-
- const columnOptions = useMemo(
- () => columns.map((col) => ({ value: col.name, label: col.name })),
- [columns]
- )
-
- const {
- comparisonOptions,
- logicalOptions,
- sortDirectionOptions,
- addRule: handleAddRule,
- removeRule: handleRemoveRule,
- updateRule: handleUpdateRule,
- } = useFilterBuilder({
- columns: columnOptions,
- rules,
- setRules,
- })
-
- const handleAddSort = useCallback(() => {
- setSortRule({
- id: nanoid(),
- column: columns[0]?.name || '',
- direction: 'asc',
- })
- }, [columns])
-
- const handleRemoveSort = useCallback(() => {
- setSortRule(null)
- }, [])
-
- const handleApply = useCallback(() => {
- const filter = filterRulesToFilter(rules)
- const sort = sortRuleToSort(sortRule)
- onApply({ filter, sort })
- }, [rules, sortRule, onApply])
-
- const handleClear = useCallback(() => {
- setRules([])
- setSortRule(null)
- onApply({
- filter: null,
- sort: null,
- })
- }, [onApply])
-
- const hasChanges = rules.length > 0 || sortRule !== null
-
- return (
-
- {rules.map((rule, index) => (
-
- ))}
-
- {sortRule && (
-
- )}
-
-
-
-
-
-
- {!sortRule && (
-
- )}
-
- {hasChanges && (
- <>
-
-
-
- >
- )}
-
-
- )
-}
-
-interface FilterRuleRowProps {
- rule: FilterRule
- index: number
- columnOptions: Array<{ value: string; label: string }>
- comparisonOptions: Array<{ value: string; label: string }>
- logicalOptions: Array<{ value: string; label: string }>
- onUpdate: (id: string, field: keyof FilterRule, value: string) => void
- onRemove: (id: string) => void
- onApply: () => void
-}
-
-function FilterRuleRow({
- rule,
- index,
- columnOptions,
- comparisonOptions,
- logicalOptions,
- onUpdate,
- onRemove,
- onApply,
-}: FilterRuleRowProps) {
- return (
-
-
-
-
- {index === 0 ? (
-
- ) : (
- onUpdate(rule.id, 'logicalOperator', value as 'and' | 'or')}
- />
- )}
-
-
-
- onUpdate(rule.id, 'column', value)}
- placeholder='Column'
- />
-
-
-
- onUpdate(rule.id, 'operator', value)}
- />
-
-
-
onUpdate(rule.id, 'value', e.target.value)}
- placeholder='Value'
- onKeyDown={(e) => {
- if (e.key === 'Enter') {
- onApply()
- }
- }}
- />
-
- )
-}
-
-interface SortRuleRowProps {
- sortRule: SortRule
- columnOptions: Array<{ value: string; label: string }>
- sortDirectionOptions: Array<{ value: string; label: string }>
- onChange: (rule: SortRule | null) => void
- onRemove: () => void
-}
-
-function SortRuleRow({
- sortRule,
- columnOptions,
- sortDirectionOptions,
- onChange,
- onRemove,
-}: SortRuleRowProps) {
- return (
-
-
-
-
-
-
-
-
- onChange({ ...sortRule, column: value })}
- placeholder='Column'
- />
-
-
-
- onChange({ ...sortRule, direction: value as 'asc' | 'desc' })}
- />
-
-
-
- {sortRule.direction === 'asc' ? (
-
- ) : (
-
- )}
-
-
- )
-}
diff --git a/apps/sim/app/workspace/[workspaceId]/tables/[tableId]/table-data-viewer/table-data-viewer.tsx b/apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/table-viewer.tsx
similarity index 91%
rename from apps/sim/app/workspace/[workspaceId]/tables/[tableId]/table-data-viewer/table-data-viewer.tsx
rename to apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/table-viewer.tsx
index 511e4b912..9560d380f 100644
--- a/apps/sim/app/workspace/[workspaceId]/tables/[tableId]/table-data-viewer/table-data-viewer.tsx
+++ b/apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/table-viewer.tsx
@@ -14,21 +14,20 @@ import {
} from '@/components/emcn'
import { cn } from '@/lib/core/utils/cn'
import type { TableRow as TableRowType } from '@/lib/table'
-import { type QueryOptions, TableActionBar, TableQueryBuilder, TableRowModal } from '../components'
-import {
- CellViewerModal,
- RowContextMenu,
- SchemaViewerModal,
- TableCellRenderer,
- TableEmptyRows,
- TableHeaderBar,
- TableLoadingRows,
- TablePagination,
-} from './components'
-import { useContextMenu, useRowSelection, useTableData } from './hooks'
-import type { CellViewerData } from './types'
+import { useContextMenu, useRowSelection, useTableData } from '../hooks'
+import type { CellViewerData, QueryOptions } from '../lib/types'
+import { ActionBar } from './action-bar'
+import { EmptyRows, LoadingRows } from './body-states'
+import { CellRenderer } from './cell-renderer'
+import { CellViewerModal } from './cell-viewer-modal'
+import { ContextMenu } from './context-menu'
+import { HeaderBar } from './header-bar'
+import { Pagination } from './pagination'
+import { QueryBuilder } from './query-builder'
+import { RowModal } from './row-modal'
+import { SchemaModal } from './schema-modal'
-export function TableDataViewer() {
+export function TableViewer() {
const params = useParams()
const router = useRouter()
@@ -146,7 +145,7 @@ export function TableDataViewer() {
return (
-
-
{hasSelection && (
-
{isLoadingRows ? (
-
+
) : rows.length === 0 ? (
- (
- setCurrentPage((p) => Math.min(totalPages - 1, p + 1))}
/>
- setShowAddModal(false)}
@@ -261,7 +260,7 @@ export function TableDataViewer() {
/>
{editingRow && (
- setEditingRow(null)}
@@ -275,7 +274,7 @@ export function TableDataViewer() {
)}
{deletingRows.length > 0 && (
- setDeletingRows([])}
@@ -289,7 +288,7 @@ export function TableDataViewer() {
/>
)}
- setShowSchemaModal(false)}
columns={columns}
@@ -302,7 +301,7 @@ export function TableDataViewer() {
copied={copied}
/>
-
+ return
}
diff --git a/apps/sim/app/workspace/[workspaceId]/tables/[tableId]/table-data-viewer/components/index.ts b/apps/sim/app/workspace/[workspaceId]/tables/[tableId]/table-data-viewer/components/index.ts
deleted file mode 100644
index 7658c1d17..000000000
--- a/apps/sim/app/workspace/[workspaceId]/tables/[tableId]/table-data-viewer/components/index.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-export * from './cell-viewer-modal'
-export * from './row-context-menu'
-export * from './schema-viewer-modal'
-export * from './table-body-states'
-export * from './table-cell-renderer'
-export * from './table-header-bar'
-export * from './table-pagination'
diff --git a/apps/sim/app/workspace/[workspaceId]/tables/[tableId]/table-data-viewer/index.ts b/apps/sim/app/workspace/[workspaceId]/tables/[tableId]/table-data-viewer/index.ts
deleted file mode 100644
index e20e57e26..000000000
--- a/apps/sim/app/workspace/[workspaceId]/tables/[tableId]/table-data-viewer/index.ts
+++ /dev/null
@@ -1,2 +0,0 @@
-export * from './table-data-viewer'
-export * from './types'
diff --git a/apps/sim/app/workspace/[workspaceId]/tables/[tableId]/table-data-viewer/types.ts b/apps/sim/app/workspace/[workspaceId]/tables/[tableId]/table-data-viewer/types.ts
deleted file mode 100644
index 172ee9b77..000000000
--- a/apps/sim/app/workspace/[workspaceId]/tables/[tableId]/table-data-viewer/types.ts
+++ /dev/null
@@ -1,13 +0,0 @@
-import type { TableRow } from '@/lib/table'
-
-export interface CellViewerData {
- columnName: string
- value: unknown
- type: 'json' | 'text' | 'date' | 'boolean' | 'number'
-}
-
-export interface ContextMenuState {
- isOpen: boolean
- position: { x: number; y: number }
- row: TableRow | null
-}