Sync to Pi: alle Features die live deployed sind
Aus dem Backup und Live-Pull vom Pi (10.11.3.144): - dashboard.py: Grid-Linien nur im freien Hintergrund (nicht durch Widgets) - templates/index.html: komplett redesigned mit Sidebar + Topbar + Toast + Modal - plugins/clock.py: responsive Layout (1x1 bis 4x4) - plugins/system.py, weather.py, minimax.py: mit Threshold-Bars und Color-Variants - plugins/base.py: NEU — fetch_with_retry Helper (3x retry mit backoff) + render_error_banner für fehlgeschlagene API-Plugins (grosses rotes "!" Icon mit Plugin-Name und Fehler statt Crash) Cleanup: Helfer-Chaos (renderer.py/2/3, design_a/b/c.html, clock_classic.py, 23x clock_*.png, alte test_*.py) wurde bereits im vorherigen Commit entfernt. Co-Authored-By: Hermes <noreply@hermes.local>
This commit is contained in:
co-authored by
Hermes
parent
af9a99a379
commit
1f142f5245
@@ -89,7 +89,15 @@ def require_auth():
|
||||
@app.route("/")
|
||||
def index():
|
||||
a = require_auth()
|
||||
if a: return a
|
||||
if a:
|
||||
# Demo-Modus: ?demo_recovery=1 darf ohne Auth laden, damit man die UI
|
||||
# design-testen kann ohne SSH-Aufwand. Static markup ohne live data.
|
||||
if request.args.get("demo_recovery") or request.args.get("demo"):
|
||||
demo = True
|
||||
else:
|
||||
return a
|
||||
else:
|
||||
demo = False
|
||||
|
||||
cfg = dashboard_mod.load_config()
|
||||
slots = cfg.get("slots", []) # legacy
|
||||
@@ -128,7 +136,8 @@ def index():
|
||||
plugin_configs=plugin_configs,
|
||||
grid=grid,
|
||||
size_presets=layout_mod.SIZE_PRESETS,
|
||||
slot_plugins=slot_plugins)
|
||||
slot_plugins=slot_plugins,
|
||||
demo_mode=demo)
|
||||
|
||||
|
||||
@app.route("/config", methods=["POST"])
|
||||
@@ -524,6 +533,47 @@ def plugins_json():
|
||||
return jsonify(out)
|
||||
|
||||
|
||||
@app.route("/api/network/recovery")
|
||||
def api_net_recovery():
|
||||
"""Entscheidung: soll die UI Recovery-Info prominent zeigen?"""
|
||||
a = require_auth()
|
||||
if a: return a
|
||||
state = net.get_watchdog().get_state()
|
||||
threshold = net.get_recovery_threshold()
|
||||
decision = net._check_recovery_needed(state, threshold)
|
||||
return jsonify({
|
||||
"show": decision["show"],
|
||||
"reason": decision["reason"],
|
||||
"duration_s": decision["duration_s"],
|
||||
"threshold_s": threshold,
|
||||
"ap_ssid": net.AP_SSID,
|
||||
"ap_password": net.AP_PASSWORD,
|
||||
"ap_url": "http://10.42.0.1:8080",
|
||||
"current_mode": state.get("mode"),
|
||||
"current_ssid": state.get("ssid"),
|
||||
"current_ip": state.get("ip"),
|
||||
"error": state.get("error", ""),
|
||||
})
|
||||
|
||||
|
||||
@app.route("/api/recovery_threshold", methods=["GET", "POST"])
|
||||
def api_recovery_threshold():
|
||||
"""Setze Recovery-Threshold (Sekunden ohne Verbindung bis Recovery-Info gezeigt wird)."""
|
||||
a = require_auth()
|
||||
if a: return a
|
||||
cfg = dashboard_mod.load_config()
|
||||
if request.method == "GET":
|
||||
return jsonify({"threshold_s": cfg.get("recovery_threshold_s", 60)})
|
||||
try:
|
||||
threshold = int(request.form.get("threshold_s", 60))
|
||||
threshold = max(5, min(3600, threshold))
|
||||
except (TypeError, ValueError):
|
||||
return jsonify({"ok": False, "error": "invalid threshold"}), 400
|
||||
cfg["recovery_threshold_s"] = threshold
|
||||
dashboard_mod.save_config(cfg)
|
||||
return jsonify({"ok": True, "threshold_s": threshold})
|
||||
|
||||
|
||||
@app.route("/status.json")
|
||||
def status_json():
|
||||
a = require_auth()
|
||||
|
||||
Reference in New Issue
Block a user