server/static/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>đđŠī¸ deepsentinel</title>
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;500&display=swap" rel="stylesheet">
<style>
body {
font-family: 'Roboto', sans-serif;
background-color: #1e1e1e;
color: #f5f5f5;
margin: 0;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
min-height: 100vh;
}
h1 {
color: #fff;
}
table {
border: 1px solid #444;
border-collapse: collapse;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
}
th,
td {
border: 1px solid #444;
padding: 12px 24px;
text-align: center;
}
th {
background-color: #333;
color: #d1d1d1;
font-size: 24px;
}
td {
font-size: 20px;
background-color: #282828;
color: #d1d1d1;
}
.loading {
color: #f0cc62;
font-size: 20px;
margin-bottom: 20px;
}
.loading::after {
content: '...';
animation: loadingDots 1.5s infinite;
}
@keyframes loadingDots {
0%,
20% {
content: '';
}
40% {
content: '.';
}
60% {
content: '..';
}
80%,
100% {
content: '...';
}
}
</style>
</head>
<body>
<h1>.deepsentinel dash.</h1>
<div id="loadingMessage" class="loading">Loading</div>
<table>
<thead>
<tr>
<th>Probe Name</th>
<th>Probe Status</th>
<th>Actions</th>
</tr>
</thead>
<tbody id="probeTable">
</tbody>
</table>
<script>
let token = getCookie('auth_token')
if (!token) {
window.location.href = '/';
}
const ws = new WebSocket(`ws://admin:${token}@${window.location.host}/dashws`);
const loadingMessage = document.getElementById('loadingMessage');
ws.onmessage = function (event) {
const data = JSON.parse(event.data);
const probeTable = document.getElementById('probeTable');
probeTable.innerHTML = ''; // Clear existing table rows
loadingMessage.style.display = 'none'; // Hide loading message
data.probes.forEach(probe => {
const row = probeTable.insertRow();
const cellName = row.insertCell(0);
const cellStatus = row.insertCell(1);
const cellActions = row.insertCell(2);
cellName.textContent = probe.name;
switch (probe.status) {
case 'normal':
cellStatus.style.color = '#4CAF50';
cellStatus.textContent = probe.status + ' â
';
break;
case 'degraded':
cellStatus.style.color = '#f0cc62';
cellStatus.textContent = probe.status + ' â ī¸';
break;
case 'failed':
case 'alertedLow':
case 'alertedHigh':
cellStatus.style.color = '#F44336';
cellStatus.textContent = probe.status + ' đ¨';
break;
default:
cellStatus.style.color = '#f5f5f5';
cellStatus.textContent = probe.status;
break;
}
const actionButton = document.createElement('button');
actionButton.textContent = 'Delete';
actionButton.onclick = function () {
let headers = new Headers();
headers.append('Authorization', `${token}`);
fetch(`/probe/${probe.name}`, {
method: 'DELETE',
headers: headers,
}).then(response => {
if (response.ok) {
console.log('Probe deleted successfully');
} else {
console.error('Failed to delete probe');
}
});
};
cellActions.appendChild(actionButton);
});
};
ws.onerror = function (event) {
console.error('WebSocket error:', event);
loadingMessage.textContent = 'Error loading data!';
};
ws.onclose = function (event) {
if (document.getElementById('probeTable').rows.length === 0) {
loadingMessage.textContent = 'Connection closed, no data received.';
}
};
function getCookie(name) {
var nameEQ = name + "=";
var ca = document.cookie.split(';');
for (var i = 0; i < ca.length; i++) {
var c = ca[i];
while (c.charAt(0) == ' ') c = c.substring(1, c.length);
if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length, c.length);
}
return null;
}
</script>
</body>
</html>