/** * Hot Topics + Blog Pipeline UX Enhancement (v0.2.5) * Loaded after main dashboard script. * Overrides generateBlog + pollBlogLlm with improved versions. */ (function() { var API = window.API || ''; var blogPipelineRunning = false; var STEP_NAMES = [ 'Topic Expansion', 'Angle Selection', 'Outline Generation', 'Master Draft (writing...)', 'Reality Injection', 'Technical Deepening', 'Opinion Layer', 'Kill AI Tone', 'QA Check', 'Quality Score' ]; // Override generateBlog with pipeline lock + progress UI window.generateBlog = function(topic, speed, customTitle, customAngle) { if (blogPipelineRunning) { if (typeof showToast === 'function') showToast('Pipeline Busy', 'A blog is already being generated. Please wait.'); return; } blogPipelineRunning = true; var blogList = document.getElementById('blog-list'); if (blogList) { blogList.innerHTML = '
' + '
Generating Blog with AI...
' + '
Starting 10-step Flexoptix Style pipeline...
' + '
Connecting to LLM (qwen2.5:14b)
' + '
' + '
' + '
0%
' + '
'; } var body = { topic: topic }; if (speed) body.speed = speed; fetch((API || '') + '/api/blog/generate', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(body) }).then(function(r) { return r.json(); }).then(function(data) { if (data.success && data.draft) { var s = document.getElementById('bp-status'); if (s) s.textContent = 'Template created. LLM pipeline running (~10 min)...'; var b = document.getElementById('bp-bar'); if (b) b.style.width = '5%'; pollPipeline(data.draft.id, 0); } else { blogPipelineRunning = false; if (typeof showToast === 'function') showToast('Error', (data.error || 'Generation failed'), true); if (typeof loadBlogDrafts === 'function') loadBlogDrafts(); } }).catch(function(err) { blogPipelineRunning = false; if (typeof showToast === 'function') showToast('Network Error', err.message, true); if (typeof loadBlogDrafts === 'function') loadBlogDrafts(); }); }; function pollPipeline(id, attempt) { if (attempt > 80) { blogPipelineRunning = false; if (typeof showToast === 'function') showToast('Timeout', 'Pipeline took too long. Check the blog list.'); if (typeof loadBlogDrafts === 'function') loadBlogDrafts(); return; } setTimeout(function() { fetch((API || '') + '/api/blog/' + id).then(function(r) { return r.json(); }).then(function(data) { var d = data.draft || data; var gen = d.generated_by || ''; var steps = d.pipeline_steps_completed || 0; var done = gen && gen !== 'tip-blog-engine-template' && gen.length > 0; if (done) { // Pipeline complete! var bar = document.getElementById('bp-bar'); var pct = document.getElementById('bp-pct'); var status = document.getElementById('bp-status'); var step = document.getElementById('bp-step'); if (bar) bar.style.width = '100%'; if (pct) pct.textContent = '100%'; if (status) { status.textContent = 'Blog generated! ' + (d.word_count || '?') + ' words'; status.style.color = '#2d6a4f'; } if (step) step.textContent = 'Generated by: ' + gen; blogPipelineRunning = false; if (typeof showToast === 'function') showToast('Blog Ready!', (d.title || 'Article') + ' — ' + (d.word_count || '?') + ' words'); setTimeout(function() { if (typeof loadBlogDrafts === 'function') loadBlogDrafts(); if (typeof viewBlogDraft === 'function') viewBlogDraft(id); }, 2000); } else { // Still processing var pctVal = Math.min(95, steps * 10 + 5); var bar = document.getElementById('bp-bar'); var pct = document.getElementById('bp-pct'); var status = document.getElementById('bp-status'); var step = document.getElementById('bp-step'); if (bar) bar.style.width = pctVal + '%'; if (pct) pct.textContent = pctVal + '%'; if (status) status.textContent = 'Step ' + steps + '/10'; if (step && steps > 0 && steps <= 10) step.textContent = STEP_NAMES[steps - 1] || 'Processing...'; pollPipeline(id, attempt + 1); } }).catch(function() { pollPipeline(id, attempt + 1); }); }, 15000); } // Hot topics loader window.loadHotTopics = function() { var grid = document.getElementById('hot-topics-grid'); if (!grid) return; grid.innerHTML = '
Discovering hot topics...
'; fetch((API || '') + '/api/hot-topics').then(function(r) { return r.json(); }).then(function(data) { if (!data.topics || data.topics.length === 0) { grid.innerHTML = '
Hype Cycle Analysis
'; return; } var colors = { breaking: '#c1121f', hot: '#FF8100', trending: '#e6a800', emerging: '#2d6a4f' }; grid.innerHTML = data.topics.slice(0, 6).map(function(t) { var c = colors[t.urgency] || '#888'; var escaped = encodeURIComponent(t.blog_type || 'hype_cycle'); var title = (t.title || '').replace(/'/g, "\\'").replace(/"/g, '"'); return '
' + '
' + '' + t.urgency + '' + '' + (t.source_type || '') + '
' + '
' + t.title + '
' + '
' + ((t.suggested_angle || t.description || '')).slice(0, 80) + '
' + '
'; }).join(''); }).catch(function() { grid.innerHTML = '
Hype Cycle
' + '
Comparison
' + '
Tutorial
'; }); }; // Auto-load hot topics when blog tab activates var origActivateTab = window.activateTab; if (origActivateTab) { window.activateTab = function(tabName) { origActivateTab(tabName); if (tabName === 'blog') loadHotTopics(); }; } })(); // Delete a single blog draft window.deleteBlogDraft = function(id, title) { if (!confirm('Delete "' + title + '"?')) return; fetch((window.API || '') + '/api/blog/' + id, { method: 'DELETE' }) .then(function(r) { return r.json(); }) .then(function(data) { if (data.success) { if (typeof showToast === 'function') showToast('Deleted', title); if (typeof loadBlogDrafts === 'function') loadBlogDrafts(); } }); }; // Delete all template drafts (keep LLM-generated ones) window.deleteAllTemplateDrafts = function() { if (!confirm('Delete ALL template drafts? LLM-generated articles will be kept.')) return; fetch((window.API || '') + '/api/blog').then(function(r) { return r.json(); }).then(function(data) { var templates = (data.drafts || []).filter(function(d) { return d.generated_by === 'tip-blog-engine-template' || !d.generated_by; }); var count = 0; templates.forEach(function(d) { fetch((window.API || '') + '/api/blog/' + d.id, { method: 'DELETE' }).then(function() { count++; if (count === templates.length && typeof loadBlogDrafts === 'function') loadBlogDrafts(); }); }); if (typeof showToast === 'function') showToast('Cleaning', 'Deleting ' + templates.length + ' template drafts...'); }); };