P1: Rollenbasiertes Dashboard mit Plugin-Karten
- Plugin-Vertrag erweitert: optionaler Hook dashboard_karten(user) + DashboardKarte-Dataclass (Kern bleibt schlank, Fachlogik im Plugin) - Karten: Neuheiten+System-Status (neuheiten), Planungs-Stats bzw. eigene Einträge (planung), offene Dedup-Konflikte (dedup), nächste Redaktionsschlüsse (erinnerung), ungelesene Benachrichtigungen (benachrichtigung), letzte Audit-Einträge (audit-log, nur Admin), Benutzer-Anzahl (Kern, nur Admin) - 'Geladene Plugins' als aufklappbarer Admin-Technikbereich
This commit is contained in:
@@ -36,7 +36,13 @@ from sqlalchemy.orm import Session
|
||||
|
||||
from redaktionskern.auth.deps import get_db, require_roles, require_user
|
||||
from redaktionskern.auth.models import Role, User
|
||||
from redaktionskern.contracts import BasePlugin, Migration, NavEntry, PluginContext
|
||||
from redaktionskern.contracts import (
|
||||
BasePlugin,
|
||||
DashboardKarte,
|
||||
Migration,
|
||||
NavEntry,
|
||||
PluginContext,
|
||||
)
|
||||
|
||||
# Bewusst `from .dienst import …` (wie `from .models import …` überall sonst):
|
||||
# `from . import dienst` funktioniert unter dem dateibasierten Plugin-Loader
|
||||
@@ -116,6 +122,39 @@ class ErinnerungPlugin(BasePlugin):
|
||||
def navigation(self) -> list[NavEntry]:
|
||||
return [NavEntry(label=self.title, url="/erinnerung")]
|
||||
|
||||
def dashboard_karten(self, user: User) -> list[DashboardKarte]:
|
||||
"""Dashboard: die nächsten Redaktionsschlüsse (für alle Rollen)."""
|
||||
from .dienst import heute
|
||||
|
||||
with self.context.session_factory() as db:
|
||||
ausgaben = db.scalars(
|
||||
select(Ausgabe)
|
||||
.where(Ausgabe.redaktionsschluss >= heute())
|
||||
.order_by(Ausgabe.redaktionsschluss)
|
||||
.limit(3)
|
||||
).all()
|
||||
if not ausgaben:
|
||||
return [
|
||||
DashboardKarte(
|
||||
titel="Nächste Redaktionsschlüsse",
|
||||
beschreibung="Aktuell ist kein Redaktionsschluss geplant.",
|
||||
link_url="/erinnerung",
|
||||
)
|
||||
]
|
||||
zeilen = tuple(
|
||||
f"{a.redaktionsschluss.strftime('%d.%m.%Y')} — {a.name}"
|
||||
for a in ausgaben
|
||||
)
|
||||
return [
|
||||
DashboardKarte(
|
||||
titel="Nächste Redaktionsschlüsse",
|
||||
wert=str(len(ausgaben)),
|
||||
zeilen=zeilen,
|
||||
link_url="/erinnerung",
|
||||
link_label="Alle Ausgaben",
|
||||
)
|
||||
]
|
||||
|
||||
def on_load(self, context: PluginContext) -> None:
|
||||
super().on_load(context)
|
||||
import os
|
||||
|
||||
Reference in New Issue
Block a user