From 42aa794713059ae76c094079568668c466283fa7 Mon Sep 17 00:00:00 2001 From: Lakee Sivaraya Date: Fri, 16 Jan 2026 12:18:38 -0800 Subject: [PATCH] updates --- .../{table-action-bar.tsx => action-bar.tsx} | 4 +- .../body-states.tsx} | 8 +- .../cell-renderer.tsx} | 8 +- .../components/cell-viewer-modal.tsx | 2 +- .../context-menu.tsx} | 6 +- .../header-bar.tsx} | 6 +- .../tables/[tableId]/components/index.ts | 14 +- .../pagination.tsx} | 6 +- .../components/query-builder/filter-row.tsx | 89 ++++++ .../components/query-builder/index.tsx | 137 +++++++++ .../components/query-builder/sort-row.tsx | 65 ++++ .../{table-row-modal.tsx => row-modal.tsx} | 14 +- .../schema-modal.tsx} | 6 +- .../components/table-query-builder.tsx | 288 ------------------ .../table-viewer.tsx} | 51 ++-- .../{table-data-viewer => }/hooks/index.ts | 0 .../hooks/use-context-menu.ts | 2 +- .../hooks/use-row-selection.ts | 0 .../hooks/use-table-data.ts | 6 +- .../{table-data-viewer => lib}/constants.ts | 0 .../tables/[tableId]/lib/index.ts | 3 + .../tables/[tableId]/lib/types.ts | 27 ++ .../{table-data-viewer => lib}/utils.ts | 9 +- .../[workspaceId]/tables/[tableId]/page.tsx | 4 +- .../table-data-viewer/components/index.ts | 7 - .../[tableId]/table-data-viewer/index.ts | 2 - .../[tableId]/table-data-viewer/types.ts | 13 - 27 files changed, 395 insertions(+), 382 deletions(-) rename apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/{table-action-bar.tsx => action-bar.tsx} (87%) rename apps/sim/app/workspace/[workspaceId]/tables/[tableId]/{table-data-viewer/components/table-body-states.tsx => components/body-states.tsx} (89%) rename apps/sim/app/workspace/[workspaceId]/tables/[tableId]/{table-data-viewer/components/table-cell-renderer.tsx => components/cell-renderer.tsx} (92%) rename apps/sim/app/workspace/[workspaceId]/tables/[tableId]/{table-data-viewer => }/components/cell-viewer-modal.tsx (98%) rename apps/sim/app/workspace/[workspaceId]/tables/[tableId]/{table-data-viewer/components/row-context-menu.tsx => components/context-menu.tsx} (86%) rename apps/sim/app/workspace/[workspaceId]/tables/[tableId]/{table-data-viewer/components/table-header-bar.tsx => components/header-bar.tsx} (95%) rename apps/sim/app/workspace/[workspaceId]/tables/[tableId]/{table-data-viewer/components/table-pagination.tsx => components/pagination.tsx} (91%) create mode 100644 apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/query-builder/filter-row.tsx create mode 100644 apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/query-builder/index.tsx create mode 100644 apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/query-builder/sort-row.tsx rename apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/{table-row-modal.tsx => row-modal.tsx} (98%) rename apps/sim/app/workspace/[workspaceId]/tables/[tableId]/{table-data-viewer/components/schema-viewer-modal.tsx => components/schema-modal.tsx} (94%) delete mode 100644 apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/table-query-builder.tsx rename apps/sim/app/workspace/[workspaceId]/tables/[tableId]/{table-data-viewer/table-data-viewer.tsx => components/table-viewer.tsx} (91%) rename apps/sim/app/workspace/[workspaceId]/tables/[tableId]/{table-data-viewer => }/hooks/index.ts (100%) rename apps/sim/app/workspace/[workspaceId]/tables/[tableId]/{table-data-viewer => }/hooks/use-context-menu.ts (94%) rename apps/sim/app/workspace/[workspaceId]/tables/[tableId]/{table-data-viewer => }/hooks/use-row-selection.ts (100%) rename apps/sim/app/workspace/[workspaceId]/tables/[tableId]/{table-data-viewer => }/hooks/use-table-data.ts (93%) rename apps/sim/app/workspace/[workspaceId]/tables/[tableId]/{table-data-viewer => lib}/constants.ts (100%) create mode 100644 apps/sim/app/workspace/[workspaceId]/tables/[tableId]/lib/index.ts create mode 100644 apps/sim/app/workspace/[workspaceId]/tables/[tableId]/lib/types.ts rename apps/sim/app/workspace/[workspaceId]/tables/[tableId]/{table-data-viewer => lib}/utils.ts (53%) delete mode 100644 apps/sim/app/workspace/[workspaceId]/tables/[tableId]/table-data-viewer/components/index.ts delete mode 100644 apps/sim/app/workspace/[workspaceId]/tables/[tableId]/table-data-viewer/index.ts delete mode 100644 apps/sim/app/workspace/[workspaceId]/tables/[tableId]/table-data-viewer/types.ts diff --git a/apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/table-action-bar.tsx b/apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/action-bar.tsx similarity index 87% rename from apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/table-action-bar.tsx rename to apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/action-bar.tsx index a8bbfe054..c5472658a 100644 --- a/apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/table-action-bar.tsx +++ b/apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/action-bar.tsx @@ -3,13 +3,13 @@ import { Trash2, X } from 'lucide-react' import { Button } from '@/components/emcn' -interface TableActionBarProps { +interface ActionBarProps { selectedCount: number onDelete: () => void onClearSelection: () => void } -export function TableActionBar({ selectedCount, onDelete, onClearSelection }: TableActionBarProps) { +export function ActionBar({ selectedCount, onDelete, onClearSelection }: ActionBarProps) { return (
diff --git a/apps/sim/app/workspace/[workspaceId]/tables/[tableId]/table-data-viewer/components/table-body-states.tsx b/apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/body-states.tsx similarity index 89% rename from apps/sim/app/workspace/[workspaceId]/tables/[tableId]/table-data-viewer/components/table-body-states.tsx rename to apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/body-states.tsx index d5c8cf874..3f391ac1e 100644 --- a/apps/sim/app/workspace/[workspaceId]/tables/[tableId]/table-data-viewer/components/table-body-states.tsx +++ b/apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/body-states.tsx @@ -3,11 +3,11 @@ import { Button, TableCell, TableRow } from '@/components/emcn' import { Skeleton } from '@/components/ui/skeleton' import type { ColumnDefinition } from '@/lib/table' -interface TableLoadingRowsProps { +interface LoadingRowsProps { columns: ColumnDefinition[] } -export function TableLoadingRows({ columns }: TableLoadingRowsProps) { +export function LoadingRows({ columns }: LoadingRowsProps) { return ( <> {Array.from({ length: 25 }).map((_, rowIndex) => ( @@ -43,13 +43,13 @@ export function TableLoadingRows({ columns }: TableLoadingRowsProps) { ) } -interface TableEmptyRowsProps { +interface EmptyRowsProps { columnCount: number hasFilter: boolean onAddRow: () => void } -export function TableEmptyRows({ columnCount, hasFilter, onAddRow }: TableEmptyRowsProps) { +export function EmptyRows({ columnCount, hasFilter, onAddRow }: EmptyRowsProps) { return ( diff --git a/apps/sim/app/workspace/[workspaceId]/tables/[tableId]/table-data-viewer/components/table-cell-renderer.tsx b/apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/cell-renderer.tsx similarity index 92% rename from apps/sim/app/workspace/[workspaceId]/tables/[tableId]/table-data-viewer/components/table-cell-renderer.tsx rename to apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/cell-renderer.tsx index b9537e257..f4e97e555 100644 --- a/apps/sim/app/workspace/[workspaceId]/tables/[tableId]/table-data-viewer/components/table-cell-renderer.tsx +++ b/apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/cell-renderer.tsx @@ -1,14 +1,14 @@ import type { ColumnDefinition } from '@/lib/table' -import { STRING_TRUNCATE_LENGTH } from '../constants' -import type { CellViewerData } from '../types' +import { STRING_TRUNCATE_LENGTH } from '../lib/constants' +import type { CellViewerData } from '../lib/types' -interface TableCellRendererProps { +interface CellRendererProps { value: unknown column: ColumnDefinition onCellClick: (columnName: string, value: unknown, type: CellViewerData['type']) => void } -export function TableCellRenderer({ value, column, onCellClick }: TableCellRendererProps) { +export function CellRenderer({ value, column, onCellClick }: CellRendererProps) { const isNull = value === null || value === undefined if (isNull) { diff --git a/apps/sim/app/workspace/[workspaceId]/tables/[tableId]/table-data-viewer/components/cell-viewer-modal.tsx b/apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/cell-viewer-modal.tsx similarity index 98% rename from apps/sim/app/workspace/[workspaceId]/tables/[tableId]/table-data-viewer/components/cell-viewer-modal.tsx rename to apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/cell-viewer-modal.tsx index 5a9f7f433..8139d2273 100644 --- a/apps/sim/app/workspace/[workspaceId]/tables/[tableId]/table-data-viewer/components/cell-viewer-modal.tsx +++ b/apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/cell-viewer-modal.tsx @@ -1,6 +1,6 @@ import { Copy, X } from 'lucide-react' import { Badge, Button, Modal, ModalBody, ModalContent } from '@/components/emcn' -import type { CellViewerData } from '../types' +import type { CellViewerData } from '../lib/types' interface CellViewerModalProps { cellViewer: CellViewerData | null diff --git a/apps/sim/app/workspace/[workspaceId]/tables/[tableId]/table-data-viewer/components/row-context-menu.tsx b/apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/context-menu.tsx similarity index 86% rename from apps/sim/app/workspace/[workspaceId]/tables/[tableId]/table-data-viewer/components/row-context-menu.tsx rename to apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/context-menu.tsx index 663a52977..eb1dcb898 100644 --- a/apps/sim/app/workspace/[workspaceId]/tables/[tableId]/table-data-viewer/components/row-context-menu.tsx +++ b/apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/context-menu.tsx @@ -6,16 +6,16 @@ import { PopoverDivider, PopoverItem, } from '@/components/emcn' -import type { ContextMenuState } from '../types' +import type { ContextMenuState } from '../lib/types' -interface RowContextMenuProps { +interface ContextMenuProps { contextMenu: ContextMenuState onClose: () => void onEdit: () => void onDelete: () => void } -export function RowContextMenu({ contextMenu, onClose, onEdit, onDelete }: RowContextMenuProps) { +export function ContextMenu({ contextMenu, onClose, onEdit, onDelete }: ContextMenuProps) { return ( void } -export function TableHeaderBar({ +export function HeaderBar({ tableName, totalCount, isLoading, onNavigateBack, onShowSchema, onRefresh, -}: TableHeaderBarProps) { +}: HeaderBarProps) { return (
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 -}