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:
@@ -33,7 +33,7 @@ from sqlalchemy.orm import Session
|
||||
|
||||
from redaktionskern.auth.deps import AccessDenied, get_db, require_user
|
||||
from redaktionskern.auth.models import Role, User
|
||||
from redaktionskern.contracts import BasePlugin, Migration, NavEntry
|
||||
from redaktionskern.contracts import BasePlugin, DashboardKarte, Migration, NavEntry
|
||||
from redaktionskern.db import Base
|
||||
|
||||
from .models import (
|
||||
@@ -134,6 +134,55 @@ class PlanungPlugin(BasePlugin):
|
||||
def navigation(self) -> list[NavEntry]:
|
||||
return [NavEntry(label=self.title, url="/planung")]
|
||||
|
||||
def dashboard_karten(self, user: User) -> list[DashboardKarte]:
|
||||
"""Dashboard: Planungs-Stats — Rezensenten ihre eigenen, die
|
||||
Redaktion die Gesamtzahlen je Status."""
|
||||
with self.context.session_factory() as db:
|
||||
zaehler = dict(
|
||||
db.execute(
|
||||
select(Planungseintrag.status, func.count())
|
||||
.group_by(Planungseintrag.status)
|
||||
).all()
|
||||
)
|
||||
if user.role in REDAKTION:
|
||||
return [
|
||||
DashboardKarte(
|
||||
titel="Planung",
|
||||
wert=str(zaehler.get("offen", 0)),
|
||||
beschreibung="offene Einträge",
|
||||
zeilen=tuple(
|
||||
f"{STATUS_ANZEIGE[s]}: {zaehler.get(s, 0)}"
|
||||
for s in GUELTIGE_STATUS
|
||||
),
|
||||
link_url="/planung",
|
||||
link_label="Zur Planung",
|
||||
ton="neutral",
|
||||
)
|
||||
]
|
||||
eigene = dict(
|
||||
db.execute(
|
||||
select(Planungseintrag.status, func.count())
|
||||
.where(Planungseintrag.rezensent_id == user.id)
|
||||
.group_by(Planungseintrag.status)
|
||||
).all()
|
||||
)
|
||||
return [
|
||||
DashboardKarte(
|
||||
titel="Meine offenen Planungseinträge",
|
||||
wert=str(eigene.get("offen", 0)),
|
||||
link_url="/planung?status=offen",
|
||||
link_label="Anzeigen",
|
||||
ton="neutral",
|
||||
),
|
||||
DashboardKarte(
|
||||
titel="Meine Einträge in Bearbeitung",
|
||||
wert=str(eigene.get("in_bearbeitung", 0)),
|
||||
link_url="/planung?status=in_bearbeitung",
|
||||
link_label="Anzeigen",
|
||||
ton="neutral",
|
||||
),
|
||||
]
|
||||
|
||||
# ---------- Hilfsfunktionen ----------
|
||||
|
||||
@staticmethod
|
||||
|
||||
Reference in New Issue
Block a user