feat: structure des classeurs Excel editable depuis la visionneuse #153

A14 : service mutate_xlsx_structure (batch ordonné d'actions
sheet_add/sheet_rename/sheet_delete/sheet_duplicate et
row/col_insert/delete, une seule réécriture verrouillée et atomique,
409 lossy sans force, backup, dernier sheet protégé) ; endpoint
PUT /api/file/{vault}/xlsx/structure (1-50 actions/requête) ;
menu « structure » dans la visionneuse : ajout/renommage/duplication/
suppression de feuilles et insertion/suppression de ligne/colonne à
partir de la cellule active, confirmations explicites pour les
destructions, re-rendu serveur après succès, reprise force après
confirmation 409.

Vérifié : test_xlsx_structure.py 11 (ops, gardes, atomicité du batch,
409 lossy + force) + contre-preuve (garde dernier sheet neutralisée ->
1 échec), xlsx-viewer.test.mjs 33/33 (3 nouveaux), ruff 0, mypy 0,
i18n parity, validate-imports.

🤖 Generated with Codebuff
Co-Authored-By: Codebuff <[email protected]>
This commit is contained in:
2026-09-28 12:53:15 -04:00
parent 38f39a10ae
commit d5c528fead
17 changed files with 700 additions and 13 deletions
+36
View File
@@ -10931,6 +10931,7 @@ body.desktop-mode .editor-container {
gap: 10px;
margin-bottom: 8px;
flex-wrap: wrap;
position: relative; /* anchors the A14 structure menu */
}
.xlsx-toolbar-actions {
margin-left: auto;
@@ -11090,6 +11091,41 @@ body.desktop-mode .editor-container {
outline: 2px solid var(--accent, #4a90d9);
outline-offset: 1px;
}
/* #153 A14 — structure menu (sheets / rows / columns) */
.xlsx-structure-menu {
position: absolute;
z-index: 30;
display: flex;
flex-direction: column;
gap: 2px;
min-width: 240px;
margin-top: 4px;
padding: 6px;
border: 1px solid var(--border);
border-radius: 6px;
background: var(--surface);
box-shadow: 0 8px 24px var(--shadow, rgba(0, 0, 0, 0.25));
}
.xlsx-structure-item {
text-align: left;
border: none;
background: transparent;
color: var(--text-primary);
}
.xlsx-structure-item:hover {
background: var(--bg-secondary);
}
.xlsx-structure-sep {
height: 1px;
margin: 4px 0;
background: var(--border);
}
/* JSDOM shims for the tests that click anchors */
mark {
font: inherit;
}
.xlsx-table td.xlsx-dirty {
background: rgba(255, 196, 0, 0.18);
}