Correction bug suppression complète coté lore (et suppression dans tout ce qui est campagne de la partie lore liée).

Améliorations ux :
- Bandeau en haut qui reste accessible lors de la création d'un élément (chapitre, page, scène etc...)
- Mise en place d'un surlignage pour voir su quel élément on est positionné
This commit is contained in:
2026-04-23 14:06:50 +02:00
parent 96bc5de942
commit 8efdf5d0e0
33 changed files with 786 additions and 71 deletions

View File

@@ -10,6 +10,10 @@
<lucide-icon [img]="Pencil" [size]="14"></lucide-icon>
Modifier
</button>
<button type="button" class="btn-danger" (click)="deleteArc()" title="Supprimer l'arc et tout son contenu">
<lucide-icon [img]="Trash2" [size]="14"></lucide-icon>
Supprimer
</button>
</div>
</header>

View File

@@ -3,7 +3,7 @@ import { CommonModule } from '@angular/common';
import { ActivatedRoute, Router, RouterModule } from '@angular/router';
import { forkJoin, of } from 'rxjs';
import { switchMap } from 'rxjs/operators';
import { LucideAngularModule, Pencil } from 'lucide-angular';
import { LucideAngularModule, Pencil, Trash2 } from 'lucide-angular';
import { CampaignService } from '../../services/campaign.service';
import { PageService } from '../../services/page.service';
import { LayoutService, GlobalItem } from '../../services/layout.service';
@@ -27,6 +27,7 @@ import { ImageGalleryComponent } from '../../shared/image-gallery/image-gallery.
})
export class ArcViewComponent implements OnInit, OnDestroy {
readonly Pencil = Pencil;
readonly Trash2 = Trash2;
campaignId = '';
arcId = '';
@@ -101,6 +102,38 @@ export class ArcViewComponent implements OnInit, OnDestroy {
this.router.navigate(['/campaigns', this.campaignId, 'arcs', this.arcId, 'edit']);
}
/**
* Suppression en cascade : récupère d'abord le compte de chapitres / scènes
* qui tomberont avec l'arc, l'annonce dans la confirmation, puis délègue au
* backend (transaction atomique).
*/
deleteArc(): void {
if (!this.arc) return;
const arc = this.arc;
this.campaignService.getArcDeletionImpact(arc.id!).subscribe({
next: impact => {
const parts: string[] = [];
if (impact.chapters > 0) parts.push(`${impact.chapters} chapitre${impact.chapters > 1 ? 's' : ''}`);
if (impact.scenes > 0) parts.push(`${impact.scenes} scène${impact.scenes > 1 ? 's' : ''}`);
const lines = [`Supprimer l'arc "${arc.name}" ?`];
if (parts.length) {
lines.push('');
lines.push(`Cette action supprimera aussi : ${parts.join(', ')}.`);
}
lines.push('');
lines.push('Cette action est irréversible.');
if (!confirm(lines.join('\n'))) return;
this.campaignService.deleteArc(arc.id!).subscribe({
next: () => this.router.navigate(['/campaigns', this.campaignId]),
error: () => console.error('Erreur lors de la suppression de l\'arc')
});
},
error: () => console.error('Impossible de récupérer les dépendances de l\'arc')
});
}
ngOnDestroy(): void {
this.layoutService.hide();
}

View File

@@ -74,6 +74,15 @@
}
.detail-header {
// Sticky : Modifier/Supprimer restent accessibles pendant le scroll de la
// campagne (potentiellement très longue avec arcs / chapitres / scènes).
position: sticky;
top: 0;
z-index: 10;
background: #0a0a14;
padding: 1rem 0;
border-bottom: 1px solid #1f2937;
margin-bottom: 1.5rem;
display: flex;
align-items: flex-start;
justify-content: space-between;

View File

@@ -15,6 +15,10 @@
<lucide-icon [img]="Pencil" [size]="14"></lucide-icon>
Modifier
</button>
<button type="button" class="btn-danger" (click)="deleteChapter()" title="Supprimer le chapitre et ses scènes">
<lucide-icon [img]="Trash2" [size]="14"></lucide-icon>
Supprimer
</button>
</div>
</header>

View File

@@ -3,7 +3,7 @@ import { CommonModule } from '@angular/common';
import { ActivatedRoute, Router, RouterModule } from '@angular/router';
import { forkJoin, of } from 'rxjs';
import { switchMap } from 'rxjs/operators';
import { LucideAngularModule, Pencil, Network } from 'lucide-angular';
import { LucideAngularModule, Pencil, Network, Trash2 } from 'lucide-angular';
import { CampaignService } from '../../services/campaign.service';
import { PageService } from '../../services/page.service';
import { LayoutService, GlobalItem } from '../../services/layout.service';
@@ -27,6 +27,7 @@ import { ImageGalleryComponent } from '../../shared/image-gallery/image-gallery.
export class ChapterViewComponent implements OnInit, OnDestroy {
readonly Pencil = Pencil;
readonly Network = Network;
readonly Trash2 = Trash2;
campaignId = '';
arcId = '';
@@ -112,6 +113,33 @@ export class ChapterViewComponent implements OnInit, OnDestroy {
]);
}
/**
* Suppression en cascade : récupère le compte de scènes qui tomberont avec
* le chapitre, l'annonce dans la confirmation, puis délègue au backend.
*/
deleteChapter(): void {
if (!this.chapter) return;
const chapter = this.chapter;
this.campaignService.getChapterDeletionImpact(chapter.id!).subscribe({
next: impact => {
const lines = [`Supprimer le chapitre "${chapter.name}" ?`];
if (impact.scenes > 0) {
lines.push('');
lines.push(`Cette action supprimera aussi : ${impact.scenes} scène${impact.scenes > 1 ? 's' : ''}.`);
}
lines.push('');
lines.push('Cette action est irréversible.');
if (!confirm(lines.join('\n'))) return;
this.campaignService.deleteChapter(chapter.id!).subscribe({
next: () => this.router.navigate(['/campaigns', this.campaignId, 'arcs', this.arcId]),
error: () => console.error('Erreur lors de la suppression du chapitre')
});
},
error: () => console.error('Impossible de récupérer les dépendances du chapitre')
});
}
ngOnDestroy(): void {
this.layoutService.hide();
}

View File

@@ -10,6 +10,10 @@
<lucide-icon [img]="Pencil" [size]="14"></lucide-icon>
Modifier
</button>
<button type="button" class="btn-danger" (click)="deleteScene()" title="Supprimer la scène">
<lucide-icon [img]="Trash2" [size]="14"></lucide-icon>
Supprimer
</button>
</div>
</header>

View File

@@ -3,7 +3,7 @@ import { CommonModule } from '@angular/common';
import { ActivatedRoute, Router, RouterModule } from '@angular/router';
import { forkJoin, of } from 'rxjs';
import { switchMap } from 'rxjs/operators';
import { LucideAngularModule, Pencil } from 'lucide-angular';
import { LucideAngularModule, Pencil, Trash2 } from 'lucide-angular';
import { CampaignService } from '../../services/campaign.service';
import { PageService } from '../../services/page.service';
import { LayoutService, GlobalItem } from '../../services/layout.service';
@@ -26,6 +26,7 @@ import { ImageGalleryComponent } from '../../shared/image-gallery/image-gallery.
})
export class SceneViewComponent implements OnInit, OnDestroy {
readonly Pencil = Pencil;
readonly Trash2 = Trash2;
campaignId = '';
arcId = '';
@@ -110,6 +111,19 @@ export class SceneViewComponent implements OnInit, OnDestroy {
]);
}
/** Suppression simple — une scène n'a pas d'enfants. Retour au chapitre parent. */
deleteScene(): void {
if (!this.scene) return;
const scene = this.scene;
if (!confirm(`Supprimer la scène "${scene.name}" ?\n\nCette action est irréversible.`)) return;
this.campaignService.deleteScene(scene.id!).subscribe({
next: () => this.router.navigate([
'/campaigns', this.campaignId, 'arcs', this.arcId, 'chapters', this.chapterId
]),
error: () => console.error('Erreur lors de la suppression de la scène')
});
}
ngOnDestroy(): void {
this.layoutService.hide();
}