329 files
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
import os
|
||||
from typing import Any
|
||||
|
||||
from homeassistant.components import websocket_api
|
||||
@@ -40,10 +41,32 @@ def _get_merged_tasks(entry: ConfigEntry) -> dict[str, Any]:
|
||||
rd = getattr(entry, "runtime_data", None)
|
||||
store = getattr(rd, "store", None) if rd else None
|
||||
if store is not None:
|
||||
return store.merge_all_tasks(tasks_data)
|
||||
merged = store.merge_all_tasks(tasks_data)
|
||||
# #73: overlay the in-cycle checklist ticks HERE rather than via the
|
||||
# merge whitelist — merged dicts feed MaintenanceTask.from_dict all
|
||||
# over the coordinator, and this field is presentation state the model
|
||||
# never needs.
|
||||
for tid, td in merged.items():
|
||||
progress = store.get_task_state(tid).get("checklist_progress")
|
||||
if progress:
|
||||
td["checklist_progress"] = progress
|
||||
return merged
|
||||
return tasks_data
|
||||
|
||||
|
||||
# How many recent history entries ride in the LIST payload. Chosen to cover
|
||||
# every non-detail consumer: the quick-actions dialog shows the last 20, the
|
||||
# detail header the last 3, the calendar card averages costs (≈stable over
|
||||
# 20), the strategy looks up the latest matching entry. The detail view's
|
||||
# full timeline/charts fetch everything via `task/history` instead.
|
||||
#
|
||||
# The env override exists ONLY for the benchmark harness: setting
|
||||
# MS_HISTORY_WINDOW to a huge value reproduces the pre-diet payload on the
|
||||
# same build, so before/after is a measured A/B on identical data instead of
|
||||
# an extrapolation. Never documented, never read anywhere else.
|
||||
_HISTORY_WINDOW = int(os.environ.get("MS_HISTORY_WINDOW", "20"))
|
||||
|
||||
|
||||
def _build_task_summary(
|
||||
hass: HomeAssistant,
|
||||
task_id: str,
|
||||
@@ -177,8 +200,20 @@ def _build_task_summary(
|
||||
"trigger_entity_info": trigger_entity_info,
|
||||
"trigger_entity_infos": trigger_entity_infos,
|
||||
"checklist": task_data.get("checklist", []),
|
||||
# #73: in-cycle ticks ({item text: bool}, store-merged) — lets the
|
||||
# detail view show progress without completing, and the complete
|
||||
# dialog prefill what was already done.
|
||||
"checklist_progress": task_data.get("checklist_progress", {}),
|
||||
"labels": task_data.get("labels", []),
|
||||
"history": task_data.get("history", []),
|
||||
# Payload diet (perf, 2026-08): the LIST response carries only the
|
||||
# most recent entries — at 150+ tasks the full histories dominated
|
||||
# the `objects` payload (407 KB measured at just 8 entries/task) and
|
||||
# every list consumer reads at most the last 20 (quick-dialog) or an
|
||||
# aggregate. The task-detail view fetches the FULL history lazily
|
||||
# via `task/history`; `history_count` tells it (and any badge)
|
||||
# what exists beyond the window.
|
||||
"history": (task_data.get("history") or [])[-_HISTORY_WINDOW:],
|
||||
"history_count": len(task_data.get("history") or []),
|
||||
# v1.3.0 — both fields are persisted by ws_create_task / ws_update_task
|
||||
# and consumed by helpers/action_listener.py on EVENT_TASK_COMPLETED, but
|
||||
# were missing from this response builder until issue #50. Without them
|
||||
@@ -312,6 +347,20 @@ def _build_object_response(hass: HomeAssistant, entry: ConfigEntry, coordinator_
|
||||
# (roadmap P2) count of attached documents (files + web-links) for
|
||||
# the objects-table paperclip badge; computed, not persisted.
|
||||
"document_count": document_count,
|
||||
# An UPLOADED manual (category tag "manual") is the same affordance
|
||||
# as documentation_url — expose them so the "manual" column and the
|
||||
# object header can fall back instead of rendering "—" next to an
|
||||
# object that plainly has its manual attached.
|
||||
"manual_docs": [
|
||||
{
|
||||
"id": d.get("id"),
|
||||
"title": d.get("title") or d.get("filename") or "",
|
||||
"kind": d.get("kind"),
|
||||
"url": d.get("url"),
|
||||
}
|
||||
for d in object_docs
|
||||
if "manual" in (d.get("tags") or [])
|
||||
],
|
||||
},
|
||||
"tasks": tasks,
|
||||
"parts": parts_payload,
|
||||
@@ -428,10 +477,12 @@ def async_register_commands(hass: HomeAssistant) -> None:
|
||||
ws_set_environmental_entity,
|
||||
)
|
||||
from .battery_fleet import (
|
||||
ws_battery_fleet_history,
|
||||
ws_battery_fleet_mark_replaced,
|
||||
ws_battery_fleet_overview,
|
||||
ws_battery_fleet_set_excluded,
|
||||
ws_battery_fleet_setup,
|
||||
ws_battery_fleet_status,
|
||||
)
|
||||
from .dashboard import (
|
||||
ws_get_budget_status,
|
||||
@@ -505,6 +556,7 @@ def async_register_commands(hass: HomeAssistant) -> None:
|
||||
from .tags import ws_list_tags
|
||||
from .tasks import (
|
||||
ws_archive_task,
|
||||
ws_checklist_progress,
|
||||
ws_complete_task,
|
||||
ws_create_task,
|
||||
ws_delete_task,
|
||||
@@ -515,6 +567,7 @@ def async_register_commands(hass: HomeAssistant) -> None:
|
||||
ws_reset_task,
|
||||
ws_skip_task,
|
||||
ws_snooze_task,
|
||||
ws_task_history,
|
||||
ws_unarchive_task,
|
||||
ws_update_history_entry,
|
||||
ws_update_task,
|
||||
@@ -548,8 +601,10 @@ def async_register_commands(hass: HomeAssistant) -> None:
|
||||
websocket_api.async_register_command(hass, ws_archive_task)
|
||||
websocket_api.async_register_command(hass, ws_unarchive_task)
|
||||
websocket_api.async_register_command(hass, ws_list_tasks)
|
||||
websocket_api.async_register_command(hass, ws_task_history)
|
||||
websocket_api.async_register_command(hass, ws_complete_task)
|
||||
websocket_api.async_register_command(hass, ws_quick_complete_task)
|
||||
websocket_api.async_register_command(hass, ws_checklist_progress)
|
||||
websocket_api.async_register_command(hass, ws_skip_task)
|
||||
websocket_api.async_register_command(hass, ws_reset_task)
|
||||
websocket_api.async_register_command(hass, ws_snooze_task)
|
||||
@@ -571,6 +626,8 @@ def async_register_commands(hass: HomeAssistant) -> None:
|
||||
websocket_api.async_register_command(hass, ws_discover_problem_sensors)
|
||||
websocket_api.async_register_command(hass, ws_adopt_problem_sensors)
|
||||
websocket_api.async_register_command(hass, ws_battery_fleet_overview)
|
||||
websocket_api.async_register_command(hass, ws_battery_fleet_history)
|
||||
websocket_api.async_register_command(hass, ws_battery_fleet_status)
|
||||
websocket_api.async_register_command(hass, ws_battery_fleet_setup)
|
||||
websocket_api.async_register_command(hass, ws_battery_fleet_mark_replaced)
|
||||
websocket_api.async_register_command(hass, ws_battery_fleet_set_excluded)
|
||||
|
||||
Reference in New Issue
Block a user