This commit is contained in:
Lakee Sivaraya
2026-01-14 18:23:01 -08:00
parent b3ca0c947c
commit df3e869f22
13 changed files with 32 additions and 108 deletions

View File

@@ -7,7 +7,7 @@ import { z } from 'zod'
import { checkHybridAuth } from '@/lib/auth/hybrid'
import { generateRequestId } from '@/lib/core/utils/request'
import { TABLE_LIMITS, validateTableName, validateTableSchema } from '@/lib/table'
import type { TableSchema } from '@/lib/table/validation/validation'
import type { TableSchema } from '@/lib/table/validation/schema'
import type { TableColumnData, TableSchemaData } from './utils'
const logger = createLogger('TableAPI')

View File

@@ -3,8 +3,8 @@
import { useCallback, useMemo, useState } from 'react'
import { ArrowDownAZ, ArrowUpAZ, Plus, X } from 'lucide-react'
import { Button, Combobox, Input } from '@/components/emcn'
import type { FilterCondition } from '@/lib/table/filters/filter-constants'
import { useFilterBuilder } from '@/lib/table/filters/use-filter-builder'
import type { FilterCondition } from '@/lib/table/filters/constants'
import { useFilterBuilder } from '@/lib/table/filters/use-builder'
/**
* Represents a sort configuration.

View File

@@ -4,12 +4,9 @@ import { useEffect, useMemo, useRef, useState } from 'react'
import { Plus, X } from 'lucide-react'
import { Button, Combobox, type ComboboxOption, Input } from '@/components/emcn'
import { cn } from '@/lib/core/utils/cn'
import {
conditionsToJsonString,
jsonStringToConditions,
} from '@/lib/table/filters/filter-builder-utils'
import type { FilterCondition } from '@/lib/table/filters/filter-constants'
import { useFilterBuilder } from '@/lib/table/filters/use-filter-builder'
import { conditionsToJsonString, jsonStringToConditions } from '@/lib/table/filters/builder-utils'
import type { FilterCondition } from '@/lib/table/filters/constants'
import { useFilterBuilder } from '@/lib/table/filters/use-builder'
import { formatDisplayText } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/formatted-text'
import { SubBlockInputController } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/sub-block-input-controller'
import { useSubBlockValue } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-sub-block-value'

View File

@@ -2,14 +2,13 @@
import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
import { Plus, X } from 'lucide-react'
import { nanoid } from 'nanoid'
import { Button, Combobox, type ComboboxOption } from '@/components/emcn'
import {
generateId,
jsonStringToSortConditions,
SORT_DIRECTIONS,
type SortCondition,
sortConditionsToJsonString,
} from '@/lib/table/filters/filter-builder-utils'
} from '@/lib/table/filters/builder-utils'
import { SORT_DIRECTIONS, type SortCondition } from '@/lib/table/filters/constants'
import { useSubBlockValue } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-sub-block-value'
interface SortFormatProps {
@@ -30,7 +29,7 @@ interface SortFormatProps {
* Creates a new sort condition with default values
*/
const createDefaultCondition = (columns: ComboboxOption[]): SortCondition => ({
id: generateId(),
id: nanoid(),
column: columns[0]?.value || '',
direction: 'asc',
})

View File

@@ -3,7 +3,7 @@ import { AlertTriangle, Wand2 } from 'lucide-react'
import { Label, Tooltip } from '@/components/emcn/components'
import { Button } from '@/components/ui/button'
import { cn } from '@/lib/core/utils/cn'
import type { FilterCondition, SortCondition } from '@/lib/table/filters/filter-builder-utils'
import type { FilterCondition, SortCondition } from '@/lib/table/filters/constants'
import type { FieldDiffStatus } from '@/lib/workflows/diff/types'
import {
CheckboxList,

View File

@@ -1,5 +1,5 @@
import { TableIcon } from '@/components/icons'
import { conditionsToFilter, sortConditionsToSort } from '@/lib/table/filters/filter-builder-utils'
import { conditionsToFilter, sortConditionsToSort } from '@/lib/table/filters/builder-utils'
import type { BlockConfig } from '@/blocks/types'
import type { TableQueryResponse } from '@/tools/table/types'

View File

@@ -1,24 +1,11 @@
/**
* Shared utilities for filter builder UI components.
*
* @module lib/table/filters/filter-builder-utils
* @module lib/table/filters/builder-utils
*/
// Re-export shared constants and types for backward compatibility
export {
COMPARISON_OPERATORS,
type FilterCondition,
generateConditionId as generateId,
LOGICAL_OPERATORS,
SORT_DIRECTIONS,
type SortCondition,
} from './filter-constants'
// Import for internal use
import { type FilterCondition, generateConditionId, type SortCondition } from './filter-constants'
// Use internal alias for generateConditionId
const generateId = generateConditionId
import { nanoid } from 'nanoid'
import type { FilterCondition, SortCondition } from './constants'
type JsonValue = string | number | boolean | null | JsonValue[] | { [key: string]: JsonValue }
@@ -141,7 +128,7 @@ function parseFilterGroup(group: Record<string, JsonValue>): FilterCondition[] {
for (const [op, opValue] of Object.entries(value)) {
if (op.startsWith('$')) {
conditions.push({
id: generateId(),
id: nanoid(),
logicalOperator: 'and',
column,
operator: op.substring(1),
@@ -151,7 +138,7 @@ function parseFilterGroup(group: Record<string, JsonValue>): FilterCondition[] {
}
} else {
conditions.push({
id: generateId(),
id: nanoid(),
logicalOperator: 'and',
column,
operator: 'eq',
@@ -234,7 +221,7 @@ export function sortToConditions(sort: Record<string, string> | null): SortCondi
if (!sort) return []
return Object.entries(sort).map(([column, direction]) => ({
id: generateId(),
id: nanoid(),
column,
direction: direction === 'desc' ? 'desc' : 'asc',
}))

View File

@@ -1,7 +1,7 @@
/**
* Shared constants and types for table filtering and sorting.
*
* @module lib/table/filters/filter-constants
* @module lib/table/filters/constants
*
*/
@@ -68,13 +68,3 @@ export interface SortCondition {
/** Sort direction */
direction: 'asc' | 'desc'
}
/**
* Generates a unique ID for filter or sort conditions.
* Used as React keys for list items in builder UI.
*
* @returns Random alphanumeric string
*/
export function generateConditionId(): string {
return Math.random().toString(36).substring(2, 9)
}

View File

@@ -4,6 +4,6 @@
* @module lib/table/filters
*/
export * from './filter-builder-utils'
export * from './filter-constants'
export * from './use-filter-builder'
export * from './builder-utils'
export * from './constants'
export * from './use-builder'

View File

@@ -3,59 +3,37 @@
*
* Provides reusable filter condition management logic shared between
* the table data viewer's FilterBuilder and workflow block's FilterFormat.
*
* @module lib/table/filters/use-filter-builder
*/
import { useCallback, useMemo } from 'react'
import { nanoid } from 'nanoid'
import {
COMPARISON_OPERATORS,
type FilterCondition,
generateConditionId,
LOGICAL_OPERATORS,
SORT_DIRECTIONS,
type SortCondition,
} from './filter-constants'
} from './constants'
/**
* Column option for dropdowns.
*/
export interface ColumnOption {
value: string
label: string
}
/**
* Props for the useFilterBuilder hook.
*/
export interface UseFilterBuilderProps {
/** Available columns for filtering */
columns: ColumnOption[]
/** Current filter conditions */
conditions: FilterCondition[]
/** Setter function for updating conditions */
setConditions: (conditions: FilterCondition[]) => void
/** Whether the builder is read-only */
isReadOnly?: boolean
}
/**
* Return type for the useFilterBuilder hook.
*/
export interface UseFilterBuilderReturn {
/** Memoized comparison operator options */
comparisonOptions: ColumnOption[]
/** Memoized logical operator options */
logicalOptions: ColumnOption[]
/** Memoized sort direction options */
sortDirectionOptions: ColumnOption[]
/** Adds a new filter condition */
addCondition: () => void
/** Removes a filter condition by ID */
removeCondition: (id: string) => void
/** Updates a specific field of a condition */
updateCondition: (id: string, field: keyof FilterCondition, value: string) => void
/** Creates a default condition (for external use) */
createDefaultCondition: () => FilterCondition
}
@@ -97,7 +75,6 @@ export function useFilterBuilder({
setConditions,
isReadOnly = false,
}: UseFilterBuilderProps): UseFilterBuilderReturn {
// Memoized options for dropdowns
const comparisonOptions = useMemo(
() => COMPARISON_OPERATORS.map((op) => ({ value: op.value, label: op.label })),
[]
@@ -113,12 +90,9 @@ export function useFilterBuilder({
[]
)
/**
* Creates a new filter condition with default values.
*/
const createDefaultCondition = useCallback((): FilterCondition => {
return {
id: generateConditionId(),
id: nanoid(),
logicalOperator: 'and',
column: columns[0]?.value || '',
operator: 'eq',
@@ -126,17 +100,11 @@ export function useFilterBuilder({
}
}, [columns])
/**
* Adds a new filter condition.
*/
const addCondition = useCallback(() => {
if (isReadOnly) return
setConditions([...conditions, createDefaultCondition()])
}, [isReadOnly, conditions, setConditions, createDefaultCondition])
/**
* Removes a filter condition by ID.
*/
const removeCondition = useCallback(
(id: string) => {
if (isReadOnly) return
@@ -145,9 +113,6 @@ export function useFilterBuilder({
[isReadOnly, conditions, setConditions]
)
/**
* Updates a specific field of a condition.
*/
const updateCondition = useCallback(
(id: string, field: keyof FilterCondition, value: string) => {
if (isReadOnly) return
@@ -167,31 +132,17 @@ export function useFilterBuilder({
}
}
/**
* Props for sort configuration management.
*/
export interface UseSortBuilderProps {
/** Available columns for sorting */
columns: ColumnOption[]
/** Current sort condition */
sortCondition: SortCondition | null
/** Setter function for updating sort */
setSortCondition: (sort: SortCondition | null) => void
}
/**
* Return type for the useSortBuilder hook.
*/
export interface UseSortBuilderReturn {
/** Memoized sort direction options */
sortDirectionOptions: ColumnOption[]
/** Adds a sort configuration */
addSort: () => void
/** Removes the sort configuration */
removeSort: () => void
/** Updates the sort column */
updateSortColumn: (column: string) => void
/** Updates the sort direction */
updateSortDirection: (direction: 'asc' | 'desc') => void
}
@@ -221,7 +172,7 @@ export function useSortBuilder({
const addSort = useCallback(() => {
setSortCondition({
id: generateConditionId(),
id: nanoid(),
column: columns[0]?.value || '',
direction: 'asc',
})

View File

@@ -4,20 +4,20 @@
* These helpers consolidate common validation patterns (size, schema, uniqueness)
* into reusable functions that return formatted error responses.
*
* @module lib/table/validation/validation-helpers
* @module lib/table/validation/helpers
*/
import { db } from '@sim/db'
import { userTableRows } from '@sim/db/schema'
import { eq } from 'drizzle-orm'
import { NextResponse } from 'next/server'
import type { TableSchema } from './validation'
import type { TableSchema } from './schema'
import {
getUniqueColumns,
validateRowAgainstSchema,
validateRowSize,
validateUniqueConstraints,
} from './validation'
} from './schema'
/**
* Row data type for validation functions.

View File

@@ -4,5 +4,5 @@
* @module lib/table/validation
*/
export * from './validation'
export * from './validation-helpers'
export * from './helpers'
export * from './schema'

View File

@@ -1,7 +1,7 @@
/**
* Validation utilities for table schemas and row data.
*
* @module lib/table/validation/validation
* @module lib/table/validation/schema
*/
import type { ColumnType } from '../constants'