from typing import Any from flask import render_template import db import document_engine from core.flask_app import app @app.route("/document//edit") def document_edit(slug: str) -> str: """Éditeur du support — route directe, sans page intermédiaire (un support = un projet = un document, voir docs/plan/PLAN.md). Contraste avec l'environnement 2D (clic sur une carte -> game_dashboard qui liste ses écrans -> éditeur de scène) : ici la carte "Mes formations" mène directement ici. Un support est composé de plusieurs PAGES (voir document_engine/ pages/, retour utilisateur du 21/09/2026 : "il faut implémenter un système de page") : le canevas n'affiche au chargement que la PREMIÈRE page (triée par order_index) — changer de page se fait ensuite entièrement côté client via /document//render?page_id= (voir static/document/js/document-editor.js), jamais un rechargement complet de cette route. La navigation entre pages (ajout/renommage/ suppression/réordonnancement) vit dans une section dédiée du panneau gauche (retour utilisateur du 21/09/2026 : "une section qui s'ajoute dans le panneau de gauche pour ajouter une page et naviguer entre elles"), qui n'a besoin que des métadonnées de page (`pages`), jamais d'un rendu de leur contenu. Les attributs de chaque élément sont revalidés (document_engine. sanitize_element_attributes) avant d'atteindre le client — jamais les valeurs brutes stockées telles quelles : un élément dont le schéma a évolué depuis sa création (ex. le mini-jeu Scénario, passé d'une liste plate à un arbre de décision) ferait sinon planter silencieusement le panneau Propriétés côté client, qui suppose la forme ACTUELLE (bug réel constaté le 21/09/2026).""" support = db.support_meta(slug) pages = document_engine.list_document_pages(slug) # active_page peut être None : un support peut avoir 0 page (retour # utilisateur du 26/09/2026, voir document_engine/pages/pages.md) — le # canevas et le panneau Pages doivent alors afficher un état "aucune # page" plutôt que de planter, voir document_edit.html et # document-editor.js (forgeDocSwitchPage/forgeDocRefreshCanvas). active_page = pages[0] if pages else None active_elements: list[dict[str, Any]] = ( [ {**el, "attributes": document_engine.sanitize_element_attributes(el["kind"], el["attributes"])} for el in document_engine.list_document_elements(slug, active_page["id"]) ] if active_page is not None else [] ) active_theme = document_engine.get_document_theme_entry(support["theme"]) if support["theme"] else None return render_template( "document/document_edit.html", support=support, pages=pages, active_page=active_page, elements=active_elements, rendered_document=document_engine.render_document(active_elements), element_library=document_engine.ELEMENT_LIBRARY, element_kind_labels=document_engine.ELEMENT_KIND_LABELS, active_theme=active_theme, # Seuls les champs utiles à la modale "Utiliser un modèle" côté # client (voir static/document/js/document-editor.js) — jamais le # `seed_pages` complet, inutilement volumineux et non nécessaire # côté client (l'aperçu et l'application se font tous deux en # appelant le serveur, voir document_theme_preview.py/ # document_theme_apply.py). Pas de route JSON dédiée pour une # donnée 100% statique côté serveur : le catalogue tient déjà # dans le contexte de cette page (voir document_engine/themes/ # theme_catalog.py). document_themes=[ {"id": t["id"], "name": t["name"], "category": t["category"], "description": t["description"]} for t in document_engine.DOCUMENT_THEMES ], )