f3b72d73c97663a15789b8b4ad40d7f87adecb20
12
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
9776fbc057 |
Score/Progression (Phase 1.1 de la feuille de route produit)
Concept de premier ordre, distinct du système de variables globales — préalable identifié aux futurs exports SCORM/xAPI (note de cadrage .claude/Forge_Engine_Cadrage.pdf) : ces standards ont besoin d'un signal "score"/"terminé" propre, pas d'une convention sur une variable choisie par le créateur. - db/scoring/ (même patron que db/global_vars/) : table _scoring, un score numérique + un statut (non_commence/en_cours/termine/reussi/ echoue) par joueur (voir db.PLAYER_SHARED pour l'aperçu créateur). - Deux nouvelles actions de flux, dans les deux éditeurs (document et scène) : "Modifier le score" (réutilise le vocabulaire d'opérations déjà là pour "Modifier une variable" — incrémenter/définir/etc., aucune nouvelle colonne de nœud) et "Définir le statut de la partie". - Routes créateur (routes/flow/flow_node_run_score.py, flow_node_run_status.py) + miroirs publics par joueur (routes/public_play/) — même principe que flow_node_run_variable.py. - GET /game/<slug>/scoring/<player_id> : lecture interne, pas exposée au joueur, préparée pour être consommée par le futur export Web/SCORM. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> |
||
|
|
76a50fa87a |
Onboarding guidé systématique + tableau de bord simplifié
Comportement SYSTÉMATIQUE à chaque création de jeu (admin compris), pas une formalité réservée à l'inscription : /onboarding (routes/onboarding/) devient le point d'entrée unique — 4 cartes retournables (survol = explication au dos), défilement horizontal animé vers le nom du jeu. Un admin y repasse à volonté (pas de project_slug dédié, jamais bloqué/ redirigé vers un projet précédent) ; un compte "user" n'en a plus qu'un créé d'office (routes/auth/register_2fa.py), guidé ici à la place. - db/games/game_type_catalog.py : catalogue des 4 types (Quiz/ Embranchement-escape game/RPG/Créer mon jeu de A à Z), _meta['onboarding_type'] décide du "kind" du premier écran créé et si le tableau de bord complet reste accessible. - routes/games/game_dashboard.py, templates/game_dashboard_simple.html : un type restreint (quiz/embranchement/rpg) voit désormais SON tableau de bord (même route que "custom"), rendu en version simplifiée — juste ses écrans en cartes avec un aperçu RÉEL du contenu (scène mise à l'échelle par container query CSS, adaptée à la largeur réelle de la carte). "+ Ajouter un écran" n'y propose pas de choix de type : imposé par le projet (routes/screens/screens_new.py), verrouillé aussi côté serveur. - core/auth_guard.py : plus de blocage de game_dashboard par type — la restriction se fait au rendu, pas à l'accès à la route. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> |
||
|
|
0f23024882 |
Structure de dossiers par utilisateur : projects/<propriétaire>/<projet>/
Remplace le rangement plat projects/<slug>/ par une vraie arborescence par compte créateur, sans toucher aux routes existantes (aucune ne déclare de "/" dans son <slug> : le chemin composé "propriétaire_projet" reste un détail interne à db/, décodé par db/games/project_slug.py, seul fichier à modifier si la convention change un jour). - db/game_dir.py, create_game.py, delete_game.py, list_games.py, move_game.py : résolvent/construisent ce chemin composé. Bénéfice direct : deux comptes différents peuvent chacun avoir un projet nommé pareil sans collision (l'unicité ne se vérifie plus que par dossier propriétaire). move_game.py renomme désormais le dossier PROPRIÉTAIRE entier (changement d'email), prêt pour un futur multi-projet. - scripts/migrate_flat_project_slugs.py : migration des projets déjà créés sous l'ancien rangement plat (simulation par défaut, --apply pour exécuter). - routes/auth/profile.py, tests/conftest.py : suppression de compte/jeu de test via db.delete_game (nettoie aussi le dossier propriétaire devenu vide) plutôt qu'un shutil.rmtree direct du seul dossier projet. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> |
||
|
|
efa7d1d9b0 |
Fondations multi-éditeurs (1/3) : game_type + schéma/CRUD des objets de scène
Première brique du plan "Fondations d'une plateforme multi-éditeurs" — l'utilisateur veut un éditeur dédié aux jeux 2D/serious games (scène à coordonnées pixel fixes, objets en couches, collision, personnages animés), distinct de l'éditeur générique actuel, sans dupliquer ce qui peut être partagé (comptes, objets de données, moteur de logique de flow, hébergement/publication). - db/games/get_game_type.py (nouveau) : "document" (défaut, éditeur actuel) ou "jeu_2d" (nouveau), stocké dans _meta comme is_public_played — aucune migration pour les jeux déjà créés (retombent sur "document"). Choisi obligatoirement à la création (templates/index.html), jamais modifiable ensuite. - screens/scenes/ (nouveau sous-module) : table _scene_objects (une scène = des objets en pixels fixes, pas les % fluides de _screen_elements — indispensable pour la collision/l'animation), CRUD complet, rendu HTML. kind="personnage" réutilise TELLE QUELLE la structure _personnage_data et les fonctions resolve_personnage_* déjà écrites pour le widget "personnage" de l'éditeur document (Phase 8) — même bibliothèque Forge, même moteur d'animation, juste une autre table de stockage. - screens/flow/ensure_flow_schema.py : += trigger_object_id/ target_object_id (ALTER TABLE sans contrainte FK, même patron que cond_element_a) — le moteur de logique de flow (_flow_nodes/_flow_edges, flow-engine.js) reste EXACTEMENT le même pour les deux éditeurs, seule la palette de nœuds change (screens/scenes/flow_palette.py, nouveau : sous-ensemble direct des triggers/actions existants, déjà génériques). - screens/screens_repo/ensure_schema.py : += scene_width/scene_height sur _screens (taille de scène fixe en pixels, sans effet sur un écran "document"). Reste à faire (prochains commits) : route + template de l'éditeur de scène, puis le rendu en mode jouable. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> |
||
|
|
3c39f1a249 |
Phase 1 (2/3) : route publique /jouer/<slug> + identité visiteur
Ajoute la vraie route hébergée multi-joueurs qui manquait totalement
(voir le constat d'exploration : /game/<slug>/play est réservé au
créateur connecté, "Publier" ne génère qu'un exécutable mono-joueur) —
un visiteur anonyme peut maintenant jouer un jeu explicitement publié en
ligne, avec sa propre partie (variables/objets per_player posés dans le
commit précédent).
core/player_identity.py : identité visiteur via un cookie NON SIGNÉ
(forge_player_id, secrets.token_urlsafe(16), 1 an) — une simple clé de
partition, jamais un jeton d'autorisation.
routes/public_play/ : 4 routes, miroirs des routes existantes de l'aperçu
créateur mais threadées avec le vrai player_id du cookie au lieu du
sentinel PLAYER_SHARED :
- GET /jouer/<slug> (game_play_public.py)
- GET /jouer/<slug>/runtime-payload
- POST /jouer/<slug>/flow/nodes/<id>/run-data
- POST /jouer/<slug>/flow/nodes/<id>/run-variable
Chacune vérifie elle-même db.is_public_played(slug) (404 sinon) — un jeu
n'est exposé publiquement que si le créateur l'a explicitement basculé
"Publier en ligne" (nouveau db/games/is_public_played.py, réutilise la
table générique _meta, comme game_meta.py pour 'name').
core/auth_guard.py : les 4 endpoints publics ajoutés à _PUBLIC_ENDPOINTS
— la garde générique de connexion les laisse passer sans session, mais
chaque vue vérifie quand même is_public_played elle-même (défense en
profondeur, pas seulement une liste d'exceptions). CSRF (core/csrf_guard.py)
n'a besoin d'AUCUN changement : le jeton est déjà lié à la session Flask,
qui existe pour n'importe quel visiteur (connecté ou non).
templates/play.html : FORGE_PLAY_URLS (posé en Phase -1) ne construit
plus ses URLs via des noms de endpoint fixes (url_for('runtime_payload',
...)) mais reçoit des URLs déjà résolues par la route elle-même
(runtime_payload_url/flow_node_run_data_url/flow_node_run_variable_url)
— nécessaire puisque ce même template sert maintenant DEUX familles de
routes (aperçu créateur ET partie publique), chacune avec ses propres
noms de endpoint. routes/play/game_play.py (aperçu créateur, INCHANGÉ
comportement) et game_play_public.py passent chacun ses propres URLs.
templates/base.html : bascule "🌐 Publier en ligne" dans la barre de
navigation du jeu, à côté de "📦 Publier" (export .zip) — deux
fonctionnalités distinctes. db/games/game_meta.py expose maintenant
is_public_played, disponible partout où `game` est dans le contexte.
Vérifié : 237 tests passent (5 nouveaux dans test_public_play.py, dont un
bout-en-bout via HTTP avec deux VRAIS clients de test anonymes — deux
cookies forge_player_id différents — qui obtiennent des valeurs de
variable indépendantes, et un qui verrouille que l'aperçu créateur reste
inchangé). Syntaxe JS validée sur les deux variantes de play.html rendu
(aperçu créateur et partie publique).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
|
||
|
|
0e390a679b |
Ajoute l'onglet "Données" au panneau objet, retire object_view.html
Suite de la demande : le panneau "Modifier un objet" (crayon ✏️, onglet Objets du tableau de bord) a maintenant 2 sous-onglets — "Champs" (déjà en place) et "Données", qui reprend data_list.html + data_form.html (retirés) : ajouter une entrée (une ligne compacte avec le bon type de champ par colonne — texte/nombre/case à cocher/date/relation, comme l'ancien formulaire), modifier/supprimer une entrée existante (tableau dense, cellules éditables en ligne, même principe que "Champs existants"). Sous-onglets scopés au panneau de LEUR objet (switchObjectPanelTab(), classes .objectPanelTabs/.objectPanelTabPanel distinctes de .builderTabs/ .builderTabPanel) — plusieurs objets ont chacun leurs propres sous-onglets indépendants sur la même page, sans jamais interférer avec les onglets du tableau de bord lui-même. routes/games/game_dashboard.py fournit maintenant, par objet : ses lignes (rows_by_definition), les libellés lisibles de ses champs relation (relation_labels_by_definition, pour l'affichage) et leurs options (relation_options_by_definition, pour les <select>), ainsi que referenced_by_definition (avertissement permanent si un autre objet a une relation vers celui-ci — repris de l'ancien object_view.py, affiché maintenant en continu plutôt qu'après une tentative de suppression échouée). data_form.py (partagé par data_new/data_edit), data_delete.py et object_delete.py redirigent maintenant vers le tableau de bord (?edit=<id>&subtab=data, +?blocked_row=<id> si la suppression d'une entrée est bloquée par une relation) au lieu de object_view/object_edit. Piège évité : de nombreux tests déduisent l'id d'un objet fraîchement créé du DERNIER SEGMENT du chemin dans le header Location d'une redirection (.../objects/<id>) — rediriger object_new directement vers le tableau de bord (chemin sans id) cassait donc 33 tests d'un coup. Fix : object_view.py reste en place, mais seulement comme redirecteur (plus de page rendue) — object_new redirige toujours vers lui (chemin qui se termine par l'id, donc les tests continuent de fonctionner), qui redirige à son tour vers le tableau de bord. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> |
||
|
|
b8dfdcb205 |
Corrige la nav pjax, panneau déplaçable/redimensionnable pour éditer un objet
1) Bug pjax trouvé : swapDocument() cherchait "header.topbar", qui n'a jamais existé (c'est un <nav>, pas un <header>) — la barre de navigation du jeu (ajoutée après pjax.js) n'était donc jamais mise à jour pendant une navigation pjax : absente en arrivant sur un jeu sans Ctrl+F5, et inversement laissée en place en revenant sur l'accueil où elle n'a rien à faire. Fix : tout ce qui est hors <main> mais doit changer d'une page à l'autre (topbar + barre du jeu) est regroupé dans un nouveau conteneur stable #pageChrome, que pjax.js remplace en bloc — plus fiable qu'un sélecteur qui ne correspondait à rien. CSS (flex:0 0 auto des layouts plein-écran) mis à jour en conséquence. 2) Renommages demandés : onglet/panneau "Écrans du jeu" -> "Écrants", "Éléments de jeu" -> "Templates" (tab, titre de panneau, bouton "+ Créer un template", état vide, infobulle, confirmation de suppression). 3) Le crayon ✏️ sur une ligne d'objet ouvre désormais un panneau déplaçable ET redimensionnable (nouveau coin de redimensionnement générique, .floatPanelResizeHandle) au lieu de naviguer vers object_edit.html (retirée) — un panneau par objet, pré-rendu et caché par défaut. Reprend telles quelles les fonctionnalités de l'ancienne page : renommer l'objet, ajouter un champ (ligne compacte), modifier/supprimer un champ existant (tableau dense déjà repris pour "Nouvel objet"), supprimer l'objet. Les routes de champs (object_field_ add/edit/delete) et object_edit lui-même redirigent maintenant vers le tableau de bord avec ?edit=<id>, pour rouvrir automatiquement le bon panneau après l'action plutôt que de le fermer silencieusement. makeFloatPanelDraggable()/makeFloatPanelResizable() généralisées pour être partagées entre "Nouvel objet" et les panneaux d'édition, plutôt que du code dupliqué par panneau. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> |
||
|
|
d875557254 |
Fusionne les 4 pages de création dans le dashboard, retire le titre/BDD
Suite de la demande précédente : les 4 pages autrefois listées dans la barre de navigation n'existent plus en tant que pages séparées — tout vit désormais dans les onglets du tableau de bord (commit précédent) ou, pour la création d'un objet, dans un panneau déplaçable. - screens_list.html + sa route (screens_list) : supprimés (l'onglet "Écrans du jeu" du dashboard couvre déjà tout : créer, réordonner, éditer, supprimer). screen_new/screen_move/screen_delete redirigent maintenant vers le dashboard (tab=screens) au lieu de cette page. - element_types.html : supprimé, mais la route element_types est conservée (GET redirige vers le dashboard, POST — utilisé par la barre de création repliable de l'onglet "Éléments de jeu" — continue de fonctionner). element_type_edit/element_type_delete redirigent aussi vers le dashboard. - game_variables.html + sa route (game_variables) : supprimés (l'onglet "Variables" du dashboard couvre déjà tout). create_global_var/ global_var_edit/global_var_delete redirigent vers le dashboard (tab=variables) au lieu de cette page. - object_form.html : supprimé. La route object_new (POST) est conservée pour traiter la soumission du panneau — voir plus bas — mais ne rend plus de page pour un GET (redirige vers le dashboard). Nouveau panneau déplaçable "Nouvel objet" sur le dashboard (bouton "+ Nouvel objet" de l'onglet Objets) : réutilise .floatPanel/ .floatPanelHeader/.floatPanelBody (déjà utilisées dans l'éditeur d'écran) avec une nouvelle variante centrée (.floatPanel--center) et son propre glisser-déposer minimal (pas de position persistée, contrairement aux panneaux de l'éditeur d'écran — inutile pour un panneau ouvert ponctuellement). Contenu et script (object_form.js) repris tels quels de l'ancienne page. base.html : la barre de navigation du jeu n'a donc plus que 2 liens — "📊 Tableau de bord" (nouveau) et "▶️ Jouer" (toujours en dernier). game_dashboard.html : titre du jeu et chemin de la base de données retirés (redondants avec le nom déjà visible dans l'onglet du navigateur/la barre de nav). Les liens "crée-en un"/"gérer les variables" dans l'éditeur d'écran (screen_edit.html) pointent maintenant vers le dashboard avec le bon onglet (?tab=...), lu et appliqué au chargement de la page (switchDashTab() côté JS). 2 tests (test_screens_and_elements.py) mis à jour : ils vérifiaient le contenu des pages supprimées (element-types, screens) — adaptés pour vérifier la même chose sur le dashboard, qui porte maintenant cette information. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> |
||
|
|
65450a5719 |
Refait le dashboard en fenêtre à onglets avec de vrais tableaux
Le précédent dashboard (grille de cartes compactes) ne correspondait pas
à ce que l'utilisateur voulait : une seule fenêtre avec de vrais tableaux
de données (denses, colonnes nettes), un bouton "Créer" par catégorie
dans l'en-tête, et une navigation horizontale pour passer d'une catégorie
à l'autre.
Réutilise telles quelles .builderTabs/.builderTabBtn/.builderTabPanel
(déjà utilisées pour "Écran / Logique / Timeline" dans l'éditeur d'écran)
plutôt que d'inventer un 2e système d'onglets — même sensation partout
dans l'outil. Un onglet par catégorie (Écrans/Objets/Éléments de
jeu/Variables), chacun avec :
- un bouton "+ Créer" dans l'en-tête qui révèle une barre de création
compacte (repliée par défaut) — sauf pour les Objets, dont la
création (plusieurs champs typés) reste sur sa propre page dédiée,
trop complexe pour tenir dans une barre ;
- le VRAI tableau de gestion de cette catégorie (colonnes, actions),
repris tel quel de screens_list.html/element_types.html/
game_variables.html plutôt que réinventé en version appauvrie.
La page défile désormais normalement (retrait de body.objectEditBody/
content-objectEdit, pensés pour une hauteur figée avec défilement
interne) — une liste peut être longue, pas besoin d'un défilement séparé
par panneau ici.
routes/games/game_dashboard.py fournit en plus variable_types
(db.GLOBAL_VARIABLE_TYPES) pour la barre de création de variable.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
|
||
|
|
8f45169209 |
Retire le fil d'Ariane, centre/réordonne la barre de nav, refait le dashboard
Trois demandes distinctes de l'utilisateur, regroupées car elles touchent
toutes à la navigation d'un jeu :
1. Fil d'Ariane retiré (devenu redondant avec la barre de navigation du
jeu ajoutée au commit précédent) : bloc breadcrumb_wrap retiré de
base.html, et son override ({% block breadcrumb %}) retiré des 9
templates qui le définissaient encore. .breadcrumbBar (CSS) retiré,
y compris des règles flex:0 0 auto de body.objectEditBody/builderBody.
2. Liens de .gameNavBar centrés (justify-content:center).
3. "Jouer" déplacé en dernier lien (c'est une action à part — ouvre
l'aperçu jouable dans un nouvel onglet — pas un éditeur de plus comme
les 4 autres).
4. game_dashboard.html devient un vrai tableau de bord : une grille de
cartes (Écrans/Objets/Éléments de jeu/Variables), chacune listant les
entrées existantes avec un accès direct (clic = éditeur concerné) et
un lien "Gérer" vers la page dédiée pour créer/réorganiser. Remplace
l'ancien panneau "Créer" (redondant avec la barre de navigation
persistante) et la simple table "Objets définis". routes/games/
game_dashboard.py alimente maintenant aussi screen_list, element_types
(+ usage) et variables, en réutilisant list_screens/
list_element_types/element_type_usage_count/list_global_variables déjà
utilisés ailleurs.
Vérifié en rendant toutes les pages concernées via le client de test
Flask : barre de nav présente partout où un `game` est dans le contexte
(absente sur l'accueil), fil d'Ariane absent partout, ordre des liens
avec "Jouer" en dernier.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
|
||
|
|
2bb0c253f9 |
Fix object-form breaking on repeat pjax visits, and stray autofill in game rename field
object_form.js declared top-level const bindings, which pjax replays verbatim on every visit — the second visit threw "already declared" and silently broke "Ajouter un champ"/"Créer l'objet". Wrapped it in an IIFE. Also renamed the generic name="name" rename-game field to name="game_name" with autocomplete off, since browsers were autofilling it with unrelated previously-typed values. |
||
|
|
3f4ebc4527 | first commit |