Update web/index.html
Add Fulcrum status dashboard
This commit is contained in:
+229
-32
@@ -2,59 +2,256 @@
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Munin Bitcoin</title>
|
||||
<style>
|
||||
:root {
|
||||
color-scheme: dark;
|
||||
font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
|
||||
background: #111827;
|
||||
color: #f9fafb;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
min-height: 100vh;
|
||||
background: #111827;
|
||||
}
|
||||
|
||||
main {
|
||||
max-width: 760px;
|
||||
margin: 0 auto;
|
||||
padding: 48px 24px;
|
||||
}
|
||||
|
||||
h1 {
|
||||
margin: 0 0 8px;
|
||||
font-size: 32px;
|
||||
}
|
||||
|
||||
.subtitle {
|
||||
margin: 0 0 32px;
|
||||
color: #9ca3af;
|
||||
}
|
||||
|
||||
.card {
|
||||
background: #1f2937;
|
||||
border: 1px solid #374151;
|
||||
border-radius: 12px;
|
||||
padding: 24px;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 16px;
|
||||
padding: 14px 0;
|
||||
border-bottom: 1px solid #374151;
|
||||
}
|
||||
|
||||
.row:last-child {
|
||||
border-bottom: 0;
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
.row:first-child {
|
||||
padding-top: 0;
|
||||
}
|
||||
|
||||
.label {
|
||||
color: #d1d5db;
|
||||
}
|
||||
|
||||
.value {
|
||||
text-align: right;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
.status {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.dot {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
border-radius: 50%;
|
||||
background: #6b7280;
|
||||
}
|
||||
|
||||
.status.connected .dot,
|
||||
.status.running .dot {
|
||||
background: #22c55e;
|
||||
}
|
||||
|
||||
.status.disconnected .dot {
|
||||
background: #ef4444;
|
||||
}
|
||||
|
||||
.muted {
|
||||
color: #9ca3af;
|
||||
}
|
||||
|
||||
.error {
|
||||
color: #fca5a5;
|
||||
}
|
||||
|
||||
button {
|
||||
margin-top: 16px;
|
||||
padding: 10px 16px;
|
||||
border: 0;
|
||||
border-radius: 8px;
|
||||
background: #374151;
|
||||
color: #f9fafb;
|
||||
cursor: pointer;
|
||||
font: inherit;
|
||||
}
|
||||
|
||||
button:hover {
|
||||
background: #4b5563;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<main>
|
||||
<h1>Munin Bitcoin</h1>
|
||||
<p class="subtitle">Bitcoin watch-only wallet monitoring and label management</p>
|
||||
|
||||
<h2>Service</h2>
|
||||
<p id="service">Loading...</p>
|
||||
<section class="card">
|
||||
<div class="row">
|
||||
<span class="label">Munin service</span>
|
||||
<span id="service-status" class="status">
|
||||
<span class="dot"></span>
|
||||
<span>Checking...</span>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<h2>Bitcoin Node</h2>
|
||||
<p id="bitcoinNode">Loading...</p>
|
||||
<div class="row">
|
||||
<span class="label">Fulcrum (Electrum server)</span>
|
||||
<span id="fulcrum-status" class="status">
|
||||
<span class="dot"></span>
|
||||
<span>Checking...</span>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<h2>Wallet</h2>
|
||||
<p id="wallet">Loading...</p>
|
||||
<div class="row">
|
||||
<span class="label">Fulcrum endpoint</span>
|
||||
<span id="fulcrum-url" class="value muted">Checking...</span>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<h2>Statistics</h2>
|
||||
<p>Labels: <span id="labels">0</span></p>
|
||||
<p>Transactions: <span id="transactions">0</span></p>
|
||||
<section class="card">
|
||||
<div class="row">
|
||||
<span class="label">Wallet</span>
|
||||
<span id="wallet" class="value muted">Not configured</span>
|
||||
</div>
|
||||
|
||||
<h2>Last scan</h2>
|
||||
<p id="lastScan">Loading...</p>
|
||||
<div class="row">
|
||||
<span class="label">Labels</span>
|
||||
<span id="labels" class="value">0</span>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<span class="label">Transactions</span>
|
||||
<span id="transactions" class="value">0</span>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<span class="label">Last scan</span>
|
||||
<span id="last-scan" class="value muted">Never</span>
|
||||
</div>
|
||||
|
||||
<button type="button" onclick="loadStatus()">Refresh status</button>
|
||||
|
||||
<p id="error" class="error"></p>
|
||||
</section>
|
||||
</main>
|
||||
|
||||
<script>
|
||||
fetch('/api/status')
|
||||
.then(response => response.json())
|
||||
.then(status => {
|
||||
document.getElementById('service').textContent =
|
||||
'🟢 ' + status.service;
|
||||
function setStatus(element, text, state) {
|
||||
element.className = `status ${state}`;
|
||||
element.querySelector('span:last-child').textContent = text;
|
||||
}
|
||||
|
||||
document.getElementById('bitcoinNode').textContent =
|
||||
status.bitcoinNode;
|
||||
async function loadStatus() {
|
||||
const errorElement = document.getElementById('error');
|
||||
errorElement.textContent = '';
|
||||
|
||||
try {
|
||||
const response = await fetch('/api/status');
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP ${response.status}`);
|
||||
}
|
||||
|
||||
const status = await response.json();
|
||||
|
||||
setStatus(
|
||||
document.getElementById('service-status'),
|
||||
status.service === 'running' ? 'Running' : 'Not running',
|
||||
status.service === 'running' ? 'running' : 'disconnected',
|
||||
);
|
||||
|
||||
const fulcrum = status.fulcrum || {};
|
||||
|
||||
if (fulcrum.connected) {
|
||||
setStatus(
|
||||
document.getElementById('fulcrum-status'),
|
||||
'Connected',
|
||||
'connected',
|
||||
);
|
||||
} else if (fulcrum.configured) {
|
||||
setStatus(
|
||||
document.getElementById('fulcrum-status'),
|
||||
'Not connected',
|
||||
'disconnected',
|
||||
);
|
||||
} else {
|
||||
setStatus(
|
||||
document.getElementById('fulcrum-status'),
|
||||
'Not configured',
|
||||
'disconnected',
|
||||
);
|
||||
}
|
||||
|
||||
document.getElementById('fulcrum-url').textContent =
|
||||
fulcrum.url || 'Not configured';
|
||||
|
||||
document.getElementById('wallet').textContent =
|
||||
status.wallet;
|
||||
status.wallet || 'Not configured';
|
||||
|
||||
document.getElementById('labels').textContent =
|
||||
status.labels;
|
||||
status.labels ?? 0;
|
||||
|
||||
document.getElementById('transactions').textContent =
|
||||
status.transactions;
|
||||
status.transactions ?? 0;
|
||||
|
||||
document.getElementById('lastScan').textContent =
|
||||
status.lastScan;
|
||||
})
|
||||
.catch(error => {
|
||||
document.getElementById('service').textContent =
|
||||
'🔴 Error loading status';
|
||||
document.getElementById('last-scan').textContent =
|
||||
status.lastScan || 'Never';
|
||||
} catch (error) {
|
||||
setStatus(
|
||||
document.getElementById('service-status'),
|
||||
'Unavailable',
|
||||
'disconnected',
|
||||
);
|
||||
|
||||
console.error(error);
|
||||
});
|
||||
setStatus(
|
||||
document.getElementById('fulcrum-status'),
|
||||
'Unavailable',
|
||||
'disconnected',
|
||||
);
|
||||
|
||||
document.getElementById('fulcrum-url').textContent = 'Unavailable';
|
||||
errorElement.textContent = 'Unable to retrieve service status.';
|
||||
}
|
||||
}
|
||||
|
||||
loadStatus();
|
||||
setInterval(loadStatus, 10000);
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user