Gestion des étapes - StevenYAMBOS/Smash-Here-API GitHub Wiki

Mise à jour d’une Roadmap

Cette page décrit le fonctionnement du composant UpdateRoadmapForm.vue qui permet de modifier une roadmap en deux volets distincts :

  1. Informations de base (titre, description, image, flags, jeux associés)
  2. Structure des étapes (liste des étapes, relations parent/enfant)

Contexte global

  • Le composant se trouve dans src/components/ui/UpdateRoadmapForm.vue.

  • La modification d’une roadmap se fait désormais en deux formulaires séparés :

    1. Formulaire 1 : Informations de base

      • Champs utilisés : title, subTitle, description, cover, published, premium, Games
      • Routes Back-End à utiliser :
        • getOneRoadmap : récupérer l’objet roadmap complet
        • updateRoadmapInfo : mettre à jour uniquement les champs « info de base »
    2. Formulaire 2 : Étapes

      • Champ utilisé : Steps (tableau d’ObjectId pointant vers des documents step)
      • Routes Back-End à utiliser :
        • getRoadmapSteps : récupérer le tableau initial Steps de la roadmap
        • updateRoadmapSteps : mettre à jour la liste d’IDs Steps dans le document roadmap
        • updateOneStep : mettre à jour un document step (champs PreviousSteps, NextSteps, Roadmaps)
        • addStepToRoadmaps et removeStepFromRoadmap (peuvent être utilisés pour des appels plus fins si nécessaire)

1. Formulaire 1 : Informations de base

1.1 Objectif

Ce premier onglet permet de modifier :

  • Le titre (title)
  • Le sous-titre (subTitle)
  • La description (description)
  • L’image de couverture (cover)
  • Les flags Publié (published) et Premium (premium)
  • Les jeux associés (Games)

1.2 Composants et données

Propriétés reçues

  • props.roadmap : objet complet de la roadmap existante, contenant notamment :
  interface Roadmap {
    id: string
    title: string
    subTitle?: string
    description: string
    cover: string       // URL de la couverture actuelle
    published: boolean
    premium: boolean
    Games: string[]     // Tableau d’IDs de jeux déjà associés
    Steps: string[]
    // … autres champs éventuels …
  }

2. Formulaire 2 : Structure des étapes

2.1 Objectif

Ce second onglet permet de gérer la liste d’étapes associées à la roadmap et leurs relations parent↔enfant.

  • On peut ajouter ou retirer une étape de la liste Steps de la roadmap.

  • On peut relier des étapes (ajouter un lien source → target) ou supprimer un lien existant.

  • Côté Back-End, on aura besoin des routes :

    • getRoadmapSteps : pour charger initialement la liste Steps (tableau d’IDs) associée à la roadmap.
    • updateRoadmapSteps : pour réécrire le seul champ Steps dans le document roadmap.
    • updateOneStep : pour mettre à jour individuellement un step (tables PreviousSteps, NextSteps et champ Roadmaps).
    • addStepToRoadmaps / removeStepFromRoadmap : peuvent être implémentés pour des appels plus granulaires si on veut gagner en efficacité.

2.2 Relations entre étapes

  • Chaque document step contient, parmi ses champs :
  {
    "Roadmaps": ["ObjectId"],     // IDs des roadmaps qui incluent cette étape
    "PreviousSteps": ["ObjectId"], // IDs des étapes parentes
    "NextSteps": ["ObjectId"],     // IDs des étapes enfants
    // ...
  }
  • Dans l’UI, on affiche les étapes sur plusieurs niveaux horizontaux :

    • Les étapes sans parent (aucun PreviousSteps) sont les racines ; elles sont sur la ligne 0.
    • Les enfants (NextSteps) du(s) parent(s) apparaissent sur la ligne 1, etc.
  • Exemple concret :

    1. Choix du personnage (Étape 1)

      • PreviousSteps: []
      • NextSteps: [ id2 ]
    2. Choix de la manette (Étape 2)

      • PreviousSteps: [ id1 ]
      • NextSteps: [ id3, id4 ]
    3. Les attaques (Étape 3)

      • PreviousSteps: [ id2 ]
      • NextSteps: [ … ]
    4. La défense (Étape 4)

      • PreviousSteps: [ id2 ]
      • NextSteps: [ … ]
  • La synchronisation des relations s’effectue via la route PUT /step/{stepId} (updateOneStep). Le back-end s’assure de mettre à jour à la fois PreviousSteps et NextSteps de l’étape en question, et de maintenir le champ Roadmaps à jour (pour inclure l’ID de la roadmap si nécessaire).


3. Comprendre le fonctionnement des étapes

3.1 Structure en base de données

Chaque document step (collection step) possède notamment :

{
  "Roadmaps": ["ObjectId"],     // IDs des roadmaps associées
  "PreviousSteps": ["ObjectId"], // IDs des étapes parentes
  "NextSteps": ["ObjectId"],     // IDs des étapes enfants
  "title": "string",
  "subtitle": "string",
  "description": "string",
  // ...
}
  • Roadmaps maintient la liste des ObjectId des roadmaps dans lesquelles cette étape apparaît.

  • PreviousSteps / NextSteps définissent un graphe orienté (DAG) sans cycles (pour la progression linéaire ou arborescente).

  • Par bonne pratique, lorsqu’on modifie un step via PUT /step/{id}, le back-end doit maintenir la cohérence inverse :

    • Si l’on ajoute targetId dans NextSteps d’un step source, updateOneStep doit automatiquement inclure sourceId dans PreviousSteps du step target, et vice-versa (bidirectionnel).

4. Résumé visuel du composant

UpdateRoadmapForm.vue
├─ Onglet 1 “Informations” (formInfo)
│   ├─ title (input text)
│   ├─ subTitle (input text)
│   ├─ description (textarea)
│   ├─ published (toggle switch)
│   ├─ premium (toggle switch)
│   ├─ Roadmap’s games (Multiselect pré-rempli + recherche)
│   └─ Cover image (preview ancien ou nouveau fichier + input[type=file] caché)
│   └─ Boutons : [Cancel] [Save]
│
└─ Onglet 2 “Steps” (formSteps)
    ├─ Étapes disponibles (Multiselect + icône “+”)
    ├─ Aperçu VueFlow (nodes + edges)
    │   ├─ nœuds = Steps sélectionnées
    │   ├─ arêtes = relations NextSteps / PreviousSteps
    │   ├─ onConnect → création d’un lien (PUT /step/{id})
    │   ├─ onEdgesChange → suppression d’un lien (PUT /step/{id})
    │   └─ Drag & Drop → ajout visuel de nœud (appel addStep + submitStructure)
    └─ Bouton : [Enregistrer la structure]


5. Exemple de schéma de l’arborescence des étapes

  1. Choix du personnage (Étape 1)

    • PreviousSteps: []
    • NextSteps: [ Étape 2 ]
  2. Choix de la manette (Étape 2)

    • PreviousSteps: [ Étape 1 ]
    • NextSteps: [ Étape 3, Étape 4 ]
  3. Les attaques (Étape 3)

    • PreviousSteps: [ Étape 2 ]
    • NextSteps: [ … ]
  4. La défense (Étape 4)

    • PreviousSteps: [ Étape 2 ]
    • NextSteps: [ … ]

Visuellement, VueFlow les organise ainsi (auto-layout) :

(ÉTAPE 1) → (ÉTAPE 2) → (ÉTAPE 3)
                    ↘ (ÉTAPE 4)
  • Les nœuds « ÉTAPE 1 » sans parent sont en haut (level 0).
  • Les enfants immédiats (« ÉTAPE 2 ») sont en level 1.
  • Les petits-enfants (« ÉTAPE 3 » et « ÉTAPE 4 ») sont sur level 2, etc.

6. Bonnes pratiques

  • Séparer la mise à jour “infos” et “structure” évite des payloads trop lourds et permet de gérer de façon découplée la logique métier (titres, flags, jeux, images d’un côté / graphe d’étapes de l’autre).
  • Toujours recycler l’URL existante props.roadmap.cover pour que l’utilisateur voie en temps réel l’ancienne couverture et sache qu’il peut la remplacer.
  • Vérifier systématiquement la taille et le type du fichier image avant de faire URL.createObjectURL() pour éviter des fichiers trop volumineux ou un format non supporté.
  • Maintenir la cohérence des relations PreviousSteps ←→ NextSteps en appelant toujours updateOneStep dès qu’un lien est ajouté ou supprimé, pour que la base reflète l’état du graphe.
  • Toujours mettre à jour le champ Roadmaps d’un step lors de son ajout dans selectedSteps (s’il n’y figure pas).
  • Tester en local avec getOneRoadmap + getStep/{id} pour vérifier que tous les PreviousSteps et NextSteps remontent correctement.

En résumé, UpdateRoadmapForm.vue se découpe en deux sous-composants logiques (onglets) :

  1. Infos de base → Chargement initial via getOneRoadmap, mise à jour via updateRoadmapInfo.
  2. Structure des étapes → Chargement initial des IDs via getRoadmapSteps (ou getOneRoadmap), construction du graphe via VueFlow, mise à jour finale de la liste d’IDs via updateRoadmapSteps, et synchronisation point-à-point des liens via updateOneStep, addStepToRoadmaps, removeStepFromRoadmap selon les besoins.