import os import uuid from typing import Any from flask import jsonify, request, url_for from werkzeug.wrappers import Response import db import document_engine from core.flask_app import app _ALLOWED_IMAGE_EXTENSIONS = (".png", ".jpg", ".jpeg", ".gif", ".webp", ".svg") @app.route("/document//elements//upload-image", methods=["POST"]) def document_element_upload_image(slug: str, element_id: int) -> Response | tuple[Response, int]: """Téléverse un fichier image pour un élément "image" (voir _render_image, document_engine/rendering/render_document_element.py) — mirroir de document_element_upload_attachment.py, mais stocké sous `uploads/` (jamais `attachments/`, réservé au bouton) et réservé au kind "image". `svg_markup` est vidé au passage : un fichier téléversé implique `src`, jamais les deux modes en même temps (voir element_default_attributes, `svg_markup` prioritaire sur `src` au rendu — le vider ici évite qu'un ancien code SVG masque silencieusement la photo qui vient d'être choisie).""" element = document_engine.get_document_element(slug, element_id) if element is None: return jsonify({"error": "élément introuvable"}), 404 if element["kind"] != "image": return jsonify({"error": "seul un élément image peut recevoir un fichier téléversé"}), 400 f = request.files.get("file") if not f or not f.filename: return jsonify({"error": "Aucun fichier reçu"}), 400 ext = os.path.splitext(f.filename)[1].lower() if ext not in _ALLOWED_IMAGE_EXTENSIONS: return jsonify({"error": "Format d'image non pris en charge (PNG, JPG, GIF, WEBP, SVG uniquement)"}), 400 stored_name = uuid.uuid4().hex + ext uploads_dir = os.path.join(db.support_dir(slug), "uploads") os.makedirs(uploads_dir, exist_ok=True) f.save(os.path.join(uploads_dir, stored_name)) attributes = { **element["attributes"], "src": url_for("document_uploaded_file", slug=slug, filename=stored_name), "svg_markup": "", } document_engine.update_document_element_attributes(slug, element_id, attributes) element = db.assert_not_none( document_engine.get_document_element(slug, element_id), "element_id verifie present juste au-dessus, aucune suppression concurrente possible entre-temps ici", ) elements_by_parent: dict[int | None, list[dict[str, Any]]] = {} for el in document_engine.list_document_elements(slug, element["page_id"]): elements_by_parent.setdefault(el["parent_id"], []).append(el) return jsonify( { "ok": True, "attributes": element["attributes"], "rendered_html": document_engine.render_document_element(element, elements_by_parent), } )