feat(sources): Aufgaben-Posteingang ersetzt Quellen-Health und Klassifikation

- Neuer Unterreiter Aufgaben buendelt Health-Vorschlaege (Tabelle inkl.
  Loesung-suchen), Klassifikations-Review-Karten und den eingeklappten
  Verlauf (erledigte Vorschlaege + letzte Prueflaeufe). Die dritte
  Navigationsebene (healthSubTabs) entfaellt komplett.
- Badge zeigt die Summe aus offenen Vorschlaegen und ausstehenden
  Klassifikationen, gespeist vom neuen billigen GET /api/sources/tasks/summary
  (gleiche Bedingung wie /classification/stats, laeuft nie auseinander).
  Badge laedt jetzt schon beim Klick auf den Quellen-Hauptreiter.
- aufgaben.js NEU (uebernimmt Vorschlags-/Verlauf-Rendering aus
  source-health.js und den kompletten Klassifikations-Block aus sources.js),
  source-health.js GELOESCHT (60s-Cache, Checks-Tabelle mit eigener
  Pagination und Filtern entfaellt, die Details stecken jetzt als
  Ausklapp-Zeile in der Quellenliste).
- Quellen hat damit 3 statt 5 Unterreiter: Quellenliste, Aufgaben,
  X-Recherche-Konten.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Dieser Commit ist enthalten in:
claude-dev
2026-07-25 18:11:19 +00:00
Ursprung bbbcc51fc2
Commit bcfdac158e
8 geänderte Dateien mit 472 neuen und 664 gelöschten Zeilen

Datei anzeigen

@@ -112,6 +112,39 @@ async def get_sources_meta(admin: dict = Depends(get_current_admin)):
return get_meta()
@router.get("/tasks/summary")
async def tasks_summary(
admin: dict = Depends(get_current_admin),
db: aiosqlite.Connection = Depends(db_dependency),
):
"""Billiger Zähler für den Aufgaben-Badge im Quellen-Reiter.
classification_pending nutzt DIESELBE Bedingung wie /classification/stats,
damit Badge und Review-Karten nie auseinanderlaufen.
"""
suggestions_pending = 0
cur = await db.execute(
"SELECT name FROM sqlite_master WHERE type='table' AND name='source_suggestions'"
)
if await cur.fetchone():
cur = await db.execute(
"SELECT COUNT(*) AS cnt FROM source_suggestions WHERE status = 'pending'"
)
suggestions_pending = (await cur.fetchone())["cnt"]
cur = await db.execute(
"""SELECT COUNT(*) AS cnt FROM sources
WHERE status = 'active' AND proposed_political_orientation IS NOT NULL"""
)
classification_pending = (await cur.fetchone())["cnt"]
return {
"suggestions_pending": suggestions_pending,
"classification_pending": classification_pending,
"total": suggestions_pending + classification_pending,
}
class GlobalSourceCreate(BaseModel):
name: str = Field(min_length=1, max_length=200)