136 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
			
		
		
	
	
			136 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
| # 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.
 | |
| 
 | |
| ```typescript
 | |
| // 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é.
 | |
| 
 | |
| ```typescript
 | |
| // 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é
 | |
| 
 | |
| 1. **Utilisateur clique sur un dossier dans Trash** (ex: `.trash/old-folder`)
 | |
| 2. `TrashExplorerComponent.onFolderClick()` est appelé
 | |
| 3. Le dossier est toggle ouvert/fermé via `vault.toggleFolder()`
 | |
| 4. L'événement `folderSelected` est émis avec le path `.trash/old-folder`
 | |
| 5. `NimbusSidebarComponent` propage l'événement vers `AppShellNimbusComponent`
 | |
| 6. `AppShellNimbusComponent.onFolderSelected()` définit `this.folderFilter = '.trash/old-folder'`
 | |
| 7. `NotesListComponent` reçoit `folderFilter` en input
 | |
| 8. Le computed `filtered()` filtre les notes où `originalPath` commence par `.trash/old-folder`
 | |
| 9. 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()`
 | |
| - ✅ `.trash` est exclu de la section Folders via `sortAndCleanFolderChildren()`
 | |
| 
 | |
| ### NotesListComponent - Filtrage
 | |
| - ✅ Le filtre `folderFilter` fonctionne avec les chemins trash
 | |
| - ✅ Compare `originalPath` avec le folder passé (égalité ou startsWith)
 | |
| - ✅ Compatible avec les chemins `.trash/subfolder`
 | |
| 
 | |
| ### Backend API
 | |
| - ✅ `/api/vault` charge tous les fichiers .md y compris `.trash`
 | |
| - ✅ Les `filePath` sont relatifs au vault: `.trash/old-folder/note.md`
 | |
| - ✅ Les `originalPath` sont sans extension: `.trash/old-folder/note`
 | |
| 
 | |
| ## Fichiers Modifiés
 | |
| 
 | |
| 1. **src/app/features/sidebar/nimbus-sidebar.component.ts**
 | |
|    - Retrait émission incorrecte au click accordion Trash
 | |
| 
 | |
| 2. **src/app/layout/sidebar/trash/trash-explorer.component.ts**
 | |
|    - Ajout émission `folderSelected` au click sur dossier
 | |
| 
 | |
| 3. **.env**
 | |
|    - VAULT_PATH pointant vers `./vault` pour tests
 | |
| 
 | |
| 4. **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 ✅
 | |
| 
 | |
| - [x] La section Trash affiche l'arborescence réelle du dossier `.trash`
 | |
| - [x] Cliquer un dossier dans Trash charge ses fichiers dans Notes-liste
 | |
| - [x] Les badges affichent le nombre correct de notes (récursif)
 | |
| - [x] `.trash` n'apparaît pas dans la section Folders
 | |
| - [x] États hover/sélection cohérents avec autres sections
 | |
| - [x] Dark mode compatible (styles existants)
 | |
| - [x] Cas vide géré avec empty-state "La corbeille est vide"
 | |
| 
 | |
| ## Tests Suggérés
 | |
| 
 | |
| ### Manuel
 | |
| 1. Démarrer `node server/index.mjs` et `npm run dev`
 | |
| 2. Ouvrir Sidebar → Trash
 | |
| 3. Vérifier que "old-folder" et "archive" s'affichent
 | |
| 4. Cliquer "old-folder" → Notes-liste doit montrer 2 notes
 | |
| 5. Vérifier badges: "old-folder (2)", "archive (1)"
 | |
| 6. Vérifier que `.trash` n'apparaît pas dans Folders
 | |
| 
 | |
| ### E2E (à créer)
 | |
| ```typescript
 | |
| 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)
 | |
| 
 | |
| 1. **Factoriser TreeView**: `FileExplorerComponent`, `TrashExplorerComponent` et le child component partagent beaucoup de logique. Créer un composant `GenericTreeView` réutilisable.
 | |
| 
 | |
| 2. **Actions sur Trash**: Ajouter boutons "Restore" / "Delete Permanently" dans le contexte menu.
 | |
| 
 | |
| 3. **Empty State amélioré**: Ajouter une icône et un message plus descriptif quand .trash est vide.
 | |
| 
 | |
| 4. **Performance**: Si `.trash` contient 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
 |