Quêtes libres : fin des conteneurs fantômes (cascade, impact annoncé, export filtré, migration V24)
Some checks failed
Qualité & Sécurité / Web (ESLint · angular-eslint + sonarjs) (push) Successful in 52s
Qualité & Sécurité / Trivy (CVE dépendances Maven / pip / npm) (push) Successful in 2m36s
Qualité & Sécurité / MegaLinter (PMD · Ruff · Bandit · gitleaks · hadolint) (push) Successful in 1m11s
Build & Push Images / build (web) (push) Failing after 35s
Build & Push Images / build (brain) (push) Successful in 1m18s
Build & Push Images / build-switcher (push) Successful in 42s
Build & Push Images / build (core) (push) Successful in 3m8s
Some checks failed
Qualité & Sécurité / Web (ESLint · angular-eslint + sonarjs) (push) Successful in 52s
Qualité & Sécurité / Trivy (CVE dépendances Maven / pip / npm) (push) Successful in 2m36s
Qualité & Sécurité / MegaLinter (PMD · Ruff · Bandit · gitleaks · hadolint) (push) Successful in 1m11s
Build & Push Images / build (web) (push) Failing after 35s
Build & Push Images / build (brain) (push) Successful in 1m18s
Build & Push Images / build-switcher (push) Successful in 42s
Build & Push Images / build (core) (push) Successful in 3m8s
Sidebar Lore : le panneau Templates ne peut plus écraser l'arbre Plafonné à 45 % de la sidebar avec ascenseur interne sur la liste — l'en-tête, le repli et le bouton + restent toujours visibles, l'arbre garde son propre scroll (remonté par un utilisateur avec ~30 templates) Passage v1.0.3
This commit is contained in:
@@ -181,14 +181,32 @@ export class QuestViewComponent implements OnInit {
|
||||
this.router.navigate(['/campaigns', this.campaignId, 'quests', this.questId, 'edit']);
|
||||
}
|
||||
|
||||
/** Suppression simple : une quête n'a pas d'enfants (les nœuds sont des références faibles). */
|
||||
/**
|
||||
* Suppression avec annonce de l'impact réel : le conteneur de scènes d'une quête
|
||||
* LIBRE (arc SYSTEM, invisible dans l'arbre) part en cascade avec ses scènes —
|
||||
* le nombre est affiché dans la confirmation. Les nœuds simplement liés et les
|
||||
* jumeaux de hub (qui restent visibles dans leur arc) ne sont pas concernés.
|
||||
*/
|
||||
deleteQuest(): void {
|
||||
if (!this.quest) return;
|
||||
const quest = this.quest;
|
||||
if (!quest?.id) return;
|
||||
this.questService.deletionImpact(this.campaignId, quest.id).subscribe({
|
||||
next: impact => this.confirmDeleteQuest(quest, impact.scenes),
|
||||
error: () => this.confirmDeleteQuest(quest, 0) // impact indisponible : confirmation simple
|
||||
});
|
||||
}
|
||||
|
||||
private confirmDeleteQuest(quest: Quest, scenes: number): void {
|
||||
const details = [
|
||||
...(scenes > 0
|
||||
? [this.translate.instant('questView.deleteImpactScenes', { count: scenes })]
|
||||
: []),
|
||||
this.translate.instant('questView.irreversible')
|
||||
];
|
||||
this.confirmDialog.confirm({
|
||||
title: this.translate.instant('questView.deleteTitle'),
|
||||
message: this.translate.instant('questView.deleteMessage', { name: quest.name }),
|
||||
details: [this.translate.instant('questView.irreversible')],
|
||||
details,
|
||||
confirmLabel: this.translate.instant('common.delete'),
|
||||
variant: 'danger'
|
||||
}).then(ok => {
|
||||
|
||||
@@ -3,6 +3,11 @@ import { HttpClient } from '@angular/common/http';
|
||||
import { Observable } from 'rxjs';
|
||||
import { Quest, QuestCreate } from './campaign.model';
|
||||
|
||||
/** Impact d'une suppression : scènes du conteneur (quête libre) qui partiront avec. */
|
||||
export interface QuestDeletionImpact {
|
||||
scenes: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Service HTTP pour les Quêtes (Niveau 1). API nestée sous la campagne :
|
||||
* /api/campaigns/{campaignId}/quests. Si {@code playthroughId} est fourni, les
|
||||
@@ -39,6 +44,10 @@ export class QuestService {
|
||||
return this.http.delete<void>(`${this.base(campaignId)}/${questId}`);
|
||||
}
|
||||
|
||||
deletionImpact(campaignId: string, questId: string): Observable<QuestDeletionImpact> {
|
||||
return this.http.get<QuestDeletionImpact>(`${this.base(campaignId)}/${questId}/deletion-impact`);
|
||||
}
|
||||
|
||||
reorder(campaignId: string, orderedIds: string[]): Observable<void> {
|
||||
return this.http.put<void>(`${this.base(campaignId)}/reorder`, { orderedIds });
|
||||
}
|
||||
|
||||
@@ -148,6 +148,11 @@
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.25rem;
|
||||
// PLAFONNÉ : avec beaucoup de templates, c'est la liste du panneau qui défile
|
||||
// (cf. .panel-list) — sans plafond, le panneau grandissait jusqu'à écraser
|
||||
// complètement l'arbre au-dessus (sidebar en overflow: hidden).
|
||||
flex-shrink: 0;
|
||||
max-height: 45%;
|
||||
}
|
||||
|
||||
.panel-header-row {
|
||||
@@ -202,6 +207,10 @@
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.1rem;
|
||||
// Ascenseur interne, symétrique de celui de l'arbre (.tree) : l'en-tête du
|
||||
// panneau et son bouton « + » restent toujours visibles.
|
||||
overflow-y: auto;
|
||||
min-height: 0;
|
||||
}
|
||||
|
||||
.panel-item {
|
||||
|
||||
@@ -1707,6 +1707,7 @@
|
||||
"notProvided": "Not provided",
|
||||
"deleteTitle": "Delete quest",
|
||||
"deleteMessage": "Delete the quest \"{{name}}\"?",
|
||||
"deleteImpactScenes": "{{count}} scene(s) of this quest will be deleted with it.",
|
||||
"irreversible": "This action is irreversible.",
|
||||
"deletedPage": "(deleted page)",
|
||||
"deletedQuest": "(deleted quest)",
|
||||
|
||||
@@ -1707,6 +1707,7 @@
|
||||
"notProvided": "Non renseigné",
|
||||
"deleteTitle": "Supprimer la quête",
|
||||
"deleteMessage": "Supprimer la quête « {{name}} » ?",
|
||||
"deleteImpactScenes": "{{count}} scène(s) de cette quête seront supprimées avec elle.",
|
||||
"irreversible": "Cette action est irréversible.",
|
||||
"deletedPage": "(page supprimée)",
|
||||
"deletedQuest": "(quête supprimée)",
|
||||
|
||||
Reference in New Issue
Block a user