Keep search, facets, and sort in the page URL.

CONTENT-WP-0002-T04 writes q, facet values, and sort into history so back and forward restore the table.

Assistant: grok
Assistant-Session: 01a1346c-fdff-7741-b1af-b7283661554b
This commit is contained in:
tegwick 2026-10-13 23:12:00 +02:00
parent d92eb25f92
commit 0cbc7baf49
8 changed files with 503 additions and 9 deletions

59
ui/lib/table-view.test.ts Normal file
View file

@ -0,0 +1,59 @@
import { describe, expect, it } from "vitest";
import { mapBrowserRow } from "./browser-row";
import { applyTableView, parseTableView, serializeTableView } from "./table-view";
const rows = [
mapBrowserRow(
{
id: "a",
title: "Alpha",
tldr: "First idea",
tags: ["one"],
kindLabel: "Concept",
route: "/a/",
kindHref: "/concept/",
},
["tags"],
),
mapBrowserRow(
{
id: "z",
title: "Zebra",
tldr: "Last idea",
tags: ["two"],
kindLabel: "Concept",
route: "/z/",
kindHref: "/concept/",
},
["tags"],
),
];
const sortable = (key: string) => key === "name" || key === "tldr" || key === "tags";
const base = { key: "name", dir: 1 as const };
describe("table view", () => {
it("round-trips search, repeated facets, and descending sort", () => {
const view = {
q: "idea",
facets: { tags: ["one", "two"] },
sort: { key: "name", dir: -1 as const },
};
const search = serializeTableView(view, base);
expect(search).toContain("q=idea");
expect(search).toContain("tags=one");
expect(search).toContain("tags=two");
expect(search).toContain("sort=-name");
expect(parseTableView(`?${search}`, ["tags"], sortable)).toEqual(view);
expect(serializeTableView({ q: "", facets: {}, sort: base }, base)).toBe("");
});
it("filters by facet and query, then sorts", () => {
const both = applyTableView(rows, parseTableView("?tags=one,two&sort=-name", ["tags"], sortable));
expect(both.map((row) => row.name)).toEqual(["Zebra", "Alpha"]);
const one = applyTableView(rows, parseTableView("?q=first&tags=one", ["tags"], sortable));
expect(one.map((row) => row.name)).toEqual(["Alpha"]);
const none = applyTableView(rows, parseTableView("?q=missing", ["tags"], sortable));
expect(none).toEqual([]);
});
});