Skip to content
Components

Pipeline

An orchestration graph: stages on the cadastral canvas, joined by cables that show where data is moving.

The graph

A stage declares a column and a row; a link names two ids. Every coordinate and every cable is computed from those — so moving a stage is one number, and the edges that touch it follow.

Ingest pipeline, mid-runDrag the canvas to pan it. One stage is running, one has warnings, one failed, one was never configured — and the cables report which paths have carried data. Tab into it and the view follows the focused card.
Code
<GdPipeline
  :stages="stages"
  :links="links"
  v-model:selected="selected"
  interactive
  @select="open"
/>

<!-- a stage places itself by CELL, never by pixel -->
{ id: "parse", title: "Parse scheme layers", icon: "layers",
  status: "running", progress: 62, column: 2, row: 0 }

<!-- a link names two ids; its appearance is derived -->
{ from: "fetch", to: "parse" }

Props

PropTypeDefault
stagesrequiredGdPipelineStage[]—

The graph. Each stage carries a `column` and `row` — grid cells, not pixels.

linksGdPipelineLink[][]

Dependencies by id. A link naming a stage that is not present draws nothing rather than throwing.

selectedstring—

Id of the stage drawn as selected.

interactivebooleanfalse

Stages render as buttons and emit `select`.

gridbooleantrue

Draw the cadastral grid as the canvas ground.

Events

select[id: string]

A stage was activated. Only fires with `interactive`.

The inspector rail

Selecting a stage has to open something, or the click is a lie. The rail is a composition, not a component — GdSidePanel holding GdPanelSection blocks — because its sections are one app's content. A GdPipelineInspector that hard-coded "Configuration / Output / Live log" would have exactly one consumer, and the next console would need its own.

What the system does ship is the two primitives those blocks needed and did not have: GdKeyFigures for the output counts, and GdLogStream for the run log.

Canvas and inspectorClick a stage on the left. Everything in the rail is a system component — the panel, its sections, the fields, the figures and the log.

Dragged, not scrolled

A graph is a place, not a document, so the canvas is dragged. Scrollbars are the giveaway that a spatial surface is being presented as a long page: they occupy two edges, they imply a beginning and an end a graph does not have, and they turn "look at the node to the left" into two gestures.

  • Zoom is on the modifier. Ctrl/⌘ and the wheel, which is also what a trackpad pinch arrives as, plus the cluster at the bottom-left and + − 01 on the keyboard. Zooming keeps the point under the cursor fixed — zooming about the origin is the version everyone writes first, and it throws the graph off-screen as soon as you are not already at 0,0. Fit never zooms past 100%: a three-stage pipeline magnified to fill a 1400px viewport looks broken rather than fitted.
  • A bare wheel is deliberately not captured. Panning on wheel is the classic map-in-a-page trap — a reader scrolling the page reaches the canvas, the canvas eats the wheel, and the page stops. Dragging is unambiguous, so the wheel is left to the document.
  • Removing scrollbars removes keyboard access, which is the easy part to forget: a scroll container moves with the arrow keys for free, a transform does not. The surface takes focus and pans on the arrow keys, and tabbing to a stage brings that stage into view — a focused card off-screen is a focus trap wearing a different hat.
  • The ground travels with the content. A fixed grid under a moving graph is worse than no grid: the cards appear to slide over a static sheet, which reads as a rendering fault rather than a camera move.
  • Panning is clamped, so the graph can never be dragged off its own canvas and lost.

A cable's appearance is derived

Links carry no styling of their own. The rule is stated once and every edge follows it, so a status change re-colours exactly the right cables and the graph cannot claim a path is live into a stage that finished an hour ago.

  • The target is running — accent, dashed, marching. Data is moving now.
  • Both ends are done — accent, solid. This path has carried data.
  • Anything else — the hairline. Nothing has happened here yet.

The dash offset animates by exactly four dashes, so the loop is seamless; any other figure shows a jump once per cycle. Under prefers-reduced-motion the cable keeps its colour and stops moving — "live" stays legible without a conveyor that never stops.

Six states

They differ in weight as well as colour, because someone scanning forty cards is looking for the two that need them.

Fetch + snapshotHTTP · retry 3

77/77 · 2m 41s

done

Parse scheme layersZone, overlay

48/77 · 1m 18s left

running

Conform to standardZone + overlay maps

waiting on parse

queued

Geometry repairSnap 0.02m

312 slivers fixed

warn

Bake tilesVector · z8–z16

endpoint 503

failed

Sliver auditOnly on full rebuild

not this run

skipped

Manual dropNot configured

empty

Every stage state
  • queued has no dot. A status colour for "not started" is a colour that means nothing.
  • failed is not louder than running. A failure is already terminal; a run is the thing being watched.
  • empty has no shadow. That is the load-bearing part — a placeholder with a card's shadow reads as a real card that failed to render.

Props

PropTypeDefault
titlerequiredstring—

The stage's name — one line, truncated rather than wrapped.

substring—

The quiet second line: transport, schedule, tool.

iconGdIconName—

A glyph from the registry, on the plaque.

status"done" | "running" | "queued" | "warn" | "failed" | "empty""done"

See the six states below. Only `running` animates, and only one stage should hold it.

metastring—

The mono line: counts and durations, set in figures that stack.

progressnumber—

0–100. Drawn only while `running`.

interactivebooleanfalse

Render a `button` and emit `select`.

selectedbooleanfalse

Draw the accent edge without claiming the stage is running.

Events

select[]

The stage was activated.

Why cables meet the header

Cards are different heights — a running stage carries a progress bar, an empty one has no meta line. Anchoring a cable at the card's vertical centre would make every line into a running stage kink downward relative to its neighbours. The header row sits at a fixed offset from the top in every state, so lines stay level across a row whatever the cards below them are doing.

Navigate

Esc