Show actual number of selected hosts (#46334)

**Related issue:** Resolves #40502

# Checklist for submitter

- [x] Changes file added for user-visible changes in `changes/`,
`orbit/changes/` or `ee/fleetd-chrome/changes`.


## Testing

- [x] Added/updated automated tests
- [x] QA'd all new/changed functionality manually

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Bug Fixes**
* Fixed "select all matching hosts" to display the actual total count
instead of showing an estimate like "50+" in table headers and delete
confirmation dialogs.

* **Tests**
* Updated test cases to reflect accurate host count display behavior
when selecting all matching hosts.

<!-- review_stack_entry_start -->

[![Review Change
Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/fleetdm/fleet/pull/46334?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack)

<!-- review_stack_entry_end -->
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
Steven Palmesano
2026-06-16 15:04:25 -05:00
committed by GitHub
parent 295e0f8501
commit cbae661149
6 changed files with 22 additions and 9 deletions
@@ -0,0 +1 @@
* Fixed "Select all matching hosts" to display the actual total host count instead of "50+" in both the hosts table header and the delete hosts modal.
@@ -50,6 +50,7 @@ interface IDataTableProps {
isAllPagesSelected: boolean; // TODO: make dependent on showMarkAllPages
toggleAllPagesSelected?: any; // TODO: an event type and make it dependent on showMarkAllPages
resultsTitle?: string;
totalCount?: number;
defaultPageSize: number;
defaultPageIndex?: number;
defaultSelectedRows?: Record<string, boolean>;
@@ -109,6 +110,7 @@ const DataTable = ({
isAllPagesSelected,
toggleAllPagesSelected,
resultsTitle = "results",
totalCount,
defaultPageSize,
defaultPageIndex,
defaultSelectedRows = {},
@@ -452,8 +454,10 @@ const DataTable = ({
return (
<p>
<span>
{selectedCount}
{isAllPagesSelected && "+"}
{isAllPagesSelected && totalCount !== undefined
? totalCount
: selectedCount}
{isAllPagesSelected && totalCount === undefined && "+"}
</span>{" "}
selected
</p>
@@ -59,6 +59,7 @@ interface ITableContainerProps<T = any> {
showMarkAllPages: boolean;
isAllPagesSelected: boolean; // TODO: make dependent on showMarkAllPages
toggleAllPagesSelected?: any; // TODO: an event type and make it dependent on showMarkAllPages
totalCount?: number;
searchable?: boolean;
disableSearch?: boolean;
wideSearch?: boolean;
@@ -152,6 +153,7 @@ const TableContainer = <T,>({
showMarkAllPages,
isAllPagesSelected,
toggleAllPagesSelected,
totalCount,
searchable,
disableSearch,
wideSearch,
@@ -558,6 +560,7 @@ const TableContainer = <T,>({
showMarkAllPages={showMarkAllPages}
isAllPagesSelected={isAllPagesSelected}
toggleAllPagesSelected={toggleAllPagesSelected}
totalCount={totalCount}
resultsTitle={resultsTitle}
defaultPageSize={pageSize}
defaultPageIndex={pageIndex}
@@ -1993,6 +1993,7 @@ const ManageHostsPage = ({
secondarySelectActions={secondarySelectActions}
showMarkAllPages={!unsupportedFilter} // Shortterm fix for #17257
isAllPagesSelected={isAllMatchingHostsSelected}
totalCount={totalFilteredHostsCount}
searchable
disableSearch={isTrulyEmpty}
renderCount={renderHostCountAndExport}
@@ -29,7 +29,7 @@ describe("DeleteHostModal", () => {
expect(screen.getByText("Host1")).toBeVisible();
});
it("renders the number of hosts selected with '+' after when select all matching hosts is true", () => {
it("renders the total hosts count when select all matching hosts is true", () => {
render(
<DeleteHostModal
selectedHostIds={[1, 2, 3]}
@@ -40,10 +40,10 @@ describe("DeleteHostModal", () => {
isUpdating={false}
/>
);
expect(screen.getByText("3+ hosts")).toBeVisible();
expect(screen.getByText("50 hosts")).toBeVisible();
});
it("renders the host count with '+' and an additional warning when there are more than 500 hosts and select all matching hosts is true", () => {
it("renders the host count with an additional warning when there are more than 500 hosts and select all matching hosts is true", () => {
render(
<DeleteHostModal
selectedHostIds={[1, 2, 3]}
@@ -54,7 +54,7 @@ describe("DeleteHostModal", () => {
isUpdating={false}
/>
);
expect(screen.getByText("3+ hosts")).toBeVisible();
expect(screen.getByText("500 hosts")).toBeVisible();
expect(
screen.getByText(
"When deleting a large volume of hosts, it may take some time for this change to be reflected in the UI."
@@ -34,9 +34,13 @@ const DeleteHostModal = ({
}: IDeleteHostModalProps): JSX.Element => {
const hostText = () => {
if (selectedHostIds) {
return `${selectedHostIds.length}${
isAllMatchingHostsSelected ? "+" : ""
} ${strUtils.pluralize(selectedHostIds.length, "host")}`;
const count =
isAllMatchingHostsSelected && hostsCount !== undefined
? hostsCount
: selectedHostIds.length;
const suffix =
isAllMatchingHostsSelected && hostsCount === undefined ? "+" : "";
return `${count}${suffix} ${strUtils.pluralize(count, "host")}`;
}
return hostName;
};