Livret PDF v2, graphe des liens côté campagne, et refactor de l'import
Livret PDF (export campagne) :
- refonte lisibilité façon livre de JdR : sommaire paginé, libellés de champs
en tête de ligne, encadrés « À lire aux joueurs » / secrets MJ / combat,
ligne de contexte des scènes, en-tête courant, tables zébrées
- reflète la fusion quête/conteneur : arc SYSTEM masqué, quêtes de hub
fusionnées dans leur chapitre, partie « Quêtes » sans doublon
- contenu complété : sorties de scènes, ennemis liés au bestiaire, pièces
explorables, partie « Tables aléatoires »
- polices DejaVu embarquées (couverture Unicode, licence incluse) et harness
visuel PdfExportPreviewTest (Mockito pur, tourne sans Postgres)
Graphe des liens :
- déplacé du Lore vers la campagne (les PNJ sont des entités de campagne) ;
endpoint /api/npcs/lore/{id} supprimé
- layout retravaillé (anti-chevauchement des libellés, éventail des feuilles
autour des hubs), scènes et quêtes ajoutées, libellés sur 2 lignes,
filtres de légende mémorisés, focus au survol
- positions drag & drop persistées sur la campagne (migration V23,
PUT /api/campaigns/{id}/graph-positions, bouton « Disposition auto »)
Divers :
- ImportService découpé en classes dédiées (parser d'archive, remapper d'ids,
inserters campagne/lore/état de jeu, conversion legacy des quêtes)
- fuites d'abonnements corrigées (takeUntilDestroyed sur paramMap) sur ~15 écrans
- garde-fou i18n fragments/consolidés branché sur npm run build (check-i18n.mjs),
budget SCSS anyComponentStyle relevé à 12 ko
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import { Component, EventEmitter, OnInit, Output } from '@angular/core';
|
||||
import { Component, EventEmitter, OnInit, Output, DestroyRef } from '@angular/core';
|
||||
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
||||
|
||||
import { ReactiveFormsModule, FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
@@ -53,7 +54,8 @@ export class CampaignCreateComponent implements OnInit {
|
||||
constructor(
|
||||
private fb: FormBuilder,
|
||||
private loreService: LoreService,
|
||||
private gameSystemService: GameSystemService
|
||||
private gameSystemService: GameSystemService,
|
||||
private destroyRef: DestroyRef
|
||||
) {
|
||||
this.form = this.fb.group({
|
||||
name: ['', Validators.required],
|
||||
@@ -77,7 +79,7 @@ export class CampaignCreateComponent implements OnInit {
|
||||
// Detecte la selection de l'option sentinelle "Creer un systeme" et bascule
|
||||
// en mode creation inline. On reinitialise immediatement le control a ''
|
||||
// pour que la sentinelle ne reste pas en valeur reelle du form.
|
||||
this.form.get('gameSystemId')?.valueChanges.subscribe(value => {
|
||||
this.form.get('gameSystemId')?.valueChanges.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(value => {
|
||||
if (value === this.CREATE_GAMESYSTEM_SENTINEL) {
|
||||
this.form.get('gameSystemId')?.setValue('', { emitEvent: false });
|
||||
this.startCreateGameSystem();
|
||||
|
||||
@@ -35,6 +35,11 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="header-actions">
|
||||
<button type="button" class="btn-secondary" (click)="openGraph()"
|
||||
[title]="'campaignDetail.graphTitle' | translate">
|
||||
<lucide-icon [img]="Network" [size]="14"></lucide-icon>
|
||||
{{ 'campaignDetail.graph' | translate }}
|
||||
</button>
|
||||
<button type="button" class="btn-secondary" (click)="exportPdf()" [disabled]="exportingPdf">
|
||||
<lucide-icon [img]="FileText" [size]="14"></lucide-icon>
|
||||
{{ (exportingPdf ? 'campaignDetail.pdfExporting' : 'campaignDetail.pdfExport') | translate }}
|
||||
|
||||
@@ -6,7 +6,7 @@ import { CampaignSidebarService } from '../../../services/campaign-sidebar.servi
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { CdkDropList, CdkDrag, CdkDragDrop, moveItemInArray } from '@angular/cdk/drag-drop';
|
||||
import { LucideAngularModule, Swords, Plus, Globe, Pencil, Trash2, Dices, Drama, Check, Play, Upload, Sparkles, Download, FileText, ChevronDown, ChevronRight, X } from 'lucide-angular';
|
||||
import { LucideAngularModule, Swords, Plus, Globe, Pencil, Trash2, Dices, Drama, Check, Play, Upload, Sparkles, Download, FileText, ChevronDown, ChevronRight, X, Network } from 'lucide-angular';
|
||||
import { TranslatePipe, TranslateService } from '@ngx-translate/core';
|
||||
import { Router, RouterLink } from '@angular/router';
|
||||
import { forkJoin, of, Observable } from 'rxjs';
|
||||
@@ -57,6 +57,7 @@ export class CampaignDetailComponent implements OnInit, OnDestroy {
|
||||
readonly ChevronDown = ChevronDown;
|
||||
readonly ChevronRight = ChevronRight;
|
||||
readonly X = X;
|
||||
readonly Network = Network;
|
||||
|
||||
/** Export Foundry en cours (anti double-clic). */
|
||||
exportingFoundry = false;
|
||||
@@ -416,6 +417,13 @@ export class CampaignDetailComponent implements OnInit, OnDestroy {
|
||||
});
|
||||
}
|
||||
|
||||
/** Ouvre le graphe des liens : PNJ de la campagne reliés aux pages de son Lore. */
|
||||
openGraph(): void {
|
||||
if (this.campaign?.id) {
|
||||
this.router.navigate(['/campaigns', this.campaign.id, 'graph']);
|
||||
}
|
||||
}
|
||||
|
||||
/** Génère et télécharge le livret PDF de la campagne. */
|
||||
exportPdf(): void {
|
||||
if (!this.campaign?.id || this.exportingPdf) return;
|
||||
|
||||
Reference in New Issue
Block a user