Deuxième moitié de la fonctionnalité "événements" (voir le commit
précédent pour le backend) : un nouvel onglet "📣 Événements" dans
screen_edit.html (scène ET modèle, même route) pour créer/modifier/
supprimer un événement (nom, description, "a un paramètre élément" oui/
non) et voir où il est déjà écouté/déclenché ; deux nouveaux types de
nœud dans le graphe de logique ; exécution réelle côté client
(play.html).
- templates/screen_edit.html :
- Onglet Événements : barre de création + tableau (patron
form/name="..." + attribut `form="eventEditFormN"` déjà utilisé par
l'onglet Variables du tableau de bord, pour éditer plusieurs champs
d'une ligne sans emboîter un <form> dans un <tr>). Colonne "Utilisé
par" avec liens directs vers les écrans/modèles concernés
(list_custom_event_usages, déjà en place côté backend).
- Nœud Déclencheur "Sur un événement personnalisé" : un simple sélecteur
d'événement (trigger_custom_event_id) — ni élément ni écran, retrouvé
par un scan global côté client (comme "À l'affichage de l'écran").
- Nœud Action "Déclencher un événement" : sélecteur d'événement
(target_custom_event_id), avec élément/ligne concernés affichés
seulement si l'événement a has_element_param (réutilise le sélecteur
d'élément existant + "Ligne cliquée" pour la ligne, pas de définition
d'objet ici donc pas de liste de lignes fixes possible).
- Nœud Action "Modifier un élément" : nouvelle case "Utiliser l'élément
transmis par l'événement en cours" (target_element_from_event) — v1,
seule cette action l'expose (extensible plus tard sans nouveau
changement de schéma).
- nodeLabel()/submitNodeForm()/toggleFlowTriggerFields()/
toggleFlowActionFields() étendus en conséquence, CUSTOM_EVENTS_MAP
(id -> nom/has_element_param) exposé côté JS pour le rendu des
libellés et l'affichage conditionnel des champs paramètre.
- templates/play.html :
- window.dispatchGameEvent(eventId, elementId, rowId) : scan de
gameData.flows (toutes scènes ET modèles à la fois, même principe que
findTriggerNode()/runScreenShowTriggers()) pour trouver chaque
écouteur, pose window.lastEventParams puis exécute son graphe
(runFlowFrom) — au même titre que window.lastClickedRowId pour "Ligne
cliquée".
- runActionNode : nouvelle branche "declencher_evenement" (résout
CLICKED_ROW_ID pour la ligne transmise, comme "Modifier une donnée")
; branche "modifier_element" étendue pour résoudre dynamiquement
l'élément depuis window.lastEventParams quand
target_element_from_event est actif.
- readFieldValue (évaluation de condition) et l'appel serveur de
"Modifier une donnée" (routes/flow/flow_node_run_data.py) résolvent
désormais aussi EVENT_ROW_ID (-2), au même endroit que CLICKED_ROW_ID
(-1) déjà en place.
- routes/screens/screen_edit.py : passe custom_events/
custom_event_usages/custom_events_map_json au template (même patron
que global_variables déjà threadé pour le sélecteur de variable dans
le formulaire de Condition).
Nouveaux tests dans tests/test_custom_events.py : forme exacte du
payload runtime exposé au JS (types entiers, pas des chaînes — une
comparaison stricte "===" échouerait silencieusement sinon),
target_element_from_event bien persisté, résolution serveur d'
EVENT_ROW_ID depuis le corps de la requête. 210 tests au total.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>