fix(mongodb): keep local value filters across page size changes

This commit is contained in:
zipg
2026-09-19 09:46:36 +08:00
committed by GitHub
parent 2fa113b495
commit 85a10be4c9
4 changed files with 26 additions and 12 deletions
@@ -339,7 +339,20 @@ function documentDataSignature(): string | undefined {
}
}
const documentLocalColumnFilterRestoreKey = computed(() => documentDataSignature());
// Local value filters describe column values, not the rows that happen to be
// loaded, so paging and page-size changes must not drop them. Only a new query
// (collection, filter or sort) invalidates the snapshot; restored filters are
// mapped back by column name, so a changed column set is handled as well.
function documentLocalColumnFilterSignature(): string | undefined {
try {
return JSON.stringify([documentStoreProvider.value.kind, props.connectionId, props.database, props.collection, currentDocumentFilter() ?? null, currentDocumentSortJson(sortInput.value) ?? null]);
} catch {
// Malformed filter/sort JSON: nothing stable to key filters against.
return undefined;
}
}
const documentLocalColumnFilterRestoreKey = computed(() => documentLocalColumnFilterSignature());
let loadedDocumentDataSignature: string | undefined;
@@ -391,13 +404,11 @@ function handleLocalColumnFiltersChange(filters: SerializedDataGridLocalColumnFi
persistDocumentBrowserState({ includeData: true });
}
// Keep these sources in lockstep with documentDataSignature(): every input that
// invalidates held rows (including pageSize and the infinite-scroll setting, which
// can change mid-session at page 0 without moving `page`) must also drop the
// local-filter snapshot, or a tab switch would replay filters the user watched
// DataGrid clear on its own restore-key change.
// Keep these sources in lockstep with documentLocalColumnFilterSignature(): a
// changed query means the local-filter snapshot no longer describes what the
// user is looking at.
watch(
[filterInput, sortInput, appliedDocumentFilter, page, pageSize, () => settingsStore.editorSettings.infiniteScroll],
[filterInput, sortInput, appliedDocumentFilter],
() => {
localColumnFilters.value = {};
localColumnFilterColumns.value = undefined;
@@ -405,6 +416,8 @@ watch(
},
{ deep: true },
);
// Paging and page-size changes reload rows, but the local value filters stay put.
watch([page, pageSize, () => settingsStore.editorSettings.infiniteScroll], () => persistDocumentBrowserState());
watch(documentFilterRules, () => persistDocumentBrowserState(), { deep: true });
// Seed the grid from the cached page so a tab switch costs no round trip
@@ -399,16 +399,17 @@ describe("DocumentBrowser tab state (tab switch persistence)", () => {
expect(dataGrid.localColumnFilterColumns).toBeUndefined();
});
it("clears mongodb local column filters when the page size changes mid-session", async () => {
it("keeps mongodb local column filters when the page size changes mid-session", async () => {
await mountBrowser({ stateKey: "tab-local-filters-page-size" });
dataGrid.localFiltersChange!({ "1": ["str:OpenGate"] });
await flushUi();
expect(dataGrid.localColumnFilters).toEqual({ "1": ["str:OpenGate"] });
// Page stays at 0 for a page-size change, so only the pageSize input invalidates the snapshot.
// A page-size change reloads rows, but the value filter is about columns, not rows.
await dataGrid.paginate!(0, 10);
await flushUi();
expect(dataGrid.localColumnFilters).toEqual({});
expect(dataGrid.localColumnFilters).toEqual({ "1": ["str:OpenGate"] });
expect(dataGrid.localColumnFilterColumns).toEqual(["_id", "name"]);
app!.unmount();
app = null;
@@ -416,8 +417,8 @@ describe("DocumentBrowser tab state (tab switch persistence)", () => {
await flushUi();
await mountBrowser({ stateKey: "tab-local-filters-page-size" });
expect(dataGrid.localColumnFilters).toEqual({});
expect(dataGrid.localColumnFilterColumns).toBeUndefined();
expect(dataGrid.localColumnFilters).toEqual({ "1": ["str:OpenGate"] });
expect(dataGrid.localColumnFilterColumns).toEqual(["_id", "name"]);
});
it("still forces a real reload from the refresh button after a restore", async () => {
Binary file not shown.

After

Width:  |  Height:  |  Size: 182 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 181 KiB