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

[ML] Replace EuiBasicTable with EuiInMemoryTable #83057

Merged
merged 13 commits into from
Nov 11, 2020
Merged
Show file tree
Hide file tree
Changes from 11 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
Expand Up @@ -4,23 +4,14 @@
* you may not use this file except in compliance with the Elastic License.
*/

import React, { Dispatch, SetStateAction, FC, Fragment, useState } from 'react';
import {
EuiSearchBar,
EuiSearchBarProps,
EuiFlexGroup,
EuiFlexItem,
EuiFormRow,
} from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { stringMatch } from '../../../../../util/string_utils';
import { stringMatch } from '../../util/string_utils';
import {
TermClause,
FieldClause,
Value,
DataFrameAnalyticsListRow,
} from '../analytics_list/common';
import { ModelItem } from '../models_management/models_list';
} from '../pages/analytics_management/components/analytics_list/common';
import { ModelItem } from '../pages/analytics_management/components/models_management/models_list';

export function filterAnalyticsModels(
items: ModelItem[],
Expand Down Expand Up @@ -151,69 +142,3 @@ export function filterAnalytics(

return filtered;
}

function getError(errorMessage: string | null) {
if (errorMessage) {
return i18n.translate('xpack.ml.analyticList.searchBar.invalidSearchErrorMessage', {
defaultMessage: 'Invalid search: {errorMessage}',
values: { errorMessage },
});
}

return '';
}

interface Props {
filters: EuiSearchBarProps['filters'];
searchQueryText: string;
setSearchQueryText: Dispatch<SetStateAction<string>>;
}

export const AnalyticsSearchBar: FC<Props> = ({ filters, searchQueryText, setSearchQueryText }) => {
const [errorMessage, setErrorMessage] = useState<null | string>(null);

const onChange: EuiSearchBarProps['onChange'] = ({ query, error }) => {
if (error) {
setErrorMessage(error.message);
} else if (query !== null && query.text !== undefined) {
setSearchQueryText(query.text);
setErrorMessage(null);
}
};

return (
<EuiFlexGroup direction="column">
<EuiFlexItem data-test-subj="mlAnalyticsSearchBar" grow={false}>
{searchQueryText === undefined && (
<EuiSearchBar
box={{
incremental: true,
}}
filters={filters}
onChange={onChange}
className="mlAnalyitcsSearchBar"
/>
)}
{searchQueryText !== undefined && (
<EuiSearchBar
box={{
incremental: true,
}}
defaultQuery={searchQueryText}
filters={filters}
onChange={onChange}
className="mlAnalyitcsSearchBar"
/>
)}
<EuiFormRow
fullWidth
isInvalid={errorMessage !== null}
error={getError(errorMessage)}
style={{ maxHeight: '0px' }}
>
<Fragment />
</EuiFormRow>
</EuiFlexItem>
</EuiFlexGroup>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {
EuiCallOut,
EuiFlexGroup,
EuiFlexItem,
EuiBasicTable,
EuiInMemoryTable,
EuiSearchBar,
EuiSearchBarProps,
EuiSpacer,
Expand All @@ -35,7 +35,7 @@ import {
getGroupQueryText,
} from '../../../../../jobs/jobs_list/components/utils';
import { SourceSelection } from '../source_selection';
import { filterAnalytics, AnalyticsSearchBar } from '../analytics_search_bar';
import { filterAnalytics } from '../../../../common/search_bar_filters';
import { AnalyticsEmptyPrompt } from './empty_prompt';
import { useTableSettings } from './use_table_settings';
import { RefreshAnalyticsListButton } from '../refresh_analytics_list_button';
Expand Down Expand Up @@ -97,6 +97,7 @@ export const DataFrameAnalyticsList: FC<Props> = ({
const [isLoading, setIsLoading] = useState(false);
const [filteredAnalytics, setFilteredAnalytics] = useState<DataFrameAnalyticsListRow[]>([]);
const [searchQueryText, setSearchQueryText] = useState('');
const [searchError, setSearchError] = useState<string | undefined>();
const [analytics, setAnalytics] = useState<DataFrameAnalyticsListRow[]>([]);
const [analyticsStats, setAnalyticsStats] = useState<AnalyticStatsBarStats | undefined>(
undefined
Expand Down Expand Up @@ -183,9 +184,21 @@ export const DataFrameAnalyticsList: FC<Props> = ({
isMlEnabledInSpace
);

const { onTableChange, pageOfItems, pagination, sorting } = useTableSettings<
DataFrameAnalyticsListRow
>(DataFrameAnalyticsListColumn.id, filteredAnalytics);
const { onTableChange, pagination, sorting } = useTableSettings<DataFrameAnalyticsListRow>(
DataFrameAnalyticsListColumn.id,
filteredAnalytics
);

const handleSearchOnChange: EuiSearchBarProps['onChange'] = (search) => {
if (search.error !== null) {
setSearchError(search.error.message);
return false;
}

setSearchError(undefined);
setSearchQueryText(search.queryText);
return true;
};

// Before the analytics have been loaded for the first time, display the loading indicator only.
// Otherwise a user would see 'No data frame analytics found' during the initial loading.
Expand Down Expand Up @@ -240,6 +253,14 @@ export const DataFrameAnalyticsList: FC<Props> = ({
</EuiFlexGroup>
</EuiFlexItem>
);
const search: EuiSearchBarProps = {
query: searchQueryText,
onChange: handleSearchOnChange,
box: {
incremental: true,
},
filters,
};

return (
<div data-test-subj="mlAnalyticsJobList">
Expand All @@ -263,25 +284,22 @@ export const DataFrameAnalyticsList: FC<Props> = ({
</EuiFlexGroup>
<EuiSpacer size="m" />
<div data-test-subj="mlAnalyticsTableContainer">
<AnalyticsSearchBar
filters={filters}
searchQueryText={searchQueryText}
setSearchQueryText={setSearchQueryText}
/>
<EuiSpacer size="l" />
<EuiBasicTable<DataFrameAnalyticsListRow>
className="mlAnalyticsTable"
<EuiInMemoryTable<DataFrameAnalyticsListRow>
allowNeutralSort={false}
className="mlAnalyticsInMemoryTable"
columns={columns}
error={searchError}
hasActions={false}
isExpandable={true}
isSelectable={false}
items={pageOfItems}
items={analytics}
itemId={DataFrameAnalyticsListColumn.id}
itemIdToExpandedRowMap={itemIdToExpandedRowMap}
loading={isLoading}
onChange={onTableChange}
pagination={pagination!}
onTableChange={onTableChange}
pagination={pagination}
sorting={sorting}
search={search}
data-test-subj={isLoading ? 'mlAnalyticsTable loading' : 'mlAnalyticsTable loaded'}
rowProps={(item) => ({
'data-test-subj': `mlAnalyticsTableRow row-${item.id}`,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,11 @@
*/

import { useState } from 'react';
import { Direction, EuiBasicTableProps, EuiTableSortingType } from '@elastic/eui';
import { sortBy, get } from 'lodash';
import { Direction, EuiBasicTableProps, Pagination, PropertySort } from '@elastic/eui';

const PAGE_SIZE = 10;
const PAGE_SIZE_OPTIONS = [10, 25, 50];

const jobPropertyMap = {
ID: 'id',
Status: 'state',
Type: 'job_type',
};

// Copying from EUI EuiBasicTable types as type is not correctly picked up for table's onChange
// Can be removed when https://github.com/elastic/eui/issues/4011 is addressed in EUI
export interface Criteria<T> {
Expand Down Expand Up @@ -47,9 +40,8 @@ interface AnalyticsBasicTableSettings<T> {

interface UseTableSettingsReturnValue<T> {
onTableChange: EuiBasicTableProps<T>['onChange'];
pageOfItems: T[];
pagination: EuiBasicTableProps<T>['pagination'];
sorting: EuiTableSortingType<any>;
pagination: Pagination;
sorting: { sort: PropertySort };
}

export function useTableSettings<TypeOfItem>(
Expand All @@ -65,33 +57,6 @@ export function useTableSettings<TypeOfItem>(
sortDirection: 'asc',
});

const getPageOfItems = (
list: TypeOfItem[],
index: number,
size: number,
sortField: keyof TypeOfItem,
sortDirection: Direction
) => {
list = sortBy(list, (item) =>
get(item, jobPropertyMap[sortField as keyof typeof jobPropertyMap] || sortField)
);
list = sortDirection === 'asc' ? list : list.reverse();
const listLength = list.length;

let pageStart = index * size;
if (pageStart >= listLength && listLength !== 0) {
// if the page start is larger than the number of items due to
// filters being applied or items being deleted, calculate a new page start
pageStart = Math.floor((listLength - 1) / size) * size;

setTableSettings({ ...tableSettings, pageIndex: pageStart / size });
}
return {
pageOfItems: list.slice(pageStart, pageStart + size),
totalItemCount: listLength,
};
};

const onTableChange: EuiBasicTableProps<TypeOfItem>['onChange'] = ({
page = { index: 0, size: PAGE_SIZE },
sort = { field: sortByField, direction: 'asc' },
Expand All @@ -110,27 +75,19 @@ export function useTableSettings<TypeOfItem>(

const { pageIndex, pageSize, sortField, sortDirection } = tableSettings;

const { pageOfItems, totalItemCount } = getPageOfItems(
items,
pageIndex,
pageSize,
sortField,
sortDirection
);

const pagination = {
pageIndex,
pageSize,
totalItemCount,
totalItemCount: items.length,
pageSizeOptions: PAGE_SIZE_OPTIONS,
};

const sorting = {
sort: {
field: sortField,
field: sortField as string,
direction: sortDirection,
},
};

return { onTableChange, pageOfItems, pagination, sorting };
return { onTableChange, pagination, sorting };
}

This file was deleted.

Loading