Content
View differences
Updated by Alexander Coles 27 days ago
### Goal
Extract the generic BorderBox list shell from `OpenProject::Common::WorkPackageCardListComponent` into a reusable `OpPrimer::BorderBoxListComponent`, then make `WorkPackageCardListComponent` render through the new generic component.
This implementation is a static component extraction. Sorting, reordering, drag-and-drop ordering, row action menus, header action menus, and meetings adoption are out of scope for this work package.
### Component API
`OpPrimer::BorderBoxListComponent` should provide these slots:
- `header`
- `with_item`
- `with_empty_item`
- `with_work_package_item`
- `footer`
Callers are responsible for iterating collections and calling item slot methods in the order they want rows rendered. The component should render through Primer's BorderBox under the hood and forward relevant system arguments such as ids, list ids, padding, classes, data attributes, and ARIA attributes.
`with_item` renders arbitrary row content. `with_empty_item` renders an explicit empty row. `with_work_package_item` provides a work-package row bridge through a configurable item/card component, without hard-coding backlog-specific behavior into the generic component.
### Work package wrapper
`OpenProject::Common::WorkPackageCardListComponent` should become a convenience wrapper around `OpPrimer::BorderBoxListComponent`.
It should continue to support:
- `project:`
- `container:`
- `work_packages:`
- `drag_and_drop:`
- `item_component_klass:`
- `params:`
- `current_user:`
- delegated `header`
- delegated `footer`
- `empty_state`
When `work_packages:` are passed, `WorkPackageCardListComponent` should iterate the collection itself and add work-package rows to the underlying `BorderBoxListComponent`. When no work packages are rendered, it should render `empty_state` through the underlying empty item slot.
### Compatibility expectations
Existing backlogs rendering should keep the relevant DOM contract:
- container id from `dom_target(container)`
- list id from `dom_target(container, :list)`
- header id and collapsible linkage
- work package row ids, classes, data attributes, and card rendering
- empty row marker
- footer row styling
- drag-and-drop data on the box
### Tests
Add focused component specs for `OpPrimer::BorderBoxListComponent` covering:
- header, item, empty item, work-package item, and footer rendering
- forwarding of system arguments to the underlying BorderBox
- work-package item bridge behavior
Update/keep `WorkPackageCardListComponent` specs covering:
- automatic `work_packages:` iteration
- delegated header and footer rendering
- `empty_state` rendering through the empty item slot
- container/list/header ids
- existing backlogs row data/classes and drag-and-drop data
Extract the generic BorderBox list shell from `OpenProject::Common::WorkPackageCardListComponent` into a reusable `OpPrimer::BorderBoxListComponent`, then make `WorkPackageCardListComponent` render through the new generic component.
This implementation is a static component extraction. Sorting, reordering, drag-and-drop ordering, row action menus, header action menus, and meetings adoption are out of scope for this work package.
### Component API
`OpPrimer::BorderBoxListComponent` should provide these slots:
- `header`
- `with_item`
- `with_empty_item`
- `with_work_package_item`
- `footer`
Callers are responsible for iterating collections and calling item slot methods in the order they want rows rendered. The component should render through Primer's BorderBox under the hood and forward relevant system arguments such as ids, list ids, padding, classes, data attributes, and ARIA attributes.
`with_item` renders arbitrary row content. `with_empty_item` renders an explicit empty row. `with_work_package_item` provides a work-package row bridge through a configurable item/card component, without hard-coding backlog-specific behavior into the generic component.
### Work package wrapper
`OpenProject::Common::WorkPackageCardListComponent` should become a convenience wrapper around `OpPrimer::BorderBoxListComponent`.
It should continue to support:
- `project:`
- `container:`
- `work_packages:`
- `drag_and_drop:`
- `item_component_klass:`
- `params:`
- `current_user:`
- delegated `header`
- delegated `footer`
- `empty_state`
When `work_packages:` are passed, `WorkPackageCardListComponent` should iterate the collection itself and add work-package rows to the underlying `BorderBoxListComponent`. When no work packages are rendered, it should render `empty_state` through the underlying empty item slot.
### Compatibility expectations
Existing backlogs rendering should keep the relevant DOM contract:
- container id from `dom_target(container)`
- list id from `dom_target(container, :list)`
- header id and collapsible linkage
- work package row ids, classes, data attributes, and card rendering
- empty row marker
- footer row styling
- drag-and-drop data on the box
### Tests
Add focused component specs for `OpPrimer::BorderBoxListComponent` covering:
- header, item, empty item, work-package item, and footer rendering
- forwarding of system arguments to the underlying BorderBox
- work-package item bridge behavior
Update/keep `WorkPackageCardListComponent` specs covering:
- automatic `work_packages:` iteration
- delegated header and footer rendering
- `empty_state` rendering through the empty item slot
- container/list/header ids
- existing backlogs row data/classes and drag-and-drop data