ObsiViewer/docs/TRASH_FIX_SUMMARY.md

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