Export/import par campagne + espace de jeu (v2), fix du nombre de joueurs, et ergonomie de jeu

Export / import de contenu (format v2)
- Export SÉLECTIF : on peut exporter une seule campagne (sa clôture : arcs →
  chapitres → scènes, PNJ, ennemis, catalogues, tables, système de jeu lié) au
  lieu de tout exporter. Options par export : inclure le lore, l'espace de jeu,
  les images. L'export global devient « Sauvegarde complète ».
- ESPACE DE JEU désormais exporté/importé : parties (Playthrough), séances,
  journal, flags, progression de quêtes, et feuilles de perso (Character.playthroughId
  préservé au lieu d'être annulé). Remapping complet des références à l'import.
- Format v2 rétro-compatible : un export v1 (sans section jeu) s'importe toujours
  (champs absents → null → traités comme vides).
- Correction d'un bug latent : collectReferencedStorageKeys traitait les références
  d'images comme des clés de stockage alors que ce sont des IDs → les binaires
  d'images n'étaient en réalité pas embarqués dans le zip. Résolution ID → clé.
- Images des Rooms d'une scène (illustration + plan) désormais collectées (elles
  étaient oubliées des deux collecteurs).
- Endpoint : GET /api/admin/data/export?campaignId=&includeLore=&includePlay=&includeImages=
  ; écran « Sauvegarde des données » avec choix campagne + cases à cocher.
- Tests : round-trip étendu au jeu + binaire image réel, export sélectif par
  campagne, import d'archive v1, et DataTransferController.

Correction : nombre de joueurs non persisté
- playerCount était saisi à la création mais jeté par le backend (absent du
  domaine/entité/DTO/mapper) → affichage « 0 joueurs ». Ajouté sur toute la stack
  + migration V7 (défaut 4 pour les campagnes existantes) + intégré à l'export.

Ergonomie de l'espace de jeu et des listes
- Description de campagne repliable (clamp 3 lignes + « Voir plus / moins »).
- Dossiers repliables (chevron + compteur) dans les listes PNJ et Ennemis, sur la
  page campagne ET les pages dédiées.
- Renommage en place des parties (« Mes parties ») via un crayon.
- Panneau de session : onglets sur 2 rangs (« Scènes » n'est plus rogné) ; scènes
  triées par ordre manuel ; arcs repliables (repliés par défaut) ; PJ/PNJ repliables
  et PNJ regroupés par dossier.
This commit is contained in:
2026-06-26 14:38:39 +02:00
parent c1e3a20e5a
commit f670735100
37 changed files with 1487 additions and 258 deletions

View File

@@ -1,5 +1,5 @@
import { Injectable, NgZone } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { HttpClient, HttpParams } from '@angular/common/http';
import { Observable } from 'rxjs';
/**
@@ -94,10 +94,22 @@ export class SettingsService {
// --- Export / Import des donnees (sauvegarde & transfert d'instance) -------
/** Telecharge l'export complet du contenu (zip : data.json + images). */
exportData(): Observable<Blob> {
/**
* Télécharge un export (zip : data.json + images). Sans options : sauvegarde complète.
* Avec `campaignId` : export ciblé d'une campagne, les options réglant l'univers (lore),
* l'espace de jeu et les binaires d'images embarqués.
*/
exportData(opts?: { campaignId?: string; includeLore?: boolean; includePlay?: boolean; includeImages?: boolean }): Observable<Blob> {
let params = new HttpParams();
if (opts?.campaignId) {
params = params
.set('campaignId', opts.campaignId)
.set('includeLore', String(opts.includeLore ?? true))
.set('includePlay', String(opts.includePlay ?? true))
.set('includeImages', String(opts.includeImages ?? true));
}
return this.http.get('/api/admin/data/export',
{ withCredentials: true, responseType: 'blob' });
{ params, withCredentials: true, responseType: 'blob' });
}
/** Importe un zip d'export en mode FUSION (ajoute, ne remplace pas). */