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
+22 -4
View File
@@ -2,7 +2,9 @@
* Vault Home Page module for ObsiGate.
*
* When a specific vault is selected (not "All"), replaces the dashboard
* with a file listing sorted by modification time (newest first).
* with a recursive file listing sorted by modification time (newest first).
* Files from the selected directory AND all its subdirectories are shown
* with their relative path displayed in the metadata line.
* The listing updates automatically when browsing into subdirectories.
*
* The visual style mirrors the search results (.search-result-item) for
@@ -184,7 +186,7 @@ function buildBreadcrumbHTML(parentEl, vaultName, dirPath) {
async function loadAndRender(vaultName, dirPath, container) {
try {
const url = `/api/vault/${encodeURIComponent(vaultName)}/files?dir=${encodeURIComponent(dirPath)}&limit=200`;
const url = `/api/vault/${encodeURIComponent(vaultName)}/files?dir=${encodeURIComponent(dirPath)}&limit=200&recursive=true`;
const data = await api(url);
if (!data.files || data.files.length === 0) {
@@ -204,7 +206,15 @@ async function loadAndRender(vaultName, dirPath, container) {
]);
header.appendChild(count);
// Sort dropdown (already sorted by mtime from backend)
// Recursive indicator
if (data.recursive) {
const recursiveBadge = el('span', { class: 'vault-home-recursive-badge' }, [
document.createTextNode('récursif'),
]);
header.appendChild(recursiveBadge);
}
// Directory label
const dirLabel = dirPath ? `/${dirPath}` : ' (racine)';
const dirInfo = el('span', { class: 'vault-home-dir-info' }, [
document.createTextNode(dirLabel),
@@ -233,8 +243,16 @@ async function loadAndRender(vaultName, dirPath, container) {
hour: '2-digit', minute: '2-digit',
});
// Build metadata line: rel_dir (if any) + date + size
const metaParts = [];
if (f.rel_dir) {
metaParts.push(f.rel_dir + '/');
}
metaParts.push(dateStr);
metaParts.push(formatSize(f.size));
const metaDiv = el('div', { class: 'search-result-vault' }, [
document.createTextNode(`${dateStr} · ${formatSize(f.size)}`),
document.createTextNode(metaParts.join(' · ')),
]);
const item = el('div', {