Replace the sample-data scaffold with real SQL, un-scoped across all presses and scoped to one plant (PLANT_NAME env, default Cadolzburg). - api/routes.py: press list from press_settings.presses; per-press good/chips from active_orders + rejects; run/stop/idle by cycle recency (cycles_new); stop note from downtimes + downtime_reasons; on-way / in-oven / finished carts + nicht-verladen from temper_tracking (live position derived IN SQL from planned times vs NOW(); reprint rows excluded so carts never double-count). Thin _fetch_* helpers (degrade to empty, never 500) + a pure _build_payload. - Oven temperature omitted (no sensor feed): ovenTempC optional in the type, °C chip hidden in OvenBand.vue, coerced in ProductionLine.vue. - Rebuilt dist/. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|---|---|---|
| api | ||
| dist | ||
| src | ||
| __init__.py | ||
| _db.py | ||
| .gitignore | ||
| .npmrc.example | ||
| env.d.ts | ||
| index.html | ||
| package.json | ||
| README.md | ||
| tailwind.config.cjs | ||
| tsconfig.app.json | ||
| tsconfig.json | ||
| tsconfig.node.json | ||
| vite.config.ts | ||
| yarn.lock | ||
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 atmodules/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)
Package manager is yarn 1.22.22 (pinned via packageManager; matches PressV /
the fleet). corepack provides it — no global yarn install needed.
# 0) let corepack honour the pinned yarn (one-time per machine)
corepack enable
# 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
# (yarn v1 reads .npmrc for the scoped registry)
# 2) install + run
yarn install
yarn 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 yarn dev shows the full design immediately (a
DEMO-DATEN tag appears in the header). yarn 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:
# 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
yarn buildand commitdist/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; the Python side builds the same
shape in api/routes.py. range scopes only the finished
figures — presses / on-the-way / oven are always real-time.
{
"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_allderives on-way / in-oven / finished from planned timestamps vsNOW()), un-scoped across all presses. Readproduction.temper_tracking(carts grouped byttCartId, keyed by origin pressttPress) +production.active_orders/finished_orders. notVerladen= produced good parts (cycles) − parts logged to temper. Open question: per-press or plant-wide?- Scope
finishedbyrangeonttOutOfOvenAt. 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-corecomponents andecharts/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:
<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.