-
Notifications
You must be signed in to change notification settings - Fork 8.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Beats Management] Add BeatsTable/Bulk Action Search Component (#21182)
* Add BeatsTable and control bar components. * Clean yarn.lock. * Move raw numbers/strings to constants. Remove obsolete state/props. * Update/add tests. * Change prop name from "items" to "beats". * Rename some variables. * Move search bar filter definitions to table render. * Update table to support assignment options. * Update action control position. * Refactor split render function into custom components.
- Loading branch information
1 parent
18d6c81
commit 9ec3d3b
Showing
15 changed files
with
1,363 additions
and
115 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License; | ||
* you may not use this file except in compliance with the Elastic License. | ||
*/ | ||
|
||
export const TABLE_CONFIG = { | ||
INITIAL_ROW_SIZE: 5, | ||
PAGE_SIZE_OPTIONS: [3, 5, 10, 20], | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
63 changes: 63 additions & 0 deletions
63
x-pack/plugins/beats_management/public/components/table/action_button.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License; | ||
* you may not use this file except in compliance with the Elastic License. | ||
*/ | ||
|
||
import { EuiButton, EuiContextMenu, EuiPopover } from '@elastic/eui'; | ||
import React from 'react'; | ||
import { ActionDefinition } from './table_type_configs'; | ||
|
||
interface ActionButtonProps { | ||
actions: ActionDefinition[]; | ||
isPopoverVisible: boolean; | ||
actionHandler(action: string, payload?: any): void; | ||
hidePopover(): void; | ||
showPopover(): void; | ||
} | ||
|
||
export function ActionButton(props: ActionButtonProps) { | ||
const { actions, actionHandler, hidePopover, isPopoverVisible, showPopover } = props; | ||
if (actions.length === 0) { | ||
return null; | ||
} else if (actions.length === 1) { | ||
const action = actions[0]; | ||
return ( | ||
<EuiButton | ||
color={action.danger ? 'danger' : 'primary'} | ||
onClick={() => actionHandler(action.action)} | ||
> | ||
{action.name} | ||
</EuiButton> | ||
); | ||
} | ||
return ( | ||
<EuiPopover | ||
anchorPosition="downLeft" | ||
button={ | ||
<EuiButton iconSide="right" iconType="arrowDown" onClick={showPopover}> | ||
Bulk Action | ||
</EuiButton> | ||
} | ||
closePopover={hidePopover} | ||
id="contextMenu" | ||
isOpen={isPopoverVisible} | ||
panelPaddingSize="none" | ||
withTitle | ||
> | ||
<EuiContextMenu | ||
initialPanelId={0} | ||
panels={[ | ||
{ | ||
id: 0, | ||
title: 'Bulk Actions', | ||
items: actions.map(action => ({ | ||
...action, | ||
onClick: () => actionHandler(action.action), | ||
})), | ||
}, | ||
]} | ||
/> | ||
</EuiPopover> | ||
); | ||
} |
103 changes: 103 additions & 0 deletions
103
x-pack/plugins/beats_management/public/components/table/assignment_options.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License; | ||
* you may not use this file except in compliance with the Elastic License. | ||
*/ | ||
|
||
import { EuiButton, EuiFlexGroup, EuiFlexItem, EuiLoadingSpinner, EuiPopover } from '@elastic/eui'; | ||
import React from 'react'; | ||
import { ActionButton } from './action_button'; | ||
import { ControlDefinitions } from './table_type_configs'; | ||
|
||
interface AssignmentOptionsProps { | ||
assignmentOptions: any[] | null; | ||
assignmentTitle: string | null; | ||
controlDefinitions: ControlDefinitions; | ||
selectionCount: number; | ||
actionHandler(action: string, payload?: any): void; | ||
} | ||
|
||
interface AssignmentOptionsState { | ||
isAssignmentPopoverVisible: boolean; | ||
isActionPopoverVisible: boolean; | ||
} | ||
|
||
export class AssignmentOptions extends React.Component< | ||
AssignmentOptionsProps, | ||
AssignmentOptionsState | ||
> { | ||
constructor(props: AssignmentOptionsProps) { | ||
super(props); | ||
|
||
this.state = { | ||
isAssignmentPopoverVisible: false, | ||
isActionPopoverVisible: false, | ||
}; | ||
} | ||
|
||
public render() { | ||
const { | ||
actionHandler, | ||
assignmentOptions, | ||
assignmentTitle, | ||
controlDefinitions: { actions }, | ||
selectionCount, | ||
} = this.props; | ||
const { isActionPopoverVisible, isAssignmentPopoverVisible } = this.state; | ||
return ( | ||
<EuiFlexGroup alignItems="center" justifyContent="spaceBetween"> | ||
<EuiFlexItem>{selectionCount} selected</EuiFlexItem> | ||
<EuiFlexItem grow={false}> | ||
<ActionButton | ||
actions={actions} | ||
actionHandler={actionHandler} | ||
hidePopover={() => { | ||
this.setState({ isActionPopoverVisible: false }); | ||
}} | ||
isPopoverVisible={isActionPopoverVisible} | ||
showPopover={() => { | ||
this.setState({ isActionPopoverVisible: true }); | ||
}} | ||
/> | ||
</EuiFlexItem> | ||
<EuiFlexItem grow={false}> | ||
<EuiPopover | ||
button={ | ||
<EuiButton | ||
color="primary" | ||
iconSide="right" | ||
iconType="arrowDown" | ||
onClick={() => { | ||
this.setState({ | ||
isAssignmentPopoverVisible: true, | ||
}); | ||
actionHandler('loadAssignmentOptions'); | ||
}} | ||
> | ||
{assignmentTitle} | ||
</EuiButton> | ||
} | ||
closePopover={() => { | ||
this.setState({ isAssignmentPopoverVisible: false }); | ||
}} | ||
id="assignmentList" | ||
isOpen={isAssignmentPopoverVisible} | ||
panelPaddingSize="s" | ||
withTitle | ||
> | ||
{assignmentOptions ? ( | ||
// @ts-ignore direction prop not available on current typing | ||
<EuiFlexGroup direction="column" gutterSize="xs"> | ||
{assignmentOptions} | ||
</EuiFlexGroup> | ||
) : ( | ||
<div> | ||
<EuiLoadingSpinner size="m" /> Loading | ||
</div> | ||
)} | ||
</EuiPopover> | ||
</EuiFlexItem> | ||
</EuiFlexGroup> | ||
); | ||
} | ||
} |
48 changes: 48 additions & 0 deletions
48
x-pack/plugins/beats_management/public/components/table/controls.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License; | ||
* you may not use this file except in compliance with the Elastic License. | ||
*/ | ||
|
||
import { | ||
// @ts-ignore typings for EuiSearchar not included in EUI | ||
EuiSearchBar, | ||
} from '@elastic/eui'; | ||
import React from 'react'; | ||
import { AssignmentOptions } from './assignment_options'; | ||
import { ControlDefinitions } from './table_type_configs'; | ||
|
||
interface ControlBarProps { | ||
assignmentOptions: any[] | null; | ||
assignmentTitle: string | null; | ||
showAssignmentOptions: boolean; | ||
controlDefinitions: ControlDefinitions; | ||
selectionCount: number; | ||
actionHandler(actionType: string, payload?: any): void; | ||
} | ||
|
||
export function ControlBar(props: ControlBarProps) { | ||
const { | ||
actionHandler, | ||
assignmentOptions, | ||
assignmentTitle, | ||
controlDefinitions, | ||
selectionCount, | ||
showAssignmentOptions, | ||
} = props; | ||
return selectionCount !== 0 && showAssignmentOptions ? ( | ||
<AssignmentOptions | ||
actionHandler={actionHandler} | ||
assignmentOptions={assignmentOptions} | ||
assignmentTitle={assignmentTitle} | ||
controlDefinitions={controlDefinitions} | ||
selectionCount={selectionCount} | ||
/> | ||
) : ( | ||
<EuiSearchBar | ||
box={{ incremental: true }} | ||
filters={controlDefinitions.filters} | ||
onChange={(query: any) => actionHandler('search', query)} | ||
/> | ||
); | ||
} |
9 changes: 9 additions & 0 deletions
9
x-pack/plugins/beats_management/public/components/table/index.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License; | ||
* you may not use this file except in compliance with the Elastic License. | ||
*/ | ||
|
||
export { Table } from './table'; | ||
export { ControlBar } from './controls'; | ||
export { BeatsTableType } from './table_type_configs'; |
88 changes: 88 additions & 0 deletions
88
x-pack/plugins/beats_management/public/components/table/table.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License; | ||
* you may not use this file except in compliance with the Elastic License. | ||
*/ | ||
|
||
import { | ||
// @ts-ignore no typings for EuiInMemoryTable in EUI | ||
EuiInMemoryTable, | ||
EuiSpacer, | ||
} from '@elastic/eui'; | ||
import React from 'react'; | ||
import styled from 'styled-components'; | ||
import { TABLE_CONFIG } from '../../../common/constants'; | ||
import { CMPopulatedBeat } from '../../../common/domain_types'; | ||
import { ControlBar } from './controls'; | ||
import { TableType } from './table_type_configs'; | ||
|
||
interface BeatsTableProps { | ||
assignmentOptions: any[] | null; | ||
assignmentTitle: string | null; | ||
items: any[]; | ||
type: TableType; | ||
actionHandler(action: string, payload?: any): void; | ||
} | ||
|
||
interface BeatsTableState { | ||
selection: CMPopulatedBeat[]; | ||
} | ||
|
||
const TableContainer = styled.div` | ||
padding: 16px; | ||
`; | ||
|
||
export class Table extends React.Component<BeatsTableProps, BeatsTableState> { | ||
constructor(props: BeatsTableProps) { | ||
super(props); | ||
|
||
this.state = { | ||
selection: [], | ||
}; | ||
} | ||
|
||
public render() { | ||
const { actionHandler, assignmentOptions, assignmentTitle, items, type } = this.props; | ||
|
||
const pagination = { | ||
initialPageSize: TABLE_CONFIG.INITIAL_ROW_SIZE, | ||
pageSizeOptions: TABLE_CONFIG.PAGE_SIZE_OPTIONS, | ||
}; | ||
|
||
const selectionOptions = { | ||
onSelectionChange: this.setSelection, | ||
selectable: () => true, | ||
selectableMessage: () => 'Select this beat', | ||
selection: this.state.selection, | ||
}; | ||
|
||
return ( | ||
<TableContainer> | ||
<ControlBar | ||
actionHandler={(action: string, payload: any) => actionHandler(action, payload)} | ||
assignmentOptions={assignmentOptions} | ||
assignmentTitle={assignmentTitle} | ||
controlDefinitions={type.controlDefinitions(items)} | ||
selectionCount={this.state.selection.length} | ||
showAssignmentOptions={true} | ||
/> | ||
<EuiSpacer size="m" /> | ||
<EuiInMemoryTable | ||
columns={type.columnDefinitions} | ||
items={items} | ||
itemId="id" | ||
isSelectable={true} | ||
pagination={pagination} | ||
selection={selectionOptions} | ||
sorting={true} | ||
/> | ||
</TableContainer> | ||
); | ||
} | ||
|
||
private setSelection = (selection: any) => { | ||
this.setState({ | ||
selection, | ||
}); | ||
}; | ||
} |
Oops, something went wrong.