a99b6b54c7
Show a colour-coded pie chart (red=critical, yellow=warning, green=ok) to the left of the clock in the nav bar. Backed by a new GET /api/0/alert_summary endpoint that counts hosts per alert level for the current user's visible hosts. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
97 lines
3.4 KiB
HTML
97 lines
3.4 KiB
HTML
<div class="nav">
|
|
<button class="nav-hamburger" id="nav-hamburger-btn" aria-label="Menu" aria-expanded="false">
|
|
<span></span><span></span><span></span>
|
|
</button>
|
|
<div class="nav-links" id="nav-links">
|
|
<a href="/live"{% if active_page == "live" %} class="active"{% endif %}>Live Dashboard</a>
|
|
<a href="/plugins"{% if active_page == "plugins" %} class="active"{% endif %}>Host Overview</a>
|
|
<a href="/alerts"{% if active_page == "alerts" %} class="active"{% endif %}>Alerts</a>
|
|
{% if current_user and current_user.admin %}
|
|
<a href="/settings"{% if active_page == "settings" %} class="active"{% endif %}>Settings</a>
|
|
{% endif %}
|
|
<a href="/about"{% if active_page == "about" %} class="active"{% endif %}>About</a>
|
|
</div>
|
|
<div class="nav-pie" title="Host alert status">
|
|
<canvas id="alert-pie" width="44" height="44"></canvas>
|
|
</div>
|
|
<div class="nav-clock" title="Click for full-screen clock">
|
|
<canvas id="swiss-clock" width="44" height="44"></canvas>
|
|
</div>
|
|
{% if current_user %}
|
|
<a href="/profile" class="nav-user{% if active_page == 'profile' %} active{% endif %}" title="{{ current_user.full_name or current_user.username }}">
|
|
{% if current_user.avatar %}
|
|
<img class="nav-avatar" src="{{ current_user.avatar_url }}" alt="{{ current_user.full_name or current_user.username }}">
|
|
{% else %}
|
|
<span class="nav-initials">{{ (current_user.full_name or current_user.username)[:1] | upper }}</span>
|
|
{% endif %}
|
|
<span class="nav-username">{{ current_user.full_name or current_user.username }}</span>
|
|
</a>
|
|
{% endif %}
|
|
</div>
|
|
|
|
<!-- Full-page clock overlay (click anywhere to dismiss) -->
|
|
<div id="clock-overlay">
|
|
<canvas id="swiss-clock-overlay" width="400" height="400"></canvas>
|
|
</div>
|
|
|
|
<script>
|
|
(function() {
|
|
var btn = document.getElementById('nav-hamburger-btn');
|
|
var links = document.getElementById('nav-links');
|
|
if (btn && links) {
|
|
btn.addEventListener('click', function() {
|
|
var open = links.classList.toggle('nav-open');
|
|
btn.setAttribute('aria-expanded', open ? 'true' : 'false');
|
|
});
|
|
}
|
|
})();
|
|
|
|
function drawAlertPie(critical, warning, ok) {
|
|
var canvas = document.getElementById('alert-pie');
|
|
if (!canvas) return;
|
|
var ctx = canvas.getContext('2d');
|
|
var SIZE = canvas.width;
|
|
var R = SIZE / 2;
|
|
ctx.clearRect(0, 0, SIZE, SIZE);
|
|
var total = critical + warning + ok;
|
|
if (total === 0) {
|
|
ctx.beginPath();
|
|
ctx.arc(R, R, R - 1, 0, Math.PI * 2);
|
|
ctx.fillStyle = '#ccc';
|
|
ctx.fill();
|
|
return;
|
|
}
|
|
var slices = [
|
|
{ value: critical, color: '#e53935' },
|
|
{ value: warning, color: '#ffb300' },
|
|
{ value: ok, color: '#43a047' }
|
|
];
|
|
var start = -Math.PI / 2;
|
|
slices.forEach(function(s) {
|
|
if (s.value === 0) return;
|
|
var sweep = (s.value / total) * Math.PI * 2;
|
|
ctx.beginPath();
|
|
ctx.moveTo(R, R);
|
|
ctx.arc(R, R, R - 1, start, start + sweep);
|
|
ctx.closePath();
|
|
ctx.fillStyle = s.color;
|
|
ctx.fill();
|
|
start += sweep;
|
|
});
|
|
}
|
|
|
|
function updateAlertPie() {
|
|
fetch('/api/0/alert_summary').then(function(r) {
|
|
if (!r.ok) return;
|
|
return r.json();
|
|
}).then(function(d) {
|
|
if (d) drawAlertPie(d.critical || 0, d.warning || 0, d.ok || 0);
|
|
}).catch(function() {});
|
|
}
|
|
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
updateAlertPie();
|
|
setInterval(updateAlertPie, 30000);
|
|
});
|
|
</script>
|