Files
Yodmon/templates/index.html
Christoph Gasser 9fc3e97546 Initial commit: Yodmon Yodeck→Zabbix bridge
- Yodeck API poller (every 10 min, paginated, 310 players)
- SQLite persistence (players + activity logs)
- SNMP v2c agent via net-snmp pass_persist
- Zabbix API auto host creation/update (6.0+)
- Flask web dashboard with live player status and log
- Docker deployment with persistent volume
- dev_server.py for local testing without Docker

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-17 09:31:00 +02:00

151 lines
5.3 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Yodmon Yodeck Monitor</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css">
<meta http-equiv="refresh" content="60">
<style>
body { background: #f0f2f5; }
.stat-card { border: none; box-shadow: 0 1px 4px rgba(0,0,0,.08); }
.online { color: #198754; font-weight: 600; }
.offline { color: #dc3545; font-weight: 600; }
.badge-yodeck_fetch { background: #0d6efd; }
.badge-zabbix_sync { background: #6f42c1; }
.badge-snmp_transfer { background: #20c997; }
.badge-error { background: #dc3545; }
.scroll-table { max-height: 420px; overflow-y: auto; }
thead.sticky-top th { position: sticky; top: 0; z-index: 1; }
</style>
</head>
<body>
<nav class="navbar navbar-dark bg-dark mb-4 px-3">
<span class="navbar-brand fw-bold fs-5">Yodmon</span>
<span class="text-secondary small">Yodeck → Zabbix Bridge</span>
</nav>
<div class="container-fluid px-4">
<!-- Summary cards -->
<div class="row g-3 mb-4">
<div class="col-6 col-md-3">
<div class="card stat-card text-center py-3 h-100">
<div class="display-6 fw-bold text-primary">{{ total }}</div>
<div class="text-muted small">Total Players</div>
</div>
</div>
<div class="col-6 col-md-3">
<div class="card stat-card text-center py-3 h-100">
<div class="display-6 fw-bold text-success">{{ online }}</div>
<div class="text-muted small">Online</div>
</div>
</div>
<div class="col-6 col-md-3">
<div class="card stat-card text-center py-3 h-100">
<div class="display-6 fw-bold text-danger">{{ total - online }}</div>
<div class="text-muted small">Offline</div>
</div>
</div>
<div class="col-6 col-md-3">
<div class="card stat-card text-center py-3 h-100">
<div class="fs-6 fw-semibold text-secondary">
{% set last_fetch = logs | selectattr('event_type', 'equalto', 'yodeck_fetch') | first %}
{% if last_fetch %}{{ last_fetch.timestamp[:19] }} UTC{% else %}—{% endif %}
</div>
<div class="text-muted small">Last API Fetch</div>
</div>
</div>
</div>
<!-- Player table -->
<div class="card shadow-sm mb-4">
<div class="card-header d-flex justify-content-between align-items-center">
<span class="fw-semibold">Players</span>
<span class="badge bg-secondary">{{ total }}</span>
</div>
<div class="card-body p-0">
<div class="scroll-table">
<table class="table table-sm table-hover mb-0">
<thead class="table-dark sticky-top">
<tr>
<th>Yodeck ID</th>
<th>Name</th>
<th>Workspace</th>
<th>Type</th>
<th>Status</th>
<th>Last Seen (UTC)</th>
<th>Updating</th>
<th>Registered</th>
</tr>
</thead>
<tbody>
{% for p in players %}
<tr>
<td class="text-muted font-monospace">{{ p.id }}</td>
<td>{{ p.name }}</td>
<td>{{ p.workspace_name or '—' }}</td>
<td>{{ p.player_type or '—' }}</td>
<td>
{% if p.online %}
<span class="online">● Online</span>
{% else %}
<span class="offline">● Offline</span>
{% endif %}
</td>
<td class="font-monospace small">{{ (p.last_seen or '—')[:19] }}</td>
<td>{% if p.updating %}<span class="text-warning fw-semibold">Yes</span>{% else %}No{% endif %}</td>
<td>{% if p.registered %}<span class="text-success"></span>{% else %}<span class="text-danger"></span>{% endif %}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
<!-- Activity log -->
<div class="card shadow-sm mb-4">
<div class="card-header d-flex justify-content-between align-items-center">
<span class="fw-semibold">Activity Log</span>
<span class="badge bg-secondary">last 200</span>
</div>
<div class="card-body p-0">
<div class="scroll-table">
<table class="table table-sm table-hover mb-0">
<thead class="table-dark sticky-top">
<tr>
<th style="width:180px">Timestamp (UTC)</th>
<th style="width:160px">Event</th>
<th>Message</th>
</tr>
</thead>
<tbody>
{% for l in logs %}
<tr>
<td class="font-monospace small text-muted">{{ l.timestamp[:19] }}</td>
<td>
<span class="badge badge-{{ l.event_type }}">{{ l.event_type }}</span>
</td>
<td class="small">{{ l.message }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
</div>
<div class="text-center text-muted small pb-3">
Page auto-refreshes every 60 seconds &nbsp;|&nbsp;
<a href="/api/stats" class="text-muted">API: stats</a> &nbsp;
<a href="/api/players" class="text-muted">players</a> &nbsp;
<a href="/api/logs" class="text-muted">logs</a>
</div>
</body>
</html>