- Change Dark Mode accent from blue to purple (#a855f7) - Balance dark backgrounds to match Light Mode structure - bg-base: #1a1a1a (was #0f0f0f - too dark) - bg-surface: #212121 (more balanced) - Improved contrast and readability - Update borders to be more visible (12% vs 8% opacity) - Adjust agent colors for purple theme: - Orchestrator: Purple - Researcher: Green - Negotiator: Orange - AR Manager: Yellow - Update Settings description: 'Violett' instead of 'Blau' - Dark Mode now mirrors Light Mode balance (just inverted)
224 lines
9.6 KiB
HTML
224 lines
9.6 KiB
HTML
{% extends "base.html" %}
|
|
{% block title %}Einstellungen{% endblock %}
|
|
|
|
{% block content %}
|
|
<div class="page-header mb-4">
|
|
<h1 class="page-title">Einstellungen</h1>
|
|
<p class="page-subtitle text-muted">App-Design, Poller-Konfiguration & System-Status</p>
|
|
</div>
|
|
|
|
<div class="row g-4">
|
|
|
|
<!-- App-Einstellungen (Name & Theme) -->
|
|
<div class="col-lg-6">
|
|
<div class="card h-100">
|
|
<div class="card-header">
|
|
<span class="material-icons me-2" style="font-size:18px;vertical-align:middle">palette</span> App-Design
|
|
</div>
|
|
<div class="card-body">
|
|
<form method="POST">
|
|
<div class="mb-4">
|
|
<label class="form-label fw-semibold">App-Name</label>
|
|
<input type="text" class="form-control" name="app_name"
|
|
value="{{ app_name }}" placeholder="Frankenbot" required>
|
|
<div class="form-text">Der Name erscheint in der Navigation und im Browser-Tab.</div>
|
|
</div>
|
|
|
|
<div class="mb-4">
|
|
<label class="form-label fw-semibold">Design-Theme</label>
|
|
<select class="form-select" name="theme" required>
|
|
<option value="dark" {% if theme == 'dark' %}selected{% endif %}>Dark Mode (Violett)</option>
|
|
<option value="light" {% if theme == 'light' %}selected{% endif %}>Light Mode (Rot)</option>
|
|
</select>
|
|
<div class="form-text">
|
|
<strong>Dark Mode:</strong> Ausgewogene dunkle Grautöne mit violetten Akzenten<br>
|
|
<strong>Light Mode:</strong> Heller Hintergrund mit roten Akzenten
|
|
</div>
|
|
</div>
|
|
|
|
<div class="d-flex gap-2">
|
|
<button type="submit" class="btn btn-primary">Design speichern</button>
|
|
<a href="/settings" class="btn btn-outline-secondary">Zurücksetzen</a>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Poller-Einstellungen -->
|
|
<div class="col-lg-6">
|
|
<div class="card h-100">
|
|
<div class="card-header">
|
|
<span class="me-2">⏱</span> Email-Poller
|
|
</div>
|
|
<div class="card-body">
|
|
<form method="POST">
|
|
<div class="mb-4">
|
|
<label class="form-label fw-semibold">Poll-Intervall <span class="text-muted fw-normal">(Sekunden)</span></label>
|
|
<input type="number" class="form-control" name="poll_interval"
|
|
value="{{ poller_settings.poll_interval }}" min="10" max="3600" required>
|
|
<div class="form-text">Wie oft der Poller den IMAP-Eingang prüft. Aktuell: <strong>{{ poller_settings.poll_interval }}s</strong> ({{ (poller_settings.poll_interval / 60) | round(1) }} min)</div>
|
|
</div>
|
|
|
|
<div class="mb-4">
|
|
<label class="form-label fw-semibold">Failsafe-Fenster <span class="text-muted fw-normal">(Sekunden)</span></label>
|
|
<input type="number" class="form-control" name="failsafe_window"
|
|
value="{{ poller_settings.failsafe_window }}" min="30" max="86400" required>
|
|
<div class="form-text">
|
|
Wie lange ein Task laufen darf bevor er als hängend gilt und erneut verarbeitet wird.
|
|
Aktuell: <strong>{{ poller_settings.failsafe_window }}s</strong> ({{ (poller_settings.failsafe_window / 60) | round(1) }} min).
|
|
<span class="text-warning">Muss größer als das Poll-Intervall sein.</span>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="d-flex gap-2">
|
|
<button type="submit" class="btn btn-primary">Speichern</button>
|
|
<a href="/settings" class="btn btn-outline-secondary">Zurücksetzen</a>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Journal-Status -->
|
|
<div class="col-lg-6">
|
|
<div class="card h-100">
|
|
<div class="card-header">
|
|
<span class="me-2">📋</span> Email-Journal Status
|
|
</div>
|
|
<div class="card-body">
|
|
{% if journal_stats %}
|
|
<table class="table table-sm">
|
|
<thead>
|
|
<tr>
|
|
<th>Status</th>
|
|
<th class="text-end">Anzahl</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{% for status, count in journal_stats.items() %}
|
|
<tr>
|
|
<td>
|
|
{% if status == 'completed' %}
|
|
<span class="badge" style="background:var(--success)">✓ {{ status }}</span>
|
|
{% elif status == 'queued' %}
|
|
<span class="badge" style="background:var(--warning);color:#000">⏳ {{ status }}</span>
|
|
{% elif status == 'skipped' %}
|
|
<span class="badge" style="background:var(--text-muted)">— {{ status }}</span>
|
|
{% elif status == 'error' %}
|
|
<span class="badge" style="background:var(--danger)">✗ {{ status }}</span>
|
|
{% else %}
|
|
<span class="badge bg-secondary">{{ status }}</span>
|
|
{% endif %}
|
|
</td>
|
|
<td class="text-end fw-semibold">{{ count }}</td>
|
|
</tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
{% else %}
|
|
<p class="text-muted">Noch keine Einträge im Journal.</p>
|
|
{% endif %}
|
|
|
|
<hr class="my-3" style="border-color:var(--border)">
|
|
<div class="d-flex justify-content-between align-items-center">
|
|
<small class="text-muted">Journal-Datenbank: <code>email_journal.db</code></small>
|
|
<form method="POST" action="/settings/journal-clear"
|
|
onsubmit="return confirm('Alle abgeschlossenen Journal-Einträge löschen?')">
|
|
<button type="submit" class="btn btn-sm btn-outline-danger">Abgeschlossene löschen</button>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Telegram Bot -->
|
|
<div class="col-lg-6">
|
|
<div class="card h-100">
|
|
<div class="card-header">
|
|
<span class="me-2">💬</span> Telegram Bot
|
|
</div>
|
|
<div class="card-body">
|
|
{% if telegram_config.bot_token %}
|
|
<div class="text-center mb-4">
|
|
<h5 class="mb-3">Scanne den QR-Code mit Telegram</h5>
|
|
<img src="/api/telegram-qr" alt="Telegram QR Code" class="img-fluid" style="max-width: 300px; border: 2px solid var(--border); border-radius: 8px; padding: 10px; background: white;">
|
|
<p class="text-muted mt-3 mb-2">
|
|
Oder öffne direkt:
|
|
<a href="https://t.me/{{ telegram_config.bot_username }}?start=connect" target="_blank" class="btn btn-sm btn-primary">
|
|
@{{ telegram_config.bot_username }}
|
|
</a>
|
|
</p>
|
|
</div>
|
|
|
|
<hr class="my-3" style="border-color:var(--border)">
|
|
|
|
<div class="mb-3">
|
|
<strong>Status:</strong>
|
|
<span class="badge bg-success">✓ Aktiv</span>
|
|
</div>
|
|
|
|
<div class="mb-3">
|
|
<strong>Bot Username:</strong>
|
|
<code>@{{ telegram_config.bot_username }}</code>
|
|
</div>
|
|
|
|
<div class="mb-3">
|
|
<strong>Autorisierte User-IDs:</strong>
|
|
{% if telegram_config.allowed_users %}
|
|
<div class="d-flex flex-wrap gap-2 mt-2">
|
|
{% for user_id in telegram_config.allowed_users %}
|
|
<code class="px-2 py-1 rounded" style="background:var(--bg-elevated);color:var(--accent-light)">{{ user_id }}</code>
|
|
{% endfor %}
|
|
</div>
|
|
{% else %}
|
|
<span class="badge bg-warning text-dark">⚠ Keine User-IDs konfiguriert</span>
|
|
{% endif %}
|
|
</div>
|
|
|
|
<div class="alert alert-info" style="font-size: 0.875rem;">
|
|
<strong>💡 Tipp:</strong> Nach dem Scannen des QR-Codes sende <code>/start</code> an den Bot.
|
|
Du erhältst eine Bestätigung wenn du autorisiert bist.
|
|
</div>
|
|
|
|
{% else %}
|
|
<div class="alert alert-warning">
|
|
<strong>⚠ Telegram Bot nicht konfiguriert</strong>
|
|
<p class="mb-2 mt-2">Um den Telegram Bot zu aktivieren:</p>
|
|
<ol class="mb-0" style="font-size: 0.875rem;">
|
|
<li>Erstelle einen Bot via <a href="https://t.me/BotFather" target="_blank">@BotFather</a></li>
|
|
<li>Kopiere den Bot Token</li>
|
|
<li>Hole deine User-ID via <a href="https://t.me/userinfobot" target="_blank">@userinfobot</a></li>
|
|
<li>Füge beides zur <code>.env</code> Datei hinzu:
|
|
<pre class="mt-2 p-2" style="background: var(--bg-elevated); border-radius: 4px; font-size: 0.8rem;">TELEGRAM_BOT_TOKEN=your_token_here
|
|
TELEGRAM_ALLOWED_USERS=your_user_id</pre>
|
|
</li>
|
|
<li>Starte die App neu</li>
|
|
</ol>
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Whitelist -->
|
|
<div class="col-lg-6">
|
|
<div class="card h-100">
|
|
<div class="card-header">
|
|
<span class="me-2">🔒</span> Email-Whitelist
|
|
</div>
|
|
<div class="card-body">
|
|
<p class="text-muted mb-2">Nur Emails von diesen Absendern werden verarbeitet (aktuell hardcoded in <code>app.py</code>):</p>
|
|
<div class="d-flex flex-wrap gap-2">
|
|
{% set whitelist = ['eric.fischer@signtime.media', 'p.dyderski@live.at', 'georg.tschare@gmail.com', 'georg.tschare@signtime.media'] %}
|
|
{% for addr in whitelist %}
|
|
<code class="px-2 py-1 rounded" style="background:var(--bg-elevated);color:var(--accent-light)">{{ addr }}</code>
|
|
{% endfor %}
|
|
<code class="px-2 py-1 rounded" style="background:var(--bg-elevated);color:var(--accent2)">*@diversityball.at</code>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
{% endblock %}
|