From caa42e458632bf927ba34305bc343109feab3fc2 Mon Sep 17 00:00:00 2001 From: Waleed Latif Date: Fri, 24 Apr 2026 16:15:31 -0700 Subject: [PATCH] fix(table-block): resolve canonical tableId in filter/sort builders The visual filter/sort builders read the selected tableId from subBlock id 'tableId', but the Table block stores it under 'tableSelector' (basic) or 'manualTableId' (advanced) via canonicalParamId. The lookup always returned null, so useTable was disabled and the column picker always showed "no options available". Adds useCanonicalSubBlockValue that resolves by canonicalParamId through the canonical index, mirroring the pattern used by dropdown dependsOn. --- .../filter-builder/filter-builder.tsx | 3 +- .../components/sort-builder/sort-builder.tsx | 3 +- .../hooks/use-canonical-sub-block-value.ts | 49 +++++++++++++++++++ 3 files changed, 53 insertions(+), 2 deletions(-) create mode 100644 apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-canonical-sub-block-value.ts diff --git a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/filter-builder/filter-builder.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/filter-builder/filter-builder.tsx index 492f2f09844..f7ef31ad5cc 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/filter-builder/filter-builder.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/filter-builder/filter-builder.tsx @@ -6,6 +6,7 @@ import type { ComboboxOption } from '@/components/emcn' import { useTableColumns } from '@/lib/table/hooks' import type { FilterRule } from '@/lib/table/query-builder/constants' import { useFilterBuilder } from '@/lib/table/query-builder/use-query-builder' +import { useCanonicalSubBlockValue } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-canonical-sub-block-value' import { useSubBlockInput } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-sub-block-input' import { useSubBlockValue } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-sub-block-value' import { FilterRuleRow } from './components/filter-rule-row' @@ -40,7 +41,7 @@ export function FilterBuilder({ tableIdSubBlockId = 'tableId', }: FilterBuilderProps) { const [storeValue, setStoreValue] = useSubBlockValue(blockId, subBlockId) - const [tableIdValue] = useSubBlockValue(blockId, tableIdSubBlockId) + const tableIdValue = useCanonicalSubBlockValue(blockId, tableIdSubBlockId) const dynamicColumns = useTableColumns({ tableId: tableIdValue }) const columns = useMemo(() => { diff --git a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/sort-builder/sort-builder.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/sort-builder/sort-builder.tsx index 12213e0b63a..b202c4a2a93 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/sort-builder/sort-builder.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/sort-builder/sort-builder.tsx @@ -5,6 +5,7 @@ import { generateId } from '@sim/utils/id' import type { ComboboxOption } from '@/components/emcn' import { useTableColumns } from '@/lib/table/hooks' import { SORT_DIRECTIONS, type SortRule } from '@/lib/table/query-builder/constants' +import { useCanonicalSubBlockValue } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-canonical-sub-block-value' import { useSubBlockValue } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-sub-block-value' import { SortRuleRow } from './components/sort-rule-row' @@ -36,7 +37,7 @@ export function SortBuilder({ tableIdSubBlockId = 'tableId', }: SortBuilderProps) { const [storeValue, setStoreValue] = useSubBlockValue(blockId, subBlockId) - const [tableIdValue] = useSubBlockValue(blockId, tableIdSubBlockId) + const tableIdValue = useCanonicalSubBlockValue(blockId, tableIdSubBlockId) const dynamicColumns = useTableColumns({ tableId: tableIdValue, includeBuiltIn: true }) const columns = useMemo(() => { diff --git a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-canonical-sub-block-value.ts b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-canonical-sub-block-value.ts new file mode 100644 index 00000000000..3cb5fc25bfc --- /dev/null +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-canonical-sub-block-value.ts @@ -0,0 +1,49 @@ +import { useCallback, useMemo } from 'react' +import { isEqual } from 'es-toolkit' +import { useStoreWithEqualityFn } from 'zustand/traditional' +import { buildCanonicalIndex, resolveDependencyValue } from '@/lib/workflows/subblocks/visibility' +import { getBlock } from '@/blocks/registry' +import { useWorkflowRegistry } from '@/stores/workflows/registry/store' +import { useSubBlockStore } from '@/stores/workflows/subblock/store' +import { useWorkflowStore } from '@/stores/workflows/workflow/store' + +/** + * Read a sub-block value by either its raw subBlockId or its canonicalParamId. + * + * `useSubBlockValue` only looks up the raw subBlockId. For fields that use + * `canonicalParamId` to unify basic/advanced inputs (e.g. `tableSelector` vs + * `manualTableId` both mapping to `tableId`), this hook resolves to whichever + * member of the canonical group currently holds the value. + */ +export function useCanonicalSubBlockValue( + blockId: string, + canonicalOrSubBlockId: string +): T | null { + const activeWorkflowId = useWorkflowRegistry((s) => s.activeWorkflowId) + const blockState = useWorkflowStore((state) => state.blocks[blockId]) + const blockConfig = blockState?.type ? getBlock(blockState.type) : null + const canonicalIndex = useMemo( + () => buildCanonicalIndex(blockConfig?.subBlocks || []), + [blockConfig?.subBlocks] + ) + const canonicalModeOverrides = blockState?.data?.canonicalModes + + return useStoreWithEqualityFn( + useSubBlockStore, + useCallback( + (state) => { + if (!activeWorkflowId) return null + const blockValues = state.workflowValues[activeWorkflowId]?.[blockId] || {} + const resolved = resolveDependencyValue( + canonicalOrSubBlockId, + blockValues, + canonicalIndex, + canonicalModeOverrides + ) + return (resolved ?? null) as T | null + }, + [activeWorkflowId, blockId, canonicalOrSubBlockId, canonicalIndex, canonicalModeOverrides] + ), + (a, b) => isEqual(a, b) + ) +}