2e2b0b45fa
Rebuild the dashboard as a Drive-style document management system on top of the existing CaveauAI hybrid RAG pipeline. Backend: - 5 migrations (versions, trash soft-delete, saved searches, categories, audit) - DMS helpers (folder ACL walker, disk storage, audit, version snapshot, XLSX/PPTX/HTML/CSV/MD extractors) - New APIs: folders, document-versions, trash, bulk, preview, saved-searches, categories, diagnostics - Extended APIs: documents (folder_id, soft-delete, ACL filter, sort), upload (9 file types, version-collision detection with replace/new/keep-both, disk persistence), chat-stream (folder scoping + graph related-documents) - 30-day trash purge cron with Qdrant + disk + graph cleanup Frontend: - Drive-style two-pane browser with folder tree, drag-drop, bulk-action bar, right-click context menu, multi-select - New pages: folders (tree + per-folder ACL editor), trash (restore/purge) - Extended pages: upload (folder picker, version-collision modal, 9 file type chips), document (Preview/Versions/Permissions tabs with PDF.js + mammoth.js + audio), index (DMS KPIs + activity feed), settings (live diagnostics ping MariaDB/Qdrant/LiteLLM/FalkorDB/disk), chat (folder scope chips + related-authorities chips) - New CSS (dms.css) + JS bundle (dms.js) exposing window.DBN_DMS - Sidebar nav adds Folders + Trash items All routes return HTTP 200 in local smoke test; all 32 files lint clean. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
97 lines
4.7 KiB
PHP
97 lines
4.7 KiB
PHP
<?php
|
||
declare(strict_types=1);
|
||
require_once __DIR__ . '/../includes/bootstrap.php';
|
||
$dashboardPage = 'settings';
|
||
$dashboardTitle = dbnToolsT('dash_title_settings', dbnToolsCurrentLanguage());
|
||
$dashboardLead = dbnToolsT('dash_lead_settings', dbnToolsCurrentLanguage());
|
||
require_once __DIR__ . '/../includes/layout_dashboard.php';
|
||
?>
|
||
<section class="dash-card">
|
||
<div class="dash-card__head">
|
||
<h2><?= htmlspecialchars(dbnToolsT('dash_section_account', $uiLang)) ?></h2>
|
||
</div>
|
||
<dl style="display:grid; grid-template-columns: max-content 1fr; gap: 0.4rem 1.5rem; font-size:0.92rem;">
|
||
<dt style="color:rgba(22,19,15,0.55);"><?= htmlspecialchars(dbnToolsT('dash_label_client_id', $uiLang)) ?></dt>
|
||
<dd><code id="setClientId">—</code></dd>
|
||
<dt style="color:rgba(22,19,15,0.55);"><?= htmlspecialchars(dbnToolsT('dash_label_corpus_id', $uiLang)) ?></dt>
|
||
<dd><code id="setCorpusId">—</code></dd>
|
||
<dt style="color:rgba(22,19,15,0.55);"><?= htmlspecialchars(dbnToolsT('dash_label_user_id', $uiLang)) ?></dt>
|
||
<dd><code id="setUserId">—</code></dd>
|
||
</dl>
|
||
</section>
|
||
|
||
<section class="dash-card">
|
||
<div class="dash-card__head">
|
||
<h2><?= htmlspecialchars(dbnToolsT('dash_section_rag', $uiLang)) ?></h2>
|
||
</div>
|
||
<dl style="display:grid; grid-template-columns: max-content 1fr; gap: 0.4rem 1.5rem; font-size:0.92rem;">
|
||
<dt style="color:rgba(22,19,15,0.55);">Chunking</dt>
|
||
<dd>600 words/passage, 75-word overlap, heading-aware</dd>
|
||
<dt style="color:rgba(22,19,15,0.55);">Embedding model</dt>
|
||
<dd><code>nomic-embed-text</code> (768-dim) via LiteLLM on Colin</dd>
|
||
<dt style="color:rgba(22,19,15,0.55);">Vector DB</dt>
|
||
<dd><code>bnl_client_chunks</code> in Qdrant (Colin Docker)</dd>
|
||
<dt style="color:rgba(22,19,15,0.55);">Search method</dt>
|
||
<dd>Hybrid (vector + keyword), reciprocal rank fusion, private boost 1.5×</dd>
|
||
<dt style="color:rgba(22,19,15,0.55);">Graph DB</dt>
|
||
<dd><code>dbn_client_graph</code> in FalkorDB (Colin) — citation edges</dd>
|
||
</dl>
|
||
</section>
|
||
|
||
<section class="dash-card">
|
||
<div class="dash-card__head">
|
||
<h2>Live diagnostics</h2>
|
||
<div class="dash-card__actions">
|
||
<button class="dash-btn" type="button" id="diagRefresh">↻ Refresh</button>
|
||
</div>
|
||
</div>
|
||
<div id="diagPanel" class="dms-diag"><div class="dms-loading"></div></div>
|
||
</section>
|
||
|
||
<section class="dash-card">
|
||
<div class="dash-card__head">
|
||
<h2><?= htmlspecialchars(dbnToolsT('dash_section_privacy', $uiLang)) ?></h2>
|
||
</div>
|
||
<p style="margin-top:0; max-width:64ch; line-height:1.6;">
|
||
<?= htmlspecialchars(dbnToolsT('dash_privacy_p1', $uiLang)) ?>
|
||
</p>
|
||
<p style="max-width:64ch; line-height:1.6;">
|
||
<?= htmlspecialchars(dbnToolsT('dash_privacy_p2a', $uiLang)) ?>
|
||
<a href="/dashboard/documents.php"><?= htmlspecialchars(dbnToolsT('dash_nav_documents', $uiLang)) ?></a>.
|
||
<?= htmlspecialchars(dbnToolsT('dash_privacy_p2b', $uiLang)) ?>
|
||
</p>
|
||
</section>
|
||
|
||
<script>
|
||
(function () {
|
||
'use strict';
|
||
const d = window.DBN_DASHBOARD || {};
|
||
document.getElementById('setClientId').textContent = d.clientId || '—';
|
||
document.getElementById('setCorpusId').textContent = d.corpusId || '—';
|
||
document.getElementById('setUserId').textContent = d.clientUserId || '—';
|
||
|
||
const $diag = document.getElementById('diagPanel');
|
||
async function loadDiag() {
|
||
$diag.innerHTML = '<div class="dms-loading"></div>';
|
||
try {
|
||
const r = await fetch((d.apiBase || '/api/dashboard') + '/diagnostics.php', { credentials:'same-origin' });
|
||
const data = await r.json();
|
||
if (!data.ok) throw new Error(data.message || 'Diagnostics unavailable');
|
||
const safe = s => String(s == null ? '' : s).replace(/[&<>"]/g, c => ({ '&':'&','<':'<','>':'>','"':'"' }[c]));
|
||
$diag.innerHTML = data.sections.map(s =>
|
||
'<div class="dms-diag__row" title="' + safe(s.detail || '') + '">' +
|
||
'<div class="dms-diag__label">' + safe(s.label) + '</div>' +
|
||
'<div class="dms-diag__value">' + safe(s.value) + '</div>' +
|
||
'<div><span class="dms-diag__status dms-diag__status--' + safe(s.status || 'warn') + '">' + safe(s.status) + '</span></div></div>'
|
||
).join('');
|
||
} catch (e) {
|
||
$diag.innerHTML = '<div class="dms-list__empty"><strong>Could not run diagnostics</strong><span>' + e.message + '</span></div>';
|
||
}
|
||
}
|
||
document.getElementById('diagRefresh').addEventListener('click', loadDiag);
|
||
loadDiag();
|
||
})();
|
||
</script>
|
||
|
||
<?php require_once __DIR__ . '/../includes/layout_dashboard_footer.php'; ?>
|