Files
ObsiGate/docs/features/xlsx-menus-185.md
T
bruno 634ba8a272
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
feat: éditeur tableur — grille A → Z par blocs, barre de menus Sheets, panneau de couleurs, création .xlsx (#180 → #186)
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.
2026-10-08 12:00:15 -04:00

6.9 KiB
Raw Blame History

#185 — Tableur : barre de menus Google Sheets, boutons façon Sheets, grille unie

Statut : ✅ livré le 2026-10-08 (v2.54.0) — ouvert le 2026-10-05 | Effort : 1-2 jours | Impact : 🟡 Références : Roadmap · Changelog · #154 · #179 · #180 · #183)

1. Constat

L'éditeur tableur avait un ruban de boutons et trois menus (Structure, Mise en forme, Export) mais 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 existentes n'étaient atteignables que par un clic droit ou par un bouton à connaître. Le ruban lui-même gardait un chromer bordersé qui ne ressemblait à rien, et la grille n'était bordée qu'en bas avec une couleur (--border) quasi identique au fond des cellules : le quadillage se lisait comme une tache, pas comme une grille.

2. Livré

A1 — Barre de menus (les 10 menus de Google Sheets)

frontend/js/xlsx/menus.js (nouveau) décrit les dix menus, dans l'ordre et avec les libellés exacts de Google Sheets (Fichier · Modifier · Affichage · Insertion · Format · Données · Outils · Gemini · Extensions · Aide), puis buildMenuBar() produit la barre et ses dix menus déroulants. 161 entrées, dont 125 wirables (67 actions distinctes) et 36 honestement déclarées indisponibles (elles s'affichent mais répondent « « X » n'est pas disponible dans ObsiGate »** — jamais un clic muet). Les sections imbriquées (Nombre, Thème, Alignement, Zoom, Nettoyage…) sont des accordéons comme dans Sheets : une seule ouverte à la fois par niveau.

Le menu Fichier a quitté la barre d'onglets pour la barre de menus, en conservant ses identifiants (#xlsx-file-btn, #xlsx-file-menu, #xlsx-download-btn, #xlsx-csv-btn, [data-xlsx-export]). Seul Enregistrer reste épinglé à droite de la barre d'onglets.

A2 — Fonctions réellement câblées

  • Fichier : Partager, Télécharger (original · CSV · Markdown · HTML), Imprimer, Renommer (PATCH /api/file/{vault}), Corbeille (DELETE /api/file/{vault}), Historique des versions (visionneuse de sauvegardes), Détails (vault, chemin, feuilles, cellules, révision, · modifications en attente via /api/health pour le numéro de version).
  • Modifier : Annuler, Rétablir, Couper, Copier, Coller, Collage spécial → valeurs uniquement (les formules sont évaluées puis collées comme texte), Supprimer → lignes / colonnes / contenu, Tout sélectionner, Rechercher et remplacer (toutes les feuilles).
  • Affichage : Figer (ici / ligne / colonne / libérer), Afficher → barre de formule · grille · en-têtes · tableau de bord, Grouper (déclaré), Feuilles masquées (déclaré), Zoom (50 → 200 %, même état que le ruban), Plein écran.
  • Insertion : Lignes (au-dessus / en dessous), Colonnes (à gauche / à droite), Cellules, Lien, Commentaire, Fonction (insère l'appel et place le curseur entre les parenthèses).
  • Format : Nombre (6 formats), Thème (liste des 15 thèmes construite à la demande), Gras / Italique / Souligné / Barré, Taille de police, Alignement (horizontal + vertical), Retour à la ligne, Rotation, Couleurs alternées (une écriture par ligne, lots de 50 — plafond du backend), Effacer la mise en forme.
  • Données : Trier la plage (croissant / décroissant / réinitialiser), Créer un filtre (sur la valeur de la cellule active), Plages nommées (panneau du tableau de bord), Nettoyage → supprimer les doublons ·trimmer, Diviser le texte en colonnes.
  • Outils : Saisie semi-automatique (bascule la liste de fonctions de la barre de formule), Accessibilité (cellules plus grandes, grille plus contrastée).
  • Gemini : les six entrées ouvrent le panneau de l'assistant IA.
  • Aide : aide intégrée, Mises à jour (version), Raccourcis clavier (liste), Signaler un problème (diagnostic copié dans le presse-papiers).

A3 — Ruban façon Google Sheets

Boutons plats : 30 × 30, sans bordure ni fond au repos, survol discret, état actif teinté, groupes séparés par des filets verticaux. Les sélecteurs (zoom, format de nombre, taille de police) suivent le même traitement. Enregistrer reste le seul pilier plein. Nouveau bouton grille (#xs-grid), piloté par le menu Affichage et inversement.

A4 — Grille unie et visible

  • Chaque cellule est encadrée sur les quatre côtés par la même ligne 1 px (les en-têtes compris : ils se distinguent par leur fond, plus par une bordure plus lourde).
  • --grid-border n'est plus --border (1-2 % d'écart avec le fond sur la plupart des thèmes) mais un color-mix du texte vers la surface calculé par themes.js : une seule valeur pour toute la grille, lisible en sombre comme en clair et dans les modes générés (contraste élevé, sépia).
  • Les valeurs de repli des 4 blocs :root ont été remontées en contraste.

3. Tests

  • tests/frontend/xlsx-menus.test.mjs : i18n amorcé, barre de menus (10 libellés, un déroulant par bouton, accordéon), ** exhaustivité des actions déclarées**, disparition des entrées d'édition en lecture seule, absence de HTML dans les libellés, ids historiques du menu Fichier ; ruban (save, « + », grille).
  • tests/frontend/xlsx-viewer.test.mjs : barre présente au-dessus du ruban, entrée indisponible qui répond (et n'envoie rien), bascules Affichage, Zoom, écriture de structure (Insertion), écriture de style (Format ▸ Nombre), Couleurs alternées (3 lignes → 3 ops), Accessibilité, Raccourcis clavier, classeur en lecture seule, jeton --grid-border.
  • tests/e2e/xlsx-viewer.spec.js : les 10 menus dans le bon ordre et au-dessus du ruban, accordéon Format ▸ Nombre, option indisponible, grille 1 px sur les 4 côtés puis masquée à 0 px.

4. Limites assumées

  • Les 36 options Google Sheets qu'ObsiGate n'implémente pas (macros, Apps Script, TCD, graphiques, formulaires,/modules, AppSheet, Looker Studio, training…) sont listées pour rester fidèle à la demande, et annoncées comme indisponibles au clic. Elles ne sont pas masquées : la parité visuelle prime, l'honnêteté prime sur le silence.
  • Déplacer lignes/colonnes est déclaré indisponible : leivinguer (supprimer + insérer + réécrire) sur un classeur avec fusions, styles et formules n'est pas sûr en un seul geste.
  • Le menu Thème est construit à la demande (import dynamique de themes.js) : 15 entrées, pas de coût au rendu.
  • Les couleurs de la grille sont dérivées via color-mix : un moteur qui ne le supporte pas retombe sur --grid-border (feuille de style).