swarm-ui: rewire a notification flow by drag or keyboard
The flow editor can now change a flow's shape on the canvas, not only through the inspector's fields: - drag a box onto another to move it and its branch there; a drop the save would refuse shows the target dashed red and gives the reason; - a palette of node kinds adds a node below the picked box on click, or below any box it is dragged onto; it offers what the controller lists; - arrow keys walk the tree, M picks a box up and Enter drops it under the focused one, Alt+Up/Down reorder a node among its siblings, Delete removes a branch; focus follows the edit; - each box with siblings says when it runs, and the inspector can move it earlier or later, since the router runs children in edge order; - request_reviewer is a second leaf kind beside todo, with a reviewer field; - leaving with unsaved edits asks first, also for in-app links and the back button (a router hook runs navigation past a page's guard).
This commit is contained in:
parent
e01770c056
commit
68e289fff5
16 changed files with 1072 additions and 133 deletions
|
|
@ -3,6 +3,8 @@ import assert from "node:assert/strict";
|
|||
import { test } from "node:test";
|
||||
import {
|
||||
layoutFlow,
|
||||
neighbour,
|
||||
nodeAt,
|
||||
NODE_HEIGHT,
|
||||
NODE_WIDTH,
|
||||
} from "../src/pages/notifications/FlowLayout.ts";
|
||||
|
|
@ -120,3 +122,41 @@ test("an empty flow has an empty layout", () => {
|
|||
assert.deepEqual(l.nodes, []);
|
||||
assert.ok(l.width >= 0 && l.height >= 0);
|
||||
});
|
||||
|
||||
test("nodeAt finds the box holding a point and nothing between boxes", () => {
|
||||
const l = layoutFlow(flow([source, match("a")], [["s", "a"]]));
|
||||
const a = at(l, "a");
|
||||
assert.equal(nodeAt(l, a.x + 5, a.y + 5), "a");
|
||||
assert.equal(
|
||||
nodeAt(l, a.x + NODE_WIDTH, a.y + NODE_HEIGHT),
|
||||
"a",
|
||||
"the edge counts",
|
||||
);
|
||||
assert.equal(nodeAt(l, a.x - 1, a.y + 5), undefined);
|
||||
assert.equal(nodeAt(l, 5000, 5000), undefined);
|
||||
});
|
||||
|
||||
test("neighbour walks to the parent, the first child and the box above or below", () => {
|
||||
const f = flow(
|
||||
[source, match("a"), match("b"), match("c")],
|
||||
[
|
||||
["s", "a"],
|
||||
["s", "b"],
|
||||
["a", "c"],
|
||||
],
|
||||
);
|
||||
const l = layoutFlow(f);
|
||||
assert.equal(neighbour(l, f, "a", "left"), "s");
|
||||
assert.equal(neighbour(l, f, "s", "right"), "a", "the first in edge order");
|
||||
assert.equal(
|
||||
neighbour(l, f, "s", "left"),
|
||||
undefined,
|
||||
"nothing left of the source",
|
||||
);
|
||||
assert.equal(neighbour(l, f, "c", "right"), undefined, "a leaf has no child");
|
||||
// a sits above b in the same column.
|
||||
assert.equal(neighbour(l, f, "a", "down"), "b");
|
||||
assert.equal(neighbour(l, f, "b", "up"), "a");
|
||||
assert.equal(neighbour(l, f, "a", "up"), undefined);
|
||||
assert.equal(neighbour(l, f, "nope", "up"), undefined);
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in a new issue