We delegate the resource name to the object itself, that way we can
override it in our record and no knowledge about the backlogs module is
necessary in the core.
We already use our own extensive sanitization pipeline, and it turns out
tagfilter is extremely slow on large oneline input (such as big tables).
Rendering a large table inside a work package (2k rows, 20k cells) caused tagfilter to run for over 2 minutes.
Added a separate spec to test all tags the tagfilter filters for to avoid its runaway execution time.
Restore the minimal admin settings blankslate so the admin menu route
remains valid after the sprint-based cleanup. Remove the remaining
settings-driven story/task classification code, dead models and
services, and the obsolete filter and spec setup that depended on it.
Overriding wp.id to return the semantic identifier (e.g. "PROJ-42")
broke cache keys, API filters, row rendering, and CSS selectors that
all depend on the numeric PK.
Instead, keep wp.id as the numeric PK and add two new properties:
- displayId: returns the user-facing identifier ("PROJ-42" or "123")
- displayIdWithHash: returns "#PROJ-42" or "#123" for UI display
Also adds a COALESCE fallback in the SQL representer so work packages
created before semantic mode was enabled still get a valid displayId.
Extract FinderMethods module that transparently resolves both numeric and
semantic identifiers (e.g. "PROJ-42") using FriendlyId's Object#friendly_id?
for dispatch. The module is included in both the WorkPackage class and
extended onto every relation, so scoped queries like
WorkPackage.visible(user).find("PROJ-42") work seamlessly.
- Override find to resolve semantic IDs via identifier column + alias table
- Override exists? with the same resolution chain
- Refactor find_by_id_or_identifier to use friendly_id? instead of semantic_id?
- Update API route to accept string IDs (type: Integer → type: String)
- Update controller and ViewComponent finders to use find_by_id_or_identifier
- Pass display_id from Rails views to Angular custom elements
Replace the conditional `semanticId` API field with `displayId` which is
always present in work package responses. In semantic mode it returns the
project-based identifier (e.g. "PROJ-42"), in classic mode it returns the
numeric ID as a string. This gives API consumers (frontend, mobile) a
single field to read without conditional logic.
- Add `WorkPackage#display_id` method that encapsulates the mode check
- Update both representers (JSON and SQL) to render `displayId` unconditionally
- Update OpenAPI schema documentation
Adds the computed semanticId property to the HAL representer,
SQL collection representer, and schema representer. The property is
gated behind the semantic_work_package_ids feature flag and returns the
value from WorkPackage#identifier. Includes OpenAPI docs
and the translation key for the schema name.
Add fetch_request_cached method that layers RequestStore in front of Rails.cache.fetch
Used in the following places, as they are repeatedly accessed during schema initialization.
all_work_package_form_attributes, form_config_attribute_representation, Query.available_columns
In my tests, this improves cold cache access by reducing initial number of queries to access cache
Documents created with zero-width Unicode characters (e.g. U+200B)
in their titles become unclickable on the index page, making them
hard to manage or delete.
Introduce RemoveInvisibleCharacters normalizer, replacing the former
RemoveAsciiControlCharacters. It strips both ASCII control characters
and Unicode zero-width characters, with each category defined as a
named constant for clarity. Apply it to Document#title and update
existing callers (Project#identifier, CustomField#name).
Add a shared RSpec example "strips invisible characters" to verify
normalization consistently across all three models.
* Add rel=nofollow to user-generated links to deter SEO spam
Links in user-generated content (work package descriptions, comments,
wiki pages) previously carried rel="noopener noreferrer" but not
nofollow. Search engines therefore passed PageRank through them, making
OpenProject community instances attractive targets for spammers posting
links for SEO gain.
Adding nofollow removes this incentive without any visible impact on
legitimate users.
* Fix missing nofollow in AutolinkCustomProtocolsFilter
Extract non-IndexedDB refinements from PR #22125 so they can ship
independently while IndexedDB offline persistence is evaluated separately.
- Gate collaboration on Setting.real_time_text_collaboration_enabled?
instead of hardcoding it to true
- Remove the test-mode fallback that created a standalone Y.Doc without
a provider; HocuspocusProvider is now required for document editing
- Refactor useCollaboration hooks: callback-based timeout with proactive
cancel on sync, extracted useProviderAuthError hook, JSDoc comments
- Add read/write context-aware connection error messages (readonly users
see "real-time updates will resume" vs writers see "changes will sync")
- Add blocked offline mode: when the server is unreachable and there is
no local cache, hide the editor entirely to prevent an empty Y.Doc
from being synced as authoritative content on reconnect
- Update feature specs to use real hocuspocus shared context instead of
stubbing collaboration_enabled, add offline blocking tests
This error is intended for cases when a method is
intentionally not implemented, because the module/class defining
it expects a subclass (or class including the module) to implement
the method.
This is intended to distinguish it from other cases, such as:
* feature not implemented yet
* edge case of a method call not yet supported
Notably it avoids the misuse of the Ruby-defined NotImplementedError,
which is only intended for much more specific scenarios:
> Raised when a feature is not implemented on the current platform. For example, methods depending on the fsync or fork system calls may raise this exception [...]
Also see https://docs.ruby-lang.org/en/master/NotImplementedError.html