Skip to content

Card bulk-select, CF apps bulk delete, and CF-scoped apps navigation - #5665

Merged
norman-abramovitz merged 8 commits into
cloudfoundry:developfrom
nabramovitz:feat/signal-list-card-bulk-select
Jul 21, 2026
Merged

Card bulk-select, CF apps bulk delete, and CF-scoped apps navigation#5665
norman-abramovitz merged 8 commits into
cloudfoundry:developfrom
nabramovitz:feat/signal-list-card-bulk-select

Conversation

@nabramovitz

Copy link
Copy Markdown
Contributor

Card view is the default for most CF lists, but multi-select and bulk operations were reachable only in table view. This restores bulk-select in card view, adds bulk delete to the CF Applications tab, and fixes a couple of navigation issues found along the way.

Card bulk-select (signal-list)

The default card renderer treated the first column as the card title, so any list whose selection column comes first (routes, space-routes, space-apps) rendered a blank title, pushed the real title down into a body row, and never showed the checkbox at all.

  • The title is now the first non-control column, so a leading checkbox no longer blanks it.
  • The selection checkbox renders in the card header cluster next to the favorite star and the actions kebab (star, checkbox, kebab), reusing existing whitespace without growing the card.
  • A per-column tooltip lets a title show a different hover value than its visible text.

Routes: the URL is the card title (the redundant "Route" label is gone), and a root-domain route with no host/path/port falls back to (unnamed) <short-guid> with the full guid on hover.

Bulk delete on the CF Applications tab

The endpoint-wide CF Applications tab had no selection column, so bulk delete was reachable only from the per-space Apps list. It now mirrors the per-space wiring: a checkbox column plus a Delete bulk action wired to the existing backend fan-out (POST /pp/v1/cf/apps/:cnsi/bulk/delete). Selection can span orgs/spaces within the endpoint; the backend deletes per guid, so no space grouping is needed.

CF-scoped navigation stays CF-scoped

Two links jumped out to the global cross-CF applications wall from a CF-scoped context:

  • The org summary's Applications count now lands on the CF-scoped tab filtered to that org, not the global wall. Fixing this surfaced a latent race: the per-CF tab loads its org/space catalog lazily, so a pre-set org filter could be cleared before the catalog arrived. The stale-selection reconciliation now waits until the validating catalog has loaded before dropping a selection.
  • The app-detail error redirect (app deleted from another tab, 404, permission revoked) now returns to the CF tab when the app was opened from it (?breadcrumbs=cf), matching the delete flow beside it.

Guard tests cover each surface, and the production build plus unit tests pass.

Card view treated columns[0] as the card title, so a list that puts its
selection column first (routes, space-routes, space-apps) rendered a blank
title, pushed the real title (the route URL) down to a body row, and hid
the checkbox entirely -- bulk select was reachable only in table view.

Pick the title as the first non-control column, and render the checkbox in
the header cluster next to the star and kebab (star, checkbox, kebab),
suppressing it and the title column as body rows. Every default-renderer
card list is now consistent: with-kebab (routes, apps) and without-kebab
(users) alike -- the users cards put the checkbox where the kebab would
sit. Add a per-column `tooltip` so a title can show a different hover value
than its visible text.

Routes: the URL is the title now (the "Route" label is gone); a root-domain
route with no host/path/port falls back to `(unnamed) <short-guid>` with the
full guid on hover.

Replaces the earlier top-left overlay, which only touched the custom
cardTemplate path (autoscaler, kubernetes) -- neither has a checkbox column,
so it never rendered. Guard tests assert the header checkbox drives the bulk
bar, a leading checkbox does not blank the title, the tooltip, and that the
title column is not also rendered as a body row.
The endpoint-wide CF Applications tab (all apps in one CNSI) had no
selection column, so bulk delete was reachable only from the per-space
Apps list -- the checkbox looked missing on the main Applications view.

Mirror the space-apps wiring: a leading checkbox column plus a Delete bulk
action wired to the shared CfAppsSignalConfigService.bulkDeleteApps, which
POSTs to /pp/v1/cf/apps/:cnsi/bulk/delete so the fan-out runs on the
backend. Selection can span orgs/spaces within the endpoint; CAPI deletes
per guid, so no space grouping is needed. With the header-cluster
formatting the checkbox sits as star, checkbox, kebab on each card. Guard
test asserts the checkbox column and a non-empty Delete bulk action survive.
Clicking an org's "Applications" count on the org summary navigated to the
global cross-CF wall (/applications) instead of the CF-scoped apps tab --
CF-scoped context should stay CF-scoped. goToAppWall predates the per-CF
applications tab and was never repointed.

Add goToCfApplications (sibling of goToAppWall) that navigates to
/cloud-foundry/<cf>/applications with the org/space filter pre-set, and use
it from the org summary. The count now lands on the CF tab filtered to the
org (with the card bulk-select checkboxes), not the multi-endpoint wall.

Also fix a latent race the switch exposed: the stale-selection reconciliation
gated only on _hasLoadedOnce, but the per-CF tab loads its org/space catalog
lazily -- so apps could finish loading (flipping the gate) while orgOptions
was still just "All", and a valid pre-set org filter got cleared. Only clear
a selection once its validating catalog actually has entries; a genuinely
stale selection still clears once the catalog loads.
When an app opened from the per-CF applications tab (?breadcrumbs=cf) errors
out (deleted from another tab, 404, permission revoked), the error-redirect
effect hard-navigated to the global cross-CF wall (/applications), ignoring
the breadcrumbs source -- inconsistent with the delete flow right beside it,
which already returns to the CF tab. Route the bounce to
/cloud-foundry/<cf>/applications when breadcrumbs=cf; the global wall stays
the default for every other source. Target decision extracted to a static
appErrorRedirect() with a guard test.
…mmary

While a bulk delete runs, the bulk-action bar now shows a "Working..." spinner
and disables its buttons. The work happens behind the confirm dialog, after
run() returns, so the bar can't infer this itself -- the consumer drives a new
optional SignalListConfig `bulkRunning` signal. On completion the snackbar
reports the full roll-up, e.g. "Bulk delete: 7 succeeded, 1 pending, 2 failed",
instead of just failed-of-total; pending = an async CF job still completing.
Guard test covers the spinner + disabled state.
The v5.0.0-rc.1 release was withdrawn, so return the version to the dev
line. dev.137 was the last dev before the rc, so the next is dev.138.
…ing"

An async CF delete comes back PENDING (job still completing), which the
BulkResult contract counts as non-error alongside succeeded. The breakdown
message printed "pending" literally, which reads as stuck. Fold succeeded +
pending into one "N applications delete requested" line; on partial failure
show "M failed, N requested". True completion tracking (polling the per-item
async jobs) is a follow-up.

@norman-abramovitz norman-abramovitz left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM - needs a followup PR

@norman-abramovitz
norman-abramovitz merged commit c005c00 into cloudfoundry:develop Jul 21, 2026
19 checks passed
@nabramovitz
nabramovitz deleted the feat/signal-list-card-bulk-select branch July 21, 2026 21:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants