| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150 |
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>News MCP Dashboard</title>
- <link rel="stylesheet" href="/dashboard/style.css">
- <script src="https://cdn.jsdelivr.net/npm/htmx.org@1.9.12"></script>
- <script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.4/dist/chart.umd.min.js"></script>
- </head>
- <body>
- <!-- TOP NAV -->
- <nav class="topnav">
- <div class="nav-brand">📡 news-mcp dashboard</div>
- <div class="nav-links">
- <a href="#" onclick="switchView('health'); return false;" class="active" data-view="health">Health</a>
- <a href="#" onclick="switchView('clusters'); return false;" data-view="clusters">Clusters</a>
- <a href="#" onclick="switchView('sentiment'); return false;" data-view="sentiment">Sentiment</a>
- <a href="#" onclick="switchView('entities'); return false;" data-view="entities">Entities</a>
- <a href="#" onclick="switchView('detail'); return false;" data-view="detail">Detail</a>
- </div>
- <div class="nav-meta" id="nav-meta"></div>
- </nav>
- <!-- HEALTH VIEW -->
- <div id="view-health" class="view active">
- <div class="card">
- <h3>📊 System Status</h3>
- <div id="health-stats" class="stat-grid">
- <div class="stat-box"><div class="label">Total Clusters</div><div class="value blue" id="stat-clusters">—</div></div>
- <div class="stat-box"><div class="label">Total Entities</div><div class="value blue" id="stat-entities">—</div></div>
- <div class="stat-box"><div class="label">Data Fresh</div><div class="value" id="stat-fresh">—</div></div>
- <div class="stat-box"><div class="label">Last Refresh</div><div class="value" style="font-size:1rem" id="stat-refresh">—</div></div>
- </div>
- </div>
- <div class="grid grid-3" style="margin-top:1rem">
- <div class="card">
- <h3>📋 Topics Distribution</h3>
- <div class="chart-wrap"><canvas id="chart-topic-dist"></canvas></div>
- </div>
- <div class="card">
- <h3>📈 Sentiment Over Time (4h buckets)</h3>
- <div class="chart-wrap"><canvas id="chart-sentiment-overview"></canvas></div>
- </div>
- <div class="card">
- <h3>🔗 Feed Activity</h3>
- <div id="feed-status"><div class="loading">Loading…</div></div>
- </div>
- </div>
- </div>
- <!-- CLUSTERS VIEW -->
- <div id="view-clusters" class="view">
- <div class="card">
- <div class="toolbar">
- <div class="filters">
- <select id="cluster-topic" onchange="reloadClusters()">
- <option value="all">All Topics</option>
- <option value="crypto">Crypto</option>
- <option value="macro">Macro</option>
- <option value="regulation">Regulation</option>
- <option value="ai">AI</option>
- </select>
- <select id="cluster-hours" onchange="reloadClusters()">
- <option value="1">Last 1h</option>
- <option value="6">Last 6h</option>
- <option value="144" selected>Last 144h</option>
- <option value="72">Last 72h</option>
- </select>
- <input type="text" id="cluster-search" placeholder="Search headlines…" onkeyup="filterClusters()" />
- <span class="badge" id="cluster-total">—</span>
- </div>
- </div>
- <div id="cluster-table"></div>
- </div>
- </div>
- <!-- SENTIMENT VIEW -->
- <div id="view-sentiment" class="view">
- <div class="card">
- <div class="toolbar">
- <div class="filters">
- <select id="sentiment-topic" onchange="reloadSentiment()">
- <option value="all">All Topics</option>
- <option value="crypto">Crypto</option>
- <option value="macro">Macro</option>
- <option value="regulation">Regulation</option>
- <option value="ai">AI</option>
- </select>
- <select id="sentiment-hours" onchange="reloadSentiment()">
- <option value="6">6h</option>
- <option value="144" selected>144h</option>
- <option value="72">72h</option>
- <option value="168">7d</option>
- </select>
- <select id="sentiment-bucket" onchange="reloadSentiment()">
- <option value="1">1h buckets</option>
- <option value="4" selected>4h buckets</option>
- <option value="12">12h buckets</option>
- </select>
- </div>
- </div>
- <div class="chart-wrap"><canvas id="chart-sentiment"></canvas></div>
- <div id="sentiment-stats" class="sentiment-stats"></div>
- </div>
- </div>
- <!-- ENTITIES VIEW -->
- <div id="view-entities" class="view">
- <div class="grid grid-3">
- <div class="card card-wide">
- <h3>🔗 Top Entities <small class="muted">(24h mentions)</small></h3>
- <div id="entity-list"><div class="loading">Loading…</div></div>
- </div>
- <div class="card">
- <h3>📊 Entity Frequency</h3>
- <div class="chart-wrap"><canvas id="chart-entities"></canvas></div>
- </div>
- <div class="card">
- <h3>ℹ️ Entity Detail</h3>
- <div id="entity-detail"><p class="muted">Click an entity in the list to see details.</p></div>
- </div>
- </div>
- </div>
- <!-- DETAIL VIEW -->
- <div id="view-detail" class="view">
- <div class="card">
- <div class="toolbar">
- <input type="text" id="detail-search" placeholder="Paste cluster_id or search…" />
- <button onclick="searchDetail()">🔍 Search</button>
- </div>
- <div id="detail-content"><p class="muted">Select a cluster from <a href="#" onclick="switchView('clusters'); return false;">Clusters</a> or search by cluster ID.</p></div>
- </div>
- </div>
- <!-- DETAIL MODAL (cluster drill-down) -->
- <div id="cluster-modal" class="modal-overlay" onclick="closeModal()">
- <div class="modal" onclick="event.stopPropagation()">
- <button class="modal-close" onclick="closeModal()">✕</button>
- <div id="modal-content"><div class="loading">Loading…</div></div>
- </div>
- </div>
- <div id="toast" class="toast"></div>
- <script src="/dashboard/dashboard.js"></script>
- </body>
- </html>
|