Merge pull request 'fix: LiveStats: show hard error when Ponder is unreachable (not silent skeletons) (#201)' (#238) from fix/issue-201 into master
This commit is contained in:
commit
1372207134
1 changed files with 24 additions and 2 deletions
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<div v-if="!error && stats" class="live-stats">
|
||||
<div v-if="stats" class="live-stats">
|
||||
<div class="live-header">
|
||||
<span class="live-dot" :class="{ 'live-dot-error': error }"></span>
|
||||
<span class="live-text">Live</span>
|
||||
|
|
@ -46,7 +46,7 @@
|
|||
</div>
|
||||
<div class="freshness">{{ error ? 'Connection lost' : `Updated ${secondsSinceUpdate}s ago` }}</div>
|
||||
</div>
|
||||
<div v-else-if="!error && !stats" class="live-stats">
|
||||
<div v-else-if="!error" class="live-stats">
|
||||
<div class="stats-grid">
|
||||
<div class="stat-item skeleton" v-for="i in 6" :key="i">
|
||||
<div class="stat-label skeleton-text"></div>
|
||||
|
|
@ -54,6 +54,9 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else class="live-stats live-stats-error" data-testid="livestats-error">
|
||||
<p class="error-message">Protocol data unavailable</p>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
|
|
@ -88,6 +91,8 @@ const changedStats = ref<Set<string>>(new Set());
|
|||
const secondsSinceUpdate = ref(0);
|
||||
let freshnessTicker: number | null = null;
|
||||
let changeTimeout: number | null = null;
|
||||
let loadingTimer: number | null = null;
|
||||
const LOADING_TIMEOUT_MS = 10_000; // escalate to error after 10s with no data
|
||||
|
||||
// Helper: safely convert a Wei BigInt string to ETH float
|
||||
function weiToEth(wei: string | null | undefined): number {
|
||||
|
|
@ -417,6 +422,7 @@ async function fetchStats() {
|
|||
stats.value = s;
|
||||
secondsSinceUpdate.value = 0;
|
||||
error.value = false;
|
||||
if (loadingTimer) { clearTimeout(loadingTimer); loadingTimer = null; }
|
||||
} else {
|
||||
throw new Error('No stats data');
|
||||
}
|
||||
|
|
@ -428,6 +434,10 @@ async function fetchStats() {
|
|||
}
|
||||
|
||||
onMounted(async () => {
|
||||
// Escalate to error state if no data arrives within the timeout window
|
||||
loadingTimer = window.setTimeout(() => {
|
||||
if (!stats.value) error.value = true;
|
||||
}, LOADING_TIMEOUT_MS);
|
||||
await fetchStats();
|
||||
fetchEthPrice();
|
||||
refreshInterval = window.setInterval(fetchStats, 30000); // Refresh every 30 seconds
|
||||
|
|
@ -440,6 +450,7 @@ onUnmounted(() => {
|
|||
if (ethPriceInterval) clearInterval(ethPriceInterval);
|
||||
if (freshnessTicker) clearInterval(freshnessTicker);
|
||||
if (changeTimeout) clearTimeout(changeTimeout);
|
||||
if (loadingTimer) clearTimeout(loadingTimer);
|
||||
});
|
||||
</script>
|
||||
|
||||
|
|
@ -610,4 +621,15 @@ onUnmounted(() => {
|
|||
background-position: 200% 0
|
||||
100%
|
||||
background-position: -200% 0
|
||||
|
||||
.live-stats-error
|
||||
display: flex
|
||||
align-items: center
|
||||
justify-content: center
|
||||
|
||||
.error-message
|
||||
font-size: 14px
|
||||
color: #f87171
|
||||
text-align: center
|
||||
letter-spacing: 0.3px
|
||||
</style>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue