diff --git a/src/MatchesWebApp.py b/src/MatchesWebApp.py index 2674998..5ed47f7 100644 --- a/src/MatchesWebApp.py +++ b/src/MatchesWebApp.py @@ -70,6 +70,7 @@ _INDEX_HTML = """ + @@ -317,6 +318,23 @@ document.getElementById("build").addEventListener("click", async () => { setStatus("Build failed: " + err.message); } }); +document.getElementById("move").addEventListener("click", async () => { + if (!confirm("Start move operation? This will process all series and may take a long time.")) return; + const btn = document.getElementById("move"); + btn.disabled = true; + setStatus("Moving… (running on the server)"); + try { + const r = await fetch("/api/move", { method: "POST" }); + if (!r.ok) throw new Error(await r.text()); + const data = await r.json(); + const total = Object.keys(data.results || {}).length; + setStatus("Move finished — " + total + " series processed"); + } catch (err) { + setStatus("Move failed: " + err.message); + } finally { + btn.disabled = false; + } +}); for (const th of document.querySelectorAll("th.sortable")) { th.addEventListener("click", () => { const col = th.dataset.col; @@ -350,6 +368,7 @@ class MatchesWebApp: self._host = host self._port = port self._build_lock = threading.Lock() + self._move_lock = threading.Lock() self._app = Flask(__name__) self._thread: "threading.Thread | None" = None self._register_routes() @@ -459,3 +478,17 @@ class MatchesWebApp: finally: self._build_lock.release() return jsonify(result) + + @app.post("/api/move") + def api_move(): + if self._mover is None: + return Response("no mover configured", status=503) + if not self._move_lock.acquire(blocking=False): + return Response("move already running", status=409) + try: + results = self._mover.process_all() + except Exception as exc: + return Response(f"move failed: {exc}", status=500) + finally: + self._move_lock.release() + return jsonify({"results": results})