Initial commit: Sentry-Emote system monitor
- Aggregator: Flask-based event broker with priority queue - Frontend: OLED-optimized UI with animations - Detectors: disk, cpu, memory, service, network - Unified entry point (sentry.py) with process management - Heartbeat TTL system for auto-clearing stale events Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
122
index.html
Normal file
122
index.html
Normal file
@@ -0,0 +1,122 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
|
||||
<title>Sentry-Emote</title>
|
||||
<style>
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
body {
|
||||
background: #000000;
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
font-family: monospace;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
#emote {
|
||||
font-size: 18vw;
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
transition: color 0.3s ease;
|
||||
}
|
||||
|
||||
#message {
|
||||
font-size: 4vw;
|
||||
margin-top: 2vh;
|
||||
opacity: 0.7;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* Breathing animation - slow pulse */
|
||||
.breathing {
|
||||
animation: breathe 3s ease-in-out infinite;
|
||||
}
|
||||
|
||||
@keyframes breathe {
|
||||
0%, 100% {
|
||||
opacity: 1;
|
||||
transform: scale(1);
|
||||
}
|
||||
50% {
|
||||
opacity: 0.7;
|
||||
transform: scale(0.98);
|
||||
}
|
||||
}
|
||||
|
||||
/* Shaking animation - rapid jitter for Critical */
|
||||
.shaking {
|
||||
animation: shake 0.15s linear infinite;
|
||||
}
|
||||
|
||||
@keyframes shake {
|
||||
0%, 100% { transform: translateX(0); }
|
||||
25% { transform: translateX(-5px); }
|
||||
75% { transform: translateX(5px); }
|
||||
}
|
||||
|
||||
/* Popping animation - scale up for Notifications */
|
||||
.popping {
|
||||
animation: pop 1s ease-in-out infinite;
|
||||
}
|
||||
|
||||
@keyframes pop {
|
||||
0%, 100% {
|
||||
transform: scale(1);
|
||||
}
|
||||
50% {
|
||||
transform: scale(1.08);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="emote" class="breathing">( ^_^)</div>
|
||||
<div id="message">Loading...</div>
|
||||
|
||||
<script>
|
||||
const emoteEl = document.getElementById('emote');
|
||||
const messageEl = document.getElementById('message');
|
||||
const POLL_INTERVAL = 2000;
|
||||
|
||||
async function fetchStatus() {
|
||||
try {
|
||||
const response = await fetch('/status');
|
||||
if (!response.ok) throw new Error('Failed to fetch');
|
||||
const data = await response.json();
|
||||
updateDisplay(data);
|
||||
} catch (err) {
|
||||
messageEl.textContent = 'Connection lost...';
|
||||
}
|
||||
}
|
||||
|
||||
function updateDisplay(data) {
|
||||
emoteEl.textContent = data.active_emote;
|
||||
emoteEl.style.color = data.color;
|
||||
messageEl.style.color = data.color;
|
||||
|
||||
// Show event message if available, otherwise show state
|
||||
const topEvent = data.active_events && data.active_events[0];
|
||||
messageEl.textContent = (topEvent && topEvent.message) || data.message;
|
||||
|
||||
// Update animation class
|
||||
emoteEl.className = '';
|
||||
if (data.animation) {
|
||||
emoteEl.classList.add(data.animation);
|
||||
}
|
||||
}
|
||||
|
||||
// Initial fetch and start polling
|
||||
fetchStatus();
|
||||
setInterval(fetchStatus, POLL_INTERVAL);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user