Skip to content

Commit 0d6538b

Browse files
committed
fix(tables): keep column rename migration atomic
1 parent 4e7eb32 commit 0d6538b

3 files changed

Lines changed: 28 additions & 48 deletions

File tree

‎apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/column-config-sidebar/column-config-sidebar.test.tsx‎

Lines changed: 4 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -103,12 +103,6 @@ function findButton(label: string): HTMLButtonElement | undefined {
103103
)
104104
}
105105

106-
function setInputValue(input: HTMLInputElement, value: string): void {
107-
const valueSetter = Object.getOwnPropertyDescriptor(HTMLInputElement.prototype, 'value')?.set
108-
valueSetter?.call(input, value)
109-
input.dispatchEvent(new Event('input', { bubbles: true }))
110-
}
111-
112106
beforeEach(() => {
113107
globalThis.IS_REACT_ACT_ENVIRONMENT = true
114108
container = document.createElement('div')
@@ -196,8 +190,7 @@ describe('ColumnConfigSidebar', () => {
196190
expect(mockUpdateColumn).not.toHaveBeenCalled()
197191
})
198192

199-
it('edits a Reference column name and target table together', async () => {
200-
const onColumnRename = vi.fn()
193+
it('edits Reference configuration without exposing column renaming', async () => {
201194
await act(async () => {
202195
root.render(
203196
<ColumnConfigSidebar
@@ -213,27 +206,21 @@ describe('ColumnConfigSidebar', () => {
213206
tableRowTtlEnabled={false}
214207
workspaceId='workspace-1'
215208
tableId='table-current'
216-
onColumnRename={onColumnRename}
217209
referenceColumnsEnabled
218210
/>
219211
)
220212
})
221213

222-
const nameInput = container.querySelector<HTMLInputElement>('#column-sidebar-name')
223-
expect(nameInput?.value).toBe('Related row')
214+
expect(container).not.toHaveTextContent('Column name')
215+
expect(container.querySelector('#column-sidebar-name')).toBeNull()
224216

225-
act(() => setInputValue(nameInput!, 'Renamed relation'))
226217
act(() => findCombobox('Select table')?.onChange?.('table-customers'))
227218
await act(async () => findButton('Save')?.click())
228219

229220
expect(mockUpdateColumn).toHaveBeenCalledWith({
230221
columnName: 'col-reference',
231-
updates: {
232-
name: 'Renamed relation',
233-
referenceTableId: 'table-customers',
234-
},
222+
updates: { referenceTableId: 'table-customers' },
235223
})
236-
expect(onColumnRename).toHaveBeenCalledWith('col-reference', 'Renamed relation')
237224
})
238225

239226
it('keeps an existing Reference column visible but not retargetable when disabled', async () => {

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

Lines changed: 21 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -58,9 +58,6 @@ interface ColumnConfigSidebarProps {
5858
referenceColumnsEnabled: boolean
5959
workspaceId: string
6060
tableId: string
61-
/** Notify parent of a rename so it can rewrite local `columnOrder` /
62-
* `columnWidths` keys that reference the old name. */
63-
onColumnRename?: (oldName: string, newName: string) => void
6461
}
6562

6663
/**
@@ -111,7 +108,6 @@ function ColumnConfigBody({
111108
referenceColumnsEnabled,
112109
workspaceId,
113110
tableId,
114-
onColumnRename,
115111
}: ColumnConfigBodyProps) {
116112
const updateColumn = useUpdateColumn({ workspaceId, tableId })
117113
const addColumn = useAddTableColumn({ workspaceId, tableId })
@@ -187,7 +183,7 @@ function ColumnConfigBody({
187183
}
188184

189185
async function handleSave() {
190-
if (!trimmedName) {
186+
if (config.mode === 'create' && !trimmedName) {
191187
setShowValidation(true)
192188
return
193189
}
@@ -219,7 +215,6 @@ function ColumnConfigBody({
219215
return
220216
}
221217

222-
const renamed = trimmedName !== (existingColumn?.name ?? config.columnName)
223218
const typeChanged = !!existingColumn && existingColumn.type !== typeInput
224219
const uniqueChanged =
225220
supportsUnique && !!existingColumn && !!existingColumn.unique !== uniqueInput
@@ -233,15 +228,13 @@ function ColumnConfigBody({
233228
wantsReference && existingColumn?.referenceTableId !== referenceTableInput
234229

235230
const updates: {
236-
name?: string
237231
type?: ColumnDefinition['type']
238232
unique?: boolean
239233
options?: SelectOption[]
240234
multiple?: boolean
241235
currencyCode?: string
242236
referenceTableId?: string
243237
} = {
244-
...(renamed ? { name: trimmedName } : {}),
245238
...(typeChanged ? { type: typeInput } : {}),
246239
...(uniqueChanged ? { unique: uniqueInput } : {}),
247240
...(uniqueCleared ? { unique: false } : {}),
@@ -260,8 +253,7 @@ function ColumnConfigBody({
260253
}
261254

262255
await updateColumn.mutateAsync({ columnName: config.columnName, updates })
263-
if (renamed) onColumnRename?.(config.columnName, trimmedName)
264-
toast.success(`Saved "${trimmedName}"`)
256+
toast.success(`Saved "${existingColumn?.name ?? config.columnName}"`)
265257
onClose()
266258
} catch (err) {
267259
if (isValidationError(err)) {
@@ -294,23 +286,25 @@ function ColumnConfigBody({
294286
</div>
295287

296288
<div className='flex-1 overflow-y-auto overflow-x-hidden px-2 pt-3 pb-2 [overflow-anchor:none]'>
297-
<div className='flex flex-col gap-[9.5px]'>
298-
<RequiredLabel htmlFor='column-sidebar-name'>Column name</RequiredLabel>
299-
<ChipInput
300-
id='column-sidebar-name'
301-
value={nameInput}
302-
onChange={(e) => {
303-
setNameInput(e.target.value)
304-
if (nameError) setNameError(null)
305-
}}
306-
spellCheck={false}
307-
autoComplete='off'
308-
error={Boolean((showValidation && !trimmedName) || nameError)}
309-
aria-invalid={(showValidation && !trimmedName) || nameError ? true : undefined}
310-
/>
311-
{showValidation && !trimmedName && <FieldError message='Column name is required' />}
312-
{nameError && !(showValidation && !trimmedName) && <FieldError message={nameError} />}
313-
</div>
289+
{config.mode === 'create' && (
290+
<div className='flex flex-col gap-[9.5px]'>
291+
<RequiredLabel htmlFor='column-sidebar-name'>Column name</RequiredLabel>
292+
<ChipInput
293+
id='column-sidebar-name'
294+
value={nameInput}
295+
onChange={(e) => {
296+
setNameInput(e.target.value)
297+
if (nameError) setNameError(null)
298+
}}
299+
spellCheck={false}
300+
autoComplete='off'
301+
error={Boolean((showValidation && !trimmedName) || nameError)}
302+
aria-invalid={(showValidation && !trimmedName) || nameError ? true : undefined}
303+
/>
304+
{showValidation && !trimmedName && <FieldError message='Column name is required' />}
305+
{nameError && !(showValidation && !trimmedName) && <FieldError message={nameError} />}
306+
</div>
307+
)}
314308

315309
{config.mode === 'edit' && (
316310
<>

‎apps/sim/app/workspace/[workspaceId]/tables/[tableId]/table.tsx‎

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -321,9 +321,9 @@ export function Table({
321321
}, [])
322322

323323
/**
324-
* Sink populated by the grid: invoked from sidebar `onColumnRename` so the
325-
* grid can rewrite its local `columnWidths` / `columnOrder` keys after a
326-
* rename. The grid's render assigns to `current`; the wrapper forwards calls.
324+
* Sink populated by the grid: invoked from the workflow sidebar after a
325+
* rename so the grid can rewrite its local `columnWidths` / `columnOrder`
326+
* keys. The grid's render assigns to `current`; the wrapper forwards calls.
327327
*/
328328
const columnRenameSinkRef = useRef<((oldName: string, newName: string) => void) | null>(null)
329329
const onColumnRename = (oldName: string, newName: string) => {
@@ -1724,7 +1724,6 @@ export function Table({
17241724
}
17251725
workspaceId={workspaceId}
17261726
tableId={tableId}
1727-
onColumnRename={onColumnRename}
17281727
/>
17291728
<EnrichmentsSidebar
17301729
open={slideout.kind === 'enrichments'}

0 commit comments

Comments
 (0)