From 591df706da23663c898247f23faa00c015c2d26c Mon Sep 17 00:00:00 2001 From: Jill Guyonnet Date: Tue, 26 Sep 2023 15:15:08 +0200 Subject: [PATCH 01/44] [Fleet] Fix bulk action dropdown (#166475) Closes https://github.com/elastic/kibana/issues/164083 Related to https://github.com/elastic/sdh-beats/issues/3759 Related to https://github.com/elastic/kibana/issues/157844 This PR addresses two current issues affecting agent selection in Fleet UI: 1. When there are inactive agents that are not listed on the current page and "Select everything on all pages" is clicked, the count of actionable agents is incorrect (cf. [this comment](https://github.com/elastic/kibana/issues/164083#issuecomment-1711780591) for details). This can have two consequences: 1. Incorrect and sometimes negative agent count in the "Actions" dropdown. 2. Disabled menu items in the "Actions" dropdown. 2. The "Select everything on all pages button is incorrectly displayed when there are agents on managed policies on the page and there is no pagination (cf. [this comment](https://github.com/elastic/kibana/issues/164083#issuecomment-1711781808)). --- .../agents_selection_status.test.tsx | 100 +++++++ .../components/agents_selection_status.tsx | 20 +- .../components/bulk_actions.test.tsx | 283 +++--------------- .../components/bulk_actions.tsx | 85 ++---- .../components/search_and_filter_bar.test.tsx | 12 +- .../components/search_and_filter_bar.tsx | 15 +- .../components/table_header.tsx | 3 + .../agents/agent_list_page/index.test.tsx | 1 + .../sections/agents/agent_list_page/index.tsx | 121 +++++--- 9 files changed, 286 insertions(+), 354 deletions(-) create mode 100644 x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/components/agents_selection_status.test.tsx diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/components/agents_selection_status.test.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/components/agents_selection_status.test.tsx new file mode 100644 index 0000000000000..07f42b65fdb0c --- /dev/null +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/components/agents_selection_status.test.tsx @@ -0,0 +1,100 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; + +import { createFleetTestRendererMock } from '../../../../../../mock'; + +import { AgentsSelectionStatus } from './agents_selection_status'; + +function render(props: any) { + const renderer = createFleetTestRendererMock(); + + return renderer.render(); +} + +const defaultProps = { + totalAgents: 30, + selectableAgents: 20, + managedAgentsOnCurrentPage: 0, + selectionMode: 'manual', + setSelectionMode: jest.fn(), + selectedAgents: [], + setSelectedAgents: jest.fn(), +}; + +function generateAgents(n: number) { + return [...Array(n).keys()].map((i) => ({ + id: `agent${i}`, + active: true, + })); +} + +describe('AgentsSelectionStatus', () => { + describe('when selection mode is manual', () => { + describe('when there are no selected agents', () => { + it('should not show any selection options', () => { + const res = render(defaultProps); + expect(res.queryByTestId('selectedAgentCountLabel')).toBeNull(); + expect(res.queryByTestId('clearAgentSelectionButton')).toBeNull(); + expect(res.queryByTestId('selectedEverythingOnAllPagesButton')).toBeNull(); + }); + }); + + describe('when there are selected agents', () => { + it('should show the number of selected agents and the Clear selection button', () => { + const res = render({ ...defaultProps, selectedAgents: generateAgents(2) }); + expect(res.queryByTestId('selectedAgentCountLabel')).not.toBeNull(); + expect(res.queryByTestId('clearAgentSelectionButton')).not.toBeNull(); + }); + + it('should not show the Select everything on all pages button if not all agents are selected', () => { + const res = render({ ...defaultProps, selectedAgents: generateAgents(2) }); + expect(res.queryByTestId('selectedEverythingOnAllPagesButton')).toBeNull(); + }); + + it('should not show the Select everything on all pages button if all agents are selected but there are no more selectable agents', () => { + const res = render({ + ...defaultProps, + totalAgents: 20, + selectableAgents: 19, + managedAgentsOnCurrentPage: 1, + selectedAgents: generateAgents(19), + }); + expect(res.queryByTestId('selectedEverythingOnAllPagesButton')).toBeNull(); + }); + + it('should show the Select everything on all pages button if all agents are selected and there are more selectable agents', () => { + const res = render({ ...defaultProps, selectedAgents: generateAgents(20) }); + expect(res.queryByTestId('selectedEverythingOnAllPagesButton')).not.toBeNull(); + }); + }); + }); + + describe('when selection mode is query', () => { + describe('when there are agents', () => { + it('should show the number of selected agents and the Clear selection button', () => { + const res = render({ + ...defaultProps, + selectionMode: 'query', + selectedAgents: generateAgents(2), + }); + expect(res.queryByTestId('selectedAgentCountLabel')).not.toBeNull(); + expect(res.queryByTestId('clearAgentSelectionButton')).not.toBeNull(); + }); + + it('should not show the Select everything on all pages button', () => { + const res = render({ + ...defaultProps, + selectionMode: 'query', + selectedAgents: generateAgents(20), + }); + expect(res.queryByTestId('selectedEverythingOnAllPagesButton')).toBeNull(); + }); + }); + }); +}); diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/components/agents_selection_status.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/components/agents_selection_status.tsx index 57728f275ccb5..0e1b6e43db46e 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/components/agents_selection_status.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/components/agents_selection_status.tsx @@ -34,6 +34,7 @@ const Button = styled(EuiButtonEmpty)` export const AgentsSelectionStatus: React.FunctionComponent<{ totalAgents: number; selectableAgents: number; + managedAgentsOnCurrentPage: number; selectionMode: SelectionMode; setSelectionMode: (mode: SelectionMode) => void; selectedAgents: Agent[]; @@ -41,15 +42,19 @@ export const AgentsSelectionStatus: React.FunctionComponent<{ }> = ({ totalAgents, selectableAgents, + managedAgentsOnCurrentPage, selectionMode, setSelectionMode, selectedAgents, setSelectedAgents, }) => { + const showSelectionInfoAndOptions = + (selectionMode === 'manual' && selectedAgents.length > 0) || + (selectionMode === 'query' && totalAgents > 0); const showSelectEverything = selectionMode === 'manual' && selectedAgents.length === selectableAgents && - selectableAgents < totalAgents; + selectableAgents < totalAgents - managedAgentsOnCurrentPage; return ( <> @@ -74,14 +79,13 @@ export const AgentsSelectionStatus: React.FunctionComponent<{ )} - {(selectionMode === 'manual' && selectedAgents.length) || - (selectionMode === 'query' && totalAgents > 0) ? ( + {showSelectionInfoAndOptions ? ( <> - + -