Refactor to-do list order and reordering in Habitica (#138566)

pull/139212/head
Manu 2025-02-24 17:36:20 +01:00 committed by GitHub
parent 461039f06a
commit 2e5f56b70d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 84 additions and 28 deletions

View File

@ -117,20 +117,24 @@ class BaseHabiticaListEntity(HabiticaBase, TodoListEntity):
"""Move an item in the To-do list."""
if TYPE_CHECKING:
assert self.todo_items
tasks_order = (
self.coordinator.data.user.tasksOrder.todos
if self.entity_description.key is HabiticaTodoList.TODOS
else self.coordinator.data.user.tasksOrder.dailys
)
if previous_uid:
pos = self.todo_items.index(
next(item for item in self.todo_items if item.uid == previous_uid)
)
if pos < self.todo_items.index(
next(item for item in self.todo_items if item.uid == uid)
):
pos = tasks_order.index(UUID(previous_uid))
if pos < tasks_order.index(UUID(uid)):
pos += 1
else:
pos = 0
try:
await self.coordinator.habitica.reorder_task(UUID(uid), pos)
tasks_order[:] = (
await self.coordinator.habitica.reorder_task(UUID(uid), pos)
).data
except TooManyRequestsError as e:
raise HomeAssistantError(
translation_domain=DOMAIN,
@ -144,20 +148,6 @@ class BaseHabiticaListEntity(HabiticaBase, TodoListEntity):
translation_key=f"move_{self.entity_description.key}_item_failed",
translation_placeholders={"pos": str(pos)},
) from e
else:
# move tasks in the coordinator until we have fresh data
tasks = self.coordinator.data.tasks
new_pos = (
tasks.index(
next(task for task in tasks if task.id == UUID(previous_uid))
)
+ 1
if previous_uid
else 0
)
old_pos = tasks.index(next(task for task in tasks if task.id == UUID(uid)))
tasks.insert(new_pos, tasks.pop(old_pos))
await self.coordinator.async_request_refresh()
async def async_update_todo_item(self, item: TodoItem) -> None:
"""Update a Habitica todo."""
@ -271,7 +261,7 @@ class HabiticaTodosListEntity(BaseHabiticaListEntity):
def todo_items(self) -> list[TodoItem]:
"""Return the todo items."""
return [
tasks = [
*(
TodoItem(
uid=str(task.id),
@ -288,6 +278,15 @@ class HabiticaTodosListEntity(BaseHabiticaListEntity):
if task.Type is TaskType.TODO
),
]
return sorted(
tasks,
key=lambda task: (
float("inf")
if (uid := UUID(task.uid))
not in (tasks_order := self.coordinator.data.user.tasksOrder.todos)
else tasks_order.index(uid)
),
)
async def async_create_todo_item(self, item: TodoItem) -> None:
"""Create a Habitica todo."""
@ -348,7 +347,7 @@ class HabiticaDailiesListEntity(BaseHabiticaListEntity):
if TYPE_CHECKING:
assert self.coordinator.data.user.lastCron
return [
tasks = [
*(
TodoItem(
uid=str(task.id),
@ -365,3 +364,12 @@ class HabiticaDailiesListEntity(BaseHabiticaListEntity):
if task.Type is TaskType.DAILY
)
]
return sorted(
tasks,
key=lambda task: (
float("inf")
if (uid := UUID(task.uid))
not in (tasks_order := self.coordinator.data.user.tasksOrder.dailys)
else tasks_order.index(uid)
),
)

View File

@ -0,0 +1,15 @@
{
"success": true,
"data": [
"f21fa608-cfc6-4413-9fc7-0eb1b48ca43a",
"2c6d136c-a1c3-4bef-b7c4-fa980784b1e1",
"bc1d1855-b2b8-4663-98ff-62e7b763dfc4",
"e97659e0-2c42-4599-a7bb-00282adc410d",
"564b9ac9-c53d-4638-9e7f-1cd96fe19baa",
"f2c85972-1a19-4426-bc6d-ce3337b9d99f",
"6e53f1f5-a315-4edd-984d-8d762e4a08ef"
],
"notifications": [],
"userV": 589,
"appVersion": "5.28.6"
}

View File

@ -0,0 +1,12 @@
{
"success": true,
"data": [
"88de7cd9-af2b-49ce-9afd-bf941d87336b",
"1aa3137e-ef72-4d1f-91ee-41933602f438",
"2f6fcabc-f670-4ec3-ba65-817e8deea490",
"86ea2475-d1b5-4020-bdcc-c188c7996afa"
],
"notifications": [],
"userV": 589,
"appVersion": "5.28.6"
}

View File

@ -6,7 +6,13 @@ from typing import Any
from unittest.mock import AsyncMock, patch
from uuid import UUID
from habiticalib import Direction, HabiticaTasksResponse, Task, TaskType
from habiticalib import (
Direction,
HabiticaTaskOrderResponse,
HabiticaTasksResponse,
Task,
TaskType,
)
import pytest
from syrupy.assertion import SnapshotAssertion
@ -601,19 +607,23 @@ async def test_delete_completed_todo_items_exception(
@pytest.mark.parametrize(
("entity_id", "uid", "second_pos", "third_pos"),
("entity_id", "uid", "second_pos", "third_pos", "fixture", "task_type"),
[
(
"todo.test_user_to_do_s",
"1aa3137e-ef72-4d1f-91ee-41933602f438",
"88de7cd9-af2b-49ce-9afd-bf941d87336b",
"2f6fcabc-f670-4ec3-ba65-817e8deea490",
"reorder_todos_response.json",
"todos",
),
(
"todo.test_user_dailies",
"2c6d136c-a1c3-4bef-b7c4-fa980784b1e1",
"564b9ac9-c53d-4638-9e7f-1cd96fe19baa",
"f2c85972-1a19-4426-bc6d-ce3337b9d99f",
"f21fa608-cfc6-4413-9fc7-0eb1b48ca43a",
"bc1d1855-b2b8-4663-98ff-62e7b763dfc4",
"reorder_dailies_response.json",
"dailys",
),
],
ids=["todo", "daily"],
@ -627,9 +637,14 @@ async def test_move_todo_item(
uid: str,
second_pos: str,
third_pos: str,
fixture: str,
task_type: str,
) -> None:
"""Test move todo items."""
reorder_response = HabiticaTaskOrderResponse.from_json(
load_fixture(fixture, DOMAIN)
)
habitica.reorder_task.return_value = reorder_response
config_entry.add_to_hass(hass)
await hass.config_entries.async_setup(config_entry.entry_id)
await hass.async_block_till_done()
@ -650,6 +665,7 @@ async def test_move_todo_item(
assert resp.get("success")
habitica.reorder_task.assert_awaited_once_with(UUID(uid), 1)
habitica.reorder_task.reset_mock()
# move down to third position
@ -665,6 +681,7 @@ async def test_move_todo_item(
assert resp.get("success")
habitica.reorder_task.assert_awaited_once_with(UUID(uid), 2)
habitica.reorder_task.reset_mock()
# move to top position
@ -679,6 +696,10 @@ async def test_move_todo_item(
assert resp.get("success")
habitica.reorder_task.assert_awaited_once_with(UUID(uid), 0)
assert (
getattr(config_entry.runtime_data.data.user.tasksOrder, task_type)
== reorder_response.data
)
@pytest.mark.parametrize(