core/homeassistant/components/ourgroceries/todo.py

120 lines
4.1 KiB
Python

"""A todo platform for OurGroceries."""
import asyncio
from typing import Any
from homeassistant.components.todo import (
TodoItem,
TodoItemStatus,
TodoListEntity,
TodoListEntityFeature,
)
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.update_coordinator import CoordinatorEntity
from .const import DOMAIN
from .coordinator import OurGroceriesDataUpdateCoordinator
async def async_setup_entry(
hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback
) -> None:
"""Set up the OurGroceries todo platform config entry."""
coordinator: OurGroceriesDataUpdateCoordinator = hass.data[DOMAIN][entry.entry_id]
async_add_entities(
OurGroceriesTodoListEntity(coordinator, sl["id"], sl["name"])
for sl in coordinator.lists
)
def _completion_status(item: dict[str, Any]) -> TodoItemStatus:
if item.get("crossedOffAt", False):
return TodoItemStatus.COMPLETED
return TodoItemStatus.NEEDS_ACTION
class OurGroceriesTodoListEntity(
CoordinatorEntity[OurGroceriesDataUpdateCoordinator], TodoListEntity
):
"""An OurGroceries TodoListEntity."""
_attr_has_entity_name = True
_attr_supported_features = (
TodoListEntityFeature.CREATE_TODO_ITEM
| TodoListEntityFeature.UPDATE_TODO_ITEM
| TodoListEntityFeature.DELETE_TODO_ITEM
)
def __init__(
self,
coordinator: OurGroceriesDataUpdateCoordinator,
list_id: str,
list_name: str,
) -> None:
"""Initialize TodoistTodoListEntity."""
super().__init__(coordinator=coordinator)
self._list_id = list_id
self._attr_unique_id = list_id
self._attr_name = list_name
@callback
def _handle_coordinator_update(self) -> None:
"""Handle updated data from the coordinator."""
if self.coordinator.data is None:
self._attr_todo_items = None
else:
self._attr_todo_items = [
TodoItem(
summary=item["name"],
uid=item["id"],
status=_completion_status(item),
)
for item in self.coordinator.data[self._list_id]["list"]["items"]
]
super()._handle_coordinator_update()
async def async_create_todo_item(self, item: TodoItem) -> None:
"""Create a To-do item."""
if item.status != TodoItemStatus.NEEDS_ACTION:
raise ValueError("Only active tasks may be created.")
await self.coordinator.og.add_item_to_list(
self._list_id, item.summary, auto_category=True
)
await self.coordinator.async_refresh()
async def async_update_todo_item(self, item: TodoItem) -> None:
"""Update a To-do item."""
if item.summary:
api_items = self.coordinator.data[self._list_id]["list"]["items"]
category = next(
api_item.get("categoryId")
for api_item in api_items
if api_item["id"] == item.uid
)
await self.coordinator.og.change_item_on_list(
self._list_id, item.uid, category, item.summary
)
if item.status is not None:
cross_off = item.status == TodoItemStatus.COMPLETED
await self.coordinator.og.toggle_item_crossed_off(
self._list_id, item.uid, cross_off=cross_off
)
await self.coordinator.async_refresh()
async def async_delete_todo_items(self, uids: list[str]) -> None:
"""Delete a To-do item."""
await asyncio.gather(
*[
self.coordinator.og.remove_item_from_list(self._list_id, uid)
for uid in uids
]
)
await self.coordinator.async_refresh()
async def async_added_to_hass(self) -> None:
"""When entity is added to hass update state from existing coordinator data."""
await super().async_added_to_hass()
self._handle_coordinator_update()