SPA_TemperProductionOverview/README.md
Erik aa115a0b8d feat: scaffold Temper-Linie live-overview page-module (temper_overview)
Vue 3 + Vite 8 + TS + PrimeVue 4 (Nora/Industrial) + Pinia + vue-i18n SPA, served
by the SPRO gateway as a static page-module under /module/temper_overview and
embedded into Grafana via iframe.

- Ports the LOCKED design #4 "Shop-floor Schematic": one connected line
  Pressen -> (cyan) -> Ofen -> (green) -> Fertig; carts under their origin press;
  oven trays as dwell-progress bars; finished band; range picker scoping only the
  Fertig figures. Flow/order colours match PressV (fleet recognisability).
- Python page-module wrapper: register(app) mounts committed dist/ + a no-auth
  read API (GET /api/overview). Kernel DB seam in _db.py.
- Backend returns SAMPLE data; frontend falls back to bundled sample so `npm run
  dev` renders with zero backend (TODO markers point at the real temper aggregates).
- Rich README bakes in the design, contract, wiring + Grafana embedding for
  standalone development.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01 20:41:04 +02:00

154 lines
7.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# SPA_TemperProductionOverview — Temper-Linie · Live-Übersicht
A **login-free, read-only** whole-line temper overview, built as a Vue 3 SPA that
the **SPRO Universal Gateway** serves as a static page-module under
`/module/temper_overview/` and that is **embedded into Grafana via an `<iframe>`**.
> **Standalone orientation.** This repo is developed on its own (like `FastPress`,
> `PressV`, `sp-ui-kit` — sibling repos), but it only comes fully alive when mounted
> into the gateway as a git submodule at `modules/temper_overview/`. This README
> bakes in everything a fresh session needs — you shouldn't need the gateway repo
> open to work on the frontend.
Board it renders (dark, one connected line): **Pressen → (cyan ↓) → Ofen →
(green ↓) → Fertig**, carts hanging under their origin press, oven trays whose
background fills with dwell progress, a finished band, and a time-range picker that
scopes only the "Fertig" figures. Run `npm run dev` to see it.
---
## Quick start (standalone dev)
```bash
# 1) auth for the private @sp-ui-kit design-token package (one-time)
cp .npmrc.example .npmrc # then paste a Gitea PAT with "package: Read" scope
# 2) install + run
npm install
npm run dev # http://localhost:5173/module/temper_overview/
```
With **no gateway backend running**, the store falls back to **bundled sample data**
(`src/data/sample.ts`), so `npm run dev` shows the full design immediately (a
`DEMO-DATEN` tag appears in the header). `npm run build``dist/` (committed).
---
## How it's wired into the gateway (page-module contract)
This is a gateway module per `agent_docs/vue-page-modules.md` in the gateway repo.
The **repo root is a Python package** (`__init__.py`) so the kernel's module loader
can `import temper_overview` and call `register(app)`:
| File | Role |
|---|---|
| `__init__.py` | `register(app)` — mounts `dist/` at `MODULE_PREFIX` + includes the API router |
| `_db.py` | kernel DB seam (`run_select_query`) — used once real SQL is wired |
| `api/routes.py` | the no-auth read API (`GET /module/temper_overview/api/overview`) |
| `dist/` | **committed** build output — the gateway serves this (deploy host has no Node) |
| `src/` etc. | the Vue app source |
**URL prefix lives in two places that MUST match** — change both together:
`vite.config.ts``base: '/module/temper_overview/'` and `__init__.py`
`MODULE_PREFIX = "/module/temper_overview"`. The frontend derives its API base from
`import.meta.env.BASE_URL`, so it follows the prefix automatically.
Add it to a gateway checkout:
```bash
# in the gateway repo (fastAPI)
git submodule add https://git.sprodat.eu/Erik/SPA_TemperProductionOverview.git modules/temper_overview
# MODULES_ENABLED in .env must include temper_overview (or be empty = load all)
```
Restart the gateway; the log shows `loaded module: temper_overview`. Smoke-test
(mind the trailing slash): `http://localhost:8800/module/temper_overview/` and
`…/api/overview`.
> **Deploy rule:** always `npm run build` and **commit `dist/`** when the app
> changes, then bump the submodule pin in the gateway repo. Never build on the
> gateway host.
---
## Data API contract
`GET /module/temper_overview/api/overview?range=12h|1d|7d|14d|30d` → one JSON
payload for the whole line. The TypeScript shape is authoritative:
[`src/types/overview.ts`](src/types/overview.ts); the Python side builds the same
shape in [`api/routes.py`](api/routes.py). `range` scopes **only** the `finished`
figures — presses / on-the-way / oven are always real-time.
```jsonc
{
"plant": "Werk 1", "generatedAt": "…", "range": "1d",
"ovenTempC": 185, "ovenAvgMin": 120, "sample": true,
"presses": [{ "name":"P1","status":"run","orders":[{"orderNo":"O-4471","colorIndex":0}],
"good":1240,"cycleTime":"4.2","notVerladen":34,"note":null,"placeholder":false }],
"onWay": { "P3":[{ "cartId":"C-014a","orders":[{"orderNo":"O-4471","qty":54,"colorIndex":0}],"etaMin":3 }] },
"oven": [{ "cartId":"C-011","orders":[],"totalMin":120,"remainingMin":42 }],
"finished": { "carts":47,"parts":5120,"scrap":63,"avgOvenMin":118,
"byOrder":[{"orderNo":"O-4471","colorIndex":0,"parts":1680}] },
"finishedList": [{ "cartId":"C-010","orders":[],"ago":"vor 8 min" }]
}
```
### Wiring the REAL data (currently SAMPLE)
`api/routes.py` returns sample data today. To make it live (see the big `TODO` there
and `.claude/memory/temper-line-overview.md` in the gateway):
- Import the kernel proxy: `from .._db import run_select_query` (read-only).
- Reuse the temper status-derivation in `modules/fastpress/press/temper.py`
(`_temper_aggregates_all` derives on-way / in-oven / finished from planned
timestamps vs `NOW()`), un-scoped across **all** presses. Read
`production.temper_tracking` (carts grouped by `ttCartId`, keyed by origin press
`ttPress`) + `production.active_orders`/`finished_orders`.
- `notVerladen` = produced good parts (cycles) parts logged to temper. **Open
question:** per-press or plant-wide?
- Scope `finished` by `range` on `ttOutOfOvenAt`. Never echo customer/price fields.
Alternatively, add a public `GET /press/temper/overview` in fastpress and have the
frontend call that — decide before wiring; keep the payload shape above either way.
---
## Tech stack (matches PressV / the fleet)
Vue 3.5 · Vite 8 · TypeScript 5.9 · Pinia 3 · vue-router 4 (hash) · vue-i18n 10
(de default, `?lang=en`) · PrimeVue 4.5 (Nora + custom **Industrial** preset, sky
primary) · Tailwind v4 (CSS-first) · `@sp-ui-kit/tokens` (shared design tokens,
private registry) · Inter Variable. **Dark-first**, flat 2px corners, 0s
transitions, `prefers-reduced-motion` disables the conveyor animations.
**Store pattern** (mirrors PressV `productionOverview`): `src/stores/temperOverview.ts`
does `loadCache()` (sessionStorage) → `hydrate()` (spinner only on cold start) →
`refresh()` (background) → `startPolling(12000)`. Robust to a dev server's SPA
fallback: a response without a `presses[]` array is treated as "no backend" → sample.
### Design tokens (recognisable across SPRO apps)
Flow accents match PressV `--c-*`: press/machine `#a78bfa`, on-the-way/cart
`#22d3ee`, oven `#f97316` (hot `#ef4444`), finished `#34d399`. Order chips (from
PressV `orderColors.ts`): `#5794F2 #E8825A #B57EDC #4FB7A8`. Defined in
`src/style.css` (`:root` dark + `html:not(.dark)` light) and `src/data/orderColors.ts`.
> Not yet used but part of the fleet stack — add when needed: `@sp-ui-kit/ui-core`
> components and `echarts`/`vue-echarts`. The board's by-order bars are CSS today.
---
## Grafana embedding
The gateway sets no `X-Frame-Options`/CSP, so a Grafana **Text** panel (HTML mode,
`disable_sanitize_html = true`) can iframe it:
```html
<iframe src="http://<gateway-host>:8800/module/temper_overview/#/"
width="100%" height="900" style="border:0"></iframe>
```
Append `?lang=en` before the `#` for English. Design is locked as design #4
"Shop-floor Schematic" — see `.claude/memory/temper-line-overview.md` and the
prototype at `modules/fastpress/reference/temper-overview/` in the gateway repo.