admin: activity history filters become a live-apply toolbar
the five-field form with its apply button is gone. one row holds a search-shaped domain field and a client ip field that debounce into the url with enter flushing at once, result segments and a time menu that commit instantly, and a clear that appears only when a filter is active without reflowing the row. presets freeze both absolute bounds at click time so a bookmark describes the same investigation later, custom ranges apply atomically through set range with inline validation, and echo queues keep in-flight commits from clobbering newer typing or newer picks. live mode renders no toolbar, the availability banner became a footer note, previous rows stay visible during refetch, and every control carries a 44px hit target.
This commit is contained in:
@@ -521,27 +521,18 @@ test("an open streamed detail survives Freeze and Resume", async () => {
|
||||
expect(detailDialog().textContent).toBe(snapshot);
|
||||
});
|
||||
|
||||
test("the filter row stays visible, keeps its values, and is out of the tab order", async () => {
|
||||
test("live renders no filter toolbar, not even a disabled one", async () => {
|
||||
await openLive("/activity?mode=live&domain=ads&client=192.0.2.10&blocked=true");
|
||||
|
||||
const domain = screen.getByLabelText("Domain contains") as HTMLInputElement;
|
||||
expect(domain.value).toBe("ads");
|
||||
expect(domain.disabled).toBe(true);
|
||||
expect((screen.getByLabelText("Client (exact)") as HTMLInputElement).disabled).toBe(true);
|
||||
expect((screen.getByLabelText("Since") as HTMLInputElement).disabled).toBe(true);
|
||||
expect((screen.getByLabelText("Until") as HTMLInputElement).disabled).toBe(true);
|
||||
|
||||
const form = domain.closest("form")!;
|
||||
const controls = [...form.querySelectorAll("input, button, select, textarea, a[href], [tabindex]")];
|
||||
expect(controls.length).toBeGreaterThan(0);
|
||||
for (const control of controls) {
|
||||
// A disabled form control is skipped by the browser's tab order, and RAC
|
||||
// pins its own trigger out of it as well. Nothing in the row may
|
||||
// reintroduce itself with a reachable tabindex.
|
||||
expect(control.hasAttribute("disabled")).toBe(true);
|
||||
const tabindex = control.getAttribute("tabindex");
|
||||
expect(tabindex === null || tabindex === "-1").toBe(true);
|
||||
}
|
||||
// The stream is unfiltered — the server sends every query — so a row of
|
||||
// controls here would promise filtering that is not happening. The filters
|
||||
// are not lost: they are in the URL, and History applies them on the way back.
|
||||
expect(screen.queryByLabelText("Filter domains")).toBeNull();
|
||||
expect(screen.queryByLabelText("Client IP (exact match)")).toBeNull();
|
||||
expect(screen.queryByRole("radio", { name: "Blocked" })).toBeNull();
|
||||
expect(screen.queryByRole("button", { name: /^Time: / })).toBeNull();
|
||||
expect(screen.queryByText("Clear")).toBeNull();
|
||||
expect(screen.getByText(/the History filters apply to history only/)).toBeTruthy();
|
||||
});
|
||||
|
||||
test("live mode asks for no query pages, whatever filters the url retained", async () => {
|
||||
@@ -555,13 +546,12 @@ test("leaving live closes the stream, and coming back opens exactly one fresh on
|
||||
await openLive("/activity?mode=live&domain=ads");
|
||||
|
||||
fireEvent.click(screen.getByRole("tab", { name: "History" }));
|
||||
await screen.findByRole("button", { name: "Apply filters" });
|
||||
await screen.findByLabelText("Filter domains");
|
||||
expect(sources).toHaveLength(1);
|
||||
expect(sources[0]!.closed).toBe(true);
|
||||
// The filters came along, which is the point of switching rather than
|
||||
// navigating: the reader keeps the question they were asking.
|
||||
expect((screen.getByLabelText("Domain contains") as HTMLInputElement).value).toBe("ads");
|
||||
expect((screen.getByLabelText("Domain contains") as HTMLInputElement).disabled).toBe(false);
|
||||
expect((screen.getByLabelText("Filter domains") as HTMLInputElement).value).toBe("ads");
|
||||
|
||||
fireEvent.click(screen.getByRole("tab", { name: "Live" }));
|
||||
await screen.findByRole("button", { name: "Freeze" });
|
||||
|
||||
Reference in New Issue
Block a user