Skip to content

Commit e1a46c9

Browse files
authored
fix: table subblock (#1937)
1 parent c7560be commit e1a46c9

File tree

1 file changed

+45
-36
lines changed
  • apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel-new/components/editor/components/sub-block/components/table

1 file changed

+45
-36
lines changed

apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel-new/components/editor/components/sub-block/components/table/table.tsx

Lines changed: 45 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { useMemo, useRef } from 'react'
1+
import { useEffect, useMemo, useRef } from 'react'
22
import { useParams } from 'next/navigation'
33
import { Button } from '@/components/emcn/components/button/button'
44
import { Trash } from '@/components/emcn/icons/trash'
@@ -60,58 +60,71 @@ export function Table({
6060
// Create refs for input elements
6161
const inputRefs = useRef<Map<string, HTMLInputElement>>(new Map())
6262

63+
// Memoized template for empty cells for current columns
64+
const emptyCellsTemplate = useMemo(
65+
() => Object.fromEntries(columns.map((col) => [col, ''])),
66+
[columns]
67+
)
68+
69+
/**
70+
* Initialize the table with a default empty row when the component mounts
71+
* and when the current store value is missing or empty.
72+
*/
73+
useEffect(() => {
74+
if (!isPreview && !disabled && (!Array.isArray(storeValue) || storeValue.length === 0)) {
75+
const initialRow: TableRow = {
76+
id: crypto.randomUUID(),
77+
cells: { ...emptyCellsTemplate },
78+
}
79+
setStoreValue([initialRow])
80+
}
81+
}, [isPreview, disabled, storeValue, setStoreValue, emptyCellsTemplate])
82+
6383
// Ensure value is properly typed and initialized
6484
const rows = useMemo(() => {
65-
if (!Array.isArray(value)) {
85+
if (!Array.isArray(value) || value.length === 0) {
6686
return [
6787
{
6888
id: crypto.randomUUID(),
69-
cells: Object.fromEntries(columns.map((col) => [col, ''])),
89+
cells: { ...emptyCellsTemplate },
7090
},
7191
]
7292
}
7393

74-
// Validate and fix each row to ensure proper structure
94+
// Validate and normalize each row without in-place mutation
7595
const validatedRows = value.map((row) => {
76-
// Ensure row has an id
77-
if (!row.id) {
78-
row.id = crypto.randomUUID()
96+
const hasValidCells = row?.cells && typeof row.cells === 'object'
97+
if (!hasValidCells) {
98+
logger.warn('Fixing malformed table row:', row)
7999
}
80100

81-
// Ensure row has cells object with proper structure
82-
if (!row.cells || typeof row.cells !== 'object') {
83-
logger.warn('Fixing malformed table row:', row)
84-
row.cells = Object.fromEntries(columns.map((col) => [col, '']))
85-
} else {
86-
// Ensure all required columns exist in cells
87-
columns.forEach((col) => {
88-
if (!(col in row.cells)) {
89-
row.cells[col] = ''
90-
}
91-
})
101+
const normalizedCells = {
102+
...emptyCellsTemplate,
103+
...(hasValidCells ? row.cells : {}),
92104
}
93105

94-
return row
106+
return {
107+
id: row?.id ?? crypto.randomUUID(),
108+
cells: normalizedCells,
109+
}
95110
})
96111

97112
return validatedRows as TableRow[]
98-
}, [value, columns])
113+
}, [value, emptyCellsTemplate])
99114

100115
// Helper to update a cell value
101116
const updateCellValue = (rowIndex: number, column: string, newValue: string) => {
102117
if (isPreview || disabled) return
103118

104119
const updatedRows = [...rows].map((row, idx) => {
105120
if (idx === rowIndex) {
106-
// Ensure the row has a proper cells object
107-
if (!row.cells || typeof row.cells !== 'object') {
108-
logger.warn('Fixing malformed row cells during cell change:', row)
109-
row.cells = Object.fromEntries(columns.map((col) => [col, '']))
110-
}
121+
const hasValidCells = row.cells && typeof row.cells === 'object'
122+
const baseCells = hasValidCells ? row.cells : { ...emptyCellsTemplate }
123+
if (!hasValidCells) logger.warn('Fixing malformed row cells during cell change:', row)
111124

112125
return {
113126
...row,
114-
cells: { ...row.cells, [column]: newValue },
127+
cells: { ...baseCells, [column]: newValue },
115128
}
116129
}
117130
return row
@@ -120,7 +133,7 @@ export function Table({
120133
if (rowIndex === rows.length - 1 && newValue !== '') {
121134
updatedRows.push({
122135
id: crypto.randomUUID(),
123-
cells: Object.fromEntries(columns.map((col) => [col, ''])),
136+
cells: { ...emptyCellsTemplate },
124137
})
125138
}
126139

@@ -152,16 +165,12 @@ export function Table({
152165

153166
const renderCell = (row: TableRow, rowIndex: number, column: string, cellIndex: number) => {
154167
// Defensive programming: ensure row.cells exists and has the expected structure
155-
if (!row.cells || typeof row.cells !== 'object') {
156-
logger.warn('Table row has malformed cells data:', row)
157-
// Create a fallback cells object
158-
row = {
159-
...row,
160-
cells: Object.fromEntries(columns.map((col) => [col, ''])),
161-
}
162-
}
168+
const hasValidCells = row.cells && typeof row.cells === 'object'
169+
if (!hasValidCells) logger.warn('Table row has malformed cells data:', row)
170+
171+
const cells = hasValidCells ? row.cells : { ...emptyCellsTemplate }
163172

164-
const cellValue = row.cells[column] || ''
173+
const cellValue = cells[column] || ''
165174
const cellKey = `${rowIndex}-${column}`
166175

167176
// Get field state and handlers for this cell

0 commit comments

Comments
 (0)