Commit Graph

2852 Commits

Author SHA1 Message Date
dependabot[bot] fc9a9a6c71 chore(deps): bump axios from 1.15.0 to 1.15.2 in /frontend
Bumps [axios](https://github.com/axios/axios) from 1.15.0 to 1.15.2.
- [Release notes](https://github.com/axios/axios/releases)
- [Changelog](https://github.com/axios/axios/blob/v1.x/CHANGELOG.md)
- [Commits](https://github.com/axios/axios/compare/v1.15.0...v1.15.2)

---
updated-dependencies:
- dependency-name: axios
  dependency-version: 1.15.2
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-05-06 12:37:48 +00:00
renovate[bot] 4754230ef0 chore(deps): update dev-dependencies 2026-05-06 12:37:26 +00:00
kolaente 3d594db725 fix(frontend): scope checkbox hit-area pseudo to the task row
The pseudo-element that extends the checkbox hit target also covered
label text content, which broke Playwright actionability checks for
clicks on text inside wider FancyCheckbox labels (e.g. the "Show
Archived" toggle on the projects list page).

Move the rule out of BaseCheckbox and into SingleTaskInProject's deep
override, where the label slot is already hidden via display: none, so
no neighboring content can be intercepted.
2026-05-05 15:42:10 +00:00
kolaente 9bea92bb6f fix(frontend): skip task detail on label and checkbox clicks
Defense in depth for the list-view row click handler: a click that
lands on a label or checkbox input no longer bubbles up to open the
task detail.
2026-05-05 15:42:10 +00:00
kolaente 1ea5675e1b fix(frontend): extend checkbox hit target to 44x44
A pseudo-element on the label provides a 44x44 minimum hit area
centered on the visible icon. Visible size and surrounding layout
are unchanged. Addresses misclicks on the task list view checkbox
where ~50% of taps would open the task detail instead of toggling
done.
2026-05-05 15:42:10 +00:00
kolaente 469ee8f364 fix(frontend): respect user's 12h/24h time format in date pickers
The flatpickr time inputs hardcoded `time_24hr: true`, so users who
selected the 12-hour format in their settings still got a 24-hour
picker — even though the displayed dates respected the preference.

Bind `time_24hr` to the existing `useTimeFormat` composable in:
- DatepickerInline (start/end/due dates and absolute reminders)
- DeferTask (defer due date)
- ApiTokenForm (API token expiry)

Reported at https://community.vikunja.io/t/4492.
2026-05-05 14:47:24 +00:00
kolaente 926e163089 chore(deps): bump workbox-precaching to 7.4.1 to match workbox-cli 2026-05-05 08:31:42 +00:00
renovate[bot] 7ed0e3ecd6 chore(deps): update dev-dependencies 2026-05-05 08:31:42 +00:00
Frederick [Bot] 65a6fc7b4b chore(i18n): update translations via Crowdin 2026-05-05 01:57:03 +00:00
kolaente 459dbe71ca
Improve modal responsive sizing with inline-size constraints (#2716) 2026-05-04 15:33:59 +02:00
renovate[bot] 55e96018f3 chore(deps): update dev-dependencies 2026-05-04 10:55:46 +00:00
Claude d9a5958bb8 feat: always enable bot users
Removes the `service.enablebotusers` config flag, the matching
`bot_users_enabled` field on /info, and the now-unused
`ErrBotUsersDisabled` error. Bot user routes and the frontend
settings tab are now always available.

https://claude.ai/code/session_01VhAR6xnoCdG1fpX52bzaCC
2026-05-04 10:38:53 +00:00
renovate[bot] 0f1bf6fab2 chore(deps): update dev-dependencies 2026-05-04 10:21:25 +00:00
Frederick [Bot] 935c950942 chore(i18n): update translations via Crowdin 2026-05-04 01:56:28 +00:00
kolaente d467a06e72 feat(frontend): add bot settings page and services 2026-05-01 14:44:10 +00:00
kolaente c4e5f55b6d feat(frontend): add bot user model support and badge 2026-05-01 14:44:10 +00:00
Claude 01fff665c6 fix(frontend): focus quick actions input after modal opens
The Modal mounts the <dialog> via v-if and calls showModal() in a
follow-up flush, so v-focus runs while the dialog is still closed and
its focus() call is dropped. The existing rAF retry was gated on
quick-add mode, leaving Ctrl+K in the regular app with no focused
input. Run the retry whenever the quick actions become active and keep
the command pre-selection scoped to quick-add mode.
2026-04-30 14:06:07 +00:00
Frederick [Bot] 304ff5a4aa chore(i18n): update translations via Crowdin 2026-04-29 02:01:56 +00:00
Timh e97b629d6c feat: support filter_include_nulls in project view configuration 2026-04-28 14:16:51 +00:00
kolaente 9852aff4ee fix(frontend): add postcss-html as explicit devDependency
Stylelint 17.9.0 resolves customSyntax modules relative to the
stylelint package, so the transitive postcss-html pulled in via
stylelint-config-recommended-vue is no longer reachable and lint
fails with "Could not find postcss-html".
2026-04-27 09:22:01 +00:00
renovate[bot] 519b65b96e chore(deps): update dev-dependencies 2026-04-27 09:22:01 +00:00
Frederick [Bot] 811e5efe20 chore(i18n): update translations via Crowdin 2026-04-26 01:48:36 +00:00
Frederick [Bot] 6ed4e759b0 chore(i18n): update translations via Crowdin 2026-04-25 01:26:11 +00:00
Xela 5cfb03a29e test(e2e): use ISOString for date seeding to prevent timezone parsing errors 2026-04-24 11:24:34 +02:00
Xela 96e08fcbdb fix(frontend): respect week_start setting when language is not explicitly set 2026-04-24 11:24:34 +02:00
Xela cbd5bf8d94 fix(frontend): use import.meta.env.MODE instead of DEV for testid directive
During E2E testing with Playwright (via `mage test:e2e`), the frontend is built using Vite with `--mode development`. However, Vite hardcodes `process.env.NODE_ENV` to `production` during the build step, which causes `import.meta.env.DEV` to statically evaluate to `false`.

Because the `v-cy` custom testing directive relied on the `DEV` flag, it silently evaluated to false and failed to render the `data-cy` attributes into the DOM during the test build. This caused test failures because Playwright could not locate the elements.

Changing the check to explicitly evaluate `import.meta.env.MODE === 'development'` successfully bypasses the Vite build behavior, ensuring that `data-cy` testing attributes are consistently rendered during E2E tests.

For more context on Vite's build behavior regarding `DEV` and development mode, see:
https://github.com/vitejs/vite/discussions/14083
2026-04-24 11:24:34 +02:00
Xela d2cac283c7 test(user): add tests for updating week start day and verifying date picker behavior 2026-04-24 11:24:34 +02:00
Xela 4add8abaa1 feat(user): support all weekdays as week start 2026-04-24 11:24:34 +02:00
Cristian Ivascu 67ad31c9c8
fix(webhook): use same casing for basic auth fields (#2688) 2026-04-24 11:20:07 +02:00
Claude 6bf586e928 fix(tasks): disable task glance tooltip on touch devices
Mouse event emulation from taps on touch devices caused the glance
tooltip to appear unexpectedly with no reliable way to dismiss it.
Gate the tooltip behind a `(hover: hover) and (pointer: fine)` media
query so it only activates on devices with a real pointer.
2026-04-24 08:52:44 +00:00
Frederick [Bot] 879f839729 chore(i18n): update translations via Crowdin 2026-04-24 01:46:52 +00:00
kolaente d2ba697686 chore(i18n): remove unused frontend translation keys
Remove 47 keys from frontend/src/i18n/lang/en.json that are not
referenced by any $t / t / i18n.t / i18n.global.t / tc / <i18n-t>
call site, nor by any stored-as-literal dynamic lookup pattern.

The keys fall into a few broad groups: leftover attribute labels on
filter and label models, dropped editor toolbar entries, unused
password/password-confirmation copy, and a handful of stale admin and
migration strings. The sibling translation files will be reconciled on
the next Crowdin sync.
2026-04-23 13:30:51 +02:00
renovate[bot] 71c2e01366 chore(deps): update dependency caniuse-lite to v1.0.30001790 2026-04-22 10:18:08 +00:00
renovate[bot] 49ac0348e4 chore(deps): update dev-dependencies 2026-04-22 06:31:37 +00:00
renovate[bot] 0b2b5b580d chore(deps): update dev-dependencies 2026-04-21 18:38:21 +00:00
kolaente 2829a851df feat(a11y): associate errors with inputs in FormInput and FormSelect
Wire aria-invalid, aria-describedby and role=alert on the form
primitive components so errors raised directly on FormInput or
FormSelect are announced by assistive tech and programmatically
linked to the control.
2026-04-21 11:44:36 +00:00
kolaente fd1a329f5d feat(a11y): add descriptive labels to task checkboxes
Adds aria-label='Mark {task} as done' to task checkboxes so
screen readers can distinguish between them. Passes ariaLabel
prop through FancyCheckbox → BaseCheckbox → input.

Fixes WCAG 2.4.6 (Headings and Labels).
2026-04-21 11:44:36 +00:00
kolaente 6f85a7fb6b feat(a11y): fix heading hierarchy across pages
- Home: greeting H2 → H1 (page needs a top-level heading)
- Task detail: task ID H1 → span (only title should be H1)
- Task detail: H6 breadcrumb → nav element
- App header: project title H1 → span (avoids duplicate H1)

Fixes WCAG 1.3.1 (Info and Relationships) and 2.4.6 (Headings).
2026-04-21 11:44:36 +00:00
kolaente c1f74ae9dc feat(a11y): add labels to color picker and sort select
Adds aria-label to the color input and sort select elements
so screen readers announce their purpose.

Fixes WCAG 3.3.2 (Labels or Instructions).
2026-04-21 11:44:36 +00:00
kolaente 4618f3491b feat(a11y): associate form errors with input fields
Adds aria-invalid, aria-describedby, and role='alert' to error
messages in FormField and Password components so screen readers
announce validation errors.

Fixes WCAG 3.3.1 (Error Identification).
2026-04-21 11:44:36 +00:00
kolaente a0d0379e95 feat(a11y): fix logo link accessible name to include 'Vikunja'
Changes aria-label from 'Overview' to 'Vikunja home' so the
accessible name includes the visible text.

Fixes WCAG 2.5.3 (Label in Name).
2026-04-21 11:44:36 +00:00
kolaente a34c247611 feat(a11y): use autocomplete='new-password' on register form
Adds autocomplete prop to Password component (defaults to
'current-password'). Register page passes 'new-password' so
password managers offer to generate a strong password.

Fixes WCAG 1.3.5 (Identify Input Purpose).
2026-04-21 11:44:36 +00:00
kolaente 21b7ae3f9f feat(a11y): add accessible names to modal dialogs
Passes aria-label to the <dialog> element via attribute inheritance
so screen readers announce the dialog's purpose.

Fixes WCAG 4.1.2 (Name, Role, Value).
2026-04-21 11:44:36 +00:00
kolaente 40ff558540 feat(a11y): add aria-live region to toast notifications
Adds role='status' and aria-live='polite' to the notification
container so screen readers announce status messages.

Fixes WCAG 4.1.3 (Status Messages).
2026-04-21 11:44:36 +00:00
kolaente 11ffb530be feat(a11y): add accessible names to icon-only buttons
Adds aria-label to sidebar toggle, mobile overlay, banner close,
modal close, quick actions close, task detail close, and dropdown
trigger buttons. Adds triggerLabel prop to Dropdown component.

Fixes WCAG 4.1.2 (Name, Role, Value).
2026-04-21 11:44:36 +00:00
kolaente 732b65ba7c feat(a11y): add skip navigation link and main landmark on auth pages
Adds a visually-hidden skip-to-content link as the first focusable
element. Adds id='main-content' to the <main> element. Changes
<section> to <main> on auth pages for proper landmark navigation.

Fixes WCAG 2.4.1 (Bypass Blocks).
2026-04-21 11:44:36 +00:00
kolaente eb441f8b0c feat(a11y): add i18n keys for accessibility labels 2026-04-21 11:44:36 +00:00
renovate[bot] 9d25864b25 chore(deps): pin dependency otplib to 12.0.1 2026-04-21 11:14:41 +00:00
kolaente b90e67d7ca test(e2e): await DELETE in caldav token revoke test to avoid race 2026-04-21 10:50:09 +00:00
kolaente be28ec70d8 test(e2e): await DELETE in session revoke test to avoid race 2026-04-21 10:50:09 +00:00
kolaente c0101afb59 test(e2e): widen recurrence due-date tolerance to 5s
CI shard 4 hit a ~996ms skew between the JS-constructed originalDue and
the backend's advanced due date, enough to bust the <500ms precision
bound. Bump precision to -4 (<5s) — still tight enough to confirm the
regeneration advanced by ~1 day, loose enough to absorb sub-second
round-tripping through Date → ISO → Go time.Time → JSON.
2026-04-21 10:50:09 +00:00
kolaente c3b86b2102 test(e2e): cover link share permission tiers 2026-04-21 10:50:09 +00:00
kolaente 17e0dde7d3 test(e2e): cover link share password protection 2026-04-21 10:50:09 +00:00
kolaente 19d3b9c4bb test(e2e): cover team share revocation 2026-04-21 10:50:09 +00:00
kolaente f20267164f test(e2e): cover team READ_WRITE permission 2026-04-21 10:50:09 +00:00
kolaente be225fd4d3 test(e2e): cover team READ permission boundary 2026-04-21 10:50:09 +00:00
kolaente 01b71577d7 test(e2e): add TeamProjectFactory 2026-04-21 10:50:09 +00:00
kolaente 268c5daf8b test(e2e): drop unused authenticatedPage from recurrence beforeEach 2026-04-21 10:50:09 +00:00
kolaente 37d7f90acf test(e2e): cover monthly repeat mode UI 2026-04-21 10:50:09 +00:00
kolaente 637d810ff7 test(e2e): assert recurring task regenerates on complete 2026-04-21 10:50:09 +00:00
kolaente c93f644363 test(e2e): cover recurrence preset buttons 2026-04-21 10:50:09 +00:00
kolaente f2eee5d8a1 test(e2e): assert readers cannot delete attachments 2026-04-21 10:50:09 +00:00
kolaente 05432d3993 test(e2e): cover attachment deletion 2026-04-21 10:50:09 +00:00
kolaente db634093e0 test(e2e): drop unused authenticatedPage from webhooks beforeEach 2026-04-21 10:50:09 +00:00
kolaente 425889b879 test(e2e): create and delete a webhook 2026-04-21 10:50:09 +00:00
kolaente 5a93149849 test(e2e): require at least one webhook event 2026-04-21 10:50:09 +00:00
kolaente 2f2aafadfd test(e2e): validate webhook target url 2026-04-21 10:50:09 +00:00
kolaente 8bcdc314b1 test(e2e): cover data export request flow 2026-04-21 10:50:09 +00:00
kolaente a9f8fbaba8 test(e2e): cover scheduled deletion cancel flow 2026-04-21 10:50:09 +00:00
kolaente 2a5e4f2b84 test(e2e): cover account deletion request flow 2026-04-21 10:50:09 +00:00
kolaente 0902c009f6 test(e2e): assert current session has no delete control 2026-04-21 10:50:09 +00:00
kolaente 76055b622b test(e2e): assert session delete breaks refresh 2026-04-21 10:50:09 +00:00
kolaente cf9d0a26ab test(e2e): cover sessions list with current marker 2026-04-21 10:50:09 +00:00
kolaente 7145440fe6 test(e2e): assert wrong password blocks email change 2026-04-21 10:50:09 +00:00
kolaente 3dfbcae4d5 test(e2e): cover caldav token deletion 2026-04-21 10:50:09 +00:00
kolaente cd9d2a2245 test(e2e): cover caldav token creation end-to-end 2026-04-21 10:50:09 +00:00
kolaente 912d6a134f test(e2e): assert wrong TOTP passcode is rejected 2026-04-21 10:50:09 +00:00
kolaente 96685fdc5b test(e2e): cover TOTP disable flow 2026-04-21 10:50:09 +00:00
kolaente 5266392bb7 test(e2e): cover TOTP enrollment flow 2026-04-21 10:50:09 +00:00
kolaente 3b7c098c84 test(e2e): add otplib dev dep for TOTP tests 2026-04-21 10:50:09 +00:00
kolaente 3816349258 test(e2e): add TotpFactory with fixed seed 2026-04-21 10:50:09 +00:00
kolaente 3271c8600a test(e2e): add WebhookFactory 2026-04-21 10:50:09 +00:00
kolaente fff7f80994 test(e2e): add SessionFactory with sha256 token hashing 2026-04-21 10:50:09 +00:00
kolaente 726a4df539 test(e2e): add user settings nav helper 2026-04-21 10:50:09 +00:00
renovate[bot] 73a597345a chore(deps): update dev-dependencies to v4.2.3 2026-04-21 07:41:56 +00:00
kolaente f7dc50faf7 refactor(frontend): port checkbox-radio rules into FormCheckbox and drop Bulma import
The Bulma form/checkbox-radio partial only defined two selectors: .checkbox
(consumed exclusively by FormCheckbox.vue) and .radio (consumed by
ViewEditForm.vue and user/settings/Avatar.vue). Ports the %checkbox-radio
placeholder rules (cursor, line-height, position, hover/disabled states,
and the input cursor override) into FormCheckbox's scoped style for the
.checkbox side, and into scoped style blocks on the two remaining .radio
call-sites for the .radio side (including the 0.5em sibling margin via
margin-inline-start). Drops the now-unused @import. Pixel-perfect verified
on /login, /user/settings/general, and /user/settings/avatar: every
measured label/input getBoundingClientRect and computed style matches the
baseline exactly (0px deltas across all 5 sampled checkboxes and all 5
avatar radios).
2026-04-20 19:55:14 +00:00
renovate[bot] 5a1db90103 chore(deps): update dev-dependencies to v8.59.0 2026-04-20 19:28:55 +00:00
kolaente e8b777d3be fix(ui): make code element background dark-mode aware and harden config store 2026-04-20 18:55:06 +00:00
kolaente db3f5d2daf feat(project): add before-delete slot to ProjectSettingsDropdown 2026-04-20 18:55:06 +00:00
kolaente c7b088ac18 feat(frontend): introduce TimeDisplay component 2026-04-20 18:55:06 +00:00
kolaente 7e4bf83fa0 refactor(frontend): extract SideNavShell for admin and user settings 2026-04-20 18:55:06 +00:00
kolaente 4e805d182a test(frontend): update form primitive tests for admin input usage 2026-04-20 18:55:06 +00:00
kolaente 7df5f127ca feat(admin): add frontend admin shell, views, services, and routes 2026-04-20 18:55:06 +00:00
kolaente 23c82bd5fa feat(frontend): expose isAdmin on current user and add config feature check 2026-04-20 18:55:06 +00:00
kolaente c9b3d4775c feat(admin): add typed models for admin users and overview 2026-04-20 18:55:06 +00:00
kolaente 825e45b4c8 test(admin): add e2e tests for admin panel 2026-04-20 18:55:06 +00:00
kolaente d32dcf3a78 feat(license): add runtime state snapshot and reload helpers 2026-04-20 18:55:06 +00:00
MidoriKurage 2d2dbf67a0 fix(tasks): Let getCommentUrl handle frontendUrl including sub-path 2026-04-20 14:28:23 +00:00
MidoriKurage 44122bfe6b fix(frontend/oidc): Prefix frontend base to redirect URL 2026-04-20 14:28:23 +00:00
MidoriKurage 57e2a33dc6 fix(frontend/vite): Configure vite dev proxy to handle frontend path 2026-04-20 14:28:23 +00:00
MidoriKurage 7710e2549e fix(frontend): Fix hard-coded API base in checkAndSetApiUrl.ts 2026-04-20 14:28:23 +00:00
MidoriKurage e31c45c44e fix(frontend): Make sw.ts respect to frontend base URL 2026-04-20 14:28:23 +00:00
kolaente b241c293d0 fix(frontend): restore tablet pagination layout (space-between + flex order)
The Bulma partial applied justify-content: space-between on .pagination and
flex-order 1/2/3 on prev/list/next inside a tablet media query under
.is-centered — the port missed both. Pixel-diff against main is now zero.
2026-04-20 10:38:08 +00:00
kolaente 8f64836999 refactor(frontend): extract PaginationItem to own pagination-link styling
BasePagination was reaching across slot boundaries with :deep() to style
.pagination-previous / -next / -link — markup it doesn't actually render.
Move that markup and the related scoped rules into a new PaginationItem
component that polymorphically renders RouterLink (when `to` is given)
or BaseButton (emit-based). BasePagination keeps only the scaffold it
actually owns: .pagination, .pagination-list, .pagination-ellipsis.

Pagination.vue and PaginationEmit.vue become thin wrappers around
BasePagination + PaginationItem; no more raw pagination-* class usage or
BaseButton imports in the emit wrapper.

The .app-container.has-background / .link-share-container.has-background
theme override moves with the .pagination-link rules into PaginationItem
as its own unscoped <style> block.

Result: 0 remaining :deep(.pagination-*) selectors (was 14).
2026-04-20 10:38:08 +00:00
kolaente 5ea7853dd6 refactor(frontend): port pagination rules into BasePagination and drop Bulma import
The Bulma components/pagination partial is only used by BasePagination
and its two wrappers (Pagination.vue, PaginationEmit.vue); no other
component renders raw .pagination-* markup. Ports the rules we actually
use (base layout, item sizing, hover/focus/disabled states, is-current
styling, mobile/tablet breakpoints) into BasePagination's scoped styles,
using :deep() to reach slotted children. The theme override for
.pagination-link on .has-background containers moves into an unscoped
style block on the same component. Drops the now-unused @import.
2026-04-20 10:38:08 +00:00
renovate[bot] 326874d94c chore(deps): update dev-dependencies 2026-04-20 06:18:12 +00:00
Frederick [Bot] 56aef03697 chore(i18n): update translations via Crowdin 2026-04-19 01:46:56 +00:00
Frederick [Bot] 9b46ad8ecc chore(i18n): update translations via Crowdin 2026-04-18 01:23:08 +00:00
kolaente 89af0a6c14 refactor(frontend): use FormCheckbox for remember-me on Login 2026-04-17 12:54:17 +00:00
kolaente b9f6eabe2c refactor(frontend): use form primitives in WebhookManager 2026-04-17 12:54:17 +00:00
kolaente cab970b59b refactor(frontend): use form primitives in user settings General view 2026-04-17 12:54:17 +00:00
kolaente a6811a922a refactor(frontend): support two-col layout on FormField 2026-04-17 12:54:17 +00:00
kolaente 59e7c9bce3 feat(frontend): add FormCheckbox primitive component 2026-04-17 12:54:17 +00:00
kolaente 740546ee5a feat(frontend): add FormSelect primitive component 2026-04-17 12:54:17 +00:00
kolaente 875f685caf feat(frontend): add FormInput primitive component 2026-04-17 12:54:17 +00:00
kolaente 10e5fa915a refactor(frontend): drop Bulma components/navbar import
.navbar and .navbar-end are only used in AppHeader.vue. Ports the
relevant rules (z-index 30 and min-block-size: $navbar-height) into
its scoped <style> block and drops the partial import.
2026-04-17 07:43:35 +00:00
dependabot[bot] 10ec3b55b0 chore(deps): bump dompurify from 3.3.2 to 3.4.0 in /frontend
Bumps [dompurify](https://github.com/cure53/DOMPurify) from 3.3.2 to 3.4.0.
- [Release notes](https://github.com/cure53/DOMPurify/releases)
- [Commits](https://github.com/cure53/DOMPurify/compare/3.3.2...3.4.0)

---
updated-dependencies:
- dependency-name: dompurify
  dependency-version: 3.4.0
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-04-16 13:01:57 +00:00
Tink 95ec3325c2
refactor(frontend): migrate .box to Card and drop Bulma elements/box (#2640) 2026-04-16 14:14:36 +02:00
Tink 19ee7f26ee
refactor(frontend): drop Bulma components/card import (#2639) 2026-04-16 14:12:36 +02:00
Frederick [Bot] 3120c2b12c chore(i18n): update translations via Crowdin 2026-04-16 01:46:56 +00:00
kolaente 50465818ae refactor(frontend): drop Bulma components/media import
The .media / .media-left / .media-content classes are only used in
Comments.vue. Ports the relevant rules into its scoped <style> block
and drops the partial import.
2026-04-15 20:15:42 +00:00
kolaente 3c3b1820a1 refactor(frontend): port is-pulled-right locally and drop Bulma float helper
Only .is-pulled-right is used (3 callsites); .is-pulled-left and
.is-clearfix from Bulma's helpers/float partial have zero usage. Ports the
one needed rule into theme/helpers.scss so the Bulma import can go.
2026-04-15 20:12:45 +00:00
renovate[bot] 2ae194e943 chore(deps): update dependency postcss to v8.5.10 2026-04-15 16:25:26 +00:00
renovate[bot] 85dbef8330 chore(deps): update dependency stylelint to v17.8.0 2026-04-15 15:49:30 +00:00
kolaente d09ef36bd4 fix(frontend): guard Object.keys against null in refactored helpers
typeof null === 'object', so null slipped past the type guards in
objectToCamelCase/objectToSnakeCase/prepareParams. The original
for...in loops silently iterated nothing on null; Object.keys(null)
throws. Also guard saveCollapsedBucketState where state[projectId]
may be undefined.
2026-04-15 11:44:47 +00:00
kolaente dd83e0d42b refactor(frontend): replace reverse-index splice loops with findIndex/filter
Single-match removals use findIndex + splice; the reminder-null cleanup
uses filter since model.reminders is on a local shallow clone.
2026-04-15 11:44:47 +00:00
kolaente 2c6029eac4 refactor(frontend): replace for...in usages and forbid via lint rule
Replaces 33 for...in loops across 18 files with for...of + Object.keys/entries
or indexed for loops. for...in iterates enumerable string keys including
inherited ones, which is especially risky on reactive arrays (tasks, labels,
assignees, etc.) where polyfilled properties may appear.

Loops that mutate via splice during iteration now iterate backwards to avoid
index-shift bugs. Adds a no-restricted-syntax ESLint rule forbidding
ForInStatement to prevent regressions.

Closes #513
2026-04-15 11:44:47 +00:00
kolaente 95180a341d refactor(frontend): drop unused Bulma form/file partial import
Every file input in the codebase is hidden (via class="is-hidden" or
scoped display:none) and triggered programmatically by a custom XButton.
None of Bulma's .file / .file-label / .file-cta / .file-input / .file-name /
.file-icon classes are used anywhere in .vue files, so the partial is dead
code.
2026-04-15 11:06:11 +00:00
kolaente 39c804f460 refactor(frontend): drop unused Bulma modal partial import
Vikunja's Modal.vue uses a native <dialog> element with its own locally-
scoped classes (modal-dialog, modal-container, modal-content, modal-header).
None of Bulma's modal classes (.modal, .modal-background, .modal-card*) are
used anywhere in the app. The two CSS variables this partial provided
(--modal-card-head-padding, --modal-content-spacing-tablet) were inlined in
the two callers in the previous commits, so the whole partial is now dead
code.

Modal.vue already had several 'reset bulma' overrides fighting the default
rules Bulma applied to .modal-content; those can be cleaned up in a
follow-up.
2026-04-15 10:56:48 +00:00
kolaente d05fd4dbb2 refactor(frontend): inline modal-content-spacing-tablet in PDF preview
The --modal-content-spacing-tablet CSS variable is provided by Bulma's
components/modal partial. Inlining Bulma's default (40px) lets us drop that
partial.
2026-04-15 10:56:48 +00:00
kolaente 0b2f625f06 refactor(frontend): inline modal-card-head-padding in Card footer
The --modal-card-head-padding CSS variable is provided by Bulma's
components/modal partial. Inlining Bulma's default (20px) lets us drop that
partial without needing a local redeclaration.
2026-04-15 10:56:48 +00:00
kolaente 9899979ca7 docs(frontend): document styles architecture and token system 2026-04-15 10:02:39 +00:00
kolaente 02ae01ad80 chore(frontend): enable vue/multi-word-component-names with legacy allowlist 2026-04-15 09:58:55 +00:00
kolaente 21609127a1 fix(frontend): guard caldav and totp settings routes when disabled 2026-04-15 09:57:17 +00:00
kolaente 91d5cfb1c0 fix(frontend): render editor popups inside modal dialog top-layer
Native <dialog> elements opened with showModal() render in the browser's
top-layer. Popups appended to document.body end up behind the dialog
regardless of z-index, which broke the slash-command menu and the user
mention suggestion inside the task detail modal.

Append the popups to the nearest open <dialog> ancestor of the editor
(falling back to document.body) so they join the same top-layer stacking
context.
2026-04-15 08:39:24 +00:00
kolaente a1fbc277be
fix(deps): patch follow-redirects and basic-ftp security vulnerabilities
Update follow-redirects to 1.16.0 (fixes auth header leak on cross-domain
redirects) and basic-ftp to 5.2.2 (fixes CRLF injection in FTP commands).
2026-04-14 20:49:42 +02:00
kolaente f208279dd2 test(editor): add e2e for emoji autocomplete 2026-04-14 13:48:49 +00:00
kolaente c0f05b6277 feat(editor): register emoji autocomplete extension 2026-04-14 13:48:49 +00:00
kolaente 7ab2804129 feat(editor): add emoji TipTap extension 2026-04-14 13:48:49 +00:00
kolaente 02d4dd1631 feat(editor): add emoji suggestion handler 2026-04-14 13:48:49 +00:00
kolaente 88136ed45e feat(editor): add EmojiList popup component 2026-04-14 13:48:49 +00:00
kolaente 542cab5ef6 feat(editor): add lazy emoji data loader and filter 2026-04-14 13:48:49 +00:00
kolaente 7227c59f5e test(e2e/kanban): seed the view only once with done_bucket_id 2026-04-14 11:32:14 +00:00
kolaente af6923524f test(e2e/kanban): cover recurring task drag to done bucket (#2618) 2026-04-14 11:32:14 +00:00
kolaente d389408618 test(kanban): cover moveTaskToBucket 2026-04-14 11:32:14 +00:00
kolaente 13c4aec461 fix(frontend/kanban): honor server bucket redirect on drag (#2618) 2026-04-14 11:32:14 +00:00
renovate[bot] c68649faf4 chore(deps): update dev-dependencies 2026-04-14 10:51:01 +00:00
Frederick [Bot] 8bde434676 chore(i18n): update translations via Crowdin 2026-04-14 01:29:51 +00:00
renovate[bot] a3ac01346a chore(deps): update dev-dependencies 2026-04-13 10:14:34 +00:00
Frederick [Bot] 5ef01965e5 chore(i18n): update translations via Crowdin 2026-04-13 01:48:06 +00:00
renovate[bot] 160495b84e chore(deps): update dependency stylelint to v17.7.0 2026-04-12 14:42:19 +00:00
kolaente f6693f81a2 test(e2e): cover quick add auto-attaching default reminders 2026-04-11 21:51:41 +00:00
kolaente 5afd066a13 feat(tasks): apply default reminders to quick-add tasks with due date
When a user has configured default reminders in their frontend settings,
those are cloned onto every task created via quick-add magic that has a
parsed due date. Tasks without a due date are silently skipped.

The buildDefaultRemindersForQuickAdd helper is exported as a pure
function so it can be unit-tested without stubbing the Pinia store.
2026-04-11 21:51:41 +00:00
kolaente 338d4d8b76 feat(settings): surface quick add default reminders in user settings
Adds the settings field next to the quick add magic mode select, hidden
when that mode is set to Disabled. Uses Reminders.vue directly with
allow-absolute=false and default-relative-to pinned to due date.
2026-04-11 21:51:41 +00:00
kolaente 6c9753328b feat(i18n): add strings for quick add default reminders 2026-04-11 21:51:41 +00:00
kolaente dc4b7a5510 refactor(reminders): make Reminders.vue take ITaskReminder[] directly
Reminders.vue only read three task fields (dueDate/startDate/endDate)
and wrote one back (reminders). The ITask coupling was accidental.

Flip the prop to ITaskReminder[] and pass defaultRelativeTo / allowAbsolute
as plain props. TaskDetailView now owns the due/start/end priority
computation and binds v-model="task.reminders" directly. This also lets
the settings page reuse Reminders.vue for configuring default reminders.
2026-04-11 21:51:41 +00:00
kolaente b61ad9d46a feat(reminders): add allowAbsolute prop to ReminderDetail
Adds an allowAbsolute prop to ReminderDetail that hides the 'Date and
time' option when set to false, and a lockRelativeTo prop on
ReminderPeriod that hides the relativeTo select and forces the chosen
value. ReminderDetail threads them together so that when absolute
reminders are disallowed, the Custom form can only produce reminders
that anchor to defaultRelativeTo.
2026-04-11 21:51:41 +00:00
kolaente e85f3fd84c feat(settings): add quickAddDefaultReminders field to frontend settings 2026-04-11 21:51:41 +00:00
kolaente c06a33fb63 test(e2e): mirror task id to index in TaskFactory
Multiple TaskFactory.create(1, {id: N, ...}, false) calls for the same
project were all defaulting to index=1 (from {increment} with count=1),
which collides on the newly added UNIQUE(project_id, index) constraint.
Mirror the numeric id override to index so each row stays unique and
matches the id == index convention used by raw seedTasks helpers.

Fixes the e2e playwright seed failures in subtask-duplicates, list/table
filter/search, kanban filter/search, and overview specs.
2026-04-11 20:44:28 +00:00
kolaente 113b77e92f fix(modal): skip showModal if enabled flipped false before mount
Re-check props.enabled inside the dialogRef watcher. The watcher fires
once Vue mounts the <dialog>, but the caller may have flipped enabled
back to false between the openDialog() call and the mount flush. In that
case the prop state is disabled and we must not open the dialog.

Addresses augmentcode review on #2604.
2026-04-11 19:00:43 +00:00
kolaente e01a599418 fix(modal): clear stale data-closing flag when re-opened mid-close
If the modal is re-enabled within the 150ms close transition the
<dialog> element is still mounted and [open], so the dialogRef watcher
does not re-fire. Clear the leftover data-closing flag directly in
openDialog() so the dialog doesn't remain stuck at opacity 0.

Addresses augmentcode review on #2604.
2026-04-11 19:00:43 +00:00
kolaente e932ee759a fix(modal): open dialog reliably in electron desktop
Replace the nextTick-based showModal() call with a watch on the template
ref so the dialog is opened exactly when the <dialog> element mounts.
The previous implementation could silently skip showModal() if the mount
was deferred past the first nextTick, leaving the dialog in the DOM with
opacity: 0 and no click target. Observed in the Vikunja Desktop v2.3.0
Electron build where the search (quick actions) button was unresponsive.

Closes #2590
2026-04-11 19:00:43 +00:00
kolaente f29f985386 test(modal): cover open race for #2590 2026-04-11 19:00:43 +00:00
Frederick [Bot] 50d6926b56 chore(i18n): update translations via Crowdin 2026-04-11 01:20:45 +00:00
renovate[bot] df7a5c645c chore(deps): update dependency wait-on to v9.0.5 2026-04-10 22:57:21 +00:00
dependabot[bot] e8c20b1244 chore(deps): bump axios from 1.13.5 to 1.15.0 in /frontend
Bumps [axios](https://github.com/axios/axios) from 1.13.5 to 1.15.0.
- [Release notes](https://github.com/axios/axios/releases)
- [Changelog](https://github.com/axios/axios/blob/v1.x/CHANGELOG.md)
- [Commits](https://github.com/axios/axios/compare/v1.13.5...v1.15.0)

---
updated-dependencies:
- dependency-name: axios
  dependency-version: 1.15.0
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-04-10 09:58:30 +00:00
kolaente 28b537837f
chore: v2.3.0 release preparations 2026-04-09 20:43:40 +02:00
kolaente b642b2a453 feat(auth): prompt for TOTP code in the OIDC callback flow
When the backend reports that 2FA is required (412/1017), the OIDC
callback view now shows a TOTP input and restarts the OIDC dance
with the typed passcode stashed in localStorage so it can be
submitted alongside a fresh authorization code.

Refs GHSA-8jvc-mcx6-r4cg
2026-04-09 17:25:47 +00:00
kolaente 546db0dc21 feat(auth): plumb totp passcode through openIdAuth action
Allows the OpenIdAuth view to resubmit the OIDC callback with a
TOTP passcode after a 412/1017 response from the backend.

Refs GHSA-8jvc-mcx6-r4cg
2026-04-09 17:25:47 +00:00
kolaente 27a88dd17a
fix(deps): bump basic-ftp override to 5.2.1 to patch CRLF injection
Resolves Dependabot alert #183 (high severity): basic-ftp 5.2.0 is
vulnerable to FTP command injection via CRLF. The package is pulled in
as a dev-only transitive dependency by @histoire/plugin-screenshot.
2026-04-09 15:34:00 +02:00
kolaente 8814cb37d8
fix(tasks): vertically center checkbox in project task row
The tooltip span wrapping the checkbox used the inherited line-height
(~24px), so the 18px inline-block checkbox sat on the baseline and
appeared misaligned with the task text. Making the span an inline-flex
container collapses it to the checkbox size and centers it properly.
2026-04-09 15:30:27 +02:00
kolaente a574d623b1 test: add e2e regression test for link share loop while logged in
Covers #2546: a logged-in user navigating to a public link share URL
used to bounce infinitely between /share/:hash/auth and the project
view, stranding the user on an empty NoAuthWrapper shell. Two distinct
issues in checkAuth() produced the same symptom:

  1. The 1-minute debounce skipped re-parsing the new link share JWT
     when the user was already authenticated.
  2. The "same user, skip setUser" fast path compared only `id`, so a
     logged-in user whose id collided with the link share's id kept
     the USER `info.value.type` and `authLinkShare` never flipped.

The test pins both the logged-in user and the link share to the same
numeric id so it exercises the collision path, which catches both
regressions at once.
2026-04-09 10:20:46 +00:00
kolaente 432c5f2817 fix: include type in checkAuth's same-user skip check
Users and link shares share the same numeric id space in JWTs. When a
logged-in user opened a link share whose id happened to match their own
user id, checkAuth() would see `info.value.id === jwtUser.id` and skip
`setUser()`, leaving `info.value.type` as USER even though the new token
was a LINK_SHARE. As a result, `authLinkShare` never flipped to true and
the router guard bounced between /share/:hash/auth and the project view,
stranding the user on an empty NoAuthWrapper shell.

Compare on type as well so USER→LINK_SHARE transitions always replace
the user object.

Refs #2546
2026-04-09 10:20:46 +00:00
kolaente 2000732e35 fix: skip refreshUserInfo for link share tokens to prevent logout loop 2026-04-09 10:20:46 +00:00
kolaente 1d3a234b05 fix: reset checkAuth debounce in linkShareAuth to prevent redirect loop
When a logged-in user opens a public link share, the 1-minute debounce
on checkAuth() caused it to skip re-parsing the new link share JWT.
This left authLinkShare as false, triggering an infinite redirect loop
in the router guard.

Fixes #2546
2026-04-09 10:20:46 +00:00
kolaente 91728c0273 test: wire up API URL for anonymous link share e2e tests
The anonymous link share tests don't use the authenticatedPage fixture
(which implicitly calls setupApiUrl via login()), so the browser was
falling back to the default `window.API_URL = '/api/v1'` baked into
index.html. That relative path resolved against the preview server port
and never reached the API, causing the tests to hang on the NoAuth
"Welcome Back" page waiting for elements that never rendered.

Adding a beforeEach that calls setupApiUrl() restores these tests.
2026-04-09 10:20:46 +00:00
renovate[bot] 4415485675 chore(deps): update dependency vitest to v4.1.4 2026-04-09 08:59:51 +00:00
kolaente e7bc5a31e4 docs(shortcuts): show platform-aware delete key in keyboard shortcuts panel 2026-04-09 08:07:48 +00:00
kolaente cee2babc58 feat(tasks): use platform-aware delete shortcut on task detail view 2026-04-09 08:07:48 +00:00
Frederick [Bot] 36cec5ccca chore(i18n): update translations via Crowdin 2026-04-09 01:16:09 +00:00
kolaente 10e7d2532e fix: derive workbox version from package.json at build time
Instead of hardcoding the workbox version string in the service worker,
read it from workbox-precaching/package.json via Vite's define option.
This ensures the service worker always references the correct workbox
version that is actually installed.

Resolves #2549
2026-04-08 08:42:11 +00:00
renovate[bot] e898c01e3d chore(deps): update dev-dependencies 2026-04-08 08:03:18 +00:00
Frederick [Bot] f528bcc276 chore(i18n): update translations via Crowdin 2026-04-08 01:25:14 +00:00
kolaente 3437f98dc3 feat(migration): add skip rows option to CSV import
Allow users to skip the first N data rows when importing CSV files.
This is useful when the CSV contains metadata rows before the actual
task data begins. Adds skip_rows to ImportConfig (backend) and a
number input in the parsing options UI (frontend).
2026-04-07 15:20:06 +00:00
Claude f555762def feat(migration): add generic CSV import with column mapping
Add a new CSV migration module that allows users to import tasks from
any CSV file with custom column mapping and parsing options.

Backend changes:
- New CSV migrator module with detection, preview, and import endpoints
- Auto-detection of delimiter, quote character, and date format
- Suggested column mappings based on column name patterns
- Transactional import using InsertFromStructure

Frontend changes:
- New CSV migration UI with two-step flow (upload -> mapping -> import)
- Column mapping selectors for all task attributes
- Live preview showing first 5 tasks with current mapping
- Parsing option controls for delimiter and date format

The CSV migrator creates a parent "Imported from CSV" project with
child projects based on the project column if provided, or a default
"Tasks" project for tasks without a specified project.
2026-04-07 15:20:06 +00:00
surfingbytes 84f4c16425
feat(user): add option to hide last viewed projects on overview page (#2429) 2026-04-07 16:56:13 +02:00
kolaente 8a8d187065 chore(frontend): deduplicate pnpm dependencies 2026-04-07 14:22:04 +00:00
renovate[bot] 11299d773f chore(deps): update dependency vitest to v4.1.3 2026-04-07 13:43:01 +00:00
kolaente 20249ee68c style(sort): position popup aligned to header right edge 2026-04-07 13:41:13 +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 408e5b347c feat(sort): add sorting popup for list view 2026-04-07 13:41:13 +00:00
kolaente b20df2ef63
fix(deps): update brace-expansion to 5.0.5
Fixes zero-step sequence causing process hang and memory
exhaustion (Dependabot #168).
2026-04-07 15:39:33 +02:00
kolaente efc9b41349
fix(deps): update lodash to 4.18.1
Fixes code injection via _.template (Dependabot #176, #178) and
prototype pollution via _.unset/_.omit (Dependabot #175, #177).
2026-04-07 15:38:52 +02:00
kolaente f40eddd4e3
fix(deps): update defu to 6.1.7
Fixes prototype pollution via __proto__ key (Dependabot #180).
2026-04-07 15:38:17 +02:00
kolaente 34480ef513 fix(migration): center and style migrator logos on migration page
Use inline-flex layout to center logos with titles below. Constrain
logo size with max-block-size and use logical CSS properties.
2026-04-07 12:05:47 +00:00
kolaente 1a1fd780ec feat(migration): add WeKan to migration page with logo
Register WeKan in the AvailableMigrators list and add the frontend
migrator entry with the WeKan logo, referenced as "WeKan ®".
2026-04-07 12:05:47 +00:00
renovate[bot] 33886d2e3c chore(deps): update dev-dependencies 2026-04-06 16:23:31 +00:00
Frederick [Bot] 41a5087198 chore(i18n): update translations via Crowdin 2026-04-06 01:26:55 +00:00
kolaente 4b3b5bb87c docs(helpers): explain djb2 seed constant in stringHash 2026-04-05 12:24:45 +00:00
kolaente 65b6e55252 test(e2e): relax home greeting assertions for rotating pool 2026-04-05 12:24:45 +00:00