- clic sur le titre: la page d'accueil s'ouvre dans un onglet Accueil (icone Maison) epingle en tete de barre, reactivable d'un clic (onglet propre au panneau actif en split) - page de navigation: menus contextuels des repertoires et des fichiers identiques a ceux de la sidebar, clic sur la racine d'un vault qui ouvre la vue, icone dossier a la couleur de l'arbre de navigation - BUG-101: bloc « Keyboard shortcuts for tabs » duplique dans ui.js (un seul Ctrl+W fermait deux onglets) - BUG-102: le menu contextuel se refermait 10 ms apres son ouverture (scroll de reflow des icones lucide)
73 lines
4.4 KiB
Markdown
73 lines
4.4 KiB
Markdown
# #158 — Navigation : vue répertoire en onglet, filtres & tris, retour Home complet
|
|
|
|
> **Statut :** livré le 2026-10-02 · **ID :** `#158` (correctif associé : `BUG-100`)
|
|
> **Fichiers :** `frontend/js/vaulthome.js`, `frontend/js/ui.js`, `frontend/js/sidebar.js`,
|
|
> `frontend/js/navfacets.js` (nouveau), `frontend/js/viewer.js`, `frontend/js/legacy.js`,
|
|
> `backend/services/vaults.py`, `backend/schemas.py`, `frontend/style.css`,
|
|
> `frontend/locales/{fr,en}.json`
|
|
|
|
## Problème
|
|
|
|
La vue « chemin + Récents + fichiers du répertoire » (vault home) ne s'affichait qu'en mode
|
|
focus vault, disparaissait dès qu'un fichier était ouvert (aucun onglet), ne listait pas les
|
|
sous-répertoires, n'avait ni filtre ni tri, et le clic sur le titre ne rendait pas la vraie
|
|
page d'accueil.
|
|
|
|
## Conception
|
|
|
|
**Un onglet de navigation par vault.** `TabManager.openNav(vault, dir)` (`frontend/js/ui.js`)
|
|
crée/rétarget l'onglet `nav::<vault>` (icône dossier) ; `TabManager.activate()` branche sur
|
|
`cache.nav` et rend `showVaultHome(vault, dir)` au lieu de fetcher un fichier. Les onglets de
|
|
fichiers ne sont jamais fermés. Le dashboard appelle `TabManager.deactivate()` : aucun onglet
|
|
ne reste « actif », donc un clic suivant ré-éffectue réellement l'onglet (avant : early-return
|
|
et vue figée).
|
|
|
|
Points d'entrée des clics (`frontend/js/sidebar.js`) : clic **répertoire** dans l'arbre (2 sites,
|
|
mode focus et mode All), clic sur la **racine d'un vault** (2 sites, expansion + navigation),
|
|
changement de contexte vault (sélecteur), facettes/filtres et fil d'Ariane de la vue
|
|
(`vaulthome.js` route tout par `openNav`, plus aucune délégation sur l'arbre).
|
|
|
|
**Menus contextuels** : les répertoires et les fichiers de la vue appellent le même
|
|
`ContextMenuManager.show()` que la sidebar, avec `stopPropagation()` — le handler global de
|
|
`ContextMenuManager` referme le menu sur tout clic droit hors `.tree-item`.
|
|
|
|
**Onglet Accueil** (`ui.js::openHome` + `pane-manager.js::openHome`) : le clic sur le titre
|
|
crée (ou remonte en position 0) l'onglet `home` — icône Maison, libellé i18n `common.home` —
|
|
et l'active ; `activate()` rend la page d'accueil via `showWelcome()` et `deactivate()`
|
|
conserve l'onglet Accueil actif (il *est* la page d'accueil). En mode split, l'onglet vit dans
|
|
le panneau actif (délégation `getActiveTabManager()`, libellé transmis par l'appelant pour ne
|
|
pas d'importer `t` dans `pane-manager.js`, qui déclare déjà des variables locales `t`).
|
|
|
|
**Contenu de la vue** (`vaulthome.js`) : fil d'Ariane · barre **Pertinence / Date** + **Sauver**
|
|
· panneau de facettes · **Répertoires** cliquables (`GET /api/browse`) · Récents (racine) ·
|
|
fichiers (`GET /api/vault/{v}/files?recursive=false`). Les facettes réutilisent les classes de
|
|
la page de recherche (`search-facets`, `search-sort`, `search-save-btn`) — même visuel, même
|
|
repli `obsigate_facets_collapsed`, filtrage **local** (pas de nouvelle requête).
|
|
|
|
**Facettes** (`frontend/js/navfacets.js`, pur, sans DOM) : `buildNavFacets`,
|
|
`filterNavFiles`, `sortNavFiles`. Le listing embarque les tags indexés :
|
|
`GET /api/vault/{v}/files` renvoie `tags` (`_indexed_tags()` dans
|
|
`backend/services/vaults.py`, lookup `vault::path` dans l'index inversé, `[]` si non indexé).
|
|
|
|
## Décisions / limites connues
|
|
|
|
- **Un seul onglet de navigation par vault** : cliquer un autre répertoire re-cible le même
|
|
onglet (pas d'empilement d'onglets). En mode split, la vue s'affiche dans la zone principale.
|
|
- **« Pertinence » = tri alphabétique** (`ponytail:` commenté) : un listing de répertoire n'a
|
|
aucun signal de pertinence tant que la vue n'a pas sa propre requête — voir
|
|
`navfacets.js::sortNavFiles`.
|
|
- Facettes calculées sur la liste courante (répertoire non récursif, 200 fichiers max) : les
|
|
sous-répertoires non listés n'apportent aucune compte.
|
|
|
|
## Tests
|
|
|
|
- `tests/test_nav_files.py` (3) : `tags` exposés + survivent au `response_model`, tags en
|
|
sous-répertoire, miss d'index → `[]`.
|
|
- `tests/frontend/navfacets.test.mjs` (10) : comptages, filtres tag/ext (insensible au point),
|
|
combinaison ET, tris, non-mutation.
|
|
- `tests/frontend/unit.test.mjs` : `navfacets.js` ajouté à la liste des modules purs.
|
|
- `tests/e2e/nav-tab.spec.js` (4) : racine vault → page de navigation, icône + menus
|
|
contextuels identiques à la sidebar, onglet Accueil en tête de barre (avec `#quick-help`).
|
|
- Vérification manuelle Playwright (jetable) : 22/22 puis 16/16 checks sur les lots A1-A3 et
|
|
A4-A6.
|