Skip to content

[AGILE-364] Apply batch selection to contextual ActionMenus - #24781

Draft
myabc wants to merge 6 commits into
implementation/AGILE-363-batch-position-actionsfrom
implementation/AGILE-364-batch-action-menus
Draft

[AGILE-364] Apply batch selection to contextual ActionMenus#24781
myabc wants to merge 6 commits into
implementation/AGILE-363-batch-position-actionsfrom
implementation/AGILE-364-batch-action-menus

Conversation

@myabc

@myabc myabc commented Aug 16, 2026

Copy link
Copy Markdown
Contributor

Ticket

AGILE-364

This PR is stacked directly on #24780 and is the user-facing tip of the coordinated #24779/#24780/#AGILE-364 release train.

What are you trying to accomplish?

Make every Backlogs ActionMenu entry point settle and present the same action scope while keeping singular actions bound to the invoking card.

The change:

  • applies one synchronous preserve/replace/singular policy before More, right-click, Context Menu, and Shift+F10 open the menu
  • groups invoker-specific actions under This work package and valid batch actions under a plural-aware selected-work-packages heading for true batches
  • retains the unchanged one-card menu presentation and silently preserves selection for fixed cards
  • projects destination and positional availability from the settled live scope without adding selection state to the contextual presenter

What approach did you choose and why?

The Backlogs item controller listens at the two established pre-open boundaries: contextual beforeOpen and the menu popover's capture-phase beforetoggle. Both call the same root prepareActionMenu operation; duplicate delivery is idempotent, and the late include-fragment refresh remains non-mutating.

Rails renders two stable Primer groups with initially hidden headings. Stimulus reveals plural headings only for a true batch, updates the nested labelled title without disturbing aria-labelledby, and hides the batch heading and group together when no batch action applies. Each action still re-resolves live scope at activation.

Merge checklist

  • Added/updated coverage: 277 focused Rails/component/request/service/concurrency/Selenium examples and 471 focused frontend tests
  • Ran focused RuboCop, ERB lint, ESLint, YAML parsing, locale export idempotence, and diff checks
  • Independent task reviews completed; whole-branch review completed before publication
  • Initial desktop Design QA through More and right-click
  • Tested major browsers beyond the Chromium feature suite

myabc added 6 commits August 16, 2026 05:04
Resolve each action menu scope before presentation so contextual and More-button invocation share one synchronous selection policy. The item projects availability from that settled scope while retaining non-mutating late refreshes for deferred menu content.

https://community.openproject.org/wp/AGILE-364
Render singular and selection-backed actions in stable Primer groups.

Project plural headings and hide empty batch groups from the settled action scope while preserving existing action and focus contracts.

https://community.openproject.org/wp/AGILE-364
Update the selected count through the group aria-labelledby relationship so Primer heading IDs remain stable.

Hide the selected-work-packages heading whenever a true batch has no visible action.

https://community.openproject.org/wp/AGILE-364
Locks all card-menu entry points to one observable action-scope
contract so presenter changes cannot silently collapse or retarget
selected batches.

https://community.openproject.org/wp/AGILE-364
Project the settled action scope before exposing deferred batch destinations and position controls. This prevents fixed invokers from presenting a stale selected-group menu while retaining defence-in-depth no-ops and one-card eligible behavior.

Remove the obsolete collapseForMove shim and document the selection port accurately.

https://community.openproject.org/wp/AGILE-364
Batch top placement into empty targets and source sprint lifecycle operations could race because only append and destination lifecycles were serialized.

Lock unanchored target placements, order source and target lifecycle mutexes, and revalidate each member's captured source under lock.

https://community.openproject.org/wp/AGILE-364
@myabc myabc changed the title implementation/AGILE 364 batch action menus [AGILE-364] Apply batch selection to contextual ActionMenus Aug 16, 2026
@myabc
myabc requested a lite review from Copilot August 16, 2026 09:50

Copilot AI left a comment

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.

Pull request overview

This PR unifies Backlogs work package ActionMenu behavior across all entry points (More button, right-click, Context Menu key, Shift+F10) by settling the live action scope before menu presentation, and by splitting the menu into stable singular vs batch action groups while preserving the one-card experience.

Changes:

  • Add a shared “prepareActionMenu” pre-open path (contextual beforeOpen + popover beforetoggle) so every invocation settles selection/action scope consistently.
  • Render two stable ActionMenu groups (“This work package” vs “Selected work packages”) and let the item controller project visibility + pluralized headings based on the resolved scope.
  • Strengthen batch move locking to include ordered source/target lifecycle locks and serialize unanchored placements (append/top), with expanded concurrency coverage.

Reviewed changes

Copilot reviewed 21 out of 21 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
modules/backlogs/spec/support/pages/backlog.rb Adds higher-level helpers for opening/validating menus via all entry points and probing batch move payloads.
modules/backlogs/spec/services/backlogs/work_packages/batch_update_service_spec.rb Updates lock-order expectations to match new lifecycle/placement locking.
modules/backlogs/spec/services/backlogs/work_packages/batch_update_service_concurrency_spec.rb Adds concurrency scenarios covering inbox placement/top moves and sprint-finish races.
modules/backlogs/spec/features/work_packages/move_via_menu_spec.rb Switches to new batch-aware menu action helper for positional actions.
modules/backlogs/spec/features/work_packages/card_context_menu_spec.rb Uses unified menu-opening helper for right-click and Shift+F10.
modules/backlogs/spec/features/work_packages/batch_action_menu_spec.rb New feature spec ensuring consistent batch projection across all menu entry points.
modules/backlogs/spec/components/backlogs/work_package_card_menu_component_spec.rb Verifies stable ActionMenu groups/headings and fixed-work-package behavior.
modules/backlogs/config/locales/js-en.yml Adds pluralized JS translation for “selected work packages” heading.
modules/backlogs/config/locales/en.yml Adds “This work package” translation for the menu group heading.
modules/backlogs/app/services/backlogs/work_packages/batch_update_service.rb Extends batch move synchronization: ordered lifecycle locks + placement serialization + tighter cohort validation.
modules/backlogs/app/components/backlogs/work_package_card_menu_component.html.erb Renders two Primer ActionMenu groups with hidden headings and moves batch actions into the batch group.
frontend/src/stimulus/controllers/dynamic/sortable-lists/selection-orchestrator.ts Removes now-unused move-collapse hook as action scope settling moves to menu preparation.
frontend/src/stimulus/controllers/dynamic/sortable-lists/selection-orchestrator.spec.ts Adds coverage for fixed invoker behavior without disturbing selection anchors.
frontend/src/stimulus/controllers/dynamic/sortable-lists/scrollable.controller.spec.ts Updates root stub to include the new prepareActionMenu port.
frontend/src/stimulus/controllers/dynamic/sortable-lists/list.controller.spec.ts Updates root stub to include the new prepareActionMenu port.
frontend/src/stimulus/controllers/dynamic/sortable-lists/item.controller.ts Adds pre-open listeners, projects grouped menu visibility/headings, and updates availability projection to use prepared scope.
frontend/src/stimulus/controllers/dynamic/sortable-lists/item.controller.spec.ts Adds extensive tests for pre-open sequencing and grouped heading/group projection.
frontend/src/stimulus/controllers/dynamic/sortable-lists/drag-and-drop.ts Updates SortableListsRoot port documentation and adds prepareActionMenu to the interface.
frontend/src/stimulus/controllers/dynamic/sortable-lists.controller.ts Implements prepareActionMenu by delegating to selection settling (selectForAction).
frontend/src/stimulus/controllers/dynamic/sortable-lists.controller.spec.ts Adds tests for action menu invocation scope behavior and idempotent duplicate delivery.
frontend/src/stimulus/controllers/dynamic/contextual-action-menu.controller.spec.ts Adds tests ensuring beforeOpen dispatch order, cancelability, and cancellation behavior.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

expect(menu).to have_css(batch_group)

if selected_count > 1
expect(menu).to have_css(singular_heading, text: "This work package")
Comment on lines +108 to +110
expect(menu.find(:menuitem, text: "Copy URL to clipboard")[:value])
.to end_with("/work_packages/#{invoker.id}")
expect(menu.find(:menuitem, text: "Copy work package ID")[:value]).to eq(invoker.id.to_s)
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.

2 participants