117 lines
4.3 KiB
Python
117 lines
4.3 KiB
Python
"""Entity + dependency CRUD routes."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from flask import Blueprint, flash, redirect, render_template, request, url_for
|
|
|
|
from physcom.models.entity import Dependency, Entity
|
|
from physcom_web.app import get_repo
|
|
|
|
bp = Blueprint("entities", __name__, url_prefix="/entities")
|
|
|
|
|
|
@bp.route("/")
|
|
def entity_list():
|
|
repo = get_repo()
|
|
entities = repo.list_entities()
|
|
# Group by dimension
|
|
grouped: dict[str, list[Entity]] = {}
|
|
for e in entities:
|
|
grouped.setdefault(e.dimension, []).append(e)
|
|
return render_template("entities/list.html", grouped=grouped)
|
|
|
|
|
|
@bp.route("/new", methods=["GET", "POST"])
|
|
def entity_new():
|
|
repo = get_repo()
|
|
if request.method == "POST":
|
|
dimension = request.form["dimension"].strip()
|
|
name = request.form["name"].strip()
|
|
description = request.form.get("description", "").strip()
|
|
if not dimension or not name:
|
|
flash("Dimension and name are required.", "error")
|
|
return render_template("entities/form.html", entity=None,
|
|
dimensions=repo.list_dimensions())
|
|
entity = Entity(name=name, dimension=dimension, description=description)
|
|
repo.add_entity(entity)
|
|
flash(f"Entity '{name}' added to '{dimension}'.", "success")
|
|
return redirect(url_for("entities.entity_detail", entity_id=entity.id))
|
|
return render_template("entities/form.html", entity=None,
|
|
dimensions=repo.list_dimensions())
|
|
|
|
|
|
@bp.route("/<int:entity_id>", methods=["GET", "POST"])
|
|
def entity_detail(entity_id: int):
|
|
repo = get_repo()
|
|
entity = repo.get_entity(entity_id)
|
|
if not entity:
|
|
flash("Entity not found.", "error")
|
|
return redirect(url_for("entities.entity_list"))
|
|
if request.method == "POST":
|
|
name = request.form["name"].strip()
|
|
description = request.form.get("description", "").strip()
|
|
if not name:
|
|
flash("Name is required.", "error")
|
|
else:
|
|
repo.update_entity(entity_id, name, description)
|
|
flash(f"Entity '{name}' updated.", "success")
|
|
entity = repo.get_entity(entity_id)
|
|
return render_template("entities/detail.html", entity=entity)
|
|
|
|
|
|
@bp.route("/<int:entity_id>/delete", methods=["POST"])
|
|
def entity_delete(entity_id: int):
|
|
repo = get_repo()
|
|
entity = repo.get_entity(entity_id)
|
|
if entity:
|
|
repo.delete_entity(entity_id)
|
|
flash(f"Entity '{entity.name}' deleted.", "success")
|
|
return redirect(url_for("entities.entity_list"))
|
|
|
|
|
|
# ── Dependency CRUD (HTMX partials) ─────────────────────────
|
|
|
|
|
|
@bp.route("/<int:entity_id>/deps/add", methods=["POST"])
|
|
def dep_add(entity_id: int):
|
|
repo = get_repo()
|
|
dep = Dependency(
|
|
category=request.form["category"].strip(),
|
|
key=request.form["key"].strip(),
|
|
value=request.form["value"].strip(),
|
|
unit=request.form.get("unit", "").strip() or None,
|
|
constraint_type=request.form.get("constraint_type", "requires").strip(),
|
|
)
|
|
if not dep.category or not dep.key or not dep.value:
|
|
flash("Category, key, and value are required.", "error")
|
|
else:
|
|
repo.add_dependency(entity_id, dep)
|
|
flash("Dependency added.", "success")
|
|
entity = repo.get_entity(entity_id)
|
|
return render_template("entities/_dep_table.html", entity=entity)
|
|
|
|
|
|
@bp.route("/<int:entity_id>/deps/<int:dep_id>/edit", methods=["POST"])
|
|
def dep_edit(entity_id: int, dep_id: int):
|
|
repo = get_repo()
|
|
dep = Dependency(
|
|
category=request.form["category"].strip(),
|
|
key=request.form["key"].strip(),
|
|
value=request.form["value"].strip(),
|
|
unit=request.form.get("unit", "").strip() or None,
|
|
constraint_type=request.form.get("constraint_type", "requires").strip(),
|
|
)
|
|
repo.update_dependency(dep_id, dep)
|
|
flash("Dependency updated.", "success")
|
|
entity = repo.get_entity(entity_id)
|
|
return render_template("entities/_dep_table.html", entity=entity)
|
|
|
|
|
|
@bp.route("/<int:entity_id>/deps/<int:dep_id>/delete", methods=["POST"])
|
|
def dep_delete(entity_id: int, dep_id: int):
|
|
repo = get_repo()
|
|
repo.delete_dependency(dep_id)
|
|
flash("Dependency deleted.", "success")
|
|
entity = repo.get_entity(entity_id)
|
|
return render_template("entities/_dep_table.html", entity=entity)
|