Ensure position is updated on bucket deletion#22956
Conversation
cb3da25 to
b4f1646
Compare
b4f1646 to
97f20ce
Compare
This comment was marked as low quality.
This comment was marked as low quality.
97f20ce to
bf71ec4
Compare
There was a problem hiding this comment.
Pull request overview
This PR improves backlog bucket deletion behavior in the Backlogs module by ensuring work package ordering remains correct after a bucket is deleted and by adding an explicit confirmation modal for bucket deletion.
Changes:
- Update
WorkPackages::RebuildPositionsServiceto partition positions bybacklog_bucket_id(in addition toproject_idandsprint_id) so inbox/buckets/sprints don’t share one position sequence. - Add a dedicated “delete backlog bucket” dialog endpoint + Primer DangerDialog component, and wire the bucket menu to open it via
async-dialog. - Extend/adjust specs to cover bucket-related positioning and the new modal-based delete flow.
Reviewed changes
Copilot reviewed 18 out of 18 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| modules/backlogs/app/services/backlog_buckets/delete_service.rb | Moves bucket work packages to inbox during bucket deletion (review note about hook ordering). |
| modules/backlogs/app/services/work_packages/rebuild_positions_service.rb | Adds backlog_bucket_id to the SQL window partitioning for position rebuilds. |
| modules/backlogs/app/controllers/backlogs/backlog_buckets_controller.rb | Adds destroy_dialog action to serve the deletion modal. |
| modules/backlogs/app/components/backlogs/backlog_bucket_menu_component.html.erb | Switches “Delete backlog bucket” action to open an async dialog instead of direct DELETE. |
| modules/backlogs/app/components/backlogs/backlog_bucket_destroy_modal_component.rb | New component backing the delete confirmation modal. |
| modules/backlogs/app/components/backlogs/backlog_bucket_destroy_modal_component.html.erb | New Primer DangerDialog modal template for bucket deletion. |
| modules/backlogs/config/routes.rb | Adds destroy_dialog member route for backlog buckets. |
| modules/backlogs/lib/open_project/backlogs/engine.rb | Permits destroy_dialog under create_sprints permission mapping. |
| modules/backlogs/config/locales/en.yml | Adds i18n strings for the new delete modal. |
| modules/backlogs/db/migrate/20260325101553_reposition_work_packages.rb | Updates migration comments to clarify why backlog buckets aren’t reflected there. |
| modules/backlogs/spec/support/pages/backlog.rb | Adds page-object helpers for asserting/confirming the delete modal. |
| modules/backlogs/spec/features/backlogs/pagination_state_spec.rb | Adapts feature spec from browser confirm to modal flow. |
| modules/backlogs/spec/features/backlog_buckets/delete_spec.rb | Adapts delete feature spec to modal flow; asserts moved WPs appear at inbox bottom. |
| modules/backlogs/spec/routing/backlogs/backlog_buckets_routing_spec.rb | New routing spec covering create/update/destroy + dialog endpoints. |
| modules/backlogs/spec/services/backlog_buckets/delete_service_spec.rb | Adds service-level coverage asserting WPs move to inbox and positions update on delete. |
| modules/backlogs/spec/services/work_packages/rebuild_positions_service_integration_spec.rb | Extends integration coverage to include bucket partitions. |
| modules/backlogs/spec/models/work_packages/position_spec.rb | Extends position behavior coverage to buckets + inbox interactions. |
toy
left a comment
There was a problem hiding this comment.
More or less nitpicks except the dialog style
| ) | ||
|
|
||
| expect(WorkPackage.where(sprint: nil).to_h { [it.subject, it.position] }) | ||
| expect(WorkPackage.where(sprint: nil, backlog_bucket: nil, project: project1).to_h { [it.subject, it.position] }) |
There was a problem hiding this comment.
Relying on subject instead of id makes test failures easier to understand, but suggests doing same in other tests
| shared_let(:bucket2_wp1) { create_work_package(subject: "Bucket 2 WorkPackage 1", backlog_bucket: bucket2, position: nil) } | ||
| shared_let(:bucket2_wp2) { create_work_package(subject: "Bucket 2 WorkPackage 2", backlog_bucket: bucket2, position: nil) } | ||
| shared_let(:bucket2_wp3) { create_work_package(subject: "Bucket 2 WorkPackage 3", backlog_bucket: bucket2, position: nil) } | ||
|
|
There was a problem hiding this comment.
Should there also be work packages that are in sprint from other project?
| inbox_wp3.subject => 3 | ||
| ) | ||
|
|
||
| expect(WorkPackage.where(sprint: sprint3).to_h { [it.subject, it.position] }) |
There was a problem hiding this comment.
I think it is better to either group together all those that change and all those that don't and/or name buckets and sprints variables to contain project id, alternatively separate tests for every sprint/bucket/project inbox to clearly explain every case
Ticket
https://community.openproject.org/wp/74369
What are you trying to accomplish?
WorkPackages::RebuildPositionsServiceincludesbacklog_bucket_idin the PARTITION BYMerge checklist