92 lines
2.7 KiB
Python
92 lines
2.7 KiB
Python
"""Admin panel routes."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import json
|
|
|
|
from flask import Blueprint, flash, redirect, render_template, request, url_for
|
|
from flask import Response
|
|
|
|
from physcom.seed.transport_example import load_transport_seed
|
|
from physcom.snapshot import export_snapshot, import_snapshot
|
|
from physcom_web.app import get_repo
|
|
|
|
bp = Blueprint("admin", __name__, url_prefix="/admin")
|
|
|
|
|
|
@bp.route("/")
|
|
def admin_index():
|
|
repo = get_repo()
|
|
entities = repo.list_entities()
|
|
domains = repo.list_domains()
|
|
status_counts = repo.count_combinations_by_status()
|
|
runs = repo.list_pipeline_runs()
|
|
stats = {
|
|
"entities": len(entities),
|
|
"domains": len(domains),
|
|
"combinations": sum(status_counts.values()),
|
|
"pipeline_runs": len(runs),
|
|
}
|
|
return render_template("admin/index.html", stats=stats)
|
|
|
|
|
|
@bp.route("/reseed", methods=["POST"])
|
|
def reseed():
|
|
repo = get_repo()
|
|
counts = load_transport_seed(repo)
|
|
total = counts["platforms"] + counts["actuators"] + counts["energy_storages"]
|
|
flash(
|
|
f"Reseed complete — added {total} entities, {counts['domains']} domains.",
|
|
"success",
|
|
)
|
|
return redirect(url_for("admin.admin_index"))
|
|
|
|
|
|
@bp.route("/wipe", methods=["POST"])
|
|
def wipe():
|
|
repo = get_repo()
|
|
repo.clear_all()
|
|
flash("Wiped all data.", "success")
|
|
return redirect(url_for("admin.admin_index"))
|
|
|
|
|
|
@bp.route("/snapshot/export")
|
|
def snapshot_export():
|
|
repo = get_repo()
|
|
data = export_snapshot(repo)
|
|
body = json.dumps(data, indent=2)
|
|
return Response(
|
|
body,
|
|
mimetype="application/json",
|
|
headers={"Content-Disposition": "attachment; filename=physcom_snapshot.json"},
|
|
)
|
|
|
|
|
|
@bp.route("/snapshot/import", methods=["POST"])
|
|
def snapshot_import():
|
|
repo = get_repo()
|
|
clear = "clear" in request.form
|
|
|
|
file = request.files.get("file")
|
|
if not file or not file.filename:
|
|
flash("No file selected.", "error")
|
|
return redirect(url_for("admin.admin_index"))
|
|
|
|
try:
|
|
raw = file.read().decode("utf-8")
|
|
data = json.loads(raw)
|
|
except (UnicodeDecodeError, json.JSONDecodeError) as exc:
|
|
flash(f"Invalid JSON file: {exc}", "error")
|
|
return redirect(url_for("admin.admin_index"))
|
|
|
|
counts = import_snapshot(repo, data, clear=clear)
|
|
mode = "Cleared DB and imported" if clear else "Merged"
|
|
flash(
|
|
f"{mode} snapshot — {counts['dimensions']} dimensions, "
|
|
f"{counts['entities']} entities, {counts['domains']} domains, "
|
|
f"{counts['combinations']} combinations, {counts['results']} results, "
|
|
f"{counts['scores']} scores.",
|
|
"success",
|
|
)
|
|
return redirect(url_for("admin.admin_index"))
|