busylight_modular/templates/dashboard.html
Christian Mueller 8a578fbe8d feat: compact dashboard + login system for admin pages
Dashboard:
- Much smaller cards (col-xl-2), compact badges
- Short labels (Buero, HO, DND, OoO, etc.)
- Optimized for small screens

Login:
- Password-protected admin pages (all except dashboard)
- Dashboard remains public (read-only status view)
- Login page with redirect back to requested page
- Session cookie (24h, regenerated on restart)
- Password set via Settings page (SHA256 hashed)
- Sidebar shows only Dashboard when not logged in
- Login/Logout link in sidebar footer

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-24 13:48:58 +02:00

103 lines
4.8 KiB
HTML

{% extends "base.html" %}
{% block title %}Dashboard - Busylight{% endblock %}
{% block content %}
<div class="d-flex justify-content-between align-items-center mb-3">
<h5 class="mb-0">Dashboard</h5>
<div>
<form method="post" action="/api/poll" class="d-inline">
<button type="submit" class="btn btn-sm btn-outline-primary py-0">
<i class="bi bi-arrow-clockwise"></i> Abfragen
</button>
</form>
<small class="text-muted ms-2" id="last-update"></small>
</div>
</div>
{% if not authenticated %}
<div class="alert alert-warning py-2 mb-3">
<small><i class="bi bi-exclamation-triangle"></i> Azure nicht verbunden.
<a href="/settings">Einstellungen</a> pruefen.</small>
</div>
{% endif %}
{% if devices %}
<div class="row g-2">
{% for device in devices %}
<div class="col-sm-6 col-md-4 col-lg-3 col-xl-2">
<div class="card busylight-card h-100">
<div class="card-body p-2">
<div class="d-flex justify-content-between align-items-center mb-1">
<strong class="small">{{ device.name }}</strong>
</div>
{% for seg in device.segments|reverse %}
{% if seg.user %}
{% if seg.aida == '-' and seg.teams == '-' %}
<div class="seg-compact" style="background: #f0f0f0; border-left: 3px solid #ccc;">
<span class="seg-name">{{ seg.user }}</span>
<small class="text-muted"><i class="bi bi-hourglass-split"></i></small>
</div>
{% else %}
<div class="seg-compact" style="background: rgba({{ seg.r }}, {{ seg.g }}, {{ seg.b }}, 0.15); border-left: 3px solid rgb({{ seg.r }}, {{ seg.g }}, {{ seg.b }});">
<span class="seg-name">{{ seg.user }}</span>
<div class="seg-badges">
{% if seg.aida == 'anwesend' %}
<span class="badge-sm bg-success">Buero</span>
{% elif seg.aida == 'abwesend' %}
<span class="badge-sm bg-secondary">Weg</span>
{% elif seg.aida == 'homeoffice' %}
<span class="badge-sm bg-warning text-dark">HO</span>
{% endif %}
{% if seg.teams != '-' %}
{% if 'available' in seg.teams %}
<span class="badge-sm bg-success">Frei</span>
{% elif 'busy' in seg.teams or 'inacall' in seg.teams or 'inameeting' in seg.teams %}
<span class="badge-sm bg-danger">Besetzt</span>
{% elif 'donotdisturb' in seg.teams %}
<span class="badge-sm" style="background:#8b00ff;color:#fff">DND</span>
{% elif 'away' in seg.teams or 'berightback' in seg.teams %}
<span class="badge-sm bg-warning text-dark">Weg</span>
{% elif 'presenting' in seg.teams %}
<span class="badge-sm bg-danger">Praes.</span>
{% elif 'offline' in seg.teams or 'inactive' in seg.teams or 'offwork' in seg.teams %}
<span class="badge-sm bg-secondary">Off</span>
{% elif 'outofoffice' in seg.teams %}
<span class="badge-sm bg-secondary">OoO</span>
{% endif %}
{% endif %}
{% if seg.phone %}
<span class="badge-sm bg-danger"><i class="bi bi-telephone-fill"></i></span>
{% endif %}
</div>
</div>
{% endif %}
{% else %}
<div class="seg-compact seg-empty">
<small class="text-muted">-- leer --</small>
</div>
{% endif %}
{% endfor %}
</div>
</div>
</div>
{% endfor %}
</div>
{% else %}
<div class="text-center py-5">
<i class="bi bi-lightbulb display-1 text-muted"></i>
<p class="text-muted mt-3">Noch keine Tuerschilder konfiguriert.</p>
<a href="/devices" class="btn btn-primary">Tuerschilder hinzufuegen</a>
</div>
{% endif %}
{% endblock %}
{% block scripts %}
<script>
setTimeout(() => location.reload(), 10000);
document.getElementById('last-update').textContent =
'Aktualisiert: ' + new Date().toLocaleTimeString('de-DE');
</script>
{% endblock %}