diff --git a/apps/client/src/widgets/view_widgets/table_view/columns.spec.ts b/apps/client/src/widgets/view_widgets/table_view/columns.spec.ts index 64d5bc4b3..083d03820 100644 --- a/apps/client/src/widgets/view_widgets/table_view/columns.spec.ts +++ b/apps/client/src/widgets/view_widgets/table_view/columns.spec.ts @@ -3,6 +3,20 @@ import { restoreExistingData } from "./columns"; import type { ColumnDefinition } from "tabulator-tables"; describe("restoreExistingData", () => { + it("maintains important columns properties", () => { + const newDefs: ColumnDefinition[] = [ + { field: "title", title: "Title", editor: "input" }, + { field: "noteId", title: "Note ID", formatter: "color", visible: false } + ]; + const oldDefs: ColumnDefinition[] = [ + { field: "title", title: "Title", width: 300, visible: true }, + { field: "noteId", title: "Note ID", width: 200, visible: true } + ]; + const restored = restoreExistingData(newDefs, oldDefs); + expect(restored[0].editor).toBe("input"); + expect(restored[1].formatter).toBe("color"); + }); + it("should restore existing column data", () => { const newDefs: ColumnDefinition[] = [ { field: "title", title: "Title", editor: "input" }, @@ -42,8 +56,26 @@ describe("restoreExistingData", () => { { field: "noteId", title: "Note ID", width: 200, visible: true } ]; const restored = restoreExistingData(newDefs, oldDefs, 0); + expect(restored.length).toBe(3); expect(restored[0].field).toBe("newColumn"); expect(restored[1].field).toBe("title"); expect(restored[2].field).toBe("noteId"); }); + + it("inserts new columns at the end if no position is specified", () => { + const newDefs: ColumnDefinition[] = [ + { field: "title", title: "Title", editor: "input" }, + { field: "noteId", title: "Note ID", visible: false }, + { field: "newColumn", title: "New Column", editor: "input" } + ]; + const oldDefs: ColumnDefinition[] = [ + { field: "title", title: "Title", width: 300, visible: true }, + { field: "noteId", title: "Note ID", width: 200, visible: true } + ]; + const restored = restoreExistingData(newDefs, oldDefs); + expect(restored.length).toBe(3); + expect(restored[0].field).toBe("title"); + expect(restored[1].field).toBe("noteId"); + expect(restored[2].field).toBe("newColumn"); + }); }); diff --git a/apps/client/src/widgets/view_widgets/table_view/columns.ts b/apps/client/src/widgets/view_widgets/table_view/columns.ts index d70cd8aca..560efdf4b 100644 --- a/apps/client/src/widgets/view_widgets/table_view/columns.ts +++ b/apps/client/src/widgets/view_widgets/table_view/columns.ts @@ -93,30 +93,30 @@ export function buildColumnDefinitions(info: AttributeDefinitionInformation[], m } export function restoreExistingData(newDefs: ColumnDefinition[], oldDefs: ColumnDefinition[], position?: number) { - const existingColumns: ColumnDefinition[] = [] - const byField = new Map; - for (const def of oldDefs) { - byField.set(def.field ?? "", def); - existingColumns.push(def); - } + // 1. Keep existing columns, but restore their properties like width, visibility and order. + const newItemsByField = new Map( + newDefs.map(def => [def.field!, def]) + ); + const existingColumns = oldDefs + .map(item => { + return { + ...newItemsByField.get(item.field!), + width: item.width, + visible: item.visible, + }; + }) as ColumnDefinition[]; - const newColumns: ColumnDefinition[] = []; - for (const newDef of newDefs) { - const oldDef = byField.get(newDef.field ?? ""); - if (!oldDef) { - newColumns.push(newDef); - } else { - newDef.width = oldDef.width; - newDef.visible = oldDef.visible; - } - } + // 2. Determine new columns. + const existingFields = new Set(existingColumns.map(item => item.field)); + const newColumns = newDefs + .filter(item => !existingFields.has(item.field!)); // Clamp position to a valid range const insertPos = position !== undefined ? Math.min(Math.max(position, 0), existingColumns.length) : existingColumns.length; - // Insert new columns at the specified position + // 3. Insert new columns at the specified position return [ ...existingColumns.slice(0, insertPos), ...newColumns,