- 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.
65 lines
2.2 KiB
Python
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
|