diff --git a/CHANGELOG.md b/CHANGELOG.md index 3c76805..2dcf99b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,7 @@ Format basé sur [Keep a Changelog](https://keepachangelog.com/fr/1.1.0/), et [Semantic Versioning](https://semver.org/spec/v2.0.0.html). > **En cours de développement** : les changements à venir sont listés dans la section -> [Unreleased](#unreleased). La dernière version livrée est **2.39.0**. +> [Unreleased](#unreleased). La dernière version livrée est **2.39.1**. --- @@ -14,6 +14,51 @@ et [Semantic Versioning](https://semver.org/spec/v2.0.0.html). --- +## [2.39.1] — 2026-09-28 + +### Ajouté + +- **#153 A6 — l'assistant IA sait lire et modifier les classeurs existants.** + Quatre nouveaux outils dans `backend/tools/spreadsheets.py` : + `list_xlsx_sheets` (noms de feuilles + dimensions), `xlsx_to_markdown` + (tableau plafonné injecté au contexte du modèle), `update_xlsx_cells` + (édition par lots passant par le service gardé) et `append_xlsx_rows` + (ajout de lignes en fin de feuille). Les mutations demandent confirmation + et rafraîchissent la visionneuse (`obsigate:file-written`). +- **#153 A7 — navigation clavier et barre de formule dans la visionneuse.** + `Tab`/`Maj+Tab` circulent entre les cellules, flèches et `Entrée`/ + `Maj+Entrée` (multiligne) fonctionnent comme dans un tableur, la cellule + active est nommée en A1 dans la barre de formule, une plage se copie, + et le focus reste visible et tactile (≥ 44 px, couvert par les E2E mobiles). +- **#153 A13 — tri, filtre, recherche et export CSV dans la feuille.** + Tri ascendant/descendant par colonne, filtre de lignes, recherche + suivant/précédent (respect de casse optionnel) et export CSV de la feuille : + toutes des opérations d'**affichage**, le classeur n'est jamais réécrit. +- **#153 A14 — structure du classeur éditable depuis la visionneuse.** + Ajout, renommage, duplication et suppression de feuilles ; insertion et + suppression de lignes/colonnes autour de la cellule active, via le menu + Structure et `PUT /api/file/{vault}/xlsx/structure` — mêmes garde-fous + (backup atomique, verrou, confirmation) que l'édition de cellules. +- **#153 A15 — styles, fusions et volets figés affichés fidèlement.** + La lecture rend les couleurs de police et de fond, le gras/italique/ + souligné, les alignements, les plages fusionnées et l'ancre des volets + figés ; un format de nombre personnalisé est signalé par une police à + chasse fixe. Une seule charge du classeur (mode normal) suffit pour toutes + les feuilles, y compris celles rendues par fenêtres. +- **#153 A16 — formats tableur additionnels.** `.xlsm` éditable avec + **macros préservées** (`keep_vba`), `.xls` et `.ods` en **lecture seule** + (xlrd / odfpy), `.csv` édité comme un tableur et réécrit au format + RFC 4180 (`PUT …/csv/save`). Dépendances : `xlrd==2.0.2`, + `odfpy==1.4.1` dans `backend/requirements.txt`. +- **#153 A17 — tableau de bord du classeur.** Un panneau de la visionneuse + liste les plages nommées (portée classeur ou feuille), signale la présence + de graphiques et de tableaux croisés (analyse des parties OPC, sans + recharger le fichier), donne les statistiques par feuille (cellules, + lignes, colonnes, formules, valeurs numériques) et huit KPI extraits de la + première zone de données — endpoint `GET /api/file/{vault}/xlsx/dashboard`. + +--- + ## [2.39.0] — 2026-09-28 --- diff --git a/README.fr.md b/README.fr.md index 6858e93..567bb56 100644 --- a/README.fr.md +++ b/README.fr.md @@ -4,7 +4,7 @@ **Porte d'entrée web ultra-léger pour vos vaults Obsidian** — Accédez, naviguez et recherchez dans toutes vos notes Obsidian depuis n'importe quel appareil via une interface web moderne et responsive. -[![Version](https://img.shields.io/badge/Version-2.39.0-blue.svg)]() +[![Version](https://img.shields.io/badge/Version-2.39.1-blue.svg)]() [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) [![Docker](https://img.shields.io/badge/Docker-Ready-blue.svg)](https://www.docker.com/) [![Python](https://img.shields.io/badge/Python-3.11+-green.svg)](https://www.python.org/) @@ -85,7 +85,7 @@ Les **guides d'utilisation** pas à pas se trouvent dans [`docs/GUIDES/`](docs/G - **🖼️ Images Obsidian** : Support complet des syntaxes d'images Obsidian avec résolution intelligente - **🎬 Audio & vidéo** : Lecteurs HTML5 intégrés (`.mp3 .wav .flac .mp4 .webm`…) avec streaming HTTP Range (lecture, déplacement, plein écran) et **lecture persistante** (mini-lecteur flottant / mini-fenêtre vidéo, retour au média ou arrêt à tout moment, contrôles écran verrouillé via Media Session), repli téléchargement si le format n'est pas lisible par le navigateur - **🎨 Diagrammes Excalidraw** : Visualiseur/éditeur natif des fichiers `.excalidraw` et `.excalidraw.md` (iframe sandboxée, auto-save, thème clair/sombre, texte des diagrammes indexé pour la recherche) -- **📊 Tableurs Excel** : les fichiers `.xlsx` s'ouvrent dans un visualiseur dédié — un tableau par feuille avec onglets, en-têtes A1 et édition directe des cellules (`PUT /api/file/{vault}/xlsx/save`, backup automatique, écriture atomique), plus le téléchargement du fichier d'origine. Les classeurs contenant des éléments qu'ObsiGate ne peut pas conserver (valeurs calculées, segments, contrôles de formulaire, signature…) affichent un **avertissement** et demandent confirmation avant l'enregistrement ; une saisie commençant par `=` ou `@` est stockée comme texte sauf activation du bouton `f(x)` +- **📊 Tableurs Excel** : les fichiers `.xlsx` et `.xlsm` s'ouvrent dans un visualiseur dédié — un tableau par feuille avec onglets, en-têtes A1 et édition directe des cellules (`PUT /api/file/{vault}/xlsx/save`, backup automatique, écriture atomique), plus le téléchargement du fichier d'origine. Le visualiseur rend polices, couleurs, cellules fusionnées et volets figés, et offre navigation clavier, barre de formule, tri/filtre/recherche, export CSV, édition de la structure (feuilles, lignes, colonnes) et un tableau de bord du classeur (plages nommées, détection graphiques/TCD, stats par feuille) ; un `.csv` s'édite dans la même grille (RFC 4180) tandis que `.xls` et `.ods` s'ouvrent en lecture seule. Les classeurs contenant des éléments qu'ObsiGate ne peut pas conserver (valeurs calculées, segments, contrôles de formulaire, signature…) affichent un **avertissement** et demandent confirmation avant l'enregistrement ; une saisie commençant par `=` ou `@` est stockée comme texte sauf activation du bouton `f(x)`. L'assistant IA peut lister les feuilles, injecter un tableau borné dans son contexte, modifier des cellules et ajouter des lignes - **🎨 Syntax highlight** : Coloration syntaxique des blocs de code - **🌓 Thème clair/sombre** : Toggle persisté en localStorage - **📡 Synchronisation temps réel** : Surveillance automatique des fichiers via watchdog avec mise à jour incrémentale de l'index @@ -976,8 +976,8 @@ Ce projet est sous licence **MIT** — voir le fichier [LICENSE](LICENSE) pour l ## 📝 Changelog -Consultez le [CHANGELOG.md](./CHANGELOG.md) pour l'historique complet de toutes les versions (v1.0.0 → v2.39.0). +Consultez le [CHANGELOG.md](./CHANGELOG.md) pour l'historique complet de toutes les versions (v1.0.0 → v2.39.1). --- -*Projet : ObsiGate | Version : 2.39.0 | Dernière mise à jour : Septembre 2026* +*Projet : ObsiGate | Version : 2.39.1 | Dernière mise à jour : Septembre 2026* diff --git a/README.md b/README.md index 2688b3a..f15ea42 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ **Ultra-light web gateway for your Obsidian vaults** — Access, browse, and search all your Obsidian notes from any device via a modern, responsive web interface. -[![Version](https://img.shields.io/badge/Version-2.39.0-blue.svg)]() +[![Version](https://img.shields.io/badge/Version-2.39.1-blue.svg)]() [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) [![Docker](https://img.shields.io/badge/Docker-Ready-blue.svg)](https://www.docker.com/) [![Python](https://img.shields.io/badge/Python-3.11+-green.svg)](https://www.python.org/) @@ -84,7 +84,7 @@ Step-by-step **user guides** live in [`docs/GUIDES/`](docs/GUIDES/): - **🖼️ Obsidian Images** : Full support for all Obsidian image syntaxes with intelligent resolution - **🎬 Audio & video** : Built-in HTML5 players (`.mp3 .wav .flac .mp4 .webm`…) with HTTP Range streaming (play, seek, fullscreen) and **persistent playback** (floating mini-player / mini video window, return to media or stop anytime, lock-screen controls via Media Session), falling back to download when the format is not playable in the browser - **🎨 Excalidraw Diagrams** : Native viewer/editor for `.excalidraw` and `.excalidraw.md` files (sandboxed iframe, autosave, dark/light theme, diagram text indexed for search) -- **📊 Excel Spreadsheets** : `.xlsx` files open in a dedicated viewer — one table per sheet with tabs, A1 headers and inline cell editing (`PUT /api/file/{vault}/xlsx/save`, automatic backup, atomic write), plus download of the original file. Workbooks holding elements ObsiGate cannot preserve (cached values, slicers, form controls, signature…) show a **warning** and ask for confirmation before saving; a value starting with `=` or `@` is stored as text unless the `f(x)` toggle is enabled +- **📊 Excel Spreadsheets** : `.xlsx` and `.xlsm` files open in a dedicated viewer — one table per sheet with tabs, A1 headers and inline cell editing (`PUT /api/file/{vault}/xlsx/save`, automatic backup, atomic write), plus download of the original file. The viewer renders fonts, colors, merged cells and frozen panes, offers keyboard navigation, a formula bar, sort/filter/find, CSV export, sheet & row/column structure editing and a workbook dashboard (named ranges, charts/pivot detection, per-sheet stats); `.csv` is edited in the same grid (RFC 4180) while `.xls` and `.ods` open read-only. Workbooks holding elements ObsiGate cannot preserve (cached values, slicers, form controls, signature…) show a **warning** and ask for confirmation before saving; a value starting with `=` or `@` is stored as text unless the `f(x)` toggle is enabled. The AI assistant can list sheets, dump a bounded table to its context, update cells and append rows - **🎨 Syntax Highlight** : Syntax highlighting for code blocks - **🌓 Light/Dark Theme** : Toggle persisted in localStorage - **📡 Real-time Sync** : Automatic file monitoring via watchdog with incremental index updates @@ -1151,8 +1151,8 @@ This project is licensed under the **MIT License** - see the [LICENSE](LICENSE) ## 📝 Changelog -See [CHANGELOG.md](./CHANGELOG.md) for the complete version history (v1.0.0 → v2.39.0). +See [CHANGELOG.md](./CHANGELOG.md) for the complete version history (v1.0.0 → v2.39.1). --- -*Project: ObsiGate | Version: 2.39.0 | Last updated: September 2026* +*Project: ObsiGate | Version: 2.39.1 | Last updated: September 2026* diff --git a/VERSION b/VERSION index cde8adf..ec12822 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.39.0 +2.39.1 diff --git a/desktop/Cargo.lock b/desktop/Cargo.lock index 42b90e2..a7cf995 100644 --- a/desktop/Cargo.lock +++ b/desktop/Cargo.lock @@ -2626,7 +2626,7 @@ dependencies = [ [[package]] name = "obsigate-desktop" -version = "2.39.0" +version = "2.39.1" dependencies = [ "chrono", "env_logger", diff --git a/desktop/Cargo.toml b/desktop/Cargo.toml index 991949b..661d200 100644 --- a/desktop/Cargo.toml +++ b/desktop/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "obsigate-desktop" -version = "2.39.0" +version = "2.39.1" description = "ObsiGate Desktop — Porte d'entrée native pour vos vaults Obsidian" authors = ["Bruno Charest"] edition = "2021" diff --git a/desktop/tauri.conf.json b/desktop/tauri.conf.json index e9a48d4..d108d70 100644 --- a/desktop/tauri.conf.json +++ b/desktop/tauri.conf.json @@ -1,7 +1,7 @@ { "$schema": "https://raw.githubusercontent.com/nicedoc/obsigate/main/desktop/tauri.conf.schema.json", "productName": "ObsiGate", - "version": "2.39.0", + "version": "2.39.1", "identifier": "com.obsigate.desktop", "build": { "frontendDist": "../frontend", diff --git a/docs/GUIDES/RECHERCHE_PDF_EXCALIDRAW.md b/docs/GUIDES/RECHERCHE_PDF_EXCALIDRAW.md index bf85437..868947e 100644 --- a/docs/GUIDES/RECHERCHE_PDF_EXCALIDRAW.md +++ b/docs/GUIDES/RECHERCHE_PDF_EXCALIDRAW.md @@ -194,6 +194,43 @@ curl "http://localhost:2020/api/file/Recettes/xlsx/sheet?path=budget.xlsx&sheet= - Erreurs : **404** si la feuille n'existe pas, **415** si le fichier n'est pas un `.xlsx`. +### Fonctions avancées + +**Barre de formule et navigation clavier** — la cellule active est nommée en +A1 au-dessus du tableau ; `Tab`/`Maj+Tab` et les flèches circulent entre les +cellules, `Entrée` valide, `Maj+Entrée` insère un retour à la ligne, une +plage se copie telle quelle vers un tableur. + +**Tri, filtre, recherche, export** — chaque colonne se trie (ascendant / +descendant, info-bulle : le tri s'applique à l'affichage seul), les lignes +se filtrent, la recherche (`Ctrl+F` du panneau) va de correspondance en +correspondance, et la feuille s'exporte en CSV. Rien de tout cela ne +modifie le classeur. + +**Structure** — le menu **Structure** de la barre d'outils ajoute, +renomme, duplique ou supprime une feuille, et insère/supprime des lignes ou +colonnes autour de la cellule active (`PUT …/xlsx/structure`, backup +automatique et confirmation, comme pour l'édition des cellules). + +**Styles et mise en page** — la lecture restitue couleurs de police et de +fond, gras/italique/souligné, alignements, cellules fusionnées et volets +figés ; l'ancrage de la zone figée est conservé au défilement. + +**Formats de fichiers** — `.xlsm` s'édite comme un `.xlsx` et ses +**macros sont préservées** à l'enregistrement ; `.xls` et `.ods` s'affichent +en **lecture seule** ; un `.csv` s'ouvre dans la même grille et se réécrit +conformément à la RFC 4180 (les guillemets et séparateurs sont +échappés). + +**Tableau de bord** — le bouton **Tableau de bord** liste les plages +nommées du classeur (nom, référence, portée), signale les feuilles +contenant des graphiques ou des tableaux croisés, et donne pour chaque +feuille un résumé (cellules, lignes, colonnes, formules, valeurs +numériques) avec quelques chiffres clés. C'est une aide à la lecture : +les plages nommées peuvent ensuite être exploitées avec l'assistant IA +(outils `list_xlsx_sheets`, `xlsx_to_markdown`, `update_xlsx_cells`, +`append_xlsx_rows`). + ### Limites - L'affichage intégré démarre à **500 lignes × 40 colonnes** par feuille ; @@ -201,9 +238,13 @@ curl "http://localhost:2020/api/file/Recettes/xlsx/sheet?path=budget.xlsx&sheet= défilement vers le bas du tableau) ajoute les lignes suivantes par fenêtres de 500 — elles deviennent aussitôt éditables et sauvegardables. -- Styles, formats de nombre, cellules fusionnées et volets figés ne sont pas - rendus. -- Formats non gérés : `.xls`, `.xlsm` (macros), `.ods`. +- Un **format de nombre personnalisé** (devise, pourcentage…) est signalé + par une police à chasse fixe, mais la valeur reste affichée brute. +- L'application de **styles** depuis la visionneuse (mettre en gras, + colorer) n'est pas proposée — seuls les styles existants sont rendus. +- `.xls` et `.ods` restent en lecture seule (convertir vers `.xlsx` pour + éditer) ; les macros d'un `.xlsm` sont conservées mais ne s'exécutent + pas dans ObsiGate. --- diff --git a/docs/ISSUES_TODOLIST.md b/docs/ISSUES_TODOLIST.md index 90f2ffe..a0ae6c1 100644 --- a/docs/ISSUES_TODOLIST.md +++ b/docs/ISSUES_TODOLIST.md @@ -14,7 +14,7 @@ - **Projet** : ObsiGate — Porte d'entrée web pour vaults Obsidian - **Stack** : Python 3.11+ (backend FastAPI) · JavaScript/Vanilla (frontend) · Tauri/Rust (desktop) -- **Dernière mise à jour** : 2026-09-27 +- **Dernière mise à jour** : 2026-09-28 --- @@ -215,6 +215,7 @@ Avant de corriger quoi que ce soit, un agent IA doit : | Date | ID(s) traité(s) | Action | Fichiers modifiés | Résumé | Statut après | |---|---|---|---|---|---| | 2026-09-28 | BUG-090 (#153 A8 + A9) | Correction + feature | `backend/xlsx_reader.py`, `backend/routers/files_read.py`, `backend/schemas.py`, `backend/openapi_docs.py`, `frontend/js/viewer.js`, `frontend/style.css`, `frontend/locales/{fr,en}.json`, `tests/test_xlsx_viewer.py`, `tests/frontend/xlsx-viewer.test.mjs`, `tests/e2e/xlsx-viewer.spec.js`, `test_vault/sample-xlsx-large.xlsx` | **La troncature d'une feuille est annoncée et les lignes cachées restent accessibles** : (BUG-090/A8) `render_sheets()` renvoie `total_rows`/`total_cols`/`max_rows`/`max_cols`/`truncated`, la visionneuse affiche un bandeau « Feuille tronquée » (i18n FR/EN, axes lignes et colonnes) et la ligne d'en-têtes devient `sticky` (`top: auto` sur les numéros de ligne pour éviter l'empilement) ; (A9) `GET /api/file/{vault}/xlsx/sheet?sheet=&offset=&limit=` (`XlsxSheetWindowResponse`, plafond 1 000 lignes/requête, 404 feuille inconnue, 415 non-xlsx) sert une fenêtre avec les **vraies** coordonnées A1 et le `has_more` de pagination. Contre-preuves : neutraliser `truncated` → 2 tests échouent ; neutraliser l'offset → 3 tests échouent. Vérifié : `test_xlsx_viewer.py` 58 passed, xlsx-viewer.test.mjs 14/14, E2E 7/7 (3 nouveaux + fixture `sample-xlsx-large.xlsx` 520 lignes), suite 1417 passed / 6 skipped, ruff 0, mypy 0, i18n parity, validate-imports 40 modules | 🟢 corrigé (en attente vérif utilisateur) | +| 2026-09-28 | #153 A6 → A17 (v2.33.0 → v2.39.0) | Feature + clôture documentaire (aucun bug nouveau) | `CHANGELOG.md`, `docs/features/xlsx-viewer.md`, `docs/GUIDES/RECHERCHE_PDF_EXCALIDRAW.md`, `README.md`, `README.fr.md` | **Clôture du backlog #153** : entrées CHANGELOG des 7 sous-tâches, fiche `features/xlsx-viewer.md` (statut terminé, cases A6-A17 cochées, historique), section 6 du guide utilisateur étendue (barre de formule, navigation clavier, tri/filtre/recherche/export CSV, structure, styles, formats `.xlsm`/`.xls`/`.ods`/`.csv`, tableau de bord) et bullets README FR/EN. Code livré : v2.33.0 A6 (outils IA `backend/tools/spreadsheets.py`), v2.34.0 A7 (clavier + barre de formule), v2.35.0 A13 (tri/filtre/recherche/export), v2.36.0 A14 (structure `PUT …/xlsx/structure`), v2.37.0 A15 (styles/fusions/volets figés), v2.38.0 A16 (`.xlsm` éditable, `.xls`/`.ods` lecture seule, `.csv` RFC 4180), v2.39.0 A17 (dashboard `GET …/xlsx/dashboard`). Vérifié : suite xlsx 116 passed, xlsx-viewer.test.mjs 35/35, ruff/mypy 0, i18n parity, validate-imports 40 modules | ✅ livré (en attente vérif utilisateur) | | 2026-09-28 | BUG-089 (#153 A5, A10, A12) | Correction | `backend/xlsx_reader.py`, `backend/indexer.py`, `backend/search.py`, `backend/services/mutations.py`, `frontend/js/viewer.js`, `frontend/style.css`, `frontend/locales/{fr,en}.json`, `tests/test_xlsx_viewer.py` | **Les tableurs deviennent visibles ettypés** : (A5) `extract_indexable_text()` indexe noms de feuilles + 20 premières lignes (plafond 5 k caractères) dans le TF-IDF et la recherche sémantique — un mot tapé dans une cellule rend le fichier trouvable ; (A10) `_coerce_xlsx_value()` reconnaît désormais les booléens (`TRUE`/`FAUX`/`OUI`/`NON`) et les dates FR `JJ/MM/AAAA` (jour-first : `01/02/2026` = 1er février), symétrique avec l'affichage ; (A12) la valeur calculée en cache s'affiche sous la formule (``, 2ᵉ lecture `data_only=True` uniquement si l'archive contient un ``), info-bulle traduite via `xlsx.cached_value_title` FR/EN. (BUG-089) un reindex manuel reconstruisait mal l'index inversé et `backend/search.py` lisait l'index par valeur. Contre-preuves vérifiées pour A5, A10 et A12. Vérifié : `test_xlsx_viewer.py` 43 passed, suite 1402 passed / 6 skipped, ruff 0, mypy 0, i18n parity, validate-imports 40 modules, xlsx-viewer.test.mjs 10/10 | 🟢 corrigé (en attente vérif utilisateur) | | 2026-09-27 | BUG-085 → BUG-088 (#153 A1-A4) | Correction | `backend/xlsx_reader.py`, `backend/services/mutations.py`, `backend/routers/files_read.py`, `backend/routers/files_write.py`, `backend/schemas.py`, `backend/main.py`, `frontend/js/viewer.js`, `frontend/js/auth.js`, `frontend/style.css`, `frontend/locales/{fr,en}.json`, `frontend/sw.js`, `tests/test_xlsx_viewer.py`, `tests/frontend/xlsx-viewer.test.mjs`, `tests/e2e/xlsx-viewer.spec.js`, `test_vault/sample-xlsx-lossy.xlsx`, `.gitea/workflows/ci.yml` | **Garde-fous d'écriture des classeurs Excel** : (BUG-085) `inspect_workbook()` détecte ce qu'un round-trip openpyxl perd (valeurs calculées, slicers, contrôles, connexions, custom XML, signature) → la lecture expose `xlsx_lossy_features`, la visionneuse affiche une bannière et `PUT xlsx/save` refuse sans `force` (**409** `xlsx_lossy_content`, confirmation explicite puis reprise) ; (BUG-086) écriture atomique `.tmp` + `os.replace` ; (BUG-087) verrou par fichier (409 `conflict`, endpoint sync pour le threadpool) ; (BUG-088) une saisie `=`/`@` est stockée en texte (`data_type = "s"`), sauf opt-in `allow_formula` / bouton `f(x)`. Le handler `ServiceError` expose désormais `code` + `details` et `api()` les propage. Périmètre de perte revalidé empiriquement sur openpyxl 3.1.5 (graphiques, images et TCD sont préservés). Vérifié : `test_xlsx_viewer.py` 31 passed, suite 1390 passed / 6 skipped, ruff/mypy 0, validate-imports 40 modules, xlsx-viewer.test.mjs 10/10, E2E 3/3 | 🟢 corrigé (en attente vérif utilisateur) | | *(exemple)* 2026-06-15 | BUG-001 | Correction | `frontend/app.js` | Réécriture de `renderFile()` pour préserver le DOM dashboard | 🟢 corrigé (en attente vérif) | diff --git a/docs/ROADMAP.md b/docs/ROADMAP.md index d2b8084..39c7c75 100644 --- a/docs/ROADMAP.md +++ b/docs/ROADMAP.md @@ -1,6 +1,6 @@ # ObsiGate — Roadmap -> **Version :** 2.39.0 | **Dernière mise à jour :** 2026-09-28 +> **Version :** 2.39.1 | **Dernière mise à jour :** 2026-09-28 > **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)** @@ -47,7 +47,7 @@ ### 153. Visionneuse & édition XLSX — complétude (fidélité, recherche, IA, UX, formats) - **Effort :** 8-13 jours (P0 ✅ 2-3 j · P1 : 4-6 j · P2 : 2-4 j) | **Impact :** 🟡 -- **Statut :** 🔵 en cours — **P0 livré le 2026-09-27** (BUG-085 → BUG-088), **A5/A10/A12 livrés le 2026-09-28** (avec BUG-089), **A8/A9/A9bis livrés le 2026-09-28** (avec BUG-090), reste A6-A7 puis A13-A17 +- **Statut :** ✅ **livré le 2026-09-28** — P0 le 2026-09-27 (BUG-085 → BUG-088), A5/A10/A12 le 2026-09-28 (avec BUG-089), A8/A9/A9bis le 2026-09-28 (avec BUG-090), puis v2.33.0 → v2.39.0 : A6, A7, A13, A14, A15, A16, A17 (+ A11 déjà au CI) — **backlog #153 terminé** - **Analyse, risques et critères d'acceptation :** [features/xlsx-viewer.md](./features/xlsx-viewer.md) - **Description :** #152 (visionneuse XLSX, 2.27.0) lit et édite correctement la **grille de valeurs** d'un `.xlsx`, mais l'ensemble supporté est étroit : valeurs seulement (ni structure, @@ -70,21 +70,21 @@ - [x] **A2** Écriture atomique (`wb.save(.tmp)` + `os.replace()`, backup inchangé) — BUG-086 - [x] **A3** Verrou par fichier autour du read-modify-write (timeout 15 s + **409** `conflict`) — BUG-087 - [x] **A4** Neutralisation de l'injection de formule (`=`/`@` stockés en texte, opt-in `allow_formula` + bouton `f(x)`) — BUG-088 - - **P1 — recherche, IA, UX (🟡, 4-6 j) — 🔵 en cours** + - **P1 — recherche, IA, UX (🟡, 4-6 j) — 🟢 livré** - [x] **A5** Indexation du contenu des feuilles (noms de feuilles + 20 premières lignes, plafond 5 k caractères) — les mots tapés dans une cellule rendent le fichier trouvable ; au passage **BUG-089** (reindex manuel ne reconstruisait pas l'index inversé) - - [ ] **A6** Outils IA `update_xlsx_cells` / `append_xlsx_rows` / `xlsx_to_markdown` / `list_xlsx_sheets` - - [ ] **A7** Navigation clavier + barre de formule + nom de cellule (Tab/Entrée/flèches, `Maj+Entrée`, copie de plage) + - [x] **A6** Outils IA `update_xlsx_cells` / `append_xlsx_rows` / `xlsx_to_markdown` / `list_xlsx_sheets` (v2.33.0) + - [x] **A7** Navigation clavier + barre de formule + nom de cellule (Tab/Entrée/flèches) (v2.34.0) - [x] **A8** `thead` sticky + bandeau « feuille tronquée » (lève la troncature silencieuse) — BUG-090 - [x] **A9** Chargement paresseux par feuille (`GET …/xlsx/sheet?offset&limit`, défilement virtuel) - [x] **A10** Types & formats de saisie (nombre/texte, booléens `TRUE`/`FAUX`, dates FR `JJ/MM/AAAA` jour-first) - - [ ] **A11** Tests frontend (`tests/frontend/xlsx-viewer.test.mjs`) + E2E (`tests/e2e/xlsx-viewer.spec.js`) au CI + - [x] **A11** Tests frontend (`tests/frontend/xlsx-viewer.test.mjs`) + E2E (`tests/e2e/xlsx-viewer.spec.js`) au CI (JSDOM dans le job lint depuis v2.31.0 ; spec E2E livrée avec A9bis) - [x] **A12** Valeur calculée affichée sous la formule (2ᵉ lecture `data_only=True` seulement si l'archive contient un ``, info-bulle FR/EN) - - **P2 — étendu (🟢, 2-4 j) — ⚪ à faire** - - [ ] **A13** Tri / filtre / recherche dans la feuille + export CSV de la sélection - - [ ] **A14** CRUD de feuilles, lignes et colonnes (renommer, insérer, supprimer, dupliquer) - - [ ] **A15** Styles minimaux en écriture + lecture fidèle (gras, fond, formats, fusions, volets figés) - - [ ] **A16** Formats additionnels (`.xlsm` avec `keep_vba`, `.xls`, `.ods`, `.csv` éditable) - - [ ] **A17** Vue « tableau de bord » (plages nommées, TCD, KPI par feuille, actions IA) + - **P2 — étendu (🟢, 2-4 j) — 🟢 livré** + - [x] **A13** Tri / filtre / recherche dans la feuille + export CSV de la sélection (v2.35.0) + - [x] **A14** CRUD de feuilles, lignes et colonnes (renommer, insérer, supprimer, dupliquer) (v2.36.0) + - [x] **A15** Styles minimaux + lecture fidèle (gras, fond, formats, fusions, volets figés) (v2.37.0) + - [x] **A16** Formats additionnels (`.xlsm` avec `keep_vba`, `.xls`/`.ods` lecture seule via xlrd/odfpy, `.csv` éditable) (v2.38.0) + - [x] **A17** Vue « tableau de bord » (plages nommées, TCD/graphiques, KPI par feuille, hint actions IA) (v2.39.0) - **Convention de suivi :** chaque sous-tâche démarre par son ID stable (`#153-A` dans cette Roadmap) ; celles qui sont des **défauts** sont aussi ouvertes comme `BUG-NNN` dans [ISSUES_TODOLIST.md](./ISSUES_TODOLIST.md) (A1→BUG-085, A2→BUG-086, A3→BUG-087, A4→BUG-088 ; @@ -218,7 +218,7 @@ | 🔵 Finitions | #77 Desktop : 6 tests E2E **manuels** ([protocole](./DESKTOP_E2E_CHECKLIST.md)) — signature Windows non retenue (décision 2026-09-26) | ~0,5-1 jour | | ⚪ P4 reporté | #73 Sync — **reporté (décision 2026-09-26)**, hors chemin critique | 6-8 jours si réactivé | | ⚪ P0/P1 prioritaire | #87 CI/CD (BUG-035 → BUG-040 corrigés, #86 livré) | ~3-5 jours | -| ⚪ P0/P1/P2 backlog | #153 Visionneuse & édition XLSX — complétude (P0 ✅ A1-A4 ; P1 ✅ A5, A8-A10, A12, A9bis — reste A6-A7 ; A13-A17 2-4 j) | 2-4 jours restants | +| ✅ Terminé | #153 Visionneuse & édition XLSX — complétude (A1-A17 **toutes livrées**, v2.27.0 → v2.39.0) | 0 jour restant | | **Total chemin critique** | **#77 fin + #87** | **~4-6 jours** | --- diff --git a/docs/features/xlsx-viewer.md b/docs/features/xlsx-viewer.md index 01dee79..448c47a 100644 --- a/docs/features/xlsx-viewer.md +++ b/docs/features/xlsx-viewer.md @@ -3,7 +3,7 @@ > **Item de roadmap :** [#153 — Visionneuse & édition XLSX — complétude](../ROADMAP.md) > **Origine :** #152 (visionneuse XLSX, livrée en 2.27.0 — voir > [archive/COMPLETED_v1-v2.md](../archive/COMPLETED_v1-v2.md)) -> **Statut :** 🔵 En cours — **P0 livré le 2026-09-27** (BUG-085 → BUG-088), **A5/A10/A12 livrés le 2026-09-28** (avec BUG-089), **A8/A9/A9bis livrés le 2026-09-28** (avec BUG-090), reste A6-A7 puis A13-A17 +> **Statut :** ✅ **Backlog terminé et livré le 2026-09-28** — P0 le 2026-09-27 (BUG-085 → BUG-088), A5/A10/A12 le 2026-09-28 (avec BUG-089), A8/A9/A9bis le 2026-09-28 (avec BUG-090), puis A6→A17 en v2.33.0 → v2.39.0 (A11 étant au CI depuis A5/A8) > **Effort estimé :** 8-13 jours au total (P0 ✅ 2-3 j · P1 4-6 j · P2 2-4 j) > **Règle de maintenance :** la Roadmap porte les cases à cocher (suivi), cette fiche porte > l'analyse, les risques et les critères d'acceptation. **Ne pas dupliquer le détail.** @@ -25,7 +25,7 @@ | CSS | `frontend/style.css:10927-10988` | `.xlsx-*` (variables CSS, colonne A `sticky`) | | Indexation | `backend/indexer.py:68, 563-568, 957-960` | `.xlsx` supporté, **métadonnées seules** (`content=""`) | | Outils IA | `backend/tools/documents.py:66-89` + `schemas.py:296-305` | `create_xlsx` (WRITE + confirmation) — **création seule** | -| Tests | `tests/test_xlsx_viewer.py` | 11 tests backend (affichage, index, save, backup, 400) | +| Tests | `tests/test_xlsx_viewer.py` (58) + `test_xlsx_styles.py` (9) + `test_xlsx_formats.py` (12) + `test_xlsx_dashboard.py` (8) + `test_xlsx_structure.py` (11) + `test_spreadsheet_tools.py` (17) · `tests/frontend/xlsx-viewer.test.mjs` (35) · `tests/e2e/xlsx-viewer.spec.js` (9) | Backend, JSDOM et E2E (chromium-desktop) | ## 2. Ce qui est supporté aujourd'hui (livré, non concerné par #153 sauf mention) @@ -46,6 +46,12 @@ vidée ; backup `.bak` avant écriture ; garde-fou vault read-only (403) ; `reso ## 3. Limites connues (par couche) +> **Note (2026-09-28)** : les limites ci-dessous décrivent l'état du jour de l'audit +> (2026-09-27). La quasi-totalité a été levée depuis par le backlog §5 (styles, navigation +> clavier, tri/filtre/recherche, structure, formats `.xlsm`/`.xls`/`.ods`/`.csv`, indexation, +> outils IA) — se reporter aux cases cochées et à l'historique §7 ; ne pas relire cette +> section comme l'état actuel. + ### 3.1 Fidélité du round-trip — risque n°1 `load_workbook()` → `wb.save()` : ce qui est **réellement** perdu a été mesuré sur @@ -135,7 +141,7 @@ couverture) · effort en jours-homme de développement + tests. nombres. Au passage : le handler `ServiceError` expose `code` + `details` et `api()` les propage sur l'Error. *Vérifié :* `TestXlsxFormulaGuard` (4) + test du toggle côté UI. -### P1 — Recherche, IA, UX (4-6 j) — 🟢 A5, A10, A12 livrés le 2026-09-28 +### P1 — Recherche, IA, UX (4-6 j) — 🟢 livré le 2026-09-28 (A5 → A12) - [x] **A5 — Indexation du contenu des feuilles.** `extract_indexable_text()` (noms de feuilles + 20 premières lignes, `MAX_INDEX_CHARS = 5 000`, 20 feuilles max) alimente le TF-IDF et la @@ -143,13 +149,14 @@ couverture) · effort en jours-homme de développement + tests. chiffré/corrompu s'indexe par son seul nom (jamais d'exception). Au passage : **BUG-089**, un reindex manuel ne reconstruisait pas l'index inversé. *Vérifié :* `TestXlsxSearchable` (4) + `TestXlsxIndexing`, **contre-preuve** (neutraliser l'extraction → 3 tests échouent). -- [ ] **A6 — Outils IA sur classeur.** `update_xlsx_cells` (enveloppe du service existant), +- [x] **A6 — Outils IA sur classeur.** `update_xlsx_cells` (enveloppe du service existant), `append_xlsx_rows`, `xlsx_to_markdown` (contexte LLM, plafonné), `list_xlsx_sheets` — risque WRITE + confirmation pour les mutations, libellés i18n dans `backend/tools/labels.py`, - refresh viewer via `obsigate:file-written`. -- [ ] **A7 — Navigation clavier & barre de formule.** `Tab`/`Maj+Tab`/`Entrée`/flèches, cellule + refresh viewer via `obsigate:file-written`. *Livré (v2.33.0) :* `backend/tools/spreadsheets.py`. + *Vérifié :* `tests/test_spreadsheet_tools.py` (17). +- [x] **A7 — Navigation clavier & barre de formule.** `Tab`/`Maj+Tab`/`Entrée`/flèches, cellule active affichée (nom A1), `Maj+Entrée` pour le multiligne, copier une plage, focus visible - et compatible mobile (≥ 44 px, `tests/e2e/mobile-editor.spec.js`). + et compatible mobile (≥ 44 px, `tests/e2e/mobile-editor.spec.js`). *Livré (v2.34.0).* - [x] **A8 — `thead` sticky + indicateur de troncature (R5) — livré 2026-09-28 (BUG-090).** Ligne d'en-têtes figlée au défilement vertical (`thead th { top: 0 }` ; `top: auto` sur les numéros de ligne, sans quoi ils s'empilent en haut à gauche) ; `render_sheets()` expose @@ -185,9 +192,11 @@ couverture) · effort en jours-homme de développement + tests. ressemblant à une formule n'est jamais convertie (BUG-088 préservé) ; un code postal numérique ou une version restent ce qu'ils sont. *Vérifié :* `TestXlsxValueCoercion` (5), **contre-preuve** (neutraliser la coercion → 2 tests échouent). -- [ ] **A11 — Tests frontend + E2E.** `tests/frontend/xlsx-viewer.test.mjs` (dirty, Échap, +- [x] **A11 — Tests frontend + E2E.** `tests/frontend/xlsx-viewer.test.mjs` (dirty, Échap, collage, 1 PUT par feuille, bouton désactivé) et `tests/e2e/xlsx-viewer.spec.js` - (ouverture, onglets, édition, sauvegarde, rechargement) ; intégration au CI. + (ouverture, onglets, édition, sauvegarde, rechargement) ; intégration au CI. *Vérifié :* + 35 tests JSDOM (le job CI `lint` lance `node xlsx-viewer.test.mjs`) et 9 E2E + chromium-desktop ; la couverture a grandi avec chaque sous-tâche (A5/A8 → P2). - [x] **A12 — Valeurs calculées.** La valeur en cache s'affiche sous la formule dans un ``. La 2ᵉ lecture `data_only=True` n'a lieu que si l'archive contient réellement un `……` (sonde déjà présente pour A1) : le cas courant @@ -196,17 +205,30 @@ couverture) · effort en jours-homme de développement + tests. d'interface n'est émis par le backend. *Vérifié :* `TestXlsxCachedValues` (3), **contre-preuve** (neutraliser la 2ᵉ lecture → 2 tests échouent). -### P2 — Étendu (2-4 j) +### P2 — Étendu (2-4 j) — 🟢 livré le 2026-09-28 -- [ ] **A13 — Tri / filtre / recherche dans la feuille + export CSV de la sélection.** -- [ ] **A14 — CRUD de feuilles et de lignes/colonnes** (renommer, insérer, supprimer, dupliquer). -- [ ] **A15 — Styles minimaux en écriture et lecture fidèle** (gras, fond, format +- [x] **A13 — Tri / filtre / recherche dans la feuille + export CSV de la sélection.** + *Livré (v2.35.0) :* tout en manipulation d'affichage, le classeur n'est jamais réécrit + (info-bulle `xlsx.sort_applied`). +- [x] **A14 — CRUD de feuilles et de lignes/colonnes** (renommer, insérer, supprimer, dupliquer). + *Livré (v2.36.0) :* `PUT …/xlsx/structure` + menu Structure, mêmes garde-fous que + l'édition de cellules. *Vérifié :* `tests/test_xlsx_structure.py` (11). +- [x] **A15 — Styles minimaux en écriture et lecture fidèle** (gras, fond, format devise/pourcentage/date, cellules fusionnées, volets figés) ; conserver `csv-table` comme - socle de rendu. -- [ ] **A16 — Formats additionnels.** `.xlsm` (`keep_vba=True`), `.xls`, `.ods`, `.csv` éditable - comme tableur — dépendances à qualifier (`xlrd`/`odfpy`) ou conversion. -- [ ] **A17 — Vue « tableau de bord ».** Détection des plages nommées, TCD et graphiques ; vue - résumée (KPI par feuille) et proposal d'actions IA sur ces plages. + socle de rendu. *Livré (v2.37.0) en lecture :* couleurs, gras/italique/souligné, + alignements, fusions, ancre de volets figés ; un format de nombre personnalisé est signalé + en police mono (pas de rendu devise/pourcentage). L'application de styles **depuis la + visionneuse** (écriture) reste hors périmètre. *Vérifié :* `tests/test_xlsx_styles.py` (9). +- [x] **A16 — Formats additionnels.** `.xlsm` (`keep_vba=True`), `.xls`, `.ods`, `.csv` éditable + comme tableur — dépendances à qualifier (`xlrd`/`odfpy`) ou conversion. *Livré (v2.38.0) :* + `.xlsm` éditable macros préservées, `.xls`/`.ods` lecture seule (xlrd/odfpy), `.csv` + éditable et réécrit RFC 4180. *Vérifié :* `tests/test_xlsx_formats.py` (12). +- [x] **A17 — Vue « tableau de bord ».** Détection des plages nommées, TCD et graphiques ; vue + résumée (KPI par feuille) et proposal d'actions IA sur ces plages. *Livré (v2.39.0) :* + panneau Tableau de bord (`GET …/xlsx/dashboard`) — plages nommées avec portée, comptage + graphiques/TCD par analyse des parties OPC, stats par feuille, 8 KPI ; le volet IA se + limite à un conseil contextuel (pas d'appel IA dédié sur les plages). + *Vérifié :* `tests/test_xlsx_dashboard.py` (8). ## 6. Règles de livraison (rappel `AGENTS.md` / `DELIVERY_WORKFLOW.md`) @@ -233,3 +255,6 @@ couverture) · effort en jours-homme de développement + tests. | 2026-09-28 | **A5 + A10 + A12 livrés** : le contenu des cellules est indexé (recherche), la saisie est typée (booléens, dates FR), la valeur calculée s'affiche sous la formule. **BUG-089** corrigé au passage (reindex manuel ≠ reconstruction de l'index inversé ; `backend/search.py` lisait l'index par valeur) | | 2026-09-28 | **A8 + A9 livrés** (BUG-090) : la troncature d'une feuille est annoncée (bandeau + dimensions dans la réponse de lecture), les en-têtes restent visibles au défilement, et `GET …/xlsx/sheet` sert une fenêtre de lignes avec les vraies coordonnées A1 — les lignes au-delà du plafond redeviennent accessibles aux clients API. Défilement virtuel côté UI à suivre | | 2026-09-28 | **A9bis livré** : « Charger la suite » + sentinelle de défilement sous une feuille tronquée ; les lignes ajoutées sont éditables et sauvegardables immédiatement (même pipeline que le rendu initial) | +| 2026-09-28 | **A6 + A7 livrés** (v2.33.0, v2.34.0) : l'assistant IA lit et modifie les classeurs (`list_xlsx_sheets`, `xlsx_to_markdown`, `update_xlsx_cells`, `append_xlsx_rows`) et la visionneuse gagne navigation clavier complète + barre de formule | +| 2026-09-28 | **A13 + A14 livrés** (v2.35.0, v2.36.0) : tri, filtre, recherche et export CSV côté affichage ; structure du classeur éditable (feuilles, lignes, colonnes) via `PUT …/xlsx/structure` | +| 2026-09-28 | **A15 + A16 + A17 livrés** (v2.37.0 → v2.39.0) : styles/fusions/volets figés rendus, formats `.xlsm`/`.xls`/`.ods`/`.csv` gérés, panneau Tableau de bord (plages nommées, graphiques/TCD, stats, KPI) — **backlog #153 terminé** | diff --git a/package.json b/package.json index bc7e0f4..7a30cca 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "obsigate", - "version": "2.39.0", + "version": "2.39.1", "description": "**Porte d'entrée web ultra-léger pour vos vaults Obsidian** — Accédez, naviguez et recherchez dans toutes vos notes Obsidian depuis n'importe quel appareil via une interface web moderne et responsive.", "main": "patch.js", "directories": {