Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion openbot/app/src/components/shell/tasks-active.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -388,12 +388,17 @@ function TaskLine({
onCheck: (done: boolean, failed: () => void) => void;
}) {
const { task, status } = item;
// The check follows the resolution timestamp, like the task page does — not the
// grouped status, which stays "needs_input" while a question waits even after
// the task was marked done. Otherwise the row offers "Mark done" again and
// resolves a second time instead of reopening.
const done = task.resolvedAt !== null;
return (
<>
<div className="flex items-start gap-3">
<CheckBox
busy={busy}
done={status === "resolved"}
done={done}
onCheck={onCheck}
title={task.title}
/>
Expand Down
45 changes: 45 additions & 0 deletions openbot/app/tests/tasks-screen.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -766,6 +766,51 @@ test("a done task's circle is filled, and pressing it reopens the task", async (
);
});

test("a done task still offers Reopen under Needs input while its question waits", async () => {
quiet();
inbox = {
requests: [],
questions: [
{
id: "q-1",
botId: "openduet",
threadId: "question-task-thread",
question: "Which deck should I review?",
createdAt: ago(10),
},
],
};
tasks = [
task({
id: "question-task",
title: "Choose a deck",
status: "needs_input",
resolvedAt: ago(3),
}),
];
serving();
const view = draw();
const needs = await view.findByRole("region", { name: "Needs input" });
expect(within(needs).getByText("Choose a deck")).toBeTruthy();
const circle = await view.findByRole("button", {
name: "Reopen Choose a deck",
});
expect(circle.getAttribute("aria-pressed")).toBe("true");
fireEvent.click(circle);
await waitFor(() =>
expect(sent).toContainEqual({
method: "POST",
path: "/api/openduet/tasks/question-task/reopen",
body: undefined,
}),
);
expect(sent).not.toContainEqual({
method: "POST",
path: "/api/openduet/tasks/question-task/resolve",
body: undefined,
});
});

test("Resolved keeps a week of done tasks, newest first, folded until its heading is pressed", async () => {
quiet();
tasks = [
Expand Down