swarm-ui: ignore a saved table filter whose column is gone
This commit is contained in:
parent
71e303ed62
commit
885c051b33
3 changed files with 43 additions and 1 deletions
|
|
@ -24,6 +24,7 @@ import { useLocalSetting } from "@hive/shared/settings-storage.js";
|
||||||
import { MultiselectFilterOptions } from "../multiselect-filter/MultiselectFilter.js";
|
import { MultiselectFilterOptions } from "../multiselect-filter/MultiselectFilter.js";
|
||||||
import { focusInto, restoreFocus } from "../popover/focus.js";
|
import { focusInto, restoreFocus } from "../popover/focus.js";
|
||||||
import { clampLeft } from "./popover-position.js";
|
import { clampLeft } from "./popover-position.js";
|
||||||
|
import { forExistingColumns } from "./table-filters.js";
|
||||||
import "./Table.css";
|
import "./Table.css";
|
||||||
|
|
||||||
export interface TableColumn<T> {
|
export interface TableColumn<T> {
|
||||||
|
|
@ -157,9 +158,15 @@ export function useTableFilters<T>(
|
||||||
rows: T[],
|
rows: T[],
|
||||||
storageKey: string,
|
storageKey: string,
|
||||||
) {
|
) {
|
||||||
const [filters, setFilters] = useLocalSetting<
|
const [saved, setFilters] = useLocalSetting<
|
||||||
Record<string, ColumnFilterState>
|
Record<string, ColumnFilterState>
|
||||||
>(storageKey, {});
|
>(storageKey, {});
|
||||||
|
// A saved filter on a column that no longer exists would hide every row;
|
||||||
|
// work from the live ones, so the next save drops the rest.
|
||||||
|
const filters = forExistingColumns(
|
||||||
|
saved,
|
||||||
|
columns.map((c) => c.key),
|
||||||
|
);
|
||||||
|
|
||||||
const activeFilters = Object.entries(filters).filter(([, f]) =>
|
const activeFilters = Object.entries(filters).filter(([, f]) =>
|
||||||
isFilterActive(f),
|
isFilterActive(f),
|
||||||
|
|
|
||||||
16
frontend/packages/swarm-ui/src/ui/table/table-filters.ts
Normal file
16
frontend/packages/swarm-ui/src/ui/table/table-filters.ts
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
// What a table does with the filters it remembered, without a DOM.
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The saved filters whose column still exists. Filters are kept by column
|
||||||
|
* key, so one saved for a column a later deploy renamed or removed would
|
||||||
|
* match no row and hide every one; it is ignored instead, and dropped the
|
||||||
|
* next time the filters are saved.
|
||||||
|
*/
|
||||||
|
export function forExistingColumns<F>(
|
||||||
|
filters: Record<string, F>,
|
||||||
|
columnKeys: string[],
|
||||||
|
): Record<string, F> {
|
||||||
|
return Object.fromEntries(
|
||||||
|
Object.entries(filters).filter(([key]) => columnKeys.includes(key)),
|
||||||
|
);
|
||||||
|
}
|
||||||
19
frontend/packages/swarm-ui/test/table-filters.test.mjs
Normal file
19
frontend/packages/swarm-ui/test/table-filters.test.mjs
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
// Which remembered table filters still apply. Run by `npm test`, which Node
|
||||||
|
// runs with its built-in test runner and type stripping, so the `.ts` module
|
||||||
|
// is imported as it is.
|
||||||
|
import assert from "node:assert/strict";
|
||||||
|
import { test } from "node:test";
|
||||||
|
import { forExistingColumns } from "../src/ui/table/table-filters.ts";
|
||||||
|
|
||||||
|
test("a filter on a column that is gone is ignored", () => {
|
||||||
|
const saved = { status: { value: "up" }, oldName: { value: "x" } };
|
||||||
|
assert.deepEqual(forExistingColumns(saved, ["status", "name"]), {
|
||||||
|
status: { value: "up" },
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test("filters on columns that all exist are kept, and none is fine", () => {
|
||||||
|
const saved = { a: 1, b: 2 };
|
||||||
|
assert.deepEqual(forExistingColumns(saved, ["a", "b"]), saved);
|
||||||
|
assert.deepEqual(forExistingColumns({}, ["a"]), {});
|
||||||
|
});
|
||||||
Loading…
Reference in a new issue