The :only_changes filter re-seeked each journal's predecessor in every EXISTS
branch (~7 LATERAL lookups per row). A CTE now shadows the journals table,
exposing predecessor_id/predecessor_data_id once per row, and each branch reads
those columns instead. On a 703-journal work package this cuts the COUNT from
~1.13M to ~35K shared buffers.
https://community.openproject.org/wp/STC-462
Two readability passes over the work package activity tab, no behaviour change. The paginator's private methods are reordered to follow their call order so the file reads top-down from `#call`, and the three activity filter modes (`:all`, `:only_comments`, `:only_changes`) — until now bare symbols duplicated across the controller, paginator, journal components and the hidden form — move into a single `WorkPackages::ActivitiesTab::Filters` module so the modes have one source of truth and can't drift apart. The diff reaches beyond the paginator into the controller, several components and a form, since that's where the symbols were scattered.
The work package activity tab computed a per-journal sequence_version on
every render — a ROW_NUMBER() window function over a LATERAL join — only to
stamp the legacy data-anchor-activity-id that #activity-N deep links rely on.
Nothing mints those links anymore; copy and share links use
#comment-<journal id>, which needs no extra query.
The activity number is now resolved on demand. Only a request carrying
?anchor=activity-N runs the window function, mapping the number to a journal
id the paginator exposes as resolved_anchor. The view hands that to the
client, which rewrites #activity-N to the canonical #comment-<id> and scrolls
using the comment anchor already present in the DOM. Default renders no longer
touch the window function.
References WP #68063.
The feature flag is gone on release/17.5 (PR #23324); the
`with_settings: { work_packages_identifier: ... }` annotation alone
is enough to pin classic vs semantic behaviour in each context.
The earlier write-time canonicalization stored the rendered
display_id ("#PROJ-7") in the journal note, which would rot under
project-identifier renames and leave dangling semantic strings if
semantic mode were rolled back. Restore the PK shape ("#42") and
let the formatter pipeline turn it into the user-facing identifier
at render time, where the resolver already handles both modes.
Both spec contexts now assert the same PK shape; the mode-specific
rendering of "#N" lives in the formatter specs.
The macro preload was visibility-scoped — references to work packages the
recipient cannot see would fall through to the literal `#43` shape, even
when the same reference rendered as `DCP-1` for an author with full view
permission. Notification recipients saw misleading numeric ids for cross-
project references in journal notes.
Splits label resolution from link gating:
- `ResourceLinksMatcher.build_lookup` now does an unscoped fetch for the
primary identifier and a separate visibility-scoped id pluck. The link
handler reads `visible_to_current_user?` to decide between a navigable
anchor and a plain-text label.
- `UpdateAncestorsService#set_journal_note` writes `#display_id` so new
notes carry the semantic shape at the source; render-time resolution
heals legacy `#N` content for users with view permission.
Tradeoff: a recipient without view permission now sees the WP's semantic
identifier (e.g. `DCP-1`) as plain text rather than `#43`. The reference's
existence was already disclosed by the stored journal text; the project
identifier is the only new piece of information surfaced, and is not
treated as a secret elsewhere in the system (URLs, exports, API).
Pagy 43.4.3 deprecated `:max_pages` and recommends capping records
before pagination instead. Caps the combined array in `base_journals`.
https://community.openproject.org/wp/75314
https://community.openproject.org/wp/74977
Add NOT NULL to *sluggable_type* and fix NULL *scope* uniqueness in *friendly_id_slugs*
- Delete duplicate NULL *scope* rows, keeping the most recent per (slug, sluggable_type)
- Delete NULL *sluggable_type* rows before adding NOT NULL constraint
- Replace unique index on (slug, sluggable_type, scope) with NULLS NOT DISTINCT variant (requires Postgres 15+)
Why?
1. *sluggable_type* NOT NULL
every slug must belong to a model (e.g. Post, User). A slug with no *sluggable_type* is orphaned and meaningless.
2. NULLS NOT DISTINCT in the unique constraint
not treating every NULL *scope* as unique leads to duplicate records if *scope* is NULL which does not make sense
and pollutes the table with unnecessary data
* Create the section component
* Create the form configuration component
* Create a controller
* change form template
* Use primer dialog for reset to defaults button
* show WP configuration modal while creating a related WPs table
* Fix the drag and drop functionality without save button
* Fix renaming functionality
* Use generic drag and drop in form configuration and move all client side action handling to server side
* Fix embedded query form configuration regressions
* Add data test selectors to all elements that we used for test
* update the current tests with the new implementations and design
* Add new tests for new controller of sections and rows
* WP quesry row should only have edit quesry action
* Update transformer spec regarding the new changes
* Fix the failing test in reset form configuration and some tests for actions
* Fix rubocop errors
* Fix eslint errors
* Add spec for removing a section
* Use condensed border boxes
* fix failing specs
* fix failing specs
* Switch the buttons in form configuration component
* Create the section at the top of the list
* Instead of using UUID, use the name of the group as the key
* Add missing check for EE for section actions
* Remove angular components
* Use action list instead of a border box for left side panel
* Reduce the margin between the right side panel and sub header, add some space to the query table left side, span to the whole available space
* Show validation errors while updating and creating a section
* Use a danger dialog for reset to default
* Add a confirmation for removing the section
* Align items in the row
* Use test_selector instead of data-test-selector
* Create move_action in rb file
* Create move_action in rb file
* Simplify section component
* Simplify form configuration component
* Remove dialog for rename and delete section on missing EE
* Create a component for inactive attribute list
* Create a separate component for reset dialog
* Remove EE feedback dialog
* Remove form partial which is not needed anymore
* Remove unused js strings
* Update using update_via_turbo
* Remove form configuration rows controller
* Create a blanksalte component
* Fix failing specs
* Fix failing specs
* Fix failing specs
* Remove unused translation strings
* Align form configuration section routes with actual create flow
* Change section to group
* Change section to group in services and controllers
* Change section to group in en.yml
* Fix rubocop errors
* Move the query group persistence assertion from the JS feature spec
to the synchronous form configuration groups controller spec.
* Reuse query service result in embedded query build
* Keep inactive attribute filter after turbo list refresh
* Extract form configuration group edit state into form model
* Fix the failing test
* Potential fix for pull request finding 'CodeQL / Potentially uninitialized local variable'
Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
* Rename inactive attribute component inputs
* Refine reset dialog wording for form configuration
* Use direct Turbo action for adding attribute groups
* Reuse generic filter-list controller for inactive attributes
* Remove focus impelementation in ts
* Group form configuration Stimulus controllers under one namespace
* Use turbo request service in form configuration controller
* Clarify legacy group key normalization in form config contract
* Replace inactive attribute list wrapper via turbo stream
* Extract duplicate untitled group key generation into Type::FormGroup.next_untitled_key
* Auto-generate untitled group name on create instead of returning an error
* Avoid mixed return types in form config group create service
* Extract shared form configuration group service behavior into concern
* Fix spacing for the last group and italic font for the placeholder rows
* Replace Angular no-results component with Primer Banner on form configuration page
* Hide dropped element immediately to prevent flickering before Turbo Stream response
* Reload type before rendering create error to prevent duplicate groups
* Await service initialization before use to prevent potential race condition
* Replace sleep calls with deterministic waits in form configuration spec
* Handle malformed JSON and invalid query errors gracefully in form configuration update
* Make query group label a clickable button and empty group hint italic
---------
Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>