feat(tasks): undo a completion, and a place to find what was closed
Reported from use: "I just closed a task by accident, and there is no undo and no list of closed tasks." Both halves were true. Completing is one click on a small circle beside a row you were only reading, and it takes the row off the screen — so the mistake and the evidence of it leave together. There was no name left to search for and nowhere to look: the project page can show its own closed tasks, but only if you already know which project it was in. The toast covers the mistake you notice at once. It names the task, so you can see which one you hit, and stands for twelve seconds rather than five — five is enough to read "could not save" and not enough to notice, decide and reach the mouse. A toast with an action also gets two targets: the message dismisses and the action acts, which were one button before and would otherwise put "yes, put it back" and "go away" in the same place. `/faerdige` covers the one you notice tomorrow. A place rather than a toggle in every view, because somebody hunting for a task they closed does not know which view they closed it in. Newest first — a record of what is finished is read backwards from now, not by a due date the task no longer has — and grouped by the day, because "I dag" and "I går" is how anybody would describe it. A recurring task is offered no undo. Completing it moves it to its next date rather than closing it, so there is nothing to reverse, and an undo that quietly rolled the date back would be a different act from the one it claims to be. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
0dbf7a40bf
commit
a52ad9817f
@@ -1392,6 +1392,61 @@ test('en opgave kan skrives direkte i en sektion @forms', async ({ page }) => {
|
||||
expect(trouble).toEqual([]);
|
||||
});
|
||||
|
||||
/**
|
||||
* A task closed by mistake can be got back, two ways.
|
||||
*
|
||||
* Reported from use: "I just closed a task by accident, and there is no undo and no
|
||||
* list of closed tasks." Both halves were true. Completing is one click on a small
|
||||
* circle beside a row you were only reading, and it takes the row off the screen —
|
||||
* so the mistake and the evidence of it leave together.
|
||||
*
|
||||
* The toast covers the mistake you notice at once. Færdige covers the one you
|
||||
* notice tomorrow, and it is a place rather than a toggle because somebody hunting
|
||||
* for a task they closed does not know which view they closed it in.
|
||||
*/
|
||||
test('en opgave lukket ved et uheld kan hentes tilbage', async ({ page }) => {
|
||||
const trouble = watchForTrouble(page);
|
||||
await page.goto('/');
|
||||
|
||||
await page.getByLabel('Ny opgave').fill('rens tagrenden i dag');
|
||||
await page.getByLabel('Ny opgave').press('Enter');
|
||||
const row = page.locator('.row').filter({ hasText: 'rens tagrenden' });
|
||||
await expect(row).toBeVisible();
|
||||
|
||||
// Closed by mistake.
|
||||
await row.getByRole('button', { name: 'Markér som færdig' }).click();
|
||||
await expect(page.getByText('rens tagrenden', { exact: true })).toBeHidden();
|
||||
|
||||
// The toast names it, so you can tell which one you hit.
|
||||
const toast = page.locator('.toast').filter({ hasText: 'rens tagrenden' });
|
||||
await expect(toast).toBeVisible();
|
||||
await toast.getByRole('button', { name: 'Fortryd' }).click();
|
||||
await expect(page.locator('.row').filter({ hasText: 'rens tagrenden' })).toBeVisible();
|
||||
|
||||
// Now the other half: close it again and walk away from the toast.
|
||||
await page
|
||||
.locator('.row')
|
||||
.filter({ hasText: 'rens tagrenden' })
|
||||
.getByRole('button', { name: 'Markér som færdig' })
|
||||
.click();
|
||||
await expect(page.getByText('rens tagrenden', { exact: true })).toBeHidden();
|
||||
|
||||
const sidebar = page.getByRole('navigation', { name: 'Hovedmenu' });
|
||||
await sidebar.getByRole('link', { name: 'Færdige' }).click();
|
||||
await expect(page.getByRole('heading', { name: 'Færdige', level: 1 })).toBeVisible();
|
||||
|
||||
const closed = page.locator('.row').filter({ hasText: 'rens tagrenden' });
|
||||
await expect(closed).toBeVisible();
|
||||
// Grouped by the day it was closed, which is how anybody would describe it.
|
||||
await expect(page.getByRole('heading', { name: 'I dag', level: 2 })).toBeVisible();
|
||||
|
||||
// And it reopens from here, leaving the list at once.
|
||||
await closed.getByRole('button', { name: 'Genåbn opgave' }).click();
|
||||
await expect(page.locator('.row').filter({ hasText: 'rens tagrenden' })).toHaveCount(0);
|
||||
|
||||
expect(trouble).toEqual([]);
|
||||
});
|
||||
|
||||
/**
|
||||
* The sidebar never scrolls sideways.
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user