Commit Graph

14403 Commits

Author SHA1 Message Date
kolaente fa0c9a8584 feat(api): exchange rich-text fields as markdown on v2
Wire the conversion helpers into every rich-text handler: read/list/echo
convert HTML to markdown, create/update convert markdown to HTML before
persisting, and each op documents the format query field. Opt-in via
?format=markdown or the X-Vikunja-Format header.
2026-06-29 08:12:35 +02:00
kolaente 71639a3dc5 feat(api): add v2 markdown conversion helpers
Adds the opt-in format plumbing for v2: requestWantsMarkdown (query or
X-Vikunja-Format header), convertToMarkdown/convertToHTML/convertTasksToMarkdown
field converters, the cross-cutting API description, and stripPatchFormatQuery
(AutoPatch drops the query, so PATCH advertises only the header).
2026-06-29 08:12:35 +02:00
kolaente 8d10e053d4 fix(caldav): store markdown descriptions as HTML, skip spurious updates
Incoming CalDAV descriptions are markdown; convert them back to canonical HTML
(rebuilding mentions) before persisting. Skip the conversion when the markdown
is unchanged from the stored HTML so a passthrough sync doesn't churn the value
or bump the ETag.
2026-06-29 08:12:35 +02:00
kolaente a728e50796 feat(caldav): serialize task descriptions as markdown
CalDAV clients render DESCRIPTION as plain text, so convert the stored HTML to
markdown when serializing VTODOs. On the near-impossible conversion error, log
it and keep the stored value.
2026-06-29 08:12:35 +02:00
kolaente 9015bad65c feat(richtext): add markdown-domain change detection
Changed reports whether inbound markdown differs from stored HTML by comparing
in the markdown domain, so callers can skip rewriting unchanged fields.
2026-06-29 08:12:35 +02:00
kolaente 3459158b99 feat(richtext): add Markdown to HTML conversion with mention rebuild
Converts GFM Markdown to canonical HTML via goldmark (GFM, no WithUnsafe),
rewriting task lists into TipTap's structure and resolving @username mentions
to <mention-user> tags against real users.
2026-06-29 08:12:35 +02:00
kolaente 3abe8d650a feat(richtext): add HTML to Markdown conversion
Converts rich-text HTML to GFM Markdown (standard + GFM extensions) including
the Vikunja/TipTap-specific nodes (mentions, task lists). Adds the
html-to-markdown/v2 dependency.
2026-06-29 08:12:35 +02:00
renovate[bot] a2063a27a8 chore(deps): update actions/ai-inference action to v2.1.1 2026-06-29 08:12:04 +02:00
Frederick [Bot] cf1273c1d9 chore(i18n): update translations via Crowdin 2026-06-29 00:45:18 +00:00
kolaente 8d0814e460
chore(ci): remove stale label from PR when there is activity 2026-06-28 19:41:30 +02:00
renovate[bot] 2690b7153e fix(deps): update module github.com/go-ldap/ldap/v3 to v3.4.13 2026-06-28 12:52:42 +00:00
renovate[bot] c55ee0b742 fix(deps): update module github.com/coder/websocket to v1.8.15 2026-06-28 12:49:21 +00:00
renovate[bot] c72cfdf50d chore(deps): update dev-dependencies 2026-06-28 12:46:39 +00:00
renovate[bot] c6b3c7cddc fix(deps): update module github.com/arran4/golang-ical to v0.3.5 2026-06-28 12:10:52 +00:00
renovate[bot] 12952516cf fix(deps): update dependency ufo to v1.6.4 2026-06-28 12:10:14 +00:00
renovate[bot] 9946ca9031 fix(deps): update dependency nanoid to v5.1.16 2026-06-28 12:10:03 +00:00
renovate[bot] a73761f4c5 fix(deps): update dependency sortablejs to v1.15.7 2026-06-28 09:08:08 +00:00
renovate[bot] ac9811826e fix(deps): update dependency marked to v17.0.6 2026-06-28 09:07:29 +00:00
renovate[bot] 0369b61001 fix(deps): update dependency dayjs to v1.11.21 2026-06-28 09:07:12 +00:00
renovate[bot] 59da1d9514 fix(deps): update dependency @floating-ui/dom to v1.7.6 2026-06-28 09:06:49 +00:00
renovate[bot] d374c8e6f9 chore(deps): update actions/checkout action to v7 2026-06-28 09:06:15 +00:00
renovate[bot] aa8c5974ae chore(deps): update node.js to cd6fb7e 2026-06-28 09:05:56 +00:00
Frederick [Bot] 0dba563a03 chore(i18n): update translations via Crowdin 2026-06-28 00:29:43 +00:00
renovate[bot] dab2ac473f chore(deps): update postgres:18 docker digest to 4aabea7 2026-06-27 19:40:01 +00:00
renovate[bot] 57b6d530f3 chore(deps): update ghcr.io/techknowlogick/xgo:go-1.25.x docker digest to 57c6285 2026-06-27 19:39:40 +00:00
renovate[bot] ba5c09f962 chore(deps): update actions/cache action to v6 2026-06-27 19:39:18 +00:00
renovate[bot] eed762097a fix(deps): update tiptap to v3.27.1 2026-06-27 19:39:07 +00:00
renovate[bot] f6baa7d472 chore(deps): update docker/dockerfile:1 docker digest to 87999aa 2026-06-27 19:38:32 +00:00
renovate[bot] 07d39b4290 chore(deps): pin dependencies 2026-06-27 18:01:23 +00:00
karl Einziger 0efae572cd fix(auth): use binddn as group sync dn instead of userbind 2026-06-27 15:12:10 +00:00
kolaente 9e880e98a5 fix(api): export api-token permission groups in snake_case
The api-token permission group key is derived from the route slug. Every
group is snake_case except "time-entries", whose URL slug carries a hyphen.
The frontend snake_cases request payloads, rewriting that group key to
"time_entries", which the backend then rejected — so a token granted the
Time Entries scope could not be saved.

Canonicalise group and path-segment names to snake_case where they are
derived, and normalise the group key on token validation and authorisation
so any token stored under the old hyphenated key keeps resolving. No data
migration is needed: the v2 time-entries resource has never shipped in a
release.
2026-06-27 15:01:54 +00:00
kolaente e25ca7ab9a fix: don't re-login after logout when OIDC auto-redirect is enabled
Set the just-logged-out flag before navigating, and skip the intermediate
router.push to login when redirecting to the IdP — otherwise Login.vue's
onBeforeMount consumed the flag before the logout round-trip landed, so the
single-provider auto-redirect fired and logged the user straight back in.

redirectToProviderOnLogout now reports whether it navigated, so logout can fall through to the login page when there's no static logout URL.
2026-06-27 14:20:05 +00:00
kolaente 18ee92f227 feat: auto-redirect to OIDC provider on login when it's the only option 2026-06-27 14:20:05 +00:00
kolaente 96452f0b71 fix(desktop): set the main window icon on Linux
On X11/XWayland (Electron's default on Wayland sessions) the window had no
icon, so KDE Plasma showed the generic placeholder. Point BrowserWindow at
the packaged icon.png so the compositor has an icon to render.
2026-06-27 14:12:10 +00:00
kolaente 3f8ce93636 fix(desktop): show hidden window when relaunched from tray
When the app is hidden in the tray, closing then relaunching it triggered
the single-instance second-instance handler, which only called focus() — a
hidden window stays hidden on focus(), so the app appeared not to start
(notably on KDE Plasma Wayland where the tray icon may also be unreachable).
Call show() to surface it, and recreate the window if it no longer exists.
2026-06-27 14:12:10 +00:00
kolaente 626e1e267e fix(desktop): quit on SIGTERM and SIGINT
The desktop app ignored termination signals because the tray and embedded
express server keep the Electron event loop alive, forcing users to kill -9
on logout/shutdown. Add SIGINT/SIGTERM handlers that set isQuitting before
app.quit() so the hide-to-tray close handler doesn't swallow the quit.
2026-06-27 14:12:10 +00:00
BlackFuffey f18813f3ff feat(projects): make gantt chart zoom in if there are space available 2026-06-27 13:44:03 +00:00
gabe f7ac69d01a feat(filters): translate My Open Tasks title in frontend 2026-06-27 13:35:50 +00:00
gabe 98b3613247 feat(filters): generate open task saved filter on user creation 2026-06-27 13:35:50 +00:00
kolaente 18a0df505b
fix(deps): bump desktop undici to patched versions
node-gyp's undici 6.26.0 -> 6.27.0 and @electron/get's 7.27.2 -> 7.28.0,
each pinned within its major via overrides so only the security patch is
taken (an open >= range would jump across majors, e.g. to undici 8).

Resolves the 9 open desktop undici Dependabot alerts.
2026-06-27 14:34:20 +02:00
kolaente 7b5b8ecad2
chore(dev): remove leftover .envrc
Now handled directly by devenv
2026-06-27 14:26:28 +02:00
kolaente 4b18d08993
chore(dev): move devcontainer config to .devcontainer/ directory
Newer devenv generates the devcontainer config at .devcontainer/devcontainer.json
instead of the legacy root-level .devcontainer.json, which left an untracked
duplicate. Track the new path so regeneration is a no-op.
2026-06-27 14:25:45 +02:00
kolaente 7c9b9e3352
chore(deps): update devenv 2026-06-27 14:25:44 +02:00
kolaente 08890895de fix(task): don't drop the list-view done save during the check animation
Marking a task done via the list-view checkbox deferred the entire update
— including the network request — by 300ms to play the check animation. If
the page was torn down within that window (a refresh, tab close, or leaving
the app), the request was never sent and the save was silently lost. For
repeating tasks this is especially confusing: the due date never advances,
yet the checkbox un-checks itself anyway, so the failure looks identical to
success.

Fire the request immediately with the intended done value snapshotted, and
defer only the animation-coupled follow-up (result swap, pop sound, toast).
The optimistic v-model state already drives the check animation during the
300ms, so nothing visual is lost.
2026-06-27 12:01:51 +00:00
kolaente 330b94c3c4 feat(migration): import recurring tasks from todoist 2026-06-26 13:32:08 +00:00
kolaente 7691f282cf fix(veans): preserve unsent task fields on update via PATCH (#2962)
The v1 update was a whole-object POST /tasks/{id}: omitted scalars were
zeroed, so a status-only `veans update` silently wiped a task's
description and priority. The v1->v2 migration replaced that with
PATCH /tasks/{id} carrying a JSON Merge Patch built from only the
changed fields (client.TaskPatch, all-pointer + omitempty), which fixes
this by construction — absent fields are left untouched server-side.

Pin it with the acceptance tests from the issue: a title-only and a
status-only update must send only the field(s) they change, so the
stored description and priority survive.
2026-06-26 11:23:14 +00:00
kolaente 6cee626383 refactor(veans): migrate API client from v1 to v2
veans is unreleased and targets bleeding-edge Vikunja, so the CLI now
speaks the Huma-backed /api/v2 exclusively (v1 is frozen and the kanban
bucket CRUD veans relies on only exists on v2).

- Transport: base path /api/v1 -> /api/v2 in Do/DoRaw; add a
  content-type-aware path (DoMerge for application/merge-patch+json).
- Pagination: drop the x-pagination-total-pages header reader; every v2
  list returns the {items,total,page,per_page,total_pages} envelope.
  Decode it with a generic Paginated[T]/doList[T] and page until
  page >= total_pages. Previously-single-GET lists (views, buckets,
  comments, bots) are enveloped too — unwrap .items.
- Verbs: creates flip PUT -> POST (projects, labels, tokens, bot users,
  shares, task create, comments, relations, assignees, label-attach,
  bucket create); the bucket-task move flips POST -> PUT with a bare
  {"task_id":N} body (URL owns project/view/bucket); task update moves
  to PATCH merge-patch with a partial body.
- Errors: parse the RFC 9457 problem+json body (detail/title/code)
  instead of v1's {code,message}; the status -> output.Code mapping is
  unchanged.
- Discovery probes /api/v2/info, which doubles as the "new enough" check.
- Label search param s -> q; add views_buckets_tasks_put to the bot's
  projects scope so the move is authorized regardless of route-init order.

Tests and the veans agent guide are updated for the new paths, verbs and
envelope. Verified end-to-end against a local v2 server: init, create,
show, list, claim, update and prime all work.
2026-06-26 11:23:14 +00:00
kolaente 0d043e80e4 feat(api/v2): add kanban bucket CRUD endpoints
Port the standalone bucket list/create/update/delete from v1 to the
Huma-backed /api/v2, under /projects/{project}/views/{view}/buckets,
using v2 verb conventions (POST creates, PUT updates). The handlers
reuse the generic handler.Do* functions, so permissions are enforced
by the Bucket model's existing Can* methods.

Mirrors v1: no read-one route (the model has no ReadOne/CanRead), so
AutoPatch synthesises no PATCH. No model changes.
2026-06-26 08:56:15 +00:00
Frederick [Bot] 9390199ce0 chore(i18n): update translations via Crowdin 2026-06-26 00:32:25 +00:00
Bradley Erickson f8eacca7c8 fix(auth): allow api tokens to access global v2 task list endpoint
The tasks.read_all special case in CanDoAPIRoute only covered v1 paths.
Both GET /api/v2/tasks and GET /api/v2/projects/:project/tasks normalize
to the same tasks.read_all map key, but only one RouteDetail survives —
the project-scoped path overwrites the global one. The exact path
comparison then rejects the global endpoint with 401.

Extend the special case to include the v2 paths.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-24 17:49:02 +00:00