mitai-jinkendo/backend/routers/app_dashboard.py
Lars e5f6e6c10d
All checks were successful
Deploy Development / deploy (push) Successful in 49s
Build Test / lint-backend (push) Successful in 0s
Build Test / build-frontend (push) Successful in 15s
feat: Integrate Dashboard-Lab layout and enhance settings navigation
- Added new routes and API endpoints for the Dashboard-Lab layout in the app.
- Updated main.py to include the app_dashboard router for backend integration.
- Enhanced App.jsx to include a route for the DashboardLabPage.
- Modified SettingsPage to add a link to the new Dashboard-Lab layout, improving user access to dashboard features.
- Updated version.py to reflect the new app_dashboard module version.
2026-04-07 11:38:35 +02:00

82 lines
2.5 KiB
Python

"""
Geschützter App-Bereich: Dashboard-Lab Layout (kein Produktiv-Dashboard).
/api/app/dashboard-layout — nur mit Session + aktivem Profil (X-Profile-Id).
"""
from typing import Any, Optional
from fastapi import APIRouter, Depends, Header, HTTPException
from psycopg2.extras import Json
from auth import require_auth
from dashboard_layout_schema import DashboardLayoutPayload, coalesce_effective_layout, default_layout_dict
from db import get_cursor, get_db
from routers.profiles import get_pid
router = APIRouter(prefix="/api/app", tags=["app-dashboard-lab"])
@router.get("/dashboard-layout")
def get_dashboard_layout(
x_profile_id: Optional[str] = Header(default=None),
session: dict = Depends(require_auth),
) -> dict[str, Any]:
_ = session
pid = get_pid(x_profile_id)
with get_db() as conn:
cur = get_cursor(conn)
cur.execute(
"SELECT dashboard_layout FROM profiles WHERE id = %s",
(pid,),
)
row = cur.fetchone()
raw = row["dashboard_layout"] if row else None
custom, effective = coalesce_effective_layout(raw)
return {
"custom": custom,
"layout": effective,
"default_layout": default_layout_dict(),
}
@router.put("/dashboard-layout")
def put_dashboard_layout(
body: dict[str, Any],
x_profile_id: Optional[str] = Header(default=None),
session: dict = Depends(require_auth),
) -> dict[str, Any]:
_ = session
pid = get_pid(x_profile_id)
try:
payload = DashboardLayoutPayload.model_validate(body)
except Exception as e:
raise HTTPException(422, str(e)) from e
stored = payload.to_stored_dict()
with get_db() as conn:
cur = get_cursor(conn)
cur.execute(
"UPDATE profiles SET dashboard_layout = %s WHERE id = %s",
(Json(stored), pid),
)
if cur.rowcount == 0:
raise HTTPException(404, "Profil nicht gefunden")
return {"ok": True, "layout": stored}
@router.post("/dashboard-layout/reset")
def reset_dashboard_layout(
x_profile_id: Optional[str] = Header(default=None),
session: dict = Depends(require_auth),
) -> dict[str, Any]:
_ = session
pid = get_pid(x_profile_id)
with get_db() as conn:
cur = get_cursor(conn)
cur.execute(
"UPDATE profiles SET dashboard_layout = NULL WHERE id = %s",
(pid,),
)
if cur.rowcount == 0:
raise HTTPException(404, "Profil nicht gefunden")
return {"ok": True, "layout": default_layout_dict()}