Spaces:
Running
Running
Upload hub_dashboard.html
Browse files- hub_dashboard.html +52 -21
hub_dashboard.html
CHANGED
|
@@ -1612,12 +1612,12 @@ td.rc {
|
|
| 1612 |
<div id="nav-logo-text">QUA<em>SAR</em></div>
|
| 1613 |
</div>
|
| 1614 |
<div id="nav-links">
|
| 1615 |
-
<button class="nav-tab active" onclick="switchTab('rankings')">Rankings</button>
|
| 1616 |
-
<button class="nav-tab" onclick="switchTab('assets')">Assets</button>
|
| 1617 |
-
<button class="nav-tab" onclick="switchTab('trading')">Trading</button>
|
| 1618 |
-
<button class="nav-tab" onclick="switchTab('logs')">Logs</button>
|
| 1619 |
-
<button class="nav-tab" onclick="switchTab('telemetry')">Telemetry</button>
|
| 1620 |
-
<button class="nav-tab" onclick="switchTab('terminal')" style="color:#E8720A">β¬ Terminal</button>
|
| 1621 |
</div>
|
| 1622 |
<div id="nav-right">
|
| 1623 |
<div class="search-wrap">
|
|
@@ -1723,14 +1723,14 @@ td.rc {
|
|
| 1723 |
</div>
|
| 1724 |
|
| 1725 |
<div id="logs-filters">
|
| 1726 |
-
<button class="filter-btn active" onclick="filterLogs('all')">All</button>
|
| 1727 |
-
<button class="filter-btn" onclick="filterLogs('INFO')">Info</button>
|
| 1728 |
-
<button class="filter-btn" onclick="filterLogs('DEBUG')">Debug</button>
|
| 1729 |
-
<button class="filter-btn" onclick="filterLogs('WARNING')">Warning</button>
|
| 1730 |
-
<button class="filter-btn" onclick="filterLogs('ERROR')">Error</button>
|
| 1731 |
-
<button class="filter-btn" onclick="filterLogs('signal')">Signals</button>
|
| 1732 |
-
<button class="filter-btn" onclick="filterLogs('trade')">Trades</button>
|
| 1733 |
-
<button class="filter-btn" onclick="filterLogs('ranking')">Rankings</button>
|
| 1734 |
</div>
|
| 1735 |
|
| 1736 |
<div style="overflow-x: auto;">
|
|
@@ -2719,16 +2719,17 @@ const accChart = new Chart(document.getElementById('acc-chart'),{ type:'line', d
|
|
| 2719 |
/* ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 2720 |
TAB SWITCHING
|
| 2721 |
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ */
|
| 2722 |
-
function switchTab(tab) {
|
| 2723 |
document.querySelectorAll('.tab-panel').forEach(p => p.classList.remove('active'));
|
| 2724 |
document.querySelectorAll('.nav-tab').forEach(t => t.classList.remove('active'));
|
| 2725 |
-
|
| 2726 |
const tabEl = document.getElementById(tab + '-tab');
|
| 2727 |
if (tabEl) {
|
| 2728 |
tabEl.classList.add('active');
|
| 2729 |
}
|
| 2730 |
-
|
| 2731 |
-
event.
|
|
|
|
| 2732 |
|
| 2733 |
if (tab === 'logs') {
|
| 2734 |
loadRankerLogs();
|
|
@@ -2934,10 +2935,10 @@ async function loadLogStats() {
|
|
| 2934 |
}
|
| 2935 |
}
|
| 2936 |
|
| 2937 |
-
function filterLogs(filter) {
|
| 2938 |
_logFilter = filter;
|
| 2939 |
document.querySelectorAll('.filter-btn').forEach(btn => btn.classList.remove('active'));
|
| 2940 |
-
|
| 2941 |
loadRankerLogs();
|
| 2942 |
}
|
| 2943 |
|
|
@@ -2970,14 +2971,44 @@ setInterval(()=>{ document.getElementById('kpi-upd').textContent=_health.last_up
|
|
| 2970 |
let _trmEquityChart = null;
|
| 2971 |
let _trmEquityCurve = []; // running cumulative PnL
|
| 2972 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2973 |
async function updateTerminal() {
|
| 2974 |
let data;
|
| 2975 |
try {
|
| 2976 |
const res = await fetch('/api/trades');
|
| 2977 |
-
if (!res.ok) throw new Error('
|
| 2978 |
data = await res.json();
|
|
|
|
| 2979 |
} catch(e) {
|
| 2980 |
console.error('[Terminal] fetch error:', e);
|
|
|
|
| 2981 |
return;
|
| 2982 |
}
|
| 2983 |
|
|
|
|
| 1612 |
<div id="nav-logo-text">QUA<em>SAR</em></div>
|
| 1613 |
</div>
|
| 1614 |
<div id="nav-links">
|
| 1615 |
+
<button class="nav-tab active" onclick="switchTab(event,'rankings')">Rankings</button>
|
| 1616 |
+
<button class="nav-tab" onclick="switchTab(event,'assets')">Assets</button>
|
| 1617 |
+
<button class="nav-tab" onclick="switchTab(event,'trading')">Trading</button>
|
| 1618 |
+
<button class="nav-tab" onclick="switchTab(event,'logs')">Logs</button>
|
| 1619 |
+
<button class="nav-tab" onclick="switchTab(event,'telemetry')">Telemetry</button>
|
| 1620 |
+
<button class="nav-tab" onclick="switchTab(event,'terminal')" style="color:#E8720A">β¬ Terminal</button>
|
| 1621 |
</div>
|
| 1622 |
<div id="nav-right">
|
| 1623 |
<div class="search-wrap">
|
|
|
|
| 1723 |
</div>
|
| 1724 |
|
| 1725 |
<div id="logs-filters">
|
| 1726 |
+
<button class="filter-btn active" onclick="filterLogs(event,'all')">All</button>
|
| 1727 |
+
<button class="filter-btn" onclick="filterLogs(event,'INFO')">Info</button>
|
| 1728 |
+
<button class="filter-btn" onclick="filterLogs(event,'DEBUG')">Debug</button>
|
| 1729 |
+
<button class="filter-btn" onclick="filterLogs(event,'WARNING')">Warning</button>
|
| 1730 |
+
<button class="filter-btn" onclick="filterLogs(event,'ERROR')">Error</button>
|
| 1731 |
+
<button class="filter-btn" onclick="filterLogs(event,'signal')">Signals</button>
|
| 1732 |
+
<button class="filter-btn" onclick="filterLogs(event,'trade')">Trades</button>
|
| 1733 |
+
<button class="filter-btn" onclick="filterLogs(event,'ranking')">Rankings</button>
|
| 1734 |
</div>
|
| 1735 |
|
| 1736 |
<div style="overflow-x: auto;">
|
|
|
|
| 2719 |
/* ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 2720 |
TAB SWITCHING
|
| 2721 |
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ */
|
| 2722 |
+
function switchTab(evt, tab) {
|
| 2723 |
document.querySelectorAll('.tab-panel').forEach(p => p.classList.remove('active'));
|
| 2724 |
document.querySelectorAll('.nav-tab').forEach(t => t.classList.remove('active'));
|
| 2725 |
+
|
| 2726 |
const tabEl = document.getElementById(tab + '-tab');
|
| 2727 |
if (tabEl) {
|
| 2728 |
tabEl.classList.add('active');
|
| 2729 |
}
|
| 2730 |
+
|
| 2731 |
+
// Use the explicitly-passed event β never rely on deprecated window.event
|
| 2732 |
+
if (evt && evt.currentTarget) evt.currentTarget.classList.add('active');
|
| 2733 |
|
| 2734 |
if (tab === 'logs') {
|
| 2735 |
loadRankerLogs();
|
|
|
|
| 2935 |
}
|
| 2936 |
}
|
| 2937 |
|
| 2938 |
+
function filterLogs(evt, filter) {
|
| 2939 |
_logFilter = filter;
|
| 2940 |
document.querySelectorAll('.filter-btn').forEach(btn => btn.classList.remove('active'));
|
| 2941 |
+
if (evt && evt.currentTarget) evt.currentTarget.classList.add('active');
|
| 2942 |
loadRankerLogs();
|
| 2943 |
}
|
| 2944 |
|
|
|
|
| 2971 |
let _trmEquityChart = null;
|
| 2972 |
let _trmEquityCurve = []; // running cumulative PnL
|
| 2973 |
|
| 2974 |
+
// ββ Terminal error banner helpers ββββββββββββββββββββββββββββββββββββββββββ
|
| 2975 |
+
function _showTerminalError(msg) {
|
| 2976 |
+
let el = document.getElementById('trm-error-banner');
|
| 2977 |
+
if (!el) {
|
| 2978 |
+
el = document.createElement('div');
|
| 2979 |
+
el.id = 'trm-error-banner';
|
| 2980 |
+
el.style.cssText = [
|
| 2981 |
+
'background:rgba(255,68,102,0.12)',
|
| 2982 |
+
'border:1px solid rgba(255,68,102,0.4)',
|
| 2983 |
+
'border-radius:8px',
|
| 2984 |
+
'padding:14px 20px',
|
| 2985 |
+
'margin-bottom:var(--sp-lg)',
|
| 2986 |
+
'color:#ff4466',
|
| 2987 |
+
'font-size:0.8rem',
|
| 2988 |
+
'font-weight:600',
|
| 2989 |
+
'letter-spacing:0.02em',
|
| 2990 |
+
].join(';');
|
| 2991 |
+
const tab = document.getElementById('terminal-tab');
|
| 2992 |
+
if (tab) tab.insertBefore(el, tab.firstChild);
|
| 2993 |
+
}
|
| 2994 |
+
el.textContent = 'β ' + msg;
|
| 2995 |
+
el.style.display = '';
|
| 2996 |
+
}
|
| 2997 |
+
function _clearTerminalError() {
|
| 2998 |
+
const el = document.getElementById('trm-error-banner');
|
| 2999 |
+
if (el) el.style.display = 'none';
|
| 3000 |
+
}
|
| 3001 |
+
|
| 3002 |
async function updateTerminal() {
|
| 3003 |
let data;
|
| 3004 |
try {
|
| 3005 |
const res = await fetch('/api/trades');
|
| 3006 |
+
if (!res.ok) throw new Error('HTTP ' + res.status + ' β ensure hub_dashboard_service.py v2.0+ is deployed');
|
| 3007 |
data = await res.json();
|
| 3008 |
+
_clearTerminalError();
|
| 3009 |
} catch(e) {
|
| 3010 |
console.error('[Terminal] fetch error:', e);
|
| 3011 |
+
_showTerminalError('/api/trades unreachable: ' + e.message + '. Deploy the latest hub_dashboard_service.py.');
|
| 3012 |
return;
|
| 3013 |
}
|
| 3014 |
|