Add LLM docs
This commit is contained in:
parent
105a913a8d
commit
a0b769164c
14 changed files with 6991 additions and 115 deletions
113
CLAUDE.md
113
CLAUDE.md
|
|
@ -48,27 +48,34 @@ npm start # Frontend on :8080, Backend on :3002
|
|||
- Migration best practices
|
||||
- Common migration operations
|
||||
|
||||
5. **[Development Workflow](docs/development-workflow.md)**
|
||||
5. **[Backups & Restoration](docs/backups.md)**
|
||||
- Automatic SQLite file backups before migrations
|
||||
- Backup retention policies (4 per day, 1 per day for 7 days)
|
||||
- Restoration procedures for development, Docker, and production
|
||||
- Emergency restore after failed migrations
|
||||
- Best practices for data safety
|
||||
|
||||
6. **[Development Workflow](docs/development-workflow.md)**
|
||||
- Initial setup
|
||||
- Daily development (two-server process)
|
||||
- Environment variables
|
||||
- Adding new features (complete walkthrough)
|
||||
- Database management commands
|
||||
|
||||
6. **[Code Conventions](docs/code-conventions.md)**
|
||||
7. **[Code Conventions](docs/code-conventions.md)**
|
||||
- Language usage (TypeScript/JavaScript)
|
||||
- Backend patterns (async/await, repository)
|
||||
- Frontend patterns (components, state)
|
||||
- Naming conventions
|
||||
- API route conventions
|
||||
|
||||
7. **[Testing](docs/testing.md)**
|
||||
8. **[Testing](docs/testing.md)**
|
||||
- Test organization
|
||||
- Running tests
|
||||
- Testing requirements
|
||||
- Test patterns (Arrange-Act-Assert)
|
||||
|
||||
8. **[Common Tasks](docs/common-tasks.md)**
|
||||
9. **[Common Tasks](docs/common-tasks.md)**
|
||||
- Add field to model
|
||||
- Create new backend module
|
||||
- Add React component
|
||||
|
|
@ -76,7 +83,101 @@ npm start # Frontend on :8080, Backend on :3002
|
|||
- Fix a bug (TDD workflow)
|
||||
- Add translations
|
||||
|
||||
9. **[Claude Memory & Preferences](docs/MEMORY.md)**
|
||||
10. **[Tasks Behavior](docs/00-tasks-behavior.md)**
|
||||
- Task creation and basic fields
|
||||
- Status lifecycle and priority levels
|
||||
- Due dates and Defer Until
|
||||
- Subtasks and hierarchy
|
||||
- File attachments
|
||||
- Project assignment and tags
|
||||
- Task completion and history
|
||||
- Habit mode and tracking
|
||||
- Task deletion and permissions
|
||||
|
||||
11. **[Recurring Tasks Behavior](docs/01-recurring-tasks-behavior.md)**
|
||||
- How recurring tasks work (non-technical rules)
|
||||
- Completion behavior and patterns
|
||||
- Virtual instances and display rules
|
||||
- Parent-child relationships
|
||||
- Editing and deletion behavior
|
||||
|
||||
12. **[Today Page Sections](docs/02-today-page-sections.md)**
|
||||
- How Overdue, Planned, Suggested, and Completed sections work
|
||||
- Task filtering and display rules
|
||||
- Section priority and deduplication logic
|
||||
- User settings and customization
|
||||
- Defer Until and timezone handling
|
||||
|
||||
13. **[Upcoming View](docs/03-upcoming-view.md)**
|
||||
- How the 7-day Upcoming view works
|
||||
- Day-based grouping and organization
|
||||
- Recurring task virtual occurrences
|
||||
- Defer Until and status filtering
|
||||
- Differences from Today view
|
||||
|
||||
14. **[Inbox Page](docs/04-inbox-page.md)**
|
||||
- Quick capture system for unorganized thoughts
|
||||
- Smart parsing of hashtags, projects, and URLs
|
||||
- Intelligent suggestions (Task vs Note vs Project)
|
||||
- Converting inbox items to structured content
|
||||
- Telegram integration and auto-refresh
|
||||
- Keyboard shortcuts and workflows
|
||||
|
||||
15. **[Notes System](docs/05-notes-system.md)**
|
||||
- Flexible information and reference storage
|
||||
- Markdown support and rich text rendering
|
||||
- Auto-save functionality (1-second debounce)
|
||||
- Project linking and tag-based organization
|
||||
- Focus mode for distraction-free writing
|
||||
- Color customization for visual organization
|
||||
- Integration with inbox and project workflows
|
||||
|
||||
16. **[Projects](docs/06-projects.md)**
|
||||
- Project hierarchy and organization (Areas > Projects > Tasks)
|
||||
- Status lifecycle and stalled detection
|
||||
- Completion tracking and progress metrics
|
||||
- Project sharing and collaboration permissions
|
||||
- Due dates, notifications, and priorities
|
||||
- Deletion behavior (orphaning vs cascading)
|
||||
- Filtering, grouping, and sidebar pinning
|
||||
|
||||
17. **[Areas](docs/07-areas.md)**
|
||||
- Top-level organizational categories for life domains
|
||||
- Simple structure with name and description
|
||||
- Optional containers for grouping projects
|
||||
- Cascade behavior when deleting (orphans projects)
|
||||
- Grid view with alphabetical sorting
|
||||
- Integration with Projects page filtering and grouping
|
||||
|
||||
18. **[Views System](docs/08-views-system.md)**
|
||||
- Smart saved searches for tasks, notes, and projects
|
||||
- Creating views from Universal Search
|
||||
- Pinning and reordering views in sidebar
|
||||
- Filtering, sorting, and grouping within views
|
||||
- View management (rename, delete, pin/unpin)
|
||||
- URL parameters and deep linking
|
||||
- Pagination and performance
|
||||
|
||||
19. **[User Management](docs/08-user-management.md)**
|
||||
- Registration flow and email verification
|
||||
- Authentication (session-based and API tokens)
|
||||
- User roles and admin system
|
||||
- Resource permissions and sharing
|
||||
- Profile management and preferences
|
||||
- Password and avatar management
|
||||
- API token management
|
||||
- Admin user CRUD operations
|
||||
|
||||
20. **[Tags System](docs/09-tags-system.md)**
|
||||
- Cross-entity labeling and categorization (tasks, notes, projects)
|
||||
- Auto-creation and validation rules
|
||||
- Tag management (create, edit, delete, rename)
|
||||
- Tag detail pages with filtering and search
|
||||
- Alphabetical grouping and organization
|
||||
- Hashtag parsing from inbox items
|
||||
- Tag input component with autocomplete
|
||||
|
||||
21. **[Claude Memory & Preferences](docs/MEMORY.md)**
|
||||
- PR and commit message preferences
|
||||
- Testing preferences
|
||||
- Common patterns to remember
|
||||
|
|
@ -168,5 +269,5 @@ Tududi is a self-hosted task management system designed around hierarchical orga
|
|||
---
|
||||
|
||||
**Document Version:** 1.0.0
|
||||
**Last Updated:** 2026-03-13
|
||||
**Last Updated:** 2026-03-14
|
||||
**Maintainer:** Update when architecture changes or patterns evolve
|
||||
|
|
|
|||
514
docs/00-tasks-behavior.md
Normal file
514
docs/00-tasks-behavior.md
Normal file
|
|
@ -0,0 +1,514 @@
|
|||
# Tasks - Behavior Rules
|
||||
|
||||
This document explains how tasks work in tududi from a user behavior perspective (excluding recurring tasks, which are covered in [01-recurring-tasks-behavior.md](01-recurring-tasks-behavior.md)). For technical implementation details, see the backend code in `/backend/modules/tasks/` and `/backend/models/task.js`.
|
||||
|
||||
---
|
||||
|
||||
## **Task Creation**
|
||||
|
||||
### Basic Task Creation
|
||||
|
||||
1. **A task requires only a name to be created**
|
||||
- All other fields (due date, priority, project, etc.) are optional
|
||||
- Task name cannot be empty or just whitespace
|
||||
- Tasks are created with "Not Started" status by default
|
||||
|
||||
2. **Every task gets a unique identifier (UID)**
|
||||
- Used in URLs and API calls
|
||||
- Never changes during the task's lifetime
|
||||
- Example: `tsk_abc123def456`
|
||||
|
||||
3. **Tasks belong to a user**
|
||||
- The creator becomes the owner
|
||||
- Only the owner (or those with shared access) can view/modify the task
|
||||
- Admins can access all tasks
|
||||
|
||||
### Quick Capture
|
||||
|
||||
4. **Tasks can be created from multiple places:**
|
||||
- Main task list (+ button)
|
||||
- Today page quick add
|
||||
- Inbox (converted from inbox items)
|
||||
- Quick capture modal (keyboard shortcut)
|
||||
- Telegram bot
|
||||
- API
|
||||
|
||||
---
|
||||
|
||||
## **Task Fields & Properties**
|
||||
|
||||
### Name & Description
|
||||
|
||||
5. **Task name is the primary identifier**
|
||||
- Required field, maximum length varies by database
|
||||
- Displayed in lists, calendars, and notifications
|
||||
- Can be edited at any time
|
||||
|
||||
6. **Task note is for detailed information**
|
||||
- Optional text field for longer descriptions
|
||||
- Supports plain text (no markdown formatting)
|
||||
- Useful for context, instructions, or reference materials
|
||||
|
||||
### Status Lifecycle
|
||||
|
||||
7. **Seven status states exist:**
|
||||
- **Not Started (0):** Default state, task hasn't been worked on yet
|
||||
- **In Progress (1):** Task is actively being worked on
|
||||
- **Done (2):** Task is completed
|
||||
- **Archived (3):** Task is finished and archived for historical record
|
||||
- **Waiting (4):** Task is blocked or waiting on something/someone
|
||||
- **Cancelled (5):** Task was abandoned or is no longer needed
|
||||
- **Planned (6):** Task is scheduled to be worked on
|
||||
|
||||
8. **Status changes affect visibility:**
|
||||
- "Done", "Archived", and "Cancelled" remove tasks from active views
|
||||
- "In Progress", "Planned", and "Waiting" appear in Today page Planned section
|
||||
- Status determines which section of the Today page shows the task
|
||||
|
||||
9. **Completion tracking is automatic:**
|
||||
- Changing status to "Done" sets `completed_at` timestamp to current time
|
||||
- Changing status from "Done" to anything else clears `completed_at`
|
||||
- Completed tasks show in "Completed" section of Today page
|
||||
|
||||
### Priority Levels
|
||||
|
||||
10. **Three priority levels:**
|
||||
- **Low (0):** Default priority, no special urgency
|
||||
- **Medium (1):** Moderate importance
|
||||
- **High (2):** Urgent or critical task
|
||||
|
||||
11. **Priority affects sorting:**
|
||||
- In most views, tasks are sorted High → Medium → Low
|
||||
- Priority is a visual indicator (colored flag icons)
|
||||
- Does not affect task behavior, only display order
|
||||
|
||||
### Due Dates
|
||||
|
||||
12. **Due dates are optional:**
|
||||
- Tasks without due dates are considered "someday/maybe"
|
||||
- Due dates are stored with date and time
|
||||
- Displayed in user's timezone
|
||||
|
||||
13. **Due date behavior:**
|
||||
- Tasks become "overdue" if due date passes and status is not "Done"
|
||||
- Overdue tasks appear in "Overdue" section on Today page
|
||||
- Due today tasks appear in "Suggested" section (if not in Planned status)
|
||||
- No automatic status changes when due date passes
|
||||
|
||||
### Defer Until
|
||||
|
||||
14. **Defer Until hides tasks until a specific time:**
|
||||
- Set a date/time when you want the task to become visible
|
||||
- Task is completely hidden from all views until defer time passes
|
||||
- Useful for "start this task on Monday" or "remind me in 2 hours"
|
||||
|
||||
15. **Defer Until behavior:**
|
||||
- System checks every 5 minutes for tasks whose defer time has passed
|
||||
- When defer time is reached, task becomes visible in appropriate sections
|
||||
- Optional notification sent when task becomes active (configurable)
|
||||
- Defer time can be edited or cleared at any time
|
||||
|
||||
16. **Defer Until is different from due date:**
|
||||
- Defer = "don't show me this until..."
|
||||
- Due date = "this needs to be finished by..."
|
||||
- A task can have both defer and due date
|
||||
- If both exist: task hidden until defer time, then due date determines urgency
|
||||
|
||||
---
|
||||
|
||||
## **Subtasks**
|
||||
|
||||
### Subtask Hierarchy
|
||||
|
||||
17. **Tasks can have subtasks (one level deep)**
|
||||
- Subtasks are full tasks with all properties (status, priority, due date, etc.)
|
||||
- Maximum one level: tasks can have subtasks, but subtasks cannot have their own subtasks
|
||||
- Parent-child relationship is tracked via `parent_task_id`
|
||||
|
||||
18. **Subtasks are displayed under their parent:**
|
||||
- Parent task shows a summary (e.g., "2 of 5 completed")
|
||||
- Subtasks can be collapsed/expanded in the UI
|
||||
- Subtasks are ordered by `order` field, then creation date
|
||||
|
||||
19. **Subtasks have their own lifecycle:**
|
||||
- Each subtask has independent status, priority, due date
|
||||
- Completing all subtasks doesn't auto-complete the parent
|
||||
- Completing the parent doesn't auto-complete subtasks
|
||||
- Deleting the parent deletes all subtasks (cascade)
|
||||
|
||||
20. **Subtask visibility rules:**
|
||||
- Subtasks don't appear in main task lists (only under parent)
|
||||
- Subtasks don't show in Today page sections independently
|
||||
- Searching for subtasks shows them with parent context
|
||||
- Filtering applies to parent tasks, not individual subtasks
|
||||
|
||||
### Subtask Ordering
|
||||
|
||||
21. **Subtasks can be manually reordered:**
|
||||
- Drag-and-drop in the UI updates the `order` field
|
||||
- Order is sequential integers (1, 2, 3, etc.)
|
||||
- New subtasks are added at the end (highest order + 1)
|
||||
|
||||
---
|
||||
|
||||
## **Attachments**
|
||||
|
||||
### File Uploads
|
||||
|
||||
22. **Tasks can have file attachments:**
|
||||
- Multiple files can be attached to a single task
|
||||
- File size limit: 10MB per file
|
||||
- Stored in `/uploads/tasks/` directory
|
||||
|
||||
23. **Allowed file types:**
|
||||
- Images: jpg, jpeg, png, gif, webp, svg
|
||||
- Documents: pdf, doc, docx, xls, xlsx, ppt, pptx
|
||||
- Text: txt, md, csv
|
||||
- Archives: zip, tar, gz
|
||||
- Other common formats
|
||||
|
||||
24. **Attachment metadata:**
|
||||
- Original filename is preserved in database
|
||||
- File is renamed on disk for uniqueness (task-[timestamp]-[random].[ext])
|
||||
- Each attachment gets a unique UID
|
||||
- Attachments track: filename, file size, MIME type, upload date
|
||||
|
||||
25. **Attachment management:**
|
||||
- Uploaded by task owner or users with write access
|
||||
- Can be downloaded by anyone with read access to the task
|
||||
- Deleting attachment removes file from disk
|
||||
- Deleting task removes all attachments and their files
|
||||
|
||||
---
|
||||
|
||||
## **Project Assignment**
|
||||
|
||||
### Linking to Projects
|
||||
|
||||
26. **Tasks can belong to a project:**
|
||||
- Optional `project_id` field links task to project
|
||||
- Tasks without a project are "standalone"
|
||||
- Project assignment determines which project view shows the task
|
||||
|
||||
27. **Project assignment effects:**
|
||||
- Task inherits project's sharing permissions
|
||||
- If user has access to project, they have same access to project's tasks
|
||||
- Deleting a project can orphan or delete tasks (depends on user choice)
|
||||
- Task completion contributes to project's progress metrics
|
||||
|
||||
28. **Changing project assignment:**
|
||||
- Can move task from one project to another
|
||||
- Can remove task from project (makes it standalone)
|
||||
- Subtasks inherit parent task's project
|
||||
- Changing parent's project doesn't automatically update subtasks
|
||||
|
||||
---
|
||||
|
||||
## **Tags**
|
||||
|
||||
### Tagging System
|
||||
|
||||
29. **Tasks can have multiple tags:**
|
||||
- Tags are flexible labels for categorization
|
||||
- Same tag can be used across tasks, notes, and projects
|
||||
- Tags are created automatically when first used
|
||||
- Tags are case-insensitive and normalized
|
||||
|
||||
30. **Tag behavior:**
|
||||
- Adding/removing tags doesn't affect task status or visibility
|
||||
- Tags enable filtering: "show all tasks with #urgent"
|
||||
- Tags appear as clickable chips in the UI
|
||||
- Tag autocomplete suggests existing tags while typing
|
||||
|
||||
31. **Tag inheritance:**
|
||||
- Subtasks have their own independent tags
|
||||
- Tags are not inherited from parent task or project
|
||||
- Deleting a tag removes it from all tasks (but doesn't delete tasks)
|
||||
|
||||
---
|
||||
|
||||
## **Task Completion**
|
||||
|
||||
### Marking Tasks as Done
|
||||
|
||||
32. **Completing a task:**
|
||||
- Change status to "Done" (manually or via checkbox)
|
||||
- `completed_at` timestamp is set to current time
|
||||
- Task moves to "Completed" section on Today page
|
||||
- Task disappears from active task lists
|
||||
|
||||
33. **Completion behavior for subtasks:**
|
||||
- Parent can be completed even if subtasks are not done
|
||||
- Subtasks can be completed independently
|
||||
- Completing the parent doesn't complete subtasks
|
||||
- Progress indicator shows "X of Y completed" for subtasks
|
||||
|
||||
34. **Un-completing a task:**
|
||||
- Changing status from "Done" to any other status
|
||||
- Clears the `completed_at` timestamp
|
||||
- Task reappears in active views
|
||||
- Task history preserves the completion event
|
||||
|
||||
### Completed Task Visibility
|
||||
|
||||
35. **Where completed tasks appear:**
|
||||
- "Completed" section on Today page (if completed today)
|
||||
- Project details page with "Show completed" filter
|
||||
- Search results (if specifically queried)
|
||||
- Task history and timeline views
|
||||
|
||||
36. **Completed tasks are excluded from:**
|
||||
- Main task lists by default
|
||||
- Today page "Planned" and "Suggested" sections
|
||||
- Overdue calculations
|
||||
- Upcoming view (future due dates)
|
||||
|
||||
---
|
||||
|
||||
## **Task Events & History**
|
||||
|
||||
### Activity Tracking
|
||||
|
||||
37. **Every task change is logged:**
|
||||
- Task creation event
|
||||
- Status changes
|
||||
- Field updates (name, due date, priority, etc.)
|
||||
- Assignment to project
|
||||
- Tag additions/removals
|
||||
- Attachment uploads/deletions
|
||||
|
||||
38. **Event data includes:**
|
||||
- Event type (created, status_changed, field_updated, etc.)
|
||||
- User who made the change
|
||||
- Timestamp of the change
|
||||
- Old value and new value (for field changes)
|
||||
- Additional metadata (source: web, API, Telegram, etc.)
|
||||
|
||||
39. **Task timeline:**
|
||||
- Events are displayed in chronological order
|
||||
- Shows full audit trail of task's lifecycle
|
||||
- Useful for understanding when and why changes occurred
|
||||
- Cannot be edited or deleted (immutable history)
|
||||
|
||||
---
|
||||
|
||||
## **Habit Mode**
|
||||
|
||||
### Habit Tracking
|
||||
|
||||
40. **Tasks can be habit trackers:**
|
||||
- `habit_mode` flag enables habit-specific features
|
||||
- Different from recurring tasks (habits focus on streak tracking)
|
||||
- Example: "Exercise 3 times per week"
|
||||
|
||||
41. **Habit properties:**
|
||||
- **Target count:** How many times per period (e.g., 3 times)
|
||||
- **Frequency period:** daily, weekly, or monthly
|
||||
- **Streak mode:**
|
||||
- Calendar: Count consecutive days
|
||||
- Scheduled: Count consecutive completions on scheduled days
|
||||
- **Flexibility mode:**
|
||||
- Strict: Must complete on exact schedule
|
||||
- Flexible: Can complete within the period
|
||||
|
||||
42. **Habit tracking:**
|
||||
- `habit_current_streak`: Current consecutive completions
|
||||
- `habit_best_streak`: Longest streak ever achieved
|
||||
- `habit_total_completions`: Total times completed
|
||||
- `habit_last_completion_at`: When last completed
|
||||
|
||||
43. **Habit completion:**
|
||||
- Completing a habit increments counters
|
||||
- Streak breaks if missed according to mode rules
|
||||
- Habit widgets show progress toward target count
|
||||
- Visual indicators for streak status (on track, at risk, broken)
|
||||
|
||||
---
|
||||
|
||||
## **Task Deletion**
|
||||
|
||||
### Deleting Tasks
|
||||
|
||||
44. **Deleting a task:**
|
||||
- Removes the task from the database
|
||||
- Cascade deletes all subtasks
|
||||
- Removes all attachments (files deleted from disk)
|
||||
- Removes task events/history
|
||||
- Removes tag associations (tags themselves remain)
|
||||
|
||||
45. **Soft delete is not implemented:**
|
||||
- Deletion is permanent (no trash/recycle bin)
|
||||
- No undo operation
|
||||
- Completed tasks can be archived instead of deleted
|
||||
|
||||
46. **Deleting a parent task:**
|
||||
- All subtasks are deleted (cannot be orphaned)
|
||||
- Warning shown if parent has subtasks
|
||||
- User must confirm deletion
|
||||
|
||||
47. **Permission to delete:**
|
||||
- Only task owner can delete their tasks
|
||||
- Users with write access via project sharing can delete
|
||||
- Admins can delete any task
|
||||
|
||||
---
|
||||
|
||||
## **Task Sharing & Permissions**
|
||||
|
||||
### Access Control
|
||||
|
||||
48. **Tasks inherit permissions from projects:**
|
||||
- If a task belongs to a project, anyone with project access has same access to task
|
||||
- Access levels: none, read-only (ro), read-write (rw), admin
|
||||
- Owner always has full access
|
||||
|
||||
49. **Standalone tasks:**
|
||||
- Tasks without a project are only visible to owner
|
||||
- Cannot be shared directly (must assign to a project to share)
|
||||
- Admins can view all tasks regardless of ownership
|
||||
|
||||
50. **Permission effects:**
|
||||
- **Read-only:** Can view task, cannot edit or delete
|
||||
- **Read-write:** Can edit task fields, add subtasks, upload attachments
|
||||
- **Admin/Owner:** Can delete task, change project assignment, share
|
||||
|
||||
---
|
||||
|
||||
## **Task Ordering & Sorting**
|
||||
|
||||
### Default Sort Order
|
||||
|
||||
51. **Tasks are typically sorted by:**
|
||||
1. Priority (High → Medium → Low)
|
||||
2. Due date (earliest first, nulls last)
|
||||
3. Created date (newest first for same priority/due date)
|
||||
|
||||
52. **Custom sorting options:**
|
||||
- Name (alphabetical)
|
||||
- Status
|
||||
- Created date
|
||||
- Updated date
|
||||
- Manual order (drag-and-drop, for subtasks)
|
||||
|
||||
53. **Grouping options:**
|
||||
- By project
|
||||
- By status
|
||||
- By priority
|
||||
- By due date (today, tomorrow, this week, later)
|
||||
- By tags
|
||||
|
||||
---
|
||||
|
||||
## **Task Notifications**
|
||||
|
||||
### Notification Types
|
||||
|
||||
54. **Tasks trigger notifications for:**
|
||||
- Task due soon (based on due date)
|
||||
- Task overdue
|
||||
- Defer Until time reached
|
||||
- Task assigned to you (shared via project)
|
||||
|
||||
55. **Notification channels:**
|
||||
- In-app notifications (navbar indicator)
|
||||
- Email (configurable per notification type)
|
||||
- Telegram (configurable per notification type)
|
||||
- Push notifications (configurable per notification type)
|
||||
|
||||
56. **Notification preferences:**
|
||||
- User can enable/disable per notification type
|
||||
- User can choose which channels for each type
|
||||
- Notifications can be dismissed or marked as read
|
||||
- Duplicate notifications are prevented (deduplication logic)
|
||||
|
||||
---
|
||||
|
||||
## **Special Behaviors**
|
||||
|
||||
### Task Visibility Rules
|
||||
|
||||
57. **A task is hidden from views if:**
|
||||
- Defer Until time has not yet passed
|
||||
- Status is "Done", "Archived", or "Cancelled" (unless showing completed)
|
||||
- User doesn't have permission to view it
|
||||
- It's a subtask (only shown under parent)
|
||||
- It's a recurring parent template (only instances shown)
|
||||
|
||||
58. **Overdue detection:**
|
||||
- Task is overdue if: `due_date < now` AND `status != Done/Archived/Cancelled`
|
||||
- Overdue tasks appear in "Overdue" section on Today page
|
||||
- Overdue count shows in navbar and project metrics
|
||||
- No automatic status change occurs
|
||||
|
||||
### Task Intelligence
|
||||
|
||||
59. **Task intelligence features (optional, can be disabled):**
|
||||
- Auto-suggest next actions based on task context
|
||||
- Smart suggestions for tasks to work on (Today page "Suggested" section)
|
||||
- Productivity insights and patterns
|
||||
- Next task recommendation based on priority, due date, and context
|
||||
|
||||
60. **Suggestion algorithm considers:**
|
||||
- Due dates (tasks due soon ranked higher)
|
||||
- Priority level
|
||||
- Project deadlines
|
||||
- Task age (older tasks surfaced)
|
||||
- Completion patterns (time of day you usually work on similar tasks)
|
||||
|
||||
---
|
||||
|
||||
## **Key Concepts**
|
||||
|
||||
### Task Instance
|
||||
|
||||
A single task record in the database with a unique ID and UID. Contains all task properties (name, status, priority, dates, etc.).
|
||||
|
||||
### Parent-Child Relationship
|
||||
|
||||
Hierarchical link between a parent task and its subtasks. One level deep only. Tracked via `parent_task_id` field.
|
||||
|
||||
### Completion Timestamp
|
||||
|
||||
The exact date and time when a task's status changed to "Done". Stored in `completed_at` field. Used for filtering "completed today" tasks.
|
||||
|
||||
### Task Events
|
||||
|
||||
Immutable audit log of all changes to a task. Each event records who changed what, when, and the before/after values.
|
||||
|
||||
### Defer Until
|
||||
|
||||
A feature that hides a task from all views until a specified date/time. Different from due dates - it's about when to START thinking about the task, not when to FINISH it.
|
||||
|
||||
### Task Ownership
|
||||
|
||||
The user who created the task owns it by default. Ownership can be transferred via project sharing, but the original `user_id` doesn't change.
|
||||
|
||||
### Habit Tracking
|
||||
|
||||
A mode that transforms a task into a habit tracker with streak counting, target counts, and flexible scheduling. Useful for building consistent behaviors.
|
||||
|
||||
---
|
||||
|
||||
## **Related Documentation**
|
||||
|
||||
- [Recurring Tasks Behavior](01-recurring-tasks-behavior.md) - How recurring tasks work
|
||||
- [Today Page Sections](02-today-page-sections.md) - Task filtering and display on Today page
|
||||
- [Upcoming View](03-upcoming-view.md) - 7-day task preview
|
||||
- [Projects](06-projects.md) - Project assignment and task organization
|
||||
- [Tags System](09-tags-system.md) - Tagging and categorization
|
||||
- [User Management](08-user-management.md) - Permissions and sharing
|
||||
|
||||
**Technical Implementation Files:**
|
||||
- Task model: `/backend/models/task.js`
|
||||
- Task service: `/backend/modules/tasks/`
|
||||
- Task completion: `/backend/modules/tasks/operations/completion.js`
|
||||
- Subtasks: `/backend/modules/tasks/operations/subtasks.js`
|
||||
- Attachments: `/backend/modules/tasks/attachments.js`
|
||||
- Task events: `/backend/modules/tasks/taskEventService.js`
|
||||
- Deferred tasks: `/backend/modules/tasks/deferredTaskService.js`
|
||||
|
||||
---
|
||||
|
||||
**Document Version:** 1.0.0
|
||||
**Last Updated:** 2026-03-15
|
||||
**Audience:** Developers, AI assistants, and end users
|
||||
146
docs/01-recurring-tasks-behavior.md
Normal file
146
docs/01-recurring-tasks-behavior.md
Normal file
|
|
@ -0,0 +1,146 @@
|
|||
# Recurring Tasks - Behavior Rules
|
||||
|
||||
This document explains how recurring tasks work in tududi from a user behavior perspective. For technical implementation details, see the backend code in `/backend/modules/tasks/recurringTaskService.js`.
|
||||
|
||||
---
|
||||
|
||||
## **Basic Rules**
|
||||
|
||||
1. **A recurring task is a single task that automatically resets itself when completed**
|
||||
- You mark it done, and it immediately reappears with a new due date
|
||||
|
||||
2. **The task doesn't create copies - it's the same task reusing itself**
|
||||
- Same task ID, same title, same details
|
||||
- Only the due date changes
|
||||
|
||||
3. **Future occurrences are shown in your task list even though they don't exist yet**
|
||||
- These are "virtual" - they're previews of what's coming
|
||||
- They become real when the previous occurrence is completed
|
||||
|
||||
---
|
||||
|
||||
## **Completion Behavior**
|
||||
|
||||
4. **When you complete a recurring task:**
|
||||
- It records that you completed this occurrence
|
||||
- It immediately changes to "Not Started" again
|
||||
- It gets a new due date based on the pattern
|
||||
|
||||
5. **Two ways to calculate the next due date:**
|
||||
- **Due-date based** (default): Next occurrence calculated from original due date
|
||||
- Example: Task due Monday, you complete it Wednesday → Next is still next Monday
|
||||
- **Completion-based**: Next occurrence calculated from when you actually completed it
|
||||
- Example: Task due Monday, you complete it Wednesday → Next is 7 days from Wednesday
|
||||
|
||||
---
|
||||
|
||||
## **Pattern Rules**
|
||||
|
||||
6. **Daily recurring:**
|
||||
- Every N days from the due date (or completion date)
|
||||
|
||||
7. **Weekly recurring:**
|
||||
- Every N weeks on specific day(s)
|
||||
- Can repeat on multiple days (e.g., every Mon+Wed+Fri)
|
||||
|
||||
8. **Monthly recurring:**
|
||||
- **Fixed day**: Every N months on day 15
|
||||
- **Weekday pattern**: Every N months on "2nd Thursday"
|
||||
- **Last day**: Every N months on the last day of the month
|
||||
|
||||
9. **Recurring tasks can have an end date:**
|
||||
- After that date, the task stops recurring
|
||||
- Without an end date, they repeat forever
|
||||
|
||||
---
|
||||
|
||||
## **Editing Rules**
|
||||
|
||||
10. **If you edit the recurrence pattern of a parent task:**
|
||||
- Future occurrences update to match the new pattern
|
||||
- Past completed occurrences stay in the history unchanged
|
||||
|
||||
11. **You can edit individual details (title, priority, notes) on the parent:**
|
||||
- Changes apply to future occurrences
|
||||
- Past completions keep their original details
|
||||
|
||||
12. **If you edit a future occurrence (a virtual instance):**
|
||||
- You're actually editing the parent template
|
||||
- The change affects all future occurrences
|
||||
|
||||
---
|
||||
|
||||
## **Display Rules**
|
||||
|
||||
13. **Recurring tasks show up multiple times in your lists:**
|
||||
- Today's occurrence (if due today)
|
||||
- Future occurrences (as previews)
|
||||
- Typically shows next 6-7 occurrences
|
||||
|
||||
14. **Each occurrence looks like a separate task in the UI:**
|
||||
- But it's really the same task showing at different dates
|
||||
|
||||
15. **You can see completion history:**
|
||||
- Records of when you completed past occurrences
|
||||
- Shows your pattern of completing the task
|
||||
|
||||
---
|
||||
|
||||
## **Special Cases**
|
||||
|
||||
16. **If a recurring task is overdue:**
|
||||
- It doesn't pile up multiple occurrences
|
||||
- Shows the current/next occurrence only
|
||||
- Past-due occurrences are skipped automatically
|
||||
|
||||
17. **If you delete a recurring task:**
|
||||
- The parent template is deleted
|
||||
- All future occurrences disappear
|
||||
- Past completion history is preserved
|
||||
|
||||
18. **Recurring tasks can belong to projects:**
|
||||
- Every occurrence inherits the project
|
||||
- Changing the project changes it for all future occurrences
|
||||
|
||||
---
|
||||
|
||||
## **Key Concepts**
|
||||
|
||||
### Virtual Instances
|
||||
Future occurrences that are generated on-the-fly for display purposes. They don't exist in the database as separate tasks - they're computed from the parent task's recurrence pattern.
|
||||
|
||||
### Parent Task
|
||||
The original recurring task that acts as a template. It has `recurring_parent_id = null` and stores the recurrence pattern configuration.
|
||||
|
||||
### In-Place Advancement
|
||||
When you complete a recurring task, the same task record is reused with an updated due date, rather than creating a new task instance.
|
||||
|
||||
### Completion History
|
||||
All past completions are tracked in a separate table (`recurring_completions`) to preserve your completion record even though the task itself advances.
|
||||
|
||||
---
|
||||
|
||||
## **Analogy**
|
||||
|
||||
Think of it like a gym membership that auto-renews - it's one subscription that keeps coming back on a schedule, not multiple separate subscriptions.
|
||||
|
||||
---
|
||||
|
||||
## **Related Documentation**
|
||||
|
||||
- [Architecture Overview](architecture.md) - Technical architecture
|
||||
- [Backend Patterns](backend-patterns.md) - Module structure
|
||||
- [Database & Migrations](database.md) - Data model details
|
||||
- [Common Tasks](common-tasks.md) - How to work with recurring tasks in code
|
||||
|
||||
**Technical Implementation Files:**
|
||||
- Recurrence calculation: `/backend/modules/tasks/recurringTaskService.js`
|
||||
- Completion handling: `/backend/modules/tasks/routes.js`
|
||||
- Task model: `/backend/models/task.js`
|
||||
- Completion tracking: `/backend/models/recurringCompletion.js`
|
||||
|
||||
---
|
||||
|
||||
**Document Version:** 1.0.0
|
||||
**Last Updated:** 2026-03-14
|
||||
**Audience:** Developers, AI assistants, and end users
|
||||
364
docs/02-today-page-sections.md
Normal file
364
docs/02-today-page-sections.md
Normal file
|
|
@ -0,0 +1,364 @@
|
|||
# Today Page Sections - Behavior Rules
|
||||
|
||||
This document explains how the four main sections of the Today page work in tududi. For technical implementation details, see `/backend/modules/tasks/queries/metrics-queries.js` and `/backend/modules/tasks/queries/metrics-computation.js`.
|
||||
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
The Today page is divided into **four main sections** that organize your tasks:
|
||||
|
||||
1. **Overdue** - Tasks past their due date that need attention
|
||||
2. **Planned** - Tasks you're actively working on today
|
||||
3. **Suggested** - Tasks recommended for you to work on next
|
||||
4. **Completed** - Tasks you finished today
|
||||
|
||||
Each section follows specific rules to show the right tasks without duplication.
|
||||
|
||||
---
|
||||
|
||||
## 1. PLANNED SECTION
|
||||
|
||||
### What Appears Here
|
||||
|
||||
Tasks with any of these three statuses:
|
||||
- **In Progress** - Tasks you're actively working on
|
||||
- **Planned** - Tasks you scheduled to work on
|
||||
- **Waiting** - Tasks blocked or waiting for something
|
||||
|
||||
### Key Rules
|
||||
|
||||
1. **Status is what matters, not the "today" checkbox**
|
||||
- A task marked "Planned" appears here even if you haven't checked "today"
|
||||
- A task with "Not Started" status won't appear here even with "today" checked
|
||||
|
||||
2. **Deferred tasks are hidden**
|
||||
- If you set "Defer Until" to a future time, the task won't appear until that time arrives
|
||||
- Once the defer time passes, the task automatically becomes visible
|
||||
|
||||
3. **Only parent tasks appear**
|
||||
- Subtasks don't show up (they're shown under their parent)
|
||||
- Recurring parent templates are hidden (only today's instance shows)
|
||||
|
||||
4. **Completed or cancelled tasks are excluded**
|
||||
- Once done, archived, or cancelled, tasks move out of this section
|
||||
|
||||
### Display Order
|
||||
|
||||
Tasks are sorted by:
|
||||
1. Priority (High → Medium → Low)
|
||||
2. Due date (earliest first)
|
||||
3. Project (grouped together)
|
||||
|
||||
### Special Cases
|
||||
|
||||
- **Habits**: Appear under a separate "Habits planned for today" header
|
||||
- **Recurring tasks**: Only today's occurrence shows, not the template
|
||||
|
||||
---
|
||||
|
||||
## 2. OVERDUE SECTION
|
||||
|
||||
### What Appears Here
|
||||
|
||||
Tasks with a due date **before today** that are **NOT already in the Planned section**.
|
||||
|
||||
### Key Rules
|
||||
|
||||
1. **Time-based filtering**
|
||||
- Due date must be before today (respects your timezone)
|
||||
- "Today" is calculated using your local timezone settings
|
||||
|
||||
2. **Excludes tasks already in Planned**
|
||||
- If a task is overdue but you marked it "In Progress" or "Planned", it stays in Planned
|
||||
- Avoids showing the same task in multiple sections
|
||||
|
||||
3. **No completed or cancelled tasks**
|
||||
- Done, archived, and cancelled tasks don't appear
|
||||
|
||||
4. **Project deadlines affect task visibility**
|
||||
- If a task has no due date but its project is overdue, the task appears here
|
||||
- Helps you see work related to overdue projects
|
||||
|
||||
5. **Deferred tasks are hidden**
|
||||
- If you deferred a task to tomorrow, it won't show in Overdue today
|
||||
- Even if originally overdue, deferred tasks hide until defer time passes
|
||||
|
||||
### Display Order
|
||||
|
||||
Same as Planned section:
|
||||
1. Priority (High → Medium → Low)
|
||||
2. Due date (earliest first)
|
||||
3. Project (grouped together)
|
||||
|
||||
### User Control
|
||||
|
||||
- Can be hidden entirely via Today Settings
|
||||
- Collapse/expand state is remembered in your browser
|
||||
|
||||
---
|
||||
|
||||
## 3. SUGGESTED SECTION
|
||||
|
||||
### What Appears Here
|
||||
|
||||
Up to **10 tasks** automatically selected as good candidates for you to work on next.
|
||||
|
||||
### When Suggestions Appear
|
||||
|
||||
Suggestions are only shown if:
|
||||
- You have 3 or more open tasks, OR
|
||||
- You have tasks in progress, OR
|
||||
- You have tasks due today
|
||||
|
||||
If none of these are true, no suggestions are shown.
|
||||
|
||||
### Selection Rules
|
||||
|
||||
1. **Excludes tasks already visible elsewhere**
|
||||
- Tasks in Planned, Overdue, Due Today, or In Progress don't appear
|
||||
- Avoids duplication across sections
|
||||
|
||||
2. **Excludes "someday" tasks by default**
|
||||
- Tasks tagged as "someday" are only included if there aren't enough other suggestions
|
||||
- Prioritizes actionable tasks over future ideas
|
||||
|
||||
3. **Excludes deferred tasks**
|
||||
- Tasks with "Defer Until" set to the future don't appear
|
||||
- Only shows tasks available to work on now
|
||||
|
||||
4. **No subtasks or recurring templates**
|
||||
- Only shows parent tasks you can directly work on
|
||||
|
||||
### How Tasks Are Selected
|
||||
|
||||
The system picks suggestions in this order:
|
||||
|
||||
1. **High-priority tasks without a project** (unscheduled important work)
|
||||
2. **High-priority tasks with a project** (project-related important work)
|
||||
3. **Medium-priority tasks** (both with and without projects)
|
||||
4. **Tasks with upcoming due dates** (time-sensitive work)
|
||||
5. **"Someday" tasks** (only if fewer than 6 suggestions found above)
|
||||
|
||||
Within each priority level, tasks with earlier due dates are preferred.
|
||||
|
||||
### Limits
|
||||
|
||||
- Maximum 10 suggestions shown
|
||||
- If you have fewer than 10 qualifying tasks, all are shown
|
||||
|
||||
### User Control
|
||||
|
||||
- Can be hidden entirely via Today Settings (hidden by default)
|
||||
- Collapse/expand state is remembered in your browser
|
||||
|
||||
---
|
||||
|
||||
## 4. COMPLETED SECTION
|
||||
|
||||
### What Appears Here
|
||||
|
||||
Tasks you **completed today**, including:
|
||||
- Regular tasks marked as "Done" today
|
||||
- Recurring tasks you completed today (can appear multiple times if you completed multiple occurrences)
|
||||
|
||||
### Key Rules
|
||||
|
||||
1. **Time-based filtering**
|
||||
- Only tasks completed within today's 24-hour window (respects your timezone)
|
||||
- "Today" runs from 00:00:00 to 23:59:59 in your local timezone
|
||||
|
||||
2. **Includes recurring task history**
|
||||
- Recurring tasks track each completion separately
|
||||
- If you complete a recurring task multiple times today, all instances are shown
|
||||
- Completions are preserved in history even though the task advances to the next occurrence
|
||||
|
||||
3. **Only parent tasks appear**
|
||||
- Subtasks don't show (they're counted with their parent)
|
||||
- Recurring parent templates are excluded (only completed instances shown)
|
||||
|
||||
4. **Excludes skipped occurrences**
|
||||
- If you skipped a recurring task occurrence, it doesn't count as completed
|
||||
|
||||
### Display Order
|
||||
|
||||
Tasks are sorted by:
|
||||
- **Completion time** (most recently completed first)
|
||||
|
||||
### Additional Data
|
||||
|
||||
The Completed section also provides:
|
||||
- **Weekly completion trend**: 7-day chart showing your completion pattern
|
||||
- **Completion count**: Total tasks completed today
|
||||
- **Progress percentage**: Completed vs. planned tasks
|
||||
|
||||
### User Control
|
||||
|
||||
- Can be hidden entirely via Today Settings (visible by default)
|
||||
- Collapse/expand state is remembered in your browser
|
||||
|
||||
---
|
||||
|
||||
## Section Priority Rules
|
||||
|
||||
### No Duplication
|
||||
|
||||
A task appears in **exactly one section** based on this priority:
|
||||
|
||||
1. **Completed** (highest priority) - If done today, shows only here
|
||||
2. **Planned** - If status is in_progress/planned/waiting, shows only here
|
||||
3. **Overdue** - If due before today and not planned, shows here
|
||||
4. **Suggested** - If not in any above section and meets criteria, shows here
|
||||
|
||||
### Example Scenarios
|
||||
|
||||
**Scenario 1: Overdue task you're working on**
|
||||
- Due date: 2 days ago
|
||||
- Status: In Progress
|
||||
- **Appears in:** Planned (not Overdue, because status takes priority)
|
||||
|
||||
**Scenario 2: High-priority task with no due date**
|
||||
- Priority: High
|
||||
- Due date: None
|
||||
- Status: Not Started
|
||||
- **Appears in:** Suggested (not Overdue, because no due date)
|
||||
|
||||
**Scenario 3: Task deferred until tomorrow**
|
||||
- Due date: Yesterday (overdue)
|
||||
- Defer until: Tomorrow
|
||||
- Status: Not Started
|
||||
- **Appears in:** Nowhere (hidden until defer time passes)
|
||||
|
||||
**Scenario 4: Recurring task completed**
|
||||
- Recurrence: Daily
|
||||
- Status: Done (just completed)
|
||||
- **Appears in:** Completed (and task automatically resets for tomorrow)
|
||||
|
||||
---
|
||||
|
||||
## Time & Timezone Handling
|
||||
|
||||
### How "Today" is Calculated
|
||||
|
||||
- Your local timezone is detected from your account settings
|
||||
- "Today" means from midnight to midnight in **your timezone**, not UTC
|
||||
- All date comparisons respect your timezone
|
||||
|
||||
### Example
|
||||
|
||||
If you're in New York (EST, UTC-5):
|
||||
- Today starts: 2026-03-14 00:00:00 EST = 2026-03-14 05:00:00 UTC
|
||||
- Today ends: 2026-03-14 23:59:59 EST = 2026-03-15 04:59:59 UTC
|
||||
|
||||
A task completed at 11:30 PM EST shows in "Completed Today" even though it's technically the next day in UTC.
|
||||
|
||||
---
|
||||
|
||||
## User Settings
|
||||
|
||||
### Today Page Settings
|
||||
|
||||
You can customize what appears on your Today page:
|
||||
|
||||
| Setting | Default | Effect |
|
||||
|---------|---------|--------|
|
||||
| Show Overdue/Due Today | On | Shows/hides Overdue section |
|
||||
| Show Suggestions | Off | Shows/hides Suggested section |
|
||||
| Show Completed | On | Shows/hides Completed section |
|
||||
| Show Metrics | Off | Shows/hides task metrics widget |
|
||||
| Show Daily Quote | On | Shows/hides daily motivational quote |
|
||||
| Show Progress Bar | On | Shows/hides completion progress bar |
|
||||
|
||||
### Where to Change Settings
|
||||
|
||||
- Click the settings icon (⚙️) on the Today page
|
||||
- Settings auto-save when you toggle them
|
||||
- Settings are stored per user account
|
||||
|
||||
### Collapsible Sections
|
||||
|
||||
Each section can be collapsed or expanded:
|
||||
- Click the section header to collapse/expand
|
||||
- Your preference is saved in your browser
|
||||
- Persists across sessions
|
||||
|
||||
---
|
||||
|
||||
## Special Features
|
||||
|
||||
### Defer Until
|
||||
|
||||
**What it does:**
|
||||
- Hides a task from all sections until a specific date/time
|
||||
- Useful for tasks you can't work on yet
|
||||
|
||||
**How it works:**
|
||||
1. Set "Defer Until" to a future date/time
|
||||
2. Task disappears from Planned, Overdue, and Suggested sections
|
||||
3. System sends you a notification 5 minutes before defer time
|
||||
4. Task automatically reappears when defer time is reached
|
||||
|
||||
**Example:**
|
||||
- Task: "Call plumber"
|
||||
- Defer until: Monday 9 AM
|
||||
- Result: Task hidden until Monday at 9 AM, then appears in appropriate section
|
||||
|
||||
### Recurring Tasks
|
||||
|
||||
**How they appear:**
|
||||
- Only today's occurrence shows in sections (not the parent template)
|
||||
- Parent templates are automatically hidden to avoid duplication
|
||||
- When you complete today's occurrence, it moves to Completed and resets for next occurrence
|
||||
|
||||
**Completion tracking:**
|
||||
- Each completion is recorded separately
|
||||
- You can complete a recurring task multiple times in one day
|
||||
- All completions show in the Completed section
|
||||
|
||||
### Habits
|
||||
|
||||
**Special handling:**
|
||||
- Habits appear in the Planned section under "Habits planned for today"
|
||||
- Separate from regular tasks
|
||||
- Have their own "Habits completed today" subsection in Completed
|
||||
|
||||
---
|
||||
|
||||
## Performance & Limits
|
||||
|
||||
### Pagination
|
||||
|
||||
Each section shows a limited number of tasks by default:
|
||||
- Initial display: 20 tasks per section
|
||||
- "Load More" button: Loads next 20 tasks
|
||||
- "Load All" button: Shows all tasks at once
|
||||
- Counter shows: "Showing X of Y tasks"
|
||||
|
||||
### Auto-Refresh
|
||||
|
||||
The Today page automatically refreshes:
|
||||
- When you mark a task complete
|
||||
- When you change task status
|
||||
- When you defer a task
|
||||
- Every few minutes to catch changes made elsewhere
|
||||
|
||||
---
|
||||
|
||||
## Related Documentation
|
||||
|
||||
- [Recurring Tasks Behavior](01-recurring-tasks-behavior.md) - How recurring tasks work
|
||||
- [Architecture Overview](architecture.md) - Technical architecture
|
||||
- [Development Workflow](development-workflow.md) - Working with the codebase
|
||||
- [Database & Migrations](database.md) - Data model details
|
||||
|
||||
**Technical Implementation Files:**
|
||||
- Backend queries: `/backend/modules/tasks/queries/metrics-queries.js`
|
||||
- Suggested tasks logic: `/backend/modules/tasks/queries/metrics-computation.js`
|
||||
- Frontend component: `/frontend/components/Task/TasksToday.tsx`
|
||||
- Task model: `/backend/models/task.js`
|
||||
|
||||
---
|
||||
|
||||
**Document Version:** 1.0.0
|
||||
**Last Updated:** 2026-03-14
|
||||
**Audience:** Developers, AI assistants, and end users
|
||||
481
docs/03-upcoming-view.md
Normal file
481
docs/03-upcoming-view.md
Normal file
|
|
@ -0,0 +1,481 @@
|
|||
# Upcoming View - Behavior Rules
|
||||
|
||||
This document explains how the Upcoming view works in tududi. For technical implementation details, see `/backend/modules/tasks/queries/query-builders.js` and `/backend/modules/tasks/recurringTaskService.js`.
|
||||
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
The **Upcoming view** is a forward-looking calendar that shows tasks scheduled for the next 7 days, organized by date. It differs from the Today view by showing all upcoming work rather than just today's active tasks.
|
||||
|
||||
**Key characteristics:**
|
||||
- Shows tasks due in the next 7 days
|
||||
- Grouped by day of the week
|
||||
- Displays recurring task occurrences
|
||||
- Includes deferred tasks when they become available
|
||||
- Shows upcoming projects
|
||||
|
||||
**URL:** `/upcoming`
|
||||
|
||||
---
|
||||
|
||||
## Basic Rules
|
||||
|
||||
1. **Time range is 7 days ahead**
|
||||
- Starts today at midnight (your timezone)
|
||||
- Ends 7 days from now at 11:59 PM (your timezone)
|
||||
|
||||
2. **Grouped by day, not by status or project**
|
||||
- Tasks organized into columns/sections by due date
|
||||
- Labels: "Today", "Tomorrow", "Monday, March 17", etc.
|
||||
- Tasks without due dates appear in "No Due Date" section
|
||||
|
||||
3. **All tasks are loaded at once**
|
||||
- No "Load More" or pagination
|
||||
- Shows complete 7-day view
|
||||
|
||||
4. **Recurring tasks show as multiple occurrences**
|
||||
- Each occurrence appears on its due date
|
||||
- Same task can appear on multiple days
|
||||
- These are "virtual" previews generated on-the-fly
|
||||
|
||||
5. **Cannot create new tasks from Upcoming view**
|
||||
- "New Task" button is hidden
|
||||
- Create tasks from Inbox, Today, or specific projects instead
|
||||
|
||||
---
|
||||
|
||||
## What Tasks Appear in Upcoming
|
||||
|
||||
### Tasks Included
|
||||
|
||||
A task appears in Upcoming if it matches **any** of these conditions:
|
||||
|
||||
1. **Regular tasks with due dates**
|
||||
- Due date falls within the next 7 days
|
||||
- Not marked as completed (unless viewing completed tasks)
|
||||
|
||||
2. **Tasks becoming available from deferral**
|
||||
- "Defer Until" date falls within the next 7 days
|
||||
- Shows when the task becomes actionable, not when it's due
|
||||
|
||||
3. **Recurring task occurrences**
|
||||
- All occurrences of recurring tasks in the next 7 days
|
||||
- Generated automatically from the recurring pattern
|
||||
- Each occurrence appears on its scheduled date
|
||||
|
||||
4. **Tasks without due dates**
|
||||
- Appear in "No Due Date" section
|
||||
- Only if they match other filters (status, etc.)
|
||||
|
||||
### Tasks Excluded
|
||||
|
||||
**Tasks that don't appear:**
|
||||
|
||||
1. **Overdue tasks** (due before today)
|
||||
- Past-due non-recurring tasks don't appear
|
||||
- Exception: Recurring tasks continue showing future occurrences
|
||||
|
||||
2. **Future tasks** (due more than 7 days ahead)
|
||||
- Only shows the next 7-day window
|
||||
- Tasks due next month won't appear
|
||||
|
||||
3. **Completed tasks** (by default)
|
||||
- Unless you select "Completed" status filter
|
||||
- Can toggle between Active/Completed/All
|
||||
|
||||
4. **Subtasks**
|
||||
- Only parent tasks appear
|
||||
- Subtasks are shown within their parent task details
|
||||
|
||||
---
|
||||
|
||||
## How Recurring Tasks Work in Upcoming
|
||||
|
||||
### Virtual Occurrences
|
||||
|
||||
Recurring tasks appear as **virtual occurrences** - previews of future instances:
|
||||
|
||||
1. **Each occurrence gets its own date**
|
||||
- A daily task appears 7 times (once per day)
|
||||
- A weekly task appears 1-2 times (depending on the week)
|
||||
- A monthly task appears 0-1 times (if it falls within 7 days)
|
||||
|
||||
2. **Occurrences are generated automatically**
|
||||
- Based on the recurring pattern (daily, weekly, monthly, etc.)
|
||||
- Respects the recurrence interval (every 2 days, every 3 weeks, etc.)
|
||||
- Stops at the recurrence end date (if set)
|
||||
|
||||
3. **Each occurrence can be acted on independently**
|
||||
- Click to view details
|
||||
- Mark as complete
|
||||
- Edit the parent task (affects all future occurrences)
|
||||
|
||||
### Recurrence Patterns
|
||||
|
||||
**Patterns shown in Upcoming:**
|
||||
|
||||
- **Daily**: Every N days
|
||||
- Example: Every 2 days shows on Day 1, Day 3, Day 5, Day 7
|
||||
|
||||
- **Weekly**: Every N weeks on specific day(s)
|
||||
- Example: Every Monday shows next Monday (and following Monday if within 7 days)
|
||||
- Example: Mon+Wed+Fri shows 3 occurrences per week
|
||||
|
||||
- **Monthly**: Every N months on specific day
|
||||
- Example: 15th of every month (only appears if within 7 days)
|
||||
|
||||
- **Monthly Weekday**: Every N months on specific weekday
|
||||
- Example: 2nd Thursday of every month
|
||||
|
||||
- **Monthly Last Day**: Last day of every month
|
||||
|
||||
### Overdue Recurring Tasks
|
||||
|
||||
If a recurring task is overdue:
|
||||
- The system automatically advances to the next future occurrence
|
||||
- Past-due occurrences are skipped
|
||||
- Only upcoming occurrences appear in the view
|
||||
|
||||
**Example:**
|
||||
- Recurring task: "Weekly Report" every Monday
|
||||
- Today: Wednesday, March 12
|
||||
- Last completed: Monday, March 3 (overdue)
|
||||
- **Shows in Upcoming**: Monday, March 17 (next occurrence)
|
||||
- **Doesn't show**: Monday, March 10 (past, skipped)
|
||||
|
||||
---
|
||||
|
||||
## Grouping and Organization
|
||||
|
||||
### Day-Based Grouping
|
||||
|
||||
Tasks are organized into date columns/sections:
|
||||
|
||||
**Group Labels:**
|
||||
1. **"Today"** - Tasks due today
|
||||
2. **"Tomorrow"** - Tasks due tomorrow
|
||||
3. **"[Weekday], [Date]"** - Other dates (e.g., "Monday, March 17")
|
||||
4. **"No Due Date"** - Tasks without due dates
|
||||
|
||||
**Languages:**
|
||||
- Group labels are translated into 24 supported languages
|
||||
- Date formats respect your locale settings
|
||||
|
||||
### Within Each Day
|
||||
|
||||
Tasks are sorted by:
|
||||
- Selected sort order (due date, priority, name, etc.)
|
||||
- Default: Creation date (newest first)
|
||||
|
||||
**Sort options available:**
|
||||
- Due date (earliest or latest first)
|
||||
- Priority (high to low, or low to high)
|
||||
- Name (A-Z or Z-A)
|
||||
- Status (by completion state)
|
||||
- Created date (newest or oldest first)
|
||||
- Completed date (for completed tasks)
|
||||
|
||||
### No Project Grouping
|
||||
|
||||
Unlike the main Tasks view:
|
||||
- Cannot group by project
|
||||
- All tasks mixed together by date
|
||||
- Projects shown separately below the task list
|
||||
|
||||
---
|
||||
|
||||
## Status Filtering
|
||||
|
||||
### Filter Options
|
||||
|
||||
You can filter what appears in Upcoming:
|
||||
|
||||
1. **Active** (default)
|
||||
- Shows only non-completed tasks
|
||||
- Includes: Not Started, In Progress, Planned, Waiting
|
||||
|
||||
2. **Completed**
|
||||
- Shows only completed tasks from the past 7 days
|
||||
- Useful for reviewing what you finished
|
||||
|
||||
3. **All** (no filter)
|
||||
- Shows both active and completed tasks
|
||||
- Mixed view of everything
|
||||
|
||||
### How to Filter
|
||||
|
||||
- Click the status filter dropdown in the toolbar
|
||||
- Selection is saved to URL (can bookmark)
|
||||
- Changes immediately update the view
|
||||
|
||||
---
|
||||
|
||||
## Defer Until Behavior
|
||||
|
||||
### How Deferred Tasks Appear
|
||||
|
||||
Tasks with "Defer Until" dates show special behavior:
|
||||
|
||||
1. **Task deferred to future date within 7 days**
|
||||
- Appears in Upcoming on the defer date
|
||||
- Shows in the day column for when it becomes available
|
||||
- May have a different due date (later than defer date)
|
||||
|
||||
2. **Task deferred beyond 7 days**
|
||||
- Doesn't appear in Upcoming
|
||||
- Hidden until defer date gets closer
|
||||
|
||||
3. **Task deferred to today or past**
|
||||
- Appears immediately in Upcoming
|
||||
- Acts like a normal task
|
||||
|
||||
### Example Scenarios
|
||||
|
||||
**Scenario 1: Deferred task appears**
|
||||
- Task: "Review contract"
|
||||
- Due date: March 20
|
||||
- Defer until: March 15
|
||||
- Today: March 12
|
||||
- **Shows in Upcoming:** Yes, under "March 15" (when it becomes available)
|
||||
|
||||
**Scenario 2: Deferred task hidden**
|
||||
- Task: "Q2 planning"
|
||||
- Due date: April 1
|
||||
- Defer until: March 25
|
||||
- Today: March 12
|
||||
- **Shows in Upcoming:** No (defer date is beyond 7 days)
|
||||
|
||||
---
|
||||
|
||||
## Upcoming Projects
|
||||
|
||||
### What Projects Appear
|
||||
|
||||
Projects show separately at the bottom of Upcoming if:
|
||||
- Project has a due date set
|
||||
- Due date falls within the next 7 days
|
||||
- Project is not archived or completed
|
||||
|
||||
### Project Display
|
||||
|
||||
- Shown below all tasks
|
||||
- Grouped by the same date system
|
||||
- Click to view project details
|
||||
- Shows project progress and task count
|
||||
|
||||
---
|
||||
|
||||
## Special Features
|
||||
|
||||
### Responsive Layout
|
||||
|
||||
**Desktop (wide screens):**
|
||||
- Horizontal columns for each day
|
||||
- Board-style layout
|
||||
- Tasks arranged left to right across the week
|
||||
|
||||
**Mobile (narrow screens):**
|
||||
- Vertical stacked sections
|
||||
- One day at a time
|
||||
- Scroll down to see future days
|
||||
|
||||
### No Search
|
||||
|
||||
- Search bar is hidden in Upcoming view
|
||||
- Use main Tasks view or Inbox for searching
|
||||
- Upcoming is for browsing by date only
|
||||
|
||||
### No Pagination
|
||||
|
||||
- All tasks for 7 days load immediately
|
||||
- No "Load More" button
|
||||
- Fast loading optimized for weekly view
|
||||
|
||||
### Auto-Refresh
|
||||
|
||||
The Upcoming view automatically refreshes:
|
||||
- When you complete a task
|
||||
- When you change task status
|
||||
- When you edit a task's due date
|
||||
- Every few minutes to catch external changes
|
||||
|
||||
---
|
||||
|
||||
## Differences from Today View
|
||||
|
||||
| Feature | Today View | Upcoming View |
|
||||
|---------|------------|---------------|
|
||||
| **Time range** | Only today | Next 7 days |
|
||||
| **Grouping** | By section (Planned, Overdue, etc.) | By date |
|
||||
| **Status focus** | Active tasks only | All tasks (filterable) |
|
||||
| **Recurring display** | Parent + today's instance | All virtual occurrences |
|
||||
| **New task creation** | Available | Not available |
|
||||
| **Search** | Available | Not available |
|
||||
| **Pagination** | Yes (Load More) | No (all loaded) |
|
||||
| **Layout** | Vertical list | Board layout |
|
||||
|
||||
---
|
||||
|
||||
## User Settings
|
||||
|
||||
### Configurable Options
|
||||
|
||||
| Setting | Default | How to Change |
|
||||
|---------|---------|---------------|
|
||||
| **Status filter** | Active | Dropdown in toolbar |
|
||||
| **Sort order** | Created date (newest) | Sort dropdown in toolbar |
|
||||
| **Sort direction** | Descending | Toggle in sort dropdown |
|
||||
|
||||
### Saved Preferences
|
||||
|
||||
- **Sort order**: Saved to browser localStorage
|
||||
- **Status filter**: Saved to URL (can bookmark)
|
||||
- **Mobile/Desktop**: Auto-detected from screen size
|
||||
|
||||
---
|
||||
|
||||
## Common Use Cases
|
||||
|
||||
### 1. Planning Your Week
|
||||
|
||||
**What to do:**
|
||||
- Open Upcoming view on Monday morning
|
||||
- Scan across all 7 days
|
||||
- See what's coming and when
|
||||
- Reschedule overloaded days
|
||||
|
||||
### 2. Checking Recurring Tasks
|
||||
|
||||
**What to do:**
|
||||
- Look for recurring tasks appearing multiple times
|
||||
- Verify the pattern is correct
|
||||
- Edit parent task if pattern needs adjustment
|
||||
|
||||
### 3. Finding Available Tasks
|
||||
|
||||
**What to do:**
|
||||
- Check "No Due Date" section
|
||||
- See tasks you deferred that become available
|
||||
- Plan when to work on undated tasks
|
||||
|
||||
### 4. Reviewing Completed Work
|
||||
|
||||
**What to do:**
|
||||
- Switch to "Completed" status filter
|
||||
- See what you finished this week
|
||||
- Track recurring task completion history
|
||||
|
||||
---
|
||||
|
||||
## Example Scenarios
|
||||
|
||||
### Scenario 1: Daily Recurring Task
|
||||
|
||||
**Setup:**
|
||||
- Task: "Morning workout"
|
||||
- Pattern: Every day at 7 AM
|
||||
- Today: Monday, March 10
|
||||
|
||||
**Shows in Upcoming:**
|
||||
- Monday, March 10: Morning workout
|
||||
- Tuesday, March 11: Morning workout
|
||||
- Wednesday, March 12: Morning workout
|
||||
- Thursday, March 13: Morning workout
|
||||
- Friday, March 14: Morning workout
|
||||
- Saturday, March 15: Morning workout
|
||||
- Sunday, March 16: Morning workout
|
||||
|
||||
**Total appearances:** 7 times (once per day)
|
||||
|
||||
### Scenario 2: Weekly Multi-Day Recurring Task
|
||||
|
||||
**Setup:**
|
||||
- Task: "Team standup"
|
||||
- Pattern: Every Mon, Wed, Fri
|
||||
- Today: Monday, March 10
|
||||
|
||||
**Shows in Upcoming:**
|
||||
- Monday, March 10: Team standup
|
||||
- Wednesday, March 12: Team standup
|
||||
- Friday, March 14: Team standup
|
||||
- Monday, March 17: Team standup
|
||||
|
||||
**Total appearances:** 4 times
|
||||
|
||||
### Scenario 3: Deferred Task Becoming Available
|
||||
|
||||
**Setup:**
|
||||
- Task: "Review proposal"
|
||||
- Due date: March 25
|
||||
- Defer until: March 14
|
||||
- Today: March 10
|
||||
|
||||
**Shows in Upcoming:**
|
||||
- Thursday, March 14: Review proposal
|
||||
- (Not shown on March 10-13 because still deferred)
|
||||
- (Won't show on March 15-16 unless due date moves)
|
||||
|
||||
### Scenario 4: One-Time Task with Due Date
|
||||
|
||||
**Setup:**
|
||||
- Task: "Submit report"
|
||||
- Due date: March 15
|
||||
- Today: March 10
|
||||
|
||||
**Shows in Upcoming:**
|
||||
- Friday, March 15: Submit report
|
||||
|
||||
**Total appearances:** 1 time (not recurring)
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### "My task doesn't appear in Upcoming"
|
||||
|
||||
**Check these:**
|
||||
1. Is the due date more than 7 days away? (Only shows next 7 days)
|
||||
2. Is the due date in the past? (Overdue tasks don't appear)
|
||||
3. Is it marked as completed? (Switch to "Completed" filter to see)
|
||||
4. Is it a subtask? (Only parent tasks appear)
|
||||
5. Is it deferred beyond 7 days? (Won't appear until defer date is closer)
|
||||
|
||||
### "My recurring task shows too many times"
|
||||
|
||||
**This is normal if:**
|
||||
- Pattern is daily (shows 7 times)
|
||||
- Pattern is multi-day weekly (shows multiple times per week)
|
||||
|
||||
**To reduce occurrences:**
|
||||
- Increase the recurrence interval (every 2 days instead of daily)
|
||||
- Change to single-day weekly pattern
|
||||
- Set a recurrence end date
|
||||
|
||||
### "My recurring task doesn't show at all"
|
||||
|
||||
**Check these:**
|
||||
1. Is the recurrence end date in the past? (Task stopped recurring)
|
||||
2. Is the task completed and not advancing? (Check completion-based setting)
|
||||
3. Is the next occurrence beyond 7 days? (Monthly tasks may not appear)
|
||||
|
||||
---
|
||||
|
||||
## Related Documentation
|
||||
|
||||
- [Recurring Tasks Behavior](01-recurring-tasks-behavior.md) - How recurring tasks work
|
||||
- [Today Page Sections](02-today-page-sections.md) - How Today page differs from Upcoming
|
||||
- [Architecture Overview](architecture.md) - Technical architecture
|
||||
- [Development Workflow](development-workflow.md) - Working with the codebase
|
||||
|
||||
**Technical Implementation Files:**
|
||||
- Backend query builder: `/backend/modules/tasks/queries/query-builders.js`
|
||||
- Recurring task service: `/backend/modules/tasks/recurringTaskService.js`
|
||||
- Frontend component: `/frontend/components/Tasks.tsx`
|
||||
- Grouping logic: `/backend/modules/tasks/operations/grouping.js`
|
||||
|
||||
---
|
||||
|
||||
**Document Version:** 1.0.0
|
||||
**Last Updated:** 2026-03-14
|
||||
**Audience:** Developers, AI assistants, and end users
|
||||
755
docs/04-inbox-page.md
Normal file
755
docs/04-inbox-page.md
Normal file
|
|
@ -0,0 +1,755 @@
|
|||
# Inbox Page - Behavior Rules
|
||||
|
||||
This document explains how the Inbox page works in tududi from a user behavior perspective. For technical implementation details, see the backend code in `/backend/modules/inbox/` and frontend components in `/frontend/components/Inbox/`.
|
||||
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
The **Inbox** is tududi's quick capture system - a temporary holding area where you can rapidly dump ideas, tasks, notes, and links without worrying about organization. It's designed to get things out of your head fast, then process them later into structured tasks, projects, or notes.
|
||||
|
||||
**Key characteristics:**
|
||||
- Zero friction capture - just type and submit
|
||||
- Smart parsing of hashtags, projects, and URLs
|
||||
- AI-powered suggestions for what to create
|
||||
- Convert items to tasks, notes, or projects
|
||||
- Integration with Telegram for remote capture
|
||||
|
||||
**URL:** `/inbox`
|
||||
|
||||
---
|
||||
|
||||
## Core Principles
|
||||
|
||||
1. **Capture first, organize later**
|
||||
- Add items instantly without choosing status, priority, or due dates
|
||||
- Process and categorize items when you have time to think
|
||||
|
||||
2. **One place for everything**
|
||||
- Tasks, notes, bookmarks, random thoughts - all start here
|
||||
- Sort them out later into appropriate places
|
||||
|
||||
3. **Smart automation helps**
|
||||
- System detects patterns in your input
|
||||
- Suggests task vs. note vs. project based on content
|
||||
- Auto-extracts tags and project references
|
||||
|
||||
---
|
||||
|
||||
## How to Add Items to Inbox
|
||||
|
||||
### Quick Capture Input
|
||||
|
||||
Located at the top of the Inbox page:
|
||||
|
||||
1. **Type your content** in the text field
|
||||
- Plain text: `Remember to buy milk`
|
||||
- With tags: `Call dentist #health #urgent`
|
||||
- With project: `Review proposal +ClientProject #review`
|
||||
- URLs: `https://example.com/article`
|
||||
- Mixed: `Read this article https://example.com +Reading #bookmark`
|
||||
|
||||
2. **Press Enter or Tab** to submit (configurable in settings)
|
||||
- Item is saved to inbox immediately
|
||||
- Input clears, ready for next item
|
||||
- Can add multiple items rapidly
|
||||
|
||||
3. **Input auto-focuses** when you navigate to `/inbox`
|
||||
- Keyboard shortcut: `g` then `i` (Go to Inbox)
|
||||
- Sidebar navigation clicks auto-focus input
|
||||
|
||||
### Telegram Integration
|
||||
|
||||
Send messages to your tududi bot:
|
||||
- Each message creates an inbox item
|
||||
- Source is marked as `telegram`
|
||||
- Appears in your inbox within ~15 seconds
|
||||
- You get a toast notification when new items arrive
|
||||
|
||||
---
|
||||
|
||||
## Smart Parsing Rules
|
||||
|
||||
The system automatically analyzes your input and extracts metadata:
|
||||
|
||||
### 1. Hashtags (Tags)
|
||||
|
||||
**Syntax:** `#tagname`
|
||||
|
||||
**Rules:**
|
||||
- Must start with `#` followed by alphanumeric characters, hyphens, or underscores
|
||||
- Valid: `#work`, `#high-priority`, `#q1_2026`
|
||||
- Invalid: `#with spaces`, `#emoji🎉`, `#punctuation!`
|
||||
- Can appear anywhere in the text
|
||||
- Multiple tags supported: `Task here #work #urgent #review`
|
||||
|
||||
**Grouping:**
|
||||
- Consecutive tags/projects are treated as a group
|
||||
- Example: `Buy groceries #food #shopping #weekly` → extracts all 3 tags
|
||||
- Group must be contiguous (separated by spaces from other words)
|
||||
|
||||
**Tag creation:**
|
||||
- If tag doesn't exist, it's created when you convert to task/note/project
|
||||
- Tags are case-insensitive: `#Work` = `#work` = `#WORK`
|
||||
|
||||
### 2. Project References
|
||||
|
||||
**Syntax:** `+projectname` or `+"project with spaces"`
|
||||
|
||||
**Rules:**
|
||||
- Must start with `+` followed by project name
|
||||
- No spaces: `+HomeRenovation`
|
||||
- With spaces: `+"Home Renovation"` (use quotes)
|
||||
- Valid: `+work`, `+Q1Planning`, `+"Client Project"`
|
||||
- Can appear anywhere in the text
|
||||
|
||||
**Behavior:**
|
||||
- If project exists, it's linked automatically
|
||||
- If project doesn't exist, you'll be prompted to create it
|
||||
- Only the first project reference is used when converting
|
||||
- Multiple references are parsed but only first is applied
|
||||
|
||||
### 3. URL Detection
|
||||
|
||||
**What counts as a URL:**
|
||||
- Must start with `http://` or `https://`
|
||||
- Example: `https://example.com`, `http://blog.com/post`
|
||||
|
||||
**Special handling:**
|
||||
- URLs automatically get `#bookmark` tag added
|
||||
- When converted to note, system tries to fetch page title
|
||||
- Title extraction has 3-second timeout
|
||||
- If title fetch fails, URL itself is used as title
|
||||
|
||||
**Bookmark auto-tagging:**
|
||||
- If you add `#bookmark` manually, it's preserved
|
||||
- If you don't, system adds it automatically for URLs
|
||||
- Applies to both explicit tags and when converting to note
|
||||
|
||||
### 4. Cleaned Content
|
||||
|
||||
After parsing, the system creates "cleaned content":
|
||||
- Original: `Review contract +ClientWork #urgent #review`
|
||||
- Cleaned: `Review contract`
|
||||
- Tags and projects are stripped for display/conversion
|
||||
- Cleaned version is used as task name, note title, or project name
|
||||
|
||||
---
|
||||
|
||||
## Intelligent Suggestions
|
||||
|
||||
The system analyzes your content and suggests what type of item to create:
|
||||
|
||||
### Suggestion Logic
|
||||
|
||||
**1. Suggests TASK when:**
|
||||
- Content starts with an action verb (detected using NLP)
|
||||
- Has a project reference
|
||||
- Examples:
|
||||
- ✅ `Call John +Work` → Suggests Task (verb "Call")
|
||||
- ✅ `Review proposal +ClientProject` → Suggests Task (verb "Review")
|
||||
- ✅ `Fix the bug +Development` → Suggests Task (verb "Fix")
|
||||
|
||||
**2. Suggests NOTE when:**
|
||||
- Content is a URL (bookmark)
|
||||
- Has explicit `#bookmark` tag
|
||||
- Has a project reference but no action verb
|
||||
- Examples:
|
||||
- ✅ `https://example.com/article +Reading` → Suggests Note (URL)
|
||||
- ✅ `Meeting notes from today +Project1 #bookmark` → Suggests Note (bookmark tag)
|
||||
- ✅ `Important info +Work` → Suggests Note (no verb)
|
||||
|
||||
**3. No suggestion when:**
|
||||
- No project reference
|
||||
- Just plain text or tags without context
|
||||
- Examples:
|
||||
- ⚪ `Random thought #idea` → No suggestion
|
||||
- ⚪ `Buy milk` → No suggestion
|
||||
- ⚪ `https://example.com` → Shows URL icon, but no suggestion (no project)
|
||||
|
||||
### Visual Indicators
|
||||
|
||||
**Suggestion badges:**
|
||||
- Blue "Task" badge appears if suggested as task
|
||||
- Purple "Note" badge appears if suggested as note
|
||||
- Reason shown in tooltip: "verb detected", "bookmark tag", "URL detected"
|
||||
|
||||
**Icons:**
|
||||
- 🌐 Globe icon: Bookmark/URL content
|
||||
- 📄 Document icon: Plain text
|
||||
- 📝 Purple document: Long-form text (has title + content)
|
||||
|
||||
---
|
||||
|
||||
## Converting Inbox Items
|
||||
|
||||
Each inbox item can be converted to three types:
|
||||
|
||||
### 1. Convert to Task
|
||||
|
||||
**What happens:**
|
||||
1. Opens the task detail page in edit mode
|
||||
2. Pre-fills task name with cleaned content
|
||||
3. Applies tags from hashtags
|
||||
4. Links to project if project reference found
|
||||
5. Status defaults to "Not Started"
|
||||
6. After saving, inbox item is marked as "processed"
|
||||
|
||||
**Use cases:**
|
||||
- Action items: `Call dentist #health`
|
||||
- Work tasks: `Review PR #dev +ProjectX`
|
||||
- Todos with deadlines: `Submit report #work #urgent`
|
||||
|
||||
**Keyboard shortcut in quick capture:**
|
||||
- `Ctrl+T` (Windows/Linux) or `Cmd+T` (Mac) to convert to task directly
|
||||
|
||||
### 2. Convert to Note
|
||||
|
||||
**What happens:**
|
||||
1. Opens note modal
|
||||
2. Pre-fills note content with original text
|
||||
3. If URL: fetches page title and uses as note title (3s timeout)
|
||||
4. Applies tags from hashtags + `#bookmark` if URL
|
||||
5. Links to project if project reference found
|
||||
6. After saving, inbox item is marked as "processed"
|
||||
|
||||
**Use cases:**
|
||||
- Bookmarks: `https://article.com +Reading`
|
||||
- Ideas: `New feature idea for app +Development`
|
||||
- Reference material: `Meeting notes from today +ClientProject`
|
||||
|
||||
**Keyboard shortcut in quick capture:**
|
||||
- `Ctrl+N` (Windows/Linux) or `Cmd+N` (Mac) to convert to note directly
|
||||
|
||||
### 3. Convert to Project
|
||||
|
||||
**What happens:**
|
||||
1. Opens project modal
|
||||
2. Pre-fills project name with cleaned content
|
||||
3. Applies tags from hashtags
|
||||
4. Status defaults to "Planned"
|
||||
5. After saving, inbox item is marked as "processed"
|
||||
|
||||
**Use cases:**
|
||||
- New initiatives: `Website redesign #q1 #priority`
|
||||
- Areas of work: `Home renovation #personal`
|
||||
- Client work: `New client onboarding #clients`
|
||||
|
||||
**Keyboard shortcut in quick capture:**
|
||||
- `Ctrl+P` (Windows/Linux) or `Cmd+P` (Mac) to convert to project directly
|
||||
|
||||
### Direct Creation vs. Modal Editing
|
||||
|
||||
**For tasks:** System immediately navigates to task detail page for editing
|
||||
- No modal - you edit inline on the task page
|
||||
- Gives you full access to all task fields
|
||||
- Back button returns to inbox
|
||||
|
||||
**For notes and projects:** Modal opens for editing
|
||||
- Edit within overlay modal
|
||||
- Save or cancel without leaving inbox page
|
||||
- More lightweight for quick additions
|
||||
|
||||
---
|
||||
|
||||
## Inbox Item Lifecycle
|
||||
|
||||
### States
|
||||
|
||||
1. **Added** (status: `added`)
|
||||
- Freshly created item
|
||||
- Appears in inbox list
|
||||
- Awaiting processing
|
||||
|
||||
2. **Processed** (status: `processed`)
|
||||
- Converted to task, note, or project
|
||||
- Removed from inbox view
|
||||
- Stored in database for history (not deleted)
|
||||
|
||||
### Processing
|
||||
|
||||
**What "processing" means:**
|
||||
- Marks item as `processed`
|
||||
- Removes from visible inbox
|
||||
- Preserves in database for audit trail
|
||||
- Cannot be un-processed (one-way action)
|
||||
|
||||
**When items are auto-processed:**
|
||||
- When you convert to task and save
|
||||
- When you convert to note and save
|
||||
- When you convert to project and save
|
||||
|
||||
**Manual processing:**
|
||||
- Not directly exposed in UI
|
||||
- Happens automatically on conversion
|
||||
- No "Mark as processed" button needed
|
||||
|
||||
---
|
||||
|
||||
## Editing Inbox Items
|
||||
|
||||
### Inline Editing
|
||||
|
||||
**How to edit:**
|
||||
1. Click anywhere on the inbox item text
|
||||
2. Item expands into editable composer
|
||||
3. Modify text, add/remove tags or projects
|
||||
4. Press Enter or click outside to save
|
||||
5. Press Esc to cancel changes
|
||||
|
||||
**What you can edit:**
|
||||
- Full content/text
|
||||
- Add or remove hashtags
|
||||
- Add or remove project references
|
||||
- URLs are preserved as text
|
||||
|
||||
**Editing rules:**
|
||||
- If content unchanged, no update is sent
|
||||
- Editing re-runs smart parsing
|
||||
- Suggestions update based on new content
|
||||
- Keyboard shortcuts (Ctrl+T, Ctrl+N, Ctrl+P) work while editing
|
||||
|
||||
### Composer Footer Actions
|
||||
|
||||
While editing, you see action buttons:
|
||||
- **Task** button: Convert to task with current content
|
||||
- **Note** button: Convert to note with current content
|
||||
- **Project** button: Convert to project with current content
|
||||
- **Delete** button: Remove inbox item permanently
|
||||
|
||||
---
|
||||
|
||||
## Deleting Inbox Items
|
||||
|
||||
### Confirmation
|
||||
|
||||
**Steps:**
|
||||
1. Click Delete button in composer footer
|
||||
2. Confirmation dialog appears
|
||||
3. Confirm or cancel
|
||||
|
||||
**What gets deleted:**
|
||||
- Inbox item is permanently removed from database
|
||||
- NOT marked as processed - it's deleted
|
||||
- No undo option
|
||||
|
||||
### When to delete vs. process
|
||||
|
||||
**Delete when:**
|
||||
- Item is no longer relevant
|
||||
- Duplicate entry
|
||||
- Captured by mistake
|
||||
- Spam/noise
|
||||
|
||||
**Process when:**
|
||||
- Item becomes task/note/project
|
||||
- Actually converting to structured content
|
||||
- Want to preserve in audit trail
|
||||
|
||||
---
|
||||
|
||||
## Pagination and Loading
|
||||
|
||||
### Initial Load
|
||||
|
||||
- Shows **20 items** by default
|
||||
- Most recent items first (newest at top)
|
||||
- Loading screen while fetching
|
||||
|
||||
### Load More
|
||||
|
||||
**When "Load More" button appears:**
|
||||
- You have more than 20 items
|
||||
- Shows: "Showing X of Y items"
|
||||
- Button at bottom of list
|
||||
|
||||
**How it works:**
|
||||
1. Click "Load More" button
|
||||
2. Fetches next 20 items
|
||||
3. Appends to current list
|
||||
4. Updates count display
|
||||
5. Button disappears when all items loaded
|
||||
|
||||
**URL state:**
|
||||
- After loading more: URL updates to `?loaded=40` (or current count)
|
||||
- Bookmarking preserves loaded count
|
||||
- Refreshing page maintains loaded count from URL
|
||||
|
||||
**No infinite scroll:**
|
||||
- Manual "Load More" button only
|
||||
- Intentional - prevents accidental loading
|
||||
- Better performance for large inboxes
|
||||
|
||||
---
|
||||
|
||||
## Auto-Refresh and Polling
|
||||
|
||||
### Background Polling
|
||||
|
||||
**How it works:**
|
||||
- Every **15 seconds**, checks for new items
|
||||
- Fetches updated inbox from server
|
||||
- Preserves current scroll position
|
||||
- Maintains loaded count (doesn't reset to 20)
|
||||
|
||||
**What triggers updates:**
|
||||
- Telegram messages arrive
|
||||
- Other devices add items
|
||||
- Web app open in multiple tabs
|
||||
|
||||
**Notifications:**
|
||||
- Toast notification when new Telegram item detected
|
||||
- Shows first item's content
|
||||
- If multiple items: shows count of additional items
|
||||
- Example: "New item from Telegram: Buy milk" + "2 more new items added"
|
||||
|
||||
### Manual Refresh
|
||||
|
||||
**Keyboard shortcut:**
|
||||
- `r` key: Force refresh inbox
|
||||
- Fetches latest items immediately
|
||||
- Useful if polling missed an update
|
||||
|
||||
**When refresh happens automatically:**
|
||||
- After you create an item via quick capture
|
||||
- After you delete an item
|
||||
- After you convert an item (it's removed)
|
||||
- Navigation to/from inbox page
|
||||
|
||||
---
|
||||
|
||||
## Keyboard Shortcuts
|
||||
|
||||
### Global (anywhere in app)
|
||||
|
||||
| Shortcut | Action |
|
||||
|----------|--------|
|
||||
| `g` then `i` | Go to Inbox page |
|
||||
|
||||
### On Inbox page
|
||||
|
||||
| Shortcut | Action |
|
||||
|----------|--------|
|
||||
| `r` | Refresh inbox items |
|
||||
| Focus in input | Type to add item |
|
||||
| `Enter` or `Tab` | Submit item (configurable in settings) |
|
||||
|
||||
### In quick capture composer
|
||||
|
||||
| Shortcut (Win/Linux) | Shortcut (Mac) | Action |
|
||||
|----------------------|----------------|--------|
|
||||
| `Ctrl+T` | `Cmd+T` | Convert to Task |
|
||||
| `Ctrl+N` | `Cmd+N` | Convert to Note |
|
||||
| `Ctrl+P` | `Cmd+P` | Convert to Project |
|
||||
| `Ctrl+Enter` | `Cmd+Enter` | Save to inbox instead of converting |
|
||||
| `Esc` | `Esc` | Cancel editing |
|
||||
|
||||
### While editing item
|
||||
|
||||
| Shortcut | Action |
|
||||
|----------|--------|
|
||||
| `Esc` | Cancel editing, revert changes |
|
||||
| Click outside | Save changes |
|
||||
| `Enter` | Save changes (if not multiline) |
|
||||
|
||||
---
|
||||
|
||||
## Special Features
|
||||
|
||||
### 1. Project Creation on the Fly
|
||||
|
||||
**When converting:**
|
||||
- If you reference a project that doesn't exist: `+NewProject`
|
||||
- System prompts to create the project
|
||||
- Project created with name "NewProject", status "Planned"
|
||||
- Task/note is then linked to newly created project
|
||||
|
||||
**Workflow:**
|
||||
1. Add inbox item: `Review docs +NewClientProject #urgent`
|
||||
2. Click "Task" to convert
|
||||
3. System detects `NewClientProject` doesn't exist
|
||||
4. Project created automatically
|
||||
5. Task is linked to new project
|
||||
|
||||
### 2. Tag Creation on the Fly
|
||||
|
||||
**When converting:**
|
||||
- If you use hashtag that doesn't exist: `#newtag`
|
||||
- Tag is created automatically during conversion
|
||||
- No confirmation needed
|
||||
- Tag appears in tag list immediately
|
||||
|
||||
**Case insensitivity:**
|
||||
- `#Work`, `#work`, `#WORK` all resolve to same tag
|
||||
- First occurrence determines the canonical case
|
||||
- Subsequent uses are normalized to existing tag
|
||||
|
||||
### 3. URL Title Extraction
|
||||
|
||||
**For bookmarks:**
|
||||
- When converting URL to note
|
||||
- System fetches the webpage
|
||||
- Extracts `<title>` tag from HTML
|
||||
- Uses as note title
|
||||
- 3-second timeout - if it fails, uses URL as title
|
||||
|
||||
**Example:**
|
||||
- Input: `https://example.com/article`
|
||||
- System fetches page, finds title: "10 Tips for Productivity"
|
||||
- Note created with title: "10 Tips for Productivity"
|
||||
- Content: `https://example.com/article`
|
||||
- Tags: `#bookmark` (auto-added)
|
||||
|
||||
### 4. Multi-Source Capture
|
||||
|
||||
**Sources tracked:**
|
||||
- `web`: Added via web interface (quick capture)
|
||||
- `telegram`: Added via Telegram bot
|
||||
- `api`: Added via REST API (rare)
|
||||
|
||||
**Why it matters:**
|
||||
- Can filter by source (not in UI, but in database)
|
||||
- Telegram items show notification on arrival
|
||||
- Useful for debugging integration issues
|
||||
|
||||
### 5. Long-Form Content
|
||||
|
||||
**Handling multi-line input:**
|
||||
- Quick capture supports multi-line (Shift+Enter for new line)
|
||||
- First line becomes `title`
|
||||
- Full text stored as `content`
|
||||
- Title shown in inbox list
|
||||
- Content accessible when editing
|
||||
|
||||
**Visual indicator:**
|
||||
- Purple document icon for items with title+content
|
||||
- Gray document icon for plain text items
|
||||
- Globe icon for URLs/bookmarks
|
||||
|
||||
---
|
||||
|
||||
## Display and Organization
|
||||
|
||||
### Sort Order
|
||||
|
||||
**Inbox items are always sorted by:**
|
||||
- Creation date descending (newest first)
|
||||
- No other sort options available
|
||||
- Newest items at top encourages processing fresh captures
|
||||
|
||||
### No Filtering
|
||||
|
||||
**Intentional limitation:**
|
||||
- No search within inbox
|
||||
- No tag filtering
|
||||
- No project filtering
|
||||
- Philosophy: Inbox is temporary - process items, don't organize them here
|
||||
|
||||
### No Grouping
|
||||
|
||||
**All items in flat list:**
|
||||
- No grouping by date
|
||||
- No grouping by source
|
||||
- No grouping by tags/projects
|
||||
- Keeps it simple and fast to scan
|
||||
|
||||
---
|
||||
|
||||
## Example Workflows
|
||||
|
||||
### Workflow 1: Quick Task Capture
|
||||
|
||||
**Scenario:** You remember a task while working on something else
|
||||
|
||||
1. Press `g` then `i` to open inbox
|
||||
2. Type: `Email report to manager +Work #urgent`
|
||||
3. Press Enter
|
||||
4. System suggests "Task" (verb detected)
|
||||
5. Click "Task" button or press Ctrl+T
|
||||
6. Task detail page opens with:
|
||||
- Name: "Email report to manager"
|
||||
- Project: Work
|
||||
- Tags: #urgent
|
||||
7. Set due date, priority, etc.
|
||||
8. Save task
|
||||
9. Inbox item auto-processed and removed
|
||||
|
||||
### Workflow 2: Bookmark Collection
|
||||
|
||||
**Scenario:** Found an interesting article to read later
|
||||
|
||||
1. Navigate to `/inbox`
|
||||
2. Paste URL: `https://medium.com/article +Reading`
|
||||
3. Press Enter
|
||||
4. System shows globe icon (URL detected)
|
||||
5. Click "Note" button or press Ctrl+N
|
||||
6. System fetches article title: "How to Learn Faster"
|
||||
7. Note modal opens:
|
||||
- Title: "How to Learn Faster"
|
||||
- Content: `https://medium.com/article`
|
||||
- Project: Reading
|
||||
- Tags: #bookmark (auto-added)
|
||||
8. Save note
|
||||
9. Inbox item removed
|
||||
|
||||
### Workflow 3: Telegram to Task
|
||||
|
||||
**Scenario:** You're away from computer, send task to Telegram bot
|
||||
|
||||
1. Send message to Telegram bot: `Buy birthday gift for mom #personal #shopping`
|
||||
2. Within 15 seconds, item appears in web inbox
|
||||
3. Toast notification: "New item from Telegram: Buy birthday gift for mom"
|
||||
4. Later, at computer, open `/inbox`
|
||||
5. See the item with tags parsed: #personal, #shopping
|
||||
6. Click to edit, add project: `+PersonalLife`
|
||||
7. Click "Task" to convert
|
||||
8. Set due date (her birthday)
|
||||
9. Save - task created, inbox cleared
|
||||
|
||||
### Workflow 4: Batch Processing
|
||||
|
||||
**Scenario:** Morning routine - clear out yesterday's inbox
|
||||
|
||||
1. Open `/inbox` - see 8 items
|
||||
2. First item: `Call plumber #home` → Click "Task", set due today, save
|
||||
3. Second item: `https://article.com +Reading` → Click "Note", save
|
||||
4. Third item: `Random idea for app` → Edit, add `+ProjectIdeas`, click "Note"
|
||||
5. Fourth item: `Buy milk` → Delete (already done)
|
||||
6. Continue through all items
|
||||
7. Inbox empty - ready for new day
|
||||
|
||||
### Workflow 5: Quick Project Ideation
|
||||
|
||||
**Scenario:** Brainstorming new project ideas
|
||||
|
||||
1. Press `g` then `i`
|
||||
2. Type rapid-fire ideas:
|
||||
- `Redesign homepage #q2 #design`
|
||||
- `Build mobile app #q2 #dev`
|
||||
- `Customer research #q1 #research`
|
||||
3. Later, convert each to projects:
|
||||
- Each becomes a project with tags
|
||||
- Start fleshing out project details
|
||||
- Add tasks to each project
|
||||
|
||||
---
|
||||
|
||||
## Common Patterns
|
||||
|
||||
### Pattern: URL → Note with Bookmark Tag
|
||||
|
||||
**Input:** `https://example.com +Reading`
|
||||
**Result:**
|
||||
- System detects URL
|
||||
- Auto-adds `#bookmark` tag
|
||||
- Suggests "Note"
|
||||
- Fetches page title
|
||||
- Creates note linked to Reading project
|
||||
|
||||
### Pattern: Verb + Project → Task
|
||||
|
||||
**Input:** `Review proposal +ClientWork #urgent`
|
||||
**Result:**
|
||||
- System detects verb "Review"
|
||||
- Suggests "Task"
|
||||
- Creates task:
|
||||
- Name: "Review proposal"
|
||||
- Project: ClientWork
|
||||
- Tags: #urgent
|
||||
|
||||
### Pattern: No Project → No Suggestion
|
||||
|
||||
**Input:** `Random thought #idea`
|
||||
**Result:**
|
||||
- No project reference
|
||||
- No suggestion shown
|
||||
- Can manually convert to task, note, or project
|
||||
- Tags are still parsed
|
||||
|
||||
### Pattern: Multi-Tag Grouping
|
||||
|
||||
**Input:** `Task here #work #urgent #review and more text`
|
||||
**Result:**
|
||||
- All consecutive tags extracted: work, urgent, review
|
||||
- Cleaned content: "Task here and more text"
|
||||
- Tags group is contiguous at end of thought
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### "My tags aren't being detected"
|
||||
|
||||
**Check:**
|
||||
1. Are tags alphanumeric + hyphens/underscores only?
|
||||
- ❌ `#tag with spaces`
|
||||
- ✅ `#tag-with-hyphens`
|
||||
2. Are tags separated by spaces from words?
|
||||
- ❌ `word#tag`
|
||||
- ✅ `word #tag`
|
||||
|
||||
### "My project reference isn't working"
|
||||
|
||||
**Check:**
|
||||
1. Did you use `+` prefix?
|
||||
- ❌ `Project Name`
|
||||
- ✅ `+ProjectName`
|
||||
2. Does project name have spaces? Use quotes:
|
||||
- ❌ `+Client Project`
|
||||
- ✅ `+"Client Project"`
|
||||
3. Does the project exist? System links only to existing projects
|
||||
|
||||
### "Inbox item didn't get processed after conversion"
|
||||
|
||||
**Possible causes:**
|
||||
- Conversion failed (check for error toast)
|
||||
- Network error during save
|
||||
- Item still showing because page didn't refresh
|
||||
- Try manual refresh with `r` key
|
||||
|
||||
### "Telegram items not appearing"
|
||||
|
||||
**Check:**
|
||||
1. Is Telegram bot properly configured? (Settings > Telegram)
|
||||
2. Wait up to 15 seconds for polling cycle
|
||||
3. Check inbox for toast notification
|
||||
4. Try manual refresh with `r` key
|
||||
5. Verify bot token is correct in settings
|
||||
|
||||
### "URL title extraction failed"
|
||||
|
||||
**Why it happens:**
|
||||
- Website blocks scraping/bots
|
||||
- Website requires JavaScript to load
|
||||
- Network timeout (3 seconds)
|
||||
- Invalid URL format
|
||||
|
||||
**What to do:**
|
||||
- System falls back to using URL as title
|
||||
- You can manually edit title in note modal
|
||||
- URL content is still saved correctly
|
||||
|
||||
---
|
||||
|
||||
## Related Documentation
|
||||
|
||||
- [Today Page Sections](02-today-page-sections.md) - How tasks flow from inbox to Today
|
||||
- [Architecture Overview](architecture.md) - Technical architecture
|
||||
- [Development Workflow](development-workflow.md) - Working with the codebase
|
||||
- [Common Tasks](common-tasks.md) - How to modify inbox functionality
|
||||
|
||||
**Technical Implementation Files:**
|
||||
- Inbox processing service: `/backend/modules/inbox/inboxProcessingService.js`
|
||||
- Inbox model: `/backend/models/inbox_item.js`
|
||||
- Inbox API routes: `/backend/modules/inbox/routes.js`
|
||||
- Inbox controller: `/backend/modules/inbox/controller.js`
|
||||
- Frontend components: `/frontend/components/Inbox/`
|
||||
- Quick capture input: `/frontend/components/Inbox/QuickCaptureInput.tsx`
|
||||
- Item detail: `/frontend/components/Inbox/InboxItemDetail.tsx`
|
||||
- Inbox service: `/frontend/utils/inboxService.ts`
|
||||
|
||||
---
|
||||
|
||||
**Document Version:** 1.0.0
|
||||
**Last Updated:** 2026-03-14
|
||||
**Audience:** Developers, AI assistants, and end users
|
||||
952
docs/05-notes-system.md
Normal file
952
docs/05-notes-system.md
Normal file
|
|
@ -0,0 +1,952 @@
|
|||
# Notes System - Behavior Rules
|
||||
|
||||
This document explains how the Notes system works in tududi from a user behavior perspective. For technical implementation details, see the backend code in `/backend/modules/notes/` and frontend components in `/frontend/components/Notes.tsx`.
|
||||
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
**Notes** are tududi's flexible capture and reference system - a place to store information, ideas, bookmarks, meeting notes, and any other content that doesn't fit the structured task workflow. Unlike tasks, notes don't have due dates, priorities, or completion states - they're purely informational.
|
||||
|
||||
**Key characteristics:**
|
||||
- Rich text support via Markdown
|
||||
- Optional project association
|
||||
- Tag-based organization
|
||||
- Color customization (10 predefined colors)
|
||||
- Focus mode for distraction-free writing
|
||||
- Auto-save every 1 second
|
||||
- Search across title and content
|
||||
|
||||
**URL:** `/notes` or `/notes/:uid`
|
||||
|
||||
---
|
||||
|
||||
## Core Principles
|
||||
|
||||
1. **Information, not action**
|
||||
- Notes store knowledge, not tasks
|
||||
- No due dates, priorities, or status tracking
|
||||
- Permanent reference material vs. temporary to-dos
|
||||
|
||||
2. **Flexible structure**
|
||||
- Can be standalone or linked to projects
|
||||
- Tag-based categorization
|
||||
- Full Markdown formatting support
|
||||
|
||||
3. **Seamless capture**
|
||||
- Auto-save prevents data loss
|
||||
- Quick creation from inbox items
|
||||
- Inline editing without modals
|
||||
|
||||
---
|
||||
|
||||
## Note Structure
|
||||
|
||||
### Fields
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
|-------|------|----------|-------------|
|
||||
| **Title** | String | No | Note heading (untitled if empty) |
|
||||
| **Content** | Text | No | Main note body (Markdown supported) |
|
||||
| **Project** | Reference | No | Associated project |
|
||||
| **Tags** | Array | No | Categorization tags |
|
||||
| **Color** | String | No | Background color (visual organization) |
|
||||
| **Created At** | Timestamp | Auto | Creation timestamp |
|
||||
| **Updated At** | Timestamp | Auto | Last modification timestamp |
|
||||
|
||||
### Unique Identifier
|
||||
|
||||
- Each note has a **UID** (unique identifier): `uid` field
|
||||
- Used in URLs: `/notes/abc123def456`
|
||||
- Immutable - persists through all edits
|
||||
|
||||
---
|
||||
|
||||
## Creating Notes
|
||||
|
||||
### Method 1: Direct Creation
|
||||
|
||||
**From Notes page:**
|
||||
1. Navigate to `/notes`
|
||||
2. Click **+ icon** in top right
|
||||
3. New note opens in edit mode
|
||||
4. Start typing - auto-saves after 1 second
|
||||
5. No explicit "Save" required
|
||||
|
||||
**Keyboard shortcut:**
|
||||
- `n` (while on Notes page) - Create new note
|
||||
|
||||
### Method 2: From Inbox
|
||||
|
||||
**Convert inbox item to note:**
|
||||
1. Capture item in Inbox: `Article link https://example.com +Reading #bookmark`
|
||||
2. Click "Note" button or press Ctrl+N (Cmd+N on Mac)
|
||||
3. System creates note with:
|
||||
- Title: Fetched from URL (or URL itself if fetch fails)
|
||||
- Content: Full inbox text
|
||||
- Project: Linked from `+Reading`
|
||||
- Tags: Extracted from `#bookmark`
|
||||
4. Inbox item marked as processed
|
||||
|
||||
**See:** [Inbox Page documentation](04-inbox-page.md) for details
|
||||
|
||||
### Method 3: From Project Page
|
||||
|
||||
**Via project view:**
|
||||
1. Open project detail page
|
||||
2. Click "Add Note" in notes section
|
||||
3. Note pre-linked to current project
|
||||
4. Start editing
|
||||
|
||||
---
|
||||
|
||||
## Editing Notes
|
||||
|
||||
### Inline Editing
|
||||
|
||||
**How it works:**
|
||||
1. Click on a note in the list to preview it
|
||||
2. Click anywhere on the preview (title or content)
|
||||
3. Note switches to edit mode
|
||||
4. Changes auto-save every 1 second
|
||||
5. Press Escape to save and exit edit mode
|
||||
|
||||
**Save behavior:**
|
||||
- **Auto-save:** Triggers 1 second after you stop typing
|
||||
- **Save status indicators:**
|
||||
- ✓ Saved (green) - Changes persisted
|
||||
- Saving... (blue) - Upload in progress
|
||||
- • Unsaved changes (amber) - Save failed or pending
|
||||
|
||||
**What triggers auto-save:**
|
||||
- Typing in title field
|
||||
- Typing in content field
|
||||
- Changing project
|
||||
- Adding/removing tags
|
||||
- Changing note color
|
||||
|
||||
### Title Editing
|
||||
|
||||
**Rules:**
|
||||
- Title is optional - can be blank
|
||||
- Blank titles show as "Untitled Note" in UI
|
||||
- Auto-save only triggers if title is non-empty
|
||||
- Click title in preview mode to enter edit mode
|
||||
|
||||
### Content Editing
|
||||
|
||||
**Markdown support:**
|
||||
- Full GitHub-flavored Markdown
|
||||
- Headings: `# H1`, `## H2`, `### H3`
|
||||
- Lists: `- item` or `1. item`
|
||||
- Links: `[text](url)`
|
||||
- Bold: `**text**`
|
||||
- Italic: `_text_`
|
||||
- Code: `` `inline` `` or triple backticks for blocks
|
||||
- Checkboxes: `- [ ] unchecked` or `- [x] checked`
|
||||
|
||||
**Preview rendering:**
|
||||
- Content renders as formatted Markdown in preview mode
|
||||
- Click to edit - shows raw Markdown
|
||||
- Live preview updates on save
|
||||
|
||||
### Multi-line Editing
|
||||
|
||||
**Textarea behavior:**
|
||||
- Content field is a resizable textarea
|
||||
- Minimum height: 300px
|
||||
- Expands to fill available vertical space
|
||||
- Shift+Enter for new lines
|
||||
|
||||
---
|
||||
|
||||
## Note Organization
|
||||
|
||||
### Projects
|
||||
|
||||
**Linking notes to projects:**
|
||||
1. In edit mode, click **project icon** or "Add project"
|
||||
2. Dropdown shows all available projects
|
||||
3. Select project or choose "No Project" to unlink
|
||||
4. Auto-saves immediately
|
||||
|
||||
**Project behavior:**
|
||||
- Notes can belong to 0 or 1 project (not multiple)
|
||||
- Changing projects moves the note
|
||||
- Deleting a project unlinks all its notes (notes remain)
|
||||
- Project appears in note metadata (preview and edit mode)
|
||||
|
||||
**Permission handling:**
|
||||
- Can only link notes to projects you have write access to
|
||||
- Shared projects: respects collaboration permissions
|
||||
- Attempting to link to restricted project shows error
|
||||
|
||||
### Tags
|
||||
|
||||
**Adding tags:**
|
||||
1. In edit mode, click **tag icon** or "Add tags"
|
||||
2. Tag input field appears
|
||||
3. Type tag name and press Enter
|
||||
4. Select from existing tags (autocomplete) or create new
|
||||
5. Tags save immediately with note
|
||||
|
||||
**Tag rules:**
|
||||
- **Valid characters:** Alphanumeric, hyphens, underscores
|
||||
- ✅ `work`, `high-priority`, `q1_2026`
|
||||
- ❌ `tag with spaces`, `emoji🎉`, `punctuation!`
|
||||
- **Case insensitive:** `Work` = `work` = `WORK`
|
||||
- **Auto-create:** New tags created on-the-fly
|
||||
- **Multiple tags:** No limit on number per note
|
||||
|
||||
**Removing tags:**
|
||||
- Click **X** on tag chip in tag input
|
||||
- Changes save immediately
|
||||
|
||||
**Tag navigation:**
|
||||
- Click tag name in preview mode → Go to tag page
|
||||
- Shows all tasks/notes/projects with that tag
|
||||
|
||||
### Colors
|
||||
|
||||
**Note color feature:**
|
||||
- **Feature flag:** `ENABLE_NOTE_COLOR` (enabled by default)
|
||||
- **10 predefined colors:** Red, Orange, Amber, Green, Teal, Blue, Indigo, Purple, Pink, Grey
|
||||
- **None option:** Default white/dark background
|
||||
|
||||
**Setting color:**
|
||||
1. Click **⋮ menu** (three vertical dots) in top right
|
||||
2. Color palette grid appears
|
||||
3. Click desired color swatch
|
||||
4. Background changes immediately
|
||||
5. Auto-saves
|
||||
|
||||
**Color behavior:**
|
||||
- Applies to entire note background (edit and preview)
|
||||
- Text color adjusts automatically (dark text on light colors, light text on dark colors)
|
||||
- Persists across sessions
|
||||
- Visible in note preview (full panel uses color)
|
||||
|
||||
**Accessibility:**
|
||||
- Luminance calculation ensures readable text contrast
|
||||
- Dark colors → White text (#ffffff)
|
||||
- Light colors → Dark gray text (#333333)
|
||||
|
||||
---
|
||||
|
||||
## Note Views
|
||||
|
||||
### List View (Left Panel)
|
||||
|
||||
**Default behavior:**
|
||||
- Shows all notes in scrollable list
|
||||
- Most recent first (by default)
|
||||
- Each item displays:
|
||||
- Title (bold, truncated)
|
||||
- Content preview (first 100 characters, 2 lines max)
|
||||
- Last updated date
|
||||
|
||||
**Active note indicator:**
|
||||
- Blue vertical bar on left edge
|
||||
- Highlighted background (white/gray-900)
|
||||
- Indicates currently selected note
|
||||
|
||||
**Empty state:**
|
||||
- "No notes found" message
|
||||
- Appears when search returns zero results
|
||||
- Or when user has no notes
|
||||
|
||||
### Preview Mode (Right Panel)
|
||||
|
||||
**When note selected:**
|
||||
- Full title at top (large, bold)
|
||||
- Metadata row:
|
||||
- 🕐 Last updated date
|
||||
- 📁 Project (clickable link if assigned)
|
||||
- 🏷️ Tags (clickable links)
|
||||
- Content rendered as Markdown below
|
||||
- Click anywhere to enter edit mode
|
||||
|
||||
**Click behavior:**
|
||||
- Title → Enter edit mode
|
||||
- Content → Enter edit mode
|
||||
- Project link → Navigate to project page
|
||||
- Tag link → Navigate to tag page
|
||||
|
||||
**Empty state:**
|
||||
- "Select a note to preview" message
|
||||
- Shows when no note is selected (desktop only)
|
||||
|
||||
### Edit Mode (Right Panel)
|
||||
|
||||
**Layout:**
|
||||
- Title input at top (large, 2rem font)
|
||||
- Metadata controls:
|
||||
- 🕐 Last updated or "New"
|
||||
- 📁 Project selector
|
||||
- 🏷️ Tag manager
|
||||
- Save status indicator (✓ Saved / Saving... / • Unsaved)
|
||||
- Content textarea (full height)
|
||||
- **⋮ menu** (options):
|
||||
- Color picker
|
||||
- Save button
|
||||
- Delete button (if note exists)
|
||||
|
||||
**Back button (mobile):**
|
||||
- ← Back to list
|
||||
- Appears only on mobile/tablet views
|
||||
- Saves note before returning
|
||||
|
||||
**Keyboard shortcuts:**
|
||||
- `Esc` - Save and exit edit mode (if title exists)
|
||||
- `Ctrl/Cmd+S` - Manual save (implicit - auto-save handles this)
|
||||
|
||||
---
|
||||
|
||||
## Focus Mode
|
||||
|
||||
**Purpose:** Distraction-free editing for deep work
|
||||
|
||||
**Entering focus mode:**
|
||||
1. Click **expand icon** (↗️) in top right
|
||||
2. Note expands to full screen
|
||||
3. Hides sidebar, navigation, and note list
|
||||
|
||||
**What's visible in focus mode:**
|
||||
- Note title (editable)
|
||||
- Note content (editable)
|
||||
- Minimal toolbar:
|
||||
- Close button (top right)
|
||||
- Save status
|
||||
- Optional: Project and tag buttons (collapsed)
|
||||
|
||||
**Exiting focus mode:**
|
||||
- Click **X** or **close button**
|
||||
- Press `Esc` key
|
||||
- Returns to standard two-panel view
|
||||
|
||||
**Auto-save in focus mode:**
|
||||
- Same 1-second debounce
|
||||
- Save status indicator remains visible
|
||||
- Changes persist automatically
|
||||
|
||||
---
|
||||
|
||||
## Searching and Filtering
|
||||
|
||||
### Search
|
||||
|
||||
**How to search:**
|
||||
1. Enter query in search box (top of note list)
|
||||
2. Results filter in real-time
|
||||
3. Searches both title AND content
|
||||
|
||||
**Search behavior:**
|
||||
- **Case insensitive:** "markdown" matches "Markdown", "MARKDOWN"
|
||||
- **Substring matching:** "task" matches "tasks", "multitasking"
|
||||
- **Multi-word:** All words must appear (AND logic)
|
||||
- **No regex:** Plain text search only
|
||||
|
||||
**Search scope:**
|
||||
- Title field
|
||||
- Content field (full text)
|
||||
- Does NOT search tags or project names
|
||||
|
||||
### Sorting
|
||||
|
||||
**Sort options:**
|
||||
1. **Created At** (default) - Newest first
|
||||
2. **Title** - Alphabetical A-Z
|
||||
3. **Updated** - Most recently modified first
|
||||
|
||||
**How to sort:**
|
||||
- Click **sort icon** (top of note list)
|
||||
- Select sort option from dropdown
|
||||
- List re-orders immediately
|
||||
|
||||
**Sort persistence:**
|
||||
- Persists during session
|
||||
- Resets to "Created At" on page reload
|
||||
|
||||
### Tag Filtering
|
||||
|
||||
**Via URL query:**
|
||||
- `/notes?tag=bookmark` - Show only notes with #bookmark tag
|
||||
- API endpoint: `GET /api/notes?tag=bookmark`
|
||||
- Filter by single tag only (not multiple)
|
||||
|
||||
**No UI filter currently:**
|
||||
- Must use URL directly or navigate via tag page
|
||||
- Click tag in note preview → Navigates to tag page showing all tagged items
|
||||
|
||||
---
|
||||
|
||||
## Deleting Notes
|
||||
|
||||
### Confirmation Required
|
||||
|
||||
**Steps:**
|
||||
1. Select note or enter edit mode
|
||||
2. Click **⋮ menu** (three dots)
|
||||
3. Click **Delete** (red text)
|
||||
4. Confirmation dialog appears:
|
||||
- "Are you sure you want to delete this note?"
|
||||
- Shows note title
|
||||
5. Confirm or cancel
|
||||
|
||||
**What gets deleted:**
|
||||
- Note record (title, content, metadata)
|
||||
- Tag associations (note-tag links)
|
||||
- Project association (if any)
|
||||
|
||||
**What's preserved:**
|
||||
- Project (unlinking only)
|
||||
- Tags (remain in tag list)
|
||||
- No note history (deletion is permanent)
|
||||
|
||||
**No undo:**
|
||||
- Deletion is immediate and irreversible
|
||||
- No trash/archive feature
|
||||
- Ensure confirmation before proceeding
|
||||
|
||||
---
|
||||
|
||||
## Responsive Behavior
|
||||
|
||||
### Desktop (≥768px)
|
||||
|
||||
**Two-panel layout:**
|
||||
- Left panel: Note list (fixed width: 320px)
|
||||
- Right panel: Preview/edit (flexible width)
|
||||
- Both panels visible simultaneously
|
||||
|
||||
**Auto-selection:**
|
||||
- First note auto-selected on page load
|
||||
- Clicking note updates right panel
|
||||
- No "back" navigation needed
|
||||
|
||||
### Mobile/Tablet (<768px)
|
||||
|
||||
**Single panel:**
|
||||
- Shows note list OR preview/edit (not both)
|
||||
- Clicking note → Hides list, shows preview
|
||||
- "← Back to list" button → Returns to list
|
||||
|
||||
**Navigation flow:**
|
||||
1. View note list
|
||||
2. Tap note → Preview opens (list hidden)
|
||||
3. Tap anywhere → Edit mode
|
||||
4. Tap "← Back" → Returns to list
|
||||
|
||||
---
|
||||
|
||||
## Integration with Other Features
|
||||
|
||||
### Inbox Integration
|
||||
|
||||
**Creating notes from inbox:**
|
||||
- Inbox items with URLs suggest "Note"
|
||||
- Inbox items with `#bookmark` tag suggest "Note"
|
||||
- Conversion preserves tags and project references
|
||||
- See: [Inbox Page documentation](04-inbox-page.md)
|
||||
|
||||
**URL title extraction:**
|
||||
- System fetches webpage `<title>` tag
|
||||
- 3-second timeout
|
||||
- Falls back to URL if fetch fails
|
||||
- Auto-adds `#bookmark` tag
|
||||
|
||||
### Project Integration
|
||||
|
||||
**Notes in project view:**
|
||||
- Project detail page shows associated notes
|
||||
- "Add Note" button creates pre-linked note
|
||||
- Notes count appears in project card
|
||||
- Deleting project unlinks notes (notes remain)
|
||||
|
||||
**Shared project notes:**
|
||||
- Respects collaboration permissions
|
||||
- Read-only access: Can view notes, cannot edit
|
||||
- Read-write access: Can create/edit/delete notes
|
||||
- Admin access: Full control
|
||||
|
||||
### Tag Integration
|
||||
|
||||
**Tag page shows notes:**
|
||||
- `/tag/:uid` lists all tasks, notes, projects with tag
|
||||
- Notes appear in dedicated "Notes" section
|
||||
- Clicking note → Opens in Notes page
|
||||
|
||||
**Tag management:**
|
||||
- Tags created via notes appear in tag list
|
||||
- Deleting tag removes from all notes
|
||||
- Renaming tag (if supported) updates all notes
|
||||
|
||||
---
|
||||
|
||||
## Auto-Save Behavior
|
||||
|
||||
### Debounced Save
|
||||
|
||||
**How it works:**
|
||||
1. User types in title or content
|
||||
2. Save status changes to "• Unsaved changes"
|
||||
3. After 1 second of inactivity, triggers save
|
||||
4. Status changes to "Saving..."
|
||||
5. On success: "✓ Saved"
|
||||
6. On failure: "• Unsaved changes" (stays amber)
|
||||
|
||||
**Debounce settings:**
|
||||
- **Delay:** 1000ms (1 second)
|
||||
- **Trailing:** Yes (saves after typing stops)
|
||||
- **Leading:** No (doesn't save on first keystroke)
|
||||
|
||||
### What Triggers Save
|
||||
|
||||
**Auto-save triggers:**
|
||||
- Title field changes
|
||||
- Content field changes
|
||||
- Project selection changes
|
||||
- Tag additions/removals
|
||||
- Color changes
|
||||
|
||||
**No save triggers:**
|
||||
- Focusing input fields
|
||||
- Scrolling
|
||||
- Opening dropdowns
|
||||
- Viewing preview mode
|
||||
|
||||
### Save Guarantees
|
||||
|
||||
**When navigation occurs:**
|
||||
- Leaving Notes page → Pending saves complete first
|
||||
- Selecting different note → Current note saves first
|
||||
- Mobile "Back" button → Saves before hiding panel
|
||||
|
||||
**Error handling:**
|
||||
- Network failure → Status shows "• Unsaved changes"
|
||||
- No automatic retry (user must trigger re-save by editing)
|
||||
- Console error logged for debugging
|
||||
|
||||
**Edge case - empty title:**
|
||||
- Auto-save only triggers if `title` is non-empty
|
||||
- Empty title note → Not saved to server
|
||||
- User must enter title to persist note
|
||||
|
||||
---
|
||||
|
||||
## Display and Rendering
|
||||
|
||||
### Markdown Rendering
|
||||
|
||||
**Supported syntax:**
|
||||
- **Headings:** `#`, `##`, `###`, `####`, `#####`, `######`
|
||||
- **Bold:** `**text**` or `__text__`
|
||||
- **Italic:** `*text*` or `_text_`
|
||||
- **Links:** `[text](url)` or `<url>`
|
||||
- **Lists:** `- item` (unordered) or `1. item` (ordered)
|
||||
- **Checkboxes:** `- [ ] todo` or `- [x] done`
|
||||
- **Code:** `` `inline` `` or ` ```language\nblock\n``` `
|
||||
- **Blockquotes:** `> quote`
|
||||
- **Horizontal rules:** `---` or `***`
|
||||
- **Tables:** Pipe-separated cells
|
||||
- **Images:** `` (rendered as `<img>`)
|
||||
|
||||
**Rendering engine:**
|
||||
- Uses `MarkdownRenderer` component
|
||||
- Safe HTML escaping (prevents XSS)
|
||||
- Syntax highlighting for code blocks
|
||||
- Opens external links in new tab
|
||||
|
||||
### Title Display
|
||||
|
||||
**Preview mode:**
|
||||
- Large heading (2rem font size)
|
||||
- Medium weight (500)
|
||||
- Truncated if very long (responsive)
|
||||
- Shows "Untitled Note" if empty
|
||||
|
||||
**Edit mode:**
|
||||
- Full-width input field
|
||||
- Same size/weight as preview (2rem/500)
|
||||
- Placeholder: "Note title..."
|
||||
- Auto-focus on new note creation
|
||||
|
||||
### Content Display
|
||||
|
||||
**Preview mode:**
|
||||
- Rendered Markdown with styling
|
||||
- Text size: 0.875rem (14px) on mobile, 1rem (16px) on desktop
|
||||
- Line height: 1.5
|
||||
- Scrollable if content exceeds viewport
|
||||
|
||||
**Edit mode:**
|
||||
- Plain textarea (raw Markdown)
|
||||
- Minimum height: 300px
|
||||
- Expands to fill vertical space
|
||||
- Monospace font (not specified, browser default)
|
||||
- Placeholder: "Write your note content here... (Markdown supported)"
|
||||
|
||||
### Color-Aware Text
|
||||
|
||||
**Text color adjustment:**
|
||||
- Background luminance calculated from hex color
|
||||
- Luminance < 0.4 → White text (#ffffff)
|
||||
- Luminance ≥ 0.4 → Dark gray text (#333333)
|
||||
- Applies to title, content, and metadata text
|
||||
|
||||
**Formula:**
|
||||
```
|
||||
luminance = (0.299 * R + 0.587 * G + 0.114 * B) / 255
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Keyboard Shortcuts
|
||||
|
||||
### Global (anywhere in app)
|
||||
|
||||
| Shortcut | Action |
|
||||
|----------|--------|
|
||||
| `g` then `n` | Go to Notes page |
|
||||
|
||||
### On Notes page
|
||||
|
||||
| Shortcut | Action |
|
||||
|----------|--------|
|
||||
| `n` | Create new note |
|
||||
| Click note | Open in preview mode |
|
||||
|
||||
### In edit mode
|
||||
|
||||
| Shortcut | Action |
|
||||
|----------|--------|
|
||||
| `Esc` | Save and exit edit mode (if title exists) |
|
||||
| `Tab` | Navigate between fields |
|
||||
|
||||
### In focus mode
|
||||
|
||||
| Shortcut | Action |
|
||||
|----------|--------|
|
||||
| `Esc` | Exit focus mode |
|
||||
| Click X | Close focus mode |
|
||||
|
||||
---
|
||||
|
||||
## Common Workflows
|
||||
|
||||
### Workflow 1: Quick Note Capture
|
||||
|
||||
**Scenario:** Capture a fleeting idea
|
||||
|
||||
1. Press `g` then `n` to open Notes page
|
||||
2. Click **+** to create new note
|
||||
3. Type title: "Product idea - Voice control"
|
||||
4. Write content:
|
||||
```markdown
|
||||
## Overview
|
||||
Users want hands-free interaction
|
||||
|
||||
## Features
|
||||
- Voice commands for task creation
|
||||
- Smart parsing of natural language
|
||||
- Integration with existing task flow
|
||||
```
|
||||
5. Auto-saves after 1 second
|
||||
6. Add tags: `#product`, `#ideas`
|
||||
7. Link to project: "Product Roadmap"
|
||||
8. Press Esc to exit edit mode
|
||||
|
||||
### Workflow 2: Meeting Notes
|
||||
|
||||
**Scenario:** Documenting a client meeting
|
||||
|
||||
1. Navigate to `/notes`
|
||||
2. Create new note
|
||||
3. Title: "Client Meeting - Acme Corp - 2026-03-14"
|
||||
4. Content:
|
||||
```markdown
|
||||
## Attendees
|
||||
- John (Acme Corp CEO)
|
||||
- Sarah (Product Manager)
|
||||
- Me
|
||||
|
||||
## Discussion
|
||||
- Requested new reporting dashboard
|
||||
- Timeline: Q2 2026
|
||||
- Budget: $50k
|
||||
|
||||
## Action Items
|
||||
- [ ] Send proposal by Monday
|
||||
- [ ] Schedule follow-up call
|
||||
- [ ] Share mockups
|
||||
```
|
||||
5. Link to project: "Acme Corp"
|
||||
6. Add tags: `#meetings`, `#clients`, `#acme`
|
||||
7. Auto-saves throughout
|
||||
8. Click "Focus mode" for distraction-free review
|
||||
|
||||
### Workflow 3: Bookmark Collection
|
||||
|
||||
**Scenario:** Save an article to read later
|
||||
|
||||
1. From Inbox: `https://example.com/article +Reading #bookmark`
|
||||
2. Press `Ctrl+N` (or `Cmd+N`)
|
||||
3. System:
|
||||
- Fetches title: "10 Tips for Better Focus"
|
||||
- Creates note with URL as content
|
||||
- Links to "Reading" project
|
||||
- Adds `#bookmark` tag
|
||||
4. Note auto-saved and opens in edit mode
|
||||
5. Add notes below URL:
|
||||
```markdown
|
||||
https://example.com/article
|
||||
|
||||
## Key Takeaways
|
||||
- Pomodoro technique
|
||||
- Single-tasking
|
||||
- Environment matters
|
||||
```
|
||||
6. Press Esc to save and exit
|
||||
|
||||
### Workflow 4: Knowledge Base
|
||||
|
||||
**Scenario:** Building a personal wiki
|
||||
|
||||
1. Create note: "Git Cheatsheet"
|
||||
2. Content:
|
||||
```markdown
|
||||
## Common Commands
|
||||
|
||||
### Branching
|
||||
- `git branch <name>` - Create branch
|
||||
- `git checkout <name>` - Switch branch
|
||||
- `git checkout -b <name>` - Create and switch
|
||||
|
||||
### Committing
|
||||
- `git add .` - Stage all changes
|
||||
- `git commit -m "message"` - Commit with message
|
||||
- `git commit --amend` - Amend last commit
|
||||
|
||||
### Remote
|
||||
- `git push origin <branch>` - Push to remote
|
||||
- `git pull` - Fetch and merge
|
||||
```
|
||||
3. Add tags: `#reference`, `#git`, `#dev`
|
||||
4. Link to project: "Developer Resources"
|
||||
5. Set color: Blue (for tech references)
|
||||
6. Bookmark `/notes/:uid` for quick access
|
||||
|
||||
### Workflow 5: Weekly Review
|
||||
|
||||
**Scenario:** Process and organize accumulated notes
|
||||
|
||||
1. Navigate to `/notes`
|
||||
2. Sort by "Updated" to see recent notes
|
||||
3. Search for "meeting" to find unprocessed meeting notes
|
||||
4. For each note:
|
||||
- Review content
|
||||
- Extract action items → Convert to tasks
|
||||
- Add relevant tags
|
||||
- Link to appropriate projects
|
||||
- Archive or delete if no longer needed
|
||||
5. Search for untagged notes (manual review)
|
||||
6. Ensure all bookmarks are properly categorized
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### "Auto-save not working"
|
||||
|
||||
**Possible causes:**
|
||||
1. Title is empty → Auto-save only triggers with non-empty title
|
||||
2. Network error → Check browser console for errors
|
||||
3. Session expired → Re-authenticate
|
||||
4. Debounce hasn't elapsed → Wait 1 second after typing
|
||||
|
||||
**Solution:**
|
||||
- Add a title (at minimum)
|
||||
- Check network connection
|
||||
- Refresh page and re-login if needed
|
||||
- Observe save status indicator
|
||||
|
||||
### "Note disappeared after creating"
|
||||
|
||||
**Likely cause:** Empty title + navigated away
|
||||
|
||||
**What happened:**
|
||||
- Created note without title
|
||||
- Auto-save didn't trigger (requires title)
|
||||
- Navigated away → Note not persisted
|
||||
|
||||
**Prevention:**
|
||||
- Always add a title before leaving edit mode
|
||||
- Check for "✓ Saved" status before navigating
|
||||
|
||||
### "Markdown not rendering"
|
||||
|
||||
**Check:**
|
||||
1. Are you in edit mode? (shows raw Markdown)
|
||||
2. Switch to preview mode (click note in list or press Esc)
|
||||
3. Ensure Markdown syntax is correct
|
||||
- ❌ `#Heading` (no space)
|
||||
- ✅ `# Heading` (space required)
|
||||
|
||||
### "Can't link note to project"
|
||||
|
||||
**Possible causes:**
|
||||
1. Project doesn't exist → Create project first
|
||||
2. No write access to project → Check collaboration permissions
|
||||
3. Project is archived → Unarchive or choose different project
|
||||
|
||||
**Solution:**
|
||||
- Verify project exists in project list
|
||||
- Check permissions with project owner
|
||||
- Select different project
|
||||
|
||||
### "Tags not saving"
|
||||
|
||||
**Check:**
|
||||
1. Tag name has invalid characters?
|
||||
- Use only alphanumeric, hyphens, underscores
|
||||
2. Network error during save?
|
||||
- Check browser console
|
||||
3. Tag input didn't close properly?
|
||||
- Click outside tag input to trigger save
|
||||
|
||||
### "Color not appearing"
|
||||
|
||||
**Check:**
|
||||
1. Is `ENABLE_NOTE_COLOR` feature flag enabled?
|
||||
- Check with admin/developer
|
||||
2. Browser caching issue?
|
||||
- Hard refresh: `Ctrl+Shift+R` or `Cmd+Shift+R`
|
||||
3. Dark mode conflict?
|
||||
- Try switching theme
|
||||
|
||||
---
|
||||
|
||||
## Best Practices
|
||||
|
||||
### Organization
|
||||
|
||||
1. **Use consistent tagging:**
|
||||
- Create a tag hierarchy: `#project-ideas`, `#project-specs`, `#project-retros`
|
||||
- Avoid tag proliferation: Reuse existing tags
|
||||
|
||||
2. **Link notes to projects:**
|
||||
- Project-specific notes → Link to project
|
||||
- General knowledge → Leave unlinked or create "Resources" project
|
||||
|
||||
3. **Color coding:**
|
||||
- Develop personal system: Red = urgent, Blue = reference, Green = ideas
|
||||
- Or by topic: Purple = client work, Teal = personal
|
||||
|
||||
### Content
|
||||
|
||||
1. **Use Markdown effectively:**
|
||||
- Headings for structure
|
||||
- Lists for clarity
|
||||
- Checkboxes for tracking follow-ups within notes
|
||||
- Code blocks for technical snippets
|
||||
|
||||
2. **Include metadata:**
|
||||
- Date in title for meeting notes: "Meeting - Client - 2026-03-14"
|
||||
- Context in content: "Source: [Article](url)"
|
||||
|
||||
3. **Break up long notes:**
|
||||
- Split into multiple notes by subtopic
|
||||
- Link between notes using markdown links
|
||||
- Use tags to group related notes
|
||||
|
||||
### Maintenance
|
||||
|
||||
1. **Regular review:**
|
||||
- Weekly: Process new notes, add tags, link to projects
|
||||
- Monthly: Archive or delete obsolete notes
|
||||
- Quarterly: Reorganize tag system
|
||||
|
||||
2. **Search before creating:**
|
||||
- Check if similar note exists
|
||||
- Consolidate duplicates
|
||||
|
||||
3. **Bookmark frequently accessed:**
|
||||
- Copy note URL: `/notes/:uid`
|
||||
- Save in browser bookmarks for quick access
|
||||
|
||||
---
|
||||
|
||||
## Limitations and Constraints
|
||||
|
||||
### Current Limitations
|
||||
|
||||
1. **No note history/versions:**
|
||||
- Edits overwrite previous content
|
||||
- No undo beyond current session
|
||||
- Workaround: Use external version control for critical notes
|
||||
|
||||
2. **Single project per note:**
|
||||
- Cannot link note to multiple projects
|
||||
- Workaround: Duplicate note or use tags for cross-referencing
|
||||
|
||||
3. **No hierarchical notes:**
|
||||
- Flat structure only (no sub-notes)
|
||||
- Workaround: Use Markdown headings and lists
|
||||
|
||||
4. **No collaborative editing:**
|
||||
- Only one user can edit at a time
|
||||
- No conflict resolution
|
||||
- Last save wins (potential data loss)
|
||||
|
||||
5. **No attachments:**
|
||||
- Cannot upload files/images to notes
|
||||
- Workaround: Host elsewhere, link via Markdown
|
||||
|
||||
6. **Limited rich text:**
|
||||
- Markdown only (no WYSIWYG editor)
|
||||
- No inline images (must use external URLs)
|
||||
- No tables with complex formatting
|
||||
|
||||
### Technical Constraints
|
||||
|
||||
1. **Search limitations:**
|
||||
- No fuzzy matching
|
||||
- No search within tags/projects
|
||||
- No advanced operators (AND, OR, NOT)
|
||||
|
||||
2. **Performance:**
|
||||
- All notes loaded at once (no pagination)
|
||||
- Slow with 1000+ notes
|
||||
- No virtualized scrolling
|
||||
|
||||
3. **Mobile experience:**
|
||||
- Single-panel only (no split view)
|
||||
- Harder to reference multiple notes
|
||||
|
||||
---
|
||||
|
||||
## Related Documentation
|
||||
|
||||
- [Inbox Page](04-inbox-page.md) - Quick capture and conversion to notes
|
||||
- [Today Page Sections](02-today-page-sections.md) - Task-focused workflow
|
||||
- [Architecture Overview](architecture.md) - Technical architecture
|
||||
- [Development Workflow](development-workflow.md) - Working with the codebase
|
||||
- [Common Tasks](common-tasks.md) - How to modify notes functionality
|
||||
|
||||
**Technical Implementation Files:**
|
||||
- Note model: `/backend/models/note.js`
|
||||
- Note service: `/backend/modules/notes/service.js`
|
||||
- Note controller: `/backend/modules/notes/controller.js`
|
||||
- Note repository: `/backend/modules/notes/repository.js`
|
||||
- Note API routes: `/backend/modules/notes/routes.js`
|
||||
- Notes component: `/frontend/components/Notes.tsx`
|
||||
- Note modal: `/frontend/components/Note/NoteModal.tsx`
|
||||
- Note focus mode: `/frontend/components/Note/NoteFocusMode.tsx`
|
||||
- Markdown renderer: `/frontend/components/Shared/MarkdownRenderer.tsx`
|
||||
- Note service (frontend): `/frontend/utils/notesService.ts`
|
||||
|
||||
---
|
||||
|
||||
**Document Version:** 1.0.0
|
||||
**Last Updated:** 2026-03-14
|
||||
**Audience:** Developers, AI assistants, and end users
|
||||
901
docs/06-projects.md
Normal file
901
docs/06-projects.md
Normal file
|
|
@ -0,0 +1,901 @@
|
|||
# Projects - Behavior Rules
|
||||
|
||||
This document explains how projects work in tududi from a user behavior perspective. For technical implementation details, see the backend code in `/backend/modules/projects/` and frontend components in `/frontend/components/Project/`.
|
||||
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
**Projects** are containers for organizing related tasks and notes in tududi. They sit in the middle of the hierarchy (Areas > Projects > Tasks) and provide a focused workspace for achieving specific goals.
|
||||
|
||||
**Key characteristics:**
|
||||
- Group related tasks and notes together
|
||||
- Track progress and completion percentage
|
||||
- Can belong to an Area for higher-level organization
|
||||
- Support collaboration through sharing
|
||||
- Have status lifecycle (Planned → In Progress → Done)
|
||||
- Can be pinned to sidebar for quick access
|
||||
- Support tags, priorities, and due dates
|
||||
|
||||
**URL:** `/project/:uid`
|
||||
|
||||
---
|
||||
|
||||
## Core Principles
|
||||
|
||||
1. **Projects are optional containers**
|
||||
- Tasks and notes can exist without projects (orphaned)
|
||||
- But projects help organize work into logical groupings
|
||||
|
||||
2. **Projects don't cascade delete**
|
||||
- Deleting a project orphans its tasks/notes, doesn't delete them
|
||||
- This prevents accidental data loss
|
||||
|
||||
3. **Projects track progress automatically**
|
||||
- Completion percentage calculated from child tasks
|
||||
- "Stalled" detection for projects with no active tasks
|
||||
|
||||
4. **Projects can be shared**
|
||||
- Share with other users (read-only or read-write)
|
||||
- Shared project access extends to all tasks/notes within
|
||||
|
||||
---
|
||||
|
||||
## Hierarchy
|
||||
|
||||
```
|
||||
Areas (highest level - life domains)
|
||||
└── Projects (mid level - specific goals/initiatives)
|
||||
├── Tasks (actionable items)
|
||||
└── Notes (reference material)
|
||||
```
|
||||
|
||||
**Example:**
|
||||
```
|
||||
Area: "Personal"
|
||||
└── Project: "Home Renovation"
|
||||
├── Task: "Get quotes from contractors"
|
||||
├── Task: "Choose paint colors"
|
||||
└── Note: "Inspiration photos from Pinterest"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Project Properties
|
||||
|
||||
### Basic Information
|
||||
|
||||
1. **Name** (required)
|
||||
- The project title
|
||||
- Example: "Q1 Marketing Campaign", "Home Renovation", "Learn Spanish"
|
||||
|
||||
2. **Description** (optional)
|
||||
- Longer explanation of the project's purpose
|
||||
- Supports multi-line text
|
||||
- Displayed at top of project page
|
||||
|
||||
3. **UID** (auto-generated)
|
||||
- Unique identifier for the project
|
||||
- Used in URLs: `/project/:uid`
|
||||
- Cannot be changed
|
||||
|
||||
### Organization
|
||||
|
||||
4. **Area** (optional)
|
||||
- Parent area this project belongs to
|
||||
- Used for high-level grouping
|
||||
- Can be changed or removed
|
||||
- Examples: "Work", "Personal", "Health"
|
||||
|
||||
5. **Tags** (optional)
|
||||
- Flexible categorization system
|
||||
- Multiple tags supported: `#q1`, `#urgent`, `#client-work`
|
||||
- Tags created automatically when used
|
||||
- Shared across projects, tasks, and notes
|
||||
|
||||
### Status and Lifecycle
|
||||
|
||||
6. **Status** (required, default: `not_started`)
|
||||
- **Planned**: Future project, not started yet
|
||||
- **Not Started**: Ready to begin but not yet started
|
||||
- **In Progress**: Currently being worked on
|
||||
- **Waiting**: Blocked or waiting on external dependency
|
||||
- **Done**: Project completed successfully
|
||||
- **Cancelled**: Project abandoned or no longer relevant
|
||||
|
||||
7. **Priority** (optional)
|
||||
- 0 = None (default)
|
||||
- 1 = Medium
|
||||
- 2 = High
|
||||
- Visual indicator in UI (colored dot)
|
||||
|
||||
8. **Due Date** (optional)
|
||||
- When the project should be completed
|
||||
- Triggers notifications when approaching or overdue
|
||||
- Displayed in project cards and detail view
|
||||
|
||||
### Display and Organization
|
||||
|
||||
9. **Pin to Sidebar** (boolean, default: `false`)
|
||||
- Pins project to left sidebar for quick access
|
||||
- Pinned projects shown above unpinned ones
|
||||
- Useful for currently active projects
|
||||
|
||||
10. **Banner Image** (optional)
|
||||
- Visual header image for the project
|
||||
- Uploaded via image picker
|
||||
- Displayed at top of project detail page
|
||||
- Can be edited or removed
|
||||
|
||||
### Task Display Preferences
|
||||
|
||||
11. **Show Completed Tasks** (boolean, default: `false`)
|
||||
- Controls whether completed tasks are visible
|
||||
- Per-project setting
|
||||
- Helps reduce clutter on active projects
|
||||
|
||||
12. **Task Sort Order** (string, default: `created_at:desc`)
|
||||
- How tasks are sorted within the project
|
||||
- Options: `created_at:asc`, `created_at:desc`, `due_date:asc`, `priority:desc`, etc.
|
||||
- Per-project preference
|
||||
|
||||
---
|
||||
|
||||
## Calculated Properties
|
||||
|
||||
These properties are computed automatically based on project content:
|
||||
|
||||
### Task Status Tracking
|
||||
|
||||
**task_status** object:
|
||||
- `total`: Total number of tasks in project
|
||||
- `done`: Count of completed tasks
|
||||
- `in_progress`: Count of tasks currently being worked on
|
||||
- `not_started`: Count of tasks not yet started
|
||||
|
||||
**Example:**
|
||||
```json
|
||||
{
|
||||
"total": 10,
|
||||
"done": 6,
|
||||
"in_progress": 3,
|
||||
"not_started": 1
|
||||
}
|
||||
```
|
||||
|
||||
### Completion Percentage
|
||||
|
||||
**completion_percentage**: `0-100`
|
||||
- Calculated as: `(done / total) * 100`
|
||||
- Rounded to whole number
|
||||
- Shows `0%` if project has no tasks
|
||||
- Based on parent tasks only (subtasks don't count separately)
|
||||
|
||||
### Stalled Detection
|
||||
|
||||
**is_stalled**: `true | false`
|
||||
- A project is "stalled" when:
|
||||
- Status is `in_progress` OR `planned`
|
||||
- AND has zero active tasks (no "in_progress" or "not_started" tasks)
|
||||
- Indicates projects that need attention
|
||||
- Surfaced in Productivity Assistant
|
||||
|
||||
**Example scenarios:**
|
||||
- ✅ Status: `in_progress`, Tasks: 5 (3 done, 2 not_started) → NOT stalled
|
||||
- ❌ Status: `in_progress`, Tasks: 5 (all done) → STALLED
|
||||
- ✅ Status: `done`, Tasks: 5 (all done) → NOT stalled (done projects can't be stalled)
|
||||
- ❌ Status: `planned`, Tasks: 0 → STALLED
|
||||
|
||||
### Sharing Metadata
|
||||
|
||||
**share_count**: Number of users project is shared with
|
||||
**is_shared**: `true` if `share_count > 0`
|
||||
|
||||
---
|
||||
|
||||
## Project Lifecycle
|
||||
|
||||
### Creating a Project
|
||||
|
||||
**Ways to create:**
|
||||
1. Click "New Project" button on Projects page
|
||||
2. Use `+Project` syntax in Inbox and convert
|
||||
3. Create via modal when adding task/note
|
||||
|
||||
**Required fields:**
|
||||
- Name
|
||||
|
||||
**Default values:**
|
||||
- Status: `not_started`
|
||||
- Pin to sidebar: `false`
|
||||
- Show completed tasks: `false`
|
||||
- Task sort order: `created_at:desc`
|
||||
|
||||
**Auto-generated:**
|
||||
- UID (unique identifier)
|
||||
- Timestamps (created_at, updated_at)
|
||||
|
||||
### Editing a Project
|
||||
|
||||
**What you can edit:**
|
||||
- All basic properties (name, description, area, status, priority, due date)
|
||||
- Tags (add/remove)
|
||||
- Banner image (upload/change/remove)
|
||||
- Display preferences (pin, show completed, sort order)
|
||||
|
||||
**What you cannot edit:**
|
||||
- UID
|
||||
- User ID (owner)
|
||||
- Created timestamp
|
||||
|
||||
**Who can edit:**
|
||||
- Project owner (full access)
|
||||
- Users with read-write (`rw`) share access
|
||||
- Admin users
|
||||
|
||||
### Changing Status
|
||||
|
||||
**Status transitions:**
|
||||
- Any status can change to any other status (no enforced workflow)
|
||||
- Common flows:
|
||||
- `planned` → `in_progress` → `done`
|
||||
- `not_started` → `in_progress` → `done`
|
||||
- `in_progress` → `waiting` → `in_progress`
|
||||
- `in_progress` → `cancelled`
|
||||
|
||||
**Effects of status change:**
|
||||
- Affects "active projects" filter (planned/in_progress/waiting)
|
||||
- Affects stalled detection
|
||||
- Updates last modified timestamp
|
||||
|
||||
### Deleting a Project
|
||||
|
||||
**What happens:**
|
||||
1. Project record is deleted from database
|
||||
2. **Tasks belonging to project are orphaned** (project_id set to null)
|
||||
3. **Notes belonging to project are orphaned** (project_id set to null)
|
||||
4. Project tags associations are removed
|
||||
5. Share permissions are deleted
|
||||
|
||||
**What is NOT deleted:**
|
||||
- Tasks (they become orphaned, appear in "No Project" filter)
|
||||
- Notes (they become orphaned)
|
||||
- Tags (they remain in system)
|
||||
- Area (parent area is unaffected)
|
||||
|
||||
**Who can delete:**
|
||||
- Project owner only
|
||||
- Admin users
|
||||
|
||||
**No undo:**
|
||||
- Deletion is permanent
|
||||
- Use status `cancelled` if you want to preserve but deactivate
|
||||
|
||||
---
|
||||
|
||||
## Areas and Projects
|
||||
|
||||
### What is an Area?
|
||||
|
||||
An **Area** is a top-level category representing a life domain or responsibility area. Examples:
|
||||
- Personal
|
||||
- Work
|
||||
- Health
|
||||
- Finance
|
||||
- Learning
|
||||
|
||||
### Relationship
|
||||
|
||||
**Projects belong to Areas (optional):**
|
||||
- One project can belong to one area
|
||||
- A project can have no area (orphaned)
|
||||
- An area can have multiple projects
|
||||
- Deleting an area orphans its projects (doesn't delete them)
|
||||
|
||||
### Grouping
|
||||
|
||||
**On Projects page:**
|
||||
- Projects can be grouped by area (`?grouped=true`)
|
||||
- Shows "No Area" group for orphaned projects
|
||||
- Useful for high-level overview of work
|
||||
|
||||
**Example grouped view:**
|
||||
```
|
||||
Work
|
||||
├── Q1 Marketing Campaign
|
||||
├── Website Redesign
|
||||
└── Client Onboarding
|
||||
|
||||
Personal
|
||||
├── Home Renovation
|
||||
└── Learn Spanish
|
||||
|
||||
No Area
|
||||
└── Random Ideas
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Tasks and Notes in Projects
|
||||
|
||||
### Adding Tasks to Projects
|
||||
|
||||
**Ways to assign task to project:**
|
||||
1. Select project in task detail modal
|
||||
2. Use `+ProjectName` syntax in Inbox
|
||||
3. Create task directly from project page
|
||||
4. Bulk assign existing orphaned tasks
|
||||
|
||||
**Task inheritance:**
|
||||
- Tasks inherit nothing from parent project
|
||||
- Task status is independent of project status
|
||||
- Task due date is independent of project due date
|
||||
- Task priority is independent of project priority
|
||||
|
||||
**Task visibility:**
|
||||
- All project tasks shown on project detail page
|
||||
- Can filter by status (not_started, in_progress, done)
|
||||
- Can toggle "Show completed" per project
|
||||
- Parent tasks only (subtasks nested under parents)
|
||||
|
||||
### Adding Notes to Projects
|
||||
|
||||
**Ways to assign note to project:**
|
||||
1. Select project in note modal
|
||||
2. Use `+ProjectName` syntax in Inbox when converting to note
|
||||
3. Create note directly from project page
|
||||
|
||||
**Note display:**
|
||||
- Notes shown in separate "Notes" section on project page
|
||||
- Sorted by most recent first
|
||||
- Can be tagged independently
|
||||
|
||||
### Orphaned Tasks/Notes
|
||||
|
||||
**What are orphaned items:**
|
||||
- Tasks or notes with no project assigned (`project_id = null`)
|
||||
- Created without project, or project was deleted
|
||||
|
||||
**How to find:**
|
||||
- Tasks page: Filter by "No Project"
|
||||
- Can bulk-assign to projects later
|
||||
|
||||
**Not a problem:**
|
||||
- Orphaned items are perfectly valid
|
||||
- Projects are optional organizational containers
|
||||
|
||||
---
|
||||
|
||||
## Project Sharing and Collaboration
|
||||
|
||||
### Share Levels
|
||||
|
||||
1. **Read-Only (`ro`)**
|
||||
- View project, tasks, and notes
|
||||
- Cannot edit or add content
|
||||
- Cannot share with others
|
||||
|
||||
2. **Read-Write (`rw`)**
|
||||
- View project, tasks, and notes
|
||||
- Edit existing content
|
||||
- Add new tasks and notes
|
||||
- Cannot delete project
|
||||
- Cannot change sharing settings
|
||||
|
||||
3. **Owner (implicit)**
|
||||
- Full control
|
||||
- Can delete project
|
||||
- Can change sharing settings
|
||||
- Can change project status
|
||||
|
||||
### Sharing a Project
|
||||
|
||||
**How to share:**
|
||||
1. Open project detail page
|
||||
2. Click "Share" button
|
||||
3. Enter email of user to share with
|
||||
4. Select access level (read-only or read-write)
|
||||
5. User receives notification
|
||||
|
||||
**Requirements:**
|
||||
- Other user must have a tududi account
|
||||
- Must use exact email address
|
||||
- Cannot share with yourself
|
||||
|
||||
### Access Inheritance
|
||||
|
||||
**When you share a project:**
|
||||
- Shared user gets access to ALL tasks in project
|
||||
- Shared user gets access to ALL notes in project
|
||||
- Access level applies to entire project tree
|
||||
|
||||
**Example:**
|
||||
- You share "Website Redesign" project with Alice (read-write)
|
||||
- Alice can now view/edit:
|
||||
- The project itself
|
||||
- All tasks in the project
|
||||
- All notes in the project
|
||||
- All subtasks of tasks in the project
|
||||
|
||||
### Shared Projects Behavior
|
||||
|
||||
**For shared users:**
|
||||
- Shared projects appear in their Projects list
|
||||
- Can filter projects by ownership vs shared
|
||||
- Shared indicator shown on project card
|
||||
- Cannot change Area (only owner can)
|
||||
- Cannot delete project (only owner can)
|
||||
|
||||
**Notifications:**
|
||||
- Project owner sees share count badge
|
||||
- Shared users see owner's name
|
||||
- Activity on shared project can trigger notifications
|
||||
|
||||
---
|
||||
|
||||
## Due Dates and Notifications
|
||||
|
||||
### Setting Due Dates
|
||||
|
||||
**Project due date:**
|
||||
- Optional field
|
||||
- Date + time picker
|
||||
- Represents project deadline
|
||||
|
||||
**Independent from task due dates:**
|
||||
- Project due date doesn't affect task due dates
|
||||
- Tasks can be due before, during, or after project due date
|
||||
- No validation or warnings if dates mismatch
|
||||
|
||||
### Due Date Notifications
|
||||
|
||||
**Automated notifications created when:**
|
||||
1. **Due Soon**: Project due date within 24 hours
|
||||
2. **Overdue**: Project due date has passed
|
||||
|
||||
**Notification timing:**
|
||||
- Checked via cron job (runs periodically)
|
||||
- Notifications sent in-app
|
||||
- Can also send via Telegram if configured
|
||||
|
||||
**Notification rules:**
|
||||
- Only for projects with status NOT `done` or `cancelled`
|
||||
- Only if user has notifications enabled for this type
|
||||
- Won't create duplicate notifications
|
||||
- Old unread notifications deleted before creating new one
|
||||
- Dismissed notifications won't be recreated
|
||||
|
||||
**Example messages:**
|
||||
- "Your project 'Website Redesign' is due in 6 hours"
|
||||
- "Your project 'Q1 Report' was due yesterday"
|
||||
- "Your project 'Client Onboarding' was due 3 days ago"
|
||||
|
||||
---
|
||||
|
||||
## Filtering and Viewing Projects
|
||||
|
||||
### Projects List Page
|
||||
|
||||
**URL:** `/projects`
|
||||
|
||||
**Default view:**
|
||||
- All projects for current user
|
||||
- Includes owned and shared projects
|
||||
- Sorted alphabetically by name
|
||||
- Shows project cards with:
|
||||
- Name, description (truncated)
|
||||
- Status badge
|
||||
- Priority indicator
|
||||
- Completion percentage
|
||||
- Task count
|
||||
- Tags
|
||||
- Area name
|
||||
- Pinned indicator
|
||||
- Shared indicator
|
||||
|
||||
### Filter Options
|
||||
|
||||
1. **By Status**
|
||||
- Query: `?status=in_progress`
|
||||
- Values: `planned`, `not_started`, `in_progress`, `waiting`, `done`, `cancelled`
|
||||
- Can filter multiple: `?status[]=in_progress&status[]=planned`
|
||||
|
||||
2. **By Active State**
|
||||
- Query: `?active=true`
|
||||
- `true`: Shows planned, in_progress, waiting
|
||||
- `false`: Shows not_started, done, cancelled
|
||||
|
||||
3. **By Area**
|
||||
- Query: `?area=:area-uid`
|
||||
- Shows only projects in specified area
|
||||
- Use area UID from URL
|
||||
|
||||
4. **By Pinned**
|
||||
- Query: `?pin_to_sidebar=true`
|
||||
- `true`: Only pinned projects
|
||||
- `false`: Only unpinned projects
|
||||
|
||||
5. **Grouped by Area**
|
||||
- Query: `?grouped=true`
|
||||
- Groups projects under area names
|
||||
- Special "No Area" group for orphaned projects
|
||||
|
||||
**Example URLs:**
|
||||
- `/projects?status=in_progress` - Active projects
|
||||
- `/projects?active=true` - All active projects
|
||||
- `/projects?pin_to_sidebar=true` - Pinned projects only
|
||||
- `/projects?area=abc123&grouped=true` - Projects in specific area, grouped
|
||||
|
||||
---
|
||||
|
||||
## Sidebar Pinning
|
||||
|
||||
### What is Pinning?
|
||||
|
||||
**Pin to Sidebar** is a quick-access feature that:
|
||||
- Shows project in left sidebar navigation
|
||||
- Provides one-click access to frequently used projects
|
||||
- Appears under "Pinned Projects" section
|
||||
|
||||
### How to Pin
|
||||
|
||||
**Ways to pin:**
|
||||
1. Click pin icon on project card
|
||||
2. Toggle "Pin to sidebar" in project modal
|
||||
3. Update via project detail page
|
||||
|
||||
**Pin behavior:**
|
||||
- Pinned projects shown above unpinned ones in sidebar
|
||||
- Sorted alphabetically within pinned section
|
||||
- Can pin unlimited projects (but UI gets crowded)
|
||||
|
||||
### When to Pin
|
||||
|
||||
**Good candidates for pinning:**
|
||||
- Currently active projects you access daily
|
||||
- Projects in "in_progress" status
|
||||
- Projects with frequent task additions
|
||||
- Projects you're actively collaborating on
|
||||
|
||||
**Not recommended:**
|
||||
- Completed or cancelled projects
|
||||
- Future/planned projects not yet active
|
||||
- Projects you rarely access
|
||||
|
||||
---
|
||||
|
||||
## Project Insights and Metrics
|
||||
|
||||
### Task Status Metrics
|
||||
|
||||
Displayed on project cards and detail page:
|
||||
|
||||
**Total tasks**: Count of all parent tasks (excluding subtasks)
|
||||
**Completion percentage**: Visual progress bar
|
||||
**Breakdown by status**:
|
||||
- Done (green)
|
||||
- In progress (blue)
|
||||
- Not started (gray)
|
||||
|
||||
### Stalled Projects
|
||||
|
||||
**What is a stalled project?**
|
||||
- Status is `planned` or `in_progress`
|
||||
- Has zero active tasks (all tasks are done, or no tasks exist)
|
||||
|
||||
**Why it matters:**
|
||||
- Indicates project needs attention
|
||||
- Either needs new tasks, or should change status to "done"
|
||||
- Surfaced in Productivity Assistant feature
|
||||
|
||||
**How to fix:**
|
||||
1. Add new tasks to move project forward
|
||||
2. Change status to "done" if actually complete
|
||||
3. Change status to "waiting" or "cancelled" if appropriate
|
||||
|
||||
### Productivity Assistant
|
||||
|
||||
**Location:** Today page (if enabled in settings)
|
||||
|
||||
**Insights about projects:**
|
||||
- **Stalled Projects**: Lists projects that need tasks/actions
|
||||
- **Projects Near Deadline**: Due soon or overdue
|
||||
- **Vague Projects**: Projects with vague task descriptions
|
||||
|
||||
---
|
||||
|
||||
## Common Workflows
|
||||
|
||||
### Workflow 1: Start a New Project
|
||||
|
||||
**Scenario:** Beginning a new initiative
|
||||
|
||||
1. Navigate to `/projects`
|
||||
2. Click "New Project" button
|
||||
3. Fill in details:
|
||||
- Name: "Website Redesign"
|
||||
- Description: "Redesign company website for Q1 launch"
|
||||
- Area: Work
|
||||
- Status: Planned
|
||||
- Priority: High
|
||||
- Tags: #q1, #design
|
||||
4. Save project
|
||||
5. Add first task: "Research design trends"
|
||||
6. Change status to "In Progress" when ready to begin
|
||||
|
||||
### Workflow 2: Track Project Progress
|
||||
|
||||
**Scenario:** Monitoring ongoing project
|
||||
|
||||
1. Open project detail page
|
||||
2. Review completion percentage (e.g., 60%)
|
||||
3. Check task breakdown:
|
||||
- 6 done
|
||||
- 2 in progress
|
||||
- 2 not started
|
||||
4. Complete some tasks
|
||||
5. Completion percentage updates automatically
|
||||
6. When all tasks done, mark project status as "Done"
|
||||
|
||||
### Workflow 3: Share Project with Collaborator
|
||||
|
||||
**Scenario:** Working with team member
|
||||
|
||||
1. Open project "Client Onboarding"
|
||||
2. Click "Share" button
|
||||
3. Enter collaborator email: alice@example.com
|
||||
4. Select "Read-Write" access
|
||||
5. Save
|
||||
6. Alice receives notification
|
||||
7. Alice can now:
|
||||
- View all project tasks
|
||||
- Add new tasks
|
||||
- Complete tasks
|
||||
- Add notes
|
||||
8. Both see real-time updates
|
||||
|
||||
### Workflow 4: Organize with Areas
|
||||
|
||||
**Scenario:** High-level life organization
|
||||
|
||||
1. Create Areas:
|
||||
- Work
|
||||
- Personal
|
||||
- Health
|
||||
2. Assign projects to areas:
|
||||
- "Q1 Marketing" → Work
|
||||
- "Home Renovation" → Personal
|
||||
- "Exercise Routine" → Health
|
||||
3. View projects grouped by area
|
||||
4. Get high-level view of balance across life domains
|
||||
|
||||
### Workflow 5: Clean Up Completed Projects
|
||||
|
||||
**Scenario:** End of quarter cleanup
|
||||
|
||||
1. Navigate to `/projects?status=in_progress`
|
||||
2. Review each project:
|
||||
- If all tasks done → Change status to "Done"
|
||||
- If abandoned → Change status to "Cancelled"
|
||||
- If stalled → Add new tasks or change status
|
||||
3. Move completed projects out of active view
|
||||
4. Focus on truly active projects
|
||||
|
||||
---
|
||||
|
||||
## Project Display Rules
|
||||
|
||||
### Project Cards (List View)
|
||||
|
||||
**Information shown:**
|
||||
- Project name (bold, clickable)
|
||||
- Description (first 100 chars, truncated with "...")
|
||||
- Status badge (color-coded)
|
||||
- Priority dot (if set)
|
||||
- Completion percentage bar
|
||||
- Task count: "X of Y tasks done"
|
||||
- Area name (if assigned)
|
||||
- Tags (up to 3 shown, "+N more" if exceeded)
|
||||
- Last updated timestamp
|
||||
- Pin indicator (star icon)
|
||||
- Share indicator (user icon + count)
|
||||
|
||||
**Color coding:**
|
||||
- **Planned**: Purple badge
|
||||
- **Not Started**: Gray badge
|
||||
- **In Progress**: Blue badge
|
||||
- **Waiting**: Yellow badge
|
||||
- **Done**: Green badge
|
||||
- **Cancelled**: Red badge
|
||||
|
||||
### Project Detail Page
|
||||
|
||||
**Sections:**
|
||||
1. **Banner Image** (if set) - full-width header
|
||||
2. **Project Header**
|
||||
- Name (editable inline)
|
||||
- Status dropdown
|
||||
- Priority selector
|
||||
- Pin toggle
|
||||
- Share button
|
||||
3. **Metadata Row**
|
||||
- Area (linked)
|
||||
- Due date (if set)
|
||||
- Tags (editable)
|
||||
4. **Description** (expandable text area)
|
||||
5. **Progress Section**
|
||||
- Completion percentage bar
|
||||
- Task breakdown (done/in progress/not started)
|
||||
6. **Tasks Section**
|
||||
- Task list (sorted per project preference)
|
||||
- "Add Task" button
|
||||
- Show/hide completed toggle
|
||||
7. **Notes Section**
|
||||
- Note cards (most recent first)
|
||||
- "Add Note" button
|
||||
8. **Insights Panel** (if productivity assistant enabled)
|
||||
- Auto-suggested next actions
|
||||
- Stalled warning
|
||||
- Due date alerts
|
||||
|
||||
---
|
||||
|
||||
## Special Features
|
||||
|
||||
### 1. Auto-Suggest Next Action
|
||||
|
||||
**What it does:**
|
||||
- AI-powered suggestions for next steps
|
||||
- Analyzes project context, tasks, and notes
|
||||
- Suggests concrete actions to move project forward
|
||||
|
||||
**Appears when:**
|
||||
- Project has description and some tasks
|
||||
- User has AI features enabled
|
||||
- Accessed via "Suggest Next Action" button
|
||||
|
||||
**Example suggestions:**
|
||||
- "Schedule a meeting with the designer"
|
||||
- "Review the latest mockups"
|
||||
- "Get feedback from stakeholders"
|
||||
|
||||
### 2. Banner Images
|
||||
|
||||
**Purpose:**
|
||||
- Visual identity for projects
|
||||
- Makes projects more recognizable
|
||||
- Improves aesthetic appeal
|
||||
|
||||
**How to set:**
|
||||
1. Click "Edit Banner" on project detail page
|
||||
2. Upload image file (JPG, PNG)
|
||||
3. Image stored in `/api/uploads/projects/`
|
||||
4. Can replace or remove later
|
||||
|
||||
**Recommended:**
|
||||
- Use relevant imagery (website screenshot for web project, house for renovation)
|
||||
- High resolution (1200x400 or larger)
|
||||
- Landscape orientation
|
||||
|
||||
### 3. Task Sorting Preferences
|
||||
|
||||
**Per-project sorting:**
|
||||
- Each project can have its own task sort order
|
||||
- Doesn't affect other projects
|
||||
- Persisted across sessions
|
||||
|
||||
**Sort options:**
|
||||
- Created date (newest/oldest first)
|
||||
- Due date (soonest/latest first)
|
||||
- Priority (highest/lowest first)
|
||||
- Status (by progress)
|
||||
- Name (A-Z, Z-A)
|
||||
|
||||
**Use cases:**
|
||||
- Sprint project: Sort by priority
|
||||
- Research project: Sort by created date
|
||||
- Deadline-driven project: Sort by due date
|
||||
|
||||
### 4. Keyboard Shortcuts
|
||||
|
||||
**On project page:**
|
||||
- `n`: Create new task
|
||||
- `Shift+N`: Create new note
|
||||
- `e`: Edit project details
|
||||
- `p`: Pin/unpin project
|
||||
- `/`: Focus search
|
||||
|
||||
**Global shortcuts:**
|
||||
- `g` then `p`: Go to Projects page
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### "My tasks disappeared when I deleted the project"
|
||||
|
||||
**What happened:**
|
||||
- Tasks are not deleted, they're orphaned
|
||||
- They still exist in your database
|
||||
|
||||
**How to find:**
|
||||
1. Go to Tasks page
|
||||
2. Filter by "No Project"
|
||||
3. You'll see all orphaned tasks
|
||||
4. Re-assign to a different project if needed
|
||||
|
||||
### "Project shows 0% complete but I have completed tasks"
|
||||
|
||||
**Possible causes:**
|
||||
1. All completed items are subtasks (only parent tasks count)
|
||||
2. Completed items were soft-deleted
|
||||
3. Tasks belong to different project
|
||||
|
||||
**How to check:**
|
||||
1. Open project detail page
|
||||
2. Check task list - are completed tasks visible?
|
||||
3. Toggle "Show completed tasks" if hidden
|
||||
4. Verify tasks actually belong to this project
|
||||
|
||||
### "Shared project not appearing for collaborator"
|
||||
|
||||
**Checklist:**
|
||||
1. Did you use exact email address?
|
||||
2. Does user have tududi account with that email?
|
||||
3. Check share count - is it > 0?
|
||||
4. Have them refresh their projects list
|
||||
5. Check notifications - did they receive share notification?
|
||||
|
||||
### "Project marked as stalled but it has tasks"
|
||||
|
||||
**Why it's stalled:**
|
||||
- All tasks are marked "done"
|
||||
- Or all tasks are subtasks (parent tasks are all done)
|
||||
|
||||
**How to fix:**
|
||||
1. Add new tasks for next phase of work
|
||||
2. Or change project status to "done" if actually complete
|
||||
3. Or change status to "waiting" if blocked
|
||||
|
||||
### "Can't delete a project"
|
||||
|
||||
**Possible reasons:**
|
||||
1. You're not the owner (only owner can delete)
|
||||
2. Permission issue (check if you have `rw` or just `ro`)
|
||||
|
||||
**Alternative:**
|
||||
- If you can't delete, change status to "cancelled"
|
||||
- Unpin from sidebar
|
||||
- Filter it out of active views
|
||||
|
||||
---
|
||||
|
||||
## Related Documentation
|
||||
|
||||
- [Areas](07-areas.md) - Top-level organizational categories and project grouping
|
||||
- [Recurring Tasks Behavior](01-recurring-tasks-behavior.md) - How recurring tasks work within projects
|
||||
- [Today Page Sections](02-today-page-sections.md) - How project tasks appear on Today page
|
||||
- [Inbox Page](04-inbox-page.md) - How to create projects from inbox
|
||||
- [Architecture Overview](architecture.md) - Technical architecture
|
||||
- [Backend Patterns](backend-patterns.md) - Module structure
|
||||
- [Database & Migrations](database.md) - Data model details
|
||||
|
||||
**Technical Implementation Files:**
|
||||
- Project model: `/backend/models/project.js`
|
||||
- Area model: `/backend/models/area.js`
|
||||
- Projects service: `/backend/modules/projects/service.js`
|
||||
- Projects controller: `/backend/modules/projects/controller.js`
|
||||
- Projects repository: `/backend/modules/projects/repository.js`
|
||||
- Due project service: `/backend/modules/projects/dueProjectService.js`
|
||||
- Permissions service: `/backend/services/permissionsService.js`
|
||||
- Frontend components: `/frontend/components/Project/`
|
||||
- Project detail page: `/frontend/components/Project/ProjectDetails.tsx`
|
||||
- Project item card: `/frontend/components/Project/ProjectItem.tsx`
|
||||
- Project modal: `/frontend/components/Project/ProjectModal.tsx`
|
||||
- Share modal: `/frontend/components/Project/ProjectShareModal.tsx`
|
||||
|
||||
---
|
||||
|
||||
**Document Version:** 1.0.0
|
||||
**Last Updated:** 2026-03-14
|
||||
**Audience:** Developers, AI assistants, and end users
|
||||
763
docs/07-areas.md
Normal file
763
docs/07-areas.md
Normal file
|
|
@ -0,0 +1,763 @@
|
|||
# Areas - Behavior Rules
|
||||
|
||||
This document explains how areas work in tududi from a user behavior perspective. For technical implementation details, see the backend code in `/backend/modules/areas/` and frontend components in `/frontend/components/Area/`.
|
||||
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
**Areas** are the highest level of organization in tududi, representing major life domains or responsibility categories. They provide a way to group projects into meaningful top-level segments.
|
||||
|
||||
**Key characteristics:**
|
||||
- Represent broad life domains (Work, Personal, Health, Finance, etc.)
|
||||
- Sit at the top of the organizational hierarchy
|
||||
- Provide high-level grouping for projects
|
||||
- Simple structure with just name and description
|
||||
- User-specific (each user has their own areas)
|
||||
- Optional organizational layer (projects can exist without areas)
|
||||
|
||||
**Hierarchy Position:**
|
||||
```
|
||||
Areas (highest level - life domains)
|
||||
└── Projects (mid level - specific goals)
|
||||
└── Tasks (actionable items)
|
||||
└── Subtasks
|
||||
```
|
||||
|
||||
**URL:** `/areas`
|
||||
|
||||
---
|
||||
|
||||
## Core Principles
|
||||
|
||||
1. **Areas are top-level organizational containers**
|
||||
- They represent the broadest categories of your life and work
|
||||
- Examples: Work, Personal, Health, Finance, Learning, Home
|
||||
|
||||
2. **Areas are optional**
|
||||
- Projects can exist without belonging to an area
|
||||
- Areas provide structure but aren't required
|
||||
|
||||
3. **Areas don't cascade delete**
|
||||
- Deleting an area orphans its projects, doesn't delete them
|
||||
- This prevents accidental data loss
|
||||
- Orphaned projects remain accessible
|
||||
|
||||
4. **Areas are simple by design**
|
||||
- Just a name and optional description
|
||||
- No status, priority, or due dates
|
||||
- Focus is on categorization, not task management
|
||||
|
||||
5. **One project, one area**
|
||||
- A project can belong to at most one area
|
||||
- But an area can contain many projects
|
||||
|
||||
---
|
||||
|
||||
## Hierarchy
|
||||
|
||||
```
|
||||
Areas (highest level - life domains)
|
||||
└── Projects (mid level - specific goals/initiatives)
|
||||
├── Tasks (actionable items)
|
||||
└── Notes (reference material)
|
||||
```
|
||||
|
||||
**Example structure:**
|
||||
```
|
||||
Area: "Work"
|
||||
├── Project: "Q1 Marketing Campaign"
|
||||
│ ├── Task: "Design landing page"
|
||||
│ └── Task: "Write email copy"
|
||||
├── Project: "Website Redesign"
|
||||
│ └── Task: "Research design trends"
|
||||
└── Project: "Team Onboarding"
|
||||
|
||||
Area: "Personal"
|
||||
├── Project: "Home Renovation"
|
||||
│ ├── Task: "Get contractor quotes"
|
||||
│ └── Task: "Choose paint colors"
|
||||
└── Project: "Learn Spanish"
|
||||
└── Task: "Complete Duolingo lesson"
|
||||
|
||||
Area: "Health"
|
||||
└── Project: "Exercise Routine"
|
||||
├── Task: "Go for morning run"
|
||||
└── Task: "Meal prep for the week"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Area Properties
|
||||
|
||||
### Basic Information
|
||||
|
||||
1. **Name** (required)
|
||||
- The area title
|
||||
- Examples: "Work", "Personal", "Health", "Finance", "Learning"
|
||||
- Displayed in uppercase on area cards
|
||||
- Sorted alphabetically
|
||||
|
||||
2. **Description** (optional)
|
||||
- Longer explanation of what this area encompasses
|
||||
- Helps clarify the scope and purpose
|
||||
- Displayed on area card in smaller text
|
||||
- Example: "Work related projects and professional development"
|
||||
|
||||
3. **UID** (auto-generated)
|
||||
- Unique identifier for the area
|
||||
- Used in URLs and API calls
|
||||
- Cannot be changed
|
||||
|
||||
4. **User ID** (system-managed)
|
||||
- Links area to the user who created it
|
||||
- Areas are private to each user
|
||||
- Cannot be shared between users
|
||||
|
||||
---
|
||||
|
||||
## Area Lifecycle
|
||||
|
||||
### Creating an Area
|
||||
|
||||
**Ways to create:**
|
||||
1. Navigate to `/areas`
|
||||
2. Click "New Area" button (if implemented)
|
||||
3. Use the area modal to enter details
|
||||
|
||||
**Required fields:**
|
||||
- Name (must not be empty or just whitespace)
|
||||
|
||||
**Default values:**
|
||||
- Description: Empty string
|
||||
|
||||
**Auto-generated:**
|
||||
- UID (unique identifier)
|
||||
- User ID (current user)
|
||||
- Timestamps (created_at, updated_at)
|
||||
|
||||
**Example:**
|
||||
```
|
||||
Name: "Work"
|
||||
Description: "Professional projects, career development, and work-related tasks"
|
||||
```
|
||||
|
||||
### Editing an Area
|
||||
|
||||
**What you can edit:**
|
||||
- Name (required, cannot be empty)
|
||||
- Description (optional)
|
||||
|
||||
**What you cannot edit:**
|
||||
- UID
|
||||
- User ID
|
||||
- Created timestamp
|
||||
|
||||
**How to edit:**
|
||||
1. Navigate to `/areas`
|
||||
2. Hover over area card
|
||||
3. Click three-dot menu (appears on hover)
|
||||
4. Click "Edit"
|
||||
5. Modify fields in modal
|
||||
6. Click "Save" or "Update Area"
|
||||
|
||||
**Validation:**
|
||||
- Name cannot be empty
|
||||
- Name cannot be only whitespace
|
||||
- Whitespace is trimmed from name
|
||||
|
||||
### Deleting an Area
|
||||
|
||||
**What happens:**
|
||||
1. Area record is deleted from database
|
||||
2. **Projects belonging to area are orphaned** (area_id set to null)
|
||||
3. Projects are NOT deleted
|
||||
4. Tasks and notes within projects are unaffected
|
||||
|
||||
**What is NOT deleted:**
|
||||
- Projects (they become orphaned, with no area)
|
||||
- Tasks within projects
|
||||
- Notes within projects
|
||||
- Any data except the area itself
|
||||
|
||||
**How to delete:**
|
||||
1. Navigate to `/areas`
|
||||
2. Hover over area card
|
||||
3. Click three-dot menu
|
||||
4. Click "Delete"
|
||||
5. Confirm deletion in dialog
|
||||
|
||||
**Who can delete:**
|
||||
- Area owner only
|
||||
- Admin users (if admin functionality exists)
|
||||
|
||||
**No undo:**
|
||||
- Deletion is permanent for the area
|
||||
- But projects can be manually reassigned to a new area
|
||||
|
||||
**Finding orphaned projects after deletion:**
|
||||
1. Go to Projects page
|
||||
2. Filter by "No Area"
|
||||
3. Re-assign to a new area if needed
|
||||
|
||||
---
|
||||
|
||||
## Using Areas
|
||||
|
||||
### Viewing Areas
|
||||
|
||||
**Areas List Page:**
|
||||
- URL: `/areas`
|
||||
- Shows all areas for current user
|
||||
- Displayed as a responsive grid
|
||||
- Grid adapts to screen size:
|
||||
- Mobile: 1 column
|
||||
- Tablet: 2 columns
|
||||
- Desktop: 3 columns
|
||||
- Large desktop: 4 columns
|
||||
|
||||
**Area Cards:**
|
||||
Each card displays:
|
||||
- Area name (uppercase, centered, large font)
|
||||
- Description (if provided, smaller text, centered)
|
||||
- Three-dot menu (appears on hover)
|
||||
- Edit option
|
||||
- Delete option
|
||||
|
||||
**Card Layout:**
|
||||
- Fixed height (120px)
|
||||
- Centered content
|
||||
- Hover effect (slight opacity change)
|
||||
- Click card to view projects in that area
|
||||
|
||||
### Linking to Projects
|
||||
|
||||
**From area card:**
|
||||
- Clicking an area card navigates to: `/projects?area={uid}-{slug}`
|
||||
- This filters the Projects page to show only projects in that area
|
||||
- Example: `/projects?area=abc123-work`
|
||||
|
||||
**Slug generation:**
|
||||
- Area name converted to lowercase
|
||||
- Non-alphanumeric characters replaced with hyphens
|
||||
- Leading/trailing hyphens removed
|
||||
- Example: "My Work Area" → "my-work-area"
|
||||
|
||||
**From area detail page:**
|
||||
- Displays link: "View projects in {area name}"
|
||||
- Clicking navigates to filtered projects view
|
||||
|
||||
### Grouping Projects by Area
|
||||
|
||||
**On Projects page:**
|
||||
- Add query parameter: `?grouped=true`
|
||||
- Projects grouped under their area names
|
||||
- Special "No Area" group for orphaned projects
|
||||
|
||||
**Example grouped view:**
|
||||
```
|
||||
Work
|
||||
├── Q1 Marketing Campaign (75% complete)
|
||||
├── Website Redesign (30% complete)
|
||||
└── Client Onboarding (done)
|
||||
|
||||
Personal
|
||||
├── Home Renovation (in progress)
|
||||
└── Learn Spanish (planned)
|
||||
|
||||
No Area
|
||||
└── Random Ideas (not started)
|
||||
```
|
||||
|
||||
**Benefits:**
|
||||
- High-level overview of work distribution
|
||||
- See balance across life domains
|
||||
- Identify areas with too many/few projects
|
||||
|
||||
---
|
||||
|
||||
## Display Rules
|
||||
|
||||
### Area Cards (Grid View)
|
||||
|
||||
**Information shown:**
|
||||
- Area name (bold, uppercase, 18px)
|
||||
- Description (if exists, 12px, gray text)
|
||||
- Three-dot menu (visible on hover)
|
||||
|
||||
**Visual design:**
|
||||
- Light background: `bg-gray-50` (light mode)
|
||||
- Dark background: `bg-gray-900` (dark mode)
|
||||
- Rounded corners with shadow
|
||||
- Fixed height: 120px
|
||||
- Centered text alignment
|
||||
- Hover: Slight opacity reduction (90%)
|
||||
|
||||
**Interaction:**
|
||||
- Click anywhere on card → Navigate to projects filtered by area
|
||||
- Click three-dot menu → Show edit/delete options
|
||||
- Hover card → Show three-dot menu
|
||||
|
||||
**Sorting:**
|
||||
- Areas always sorted alphabetically by name (A-Z)
|
||||
- Case-insensitive sorting
|
||||
- Consistent across all views
|
||||
|
||||
### Empty State
|
||||
|
||||
**When no areas exist:**
|
||||
- Shows message: "No areas found" (translated)
|
||||
- Prompts user to create their first area
|
||||
|
||||
---
|
||||
|
||||
## Area-Project Relationship
|
||||
|
||||
### Assigning Projects to Areas
|
||||
|
||||
**Ways to assign:**
|
||||
1. **During project creation:**
|
||||
- Select area from dropdown in project modal
|
||||
- Area dropdown shows all user's areas alphabetically
|
||||
|
||||
2. **When editing existing project:**
|
||||
- Open project detail or edit modal
|
||||
- Change area in dropdown
|
||||
- Can set to "No Area" to orphan project
|
||||
|
||||
3. **Bulk operations (if implemented):**
|
||||
- Select multiple projects
|
||||
- Assign to area in bulk
|
||||
|
||||
**Project can have:**
|
||||
- One area (normal case)
|
||||
- No area (orphaned - still valid)
|
||||
- Cannot have multiple areas
|
||||
|
||||
### Area Display on Projects
|
||||
|
||||
**On project cards:**
|
||||
- Area name shown as a label/tag
|
||||
- Usually displayed below project name
|
||||
- Clickable link to filter by area
|
||||
|
||||
**On project detail page:**
|
||||
- Area name displayed in metadata section
|
||||
- Linked to area's projects list
|
||||
- Can be changed inline (if editable)
|
||||
|
||||
**On project forms:**
|
||||
- Dropdown selector for area
|
||||
- Includes "No Area" option
|
||||
- Sorted alphabetically
|
||||
|
||||
### Orphaned Projects
|
||||
|
||||
**What are orphaned projects:**
|
||||
- Projects with no area assigned (`area_id = null`)
|
||||
- Created without an area, or area was deleted
|
||||
- Perfectly valid state
|
||||
|
||||
**How to find:**
|
||||
1. Navigate to Projects page
|
||||
2. Filter by "No Area"
|
||||
3. Or use grouped view - they appear in "No Area" section
|
||||
|
||||
**How to fix (if desired):**
|
||||
1. Open orphaned project
|
||||
2. Edit project details
|
||||
3. Select an area from dropdown
|
||||
4. Save changes
|
||||
|
||||
**Not a problem:**
|
||||
- Areas are optional organizational tools
|
||||
- Projects work perfectly fine without areas
|
||||
- Some users prefer not to use areas at all
|
||||
|
||||
---
|
||||
|
||||
## Common Workflows
|
||||
|
||||
### Workflow 1: Set Up Life Domains
|
||||
|
||||
**Scenario:** Initial organization of your life
|
||||
|
||||
1. Navigate to `/areas`
|
||||
2. Create areas for major life domains:
|
||||
- Work
|
||||
- Personal
|
||||
- Health
|
||||
- Finance
|
||||
- Learning
|
||||
- Home
|
||||
3. Add descriptions to clarify scope:
|
||||
- Work: "Professional projects and career development"
|
||||
- Personal: "Personal goals and hobbies"
|
||||
- Health: "Fitness, nutrition, and wellness"
|
||||
4. Assign existing projects to appropriate areas
|
||||
5. Review grouped projects view for balance
|
||||
|
||||
### Workflow 2: Organize Projects into Areas
|
||||
|
||||
**Scenario:** You have many unorganized projects
|
||||
|
||||
1. Go to Projects page
|
||||
2. Filter by "No Area" to see orphaned projects
|
||||
3. For each project:
|
||||
- Open project detail
|
||||
- Consider its nature (work, personal, etc.)
|
||||
- Assign to appropriate area
|
||||
4. Use grouped view to verify organization
|
||||
5. Adjust as needed
|
||||
|
||||
### Workflow 3: Focus on Specific Life Domain
|
||||
|
||||
**Scenario:** You want to focus on work projects only
|
||||
|
||||
1. Navigate to `/areas`
|
||||
2. Click on "Work" area card
|
||||
3. See only work-related projects
|
||||
4. Review active projects in work domain
|
||||
5. Identify stalled projects
|
||||
6. Plan next actions
|
||||
|
||||
### Workflow 4: Review Life Balance
|
||||
|
||||
**Scenario:** Check if you're balanced across domains
|
||||
|
||||
1. Navigate to `/projects?grouped=true`
|
||||
2. See projects grouped by area
|
||||
3. Count projects in each area
|
||||
4. Identify areas with:
|
||||
- Too many projects (overcommitted)
|
||||
- Too few projects (neglected domain)
|
||||
- All completed projects (ready for new initiatives)
|
||||
5. Make adjustments to achieve balance
|
||||
|
||||
### Workflow 5: Reorganize Life Structure
|
||||
|
||||
**Scenario:** Your life structure has changed
|
||||
|
||||
1. Navigate to `/areas`
|
||||
2. Edit area names/descriptions to reflect new reality
|
||||
3. Consider creating new areas:
|
||||
- New job → New work area or split areas
|
||||
- New hobby → Personal or new Learning area
|
||||
4. Delete obsolete areas (projects become orphaned)
|
||||
5. Re-assign orphaned projects to new structure
|
||||
6. Review and refine
|
||||
|
||||
---
|
||||
|
||||
## Integration with Other Features
|
||||
|
||||
### Areas and Projects Page
|
||||
|
||||
**Filtering by area:**
|
||||
- URL: `/projects?area={uid}-{slug}`
|
||||
- Shows only projects in that area
|
||||
- Breadcrumb or header shows current area filter
|
||||
- Can clear filter to see all projects
|
||||
|
||||
**Grouping by area:**
|
||||
- URL: `/projects?grouped=true`
|
||||
- Projects organized under area headings
|
||||
- Collapsible sections (if implemented)
|
||||
- Shows "No Area" group for orphaned projects
|
||||
|
||||
### Areas and Project Detail Page
|
||||
|
||||
**Area shown on project:**
|
||||
- Displayed in metadata section
|
||||
- Linked to area's projects list
|
||||
- Can edit to change or remove area (if permissions allow)
|
||||
|
||||
### Areas and Navigation
|
||||
|
||||
**Sidebar (if areas shown):**
|
||||
- May show top areas for quick access
|
||||
- Click to navigate to area's projects
|
||||
- Usually shows 3-5 most used areas
|
||||
|
||||
**Quick filters:**
|
||||
- Projects page may have area pills/tags
|
||||
- Click to toggle area filter
|
||||
- Multiple areas can be selected (OR logic)
|
||||
|
||||
---
|
||||
|
||||
## Best Practices
|
||||
|
||||
### Naming Areas
|
||||
|
||||
**Good area names:**
|
||||
- Short and clear: "Work", "Personal", "Health"
|
||||
- Broad categories, not specific projects
|
||||
- Parallel structure: All nouns or all adjectives
|
||||
- Examples: "Work", "Home", "Health", "Finance"
|
||||
|
||||
**Avoid:**
|
||||
- Overly specific: "Q1 Marketing" (that's a project)
|
||||
- Too many areas (diminishes organizational value)
|
||||
- Overlapping categories: "Work" and "Career" (redundant)
|
||||
- Vague names: "Stuff", "Things", "Other"
|
||||
|
||||
### Structuring Your Areas
|
||||
|
||||
**Recommended approach:**
|
||||
- Start with 4-7 major areas
|
||||
- Based on life domains, not task types
|
||||
- Examples:
|
||||
- Professional: Work, Business
|
||||
- Personal: Personal, Family, Social
|
||||
- Self-improvement: Health, Learning
|
||||
- Maintenance: Home, Finance
|
||||
|
||||
**Too many areas:**
|
||||
- Defeats the purpose of high-level organization
|
||||
- Hard to remember and maintain
|
||||
- Projects get scattered
|
||||
- Consider: Do you really need that area?
|
||||
|
||||
**Too few areas:**
|
||||
- Everything in "Work" and "Personal"
|
||||
- Loses organizational granularity
|
||||
- Consider: Are you neglecting important life domains?
|
||||
|
||||
### Using Descriptions
|
||||
|
||||
**Good descriptions:**
|
||||
- Clarify the scope of the area
|
||||
- Help with project assignment decisions
|
||||
- Examples:
|
||||
- "Work": "Professional projects, career development, and work relationships"
|
||||
- "Health": "Physical fitness, nutrition, mental wellness, and medical care"
|
||||
- "Learning": "Online courses, reading, language learning, and skill development"
|
||||
|
||||
**When to skip descriptions:**
|
||||
- Area name is self-explanatory ("Personal", "Work")
|
||||
- You're the only user and know what it means
|
||||
|
||||
### Maintaining Your Areas
|
||||
|
||||
**Regular review:**
|
||||
- Every 3-6 months, review your areas
|
||||
- Are they still relevant to your life?
|
||||
- Do you need to add/remove/rename areas?
|
||||
- Are projects correctly categorized?
|
||||
|
||||
**When life changes:**
|
||||
- New job → Adjust work areas
|
||||
- New responsibility → Add new area
|
||||
- Completed major goal → Remove or repurpose area
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### "My projects disappeared when I deleted the area"
|
||||
|
||||
**What happened:**
|
||||
- Projects are not deleted, they're orphaned
|
||||
- They still exist in your database
|
||||
|
||||
**How to find:**
|
||||
1. Go to Projects page
|
||||
2. Filter by "No Area"
|
||||
3. You'll see all orphaned projects
|
||||
4. Re-assign to a new area if needed
|
||||
|
||||
### "I can't see my area in the projects dropdown"
|
||||
|
||||
**Possible causes:**
|
||||
1. Area belongs to different user (not shared)
|
||||
2. Area was deleted
|
||||
3. Frontend cache issue
|
||||
|
||||
**How to fix:**
|
||||
1. Refresh the page
|
||||
2. Check `/areas` page to confirm area exists
|
||||
3. If missing, recreate the area
|
||||
|
||||
### "Area cards not showing in grid"
|
||||
|
||||
**Possible causes:**
|
||||
1. No areas created yet
|
||||
2. Loading state
|
||||
3. API error
|
||||
|
||||
**How to check:**
|
||||
1. Wait for loading to complete
|
||||
2. Check browser console for errors
|
||||
3. Verify `/api/areas` endpoint returns data
|
||||
4. Create first area if none exist
|
||||
|
||||
### "Projects grouped view not working"
|
||||
|
||||
**Checklist:**
|
||||
1. Is `?grouped=true` in URL?
|
||||
2. Do projects have `area_id` set?
|
||||
3. Are areas loaded in global state?
|
||||
4. Check browser console for errors
|
||||
|
||||
### "Can't delete an area"
|
||||
|
||||
**Possible reasons:**
|
||||
1. You're not the owner (areas can't be shared)
|
||||
2. Network error
|
||||
3. Permission issue
|
||||
|
||||
**Alternative:**
|
||||
- If you can't delete, just don't use it
|
||||
- Remove all projects from the area
|
||||
- It won't show up in grouped views
|
||||
|
||||
---
|
||||
|
||||
## Use Cases
|
||||
|
||||
### 1. **Life-Work Balance Monitoring**
|
||||
|
||||
Areas help you see if you're:
|
||||
- Overcommitting in work area
|
||||
- Neglecting personal projects
|
||||
- Ignoring health/fitness
|
||||
- Balancing across all domains
|
||||
|
||||
**Action:** Review grouped projects view monthly
|
||||
|
||||
### 2. **Context Switching**
|
||||
|
||||
When switching contexts (work → personal):
|
||||
- Click area card to see relevant projects
|
||||
- Focus on that domain exclusively
|
||||
- Avoid distraction from other areas
|
||||
|
||||
**Action:** Use area filters during focused work sessions
|
||||
|
||||
### 3. **Goal Setting Across Life Domains**
|
||||
|
||||
Ensure you have:
|
||||
- Active projects in each important area
|
||||
- Balance between maintenance and growth
|
||||
- Projects in neglected domains
|
||||
|
||||
**Action:** Set quarterly goals per area
|
||||
|
||||
### 4. **Delegation and Collaboration**
|
||||
|
||||
Though areas themselves aren't shared:
|
||||
- Projects within areas can be shared
|
||||
- Use areas to organize shared vs. personal work
|
||||
- Example: "Work" area has shared team projects
|
||||
|
||||
**Action:** Keep team projects in shared areas
|
||||
|
||||
### 5. **Year-End Review**
|
||||
|
||||
At year end, review each area:
|
||||
- How many projects completed?
|
||||
- Which areas were neglected?
|
||||
- Where did you make most progress?
|
||||
- What needs attention next year?
|
||||
|
||||
**Action:** Annual area-by-area retrospective
|
||||
|
||||
---
|
||||
|
||||
## Technical Notes
|
||||
|
||||
### Data Model
|
||||
|
||||
**Database table:** `areas`
|
||||
|
||||
**Columns:**
|
||||
- `id` (integer, primary key, auto-increment)
|
||||
- `uid` (string, unique, auto-generated)
|
||||
- `name` (string, required)
|
||||
- `description` (string, optional)
|
||||
- `user_id` (integer, foreign key to users table)
|
||||
- `created_at` (timestamp)
|
||||
- `updated_at` (timestamp)
|
||||
|
||||
**Indexes:**
|
||||
- Primary key on `id`
|
||||
- Unique index on `uid`
|
||||
- Index on `user_id` (for fast user-based queries)
|
||||
|
||||
### API Endpoints
|
||||
|
||||
**GET /api/areas**
|
||||
- List all areas for current user
|
||||
- Sorted alphabetically by name
|
||||
- Returns: Array of area objects
|
||||
|
||||
**GET /api/areas/:uid**
|
||||
- Get single area by UID
|
||||
- Returns: Area object
|
||||
|
||||
**POST /api/areas**
|
||||
- Create new area
|
||||
- Body: `{ name, description }`
|
||||
- Returns: Created area object (201)
|
||||
|
||||
**PATCH /api/areas/:uid**
|
||||
- Update existing area
|
||||
- Body: `{ name?, description? }`
|
||||
- Returns: Updated area object
|
||||
|
||||
**DELETE /api/areas/:uid**
|
||||
- Delete area (orphans projects)
|
||||
- Returns: 204 No Content
|
||||
|
||||
**Authentication:**
|
||||
- All endpoints require authentication
|
||||
- 401 if not authenticated
|
||||
|
||||
### Validation Rules
|
||||
|
||||
**Name validation:**
|
||||
- Required (cannot be null or undefined)
|
||||
- Cannot be empty string
|
||||
- Cannot be only whitespace
|
||||
- Whitespace trimmed before saving
|
||||
|
||||
**Description validation:**
|
||||
- Optional
|
||||
- Can be empty string or null
|
||||
- Stored as empty string if not provided
|
||||
|
||||
**UID validation:**
|
||||
- Must be valid string format
|
||||
- Checked when getting/updating/deleting
|
||||
|
||||
---
|
||||
|
||||
## Related Documentation
|
||||
|
||||
- [Projects Behavior](06-projects.md) - How areas relate to projects
|
||||
- [Today Page Sections](02-today-page-sections.md) - How area filtering affects Today view
|
||||
- [Architecture Overview](architecture.md) - Technical architecture
|
||||
- [Backend Patterns](backend-patterns.md) - Module structure
|
||||
- [Database & Migrations](database.md) - Data model details
|
||||
- [Directory Structure](directory-structure.md) - File locations
|
||||
|
||||
**Technical Implementation Files:**
|
||||
- Area model: [/backend/models/area.js](../backend/models/area.js)
|
||||
- Areas service: [/backend/modules/areas/service.js](../backend/modules/areas/service.js)
|
||||
- Areas controller: [/backend/modules/areas/controller.js](../backend/modules/areas/controller.js)
|
||||
- Areas repository: [/backend/modules/areas/repository.js](../backend/modules/areas/repository.js)
|
||||
- Areas routes: [/backend/modules/areas/routes.js](../backend/modules/areas/routes.js)
|
||||
- Areas validation: [/backend/modules/areas/validation.js](../backend/modules/areas/validation.js)
|
||||
- Frontend components: [/frontend/components/Area/](../frontend/components/Area/)
|
||||
- Areas list page: [/frontend/components/Areas.tsx](../frontend/components/Areas.tsx)
|
||||
- Area detail page: [/frontend/components/Area/AreaDetails.tsx](../frontend/components/Area/AreaDetails.tsx)
|
||||
- Area modal: [/frontend/components/Area/AreaModal.tsx](../frontend/components/Area/AreaModal.tsx)
|
||||
- Areas API client: [/frontend/utils/areasService.ts](../frontend/utils/areasService.ts)
|
||||
- Integration tests: [/backend/tests/integration/areas.test.js](../backend/tests/integration/areas.test.js)
|
||||
|
||||
---
|
||||
|
||||
**Document Version:** 1.0.0
|
||||
**Last Updated:** 2026-03-14
|
||||
**Audience:** Developers, AI assistants, and end users
|
||||
391
docs/08-user-management.md
Normal file
391
docs/08-user-management.md
Normal file
|
|
@ -0,0 +1,391 @@
|
|||
# User Management - Behavior Rules
|
||||
|
||||
This document explains how user management works in tududi from a user behavior perspective. For technical implementation details, see the backend code in `/backend/modules/users/`, `/backend/modules/auth/`, and `/backend/modules/admin/`.
|
||||
|
||||
---
|
||||
|
||||
## **Registration & Onboarding**
|
||||
|
||||
### Registration Flow
|
||||
|
||||
1. **Registration is controlled by admins**
|
||||
- By default, registration is disabled
|
||||
- Admins can toggle registration on/off via the Admin panel
|
||||
- When disabled, only admins can create new user accounts
|
||||
|
||||
2. **Email verification is required**
|
||||
- When a user registers, they receive a verification email
|
||||
- The email contains a unique link that expires in 24 hours (configurable)
|
||||
- Users cannot log in until they verify their email address
|
||||
- If email service is disabled, users must be verified manually by an admin
|
||||
|
||||
3. **The first user becomes an admin automatically**
|
||||
- When no admin users exist in the system, the first user to register becomes an admin
|
||||
- This ensures someone can manage the system after initial setup
|
||||
- All subsequent users are created as regular users by default
|
||||
|
||||
4. **Registration validation rules:**
|
||||
- Email must be valid format and unique
|
||||
- Password must be at least 6 characters long
|
||||
- Email is automatically normalized (trimmed and lowercased)
|
||||
|
||||
---
|
||||
|
||||
## **Authentication**
|
||||
|
||||
### Login
|
||||
|
||||
5. **Users log in with email and password**
|
||||
- Email verification must be completed before login
|
||||
- Attempting to log in with an unverified email returns a specific error
|
||||
- Invalid credentials return a generic "Invalid credentials" error (security best practice)
|
||||
|
||||
6. **Session-based authentication**
|
||||
- After successful login, a session is created and stored in a cookie
|
||||
- Sessions persist until logout or session expiry
|
||||
- Users can be logged in across multiple devices/browsers simultaneously
|
||||
|
||||
7. **API token authentication**
|
||||
- Users can create personal API tokens for programmatic access
|
||||
- Tokens are prefixed with `tt_` and are 64 characters long
|
||||
- Tokens can have optional expiration dates
|
||||
- Multiple tokens can be active simultaneously
|
||||
- Tokens can be revoked or deleted at any time
|
||||
|
||||
### Logout
|
||||
|
||||
8. **Logout destroys the session**
|
||||
- The session is removed from the server
|
||||
- The user must log in again to access the system
|
||||
|
||||
---
|
||||
|
||||
## **User Roles & Permissions**
|
||||
|
||||
### Role System
|
||||
|
||||
9. **Two role types exist: Admin and User**
|
||||
- **Admin:** Full system access, can manage users, toggle registration, access admin panel
|
||||
- **User:** Standard access to their own data and shared resources
|
||||
|
||||
10. **Role assignment:**
|
||||
- First user is automatically assigned admin role
|
||||
- Admins can promote/demote other users to/from admin
|
||||
- Every user has exactly one role record
|
||||
- Roles are created automatically when a user account is created
|
||||
|
||||
11. **Admin capabilities:**
|
||||
- Create, update, and delete user accounts
|
||||
- Promote/demote users to/from admin role
|
||||
- Toggle registration on/off
|
||||
- Cannot delete their own account (prevents lockout)
|
||||
|
||||
---
|
||||
|
||||
## **Resource Permissions**
|
||||
|
||||
### Sharing & Access Control
|
||||
|
||||
12. **Resources can be owned or shared**
|
||||
- Users own resources they create (projects, tasks, notes)
|
||||
- Owners have full read-write access to their resources
|
||||
- Resources can be shared with other users with specific access levels
|
||||
|
||||
13. **Access levels:**
|
||||
- **none:** No access
|
||||
- **ro (read-only):** Can view but not modify
|
||||
- **rw (read-write):** Can view and modify
|
||||
- **admin:** Full control (owners and admins have this level)
|
||||
|
||||
14. **Hierarchical permission inheritance:**
|
||||
- Tasks inherit permissions from their parent project
|
||||
- Notes inherit permissions from their parent project
|
||||
- If a user has access to a project, they have the same access to its tasks and notes
|
||||
|
||||
15. **Admins bypass permission checks**
|
||||
- Users with admin role have admin-level access to all resources
|
||||
- This enables admins to help users with issues or perform system maintenance
|
||||
|
||||
---
|
||||
|
||||
## **User Profile Management**
|
||||
|
||||
### Profile Information
|
||||
|
||||
16. **Users can update their profile details:**
|
||||
- Name and surname (optional)
|
||||
- Email (must remain unique)
|
||||
- Password (requires current password confirmation)
|
||||
- Avatar image (upload/delete)
|
||||
|
||||
17. **User preferences stored in profile:**
|
||||
- **Appearance:** Light or dark theme
|
||||
- **Language:** One of 24 supported languages
|
||||
- **Timezone:** User's timezone for date/time display
|
||||
- **First day of week:** 0 (Sunday) to 6 (Saturday)
|
||||
|
||||
18. **Feature toggles:**
|
||||
- Task intelligence enabled/disabled
|
||||
- Auto-suggest next actions enabled/disabled
|
||||
- Pomodoro timer enabled/disabled
|
||||
- Productivity assistant enabled/disabled
|
||||
- Next task suggestion enabled/disabled
|
||||
|
||||
19. **Telegram integration settings:**
|
||||
- Bot token for personal Telegram bot
|
||||
- Chat ID for receiving messages
|
||||
- Allowed users list (comma-separated usernames/IDs)
|
||||
- Task summary enabled/disabled
|
||||
- Task summary frequency (daily, weekdays, weekly, hourly intervals)
|
||||
|
||||
20. **Notification preferences:**
|
||||
- Configure per notification type (due tasks, overdue tasks, due projects, etc.)
|
||||
- Configure per channel (in-app, email, push, Telegram)
|
||||
- Stored as JSON with defaults for new users
|
||||
|
||||
21. **UI settings:**
|
||||
- Today page settings (show/hide sections, metrics, suggestions)
|
||||
- Sidebar settings (pinned views order)
|
||||
- Project detail settings (show/hide metrics)
|
||||
- Keyboard shortcuts (custom mappings)
|
||||
|
||||
---
|
||||
|
||||
## **Password Management**
|
||||
|
||||
### Changing Password
|
||||
|
||||
22. **Password change requires current password**
|
||||
- User must provide their current password
|
||||
- New password must be at least 6 characters
|
||||
- Prevents unauthorized password changes if session is compromised
|
||||
|
||||
23. **Password storage is secure**
|
||||
- Passwords are hashed using bcrypt (10 rounds)
|
||||
- Original passwords are never stored
|
||||
- Password field is virtual in the model (not persisted)
|
||||
- Only `password_digest` is stored in the database
|
||||
|
||||
---
|
||||
|
||||
## **Avatar Management**
|
||||
|
||||
### Upload & Delete
|
||||
|
||||
24. **Users can upload a profile avatar image**
|
||||
- Uploaded files are stored in `/uploads/avatars/`
|
||||
- Avatar URL is stored in user profile
|
||||
- Uploading a new avatar replaces the old one (old file is deleted)
|
||||
|
||||
25. **Deleting avatar:**
|
||||
- Removes the avatar file from the server
|
||||
- Sets avatar URL to null in the profile
|
||||
- User displays with default avatar after deletion
|
||||
|
||||
---
|
||||
|
||||
## **API Tokens (Personal Access Tokens)**
|
||||
|
||||
### Token Management
|
||||
|
||||
26. **Users can create multiple API tokens**
|
||||
- Each token has a name/label for identification
|
||||
- Tokens are displayed with a prefix (first 12 characters) for identification
|
||||
- Full token value is only shown once upon creation
|
||||
- Tokens are hashed before storage (bcrypt, 12 rounds)
|
||||
|
||||
27. **Token properties:**
|
||||
- **Name:** User-defined label for the token
|
||||
- **Token prefix:** First 12 characters for identification (e.g., `tt_ab12cd34`)
|
||||
- **Created at:** When the token was created
|
||||
- **Last used at:** When the token was last used for authentication
|
||||
- **Expires at:** Optional expiration date (null = never expires)
|
||||
- **Revoked at:** When the token was revoked (null = active)
|
||||
|
||||
28. **Token operations:**
|
||||
- **Create:** Generates new token, returns full value once
|
||||
- **List:** Shows all tokens with metadata (not the full value)
|
||||
- **Revoke:** Marks token as revoked (soft delete, keeps history)
|
||||
- **Delete:** Permanently removes token from database
|
||||
|
||||
29. **Token authentication:**
|
||||
- Tokens are used with `Authorization: Bearer tt_...` header
|
||||
- System finds tokens by prefix, then validates hash
|
||||
- Expired or revoked tokens are rejected
|
||||
- Last used timestamp is updated on successful authentication
|
||||
|
||||
---
|
||||
|
||||
## **Admin User Management**
|
||||
|
||||
### User CRUD Operations
|
||||
|
||||
30. **Admins can create new users directly**
|
||||
- Bypasses registration flow and email verification
|
||||
- Created users can log in immediately
|
||||
- Requires: email, password
|
||||
- Optional: name, surname, role (admin or user)
|
||||
|
||||
31. **Admins can list all users**
|
||||
- Shows email, name, surname, role, creation date
|
||||
- Includes role information (admin or user)
|
||||
|
||||
32. **Admins can update any user's details**
|
||||
- Can change: email, password, name, surname, role
|
||||
- Email must remain unique across all users
|
||||
- Password change doesn't require current password (admin privilege)
|
||||
|
||||
33. **Admins can delete users**
|
||||
- Cannot delete their own account (prevents lockout)
|
||||
- Deleting a user also deletes their data:
|
||||
- Tasks are deleted (cascades to subtasks, attachments, etc.)
|
||||
- Projects are deleted (cascades to tasks within)
|
||||
- Notes are deleted
|
||||
- Permissions granted by/to the user are removed
|
||||
- API tokens are deleted
|
||||
- Shared resources are unshared
|
||||
|
||||
34. **Admin bootstrapping:**
|
||||
- When no admin roles exist, the system is in "bootstrap mode"
|
||||
- In bootstrap mode, any authenticated user can set admin roles
|
||||
- After at least one admin exists, only admins can manage roles
|
||||
|
||||
---
|
||||
|
||||
## **Settings & Preferences**
|
||||
|
||||
### Today Page Settings
|
||||
|
||||
35. **Today page is highly customizable:**
|
||||
- Show/hide metrics panel
|
||||
- Show/hide productivity assistant
|
||||
- Show/hide next task suggestion
|
||||
- Show/hide AI suggestions section
|
||||
- Show/hide tasks due today
|
||||
- Show/hide completed tasks
|
||||
- Show/hide progress bar
|
||||
- Show/hide daily quote
|
||||
|
||||
36. **Settings are stored per user:**
|
||||
- Defaults are applied for new users
|
||||
- Changes are saved immediately
|
||||
- Settings sync across devices/sessions
|
||||
|
||||
### Sidebar Settings
|
||||
|
||||
37. **Sidebar view pinning:**
|
||||
- Users can pin saved views to the sidebar
|
||||
- Pinned views can be reordered
|
||||
- Order is stored in `sidebar_settings.pinnedViewsOrder` array
|
||||
|
||||
### Task Summary Settings
|
||||
|
||||
38. **Telegram task summaries can be scheduled:**
|
||||
- Enable/disable toggle
|
||||
- Frequency options: daily, weekdays, weekly, 1h, 2h, 4h, 8h, 12h
|
||||
- Last run and next run timestamps are tracked
|
||||
- "Send now" option for immediate summary
|
||||
|
||||
---
|
||||
|
||||
## **User Lifecycle**
|
||||
|
||||
### Account Creation to Deletion
|
||||
|
||||
39. **User creation flow:**
|
||||
```
|
||||
Registration → Email Verification → First Login → Profile Setup → Active User
|
||||
```
|
||||
- Or: Admin creates user → Active user (no verification needed)
|
||||
|
||||
40. **User deletion flow:**
|
||||
```
|
||||
Admin deletes user → Cascade delete resources → Remove permissions → Remove sessions
|
||||
```
|
||||
- User cannot log in after deletion
|
||||
- All owned data is removed
|
||||
- Shared access is revoked
|
||||
|
||||
---
|
||||
|
||||
## **Security Considerations**
|
||||
|
||||
### Password Security
|
||||
|
||||
41. **Passwords are protected:**
|
||||
- Hashed with bcrypt (10 rounds for user passwords, 12 for tokens)
|
||||
- Never transmitted in API responses
|
||||
- Virtual field prevents accidental persistence
|
||||
|
||||
42. **Email normalization:**
|
||||
- Emails are trimmed and lowercased before storage
|
||||
- Prevents duplicate accounts with different casing
|
||||
|
||||
### Session Security
|
||||
|
||||
43. **Session management:**
|
||||
- Sessions are stored server-side
|
||||
- Session cookies are HTTP-only (prevents XSS)
|
||||
- Sessions expire after inactivity
|
||||
- Logout properly destroys sessions
|
||||
|
||||
### API Token Security
|
||||
|
||||
44. **Token security:**
|
||||
- Tokens are cryptographically random (32 bytes = 256 bits)
|
||||
- Tokens are prefixed (`tt_`) for easy identification
|
||||
- Tokens are hashed before storage (bcrypt, 12 rounds)
|
||||
- Expired and revoked tokens are rejected
|
||||
|
||||
---
|
||||
|
||||
## **Key Concepts**
|
||||
|
||||
### User Identity
|
||||
|
||||
A user account is identified by:
|
||||
- **ID:** Internal database ID (integer)
|
||||
- **UID:** External unique identifier (string, used in URLs)
|
||||
- **Email:** Unique, normalized email address
|
||||
|
||||
### Role Record
|
||||
|
||||
Every user has exactly one role record that determines admin status. Created automatically when the user account is created.
|
||||
|
||||
### Permission Record
|
||||
|
||||
Grants access to a specific resource (project, task, note) with a specific access level (ro, rw). Multiple permission records enable sharing resources across users.
|
||||
|
||||
### API Token
|
||||
|
||||
A personal access token that enables programmatic API access. Tokens are long-lived credentials that should be treated like passwords.
|
||||
|
||||
### Bootstrap Mode
|
||||
|
||||
Special state when no admin users exist. Allows the first authenticated user to set admin roles, preventing system lockout after initial setup.
|
||||
|
||||
---
|
||||
|
||||
## **Related Documentation**
|
||||
|
||||
- [Architecture Overview](architecture.md) - System architecture
|
||||
- [Backend Patterns](backend-patterns.md) - Module structure
|
||||
- [Database & Migrations](database.md) - Data model details
|
||||
- [Projects](06-projects.md) - Project sharing and permissions
|
||||
|
||||
**Technical Implementation Files:**
|
||||
- User model: `/backend/models/user.js`
|
||||
- Role model: `/backend/models/role.js`
|
||||
- Permission model: `/backend/models/permission.js`
|
||||
- User service: `/backend/modules/users/service.js`
|
||||
- Auth service: `/backend/modules/auth/service.js`
|
||||
- Admin service: `/backend/modules/admin/service.js`
|
||||
- Permissions service: `/backend/services/permissionsService.js`
|
||||
- Registration service: `/backend/modules/auth/registrationService.js`
|
||||
- API token service: `/backend/modules/users/apiTokenService.js`
|
||||
|
||||
---
|
||||
|
||||
**Document Version:** 1.0.0
|
||||
**Last Updated:** 2026-03-15
|
||||
**Audience:** Developers, AI assistants, and end users
|
||||
422
docs/08-views-system.md
Normal file
422
docs/08-views-system.md
Normal file
|
|
@ -0,0 +1,422 @@
|
|||
# Views - Smart Saved Searches
|
||||
|
||||
This document explains how Views work in tududi from a user behavior perspective. For technical implementation details, see the backend code in `/backend/modules/views/` and frontend components in `/frontend/components/Views.tsx` and `/frontend/components/ViewDetail.tsx`.
|
||||
|
||||
---
|
||||
|
||||
## **What Are Views?**
|
||||
|
||||
**Views are saved search configurations** that allow you to quickly filter and access tasks, notes, and projects based on specific criteria. Think of them as "smart folders" that automatically show items matching your saved filters.
|
||||
|
||||
### Key Concepts
|
||||
|
||||
1. **Views save your search criteria, not the items themselves**
|
||||
- When you open a view, it runs the search in real-time
|
||||
- Results are always up-to-date with your latest data
|
||||
|
||||
2. **Views can filter across multiple entity types**
|
||||
- Tasks
|
||||
- Notes
|
||||
- Projects
|
||||
|
||||
3. **Views are personal**
|
||||
- Each user has their own views
|
||||
- Views cannot be shared (unlike projects)
|
||||
|
||||
---
|
||||
|
||||
## **Creating Views**
|
||||
|
||||
### From Universal Search
|
||||
|
||||
1. **Open Universal Search** (Cmd/Ctrl + K or click search icon)
|
||||
2. **Configure your search criteria:**
|
||||
- Enter search text
|
||||
- Select entity types (Tasks, Notes, Projects)
|
||||
- Set priority filter (High, Medium, Low)
|
||||
- Set due date filter (Today, This Week, Overdue, etc.)
|
||||
- Set defer filter (Deferred, Not Deferred, etc.)
|
||||
- Add tags
|
||||
- Add extras (Recurring, Subtasks, etc.)
|
||||
|
||||
3. **Click "Save as View"**
|
||||
4. **Enter a name** for your view
|
||||
5. **Click "Save View"**
|
||||
|
||||
### What Gets Saved
|
||||
|
||||
When you save a view, it stores:
|
||||
- **Search query** - The text you searched for
|
||||
- **Filters** - Entity types (Tasks, Notes, Projects)
|
||||
- **Priority** - Priority filter setting
|
||||
- **Due** - Due date filter setting
|
||||
- **Defer** - Defer filter setting
|
||||
- **Tags** - Selected tags
|
||||
- **Extras** - Additional filters (recurring, subtasks, etc.)
|
||||
|
||||
The view does **NOT** save:
|
||||
- Sort order (set per-session when viewing)
|
||||
- Group by setting (set per-session when viewing)
|
||||
- Show status (active/completed/all) (set per-session when viewing)
|
||||
|
||||
---
|
||||
|
||||
## **Accessing Views**
|
||||
|
||||
### View List Page
|
||||
|
||||
Navigate to `/views` to see all your views:
|
||||
- Shows all views in a card grid layout
|
||||
- **Pinned views** appear first (with star icon)
|
||||
- **Search bar** to filter views by name
|
||||
- Click any view card to open it
|
||||
|
||||
### Pinned Views in Sidebar
|
||||
|
||||
**Pinned views appear in the sidebar** for quick access:
|
||||
- Shows up to all pinned views
|
||||
- Appears below the main "VIEWS" menu item
|
||||
- Can be **reordered via drag-and-drop**
|
||||
- Click the star icon to pin/unpin
|
||||
|
||||
---
|
||||
|
||||
## **Using Views**
|
||||
|
||||
### Opening a View
|
||||
|
||||
When you open a view, it displays:
|
||||
1. **View name** at the top (click to rename)
|
||||
2. **Action buttons**: Search toggle, Sort/Filter, Info, Pin, Delete
|
||||
3. **Search criteria info** (click ℹ️ icon to see)
|
||||
4. **Results grouped by type:**
|
||||
- Tasks section
|
||||
- Notes section
|
||||
- Projects section
|
||||
|
||||
### Filtering Results
|
||||
|
||||
**Search within view:**
|
||||
- Click magnifying glass icon to show search input
|
||||
- Filters results by task name, original name, or note content
|
||||
- Does not modify the saved view criteria
|
||||
|
||||
**Sort tasks:**
|
||||
- Click sort icon to open dropdown
|
||||
- Options: Due Date, Name, Priority, Status, Created At
|
||||
- Choose Ascending or Descending
|
||||
|
||||
**Group tasks:**
|
||||
- Click sort icon → "Group by" section
|
||||
- Options: None, Project
|
||||
|
||||
**Show status:**
|
||||
- Click sort icon → "Show" section
|
||||
- **Active** (default) - Shows open tasks only
|
||||
- **All** - Shows all tasks
|
||||
- **Completed** - Shows completed tasks only
|
||||
|
||||
### Display Behavior
|
||||
|
||||
1. **Tasks are shown without subtasks**
|
||||
- Only parent tasks appear in view results
|
||||
- Subtasks are excluded to avoid duplication
|
||||
|
||||
2. **Pagination**
|
||||
- Initial load: 20 items
|
||||
- Click "Load More" to fetch next 20 items
|
||||
- Counter shows "Showing X of Y tasks"
|
||||
|
||||
3. **Real-time updates**
|
||||
- Results refresh when you complete, update, or delete items
|
||||
- Matches are always current
|
||||
|
||||
---
|
||||
|
||||
## **Managing Views**
|
||||
|
||||
### Renaming a View
|
||||
|
||||
1. Click on the view name at the top
|
||||
2. Edit the name inline
|
||||
3. Press Enter to save, or click outside to save
|
||||
4. Press Escape to cancel
|
||||
|
||||
### Pinning/Unpinning
|
||||
|
||||
**Pin a view:**
|
||||
- Click the star icon (outline)
|
||||
- View appears in sidebar
|
||||
- Star turns solid yellow
|
||||
|
||||
**Unpin a view:**
|
||||
- Click the star icon (solid)
|
||||
- View is removed from sidebar
|
||||
- Star turns outline gray
|
||||
|
||||
**Maximum pins:** Unlimited (but recommended to keep manageable)
|
||||
|
||||
### Reordering Pinned Views
|
||||
|
||||
**In the sidebar:**
|
||||
1. **Press and hold** on a pinned view (250ms delay)
|
||||
2. **Drag** to the desired position
|
||||
3. **Release** to drop
|
||||
4. Order is saved automatically
|
||||
|
||||
**Keyboard alternative:**
|
||||
- Use keyboard navigation (if supported)
|
||||
- Arrow keys to navigate, Space to grab, Arrow keys to move, Space to drop
|
||||
|
||||
### Deleting a View
|
||||
|
||||
1. Open the view or find it in the view list
|
||||
2. Click the trash icon
|
||||
3. Confirm deletion in dialog
|
||||
4. View is permanently deleted
|
||||
|
||||
**Note:** Deleting a view does not delete the items it shows - only the saved search criteria.
|
||||
|
||||
---
|
||||
|
||||
## **View Data Model**
|
||||
|
||||
### View Fields
|
||||
|
||||
| Field | Type | Description |
|
||||
|-------|------|-------------|
|
||||
| `id` | Integer | Internal database ID |
|
||||
| `uid` | String | Public unique identifier (used in URLs) |
|
||||
| `name` | String | View name (required) |
|
||||
| `user_id` | Integer | Owner of the view |
|
||||
| `search_query` | String | Text search term (nullable) |
|
||||
| `filters` | JSON Array | Entity types ["Tasks", "Notes", "Projects"] |
|
||||
| `priority` | String | Priority filter: "high", "medium", "low" (nullable) |
|
||||
| `due` | String | Due date filter: "today", "this_week", "overdue", etc. (nullable) |
|
||||
| `defer` | String | Defer filter: "deferred", "not_deferred", etc. (nullable) |
|
||||
| `tags` | JSON Array | Tag names to filter by |
|
||||
| `extras` | JSON Array | Extra filters: "recurring", "subtasks", etc. |
|
||||
| `is_pinned` | Boolean | Whether view is pinned to sidebar |
|
||||
| `created_at` | DateTime | When view was created |
|
||||
| `updated_at` | DateTime | Last modified time |
|
||||
|
||||
---
|
||||
|
||||
## **Display Rules**
|
||||
|
||||
### Results Matching
|
||||
|
||||
A view shows items that match **ALL** of the following criteria (AND logic):
|
||||
|
||||
1. **Entity type matches filters**
|
||||
- If filters = ["Tasks"], only tasks appear
|
||||
- If filters = ["Tasks", "Notes"], tasks and notes appear
|
||||
- If filters = [], all types appear (rare)
|
||||
|
||||
2. **Text matches search query** (if set)
|
||||
- Tasks: Matches name, original_name, or note
|
||||
- Notes: Matches title or content
|
||||
- Projects: Matches name or description
|
||||
|
||||
3. **Priority matches** (if set)
|
||||
- Only items with that priority level
|
||||
|
||||
4. **Due date matches** (if set)
|
||||
- Filters based on due date range
|
||||
- Options: today, this_week, next_week, overdue, no_due_date
|
||||
|
||||
5. **Defer matches** (if set)
|
||||
- Filters based on defer status
|
||||
- Options: deferred, not_deferred
|
||||
|
||||
6. **Has ALL specified tags** (if set)
|
||||
- Items must have every tag in the list
|
||||
|
||||
7. **Matches extra filters** (if set)
|
||||
- recurring: Only recurring tasks
|
||||
- subtasks: Only subtasks (usually excluded)
|
||||
|
||||
### Empty Results
|
||||
|
||||
If no items match, the view shows:
|
||||
- Empty state icon
|
||||
- Message: "No items found matching the view criteria"
|
||||
|
||||
---
|
||||
|
||||
## **Sidebar Integration**
|
||||
|
||||
### Sidebar View Order
|
||||
|
||||
Pinned views appear in the sidebar in this order:
|
||||
1. **Custom order** (if user has dragged to reorder)
|
||||
2. **Fallback order** (creation date, newest first)
|
||||
|
||||
The order is stored in the user's `sidebar_settings` profile field as:
|
||||
```json
|
||||
{
|
||||
"pinnedViewsOrder": ["uid1", "uid2", "uid3"]
|
||||
}
|
||||
```
|
||||
|
||||
### Sidebar Refresh
|
||||
|
||||
The sidebar updates automatically when:
|
||||
- A view is created
|
||||
- A view is deleted
|
||||
- A view is pinned/unpinned
|
||||
- Pinned views are reordered
|
||||
|
||||
**Trigger:** `window.dispatchEvent(new CustomEvent('viewUpdated'))`
|
||||
|
||||
---
|
||||
|
||||
## **URL Parameters**
|
||||
|
||||
When viewing a view at `/views/:uid`, you can use URL parameters to control display:
|
||||
|
||||
| Parameter | Values | Default | Description |
|
||||
|-----------|--------|---------|-------------|
|
||||
| `order_by` | `due_date:asc`, `name:asc`, `priority:desc`, `status:desc`, `created_at:desc` | `created_at:desc` | Task sort order |
|
||||
| `group_by` | `none`, `project` | `none` | Task grouping |
|
||||
| `status` | `active`, `all`, `completed` | `active` | Task status filter |
|
||||
| `search` | Any text | Empty | Search within view results |
|
||||
|
||||
**Example:**
|
||||
```
|
||||
/views/abc123?order_by=priority:desc&group_by=project&status=all&search=urgent
|
||||
```
|
||||
|
||||
**Behavior:**
|
||||
- Parameters are synced to URL as you change filters
|
||||
- Browser back/forward works correctly
|
||||
- Sharing a URL preserves filters
|
||||
|
||||
---
|
||||
|
||||
## **Special Features**
|
||||
|
||||
### View Criteria Badge
|
||||
|
||||
Click the **ℹ️ (info) icon** to see a dropdown showing:
|
||||
- Entity types filter
|
||||
- Search text
|
||||
- Priority filter
|
||||
- Due date filter
|
||||
- Defer filter
|
||||
- Tags filter
|
||||
- Extras filter
|
||||
|
||||
If no criteria are set, shows: "No criteria set"
|
||||
|
||||
### Edit Name Inline
|
||||
|
||||
Click the view name to edit it inline:
|
||||
- Auto-focuses input field
|
||||
- Press Enter to save
|
||||
- Press Escape to cancel
|
||||
- Click outside to save
|
||||
- Empty names are rejected
|
||||
|
||||
### Task Interactions
|
||||
|
||||
Within a view, you can:
|
||||
- **Complete/uncomplete** tasks (checkbox)
|
||||
- **Open task details** (click task name)
|
||||
- **Update task** (via task detail modal)
|
||||
- **Delete task** (via task detail modal)
|
||||
|
||||
Changes are reflected immediately in the view results.
|
||||
|
||||
---
|
||||
|
||||
## **Performance & Limits**
|
||||
|
||||
### Pagination
|
||||
|
||||
- **Initial load:** 20 items per entity type
|
||||
- **Load more:** Additional 20 items per click
|
||||
- **Load all:** Fetches remaining items (use with caution on large result sets)
|
||||
|
||||
### Search Performance
|
||||
|
||||
- Views use the universal search backend
|
||||
- Searches are **indexed** for performance
|
||||
- Text search supports **partial matches**
|
||||
- Tag search requires **exact matches**
|
||||
|
||||
### View Limits
|
||||
|
||||
- **No limit** on number of views per user
|
||||
- **No limit** on number of pinned views
|
||||
- Recommended to keep pinned views manageable (5-10)
|
||||
|
||||
---
|
||||
|
||||
## **Common Use Cases**
|
||||
|
||||
### Example 1: High-Priority Tasks Due This Week
|
||||
|
||||
**Criteria:**
|
||||
- Filters: Tasks
|
||||
- Priority: High
|
||||
- Due: this_week
|
||||
|
||||
**Result:** Shows all high-priority tasks due within the next 7 days
|
||||
|
||||
---
|
||||
|
||||
### Example 2: Work Notes
|
||||
|
||||
**Criteria:**
|
||||
- Filters: Notes
|
||||
- Tags: ["work"]
|
||||
|
||||
**Result:** Shows all notes tagged with "work"
|
||||
|
||||
---
|
||||
|
||||
### Example 3: Overdue Tasks in Project X
|
||||
|
||||
**Criteria:**
|
||||
- Filters: Tasks
|
||||
- Due: overdue
|
||||
- Search query: "Project X"
|
||||
|
||||
**Result:** Shows all overdue tasks whose name or note contains "Project X"
|
||||
|
||||
---
|
||||
|
||||
### Example 4: Recurring Tasks
|
||||
|
||||
**Criteria:**
|
||||
- Filters: Tasks
|
||||
- Extras: ["recurring"]
|
||||
|
||||
**Result:** Shows all recurring task templates
|
||||
|
||||
---
|
||||
|
||||
## **Related Documentation**
|
||||
|
||||
- [Today Page Sections](02-today-page-sections.md) - How Today page filters tasks
|
||||
- [Upcoming View](03-upcoming-view.md) - 7-day upcoming task view
|
||||
- [Notes System](05-notes-system.md) - How notes work
|
||||
- [Projects](06-projects.md) - Project organization
|
||||
- [Architecture Overview](architecture.md) - Technical architecture
|
||||
|
||||
**Technical Implementation Files:**
|
||||
- Backend service: `/backend/modules/views/service.js`
|
||||
- Backend routes: `/backend/modules/views/routes.js`
|
||||
- Backend repository: `/backend/modules/views/repository.js`
|
||||
- View model: `/backend/models/view.js`
|
||||
- Frontend views list: `/frontend/components/Views.tsx`
|
||||
- Frontend view detail: `/frontend/components/ViewDetail.tsx`
|
||||
- Sidebar views: `/frontend/components/Sidebar/SidebarViews.tsx`
|
||||
- Save view modal: `/frontend/components/UniversalSearch/SaveViewModal.tsx`
|
||||
|
||||
---
|
||||
|
||||
**Document Version:** 1.0.0
|
||||
**Last Updated:** 2026-03-14
|
||||
**Audience:** Developers, AI assistants, and end users
|
||||
836
docs/09-tags-system.md
Normal file
836
docs/09-tags-system.md
Normal file
|
|
@ -0,0 +1,836 @@
|
|||
# Tags System - Behavior Rules
|
||||
|
||||
This document explains how the Tags system works in tududi from a user behavior perspective. For technical implementation details, see the backend code in `/backend/modules/tags/` and frontend components in `/frontend/components/Tags.tsx` and `/frontend/components/Tag/`.
|
||||
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
**Tags** are tududi's flexible labeling and categorization system - a way to organize and group related items across tasks, notes, and projects. Unlike the hierarchical organization of Areas > Projects > Tasks, tags provide a flat, cross-cutting way to find and filter content.
|
||||
|
||||
**Key characteristics:**
|
||||
- Work across all content types (tasks, notes, projects)
|
||||
- User-scoped (each user has their own tag set)
|
||||
- Unique per user (no duplicate tag names)
|
||||
- Auto-created on-the-fly
|
||||
- Case-insensitive
|
||||
- Character restrictions for URL safety
|
||||
- Maximum 50 characters per tag name
|
||||
|
||||
**URL:** `/tags` (tag list) or `/tag/:uid-:slug` (tag detail page)
|
||||
|
||||
---
|
||||
|
||||
## Core Principles
|
||||
|
||||
1. **Cross-entity organization**
|
||||
- Same tag can be applied to tasks, notes, and projects
|
||||
- Creates horizontal connections across hierarchical boundaries
|
||||
- Enables finding related items regardless of their type
|
||||
|
||||
2. **Flexible categorization**
|
||||
- No predefined taxonomy
|
||||
- Create tags as needed
|
||||
- No hierarchy (tags are flat)
|
||||
- Multiple tags per item (up to 10 tags per task/note/project)
|
||||
|
||||
3. **User-scoped isolation**
|
||||
- Each user has their own tag namespace
|
||||
- Tags are not shared between users
|
||||
- Even in shared projects, tags remain user-specific
|
||||
- Deleting a tag only affects your view
|
||||
|
||||
---
|
||||
|
||||
## Tag Structure
|
||||
|
||||
### Fields
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
|-------|------|----------|-------------|
|
||||
| **UID** | String | Auto | Unique identifier (immutable) |
|
||||
| **Name** | String | Yes | Tag name (unique per user) |
|
||||
| **User ID** | Integer | Auto | Owner of the tag |
|
||||
| **Created At** | Timestamp | Auto | Creation timestamp |
|
||||
| **Updated At** | Timestamp | Auto | Last modification timestamp |
|
||||
|
||||
### Unique Identifier
|
||||
|
||||
- Each tag has a **UID** (unique identifier): `uid` field
|
||||
- Used in URLs: `/tag/abc123def456-tag-name`
|
||||
- Immutable - persists through renames
|
||||
- Format: Generated unique string (8+ characters)
|
||||
|
||||
### Validation Rules
|
||||
|
||||
**Tag name restrictions:**
|
||||
- **Length:** 1-50 characters (after trimming whitespace)
|
||||
- **Invalid characters:** `# % & { } \ < > * ? / $ ! ' " @ + \` | =`
|
||||
- **Valid characters:** Letters, numbers, spaces, hyphens, underscores
|
||||
- **Case:** Stored as-is, but treated case-insensitively for uniqueness
|
||||
- ✅ `work`, `Work Projects`, `Q1-2026`, `backend_dev`
|
||||
- ❌ `#hashtag`, `foo/bar`, `price$`, `email@domain`
|
||||
|
||||
**Uniqueness:**
|
||||
- Tag names must be unique per user (case-insensitive)
|
||||
- `work` = `Work` = `WORK` (same tag)
|
||||
- Error if you try to create a duplicate: "A tag with the name 'work' already exists"
|
||||
|
||||
**Automatic cleanup:**
|
||||
- Leading/trailing whitespace trimmed automatically
|
||||
- Example: `" productivity "` becomes `"productivity"`
|
||||
|
||||
---
|
||||
|
||||
## Creating Tags
|
||||
|
||||
### Method 1: Auto-Creation (Most Common)
|
||||
|
||||
Tags are automatically created when you add them to a task, note, or project:
|
||||
|
||||
1. **From task creation/edit:**
|
||||
- In task form, click "Add tags" or tag icon
|
||||
- Type tag name in input field
|
||||
- Press Enter or comma
|
||||
- If tag doesn't exist, it's created automatically
|
||||
- Tag is immediately applied to the task
|
||||
|
||||
2. **From note creation/edit:**
|
||||
- In note edit mode, click tag icon
|
||||
- Type tag name and press Enter
|
||||
- Auto-created and applied
|
||||
|
||||
3. **From project form:**
|
||||
- Similar to tasks - type and press Enter
|
||||
- Auto-created and linked to project
|
||||
|
||||
**Auto-creation behavior:**
|
||||
- No confirmation required
|
||||
- Tag appears in tag list immediately
|
||||
- Available for autocomplete in other forms
|
||||
- Validation errors shown inline
|
||||
|
||||
### Method 2: Direct Creation
|
||||
|
||||
**From Tags page:**
|
||||
1. Navigate to `/tags`
|
||||
2. No "Create Tag" button exists
|
||||
3. Tags are created implicitly by using them
|
||||
|
||||
**Limitation:** You cannot create standalone tags - they must be created by associating them with a task, note, or project.
|
||||
|
||||
### Method 3: From Inbox (Hashtag Parsing)
|
||||
|
||||
**Automatic tag extraction:**
|
||||
1. Capture item in Inbox: `Review #quarterly-report +Work`
|
||||
2. System detects `#quarterly-report`
|
||||
3. When converting to task/note, tag is auto-created
|
||||
4. Applied to the resulting item
|
||||
|
||||
**Hashtag rules:**
|
||||
- Must start with `#`
|
||||
- Followed by valid tag characters
|
||||
- Stops at whitespace or invalid character
|
||||
- Example: `#work-item` creates tag `work-item`
|
||||
|
||||
---
|
||||
|
||||
## Using Tags
|
||||
|
||||
### Adding Tags to Tasks
|
||||
|
||||
**During task creation:**
|
||||
1. Click "+ Add Task" or open task form
|
||||
2. Scroll to "Tags" section
|
||||
3. Click tag icon or "Add tags"
|
||||
4. Tag input field appears
|
||||
5. Type tag name (autocomplete suggests existing tags)
|
||||
6. Press Enter or comma to add
|
||||
7. Repeat for multiple tags (max 10)
|
||||
8. Save task
|
||||
|
||||
**During task editing:**
|
||||
1. Open task detail modal
|
||||
2. Click "Tags" card or tag icon
|
||||
3. Same input flow as creation
|
||||
4. Changes save automatically
|
||||
|
||||
**Tag input features:**
|
||||
- **Autocomplete:** Shows matching existing tags as you type
|
||||
- **Keyboard navigation:** Arrow keys to navigate suggestions, Enter to select
|
||||
- **Multiple selection:** Add up to 10 tags per task
|
||||
- **Remove tag:** Click × on tag chip
|
||||
- **Create new:** Type non-existent tag, press Enter
|
||||
- **Backspace removal:** Press Backspace on empty input to remove last tag
|
||||
|
||||
### Adding Tags to Notes
|
||||
|
||||
**In note edit mode:**
|
||||
1. Open note in edit mode
|
||||
2. Click tag icon (🏷️) in metadata section
|
||||
3. Tag input appears
|
||||
4. Type and press Enter to add tags
|
||||
5. Auto-saves after 1 second
|
||||
|
||||
**Tag display in notes:**
|
||||
- Preview mode: Tags shown as clickable links below title
|
||||
- Edit mode: Tag input with chips
|
||||
- Click tag → Navigate to tag page
|
||||
|
||||
### Adding Tags to Projects
|
||||
|
||||
**In project form:**
|
||||
1. Create or edit project
|
||||
2. "Tags" field in form
|
||||
3. Same tag input component
|
||||
4. Type, autocomplete, and select
|
||||
5. Save project
|
||||
|
||||
**Project tag behavior:**
|
||||
- Tags inherited by tasks? **No** - tags are independent per entity
|
||||
- Changing project tags doesn't affect existing tasks
|
||||
- Tags help group projects by theme/category
|
||||
|
||||
---
|
||||
|
||||
## Tag Management
|
||||
|
||||
### Editing Tags
|
||||
|
||||
**Rename a tag:**
|
||||
1. Navigate to `/tags` or `/tag/:uid-slug`
|
||||
2. Click **edit icon** (pencil) on tag
|
||||
3. Tag modal opens
|
||||
4. Change tag name
|
||||
5. Click "Save"
|
||||
6. All associations update automatically
|
||||
|
||||
**What updates when you rename:**
|
||||
- Tag name updates across all tasks, notes, projects using it
|
||||
- URLs update to use new slug
|
||||
- Autocomplete suggestions reflect new name
|
||||
- No broken links (UID remains the same)
|
||||
|
||||
**Rename restrictions:**
|
||||
- Must follow validation rules (1-50 chars, valid characters)
|
||||
- Cannot rename to existing tag name (conflict error)
|
||||
|
||||
### Deleting Tags
|
||||
|
||||
**Confirmation required:**
|
||||
|
||||
**From tags list page:**
|
||||
1. Navigate to `/tags`
|
||||
2. Hover over tag card
|
||||
3. Click **delete icon** (trash)
|
||||
4. Confirmation dialog: "Are you sure you want to delete the tag 'tag-name'?"
|
||||
5. Confirm or cancel
|
||||
|
||||
**From tag detail page:**
|
||||
1. Navigate to `/tag/:uid-slug`
|
||||
2. Click delete button (top right)
|
||||
3. Confirmation dialog
|
||||
4. Confirm → Redirects to `/tags`
|
||||
|
||||
**What gets deleted:**
|
||||
- Tag record itself
|
||||
- All associations with tasks (from `tasks_tags` table)
|
||||
- All associations with notes (from `notes_tags` table)
|
||||
- All associations with projects (from `projects_tags` table)
|
||||
|
||||
**What's preserved:**
|
||||
- Tasks, notes, and projects themselves (only tag link removed)
|
||||
- No cascading deletion
|
||||
- Other tags remain intact
|
||||
|
||||
**No undo:**
|
||||
- Deletion is immediate and irreversible
|
||||
- All items lose the tag permanently
|
||||
|
||||
---
|
||||
|
||||
## Tag Pages and Navigation
|
||||
|
||||
### Tags List Page (`/tags`)
|
||||
|
||||
**Layout:**
|
||||
- Alphabetical grouping (A, B, C, ...)
|
||||
- Each group shows tags starting with that letter
|
||||
- Search bar at top (collapsible)
|
||||
- Grid layout (1-3 columns based on screen size)
|
||||
|
||||
**Tag display:**
|
||||
- Tag name (truncated if long)
|
||||
- Edit button (on hover)
|
||||
- Delete button (on hover)
|
||||
- Click tag name → Navigate to tag detail page
|
||||
|
||||
**Search functionality:**
|
||||
- Case-insensitive
|
||||
- Substring matching
|
||||
- Real-time filtering
|
||||
- No regex support
|
||||
|
||||
**Empty state:**
|
||||
- "No tags found" when search returns zero results
|
||||
- No tags exist → Empty list (no special message)
|
||||
|
||||
### Tag Detail Page (`/tag/:uid-slug`)
|
||||
|
||||
**URL format:**
|
||||
- UID + slug: `/tag/abc123def-quarterly-report`
|
||||
- UID only (fallback): `/tag/abc123def`
|
||||
- Name (legacy, URL-encoded): `/tag/quarterly-report`
|
||||
|
||||
**Page sections:**
|
||||
1. **Header:**
|
||||
- Tag name as title
|
||||
- Search button (collapsible)
|
||||
- Edit button (pencil icon)
|
||||
- Delete button (trash icon)
|
||||
|
||||
2. **Summary stats:**
|
||||
- Tasks count (with icon)
|
||||
- Notes count (with icon)
|
||||
- Projects count (with icon)
|
||||
|
||||
3. **Tasks section:**
|
||||
- All tasks with this tag
|
||||
- Filter by status: Open / All / Completed
|
||||
- Sort options: Due Date, Name, Priority, Status, Created At
|
||||
- Group by: None / Project
|
||||
- Search within tasks
|
||||
- TaskList or GroupedTaskList component
|
||||
|
||||
4. **Notes section:**
|
||||
- All notes with this tag
|
||||
- List view with title, content preview
|
||||
- Edit/delete buttons (on hover)
|
||||
- Click note → Navigate to note detail
|
||||
|
||||
5. **Projects section:**
|
||||
- All projects with this tag
|
||||
- ProjectItem component
|
||||
- Filter by status (active/completed)
|
||||
- Completion percentage shown
|
||||
|
||||
**Interactive features:**
|
||||
- Sort and filter tasks without page reload
|
||||
- Search updates results in real-time
|
||||
- Click any item → Navigate to detail page
|
||||
- Edit/delete actions on tag propagate immediately
|
||||
|
||||
**Empty state:**
|
||||
- "No items found with the tag 'tag-name'" when no tasks/notes/projects exist
|
||||
- Search returns zero results → "No tasks available"
|
||||
|
||||
---
|
||||
|
||||
## Tag Display and Rendering
|
||||
|
||||
### In Task Lists
|
||||
|
||||
**Tag display:**
|
||||
- Small chips/badges below task name
|
||||
- Truncated if many tags
|
||||
- Clickable → Navigate to tag page
|
||||
- Color: Gray background, dark text
|
||||
- Icon: Tag icon (🏷️) before tag list
|
||||
|
||||
**Hover behavior:**
|
||||
- Underline on hover
|
||||
- Cursor changes to pointer
|
||||
- Tooltip with full tag name (if truncated)
|
||||
|
||||
### In Note Previews
|
||||
|
||||
**Metadata row:**
|
||||
- Tags shown after project (if any)
|
||||
- Format: `🏷️ tag1, tag2, tag3`
|
||||
- Each tag is a clickable link
|
||||
- Comma-separated list
|
||||
|
||||
### In Project Cards
|
||||
|
||||
**Tag display:**
|
||||
- Similar to tasks - chips or inline list
|
||||
- Shown in project metadata
|
||||
- Clickable links to tag pages
|
||||
|
||||
### Tag Chips Styling
|
||||
|
||||
**Default appearance:**
|
||||
- Background: Light gray (`bg-gray-200`)
|
||||
- Text: Dark gray (`text-gray-700`)
|
||||
- Font size: Extra small (`text-xs`)
|
||||
- Padding: Small (`px-2.5 py-0.5`)
|
||||
- Border radius: Rounded (`rounded`)
|
||||
|
||||
**Dark mode:**
|
||||
- Background: Dark gray (`bg-gray-700`)
|
||||
- Text: Light gray (`text-gray-300`)
|
||||
|
||||
**Remove button (in edit mode):**
|
||||
- × symbol
|
||||
- Hover effect: Darker color
|
||||
- Click to remove tag from item
|
||||
|
||||
---
|
||||
|
||||
## Tag Input Component
|
||||
|
||||
### Features
|
||||
|
||||
**Autocomplete:**
|
||||
- Shows existing tags matching your input
|
||||
- Filters out already-selected tags
|
||||
- Debounced (300ms delay)
|
||||
- Keyboard navigable (Arrow Up/Down)
|
||||
- Enter to select
|
||||
|
||||
**Keyboard shortcuts:**
|
||||
- `Enter` - Add tag (highlighted suggestion or new tag)
|
||||
- `,` (comma) - Add tag and continue typing
|
||||
- `Backspace` - Remove last tag (when input is empty)
|
||||
- `Escape` - Close dropdown
|
||||
- `Arrow Up/Down` - Navigate suggestions
|
||||
|
||||
**Tag limits:**
|
||||
- Maximum 10 tags per item
|
||||
- Input disabled after reaching limit
|
||||
- No error message, just prevents adding more
|
||||
|
||||
**Visual feedback:**
|
||||
- Selected tags shown as chips above input
|
||||
- Placeholder: "Type to add tags..."
|
||||
- Dropdown with suggestions (max height 240px, scrollable)
|
||||
- Highlighted suggestion on hover/keyboard navigation
|
||||
|
||||
### Autocomplete Behavior
|
||||
|
||||
**Matching:**
|
||||
- Case-insensitive
|
||||
- Substring matching anywhere in tag name
|
||||
- Example: "dev" matches "backend-dev", "development", "DevOps"
|
||||
|
||||
**Dropdown display:**
|
||||
- Only shows tags not already selected
|
||||
- Up to 10 suggestions (scrollable if more)
|
||||
- Highlighted first match by default
|
||||
- Mouseover changes highlight
|
||||
|
||||
**Create new tag:**
|
||||
- If no matches, shows "+ Create 'tag-name'"
|
||||
- Or just press Enter to create
|
||||
- Validation happens on creation attempt
|
||||
|
||||
---
|
||||
|
||||
## Tag Organization
|
||||
|
||||
### Alphabetical Grouping
|
||||
|
||||
**Tags list page:**
|
||||
- Groups by first letter (uppercase)
|
||||
- A, B, C, ..., Z
|
||||
- Special characters/numbers grouped together
|
||||
- Within each group, sorted alphabetically (case-insensitive)
|
||||
|
||||
**Sorting:**
|
||||
- Global sort: Alphabetical by name
|
||||
- No custom sorting options
|
||||
- Case-insensitive sort (A = a)
|
||||
|
||||
### User-Scoped Tags
|
||||
|
||||
**Privacy:**
|
||||
- Tags are private to each user
|
||||
- Other users cannot see your tags
|
||||
- Shared projects: Each collaborator has their own tags
|
||||
|
||||
**Example scenario:**
|
||||
- User A tags project with `#urgent`
|
||||
- User B (collaborator) doesn't see `#urgent` in their tag list
|
||||
- User B can create their own `#urgent` tag independently
|
||||
|
||||
### No Tag Hierarchy
|
||||
|
||||
**Flat structure:**
|
||||
- Tags don't have parent/child relationships
|
||||
- No nesting (e.g., `work/backend` is one tag, not a hierarchy)
|
||||
- Workaround: Use naming conventions (`work-backend`, `work-frontend`)
|
||||
|
||||
**Multi-level categorization:**
|
||||
- Not supported natively
|
||||
- Use prefixes: `project-alpha`, `project-beta`
|
||||
- Or combine tags: Add both `work` and `backend` to same item
|
||||
|
||||
---
|
||||
|
||||
## Search and Filtering
|
||||
|
||||
### Search Tags (Tags List Page)
|
||||
|
||||
**How to search:**
|
||||
1. Navigate to `/tags`
|
||||
2. Click search icon (top right)
|
||||
3. Search input expands
|
||||
4. Type query
|
||||
5. Results filter in real-time
|
||||
|
||||
**Search behavior:**
|
||||
- **Case insensitive:** "work" matches "Work", "WORK"
|
||||
- **Substring matching:** "dev" matches "development", "backend-dev"
|
||||
- **Single query:** No multi-word AND/OR logic
|
||||
- **No fuzzy matching:** Exact substring required
|
||||
|
||||
**Search scope:**
|
||||
- Tag name only
|
||||
- Does not search tags' associated items
|
||||
|
||||
### Filter by Tag (Content Pages)
|
||||
|
||||
**Task filtering:**
|
||||
- API endpoint: `GET /api/tasks?tag=tag-name`
|
||||
- Frontend: Navigate via tag page → Shows tasks with that tag
|
||||
|
||||
**Note filtering:**
|
||||
- API endpoint: `GET /api/notes?tag=tag-name`
|
||||
- URL query parameter: `/notes?tag=bookmark`
|
||||
|
||||
**Project filtering:**
|
||||
- No dedicated API endpoint
|
||||
- Tag detail page filters projects client-side
|
||||
|
||||
**Multiple tag filtering:**
|
||||
- Not supported in UI
|
||||
- API supports single tag filter only
|
||||
- Workaround: Use tag detail page, then search
|
||||
|
||||
---
|
||||
|
||||
## Integration with Other Features
|
||||
|
||||
### Inbox Integration
|
||||
|
||||
**Hashtag parsing:**
|
||||
- Inbox items can include `#tag-name` syntax
|
||||
- Example: `Buy groceries #home #errands`
|
||||
- When converting to task: Tags `home` and `errands` auto-created and applied
|
||||
|
||||
**Smart suggestions:**
|
||||
- Inbox processor detects hashtags
|
||||
- Suggests converting to task/note with tags pre-filled
|
||||
|
||||
**URL detection:**
|
||||
- Inbox items with URLs suggest "Note"
|
||||
- Can include tags: `https://example.com #bookmark #reading`
|
||||
|
||||
### Task Integration
|
||||
|
||||
**Task creation:**
|
||||
- Tag input in task form
|
||||
- Auto-save when tags change
|
||||
- Tags persist with task
|
||||
|
||||
**Recurring tasks:**
|
||||
- Tags applied to parent task
|
||||
- All future occurrences inherit tags
|
||||
- Changing tags on parent updates all future instances
|
||||
|
||||
**Subtasks:**
|
||||
- Can have different tags than parent
|
||||
- No automatic inheritance
|
||||
- Independent tag management
|
||||
|
||||
### Note Integration
|
||||
|
||||
**Note tagging:**
|
||||
- Tag input in edit mode
|
||||
- Tags shown in preview mode as links
|
||||
- Click tag → Navigate to tag page
|
||||
|
||||
**Auto-save behavior:**
|
||||
- Tag changes trigger auto-save
|
||||
- 1-second debounce
|
||||
- Save status indicator updates
|
||||
|
||||
### Project Integration
|
||||
|
||||
**Project tagging:**
|
||||
- Tag field in project form
|
||||
- Tags help categorize projects
|
||||
- Useful for filtering project list
|
||||
|
||||
**Shared projects:**
|
||||
- Tags remain user-specific
|
||||
- Collaborators don't see your tags
|
||||
- Each user maintains their own tag set for shared projects
|
||||
|
||||
---
|
||||
|
||||
## Common Workflows
|
||||
|
||||
### Workflow 1: Tag-Based Task Management
|
||||
|
||||
**Scenario:** Organize tasks by context (e.g., @home, @office, @phone)
|
||||
|
||||
1. Create tasks and tag them:
|
||||
- "Fix garage door" → `#home`, `#maintenance`
|
||||
- "Review budget report" → `#office`, `#finance`
|
||||
- "Call dentist" → `#phone`, `#health`
|
||||
|
||||
2. Navigate to tag page to see filtered view:
|
||||
- `/tag/home` → All home tasks
|
||||
- `/tag/phone` → All phone-related tasks
|
||||
|
||||
3. Complete tasks in batches by context:
|
||||
- At home? View `#home` tag, complete all tasks
|
||||
- Have phone? View `#phone` tag, make all calls
|
||||
|
||||
### Workflow 2: Cross-Project Tracking
|
||||
|
||||
**Scenario:** Track all "urgent" items across multiple projects
|
||||
|
||||
1. Tag urgent tasks/notes/projects with `#urgent`
|
||||
2. Navigate to `/tag/urgent`
|
||||
3. See all urgent items regardless of project
|
||||
4. Filter and sort as needed
|
||||
5. Update status, priorities, etc.
|
||||
|
||||
### Workflow 3: Thematic Note Organization
|
||||
|
||||
**Scenario:** Collect bookmarks, articles, and references by topic
|
||||
|
||||
1. Save articles as notes with tags:
|
||||
- "React Hooks Guide" → `#development`, `#react`, `#reference`
|
||||
- "Design Patterns" → `#development`, `#patterns`, `#reference`
|
||||
|
||||
2. Navigate to `/tag/development` to see all dev-related notes
|
||||
3. Or `/tag/reference` for all reference materials
|
||||
|
||||
### Workflow 4: Quarterly Review
|
||||
|
||||
**Scenario:** Review all items related to Q1 goals
|
||||
|
||||
1. During Q1, tag relevant tasks/notes/projects with `#q1-2026`
|
||||
2. At end of quarter, navigate to `/tag/q1-2026`
|
||||
3. See all items related to Q1 goals
|
||||
4. Review completion rates
|
||||
5. Archive or re-tag for next quarter
|
||||
|
||||
### Workflow 5: Tag Cleanup
|
||||
|
||||
**Scenario:** Remove unused or redundant tags
|
||||
|
||||
1. Navigate to `/tags`
|
||||
2. Search for old tags (e.g., `#2025`)
|
||||
3. Click tag to see what items use it
|
||||
4. If empty or obsolete, delete tag
|
||||
5. If overlapping (e.g., `work` and `work-related`), rename or consolidate
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### "Tag name contains invalid characters"
|
||||
|
||||
**Possible causes:**
|
||||
1. Using restricted characters: `# % & { } \ < > * ? / $ ! ' " @ + \` | =`
|
||||
2. Example: Trying to create `#hashtag` (contains `#`)
|
||||
|
||||
**Solution:**
|
||||
- Remove invalid characters
|
||||
- Use hyphens or underscores: `hashtag`, `hash-tag`
|
||||
|
||||
### "A tag with the name 'X' already exists"
|
||||
|
||||
**Cause:** Tag names are unique per user (case-insensitive)
|
||||
|
||||
**Example:**
|
||||
- You have tag `Work`
|
||||
- Try to create `work` → Error (same tag)
|
||||
|
||||
**Solution:**
|
||||
- Use existing tag
|
||||
- Or create variation: `work-projects`, `work-tasks`
|
||||
|
||||
### "Tag disappeared after creating task"
|
||||
|
||||
**Possible causes:**
|
||||
1. Task creation failed (network error)
|
||||
2. Tag wasn't saved before closing form
|
||||
3. Browser refresh before save completed
|
||||
|
||||
**Solution:**
|
||||
- Check task exists in task list
|
||||
- Open task → Check tags section
|
||||
- Re-add tag if missing
|
||||
|
||||
### "Cannot add more than 10 tags"
|
||||
|
||||
**Cause:** Tag limit per item is 10
|
||||
|
||||
**Solution:**
|
||||
- Remove less important tags
|
||||
- Or consolidate tags (e.g., merge `urgent` and `high-priority` into one)
|
||||
|
||||
### "Tag page shows wrong items"
|
||||
|
||||
**Possible causes:**
|
||||
1. Cached data (page not refreshed)
|
||||
2. Tag was renamed, URL slug outdated
|
||||
3. Items were untagged recently
|
||||
|
||||
**Solution:**
|
||||
- Hard refresh: `Ctrl+Shift+R` or `Cmd+Shift+R`
|
||||
- Navigate via `/tags` list (ensures correct UID)
|
||||
- Check item details to confirm tag association
|
||||
|
||||
---
|
||||
|
||||
## Best Practices
|
||||
|
||||
### Naming Conventions
|
||||
|
||||
1. **Be consistent:**
|
||||
- Choose singular vs. plural: `project` vs. `projects`
|
||||
- Stick with convention across all tags
|
||||
|
||||
2. **Use prefixes for grouping:**
|
||||
- `status-active`, `status-pending`, `status-done`
|
||||
- `area-work`, `area-personal`, `area-health`
|
||||
|
||||
3. **Keep names short but descriptive:**
|
||||
- ✅ `backend-dev`, `urgent`, `q1-2026`
|
||||
- ❌ `this-is-a-really-long-tag-name-that-describes-too-much`
|
||||
|
||||
4. **Use hyphens or underscores for multi-word:**
|
||||
- ✅ `project-alpha`, `meeting_notes`
|
||||
- ❌ `project alpha` (spaces are valid but harder to read)
|
||||
|
||||
### Organization
|
||||
|
||||
1. **Limit tag proliferation:**
|
||||
- Don't create tags for one-off uses
|
||||
- Reuse existing tags when possible
|
||||
- Regularly review and delete unused tags
|
||||
|
||||
2. **Use tags for cross-cutting concerns:**
|
||||
- Themes that span multiple projects: `#urgent`, `#waiting-on`
|
||||
- Contexts: `#home`, `#office`, `#errands`
|
||||
- Time periods: `#q1-2026`, `#january`
|
||||
|
||||
3. **Combine with hierarchy:**
|
||||
- Use projects for structure (Areas > Projects > Tasks)
|
||||
- Use tags for flexible categorization
|
||||
- Example: Project "Website Redesign", tag `#frontend` on relevant tasks
|
||||
|
||||
### Maintenance
|
||||
|
||||
1. **Regular cleanup:**
|
||||
- Monthly: Review tag list, delete unused tags
|
||||
- Quarterly: Consolidate similar tags
|
||||
- Rename outdated tags (e.g., `#2025` → `#2026`)
|
||||
|
||||
2. **Tag naming audit:**
|
||||
- Ensure consistency (singular vs. plural)
|
||||
- Fix typos: `developement` → `development`
|
||||
- Merge duplicates: `work` and `work-related` → choose one
|
||||
|
||||
3. **Document tag taxonomy:**
|
||||
- Create a note listing standard tags and their meanings
|
||||
- Tag it with `#reference`, `#tags`
|
||||
- Share with team if using shared projects
|
||||
|
||||
---
|
||||
|
||||
## Limitations and Constraints
|
||||
|
||||
### Current Limitations
|
||||
|
||||
1. **No tag hierarchy:**
|
||||
- Flat structure only
|
||||
- No parent-child relationships
|
||||
- Workaround: Use naming conventions (`parent-child`)
|
||||
|
||||
2. **User-scoped only:**
|
||||
- Cannot share tags with other users
|
||||
- Collaborators on shared projects have separate tag sets
|
||||
- No team-wide tag taxonomy
|
||||
|
||||
3. **Single tag filter:**
|
||||
- Cannot filter by multiple tags simultaneously in UI
|
||||
- API supports one tag filter at a time
|
||||
- Workaround: Use tag detail page + search
|
||||
|
||||
4. **No tag colors/icons:**
|
||||
- All tags display the same (gray chips)
|
||||
- No visual customization
|
||||
- Cannot assign colors or emojis
|
||||
|
||||
5. **10 tag limit per item:**
|
||||
- Tasks, notes, projects limited to 10 tags each
|
||||
- No warning when approaching limit
|
||||
- Must remove existing tag to add new one
|
||||
|
||||
6. **No tag usage statistics:**
|
||||
- Cannot see how many items use a tag (without visiting tag page)
|
||||
- No "popular tags" or "recently used"
|
||||
- Tag count not shown in tag list
|
||||
|
||||
### Technical Constraints
|
||||
|
||||
1. **Character restrictions:**
|
||||
- Invalid chars: `# % & { } \ < > * ? / $ ! ' " @ + \` | =`
|
||||
- Limits URL-friendly tag names
|
||||
- No emoji support
|
||||
|
||||
2. **50-character limit:**
|
||||
- Tag names truncated at 50 characters
|
||||
- Long descriptive names not possible
|
||||
|
||||
3. **Case-insensitive uniqueness:**
|
||||
- Cannot have `Work` and `work` as separate tags
|
||||
- Display preserves case, but uniqueness ignores it
|
||||
|
||||
4. **No batch operations:**
|
||||
- Cannot bulk-tag items
|
||||
- Cannot mass-rename tags
|
||||
- Must edit one at a time
|
||||
|
||||
---
|
||||
|
||||
## Related Documentation
|
||||
|
||||
- [Inbox Page](04-inbox-page.md) - Hashtag parsing and tag auto-creation
|
||||
- [Notes System](05-notes-system.md) - Tagging notes
|
||||
- [Projects](06-projects.md) - Tagging projects
|
||||
- [Today Page Sections](02-today-page-sections.md) - Task filtering
|
||||
- [Architecture Overview](architecture.md) - Technical architecture
|
||||
- [Development Workflow](development-workflow.md) - Working with the codebase
|
||||
|
||||
**Technical Implementation Files:**
|
||||
- Tag model: `/backend/models/tag.js`
|
||||
- Tag service: `/backend/modules/tags/service.js`
|
||||
- Tag controller: `/backend/modules/tags/controller.js`
|
||||
- Tag repository: `/backend/modules/tags/repository.js`
|
||||
- Tag validation: `/backend/modules/tags/validation.js`
|
||||
- Tag API routes: `/backend/modules/tags/routes.js`
|
||||
- Tags list component: `/frontend/components/Tags.tsx`
|
||||
- Tag detail component: `/frontend/components/Tag/TagDetails.tsx`
|
||||
- Tag input component: `/frontend/components/Tag/TagInput.tsx`
|
||||
- Tag modal: `/frontend/components/Tag/TagModal.tsx`
|
||||
- Tags service (frontend): `/frontend/utils/tagsService.ts`
|
||||
|
||||
**Database Tables:**
|
||||
- `tags` - Tag definitions
|
||||
- `tasks_tags` - Task-tag associations (many-to-many)
|
||||
- `notes_tags` - Note-tag associations (many-to-many)
|
||||
- `projects_tags` - Project-tag associations (many-to-many)
|
||||
|
||||
---
|
||||
|
||||
**Document Version:** 1.0.0
|
||||
**Last Updated:** 2026-03-14
|
||||
**Audience:** Developers, AI assistants, and end users
|
||||
|
|
@ -45,124 +45,92 @@
|
|||
|
||||
### Development Mode
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Development Flow │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Browser (http://localhost:8080) │
|
||||
│ ↓ │
|
||||
│ ┌─────────────────────┐ │
|
||||
│ │ Webpack Dev Server │ │
|
||||
│ │ Port: 8080 │ │
|
||||
│ │ - Hot reload │ │
|
||||
│ │ - Proxy /api/* │ │
|
||||
│ │ - Proxy /locales/*│ │
|
||||
│ └──────────┬──────────┘ │
|
||||
│ │ │
|
||||
│ │ Proxies requests to backend │
|
||||
│ ↓ │
|
||||
│ ┌─────────────────────┐ │
|
||||
│ │ Express Server │ │
|
||||
│ │ Port: 3002 │ │
|
||||
│ │ - API endpoints │ │
|
||||
│ │ - Session auth │ │
|
||||
│ │ - Rate limiting │ │
|
||||
│ └──────────┬──────────┘ │
|
||||
│ │ │
|
||||
│ ↓ │
|
||||
│ ┌─────────────────────┐ │
|
||||
│ │ Sequelize ORM │ │
|
||||
│ │ - Model layer │ │
|
||||
│ │ - Relationships │ │
|
||||
│ │ - Migrations │ │
|
||||
│ └──────────┬──────────┘ │
|
||||
│ │ │
|
||||
│ ↓ │
|
||||
│ ┌─────────────────────┐ │
|
||||
│ │ SQLite Database │ │
|
||||
│ │ (database.sqlite) │ │
|
||||
│ │ - WAL mode │ │
|
||||
│ │ - Optimized I/O │ │
|
||||
│ └─────────────────────┘ │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```mermaid
|
||||
graph TD
|
||||
Browser["Browser<br>http://localhost:8080"] --> WebpackDev["Webpack Dev Server<br>Port: 8080<br>- Hot reload<br>- Proxy /api/*<br>- Proxy /locales/*"]
|
||||
WebpackDev -->|Proxies requests| Express["Express Server<br>Port: 3002<br>- API endpoints<br>- Session auth<br>- Rate limiting"]
|
||||
Express --> Sequelize["Sequelize ORM<br>- Model layer<br>- Relationships<br>- Migrations"]
|
||||
Sequelize --> SQLite["SQLite Database<br>database.sqlite<br>- WAL mode<br>- Optimized I/O"]
|
||||
|
||||
style Browser fill:#1e3a5f,stroke:#4a9eff,color:#fff
|
||||
style WebpackDev fill:#5f4a1e,stroke:#ffa94a,color:#fff
|
||||
style Express fill:#5f1e4a,stroke:#ff4a9e,color:#fff
|
||||
style Sequelize fill:#1e5f1e,stroke:#4aff4a,color:#fff
|
||||
style SQLite fill:#4a1e5f,stroke:#9e4aff,color:#fff
|
||||
```
|
||||
|
||||
### Production Mode
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Production Flow │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Browser → Express Server (Port 3002) │
|
||||
│ ↓ │
|
||||
│ ├─ Serves static files from /dist │
|
||||
│ │ (compiled React app) │
|
||||
│ │ │
|
||||
│ └─ /api routes → Sequelize → SQLite │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```mermaid
|
||||
graph LR
|
||||
Browser["Browser"] --> Express["Express Server<br>Port 3002"]
|
||||
Express -->|Static files| Dist["/dist<br>compiled React app"]
|
||||
Express -->|/api routes| API["API Layer"]
|
||||
API --> Sequelize["Sequelize"]
|
||||
Sequelize --> SQLite["SQLite"]
|
||||
|
||||
style Browser fill:#1e3a5f,stroke:#4a9eff,color:#fff
|
||||
style Express fill:#5f1e4a,stroke:#ff4a9e,color:#fff
|
||||
style Dist fill:#5f4a1e,stroke:#ffa94a,color:#fff
|
||||
style API fill:#1e5f1e,stroke:#4aff4a,color:#fff
|
||||
style Sequelize fill:#1e5f1e,stroke:#4aff4a,color:#fff
|
||||
style SQLite fill:#4a1e5f,stroke:#9e4aff,color:#fff
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Data Model Hierarchy
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
User["User<br>Authentication, Settings, Timezone"]
|
||||
Area["Area<br>Work, Personal, Health"]
|
||||
Project["Project<br>Website Redesign, Marketing Campaign"]
|
||||
Task["Task<br>Design Homepage, Write Blog Post"]
|
||||
Subtask["Subtask<br>Create mockup, Get feedback"]
|
||||
Tag["Tag<br>urgent, design, bug"]
|
||||
Note["Note"]
|
||||
RecurringCompletion["RecurringCompletion<br>Completion history"]
|
||||
TaskEvent["TaskEvent<br>Audit log"]
|
||||
TaskAttachment["TaskAttachment<br>File attachments"]
|
||||
|
||||
User -->|1:N| Area
|
||||
Area -->|1:N| Project
|
||||
Project -->|1:N| Task
|
||||
Task -->|1:N| Subtask
|
||||
|
||||
Project -.->|N:M| Tag
|
||||
Task -.->|N:M| Tag
|
||||
Note -.->|N:M| Tag
|
||||
|
||||
Project -->|1:N| Note
|
||||
|
||||
Task -->|1:N| RecurringCompletion
|
||||
Task -->|1:N| TaskEvent
|
||||
Task -->|1:N| TaskAttachment
|
||||
|
||||
Task -.->|"parent_task_id<br>self-referential"| Task
|
||||
Task -.->|"recurring_parent_id<br>self-referential"| Task
|
||||
|
||||
style User fill:#1e3a5f,stroke:#4a9eff,color:#fff
|
||||
style Area fill:#5f4a1e,stroke:#ffa94a,color:#fff
|
||||
style Project fill:#5f1e4a,stroke:#ff4a9e,color:#fff
|
||||
style Task fill:#1e5f1e,stroke:#4aff4a,color:#fff
|
||||
style Subtask fill:#1e5f1e,stroke:#4aff4a,color:#fff
|
||||
style Tag fill:#4a1e5f,stroke:#9e4aff,color:#fff
|
||||
style Note fill:#5f4a1e,stroke:#ffa94a,color:#fff
|
||||
style RecurringCompletion fill:#2a2a2a,stroke:#666,color:#ccc
|
||||
style TaskEvent fill:#2a2a2a,stroke:#666,color:#ccc
|
||||
style TaskAttachment fill:#2a2a2a,stroke:#666,color:#ccc
|
||||
```
|
||||
┌────────────────────────────────────────────────────────────────┐
|
||||
│ User │
|
||||
│ (Authentication, Settings, Timezone) │
|
||||
└───────────────────┬────────────────────────────────────────────┘
|
||||
│
|
||||
│ 1:N (One user has many areas)
|
||||
↓
|
||||
┌───────────────────────┐
|
||||
│ Area │ (Optional organizational layer)
|
||||
│ (e.g., Work, │
|
||||
│ Personal, Health) │
|
||||
└──────────┬────────────┘
|
||||
│
|
||||
│ 1:N (One area has many projects)
|
||||
↓
|
||||
┌───────────────────────┐ ┌──────────┐
|
||||
│ Project │────────────────│ Tag │
|
||||
│ (Website Redesign, │ N:M │ (urgent,│
|
||||
│ Marketing Campaign) │ │ design, │
|
||||
└──────────┬────────────┘ │ bug) │
|
||||
│ └─────┬────┘
|
||||
│ 1:N (One project has │
|
||||
│ many tasks) │ N:M
|
||||
↓ │
|
||||
┌───────────────────────┐ │
|
||||
│ Task │────────────────────┘
|
||||
│ (Design Homepage, │ N:M (Tasks can
|
||||
│ Write Blog Post) │ have tags)
|
||||
└──────────┬────────────┘
|
||||
│
|
||||
│ 1:N (Task can have subtasks)
|
||||
↓
|
||||
┌───────────────────────┐
|
||||
│ Subtask │ (Self-referential)
|
||||
│ (Create mockup, │
|
||||
│ Get feedback) │
|
||||
└───────────────────────┘
|
||||
|
||||
**Relationship Key:**
|
||||
- Solid lines (→) represent one-to-many (1:N) relationships
|
||||
- Dotted lines (-.→) represent many-to-many (N:M) or special relationships
|
||||
|
||||
Additional Relationships:
|
||||
|
||||
Project 1:N Note (One project has many notes)
|
||||
Note N:M Tag (Notes can have tags)
|
||||
|
||||
Task → RecurringCompletion (Tracks completion history)
|
||||
Task → TaskEvent (Audit log of all changes)
|
||||
Task → TaskAttachment (File attachments)
|
||||
|
||||
Special Task Relationships:
|
||||
- parent_task_id: Links subtasks to parent task
|
||||
- recurring_parent_id: Links recurring instances to original pattern
|
||||
```
|
||||
**Special Task Relationships:**
|
||||
- `parent_task_id`: Links subtasks to parent task (self-referential)
|
||||
- `recurring_parent_id`: Links recurring instances to original pattern (self-referential)
|
||||
|
||||
---
|
||||
|
||||
|
|
|
|||
282
docs/backups.md
Normal file
282
docs/backups.md
Normal file
|
|
@ -0,0 +1,282 @@
|
|||
# Backups & Restoration
|
||||
|
||||
[← Back to Index](../CLAUDE.md)
|
||||
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
Tududi automatically creates SQLite database file backups before migrations and on startup to protect your data. These backups ensure you have a recovery point if a migration fails or if you need to restore to a previous state.
|
||||
|
||||
---
|
||||
|
||||
## Automatic SQLite File Backups
|
||||
|
||||
### When Backups Are Created
|
||||
|
||||
SQLite database file backups are **automatically created** in these scenarios:
|
||||
|
||||
1. **Before migrations** - Every time the app starts and finds an existing database
|
||||
2. **On startup** - Before running any database operations (Docker/production)
|
||||
3. **Manual trigger** - Via the backup script
|
||||
|
||||
**Location:** `/backend/cmd/start.sh` (lines 9-78)
|
||||
|
||||
### Backup File Location
|
||||
|
||||
- **Development:** `/backend/db/db-backup-YYYYMMDDHHMMSS.sqlite3`
|
||||
- **Docker/Production:** `/app/backend/db/db-backup-YYYYMMDDHHMMSS.sqlite3` (mounted volume)
|
||||
|
||||
### Backup Retention Policy
|
||||
|
||||
The system automatically manages backup retention with these rules:
|
||||
|
||||
| Timeframe | Retention Policy |
|
||||
|-----------|------------------|
|
||||
| **Today** | Keep up to 4 most recent backups |
|
||||
| **Past 7 days** | Keep 1 backup per day (most recent) |
|
||||
| **Older than 7 days** | Automatically deleted |
|
||||
|
||||
**Example:**
|
||||
```
|
||||
db-backup-20260315083000.sqlite3 ← Today (backup #1)
|
||||
db-backup-20260315070000.sqlite3 ← Today (backup #2)
|
||||
db-backup-20260314193000.sqlite3 ← Yesterday (only 1 kept)
|
||||
db-backup-20260313100000.sqlite3 ← 2 days ago (only 1 kept)
|
||||
db-backup-20260308120000.sqlite3 ← Automatically deleted (>7 days)
|
||||
```
|
||||
|
||||
### How Automatic Backups Work
|
||||
|
||||
When the app starts (via `npm start` or Docker):
|
||||
|
||||
1. Check if `DB_FILE` exists
|
||||
2. If exists, call `backup_db()` function
|
||||
3. Clean old backups based on retention policy
|
||||
4. Create timestamped copy: `cp $DB_FILE $backup_file`
|
||||
5. Run migrations: `npx sequelize-cli db:migrate`
|
||||
6. Start application
|
||||
|
||||
**Critical:** Backups are created **before** migrations run, ensuring you have a recovery point if a migration fails.
|
||||
|
||||
---
|
||||
|
||||
## Restoring from SQLite File Backup
|
||||
|
||||
### Quick Restore (Development)
|
||||
|
||||
```bash
|
||||
# 1. Stop the application
|
||||
npm stop # or Ctrl+C
|
||||
|
||||
# 2. List available backups
|
||||
ls -lh backend/db/db-backup-*.sqlite3
|
||||
|
||||
# 3. Identify the backup to restore (e.g., db-backup-20260314193000.sqlite3)
|
||||
|
||||
# 4. Backup current state (optional but recommended)
|
||||
cp backend/db/development.sqlite3 backend/db/development.sqlite3.before-restore
|
||||
|
||||
# 5. Restore the backup
|
||||
cp backend/db/db-backup-20260314193000.sqlite3 backend/db/development.sqlite3
|
||||
|
||||
# 6. Restart the application
|
||||
npm start
|
||||
```
|
||||
|
||||
### Restore in Docker
|
||||
|
||||
```bash
|
||||
# 1. Stop the container
|
||||
docker-compose down
|
||||
|
||||
# 2. Access the host volume (find your volume location)
|
||||
docker volume inspect tududi_db_data
|
||||
|
||||
# 3. Navigate to the mount point and list backups
|
||||
cd /var/lib/docker/volumes/tududi_db_data/_data
|
||||
ls -lh db-backup-*.sqlite3
|
||||
|
||||
# 4. Backup current state
|
||||
cp production.sqlite3 production.sqlite3.before-restore
|
||||
|
||||
# 5. Restore from backup
|
||||
cp db-backup-20260314193000.sqlite3 production.sqlite3
|
||||
|
||||
# 6. Restart the container
|
||||
docker-compose up -d
|
||||
```
|
||||
|
||||
### Emergency Restore (Production)
|
||||
|
||||
If a migration fails and the app won't start:
|
||||
|
||||
```bash
|
||||
# The start script creates a backup BEFORE migrations
|
||||
# So the most recent backup is from before the failed migration
|
||||
|
||||
cd backend/db
|
||||
|
||||
# Find the most recent backup (will be from just before failure)
|
||||
ls -lt db-backup-*.sqlite3 | head -1
|
||||
|
||||
# Restore it
|
||||
cp db-backup-20260315083000.sqlite3 production.sqlite3
|
||||
|
||||
# Try starting again
|
||||
npm start
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Best Practices
|
||||
|
||||
### 1. Before Major Changes
|
||||
|
||||
Create a manual backup before:
|
||||
- Upgrading Tududi to a new version
|
||||
- Running manual migrations
|
||||
- Bulk data operations
|
||||
- Testing new features
|
||||
|
||||
```bash
|
||||
# Quick manual backup (development)
|
||||
cp backend/db/development.sqlite3 backend/db/manual-backup-$(date +%Y%m%d%H%M%S).sqlite3
|
||||
```
|
||||
|
||||
### 2. External Backups
|
||||
|
||||
For production:
|
||||
- Copy `/backend/db/*.sqlite3` to external storage weekly
|
||||
- Test restore procedures periodically
|
||||
|
||||
### 3. Docker Volume Backups
|
||||
|
||||
Backup the entire Docker volume:
|
||||
|
||||
```bash
|
||||
# Backup Docker volume
|
||||
docker run --rm \
|
||||
-v tududi_db_data:/data \
|
||||
-v $(pwd):/backup \
|
||||
alpine tar czf /backup/tududi-db-backup-$(date +%Y%m%d).tar.gz -C /data .
|
||||
|
||||
# Restore Docker volume
|
||||
docker run --rm \
|
||||
-v tududi_db_data:/data \
|
||||
-v $(pwd):/backup \
|
||||
alpine tar xzf /backup/tududi-db-backup-20260314.tar.gz -C /data
|
||||
```
|
||||
|
||||
### 4. Migration Rollback Strategy
|
||||
|
||||
If a migration fails:
|
||||
|
||||
1. **Don't panic** - automatic backup was created
|
||||
2. Stop the application
|
||||
3. Restore the most recent automatic backup (created before migration)
|
||||
4. Investigate the migration issue
|
||||
5. Fix the migration or rollback: `npm run migration:undo`
|
||||
|
||||
### 5. Test Restore Procedures
|
||||
|
||||
Periodically test that backups can be restored:
|
||||
|
||||
```bash
|
||||
# Test restore in a safe environment
|
||||
cp backend/db/db-backup-20260314193000.sqlite3 backend/db/test-restore.sqlite3
|
||||
|
||||
# Verify the backup file is readable
|
||||
sqlite3 backend/db/test-restore.sqlite3 "SELECT COUNT(*) FROM Tasks;"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Backup Commands Reference
|
||||
|
||||
```bash
|
||||
# Manual backup (development)
|
||||
cp backend/db/development.sqlite3 backend/db/manual-backup-$(date +%Y%m%d%H%M%S).sqlite3
|
||||
|
||||
# Manual backup (production)
|
||||
cp backend/db/production.sqlite3 backend/db/manual-backup-$(date +%Y%m%d%H%M%S).sqlite3
|
||||
|
||||
# List all backups
|
||||
ls -lh backend/db/db-backup-*.sqlite3
|
||||
|
||||
# Restore specific backup
|
||||
cp backend/db/db-backup-20260314193000.sqlite3 backend/db/development.sqlite3
|
||||
|
||||
# Verify backup file integrity
|
||||
sqlite3 backend/db/db-backup-20260314193000.sqlite3 "PRAGMA integrity_check;"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Backup File Not Found
|
||||
|
||||
**Problem:** Can't find automatic backup after startup failure
|
||||
|
||||
**Solution:** Check if database existed before startup. Backups are only created for existing databases.
|
||||
|
||||
```bash
|
||||
# New installations won't have backups yet
|
||||
# First run creates database, second run creates first backup
|
||||
```
|
||||
|
||||
### Restore Fails with "Database is locked"
|
||||
|
||||
**Problem:** SQLite database is locked during restore
|
||||
|
||||
**Solution:** Ensure the application is fully stopped
|
||||
|
||||
```bash
|
||||
# Kill all node processes
|
||||
pkill -f "node.*tududi"
|
||||
|
||||
# Verify no processes are using the database
|
||||
lsof backend/db/development.sqlite3
|
||||
|
||||
# Then attempt restore
|
||||
```
|
||||
|
||||
### Large Backup Files
|
||||
|
||||
**Problem:** Backup files consuming too much space
|
||||
|
||||
**Solution:** Automatic cleanup runs on every startup. For manual cleanup:
|
||||
|
||||
```bash
|
||||
# Delete backups older than 7 days manually
|
||||
find backend/db -name "db-backup-*.sqlite3" -mtime +7 -delete
|
||||
|
||||
# Or keep only last 10 backups
|
||||
ls -t backend/db/db-backup-*.sqlite3 | tail -n +11 | xargs rm
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Implementation Details
|
||||
|
||||
### Backup Script Location
|
||||
|
||||
The automatic backup script is located at `/backend/cmd/start.sh` (lines 9-78).
|
||||
|
||||
**Key functions:**
|
||||
- `backup_db()` - Creates timestamped SQLite file copy
|
||||
- Automatic cleanup based on retention policy
|
||||
- Runs before every migration
|
||||
|
||||
---
|
||||
|
||||
## Related Documentation
|
||||
|
||||
- [Database & Migrations](database.md) - Schema changes and migrations
|
||||
- [Development Workflow](development-workflow.md) - Database management commands
|
||||
- [Architecture](architecture.md) - Data model relationships
|
||||
|
||||
---
|
||||
|
||||
[← Back to Index](../CLAUDE.md)
|
||||
Loading…
Add table
Add a link
Reference in a new issue