mirror of
https://github.com/zvx-echo6/recon.git
synced 2026-05-20 06:34:40 +02:00
Phase 6b: fix dashboard Untitled/WEB bug for transcripts
Two bugs in the Recently Completed table: 1. Title showed "Untitled" for all transcripts because the dashboard read documents.book_title (populated by PDF metadata voting) which is NULL for transcripts. Fixed by COALESCE(book_title, filename) in the SQL query -- falls back to catalogue.filename which holds the real video title. 2. Type showed "WEB" for all transcripts because the type CASE expression only had web and pdf branches, with web matching any http% path -- and transcript paths are PeerTube watch URLs. Fixed by adding a transcript branch keyed on catalogue.source = stream.echo6.co, evaluated before the web branch. Also adds badge-transcript CSS (purple) and JS rendering case. Applied consistently to both the Recently Completed and Sources table queries. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
df29d598d3
commit
70b80cb312
3 changed files with 20 additions and 9 deletions
24
lib/api.py
24
lib/api.py
|
|
@ -882,7 +882,11 @@ def _build_knowledge_stats():
|
||||||
sources = conn.execute("""
|
sources = conn.execute("""
|
||||||
SELECT
|
SELECT
|
||||||
c.source,
|
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 c.hash) as catalogued,
|
||||||
COUNT(DISTINCT CASE WHEN d.status = 'complete' THEN d.hash END) as complete,
|
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,
|
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]
|
""").fetchone()[0]
|
||||||
|
|
||||||
recent = conn.execute("""
|
recent = conn.execute("""
|
||||||
SELECT book_title, status, concepts_extracted, vectors_inserted,
|
SELECT COALESCE(d.book_title, c.filename) as title,
|
||||||
CASE WHEN path LIKE 'http%' THEN 'web' ELSE 'pdf' END as type
|
d.status, d.concepts_extracted, d.vectors_inserted,
|
||||||
FROM documents
|
CASE
|
||||||
WHERE status = 'complete'
|
WHEN c.source = 'stream.echo6.co' THEN 'transcript'
|
||||||
ORDER BY embedded_at DESC
|
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
|
LIMIT 10
|
||||||
""").fetchall()
|
""").fetchall()
|
||||||
|
|
||||||
|
|
@ -979,7 +989,7 @@ def _build_knowledge_stats():
|
||||||
'source_types': dict(sorted(source_type_counts.items(), key=lambda x: -x[1])),
|
'source_types': dict(sorted(source_type_counts.items(), key=lambda x: -x[1])),
|
||||||
'sample_size': sample_size,
|
'sample_size': sample_size,
|
||||||
'recent_complete': [{
|
'recent_complete': [{
|
||||||
'title': r['book_title'] or 'Untitled',
|
'title': r['title'] or 'Untitled',
|
||||||
'concepts': r['concepts_extracted'] or 0,
|
'concepts': r['concepts_extracted'] or 0,
|
||||||
'vectors': r['vectors_inserted'] or 0,
|
'vectors': r['vectors_inserted'] or 0,
|
||||||
'type': r['type'],
|
'type': r['type'],
|
||||||
|
|
|
||||||
|
|
@ -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-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-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 indicators ── */
|
||||||
.trend { font-size: 11px; margin-left: 6px; }
|
.trend { font-size: 11px; margin-left: 6px; }
|
||||||
|
|
|
||||||
|
|
@ -88,7 +88,7 @@
|
||||||
var pipeCount = s.in_pipeline || 0;
|
var pipeCount = s.in_pipeline || 0;
|
||||||
totalCat += catCount; totalComp += compCount; totalPipe += pipeCount;
|
totalCat += catCount; totalComp += compCount; totalPipe += pipeCount;
|
||||||
totalConcepts += s.concepts; totalVectors += s.vectors;
|
totalConcepts += s.concepts; totalVectors += s.vectors;
|
||||||
var badge = s.type === 'web' ? '<span class="badge-web">WEB</span>' : '<span class="badge-pdf">PDF</span>';
|
var badge = s.type === 'transcript' ? '<span class="badge-transcript">TRANSCRIPT</span>' : s.type === 'web' ? '<span class="badge-web">WEB</span>' : '<span class="badge-pdf">PDF</span>';
|
||||||
var compPct = catCount > 0 ? (compCount / catCount * 100) : 0;
|
var compPct = catCount > 0 ? (compCount / catCount * 100) : 0;
|
||||||
var pipePct = catCount > 0 ? (pipeCount / catCount * 100) : 0;
|
var pipePct = catCount > 0 ? (pipeCount / catCount * 100) : 0;
|
||||||
var compColor = compPct >= 100 ? '#00ff41' : compPct > 0 ? '#ffa500' : '#666';
|
var compColor = compPct >= 100 ? '#00ff41' : compPct > 0 ? '#ffa500' : '#666';
|
||||||
|
|
@ -185,7 +185,7 @@
|
||||||
rtb.innerHTML = '<tr><td colspan="4" class="text-dim">None yet</td></tr>';
|
rtb.innerHTML = '<tr><td colspan="4" class="text-dim">None yet</td></tr>';
|
||||||
} else {
|
} else {
|
||||||
rtb.innerHTML = data.recent_complete.map(function(r) {
|
rtb.innerHTML = data.recent_complete.map(function(r) {
|
||||||
var badge = r.type === 'web' ? '<span class="badge-web">WEB</span>' : '<span class="badge-pdf">PDF</span>';
|
var badge = r.type === 'transcript' ? '<span class="badge-transcript">TRANSCRIPT</span>' : r.type === 'web' ? '<span class="badge-web">WEB</span>' : '<span class="badge-pdf">PDF</span>';
|
||||||
return '<tr><td>' + r.title + '</td><td>' + badge + '</td><td>' +
|
return '<tr><td>' + r.title + '</td><td>' + badge + '</td><td>' +
|
||||||
r.concepts + '</td><td>' + r.vectors + '</td></tr>';
|
r.concepts + '</td><td>' + r.vectors + '</td></tr>';
|
||||||
}).join('');
|
}).join('');
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue