feat(grid): add persistent SQL filter views

This commit is contained in:
zipg authored and GitHub committed 2026-08-15 14:45:52 +08:00
1 parent 8bf4485a75
commit 9e7d80f467
27 files changed
+1428 -107

No files matched your search

@@ -1,5 +1,5 @@
import { describe, expect, it } from "vitest";
import { buildDataGridStructuredWhere, useDataGridFilterBuilder, type DataGridStructuredFilterRule } from "@/composables/useDataGridFilterBuilder";
import { describe, expect, it, vi } from "vitest";
import { buildDataGridStructuredWhere, createDataGridFilterConditionCache, moveDataGridStructuredFilterRule, useDataGridFilterBuilder, type DataGridStructuredFilterRule } from "@/composables/useDataGridFilterBuilder";
describe("useDataGridFilterBuilder", () => {
it("searches columns by camel-case initials and any-position text", () => {
@@ -52,4 +52,52 @@ describe("useDataGridFilterBuilder", () => {
]),
).toBe("((a) AND (b)) OR (c)");
});
it("moves complete and disabled rules while preserving their condition data", async () => {
let nextId = 0;
const builder = useDataGridFilterBuilder({
columns: ["a", "b", "c"],
createId: () => `rule-${++nextId}`,
isComplete: () => true,
buildCondition: async (rule) => `${rule.columnName} = ${rule.rawValue}`,
});
builder.ensureRule();
builder.updateRule("rule-1", { columnName: "a", rawValue: "1" });
builder.addRule();
builder.updateRule("rule-2", { columnName: "b", rawValue: "2", disabled: true });
builder.addRule();
builder.updateRule("rule-3", { columnName: "c", rawValue: "3" });
builder.moveRule("rule-3", 0);
expect(builder.rules.value.map((rule) => rule.id)).toEqual(["rule-3", "rule-1", "rule-2"]);
expect(builder.rules.value[2]).toMatchObject({ columnName: "b", rawValue: "2", disabled: true });
expect(await builder.buildWhere()).toBe("(c = 3) AND (a = 1)");
});
it("clamps rule moves and ignores unknown rule ids", () => {
const rule = (id: string): DataGridStructuredFilterRule => ({ id, columnName: id, mode: "equals", rawValue: id, rawEndValue: "", conjunction: "AND" });
const rules = [rule("a"), rule("b"), rule("c")];
expect(moveDataGridStructuredFilterRule(rules, "a", 99).map((item) => item.id)).toEqual(["b", "c", "a"]);
expect(moveDataGridStructuredFilterRule(rules, "c", -2).map((item) => item.id)).toEqual(["c", "a", "b"]);
expect(moveDataGridStructuredFilterRule(rules, "missing", 1)).toEqual(rules);
});
it("reuses unchanged rule conditions and drops removed rules", async () => {
const cache = createDataGridFilterConditionCache();
const buildFirst = vi.fn(async () => "id = 1");
const buildChanged = vi.fn(async () => "id = 2");
await expect(cache.resolve("rule-1", "id:1", buildFirst)).resolves.toBe("id = 1");
await expect(cache.resolve("rule-1", "id:1", buildFirst)).resolves.toBe("id = 1");
expect(buildFirst).toHaveBeenCalledOnce();
await expect(cache.resolve("rule-1", "id:2", buildChanged)).resolves.toBe("id = 2");
expect(buildChanged).toHaveBeenCalledOnce();
cache.retain([]);
await expect(cache.resolve("rule-1", "id:2", buildChanged)).resolves.toBe("id = 2");
expect(buildChanged).toHaveBeenCalledTimes(2);
});
});