feat(FN-1081): add dashboard nodes management workflow

- Add node API typings and client methods plus a polling useNodes hook with visibility-triggered refresh
- Introduce NodesView with NodeCard, AddNodeModal, and NodeDetailModal to register, inspect, update, health-check, and remove nodes
- Wire the Nodes surface into the app shell/header and add project node assignment UI with project card node badges
- Add unit coverage for useNodes, NodesView, NodeCard, Header, and ProjectCard behavior, plus node-specific dashboard styling
This commit is contained in:
gsxdsm
2026-04-07 23:30:32 -07:00
parent 74cae4f870
commit 075402c11d
17 changed files with 2218 additions and 32 deletions

View File

@@ -644,6 +644,28 @@ describe("Header", () => {
});
});
describe("nodes button", () => {
it("renders Nodes button on desktop when handler is provided", () => {
renderHeader({ onOpenNodes: vi.fn() }, "desktop");
expect(screen.getByTitle("Nodes")).toBeDefined();
});
it("calls onOpenNodes when Nodes button is clicked", () => {
const onOpenNodes = vi.fn();
renderHeader({ onOpenNodes }, "desktop");
fireEvent.click(screen.getByTitle("Nodes"));
expect(onOpenNodes).toHaveBeenCalled();
});
it("shows Nodes action in mobile overflow menu", () => {
const onOpenNodes = vi.fn();
renderHeader({ onOpenNodes }, "mobile");
fireEvent.click(screen.getByTitle("More header actions"));
fireEvent.click(screen.getByTestId("overflow-nodes-btn"));
expect(onOpenNodes).toHaveBeenCalled();
});
});
describe("search functionality", () => {
it("does not render search input when onSearchChange is not provided", () => {
renderHeader({ view: "board" });