Content
View differences
Updated by Alexander Coles about 1 month ago
### Description
Retire Dragula from the shared Stimulus drag-and-drop controller by migrating `generic-drag-and-drop.controller.ts` to dnd-kit, and make the rollout complete only when all current consumers of that shared controller work and are verified.
This is not just a like-for-like port. The target is a clean, idiomatic dnd-kit + Stimulus implementation 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-specific advanced-surface work such as whole-card drag / drag-handle removal, multi-select / multi-drag, and unifying “Move to” menu actions with the frontend reorder pipeline
* Independent Dragula Stimulus controllers outside the shared controller
### Acceptance criteria
* Dragula is removed from `generic-drag-and-drop.controller.ts`.
* All current consumers of the shared controller work on dnd-kit.
* The implementation uses 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 dnd-kit rather than preserving Dragula as an escape hatch.
* Same-list reorder responses may use `204 No Content` where the optimistic client move already represents the 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**
* Backlogs future work remains separate:
* <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:
* dnd-kit sortable `index` / `initialIndex` / `group` / `initialGroup`
* `Sortable.target` for nested surfaces
* `Feedback.configure(...)`
* 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 dnd-kit, and make the rollout complete only when all current consumers of that shared controller work and are verified.
This is not just a like-for-like port. The target is a clean, idiomatic dnd-kit + Stimulus implementation 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-specific advanced-surface work such as whole-card drag / drag-handle removal, multi-select / multi-drag, and unifying “Move to” menu actions with the frontend reorder pipeline
* Independent Dragula Stimulus controllers outside the shared controller
### Acceptance criteria
* Dragula is removed from `generic-drag-and-drop.controller.ts`.
* All current consumers of the shared controller work on dnd-kit.
* The implementation uses 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 dnd-kit rather than preserving Dragula as an escape hatch.
* Same-list reorder responses may use `204 No Content` where the optimistic client move already represents the 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**
* Backlogs future work remains separate:
* <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:
* dnd-kit sortable `index` / `initialIndex` / `group` / `initialGroup`
* `Sortable.target` for nested surfaces
* `Feedback.configure(...)`
* 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.