Commit Graph

3666 Commits

Author SHA1 Message Date
OpenProject Actions CI 523ef39065 Merge branch 'release/17.5' into dev 2026-06-01 14:42:29 +00:00
Oliver Günther 1f3da064ac Escape CSV formula cells by default 2026-06-01 13:44:29 +02:00
Klaus Zanders e53b50fa94 Merge branch 'dev' into filter-form-with-wp-query 2026-05-30 17:08:42 +02:00
OpenProject Actions CI b2f72fd486 Merge branch 'release/17.5' into dev 2026-05-30 04:49:04 +00:00
Kabiru Mwenja 14ef6f901d Use semantic identifier for server-rendered search result links
Work package results on the search page build their link through the
acts_as_event url proc, which passed the numeric primary key instead of
the work package's display id. In semantic mode this rendered
/work_packages/<id> even though the row showed the semantic identifier,
unlike Rails URL helpers that already resolve the object via to_param.
Pass display_id so the link follows the same convention everywhere.
2026-05-29 19:12:27 +03:00
Klaus Zanders 5db7e6afaf Add specs 2026-05-29 13:56:36 +02:00
Tom Hykel 91c3d143dc fix(ui): Numeric ID instead of semantic one on the Activity page (WP #74912) (#23345)
---------

Co-authored-by: Kabiru Mwenja <k.mwenja@openproject.com>
2026-05-29 14:45:43 +03:00
Klaus Zanders 7af6f5d6cf Merge pull request #23441 from opf/filter-form-component
Filter form component
2026-05-29 11:18:27 +02:00
Oliver Günther 5330745e69 Add the content type for external URLs 2026-05-29 10:26:43 +02:00
Oliver Günther 6f63faeed1 Extract and use charset to properly encode attachments 2026-05-29 10:26:43 +02:00
Klaus Zanders 2a7e93d978 Add compatability for Work Package Queries 2026-05-29 09:28:03 +02:00
Kabiru Mwenja 58a5e19669 bug/74156 Sort WP lists by project identifier, not project_id, in semantic mode (#23400)
Sort WP lists by project identifier, not project_id, in semantic mode

The semantic-mode "ID" sort grouped projects by project_id (insertion
order) before the per-project sequence. Projects added after others
landed below them in the list even when their identifier sorted
alphabetically earlier. Sort by projects.identifier instead so the order
matches the visible "<project identifier>-<sequence>" column.

The projects table is already joined for every work-package list query,
so the new sort term costs no extra round-trip.
2026-05-28 12:05:24 +03:00
Kabiru Mwenja ab32cab495 Merge pull request #23337 from opf/bug/74762-numeric-id-in-the-email-notification-after-adding-watchers
bug/74762 Numeric ID in the email notification after adding watchers
2026-05-28 11:38:02 +03:00
Andrej fca9d9cf3f Merge pull request #23379 from opf/bug/75381-jira-migrator-give-not-helpful-error-message-if-user-email-is-blank
[#75381] Jira Migrator give not helpful error message if user email is blank
2026-05-27 11:55:22 +02:00
Pavel Balashou 365db7e703 [#75381] Jira Migrator give not helpful error message if user email is blank
https://community.openproject.org/wp/75381

- Add user/group information to the error message in case of creation failure.
2026-05-27 10:55:22 +02:00
Kabiru Mwenja c607b36b8e Rename with_hash_prefix to format_display_id 2026-05-26 22:10:07 +03:00
Kabiru Mwenja 7c9d15e506 Render WP identifiers per current mode in plain-text mailer notes
The `mentioned` and `watcher_changed` text-mailer bodies surfaced raw
journal markdown — numeric `#42` references stayed numeric in semantic
mode, and `<mention>` envelopes leaked as HTML source.

Introduces `:plain_text` as a sibling format inside the existing Plain
module. The filter chain mirrors the markdown pipeline (markdown,
sanitization, mention, pattern-matcher) and finishes with a new
`PlainTextOutputFilter` that collapses the DOM to text. The
`WorkPackages` link handler and `MentionFilter` get plain-text branches
keyed off `context[:plain_text]` so identifier resolution stays in one
place across rich and plain channels.

Closes https://community.openproject.org/wp/74762
2026-05-26 14:18:17 +03:00
Andrej 7e53ebf981 Merge branch 'release/17.5' into bug/75238-jira-migrator-cannot-import-a-user-with-non-alphanumeric-characters-in-their-name 2026-05-26 09:08:25 +02:00
Tomas Hykel 948fa43321 chore: Remove feature flag for project-based work package identifiers 2026-05-25 17:45:06 +02:00
Kabiru Mwenja 6de4e2a76b bug/74156 Lists of work packages should sort correctly in semantic mode (#23299)
Sort work packages by sequence_number in semantic mode

In semantic mode the visible "ID" is `<project_identifier>-<sequence_number>`,
but the list sort key was the database primary key. A work package moved
between projects keeps its primary key and receives a new sequence number
in the target project, so it could appear above natively-created rows with
higher sequence numbers — e.g. `LARGE-3` above `LARGE-1` and `LARGE-2`.

The "ID" sortable on the work-package query select now resolves at request
time. In semantic mode it returns `(work_packages.project_id, work_packages
.sequence_number)`, backed by the existing partial unique index. In classic
mode it stays `work_packages.id`. The Proc resolution lives in
`WorkPackageSelect#sortable` so every consumer (`Query::SortCriteria`,
group-by composition, the HAL/API sortBy resource) sees the resolved value.
2026-05-21 20:00:09 +03:00
as-op 43291c56ea [#75238] Jira Migrator cannot import a user with non-alphanumeric characters in their name
https://community.openproject.org/wp/75238
2026-05-21 16:36:37 +02:00
Kabiru Mwenja e597aa4216 Fix NameError: uninitialized constant Projects::Identifier::CLASSIC_IDENTIFIER_FORMAT (#23293) 2026-05-20 22:02:41 +03:00
Kabiru Mwenja b87afc480a Merge pull request #23138 from opf/implementation/74766-adapt-pdf-text-macro-link-handler-for-semantic-work-package-identifiers
Resolve semantic identifiers in PDF text macro links
2026-05-20 19:11:31 +03:00
Kabiru Mwenja 24c869b5c4 Apply review feedback to PDF semantic macro handler
Scope semantic-id resolution through `WorkPackage.visible` so a reference to a
work package outside the current user's visibility falls through to literal
text. Without this, semantic identifiers (guessable, project-prefixed) would
disclose existence: a hidden `#PROJ-1` would resolve and render a mention,
whereas a non-existent `#GHOST-1` would fall through — a discoverable oracle.
Spec pins the new contract; matches the in-app preload pipeline which already
uses `WorkPackage.visible`.

Drop the `to_i.to_s` round-trip on the numeric branch. `numeric_id?` already
verifies the matched string is canonical, so the round-trip is a no-op.

Tighten the alias spec to assert the rendered `data-text` carries the current
identifier, not just that the old one is absent. Trim the `render_link`
comment to the load-bearing claim (defence-in-depth escape).
2026-05-20 17:32:17 +03:00
Jens Ulferts 0ceaa2617c Merge pull request #23181 from opf/code-maintenance/74768-remove-calculated_value_project_attribute-feature-flag
[#74768] Remove calculated_value_project_attribute feature flag
2026-05-20 16:09:46 +02:00
Kabiru Mwenja 796f6b1ccd Resolve semantic identifiers in PDF text macro links
In semantic mode, the PDF text-macro handler resolves `#PROJ-1`,
`##PROJ-1`, and `###PROJ-1` through `find_by_display_id` and emits a
`<mention>` whose `data-id` carries the display id straight through to
the PDF renderer. Cache misses (unknown identifier, deleted WP) fall
through to literal text. Historical aliases resolve to the current
identifier. Classic mode rejects semantic-shape input — `#PROJ-1` in
a classic-mode export stays literal.

Numeric input keeps its current path: the matcher emits the mention
from the matched id without a DB lookup.

`render_link` HTML-escapes both interpolated values. The matcher
regex (`ID_ROUTE_CONSTRAINT`) already constrains shape to
`\d+|[A-Z][A-Z0-9_]*-\d+`, so the escape is defence-in-depth: a
future caller bypassing the matcher cannot regress into HTML
attribute injection.

The fast-path filter `Links.applicable?` matches `/#[A-Z\d]/` so
semantic-only bodies reach the full regex.

Downstream `Exports::PDF::Common::Markdown#wp_mention_macro` is
updated to `find_by_display_id` in PR 23093. This commit must land
after that PR — otherwise its existing `id[/\d+/]; find_by(id:)`
extracts the trailing digits from `data-id="PROJ-7"` and resolves
to WP id 7.
2026-05-20 16:35:04 +03:00
Dombi Attila 8a8e47550d Merge branch 'dev' into feature/71305-exclude-certain-work-package-types-from-automated-backlog-per-project 2026-05-20 12:47:25 +03:00
Oliver Günther 3b3791f9ec Use correct configuration for group filter on user administration
https://community.openproject.org/work_packages/74763
2026-05-20 09:18:57 +02:00
OpenProject Actions CI 7e1c003ba7 Merge branch 'release/17.4' into dev 2026-05-20 06:43:24 +00:00
OpenProject Actions CI 82c65d6a27 Merge branch 'release/17.3' into release/17.4 2026-05-20 06:42:24 +00:00
Ivan Kuchin b648341030 [#74768] Remove calculated_value_project_attribute feature flag
https://community.openproject.org/wp/74768
2026-05-19 17:42:42 +02:00
Tobias Dillmann 0537f52f4b [#71305] Introduce MODULE_ENABLED event and use it for backlogs 2026-05-19 14:21:54 +02:00
Kabiru Mwenja 1ce4251c23 Merge pull request #23203 from opf/feature/text-macro-semantic-id-rendering
Accept semantic work-package identifiers in text macros
2026-05-19 14:42:30 +03:00
Pavel Balashou 09c5c443f4 Add specs to test some db unique constraints.
- For projects.identifier
- For friendly_id_slugs(slug, sluggable_type, scope)
2026-05-19 12:09:34 +02:00
Oliver Günther fea9ecf623 Use project specific checking for custom field visibility in journals 2026-05-19 08:41:14 +02:00
Tomas Hykel 506198d55d chore: Consolidate classic project ID generation 2026-05-18 14:15:20 +02:00
Judith Roth ca1cff55af Merge pull request #23093 from opf/feature/74366-adapt-pdf-export-for-semantic-identifiers
[#74366] Adapt PDF exports for semantic identifiers
2026-05-18 13:00:33 +02:00
Alexander 6350700c99 Prevent WorkPackage::SemanticIdentifier::UnsupportedLookup with empty ID (#23213)
---------

Co-authored-by: Kabiru Mwenja <k.mwenja@openproject.com>
2026-05-15 08:36:10 +03:00
Kabiru Mwenja f9406ff1c7 Trim verbose contextual comments on WP identifier branch
Cuts comments that restate code mechanics, narrate the journey, or
pile on implementation detail. Genuine WHYs (perf rationale of the
to_i.to_s round-trip, the alias second-query reason, leading-zero
rejection, classic-mode preload skip) all stayed.
2026-05-15 08:24:16 +03:00
Kabiru Mwenja ba974ebed2 Pin PDF export macros to numeric-only references
`Macros::Links` extends `ResourceLinksMatcher`, so the regex broadening
in the previous commit also matches `#PROJ-1` shapes inside markdown
that's about to be exported as PDF. Without an explicit guard, the PDF
custom handler would silently emit `<mention data-id="0">` (since
`"PROJ-1".to_i == 0`) — broken-looking output that's hard to attribute.

Tighten `WorkPackagesLinkHandler#applicable?` to reject semantic-shape
input. Override `call` so it doesn't fall through the parent's
cache-driven path (PDF rendering walks Markly nodes via a separate
pipeline that doesn't populate the per-render cache). Cite WP #74366 in
the comment as the follow-up that adds semantic-id support to the PDF
side via the Markly walk in `app/models/exports/pdf/common/macro.rb`.

New specs assert `#PROJ-1` falls through to literal text in PDF output
and never produces a `data-id="0"` mention, both alone and mixed with
numeric references.
2026-05-15 08:24:14 +03:00
Kabiru Mwenja ab375e56c2 Merge pull request #23200 from opf/feature/use-formatted-id-in-wp-identifier-rendering
Use formatted_id in user-facing WP identifier rendering
2026-05-14 16:54:30 +03:00
Kabiru Mwenja c24e3cfab0 Accept scalars, varargs, and arrays in where_display_id_in
Splat with a depth-1 flatten lets callers pass scalars, varargs, or a
pre-built array interchangeably. `Array(values)` would have been
misleading here — `Array([[1, "a"], 2])` leaves the inner array
intact and `map(&:to_s)` stringifies it as `"[1, \"a\"]"`, which
then misclassifies through the semantic-id branch. Bounded `flatten(1)`
absorbs the (scalar) and ([scalar, scalar]) shapes that production
code already uses while leaving deeper nesting alone, so the same
pathology produces no match rather than silently working.

Refs https://github.com/opf/openproject/pull/23202#discussion_r3235337043
2026-05-13 18:26:23 +03:00
Kabiru Mwenja 4b164150ac Pin ID_ROUTE_CONSTRAINT against silent widening
The route constraint composes the numeric and semantic shapes from
SEMANTIC_ID_PATTERN, which itself composes the project-identifier shape
from `Projects::Identifier::SEMANTIC_FORMAT`. A future change to either
upstream pattern would shift what URLs Rails accepts without touching
routes.rb. Three anchored assertions lock the boundary in place — the
constant is used only as a route constraint, so anchored matching mirrors
the actual call site.
2026-05-13 17:51:44 +03:00
Kabiru Mwenja 0a5b2b8646 Make numeric_id? the exact complement of semantic_id? for Strings
`semantic_id?` already strips surrounding whitespace before its round-trip
check, so `" 123 "` was classified as not-semantic. `numeric_id?` did
not strip, so the same value was also not-numeric — leaving it
"neither" and unreachable through normal routing.

Stripping in `numeric_id?` and expressing the String branch as
`!semantic_id?(value)` removes the duplicated round-trip logic and gives
the routing predicates a single source of truth: any String classified
not-semantic is necessarily numeric. Integer/nil/other types are
unaffected — they fall on their own branches.

Routing-table spec gains a `" 123 "` row to lock the symmetry in.
2026-05-13 17:51:43 +03:00
Kabiru Mwenja c67978a7d1 Encapsulate canonical-numeric guard as numeric_id?
The `value == value.to_i.to_s` round-trip check that filters leading-
zero ID forms ("0123") was duplicated across the WP link handler, the
PDF export macro, and the cost-query filter.

A new `WorkPackage::SemanticIdentifier.numeric_id?(value)` predicate
captures the canonical-numeric check at one site. It pairs with
`semantic_id?` as the WP-finder shape gate; the two answer different
questions (shape vs routing) and so are kept independent rather than
expressed as one another's negation.

The cost-query filter switches to the predicate in this slice; the
text-formatting and PDF callers convert in a follow-up.
2026-05-13 17:51:43 +03:00
Kabiru Mwenja f1e729ce16 Use formatted_id in WorkPackage#to_s so autocomplete labels speak semantic ids
The autocomplete dropdown in CKEditor renders each result with
`item.name = wp.to_s`, and `to_s` hardcoded `##{id}` — so a semantic-mode
search for `#KSTP-2` resolved correctly but the dropdown row showed
`Task #10244: Subject` instead of `Task KSTP-2: Subject`.

Switch to `formatted_id`, which already produces the user-facing form in
both modes (`PROJ-7` semantic, `#42` classic). The other caller — the
delete-dialog component — benefits from the same mode awareness.
2026-05-13 17:41:48 +03:00
Oliver Günther f4cc426b2c Merge pull request #23133 from opf/feat/users-filter-component
Convert custom filters on user administration to standard query
2026-05-13 14:34:04 +02:00
Oliver Günther e9ea2f279e Add visible scope to user 2026-05-13 13:11:19 +02:00
Alexander Brandon Coles f8e3ea3019 Merge remote-tracking branch 'opf/dev' into HEAD
# Conflicts:
#	frontend/src/assets/sass/backlogs/_master_backlog.sass
#	modules/backlogs/config/locales/crowdin/es.yml
#	modules/backlogs/config/locales/crowdin/uk.yml
#	modules/storages/config/locales/crowdin/zh-CN.yml
#	modules/wikis/config/locales/crowdin/es.yml
#	modules/wikis/config/locales/crowdin/uk.yml
#	modules/wikis/config/locales/crowdin/zh-CN.yml
2026-05-11 17:31:22 +02:00
Andrej 7694347d10 Merge pull request #23108 from opf/code-maintenance/74746-avoid-additional-journal-background-jobs-to-be-started-by-jira-import-job
[#74746] Avoid additional journal background jobs to be started by Jira import job
2026-05-11 09:23:47 +02:00