Amélioration du feedback pendant les imports sur les PDF
All checks were successful
Build & Push Images / build (brain) (push) Successful in 1m38s
Build & Push Images / build (core) (push) Successful in 1m59s
Build & Push Images / build-switcher (push) Successful in 17s
Build & Push Images / build (web) (push) Successful in 1m54s

passage en 0.12.4-beta
This commit is contained in:
2026-06-12 14:35:10 +02:00
parent 14fc1c28fe
commit 8cc90bd24d
28 changed files with 364 additions and 115 deletions

View File

@@ -31,6 +31,9 @@
</div>
</div>
}
@if (importStatus) {
<p class="import-status" role="status">{{ importStatus }}</p>
}
@if (importCounts) {
<p class="import-counts">
Trouvé jusqu'ici : {{ importCounts.arcs }} arc(s) · {{ importCounts.chapters }} chapitre(s) · {{ importCounts.scenes }} scène(s) · {{ importCounts.npcs }} PNJ

View File

@@ -87,6 +87,16 @@
.import-counts { margin: 0.55rem 0 0; color: #9ca3af; font-size: 0.8rem; }
// Message d'attente live (fournisseur saturé → retry, morceau re-découpé…) :
// ambre pour signaler « ça travaille, mais il se passe quelque chose ».
.import-status {
margin: 0.55rem 0 0;
color: #fbbf24;
font-size: 0.8rem;
font-style: italic;
line-height: 1.4;
}
.import-error,
.apply-error {
margin: 1rem 0 0;

View File

@@ -74,6 +74,12 @@ export class CampaignImportComponent implements OnInit {
importing = false;
importPhase = '';
importProgress: { current: number; total: number } | null = null;
/**
* Dernier message de statut du flux (fournisseur saturé → retry, morceau
* re-découpé/ignoré…). Effacé à chaque progression : il explique l'ATTENTE
* en cours, pas l'historique.
*/
importStatus: string | null = null;
importCounts: { arcs: number; chapters: number; scenes: number; npcs: number } | null = null;
importError: string | null = null;
/** Vrai une fois la proposition reçue (on affiche l'arbre éditable). */
@@ -132,12 +138,15 @@ export class CampaignImportComponent implements OnInit {
this.applyError = null;
this.importPhase = 'Extraction du texte…';
this.importProgress = null;
this.importStatus = null;
this.importCounts = null;
this.tree = [];
this.service.importStructureStream(this.campaignId, file).subscribe({
next: (ev) => {
if (ev.type === 'progress') {
// Un morceau vient d'aboutir : le message d'attente est obsolète.
this.importStatus = null;
if (ev.total === 0) {
this.importPhase = 'Extraction du texte…';
this.importProgress = null;
@@ -149,10 +158,13 @@ export class CampaignImportComponent implements OnInit {
scenes: ev.sceneCount, npcs: ev.npcCount ?? 0
};
}
} else if (ev.type === 'status') {
this.importStatus = ev.message;
} else if (ev.type === 'done') {
this.importing = false;
this.importPhase = '';
this.importProgress = null;
this.importStatus = null;
if ((ev.arcs ?? []).length === 0 && (ev.npcs ?? []).length === 0) {
this.importError = "Aucune structure narrative détectée dans ce PDF.";
this.reviewing = false;