- Added new API endpoints for managing the product dashboard standard, including retrieval, update, and deletion functionalities. - Enhanced the DashboardConfigurePage to support admin mode for configuring the product dashboard standard. - Updated the admin navigation to include a link for the product dashboard standard configuration. - Refactored the dashboard layout logic to utilize the new product standard management features. - Bumped app_dashboard version to 1.10.0 to reflect these enhancements and changes.
78 lines
2.3 KiB
Python
78 lines
2.3 KiB
Python
"""
|
|
Persistenter System-Standard für die Produkt-Übersicht (Dashboard).
|
|
|
|
Key in system_config: dashboard_product_default — gültiges DashboardLayoutPayload (JSON).
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
from typing import Any
|
|
|
|
from psycopg2.extras import Json
|
|
|
|
from dashboard_layout_schema import DashboardLayoutPayload, product_default_layout_dict
|
|
from db import get_cursor
|
|
|
|
SYSTEM_CONFIG_KEY_DASHBOARD_PRODUCT_DEFAULT = "dashboard_product_default"
|
|
|
|
|
|
def get_stored_product_default_validated(conn) -> dict[str, Any] | None:
|
|
"""Gültiges Layout aus DB oder None (fehlt/ungültig)."""
|
|
cur = get_cursor(conn)
|
|
cur.execute(
|
|
"SELECT value FROM system_config WHERE key = %s",
|
|
(SYSTEM_CONFIG_KEY_DASHBOARD_PRODUCT_DEFAULT,),
|
|
)
|
|
row = cur.fetchone()
|
|
if not row or row.get("value") is None:
|
|
return None
|
|
raw = row["value"]
|
|
if isinstance(raw, str):
|
|
import json
|
|
|
|
try:
|
|
raw = json.loads(raw)
|
|
except json.JSONDecodeError:
|
|
return None
|
|
if not isinstance(raw, dict):
|
|
return None
|
|
try:
|
|
payload = DashboardLayoutPayload.model_validate(
|
|
{"version": raw.get("version", 1), "widgets": raw.get("widgets", [])}
|
|
)
|
|
return payload.to_stored_dict()
|
|
except Exception:
|
|
return None
|
|
|
|
|
|
def get_product_default_base_dict(conn) -> dict[str, Any]:
|
|
"""Basis-Layout (ohne Entitlements): DB-Override oder Code-Standard."""
|
|
stored = get_stored_product_default_validated(conn)
|
|
if stored is not None:
|
|
return stored
|
|
return product_default_layout_dict()
|
|
|
|
|
|
def upsert_product_default_base(conn, layout: dict[str, Any]) -> dict[str, Any]:
|
|
payload = DashboardLayoutPayload.model_validate(layout)
|
|
stored = payload.to_stored_dict()
|
|
cur = get_cursor(conn)
|
|
cur.execute(
|
|
"""
|
|
INSERT INTO system_config (key, value, updated_at)
|
|
VALUES (%s, %s, CURRENT_TIMESTAMP)
|
|
ON CONFLICT (key) DO UPDATE SET
|
|
value = EXCLUDED.value,
|
|
updated_at = CURRENT_TIMESTAMP
|
|
""",
|
|
(SYSTEM_CONFIG_KEY_DASHBOARD_PRODUCT_DEFAULT, Json(stored)),
|
|
)
|
|
return stored
|
|
|
|
|
|
def delete_product_default_override(conn) -> None:
|
|
cur = get_cursor(conn)
|
|
cur.execute(
|
|
"DELETE FROM system_config WHERE key = %s",
|
|
(SYSTEM_CONFIG_KEY_DASHBOARD_PRODUCT_DEFAULT,),
|
|
)
|