Commit Graph

13459 Commits

Author SHA1 Message Date
kolaente d152fa8475 fix(gantt): use reactive date range in Flatpickr config to prevent reset on task update
Replace static initialDateRange snapshot with reactive filters.value
references inside the computed flatPickerConfig. This ensures the
Flatpickr defaultDate always reflects the current user-selected range
instead of the mount-time values.

Ref #2462
2026-04-05 11:31:37 +00:00
Frederick [Bot] 23d9cbc664 [skip ci] Updated swagger docs 2026-04-05 10:05:20 +00:00
kolaente 297c0c1d8b fix(e2e): seed project in empty-tasks overview test
With truncateAll wiping all tables, the test user has no projects,
so ShowTasks never renders and tasksLoaded stays false — meaning
ImportHint (which is gated on tasksLoaded) never appears. Seed a
project with default views so the empty-state hint is visible.
2026-04-05 09:48:09 +00:00
kolaente adcc74b056 fix: make apiContext auto-fixture and fix remaining view ID conflicts 2026-04-05 09:48:09 +00:00
kolaente 4888b1d8ca fix: move truncateAll to apiContext fixture and fix view ID conflicts 2026-04-05 09:48:09 +00:00
kolaente aa1202fea8 chore: remove redundant truncate calls now that all tables are wiped before each test 2026-04-05 09:48:09 +00:00
kolaente 2ee8ad4109 feat: truncate all tables before each e2e test for clean isolation 2026-04-05 09:48:09 +00:00
kolaente f477da48ec feat: add Factory.truncateAll() helper for e2e tests 2026-04-05 09:48:09 +00:00
kolaente e9a26b9088 feat: add DELETE /test/all endpoint to truncate all tables 2026-04-05 09:48:09 +00:00
kolaente 6a3dd8b281 feat: add TruncateAllTables function for e2e test isolation 2026-04-05 09:48:09 +00:00
kolaente 0834d19f9c
feat: remove flexsearch dependency and replace with simple string filtering (#2542) 2026-04-04 21:41:25 +02:00
kolaente f5752b97e9
feat: add inline PDF viewer for task attachments (#2541) 2026-04-04 21:25:54 +02:00
renovate[bot] 33d607714d chore(deps): update dependency caniuse-lite to v1.0.30001785 2026-04-04 18:38:07 +00:00
kolaente 841b458a5f fix: pass saved filter context to subtask visibility check
When viewing tasks through a saved filter, pass isFilteredView=true
to shouldShowTaskInListView so subtasks are not incorrectly hidden.

Ref: #2494
2026-04-03 19:25:46 +00:00
kolaente d895053d2e fix: show subtasks in saved filter views regardless of parent presence
Add isFilteredView parameter to shouldShowTaskInListView() that skips
the parent-hiding logic when viewing tasks through a saved filter.
This ensures all filter-matching tasks are shown.

Ref: #2494
2026-04-03 19:25:46 +00:00
kolaente 616ac8b95f test: add failing tests for subtask visibility in filtered views
Add test cases to verify that subtasks are shown in saved filter views
regardless of whether their parent task is also in the results.

Ref: #2494
2026-04-03 19:25:46 +00:00
kolaente 174c67cfd8 fix(gantt): isolate chart stacking context so date picker renders above it
Sets position: relative and z-index: 0 on .gantt-chart-container to
create a new stacking context. This ensures z-index values inside the
Gantt chart (e.g. the sticky timeline header) cannot compete with the
Flatpickr popup that renders at the body level.

Ref #2337
2026-04-03 19:07:49 +00:00
kolaente f25147d09c fix(gantt): ensure chart container fills viewport width for narrow date ranges
Adds min-inline-size: 100% to .gantt-container so the scrollable area
never appears narrower than the card width, even with short date ranges.

Ref #2337
2026-04-03 19:07:49 +00:00
kolaente 48a91ce32c fix(frontend): prevent drag handle from overlapping project color in sidebar
Moves the drag handle inside the color-bubble-wrapper so both elements
share the same positioned container, eliminating the absolute positioning
mismatch that caused the overlap. Fixes #2493.
2026-04-03 19:05:10 +00:00
kolaente a57cbd3e51 feat: add tooltip to readonly checkbox explaining why it's not clickable 2026-04-03 19:01:45 +00:00
kolaente c5bce07a25 test(e2e): add test for read-only checkbox on overview page
Verifies that tasks from read-only shared projects have disabled
checkboxes on the overview page, while tasks from owned projects
remain interactive.

Refs #2399
2026-04-03 19:01:45 +00:00
kolaente 063155a46b fix(overview): disable checkbox for read-only tasks on overview page
The Overview's ShowTasks component was not passing the canMarkAsDone prop
to SingleTaskInProject, which defaults to true. This caused read-only tasks
to show an interactive checkbox even though the user doesn't have write
permission.

Use the project's maxPermission from the project store to determine if the
user can mark the task as done. Also fix the disabled condition to use OR
logic so the checkbox is disabled when ANY condition applies: archived,
disabled, or when the user lacks write permission.

Fixes #2399
2026-04-03 19:01:45 +00:00
kolaente 4f232957c4 fix(auth): add retry and logging for token refresh failures
Add a single retry with a 1-second delay in the 401 interceptor's
doRefresh() before giving up on token renewal. This handles transient
failures like brief network blips or server restarts without immediately
logging the user out.

Also log refresh failures via console.warn so the reason is visible
in browser DevTools for easier diagnosis.

Ref: #2391
2026-04-03 18:45:59 +00:00
kolaente fd8a8ecba2 fix(auth): normalize API base URL to prevent refresh cookie path mismatch
When window.API_URL lacks a trailing slash, axios resolves relative URLs
by stripping path segments, causing the refresh request to hit a different
path than the cookie's Path attribute. The browser then omits the HttpOnly
refresh cookie, silently breaking token renewal and logging users out
after the short JWT TTL expires.

Extract a getApiBaseUrl() helper that ensures baseURL always ends with
'/' so relative URL resolution preserves the full path, matching the
cookie scope.

Ref: #2391
2026-04-03 18:45:59 +00:00
kolaente 6299bea794 fix(mail): guard log calls in GetMailDomain and fix hostname-dependent tests
GetMailDomain called log.Warningf which panics when the logger is not
initialized (e.g. in unit tests). Add log.IsInitialized() guard.

Also fix TestGetThreadID tests that hardcoded "vikunja" as the expected
fallback domain - on CI the os.Hostname() fallback produces a different
value. Tests now dynamically compute the expected domain.
2026-04-03 18:30:39 +00:00
kolaente 85a350749b refactor(mail): use CryptoRandomString for Message-ID generation
Replace manual rand.Read + hex.EncodeToString with the existing
utils.CryptoRandomString helper for generating the random part
of the Message-ID header.
2026-04-03 18:30:39 +00:00
kolaente 07aa3c1b04 fix(mail): fall back to os.Hostname() before hardcoded domain
When the public URL is not configured, GetMailDomain() now tries
os.Hostname() before falling back to the hardcoded "vikunja" string,
and logs a warning in both fallback cases.
2026-04-03 18:30:39 +00:00
kolaente 5249366aa3 refactor(models): use shared GetMailDomain in getThreadID 2026-04-03 18:30:39 +00:00
kolaente bbcd0648ac fix(mail): set RFC 5322 compliant Message-ID using public URL domain
Fixes #2522
2026-04-03 18:30:39 +00:00
kolaente 2f9ff51c60 feat(mail): add GetMailDomain helper for RFC 5322 compliant email IDs 2026-04-03 18:30:39 +00:00
renovate[bot] 12ba9ff985 chore(deps): update dev-dependencies 2026-04-03 17:52:24 +00:00
kolaente a628c99006 test: assert position existence instead of conditional skip
Replace if-exists guard with require.True assertion so a
missing position correctly fails the test.
2026-04-03 17:26:55 +00:00
kolaente ce3e56f192 refactor: use nested map for position conflict tracking
Replace struct key map[viewPos]bool with nested
map[int64]map[float64]bool for cleaner lookups.
2026-04-03 17:26:55 +00:00
kolaente 104c8eadae fix: use InDelta for float comparison in tests 2026-04-03 17:26:55 +00:00
kolaente 0c3d01099f fix: detect and resolve position conflicts during task creation
Fixes #2495, fixes #2400

When tasks are created, setTaskInBucketInViews() assigns positions
without checking for conflicts. If two tasks get the same position value,
their order scrambles on reload. This adds a conflict check after
bulk-inserting positions, reusing the existing resolution logic from the
update path.
2026-04-03 17:26:55 +00:00
kolaente c6e79926f0 fix: add position conflict resolution for batch-inserted positions
Add resolvePositionConflictsAfterInsert() which checks newly inserted
task positions for duplicate position values within the same view and
resolves them using existing conflict resolution logic.
2026-04-03 17:26:55 +00:00
kolaente 88c2f0a289 fix(project): remove non-existent columns from UpdateProject column list
The UpdateProject function referenced done_bucket_id and default_bucket_id
in its column update list, but these columns belong to the project_views
table, not the projects table. This caused SQL errors when archiving or
updating a project on MySQL/PostgreSQL.

Also adds a test for archiving a non-archived project.

Fixes #2459
2026-04-03 16:59:05 +00:00
renovate[bot] ea54f3eb85 chore(deps): update dependency ws to v8.20.0 2026-04-03 16:57:34 +00:00
renovate[bot] b69564a77c chore(deps): pin dependencies 2026-04-03 16:16:07 +00:00
dependabot[bot] 6453953ba0 chore(deps): bump github.com/go-jose/go-jose/v4 from 4.1.3 to 4.1.4
Bumps [github.com/go-jose/go-jose/v4](https://github.com/go-jose/go-jose) from 4.1.3 to 4.1.4.
- [Release notes](https://github.com/go-jose/go-jose/releases)
- [Commits](https://github.com/go-jose/go-jose/compare/v4.1.3...v4.1.4)

---
updated-dependencies:
- dependency-name: github.com/go-jose/go-jose/v4
  dependency-version: 4.1.4
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-04-03 16:15:46 +00:00
Frederick [Bot] f87f3e36e9 chore(i18n): update translations via Crowdin 2026-04-03 01:23:06 +00:00
kolaente e7b693c788 fix(tasks): include tasks with deleted parents in subtask-expanded queries
When expand[]=subtasks is used, the LEFT JOIN on task_relations filters
out same-project subtasks. If a parent task was deleted, the JOIN
produces NULL for parent_tasks.id/project_id, and since NULL != value
evaluates to NULL (not TRUE) in SQL, these tasks were incorrectly
excluded.

Add builder.IsNull{"parent_tasks.id"} to the OR condition so tasks
whose parent was deleted are still included in results.
2026-04-02 16:30:23 +00:00
kolaente 132187e451 fix(e2e): truncate bucket data in bucket-select tests
Truncate buckets, task_buckets, and task_relations before seeding to
prevent leftover data from previous tests causing false positives
(e.g., bucket selector appearing when it shouldn't).
2026-04-02 16:30:23 +00:00
kolaente 4cd79088d1 test: add WebSocket e2e tests
Add comprehensive end-to-end tests for the WebSocket system:

- Protocol tests: auth (valid/invalid token, timeout, double auth),
  subscriptions (valid/invalid event, auth required, unsubscribe),
  message delivery (notification on team add, doer exclusion,
  multi-connection)
- Frontend integration tests: notification badge update, dropdown
  rendering, and logout cleanup via browser-level Playwright tests
- Comment notification test: full flow where user B mentions user A
  in a task comment and user A receives real-time WebSocket notification

Includes ws test dependency, shared test helper utilities, and
cascade-truncation of notifications when truncating users to prevent
test pollution.
2026-04-02 16:30:23 +00:00
kolaente 09232ed880 feat(websocket): add frontend WebSocket support
Add useWebSocket composable with:
- Auto-connect on login, disconnect on logout
- Exponential backoff with ±25% jitter for reconnects
- Auth failure detection to prevent reconnect loops
- Trailing slash stripping from API_URL
- Overlapping reconnect prevention
- visibilityState check for fallback polling

Replace notification polling with real-time WebSocket push in the
Notifications component. Initial state is still loaded via REST on
mount, with fallback polling when WebSocket is disconnected. Incoming
notifications are deduplicated against already-loaded REST data.
Notifications are reloaded via REST on WS disconnect to catch missed
events.
2026-04-02 16:30:23 +00:00
kolaente f5385c574e feat(websocket): add notification event with XORM AfterInsert dispatch
Add NotificationCreatedEvent that fires automatically when a
DatabaseNotification is inserted, using XORM's AfterInsertProcessor
interface. The AfterInsert hook dispatches the event after the row
is persisted, without callers needing to manage DispatchOnCommit or
DispatchPending.

The WebSocket listener subscribes to this event, reloads the
notification from the database (ensuring accurate timestamps), and
pushes it to connected clients subscribed to the notification.created
event. Dispatch errors are logged rather than propagated since the
DB notification is already committed at that point.
2026-04-02 16:30:23 +00:00
kolaente 55ea5bd966 refactor(auth): extract shared token validation into auth package
Move JWT parsing (GetUserIDFromToken) and API token validation
(ValidateAPITokenString) into pkg/modules/auth so both HTTP middleware
and WebSocket auth use the same logic. This ensures consistent token
validity checks including expiry and user status (disabled/locked).

The HTTP API token middleware now delegates to the shared function,
removing duplicated lookup/expiry logic.
2026-04-02 16:30:23 +00:00
kolaente 0139e9a2ab feat(websocket): add HTTP upgrade handler and /api/v1/ws route
Add the WebSocket upgrade endpoint at /api/v1/ws with CORS origin
verification using the configured allowed origins. Includes nil hub
guard returning 503 if the WebSocket system hasn't been initialized.

Register the hub initialization in the app startup sequence and wire
the upgrade handler into the Echo router.
2026-04-02 16:30:23 +00:00
kolaente 9255fe07a9 feat(websocket): add message types, connection hub, and connection handler
Add the core WebSocket infrastructure:

- Message type definitions for the wire protocol (subscribe, unsubscribe,
  auth, error, push events)
- In-memory connection hub that tracks per-user connections and routes
  messages to subscribed clients
- Connection wrapper with auth-after-connect flow: connections start
  unauthenticated, client sends JWT as first message, only then can
  subscribe to event topics

Includes auth timeout (30s), shared cancellation context for read/write
loops, hub map cleanup on last connection removal, and proper error
delivery before closing on auth failure.
2026-04-02 16:30:23 +00:00
kolaente 4f9355c915 feat(websocket): add coder/websocket dependency 2026-04-02 16:30:23 +00:00