feat(ws): add connection status and last updated time

This commit is contained in:
Leons Aleksandrovs
2025-07-07 19:46:14 +03:00
parent f0c94fa3ee
commit 4d8cffa78f
5 changed files with 121 additions and 69 deletions

View File

@@ -1,62 +1,62 @@
[
{
"number": 43,
"timestamp": 1751904678378
},
{
"number": 44,
"timestamp": 1751904688400
},
{
"number": 50,
"timestamp": 1751904698413
},
{
"number": 55,
"timestamp": 1751904708422
},
{
"number": 52,
"timestamp": 1751904718446
},
{
"number": 45,
"timestamp": 1751904728342
},
{
"number": 73,
"timestamp": 1751904738349
},
{
"number": 45,
"timestamp": 1751904748375
},
{
"number": 45,
"timestamp": 1751904758402
},
{
"number": 49,
"timestamp": 1751904768420
},
{
"number": 71,
"timestamp": 1751904778446
},
{
"number": 62,
"timestamp": 1751904788455
},
{
"number": 46,
"timestamp": 1751904798494
},
{
"number": 46,
"timestamp": 1751904808488
"number": 76,
"timestamp": 1751906592502
},
{
"number": 63,
"timestamp": 1751904818496
"timestamp": 1751906602503
},
{
"number": 87,
"timestamp": 1751906612523
},
{
"number": 68,
"timestamp": 1751906622542
},
{
"number": 55,
"timestamp": 1751906632552
},
{
"number": 57,
"timestamp": 1751906642555
},
{
"number": 69,
"timestamp": 1751906652569
},
{
"number": 78,
"timestamp": 1751906662576
},
{
"number": 78,
"timestamp": 1751906672595
},
{
"number": 58,
"timestamp": 1751906682619
},
{
"number": 91,
"timestamp": 1751906692626
},
{
"number": 76,
"timestamp": 1751906702646
},
{
"number": 64,
"timestamp": 1751906712664
},
{
"number": 70,
"timestamp": 1751906722670
},
{
"number": 68,
"timestamp": 1751906732689
}
]

View File

@@ -1,19 +1,14 @@
<script setup>
import LineChart from './components/LineChart.vue';
import { ref, onMounted, onUnmounted } from 'vue';
import { tryCatchSync } from './utils/tryCatch.js';
import LineChart from './components/LineChart.vue';
import tryCatchSync from './utils/tryCatch';
import formatTimestamp from './utils/formatDate';
const data = ref([]); // Handles data
const connected = ref(false); // Stores connection state
let socket = null;
// Start WS connection
onMounted(connectWebSocket);
onUnmounted(() => {
// Close socket when component gets unmounted
if (socket) socket.close();
});
// Function for webhook connection handling
function connectWebSocket() {
// Connect to WebSocket server
socket = new WebSocket('/ws');
@@ -21,7 +16,6 @@
// Event on connection
socket.onopen = () => {
connected.value = true;
console.log('Connected to websocker');
};
// Event on data received
@@ -30,6 +24,7 @@
const { data: message, error: parseErr } = tryCatchSync(() => JSON.parse(event.data));
if (parseErr) {
console.error(`[WS] Error while parsing `, parseErr);
return;
}
// Load data initial data, or update it
@@ -47,27 +42,50 @@
data.value = data.value.slice(-15);
}
break;
default:
// No default behaviour for now
break;
}
};
// Event on socket close
socket.onclose = () => {
// Mark as disconnected, and retry connection in 5 seconds
connected.value = false;
console.warn('[WS] Disconnected, trying to reconnect in 5 seconds ...');
setTimeout(connectWebSocket, 5000);
};
// On socket error
socket.onerror = (err) => {
// Close socket on error, and print to console
console.error('[WS] Error: ', err);
socket.close();
};
}
// Start WS connection
onMounted(connectWebSocket);
onUnmounted(() => {
// Close socket when component gets unmounted
if (socket) socket.close();
});
</script>
<template>
<main class="container">
<h1 class="text-primary">Live data from WebSocket</h1>
<div class="connection-container">
<div :class="{ connected: connected }" class="circle" />
<p class="text-secondary">{{ connected ? 'Connected' : 'Disconnected' }}</p>
</div>
<div v-if="data.length > 0" class="update-container">
<p class="text-secondary">
Last update:
<span class="text-primary">{{ formatTimestamp(data[data.length - 1].timestamp) }}</span>
</p>
</div>
<LineChart :data="data" />
</main>
</template>
@@ -76,4 +94,31 @@
h1 {
text-align: center;
}
.update-container {
text-align: center;
}
.connection-container {
display: flex;
align-items: center;
justify-content: center;
gap: 8px;
.circle {
width: 15px;
height: 15px;
background-color: red;
border-radius: 100%;
}
.connected {
background-color: green;
}
p {
margin: 0;
}
}
</style>

View File

@@ -0,0 +1,5 @@
// Format timestamp into readable time
export default function formatTimestamp(timestamp) {
const date = new Date(timestamp);
return date.toLocaleString(); // or use toLocaleTimeString() for just the time
}

View File

@@ -1,9 +1,11 @@
// function for sync
export function tryCatchSync(callback) {
/**
* A simple try/catch wrapper for synchronous code
*/
export default function tryCatchSync(callback) {
try {
const data = callback();
return { data, error: null };
} catch (error) {
return { data: null, error: error };
return { data: null, error };
}
}