PROJEKTE: Speichern/Laden/Autostart (25/25 E2E inkl. Server-Neustart)
- hms_app/projects.py: ProjectStore mit atomarem Speichern (.hms.json in projects/), Format-Kennung, Namens-Sanitize (Pfad-Traversal-Schutz, Leerzeichen erlaubt), Liste/Loeschen - engine.py: export_state() (Layer mit Alpha/Pos/Groesse/Z/FX + Intensitaeten + Master) und load_state() (ersetzt alle Layer, fehlende Medien werden uebersprungen und gemeldet, Werte geclamped, ungueltige FX-IDs verworfen) - server.py: /api/projects (GET Liste + Autostart), POST projects/save|load|delete|autostart; Loeschen des Autostart-Projekts raeumt config.json automatisch auf - config.py: engine.autostart_project (validiert, optional) - run.py: laedt Autostart-Projekt beim Programmstart - ui.py: neuer Reiter 'Projekte': Name eingeben + Speichern, Tabelle mit Laden/Autostart/Loeschen, Autostart-Badge E2E-BEWEIS (25/25 PASS, mit ECHTEM Server-Neustart): 1 Server startet · 2 Upload · 3 Layer · 4 FX/Alpha/Pos gesetzt · 5 Projekt 'Show A' gespeichert · 6 Traversal-Name sanitizet zu 'evil' · 7 Liste · 8 Layerzahl · 9 Zustand geleert (master=0.1) · 10 Projekt geladen · 11 Layer wiederhergestellt · 12 Alpha 0.7 wiederhergestellt · 13 FX1 blur 0.8 wiederhergestellt · 14 Position x=50 y=20 wiederhergestellt · 15 Master 0.9 · 16 Engine rendert · 17 Autostart gesetzt · 18 Server NEU GESTARTET · 19 Autostart: Layer+FX automatisch geladen · 20 Autostart: Engine rendert (60 Frames) · 21 config.json Autostart · 22 fehlendes Projekt 404 · 23 geloescht · 24 Autostart automatisch geleert · 25 config.json geleert Regressionen: App-E2E 14/14 (app=0) + FX-E2E 16/16 (fx=0) unveraendert gruen
This commit is contained in:
@@ -9,6 +9,7 @@ import urllib.parse
|
||||
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
|
||||
|
||||
from . import config as cfgmod
|
||||
from .projects import ProjectStore
|
||||
from .ui import HTML_UI
|
||||
|
||||
|
||||
@@ -21,6 +22,7 @@ class EngineServer:
|
||||
self.library = library
|
||||
self.settings = settings
|
||||
self.root = root
|
||||
self.projects = ProjectStore(root)
|
||||
self.httpd: ThreadingHTTPServer | None = None
|
||||
self.running = False
|
||||
|
||||
@@ -100,6 +102,10 @@ class EngineServer:
|
||||
self._json(artnet.monitor())
|
||||
elif path == "/api/fx":
|
||||
self._json(engine.fx_catalog())
|
||||
elif path == "/api/projects":
|
||||
self._json({"items": server.projects.list(),
|
||||
"autostart": settings["engine"].get(
|
||||
"autostart_project")})
|
||||
else:
|
||||
self._send_error_json(404, "nicht gefunden")
|
||||
|
||||
@@ -156,6 +162,48 @@ class EngineServer:
|
||||
elif path == "/api/retrigger":
|
||||
engine.retrigger()
|
||||
self._json({"ok": True})
|
||||
elif path == "/api/projects/save":
|
||||
body = self._read_json()
|
||||
name = str(body.get("name", "")).strip()
|
||||
if not name:
|
||||
self._send_error_json(400, "Name fehlt")
|
||||
else:
|
||||
info = server.projects.save(
|
||||
name, engine.export_state())
|
||||
if info is None:
|
||||
self._send_error_json(500, "Speichern fehlgeschlagen")
|
||||
else:
|
||||
self._json(info)
|
||||
elif path == "/api/projects/load":
|
||||
body = self._read_json()
|
||||
name = str(body.get("name", ""))
|
||||
doc = server.projects.load(name)
|
||||
if doc is None:
|
||||
self._send_error_json(404, "Projekt nicht gefunden")
|
||||
else:
|
||||
ok = engine.load_state(doc.get("state") or {})
|
||||
self._json({"loaded": bool(ok),
|
||||
"name": doc.get("name"),
|
||||
"error": None if ok else engine.last_error})
|
||||
elif path == "/api/projects/delete":
|
||||
body = self._read_json()
|
||||
ok = server.projects.delete(str(body.get("name", "")))
|
||||
if (settings["engine"].get("autostart_project")
|
||||
== str(body.get("name", ""))):
|
||||
settings["engine"]["autostart_project"] = None
|
||||
cfgmod.save(root, settings)
|
||||
self._json({"deleted": bool(ok)})
|
||||
elif path == "/api/projects/autostart":
|
||||
body = self._read_json()
|
||||
name = body.get("name")
|
||||
if name and not server.projects.exists(str(name)):
|
||||
self._send_error_json(404, "Projekt nicht gefunden")
|
||||
else:
|
||||
settings["engine"]["autostart_project"] = (
|
||||
str(name) if name else None)
|
||||
cfgmod.save(root, settings)
|
||||
self._json({"autostart": settings["engine"][
|
||||
"autostart_project"]})
|
||||
elif path == "/api/settings":
|
||||
self._post_settings()
|
||||
else:
|
||||
|
||||
Reference in New Issue
Block a user