Add graph telemetry and remote signer login

This commit is contained in:
Dorian
2026-05-06 18:09:58 +01:00
parent aee42e9c5f
commit c77c74612d
16 changed files with 855 additions and 41 deletions

View File

@@ -16,6 +16,27 @@ const totalThs = computed(() => stats.snapshot?.pool.combinedHashrateThs ?? 0);
const miners = computed(() => stats.snapshot?.miners ?? []);
const errorMsg = computed(() => stats.error);
const upstreamErr = computed(() => stats.snapshot?.error);
const bestWorkByMiner = computed(() => {
const out: Record<string, number> = {};
for (let i = 1; i < stats.history.length; i += 1) {
const prev = stats.history[i - 1];
const next = stats.history[i];
if (!prev?.minerWork || !next?.minerWork || !prev.minerShares || !next.minerShares) continue;
for (const [key, work] of Object.entries(next.minerWork)) {
const shareDelta = (next.minerShares[key] ?? 0) - (prev.minerShares[key] ?? 0);
const workDelta = work - (prev.minerWork[key] ?? work);
if (shareDelta <= 0 || workDelta <= 0) continue;
out[key] = Math.max(out[key] ?? 0, workDelta / shareDelta);
}
}
return out;
});
const poolBestWork = computed(() => Math.max(0, ...Object.values(bestWorkByMiner.value)));
function minerKey(m: { nickname: string; authUsername: string; remoteHost: string }): string {
return m.nickname || m.authUsername || m.remoteHost;
}
</script>
<template>
@@ -30,13 +51,28 @@ const upstreamErr = computed(() => stats.snapshot?.error);
<PoolHero :snapshot="stats.snapshot" />
<section class="best panel">
<div>
<div class="label">best accepted calculation observed</div>
<strong class="glow-amber">
{{ poolBestWork > 0 ? poolBestWork.toLocaleString(undefined, { maximumFractionDigits: 2 }) : "collecting" }}
</strong>
</div>
<span class="muted">derived from accepted difficulty jumps while this browser has history</span>
</section>
<div class="grid-row">
<LotteryWidget :total-ths="totalThs" />
<ShareTicker :snapshot="stats.snapshot" />
</div>
<div class="miners">
<MinerCard v-for="m in miners" :key="m.authUsername || m.nickname" :miner="m" />
<MinerCard
v-for="m in miners"
:key="m.authUsername || m.nickname"
:miner="m"
:best-work="bestWorkByMiner[minerKey(m)]"
/>
<div v-if="!miners.length && !errorMsg" class="empty panel muted">
waiting for the first poll · the boards are warming up
</div>
@@ -58,6 +94,22 @@ const upstreamErr = computed(() => stats.snapshot?.error);
gap: 16px;
margin: 16px 0;
}
.best {
display: flex;
justify-content: space-between;
gap: 16px;
align-items: center;
margin-top: 16px;
}
.best strong {
display: block;
margin-top: 4px;
font-size: 24px;
}
.best span {
font-size: 11px;
text-align: right;
}
.miners {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
@@ -70,5 +122,12 @@ const upstreamErr = computed(() => stats.snapshot?.error);
}
@media (max-width: 800px) {
.grid-row { grid-template-columns: 1fr; }
.best {
align-items: flex-start;
flex-direction: column;
}
.best span {
text-align: left;
}
}
</style>