774 Commits

Author SHA1 Message Date
Tom Hykel ff6d46b067 Merge pull request #23720 from opf/task/69498-documents-admin-page-type-button-has-a-w
[STC-563] Fix label of new document type button in admin
2026-06-13 17:19:35 +02:00
Tomas Hykel 48b2f9d3ac [OP-18996] fix: Do not adjust capitalization of new document types 2026-06-12 16:20:40 +02:00
Tomas Hykel 4ecd255b59 fix: Documents admin page: "+Type" button has a wrong label ("+Add") (WP #69498) 2026-06-12 13:17:09 +00:00
Oliver Günther d851d25524 Merge remote-tracking branch 'origin/release/17.5' into dev 2026-06-10 11:29:44 +02:00
Kabiru Mwenja bb317278ba Merge pull request #23582 from opf/bug/stc-811-documents-pagination-breaks-upon-filtering-the-list
[STC-811] Fix pagination for filtered Documents & Reserved identifiers
2026-06-09 14:32:29 +03:00
ulferts db815d0d22 Merge remote-tracking branch 'origin/dev' into merge-release/17.5-20260609045502 2026-06-09 09:32:19 +02:00
Wieland Lindenthal 9763ebfeed Fix vertical content jumps in BlockNote editor (#23609)
Fix vertical content jumps in the BlockNote editor on selection

BlockNote 0.51 puts the className we pass to <BlockNoteView>
(`block-note-editor-container`) onto BOTH the outer `.bn-container`
wrapper AND an inner wrapper that does NOT carry `.bn-container`. With
the previous selector matching by class name alone, every rule cascaded
onto both nesting levels — most importantly `display: flex`,
`flex-direction: column-reverse` and `gap: 10px`.

Two flex layouts stacked one inside the other meant that whenever the
side menu / drag handle plugin views re-rendered (which happens every
time the selection moves or the mouse leaves the editor), both layout
calcs ran and the inner wrapper's gap shifted the visible content by a
few pixels.

Tightening the selector to `.block-note-editor-container.bn-container`
restricts the rules to the outer wrapper only; the inner wrapper falls
back to defaults (`display: block`, no gap) and stops contributing to
the layout.

Refs https://community.openproject.org/wp/STC-779

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-09 06:36:17 +02:00
Judith Roth 595872727c [STC-779] Add tests for CTRL-Z in documents
https://community.openproject.org/wp/STC-779
2026-06-08 16:26:19 +02:00
Tom Hykel 10c85224a9 Update modules/documents/spec/controllers/documents_controller_spec.rb
Co-authored-by: Kabiru Mwenja <k.mwenja@openproject.com>
2026-06-08 09:42:24 +02:00
Tomas Hykel 285f3381a9 [STC-811] Fix pagination for filtered Documents & Reserved identifiers 2026-06-05 14:18:05 +02:00
OpenProject Actions CI f9336b69c1 update locales from crowdin [ci skip] 2026-06-04 04:41:43 +00:00
OpenProject Actions CI a0b7b96ea4 update locales from crowdin [ci skip] 2026-06-04 04:37:15 +00:00
ihordubas99 4e73bd47d3 remove spec that cannot be reliably reproduced after BlockNote 0.51 upgrade 2026-06-03 14:56:04 +03:00
Alexander Brandon Coles fa5b7ee1b5 Merge remote-tracking branch 'opf/dev' into merge-release/17.5-20260603051246 2026-06-03 09:52:08 +02:00
Judith Roth 90317785d7 [#74654] Test markdown generation of BlockNote extensions
https://community.openproject.org/wp/74654
2026-06-02 17:02:40 +02:00
OpenProject Actions CI b2f72fd486 Merge branch 'release/17.5' into dev 2026-05-30 04:49:04 +00:00
Judith Roth 4dd97c267c [#75231] Add tests for inserting WP links with # notation
https://community.openproject.org/wp/75231

in BlockNote editor
2026-05-29 10:30:29 +02:00
Judith Roth f1b1ab307d [#75231] Fix test for op-blocknote-extensions in open project
https://community.openproject.org/wp/75231
2026-05-29 10:30:29 +02:00
Kabiru Mwenja f12fc7551f Migrate remaining mailers to format_mail_html / format_mail_text (#23387)
The view-helper migration introduced by the parent PR now covers the
remaining mailer surfaces: UserMailer (`message_posted`, `news_added`,
`news_comment_added`), ProjectMailer (`project_created`),
ProjectArtifactsMailer (`creation_wizard_submitted`), MemberMailer
(`added_project`, `updated_project`, `updated_global`), AnnouncementMailer
(`announce`), DocumentsMailer (`document_added`), and the shared mailer
layout (`localized_emails_header`, `localized_emails_footer`).

Sites drop the `static_html: true` / `only_path: false` / `plain_text: true`
boilerplate; `render_mode:` pinning lives in the helper.

The layout previously called `OpenProject::TextFormatting::Renderer.format_text`
directly, bypassing the helper layer. The empty visibility cache (no
current_user-scoped preload at layout time) is handled by the existing
fallback in `LinkHandlers::WorkPackages#text_only?` — covered by a new
sanity spec in `user_mailer_spec.rb` that exercises the header path with
a WP reference and asserts plain-text formatted_id rendering.

Per-bucket regression coverage added: absolute-URL and formatted_id
assertions across both classic and semantic identifier modes, mirroring
the WorkPackageMailer spec pattern.
2026-05-28 12:48:43 +03:00
Ivan Kuchin e3afba4465 follow yamllint except key ordering 2026-05-26 16:33:15 +02:00
Kabiru Mwenja 9edacbf73f Merge pull request #22892 from opf/feature/blocknote-external-link-a11y
(Blocknote): Add screen-reader hint for external links
2026-05-26 14:47:00 +03:00
Kabiru Mwenja 8a213e2c03 Move browser-action helpers to spec/support sibling file
Park BlockNoteEditorBrowserActions next to BlockNoteEditorInput in
spec/support/form_fields/primerized/. spec/support/**/*.rb is autoloaded
by rails_helper, so the spec file just `include`s the qualified module
name. Keeps raw-driver concerns (DOM Range selection, paste
ClipboardEvent dispatch, W3C-action Delete) out of the high-level page
object — that one stays focused on semantic actions like paste_links
and attach_file — and avoids the test-file fatigue of a 50-line helper
module inside the describe scope.
2026-05-21 15:36:39 +03:00
ihordubas99 437d0ec876 Merge pull request #23263 from opf/bug/74979-block-blue-border-is-clipped-on-the-left-side
Chip/block blue border is clipped on the left side at the beginning of a line
2026-05-21 13:54:16 +03:00
Kabiru Mwenja 28c94cfb46 Extract browser-action helpers in external-link spec
The two delete-path tests and the multi-inline-node paste test each
inlined a slab of `page.execute_script` to drive the editor's
contenteditable inside its shadow root, with significant duplication
around DOM Range setup and ClipboardEvent construction.

Pull these into a `BlockNoteEditorBrowserActions` module:

- `select_text_in_external_link(start_offset:, end_offset:)` — selects
  a substring of the first link's text node, with String-slicing
  semantics for the offsets (negatives count from the end).
- `send_forward_delete` — forward Delete via the W3C actions API,
  needed because Capybara's send_keys does not reach PM's editable in
  this setup.
- `paste_clipboard_into(element, html:, plain:)` — fires a paste
  ClipboardEvent on the given editor element.

The deletion-test comments are also tightened to describe the current
invariant (apply gate reseats the widget on any range deletion) rather
than the pre-rebuild mapping mechanics they used to enumerate.
2026-05-21 11:58:36 +03:00
Kabiru Mwenja 4113a2c382 Add spec for editing tail of surviving external link
Locks in the invariant that editing inside an existing link routes
through decoration mapping rather than a rebuild: the ReplaceStep
slice carries no link mark, so the apply gate maps the existing
widget set instead of recomputing it. The screen-reader hint must
shrink with the link run from the right and stay anchored to the
new tail, leaving exactly one hint on the surviving link.
2026-05-21 11:20:41 +03:00
Kabiru Mwenja ee4dfdeb19 Drop "Limitation" doc, codify deletion invariant in spec
The orphan-widget concern Copilot raised on the apply gate isn't
reachable. Forcing the gate's slice check off and deleting a whole
linked range still produces a clean DOM — PM's WidgetType.map
resolves the widget's position with assoc=-1 (which the widget's
side: -1 enforces), finds the anchor inside the deleted content,
and reports deleted: true. PM drops the decoration on its own.

Replacing the "Limitation" JSDoc paragraph (which described a
mental model that doesn't match WidgetType.map's rules) with a
feature spec that exercises a single-tx delete via DOM Range +
W3C actions Delete. The spec fails if side, the apply gate, or
buildDecorations ever stops preserving the invariant — serving
the disclosure purpose the JSDoc tried to, but mechanically.
2026-05-21 11:20:40 +03:00
Kabiru Mwenja cd735c01de Separate sr-only link hint from preceding link text
The sr-only "Open link in a new tab" hint becomes part of the link's
computed accessible name. Without a separator between the link text and
the hint, AT can announce them as a single concatenated word — descendant
text-node concatenation isn't guaranteed to insert whitespace, especially
in contenteditable. Prefix the widget text with an NBSP and relax the
feature spec to use `include` so the separator detail stays an
implementation concern of the extension.
2026-05-21 11:20:40 +03:00
Kabiru Mwenja 50b1a986c6 Add screen-reader hint for external links in BlockNote
VoiceOver and NVDA do not announce aria-describedby on links inside
contenteditable regions — both screen readers switch to edit mode and
ignore supplementary ARIA there. Even moving the attribute to the <a>
itself does not help.

Add an ExternalLinkA11yExtension that injects a sr-only,
contenteditable="false" span as a child of each external <a> via a
ProseMirror widget decoration wrapped in the link mark. The span text
becomes part of the link's accessible name, which screen readers
announce in every mode.

- Widget uses marks: [linkMark] + side: -1 so it renders inside the
  anchor and stays attached to the preceding link run on insertion.
- sameLinkContinues coalesces runs split across inline nodes (e.g.
  link text with a nested bold mark) so each link gets exactly one hint.
- readDescription warns once if #open-blank-target-link-description is
  missing, surfacing silent empty-hint regressions.
- Extracts isHrefExternal from isLinkExternal so the extension can
  check ProseMirror mark attrs (URL strings) directly.
- Decorations never mutate the document model — no DOMObserver
  mutation loop, no Yjs/collaboration side effects, no persistence.

References https://community.openproject.org/wp/73721
2026-05-21 11:20:38 +03:00
Judith Roth 3a97308083 [#73664] Create work package links through # notation in documents / BlockNote
https://community.openproject.org/wp/73664
2026-05-20 14:56:40 +02:00
ihordubas99 6e59a19769 fix: remove overflow auto from bn-editor to prevent card border clipping 2026-05-19 14:27:50 +03:00
OpenProject Actions CI d5b027b04b update locales from crowdin [ci skip] 2026-05-19 04:31:41 +00:00
OpenProject Actions CI bda5ed1cdc update locales from crowdin [ci skip] 2026-05-10 04:24:16 +00:00
Ivan Kuchin bd7a0cfde1 Merge pull request #22930 from opf/fix-multiple-equality-non-equailty-filters
fix multiple equality, non equality filters
2026-05-07 15:52:07 +02:00
Alexander Brandon Coles e8767481e9 [#70166] Fix accessibility errors found by ERB Lint (#21503)
* Fix GitHub/NoTitleAttribute, LinkHasHref errors

- Replaces `title` attribute with `aria-label` for interactive elements.
- Removes `title` from non-interactive elements.
- Converts `<a>` tags without proper `href` to `<button>` elements,
  using Primer `Button`/`IconButton` where possible.

# Conflicts:
#	app/views/custom_fields/_custom_options.html.erb
#	spec/features/admin/custom_fields/shared_custom_field_expectations.rb
#	spec/features/admin/custom_fields/work_packages/list_spec.rb

* Fix Autocomplete missing errors

* Fix GitHub/NoPositiveTabIndex errors

Removes all positive `tabindex` values.

* Fix Rails/LinkToBlank errors

* Replace toast with Primer Banner on LDAP form

* Add frozen_string_literal

* Ignore erb lint for deprecated files

* Fix linting errors in repository module

* Fix linting errors in budgets and custom actions

* Fix linting errors in member form and 2fa

* Fix linting errors in mcost types and wiki help and storages

* Fix linting errors in multi select filters, ifc viewer, and unsupported browser banner

* Fix failing spec

* Use Primer banner instead of op-toast where ever it is possible

* Use octicon instead of op_icon

* Fix failing tests

* Use no-decoration-on-hover for button links and change the button with only an icon to primer icon button

* Keep webhook response modal activation selector class-based

* use icon button for edit of hourly rate

---------

Co-authored-by: Behrokh Satarnejad <b.satarnejad@openproject.com>
2026-05-07 10:31:10 +02:00
OpenProject Actions CI 0e4437def6 update locales from crowdin [ci skip] 2026-05-06 04:21:38 +00:00
Ivan Kuchin 7756f44acc fix multiple equality, non equality filters 2026-05-05 20:33:25 +02:00
Dombi Attila eaa82a95ca Merge branch 'dev' into merge-release/17.4-20260505152418 2026-05-05 19:37:24 +03:00
Judith Roth f9b0f21c8b Merge pull request #23009 from opf/jr/bump/op-blocknote-extensions-version-to-0-0-24
Update op-blocknote-extensions to version 0.0.24 for improvements in the search input
2026-05-05 13:12:10 +02:00
Judith Roth c38d935f59 [#69706] Fix tests for op-blocknote-extensions 0.0.24
In 0.0.24 a callback was added that removes the whole search input from
the DOM / document when a blur event (e.g. clicking anywhere else)
occurs. This broke the capybara tests, since they somehow triggered that
blur and then the whole input was removed from the DOM before the tests
were finished testing it.
Therefore now all interaction of with the work package search input is
done via js whithout any interruptions that cause a blur event.
I am not happy about this solution and asked to relax that blur
requirement to e.g. only remove the search when the document / browser
tab is closed, but this was refused. So this is the only solution to
keep the tests in at all.

https://community.openproject.org/wp/69706
2026-05-04 14:51:36 +02:00
OpenProject Actions CI 1bfcabdcf0 update locales from crowdin [ci skip] 2026-05-03 04:23:33 +00:00
OpenProject Actions CI f23a76833a update locales from crowdin [ci skip] 2026-05-03 04:21:13 +00:00
Jan Sandbrink fdef123dd1 Merge pull request #22921 from opf/css-fixes
CSS improvements
2026-04-24 12:02:27 +02:00
Jan Sandbrink 734b049a8a CSS improvements
Improve visual representation of inline macros, by ensuring
they all use the same CSS attributes and have a reduced vertical padding,
so they don't overlap as much.

We also improved the vertical alignment of the leading icon for these macros.

As a sidefind, we replaced a handcrafted version of the InlineMessage with the
existing InlineMessage component. This also improved alignment of the icon.
2026-04-24 11:17:24 +02:00
OpenProject Actions CI f579df8b4b update locales from crowdin [ci skip] 2026-04-24 04:18:08 +00:00
OpenProject Actions CI 4e56e47774 update locales from crowdin [ci skip] 2026-04-24 04:10:24 +00:00
Kabiru Mwenja 92a1346f81 Merge pull request #22696 from opf/feature/blocknote-native-extensions
(Blocknote): Add external link capture
2026-04-23 13:41:48 +03:00
Kabiru Mwenja 01cd3f5663 Drop block-form rescue modifier in capture window cleanup
Lint/RedundantCopDisableDirective flagged the inline Style/RescueModifier
disable as unnecessary on CI. Locally the cop fires and the disable is
needed, so the constructs disagree across environments. Rewrite the
ensure-block cleanup to use a rescue-in-do form instead — no modifier,
no directive, same behavior.
2026-04-23 13:02:56 +03:00
Kabiru Mwenja 2077f295cc Migrate from TipTap extensions to BlockNote native extensions
Use BlockNote's createExtension() with prosemirrorPlugins instead of
TipTap's Extension.create() via the internal _tiptapOptions escape
hatch. The BlockNote team has clarified that _tiptapOptions is not
part of the public API and should not be relied on.

Functionally identical — same ProseMirror plugin, same mousedown
interception — just wrapped in the supported BlockNote primitive.
2026-04-23 12:18:17 +03:00
Kabiru Mwenja 81dd632371 Harden link capture plugin and improve test reliability
Handle Text node event targets by normalizing to parentElement
before calling closest('a'). Guard against clicks on anchors
outside the editor content with view.dom.contains(). Replace
brittle sleep with rspec-wait polling for window count.
2026-04-23 12:15:17 +03:00
Kabiru Mwenja db857fd872 Fix double-window bug by moving link capture to ProseMirror plugin
TipTap's Link extension handles clicks via ProseMirror's mouseup-based
handleClick, which fires before any DOM click event. The Stimulus
controller's click interception couldn't prevent TipTap from also
opening a window, resulting in two windows on every external link click.

Replace the Stimulus click interception with a TipTap extension that
uses handleDOMEvents.mousedown. Returning true from mousedown prevents
ProseMirror from creating its internal MouseDown tracker, so the entire
handleClick chain never fires. Only our redirect window opens.

The extension is conditionally registered via _tiptapOptions only when
external link capture is enabled. When disabled, TipTap's default
openOnClick behavior handles link clicks natively.
2026-04-23 12:15:17 +03:00