Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Beats CM] Add Search component for table assignment options #23202

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/*
* 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 { EuiFlexGroup } from '@elastic/eui';
import React from 'react';
import { AssignmentOptionList } from './assignment_option_types';

interface AssignmentListProps {
assignmentOptions: AssignmentOptionList;
}

export const AssignmentList = ({
assignmentOptions: { items, renderAssignmentOptions },
}: AssignmentListProps) => (
<EuiFlexGroup direction="column" gutterSize="xs">
{items.map((options, index) => renderAssignmentOptions(options, `${index}`))}
</EuiFlexGroup>
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* 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 { ColumnDefinition } from './table_type_configs';

export enum AssignmentOptionsComponent {
List = 'list',
Primary = 'primary',
Search = 'search',
}

export interface BaseAssignmentOptions {
title: string;
type: AssignmentOptionsComponent;
actionHandler(action: string, payload?: any): void;
}

export interface AssignmentOptionList extends BaseAssignmentOptions {
items: any[];
renderAssignmentOptions(item: any, key: string): any;
}

export interface AssignmentOptionSearch extends BaseAssignmentOptions {
columnDefinitions: ColumnDefinition[];
searchBox: { placeholder: string; incremental: boolean };
searchResults?: any[];
searchFailureMessage?: string;
}

export function isListOptions(options: any): options is AssignmentOptionList {
return options.type === 'list';
}

export function isSearchOptions(options: any): options is AssignmentOptionSearch {
return options.type === 'search';
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,24 @@
* you may not use this file except in compliance with the Elastic License.
*/

import { EuiButton, EuiFlexGroup, EuiFlexItem, EuiLoadingSpinner, EuiPopover } from '@elastic/eui';
import { EuiButton, EuiFlexGroup, EuiFlexItem, EuiPopover } from '@elastic/eui';
import React from 'react';
import { ActionButton } from './action_button';
import { AssignmentList } from './assignment_list';
import {
AssignmentOptionList,
AssignmentOptionSearch,
BaseAssignmentOptions,
isListOptions,
isSearchOptions,
} from './assignment_option_types';
import { AssignmentSearch } from './assignment_search';
import { ControlDefinitions } from './table_type_configs';

interface AssignmentOptionsProps {
assignmentOptions: any[] | null;
assignmentTitle: string | null;
renderAssignmentOptions?: (item: any, key: string) => any;
assignmentOptions: AssignmentOptionList | AssignmentOptionSearch | BaseAssignmentOptions;
controlDefinitions: ControlDefinitions;
selectionCount: number;
actionHandler(action: string, payload?: any): void;
}

interface AssignmentOptionsState {
Expand All @@ -38,10 +44,8 @@ export class AssignmentOptions extends React.Component<

public render() {
const {
actionHandler,
assignmentOptions,
renderAssignmentOptions,
assignmentTitle,
assignmentOptions: { actionHandler, title },
controlDefinitions: { actions },
selectionCount,
} = this.props;
Expand All @@ -62,47 +66,37 @@ export class AssignmentOptions extends React.Component<
}}
/>
</EuiFlexItem>
{assignmentTitle && (
<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 && renderAssignmentOptions ? (
// @ts-ignore direction prop not available on current typing
<EuiFlexGroup direction="column" gutterSize="xs">
{assignmentOptions.map((options, index) =>
renderAssignmentOptions(options, `${index}`)
)}
</EuiFlexGroup>
) : (
<div>
<EuiLoadingSpinner size="m" /> Loading
</div>
)}
</EuiPopover>
</EuiFlexItem>
)}
<EuiFlexItem grow={false}>
<EuiPopover
button={
<EuiButton
color="primary"
iconSide="right"
iconType="arrowDown"
onClick={() => {
this.setState({
isAssignmentPopoverVisible: true,
});
actionHandler('loadAssignmentOptions');
}}
>
{title}
</EuiButton>
}
closePopover={() => {
this.setState({ isAssignmentPopoverVisible: false });
}}
id="assignmentList"
isOpen={isAssignmentPopoverVisible}
panelPaddingSize="s"
withTitle
>
{isListOptions(assignmentOptions) && (
<AssignmentList assignmentOptions={assignmentOptions} />
)}
{isSearchOptions(assignmentOptions) && <AssignmentSearch options={assignmentOptions} />}
</EuiPopover>
</EuiFlexItem>
</EuiFlexGroup>
);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* 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.
*/

// @ts-ignore EuiSearchBar has no type definitions yet
import { EuiInMemoryTable } from '@elastic/eui';
import React from 'react';
import { AssignmentOptionSearch } from './assignment_option_types';

interface AssignmentSearchProps {
options: AssignmentOptionSearch;
}

export const AssignmentSearch = ({
options: { actionHandler, columnDefinitions, searchFailureMessage, searchBox, searchResults },
}: AssignmentSearchProps) => (
<EuiInMemoryTable
columns={columnDefinitions}
items={searchResults}
message={searchFailureMessage}
search={{
searchBox,
onChange: (query: any, queryString: string, error: any) =>
actionHandler('assignmentSearch', { query, queryString, error }),
}}
style={{ maxWidth: '500px' }}
/>
);
Original file line number Diff line number Diff line change
Expand Up @@ -5,48 +5,42 @@
*/

import React from 'react';
import {
AssignmentOptionList,
AssignmentOptionSearch,
BaseAssignmentOptions,
} from './assignment_option_types';
import { AssignmentOptions } from './assignment_options';
import { PrimaryOptions } from './primary_options';
import { ControlDefinitions } from './table_type_configs';

interface ControlBarProps {
assignmentOptions: any[] | null;
assignmentTitle: string | null;
renderAssignmentOptions?: (item: any, key: string) => any;

showAssignmentOptions: boolean;
assignmentOptions: AssignmentOptionList | AssignmentOptionSearch | BaseAssignmentOptions;
controlDefinitions: ControlDefinitions;
selectionCount: number;
actionHandler(actionType: string, payload?: any): void;
}

export function ControlBar(props: ControlBarProps) {
const {
actionHandler,
assignmentOptions,
renderAssignmentOptions,
assignmentTitle,
assignmentOptions: { actionHandler },
controlDefinitions,
controlDefinitions: { filters, primaryActions },
selectionCount,
showAssignmentOptions,
} = props;

const filters = controlDefinitions.filters.length === 0 ? null : controlDefinitions.filters;
return selectionCount !== 0 && showAssignmentOptions ? (
<AssignmentOptions
return assignmentOptions.type === 'primary' ? (
<PrimaryOptions
actionHandler={actionHandler}
filters={filters.length ? filters : null}
onSearchQueryChange={(query: any) => actionHandler('search', query)}
primaryActions={primaryActions || []}
/>
) : selectionCount !== 0 ? (
<AssignmentOptions
assignmentOptions={assignmentOptions}
renderAssignmentOptions={renderAssignmentOptions}
assignmentTitle={assignmentTitle}
controlDefinitions={controlDefinitions}
selectionCount={selectionCount}
/>
) : (
<PrimaryOptions
actionHandler={actionHandler}
filters={filters}
onSearchQueryChange={(query: any) => actionHandler('search', query)}
primaryActions={controlDefinitions.primaryActions || []}
/>
);
) : null;
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@

export { Table } from './table';
export { ControlBar } from './controls';
export {
AssignmentOptionSearch,
AssignmentOptionList,
AssignmentOptionsComponent,
BaseAssignmentOptions,
} from './assignment_option_types';
export {
ActionDefinition,
BeatDetailTagsTable,
Expand Down
25 changes: 7 additions & 18 deletions x-pack/plugins/beats_management/public/components/table/table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,18 @@ import {
import React from 'react';
import styled from 'styled-components';
import { TABLE_CONFIG } from '../../../common/constants';
import {
AssignmentOptionList,
AssignmentOptionSearch,
BaseAssignmentOptions,
} from './assignment_option_types';
import { ControlBar } from './controls';
import { TableType } from './table_type_configs';

interface TableProps {
assignmentOptions: any[] | null;
assignmentTitle: string | null;
assignmentOptions: AssignmentOptionList | AssignmentOptionSearch | BaseAssignmentOptions;
items: any[];
renderAssignmentOptions?: (item: any, key: string) => any;
showAssignmentOptions: boolean;
type: TableType;
actionHandler(action: string, payload?: any): void;
}

interface TableState {
Expand Down Expand Up @@ -53,15 +54,7 @@ export class Table extends React.Component<TableProps, TableState> {
};

public render() {
const {
actionHandler,
assignmentOptions,
renderAssignmentOptions,
assignmentTitle,
items,
showAssignmentOptions,
type,
} = this.props;
const { assignmentOptions, items, type } = this.props;

const pagination = {
initialPageSize: TABLE_CONFIG.INITIAL_ROW_SIZE,
Expand All @@ -78,13 +71,9 @@ export class Table extends React.Component<TableProps, TableState> {
return (
<TableContainer>
<ControlBar
actionHandler={actionHandler}
assignmentOptions={assignmentOptions}
renderAssignmentOptions={renderAssignmentOptions}
assignmentTitle={assignmentTitle}
controlDefinitions={type.controlDefinitions(items)}
selectionCount={this.state.selection.length}
showAssignmentOptions={showAssignmentOptions}
/>
<EuiSpacer size="m" />
<EuiInMemoryTable
Expand Down
Loading