Commit Graph

2820 Commits

Author SHA1 Message Date
kolaente 0e17556a16 fix(editor): make link prompt a sub-modal — Escape cancels it without closing the task dialog
Review point (#2950, comment 3444116036): when the surrounding task
<dialog> closed while the link prompt was open, the prompt was orphaned
and cleanup() never ran, leaking listeners and an unresolved promise.

Treat the prompt as a sub-modal of the task dialog: pressing Escape while
it is open now preventDefault()/stopPropagation()s the keydown so the
native modal <dialog> does not close on Escape, resolves the prompt with
'' (cancel) and runs cleanup() — only the prompt is dismissed, the task
dialog stays open. A one-shot 'cancel' listener on the enclosing dialog
backs this up in case the keydown handling is insufficient in some browser.

Tighten cleanup() so the prompt fully tears down regardless of how it
closes (Enter / Escape / click-outside): it now removes the scroll
listener, the document click listener and the dialog cancel listener, and
removes the element. handleClickOutside was hoisted so cleanup() can
remove it, closing the leaked-listener gap directly.

Adds an e2e asserting Escape cancels the prompt while the task dialog
stays open; the existing 'Enter creates the link' case still passes.
2026-06-19 20:14:19 +00:00
kolaente 84dc57c562 fix(editor): render link prompt inside the task dialog so it works in the Kanban popup (#2940)
The Kanban task popup renders the description editor inside a native
<dialog> opened via showModal(), which lives in the browser's top-layer.
inputPrompt appended its URL <input> to document.body, so it was painted
behind the top-layer dialog (z-index cannot beat the top-layer) and could
not be focused through the dialog's focus trap. As a result clicking "Link"
in the popup did nothing, while it worked on the full task page (no modal).

Thread the TipTap editor through inputPrompt and append the prompt to
getPopupContainer(editor) — the open dialog ancestor when present, falling
back to document.body otherwise, so non-modal usage is unchanged. This is
the same helper the slash menu and mentions already use to escape the
top-layer (#1746).

Fixes #2940
2026-06-19 20:14:19 +00:00
Tink 82dae774f1
fix(views): persist list/table sort across sidebar navigation (#2778) 2026-06-19 22:08:06 +02:00
kolaente 63b7f32379 fix(editor): render floating popups inside the task dialog (Kanban popup)
The Kanban task detail opens as a native <dialog> via showModal(), which
paints in the browser top-layer. Floating UI appended to document.body
(or teleported to <body>) then renders behind the dialog regardless of
z-index, matching the bug class of #2940 / #1746 / #1899 / #1929.

- Emoji autocomplete popup: append to getPopupContainer(editor) (the open
  dialog ancestor, else body), the same helper the slash menu and mentions
  already use. Also switch its unmount to popupElement.remove() so it works
  no matter which container it was appended to.
- Attachment dropzone overlay: teleport into the topmost open
  dialog.modal-dialog instead of always <body>, mirroring Notification.vue,
  so the drag-and-drop hint is visible while a task detail dialog is open.
2026-06-19 19:03:20 +00:00
Tink b6af132845
fix(auth): preserve desktop authorize URL when not signed in (#2944) 2026-06-19 19:50:47 +02:00
renovate[bot] ab927aa772 chore(deps): update dev-dependencies to v4.62.2 2026-06-19 17:32:00 +00:00
Tink 7208694960
fix(auth): build OIDC end-session URL with RP-Initiated Logout params (#2943) 2026-06-19 18:27:33 +02:00
renovate[bot] 54fbc79a52 chore(deps): update dev-dependencies to v4.62.1 2026-06-19 16:09:04 +00:00
kolaente 6e1b15e344 fix(tasks): add labels sequentially when the backend db serializes writes
Quick Add Magic with multiple labels (`*a *b *c`) fired all
`PUT /tasks/{id}/labels` requests concurrently via `Promise.all`. On
SQLite these overlap as read-then-write upgrade transactions, which the
busy_timeout can't resolve, so some requests fail with HTTP 500
("database is locked") and the labels are silently dropped while the
quick-add input gets stuck.

Expose a `concurrent_writes` flag on the shared `/info` response (true
for Postgres/MySQL, false for SQLite). The frontend config store reads
it and `addLabelsToTask` now branches: parallel `Promise.all` when the
backend supports concurrent writes, sequential awaits otherwise.

Fixes #2680
2026-06-19 14:19:19 +00:00
Tink f3c6312a9e
feat(projects): make duplicating shares opt-in (#2932) 2026-06-19 10:15:58 +02:00
Rashed Arman 5edc7b5160 fix: blur quick add input on escape 2026-06-18 21:42:21 +00:00
kolaente 9d18ba236f
feat(time-tracking): add favicon indicator for active time tracking sessions (#2937) 2026-06-18 23:52:52 +02:00
dependabot[bot] 1e1e733c36 chore(deps): bump dompurify from 3.4.9 to 3.4.11 in /frontend
Bumps [dompurify](https://github.com/cure53/DOMPurify) from 3.4.9 to 3.4.11.
- [Release notes](https://github.com/cure53/DOMPurify/releases)
- [Commits](https://github.com/cure53/DOMPurify/compare/3.4.9...3.4.11)

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

Signed-off-by: dependabot[bot] <support@github.com>
2026-06-18 21:25:47 +00:00
renovate[bot] 80bb9aadc1 chore(deps): update dev-dependencies to v20.10.6 2026-06-18 20:54:23 +00:00
kolaente 86ec62d10b
fix(frontend): scroll tall default modals instead of clipping their top
Centered default/hint-modal content used translate(-50%, -50%) with no
height cap, so a taller-than-viewport modal (e.g. project background
settings with the Unsplash grid) pushed its top edge above the viewport
where the container's overflow can't reach it — the upload button became
unreachable on short screens.

Cap the centered content to the viewport and scroll inside it, mirroring
the height limit the .top (quick actions) variant already has. The mobile
breakpoint resets both so the fullscreen layout keeps flowing in
.modal-container.
2026-06-18 22:24:47 +02:00
kolaente 2cc7c0b6f0 fix(frontend): auto-refresh relative dates as time passes
Relative dates ("5 minutes ago", "in 2 hours") were computed once via
dayjs().fromNow() and never recomputed, so a view left open kept showing
the value from the moment it was rendered.

Compute the relative string against the shared, ticking `now` from
useGlobalNow() instead. This makes every reactive caller — <TimeDisplay>,
direct formatDateSince() calls, and formatDisplayDate() when the user's
date display is set to relative — re-render on the existing 60s tick.
Absolute date formats don't read `now`, so they never needlessly
re-render.

useGlobalNow can now be initialised from a plain helper rather than only
from a component, so its route-update hook is guarded with
getCurrentInstance().
2026-06-17 20:10:21 +00:00
renovate[bot] 434b5d9fe3 chore(deps): update dev-dependencies to v10.5.0 2026-06-17 19:14:26 +00:00
kolaente 8a255cbff6 fix(gantt): preserve horizontal scroll when focusing a task bar
Focusing the task bar SVG `<g role="slider">` inside the
`overflow-x:auto` `.gantt-container` triggered Firefox's focus-induced
scroll-into-view, which jumped the scroll container back toward
`scrollLeft=0` (today). Pass `{ preventScroll: true }` to `focus()` so
selecting a bar keeps the current scroll position. Chromium scrolls
minimally on focus so it never manifested there.

Fixes #2728
2026-06-17 18:17:29 +00:00
renovate[bot] ffcf92936a chore(deps): update dev-dependencies 2026-06-17 12:02:41 +00:00
renovate[bot] ea4bb09679 chore(deps): update dev-dependencies 2026-06-17 11:22:03 +00:00
Frederick [Bot] a8bce2ef0b chore(i18n): update translations via Crowdin 2026-06-17 00:35:30 +00:00
renovate[bot] f851e6f959 chore(deps): update dev-dependencies 2026-06-16 11:46:40 +00:00
kolaente e13d3f537c
fix(deps): bump js-yaml to >=4.2.0 where possible
Desktop only has the v4 copy, so a plain override pins it to >=4.2.0
(resolves alert #245). The frontend also pulls js-yaml v3 via
gray-matter (histoire story tooling), which has no v4-compatible
release, so a scoped 'js-yaml@4' override bumps only the v4 copies
(eslint/cosmiconfig) and leaves gray-matter on 3.14.2. Alert #256
stays open for that dev-only, trusted-input path.
2026-06-16 08:33:16 +02:00
kolaente 9cc47a3da4
fix(deps): force @babel/core >=7.29.6
Resolves the @babel/core <=7.29.0 advisory. Transitive; pinned via
pnpm override. Dependabot alert #255 (frontend).
2026-06-16 08:32:36 +02:00
kolaente d054fb7a5b
fix(deps): force launch-editor >=2.14.1
Resolves the launch-editor <=2.14.0 advisory. Transitive (via
vite-plugin-vue-devtools); pinned via pnpm override. Dependabot
alert #257 (frontend).
2026-06-16 08:32:20 +02:00
kolaente be5858aafe
fix(deps): force markdown-it >=14.2.0 to fix ReDoS advisory
Resolves the markdown-it <=14.1.1 advisory. Transitive; pinned via
pnpm override. Dependabot alert #266 (frontend).
2026-06-16 08:31:46 +02:00
kolaente 460e8f3ab1
fix(deps): force form-data >=4.0.6 to fix unsafe boundary advisory
Resolves the form-data <4.0.6 advisory (predictable multipart
boundary). Transitive in both workspaces; pinned via pnpm overrides.
Dependabot alerts #247 (desktop) and #258 (frontend).
2026-06-16 08:30:33 +02:00
kolaente 652f61da50
fix(deps): bump dompurify to 3.4.9 to fix XSS advisories
dompurify 3.4.0 was affected by several stacked advisories (mXSS /
sanitizer bypasses). 3.4.9 is past all vulnerable ranges. Resolves
Dependabot alerts #248-#254 (package.json) and #259-#265 (lockfile).
2026-06-16 08:30:00 +02:00
kolaente b42a7fdcc4
fix(deps): force esbuild >=0.28.1 to fix transitive advisories
The frontend pins esbuild 0.28.1 directly, but vite/histoire and
@intlify/bundle-utils pulled in transitive copies (0.27.7 and 0.25.12)
still affected by GHSA-gv7w-rqvm-qjhr (RCE via missing binary integrity
verification) and GHSA-g7r4-m6w7-qqqr (dev-server file read on Windows).
A pnpm override forces all copies to the patched 0.28.1. Dependabot
alerts #239 and #241.
2026-06-16 08:18:18 +02:00
kolaente 1d6d332c18
fix(deps): bump tmp to >=0.2.7 to fix path traversal advisory
Resolves GHSA-7c78-jf6q-g5cm (type-confusion bypass of _assertPath
allowing path traversal). tmp was pinned to >=0.2.6 via pnpm overrides
in both the frontend and desktop workspaces, which resolved to the
vulnerable 0.2.6. Dependabot alerts #243 (desktop) and #244 (frontend).
2026-06-16 08:17:51 +02:00
Frederick [Bot] 85b820fa7c chore(i18n): update translations via Crowdin 2026-06-16 00:40:29 +00:00
dependabot[bot] 35bcb7ed26 chore(deps-dev): bump esbuild from 0.28.0 to 0.28.1 in /frontend
Bumps [esbuild](https://github.com/evanw/esbuild) from 0.28.0 to 0.28.1.
- [Release notes](https://github.com/evanw/esbuild/releases)
- [Changelog](https://github.com/evanw/esbuild/blob/main/CHANGELOG.md)
- [Commits](https://github.com/evanw/esbuild/compare/v0.28.0...v0.28.1)

---
updated-dependencies:
- dependency-name: esbuild
  dependency-version: 0.28.1
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-06-15 17:34:06 +02:00
kolaente 8ff4696786 fix(frontend): restore quick actions menu styling and height limit
The quick actions menu (cmd+k) rendered without any background and grew
beyond the viewport:

- Its card visuals came from the global Bulma .card styles, which were
  dropped when Card.vue got its own scoped copy — QuickActions is the
  only place using a bare class="card" div, so it lost background,
  border and shadow. Give it its own card styles.
- Its height limit came from Bulma's .modal-content max-height, lost
  when the Bulma modal import was dropped in the native-dialog refactor.
  The :deep(.modal-content) position override in QuickActions never
  matched (.modal-content is an ancestor of the scoped selector, not a
  descendant). Replace both with a proper `top` modal variant that
  anchors the content 3rem below the top edge and caps its height,
  resolving the FIXME asking for exactly that option.
- The dark scrim never showed: Chromium intermittently stops painting a
  styled ::backdrop (after subtree re-renders, or while display is
  transitioned) even though getComputedStyle reports the color. Move
  the scrim onto the viewport-filling dialog element itself — same as
  the old div-based .modal-mask — and drop the display/allow-discrete
  transitions, which the JS-timed close fade never needed.
2026-06-12 07:26:17 +00:00
Frederick [Bot] f819b685d8 chore(i18n): update translations via Crowdin 2026-06-12 00:35:31 +00:00
Milad Nazari 1cf10b563a fix(frontend): fix buttons alignments in rtl direction 2026-06-11 19:45:57 +00:00
Milad Nazari adc8070ff9 feat(i18n): add persian to list of selectable languages 2026-06-11 19:45:57 +00:00
renovate[bot] 070ce19286 chore(deps): update dev-dependencies 2026-06-11 18:23:55 +00:00
kolaente a88aef0e47
fix(deps): update shell-quote to 1.8.4 2026-06-11 09:51:41 +02:00
kolaente e16d120236 fix(time-tracking): cap smart-fill start at now so the range is never inverted
Smart-fill set the From time to the configured default start (09:00) when there
was no recent entry to continue from. Before that time of day the default lands
in the future, after the To time of now, producing an inverted range the backend
rejects (end_time before start_time). The save then failed silently and the
entry never appeared.

This surfaced as a flaky time-tracking e2e suite: the smart-fill specs failed
only when CI happened to run before 09:00 UTC.
2026-06-10 11:47:47 +02:00
Frederick [Bot] 8502c541a6 chore(i18n): update translations via Crowdin 2026-06-10 00:33:40 +00:00
renovate[bot] cb0d24dae1 chore(deps): update dev-dependencies to v8.61.0 2026-06-09 11:47:14 +00:00
Frederick [Bot] df6a56b195 chore(i18n): update translations via Crowdin 2026-06-09 00:26:57 +00:00
kolaente 00bbdbf95b refactor(time-tracking): drop the now-redundant duration clamp in the entry list 2026-06-08 13:54:09 +00:00
kolaente 4390af4773 test(time-tracking): add end-to-end coverage 2026-06-08 13:54:09 +00:00
kolaente 2d334e56c7 i18n(time-tracking): add the time-tracking UI strings 2026-06-08 13:54:09 +00:00
kolaente 7c021dd663 feat(time-tracking): configure the smart-fill start time in settings 2026-06-08 13:54:09 +00:00
kolaente e948b191b0 feat(time-tracking): add the time-tracking view 2026-06-08 13:54:09 +00:00
kolaente 2ef898e89d feat(time-tracking): add the task-detail time-tracking section 2026-06-08 13:54:09 +00:00
kolaente 8febfac742 feat(time-tracking): add the sidebar navigation entry 2026-06-08 13:54:09 +00:00
kolaente 212d891fa1 feat(time-tracking): show a running-elsewhere badge in the header 2026-06-08 13:54:09 +00:00