fix: vault home recursive + backup viewer fixes + AI status at startup
CI / security (push) Failing after 10m56s
CI / lint (push) Failing after 11m14s
CI / test (push) Has been cancelled
CI / build (push) Has been cancelled

- Vault home (#12): recursive file listing (rglob), rel_dir in metadata,
  'recursif' badge, updated roadmap description
- Backup viewer: fix close button (inline onclick + event delegation
  fallback for text nodes), improve error messages
- Backup API: remove response_model to prevent Pydantic 500 errors,
  add try/except + logging on backups/diff/restore endpoints,
  per-entry error handling in _list_backup_files,
  encoding safety (errors='replace') on read_text
- AI status: call /api/ai/status at startup in _initAIStatus
  instead of waiting for user click on sync badge
This commit is contained in:
2026-06-04 09:28:57 -04:00
parent b077c24bf1
commit fc1a4e336e
6 changed files with 200 additions and 85 deletions
+21 -9
View File
@@ -59,7 +59,8 @@ export async function openBackupViewer(vault, path) {
const data = await api(`/api/file/${encodeURIComponent(vault)}/backups?path=${encodeURIComponent(path)}`);
state.backups = data.backups || [];
} catch (err) {
setBody(renderError('Failed to load backups'));
const msg = err?.detail || err?.message || 'Erreur inconnue';
setBody(renderError(`Erreur API: ${msg}`));
return;
}
@@ -95,6 +96,17 @@ function createOverlay() {
panel.id = 'backup-viewer-panel';
overlay.appendChild(panel);
// Event delegation fallback for close button (in case inline onclick fails)
panel.addEventListener('click', (e) => {
// e.target might be a text node (e.g. "×") — use parentElement as fallback
const target = e.target.nodeType === Node.TEXT_NODE ? e.target.parentElement : e.target;
const closeBtn = target && target.closest ? target.closest('.backup-close-btn') : null;
if (closeBtn) {
e.stopPropagation();
close();
}
});
return overlay;
}
@@ -113,6 +125,9 @@ function close() {
}
}
// Expose globally for inline onclick handlers (bypasses text-node target issues)
window._backupViewerClose = close;
// ---------------------------------------------------------------------------
// Rendering
// ---------------------------------------------------------------------------
@@ -121,7 +136,7 @@ function renderLoading() {
return `
<div class="backup-header">
<h3>Backups</h3>
<button class="backup-close-btn" title="Fermer">&times;</button>
<button class="backup-close-btn" title="Fermer" onclick="window._backupViewerClose()">&times;</button>
</div>
<div class="backup-body">
<div class="tree-loading" style="padding:2rem;text-align:center">
@@ -143,10 +158,10 @@ function renderError(msg) {
}
function renderEmpty() {
return `
return \`
<div class="backup-header">
<h3>Backups — ${escapeHtml(state.path)}</h3>
<button class="backup-close-btn" title="Fermer">&times;</button>
<h3>Backups — \${escapeHtml(state.path)}</h3>
<button class="backup-close-btn" title="Fermer" onclick="window._backupViewerClose()">&times;</button>
</div>
<div class="backup-body" style="text-align:center;padding:2rem;color:var(--text-muted)">
<p>Aucun backup disponible pour ce fichier.</p>
@@ -177,7 +192,7 @@ function renderMainView() {
</div>
<div class="backup-header-right">
<span class="backup-count">${b.length} backup${b.length > 1 ? 's' : ''}</span>
<button class="backup-close-btn" title="Fermer">&times;</button>
<button class="backup-close-btn" title="Fermer" onclick="window._backupViewerClose()">&times;</button>
</div>
</div>
@@ -220,9 +235,6 @@ function bindEvents() {
const panel = document.getElementById('backup-viewer-panel');
if (!panel) return;
// Close button
panel.querySelector('.backup-close-btn')?.addEventListener('click', close);
// Left select
const leftSelect = document.getElementById('backup-left-select');
leftSelect?.addEventListener('change', async () => {