diff --git a/lib/api.py b/lib/api.py index 4ceab68..fa72c3f 100644 --- a/lib/api.py +++ b/lib/api.py @@ -882,7 +882,11 @@ def _build_knowledge_stats(): sources = conn.execute(""" SELECT c.source, - CASE WHEN c.path LIKE 'http%' THEN 'web' ELSE 'pdf' END as type, + CASE + WHEN c.source = 'stream.echo6.co' THEN 'transcript' + WHEN c.path LIKE 'http%' THEN 'web' + ELSE 'pdf' + END as type, COUNT(DISTINCT c.hash) as catalogued, COUNT(DISTINCT CASE WHEN d.status = 'complete' THEN d.hash END) as complete, COUNT(DISTINCT CASE WHEN d.status NOT IN ('complete', 'failed') AND d.status IS NOT NULL THEN d.hash END) as in_pipeline, @@ -935,11 +939,17 @@ def _build_knowledge_stats(): """).fetchone()[0] recent = conn.execute(""" - SELECT book_title, status, concepts_extracted, vectors_inserted, - CASE WHEN path LIKE 'http%' THEN 'web' ELSE 'pdf' END as type - FROM documents - WHERE status = 'complete' - ORDER BY embedded_at DESC + SELECT COALESCE(d.book_title, c.filename) as title, + d.status, d.concepts_extracted, d.vectors_inserted, + CASE + WHEN c.source = 'stream.echo6.co' THEN 'transcript' + WHEN d.path LIKE 'http%' THEN 'web' + ELSE 'pdf' + END as type + FROM documents d + JOIN catalogue c ON d.hash = c.hash + WHERE d.status = 'complete' + ORDER BY d.embedded_at DESC LIMIT 10 """).fetchall() @@ -979,7 +989,7 @@ def _build_knowledge_stats(): 'source_types': dict(sorted(source_type_counts.items(), key=lambda x: -x[1])), 'sample_size': sample_size, 'recent_complete': [{ - 'title': r['book_title'] or 'Untitled', + 'title': r['title'] or 'Untitled', 'concepts': r['concepts_extracted'] or 0, 'vectors': r['vectors_inserted'] or 0, 'type': r['type'], diff --git a/static/css/recon.css b/static/css/recon.css index d6752cf..95aed52 100644 --- a/static/css/recon.css +++ b/static/css/recon.css @@ -210,6 +210,7 @@ tr:hover { background: var(--bg-secondary); } } .badge-web { background: #1e3a5f; color: #60a5fa; padding: 2px 8px; border-radius: var(--radius); font-size: 11px; } .badge-pdf { background: #2d5a2d; color: #4ade80; padding: 2px 8px; border-radius: var(--radius); font-size: 11px; } +.badge-transcript { background: #3b1f5e; color: #c084fc; padding: 2px 8px; border-radius: var(--radius); font-size: 11px; } /* ── Trend indicators ── */ .trend { font-size: 11px; margin-left: 6px; } diff --git a/static/js/dashboard.js b/static/js/dashboard.js index 4e0b3d1..254d92a 100644 --- a/static/js/dashboard.js +++ b/static/js/dashboard.js @@ -88,7 +88,7 @@ var pipeCount = s.in_pipeline || 0; totalCat += catCount; totalComp += compCount; totalPipe += pipeCount; totalConcepts += s.concepts; totalVectors += s.vectors; - var badge = s.type === 'web' ? 'WEB' : 'PDF'; + var badge = s.type === 'transcript' ? 'TRANSCRIPT' : s.type === 'web' ? 'WEB' : 'PDF'; var compPct = catCount > 0 ? (compCount / catCount * 100) : 0; var pipePct = catCount > 0 ? (pipeCount / catCount * 100) : 0; var compColor = compPct >= 100 ? '#00ff41' : compPct > 0 ? '#ffa500' : '#666'; @@ -185,7 +185,7 @@ rtb.innerHTML = 'None yet'; } else { rtb.innerHTML = data.recent_complete.map(function(r) { - var badge = r.type === 'web' ? 'WEB' : 'PDF'; + var badge = r.type === 'transcript' ? 'TRANSCRIPT' : r.type === 'web' ? 'WEB' : 'PDF'; return '' + r.title + '' + badge + '' + r.concepts + '' + r.vectors + ''; }).join('');