Server page restyled in the site's look
- Header with back button, server card with status badge, Listing card (expiry, days left, renewal window), Activity tiles, WeTime table in the home style - Inline CSS only; qrcode.min.js dropped (unused); bal.js pager renders prev / page / next buttons
This commit is contained in:
21
bal.js
21
bal.js
@@ -76,18 +76,19 @@ async function fetchDataAndPopulateTable(url,params,fnPopulateTable,downloadOpt,
|
||||
function make_paginator(){
|
||||
document.getElementById("chainth").innerHTML = chain;
|
||||
const pag = document.getElementById("paginator");
|
||||
|
||||
pag.appendChild(document.createTextNode("_"));
|
||||
pag.innerHTML = "";
|
||||
// prev (a plain, dimmed arrow on the first page), "page N", next
|
||||
if (page > 0) {
|
||||
pag.appendChild(createlink("<","?page="+paginator.prev));
|
||||
pag.appendChild(createlink("‹","?page="+paginator.prev));
|
||||
} else {
|
||||
const off = document.createElement("span");
|
||||
off.className = "pg-off"; off.innerHTML = "‹";
|
||||
pag.appendChild(off);
|
||||
}
|
||||
else{
|
||||
pag.appendChild(document.createTextNode("<"));
|
||||
}
|
||||
pag.appendChild(document.createTextNode("_"));
|
||||
pag.appendChild(document.createTextNode(page));
|
||||
pag.appendChild(document.createTextNode("_"));
|
||||
pag.appendChild(createlink(">","?page="+paginator.next));
|
||||
const lbl = document.createElement("span");
|
||||
lbl.className = "pg-label"; lbl.textContent = "page " + page;
|
||||
pag.appendChild(lbl);
|
||||
pag.appendChild(createlink("›","?page="+paginator.next));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
365
weinfo.html
365
weinfo.html
@@ -1,83 +1,207 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Bal Server List</title>
|
||||
<link rel="icon" href="Logo_nero.ico" type="image/x-icon">
|
||||
<script src="/qrcode.min.js"></script>
|
||||
<script src="/purify.min.js"></script>
|
||||
<script src="/bal.js"></script>
|
||||
</head>
|
||||
<style>
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
width: 100%;
|
||||
margin-top: 20px;
|
||||
}
|
||||
th, td {
|
||||
border: 1px solid #ddd;
|
||||
padding: 8px;
|
||||
text-align: left;
|
||||
}
|
||||
th {
|
||||
background-color: #f2f2f2;
|
||||
}
|
||||
tr:nth-child(even) {
|
||||
background-color: #f9f9f9;
|
||||
}
|
||||
span {
|
||||
margin-left:10px;
|
||||
}
|
||||
</style>
|
||||
<body>
|
||||
<div align="center">
|
||||
<a href="/"><img alt="BAL LOGO" src="/Logo_nero.png"></a>
|
||||
<h2 id="wename"> </h2>
|
||||
<h3 id="weinfo"> </h3>
|
||||
<h4 id="wechain"> </h4>
|
||||
<div id="wepayment" style="display:none;max-width:640px;margin:10px auto 18px;padding:10px 14px;border-radius:8px;font-weight:600"></div>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Will Executor — Server page</title>
|
||||
<meta name="robots" content="noindex">
|
||||
<link rel="icon" href="/Logo_nero.ico" type="image/x-icon">
|
||||
<script src="/purify.min.js"></script>
|
||||
<script src="/bal.js"></script>
|
||||
<!--
|
||||
Server detail page, restyled 2026-11-06 in the look of index.html (same colour
|
||||
variables and type). Deliberately light: inline CSS only, no new script
|
||||
(qrcode.min.js was loaded and never used, so it is gone). The data flow is
|
||||
unchanged: fetchDataAndPopulateTable (bal.js) reads /weinfodata/<chain>/<id>
|
||||
with ?page/?limit and draws the prev/next links into #paginator; the payment
|
||||
banner polls the same endpoint until the deposit is credited.
|
||||
-->
|
||||
<style>
|
||||
:root{
|
||||
--maxw:1120px;--radius:10px;
|
||||
--bg:#eef1f4;--panel:#ffffff;--ink:#1a2027;--muted:#5b6672;
|
||||
--line:#dfe4ea;--line-strong:#cbd2da;
|
||||
--accent:#2d6cdf;--accent-soft:#e6eefc;
|
||||
--ok:#1f9d57;--ok-soft:#e3f4ea;--off:#9aa4b0;--off-soft:#eceff3;
|
||||
--display:"Inter","Segoe UI",system-ui,-apple-system,sans-serif;
|
||||
--body:"Inter","Segoe UI",system-ui,-apple-system,sans-serif;
|
||||
--mono:ui-monospace,"SF Mono",Menlo,Consolas,monospace;
|
||||
--shadow:0 1px 2px rgba(20,30,50,.05);
|
||||
}
|
||||
*{box-sizing:border-box}
|
||||
html,body{margin:0}
|
||||
body{background:var(--bg);color:var(--ink);font-family:var(--body);font-size:15px;line-height:1.5}
|
||||
a{color:var(--accent)}
|
||||
.wrap{max-width:var(--maxw);margin:0 auto;padding:0 20px}
|
||||
.mono{font-family:var(--mono)}
|
||||
|
||||
header.hero{padding:28px 0 22px;border-bottom:1px solid var(--line);background:var(--panel)}
|
||||
.hero .wrap{display:flex;align-items:center;justify-content:space-between;gap:20px;flex-wrap:wrap}
|
||||
.brand{display:flex;align-items:center;gap:14px;text-decoration:none;color:inherit}
|
||||
.brand .mark{width:44px;height:44px;border-radius:12px;border:1px solid var(--line);display:flex;align-items:center;justify-content:center;background:#fff}
|
||||
.brand .mark img{width:30px;height:30px;display:block}
|
||||
.brand h1{font-family:var(--display);font-size:18px;font-weight:600;margin:0;letter-spacing:-.01em}
|
||||
.brand .sub{color:var(--muted);font-size:13px}
|
||||
.back-btn{display:inline-flex;align-items:center;gap:8px;padding:9px 14px;border-radius:10px;border:1px solid var(--line-strong);
|
||||
background:var(--panel);color:var(--accent);font-weight:600;font-size:14px;text-decoration:none;box-shadow:var(--shadow)}
|
||||
.back-btn:hover{border-color:var(--accent)}
|
||||
.back-btn svg{width:18px;height:18px}
|
||||
|
||||
main{padding:28px 0 40px}
|
||||
.card{background:var(--panel);border:1px solid var(--line);border-radius:var(--radius);box-shadow:var(--shadow);padding:22px 24px}
|
||||
.server .url{font-family:var(--mono);font-size:22px;font-weight:600;word-break:break-all;margin:0 0 6px}
|
||||
.server .info{color:var(--muted);margin:0 0 14px}
|
||||
.badges{display:flex;flex-wrap:wrap;gap:8px}
|
||||
.badge{display:inline-flex;align-items:center;gap:6px;font-size:12px;font-family:var(--mono);padding:4px 10px;border-radius:999px;
|
||||
background:var(--off-soft);color:var(--muted);border:1px solid var(--line)}
|
||||
.badge.ok{background:var(--ok-soft);color:var(--ok);border-color:#bfe3cd}
|
||||
.badge.ok::before{content:"";width:8px;height:8px;border-radius:50%;background:var(--ok)}
|
||||
.badge.bad{background:#fdecec;color:#b42318;border-color:#f5c2c0}
|
||||
.badge.bad::before{content:"";width:8px;height:8px;border-radius:50%;background:#b42318}
|
||||
|
||||
#wepayment{display:none;margin:16px 0 0;padding:10px 14px;border-radius:8px;font-weight:600;font-size:14px}
|
||||
|
||||
.grid2{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1.4fr);gap:20px;margin-top:20px}
|
||||
.sec-title{font-size:11px;letter-spacing:.12em;text-transform:uppercase;color:var(--accent);font-weight:600;margin:0 0 12px}
|
||||
.expiry .big{font-family:var(--display);font-size:32px;font-weight:600;line-height:1.1;margin:0}
|
||||
.expiry .days{color:var(--muted);font-size:13px;margin:2px 0 14px}
|
||||
.kv{display:grid;grid-template-columns:1fr 1fr;gap:10px 18px;font-size:13px}
|
||||
.kv div{display:flex;flex-direction:column;gap:2px;border-top:1px solid var(--line);padding-top:8px}
|
||||
.kv span{color:var(--muted)}
|
||||
.kv b{font-family:var(--mono);font-weight:600}
|
||||
.open{color:var(--ok)}
|
||||
.tiles{display:grid;grid-template-columns:repeat(3,1fr);gap:10px}
|
||||
.tile{border:1px solid var(--line);border-radius:8px;padding:12px 14px;background:var(--bg)}
|
||||
.tile .n{font-family:var(--display);font-size:22px;font-weight:600;line-height:1.1}
|
||||
.tile .l{font-size:11px;letter-spacing:.1em;text-transform:uppercase;color:var(--muted);margin-top:4px}
|
||||
.tile.wide{grid-column:1 / -1;display:flex;justify-content:space-between;align-items:center;gap:12px}
|
||||
.tile.wide .n{font-size:13px;font-family:var(--mono)}
|
||||
|
||||
.rounds{margin-top:20px;padding:0;overflow:hidden}
|
||||
.rounds .head{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap;padding:16px 24px;border-bottom:1px solid var(--line)}
|
||||
.rounds .head h2{font-family:var(--display);font-size:16px;margin:0}
|
||||
.rounds .head .note{color:var(--muted);font-size:13px}
|
||||
.pager{display:flex;align-items:center;gap:6px;font-family:var(--mono);font-size:13px;color:var(--muted)}
|
||||
#paginator a{display:inline-flex;align-items:center;justify-content:center;width:30px;height:30px;border:1px solid var(--line-strong);
|
||||
border-radius:8px;background:var(--panel);color:var(--ink);text-decoration:none;font-weight:600}
|
||||
#paginator a:hover{border-color:var(--accent);color:var(--accent)}
|
||||
.pg-off{display:inline-flex;align-items:center;justify-content:center;width:30px;height:30px;border:1px solid var(--line);border-radius:8px;color:var(--off)}
|
||||
.pg-label{padding:0 4px}
|
||||
.table-wrap{overflow-x:auto}
|
||||
table{border-collapse:collapse;width:100%;font-size:13px}
|
||||
th{font-family:var(--mono);font-size:11px;letter-spacing:.08em;text-transform:uppercase;color:var(--muted);text-align:left;
|
||||
padding:10px 14px;border-bottom:1px solid var(--line);background:#fafbfc;white-space:nowrap}
|
||||
td{padding:10px 14px;border-bottom:1px solid var(--line);white-space:nowrap;vertical-align:top}
|
||||
tr:last-child td{border-bottom:0}
|
||||
td.num,th.num{text-align:right;font-family:var(--mono)}
|
||||
td.hash{font-family:var(--mono);color:var(--muted)}
|
||||
.pos-1{color:var(--ok);font-weight:600}
|
||||
.foot{display:flex;justify-content:space-between;align-items:center;gap:12px;flex-wrap:wrap;padding:14px 24px;border-top:1px solid var(--line);font-size:13px;color:var(--muted)}
|
||||
.btn-ghost{font:inherit;font-size:13px;text-decoration:none;padding:8px 12px;border-radius:8px;border:1px solid var(--line-strong);
|
||||
background:var(--panel);color:var(--ink);display:inline-flex;gap:7px;align-items:center}
|
||||
.btn-ghost:hover{border-color:var(--accent);color:var(--accent)}
|
||||
|
||||
footer{border-top:1px solid var(--line);margin-top:32px;padding:24px 0;color:var(--muted);font-size:13px}
|
||||
footer .wrap{display:flex;justify-content:space-between;flex-wrap:wrap;gap:12px}
|
||||
footer a{color:var(--accent);text-decoration:none}
|
||||
|
||||
@media (max-width:760px){
|
||||
.grid2{grid-template-columns:1fr}
|
||||
.tiles{grid-template-columns:repeat(2,1fr)}
|
||||
.server .url{font-size:18px}
|
||||
.expiry .big{font-size:28px}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<header class="hero">
|
||||
<div class="wrap">
|
||||
<a class="brand" href="/">
|
||||
<span class="mark"><img alt="Bitcoin After Life" src="/Logo_nero.png"></span>
|
||||
<span><h1>Will Executor — Server List</h1><span class="sub">Bitcoin After Life · server page</span></span>
|
||||
</a>
|
||||
<a class="back-btn" href="/"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M11 17l-5-5 5-5"/><path d="M6 12h6"/><path d="M15 6h4M15 12h4M15 18h4"/></svg>Back to the server list</a>
|
||||
</div>
|
||||
<div style="float:left;border:1;margin-right:50px;">
|
||||
<div><span>Version:</span><span id="weversion"> </span></div>
|
||||
<div><span>Fees:</span><span id="wefees"> </span></div>
|
||||
<div><span>Tld:</span><span id="wetld"> </span></div>
|
||||
<div><span>Last Update:</span><span id="weupdate"> </span></div>
|
||||
</header>
|
||||
|
||||
<main class="wrap">
|
||||
|
||||
<section class="card server">
|
||||
<p class="url" id="wename"> </p>
|
||||
<p class="info" id="weinfo"> </p>
|
||||
<div class="badges">
|
||||
<span class="badge" id="wechain"> </span>
|
||||
<span class="badge"><span>v</span><span id="weversion"> </span></span>
|
||||
<span class="badge" id="westatus-badge"><span id="westatus"> </span></span>
|
||||
</div>
|
||||
<div id="wepayment"></div>
|
||||
</section>
|
||||
|
||||
<div class="grid2">
|
||||
<section class="card expiry">
|
||||
<p class="sec-title">Listing</p>
|
||||
<p class="big" id="weexpiry"> </p>
|
||||
<p class="days" id="wedays"> </p>
|
||||
<div class="kv">
|
||||
<div><span>Renewal window</span><b id="wewindow">—</b></div>
|
||||
<div><span>Balance</span><b id="webalance">—</b></div>
|
||||
<div><span>Donations</span><b id="wedonations">—</b></div>
|
||||
<div><span>Domain</span><b id="wetld">—</b></div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="card">
|
||||
<p class="sec-title">Activity</p>
|
||||
<div class="tiles">
|
||||
<div class="tile"><div class="n" id="wepoints">—</div><div class="l">Points</div></div>
|
||||
<div class="tile"><div class="n" id="wewin">—</div><div class="l">Wins</div></div>
|
||||
<div class="tile"><div class="n" id="wefees">—</div><div class="l">Fee (sats)</div></div>
|
||||
<div class="tile"><div class="n" id="weheight">—</div><div class="l">Height</div></div>
|
||||
<div class="tile wide"><div class="l" style="margin:0">Last update</div><div class="n" id="weupdate">—</div></div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
<div style="float:left;border:1;margin-right:50px;">
|
||||
<div><span>Height:</span><span id="weheight"> </span></div>
|
||||
<div><span>Points:</span><span id="wepoints"> </span></div>
|
||||
<div><span>Win:</span><span id="wewin"> </span></div>
|
||||
|
||||
<section class="card rounds">
|
||||
<div class="head">
|
||||
<div><h2>WeTime rounds</h2><div class="note">Each round: the block hash sent by this server and how fast it was. Chain: <span class="mono" id="chainth"></span></div></div>
|
||||
<div class="pager"><span id="paginator"></span></div>
|
||||
</div>
|
||||
<div class="table-wrap">
|
||||
<table id="wetimes">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="num">Height</th>
|
||||
<th>Block hash</th>
|
||||
<th>Time</th>
|
||||
<th class="num">Delay</th>
|
||||
<th class="num">Position</th>
|
||||
<th class="num">Participants</th>
|
||||
<th class="num">Points</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody><!-- rows from the script --></tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="foot">
|
||||
<span>Points reward fast answers within the same block; they only break ties in the list.</span>
|
||||
<a class="btn-ghost" href="" id="download">↓ Download JSON</a>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
</main>
|
||||
|
||||
<footer>
|
||||
<div class="wrap">
|
||||
<span>Bitcoin After Life — Will Executor List</span>
|
||||
<a href="/">← Server list</a>
|
||||
<a href="/terms.html">Terms</a>
|
||||
<a href="mailto:welist@bitcoin-after.life">welist@bitcoin-after.life</a>
|
||||
</div>
|
||||
<div style="border:1;margin-right:50px;">
|
||||
<div><span>Balance:</span><span id="webalance"> </span></div>
|
||||
<div><span>Donations:</span><span id="wedonations"> </span></div>
|
||||
<div><span>Status:</span><span id="westatus"> </span></div>
|
||||
<div><span>Expiry:</span><span id="weexpiry"> </span></div>
|
||||
</div>
|
||||
<div>
|
||||
<table id="wetimes">
|
||||
<thead>
|
||||
<tr>
|
||||
<th colspan=5><span id="chainth"><!-- --></span>: <span id="paginator"></span></th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>height</th>
|
||||
<th>block hash</th>
|
||||
<th>time</th>
|
||||
<th>diff</th>
|
||||
<th>position</th>
|
||||
<th>participants</th>
|
||||
<th>points</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<!-- -->
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<a href="" id="download">Download</a>
|
||||
<script type="text/javascript">
|
||||
</footer>
|
||||
|
||||
<script type="text/javascript">
|
||||
// Payment banner: this page has a fixed address, so whoever paid can close the
|
||||
// invoice and follow the deposit here. It asks the server data every 30 seconds
|
||||
// until the server is listed. The status only moves forward, because
|
||||
@@ -87,6 +211,30 @@
|
||||
const paymentStarted = Date.now();
|
||||
let paymentTimer = null, paymentSeen = false, paymentAmount = 0, firstExpiry;
|
||||
|
||||
const fmt = n => (n != null ? Number(n).toLocaleString('en-US') : '—');
|
||||
const pad = n => String(n).padStart(2, '0');
|
||||
function fmtTime(d) {
|
||||
return d.getFullYear() + '-' + pad(d.getMonth() + 1) + '-' + pad(d.getDate()) + ' ' +
|
||||
pad(d.getHours()) + ':' + pad(d.getMinutes()) + ':' + pad(d.getSeconds());
|
||||
}
|
||||
|
||||
// Expiry card: the date big, the days left, the renewal window (from 6 months
|
||||
// before expiry, Terms Section 1).
|
||||
function showExpiry(expiryRaw) {
|
||||
const expiry = (expiryRaw || '').slice(0, 10);
|
||||
document.getElementById('weexpiry').textContent = expiry ? 'Expires ' + expiry : 'Not listed';
|
||||
const daysEl = document.getElementById('wedays');
|
||||
const winEl = document.getElementById('wewindow');
|
||||
if (!expiry) { daysEl.textContent = 'No listing time: see the Terms to get listed.'; winEl.textContent = '—'; winEl.className = ''; return; }
|
||||
const exp = new Date(expiry + 'T00:00:00Z');
|
||||
const win = new Date(exp); win.setUTCMonth(win.getUTCMonth() - 6);
|
||||
const days = Math.ceil((exp - Date.now()) / 86400000);
|
||||
daysEl.textContent = days > 0 ? days + ' days of listing left' : 'Listing expired';
|
||||
const open = Date.now() >= win.getTime() && days > 0;
|
||||
winEl.textContent = open ? 'open now' : 'opens on ' + win.toISOString().slice(0, 10);
|
||||
winEl.className = open ? 'open' : '';
|
||||
}
|
||||
|
||||
function showPayment(text, ok) {
|
||||
const box = document.getElementById('wepayment');
|
||||
box.textContent = text;
|
||||
@@ -116,12 +264,10 @@
|
||||
if (firstExpiry === undefined) firstExpiry = expiry;
|
||||
const unconfirmed = Number(data.unconfirmed_balance) > 0;
|
||||
const active = expiry && new Date(expiry.replace(' ', 'T') + 'Z') > new Date();
|
||||
const bal = data.balance != null ? data.balance : null;
|
||||
const unc = data.unconfirmed_balance != null ? data.unconfirmed_balance : null;
|
||||
const bal = data.balance != null ? fmt(data.balance) : null;
|
||||
const unc = data.unconfirmed_balance != null ? fmt(data.unconfirmed_balance) : null;
|
||||
document.getElementById('webalance').textContent = bal ? (unc ? bal + ' (' + unc + ')' : bal) : '—';
|
||||
const expiryCell = document.createElement('b');
|
||||
expiryCell.textContent = expiry || '—';
|
||||
document.getElementById('weexpiry').replaceChildren(expiryCell);
|
||||
showExpiry(expiry);
|
||||
if (expiry && expiry !== firstExpiry) {
|
||||
showPayment('✓ Payment confirmed: this server is now listed.', true);
|
||||
stopPayment();
|
||||
@@ -147,21 +293,22 @@
|
||||
const chain = path[1];
|
||||
const cdate=new Date().toISOString().replace(/[-:T.Z]/g, '').slice(0, 14);
|
||||
fetchDataAndPopulateTable('/weinfodata/'+chain+"/"+we_id, new URLSearchParams(),(data) => {
|
||||
document.getElementById('wename').innerHTML = DOMPurify.sanitize(data.url||'—');
|
||||
document.getElementById('wechain').innerHTML = DOMPurify.sanitize(data.chain||'—');
|
||||
document.getElementById('weinfo').innerHTML = DOMPurify.sanitize(data.info||'—');
|
||||
document.getElementById('wefees').innerHTML = data.base_fee != null ? data.base_fee : '—';
|
||||
document.getElementById('weheight').innerHTML = data.last_block != null ? data.last_block : '—';
|
||||
document.getElementById('wepoints').innerHTML = data.points != null ? data.points : '—';
|
||||
document.getElementById('wewin').innerHTML = data.count_win != null ? data.count_win : '—';
|
||||
document.getElementById('wetld').innerHTML = DOMPurify.sanitize(data.tld||'—');
|
||||
const bal = data.balance != null ? data.balance : null;
|
||||
const unc = data.unconfirmed_balance != null ? data.unconfirmed_balance : null;
|
||||
document.getElementById('webalance').innerHTML = bal ? (unc ? bal + ' (' + unc + ')' : bal) : '—';
|
||||
document.getElementById('wedonations').innerHTML = data.donation != null ? data.donation : '—';
|
||||
document.getElementById('weversion').innerHTML = data.version||'—';
|
||||
document.getElementById('weexpiry').innerHTML = '<b>' + (data.expiry_date || '—') + '</b>';
|
||||
document.getElementById('weupdate').innerHTML = data.last_update || '—';
|
||||
document.getElementById('wename').textContent = data.url || '—';
|
||||
document.title = (data.url || 'Server') + ' — Will Executor';
|
||||
document.getElementById('wechain').textContent = data.chain || chain;
|
||||
document.getElementById('weinfo').textContent = data.info || '';
|
||||
document.getElementById('wefees').textContent = fmt(data.base_fee);
|
||||
document.getElementById('weheight').textContent = fmt(data.last_block);
|
||||
document.getElementById('wepoints').textContent = fmt(data.points);
|
||||
document.getElementById('wewin').textContent = fmt(data.count_win);
|
||||
document.getElementById('wetld').textContent = data.tld || '—';
|
||||
const bal = data.balance != null ? fmt(data.balance) : null;
|
||||
const unc = data.unconfirmed_balance != null ? fmt(data.unconfirmed_balance) : null;
|
||||
document.getElementById('webalance').textContent = bal ? (unc ? bal + ' (' + unc + ')' : bal) : '—';
|
||||
document.getElementById('wedonations').textContent = fmt(data.donation);
|
||||
document.getElementById('weversion').textContent = data.version || '—';
|
||||
document.getElementById('weupdate').textContent = data.last_update || '—';
|
||||
showExpiry(data.expiry_date);
|
||||
const statusMap = {
|
||||
'OK': 'Health check passed',
|
||||
'TIMEOUT': 'Connection timeout',
|
||||
@@ -174,7 +321,8 @@
|
||||
'KO': 'Generic error'
|
||||
};
|
||||
const st = (data.status||'').split(':')[0];
|
||||
document.getElementById('westatus').innerHTML = statusMap[st] || '—';
|
||||
document.getElementById('westatus').textContent = statusMap[st] || (data.status ? 'Unknown status' : '—');
|
||||
document.getElementById('westatus-badge').className = 'badge ' + (st === 'OK' ? 'ok' : (st ? 'bad' : ''));
|
||||
|
||||
const tableBody = document.querySelector('#wetimes tbody');
|
||||
tableBody.innerHTML ='';
|
||||
@@ -182,19 +330,22 @@
|
||||
Object.entries(data.times).forEach(([key,wetime]) => {
|
||||
const row = document.createElement('tr');
|
||||
const d = new Date(wetime.time/1000);
|
||||
const hash = DOMPurify.sanitize(wetime.blockHash||'');
|
||||
const short = hash.length > 20 ? hash.slice(0, 10) + '…' + hash.slice(-8) : (hash || '—');
|
||||
const pos = wetime.position != null ? wetime.position + 1 : null;
|
||||
row.innerHTML = `
|
||||
<td>${wetime.blockHeight != null ? wetime.blockHeight : '—'}</td>
|
||||
<td>${DOMPurify.sanitize(wetime.blockHash||'—')}</td>
|
||||
<td>${d}</td>
|
||||
<td>${wetime.diff != null ? wetime.diff/1000000 + ' s' : '—'}</td>
|
||||
<td>${wetime.position != null ? wetime.position+1 : '—'}</td>
|
||||
<td>${wetime.participants != null ? wetime.participants : '—'}</td>
|
||||
<td>${wetime.points != null ? wetime.points : '—'}</td>
|
||||
<td class="num">${wetime.blockHeight != null ? fmt(wetime.blockHeight) : '—'}</td>
|
||||
<td class="hash" title="${hash}">${short}</td>
|
||||
<td>${fmtTime(d)}</td>
|
||||
<td class="num">${wetime.diff != null ? (wetime.diff/1000000).toFixed(3) + ' s' : '—'}</td>
|
||||
<td class="num ${pos === 1 ? 'pos-1' : ''}">${pos != null ? '#' + pos : '—'}</td>
|
||||
<td class="num">${wetime.participants != null ? wetime.participants : '—'}</td>
|
||||
<td class="num">${wetime.points != null ? wetime.points : '—'}</td>
|
||||
`;
|
||||
tableBody.appendChild(row);
|
||||
});
|
||||
} else {
|
||||
tableBody.innerHTML = '<tr><td colspan="7" style="padding:20px;text-align:center;color:#999">No rounds yet.</td></tr>';
|
||||
tableBody.innerHTML = '<tr><td colspan="7" style="padding:24px;text-align:center;color:var(--muted)">No rounds yet.</td></tr>';
|
||||
}
|
||||
var prev=0;
|
||||
var next=0;
|
||||
@@ -209,9 +360,9 @@
|
||||
const paginator = {prev:prev,next:next};
|
||||
return paginator;
|
||||
},{elementName:"download",fileName:"weinfo_"+cdate+".json",linkText:"download"})
|
||||
}
|
||||
}
|
||||
|
||||
getWeInfo();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Reference in New Issue
Block a user