feat: inspecteur droit pour le tableau de bord XLSX #154
CI / lint (push) Successful in 2m30s
CI / security (push) Failing after 1m46s
CI / build (push) Canceled after 0s
CI / e2e (push) Canceled after 0s
CI / test (push) Canceled after 1h32m51s

This commit is contained in:
2026-09-29 14:56:08 -04:00
parent 8da65611cb
commit e94af0369b
16 changed files with 183 additions and 31 deletions
+37 -4
View File
@@ -15,6 +15,7 @@ import { cacheViewedFile, getCachedFile } from './offline.js';
import { t } from './i18n.js';
import { onFileRender } from './plugins.js';
import { NowPlaying } from './now-playing.js';
import { openAssistant } from './ai-fab.js';
// ── Multi-format export ────────────────────────────────────────────────────
// Downloads a file export (HTML / MD bundle / ePub) via the authenticated
@@ -1198,7 +1199,23 @@ export function renderXlsxViewer(area, data) {
</button>
</span>
</div>
<div class="xlsx-panels">${panels}</div>
<div class="xlsx-body">
<div class="xlsx-main">
<div class="xlsx-panels">${panels}</div>
</div>
<aside class="xlsx-inspector" id="xlsx-inspector" aria-hidden="true">
<div class="xlsx-inspector-head">
<span class="xlsx-inspector-title">${escapeHtml(t("xlsx.inspector_title"))}</span>
<span class="xlsx-inspector-actions">
<button class="btn-action xlsx-inspector-ai" id="xlsx-inspector-ai" type="button" title="${escapeHtml(t("xlsx.inspector_ai"))}">
<i data-lucide="bot" style="width:14px;height:14px"></i> ${escapeHtml(t("xlsx.inspector_ai_short"))}
</button>
<button class="btn-action xlsx-inspector-close" id="xlsx-inspector-close" type="button" aria-label="${escapeHtml(t("common.cancel"))}">✕</button>
</span>
</div>
<div class="xlsx-inspector-body" id="xlsx-inspector-body"></div>
</aside>
</div>
</div>`;
// ── #153 A17 — dashboard panel: named ranges, objects, per-sheet KPI ──
@@ -1212,14 +1229,26 @@ export function renderXlsxViewer(area, data) {
title: t("xlsx.dashboard_btn"),
}, [icon("layout-dashboard", 14), document.createTextNode(t("xlsx.dashboard_btn"))]);
(area.querySelector("#xlsx-view-group") || area.querySelector(".xlsx-toolbar-actions")).appendChild(dashBtn);
const inspector = area.querySelector("#xlsx-inspector");
const inspectorBody = area.querySelector("#xlsx-inspector-body");
const closeInspector = () => {
const panel = inspectorBody.querySelector(".xlsx-dashboard");
if (panel) panel.remove();
inspector.classList.remove("open");
inspector.setAttribute("aria-hidden", "true");
dashBtn.classList.remove("active");
};
dashBtn.addEventListener("click", async () => {
const old = area.querySelector(".xlsx-dashboard");
if (old) { old.remove(); dashBtn.classList.remove("active"); return; }
// #154-A3 — the dashboard lives in a right-hand inspector so the grid
// stays visible beside it (it used to be prepended into the grid flow).
if (inspectorBody.querySelector(".xlsx-dashboard")) { closeInspector(); return; }
dashBtn.classList.add("active");
inspector.classList.add("open");
inspector.setAttribute("aria-hidden", "false");
const panel = document.createElement("div");
panel.className = "xlsx-dashboard";
panel.innerHTML = `<div class="xlsx-dashboard-loading">…</div>`;
area.querySelector(".xlsx-panels").prepend(panel);
inspectorBody.prepend(panel);
try {
const dash = await api(
`/api/file/${encodeURIComponent(data.vault)}/xlsx/dashboard?path=${encodeURIComponent(data.path)}`,
@@ -1261,6 +1290,10 @@ export function renderXlsxViewer(area, data) {
panel.innerHTML = `<p class="xlsx-kpi-empty">${escapeHtml(t("xlsx.load_error"))}: ${escapeHtml(String(err.message || err))}</p>`;
}
});
area.querySelector("#xlsx-inspector-close").addEventListener("click", closeInspector);
// #154-A3 — the assistant is the existing global side panel; the inspector
// just gives it a contextual entry point from the spreadsheet.
area.querySelector("#xlsx-inspector-ai").addEventListener("click", () => { openAssistant(); });
}
const saveBtn = area.querySelector("#xlsx-save-btn");