uxowe i funkcjonalne

This commit is contained in:
Mateusz Gruszczyński
2026-03-25 13:16:47 +01:00
parent 84fe898a74
commit 077ea315f5
7 changed files with 352 additions and 53 deletions

View File

@@ -11,6 +11,8 @@ from app.storage.kiosk_settings import SQLiteKioskSettingsRepository
VALID_MODES = {"public", "private"}
USER_MODE_PREFIX = "user:"
DEFAULT_WIDGETS = ["hero", "history", "strings", "status", "production", "comparison", "importStatus"]
DEFAULT_HERO_METRICS = ["ac_power", "dc_power_total", "energy_today", "energy_total"]
DEFAULT_CHART_GROUPS = [{"id": "overview", "title": None, "metric_ids": ["ac_power", "dc_power_total", "inverter_temp"]}]
VALID_WIDGETS = {"hero", "quickMetrics", "history", "status", "strings", "production", "comparison", "distribution", "importStatus"}
VALID_REALTIME_RANGES = {"today", "yesterday", "6h", "12h", "24h", "48h", "7d"}
VALID_ANALYTICS_RANGES = {"today", "yesterday", "7d", "30d", "90d", "365d", "custom"}
@@ -42,10 +44,12 @@ class KioskSettingsService:
return {
"mode": mode,
"widgets": list(DEFAULT_WIDGETS),
"hero_metric_ids": list(DEFAULT_HERO_METRICS),
"realtime_range": self._default_realtime_range(),
"analytics_range": self._default_analytics_range(),
"analytics_bucket": self._default_analytics_bucket(),
"compare_mode": self._default_compare_mode(),
"chart_groups": self._normalize_chart_groups(None),
"updated_at": None,
"updated_by": None,
}
@@ -54,10 +58,12 @@ class KioskSettingsService:
cleaned = {
"mode": mode,
"widgets": self._normalize_widgets(payload.get("widgets")),
"hero_metric_ids": self._normalize_metric_ids(payload.get("hero_metric_ids"), DEFAULT_HERO_METRICS),
"realtime_range": self._normalize_realtime_range(payload.get("realtime_range")),
"analytics_range": self._normalize_analytics_range(payload.get("analytics_range")),
"analytics_bucket": self._normalize_bucket(payload.get("analytics_bucket")),
"compare_mode": self._normalize_compare_mode(payload.get("compare_mode")),
"chart_groups": self._normalize_chart_groups(payload.get("chart_groups")),
"updated_at": payload.get("updated_at"),
"updated_by": payload.get("updated_by"),
}
@@ -83,6 +89,16 @@ class KioskSettingsService:
normalized.append(widget)
return normalized or list(DEFAULT_WIDGETS)
def _normalize_metric_ids(self, metric_ids: Any, defaults: list[str]) -> list[str]:
if not isinstance(metric_ids, list):
return list(defaults)
normalized: list[str] = []
for item in metric_ids:
value = str(item or "").strip()
if value and value not in normalized:
normalized.append(value)
return normalized[:12] or list(defaults)
def _normalize_realtime_range(self, value: Any) -> str:
normalized = str(value or self._default_realtime_range()).strip()
return normalized if normalized in VALID_REALTIME_RANGES else self._default_realtime_range()
@@ -99,6 +115,31 @@ class KioskSettingsService:
normalized = str(value or self._default_compare_mode()).strip()
return normalized if normalized in self.settings.analytics["compare_modes"] else self._default_compare_mode()
def _normalize_chart_groups(self, groups: Any) -> list[dict[str, Any]]:
if not isinstance(groups, list):
return [dict(item) for item in DEFAULT_CHART_GROUPS]
normalized: list[dict[str, Any]] = []
for index, item in enumerate(groups):
if not isinstance(item, dict):
continue
raw_metrics = item.get("metric_ids")
if not isinstance(raw_metrics, list):
continue
metric_ids: list[str] = []
for metric in raw_metrics:
value = str(metric or "").strip()
if value and value not in metric_ids:
metric_ids.append(value)
if not metric_ids:
continue
chart_id = str(item.get("id") or f"chart_{index + 1}").strip() or f"chart_{index + 1}"
title_raw = item.get("title")
title = None if title_raw is None else str(title_raw).strip() or None
normalized.append({"id": chart_id[:80], "title": title, "metric_ids": metric_ids[:24]})
return normalized[:8] or [dict(item) for item in DEFAULT_CHART_GROUPS]
def _default_realtime_range(self) -> str:
raw = str(self.settings.realtime.get("history_default_range", "12h"))
return raw if raw in VALID_REALTIME_RANGES else "12h"