fix ux
This commit is contained in:
@@ -37,7 +37,7 @@ class AnalyticsService:
|
||||
window = resolve_window(range_key=range_key, start=start, end=end)
|
||||
current_days = self.energy.daily_records_for_window(window.start, window.end, persist_missing=True)
|
||||
current = self.energy.bucketize_daily(current_days, bucket)
|
||||
total = round(sum(item.value for item in current), 2)
|
||||
total = round(sum((item.value or 0.0) for item in current), 2)
|
||||
|
||||
comparison = []
|
||||
comparison_total = None
|
||||
@@ -52,7 +52,7 @@ class AnalyticsService:
|
||||
compare_window = resolve_window(start=compare_start, end=compare_end)
|
||||
comparison_days = self.energy.daily_records_for_window(compare_window.start, compare_window.end, persist_missing=True)
|
||||
comparison_series = self.energy.bucketize_daily(comparison_days, bucket)
|
||||
comparison_total_value = round(sum(point.value for point in comparison_series), 2)
|
||||
comparison_total_value = round(sum((point.value or 0.0) for point in comparison_series), 2)
|
||||
comparisons.append({
|
||||
"key": item.get("key") or f"custom_{index + 1}",
|
||||
"label": item.get("label") or f"Custom {index + 1}",
|
||||
@@ -70,7 +70,7 @@ class AnalyticsService:
|
||||
compare_window = shift_window(window, compare_mode)
|
||||
comparison_days = self.energy.daily_records_for_window(compare_window.start, compare_window.end, persist_missing=True)
|
||||
comparison = self.energy.bucketize_daily(comparison_days, bucket)
|
||||
comparison_total = round(sum(item.value for item in comparison), 2)
|
||||
comparison_total = round(sum((item.value or 0.0) for item in comparison), 2)
|
||||
comparison_delta_pct = compare_delta_pct(total, comparison_total)
|
||||
comparisons.append({
|
||||
"key": compare_mode,
|
||||
@@ -82,8 +82,9 @@ class AnalyticsService:
|
||||
"points": comparison,
|
||||
})
|
||||
|
||||
average_bucket = round(total / len(current), 2) if current else 0.0
|
||||
best_bucket = max(current, key=lambda item: item.value, default=None)
|
||||
populated_current = [item for item in current if item.value is not None]
|
||||
average_bucket = round(total / len(populated_current), 2) if populated_current else 0.0
|
||||
best_bucket = max(populated_current, key=lambda item: item.value or 0.0, default=None)
|
||||
|
||||
return {
|
||||
"unit": "kWh",
|
||||
@@ -121,7 +122,7 @@ class AnalyticsService:
|
||||
) -> dict:
|
||||
payload = self.production(range_key=range_key, bucket=bucket, compare_mode="none", start=start, end=end)
|
||||
current = payload["current"]
|
||||
total = round(sum(item.value for item in current), 2)
|
||||
total = round(sum((item.value or 0.0) for item in current), 2)
|
||||
denominator = total or 1.0
|
||||
return {
|
||||
"unit": payload["unit"],
|
||||
@@ -134,7 +135,7 @@ class AnalyticsService:
|
||||
"share": round((item.value / denominator) * 100.0, 2),
|
||||
}
|
||||
for item in current
|
||||
if item.value > 0
|
||||
if item.value is not None and item.value > 0
|
||||
],
|
||||
"meta": payload["meta"],
|
||||
}
|
||||
|
||||
@@ -104,7 +104,7 @@ class EnergyService:
|
||||
return rows
|
||||
|
||||
def bucketize_daily(self, records: list[DailyEnergyRecord], bucket: str) -> list[BucketPoint]:
|
||||
grouped: dict[str, dict] = defaultdict(lambda: {"value": 0.0, "start": None, "end": None, "label": ""})
|
||||
grouped: dict[str, dict] = defaultdict(lambda: {"value": 0.0, "start": None, "end": None, "label": "", "has_data": False})
|
||||
|
||||
for record in records:
|
||||
start = datetime.combine(record.day, time.min, tzinfo=self.tz)
|
||||
@@ -137,7 +137,9 @@ class EnergyService:
|
||||
|
||||
current = grouped[key]
|
||||
current["label"] = label
|
||||
current["value"] += record.energy_kwh
|
||||
if record.samples_count > 0:
|
||||
current["value"] += record.energy_kwh
|
||||
current["has_data"] = True
|
||||
current["start"] = bucket_start if current["start"] is None else min(current["start"], bucket_start)
|
||||
current["end"] = bucket_end if current["end"] is None else max(current["end"], bucket_end)
|
||||
|
||||
@@ -149,7 +151,7 @@ class EnergyService:
|
||||
label=item["label"],
|
||||
start=item["start"],
|
||||
end=item["end"],
|
||||
value=round(item["value"], 2),
|
||||
value=round(item["value"], 2) if item["has_data"] else None,
|
||||
)
|
||||
)
|
||||
return rows
|
||||
|
||||
@@ -9,6 +9,7 @@ from app.storage.kiosk_settings import SQLiteKioskSettingsRepository
|
||||
|
||||
|
||||
VALID_MODES = {"public", "private"}
|
||||
USER_MODE_PREFIX = "user:"
|
||||
DEFAULT_WIDGETS = ["hero", "history", "strings", "status", "production", "comparison", "importStatus"]
|
||||
VALID_WIDGETS = {"hero", "quickMetrics", "history", "status", "strings", "production", "comparison", "distribution", "importStatus"}
|
||||
VALID_REALTIME_RANGES = {"today", "yesterday", "6h", "12h", "24h", "48h", "7d"}
|
||||
@@ -66,9 +67,11 @@ class KioskSettingsService:
|
||||
|
||||
def _normalize_mode(self, mode: str) -> str:
|
||||
normalized = (mode or "").strip().lower()
|
||||
if normalized not in VALID_MODES:
|
||||
raise ValueError("Mode musi byc jednym z: public, private")
|
||||
return normalized
|
||||
if normalized in VALID_MODES:
|
||||
return normalized
|
||||
if normalized.startswith(USER_MODE_PREFIX) and len(normalized) > len(USER_MODE_PREFIX):
|
||||
return normalized
|
||||
raise ValueError("Mode musi byc jednym z: public, private")
|
||||
|
||||
def _normalize_widgets(self, widgets: Any) -> list[str]:
|
||||
if not isinstance(widgets, list):
|
||||
|
||||
Reference in New Issue
Block a user