Skip to content

Adapt work package show view for semantic identifiers#22704

Open
akabiru wants to merge 11 commits intofeature/73756-adapt-routes-for-project-based-semantic-work-package-identifiersfrom
feature/73716-adapt-work-package-show-view-for-project-based-semantic-work-package-identifiers
Open

Adapt work package show view for semantic identifiers#22704
akabiru wants to merge 11 commits intofeature/73756-adapt-routes-for-project-based-semantic-work-package-identifiersfrom
feature/73716-adapt-work-package-show-view-for-project-based-semantic-work-package-identifiers

Conversation

@akabiru
Copy link
Copy Markdown
Member

@akabiru akabiru commented Apr 9, 2026

Ticket

https://community.openproject.org/work_packages/73716

What are you trying to accomplish?

Propagate the displayId API field to the frontend work package show view. After PRs #22710 and #22718 made the API always return a displayId and the backend finders resolve semantic identifiers, this PR adds displayId and formattedId properties to the frontend resource so the correct identifier can be shown in the show view.

Screenshot 2026-04-15 at 8 07 41 PM

What approach did you choose and why?

Keeps machine and display identifiers separate. Instead of overriding wp.id (which is a machine identifier used for cache keys, API paths, filter values, row IDs, and CSS selectors), two new read-only properties are added to WorkPackageBaseResource:

  • displayId - returns the user-facing identifier from the API ("PROJ-42" in semantic mode, "42" in classic mode). Uses null-coalescing fallback to numeric PK as a safety net for stale cache during rolling deploys, but the field is now mandatory in API responses (per PR Expose displayId in API v3 work package endpoints #22710).
  • formattedId - returns the display-ready form: PROJ-42 (no prefix) for semantic identifiers, #42 (hash-prefixed) for classic numeric IDs. Semantic identifiers are self-describing so they don't need the # prefix, matching Jira's convention.

subjectWithId and subjectWithType now use formattedId, so tooltip-style labels render as "Fix the bug (PROJ-42)" in semantic mode and "Fix the bug (#42)" in classic mode.

Also widens SPA route patterns from [0-9]+ to a shared WP_ID_URL_PATTERN constant so semantic IDs like PROJ-42 can be used in split view and BIM URLs.

On the backend, the SQL representer now uses COALESCE(identifier, id::text) so work packages created before semantic mode was enabled still get a valid displayId instead of NULL.

Merge checklist

  • Added/updated tests
  • Added/updated documentation in Lookbook (patterns, previews, etc)
  • Tested major browsers (Chrome, Firefox, Edge, ...)

@akabiru akabiru force-pushed the feature/73716-adapt-work-package-show-view-for-project-based-semantic-work-package-identifiers branch from 9bce150 to 206d502 Compare April 9, 2026 12:09
@akabiru akabiru self-assigned this Apr 9, 2026
@akabiru akabiru force-pushed the feature/73716-adapt-work-package-show-view-for-project-based-semantic-work-package-identifiers branch 2 times, most recently from 7756686 to 1f8bf4c Compare April 10, 2026 15:14
@akabiru akabiru changed the title Feature/73716 adapt work package show view for project based semantic work package identifiers Adapt work package show view for semantic identifiers Apr 10, 2026
@akabiru akabiru changed the base branch from dev to feature/73756-adapt-routes-for-project-based-semantic-work-package-identifiers April 10, 2026 15:23
@akabiru akabiru force-pushed the feature/73756-adapt-routes-for-project-based-semantic-work-package-identifiers branch from 7c38287 to a3b5e32 Compare April 10, 2026 15:37
@akabiru akabiru force-pushed the feature/73716-adapt-work-package-show-view-for-project-based-semantic-work-package-identifiers branch from 1f8bf4c to a88120e Compare April 10, 2026 15:37
@akabiru akabiru force-pushed the feature/73756-adapt-routes-for-project-based-semantic-work-package-identifiers branch from a3b5e32 to bb04400 Compare April 10, 2026 15:47
@akabiru akabiru force-pushed the feature/73716-adapt-work-package-show-view-for-project-based-semantic-work-package-identifiers branch from a88120e to d517a42 Compare April 10, 2026 15:47
@akabiru akabiru force-pushed the feature/73756-adapt-routes-for-project-based-semantic-work-package-identifiers branch from bb04400 to c466ac6 Compare April 10, 2026 16:04
@akabiru akabiru force-pushed the feature/73716-adapt-work-package-show-view-for-project-based-semantic-work-package-identifiers branch 7 times, most recently from 7d160d6 to 0c3e8bd Compare April 13, 2026 10:42
@akabiru akabiru force-pushed the feature/73756-adapt-routes-for-project-based-semantic-work-package-identifiers branch from 128f33b to be79dc3 Compare April 13, 2026 11:05
@akabiru akabiru force-pushed the feature/73716-adapt-work-package-show-view-for-project-based-semantic-work-package-identifiers branch 2 times, most recently from 257e36d to abe86e8 Compare April 14, 2026 14:59
@akabiru akabiru force-pushed the feature/73756-adapt-routes-for-project-based-semantic-work-package-identifiers branch from 73bae1e to 48946fe Compare April 14, 2026 15:00
@akabiru akabiru marked this pull request as ready for review April 14, 2026 15:02
@akabiru akabiru requested a review from a team April 14, 2026 15:03
@akabiru akabiru force-pushed the feature/73716-adapt-work-package-show-view-for-project-based-semantic-work-package-identifiers branch from abe86e8 to 95be852 Compare April 14, 2026 15:25
@akabiru akabiru requested a review from a team April 15, 2026 06:42
Copy link
Copy Markdown
Contributor

@HDinger HDinger left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM 👍

Copy link
Copy Markdown
Contributor

@judithroth judithroth left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can't properly finish this review, because I have to leave now. So just some quick first feedback, but looks promising!

Comment thread app/models/work_package/semantic_identifier.rb
Comment thread frontend/src/app/features/hal/resources/work-package-resource.ts Outdated
@akabiru akabiru force-pushed the feature/73716-adapt-work-package-show-view-for-project-based-semantic-work-package-identifiers branch from 95be852 to 2fb1cff Compare April 15, 2026 12:43
@akabiru akabiru force-pushed the feature/73756-adapt-routes-for-project-based-semantic-work-package-identifiers branch from 36d081a to 3b6ba7d Compare April 15, 2026 12:54
@akabiru akabiru force-pushed the feature/73716-adapt-work-package-show-view-for-project-based-semantic-work-package-identifiers branch from 2fb1cff to 4c1b1a6 Compare April 15, 2026 12:55
akabiru added 10 commits April 15, 2026 18:59
Override WorkPackageBaseResource.id to read the API's displayId field,
which is always present and returns the appropriate identifier for the
current mode ("PROJ-42" in semantic, "123" in classic). This single
change propagates to all WP views without per-view conditional logic.

Also widen SPA route patterns from numeric-only to alphanumeric so
semantic IDs like "PROJ-42" can be used in split view and BIM URLs,
and remove parseInt coercion in hover sync since WP IDs may now be
non-numeric strings.
Filters like resourceId, entityId, and parent map to integer database
columns. Now that wp.id returns the display identifier ("KSTP-7"), these
must use $source.id (the numeric PK) instead.
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.
Centralise the URL segment pattern that matches work package
identifiers into a named constant so route definitions reference
a single source of truth instead of duplicating the regex.
parent_id is consumed by parseInt() in wp-create.component.ts, which
returns NaN for semantic identifiers like "PROJ-42". This silently
breaks parent assignment when creating child work packages.

Revert the route constraint back to [0-9]+ since parent_id is a
machine-level concern used in API calls, not a display identifier.

Add a feature spec with semantic mode enabled to verify the URL uses
the numeric PK and the parent relationship is set correctly.
The frontend pattern was [A-Za-z0-9_-]+ which accepted invalid
identifiers like "---", "abc", or "42abc". Tighten it to match
the backend ID_ROUTE_CONSTRAINT: either a pure numeric ID or a
semantic identifier starting with a letter and ending with a
hyphen followed by digits (e.g. "PROJ-42").
Cover the changed behavior where subjectWithId now delegates to
displayIdWithHash instead of inlining the numeric id. Tests verify
semantic mode output (#PROJ-7), classic mode (#42), and no suffix
for new resources.
In semantic mode, work packages created before the feature was enabled
have a nil identifier column. Previously display_id returned nil for
these, causing the Ruby representer to serialize displayId as null
while the SQL representer used COALESCE to return the numeric id.

Use identifier.presence to fall back to the numeric id, aligning both
representer paths.
Semantic identifiers (e.g. PROJ-42) are self-describing and should not
be prefixed with #. Only classic numeric IDs retain the hash prefix
(e.g. #42). This matches Jira's convention and PR review feedback.

The detection uses a simple regex check: if the displayId contains any
letter, it's semantic (no hash); otherwise it's classic (hash prefix).
PR #22710 made displayId a required field in all API v3 work package
responses. The if/else fallback to this.id and corresponding legacy
specs are now dead code.

Collapse to a null-coalescing one-liner (still safe against stale cache
during rolling deploys) and remove specs that tested the absent-field
scenario.
@akabiru akabiru force-pushed the feature/73716-adapt-work-package-show-view-for-project-based-semantic-work-package-identifiers branch from 4c1b1a6 to 26f87c6 Compare April 15, 2026 16:35
The idLabel getter was bypassing formattedId entirely, always rendering
the numeric PK with a # prefix. In semantic mode this showed #9720
instead of KSTP-1.
@akabiru akabiru requested review from HDinger and judithroth April 15, 2026 17:44
*/
public get formattedId():string {
const wpId = this.displayId;
return /[A-Za-z]/.test(wpId) ? wpId : `#${wpId}`;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd prefer a more clean way of detecting the semantic mode in the frontend but since we don't have that, the regex is probably fine. However, please add that as a const to the work-package-id-pattern.ts file that you created. Thus it is at least reusable

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

3 participants