Skip to content

Commit 411dc00

Browse files
committed
Update cell notation
1 parent b9ec302 commit 411dc00

File tree

6 files changed

+202
-204
lines changed

6 files changed

+202
-204
lines changed

llmstack/client/src/components/sheets/Sheet.jsx

Lines changed: 89 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,32 @@ import { enqueueSnackbar } from "notistack";
2222

2323
import "@glideapps/glide-data-grid/dist/index.css";
2424

25+
const columnIndexToLetter = (index) => {
26+
let temp = index + 1;
27+
let letter = "";
28+
while (temp > 0) {
29+
let remainder = (temp - 1) % 26;
30+
letter = String.fromCharCode(65 + remainder) + letter;
31+
temp = Math.floor((temp - 1) / 26);
32+
}
33+
return letter;
34+
};
35+
36+
const cellIdToGridCell = (cellId, columns) => {
37+
const match = cellId.match(/([A-Z]+)(\d+)/);
38+
if (!match) return null;
39+
const [, colLetter, rowString] = match;
40+
const row = parseInt(rowString, 10) - 1;
41+
const col = columns.findIndex((c) => c.col === colLetter);
42+
return [col, row];
43+
};
44+
45+
const gridCellToCellId = (gridCell, columns) => {
46+
const [colIndex, rowIndex] = gridCell;
47+
const colLetter = columns[colIndex].col;
48+
return `${colLetter}${rowIndex + 1}`;
49+
};
50+
2551
const SheetHeader = ({ sheet, setRunId, hasChanges, onSave }) => {
2652
const navigate = useNavigate();
2753

@@ -129,16 +155,15 @@ function Sheet(props) {
129155

130156
const getCellContent = useCallback(
131157
([column, row]) => {
132-
// Find the column in cells
133-
const col = columns[column].col;
134-
const cell = cells[row]?.[col];
158+
const colLetter = columns[column].col;
159+
const cell = cells[`${colLetter}${row + 1}`];
135160

136161
return {
137162
kind:
138163
(cell?.kind === "app_run" ? GridCellKind.Text : cell?.kind) ||
139164
columns[column].kind,
140-
displayData: cell?.displayData || cell?.data || "",
141-
data: cell?.data || "",
165+
displayData: cell?.display_data || "",
166+
data: cell?.display_data || "",
142167
allowOverlay: true,
143168
allowWrapping: true,
144169
skeletonWidth: 80,
@@ -153,9 +178,9 @@ function Sheet(props) {
153178
return [];
154179
}
155180

156-
return columns.map((column) => {
181+
return columns.map((column, index) => {
157182
return {
158-
col: column.col,
183+
col: columnIndexToLetter(index),
159184
title: column.title,
160185
kind: column.kind,
161186
data: column.data,
@@ -231,41 +256,44 @@ function Sheet(props) {
231256

232257
const onCellEdited = useCallback(
233258
(cell, value) => {
259+
const [col, row] = cell;
260+
const cellId = gridCellToCellId(cell, columns);
261+
234262
setCells((prevCells) => {
235263
const newCells = {
236264
...prevCells,
237-
[cell[1]]: {
238-
...prevCells[cell[1]],
239-
[columns[cell[0]].col]: {
240-
...(prevCells[cell[1]]?.[columns[cell[0]].col] || {}),
241-
...value,
242-
kind: columns[cell[0]].kind,
243-
data: value.data,
244-
displayData: value.displayData || value.data,
245-
},
265+
[cellId]: {
266+
...(prevCells[cellId] || {}),
267+
row: row + 1,
268+
col: columns[col]?.col,
269+
kind: GridCellKind.Text,
270+
display_data: value.displayData || value.data,
246271
},
247272
};
248-
updateUserChanges("cells", `${cell[1]}-${columns[cell[0]].col}`, value);
273+
updateUserChanges("cells", cellId, value);
249274
return newCells;
250275
});
251276
sheetRef.current?.updateCells([{ cell: cell }]);
252277
},
253-
[columns, updateUserChanges],
278+
[columns, updateUserChanges, sheetRef],
254279
);
255280

256281
const onRowAppended = useCallback(() => {
282+
const newRowIndex = numRows + 1;
283+
const newCells = columns.reduce((acc, column) => {
284+
const cellId = `${column.col}${newRowIndex}`;
285+
acc[cellId] = {
286+
kind: GridCellKind.Text,
287+
display_data: "",
288+
row: newRowIndex,
289+
col: column.col,
290+
};
291+
return acc;
292+
}, {});
293+
257294
setCells((prevCells) => ({
258295
...prevCells,
259-
[numRows]: {
260-
...columns.reduce((acc, column) => {
261-
acc[column.col] = {
262-
kind: GridCellKind.Text,
263-
displayData: "",
264-
data: "",
265-
};
266-
return acc;
267-
}, {}),
268-
},
296+
...newCells,
269297
}));
270298
setNumRows((prevNumRows) => {
271299
const newNumRows = prevNumRows + 1;
@@ -278,12 +306,9 @@ function Sheet(props) {
278306
return new Promise((resolve, reject) => {
279307
const updatedSheet = {
280308
...sheet,
281-
data: {
282-
...sheet.data,
283-
columns: columns,
284-
cells: cells,
285-
total_rows: numRows,
286-
},
309+
columns: columns,
310+
cells: cells,
311+
total_rows: numRows,
287312
};
288313
axios()
289314
.patch(`/api/sheets/${sheet.uuid}`, updatedSheet)
@@ -320,47 +345,37 @@ function Sheet(props) {
320345

321346
if (event.type === "cell.update") {
322347
const cell = event.cell;
323-
const [row, col] = cell.id.split("-");
324-
const column = columns.find((c) => c.col === col);
325-
326-
setCells((cells) => ({
327-
...cells,
328-
[row]: {
329-
...cells[row],
330-
[col]: {
331-
...cells[row]?.[col],
332-
...{
333-
kind: column?.kind || GridCellKind.Text,
334-
data: cell.data,
335-
displayData: cell.data,
336-
},
348+
const gridCell = cellIdToGridCell(cell.id, columns);
349+
if (gridCell) {
350+
const [colIndex] = gridCell;
351+
const column = columns[colIndex];
352+
353+
setCells((cells) => ({
354+
...cells,
355+
[cell.id]: {
356+
...cells[cell.id],
357+
kind: column?.kind || GridCellKind.Text,
358+
data: cell.data,
359+
display_data: cell.data,
337360
},
338-
},
339-
}));
361+
}));
340362

341-
sheetRef.current?.updateCells([
342-
{ cell: [columns.findIndex((c) => c.col === col), row] },
343-
]);
363+
sheetRef.current?.updateCells([{ cell: gridCell }]);
364+
}
344365
} else if (event.type === "cell.updating") {
345366
const cell = event.cell;
346-
const [row, col] = cell.id.split("-");
347-
348-
setCells((cells) => ({
349-
...cells,
350-
[row]: {
351-
...cells[row],
352-
[col]: {
353-
...cells[row]?.[col],
354-
...{
355-
kind: GridCellKind.Loading,
356-
},
367+
const gridCell = cellIdToGridCell(cell.id, columns);
368+
if (gridCell) {
369+
setCells((cells) => ({
370+
...cells,
371+
[cell.id]: {
372+
...cells[cell.id],
373+
kind: GridCellKind.Loading,
357374
},
358-
},
359-
}));
375+
}));
360376

361-
sheetRef.current?.updateCells([
362-
{ cell: [columns.findIndex((c) => c.col === col), row] },
363-
]);
377+
sheetRef.current?.updateCells([{ cell: gridCell }]);
378+
}
364379
}
365380
});
366381

@@ -399,7 +414,9 @@ function Sheet(props) {
399414
}
400415
onCellEdited={onCellEdited}
401416
onHeaderMenuClick={(column, bounds) => {
402-
setSelectedColumnId(column);
417+
setSelectedColumnId(
418+
columns.findIndex((c) => c.col === columnIndexToLetter(column)),
419+
);
403420
editColumnAnchorEl.current = {
404421
getBoundingClientRect: () => DOMRect.fromRect(bounds),
405422
};
@@ -426,7 +443,8 @@ function Sheet(props) {
426443
updateColumn={(column) => {
427444
setColumns((columns) => {
428445
const newColumns = [...columns];
429-
newColumns[selectedColumnId] = column;
446+
const index = columns.findIndex((c) => c.col === column.col);
447+
newColumns[index] = column;
430448
updateUserChanges("columns", selectedColumnId, column);
431449
return newColumns;
432450
});

llmstack/client/src/components/sheets/SheetColumnMenu.jsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ export function SheetColumnMenu({
145145

146146
const handleAddOrEditColumn = () => {
147147
const newColumn = {
148-
col: columns.length,
148+
col: column ? column.col : numberToLetters(columns.length),
149149
title: columnName || "New Column",
150150
kind: columnType,
151151
data:

llmstack/sheets/apis.py

Lines changed: 11 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -101,37 +101,22 @@ def patch(self, request, sheet_uuid=None):
101101
sheet.name = request.data.get("name", sheet.name)
102102
sheet.extra_data = request.data.get("extra_data", sheet.extra_data)
103103

104-
if "data" in request.data:
105-
if "columns" in request.data["data"]:
106-
sheet.data["columns"] = [
107-
PromptlySheetColumn(**column_data).model_dump() for column_data in request.data["data"]["columns"]
108-
]
104+
if "total_rows" in request.data:
105+
sheet.data["total_rows"] = request.data["total_rows"]
109106

110-
if "total_rows" in request.data["data"]:
111-
sheet.data["total_rows"] = request.data["data"]["total_rows"]
107+
if "description" in request.data:
108+
sheet.data["description"] = request.data["description"]
112109

113-
if "description" in request.data["data"]:
114-
sheet.data["description"] = request.data["data"]["description"]
110+
if "columns" in request.data:
111+
sheet.data["columns"] = [
112+
PromptlySheetColumn(**column_data).model_dump() for column_data in request.data["columns"]
113+
]
115114

116115
sheet.save()
117116

118-
if "data" in request.data and "cells" in request.data["data"]:
119-
cells_data = []
120-
for row_number in request.data["data"]["cells"]:
121-
if not isinstance(request.data["data"]["cells"][row_number], dict):
122-
raise ValueError("Invalid cells data")
123-
for column_number in request.data["data"]["cells"][row_number]:
124-
cell_data = request.data["data"]["cells"][row_number][column_number]
125-
cell_data.pop("row", None)
126-
cell_data.pop("col", None)
127-
cells_data.append(PromptlySheetCell(row=row_number, col=column_number, **cell_data))
128-
129-
if cells_data: # Only save cells if there's data
130-
sheet.save(cells=cells_data)
131-
else:
132-
# If there are no cells, update the total_rows to 0
133-
sheet.data["total_rows"] = 0
134-
sheet.save()
117+
if "cells" in request.data:
118+
cells = [PromptlySheetCell(**cell_data) for cell_data in request.data.get("cells", {}).values()]
119+
sheet.save(cells=cells, update_fields=["data"])
135120

136121
return DRFResponse(PromptlySheetSerializer(instance=sheet).data)
137122

0 commit comments

Comments
 (0)