feat: inspecteur droit pour le tableau de bord XLSX #154
This commit is contained in:
+37
-4
@@ -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");
|
||||
|
||||
@@ -1877,6 +1877,9 @@
|
||||
"xlsx.structure_error": "Could not change the structure",
|
||||
"xlsx.last_sheet": "The last sheet cannot be deleted",
|
||||
"xlsx.dashboard_btn": "Dashboard",
|
||||
"xlsx.inspector_title": "Inspector",
|
||||
"xlsx.inspector_ai": "AI assistant",
|
||||
"xlsx.inspector_ai_short": "AI",
|
||||
"xlsx.dashboard_title": "Workbook dashboard",
|
||||
"xlsx.dashboard_stats": "{{cells}} cells · {{rows}} rows · {{cols}} columns · {{formulas}} formulas · {{numeric}} numeric values",
|
||||
"xlsx.dashboard_charts": "{{n}} chart(s)",
|
||||
|
||||
@@ -1877,6 +1877,9 @@
|
||||
"xlsx.structure_error": "Modification de la structure impossible",
|
||||
"xlsx.last_sheet": "Impossible de supprimer la dernière feuille",
|
||||
"xlsx.dashboard_btn": "Tableau de bord",
|
||||
"xlsx.inspector_title": "Inspecteur",
|
||||
"xlsx.inspector_ai": "Assistant IA",
|
||||
"xlsx.inspector_ai_short": "IA",
|
||||
"xlsx.dashboard_title": "Tableau de bord du classeur",
|
||||
"xlsx.dashboard_stats": "{{cells}} cellules · {{rows}} lignes · {{cols}} colonnes · {{formulas}} formules · {{numeric}} valeurs numériques",
|
||||
"xlsx.dashboard_charts": "{{n}} graphique(s)",
|
||||
|
||||
@@ -11289,6 +11289,71 @@ body.desktop-mode .editor-container {
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
/* #154-A3 — right-hand inspector (dashboard, assistant) beside the grid. */
|
||||
.xlsx-body {
|
||||
display: flex;
|
||||
align-items: stretch;
|
||||
gap: 10px;
|
||||
}
|
||||
.xlsx-main {
|
||||
flex: 1 1 auto;
|
||||
min-width: 0;
|
||||
}
|
||||
.xlsx-inspector {
|
||||
flex: 0 0 340px;
|
||||
width: 340px;
|
||||
max-width: 45%;
|
||||
display: none;
|
||||
flex-direction: column;
|
||||
border: 1px solid var(--border);
|
||||
border-radius: var(--radius);
|
||||
background: var(--surface);
|
||||
max-height: 70vh;
|
||||
}
|
||||
.xlsx-inspector.open {
|
||||
display: flex;
|
||||
}
|
||||
.xlsx-inspector-head {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 8px;
|
||||
padding: 8px 10px;
|
||||
border-bottom: 1px solid var(--border);
|
||||
}
|
||||
.xlsx-inspector-title {
|
||||
font-weight: 600;
|
||||
font-size: 0.85rem;
|
||||
color: var(--text-primary);
|
||||
}
|
||||
.xlsx-inspector-actions {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
}
|
||||
.xlsx-inspector-body {
|
||||
flex: 1 1 auto;
|
||||
overflow: auto;
|
||||
padding: 10px;
|
||||
}
|
||||
.xlsx-inspector .xlsx-dashboard {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: none;
|
||||
border-radius: 0;
|
||||
background: transparent;
|
||||
}
|
||||
@media (max-width: 900px) {
|
||||
.xlsx-body {
|
||||
flex-direction: column;
|
||||
}
|
||||
.xlsx-inspector {
|
||||
flex-basis: auto;
|
||||
width: auto;
|
||||
max-width: none;
|
||||
}
|
||||
}
|
||||
|
||||
/* #153 A17 — workbook dashboard panel: named ranges table + KPI cards.
|
||||
Colors come from the existing CSS variables (no hardcoded values). */
|
||||
.xlsx-dashboard {
|
||||
|
||||
Reference in New Issue
Block a user