first commit
This commit is contained in:
@@ -0,0 +1,14 @@
|
||||
from . import (
|
||||
parse_field_rows,
|
||||
object_new,
|
||||
object_view,
|
||||
object_edit,
|
||||
object_field_add,
|
||||
object_field_edit,
|
||||
object_field_delete,
|
||||
object_delete,
|
||||
data_form,
|
||||
data_new,
|
||||
data_edit,
|
||||
data_delete,
|
||||
)
|
||||
@@ -0,0 +1,20 @@
|
||||
from flask import redirect, url_for, abort
|
||||
|
||||
import db
|
||||
|
||||
from core.flask_app import app
|
||||
|
||||
|
||||
@app.route("/game/<slug>/objects/<int:definition_id>/data/<int:row_id>/delete", methods=["POST"])
|
||||
def data_delete(slug, definition_id, row_id):
|
||||
definition = db.get_definition(slug, definition_id)
|
||||
if not definition:
|
||||
abort(404)
|
||||
referencing = db.rows_referencing(slug, definition_id, row_id)
|
||||
if referencing:
|
||||
# Suppression bloquée : d'autres lignes pointent vers celle-ci via
|
||||
# une relation. On revient à la liste, qui explique pourquoi via un
|
||||
# paramètre de requête simple plutôt qu'une session/flash message.
|
||||
return redirect(url_for("object_view", slug=slug, definition_id=definition_id, blocked_row=row_id))
|
||||
db.delete_row(slug, definition, row_id)
|
||||
return redirect(url_for("object_view", slug=slug, definition_id=definition_id))
|
||||
@@ -0,0 +1,17 @@
|
||||
from flask import abort
|
||||
|
||||
import db
|
||||
|
||||
from core.flask_app import app
|
||||
from .data_form import _data_form
|
||||
|
||||
|
||||
@app.route("/game/<slug>/objects/<int:definition_id>/data/<int:row_id>/edit", methods=["GET", "POST"])
|
||||
def data_edit(slug, definition_id, row_id):
|
||||
definition = db.get_definition(slug, definition_id)
|
||||
if not definition:
|
||||
abort(404)
|
||||
row = db.get_row(slug, definition, row_id)
|
||||
if not row:
|
||||
abort(404)
|
||||
return _data_form(slug, definition_id, row=row)
|
||||
@@ -0,0 +1,32 @@
|
||||
from flask import render_template, request, redirect, url_for, abort
|
||||
|
||||
import db
|
||||
|
||||
|
||||
def _data_form(slug, definition_id, row):
|
||||
game = db.game_meta(slug)
|
||||
definition = db.get_definition(slug, definition_id)
|
||||
if not definition:
|
||||
abort(404)
|
||||
|
||||
# Pour chaque champ de type relation, on prépare les options du <select>
|
||||
# à partir des lignes déjà enregistrées de l'objet lié.
|
||||
relation_options = {}
|
||||
for f in definition["fields"]:
|
||||
if f["type"] == "relation":
|
||||
relation_options[f["id"]] = db.relation_options(slug, f["relation_definition_id"])
|
||||
|
||||
if request.method == "POST":
|
||||
if row is None:
|
||||
db.insert_row(slug, definition, request.form)
|
||||
else:
|
||||
db.update_row(slug, definition, row["id"], request.form)
|
||||
return redirect(url_for("object_view", slug=slug, definition_id=definition_id))
|
||||
|
||||
return render_template(
|
||||
"data_form.html",
|
||||
game=game,
|
||||
definition=definition,
|
||||
relation_options=relation_options,
|
||||
row=row,
|
||||
)
|
||||
@@ -0,0 +1,7 @@
|
||||
from core.flask_app import app
|
||||
from .data_form import _data_form
|
||||
|
||||
|
||||
@app.route("/game/<slug>/objects/<int:definition_id>/data/new", methods=["GET", "POST"])
|
||||
def data_new(slug, definition_id):
|
||||
return _data_form(slug, definition_id, row=None)
|
||||
@@ -0,0 +1,18 @@
|
||||
from flask import redirect, url_for
|
||||
|
||||
import db
|
||||
|
||||
from core.flask_app import app
|
||||
|
||||
|
||||
@app.route("/game/<slug>/objects/<int:definition_id>/delete", methods=["POST"])
|
||||
def object_delete(slug, definition_id):
|
||||
referenced_by = db.definitions_referencing(slug, definition_id)
|
||||
if referenced_by:
|
||||
# Suppression bloquée : d'autres objets ont une relation vers
|
||||
# celui-ci. On revient à l'écran de l'objet, qui affiche déjà cet
|
||||
# avertissement (referenced_by), plutôt que de casser ces relations
|
||||
# silencieusement.
|
||||
return redirect(url_for("object_view", slug=slug, definition_id=definition_id))
|
||||
db.delete_definition(slug, definition_id)
|
||||
return redirect(url_for("game_dashboard", slug=slug))
|
||||
@@ -0,0 +1,28 @@
|
||||
from flask import render_template, request, redirect, url_for, abort
|
||||
|
||||
import db
|
||||
|
||||
from core.flask_app import app
|
||||
|
||||
|
||||
@app.route("/game/<slug>/objects/<int:definition_id>/edit", methods=["GET", "POST"])
|
||||
def object_edit(slug, definition_id):
|
||||
game = db.game_meta(slug)
|
||||
definition = db.get_definition(slug, definition_id)
|
||||
if not definition:
|
||||
abort(404)
|
||||
existing_definitions = [d for d in db.list_definitions(slug) if d["id"] != definition_id]
|
||||
|
||||
if request.method == "POST":
|
||||
new_name = request.form.get("object_name", "").strip()
|
||||
if new_name and new_name != definition["name"]:
|
||||
db.rename_definition(slug, definition_id, new_name)
|
||||
return redirect(url_for("object_edit", slug=slug, definition_id=definition_id))
|
||||
|
||||
return render_template(
|
||||
"object_edit.html",
|
||||
game=game,
|
||||
definition=definition,
|
||||
existing_definitions=existing_definitions,
|
||||
field_types=db.FIELD_TYPES,
|
||||
)
|
||||
@@ -0,0 +1,20 @@
|
||||
from flask import request, redirect, url_for
|
||||
|
||||
import db
|
||||
|
||||
from core.flask_app import app
|
||||
|
||||
|
||||
@app.route("/game/<slug>/objects/<int:definition_id>/fields/add", methods=["POST"])
|
||||
def object_field_add(slug, definition_id):
|
||||
name = request.form.get("field_name", "").strip()
|
||||
if name:
|
||||
db.add_field_to_definition(slug, definition_id, {
|
||||
"name": name,
|
||||
"type": request.form.get("field_type", "texte"),
|
||||
"relation_definition_id": request.form.get("field_relation"),
|
||||
"required": request.form.get("field_required") == "1",
|
||||
"min_value": request.form.get("field_min") or None,
|
||||
"max_value": request.form.get("field_max") or None,
|
||||
})
|
||||
return redirect(url_for("object_edit", slug=slug, definition_id=definition_id))
|
||||
@@ -0,0 +1,11 @@
|
||||
from flask import redirect, url_for
|
||||
|
||||
import db
|
||||
|
||||
from core.flask_app import app
|
||||
|
||||
|
||||
@app.route("/game/<slug>/objects/<int:definition_id>/fields/<int:field_id>/delete", methods=["POST"])
|
||||
def object_field_delete(slug, definition_id, field_id):
|
||||
db.delete_field(slug, definition_id, field_id)
|
||||
return redirect(url_for("object_edit", slug=slug, definition_id=definition_id))
|
||||
@@ -0,0 +1,20 @@
|
||||
from flask import request, redirect, url_for
|
||||
|
||||
import db
|
||||
|
||||
from core.flask_app import app
|
||||
|
||||
|
||||
@app.route("/game/<slug>/objects/<int:definition_id>/fields/<int:field_id>/edit", methods=["POST"])
|
||||
def object_field_edit(slug, definition_id, field_id):
|
||||
new_name = request.form.get("field_name", "").strip()
|
||||
if new_name:
|
||||
db.update_field(
|
||||
slug, definition_id, field_id,
|
||||
new_name=new_name,
|
||||
required=request.form.get("field_required") == "1",
|
||||
relation_definition_id=request.form.get("field_relation"),
|
||||
min_value=request.form.get("field_min") or None,
|
||||
max_value=request.form.get("field_max") or None,
|
||||
)
|
||||
return redirect(url_for("object_edit", slug=slug, definition_id=definition_id))
|
||||
@@ -0,0 +1,27 @@
|
||||
from flask import render_template, request, redirect, url_for
|
||||
|
||||
import db
|
||||
|
||||
from core.flask_app import app
|
||||
from .parse_field_rows import _parse_field_rows
|
||||
|
||||
|
||||
@app.route("/game/<slug>/objects/new", methods=["GET", "POST"])
|
||||
def object_new(slug):
|
||||
game = db.game_meta(slug)
|
||||
existing_definitions = db.list_definitions(slug)
|
||||
|
||||
if request.method == "POST":
|
||||
name = request.form.get("object_name", "").strip()
|
||||
fields = _parse_field_rows(request.form)
|
||||
|
||||
if name and fields:
|
||||
definition_id = db.create_definition(slug, name, fields)
|
||||
return redirect(url_for("object_view", slug=slug, definition_id=definition_id))
|
||||
|
||||
return render_template(
|
||||
"object_form.html",
|
||||
game=game,
|
||||
existing_definitions=existing_definitions,
|
||||
field_types=db.FIELD_TYPES,
|
||||
)
|
||||
@@ -0,0 +1,33 @@
|
||||
from flask import render_template, request, abort
|
||||
|
||||
import db
|
||||
|
||||
from core.flask_app import app
|
||||
|
||||
|
||||
@app.route("/game/<slug>/objects/<int:definition_id>")
|
||||
def object_view(slug, definition_id):
|
||||
game = db.game_meta(slug)
|
||||
definition = db.get_definition(slug, definition_id)
|
||||
if not definition:
|
||||
abort(404)
|
||||
rows = db.list_rows(slug, definition)
|
||||
|
||||
# Pour l'affichage : traduit chaque id de relation en un libellé lisible
|
||||
# (ex. "Salle serveur (#1)") au lieu d'un identifiant numérique brut.
|
||||
relation_labels = {}
|
||||
for f in definition["fields"]:
|
||||
if f["type"] == "relation":
|
||||
options = db.relation_options(slug, f["relation_definition_id"])
|
||||
relation_labels[f["id"]] = {opt["id"]: opt["label"] for opt in options}
|
||||
|
||||
referenced_by = db.definitions_referencing(slug, definition_id)
|
||||
|
||||
blocked_row_id = request.args.get("blocked_row", type=int)
|
||||
blocked_row_refs = db.rows_referencing(slug, definition_id, blocked_row_id) if blocked_row_id else None
|
||||
|
||||
return render_template(
|
||||
"data_list.html", game=game, definition=definition, rows=rows,
|
||||
relation_labels=relation_labels, referenced_by=referenced_by,
|
||||
blocked_row_id=blocked_row_id, blocked_row_refs=blocked_row_refs,
|
||||
)
|
||||
@@ -0,0 +1,20 @@
|
||||
def _parse_field_rows(form):
|
||||
field_names = form.getlist("field_name[]")
|
||||
field_types = form.getlist("field_type[]")
|
||||
field_relations = form.getlist("field_relation[]")
|
||||
field_required = form.getlist("field_required[]")
|
||||
field_min = form.getlist("field_min[]")
|
||||
field_max = form.getlist("field_max[]")
|
||||
fields = []
|
||||
for i, fname in enumerate(field_names):
|
||||
if not fname.strip():
|
||||
continue
|
||||
fields.append({
|
||||
"name": fname.strip(),
|
||||
"type": field_types[i],
|
||||
"relation_definition_id": field_relations[i] if i < len(field_relations) else None,
|
||||
"required": field_required[i] == "1" if i < len(field_required) else False,
|
||||
"min_value": (field_min[i].strip() or None) if i < len(field_min) else None,
|
||||
"max_value": (field_max[i].strip() or None) if i < len(field_max) else None,
|
||||
})
|
||||
return fields
|
||||
Reference in New Issue
Block a user