Nettoyage post-revue : factorisation, code mort et fiabilité (reorder/lore/foundry/PDF)
All checks were successful
All checks were successful
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:
@@ -9,7 +9,7 @@ const t = { instant: (k: string) => k } as unknown as TranslateService;
|
||||
function data(partial: Partial<CampaignTreeData> = {}): CampaignTreeData {
|
||||
return {
|
||||
arcs: [], chaptersByArc: {}, scenesByChapter: {},
|
||||
characters: [], npcs: [], randomTables: [], enemies: [],
|
||||
npcs: [], randomTables: [], enemies: [],
|
||||
...partial,
|
||||
};
|
||||
}
|
||||
@@ -23,15 +23,15 @@ describe('buildCampaignTree', () => {
|
||||
]);
|
||||
});
|
||||
|
||||
it('trie les arcs en ordre NUMÉRIQUE naturel (1, 2, 10)', () => {
|
||||
it('trie les arcs par ordre manuel (champ order, réagencé au glisser-déposer)', () => {
|
||||
const arcs = [
|
||||
{ id: 'a', name: '10. Final' },
|
||||
{ id: 'b', name: '2. Voyage' },
|
||||
{ id: 'c', name: '1. Intro' },
|
||||
{ id: 'a', name: 'Final', order: 2 },
|
||||
{ id: 'b', name: 'Voyage', order: 1 },
|
||||
{ id: 'c', name: 'Intro', order: 0 },
|
||||
];
|
||||
const tree = buildCampaignTree('c1', data({ arcs: arcs as never }), t);
|
||||
const arcLabels = tree.filter((n) => n.id?.startsWith('arc-')).map((n) => n.label);
|
||||
expect(arcLabels).toEqual(['1. Intro', '2. Voyage', '10. Final']);
|
||||
expect(arcLabels).toEqual(['Intro', 'Voyage', 'Final']);
|
||||
});
|
||||
|
||||
it('imbrique chapitres et scènes et marque les chapitres à prérequis', () => {
|
||||
@@ -47,7 +47,7 @@ describe('buildCampaignTree', () => {
|
||||
expect(chapter.children![0].id).toBe('scene-s1');
|
||||
});
|
||||
|
||||
it('regroupe les PNJ par dossier et laisse les non classés à la racine', () => {
|
||||
it('regroupe les PNJ par dossier et place les non classés dans un pseudo-dossier', () => {
|
||||
const npcs = [
|
||||
{ id: 'n1', name: 'Alice', folder: 'Ville' },
|
||||
{ id: 'n2', name: 'Bob', folder: 'Ville' },
|
||||
@@ -58,15 +58,19 @@ describe('buildCampaignTree', () => {
|
||||
expect(npcsRoot.meta).toBe('3');
|
||||
const folder = npcsRoot.children!.find((c) => c.id === 'npc-folder-Ville')!;
|
||||
expect(folder.children!.map((c) => c.label)).toEqual(['Alice', 'Bob']);
|
||||
expect(npcsRoot.children!.some((c) => c.id === 'npc-n3')).toBe(true);
|
||||
// Les non classés vont dans un pseudo-dossier « Sans dossier » (et non en enfants
|
||||
// directs) : tous les dossiers restent FRÈRES → glisser-déposer inter-dossiers fiable.
|
||||
const none = npcsRoot.children!.find((c) => c.id === 'npc-folder-__none__')!;
|
||||
expect(none.children!.some((c) => c.id === 'npc-n3')).toBe(true);
|
||||
});
|
||||
|
||||
it("affiche le niveau de l'ennemi en méta", () => {
|
||||
const tree = buildCampaignTree('c', data({
|
||||
enemies: [{ id: 'e1', name: 'Gobelin', level: 3 }] as never,
|
||||
enemies: [{ id: 'e1', name: 'Gobelin', level: 3, folder: 'Cave' }] as never,
|
||||
}), t);
|
||||
const enemiesRoot = tree.find((n) => n.id === 'enemies-root')!;
|
||||
expect(enemiesRoot.children![0].meta).toBe('Niv. 3');
|
||||
const folder = enemiesRoot.children!.find((c) => c.id === 'enemy-folder-Cave')!;
|
||||
expect(folder.children![0].meta).toBe('Niv. 3');
|
||||
});
|
||||
|
||||
it('libelle « nouvelle quête » dans un arc HUB (vs « nouveau chapitre »)', () => {
|
||||
|
||||
Reference in New Issue
Block a user