Files
openproject/app
Alexander Brandon Coles 3f3ca4b821 [#74088] Extract shared WorkPackageCardComponent and rename Backlogs components (#22936)
* [#73968] Extract work package card primitives

Adds the shared `WorkPackageCardBoxComponent` (with nested `Header`)
and `WorkPackageCardComponent` (with nested `Menu`), so
`SprintComponent`, `BucketComponent`, and the inbox can converge on
a single Primer `BorderBox` + card-row rendering path.

The box derives its DOM id, list id, drop-target id, and per-card URLs
from a single `container:` argument (`Sprint`, `BacklogBucket`, or
`nil` for the inbox). It exposes `header`, `empty_state`, and
`footer` slots; the header exposes `description`, `actions` (typed
`:button` slot), and `menu`.

Adds component specs for all four classes plus Lookbook previews for
the two top-level primitives. Consumers are migrated in follow-up
commits.

https://community.openproject.org/wp/73968

* [#74088] Compose SprintComponent over shared cards

Refactors `SprintComponent` to compose `WorkPackageCardBoxComponent`
and its nested `Header` instead of plumbing its own `BorderBox`.
Sprint-specific concerns (start/finish buttons, grouped action menu,
story-points total, blankslate copy) move into the consumer ERB.

Removes `SprintHeaderComponent`, `SprintMenuComponent`, and
`StoryComponent` along with their specs. Renames the turbo morph
target in `SprintsController#update` from
`backlogs-sprint-header-component-<id>` to
`backlogs-sprint-component-<id>`, so the whole sprint re-renders.
Locale keys consolidate under `sprint_component.*`.

https://community.openproject.org/wp/74088

* [#74088] Rename Backlogs UI components and forms

Drops the redundant `Backlog` prefix on bucket components (already
namespaced under `Backlogs::`) and the `New` prefix on forms and
dialogs that handle both create and edit:

- `BacklogBucketComponent` -> `BucketComponent` (with sibling
  `Header`/`Item`/`Menu`)
- `NewBacklogBucketDialogComponent` -> `BucketDialogComponent`
- `NewBacklogBucketFormComponent` -> `BucketFormComponent`
- `NewSprintDialogComponent` -> `SprintDialogComponent`
- `NewSprintFormComponent` -> `SprintFormComponent`
- `app/forms/backlogs/backlog_buckets/details_form.rb` ->
  `app/forms/backlogs/buckets/details_form.rb`

Locale namespaces follow the renames. No behavioural changes.

https://community.openproject.org/wp/74088

* [#74088] Singularise BacklogsComponent

The component composes one project's backlog column (sprints,
buckets, inbox), so the singular noun fits better. Renames the
class to `BacklogComponent`.

Also renames the constructor kwarg `backlog_buckets:` to `buckets:`
to drop the redundant prefix; updates the matching `attr_reader`
and the `_backlog_list` partial that instantiates it. The
controller still loads into `@backlog_buckets` and passes
`buckets: @backlog_buckets`.

https://community.openproject.org/wp/74088

* [#74088] Compose BucketComponent over shared cards

Refactors `BucketComponent` to compose `WorkPackageCardBoxComponent`
and its nested `Header`, mirroring the earlier sprint migration.
Bucket-specific concerns (edit/delete actions, blankslate copy)
move into the consumer ERB.

Removes `BucketHeaderComponent`, `BucketItemComponent`, and
`BucketMenuComponent` along with the bucket-item spec. Adds a new
`bucket_component_spec` covering the composed render path. Locale
keys consolidate under `bucket_component.*` and the shared header's
`work_package_card_box_component.header.label_work_package_count`;
the `expect_backlog_bucket_work_package_count` page helper updates
to track the new key.

https://community.openproject.org/wp/74088

* [#73968] Add card box truncate-middle pagination

Teaches `WorkPackageCardBoxComponent` an optional
`with_show_more(truncate_middle:, text:)` slot. When set, the box
truncates `work_packages` to the first `truncate_middle` rows plus
a derived tail (20% of first page, min 1) and emits a
`Box-row scheme: :neutral` between them advertising the omitted
middle. The slot is also the toggle — leaving it unset means no
truncation, preserving sprint and bucket behaviour.

Default copy is sourced from the new
`work_package_card_box_component.show_more` locale key with
`one`/`other` plurals; consumers can override via `text:` (with a
`%{count}` placeholder). Adds a Lookbook preview for the slot.

https://community.openproject.org/wp/73968

* [#74088] Compose InboxComponent over shared cards

Refactors `InboxComponent` to compose `WorkPackageCardBoxComponent`
with `container: nil`. Truncate-middle pagination moves into the
shared box via `box.with_show_more(truncate_middle: 50)`; the inbox
keeps only the consumer-side `show_all_backlog` guard.

Removes `InboxItemComponent` + spec (coverage already in
`WorkPackageCardComponentSpec`'s `container: nil` branch) and the
inbox-local `show_more`/`label_actions` locale keys (now sourced
from the shared box and card menu).

The show-more row id changes from `inbox-more-row-<project.id>` to
`inbox_<project.id>-show-more` (derived from `container_id`). Page
helpers and controller specs updated; the removed
`PAGINATION_THRESHOLD`/`FIRST_PAGE_SIZE`/`LAST_PAGE_SIZE` stubs
become a single `TRUNCATE_MIDDLE` knob.

https://community.openproject.org/wp/74088

* [#73968] Document backlog card component API

Adds YARDoc to `WorkPackageCardComponent#initialize` and to
`WorkPackageCardBoxComponent` (constructor and the four slots:
`header`, `empty_state`, `footer`, `show_more`), so consumers can
read the API surface without reading the lambda bodies.

https://community.openproject.org/wp/73968

* Drop dead Backlogs Sass rules

Removes `_master_backlog.sass` rules tied to UI primitives that were
deleted in opf/openproject#22740 but were not cleaned up alongside them:
`.op-backlogs-header` and its modifiers, `.op-backlogs-container`,
`.op-backlogs-lists`, and the `backlogsListsContainer` container queries
that targeted the old header layout.

* Rename .action-sprint_planning to .action-backlog

The `sprint_planning` action was renamed to `backlog` in
opf/openproject#22740, but the corresponding body class selector in
`_master_backlog.sass` was missed.

* [#73968] Colocate card component styles

Renames the Backlogs-named card classes (`.op-backlogs-story`,
`.op-sprint-header`, `.op-backlogs-points-label`) after the
component classes extracted under `app/components/open_project/common/`
and moves the rules into colocated `.sass` files. Preparatory work
for https://community.openproject.org/wp/73890.

https://community.openproject.org/work_packages/73968

* Drop unused Backlogs Sass index file

* Rename backlog_buckets feature spec dir to buckets

Drops the redundant `backlog_` prefix from the feature spec
directory and one work_packages drag spec filename, consistent
with the component renaming on this branch. Model, controller,
and request specs are left for a follow-up pass.

* Align dialog component ID constants with names

Drops the stale `new-` and `backlog-` prefixes from the ID
constants in `SprintDialogComponent` and `BucketDialogComponent`
so they match the class names established in the earlier rename
commit.

Co-Authored-By: Dombi Attila <83396+dombesz@users.noreply.github.com>

* [#73968] Allow card menus without src

Treat the work package card menu source as optional so the shared
card component can render inline menus as well as deferred menus.
Honor caller-provided menu IDs and use the header reader when
deriving the default card box header menu ID.

https://community.openproject.org/wp/73968

* Expose sprint form component state

Add readers for the sprint form component state and use them from the
template and helper methods instead of reading instance variables
directly. Cover the reader and rendering behavior with a focused
component spec.

* [#73968] Generalize card box container IDs

Treat card box containers as Rails dom_target sources so shared card
boxes can accept symbols, strings, model classes, and model instances
without Backlogs-specific ID branching.

Move Backlogs drag-and-drop target IDs into explicit caller-provided
configuration, keeping the existing controller protocol while omitting
generic DnD data for consumers that do not opt in.

https://community.openproject.org/wp/73968

* [#73968] Add card box item bridge

Extracts the BorderBox row arguments into a row-bridge object
(`WorkPackageCardBoxComponent::Item`) so the box can build rows without
forcing the visual card to render row-level concerns. The visual
`WorkPackageCardComponent` constructor narrows to
`(work_package:, menu_src:)`; in-repo callers updated.

Adds a polymorphic slot API (`with_work_package_item`,
`with_empty_item`) modeled on `Primer::Alpha::FileTreeView`, plus a
public `#build_item` for off-box callers. Renames the URL pass-through
to a generic `params:` kwarg, leaving Backlogs all-state handling at the
call sites.

https://community.openproject.org/wp/73968

* [#73968] Move card metrics to Backlogs

Remove the story-points display from the shared work package card and
expose a generic metric slot instead. Backlogs now opts into that slot
with a small story-points component when rendering sprint, bucket, and
inbox cards.

https://community.openproject.org/wp/73968

* [#73968] Extract Backlogs card box items

Move Backlogs-specific item/card concerns behind Backlogs components
while keeping the common card box API focused on generic item
rendering. The common item keeps generic draggability hooks, while
Backlogs owns story points, menu URLs, and story controller row data.

https://community.openproject.org/wp/73968

* [#73968] Add card menu slot

Expose a top-level menu slot on the common work package card so card
and card-box callers can configure action menus in the same style. Keep
menu_src as a compatibility shortcut for existing deferred Backlogs
menus while allowing inline non-deferred menu items through the slot.

https://community.openproject.org/wp/73968

* [#73968] Harmonize Backlogs card metric

Forward metric slot calls from the Backlogs card wrapper to the wrapped
common card so Backlogs card box items keep the same customization
surface as generic items. Keep story points as the default metric when
callers do not provide their own metric slot.

https://community.openproject.org/wp/73968

* [#73968] Note InfoLine arg passthrough TODO

Marks the hard-coded `InfoLineComponent.new(work_package:)` call in
the common card template as the integration point for InfoLine
variants and status presentation requested by WP 73089. Defers the
actual argument forwarding so this PR keeps a narrow scope.

https://community.openproject.org/wp/73968

* [#73968] Move show-more out of common box

The common card box now exposes a generic `item` slot via `with_item`
for manually composed rows. Automatic rendering still only builds
work package items from the `work_packages:` argument.

The Backlogs inbox now owns the truncate-middle show-more row, its
route, Turbo frame, and draggable marker.

https://community.openproject.org/wp/73968

* [#73968] Simplify empty card box item

Reuse the generic content item bridge for empty card box rows and keep
only the empty-row data override.

https://community.openproject.org/wp/73968

* Fix WorkPackageCardComponent metric preview

Removes dependency on Backlogs-specific `StoryPointsComponent`.

---------

Co-authored-by: Dombi Attila <83396+dombesz@users.noreply.github.com>
2026-05-05 14:13:56 +01:00
..
2026-04-28 14:56:44 +02:00
2026-05-05 08:51:13 +01:00