From aad5672a6b215dbf4d8b0e12b3215a299b8a087b Mon Sep 17 00:00:00 2001 From: sjat Date: Wed, 24 Jun 2026 18:22:41 +0200 Subject: [PATCH] docs(rack): graphical presentation improvements design spec --- .../2026-06-24-rack-presentation-design.md | 136 ++++++++++++++++++ 1 file changed, 136 insertions(+) create mode 100644 notes/dev/specs/2026-06-24-rack-presentation-design.md diff --git a/notes/dev/specs/2026-06-24-rack-presentation-design.md b/notes/dev/specs/2026-06-24-rack-presentation-design.md new file mode 100644 index 0000000..6250df2 --- /dev/null +++ b/notes/dev/specs/2026-06-24-rack-presentation-design.md @@ -0,0 +1,136 @@ +# Rack Presentation Improvements Design + +**Date:** 2026-06-24 +**Status:** Approved +**Parent spec:** `notes/dev/specs/2026-06-24-rack-documentation-design.md` (extension) + +## Goal + +Improve the graphical presentation of the generated rack page: make the +elevation **interactive** (inline SVG, clickable boxes, hover tooltips), encode +device **status** visually, add a **legend**, and **polish** both the elevation +and the mermaid power/network graphs. No new data is modelled; this is a +rendering upgrade of what `gen_rack.py` already produces. + +## Context + +- `render_svg` writes a standalone `rack01-elevation.svg`, embedded in + `rack01.md` as `![Rack rack01 elevation](rack01-elevation.svg)` — i.e. an + ``, which is a **flat image**: links and tooltips inside it do not work. +- `render_power`/`render_network` emit default-themed mermaid flowcharts with + uncoloured, non-clickable nodes. +- The occupancy table already links to host pages; the SVG and graphs do not. +- `md_in_html` is enabled in `mkdocs.yml`, so raw inline HTML/SVG in a Markdown + page is rendered. Mermaid is enabled (Phase 2). +- `use_directory_urls` is unset → defaults to **true**: pages build to + `//index.html`, so a host page is served at `/hardware//` and the + rack page at `/infrastructure/racks/rack01/`. The site is served at the domain + root (`docs.makerfloss.eu`). +- `KIND_COLORS` already maps kinds → fill colours. There is no status encoding, + legend, link, or tooltip today. + +## Decisions + +### A. Inline, interactive elevation + +- `render_page` embeds the SVG markup **inline** in `rack01.md`, inside a + `
` block, replacing the + `![…](rack01-elevation.svg)` image line. (`md_in_html` passes the raw block + through.) +- The standalone `rack01-elevation.svg` is **still generated** (identical markup, + still drift-checked) and offered below the diagram as a + `[Download SVG](rack01-elevation.svg)` link. +- The `` opening tag gains `style="max-width:100%;height:auto"` so it scales + on narrow screens. +- **Clickable boxes:** every device drawing (rail box, shelf-occupant box, 0U + rail bar, shelf strip) is wrapped in + ``. URLs are **root-relative final + URLs** — mkdocs does **not** rewrite `.md`/source-relative hrefs inside raw + inline SVG, and `use_directory_urls` + domain-root hosting make + `/hardware//` correct and robust. +- **Tooltips:** the `` wrapper's first child is an SVG `` carrying full + details: `" · · · cluster: · "`, + where `` is the U-range (rail item), `0U ` (0U rail), or + `//slot ` (mounted item). Text run through `_esc`. + +### B. Status encoded as border + +Fill stays the kind colour; the box **border** encodes `status` via a +`_status_stroke(status) -> (stroke, stroke_width, dash)` helper: + +| status | stroke | width | dash | +|--------|--------|-------|------| +| in-use | `#333` | 1.5 | none | +| staging | `#333` | 1.5 | `4 2` (dashed) | +| broken | `#e15759` | 3 | none | +| spare | `#bbbbbb` | 1.5 | none | +| donated | `#bbbbbb` | 1.5 | none | +| (other/missing) | `#333` | 1.5 | none | + +Applied to every device rect (rail `draw_device` and shelf-occupant boxes). The +shelf strip and the faint empty-U slots keep their existing styling. + +### C. Legend + +A legend strip is drawn at the **bottom of the SVG canvas**, below the columns; +the canvas height grows by a fixed `LEGEND_H` band: + +- **Kind swatches:** for each `kind` actually present in the rack (sorted), a + small colour rect + the kind name. +- **Status key:** four small sample borders (solid, dashed, red-thick, grey) with + labels `in-use`, `staging`, `broken`, `spare`. + +### D. Aesthetic polish + +- **U-numbers in both gutters:** the existing left-gutter U-number column is + mirrored to the right of the rear column. +- **Column frame:** a thin outer stroke rectangle around each column's full body + (front and rear). +- **Mermaid graphs** (`render_power`/`render_network`): + - **Colour nodes by kind:** emit a `style fill:,stroke:#333,color:#ffffff` + line per node, looking the kind up from the rack items (`KIND_COLORS`, + falling back to `DEFAULT_COLOR`). + - **Clickable nodes:** emit `click "/hardware//"` for every node whose + hostname resolves to a rack item; off-rack nodes get no click. + - Edge labels and layout are unchanged. + +## Technical constraints (rationale carried into implementation) + +- ``-embedded SVG is inert → inlining is required for links/tooltips. +- mkdocs rewrites Markdown `.md` links but **not** raw `href`/`click` URLs inside + inline SVG or mermaid → emit final root-relative URLs `/hardware//`. +- `md_in_html` (already enabled) renders the raw `
` block. + +## Integration + +| File | Change | +|------|--------| +| `scripts/gen_rack.py` | helpers `_host_url`, `_status_stroke`, `_tooltip`; `render_svg` (status borders, ``+`` wrapping, both-gutter U-numbers, column frame, legend, `style=` on `<svg>`); `render_page` (inline SVG `<div>` + download link); `render_power`/`render_network` (per-node `style` + `click`) | +| `tests/test_gen_rack.py` | assertions for links, titles, status strokes, legend, both-gutter numbers, inline page block, mermaid style/click | +| `docs/infrastructure/racks/rack01.md`, `rack01-elevation.svg` | regenerated | + +No `mkdocs.yml`, `Makefile`, `.forgejo/workflows/docs.yml`, or +`overview_config.yml` changes. Occupancy table and all validation unchanged. + +## Test plan + +- **`render_svg`:** output contains `<a href="/hardware/srv04/"`, a `<title>` with + the host details, a dashed stroke for a `staging` fixture and a thick red stroke + for a `broken` fixture, kind swatches for the kinds present, U-number text on + both sides; deterministic for reordered input. +- **`render_page`:** contains `<div class="rack-elevation">` and `<svg`, the + `[Download SVG](rack01-elevation.svg)` link, and **no** `![`-image embed of the + elevation. +- **`render_power`/`render_network`:** contain `style <id> fill:` lines coloured + by kind and `click <id> "/hardware/<host>/"` lines; still start with + ` ```mermaid ` + `flowchart LR`. +- **Drift / build / visual:** `make docs-check` exits 0; `mkdocs build --strict` + passes; on the rendered page the elevation boxes are clickable, hovering shows + the tooltip, the legend is visible, and the mermaid nodes are coloured and + clickable. + +## Out of scope + +- The summary dashboard (U-utilisation / counts) — not selected. +- Dark-mode-specific palettes. +- A cluster colour system — cluster appears in the tooltip only.