first commit
Build and deploy / build-and-push (push) Successful in 17s
Build and deploy / deploy (push) Successful in 10s

This commit is contained in:
william
2026-08-21 16:23:49 +02:00
committed by william
commit 3f4ebc4527
248 changed files with 10180 additions and 0 deletions
+8
View File
@@ -0,0 +1,8 @@
from . import (
element_add,
element_add_child,
element_geometry,
element_save,
element_delete,
element_rename,
)
+20
View File
@@ -0,0 +1,20 @@
from flask import request, redirect, url_for
import screens
from core.flask_app import app
@app.route("/game/<slug>/screens/<int:screen_id>/elements/add", methods=["POST"])
def element_add(slug, screen_id):
widget = request.form.get("widget", "conteneur")
from_catalogue = widget == "__catalogue__"
element_type_id = request.form.get("element_type_id") or None if from_catalogue else None
if from_catalogue and not element_type_id:
return redirect(url_for("screen_edit", slug=slug, screen_id=screen_id))
if from_catalogue:
types = {t["id"]: t for t in screens.list_element_types(slug)}
et = types.get(int(element_type_id))
widget = et["default_widget"] if et else "conteneur"
new_id = screens.add_element(slug, screen_id, widget, element_type_id)
return redirect(url_for("screen_edit", slug=slug, screen_id=screen_id, selected=new_id))
+25
View File
@@ -0,0 +1,25 @@
from flask import request, redirect, url_for, abort
import screens
from core.flask_app import app
@app.route("/game/<slug>/elements/<int:parent_id>/children/add", methods=["POST"])
def element_add_child(slug, parent_id):
"""Ajoute un élément PHYSIQUEMENT à l'intérieur d'un conteneur, d'un
répéteur de données ou d'un groupe de champs déjà posé sur l'écran."""
parent = screens.get_element(slug, parent_id)
if not parent:
abort(404)
widget = request.form.get("widget", "conteneur")
from_catalogue = widget == "__catalogue__"
element_type_id = request.form.get("element_type_id") or None if from_catalogue else None
if from_catalogue and element_type_id:
types = {t["id"]: t for t in screens.list_element_types(slug)}
et = types.get(int(element_type_id))
widget = et["default_widget"] if et else "conteneur"
elif from_catalogue:
return redirect(url_for("screen_edit", slug=slug, screen_id=parent["screen_id"], selected=parent_id))
new_id = screens.add_element(slug, parent["screen_id"], widget, element_type_id, parent_id=parent_id)
return redirect(url_for("screen_edit", slug=slug, screen_id=parent["screen_id"], selected=new_id))
+22
View File
@@ -0,0 +1,22 @@
from flask import redirect, url_for, abort
import screens
from core.flask_app import app
@app.route("/game/<slug>/elements/<int:element_id>/delete", methods=["POST"])
def element_delete(slug, element_id):
element = screens.get_element(slug, element_id)
if not element:
abort(404)
screen_id = element["screen_id"]
parent_id = element.get("parent_id")
screens.delete_element(slug, element_id)
# Resélectionne le conteneur parent (s'il y en a un) après suppression,
# plutôt que de laisser le panneau de droite vide : sinon, supprimer un
# élément fait brusquement "sauter" l'éditeur vers un état sans rien de
# sélectionné.
if parent_id:
return redirect(url_for("screen_edit", slug=slug, screen_id=screen_id, selected=parent_id))
return redirect(url_for("screen_edit", slug=slug, screen_id=screen_id))
+20
View File
@@ -0,0 +1,20 @@
from flask import request, jsonify
import screens
from core.flask_app import app
@app.route("/game/<slug>/elements/<int:element_id>/geometry", methods=["POST"])
def element_geometry(slug, element_id):
"""Appelé en AJAX pendant/à la fin d'un glisser-déposer, d'un
redimensionnement, ou d'une modification des champs Position & taille —
ne touche qu'à la position/taille, aucun rechargement de page nécessaire
pour que ça reste fluide."""
data = request.get_json(force=True)
screens.update_element_geometry(
slug, element_id,
x=float(data["x"]), y=float(data["y"]),
width=float(data["width"]), height=float(data["height"]),
)
return jsonify({"ok": True})
+14
View File
@@ -0,0 +1,14 @@
from flask import request, redirect, url_for, abort
import screens
from core.flask_app import app
@app.route("/game/<slug>/elements/<int:element_id>/rename", methods=["POST"])
def element_rename(slug, element_id):
element = screens.get_element(slug, element_id)
if not element:
abort(404)
screens.rename_element(slug, element_id, request.form.get("name", ""))
return redirect(url_for("screen_edit", slug=slug, screen_id=element["screen_id"], selected=element_id))
+18
View File
@@ -0,0 +1,18 @@
from flask import request, redirect, url_for, abort
import screens
from core.flask_app import app
@app.route("/game/<slug>/elements/<int:element_id>/save", methods=["POST"])
def element_save(slug, element_id):
"""Un seul formulaire pour tout le panneau de propriétés : un champ par
réglage du widget (texte, case à cocher, curseur, couleur...) — c'est
screens.save_element_controls qui sait vers quel attribut ou quelle
propriété CSS chaque réglage doit être traduit."""
element = screens.get_element(slug, element_id)
if not element:
abort(404)
screens.save_element_controls(slug, element_id, request.form)
return redirect(url_for("screen_edit", slug=slug, screen_id=element["screen_id"], selected=element_id))