Skip to content

Commit

Permalink
[Fleet] Move the agents list bulk actions from the table to a new but…
Browse files Browse the repository at this point in the history
…ton (#131133)

* [Fleet] Move the agents list bulk actions from the table to a new button

* Clean up types and add divider

* Split up agent list page component

* Add test for bulk actions

Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
  • Loading branch information
criamico and kibanamachine committed May 2, 2022
1 parent c2a13af commit 4f89914
Show file tree
Hide file tree
Showing 13 changed files with 439 additions and 227 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
/*
* 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 styled from 'styled-components';
import { EuiFlexGroup, EuiFlexItem, EuiText, EuiButtonEmpty } from '@elastic/eui';
import { FormattedMessage, FormattedNumber } from '@kbn/i18n-react';

import { SO_SEARCH_LIMIT } from '../../../../constants';
import type { Agent } from '../../../../types';

import type { SelectionMode } from './types';

const Divider = styled.div`
width: 0;
height: ${(props) => props.theme.eui.euiSizeL};
border-left: ${(props) => props.theme.eui.euiBorderThin};
`;

const FlexItem = styled(EuiFlexItem)`
height: ${(props) => props.theme.eui.euiSizeL};
`;

const Button = styled(EuiButtonEmpty)`
.euiButtonEmpty__text {
font-size: ${(props) => props.theme.eui.euiFontSizeXS};
}
`;

export const AgentsSelectionStatus: React.FunctionComponent<{
totalAgents: number;
selectableAgents: number;
selectionMode: SelectionMode;
setSelectionMode: (mode: SelectionMode) => void;
selectedAgents: Agent[];
setSelectedAgents: (agents: Agent[]) => void;
}> = ({
totalAgents,
selectableAgents,
selectionMode,
setSelectionMode,
selectedAgents,
setSelectedAgents,
}) => {
const showSelectEverything =
selectionMode === 'manual' &&
selectedAgents.length === selectableAgents &&
selectableAgents < totalAgents;

return (
<>
<EuiFlexGroup gutterSize="s" alignItems="center">
<EuiFlexItem grow={false}>
<EuiText size="xs" color="subdued">
{totalAgents > SO_SEARCH_LIMIT ? (
<FormattedMessage
id="xpack.fleet.agentBulkActions.totalAgentsWithLimit"
defaultMessage="Showing {count} of {total} agents"
values={{
count: <FormattedNumber value={SO_SEARCH_LIMIT} />,
total: <FormattedNumber value={totalAgents} />,
}}
/>
) : (
<FormattedMessage
id="xpack.fleet.agentBulkActions.totalAgents"
defaultMessage="Showing {count, plural, one {# agent} other {# agents}}"
values={{ count: totalAgents }}
/>
)}
</EuiText>
</EuiFlexItem>
{(selectionMode === 'manual' && selectedAgents.length) ||
(selectionMode === 'query' && totalAgents > 0) ? (
<>
<FlexItem grow={false}>
<Divider />
</FlexItem>
<EuiFlexItem grow={false}>
<EuiText size="xs" color="subdued">
<FormattedMessage
id="xpack.fleet.agentBulkActions.agentsSelected"
defaultMessage="{count, plural, one {# agent} other {# agents} =all {All agents}} selected"
values={{
count: selectionMode === 'manual' ? selectedAgents.length : 'all',
}}
/>
</EuiText>
</EuiFlexItem>
{showSelectEverything ? (
<>
<FlexItem grow={false}>
<Divider />
</FlexItem>
<EuiFlexItem grow={false}>
<Button size="xs" flush="left" onClick={() => setSelectionMode('query')}>
<FormattedMessage
id="xpack.fleet.agentBulkActions.selectAll"
defaultMessage="Select everything on all pages"
/>
</Button>
</EuiFlexItem>
</>
) : null}
<FlexItem grow={false}>
<Divider />
</FlexItem>
<EuiFlexItem grow={false}>
<Button
size="xs"
flush="left"
onClick={() => {
setSelectionMode('manual');
setSelectedAgents([]);
}}
>
<FormattedMessage
id="xpack.fleet.agentBulkActions.clearSelection"
defaultMessage="Clear selection"
/>
</Button>
</EuiFlexItem>
</>
) : (
<FlexItem grow={false} />
)}
</EuiFlexGroup>
</>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
/*
* 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 { ThemeProvider } from 'styled-components';

import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public';

import { coreMock } from '@kbn/core/public/mocks';
import { registerTestBed } from '@kbn/test-jest-helpers';

import type { Agent } from '../../../../types';

import { FleetStatusProvider, ConfigContext, KibanaVersionContext } from '../../../../../../hooks';

import { getMockTheme } from '../../../../../../mocks';

import { AgentBulkActions } from './bulk_actions';
import type { Props } from './bulk_actions';

const mockTheme = getMockTheme({
eui: {
euiSize: '10px',
},
});

const TestComponent = (props: Props) => (
<KibanaContextProvider services={coreMock.createStart()}>
<ConfigContext.Provider value={{ agents: { enabled: true, elasticsearch: {} }, enabled: true }}>
<KibanaVersionContext.Provider value={'8.2.0'}>
<ThemeProvider theme={mockTheme}>
<FleetStatusProvider>
<AgentBulkActions {...props} />
</FleetStatusProvider>
</ThemeProvider>
</KibanaVersionContext.Provider>
</ConfigContext.Provider>
</KibanaContextProvider>
);

describe('AgentBulkActions', () => {
it('should show no Actions button when no agent is selected', async () => {
const selectedAgents: Agent[] = [];
const props: Props = {
totalAgents: 10,
totalInactiveAgents: 2,
selectionMode: 'manual',
currentQuery: '',
selectedAgents,
refreshAgents: () => undefined,
};
const testBed = registerTestBed(TestComponent)(props);
const { exists } = testBed;

expect(exists('agentBulkActionsButton')).toBe(false);
});

it('should show an Actions button when at least an agent is selected', async () => {
const selectedAgents: Agent[] = [
{
id: 'Agent1',
status: 'online',
packages: ['system'],
type: 'PERMANENT',
active: true,
enrolled_at: `${Date.now()}`,
user_provided_metadata: {},
local_metadata: {},
},
];
const props: Props = {
totalAgents: 10,
totalInactiveAgents: 2,
selectionMode: 'manual',
currentQuery: '',
selectedAgents,
refreshAgents: () => undefined,
};
const testBed = registerTestBed(TestComponent)(props);
const { exists } = testBed;

expect(exists('agentBulkActionsButton')).not.toBeNull();
});
});
Loading

0 comments on commit 4f89914

Please sign in to comment.