8e3316957c
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
46 lines
1.3 KiB
Python
46 lines
1.3 KiB
Python
"""Live monitor of the open production runs (#57).
|
|
|
|
Page at /monitor for admin and Supervisor (capoturno); the page polls a JSON proxy
|
|
of GET /api/production-runs/open every 10 seconds.
|
|
"""
|
|
from functools import wraps
|
|
|
|
from flask import Blueprint, abort, jsonify, render_template, session
|
|
|
|
from blueprints.auth import login_required
|
|
from services.api_client import api_client
|
|
|
|
monitor_bp = Blueprint("monitor", __name__)
|
|
|
|
|
|
def monitor_required(f):
|
|
"""Admin or Supervisor only: the same people the backend lets read /open."""
|
|
@wraps(f)
|
|
def decorated(*args, **kwargs):
|
|
user = session.get("user", {})
|
|
if not (user.get("is_admin") or "Supervisor" in user.get("roles", [])):
|
|
abort(403)
|
|
return f(*args, **kwargs)
|
|
return decorated
|
|
|
|
|
|
@monitor_bp.route("", strict_slashes=False)
|
|
@login_required
|
|
@monitor_required
|
|
def index():
|
|
return render_template("monitor/index.html")
|
|
|
|
|
|
@monitor_bp.route("/api/runs")
|
|
@login_required
|
|
@monitor_required
|
|
def api_runs():
|
|
"""JSON proxy polled by the page."""
|
|
resp = api_client.get("/api/production-runs/open")
|
|
if isinstance(resp, dict) and resp.get("error"):
|
|
body = {"error": True, "detail": resp.get("detail", "")}
|
|
if resp.get("session_expired"):
|
|
body["session_expired"] = True
|
|
return jsonify(body), resp.get("status_code", 500)
|
|
return jsonify(resp)
|