feat: éditeur tableur — grille A → Z par blocs, barre de menus Sheets, panneau de couleurs, création .xlsx (#180 → #186)
CI / lint (push) Successful in 2m43s
CI / security (push) Successful in 1m33s
CI / test (push) Canceled after 0s
CI / build (push) Canceled after 0s
CI / e2e (push) Canceled after 0s

Restaure et termine le lot tableur resté non committé. Il n'existait que dans un
`git stash` (24 fichiers suivis) et en fichiers non suivis (menus.js, formula.js,
color-picker.js, tests, fiches) : la 2.53.3 livrée ne le contenait donc pas. Le
stash, créé avant le commit BUG-108, n'a jamais été restauré.

#180 Redimensionnement au curseur (en-tête de bord miroité + classe de repaint),
grille thémée sur les 15 thèmes et les modes contraste élevé / sépia, menu
Fichier au niveau des onglets, barre épinglée pleine largeur.

#181 Modèle de saisie Google Sheets : sélection ≠ édition (caret masqué sans
quitter contenteditable, double-clic / F2 / première frappe qui remplace,
Entrée contextuelle, Échap qui restaure) + inventaire priorisé des écarts.

#182 Désélection fiable (clic simple sans dépendre du focus), contours de plage
non empilés (sélecteur de classes sans point), couleurs texte/fond sur une
plage, clic droit qui préserve la sélection multiple.

#183 Panneau de couleurs façon Google Sheets : palette 8 × 10, STANDARD,
PERSONNALISÉ, coche selon la luminance, sortie `#rrggbb` (une valeur HSL était
rejetée par normHex).

#184 Peinture de format complète (toutes propriétés, source sans format =
réinitialisation), sélection multi-lignes/colonnes depuis les marges, grille
étendue : colonnes A → Z d'emblée, lignes ajoutées PAR BLOCS DE 100 au
défilement jusqu'à 1000 — matérialiser 1000 lignes d'un coup = ~26 000 cellules
câblées par feuille, ce qui épuisait le tas de la suite JSDOM ; index de
cellules `ref → td`, court-circuits formule/styles, marqueur data-wired.

#185 Barre de menus : les 10 menus Google Sheets (161 entrées, 125 câblées, 36
annoncées indisponibles), ruban façon Sheets, grille unie 1 px dérivée du thème.

#186 « Créer un fichier » propose .xlsx et construit un vrai classeur OPC
(openpyxl) au lieu d'une charge utile texte illisible.

Corrections trouvées en restaurant et en exerçant le lot :
- fuite mémoire : écouteur `click` anonyme posé sur #content-area à chaque
  rendu, jamais retiré — sa fermeture retenait la grille précédente en entier ;
- sorties Markdown / HTML / Imprimer de la barre de menus inertes
  (`data-xlsx-export` jamais réparti, seul `data-xlsx-action` l'était) ;
- collision de classe `.xlsx-structure-menu` entre la barre de menus et le menu
  Structure de la barre d'outils (toute requête tombait sur un nœud masqué) ;
- curseur col/row-resize absent quand le pointeur est sur la table elle-même ;
- l'export emportait les lignes et colonnes vides du quadrillage (CSV, Markdown,
  HTML, impression) ;
- clic extérieur avalé par la grâce de 250 ms du menu contextuel (destinée au
  seul appui long tactile) ;
- une entrée indisponible laissait la barre de menus ouverte.

Tests : pytest 1595 passés / 2 ignorés ; ruff et mypy 0 erreur ; bandit 0 ;
33 suites frontend vertes (xlsx-viewer 163/163, xlsx-menus 19/19,
xlsx-formula 14/14) ; E2E complet 132 passés / 12 ignorés ; E2E xlsx-viewer
19/19.
This commit is contained in:
2026-10-08 12:00:15 -04:00
parent ce1944d437
commit 634ba8a272
39 changed files with 9996 additions and 491 deletions
+227 -16
View File
@@ -1,6 +1,6 @@
# ObsiGate — Roadmap
> **Version :** 2.53.3 | **Dernière mise à jour :** 2026-10-07
> **Version :** 2.54.0 | **Dernière mise à jour :** 2026-10-08
> **Ce fichier ne contient que le travail à venir** (🔵 En cours + ⚪ Backlog) et un index compact
> vers les fonctionnalités livrées.
> - **Méthode de livraison à appliquer pour toute tâche : [DELIVERY_WORKFLOW.md](./DELIVERY_WORKFLOW.md)**
@@ -62,7 +62,7 @@
---
## 🔵 En cours — Visionneuse & édition Excel (P0/P1/P2)
## ✅ Terminé — Visionneuse & édition Excel (P0/P1/P2)
### 153. Visionneuse & édition XLSX — complétude (fidélité, recherche, IA, UX, formats)
@@ -112,7 +112,7 @@
---
## 🔵 En cours — Refonte UI/UX tableur (P2)
## ✅ Terminé — Refonte UI/UX tableur (P2)
### 154. Refonte UI/UX de la visionneuse & éditeur XLSX (ruban, grille, inspecteur)
@@ -139,7 +139,7 @@
---
## 🔵 En cours — Ergonomie tableur
## ✅ Terminé — Ergonomie tableur
### 155. Ergonomie tableur — menu contextuel & sélection type Excel
@@ -157,12 +157,12 @@
---
## 🔵 En cours — Polish menus tableur
## ✅ Terminé — Polish menus tableur
### 179. Éditeur tableur — icônes des menus & boutons, fermeture au focus, polish mobile
- **Effort :** 1-2 jours | **Impact :** 🟡
- **Statut :** 🔵 en cours depuis 2026-10-04
- **Statut :** ✅ **livré le 2026-10-04** (v2.53.0) — ouvert le 2026-10-04
- **Fiche :** [features/xlsx-menus-179.md](./features/xlsx-menus-179.md)
- **Description :** la grille (#155), les menus Structure/Mise en forme/Export
(#156-A8/A11/A14) et les boutons du ruban (#154) sont textuels et restent
@@ -181,33 +181,236 @@
---
## ✅ Terminé — Ergonomie & grille du tableur
### 186. Création d'un fichier Excel depuis « Créer un fichier »
- **Effort :** 0,5 jour | **Impact :** 🟢
- **Statut :** ✅ **livré le 2026-10-05** - ouvert le 2026-10-05
- **Fiche :** [features/create-file-xlsx-186.md](./features/create-file-xlsx-186.md)
- **Description :** l'éditeur Excel étant disponible, la modale « Créer un fichier » ne
proposait que des formats texte (`.md`, `.txt`, `.py`, `.js`, `.json`, `.yaml`, `.sh`,
`.ps1`) + Excalidraw : impossible de démarrer un classeur depuis l'UI. Il fallait
passer par l'assistant IA (`create_xlsx`) ou déposer un fichier existant.
- **Sous-tâches :**
- [x] **A1** Option **Excel (.xlsx)** dans la liste des types, et les 10 libellés du
`<select>` passés en i18n FR/EN (`modal.ext_*`) — ils étaient codés en dur
- [x] **A2** `create_file()` backend : un `.xlsx` est une archive OPC, pas du texte —
le classeur est **construit avec openpyxl** (une feuille `Feuille1`) au lieu
d'écrire la charge utile vide, sinon le fichier est illisible par la visionneuse
- [x] **A3** Tests : non-régression pytest (`test_api_main.py` — classeur relu par
openpyxl et servi en `is_xlsx`), E2E `xlsx-viewer.spec.js` (option présente,
création depuis le menu contextuel, ouverture dans la grille)
---
## ✅ Terminé — Assistant IA
### 187. Assistant IA — mode agent toujours actif, retrait du bouton toggle
- **Effort :** 0,5 jour | **Impact :** 🟢
- **Statut :** ✅ **livré le 2026-10-06** — ouvert le 2026-10-06
- **Statut :** ✅ **livré le 2026-10-07** (v2.53.2) — ouvert le 2026-10-06
- **Description :** le bouton « mode agent » du panneau (toggle persisté en
localStorage, défaut OFF) n'était plus protecteur : Deep Research et les
quick actions `agent: true` basculaient déjà le mode en silence. Retiré au
profit d'un agent toujours actif : toute requête texte part sur
`/api/ai/bookslm/agent` (outils lire/lister/chercher/modifier ; les mutations
gardent la confirmation two-step) ; les images seules restent sur
`/api/ai/bookslm/chat` (endpoint multimodal, la boucle agent étant textuelle).
quick actions `agent: true` basculaient déjà le mode en silence. Un
utilisateur pouvait donc voir l'assistant agir sans jamais avoir activé le
bouton. Retiré au profit d'un agent toujours actif : toute requête texte
part sur `/api/ai/bookslm/agent` (outils lire/lister/chercher/modifier ; les
mutations gardent la confirmation two-step) ; les images seules restent sur
`/api/ai/bookslm/chat` (endpoint multimodal, la boucle agent étant
textuelle).
- **Sous-tâches :**
- [x] **A1** Frontend : bouton header, `_agentMode`, toggle/persistance et les
auto-bascules (Deep Research, quick actions) supprimés ; `_postChat`
route texte→`/agent`, images→`/chat` ; aide et i18n FR/EN mises à jour
- [x] **A2** Optimisations requêtes AI : `/agent` résout le provider comme
`/chat` (avant : `req.provider` brut transmis au provider adapter →
moteur réel ≠ étiquette SSE) ; schémas d'outils mis en cache (~27 ms de
pydantic économisés par requête agent/MCP)
- [x] **A2** Optimisations requêtes AI : `/agent` résout désormais le
provider comme `/chat` (avant : `req.provider` brut transmis au
provider adapter → moteur réel ≠ étiquette SSE) ; schémas d'outils
mis en cache (~27 ms de pydantic économisés par requête agent/MCP)
- [x] **A3** Tests : `ai.test.mjs` adapté (100/100) ; non-régression pytest
(`test_bookslm.py` provider résolu, `test_tools.py` cache sûr) ;
ruff/mypy 0 erreur ; build + instance Docker locale à jour
---
## ✅ Terminé — Barre de menus & grille du tableur
### 185. Tableur — barre de menus Google Sheets (10 menus), ruban Sheets, grille unie
- **Effort :** 1-2 jours | **Impact :** 🟡
- **Statut :** ✅ **livré le 2026-10-08** (v2.54.0) — ouvert le 2026-10-05
- **Fiche :** [features/xlsx-menus-185.md](./features/xlsx-menus-185.md)
- **Description :** l'éditeur n'avait **aucune barre de menus** (ni Fichier, ni
Modifier, ni Affichage, ni Insertion, ni Format, ni Données, ni Outils, ni
Gemini, ni Extensions, ni Aide) : beaucoup de fonctions n'étaient atteignables
que par clic droit. Le ruban gardait un chromer bordersé qui ne ressemblait à
rien et la grille n'était bordée qu'en bas avec une couleur quasi identique au
fond des cellules — le quadrillage se lisait comme une tache.
- **Sous-tâches :**
- [x] **A1** `frontend/js/xlsx/menus.js` : les **dix menus de Google Sheets**,
dans l'ordre et avec les libellés exacts (161 entrées) ; sections en
accordéon ; le menu **Fichier** quitte la barre d'onglets pour la barre de
menus en **conservant ses identifiants**, seul *Enregistrer* reste
épinglé
- [x] **A2** **Majorité des fonctions câblées** : Partager, Renommer,
Corbeille, Historique, Détails ; Annuler/Rétablir/Couper/Copier/Coller,
**Collage spécial (valeurs)**, Supprimer, Tout sélectionner,
Rechercher-et-remplacer ; Figer, Afficher (barre de formule / grille /
en-têtes / tableau de bord), Zoom, Plein écran ; Lignes / Colonnes /
Cellules, Lien, Commentaire, Fonction ; Nombre, Thème, B/I/U/S, Taille,
Alignement, Retour ligne, Rotation, **Couleurs alternées**, Effacer ;
Trier, **Filtre**, Plages nommées, **Nettoyage (doublons / espaces)**,
**Diviser le texte en colonnes** ; Autocomplétion, Accessibilité ;
Gemini ; Aide, Mises à jour, Raccourcis, Signalement. Les 36 options
absentes d'ObsiGate **sont listées et le disent** au clic
- [x] **A3** **Ruban façon Sheets** : boutons plats 30 × 30 sans chromer,
survol discret, groupes par filets ; nouveau bouton grille piloté par le
menu Affichage
- [x] **A4** **Grille unie et visible** : 1 px **sur les quatre côtés** de
chaque cellule (en-têtes compris) et un seul `--grid-border` dérivé du
thème (`color-mix` texte → surface) au lieu de `--border` invisible
- [x] Tests JSDOM (`xlsx-menus` + `xlsx-viewer`), E2E `xlsx-viewer.spec.js`,
i18n FR/EN (134 clés `xlsx.m*` / `xlsx.mi_*`)
---
### 184. Tableur — peinture de format, multi-lignes/colonnes, grille A→Z × 1000
- **Effort :** 1 jour | **Impact :** 🟡
- **Statut :** ✅ **livré le 2026-10-08** (v2.54.0) — ouvert le 2026-10-05
- **Fiche :** [features/xlsx-sheet-input-181.md](./features/xlsx-sheet-input-181.md) (§8)
- **Description :** « Peindre le format » échouait quand la source n'avait pas de
format propre ; il manquait la sélection de plusieurs lignes/colonnes depuis
les marges ; la grille s'arrêtait aux dimensions réelles du fichier au lieu
d'aller jusqu'à A → Z et 1000 lignes.
- **Sous-tâches :**
- [x] **A1** Peinture de format **complète** (toutes propriétés) + source sans
format ⇒ **réinitialisation** de la cible ; fuite du handler annulé
- [x] **A2** Sélection multi-lignes / multi-colonnes par glissement sur les
marges et `Maj`+clic ; le geste de redimensionnement garde la priorité
- [x] **A3** Grille étendue à **A → Z × 1000 lignes**, cellules vides
éditables, padding à l'activation de l'onglet, pas de doublons
- [x] **A4** Performance : index de cellules `findTd`, court-circuits
formule/styles, marqueur `data-wired`
---
## ✅ Terminé — Panneau de couleurs du tableur
### 183. Panneau de sélection de couleurs façon Google Sheets (texte et fond)
- **Effort :** 0,5-1 jour | **Impact :** 🟡
- **Statut :** ✅ **livré le 2026-10-08** (v2.54.0) — ouvert le 2026-10-05
- **Fiche :** [features/xlsx-sheet-input-181.md](./features/xlsx-sheet-input-181.md) (§7)
- **Description :** le sélecteur natif `<input type="color">` du ruban et du menu
Mise en forme est remplacé par un panneau conforme aux maquettes : *Réinitialiser*,
palette 8 × 10, STANDARD, PERSONNALISÉ, pied de page. Un clic sur une pastille
referme le panneau et applique la couleur.
- **Sous-tâches :**
- [x] **A1** Module `frontend/js/xlsx/color-picker.js` : palette 8 × 10
(8 gris puis 8 teintes × 9 nuances), **sortie en `#rrggbb`**
- [x] **A2** Coche de sélection blanche/noire selon la luminance
- [x] **A3** Câblage ruban + menu Mise en forme, fermeture au clic, application
sur cellule **ou plage**, réinitialisation, « + » / crayons vers le
sélecteur natif
- [x] **A4** Chrome du panneau thémé (variables CSS), i18n FR/EN (21 clés),
pied de page honnête (message explicite pour les fonctions absentes)
---
## ✅ Terminé — Correctifs éditeur tableur
### 182. Tableur — désélection fiable & couleurs sur une plage
- **Effort :** 0,5 jour | **Impact :** 🟡
- **Statut :** ✅ **livré le 2026-10-08** (v2.54.0) — ouvert le 2026-10-05
- **Fiche :** [features/xlsx-sheet-input-181.md](./features/xlsx-sheet-input-181.md) (§6)
- **Description :** suite de #181 — la sélection multiple se dessinait mais ne
s'effaçait plus, et l'application d'une couleur de texte / de fond sur une
plage paraissait inerte.
- **Sous-tâches :**
- [x] **A1** Le clic simple efface toujours la plage, sans dépendre de
l'événement `focus` (cause : `Maj`+clic + `preventDefault()` figeait le
focus, donc aucun `focus` ne partait au clic suivant)
- [x] **A2** Après `Maj`+clic, le focus suit la cellule cliquée ; la zone Nom
affiche la plage après un glissement
- [x] **A3** Couleurs de texte et de fond vérifiées sur les 3 chemins
(menu Mise en forme, nuanciers du ruban, `Maj`+flèches et glissement)
- [x] **A4** Pastille de couleur sur les nuanciers du ruban (retour visuel)
- [x] **A5** **Contours de plage qui s'empilaient** : le sélecteur de
nettoyage oubliait le `.` des classes (`querySelectorAll("xlsx-sel-top")`
cherche une balise) — rien n'était effacé, les encadrés restaient et
s'ajoutaient à chaque changement de cellule. Même famille de faute sur
les en-têtes reflétés
- [x] **A6** Pendant la saisie, les flèches **valident et déplacent** la
sélection (au lieu de déplacer le curseur), comme Google Sheets ;
`Alt`+flèche garde le saut de ligne
- [x] Tests JSDOM `xlsx-viewer` **152/152** (+6), suites frontend vertes
---
## ✅ Terminé — Polish éditeur tableur (mise en page & thèmes)
### 181. Éditeur tableur — modèle de saisie Google Sheets (sélection ≠ édition) & écarts fonctionnels
- **Effort :** 1 jour (A1-A3) + inventaire des écarts (A4) | **Impact :** 🟡
- **Statut :** ✅ **livré le 2026-10-08** (v2.54.0) — ouvert le 2026-10-05
- **Fiche :** [features/xlsx-sheet-input-181.md](./features/xlsx-sheet-input-181.md)
- **Description :** l'éditeur ne distingue pas **sélectionner** une cellule et
**l'éditer** : le curseur de texte est visible en permanence, `Entrée` valide
puis perd le focus, et l'indicateur de plage est discret. Aligner le modèle de
saisie sur Google Sheets / Excel (A1-A3) et **inventorier** précisément ce qui
manque encore face à un tableur de référence (A4) — le rapprochement exhaustif
n'est pas réalisable en une tranche.
- **Sous-tâches :**
- [x] **A1** Deux états distincts : *sélection* (clic / flèches, pas de
curseur via `caret-color: transparent`, contour visible) et *édition*
(double-clic en place, première frappe qui **remplace**, `F2`,
`Alt`+flèche pour un saut de ligne, `Échap` qui restaure)
- [x] **A2** Sélection multiple : glisser, `Maj`+clic, `Maj`+flèches, avec
contour de plage (`.xlsx-sel-*` sur les 4 bords réels) + en-têtes
`A`/`B`… et `1`/`2`… reflétés
- [x] **A3** `Entrée` contextuelle : en édition → valide et passe **à la
cellule du dessous** ; en sélection → bascule en **mode édition**
- [x] **A4** Inventaire des écarts vs Google Sheets / Excel et priorisation
(P1 poignée de recopie / remplacer / validation de données / filtre
auto / tri multi-critères ; P2 mise en forme conditionnelle / création
de graphiques / TCD éditables / protection ; P3 analyse de données,
historique, macros) — voir [fiche](./features/xlsx-sheet-input-181.md)
- [x] Tests JSDOM (`xlsx-viewer` **146/146**, +10 cas #181), suites frontend
vertes, build + déploiement de l'instance Docker locale
---
### 180. Éditeur tableur — redimensionnement au curseur, grille thémée, menu Fichier & barre épinglée
- **Effort :** 1-2 jours | **Impact :** 🟡
- **Statut :** ✅ **livré le 2026-10-08** (v2.54.0) — ouvert le 2026-10-05
- **Fiche :** [features/xlsx-sheetbar-180.md](./features/xlsx-sheetbar-180.md)
- **Description :** retours utilisateur après #179 — (1) le redimensionnement des
colonnes/lignes par les marges (`A, B, C…` / `1, 2, 3…`) doit afficher un
curseur iconique (`col-resize` / `row-resize`) quand le pointeur est sur le
bord ; (2) la grille doit suivre le thème de l'utilisateur (15 thèmes ×
4 modes + importés : tokens dérivés, plus de fond figé) ; (3) regrouper
Télécharger / CSV / Exporter dans un **menu Fichier** en haut à droite, au
niveau des onglets de feuilles, avec **Enregistrer** juste à côté ;
(4) retirer l'indicateur « Formules calculées localement » ; (5) épingler la
barre de boutons en haut, au bord de la marge, et étendre l'éditeur à la
largeur de la page.
- **Sous-tâches :**
- [x] **A1** Curseur de redimensionnement sur les marges d'en-têtes
(en-tête de bord miroité en ligne + classe de repaint `.xlsx-resize-col/row`)
- [x] **A2** Grille compatible tous thèmes (`--grid-*` dérivés dans
`themes.js`, replis CSS, modes contraste élevé / sépia, menu Export sur `--surface`)
- [x] **A3** Menu Fichier + Enregistrer au niveau des onglets (`.xlsx-sheetbar`,
identifiants des contrôles conservés)
- [x] **A4** Retrait de l'indicateur de formules + barre épinglée pleine largeur
(`position: sticky`, `:has(.xlsx-viewer)` en plein cadre)
- [x] Tests JSDOM (`xlsx-viewer` 136/136, `xlsx-menus` 12/12), E2E `xlsx-viewer.spec.js`,
i18n FR/EN, 8 tests réalignés sur l'application locale des écritures
---
## ✅ Terminé — Navigation
### 158. Navigation — vue répertoire en onglet, filtres & tris, retour Home complet
@@ -475,6 +678,14 @@
| 154 | Tableur — Refonte UI/UX (ruban groupé, onglets permanents, badges d'état, inspecteur droit, undo/redo) | 2.40.0→2.43.1 | [features/xlsx-ui-redesign.md](./features/xlsx-ui-redesign.md) |
| 155 | Tableur — Menu contextuel (clic droit / appui long) & sélection type Excel | 2.44.0 | [features/xlsx-context-menu.md](./features/xlsx-context-menu.md) |
| 156 | Tableur — Complétude éditeur : presse-papiers/clavier (A5-A7), mise en forme (A8), décision calcul (A9), undo unifié (A10), export + recherche multi-feuilles (A11), concurrence optimiste (A12), cache méta (A13), outils IA `.xlsm`/`.csv` (A14) + BUG-096 → BUG-099 | 2.45.0 | [features/xlsx-editor-completeness.md](./features/xlsx-editor-completeness.md) |
| 179 | Tableur — icônes des menus & boutons, fermeture au focus, polish mobile | 2.53.0 | [features/xlsx-menus-179.md](./features/xlsx-menus-179.md) |
| 180 | Tableur — redimensionnement au curseur, grille thémée, menu Fichier, barre épinglée | 2.54.0 | [features/xlsx-sheetbar-180.md](./features/xlsx-sheetbar-180.md) |
| 181 | Tableur — modèle de saisie Google Sheets (sélection ≠ édition) & inventaire des écarts | 2.54.0 | [features/xlsx-sheet-input-181.md](./features/xlsx-sheet-input-181.md) |
| 182 | Tableur — désélection fiable, contours non empilés, couleurs sur une plage | 2.54.0 | [features/xlsx-sheet-input-181.md](./features/xlsx-sheet-input-181.md) |
| 183 | Tableur — panneau de couleurs façon Google Sheets (texte et fond) | 2.54.0 | [features/xlsx-sheet-input-181.md](./features/xlsx-sheet-input-181.md) |
| 184 | Tableur — peinture de format complète, multi-lignes/colonnes, grille A → Z × 1000 (croissance par blocs) | 2.54.0 | [features/xlsx-sheet-input-181.md](./features/xlsx-sheet-input-181.md) |
| 185 | Tableur — barre de menus Google Sheets (10 menus), ruban Sheets, grille unie | 2.54.0 | [features/xlsx-menus-185.md](./features/xlsx-menus-185.md) |
| 186 | Création d'un fichier Excel (`.xlsx`) depuis la modale « Créer un fichier » | 2.54.0 | [features/create-file-xlsx-186.md](./features/create-file-xlsx-186.md) |
| 159 | Desktop — gestion des vaults & dossiers : retrait par menu contextuel + section Configuration (ajout vault/dossier racine) | 2.50.0 | [features/desktop-tauri.md](./features/desktop-tauri.md) |
| 160 | Desktop — premier lancement professionnel (répertoire `%USERPROFILE%\ObsiGate` + `Prise en main.md`) et section Configuration harmonisée | 2.51.0 | [features/desktop-tauri.md](./features/desktop-tauri.md) |
| BUG-047 | Versionnage — source unique `VERSION` + bump SemVer automatique au commit (hooks + tag) | 2.3.0 | [DEVELOPMENT_AND_RELEASES.md](./DEVELOPMENT_AND_RELEASES.md) |