Nettoyage post-revue : factorisation, code mort et fiabilité (reorder/lore/foundry/PDF)
All checks were successful
Build & Push Images / build (brain) (push) Successful in 1m27s
Build & Push Images / build (web) (push) Successful in 1m50s
Build & Push Images / build (core) (push) Successful in 3m29s
Build & Push Images / build-switcher (push) Successful in 18s

Corrections fonctionnelles
- order initialisé à la création des pages et dossiers de lore (nextOrderFor) :
  un nouvel élément se place désormais en dernier de sa fratrie au lieu de 0
- storePortrait : type MIME canonique dérivé de l'extension du fichier
  (un data URL "image/jpg" n'est plus rejeté silencieusement)
- takeUntilDestroyed ajouté sur les abonnements paramMap de arc-view,
  folder-view et campaign-detail (fuites mémoire)

Factorisation (suppression de duplication)
- shared/folder-grouping.util.ts : groupByFolder + byOrder + byFolderName
  mutualisés entre npc-list, enemy-list, campaign-detail et la sidebar
  (folderChildren). Le tri des dossiers est désormais cohérent entre la
  sidebar et les vues cartes (insensible casse/accents partout)
- DataSyncService.onChange()/persist() remplacent le câblage
  changed$ + reorder recopié dans 5 vues
- campaign-detail : loadCampaignBundle()/applyCampaignBundle() éliminent
  le forkJoin dupliqué entre ngOnInit et reload
- ReorderSupport (domain/shared) : squelette générique remplaçant les
  8 boucles de réordonnancement copiées dans les services
- FoundryExportService : GameSystem résolu une seule fois dans buildBundle
- module Foundry : walkScalars mutualise la récursion de flattenStats et
  flattenStructure (comportements préservés) ; esc() de l'importer aligné
  sur foundry.utils.escapeHTML

Suppression de code mort
- characterService/characters retirés de loadCampaignTreeData et de ses
  16 appelants (arguments, injections, imports et littéraux CampaignTreeData)
- CSS orphelin : .tree-row.cdk-drop-list-receiving et .btn-back
- BottomPanel.initiallyOpen (jamais lu) retiré de l'interface et de l'appelant
- commentaire trompeur du PDF corrigé

Tests
- mise à jour de 3 tests obsolètes de campaign-tree.helper.spec qui
  vérifiaient encore l'ancien comportement (tri alphabétique, non-classés
  en enfants directs) → alignés sur le modèle actuel (tri par order +
  pseudo-dossier "Sans dossier")
This commit is contained in:
2026-06-26 09:10:20 +02:00
parent 3896c5b4cb
commit a9242ba1e1
94 changed files with 2234 additions and 546 deletions

View File

@@ -0,0 +1,38 @@
import { Injectable, DestroyRef } from '@angular/core';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { Observable, Subject } from 'rxjs';
/**
* Bus d'événement minimal pour synchroniser les vues qui affichent les MÊMES données
* (arbre de la sidebar ↔ vues en cartes). Après un réordonnancement/déplacement
* (depuis n'importe quelle vue), on émet `changed$` ; chaque vue concernée se recharge
* → tout reste cohérent SANS rafraîchir la page (F5).
*/
@Injectable({ providedIn: 'root' })
export class DataSyncService {
private readonly _changed = new Subject<void>();
/** Émis quand une donnée ordonnable a changé (reorder/move). */
readonly changed$ = this._changed.asObservable();
notify(): void {
this._changed.next();
}
/**
* Abonne `handler` aux changements de données, avec auto-désabonnement lié au
* cycle de vie du composant (`destroyRef`). Évite de recopier le couple
* `changed$.pipe(takeUntilDestroyed(...)).subscribe(...)` dans chaque vue.
*/
onChange(destroyRef: DestroyRef, handler: () => void): void {
this.changed$.pipe(takeUntilDestroyed(destroyRef)).subscribe(handler);
}
/**
* Persiste un réordonnancement : au succès, notifie les autres vues
* (`notify()`) ; en cas d'échec, exécute `rollback` (typiquement recharger pour
* annuler le déplacement optimiste à l'écran).
*/
persist<T>(reorder$: Observable<T>, rollback: () => void): void {
reorder$.subscribe({ next: () => this.notify(), error: () => rollback() });
}
}