from typing import Any from flask import jsonify, request from werkzeug.wrappers import Response import db import document_engine from core.flask_app import app @app.route("/document//elements/add", methods=["POST"]) def document_element_add(slug: str) -> Response | tuple[Response, int]: """Ajoute un élément à une page précise — appelée en AJAX depuis la bibliothèque du panneau gauche (clic ou glisser-déposer initial), OU par le moteur de layout lui-même pour créer une rangée à la volée au moment d'un dépôt latéral (kind="row" — jamais choisi directement dans la bibliothèque, absent de document_engine.ELEMENT_LIBRARY, mais un kind valide comme un autre pour cette route ; voir static/document/js/document-editor.js). parent_id, quand fourni, place l'élément directement dans une rangée existante DE CETTE MÊME PAGE.""" kind = request.form.get("kind", "") if kind not in document_engine.ELEMENT_KIND_LABELS: return jsonify({"error": "type d'élément inconnu"}), 400 page_id = request.form.get("page_id", type=int) if page_id is None or document_engine.get_document_page(slug, page_id) is None: return jsonify({"error": "page introuvable"}), 404 parent_id = request.form.get("parent_id", type=int) # Un mini-jeu occupe toute la page, à lui seul (retour utilisateur du # 23/09/2026 : "un mini jeu dois occupper toute une page" -> "une page # avec mini-jeu = uniquement ce mini-jeu"). Vérifié ici, POINT D'ENTRÉE # UNIQUE de tout ajout d'élément (bibliothèque, glisser-déposer, # création de rangée à la volée, Annuler/Rétablir) : jamais dupliqué # côté client, qui se contente d'afficher l'erreur renvoyée. is_minigame = kind in document_engine.MINIGAME_KINDS existing = document_engine.list_document_elements(slug, page_id) if is_minigame and parent_id is not None: return jsonify({"error": "Un mini-jeu ne peut pas être placé dans une rangée."}), 400 if is_minigame and existing: return jsonify({"error": "Un mini-jeu doit être seul sur sa page — ajoutez-le sur une nouvelle page."}), 400 if not is_minigame and any(el["kind"] in document_engine.MINIGAME_KINDS for el in existing): return jsonify({"error": "Cette page contient déjà un mini-jeu qui occupe toute la page."}), 400 element_id = document_engine.add_document_element(slug, kind, page_id=page_id, parent_id=parent_id) element = db.assert_not_none( document_engine.get_document_element(slug, element_id), "element_id vient d'etre cree par add_document_element juste au-dessus", ) elements_by_parent: dict[int | None, list[dict[str, Any]]] = {} for el in document_engine.list_document_elements(slug, page_id): elements_by_parent.setdefault(el["parent_id"], []).append(el) return jsonify( { "id": element_id, "kind": kind, "parent_id": parent_id, "attributes": element["attributes"], "rendered_html": document_engine.render_document_element(element, elements_by_parent), } )