Paralleles WebGUI mit Kestrel, Token-Sicherung und SSE-Logs implementiert
This commit is contained in:
@@ -0,0 +1,225 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>PolyTrader Web</title>
|
||||
<link rel="stylesheet" href="/css/app.css">
|
||||
</head>
|
||||
<body>
|
||||
<header class="app-header">
|
||||
<div class="header-brand">
|
||||
<span>📈</span>
|
||||
<span>PolyTrader</span>
|
||||
<span style="font-size: 11px; padding: 2px 6px; background: var(--accent-soft); color: var(--accent); border-radius: 4px; font-weight: normal;">WebGUI</span>
|
||||
</div>
|
||||
|
||||
<nav class="header-nav">
|
||||
<button class="nav-link active" onclick="switchView('dashboard')">Dashboard</button>
|
||||
<button class="nav-link" onclick="switchView('accounts')">Konten</button>
|
||||
<button class="nav-link" onclick="switchView('jobs')">Jobs</button>
|
||||
<button class="nav-link" onclick="switchView('logs')">Terminal / Logs</button>
|
||||
<button class="nav-link" onclick="switchView('modules')">Module</button>
|
||||
<button class="nav-link" onclick="switchView('settings')">Einstellungen</button>
|
||||
</nav>
|
||||
|
||||
<div class="header-actions">
|
||||
<div class="status-indicator" title="Polymarket / Alchemy Connection">
|
||||
<span class="dot" id="dotAlchemy"></span>
|
||||
<span>WSS</span>
|
||||
</div>
|
||||
<div class="status-indicator" title="Mullvad VPN Status">
|
||||
<span class="dot" id="dotVpn"></span>
|
||||
<span>VPN</span>
|
||||
</div>
|
||||
<div class="status-indicator" title="Watchdog Heartbeat">
|
||||
<span class="dot" id="dotWatchdog"></span>
|
||||
<span>Watchdog</span>
|
||||
</div>
|
||||
<button class="btn btn-secondary" style="padding: 4px 10px; font-size: 12px;" onclick="logout()">Abmelden</button>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<main class="app-main">
|
||||
<!-- VIEW: DASHBOARD -->
|
||||
<section id="view-dashboard" class="view-panel active">
|
||||
<div class="grid-4">
|
||||
<div class="card">
|
||||
<div class="card-title">Gesamt PnL</div>
|
||||
<div class="card-value" id="valGlobalPnl">0.00 $</div>
|
||||
<div class="card-sub">Über alle aktiven Module</div>
|
||||
</div>
|
||||
<div class="card">
|
||||
<div class="card-title">USDC Guthaben</div>
|
||||
<div class="card-value" id="valTotalUsdc">0.00 $</div>
|
||||
<div class="card-sub" id="valAccountCount">0 Konten aktiv</div>
|
||||
</div>
|
||||
<div class="card">
|
||||
<div class="card-title">Portfolio-Gesamtwert</div>
|
||||
<div class="card-value" id="valPortfolioValue">0.00 $</div>
|
||||
<div class="card-sub">Guthaben + Positionen</div>
|
||||
</div>
|
||||
<div class="card">
|
||||
<div class="card-title">Notfall-Pause</div>
|
||||
<button class="btn btn-danger" id="btnPause" style="width: 100%; margin-top: 6px;" onclick="togglePause()">
|
||||
Trading pausieren
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="grid-2">
|
||||
<div class="card">
|
||||
<div class="card-title">Live Trading Modus</div>
|
||||
<div style="font-size: 13px; color: var(--muted);">Echtgeld-Ausführung auf Polymarket</div>
|
||||
<div class="toggle-group" id="groupLiveTrading">
|
||||
<button class="btn-toggle" onclick="setTradingMode('live', 'Inactive')">Inaktiv</button>
|
||||
<button class="btn-toggle" onclick="setTradingMode('live', 'SellOnly')">Nur Verkauf</button>
|
||||
<button class="btn-toggle" onclick="setTradingMode('live', 'Active')">Aktiv</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<div class="card-title">Demo Trading Modus</div>
|
||||
<div style="font-size: 13px; color: var(--muted);">Papertrading und Simulation</div>
|
||||
<div class="toggle-group" id="groupDemoTrading">
|
||||
<button class="btn-toggle" onclick="setTradingMode('demo', 'Inactive')">Inaktiv</button>
|
||||
<button class="btn-toggle" onclick="setTradingMode('demo', 'SellOnly')">Nur Verkauf</button>
|
||||
<button class="btn-toggle" onclick="setTradingMode('demo', 'Active')">Aktiv</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- VIEW: ACCOUNTS -->
|
||||
<section id="view-accounts" class="view-panel">
|
||||
<h2 style="margin-bottom: 16px; font-size: 18px;">Polymarket Konten</h2>
|
||||
<div class="table-container">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>#</th>
|
||||
<th>Name</th>
|
||||
<th>Status</th>
|
||||
<th>Modus</th>
|
||||
<th>USDC Balance</th>
|
||||
<th>Portfolio-Wert</th>
|
||||
<th>Proxy Wallet</th>
|
||||
<th>Zuletzt aktualisiert</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="tblAccounts">
|
||||
<tr><td colspan="8" style="text-align: center; color: var(--muted);">Lade Konten …</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- VIEW: JOBS -->
|
||||
<section id="view-jobs" class="view-panel">
|
||||
<h2 style="margin-bottom: 16px; font-size: 18px;">Server Jobs & Hintergrund-Dienste</h2>
|
||||
<div class="table-container">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Job Name</th>
|
||||
<th>Beschreibung</th>
|
||||
<th>Aktiv</th>
|
||||
<th>Letzter Lauf</th>
|
||||
<th>Nächster Lauf</th>
|
||||
<th>Status</th>
|
||||
<th>Aktion</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="tblJobs">
|
||||
<tr><td colspan="7" style="text-align: center; color: var(--muted);">Lade Jobs …</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- VIEW: TERMINAL / LOGS -->
|
||||
<section id="view-logs" class="view-panel">
|
||||
<div class="terminal-window">
|
||||
<div class="terminal-toolbar">
|
||||
<div style="display: flex; gap: 10px; align-items: center;">
|
||||
<span style="font-weight: 600;">Echtzeit-Log Stream</span>
|
||||
<div class="status-indicator" style="padding: 2px 6px; font-size: 11px;">
|
||||
<span class="dot online" id="sseDot"></span>
|
||||
<span id="sseStatus">Verbunden</span>
|
||||
</div>
|
||||
</div>
|
||||
<div style="display: flex; gap: 10px; align-items: center;">
|
||||
<select id="logLevelFilter" class="form-input" style="padding: 4px 8px; font-size: 12px; width: auto;" onchange="applyLogFilter()">
|
||||
<option value="ALL">Alle Level</option>
|
||||
<option value="INFO">Info</option>
|
||||
<option value="WARNING">Warning</option>
|
||||
<option value="ERROR">Error</option>
|
||||
<option value="TRADE">Trade</option>
|
||||
</select>
|
||||
<label class="checkbox-label" style="font-size: 12px; color: var(--muted);">
|
||||
<input type="checkbox" id="chkAutoScroll" checked> Auto-Scroll
|
||||
</label>
|
||||
<button class="btn btn-secondary" style="padding: 4px 8px; font-size: 12px;" onclick="clearLogs()">Leeren</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="terminal-logs" id="logContainer"></div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- VIEW: MODULES -->
|
||||
<section id="view-modules" class="view-panel">
|
||||
<h2 style="margin-bottom: 16px; font-size: 18px;">Strategie- & Analyse-Module</h2>
|
||||
<div class="grid-2" id="modulesContainer">
|
||||
<div class="card"><div class="card-title">Lade Module …</div></div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- VIEW: SETTINGS -->
|
||||
<section id="view-settings" class="view-panel">
|
||||
<h2 style="margin-bottom: 16px; font-size: 18px;">WebGUI Anwendungseinstellungen</h2>
|
||||
<div class="card settings-form">
|
||||
<form id="settingsForm" onsubmit="saveSettings(event)">
|
||||
<div class="form-row">
|
||||
<label class="checkbox-label">
|
||||
<input type="checkbox" id="cfgEnabled">
|
||||
WebGUI Server aktiv
|
||||
</label>
|
||||
<div class="form-desc">Steuert, ob Kestrel beim Programmstart hochfährt.</div>
|
||||
</div>
|
||||
|
||||
<div class="form-row">
|
||||
<label for="cfgPort">Server-Port</label>
|
||||
<input type="number" id="cfgPort" class="form-input" min="1024" max="65535" required>
|
||||
<div class="form-desc">Standard ist 5001. Änderung wird nach dem nächsten Neustart aktiv.</div>
|
||||
</div>
|
||||
|
||||
<div class="form-row">
|
||||
<label class="checkbox-label">
|
||||
<input type="checkbox" id="cfgLocalOnly">
|
||||
Nur lokaler Zugriff (127.0.0.1)
|
||||
</label>
|
||||
<div class="form-desc">Wenn deaktiviert, ist das WebUI über alle Netzwerkschnittstellen (LAN/VPN) erreichbar.</div>
|
||||
</div>
|
||||
|
||||
<div class="form-row">
|
||||
<label for="cfgToken">Zugangs-Token</label>
|
||||
<div style="display: flex; gap: 8px;">
|
||||
<input type="text" id="cfgToken" class="form-input" style="font-family: var(--font-mono); font-size: 12px;" readonly>
|
||||
<button type="button" class="btn btn-secondary" onclick="copyToken()">Kopieren</button>
|
||||
<button type="button" class="btn btn-secondary" onclick="generateNewToken()">Neu generieren</button>
|
||||
</div>
|
||||
<div class="form-desc">Wird in appsettings.Local.json gespeichert. Bei leerem Token ist das WebUI gesperrt.</div>
|
||||
</div>
|
||||
|
||||
<div style="display: flex; gap: 10px; align-items: center; margin-top: 24px;">
|
||||
<button type="submit" class="btn btn-primary" id="btnSaveSettings">Einstellungen speichern</button>
|
||||
<span id="settingsStatusMsg" style="font-size: 13px; color: var(--positive); display: none;">✓ Gespeichert</span>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
|
||||
<script src="/js/app.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user