Skip to content

Commit 3306c90

Browse files
fix(tables): enrichment columns use type icon; output names editable
- Drop the per-column enrichment icon (it duplicated the meta-header icon). Enrichment output columns now render the standard column-type icon (Text, etc.) — the enrichment's icon stays only on the group meta-header. - Make output column names editable in the enrichment config edit mode too; changed names rename their columns via useUpdateColumn (the rename cascades into the group's output refs server-side). Validation excludes the output's own current name. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent bd68516 commit 3306c90

3 files changed

Lines changed: 42 additions & 29 deletions

File tree

apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/enrichments-sidebar/enrichment-config.tsx

Lines changed: 35 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,11 @@ import { cn } from '@/lib/core/utils/cn'
2121
import type { ColumnDefinition, WorkflowGroup, WorkflowGroupOutput } from '@/lib/table'
2222
import { deriveOutputColumnName } from '@/lib/table/column-naming'
2323
import type { EnrichmentConfig as EnrichmentDef } from '@/enrichments/types'
24-
import { useAddWorkflowGroup, useUpdateWorkflowGroup } from '@/hooks/queries/tables'
24+
import {
25+
useAddWorkflowGroup,
26+
useUpdateColumn,
27+
useUpdateWorkflowGroup,
28+
} from '@/hooks/queries/tables'
2529
import { RunSettingsSection } from '../workflow-sidebar/run-settings-section'
2630

2731
interface EnrichmentConfigProps {
@@ -32,8 +36,7 @@ interface EnrichmentConfigProps {
3236
onBack: () => void
3337
onClose: () => void
3438
/** When set, the panel edits this existing enrichment group (pre-filled,
35-
* updates instead of creating). Output columns already exist and are shown
36-
* read-only. */
39+
* updates instead of creating; changed output names rename their columns). */
3740
existingGroup?: WorkflowGroup
3841
}
3942

@@ -66,8 +69,13 @@ export function EnrichmentConfig({
6669
}: EnrichmentConfigProps) {
6770
const addWorkflowGroup = useAddWorkflowGroup({ workspaceId, tableId })
6871
const updateWorkflowGroup = useUpdateWorkflowGroup({ workspaceId, tableId })
72+
const updateColumn = useUpdateColumn({ workspaceId, tableId })
6973
const isEditing = Boolean(existingGroup)
7074

75+
/** Output column's persisted name (edit mode), used to detect renames. */
76+
const originalOutputName = (outputId: string): string | undefined =>
77+
existingGroup?.outputs.find((o) => o.outputId === outputId)?.columnName
78+
7179
const [inputMappings, setInputMappings] = useState<Record<string, string>>(() => {
7280
if (existingGroup) {
7381
const seed: Record<string, string> = {}
@@ -81,8 +89,8 @@ export function EnrichmentConfig({
8189
}
8290
return seed
8391
})
84-
// Per-output column names. Edit mode reflects the existing columns (read-only);
85-
// create mode seeds deduped defaults the user can rename.
92+
// Per-output column names. Editable in both modes — edit mode seeds the
93+
// existing column names and renames changed ones on save.
8694
const [outputNames, setOutputNames] = useState<Record<string, string>>(() => {
8795
const seed: Record<string, string> = {}
8896
if (existingGroup) {
@@ -108,22 +116,29 @@ export function EnrichmentConfig({
108116
const missingRequired = enrichment.inputs.some((i) => i.required && !inputMappings[i.id])
109117
const depsValid = !autoRun || deps.length > 0
110118

111-
/** Per-output name validation (create mode only — edit mode columns exist). */
119+
/** Per-output column-name validation (both modes). Excludes the output's own
120+
* current column so renaming to its existing name isn't flagged. */
112121
function outputNameError(outputId: string): string | null {
113-
if (isEditing) return null
114122
const value = (outputNames[outputId] ?? '').trim()
115123
if (!value) return 'Required'
116124
const lower = value.toLowerCase()
117-
if (allColumns.some((c) => c.name.toLowerCase() === lower)) return 'Column already exists'
125+
const ownOriginal = originalOutputName(outputId)?.toLowerCase()
126+
if (
127+
allColumns.some((c) => c.name.toLowerCase() === lower && c.name.toLowerCase() !== ownOriginal)
128+
)
129+
return 'Column already exists'
118130
const dup = enrichment.outputs.some(
119131
(o) => o.id !== outputId && (outputNames[o.id] ?? '').trim().toLowerCase() === lower
120132
)
121133
return dup ? 'Duplicate name' : null
122134
}
123-
const outputsInvalid =
124-
!isEditing && enrichment.outputs.some((o) => outputNameError(o.id) !== null)
135+
const outputsInvalid = enrichment.outputs.some((o) => outputNameError(o.id) !== null)
125136
const saveDisabled =
126-
addWorkflowGroup.isPending || updateWorkflowGroup.isPending || !depsValid || outputsInvalid
137+
addWorkflowGroup.isPending ||
138+
updateWorkflowGroup.isPending ||
139+
updateColumn.isPending ||
140+
!depsValid ||
141+
outputsInvalid
127142

128143
async function handleSave() {
129144
if (missingRequired || (autoRun && deps.length === 0) || outputsInvalid) {
@@ -136,6 +151,15 @@ export function EnrichmentConfig({
136151

137152
if (existingGroup) {
138153
try {
154+
// Rename any output columns the user changed first; the rename cascades
155+
// into the group's output refs server-side.
156+
for (const o of enrichment.outputs) {
157+
const original = originalOutputName(o.id)
158+
const next = (outputNames[o.id] ?? '').trim()
159+
if (original && next && next !== original) {
160+
await updateColumn.mutateAsync({ columnName: original, updates: { name: next } })
161+
}
162+
}
139163
await updateWorkflowGroup.mutateAsync({
140164
groupId: existingGroup.id,
141165
name: enrichment.name,
@@ -298,7 +322,6 @@ export function EnrichmentConfig({
298322
onChange={(e) =>
299323
setOutputNames((prev) => ({ ...prev, [output.id]: e.target.value }))
300324
}
301-
disabled={isEditing}
302325
spellCheck={false}
303326
autoComplete='off'
304327
className={cn(outErr && 'border-[var(--text-error)]')}

apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/table-grid/headers/column-header-menu.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,7 @@ export const ColumnHeaderMenu = React.memo(function ColumnHeaderMenu({
250250
<div className='flex h-full w-full min-w-0 items-center px-2 py-[7px]'>
251251
<ColumnTypeIcon
252252
type={column.type}
253-
isWorkflowColumn={!!column.workflowGroupId}
253+
isWorkflowColumn={!!column.workflowGroupId && ownGroup?.type !== 'enrichment'}
254254
blockIconInfo={sourceInfo?.blockIconInfo}
255255
/>
256256
<input
@@ -270,7 +270,7 @@ export const ColumnHeaderMenu = React.memo(function ColumnHeaderMenu({
270270
<div className='flex h-full w-full min-w-0 items-center px-2 py-[7px]'>
271271
<ColumnTypeIcon
272272
type={column.type}
273-
isWorkflowColumn={!!column.workflowGroupId}
273+
isWorkflowColumn={!!column.workflowGroupId && ownGroup?.type !== 'enrichment'}
274274
blockIconInfo={sourceInfo?.blockIconInfo}
275275
/>
276276
<span className='ml-1.5 min-w-0 overflow-clip text-ellipsis whitespace-nowrap font-medium text-[13px] text-[var(--text-primary)]'>
@@ -287,7 +287,7 @@ export const ColumnHeaderMenu = React.memo(function ColumnHeaderMenu({
287287
>
288288
<ColumnTypeIcon
289289
type={column.type}
290-
isWorkflowColumn={!!column.workflowGroupId}
290+
isWorkflowColumn={!!column.workflowGroupId && ownGroup?.type !== 'enrichment'}
291291
blockIconInfo={sourceInfo?.blockIconInfo}
292292
/>
293293
<span className='ml-1.5 min-w-0 overflow-clip text-ellipsis whitespace-nowrap font-medium text-[var(--text-primary)] text-small'>

apps/sim/app/workspace/[workspaceId]/tables/[tableId]/hooks/use-table.ts

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import type { ColumnDefinition, TableDefinition, TableRow, WorkflowGroup } from
66
import { TABLE_LIMITS } from '@/lib/table/constants'
77
import type { FlattenOutputsBlockInput } from '@/lib/workflows/blocks/flatten-outputs'
88
import { getBlock } from '@/blocks'
9-
import { getEnrichment } from '@/enrichments/registry'
109
import {
1110
tableRowsInfiniteOptions,
1211
useInfiniteTableRows,
@@ -190,19 +189,10 @@ export function useTable({ workspaceId, tableId, queryOptions }: UseTableParams)
190189
const columnSourceInfo = useMemo<Map<string, ColumnSourceInfo>>(() => {
191190
const map = new Map<string, ColumnSourceInfo>()
192191
for (const group of tableWorkflowGroups) {
193-
// Enrichment groups have no workflow blocks — source the icon/name from
194-
// the enrichment registry so every output column shows the enrichment's
195-
// own icon (e.g. Mail for work-email) instead of the generic play icon.
196-
if (group.type === 'enrichment') {
197-
const enrichment = getEnrichment(group.enrichmentId)
198-
const blockIconInfo: BlockIconInfo | undefined = enrichment?.icon
199-
? { icon: enrichment.icon, color: '#6B7280' }
200-
: undefined
201-
for (const out of group.outputs) {
202-
map.set(out.columnName, { blockIconInfo, blockName: enrichment?.name })
203-
}
204-
continue
205-
}
192+
// Enrichment groups have no workflow blocks; their output columns render
193+
// with the standard column-type icon (the meta-header already carries the
194+
// enrichment's icon), so we skip building source info for them.
195+
if (group.type === 'enrichment') continue
206196
const state = workflowStates.get(group.workflowId)
207197
const blocks = (state as { blocks?: Record<string, FlattenOutputsBlockInput> } | null)?.blocks
208198
for (const out of group.outputs) {

0 commit comments

Comments
 (0)