mitai-jinkendo/backend/dashboard_widget_config.py
Lars 87c4cbc4b4
All checks were successful
Deploy Development / deploy (push) Successful in 46s
Build Test / lint-backend (push) Successful in 0s
Build Test / build-frontend (push) Successful in 14s
feat: Enhance Dashboard widget configuration and layout management
- Added validation for widget configuration in the DashboardWidgetEntry model to ensure proper data structure.
- Updated the DashboardLayoutPayload to include widget configuration in the serialized output.
- Improved the PilotBodySection and DashboardLabPage components to support dynamic chart days configuration for the body overview widget.
- Refactored layout editor functions to normalize widget configurations for better handling.
- Bumped app_dashboard version to 1.2.0 to reflect the new features and improvements.
2026-04-07 11:58:07 +02:00

65 lines
2.2 KiB
Python

"""
Pro-Widget-Konfiguration im Dashboard-Layout (v1).
Nur ausgewählte Widget-IDs dürfen nicht-leere config haben; bekannte Keys werden validiert.
"""
from __future__ import annotations
import json
import math
from typing import Any
MAX_WIDGET_CONFIG_JSON_BYTES = 1024
WIDGETS_ALLOWING_CONFIG: frozenset[str] = frozenset({"body_overview"})
def _config_json_size_bytes(config: dict[str, Any]) -> int:
return len(json.dumps(config, sort_keys=True, ensure_ascii=False).encode("utf-8"))
def validate_widget_entry_config(widget_id: str, raw: Any) -> dict[str, Any]:
if raw is None:
return {}
if not isinstance(raw, dict):
raise ValueError(f"Widget {widget_id}: config muss ein Objekt sein")
if _config_json_size_bytes(raw) > MAX_WIDGET_CONFIG_JSON_BYTES:
raise ValueError(f"Widget {widget_id}: config zu groß (max. {MAX_WIDGET_CONFIG_JSON_BYTES} Byte JSON)")
if not raw:
return {}
if widget_id not in WIDGETS_ALLOWING_CONFIG:
raise ValueError(f"Widget {widget_id}: keine Konfiguration unterstützt")
if widget_id == "body_overview":
return _validate_body_overview_config(raw)
raise ValueError(f"Widget {widget_id}: keine Konfiguration unterstützt")
def _validate_body_overview_config(raw: dict[str, Any]) -> dict[str, Any]:
allowed = frozenset({"chart_days"})
unknown = set(raw) - allowed
if unknown:
raise ValueError(f"body_overview: unbekannte config-Felder: {sorted(unknown)}")
out: dict[str, Any] = {}
if "chart_days" not in raw:
return out
v = raw["chart_days"]
if isinstance(v, bool):
raise ValueError("body_overview: chart_days muss ganze Zahl sein")
if isinstance(v, float):
if not math.isfinite(v):
raise ValueError("body_overview: chart_days muss ganze Zahl sein")
if abs(v - round(v)) > 1e-9:
raise ValueError("body_overview: chart_days muss ganze Zahl sein")
v = int(round(v))
elif isinstance(v, int):
pass
else:
raise ValueError("body_overview: chart_days muss ganze Zahl sein")
if v < 7 or v > 90:
raise ValueError("body_overview: chart_days muss zwischen 7 und 90 liegen")
out["chart_days"] = v
return out