A previous `git pull --rebase origin main` dropped 177 local commits,
losing 3400+ files across admin-v2, backend, studio-v2, website,
klausur-service, and many other services. The partial restore attempt
(660295e2) only recovered some files.
This commit restores all missing files from pre-rebase ref 98933f5e
while preserving post-rebase additions (night-scheduler, night-mode UI,
NightModeWidget dashboard integration).
Restored features include:
- AI Module Sidebar (FAB), OCR Labeling, OCR Compare
- GPU Dashboard, RAG Pipeline, Magic Help
- Klausur-Korrektur (8 files), Abitur-Archiv (5+ files)
- Companion, Zeugnisse-Crawler, Screen Flow
- Full backend, studio-v2, website, klausur-service
- All compliance SDKs, agent-core, voice-service
- CI/CD configs, documentation, scripts
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
394 lines
17 KiB
Python
394 lines
17 KiB
Python
"""
|
|
Alerts Module - HTML Template.
|
|
|
|
Enthält das HTML-Template für das Alerts Agent Modul.
|
|
"""
|
|
|
|
|
|
def get_alerts_html() -> str:
|
|
"""HTML fuer das Alerts-Modul."""
|
|
return """
|
|
<!-- ALERTS PANEL -->
|
|
<div class="panel-alerts" id="panel-alerts">
|
|
<!-- Header -->
|
|
<div class="alerts-header">
|
|
<div class="alerts-title-section">
|
|
<h1>Alerts Monitoring</h1>
|
|
<p class="alerts-subtitle">Google Alerts & Feed-Ueberwachung mit KI-Filterung</p>
|
|
</div>
|
|
<div class="alerts-header-actions">
|
|
<!-- Mode Switcher -->
|
|
<div class="alerts-mode-switcher">
|
|
<button class="mode-btn active" data-mode="guided" onclick="switchToGuidedMode()">Einfach</button>
|
|
<button class="mode-btn" data-mode="expert" onclick="switchToExpertMode()">Experte</button>
|
|
</div>
|
|
<button class="btn btn-ghost" onclick="syncAllAlerts()">
|
|
<span>↻</span> Synchronisieren
|
|
</button>
|
|
<button class="btn btn-primary" onclick="openAddTopicModal()">
|
|
<span>➕</span> Topic hinzufuegen
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- GUIDED MODE CONTAINER (standardmaessig aktiv) -->
|
|
<div class="guided-mode-container active" id="guided-mode-container">
|
|
<!-- Wizard -->
|
|
<div class="guided-wizard active" id="guided-wizard">
|
|
<!-- Progress -->
|
|
<div class="wizard-progress">
|
|
<div class="wizard-step-indicator">
|
|
<div class="wizard-step-dot active" id="wizard-dot-1">1</div>
|
|
<div class="wizard-step-line" id="wizard-line-1"></div>
|
|
</div>
|
|
<div class="wizard-step-indicator">
|
|
<div class="wizard-step-dot" id="wizard-dot-2">2</div>
|
|
<div class="wizard-step-line" id="wizard-line-2"></div>
|
|
</div>
|
|
<div class="wizard-step-indicator">
|
|
<div class="wizard-step-dot" id="wizard-dot-3">3</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Step 1: Role Selection -->
|
|
<div class="wizard-step active" id="wizard-step-1">
|
|
<h2 class="wizard-step-title">Was beschreibt Sie am besten?</h2>
|
|
<p class="wizard-step-description">
|
|
Wir zeigen Ihnen passende Themen basierend auf Ihrer Rolle.
|
|
</p>
|
|
<div class="role-cards" id="role-cards-container">
|
|
<div class="role-card" data-role="lehrkraft">
|
|
<div class="role-card-icon">📚</div>
|
|
<div class="role-card-title">Ich unterrichte</div>
|
|
<div class="role-card-description">Lehrkraft mit Fokus auf Unterricht</div>
|
|
</div>
|
|
<div class="role-card" data-role="schulleitung">
|
|
<div class="role-card-icon">🏫</div>
|
|
<div class="role-card-title">Ich leite die Schule</div>
|
|
<div class="role-card-description">Schulleitung, Verwaltung</div>
|
|
</div>
|
|
<div class="role-card" data-role="it_beauftragte">
|
|
<div class="role-card-icon">💻</div>
|
|
<div class="role-card-title">Ich bin IT-verantwortlich</div>
|
|
<div class="role-card-description">IT-Beauftragte/r</div>
|
|
</div>
|
|
</div>
|
|
<div class="wizard-nav">
|
|
<button type="button" class="wizard-nav-btn secondary" id="wizard-skip-btn">Ueberspringen</button>
|
|
<button type="button" class="wizard-nav-btn primary" id="wizard-next-1" disabled>Weiter</button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Step 2: Template Selection -->
|
|
<div class="wizard-step" id="wizard-step-2">
|
|
<h2 class="wizard-step-title">Welche Themen interessieren Sie?</h2>
|
|
<p class="wizard-step-description">
|
|
Waehlen Sie 1-3 Themen. Sie koennen diese spaeter anpassen.
|
|
</p>
|
|
<div class="template-grid" id="template-grid"></div>
|
|
<div class="template-selection-info">
|
|
<span id="template-count">0</span> von 3 Themen ausgewaehlt
|
|
</div>
|
|
<div class="wizard-nav">
|
|
<button type="button" class="wizard-nav-btn secondary" id="wizard-back-2">Zurueck</button>
|
|
<button type="button" class="wizard-nav-btn primary" id="wizard-next-2" disabled>Weiter</button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Step 3: Confirmation -->
|
|
<div class="wizard-step" id="wizard-step-3">
|
|
<h2 class="wizard-step-title">Fast geschafft!</h2>
|
|
<p class="wizard-step-description">Pruefen Sie Ihre Auswahl.</p>
|
|
<div class="confirmation-summary">
|
|
<div class="confirmation-item">
|
|
<span class="confirmation-label">Ihre Rolle</span>
|
|
<span class="confirmation-value" id="confirm-role">-</span>
|
|
</div>
|
|
<div class="confirmation-item">
|
|
<span class="confirmation-label">Themen</span>
|
|
<div class="confirmation-templates" id="confirm-templates"></div>
|
|
</div>
|
|
<div class="confirmation-item">
|
|
<span class="confirmation-label">Erwartete Meldungen</span>
|
|
<span class="confirmation-value">Ca. 5-10 pro Tag</span>
|
|
</div>
|
|
</div>
|
|
<div class="email-input-group">
|
|
<label class="email-input-label">E-Mail fuer Wochenzusammenfassung (optional)</label>
|
|
<p class="email-input-hint">Jeden Montag erhalten Sie eine Zusammenfassung.</p>
|
|
<input type="email" class="email-input" id="digest-email" placeholder="ihre.email@schule.de">
|
|
</div>
|
|
<div class="wizard-nav">
|
|
<button type="button" class="wizard-nav-btn secondary" id="wizard-back-3">Zurueck</button>
|
|
<button type="button" class="wizard-nav-btn primary" id="wizard-finish">Jetzt starten</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Guided Inbox -->
|
|
<div class="guided-inbox" id="guided-inbox">
|
|
<div class="guided-inbox-header">
|
|
<div>
|
|
<h2 style="margin: 0 0 4px 0; font-size: 20px;">Ihre Meldungen</h2>
|
|
<p style="margin: 0; font-size: 14px; color: var(--bp-text-muted);">
|
|
<span id="guided-alert-count">0</span> relevante Meldungen
|
|
</p>
|
|
</div>
|
|
<div style="display: flex; gap: 12px;">
|
|
<button class="btn btn-ghost" onclick="showDigestModal()">📄 Wochenbericht</button>
|
|
<button class="btn btn-ghost" onclick="openGuidedSettings()">⚙ Einstellungen</button>
|
|
</div>
|
|
</div>
|
|
<div class="info-cards-container">
|
|
<div class="info-cards-list" id="info-cards-list"></div>
|
|
<div class="guided-empty-state" id="guided-empty-state" style="display: none;">
|
|
<div class="guided-empty-icon">🎉</div>
|
|
<h3 class="guided-empty-title">Keine neuen Meldungen</h3>
|
|
<p style="font-size: 14px; color: var(--bp-text-muted);">
|
|
Super! Sie sind auf dem neuesten Stand.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- EXPERT MODE CONTENT (Standard-UI) -->
|
|
<div class="expert-mode-container" id="expert-mode-container" style="display: none;">
|
|
<!-- Stats Bar -->
|
|
<div class="alerts-stats-bar">
|
|
<div class="alerts-stat">
|
|
<span class="alerts-stat-icon">📥</span>
|
|
<span class="alerts-stat-value" id="alerts-stat-new">0</span>
|
|
<span class="alerts-stat-label">Neu</span>
|
|
</div>
|
|
<div class="alerts-stat">
|
|
<span class="alerts-stat-icon">✅</span>
|
|
<span class="alerts-stat-value" id="alerts-stat-keep">0</span>
|
|
<span class="alerts-stat-label">Relevant</span>
|
|
</div>
|
|
<div class="alerts-stat">
|
|
<span class="alerts-stat-icon">👁</span>
|
|
<span class="alerts-stat-value" id="alerts-stat-review">0</span>
|
|
<span class="alerts-stat-label">Pruefung</span>
|
|
</div>
|
|
<div class="alerts-stat">
|
|
<span class="alerts-stat-icon">📋</span>
|
|
<span class="alerts-stat-value" id="alerts-stat-topics">0</span>
|
|
<span class="alerts-stat-label">Topics</span>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Tab Navigation -->
|
|
<div class="alerts-tabs">
|
|
<button class="alerts-tab active" onclick="showAlertsTab('inbox')">
|
|
Inbox
|
|
<span class="alerts-tab-badge" id="alerts-inbox-badge">0</span>
|
|
</button>
|
|
<button class="alerts-tab" onclick="showAlertsTab('topics')">Topics</button>
|
|
<button class="alerts-tab" onclick="showAlertsTab('rules')">Regeln</button>
|
|
<button class="alerts-tab" onclick="showAlertsTab('profile')">Profil</button>
|
|
</div>
|
|
|
|
<!-- Content Area -->
|
|
<div class="alerts-content">
|
|
<!-- Inbox Tab -->
|
|
<div class="alerts-tab-panel active" id="alerts-panel-inbox">
|
|
<!-- Filters -->
|
|
<div class="alerts-inbox-filters">
|
|
<button class="alerts-filter-btn active" onclick="filterAlerts('all')">Alle</button>
|
|
<button class="alerts-filter-btn" onclick="filterAlerts('new')">Neu</button>
|
|
<button class="alerts-filter-btn" onclick="filterAlerts('keep')">Relevant</button>
|
|
<button class="alerts-filter-btn" onclick="filterAlerts('review')">Pruefung</button>
|
|
<div class="alerts-search">
|
|
<input type="text" placeholder="Suchen..." oninput="searchAlerts(this.value)">
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Alerts List -->
|
|
<div class="alerts-list" id="alerts-list">
|
|
<!-- Wird per JS befuellt -->
|
|
</div>
|
|
|
|
<!-- Empty State -->
|
|
<div class="alerts-empty-state" id="alerts-empty-state" style="display: none;">
|
|
<div class="alerts-empty-icon">📥</div>
|
|
<h3 class="alerts-empty-title">Keine Alerts</h3>
|
|
<p class="alerts-empty-description">
|
|
Es wurden noch keine Alerts gefunden. Fuegen Sie Topics hinzu, um Alerts zu erhalten.
|
|
</p>
|
|
<button class="btn btn-primary" onclick="openAddTopicModal()">
|
|
Topic hinzufuegen
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Topics Tab -->
|
|
<div class="alerts-tab-panel" id="alerts-panel-topics">
|
|
<div class="topics-grid" id="topics-grid">
|
|
<!-- Wird per JS befuellt -->
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Rules Tab -->
|
|
<div class="alerts-tab-panel" id="alerts-panel-rules">
|
|
<div style="margin-bottom: 20px; display: flex; justify-content: space-between; align-items: center;">
|
|
<p style="color: var(--bp-text-muted);">Regeln werden in Prioritaetsreihenfolge ausgefuehrt.</p>
|
|
<button class="btn btn-primary" onclick="openAddRuleModal()">
|
|
<span>➕</span> Regel erstellen
|
|
</button>
|
|
</div>
|
|
<div class="rules-list" id="rules-list">
|
|
<!-- Wird per JS befuellt -->
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Profile Tab -->
|
|
<div class="alerts-tab-panel" id="alerts-panel-profile">
|
|
<div style="max-width: 600px;">
|
|
<h3 style="font-size: 18px; font-weight: 600; margin-bottom: 20px;">Relevanzprofil</h3>
|
|
|
|
<div class="alerts-form-group">
|
|
<label class="alerts-form-label">Prioritaeten (wichtige Themen)</label>
|
|
<textarea class="alerts-form-input" id="profile-priorities" rows="4"
|
|
placeholder="z.B. Inklusion, digitale Bildung, Lehrerfortbildung..."></textarea>
|
|
<p class="alerts-form-hint">Ein Thema pro Zeile. Alerts zu diesen Themen werden hoeher bewertet.</p>
|
|
</div>
|
|
|
|
<div class="alerts-form-group">
|
|
<label class="alerts-form-label">Ausschluesse (unerwuenschte Themen)</label>
|
|
<textarea class="alerts-form-input" id="profile-exclusions" rows="4"
|
|
placeholder="z.B. Stellenanzeigen, Werbung, Pressemitteilungen..."></textarea>
|
|
<p class="alerts-form-hint">Alerts zu diesen Themen werden niedriger bewertet.</p>
|
|
</div>
|
|
|
|
<div class="alerts-form-group">
|
|
<label class="alerts-form-label">Schwellenwert fuer automatisches Behalten</label>
|
|
<select class="alerts-form-select" id="profile-keep-threshold">
|
|
<option value="0.8">80% (sehr streng)</option>
|
|
<option value="0.7" selected>70% (empfohlen)</option>
|
|
<option value="0.6">60% (weniger streng)</option>
|
|
<option value="0.5">50% (locker)</option>
|
|
</select>
|
|
</div>
|
|
|
|
<div class="alerts-form-group">
|
|
<label class="alerts-form-label">Schwellenwert fuer automatisches Verwerfen</label>
|
|
<select class="alerts-form-select" id="profile-drop-threshold">
|
|
<option value="0.3" selected>30% (empfohlen)</option>
|
|
<option value="0.4">40% (strenger)</option>
|
|
<option value="0.2">20% (lockerer)</option>
|
|
</select>
|
|
</div>
|
|
|
|
<button class="btn btn-primary" onclick="saveProfile()">
|
|
<span>💾</span> Profil speichern
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<!-- End Expert Mode Container -->
|
|
|
|
<!-- Add Topic Modal -->
|
|
<div class="alerts-modal" id="add-topic-modal">
|
|
<div class="alerts-modal-content">
|
|
<div class="alerts-modal-header">
|
|
<h2 class="alerts-modal-title">Topic hinzufuegen</h2>
|
|
<button class="alerts-modal-close" onclick="closeAddTopicModal()">×</button>
|
|
</div>
|
|
<div class="alerts-modal-body">
|
|
<div class="alerts-form-group">
|
|
<label class="alerts-form-label">Topic Name</label>
|
|
<input type="text" class="alerts-form-input" id="topic-name"
|
|
placeholder="z.B. Inklusion in Schulen">
|
|
</div>
|
|
<div class="alerts-form-group">
|
|
<label class="alerts-form-label">Feed URL</label>
|
|
<input type="url" class="alerts-form-input" id="topic-feed-url"
|
|
placeholder="https://www.google.com/alerts/feeds/...">
|
|
<p class="alerts-form-hint">Google Alerts RSS-Feed URL oder andere RSS/Atom Feed URL</p>
|
|
</div>
|
|
<div class="alerts-form-group">
|
|
<label class="alerts-form-label">Feed Typ</label>
|
|
<select class="alerts-form-select" id="topic-feed-type">
|
|
<option value="rss">RSS Feed</option>
|
|
<option value="email">E-Mail Parsing</option>
|
|
<option value="webhook">Webhook</option>
|
|
</select>
|
|
</div>
|
|
<div class="alerts-form-group">
|
|
<label class="alerts-form-label">Aktualisierungsintervall</label>
|
|
<select class="alerts-form-select" id="topic-interval">
|
|
<option value="15">Alle 15 Minuten</option>
|
|
<option value="30">Alle 30 Minuten</option>
|
|
<option value="60" selected>Stuendlich</option>
|
|
<option value="360">Alle 6 Stunden</option>
|
|
<option value="1440">Taeglich</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
<div class="alerts-modal-footer">
|
|
<button class="btn btn-ghost" onclick="closeAddTopicModal()">Abbrechen</button>
|
|
<button class="btn btn-primary" onclick="saveTopic()">Speichern</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Add Rule Modal -->
|
|
<div class="alerts-modal" id="add-rule-modal">
|
|
<div class="alerts-modal-content">
|
|
<div class="alerts-modal-header">
|
|
<h2 class="alerts-modal-title">Regel erstellen</h2>
|
|
<button class="alerts-modal-close" onclick="closeAddRuleModal()">×</button>
|
|
</div>
|
|
<div class="alerts-modal-body">
|
|
<div class="alerts-form-group">
|
|
<label class="alerts-form-label">Regel Name</label>
|
|
<input type="text" class="alerts-form-input" id="rule-name"
|
|
placeholder="z.B. Stellenanzeigen ausschliessen">
|
|
</div>
|
|
<div class="alerts-form-group">
|
|
<label class="alerts-form-label">Bedingung: Feld</label>
|
|
<select class="alerts-form-select" id="rule-field">
|
|
<option value="title">Titel</option>
|
|
<option value="snippet">Inhalt</option>
|
|
<option value="url">URL</option>
|
|
<option value="score">Relevanz-Score</option>
|
|
</select>
|
|
</div>
|
|
<div class="alerts-form-group">
|
|
<label class="alerts-form-label">Bedingung: Operator</label>
|
|
<select class="alerts-form-select" id="rule-operator">
|
|
<option value="contains">enthaelt</option>
|
|
<option value="not_contains">enthaelt nicht</option>
|
|
<option value="regex">Regex</option>
|
|
<option value="gt">groesser als</option>
|
|
<option value="lt">kleiner als</option>
|
|
</select>
|
|
</div>
|
|
<div class="alerts-form-group">
|
|
<label class="alerts-form-label">Bedingung: Wert</label>
|
|
<input type="text" class="alerts-form-input" id="rule-value"
|
|
placeholder="z.B. Stellenangebot">
|
|
</div>
|
|
<div class="alerts-form-group">
|
|
<label class="alerts-form-label">Aktion</label>
|
|
<select class="alerts-form-select" id="rule-action">
|
|
<option value="keep">Behalten (relevant)</option>
|
|
<option value="drop">Verwerfen</option>
|
|
<option value="email">E-Mail senden</option>
|
|
<option value="webhook">Webhook aufrufen</option>
|
|
<option value="slack">Slack Nachricht</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
<div class="alerts-modal-footer">
|
|
<button class="btn btn-ghost" onclick="closeAddRuleModal()">Abbrechen</button>
|
|
<button class="btn btn-primary" onclick="saveRule()">Speichern</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div><!-- /panel-alerts -->
|
|
"""
|
|
|