fix(grid): show deleted row details in confirmation

This commit is contained in:
Melody Ruch authored and GitHub committed 2026-08-20 20:49:47 +08:00
1 parent b3acf1e558
commit e2a4b26379
7 files changed
+284 -23

No files matched your search

@@ -154,6 +154,56 @@ describe("useDataGridEditor row deletion confirmation", () => {
expect(editor.showDeleteRowConfirm.value).toBe(false);
expect(editor.newRows.value).toHaveLength(0);
});
it("populates pendingDeleteRowIds for a single-row delete request", () => {
const editor = createEditor(undefined, true);
editor.requestDeleteRow(-1);
expect(editor.pendingDeleteRowIds.value).toEqual([-1]);
});
it("populates pendingDeleteRowIds for a multi-row delete request and clears it on confirm", () => {
const editor = createEditor(undefined, true);
editor.newRows.value = [
[null, null, null],
[null, null, null],
];
editor.requestDeleteRows([-1, -2]);
expect(editor.pendingDeleteRowIds.value).toEqual([-1, -2]);
editor.confirmDeleteRow();
expect(editor.pendingDeleteRowIds.value).toEqual([]);
expect(editor.newRows.value).toHaveLength(0);
});
it("clears pendingDeleteRowIds when the confirmation dialog is closed without confirming", () => {
const editor = createEditor(undefined, true);
editor.requestDeleteRow(-1);
expect(editor.pendingDeleteRowIds.value).toEqual([-1]);
editor.showDeleteRowConfirm.value = false;
expect(editor.pendingDeleteRowIds.value).toEqual([]);
expect(editor.newRows.value).toHaveLength(1); // row itself was never actually deleted
});
it("confirmDeleteRow deletes the row and closes the dialog itself, without racing the cancel watcher", () => {
const editor = createEditor(undefined, true);
editor.requestDeleteRow(-1);
expect(editor.newRows.value).toHaveLength(1);
editor.confirmDeleteRow();
expect(editor.newRows.value).toHaveLength(0); // the row must actually be deleted
expect(editor.showDeleteRowConfirm.value).toBe(false); // and the dialog closes on its own
expect(editor.pendingDeleteRowIds.value).toEqual([]);
});
});
describe("useDataGridEditor appendPastedRowsToNewRow", () => {
@@ -1243,16 +1243,10 @@ export function useDataGridEditor(options: UseDataGridEditorOptions) {
}
const showDeleteRowConfirm = ref(false);
const pendingDeleteRowId = ref<number | null>(null);
const pendingDeleteRowIds = ref<number[]>([]);
function requestDeleteRow(rowId: number) {
if (!confirmDangerousRowDeletion.value) {
applyDeleteRow(rowId);
return;
}
pendingDeleteRowId.value = rowId;
showDeleteRowConfirm.value = true;
requestDeleteRows([rowId]);
}
function requestDeleteRows(rowIds: number[]) {
@@ -1265,16 +1259,21 @@ export function useDataGridEditor(options: UseDataGridEditorOptions) {
}
function confirmDeleteRow() {
if (pendingDeleteRowIds.value.length > 0) {
applyDeleteRows(pendingDeleteRowIds.value);
pendingDeleteRowIds.value = [];
return;
}
if (pendingDeleteRowId.value === null) return;
applyDeleteRow(pendingDeleteRowId.value);
pendingDeleteRowId.value = null;
const rowIds = pendingDeleteRowIds.value;
pendingDeleteRowIds.value = [];
showDeleteRowConfirm.value = false;
if (rowIds.length === 0) return;
applyDeleteRows(rowIds);
}
watch(
showDeleteRowConfirm,
(isOpen) => {
if (!isOpen) pendingDeleteRowIds.value = [];
},
{ flush: "sync" },
);
function restoreRow(rowId: number) {
const item = getRowItem(rowId);
if (item?.sourceIndex !== undefined && deletedRows.value.has(item.sourceIndex)) {
@@ -1798,7 +1797,6 @@ export function useDataGridEditor(options: UseDataGridEditorOptions) {
applyDeleteRows,
applyDeleteRow,
showDeleteRowConfirm,
pendingDeleteRowId,
pendingDeleteRowIds,
requestDeleteRow,
requestDeleteRows,
@@ -1,6 +1,6 @@
import { onMounted, ref } from "vue";
import { useTheme } from "@/composables/useTheme";
import { type SqlHighlighter, createShikiSqlHighlighter } from "@/lib/sql/sqlHighlighter";
import { type SqlHighlighter, createShikiSqlHighlighter, escapeHtml } from "@/lib/sql/sqlHighlighter";
export function useSqlHighlighter() {
const { isDark } = useTheme();
@@ -13,7 +13,7 @@ export function useSqlHighlighter() {
});
function highlight(sql: string): string {
return sqlHighlighter.value?.(sql) ?? sql;
return sqlHighlighter.value?.(sql) ?? escapeHtml(sql);
}
return { highlight, sqlHighlighter };