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

137 lines
6.5 KiB
HTML

{% extends "base.html" %}
{% block title %}Einstellungen - Busylight{% endblock %}
{% block content %}
<h4 class="mb-4">Einstellungen</h4>
{% if request.query_params.get('saved') %}
<div class="alert alert-success alert-dismissible fade show">
<i class="bi bi-check-circle"></i> Einstellungen gespeichert.
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
</div>
{% endif %}
<form method="post" action="/api/settings">
<div class="row g-4">
<!-- Azure AD -->
<div class="col-lg-6">
<div class="card">
<div class="card-header">
<h6 class="mb-0"><i class="bi bi-microsoft"></i> Azure AD / Microsoft Graph</h6>
</div>
<div class="card-body">
<div class="mb-3">
<label class="form-label">Client ID</label>
<input type="text" name="azure_client_id" class="form-control font-monospace"
value="{{ settings.azure_client_id }}">
</div>
<div class="mb-3">
<label class="form-label">Client Secret</label>
<input type="password" name="azure_client_secret" class="form-control font-monospace"
value="{{ settings.azure_client_secret }}">
</div>
<div class="mb-3">
<label class="form-label">Tenant ID</label>
<input type="text" name="azure_tenant_id" class="form-control font-monospace"
value="{{ settings.azure_tenant_id }}">
</div>
<div class="mb-3">
<label class="form-label">Auth Tenant</label>
<input type="text" name="azure_auth_tenant" class="form-control"
value="{{ settings.azure_auth_tenant }}">
</div>
<div class="mb-3">
<label class="form-label">Graph Scopes</label>
<input type="text" name="azure_scopes" class="form-control"
value="{{ settings.azure_scopes }}">
</div>
<div class="border rounded p-3 bg-light">
{% if authenticated %}
<i class="bi bi-check-circle text-success"></i>
<strong class="text-success">Authentifiziert</strong>
{% else %}
<i class="bi bi-x-circle text-danger"></i>
<strong class="text-danger">Nicht authentifiziert</strong>
<p class="small text-muted mt-2 mb-0">
Fuehre auf dem Server aus:<br>
<code>python app.py --auth</code>
</p>
{% endif %}
</div>
</div>
</div>
</div>
<!-- Polling & AIDA -->
<div class="col-lg-6">
<div class="card mb-4">
<div class="card-header">
<h6 class="mb-0"><i class="bi bi-clock"></i> Polling</h6>
</div>
<div class="card-body">
<div class="mb-3">
<label class="form-label">Abfrage-Intervall (Sekunden)</label>
<input type="number" name="poll_interval" class="form-control"
value="{{ settings.poll_interval }}" min="5" max="300">
</div>
</div>
</div>
<div class="card mb-4">
<div class="card-header">
<h6 class="mb-0"><i class="bi bi-shield-lock"></i> Zugangsschutz</h6>
</div>
<div class="card-body">
<div class="mb-3">
<label class="form-label">Admin-Passwort</label>
<input type="password" name="admin_password" class="form-control"
placeholder="Neues Passwort eingeben (leer = nicht aendern)">
{% if settings.admin_password %}
<small class="text-success"><i class="bi bi-check-circle"></i> Passwort ist gesetzt</small>
{% else %}
<small class="text-warning"><i class="bi bi-exclamation-triangle"></i> Kein Passwort gesetzt - alle Seiten sind frei zugaenglich</small>
{% endif %}
</div>
</div>
</div>
<div class="card">
<div class="card-header">
<h6 class="mb-0"><i class="bi bi-file-earmark-spreadsheet"></i> AIDA Zeiterfassung</h6>
</div>
<div class="card-body">
<div class="mb-3">
<label class="form-label">CSV-Pfad</label>
<input type="text" name="aida_csv_path" class="form-control font-monospace"
value="{{ settings.aida_csv_path }}"
placeholder="/mnt/zeiterfassung/Status.csv">
<small class="text-muted">Auf Linux z.B. via SMB-Mount</small>
</div>
<div class="mb-3">
<label class="form-label">Status: Anwesend</label>
<input type="text" name="aida_status_anwesend" class="form-control"
value="{{ settings.aida_status_anwesend }}">
</div>
<div class="mb-3">
<label class="form-label">Status: Abwesend</label>
<input type="text" name="aida_status_abwesend" class="form-control"
value="{{ settings.aida_status_abwesend }}">
</div>
<div class="mb-3">
<label class="form-label">Status: Homeoffice</label>
<input type="text" name="aida_status_homeoffice" class="form-control"
value="{{ settings.aida_status_homeoffice }}">
</div>
</div>
</div>
</div>
</div>
<div class="mt-4">
<button type="submit" class="btn btn-primary">
<i class="bi bi-check-lg"></i> Einstellungen speichern
</button>
</div>
</form>
{% endblock %}