- Add explicit note about # and @ being syntax markers, not part of tag names
- Clarify that #hashtag example shows invalid character in tag name
- Add cross-reference to Inbox page documentation
- Update workflow examples to clarify Inbox syntax vs actual tag names
- Bump document version to 1.0.1
Fix calculateInitialDueDate() to properly handle recurrence_weekdays array
when creating or updating weekly recurring tasks with multiple weekdays.
Previously, the function only checked for recurrence_weekday (singular) and
ignored recurrence_weekdays (plural array), causing tasks with multiple
weekdays to incorrectly get today's date instead of the next occurrence.
Changes:
- Add support for recurrence_weekdays array in calculateInitialDueDate()
- Fix buildUpdateAttributes() to pass recurrence_weekdays parameter
- Add 8 unit tests covering multiple weekdays scenarios
- Add 3 integration tests for API CREATE and UPDATE operations
- Maintain backward compatibility with single recurrence_weekday
The fix mirrors the proven logic from calculateWeeklyRecurrence() in
recurringTaskService.js and properly handles edge cases like unsorted
arrays, wrapping to next week, and JSON string parsing.
Fixes#974
Add a prominent section explaining that feature PRs require prior
discussion (GitHub issue, Discussions, or direct communication with
maintainer). This helps ensure alignment with project vision, avoids
wasted effort, enables collaborative design, and prevents duplicate work.
The section includes:
- Clear requirement statement with warning
- Explanation of why this is important
- Step-by-step guide on how to contribute features
- Clarification that this applies to features, not bug fixes
Also updated Before You Start, PR Requirements, and Questions sections
to reference and reinforce this requirement.
* Fix project name overflow and add validation
This commit addresses issue #971 by implementing both UI fixes and
validation to prevent excessively long project names.
Changes:
1. Add word-break and line-clamp to ProjectBanner.tsx to handle
overflow gracefully with line-clamp-3 for names
2. Add frontend validation in ProjectModal.tsx limiting names to
6 words maximum
3. Add backend validation in project.js model with custom wordCount
validator
4. Show user-friendly error messages when validation fails
This ensures project names remain concise and UI-friendly while
preventing the extreme overflow cases that were possible before.
Fixes#971
* Add overflow-hidden to make line-clamp work properly
The line-clamp utility requires explicit overflow-hidden to function
correctly. Without it, the text continues to display in full rather
than being truncated with ellipsis.
* Fix line-clamp using inline CSS styles
Tailwind's line-clamp utilities weren't working, so switched to using
inline styles with the standard CSS approach:
- display: -webkit-box
- -webkit-line-clamp: 3
- -webkit-box-orient: vertical
This ensures the text truncation works reliably across browsers.
* Use Tailwind line-clamp utilities (already defined in CSS)
The project already has line-clamp-1/2/3 utilities properly defined
in tailwind.css with all the necessary webkit properties. Simplified
the component to use these existing utilities instead of inline styles.
* Add dedicated CSS classes with !important for line-clamp
Created custom project-name-clamp and project-desc-clamp classes
with !important flags to ensure they override any conflicting styles.
This should finally fix the text truncation issue.
* Use component-scoped styles for line-clamp
Adding inline style tag in the component to ensure the line-clamp
CSS is definitely loaded and applied. This bypasses any potential
issues with external CSS compilation or loading order.
* Change project name line-clamp from 3 to 2 lines
Limiting project name display to 2 lines with ellipsis for better
visual density and cleaner appearance.
* Increase line-height for project name in banner
Added line-height: 1.3 to project name for better readability
and visual spacing between lines.
* Fix Today page task completion issues
- Fix completed task border color staying as priority color
- Add isInCompletedSection prop to TaskItem for explicit completed state
- Tasks in completed section now always show green border regardless of priority
- Fixes race condition where status wasn't updated during optimistic UI update
- Fix completed task reappearing after unmarking and page refresh
- Add defensive check in backend to force clear completed_at when status is not DONE
- Add development logging in tasksService for debugging completion toggle
- Ensures database state is consistent even if handleCompletionStatus doesn't clear it
- Update TaskList and TasksToday components to pass isInCompletedSection prop
- Explicitly marks tasks rendered in the completed section
- Prevents border color flickering during state transitions
* Add comprehensive logging to debug completion issues
* Fix duplicate API requests causing completion state issues
- Separate state update logic from API call in handleTaskUpdate
- Create new updateTaskInState function for state-only updates
- Pass onTaskCompletionToggle to completed section to avoid duplicate calls
- This fixes the persistence issue where unmarked tasks came back after refresh
- Completion toggles now only make ONE API call instead of two
* Add debug logging to updateTaskInState
Fixes issue where Sequelize wasn't detecting changes to the
channel_sent_at JSON field, causing markChannelAsSent() to not
persist updates to the database.
This caused the same notification to be sent via Telegram every
15 minutes (on each scheduler run) because the rate limiting
timestamp was never saved.
The fix adds this.changed('channel_sent_at', true) before save()
to explicitly mark the field as modified, which is required for
Sequelize to detect changes to JSON fields.
Impact: Reduces duplicate Telegram notifications from every 15min
to at most once per 24 hours per task.
* Fix recurring task initial due date calculation to match recurrence pattern
Resolves#963
When creating a recurring task without an explicit due date, the system
was incorrectly setting it to "today" regardless of the recurrence pattern.
This caused issues where:
- Monthly tasks set to recur on a specific day (e.g., 28th) would show the
wrong due date (today/yesterday instead of the 28th)
- Tasks wouldn't appear correctly in the Upcoming view
- The base due_date didn't match the recurrence_month_day setting
Changes:
- Add calculateInitialDueDate() helper to compute correct first occurrence
- For monthly recurrence with specific day: calculate next occurrence of that day
- For weekly recurrence with specific weekday: calculate next occurrence of that weekday
- For other types (daily, etc.): maintain current behavior (use today)
- Apply same logic to both task creation and updates
Tests:
- Add comprehensive test suite (9 new tests) covering:
- Monthly recurrence with future day in current month
- Monthly recurrence with past day (should use next month)
- Weekly recurrence with specific weekday
- Daily recurrence (should still default to today)
- Edge cases (31st of month, explicitly provided dates)
- Task updates adding recurrence
All 54 recurring task tests pass.
* Fix UTC timezone bug in recurring task expansion and add comprehensive tests
- Fix expandRecurringTasks() to use setUTCHours instead of setHours
- Add 42 unit tests for recurringTaskService UTC consistency
- Add 24 DST transition tests (spring forward/fall back)
- Verify no occurrence skips or duplicates during DST
- Test month-end handling, leap years, and timezone boundaries
Resolves#960
The update_project endpoint now properly handles clearing nullable fields
(due_date_at, area_id, priority, image_url) when set to null or empty string.
Previously, sending an empty string would not clear the field. Now empty
strings are explicitly converted to null for database consistency.
Changes:
- Convert empty strings to null for nullable fields in project update
- Add tests for clearing due_date_at with null and empty string
- Apply same fix to area_id, priority, and image_url for consistency
* Fix visual overlap between subtasks icon and status dropdown
Increased right padding from pr-44 to pr-48 in TaskHeader desktop view
to prevent the subtasks toggle button from overlapping with the expanded
status dropdown icon.
Fixes#957
* Improve fix for subtasks icon and status dropdown overlap
- Removed flex-1 from task name container to prevent unnecessary expansion
- Wrapped SubtasksToggleButton in flex-shrink-0 div to maintain its width
- Increased right padding from pr-48 to pr-56 for better spacing
- This prevents the subtasks icon from overlapping with the status dropdown
Fixes#957
* Fix subtasks icon placement to be adjacent to task name
Moved SubtasksToggleButton to be directly after the task name within
the same flex container, instead of in a separate container. This positions
the icon immediately next to the task name on the left, rather than being
pushed to the right where it overlaps with the status dropdown.
Fixes#957
* Fix date format inconsistency in Task detail screen (#938)
Replace browser-dependent toLocaleDateString() with explicit country-based
date formatting to ensure consistent date formats based on user's timezone.
Problem:
- User with English language + Greek timezone saw MM/DD/YYYY format
- Expected DD/MM/YYYY format based on timezone/country
- Browser's Intl.DateTimeFormat had incomplete locale support for
combined locales like "en-GR"
Solution:
- Add country-to-format mapping in dateUtils.ts (60+ countries)
- New formatDateByCountry() for dates (DD/MM/YYYY, MM/DD/YYYY, YYYY/MM/DD)
- New formatDateTimeByCountry() for datetimes with 24h time
- Update TaskDueDateCard and TaskDeferUntilCard to use new functions
- Uses date-fns for consistent cross-browser formatting
Testing:
- Added 40 comprehensive test cases covering all format types
- Verified with Greece (DD/MM), US (MM/DD), Japan (YYYY/MM/DD)
- All tests passing
Fixes#938
* chore: remove unused import in dateUtils.ts
* Fix Telegram notification spam with channel-level rate limiting
Addresses issue #950 where Telegram notifications were sent excessively
(96-288 messages per day per task) due to the delete-and-recreate pattern
added in commit 105a913a to fix navbar notification pile-up.
Changes:
- Add channel_sent_at JSON field to notifications table to track when
each channel (telegram, email, push) was last sent
- Add helper methods to notification model:
- markChannelAsSent(channel): Records send timestamp
- wasChannelRecentlySent(channel, threshold): Checks if sent within 24h
- Modify sendTelegramNotification() to check rate limit before sending
- Update service layer (dueTaskService, deferredTaskService,
dueProjectService) to preserve channel_sent_at when recreating
notifications
- Add comprehensive unit and integration tests (20 tests, all passing)
Impact:
- Reduces Telegram notifications from 96-288/day to 1/day per item
- Preserves in-app notification refresh behavior (every 5-15 min)
- Maintains navbar pile-up fix from original commit
- Rate limit configurable (default: 24 hours)
Fixes#950
* Fix linting and formatting issues
* Fix integration test that was trying to access private function
* Fix prettier formatting in integration test
Both Navbar.tsx and Login.tsx hardcode absolute paths for the logo
images ('/wide-logo-light.png', '/wide-logo-dark.png'). This breaks
when tududi is served behind a reverse proxy with a subpath, such as
Home Assistant ingress.
The getAssetPath() helper from config/paths already handles base path
detection (including HA ingress auto-detection), and Login.tsx already
uses it for the login graphic. This commit applies the same pattern to
the logo images.
Changes:
- Navbar.tsx: add getAssetPath to import, use it for logo src
- Login.tsx: use getAssetPath for logo src (was already imported)
* Fix notification deduplication to prevent pile-up in navbar (#944)
When tasks/projects remained pending for multiple days, duplicate
notifications accumulated in the navbar instead of showing only the
most recent one.
Updated notification services to properly handle existing notifications:
- Delete unread notifications before creating new ones
- Respect dismissed notifications (don't recreate)
- Respect read notifications (don't duplicate)
Changes:
- Updated dueTaskService, deferredTaskService, and dueProjectService
- Added comprehensive unit tests with 8 test cases
Fixes#944
* Fix lint errors and add GitHub bug template reminder to docs
* fixup! Fix date format inconsistency in Defer Until field
* fixup! fixup! Fix date format inconsistency in Defer Until field
* fixup! fixup! fixup! Fix date format inconsistency in Defer Until field
Fixes#938
The Defer Until field was using i18n.language directly instead of
resolveUserLocale(), causing it to display dates in MM/DD/YYYY format
(US default) regardless of timezone setting.
Now uses the same locale resolution pattern as the Due Date field,
which combines language with timezone-derived country code (e.g.,
"en" + Greek timezone → "en-GR" → DD/MM/YYYY format).
Changes:
- Import useMemo and resolveUserLocale
- Add displayLocale memo to resolve timezone-aware locale
- Use displayLocale instead of i18n.language in toLocaleString()
* Increase coverage
* Add comprehensive LLM development documentation
- Add CLAUDE.md as main documentation index
- Create 8 detailed documentation files in docs/:
- architecture.md: Tech stack, data models, auth system
- directory-structure.md: Complete file tree with paths
- backend-patterns.md: Module architecture and patterns
- database.md: Models, migrations, and workflows
- development-workflow.md: Setup and daily development
- code-conventions.md: Style guide and best practices
- testing.md: Test organization and patterns
- common-tasks.md: How-to guides for frequent tasks
- Update .gitignore to allow project-level CLAUDE.md
- 4,285 lines of comprehensive documentation
- Organized for easy navigation with cross-links
- LLM-optimized with absolute paths and code examples
* fixup! Add comprehensive LLM development documentation
Remove isSidebarOpen from the useEffect dependency array and from the
API request parameters in Tasks.tsx. The sidebar visibility state has no
bearing on which tasks should be fetched, so toggling it should not
trigger a data re-fetch.
The toggle handler required onSubtaskUpdate callback to make the API
call, but TaskSubtasksCard never provided it. Extract a shared handler
that calls toggleTaskCompletion for persisted subtasks regardless of
whether onSubtaskUpdate is provided, falling back to updating local
state via onSubtasksChange.
When toggling subtask completion in TaskSubtasksSection, the toggle handler
required onSubtaskUpdate callback to make the API call. Components like
TaskSubtasksCard don't pass this callback, so toggling fell through to the
local-only state update path, never sending a network request.
Add an intermediate code path: when the subtask is persisted but
onSubtaskUpdate is not provided, call toggleTaskCompletion() directly
to persist the change, then update local state.
Fixes#920
The SubtasksToggleButton was placed inside the same flex container as
the task name with truncate, causing it to be squeezed to zero width.
Wrap the task name in an inner flex container (matching the upcoming
view layout) so the button stays visible.
Added proper ordering configuration (separate: true and order clause)
to subtask queries in query-builders.js. This ensures subtasks are
always returned in the correct order based on the 'order' field and
'created_at' timestamp, preventing the intermittent reordering bug
that occurred after checking subtasks as complete and reloading.
Fixes#921
Added proper ordering configuration (separate: true and order clause)
to subtask queries in query-builders.js. This ensures subtasks are
always returned in the correct order based on the 'order' field and
'created_at' timestamp, preventing the intermittent reordering bug
that occurred after checking subtasks as complete and reloading.
Fixes#921
* Add projects with due dates to upcoming view
Fetch and include projects with due_date_at in the upcoming range
when type=upcoming is requested. Projects are filtered by ownership
or permissions and exclude completed/archived projects.
Part of #925
* Display upcoming projects in Upcoming view
Add UI to show projects with due dates in the Upcoming view.
Projects are displayed in a separate section below tasks with
links to project details and formatted due dates.
Fixes#925
* Fix prettier formatting errors
Transform project data in createNote to match updateNote behavior.
This ensures project_uid is properly extracted from nested project
object when creating notes with project associations.
Fixes#926
Date fields in the task edit page used i18n.language (e.g. "en") to
determine date format, giving MM/DD for English even when the user's
timezone indicates a DD/MM region (e.g. Europe/Athens).
Enhance resolveUserLocale to derive the country from the user's
timezone and combine it with the language (e.g. "en" + "GR" = "en-GR")
so date formatting follows regional conventions.
Recurring task templates had their names replaced with the recurrence
type label (e.g. "Weekly") in search results, making them unrecognizable.
Skip the display name transform when serializing tasks for search.