Update web/index.html
Add Fulcrum status dashboard
This commit is contained in:
+230
-33
@@ -2,59 +2,256 @@
|
|||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<title>Munin Bitcoin</title>
|
<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>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
|
<main>
|
||||||
|
<h1>Munin Bitcoin</h1>
|
||||||
|
<p class="subtitle">Bitcoin watch-only wallet monitoring and label management</p>
|
||||||
|
|
||||||
<h1>Munin Bitcoin</h1>
|
<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>Service</h2>
|
<div class="row">
|
||||||
<p id="service">Loading...</p>
|
<span class="label">Fulcrum (Electrum server)</span>
|
||||||
|
<span id="fulcrum-status" class="status">
|
||||||
|
<span class="dot"></span>
|
||||||
|
<span>Checking...</span>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
<h2>Bitcoin Node</h2>
|
<div class="row">
|
||||||
<p id="bitcoinNode">Loading...</p>
|
<span class="label">Fulcrum endpoint</span>
|
||||||
|
<span id="fulcrum-url" class="value muted">Checking...</span>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
<h2>Wallet</h2>
|
<section class="card">
|
||||||
<p id="wallet">Loading...</p>
|
<div class="row">
|
||||||
|
<span class="label">Wallet</span>
|
||||||
|
<span id="wallet" class="value muted">Not configured</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
<h2>Statistics</h2>
|
<div class="row">
|
||||||
<p>Labels: <span id="labels">0</span></p>
|
<span class="label">Labels</span>
|
||||||
<p>Transactions: <span id="transactions">0</span></p>
|
<span id="labels" class="value">0</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
<h2>Last scan</h2>
|
<div class="row">
|
||||||
<p id="lastScan">Loading...</p>
|
<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>
|
||||||
|
|
||||||
<script>
|
<button type="button" onclick="loadStatus()">Refresh status</button>
|
||||||
fetch('/api/status')
|
|
||||||
.then(response => response.json())
|
|
||||||
.then(status => {
|
|
||||||
document.getElementById('service').textContent =
|
|
||||||
'🟢 ' + status.service;
|
|
||||||
|
|
||||||
document.getElementById('bitcoinNode').textContent =
|
<p id="error" class="error"></p>
|
||||||
status.bitcoinNode;
|
</section>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
function setStatus(element, text, state) {
|
||||||
|
element.className = `status ${state}`;
|
||||||
|
element.querySelector('span:last-child').textContent = text;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 =
|
document.getElementById('wallet').textContent =
|
||||||
status.wallet;
|
status.wallet || 'Not configured';
|
||||||
|
|
||||||
document.getElementById('labels').textContent =
|
document.getElementById('labels').textContent =
|
||||||
status.labels;
|
status.labels ?? 0;
|
||||||
|
|
||||||
document.getElementById('transactions').textContent =
|
document.getElementById('transactions').textContent =
|
||||||
status.transactions;
|
status.transactions ?? 0;
|
||||||
|
|
||||||
document.getElementById('lastScan').textContent =
|
document.getElementById('last-scan').textContent =
|
||||||
status.lastScan;
|
status.lastScan || 'Never';
|
||||||
})
|
} catch (error) {
|
||||||
.catch(error => {
|
setStatus(
|
||||||
document.getElementById('service').textContent =
|
document.getElementById('service-status'),
|
||||||
'🔴 Error loading status';
|
'Unavailable',
|
||||||
|
'disconnected',
|
||||||
|
);
|
||||||
|
|
||||||
console.error(error);
|
setStatus(
|
||||||
});
|
document.getElementById('fulcrum-status'),
|
||||||
</script>
|
'Unavailable',
|
||||||
|
'disconnected',
|
||||||
|
);
|
||||||
|
|
||||||
|
document.getElementById('fulcrum-url').textContent = 'Unavailable';
|
||||||
|
errorElement.textContent = 'Unable to retrieve service status.';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
loadStatus();
|
||||||
|
setInterval(loadStatus, 10000);
|
||||||
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
Reference in New Issue
Block a user