Multiple feature additions and improvements across the application: - NextGen Editor: drag handles, smart paste, block actions - Structured views: Kanban and table layouts for notes - Architectural Grid: new brainstorming/agent interface prototype - Flashcards: SM-2 revision algorithm with AI generation - MCP server: robustness improvements - Graph/PDF chat: fix click propagation and copy behavior - Various UI/UX enhancements and bug fixes Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
93 lines
7.3 KiB
Markdown
93 lines
7.3 KiB
Markdown
---
|
|
title: 'Unified Tasks View — cross-format aggregation study'
|
|
type: 'feature'
|
|
created: '2026-05-24'
|
|
status: 'done' # cancelled — product decision option A (2026-05-24): removed aggregated Tasks view; use Structured Kanban instead
|
|
context:
|
|
- '{project-root}/AGENTS.md'
|
|
- '{project-root}/memento-note/components/notes-list-views.tsx'
|
|
- '{project-root}/memento-note/lib/types.ts'
|
|
---
|
|
|
|
<frozen-after-approval reason="human-owned intent — do not modify unless human renegotiates">
|
|
|
|
## Intent
|
|
|
|
**Problem:** The home **Notes / Tasks** toggle only aggregates Markdown `- [ ]` / `- [x]` lines from `Note.content`. Rich-text TipTap task lists (HTML in `content`) and legacy `checklist` notes (`checkItems` JSON) are invisible in Tasks view, stats column, and sort-by-tasks — causing empty or misleading UX when users create to-dos via the editor or legacy data.
|
|
|
|
**Approach:** Introduce a single extraction layer (`lib/tasks/`) that normalizes tasks from all three sources into a stable `UnifiedTask` model with source-specific stable IDs; update toggle/save paths to write back to the correct storage; refresh i18n to explain supported formats without Markdown-only wording.
|
|
|
|
## Boundaries & Constraints
|
|
|
|
**Always:** No DB schema migration in v1 unless human approves; reuse existing `content` / `checkItems` fields; toggle must use optimistic `updateNote` + `onNotePatch`; all user-facing strings via i18n (EN+FR minimum); no new tests unless explicitly requested; do not conflate Structured Views `checkbox` properties with inline note tasks.
|
|
|
|
**Ask First:** Deprecate vs revive `type: checklist` (dedicated note type); one-way migration of legacy `checkItems` → Markdown or TipTap; nested TipTap task support in aggregated view; scope of 15-locale fill vs EN/FR keys only.
|
|
|
|
**Never:** Treat Structured View kanban/status as Tasks view; store a parallel tasks table; rewrite entire editor serialization to JSON; run destructive DB commands; claim done without manual verification on markdown + richtext + checklist sample notes.
|
|
|
|
## I/O & Edge-Case Matrix
|
|
|
|
| Scenario | Input / State | Expected Output / Behavior | Error Handling |
|
|
|----------|--------------|---------------------------|----------------|
|
|
| Markdown tasks | `type: markdown`, content with `- [ ]` lines | Tasks listed; toggle flips `[ ]`↔`[x]` in content | Skip malformed lines |
|
|
| TipTap tasks | `type: richtext`, HTML with `ul[data-type="taskList"]` | Tasks listed with text from `<p>` inside `li`; toggle updates `data-checked` + checkbox | Skip items without parseable text |
|
|
| Checklist note | `type: checklist`, `checkItems: [{id,text,checked}]` | All items listed; toggle updates matching item by `id` | Normalize legacy `done` → `checked` on read |
|
|
| Mixed note | Markdown lines + TipTap HTML in same richtext note | Both sources extracted (dedupe by normalized text optional v2) | No double-toggle same semantic item in v1 if ambiguous |
|
|
| Empty scope | Notebook with no extractable tasks | Empty state with format-agnostic hint | No errors |
|
|
| Toggle race | User toggles in Tasks while note open in editor | Last write wins or editor refresh via `emitNoteChange` | Log + refetch on mismatch |
|
|
| API update | `PUT /api/notes` with `checkItems` | Same JSON.stringify behavior as server actions | Align API with actions in same PR |
|
|
|
|
</frozen-after-approval>
|
|
|
|
## Code Map
|
|
|
|
- `memento-note/components/notes-list-views.tsx` — current `extractTasksFromNotes`, `getNoteTasksStats`, `handleToggleTask`, Tasks UI
|
|
- `memento-note/components/home-client.tsx` — Notes/Tasks toggle, passes notes into list views
|
|
- `memento-note/lib/types.ts` — `CheckItem`, `NoteType`
|
|
- `memento-note/lib/utils.ts` — `parseNote`, `checkItems` deserialization
|
|
- `memento-note/components/rich-text-editor.tsx` — TipTap TaskList/TaskItem extensions
|
|
- `memento-note/components/note-editor/note-editor-context.tsx` — save forces `checkItems: null`; dormant checklist handlers
|
|
- `memento-note/components/note-checklist.tsx` — checklist UI (legacy card path)
|
|
- `memento-note/components/note-card.tsx` — checklist toggle via `updateNote({ checkItems })`
|
|
- `memento-note/app/actions/notes.ts` — canonical server update, JSON.stringify checkItems
|
|
- `memento-note/app/api/notes/[id]/route.ts` — API checkItems inconsistency
|
|
- `memento-note/locales/en.json`, `fr.json` — `notes.viewTasks`, `tasksEmptyHint`, etc.
|
|
- `memento-note/lib/note-preview.ts` — excerpt may leak `[ ]` syntax
|
|
|
|
## Tasks & Acceptance
|
|
|
|
**Execution (proposed — after study approval):**
|
|
- [ ] `memento-note/lib/tasks/types.ts` — define `UnifiedTask`, `TaskSource`, stable `taskKey` — single contract for UI
|
|
- [ ] `memento-note/lib/tasks/extract-tasks.ts` — extract from markdown lines, TipTap HTML (DOMParser or regex+guard), checkItems — replaces inline regex in list views
|
|
- [ ] `memento-note/lib/tasks/toggle-task.ts` — source-aware write-back to content or checkItems — replaces fragile lineIndex-only toggle
|
|
- [ ] `memento-note/components/notes-list-views.tsx` — wire extract/toggle helpers; show source badge optional — keep UI, fix data layer
|
|
- [ ] `memento-note/locales/en.json`, `fr.json` — tasksEmptyHint, tasksHeader, optional `tasksSourceMarkdown` / `tasksSourceRichText` / `tasksSourceChecklist` — honest UX
|
|
- [ ] `memento-note/app/api/notes/[id]/route.ts` — stringify checkItems like server actions — fix API drift
|
|
|
|
**Acceptance Criteria:**
|
|
- Given a markdown note with `- [ ] Buy milk`, when user opens Tasks view for that notebook, then the task appears and toggling persists after reload.
|
|
- Given a richtext note with TipTap task list in saved HTML, when user opens Tasks view, then tasks appear with correct checked state.
|
|
- Given a checklist note with `checkItems`, when user opens Tasks view, then items appear and toggle updates `checkItems` not content.
|
|
- Given empty notebook, when user opens Tasks view, then empty state text does not mention Markdown-only format.
|
|
- Given user toggles task in aggregated view, when note is reopened, then editor reflects the same checked state.
|
|
|
|
## Design Notes
|
|
|
|
**Recommended architecture:** pure functions in `lib/tasks/` — no new DB columns. `UnifiedTask` fields: `taskKey`, `noteId`, `noteTitle`, `text`, `completed`, `source: 'markdown'|'tiptap'|'checklist'`, `locator` (lineIndex | domPath | checkItemId).
|
|
|
|
**TipTap HTML (observed):** `ul[data-type="taskList"] > li[data-type="taskItem"][data-checked="true|false"]` with label+checkbox and content in nested `div > p`. Toggle: flip `data-checked`, sync `input:checked`, preserve HTML structure.
|
|
|
|
**Checklist type decision:** AGENTS.md documents type as legacy/semi-dead. v1 should **read** existing `checkItems` in Tasks view; reviving full checklist editor is a separate story.
|
|
|
|
**i18n:** Replace Markdown-only hint with product copy: tasks are collected from checkboxes in notes (lists in rich text, markdown, or checklist notes). Optional short “How it works” link/tooltip.
|
|
|
|
**Out of scope v1:** Structured Views checkbox properties; cross-note deduplication; migrating all checklist notes to richtext; nested task hierarchy display.
|
|
|
|
## Verification
|
|
|
|
**Commands:**
|
|
- `cd memento-note && npm run lint` — expected: no new errors in touched files
|
|
|
|
**Manual checks:**
|
|
- Create 3 notes in one notebook: markdown with `- [ ]`, richtext with TipTap todo block, import/mock checklist with checkItems — all visible in Tasks view, each toggle survives refresh.
|