Content
View differences
Updated by Alexander Coles about 17 hours ago
### Description
Retire Dragula from the shared Stimulus drag-and-drop controller by migrating `generic-drag-and-drop.controller.ts` to the `sortable-lists` Stimulus suite built on Atlassian Pragmatic Drag dnd-kit, and Drop, and make the rollout complete only when all current consumers of that shared controller work and are verified.
> **Note:** this work package originally targeted dnd-kit. The library decision has since been made in favour of Pragmatic Drag and Drop (evaluation in #PT-139, decision recorded in #DREAM-672 / #DREAM-674); the description was rewritten accordingly on 2026-07-12.
This is not just a like-for-like port. The target is a clean, idiomatic dnd-kit + Stimulus implementation on the shared `sortable-lists` primitives (#AGILE-292) with a stricter shared DOM contract and less controller-side reconciliation. We generally own the markup, so changing component structure, Turbo update boundaries, controller mount points, or small shared ViewComponent/helper abstractions is acceptable where that leads to a simpler design.
**In scope:**
* Backlogs
* `Admin::Enumerations::IndexComponent`
* `Settings::ProjectCustomFieldSections::{Index,Show}Component`
* `Settings::ProjectPhaseDefinitions::IndexComponent`
* `WorkPackageTypes::ExportTemplateListComponent`
* Meetings subclass
**Out of scope:**
* Backlogs — migrated directly to the `sortable-lists` suite under #AGILE-251 / #AGILE-291 (no longer part of this WP).
* Backlogs-specific advanced-surface work such as whole-card drag / drag-handle removal, multi-select / multi-drag, and unifying "Move to" “Move to” menu actions with the frontend reorder pipeline
* Independent Dragula Stimulus controllers outside the shared controller (`reporting/page.controller.ts`, `admin/type-form-configuration/rows-drag-and-drop.controller.ts`, `admin/custom-fields.controller.ts`) — tracked separately under #DREAM-677
### Acceptance criteria
* Dragula is removed from `generic-drag-and-drop.controller.ts` (or the controller is retired outright in favour of `sortable-lists` controllers).
`generic-drag-and-drop.controller.ts`.
* All current consumers of the shared controller work on the Pragmatic-based `sortable-lists` suite.
dnd-kit.
* The implementation uses the `sortable-lists` primitives dnd-kit APIs and Stimulus lifecycle where possible, instead of accumulating custom DOM-repair logic.
* `data-target-container-accessor` is treated as a cleanup target; preferred end state is that the controller targets the real sortable container element directly.
* Any backlog or meetings specialization remains on the shared suite dnd-kit rather than preserving Dragula as an escape hatch.
* Same-list reorder responses follow the optimistic contract established in #AGILE-322: an event-only turbo-stream response that carries `WORK_PACKAGE_MOVED_EVENT` (or the surface's equivalent) instead of re-rendering the frame. A bare may use `204 No Content` was explicitly rejected there because it has no body to carry where the event and breaks listeners such as optimistic client move already represents the split-view `lock_version` refresh (see https://github.com/opf/openproject/pull/24157).
final state.
* Cross-tab/session consistency is treated separately and should come from explicit Turbo Stream broadcasts, not as a side effect of the initiating drag response.
* Shared-controller verification covers the full current consumer set, including meetings.
### Notes **Notes**
* Backlogs future work remains separate: #73473, #73729
* <mention class="mention" data-id="73473" data-type="work_package" data-text="##73473">##73473</mention>
* <mention class="mention" data-id="73729" data-type="work_package" data-text="##73729">##73729</mention>
* This WP may lay groundwork that helps those follow-ups, but their requirements should not bloat the shared controller contract.
* Reassess the controller with the assumption that custom reconciliation is guilty until proven necessary.
* In particular, re-evaluate against the `sortable-lists` suite as implemented in https://github.com/opf/openproject/pull/23218:
re-evaluate:
* root/list/item controller topology and outlet wiring (#AGILE-292)
dnd-kit sortable `index` / `initialIndex` / `group` / `initialGroup`
* drop-intent resolution in `drag-and-drop.ts` and the `list-dom.ts` DOM contract
`Sortable.target` for nested surfaces
* `@atlaskit/pragmatic-drag-and-drop-auto-scroll` configuration
`Feedback.configure(...)`
* the Turbo morph guard (`pragmatic-dnd-morph-attributes.ts`)
real `AutoScroller` config (`acceleration` / `threshold`)
* Temporary workarounds such as subtree observation should be treated as tactical only and removed before merge if a cleaner markup-driven solution is available.
Retire Dragula from the shared Stimulus drag-and-drop controller by migrating `generic-drag-and-drop.controller.ts` to the `sortable-lists` Stimulus suite built on Atlassian Pragmatic Drag
> **Note:** this work package originally targeted dnd-kit. The library decision has since been made in favour of Pragmatic Drag and Drop (evaluation in #PT-139, decision recorded in #DREAM-672 / #DREAM-674); the description was rewritten accordingly on 2026-07-12.
This is not just a like-for-like port. The target is a clean, idiomatic
**In scope:**
*
*
* Backlogs — migrated directly to the `sortable-lists` suite under #AGILE-251 / #AGILE-291 (no longer part of this WP).
* Backlogs-specific advanced-surface work such as whole-card drag / drag-handle removal, multi-select / multi-drag, and unifying "Move to"
* Dragula is removed from `generic-drag-and-drop.controller.ts` (or the controller is retired outright in favour of `sortable-lists` controllers).
* Backlogs future work remains separate: #73473, #73729
* <mention class="mention" data-id="73729" data-type="work_package" data-text="##73729">##73729</mention>
*