From c8ed4d5ecb15ab1711647b58e6ef18075eac05f7 Mon Sep 17 00:00:00 2001 From: "Crane.z" <1481445951@qq.com> Date: Mon, 14 Sep 2026 17:12:50 +0800 Subject: [PATCH 1/2] fix(chen): preserve pending edits during save preview --- ui/chen/components/DataGrid.client.test.ts | 71 ++++++++++++++++++++++ ui/chen/components/DataGrid.client.vue | 1 - ui/chen/utils/dataViewEditing.ts | 3 +- 3 files changed, 73 insertions(+), 2 deletions(-) create mode 100644 ui/chen/components/DataGrid.client.test.ts diff --git a/ui/chen/components/DataGrid.client.test.ts b/ui/chen/components/DataGrid.client.test.ts new file mode 100644 index 000000000..7dbc86355 --- /dev/null +++ b/ui/chen/components/DataGrid.client.test.ts @@ -0,0 +1,71 @@ +import { describe, expect, it } from "vitest"; +import { computed } from "vue"; +import dataGridSource from "~/chen/components/DataGrid.client.vue?raw"; +import { + acceptChenSaveChangesPreviewResult, + applyChenDataViewCellChange, + beginChenDataViewRequest, + buildChenSaveChangesPayload, + chenDataViewRows, + createChenDataViewEditState +} from "~/chen/utils/dataViewEditing"; + +function displayedDataGridRows(props: Record) { + const declaration = dataGridSource.match(/const rowData = computed\(\(\) => \{[\s\S]*?\n\}\);/)?.[0]; + if (!declaration) throw new Error("DataGrid rowData computation not found"); + const rowData = new Function("computed", "props", "chenDataViewRows", `${declaration}; return rowData;`)( + computed, + props, + chenDataViewRows + ); + return rowData.value; +} + +describe("Chen DataGrid save preview", () => { + it("keeps pending cell values displayed while the save confirmation is open", () => { + const state = createChenDataViewEditState(); + const data = { + editable: true, + fields: [ + { + name: "id", + sourceColumn: "id", + sourceTable: "products", + sourceSchema: "public", + primaryKey: true, + editable: false + }, + { + name: "price", + sourceColumn: "price", + sourceTable: "products", + sourceSchema: "public", + type: "DECIMAL", + editable: true + } + ], + data: [{ id: 1, price: "22.40" }] + }; + const price = data.fields[1]!; + + applyChenDataViewCellChange(state, data, data.data[0]!, price, "22.40", "33.33"); + const payload = buildChenSaveChangesPayload( + { title: "products", schema: "public", table: "products" }, + data, + state + ); + const request = beginChenDataViewRequest(state, "preview", payload); + + expect(request).not.toBeNull(); + expect( + acceptChenSaveChangesPreviewResult(state, { + success: true, + dataView: "products", + changeCount: 1 + }) + ).toBe("confirm"); + expect(state.activeRequest?.kind).toBe("confirm"); + expect(displayedDataGridRows({ dataset: data, editState: state, editMode: "none" })[0]?.price).toBe("33.33"); + expect(data.data[0]?.price).toBe("22.40"); + }); +}); diff --git a/ui/chen/components/DataGrid.client.vue b/ui/chen/components/DataGrid.client.vue index 0c082bc24..8ce090b17 100644 --- a/ui/chen/components/DataGrid.client.vue +++ b/ui/chen/components/DataGrid.client.vue @@ -194,7 +194,6 @@ const rowData = computed(() => { const dirtyVersion = props.editState?.dirtyVersion; void dirtyVersion; if (!props.dataset) return []; - if (props.editMode === "none" || !props.editState) return props.dataset.data; return chenDataViewRows(props.dataset, props.editState); }); diff --git a/ui/chen/utils/dataViewEditing.ts b/ui/chen/utils/dataViewEditing.ts index ea7418ea8..d9797b7b8 100644 --- a/ui/chen/utils/dataViewEditing.ts +++ b/ui/chen/utils/dataViewEditing.ts @@ -541,7 +541,8 @@ export function isChenDirtyCell( return Boolean(state.dirtyCells[dirtyKey(identity.key, field.sourceColumn)]); } -export function chenDataViewRows(dataset: ChenDataViewDataset, state: ChenDataViewEditState) { +export function chenDataViewRows(dataset: ChenDataViewDataset, state: ChenDataViewEditState | null | undefined) { + if (!state) return dataset.data; const rows = dataset.data.map((source) => { const row = { ...source }; for (const field of dataset.fields) { From 8091148ccbe112575ee7a4db29f7ec86bad224a6 Mon Sep 17 00:00:00 2001 From: "Crane.z" <1481445951@qq.com> Date: Mon, 14 Sep 2026 17:18:08 +0800 Subject: [PATCH 2/2] chore(chen): remove save preview test --- ui/chen/components/DataGrid.client.test.ts | 71 ---------------------- 1 file changed, 71 deletions(-) delete mode 100644 ui/chen/components/DataGrid.client.test.ts diff --git a/ui/chen/components/DataGrid.client.test.ts b/ui/chen/components/DataGrid.client.test.ts deleted file mode 100644 index 7dbc86355..000000000 --- a/ui/chen/components/DataGrid.client.test.ts +++ /dev/null @@ -1,71 +0,0 @@ -import { describe, expect, it } from "vitest"; -import { computed } from "vue"; -import dataGridSource from "~/chen/components/DataGrid.client.vue?raw"; -import { - acceptChenSaveChangesPreviewResult, - applyChenDataViewCellChange, - beginChenDataViewRequest, - buildChenSaveChangesPayload, - chenDataViewRows, - createChenDataViewEditState -} from "~/chen/utils/dataViewEditing"; - -function displayedDataGridRows(props: Record) { - const declaration = dataGridSource.match(/const rowData = computed\(\(\) => \{[\s\S]*?\n\}\);/)?.[0]; - if (!declaration) throw new Error("DataGrid rowData computation not found"); - const rowData = new Function("computed", "props", "chenDataViewRows", `${declaration}; return rowData;`)( - computed, - props, - chenDataViewRows - ); - return rowData.value; -} - -describe("Chen DataGrid save preview", () => { - it("keeps pending cell values displayed while the save confirmation is open", () => { - const state = createChenDataViewEditState(); - const data = { - editable: true, - fields: [ - { - name: "id", - sourceColumn: "id", - sourceTable: "products", - sourceSchema: "public", - primaryKey: true, - editable: false - }, - { - name: "price", - sourceColumn: "price", - sourceTable: "products", - sourceSchema: "public", - type: "DECIMAL", - editable: true - } - ], - data: [{ id: 1, price: "22.40" }] - }; - const price = data.fields[1]!; - - applyChenDataViewCellChange(state, data, data.data[0]!, price, "22.40", "33.33"); - const payload = buildChenSaveChangesPayload( - { title: "products", schema: "public", table: "products" }, - data, - state - ); - const request = beginChenDataViewRequest(state, "preview", payload); - - expect(request).not.toBeNull(); - expect( - acceptChenSaveChangesPreviewResult(state, { - success: true, - dataView: "products", - changeCount: 1 - }) - ).toBe("confirm"); - expect(state.activeRequest?.kind).toBe("confirm"); - expect(displayedDataGridRows({ dataset: data, editState: state, editMode: "none" })[0]?.price).toBe("33.33"); - expect(data.data[0]?.price).toBe("22.40"); - }); -});