Un exemplaire d'élément de jeu posé sur un écran reste maintenant lié à son modèle

Jusqu'ici, poser un élément de jeu depuis le catalogue ("Mes éléments de
jeu") copiait tout son arbre en base (instantiate_template_tree) : chaque
exemplaire devenait indépendant, y compris de son propre modèle - modifier
l'élément de jeu dans son éditeur n'avait plus aucun effet sur les
exemplaires déjà posés ailleurs.

Change ce comportement pour qu'un exemplaire reste TOUJOURS lié à son
modèle, sur le même principe déjà utilisé par un modèle de ligne de
Répéteur (jamais copié, rechargé en direct à chaque affichage - voir
_load_template_tree/_render_repeater) : add_element.py ne crée plus
qu'UNE SEULE ligne plate (avec sa position/taille propres à cet
exemplaire) au lieu de copier tout l'arbre, et render_element_html.py
recharge le contenu depuis l'écran-modèle à chaque rendu quand
element_type_id est réglé. Modifier l'élément de jeu dans son propre
éditeur met donc à jour tous ses exemplaires déjà posés, sur n'importe
quel écran (y compris ceux placés AVANT ce correctif, qui portaient déjà
element_type_id sur leur ligne de premier niveau), sans avoir à les
retoucher un par un.

Contrepartie assumée (discutée avec l'utilisateur avant ce changement) :
un exemplaire ne peut plus être personnalisé individuellement à
l'INTÉRIEUR (texte, couleur d'un enfant précis...) - seules sa position et
sa taille sur l'écran restent propres à chaque exemplaire. Pour changer le
contenu, il faut désormais passer par l'éditeur de l'élément de jeu
lui-même.

instantiate_template_tree.py, devenu inutilisé, est supprimé.

Ajoute tests/test_element_type_live_instances.py (mise à jour d'un
exemplaire déjà posé, propagation jusqu'à "Jouer", position toujours
indépendante par exemplaire) et met à jour un commentaire de test devenu
obsolète dans test_screens_and_elements.py.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
william
2026-08-25 15:26:45 +02:00
co-authored by Claude Sonnet 5
parent 79fe04c6ac
commit e9a991ed13
6 changed files with 124 additions and 73 deletions
+80
View File
@@ -0,0 +1,80 @@
"""Un exemplaire d'élément de jeu posé directement sur un écran (catalogue)
est désormais TOUJOURS lié à son modèle, comme un modèle de ligne de
Répéteur (voir add_element.py, render_element_html.py) : modifier
l'élément de jeu dans son propre éditeur met à jour tous ses exemplaires
déjà posés, sans avoir à les retoucher un par un — au prix de ne plus
pouvoir personnaliser individuellement le contenu d'un exemplaire précis."""
import re
import screens
def _create_screen(client, slug, name="Accueil"):
resp = client.post(f"/game/{slug}/screens/new", data={"name": name}, follow_redirects=False)
return int(re.search(r"/screens/(\d+)/edit", resp.headers["Location"]).group(1))
def _create_card_element_type(client, slug, name="Carte"):
resp = client.post(f"/game/{slug}/element-types", data={"name": name, "icon": "🃏"}, follow_redirects=False)
assert resp.status_code == 302
et = next(t for t in screens.list_element_types(slug) if t["name"] == name)
resp = client.post(f"/game/{slug}/screens/{et['template_screen_id']}/elements/add", data={"widget": "titre"}, follow_redirects=False)
titre_id = int(re.search(r"selected=(\d+)", resp.headers["Location"]).group(1))
client.post(f"/game/{slug}/elements/{titre_id}/save", data={"ctrl_content": "Version 1"})
return et, titre_id
def test_editing_the_template_updates_an_already_placed_instance(client, game):
et, titre_id = _create_card_element_type(client, game)
screen_id = _create_screen(client, game)
client.post(
f"/game/{game}/screens/{screen_id}/elements/add",
data={"widget": "__catalogue__", "element_type_id": str(et["id"])},
follow_redirects=False,
)
html = client.get(f"/game/{game}/screens/{screen_id}/edit").data.decode()
assert "Version 1" in html
client.post(f"/game/{game}/elements/{titre_id}/save", data={"ctrl_content": "Version 2"})
html = client.get(f"/game/{game}/screens/{screen_id}/edit").data.decode()
assert "Version 2" in html
assert "Version 1" not in html
def test_editing_the_template_updates_the_play_page_too(client, game):
et, titre_id = _create_card_element_type(client, game)
screen_id = _create_screen(client, game)
client.post(
f"/game/{game}/screens/{screen_id}/elements/add",
data={"widget": "__catalogue__", "element_type_id": str(et["id"])},
follow_redirects=False,
)
client.post(f"/game/{game}/elements/{titre_id}/save", data={"ctrl_content": "Contenu mis à jour"})
html = client.get(f"/game/{game}/play").data.decode()
assert "Contenu mis à jour" in html
def test_instance_position_on_screen_is_independent_per_instance(client, game):
"""Non-régression : la position/taille sur l'écran reste propre à
chaque exemplaire (seul le CONTENU intérieur est désormais partagé)."""
et, _titre_id = _create_card_element_type(client, game)
screen_id = _create_screen(client, game)
resp = client.post(
f"/game/{game}/screens/{screen_id}/elements/add",
data={"widget": "__catalogue__", "element_type_id": str(et["id"])},
follow_redirects=False,
)
first_id = int(re.search(r"selected=(\d+)", resp.headers["Location"]).group(1))
resp = client.post(
f"/game/{game}/screens/{screen_id}/elements/add",
data={"widget": "__catalogue__", "element_type_id": str(et["id"])},
follow_redirects=False,
)
second_id = int(re.search(r"selected=(\d+)", resp.headers["Location"]).group(1))
first = screens.get_element(game, first_id)
second = screens.get_element(game, second_id)
assert (first["x"], first["y"]) != (second["x"], second["y"])
+3 -1
View File
@@ -120,7 +120,9 @@ def test_element_type_template_case_a_and_case_b(client, game, mail_object):
element_type_id = int(re.search(r"element-types/(\d+)/delete", html).group(1))
# ---- Case A : posé directement sur un écran réel -> copie indépendante ----
# ---- Case A : posé directement sur un écran réel -> lié en direct au
# modèle (voir add_element.py/render_element_html.py), mais {{sujet}}
# reste non résolu hors Répéteur (pas de ligne de données courante) ----
real_screen_id = _create_screen(client, slug, "Accueil")
resp = client.post(
f"/game/{slug}/screens/{real_screen_id}/elements/add",