Commit Graph

54 Commits

Author SHA1 Message Date
kolaente e85f3fd84c feat(settings): add quickAddDefaultReminders field to frontend settings 2026-04-11 21:51:41 +00:00
kolaente 326427a242 feat(sort): persist sort selection to URL query parameter
Syncs the sort choice to a ?sort=field:order URL parameter so it
survives page refreshes and can be shared. The default position sort
is omitted from the URL to keep links clean.
2026-04-07 13:41:13 +00:00
kolaente b9c41e0cbf feat(home): rotate greetings from a deterministic per-user daily pool 2026-04-05 12:24:45 +00:00
kolaente d45ae31d8c fix(gantt): preserve query parameters when closing task modal
When closing a task modal opened from the Gantt view, the date range
query parameters were lost because closeModal() reconstructed the
route with only projectId and viewId. Now preserves query parameters
from the backdrop view.
2026-04-05 11:31:37 +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 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 d72a3a8c0d feat(frontend): add useQuickAddMode composable for quick-add detection 2026-04-01 21:38:38 +00:00
kolaente 79cd3433f5 refactor(shortcuts): use event.code for raw keyboard handlers
Change e.key to e.code in global keyboard shortcut handlers for
consistency with the new event.code-based shortcut system:
- ProjectList.vue: 'j'/'k'/'Enter' -> 'KeyJ'/'KeyK'/'Enter'
- useGanttBar.ts: 'ArrowLeft'/'ArrowRight' (identical values, for consistency)
- Modal.vue: 'Escape' (identical value, for consistency)
2026-03-03 14:00:25 +01:00
kolaente e3fdaed94a refactor(shortcuts): replace eventToHotkeyString with eventToShortcutString
Migrate all imperative shortcut matching from @github/hotkey's
eventToHotkeyString to the new event.code-based eventToShortcutString.

Updated comparison strings:
- 'Meta+k'/'Control+k' -> 'Meta+KeyK'/'Control+KeyK'
- 'Control+s'/'Meta+s' -> 'Control+KeyS'/'Meta+KeyS'
- 'Control+.' -> 'Control+Period'
- '.' -> 'Period'
- 'Enter' stays 'Enter' (identical in event.code)
2026-03-03 14:00:25 +01:00
kolaente 07446dc4e1 feat(gantt): integrate task tree into Gantt rendering with collapse 2026-03-03 13:11:43 +01:00
kolaente be1db018fe feat: add frontend session management with refresh tokens
- Session model, type interface, and API service
- Sessions settings page showing active sessions with device info,
  IP address, last active time, and current session indicator
- Auth store updated to use cookie-based refresh tokens for user
  sessions and JWT-based renewal for link shares
- refreshToken() uses Web Locks API to coordinate across browser
  tabs — only one tab performs the refresh, others adopt the result
- 401 response interceptor with automatic retry: detects expired JWT
  (error code 11), refreshes the token, and replays the request
- Interceptor gated to user JWTs only (link shares skip refresh)
- checkAuth() attempts cookie refresh when JWT is expired, allowing
  seamless session resumption after short TTL expiry
- Proactive token refresh on page focus/visibility via composable
- renewToken() tolerates refresh failures when JWT is still valid
2026-02-25 10:30:25 +01:00
kolaente ceb62c63d3 refactor(gantt): extract GanttBarDateType as reusable type 2026-02-18 23:04:21 +01:00
kolaente eefa48052b feat(gantt): add dateType field to GanttBarModel meta 2026-02-18 23:04:21 +01:00
kolaente 6afb166dd2
feat: add shortcut to quickly copy task identifier, title and url to clipboard (#2028)
This adds the following shortcuts:

- `.` to copy the task identifier
- `..` to copy the task identifier and title
- `...` to copy the task identifier, title, and url
- `Control + .` to copy the task url
2025-12-28 10:54:41 +01:00
Copilot 9bc67032c3
fix: validate coordinates before elementsFromPoint on Firefox mobile (#1992)
Firefox mobile drag events can provide non-finite coordinate values
(`undefined`, `NaN`, `Infinity`) which cause
`document.elementsFromPoint()` to throw: "Argument 1 is not a finite
floating-point value."

**Changes**
- Added `Number.isFinite()` validation in `findProjectIdAtPosition()`
before calling `elementsFromPoint()`
- Returns `null` when coordinates are invalid, gracefully aborting the
drop operation

```typescript
function findProjectIdAtPosition(mouseX: number, mouseY: number): number | null {
	// Validate coordinates are finite numbers (required by elementsFromPoint)
	if (!Number.isFinite(mouseX) || !Number.isFinite(mouseY)) {
		return null
	}

	const elementsUnderMouse = document.elementsFromPoint(mouseX, mouseY)
	// ... rest of implementation
}
```

The caller already handles `null` returns appropriately, treating it as
"no valid drop target found."

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: kolaente <13721712+kolaente@users.noreply.github.com>
2025-12-16 23:05:42 +00:00
kolaente 1288d0a99c
feat: make sidebar resizable (#1965)
Closes: #525

* Sidebar width is now adjustable via dragging
* The width is automatically saved to settings and restored across sessions.
2025-12-12 10:46:46 +00:00
kolaente 4aae270694
feat(tasks): move tasks between projects with drag and drop (#1945)
Drag and drop tasks between projects from list and kanban views, with cross-project move handling and success notification. With visual drop-target highlighting when hovering a project during a drag.
2025-12-10 18:59:38 +00:00
kolaente 566ff99e6c
fix(editor): prevent upload overlay from intercepting text drag operations (#1890) 2025-11-27 17:49:38 +00:00
kolaente f7acdf4ac1
fix: don't try to switch to project 0 when reloading the page (#1855) 2025-11-26 23:28:05 +01:00
kolaente 4a2f961a77 fix: ContentAuth types 2025-11-22 17:23:03 +01:00
kolaente 85fc8fffd4 feat: restrict attachment drop to files
Resolves https://github.com/go-vikunja/vikunja/issues/1663
2025-11-16 12:22:30 +01:00
kolaente abbf2ce183 chore: copy useDropZone from vueuse 2025-11-16 12:22:30 +01:00
Copilot 650fb94978
feat: add time display with configurable format (12h/24h) to non-relative date formats (#1807)
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: kolaente <k@knt.li>
2025-11-13 08:57:06 +00:00
kolaente 2977a11a2c
fix: show cross-project subtasks in List view (#1649) 2025-10-13 18:43:40 +02:00
kolaente 0dee1789a2
fix(filter): ensure filter query param is added to the page correctly (#1471) 2025-09-11 15:24:12 +00:00
kolaente 8ce8d445ba
fix(kanban): guard task modal race conditions (#1472) 2025-09-11 17:15:57 +02:00
Copilot 14e1bd2f55
fix: prevent null history.state errors in modal routing and task navigation (#1368) 2025-08-31 19:14:25 +00:00
kolaente 5fc255cb36
feat(gantt): rebuild the gantt chart (#1001) 2025-08-12 16:33:50 +02:00
kolaente b444cf8d43
feat: add display setting for dates (#1192) 2025-07-30 09:43:37 +02:00
kolaente a26fb787f9
fix(labels): correctly fall back to variable colors when no label color is set (#1124) 2025-07-15 21:15:09 +00:00
Dominik Pschenitschni 454418ee63 chore: fix indentation 2025-06-19 10:53:35 +02:00
Dominik Pschenitschni b1c200c9aa
feat(frontend): improve route filter generics (#953) 2025-06-16 22:40:09 +02:00
Dominik Pschenitschni 78fa5742c3
fix: guard null access in composables (#951) 2025-06-16 16:02:59 +02:00
Dominik Pschenitschni bb9dc03351
fix: add newline at end of line (#827) 2025-05-24 13:57:47 +02:00
Dominik Pschenitschni cb8fd09824 feat: make time reactive (#2627)
Reviewed-on: https://kolaente.dev/vikunja/vikunja/pulls/2627
Reviewed-by: konrad <k@knt.li>
Co-authored-by: Dominik Pschenitschni <mail@celement.de>
Co-committed-by: Dominik Pschenitschni <mail@celement.de>
2025-01-20 13:28:49 +00:00
Dominik Pschenitschni c7e708cf7d fix: deprecated import in useTitle 2025-01-19 20:07:55 +00:00
kolaente 9aca4ca0f6
fix(favorites): do not return subtasks on favorites page
This fixes an issue where all subtasks of a tasks would show up on the favorites page, even if they were not marked as favorite.

Resolves https://github.com/go-vikunja/vikunja/issues/375
2024-12-10 14:31:28 +01:00
Dominik Pschenitschni 44c659aa34 feat: move useProjectBackground to composables 2024-11-10 15:17:38 +00:00
kolaente 703c641aeb fix: lint issues 2024-10-29 09:57:53 +00:00
kolaente 526bd1f170
fix(filters): reload tasks silently when marking one done in the list
This fixes a UI issue where if a user had a filter set and marked the task done, it would not disappear, even though the filter does not match the done task anymore.
2024-07-18 15:51:03 +02:00
Dominik Pschenitschni 9fd17aca18 fix: useTitle types (#2369)
Reviewed-on: https://kolaente.dev/vikunja/vikunja/pulls/2369
Co-authored-by: Dominik Pschenitschni <mail@celement.de>
Co-committed-by: Dominik Pschenitschni <mail@celement.de>
2024-06-11 20:36:47 +00:00
Dominik Pschenitschni 917cbf9cb6 fix(vue): toValue instead of unref 2024-06-10 13:53:13 +00:00
kolaente 6e5b31f1e0
fix(filters): always persist filter or search in query path and load it correctly into filter query input when loading the page
Previously, when using the filter query as a search input, it would load the search as requested but the filter query parameter in the url would be empty, which meant the search would not be loaded correctly when reloading (or otherwise newly accessing) the page. We're now persisting the filter and search in the task loading logic, to make sure they are always populated correctly.
2024-04-13 23:34:25 +02:00
kolaente 4b903c4f48
fix(views): lint 2024-03-19 00:47:52 +01:00
kolaente bc34a33922
fix(views): move to new project view when moving tasks 2024-03-19 00:47:49 +01:00
kolaente cf15cc6f12
feat(views): fetch tasks via view context when accessing them through views 2024-03-19 00:47:47 +01:00
kolaente e097721817
fix(tasks): use correct filter query when filtering 2024-03-11 16:39:27 +01:00
kolaente a66e26678e
feat(filters): pass timezone down when filtering with relative date math
Resolves https://community.vikunja.io/t/my-vikunja-instance-creates-tasks-with-due-date-time-of-9am-for-tasks-with-the-word-today-word-in-it/2105/8
2024-03-11 16:28:25 +01:00
kolaente 4e6e0608c7
fix(filters): lint 2024-03-09 20:08:17 +01:00