fix: preserve pending row edits when switching tabs (#362)
Wrap ContentArea in KeepAlive to cache tab instances across switches. Add a module-level pending-changes cache in useDataGridEditor so edits survive DataGrid destruction caused by result eviction and reload.
This commit is contained in:
1 parent
fe6fead2dc
commit
47ec339d5a
8 files changed
+135
-65
No files matched your search
@@ -12,28 +12,35 @@ const ROW_NUM_WIDTH = 48;
|
||||
|
||||
export interface UseDataGridColumnResizeOptions {
|
||||
columns: ComputedRef<string[]>;
|
||||
rows: ComputedRef<CellValue[][]>;
|
||||
sourceRows: ComputedRef<CellValue[][]>;
|
||||
columnIndexes: ComputedRef<number[]>;
|
||||
gridRef: Ref<HTMLDivElement | undefined>;
|
||||
}
|
||||
|
||||
export function useDataGridColumnResize(options: UseDataGridColumnResizeOptions) {
|
||||
const { columns, rows, gridRef } = options;
|
||||
const { columns, sourceRows, columnIndexes, gridRef } = options;
|
||||
|
||||
const columnWidths = ref<number[]>([]);
|
||||
const { width: gridWidth } = useElementSize(gridRef);
|
||||
let isResizing = false;
|
||||
|
||||
function sampleColumnValues(rowData: CellValue[][], colIdx: number): CellValue[] {
|
||||
return rowData.slice(0, DATA_GRID_SAMPLE_ROWS).map((row) => row[colIdx] ?? null);
|
||||
function sampleColumnValues(visibleColIdx: number): CellValue[] {
|
||||
const actualColIdx = columnIndexes.value[visibleColIdx];
|
||||
const rows = sourceRows.value;
|
||||
const end = Math.min(rows.length, DATA_GRID_SAMPLE_ROWS);
|
||||
const values: CellValue[] = [];
|
||||
for (let i = 0; i < end; i++) {
|
||||
values.push(rows[i][actualColIdx] ?? null);
|
||||
}
|
||||
return values;
|
||||
}
|
||||
|
||||
function initColumnWidths() {
|
||||
if (columnWidths.value.length !== columns.value.length) {
|
||||
const rowData = rows.value;
|
||||
columnWidths.value = columns.value.map((colName, colIdx) => {
|
||||
return calculateDataGridColumnWidth({
|
||||
columnName: colName,
|
||||
sampleValues: sampleColumnValues(rowData, colIdx),
|
||||
sampleValues: sampleColumnValues(colIdx),
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -61,10 +68,9 @@ export function useDataGridColumnResize(options: UseDataGridColumnResizeOptions)
|
||||
function autoFitColumn(colIdx: number) {
|
||||
const colName = columns.value[colIdx];
|
||||
if (!colName) return;
|
||||
const rowData = rows.value;
|
||||
columnWidths.value[colIdx] = calculateDataGridColumnWidth({
|
||||
columnName: colName,
|
||||
sampleValues: sampleColumnValues(rowData, colIdx),
|
||||
sampleValues: sampleColumnValues(colIdx),
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { ref, computed, nextTick, watch, type ComputedRef, type Ref } from "vue";
|
||||
import { ref, computed, nextTick, watch, onBeforeUnmount, type ComputedRef, type Ref } from "vue";
|
||||
import * as api from "@/lib/api";
|
||||
import {
|
||||
buildDataGridRollbackStatements,
|
||||
@@ -73,6 +73,7 @@ export interface UseDataGridEditorOptions {
|
||||
getRowItem: (rowId: number) => RowItem | undefined;
|
||||
pageSize: Ref<number>;
|
||||
currentPage: Ref<number>;
|
||||
cacheKey?: ComputedRef<string | undefined>;
|
||||
emit: {
|
||||
(
|
||||
event: "reload",
|
||||
@@ -86,6 +87,15 @@ export interface UseDataGridEditorOptions {
|
||||
};
|
||||
}
|
||||
|
||||
interface PendingChangesSnapshot {
|
||||
newRows: CellValue[][];
|
||||
dirtyRows: Map<number, Map<number, CellValue>>;
|
||||
deletedRows: Set<number>;
|
||||
columnCount: number;
|
||||
}
|
||||
|
||||
const pendingChangesCache = new Map<string, PendingChangesSnapshot>();
|
||||
|
||||
export function useDataGridEditor(options: UseDataGridEditorOptions) {
|
||||
const connectionStore = useConnectionStore();
|
||||
const historyStore = useHistoryStore();
|
||||
@@ -110,6 +120,7 @@ export function useDataGridEditor(options: UseDataGridEditorOptions) {
|
||||
getRowItem,
|
||||
pageSize,
|
||||
currentPage,
|
||||
cacheKey,
|
||||
} = options;
|
||||
|
||||
const editingCell = ref<{ rowId: number; col: number } | null>(null);
|
||||
@@ -119,6 +130,20 @@ export function useDataGridEditor(options: UseDataGridEditorOptions) {
|
||||
const newRows = ref<CellValue[][]>([]);
|
||||
const deletedRows = ref<Set<number>>(new Set());
|
||||
|
||||
// Restore cached pending changes from a previous instance (e.g. after result eviction + reload)
|
||||
const key = cacheKey?.value;
|
||||
if (key) {
|
||||
const cached = pendingChangesCache.get(key);
|
||||
if (cached && cached.columnCount === result.value.columns.length) {
|
||||
newRows.value = cached.newRows;
|
||||
dirtyRows.value = cached.dirtyRows;
|
||||
deletedRows.value = cached.deletedRows;
|
||||
pendingChangesCache.delete(key);
|
||||
} else {
|
||||
pendingChangesCache.delete(key);
|
||||
}
|
||||
}
|
||||
|
||||
const dirtyRowCount = computed(() => dirtyRows.value.size);
|
||||
const newRowCount = computed(() => newRows.value.length);
|
||||
const deletedRowCount = computed(() => deletedRows.value.size);
|
||||
@@ -137,6 +162,10 @@ export function useDataGridEditor(options: UseDataGridEditorOptions) {
|
||||
(!!customSave?.value || (!!connectionId.value && !!database.value && !!tableMeta.value)),
|
||||
);
|
||||
|
||||
if (hasPendingChanges.value && useTransaction.value) {
|
||||
transactionActive.value = true;
|
||||
}
|
||||
|
||||
function enterTransaction() {
|
||||
transactionActive.value = true;
|
||||
}
|
||||
@@ -714,6 +743,21 @@ export function useDataGridEditor(options: UseDataGridEditorOptions) {
|
||||
},
|
||||
);
|
||||
|
||||
// Save pending changes before the component is destroyed so they can be
|
||||
// restored if a new DataGrid instance is created for the same tab
|
||||
// (e.g. after result eviction + reload).
|
||||
onBeforeUnmount(() => {
|
||||
const k = cacheKey?.value;
|
||||
if (k && hasPendingChanges.value) {
|
||||
pendingChangesCache.set(k, {
|
||||
newRows: [...newRows.value.map((r) => [...r])],
|
||||
dirtyRows: new Map([...dirtyRows.value].map(([i, m]) => [i, new Map(m)])),
|
||||
deletedRows: new Set(deletedRows.value),
|
||||
columnCount: result.value.columns.length,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
editingCell,
|
||||
editValue,
|
||||
|
||||
Reference in new issue
Block a user