Migration Angular 20 -> 21 : fin de la migration securite (0 vulnerabilite npm)

- ng update @angular/core@21 @angular/cli@21 (corrige GHSA-jrmj-c5cx-3cw6, XSS SVG)
- Migration automatique des templates vers le control flow natif (@if/@for, 138 fichiers)
- Correction des 5 `track` invalides generes par la migration (trackBy a 1 argument
  -> track $index) + suppression des fonctions trackBy mortes
- TypeScript 5.9, zone.js 0.15 ; npm audit : 0 vulnerabilite

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-10 14:55:36 +02:00
parent 6acad41672
commit 23878f1c63
142 changed files with 7055 additions and 6292 deletions

View File

@@ -1,85 +1,92 @@
<div class="folder-view" *ngIf="node">
<!-- Fil d'Ariane : Lore → ancêtres → dossier courant -->
<nav class="breadcrumb" aria-label="Fil d'Ariane">
<button type="button" class="crumb" (click)="navigateToLoreRoot()" *ngIf="lore">
{{ lore.name }}
</button>
<ng-container *ngFor="let ancestor of ancestors">
@if (node) {
<div class="folder-view">
<!-- Fil d'Ariane : Lore → ancêtres → dossier courant -->
<nav class="breadcrumb" aria-label="Fil d'Ariane">
@if (lore) {
<button type="button" class="crumb" (click)="navigateToLoreRoot()">
{{ lore.name }}
</button>
}
@for (ancestor of ancestors; track ancestor) {
<lucide-icon [img]="ChevronRight" [size]="12" class="crumb-sep"></lucide-icon>
<button type="button" class="crumb" (click)="navigateToSubfolder(ancestor.id!)">
{{ ancestor.name }}
</button>
}
<lucide-icon [img]="ChevronRight" [size]="12" class="crumb-sep"></lucide-icon>
<button type="button" class="crumb" (click)="navigateToSubfolder(ancestor.id!)">
{{ ancestor.name }}
</button>
</ng-container>
<lucide-icon [img]="ChevronRight" [size]="12" class="crumb-sep"></lucide-icon>
<span class="crumb current">{{ node.name }}</span>
</nav>
<!-- Header : icône + nom + actions -->
<div class="detail-header">
<div class="header-texts">
<h1>
<lucide-icon [img]="folderIcon" [size]="24" class="title-icon"></lucide-icon>
{{ node.name }}
</h1>
<p class="description">
{{ subfolders.length }} sous-dossier(s) · {{ pages.length }} page(s)
</p>
</div>
<div class="header-actions">
<button type="button" class="btn-secondary" (click)="navigateToEdit()" title="Modifier le dossier">
<lucide-icon [img]="Pencil" [size]="14"></lucide-icon>
Modifier
</button>
<button type="button" class="btn-danger" (click)="delete()" title="Supprimer le dossier et tout son contenu">
<lucide-icon [img]="Trash2" [size]="14"></lucide-icon>
Supprimer
</button>
<span class="crumb current">{{ node.name }}</span>
</nav>
<!-- Header : icône + nom + actions -->
<div class="detail-header">
<div class="header-texts">
<h1>
<lucide-icon [img]="folderIcon" [size]="24" class="title-icon"></lucide-icon>
{{ node.name }}
</h1>
<p class="description">
{{ subfolders.length }} sous-dossier(s) · {{ pages.length }} page(s)
</p>
</div>
<div class="header-actions">
<button type="button" class="btn-secondary" (click)="navigateToEdit()" title="Modifier le dossier">
<lucide-icon [img]="Pencil" [size]="14"></lucide-icon>
Modifier
</button>
<button type="button" class="btn-danger" (click)="delete()" title="Supprimer le dossier et tout son contenu">
<lucide-icon [img]="Trash2" [size]="14"></lucide-icon>
Supprimer
</button>
</div>
</div>
<!-- Sous-dossiers -->
<section class="detail-section">
<div class="section-header">
<h2>Sous-dossiers</h2>
<button class="btn-add" (click)="navigateToCreateSubfolder()">
<lucide-icon [img]="Plus" [size]="14"></lucide-icon>
Nouveau sous-dossier
</button>
</div>
@if (subfolders.length > 0) {
<div class="items-grid">
@for (sub of subfolders; track sub) {
<div class="node-card" (click)="navigateToSubfolder(sub.id!)">
<lucide-icon [img]="Folder" [size]="24" class="node-icon"></lucide-icon>
<span class="node-name">{{ sub.name }}</span>
</div>
}
</div>
}
@if (subfolders.length === 0) {
<div class="empty-state">
<p>Aucun sous-dossier.</p>
</div>
}
</section>
<!-- Pages -->
<section class="detail-section">
<div class="section-header">
<h2>Pages</h2>
<button class="btn-add" (click)="navigateToCreatePage()">
<lucide-icon [img]="Plus" [size]="14"></lucide-icon>
Nouvelle page
</button>
</div>
@if (pages.length > 0) {
<div class="items-grid">
@for (page of pages; track page) {
<div class="node-card" (click)="navigateToPage(page.id!)">
<lucide-icon [img]="FileText" [size]="24" class="node-icon"></lucide-icon>
<span class="node-name">{{ page.title }}</span>
</div>
}
</div>
}
@if (pages.length === 0) {
<div class="empty-state">
<p>Aucune page dans ce dossier.</p>
</div>
}
</section>
</div>
<!-- Sous-dossiers -->
<section class="detail-section">
<div class="section-header">
<h2>Sous-dossiers</h2>
<button class="btn-add" (click)="navigateToCreateSubfolder()">
<lucide-icon [img]="Plus" [size]="14"></lucide-icon>
Nouveau sous-dossier
</button>
</div>
<div class="items-grid" *ngIf="subfolders.length > 0">
<div class="node-card" *ngFor="let sub of subfolders" (click)="navigateToSubfolder(sub.id!)">
<lucide-icon [img]="Folder" [size]="24" class="node-icon"></lucide-icon>
<span class="node-name">{{ sub.name }}</span>
</div>
</div>
<div class="empty-state" *ngIf="subfolders.length === 0">
<p>Aucun sous-dossier.</p>
</div>
</section>
<!-- Pages -->
<section class="detail-section">
<div class="section-header">
<h2>Pages</h2>
<button class="btn-add" (click)="navigateToCreatePage()">
<lucide-icon [img]="Plus" [size]="14"></lucide-icon>
Nouvelle page
</button>
</div>
<div class="items-grid" *ngIf="pages.length > 0">
<div class="node-card" *ngFor="let page of pages" (click)="navigateToPage(page.id!)">
<lucide-icon [img]="FileText" [size]="24" class="node-icon"></lucide-icon>
<span class="node-name">{{ page.title }}</span>
</div>
</div>
<div class="empty-state" *ngIf="pages.length === 0">
<p>Aucune page dans ce dossier.</p>
</div>
</section>
</div>
}