v1.8.3: admin — rename Settings to LLM, merge Claude AI into LLM page, hide Claude nav
This commit is contained in:
+72
-11
@@ -326,14 +326,14 @@ a[role=button]:active {
|
||||
<button class="nav-btn w-full flex items-center gap-3 px-4 py-3 rounded-xl text-sm font-semibold transition-all" onclick="showPage('api',this)">
|
||||
<span class="msym text-lg">key</span><span>API</span>
|
||||
</button>
|
||||
<button class="nav-btn w-full flex items-center gap-3 px-4 py-3 rounded-xl text-sm font-semibold transition-all" onclick="showPage('claude',this)">
|
||||
<!-- REMOVED claude nav --><button class="nav-btn w-full hidden flex items-center gap-3 px-4 py-3 rounded-xl text-sm font-semibold transition-all" onclick="showPage('claude',this)">
|
||||
<span class="msym text-lg">neurology</span><span>Claude AI</span>
|
||||
</button>
|
||||
<button class="nav-btn w-full flex items-center gap-3 px-4 py-3 rounded-xl text-sm font-semibold transition-all" onclick="showPage('tracking',this)">
|
||||
<span class="msym text-lg">troubleshoot</span><span>Tracking</span>
|
||||
</button>
|
||||
<button class="nav-btn w-full flex items-center gap-3 px-4 py-3 rounded-xl text-sm font-semibold transition-all" onclick="showPage('settings',this)">
|
||||
<span class="msym text-lg">settings</span><span>Settings</span>
|
||||
<span class="msym text-lg">smart_toy</span><span>LLM</span>
|
||||
</button>
|
||||
<button class="nav-btn w-full flex items-center gap-3 px-4 py-3 rounded-xl text-sm font-semibold transition-all" onclick="showPage('pages',this)">
|
||||
<span class="msym text-lg">description</span><span>Pages</span>
|
||||
@@ -577,8 +577,8 @@ curl -X POST https://rag.afaqzaid.com/ingest-url \
|
||||
<!-- SETTINGS -->
|
||||
<section id="page-settings" class="page hidden">
|
||||
<div class="flex items-center justify-between mb-6">
|
||||
<div><h2 class="text-2xl font-bold">Settings</h2><p class="text-on-surface-variant text-sm mt-1">AI & system configuration</p></div>
|
||||
<button onclick="loadSettings()" class="glass glass-hover px-4 py-2 rounded-xl text-sm flex items-center gap-2">
|
||||
<div><h2 class="text-2xl font-bold">LLM</h2><p class="text-on-surface-variant text-sm mt-1">AI provider, keys & system configuration</p></div>
|
||||
<button onclick="loadSettings();loadClaude();" class="glass glass-hover px-4 py-2 rounded-xl text-sm flex items-center gap-2">
|
||||
<span class="msym text-base">refresh</span> Refresh
|
||||
</button>
|
||||
</div>
|
||||
@@ -588,10 +588,48 @@ curl -X POST https://rag.afaqzaid.com/ingest-url \
|
||||
</div>
|
||||
<div id="settings-llm" class="glass rounded-2xl p-6 mt-6"></div>
|
||||
<div id="settings-r2" class="glass rounded-2xl p-6 mt-6"></div>
|
||||
|
||||
<!-- ── Claude AI Section (moved from Claude page) ──────────────────── -->
|
||||
<div class="glass rounded-2xl p-6 mt-6">
|
||||
<h3 class="text-primary text-xs font-bold uppercase tracking-widest mb-5 flex items-center gap-2">
|
||||
<span class="msym text-base">smart_toy</span> Claude AI
|
||||
</h3>
|
||||
<!-- Key input -->
|
||||
<div class="glass rounded-2xl p-6 mb-6">
|
||||
<h3 class="text-primary text-xs font-bold uppercase tracking-widest mb-5 flex items-center gap-2"><span class="msym text-base">key</span>API Key</h3>
|
||||
<div class="flex gap-3 mb-3">
|
||||
<input type="password" id="claude-key-input" placeholder="sk-ant-..."
|
||||
class="flex-1 bg-surface-high border border-outline-variant rounded-xl px-4 py-3 text-sm text-on-surface outline-none focus:border-primary transition-colors font-mono"/>
|
||||
<button onclick="toggleClaudeKey()" id="claude-key-toggle" class="glass glass-hover px-4 py-2 rounded-xl text-xs text-on-surface-variant">Show</button>
|
||||
</div>
|
||||
<div class="flex items-center gap-3 mb-4">
|
||||
<div id="claude-status" class="flex items-center gap-2 text-xs text-on-surface-variant">
|
||||
<span class="w-2 h-2 rounded-full bg-outline-variant inline-block"></span> Not configured
|
||||
</div>
|
||||
</div>
|
||||
<button onclick="saveClaudeKey()" class="bg-primary text-surface font-bold px-6 py-2.5 rounded-xl text-sm hover:shadow-[0_0_20px_rgba(78,222,163,0.4)] transition-all flex items-center gap-2">
|
||||
<span class="msym text-base">save</span> Save Key
|
||||
</button>
|
||||
<p class="text-on-surface-variant text-xs mt-3">Key is stored securely in the database and loaded at runtime. Get yours at <span class="text-primary">console.anthropic.com</span></p>
|
||||
</div>
|
||||
<!-- Usage stats -->
|
||||
<div class="grid grid-cols-2 lg:grid-cols-4 gap-4 mb-6" id="claude-stats"></div>
|
||||
<!-- Daily usage chart -->
|
||||
<div class="glass rounded-2xl p-6 mb-6">
|
||||
<h3 class="text-primary text-xs font-bold uppercase tracking-widest mb-4 flex items-center gap-2"><span class="msym text-base">bar_chart</span>Daily Usage</h3>
|
||||
<div id="claude-daily-chart"></div>
|
||||
</div>
|
||||
<!-- Recent calls -->
|
||||
<div class="glass rounded-2xl p-6">
|
||||
<h3 class="text-primary text-xs font-bold uppercase tracking-widest mb-4 flex items-center gap-2"><span class="msym text-base">history</span>Recent Calls</h3>
|
||||
<div id="claude-usage-list" class="space-y-2"></div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- CLAUDE -->
|
||||
<section id="page-claude" class="page hidden">
|
||||
<section id="page-claude" class="page hidden" style="display:none!important">
|
||||
<div class="flex items-center justify-between mb-6">
|
||||
<div><h2 class="text-2xl font-bold">Claude AI</h2><p class="text-on-surface-variant text-sm mt-1">API key & usage tracking</p></div>
|
||||
<button onclick="loadClaude()" class="glass glass-hover px-4 py-2 rounded-xl text-sm flex items-center gap-2">
|
||||
@@ -941,7 +979,7 @@ function showPage(name, btn) {
|
||||
if (btn) { btn.classList.add('active','bg-primary/10','text-primary'); btn.classList.remove('text-on-surface-variant'); }
|
||||
closeSidebar();
|
||||
const loaders = {overview:loadOverview, books:loadBooks, users:loadUsers,
|
||||
conversations:loadConversations, resources:loadResources, settings:loadSettings,
|
||||
conversations:loadConversations, resources:loadResources, settings:()=>{loadSettings();loadClaude();},
|
||||
branding:loadBranding, members:loadMembers, claude:loadClaude, tracking:loadTracking};
|
||||
if (loaders[name]) loaders[name]();
|
||||
}
|
||||
@@ -1001,19 +1039,26 @@ async function loadLibraryHealth() {
|
||||
<div class="text-xs text-on-surface-variant mt-1">Missing Chunks</div>
|
||||
</div>
|
||||
<div class="bg-surface-high rounded-xl p-3 text-center">
|
||||
<div class="text-xl font-bold text-blue-400">${d.vectors?.toLocaleString()}</div>
|
||||
<div class="text-xl font-bold text-blue-400">${(d.vector_count||d.total_chunks||0).toLocaleString()}</div>
|
||||
<div class="text-xs text-on-surface-variant mt-1">Vectors</div>
|
||||
</div>
|
||||
</div>`;
|
||||
|
||||
// Books with no chunks
|
||||
if (d.no_chunks?.length > 0) {
|
||||
if (d.missing_books?.length > 0) {
|
||||
html += `<div class="mb-4">
|
||||
<div class="text-xs font-bold text-red-400 uppercase tracking-widest mb-2 flex items-center gap-1">
|
||||
<span class="msym text-sm">warning</span> Books with no chunks (${d.no_chunks.length})
|
||||
<span class="msym text-sm">warning</span> Not Indexed (${d.missing_books.length})
|
||||
</div>
|
||||
<div class="space-y-1 max-h-40 overflow-y-auto">
|
||||
${d.no_chunks.map(b => `<div class="bg-red-900/20 border border-red-900/30 rounded-lg px-3 py-2 text-xs text-on-surface-variant">${b.title || b.filename}</div>`).join('')}
|
||||
<div class="space-y-1 max-h-60 overflow-y-auto">
|
||||
${d.missing_books.map(b => `
|
||||
<div class="bg-red-900/20 border border-red-900/30 rounded-lg px-3 py-2 text-xs flex items-center justify-between gap-2">
|
||||
<span class="text-on-surface-variant truncate">${b.title || b.filename}</span>
|
||||
<button onclick="ingestBook(${b.id}, '${b.filename.replace(/'/g,"\'")}', this)"
|
||||
class="shrink-0 glass glass-hover px-2 py-1 rounded-lg text-xs font-bold text-emerald-400 flex items-center gap-1">
|
||||
<span class="msym text-sm">sync</span> Ingest Now
|
||||
</button>
|
||||
</div>`).join('')}
|
||||
</div>
|
||||
</div>`;
|
||||
}
|
||||
@@ -1081,6 +1126,22 @@ async function clearCache() {
|
||||
btn.disabled = false; btn.innerHTML = '<span class="msym text-sm">delete_sweep</span> Clear Cache';
|
||||
}
|
||||
|
||||
async function ingestBook(bookId, filename, btn) {
|
||||
btn.disabled = true;
|
||||
btn.innerHTML = '<span class="msym text-sm animate-spin">sync</span> Ingesting...';
|
||||
try {
|
||||
const r = await api(`/admin/ingest-book/${bookId}`, {method:'POST'});
|
||||
btn.innerHTML = '<span class="msym text-sm">check_circle</span> Done';
|
||||
btn.classList.replace('text-emerald-400','text-primary');
|
||||
toast('Ingested: ' + filename.substring(0,40));
|
||||
setTimeout(loadLibraryHealth, 2000);
|
||||
} catch(e) {
|
||||
btn.innerHTML = '<span class="msym text-sm">error</span> Failed';
|
||||
btn.classList.replace('text-emerald-400','text-red-400');
|
||||
toast('Error: ' + e.message);
|
||||
}
|
||||
}
|
||||
|
||||
async function reingestMissing() {
|
||||
const btn = document.getElementById('btn-reingest');
|
||||
btn.disabled = true; btn.innerHTML = '<span class="msym text-sm">sync</span> Queuing...';
|
||||
|
||||
Reference in New Issue
Block a user