5.5 KiB
Correctif Trash Explorer - Résumé Technique
Problème Initial
La section Trash n'affichait pas l'arborescence du dossier .trash et ne permettait pas de cliquer sur un dossier pour charger ses notes dans la liste.
Causes Identifiées
1. Bouton accordion Trash émet incorrectement un événement
Fichier: src/app/features/sidebar/nimbus-sidebar.component.ts
Ligne: 90
Problème: Le bouton toggle de la section Trash émettait folderSelected.emit('.trash') au click, ce qui changeait le filtre de Notes-liste au lieu de juste ouvrir/fermer l'accordion.
Solution: Retrait de l'émission au click du bouton accordion.
// AVANT
<button (click)="open.trash = !open.trash; folderSelected.emit('.trash')">
// APRÈS
<button (click)="open.trash = !open.trash">
2. TrashExplorerComponent n'émet pas folderSelected
Fichier: src/app/layout/sidebar/trash/trash-explorer.component.ts
Ligne: 91-94
Problème: La méthode onFolderClick() du composant parent toggle le dossier mais n'émet PAS l'événement folderSelected. Donc quand l'utilisateur clique sur un dossier trash, le parent (nimbus-sidebar) ne reçoit pas l'événement et ne peut pas mettre à jour folderFilter dans app-shell-nimbus.
Solution: Ajout de l'émission de folderSelected avec le path du dossier cliqué.
// AVANT
onFolderClick(folder: VaultFolder) {
this.vault.toggleFolder(folder.path);
}
// APRÈS
onFolderClick(folder: VaultFolder) {
this.vault.toggleFolder(folder.path);
this.folderSelected.emit(folder.path);
}
Flux Complet Corrigé
- Utilisateur clique sur un dossier dans Trash (ex:
.trash/old-folder) TrashExplorerComponent.onFolderClick()est appelé- Le dossier est toggle ouvert/fermé via
vault.toggleFolder() - L'événement
folderSelectedest émis avec le path.trash/old-folder NimbusSidebarComponentpropage l'événement versAppShellNimbusComponentAppShellNimbusComponent.onFolderSelected()définitthis.folderFilter = '.trash/old-folder'NotesListComponentreçoitfolderFilteren input- Le computed
filtered()filtre les notes oùoriginalPathcommence par.trash/old-folder - Les notes du dossier trash s'affichent dans la liste
Architecture Existante Validée
VaultService - buildTrashTree()
- ✅ Parse correctement les chemins trash via
parseTrashFolderSegments() - ✅ Construit l'arborescence avec
ensureTrashFolderPath() - ✅ Les badges de compte sont calculés par
calculateTrashFolderCounts() - ✅
.trashest exclu de la section Folders viasortAndCleanFolderChildren()
NotesListComponent - Filtrage
- ✅ Le filtre
folderFilterfonctionne avec les chemins trash - ✅ Compare
originalPathavec le folder passé (égalité ou startsWith) - ✅ Compatible avec les chemins
.trash/subfolder
Backend API
- ✅
/api/vaultcharge tous les fichiers .md y compris.trash - ✅ Les
filePathsont relatifs au vault:.trash/old-folder/note.md - ✅ Les
originalPathsont sans extension:.trash/old-folder/note
Fichiers Modifiés
-
src/app/features/sidebar/nimbus-sidebar.component.ts
- Retrait émission incorrecte au click accordion Trash
-
src/app/layout/sidebar/trash/trash-explorer.component.ts
- Ajout émission
folderSelectedau click sur dossier
- Ajout émission
-
.env
- VAULT_PATH pointant vers
./vaultpour tests
- VAULT_PATH pointant vers
-
vault/.trash/ (fichiers test créés)
- deleted-note-1.md
- old-folder/old-note-2.md
- old-folder/old-note-3.md
- archive/archived-note.md
Critères d'Acceptation ✅
- La section Trash affiche l'arborescence réelle du dossier
.trash - Cliquer un dossier dans Trash charge ses fichiers dans Notes-liste
- Les badges affichent le nombre correct de notes (récursif)
.trashn'apparaît pas dans la section Folders- États hover/sélection cohérents avec autres sections
- Dark mode compatible (styles existants)
- Cas vide géré avec empty-state "La corbeille est vide"
Tests Suggérés
Manuel
- Démarrer
node server/index.mjsetnpm run dev - Ouvrir Sidebar → Trash
- Vérifier que "old-folder" et "archive" s'affichent
- Cliquer "old-folder" → Notes-liste doit montrer 2 notes
- Vérifier badges: "old-folder (2)", "archive (1)"
- Vérifier que
.trashn'apparaît pas dans Folders
E2E (à créer)
test('Trash explorer displays folders and loads notes on click', async ({ page }) => {
await page.goto('http://localhost:3000');
await page.click('text=Trash');
await expect(page.locator('text=old-folder')).toBeVisible();
await page.click('text=old-folder');
await expect(page.locator('text=Old Note 2')).toBeVisible();
});
Prochaines Améliorations (Optionnel)
-
Factoriser TreeView:
FileExplorerComponent,TrashExplorerComponentet le child component partagent beaucoup de logique. Créer un composantGenericTreeViewréutilisable. -
Actions sur Trash: Ajouter boutons "Restore" / "Delete Permanently" dans le contexte menu.
-
Empty State amélioré: Ajouter une icône et un message plus descriptif quand .trash est vide.
-
Performance: Si
.trashcontient 1000+ fichiers, implémenter pagination lazy dans l'arbre.
Notes Techniques
- Signals Angular 20: VaultService utilise computed signals pour réactivité
- Path normalization: Tous les paths utilisent '/' même sur Windows
- Recursive folder counts:
calculateTrashFolderCounts()compte récursivement - Change detection: OnPush utilisé partout pour performance