From cea571c535bfe561341a0a3f67daf6f48d98e861 Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 21 Jun 2026 14:52:53 +0000 Subject: [PATCH 1/3] Add 'Copy ID to clipboard' action to work package context menus Adds a new context menu action that copies the work package's display_id (e.g. "PROJ-42" in semantic mode or "42" in classic mode) to the clipboard. The action appears: - In the work package table right-click context menu, below 'Copy link to clipboard' - In the work package split view and full view 'more' (three-dot) menu Co-Authored-By: Claude Sonnet 4.6 Claude-Session: https://claude.ai/code/session_01VgELPADVmKvFetVXqj1xKz --- config/locales/js-en.yml | 1 + .../wp-context-menu/wp-single-context-menu.ts | 5 ++++- .../wp-context-menu/wp-static-context-menu-actions.ts | 5 +++++ .../wp-context-menu/wp-view-context-menu.directive.ts | 4 ++++ 4 files changed, 14 insertions(+), 1 deletion(-) diff --git a/config/locales/js-en.yml b/config/locales/js-en.yml index f59d99a12d48..58a53dcad290 100644 --- a/config/locales/js-en.yml +++ b/config/locales/js-en.yml @@ -91,6 +91,7 @@ en: button_copy: "Copy" button_copy_numeric_id_to_clipboard: "Copy numeric ID to clipboard" button_copy_link_to_clipboard: "Copy link to clipboard" + button_copy_display_id_to_clipboard: "Copy ID to clipboard" button_copy_to_clipboard: "Copy to clipboard" button_copy_to_other_project: "Duplicate in another project" button_custom-fields: "Custom fields" diff --git a/frontend/src/app/shared/components/op-context-menu/wp-context-menu/wp-single-context-menu.ts b/frontend/src/app/shared/components/op-context-menu/wp-context-menu/wp-single-context-menu.ts index 116772f67702..1c0fb683ee84 100644 --- a/frontend/src/app/shared/components/op-context-menu/wp-context-menu/wp-single-context-menu.ts +++ b/frontend/src/app/shared/components/op-context-menu/wp-context-menu/wp-single-context-menu.ts @@ -122,6 +122,9 @@ export class WorkPackageSingleContextMenuDirective extends OpContextMenuTrigger case 'copy_numeric_id_to_clipboard': this.copyToClipboardService.copy(`${this.workPackage.id!}`); break; + case 'copy_display_id_to_clipboard': + this.copyToClipboardService.copy(this.workPackage.displayId); + break; default: window.location.href = link!; break; @@ -199,7 +202,7 @@ export class WorkPackageSingleContextMenuDirective extends OpContextMenuTrigger // Rendering it as a link would show a misleading link preview on hover and // make the clipboard copy originate from an anchor, so render it as a // button (no href). - const href = key === 'copy_numeric_id_to_clipboard' ? undefined : action.link; + const href = (key === 'copy_numeric_id_to_clipboard' || key === 'copy_display_id_to_clipboard') ? undefined : action.link; return { disabled: false, diff --git a/frontend/src/app/shared/components/op-context-menu/wp-context-menu/wp-static-context-menu-actions.ts b/frontend/src/app/shared/components/op-context-menu/wp-context-menu/wp-static-context-menu-actions.ts index 27e58db4e707..52bbdc2fcdf8 100644 --- a/frontend/src/app/shared/components/op-context-menu/wp-context-menu/wp-static-context-menu-actions.ts +++ b/frontend/src/app/shared/components/op-context-menu/wp-context-menu/wp-static-context-menu-actions.ts @@ -8,6 +8,11 @@ export const PERMITTED_CONTEXT_MENU_ACTIONS:WorkPackageAction[] = [ icon: 'icon-clipboard', link: 'id', }, + { + key: 'copy_display_id_to_clipboard', + icon: 'icon-clipboard', + link: 'id', + }, { key: 'log_time', link: 'logTime', diff --git a/frontend/src/app/shared/components/op-context-menu/wp-context-menu/wp-view-context-menu.directive.ts b/frontend/src/app/shared/components/op-context-menu/wp-context-menu/wp-view-context-menu.directive.ts index ad08e4437a3d..ffc5d1fff2ee 100644 --- a/frontend/src/app/shared/components/op-context-menu/wp-context-menu/wp-view-context-menu.directive.ts +++ b/frontend/src/app/shared/components/op-context-menu/wp-context-menu/wp-view-context-menu.directive.ts @@ -123,6 +123,10 @@ export class WorkPackageViewContextMenu extends OpContextMenuHandler { this.copyToClipboardService.copy(url.toString()); break; } + + case 'copy_display_id_to_clipboard': + this.copyToClipboardService.copy(this.workPackage.displayId); + break; case 'copy_to_other_project': window.location.href = `${this.pathHelper.staticBase}/work_packages/move/new?copy=true&ids[]=${id}`; break; From f92a507c3a1bed35b68af60eba0073c3c6e44297 Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 21 Jun 2026 15:12:17 +0000 Subject: [PATCH 2/3] Fix copy_numeric_id_to_clipboard broken in work package table context menu MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The action was only wired up in the single context menu (split/full view) but PERMITTED_CONTEXT_MENU_ACTIONS is shared, so it also appeared in the table right-click menu without a handler — falling through to the default window.location.href branch with an undefined link. Co-Authored-By: Claude Sonnet 4.6 Claude-Session: https://claude.ai/code/session_01VgELPADVmKvFetVXqj1xKz --- .../wp-context-menu/wp-view-context-menu.directive.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/frontend/src/app/shared/components/op-context-menu/wp-context-menu/wp-view-context-menu.directive.ts b/frontend/src/app/shared/components/op-context-menu/wp-context-menu/wp-view-context-menu.directive.ts index ffc5d1fff2ee..a081a415fcda 100644 --- a/frontend/src/app/shared/components/op-context-menu/wp-context-menu/wp-view-context-menu.directive.ts +++ b/frontend/src/app/shared/components/op-context-menu/wp-context-menu/wp-view-context-menu.directive.ts @@ -127,6 +127,10 @@ export class WorkPackageViewContextMenu extends OpContextMenuHandler { case 'copy_display_id_to_clipboard': this.copyToClipboardService.copy(this.workPackage.displayId); break; + + case 'copy_numeric_id_to_clipboard': + this.copyToClipboardService.copy(String(this.workPackage.id!)); + break; case 'copy_to_other_project': window.location.href = `${this.pathHelper.staticBase}/work_packages/move/new?copy=true&ids[]=${id}`; break; From 2a540503a507f430087e5ff1024fc22267957b4e Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 21 Jun 2026 15:39:21 +0000 Subject: [PATCH 3/3] Fix copy_numeric_id_to_clipboard shown in classic (non-semantic) mode Two bugs prevented the hide logic from working: - The context menu template never checked item.hidden, rendering all items regardless of the flag - The table right-click (view) context menu never set hidden for the action at all, unlike the single context menu which already had the check Co-Authored-By: Claude Sonnet 4.6 Claude-Session: https://claude.ai/code/session_01VgELPADVmKvFetVXqj1xKz --- .../app/shared/components/op-context-menu/op-context-menu.html | 2 +- .../wp-context-menu/wp-view-context-menu.directive.ts | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/frontend/src/app/shared/components/op-context-menu/op-context-menu.html b/frontend/src/app/shared/components/op-context-menu/op-context-menu.html index 1a0ee37a4afb..012f9456f95b 100644 --- a/frontend/src/app/shared/components/op-context-menu/op-context-menu.html +++ b/frontend/src/app/shared/components/op-context-menu/op-context-menu.html @@ -19,7 +19,7 @@ @if (item.divider) { } - @if (!item.divider && !item.isHeader) { + @if (!item.divider && !item.isHeader && !item.hidden) {
  • @if (item.href) { ({ class: undefined as string | undefined, disabled: false, + hidden: action.key === 'copy_numeric_id_to_clipboard' && !isSemanticWorkPackageId(this.workPackage.displayId), linkText: action.text, href: action.href, icon: action.icon != null ? action.icon : `icon-${action.key}`,