mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 17:28:26 -04:00
[EuiInMemoryTable] Persist table rows per page and sort (#198297)
This commit is contained in:
parent
ab0375f56f
commit
020acbeaa3
57 changed files with 798 additions and 186 deletions
|
@ -23,6 +23,7 @@ export const FinderApp = (props: {
|
|||
<ContentClientProvider contentClient={props.contentClient}>
|
||||
<I18nProvider>
|
||||
<SavedObjectFinder
|
||||
id="cmFinderApp"
|
||||
showFilter={true}
|
||||
services={{
|
||||
savedObjectsTagging: props.savedObjectsTagging.getTaggingApi(),
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
import React from 'react';
|
||||
import { from } from 'rxjs';
|
||||
import type { IStorage } from '@kbn/kibana-utils-plugin/public';
|
||||
|
||||
import type { Services, TagListProps } from './services';
|
||||
|
||||
|
@ -149,3 +150,22 @@ export const getStoryArgTypes = () => ({
|
|||
defaultValue: false,
|
||||
},
|
||||
});
|
||||
|
||||
export const localStorageMock = (): IStorage => {
|
||||
let store: Record<string, unknown> = {};
|
||||
|
||||
return {
|
||||
getItem: (key: string) => {
|
||||
return store[key] || null;
|
||||
},
|
||||
setItem: (key: string, value: unknown) => {
|
||||
store[key] = value;
|
||||
},
|
||||
clear() {
|
||||
store = {};
|
||||
},
|
||||
removeItem(key: string) {
|
||||
delete store[key];
|
||||
},
|
||||
};
|
||||
};
|
||||
|
|
|
@ -18,7 +18,7 @@ import type { LocationDescriptor, History } from 'history';
|
|||
import type { UserContentCommonSchema } from '@kbn/content-management-table-list-view-common';
|
||||
|
||||
import { WithServices } from './__jest__';
|
||||
import { getTagList } from './mocks';
|
||||
import { getTagList, localStorageMock } from './mocks';
|
||||
import { TableListViewTable, type TableListViewTableProps } from './table_list_view_table';
|
||||
import { getActions } from './table_list_view.test.helpers';
|
||||
import type { Services } from './services';
|
||||
|
@ -335,6 +335,12 @@ describe('TableListView', () => {
|
|||
const totalItems = 30;
|
||||
const updatedAt = new Date().toISOString();
|
||||
|
||||
beforeEach(() => {
|
||||
Object.defineProperty(window, 'localStorage', {
|
||||
value: localStorageMock(),
|
||||
});
|
||||
});
|
||||
|
||||
const hits: UserContentCommonSchema[] = [...Array(totalItems)].map((_, i) => ({
|
||||
id: `item${i}`,
|
||||
type: 'dashboard',
|
||||
|
@ -429,6 +435,54 @@ describe('TableListView', () => {
|
|||
expect(firstRowTitle).toBe('Item 20');
|
||||
expect(lastRowTitle).toBe('Item 29');
|
||||
});
|
||||
|
||||
test('should persist the number of rows in the table', async () => {
|
||||
let testBed: TestBed;
|
||||
|
||||
const tableId = 'myTable';
|
||||
|
||||
await act(async () => {
|
||||
testBed = await setup({
|
||||
initialPageSize,
|
||||
findItems: jest.fn().mockResolvedValue({ total: hits.length, hits: [...hits] }),
|
||||
id: tableId,
|
||||
});
|
||||
});
|
||||
|
||||
{
|
||||
const { component, table, find } = testBed!;
|
||||
component.update();
|
||||
|
||||
const { tableCellsValues } = table.getMetaData('itemsInMemTable');
|
||||
expect(tableCellsValues.length).toBe(20); // 20 by default
|
||||
|
||||
let storageValue = localStorage.getItem(`tablePersist:${tableId}`);
|
||||
expect(storageValue).toBe(null);
|
||||
|
||||
find('tablePaginationPopoverButton').simulate('click');
|
||||
find('tablePagination-10-rows').simulate('click');
|
||||
|
||||
storageValue = localStorage.getItem(`tablePersist:${tableId}`);
|
||||
expect(storageValue).not.toBe(null);
|
||||
expect(JSON.parse(storageValue!).pageSize).toBe(10);
|
||||
}
|
||||
|
||||
// Mount a second table and verify that is shows only 10 rows
|
||||
{
|
||||
await act(async () => {
|
||||
testBed = await setup({
|
||||
initialPageSize,
|
||||
findItems: jest.fn().mockResolvedValue({ total: hits.length, hits: [...hits] }),
|
||||
id: tableId,
|
||||
});
|
||||
});
|
||||
|
||||
const { component, table } = testBed!;
|
||||
component.update();
|
||||
const { tableCellsValues } = table.getMetaData('itemsInMemTable');
|
||||
expect(tableCellsValues.length).toBe(10); // 10 items this time
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe('column sorting', () => {
|
||||
|
|
|
@ -43,6 +43,7 @@ import {
|
|||
ContentInsightsProvider,
|
||||
useContentInsightsServices,
|
||||
} from '@kbn/content-management-content-insights-public';
|
||||
import { useEuiTablePersist } from '@kbn/shared-ux-table-persist';
|
||||
|
||||
import {
|
||||
Table,
|
||||
|
@ -443,7 +444,7 @@ function TableListViewTableComp<T extends UserContentCommonSchema>({
|
|||
hasUpdatedAtMetadata,
|
||||
hasCreatedByMetadata,
|
||||
hasRecentlyAccessedMetadata,
|
||||
pagination,
|
||||
pagination: _pagination,
|
||||
tableSort,
|
||||
tableFilter,
|
||||
} = state;
|
||||
|
@ -903,7 +904,7 @@ function TableListViewTableComp<T extends UserContentCommonSchema>({
|
|||
[updateTableSortFilterAndPagination]
|
||||
);
|
||||
|
||||
const onTableChange = useCallback(
|
||||
const customOnTableChange = useCallback(
|
||||
(criteria: CriteriaWithPagination<T>) => {
|
||||
const data: {
|
||||
sort?: State<T>['tableSort'];
|
||||
|
@ -1038,6 +1039,20 @@ function TableListViewTableComp<T extends UserContentCommonSchema>({
|
|||
);
|
||||
}, [entityName, fetchError]);
|
||||
|
||||
const { pageSize, onTableChange } = useEuiTablePersist({
|
||||
tableId: listingId,
|
||||
initialPageSize,
|
||||
customOnTableChange,
|
||||
pageSizeOptions: uniq([10, 20, 50, initialPageSize]).sort(),
|
||||
});
|
||||
|
||||
const pagination = useMemo<Pagination>(() => {
|
||||
return {
|
||||
..._pagination,
|
||||
pageSize,
|
||||
};
|
||||
}, [_pagination, pageSize]);
|
||||
|
||||
// ------------
|
||||
// Effects
|
||||
// ------------
|
||||
|
|
|
@ -37,7 +37,9 @@
|
|||
"@kbn/content-management-user-profiles",
|
||||
"@kbn/recently-accessed",
|
||||
"@kbn/content-management-content-insights-public",
|
||||
"@kbn/content-management-favorites-public"
|
||||
"@kbn/content-management-favorites-public",
|
||||
"@kbn/kibana-utils-plugin",
|
||||
"@kbn/shared-ux-table-persist"
|
||||
],
|
||||
"exclude": [
|
||||
"target/**/*"
|
||||
|
|
|
@ -13,12 +13,13 @@ import {
|
|||
EuiTabbedContent,
|
||||
EuiTabbedContentProps,
|
||||
useEuiOverflowScroll,
|
||||
EuiBasicTableColumn,
|
||||
} from '@elastic/eui';
|
||||
import { css } from '@emotion/react';
|
||||
import React, { memo, useCallback, useMemo, useState } from 'react';
|
||||
import React, { memo, useMemo } from 'react';
|
||||
import { Alert } from '@kbn/alerting-types';
|
||||
import { euiThemeVars } from '@kbn/ui-theme';
|
||||
import { EuiBasicTableColumn } from '@elastic/eui/src/components/basic_table/basic_table';
|
||||
import { useEuiTablePersist } from '@kbn/shared-ux-table-persist';
|
||||
|
||||
export const search = {
|
||||
box: {
|
||||
|
@ -66,28 +67,6 @@ export const ScrollableFlyoutTabbedContent = (props: EuiTabbedContentProps) => (
|
|||
|
||||
const COUNT_PER_PAGE_OPTIONS = [25, 50, 100];
|
||||
|
||||
const useFieldBrowserPagination = () => {
|
||||
const [pagination, setPagination] = useState<{ pageIndex: number }>({
|
||||
pageIndex: 0,
|
||||
});
|
||||
|
||||
const onTableChange = useCallback(({ page: { index } }: { page: { index: number } }) => {
|
||||
setPagination({ pageIndex: index });
|
||||
}, []);
|
||||
const paginationTableProp = useMemo(
|
||||
() => ({
|
||||
...pagination,
|
||||
pageSizeOptions: COUNT_PER_PAGE_OPTIONS,
|
||||
}),
|
||||
[pagination]
|
||||
);
|
||||
|
||||
return {
|
||||
onTableChange,
|
||||
paginationTableProp,
|
||||
};
|
||||
};
|
||||
|
||||
type AlertField = Exclude<
|
||||
{
|
||||
[K in keyof Alert]: { key: K; value: Alert[K] };
|
||||
|
@ -111,7 +90,11 @@ export interface AlertFieldsTableProps {
|
|||
* A paginated, filterable table to show alert object fields
|
||||
*/
|
||||
export const AlertFieldsTable = memo(({ alert, fields }: AlertFieldsTableProps) => {
|
||||
const { onTableChange, paginationTableProp } = useFieldBrowserPagination();
|
||||
const { pageSize, sorting, onTableChange } = useEuiTablePersist<AlertField>({
|
||||
tableId: 'obltAlertFields',
|
||||
initialPageSize: 25,
|
||||
});
|
||||
|
||||
const items = useMemo(() => {
|
||||
let _items = Object.entries(alert).map(
|
||||
([key, value]) =>
|
||||
|
@ -131,7 +114,11 @@ export const AlertFieldsTable = memo(({ alert, fields }: AlertFieldsTableProps)
|
|||
itemId="key"
|
||||
columns={columns}
|
||||
onTableChange={onTableChange}
|
||||
pagination={paginationTableProp}
|
||||
pagination={{
|
||||
pageSize,
|
||||
pageSizeOptions: COUNT_PER_PAGE_OPTIONS,
|
||||
}}
|
||||
sorting={sorting}
|
||||
search={search}
|
||||
css={css`
|
||||
& .euiTableRow {
|
||||
|
|
|
@ -49,6 +49,7 @@
|
|||
"@kbn/core-ui-settings-browser",
|
||||
"@kbn/core-http-browser-mocks",
|
||||
"@kbn/core-notifications-browser-mocks",
|
||||
"@kbn/kibana-react-plugin"
|
||||
"@kbn/kibana-react-plugin",
|
||||
"@kbn/shared-ux-table-persist"
|
||||
]
|
||||
}
|
||||
|
|
|
@ -17,7 +17,6 @@ import {
|
|||
EuiInMemoryTable,
|
||||
EuiBasicTableColumn,
|
||||
EuiButtonEmpty,
|
||||
Criteria,
|
||||
EuiButtonIcon,
|
||||
CustomItemAction,
|
||||
EuiCopy,
|
||||
|
@ -25,6 +24,7 @@ import {
|
|||
euiScrollBarStyles,
|
||||
} from '@elastic/eui';
|
||||
import { css, Interpolation, Theme } from '@emotion/react';
|
||||
import { useEuiTablePersist } from '@kbn/shared-ux-table-persist';
|
||||
import { type QueryHistoryItem, getHistoryItems } from '../history_local_storage';
|
||||
import { getReducedSpaceStyling, swapArrayElements } from './query_history_helpers';
|
||||
|
||||
|
@ -212,8 +212,16 @@ export function QueryHistory({
|
|||
}) {
|
||||
const theme = useEuiTheme();
|
||||
const scrollBarStyles = euiScrollBarStyles(theme);
|
||||
const [sortDirection, setSortDirection] = useState<'asc' | 'desc'>('desc');
|
||||
const historyItems: QueryHistoryItem[] = getHistoryItems(sortDirection);
|
||||
|
||||
const { sorting, onTableChange } = useEuiTablePersist<QueryHistoryItem>({
|
||||
tableId: 'esqlQueryHistory',
|
||||
initialSort: {
|
||||
field: 'timeRan',
|
||||
direction: 'desc',
|
||||
},
|
||||
});
|
||||
|
||||
const historyItems: QueryHistoryItem[] = getHistoryItems(sorting.sort.direction);
|
||||
|
||||
const actions: Array<CustomItemAction<QueryHistoryItem>> = useMemo(() => {
|
||||
return [
|
||||
|
@ -276,19 +284,6 @@ export function QueryHistory({
|
|||
return getTableColumns(containerWidth, isOnReducedSpaceLayout, actions);
|
||||
}, [actions, containerWidth, isOnReducedSpaceLayout]);
|
||||
|
||||
const onTableChange = ({ page, sort }: Criteria<QueryHistoryItem>) => {
|
||||
if (sort) {
|
||||
const { direction } = sort;
|
||||
setSortDirection(direction);
|
||||
}
|
||||
};
|
||||
|
||||
const sorting = {
|
||||
sort: {
|
||||
field: 'timeRan',
|
||||
direction: sortDirection,
|
||||
},
|
||||
};
|
||||
const { euiTheme } = theme;
|
||||
const extraStyling = isOnReducedSpaceLayout ? getReducedSpaceStyling() : '';
|
||||
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
"@kbn/fields-metadata-plugin",
|
||||
"@kbn/esql-validation-autocomplete",
|
||||
"@kbn/esql-utils",
|
||||
"@kbn/shared-ux-table-persist",
|
||||
],
|
||||
"exclude": [
|
||||
"target/**/*",
|
||||
|
|
|
@ -100,6 +100,7 @@ export const EventAnnotationGroupSavedObjectFinder = ({
|
|||
) : (
|
||||
<SavedObjectFinder
|
||||
key="searchSavedObjectFinder"
|
||||
id="eventAnnotationGroup"
|
||||
fixedPageSize={fixedPageSize}
|
||||
onChoose={(id, type, fullName, savedObject) => {
|
||||
onChoose({ id, type, fullName, savedObject });
|
||||
|
|
|
@ -7,4 +7,5 @@
|
|||
* License v3.0 only", or the "Server Side Public License, v 1".
|
||||
*/
|
||||
|
||||
export { useEuiTablePersist, DEFAULT_PAGE_SIZE_OPTIONS } from './src';
|
||||
export { useEuiTablePersist, DEFAULT_PAGE_SIZE_OPTIONS, withEuiTablePersist } from './src';
|
||||
export type { EuiTablePersistInjectedProps, EuiTablePersistPropsGetter, HOCProps } from './src';
|
||||
|
|
|
@ -9,3 +9,9 @@
|
|||
|
||||
export { useEuiTablePersist } from './use_table_persist';
|
||||
export { DEFAULT_PAGE_SIZE_OPTIONS } from './constants';
|
||||
export { withEuiTablePersist } from './table_persist_hoc';
|
||||
export type {
|
||||
EuiTablePersistInjectedProps,
|
||||
EuiTablePersistPropsGetter,
|
||||
HOCProps,
|
||||
} from './table_persist_hoc';
|
||||
|
|
113
packages/shared-ux/table_persist/src/table_persist_hoc.test.tsx
Normal file
113
packages/shared-ux/table_persist/src/table_persist_hoc.test.tsx
Normal file
|
@ -0,0 +1,113 @@
|
|||
/*
|
||||
* 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", the "GNU Affero General Public License v3.0 only", and the "Server Side
|
||||
* Public License v 1"; you may not use this file except in compliance with, at
|
||||
* your election, the "Elastic License 2.0", the "GNU Affero General Public
|
||||
* License v3.0 only", or the "Server Side Public License, v 1".
|
||||
*/
|
||||
|
||||
import React, { PureComponent } from 'react';
|
||||
import { render, screen } from '@testing-library/react';
|
||||
|
||||
import { withEuiTablePersist, type EuiTablePersistInjectedProps } from './table_persist_hoc';
|
||||
|
||||
const mockUseEuiTablePersist = jest.fn().mockReturnValue({
|
||||
pageSize: 'mockPageSize',
|
||||
sorting: 'mockSorting',
|
||||
onTableChange: 'mockOnTableChange',
|
||||
});
|
||||
|
||||
jest.mock('./use_table_persist', () => {
|
||||
const original = jest.requireActual('./use_table_persist');
|
||||
|
||||
return {
|
||||
...original,
|
||||
useEuiTablePersist: (...args: unknown[]) => mockUseEuiTablePersist(...args),
|
||||
};
|
||||
});
|
||||
|
||||
class TestComponent extends PureComponent<EuiTablePersistInjectedProps<any>> {
|
||||
constructor(props: EuiTablePersistInjectedProps<any>) {
|
||||
super(props);
|
||||
}
|
||||
|
||||
render() {
|
||||
return <div data-test-subj="value">{JSON.stringify(this.props.euiTablePersist)}</div>;
|
||||
}
|
||||
}
|
||||
|
||||
describe('withEuiTablePersist', () => {
|
||||
it('should call useEuiTablePersist and return its values', () => {
|
||||
const customOnTableChange = jest.fn();
|
||||
const pageSizeOptions = [5, 10, 25, 50];
|
||||
|
||||
const WrappedComponent = withEuiTablePersist(TestComponent, {
|
||||
tableId: 'testTableId',
|
||||
initialPageSize: 10,
|
||||
initialSort: { field: 'testField', direction: 'asc' },
|
||||
customOnTableChange,
|
||||
pageSizeOptions,
|
||||
});
|
||||
|
||||
render(<WrappedComponent />);
|
||||
|
||||
expect(mockUseEuiTablePersist).toHaveBeenCalledWith({
|
||||
tableId: 'testTableId',
|
||||
customOnTableChange,
|
||||
initialPageSize: 10,
|
||||
initialSort: { field: 'testField', direction: 'asc' },
|
||||
pageSizeOptions,
|
||||
});
|
||||
|
||||
expect(screen.getByTestId('value').textContent).toBe(
|
||||
JSON.stringify({
|
||||
pageSize: 'mockPageSize',
|
||||
sorting: 'mockSorting',
|
||||
onTableChange: 'mockOnTableChange',
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
it('should allow override through props', () => {
|
||||
const customOnTableChangeDefault = jest.fn();
|
||||
const customOnTableChangeProp = jest.fn();
|
||||
const pageSizeOptions = [5, 10, 25, 50];
|
||||
|
||||
const WrappedComponent = withEuiTablePersist(TestComponent, {
|
||||
tableId: 'testTableId',
|
||||
initialPageSize: 10,
|
||||
initialSort: { field: 'testField', direction: 'asc' },
|
||||
customOnTableChange: customOnTableChangeDefault,
|
||||
pageSizeOptions,
|
||||
});
|
||||
|
||||
render(
|
||||
<WrappedComponent
|
||||
euiTablePersistProps={{
|
||||
tableId: 'testTableIdChanged',
|
||||
initialPageSize: 20,
|
||||
initialSort: { field: 'testFieldChanged', direction: 'desc' },
|
||||
customOnTableChange: customOnTableChangeProp,
|
||||
pageSizeOptions: [5],
|
||||
}}
|
||||
/>
|
||||
);
|
||||
|
||||
expect(mockUseEuiTablePersist).toHaveBeenCalledWith({
|
||||
tableId: 'testTableIdChanged',
|
||||
customOnTableChange: customOnTableChangeProp,
|
||||
initialPageSize: 20,
|
||||
initialSort: { field: 'testFieldChanged', direction: 'desc' },
|
||||
pageSizeOptions: [5],
|
||||
});
|
||||
|
||||
expect(screen.getByTestId('value').textContent).toBe(
|
||||
JSON.stringify({
|
||||
pageSize: 'mockPageSize',
|
||||
sorting: 'mockSorting',
|
||||
onTableChange: 'mockOnTableChange',
|
||||
})
|
||||
);
|
||||
});
|
||||
});
|
74
packages/shared-ux/table_persist/src/table_persist_hoc.tsx
Normal file
74
packages/shared-ux/table_persist/src/table_persist_hoc.tsx
Normal file
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* 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", the "GNU Affero General Public License v3.0 only", and the "Server Side
|
||||
* Public License v 1"; you may not use this file except in compliance with, at
|
||||
* your election, the "Elastic License 2.0", the "GNU Affero General Public
|
||||
* License v3.0 only", or the "Server Side Public License, v 1".
|
||||
*/
|
||||
import React from 'react';
|
||||
import { type CriteriaWithPagination } from '@elastic/eui';
|
||||
import { EuiTablePersistProps, useEuiTablePersist } from './use_table_persist';
|
||||
import { PropertySort } from './types';
|
||||
|
||||
export interface EuiTablePersistInjectedProps<T> {
|
||||
euiTablePersist: {
|
||||
/** The EuiInMemoryTable onTableChange prop */
|
||||
onTableChange: (change: CriteriaWithPagination<T>) => void;
|
||||
/** The EuiInMemoryTable sorting prop */
|
||||
sorting: { sort: PropertySort<T> } | true;
|
||||
/** The EuiInMemoryTable pagination.pageSize value */
|
||||
pageSize: number;
|
||||
};
|
||||
}
|
||||
|
||||
export type EuiTablePersistPropsGetter<T extends object, P extends object> = (
|
||||
props: Omit<P, keyof EuiTablePersistInjectedProps<T>>
|
||||
) => EuiTablePersistProps<T>;
|
||||
|
||||
export type HOCProps<T extends object, P extends object> = P & {
|
||||
/** Custom value for the EuiTablePersist HOC */
|
||||
euiTablePersistProps?: Partial<EuiTablePersistProps<T>>;
|
||||
};
|
||||
|
||||
export function withEuiTablePersist<T extends object, Props extends object>(
|
||||
WrappedComponent: React.ComponentClass<Props & EuiTablePersistInjectedProps<T>>,
|
||||
euiTablePersistDefault:
|
||||
| (EuiTablePersistProps<T> & { get?: undefined })
|
||||
| {
|
||||
get: EuiTablePersistPropsGetter<T, Props>;
|
||||
}
|
||||
) {
|
||||
const HOC: React.FC<HOCProps<T, Omit<Props, keyof EuiTablePersistInjectedProps<T>>>> = (
|
||||
props
|
||||
) => {
|
||||
const getterOverride = euiTablePersistDefault.get ? euiTablePersistDefault.get(props) : {};
|
||||
|
||||
const mergedProps = {
|
||||
...euiTablePersistDefault,
|
||||
...props.euiTablePersistProps,
|
||||
...getterOverride, // Getter override other props
|
||||
};
|
||||
|
||||
const { tableId, customOnTableChange, initialSort, initialPageSize, pageSizeOptions } =
|
||||
mergedProps;
|
||||
|
||||
if (!tableId) {
|
||||
throw new Error('tableId is required');
|
||||
}
|
||||
|
||||
const euiTablePersist = useEuiTablePersist<T>({
|
||||
tableId,
|
||||
customOnTableChange,
|
||||
initialSort,
|
||||
initialPageSize,
|
||||
pageSizeOptions,
|
||||
});
|
||||
|
||||
const { euiTablePersistProps, ...rest } = props;
|
||||
|
||||
return <WrappedComponent {...(rest as Props)} euiTablePersist={euiTablePersist} />;
|
||||
};
|
||||
|
||||
return HOC;
|
||||
}
|
|
@ -7,7 +7,7 @@
|
|||
* License v3.0 only", or the "Server Side Public License, v 1".
|
||||
*/
|
||||
|
||||
import { Criteria } from '@elastic/eui';
|
||||
import { CriteriaWithPagination } from '@elastic/eui';
|
||||
import { renderHook, act } from '@testing-library/react-hooks';
|
||||
import { useEuiTablePersist } from './use_table_persist';
|
||||
import { createStorage } from './storage'; // Mock this if it's external
|
||||
|
@ -58,7 +58,7 @@ describe('useEuiTablePersist', () => {
|
|||
};
|
||||
|
||||
act(() => {
|
||||
result.current.onTableChange(nextCriteria as Criteria<any>);
|
||||
result.current.onTableChange(nextCriteria as CriteriaWithPagination<any>);
|
||||
});
|
||||
|
||||
expect(result.current.pageSize).toBe(100);
|
||||
|
@ -85,7 +85,7 @@ describe('useEuiTablePersist', () => {
|
|||
};
|
||||
|
||||
act(() => {
|
||||
result.current.onTableChange(nextCriteria as Criteria<any>);
|
||||
result.current.onTableChange(nextCriteria as CriteriaWithPagination<any>);
|
||||
});
|
||||
|
||||
expect(customOnTableChange).toHaveBeenCalledWith(nextCriteria);
|
||||
|
@ -98,7 +98,7 @@ describe('useEuiTablePersist', () => {
|
|||
const { result } = renderHook(() => useEuiTablePersist({ tableId: 'testTable' }));
|
||||
|
||||
act(() => {
|
||||
result.current.onTableChange({}); // Empty change
|
||||
result.current.onTableChange({} as CriteriaWithPagination<any>); // Empty change
|
||||
});
|
||||
|
||||
expect(result.current.pageSize).toBe(25);
|
||||
|
@ -118,7 +118,7 @@ describe('useEuiTablePersist', () => {
|
|||
};
|
||||
|
||||
act(() => {
|
||||
result.current.onTableChange(nextCriteria as Criteria<any>);
|
||||
result.current.onTableChange(nextCriteria as CriteriaWithPagination<any>);
|
||||
});
|
||||
|
||||
expect(result.current.pageSize).toBe(100);
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
*/
|
||||
|
||||
import { useState, useCallback } from 'react';
|
||||
import { Criteria } from '@elastic/eui';
|
||||
import type { CriteriaWithPagination } from '@elastic/eui';
|
||||
import { DEFAULT_INITIAL_PAGE_SIZE, DEFAULT_PAGE_SIZE_OPTIONS } from './constants';
|
||||
import { createStorage } from './storage';
|
||||
import { validatePersistData } from './validate_persist_data';
|
||||
|
@ -18,7 +18,7 @@ export interface EuiTablePersistProps<T> {
|
|||
/** A unique id that will be included in the local storage variable for this table. */
|
||||
tableId: string;
|
||||
/** (Optional) Specifies a custom onTableChange handler. */
|
||||
customOnTableChange?: (change: Criteria<T>) => void;
|
||||
customOnTableChange?: (change: CriteriaWithPagination<T>) => void;
|
||||
/** (Optional) Specifies a custom initial table sorting. */
|
||||
initialSort?: PropertySort<T>;
|
||||
/** (Optional) Specifies a custom initial page size for the table. Defaults to 50. */
|
||||
|
@ -33,13 +33,37 @@ export interface EuiTablePersistProps<T> {
|
|||
* Returns the persisting page size and sort and the onTableChange handler that should be passed
|
||||
* as props to an Eui table component.
|
||||
*/
|
||||
export const useEuiTablePersist = <T extends object>({
|
||||
export function useEuiTablePersist<T extends object>(
|
||||
props: EuiTablePersistProps<T> & { initialSort: PropertySort<T> }
|
||||
): {
|
||||
sorting: { sort: PropertySort<T> };
|
||||
pageSize: number;
|
||||
onTableChange: (nextValues: CriteriaWithPagination<T>) => void;
|
||||
};
|
||||
|
||||
export function useEuiTablePersist<T extends object>(
|
||||
props: EuiTablePersistProps<T> & { initialSort?: undefined }
|
||||
): {
|
||||
sorting: true;
|
||||
pageSize: number;
|
||||
onTableChange: (nextValues: CriteriaWithPagination<T>) => void;
|
||||
};
|
||||
|
||||
export function useEuiTablePersist<T extends object>(
|
||||
props: EuiTablePersistProps<T>
|
||||
): {
|
||||
sorting: true | { sort: PropertySort<T> };
|
||||
pageSize: number;
|
||||
onTableChange: (nextValues: CriteriaWithPagination<T>) => void;
|
||||
};
|
||||
|
||||
export function useEuiTablePersist<T extends object>({
|
||||
tableId,
|
||||
customOnTableChange,
|
||||
initialSort,
|
||||
initialPageSize,
|
||||
pageSizeOptions,
|
||||
}: EuiTablePersistProps<T>) => {
|
||||
}: EuiTablePersistProps<T>) {
|
||||
const storage = createStorage();
|
||||
const storedPersistData = storage.get(tableId, undefined);
|
||||
|
||||
|
@ -55,7 +79,7 @@ export const useEuiTablePersist = <T extends object>({
|
|||
const sorting = sort ? { sort } : true; // If sort is undefined, return true to allow sorting
|
||||
|
||||
const onTableChange = useCallback(
|
||||
(nextValues: Criteria<T>) => {
|
||||
(nextValues: CriteriaWithPagination<T>) => {
|
||||
if (customOnTableChange) {
|
||||
customOnTableChange(nextValues);
|
||||
}
|
||||
|
@ -92,4 +116,4 @@ export const useEuiTablePersist = <T extends object>({
|
|||
);
|
||||
|
||||
return { pageSize, sorting, onTableChange };
|
||||
};
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ import { CoreStart } from '@kbn/core/public';
|
|||
import moment from 'moment';
|
||||
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
||||
import useDebounce from 'react-use/lib/useDebounce';
|
||||
import { useEuiTablePersist } from '@kbn/shared-ux-table-persist';
|
||||
import { TableText } from '..';
|
||||
import { SEARCH_SESSIONS_TABLE_ID } from '../../../../../../common';
|
||||
import { SearchSessionsMgmtAPI } from '../../lib/api';
|
||||
|
@ -45,7 +46,6 @@ export function SearchSessionsMgmtTable({
|
|||
const [tableData, setTableData] = useState<UISession[]>([]);
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const [debouncedIsLoading, setDebouncedIsLoading] = useState(false);
|
||||
const [pagination, setPagination] = useState({ pageIndex: 0 });
|
||||
const showLatestResultsHandler = useRef<Function>();
|
||||
const refreshTimeoutRef = useRef<number | null>(null);
|
||||
const refreshInterval = useMemo(
|
||||
|
@ -53,6 +53,14 @@ export function SearchSessionsMgmtTable({
|
|||
[config.management.refreshInterval]
|
||||
);
|
||||
|
||||
const { pageSize, sorting, onTableChange } = useEuiTablePersist<UISession>({
|
||||
tableId: 'searchSessionsMgmt',
|
||||
initialSort: {
|
||||
field: 'created',
|
||||
direction: 'desc',
|
||||
},
|
||||
});
|
||||
|
||||
// Debounce rendering the state of the Refresh button
|
||||
useDebounce(
|
||||
() => {
|
||||
|
@ -148,12 +156,12 @@ export function SearchSessionsMgmtTable({
|
|||
searchUsageCollector
|
||||
)}
|
||||
items={tableData}
|
||||
pagination={pagination}
|
||||
search={search}
|
||||
sorting={{ sort: { field: 'created', direction: 'desc' } }}
|
||||
onTableChange={({ page: { index } }) => {
|
||||
setPagination({ pageIndex: index });
|
||||
pagination={{
|
||||
pageSize,
|
||||
}}
|
||||
search={search}
|
||||
sorting={sorting}
|
||||
onTableChange={onTableChange}
|
||||
tableLayout="auto"
|
||||
/>
|
||||
);
|
||||
|
|
|
@ -22,11 +22,17 @@ import { FormattedMessage } from '@kbn/i18n-react';
|
|||
import { i18n } from '@kbn/i18n';
|
||||
|
||||
import { IUiSettingsClient } from '@kbn/core/public';
|
||||
import { Datatable, DatatableColumn } from '@kbn/expressions-plugin/public';
|
||||
import { Datatable, DatatableColumn, DatatableRow } from '@kbn/expressions-plugin/public';
|
||||
import { FieldFormatsStart } from '@kbn/field-formats-plugin/public';
|
||||
import { UiActionsStart } from '@kbn/ui-actions-plugin/public';
|
||||
import {
|
||||
withEuiTablePersist,
|
||||
type EuiTablePersistInjectedProps,
|
||||
} from '@kbn/shared-ux-table-persist/src';
|
||||
import { DataViewRow, DataViewColumn } from '../types';
|
||||
|
||||
const PAGE_SIZE_OPTIONS = [10, 20, 50];
|
||||
|
||||
interface DataTableFormatState {
|
||||
columns: DataViewColumn[];
|
||||
rows: DataViewRow[];
|
||||
|
@ -49,7 +55,10 @@ interface RenderCellArguments {
|
|||
isFilterable: boolean;
|
||||
}
|
||||
|
||||
export class DataTableFormat extends Component<DataTableFormatProps, DataTableFormatState> {
|
||||
class DataTableFormatClass extends Component<
|
||||
DataTableFormatProps & EuiTablePersistInjectedProps<DatatableRow>,
|
||||
DataTableFormatState
|
||||
> {
|
||||
static propTypes = {
|
||||
data: PropTypes.object.isRequired,
|
||||
uiSettings: PropTypes.object.isRequired,
|
||||
|
@ -169,7 +178,7 @@ export class DataTableFormat extends Component<DataTableFormatProps, DataTableFo
|
|||
const formattedValue = fieldFormatter.convert(value);
|
||||
const rowIndex = data.rows.findIndex((row) => row[dataColumn.id] === value) || 0;
|
||||
|
||||
return DataTableFormat.renderCell({
|
||||
return DataTableFormatClass.renderCell({
|
||||
table: data,
|
||||
columnIndex: index,
|
||||
rowIndex,
|
||||
|
@ -186,9 +195,10 @@ export class DataTableFormat extends Component<DataTableFormatProps, DataTableFo
|
|||
|
||||
render() {
|
||||
const { columns, rows } = this.state;
|
||||
const { pageSize, sorting, onTableChange } = this.props.euiTablePersist;
|
||||
const pagination = {
|
||||
pageSizeOptions: [10, 20, 50],
|
||||
initialPageSize: 20,
|
||||
pageSizeOptions: PAGE_SIZE_OPTIONS,
|
||||
pageSize,
|
||||
};
|
||||
|
||||
return (
|
||||
|
@ -198,8 +208,9 @@ export class DataTableFormat extends Component<DataTableFormatProps, DataTableFo
|
|||
data-test-subj="inspectorTable"
|
||||
columns={columns}
|
||||
items={rows}
|
||||
sorting={true}
|
||||
sorting={sorting}
|
||||
pagination={pagination}
|
||||
onChange={onTableChange}
|
||||
css={css`
|
||||
// Set a min width on each column - you can use [data-test-subj] to target specific columns
|
||||
.euiTableHeaderCell {
|
||||
|
@ -216,3 +227,9 @@ export class DataTableFormat extends Component<DataTableFormatProps, DataTableFo
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
export const DataTableFormat = withEuiTablePersist(DataTableFormatClass, {
|
||||
tableId: 'inspectorDataTable',
|
||||
pageSizeOptions: PAGE_SIZE_OPTIONS,
|
||||
initialPageSize: 20,
|
||||
});
|
||||
|
|
|
@ -54,7 +54,8 @@
|
|||
"@kbn/react-kibana-mount",
|
||||
"@kbn/search-types",
|
||||
"@kbn/safer-lodash-set",
|
||||
"@kbn/esql-utils"
|
||||
"@kbn/esql-utils",
|
||||
"@kbn/shared-ux-table-persist"
|
||||
],
|
||||
"exclude": [
|
||||
"target/**/*",
|
||||
|
|
|
@ -290,9 +290,10 @@ exports[`Table should render normally 1`] = `
|
|||
},
|
||||
]
|
||||
}
|
||||
onTableChange={[Function]}
|
||||
pagination={
|
||||
Object {
|
||||
"initialPageSize": 10,
|
||||
"pageSize": 10,
|
||||
"pageSizeOptions": Array [
|
||||
5,
|
||||
10,
|
||||
|
@ -306,7 +307,7 @@ exports[`Table should render normally 1`] = `
|
|||
Object {
|
||||
"sort": Object {
|
||||
"direction": "asc",
|
||||
"field": "displayName",
|
||||
"field": "name",
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,7 +11,12 @@ import React from 'react';
|
|||
import { shallow } from 'enzyme';
|
||||
import { DataView } from '@kbn/data-views-plugin/public';
|
||||
import { IndexedFieldItem } from '../../types';
|
||||
import { Table, renderFieldName, getConflictModalContent, showDelete } from './table';
|
||||
import {
|
||||
TableWithoutPersist as Table,
|
||||
renderFieldName,
|
||||
getConflictModalContent,
|
||||
showDelete,
|
||||
} from './table';
|
||||
import { coreMock, overlayServiceMock } from '@kbn/core/public/mocks';
|
||||
|
||||
const coreStart = coreMock.createStart();
|
||||
|
@ -80,6 +85,14 @@ const items: IndexedFieldItem[] = [
|
|||
},
|
||||
];
|
||||
|
||||
const baseProps = {
|
||||
euiTablePersist: {
|
||||
pageSize: 10,
|
||||
onTableChange: () => {},
|
||||
sorting: { sort: { direction: 'asc' as const, field: 'name' as const } },
|
||||
},
|
||||
};
|
||||
|
||||
const renderTable = (
|
||||
{ editField } = {
|
||||
editField: () => {},
|
||||
|
@ -87,6 +100,7 @@ const renderTable = (
|
|||
) =>
|
||||
shallow(
|
||||
<Table
|
||||
{...baseProps}
|
||||
indexPattern={indexPattern}
|
||||
items={items}
|
||||
editField={editField}
|
||||
|
|
|
@ -31,6 +31,10 @@ import {
|
|||
import { i18n } from '@kbn/i18n';
|
||||
import { FormattedMessage } from '@kbn/i18n-react';
|
||||
import { toMountPoint } from '@kbn/react-kibana-mount';
|
||||
import {
|
||||
withEuiTablePersist,
|
||||
type EuiTablePersistInjectedProps,
|
||||
} from '@kbn/shared-ux-table-persist';
|
||||
|
||||
import { DataView } from '@kbn/data-views-plugin/public';
|
||||
import { StartServices } from '../../../../../types';
|
||||
|
@ -379,7 +383,11 @@ const getConflictBtn = (
|
|||
);
|
||||
};
|
||||
|
||||
export class Table extends PureComponent<IndexedFieldProps> {
|
||||
const PAGE_SIZE_OPTIONS = [5, 10, 25, 50];
|
||||
|
||||
class TableClass extends PureComponent<
|
||||
IndexedFieldProps & EuiTablePersistInjectedProps<IndexedFieldItem>
|
||||
> {
|
||||
renderBooleanTemplate(value: string, arialLabel: string) {
|
||||
return value ? <EuiIcon type="dot" color="success" aria-label={arialLabel} /> : <span />;
|
||||
}
|
||||
|
@ -403,11 +411,17 @@ export class Table extends PureComponent<IndexedFieldProps> {
|
|||
}
|
||||
|
||||
render() {
|
||||
const { items, editField, deleteField, indexPattern } = this.props;
|
||||
const {
|
||||
items,
|
||||
editField,
|
||||
deleteField,
|
||||
indexPattern,
|
||||
euiTablePersist: { pageSize, sorting, onTableChange },
|
||||
} = this.props;
|
||||
|
||||
const pagination = {
|
||||
initialPageSize: 10,
|
||||
pageSizeOptions: [5, 10, 25, 50],
|
||||
pageSize,
|
||||
pageSizeOptions: PAGE_SIZE_OPTIONS,
|
||||
};
|
||||
|
||||
const columns: Array<EuiBasicTableColumn<IndexedFieldItem>> = [
|
||||
|
@ -508,8 +522,18 @@ export class Table extends PureComponent<IndexedFieldProps> {
|
|||
items={items}
|
||||
columns={columns}
|
||||
pagination={pagination}
|
||||
sorting={{ sort: { field: 'displayName', direction: 'asc' } }}
|
||||
sorting={sorting}
|
||||
onTableChange={onTableChange}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export const TableWithoutPersist = TableClass; // For testing purposes
|
||||
|
||||
export const Table = withEuiTablePersist(TableClass, {
|
||||
tableId: 'dataViewsIndexedFields',
|
||||
pageSizeOptions: PAGE_SIZE_OPTIONS,
|
||||
initialSort: { field: 'displayName', direction: 'asc' },
|
||||
initialPageSize: 10,
|
||||
});
|
||||
|
|
|
@ -18,6 +18,7 @@ import {
|
|||
import { CoreStart } from '@kbn/core/public';
|
||||
import { get } from 'lodash';
|
||||
import { RedirectAppLinks } from '@kbn/shared-ux-link-redirect-app';
|
||||
import { useEuiTablePersist } from '@kbn/shared-ux-table-persist';
|
||||
|
||||
import {
|
||||
SavedObjectRelation,
|
||||
|
@ -139,12 +140,20 @@ export const RelationshipsTable = ({
|
|||
] as SearchFilterConfig[],
|
||||
};
|
||||
|
||||
const { pageSize, onTableChange } = useEuiTablePersist<SavedObjectRelation>({
|
||||
tableId: 'dataViewMgmtRelationships',
|
||||
initialPageSize: 10,
|
||||
});
|
||||
|
||||
return (
|
||||
<RedirectAppLinks currentAppId={IPM_APP_ID} navigateToUrl={navigateToUrl}>
|
||||
<EuiInMemoryTable<SavedObjectRelation>
|
||||
items={relationships}
|
||||
columns={columns}
|
||||
pagination={true}
|
||||
pagination={{
|
||||
pageSize,
|
||||
}}
|
||||
onTableChange={onTableChange}
|
||||
search={search}
|
||||
rowProps={() => ({
|
||||
'data-test-subj': `relationshipsTableRow`,
|
||||
|
|
|
@ -75,9 +75,10 @@ exports[`Table should render normally 1`] = `
|
|||
},
|
||||
]
|
||||
}
|
||||
onTableChange={[Function]}
|
||||
pagination={
|
||||
Object {
|
||||
"initialPageSize": 10,
|
||||
"pageSize": 10,
|
||||
"pageSizeOptions": Array [
|
||||
5,
|
||||
10,
|
||||
|
@ -87,7 +88,14 @@ exports[`Table should render normally 1`] = `
|
|||
}
|
||||
}
|
||||
searchFormat="eql"
|
||||
sorting={true}
|
||||
sorting={
|
||||
Object {
|
||||
"sort": Object {
|
||||
"direction": "asc",
|
||||
"field": "name",
|
||||
},
|
||||
}
|
||||
}
|
||||
tableLayout="fixed"
|
||||
/>
|
||||
`;
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
import React from 'react';
|
||||
import { shallow } from 'enzyme';
|
||||
|
||||
import { Table } from '.';
|
||||
import { TableWithoutPersist as Table } from './table';
|
||||
import { ScriptedFieldItem } from '../../types';
|
||||
import { DataView } from '@kbn/data-views-plugin/public';
|
||||
|
||||
|
@ -21,6 +21,14 @@ const items: ScriptedFieldItem[] = [
|
|||
{ name: '2', lang: 'painless', script: '', isUserEditable: false },
|
||||
];
|
||||
|
||||
const baseProps = {
|
||||
euiTablePersist: {
|
||||
pageSize: 10,
|
||||
onTableChange: () => {},
|
||||
sorting: { sort: { direction: 'asc' as const, field: 'name' as const } },
|
||||
},
|
||||
};
|
||||
|
||||
describe('Table', () => {
|
||||
let indexPattern: DataView;
|
||||
|
||||
|
@ -37,8 +45,9 @@ describe('Table', () => {
|
|||
});
|
||||
|
||||
test('should render normally', () => {
|
||||
const component = shallow<Table>(
|
||||
const component = shallow<typeof Table>(
|
||||
<Table
|
||||
{...baseProps}
|
||||
indexPattern={indexPattern}
|
||||
items={items}
|
||||
editField={() => {}}
|
||||
|
@ -52,6 +61,7 @@ describe('Table', () => {
|
|||
test('should render the format', () => {
|
||||
const component = shallow(
|
||||
<Table
|
||||
{...baseProps}
|
||||
indexPattern={indexPattern}
|
||||
items={items}
|
||||
editField={() => {}}
|
||||
|
@ -68,6 +78,7 @@ describe('Table', () => {
|
|||
|
||||
const component = shallow(
|
||||
<Table
|
||||
{...baseProps}
|
||||
indexPattern={indexPattern}
|
||||
items={items}
|
||||
editField={editField}
|
||||
|
@ -85,6 +96,7 @@ describe('Table', () => {
|
|||
|
||||
const component = shallow(
|
||||
<Table
|
||||
{...baseProps}
|
||||
indexPattern={indexPattern}
|
||||
items={items}
|
||||
editField={() => {}}
|
||||
|
@ -100,6 +112,7 @@ describe('Table', () => {
|
|||
test('should not allow edit or deletion for user with only read access', () => {
|
||||
const component = shallow(
|
||||
<Table
|
||||
{...baseProps}
|
||||
indexPattern={indexPattern}
|
||||
items={items}
|
||||
editField={() => {}}
|
||||
|
|
|
@ -13,8 +13,14 @@ import { i18n } from '@kbn/i18n';
|
|||
import { EuiInMemoryTable, EuiBasicTableColumn } from '@elastic/eui';
|
||||
|
||||
import { DataView } from '@kbn/data-views-plugin/public';
|
||||
import {
|
||||
withEuiTablePersist,
|
||||
type EuiTablePersistInjectedProps,
|
||||
} from '@kbn/shared-ux-table-persist';
|
||||
import { ScriptedFieldItem } from '../../types';
|
||||
|
||||
const PAGE_SIZE_OPTIONS = [5, 10, 25, 50];
|
||||
|
||||
interface TableProps {
|
||||
indexPattern: DataView;
|
||||
items: ScriptedFieldItem[];
|
||||
|
@ -22,7 +28,9 @@ interface TableProps {
|
|||
deleteField: (field: ScriptedFieldItem) => void;
|
||||
}
|
||||
|
||||
export class Table extends PureComponent<TableProps> {
|
||||
class TableClass extends PureComponent<
|
||||
TableProps & EuiTablePersistInjectedProps<ScriptedFieldItem>
|
||||
> {
|
||||
renderFormatCell = (value: string) => {
|
||||
const { indexPattern } = this.props;
|
||||
const title = get(indexPattern, ['fieldFormatMap', value, 'type', 'title'], '');
|
||||
|
@ -31,7 +39,12 @@ export class Table extends PureComponent<TableProps> {
|
|||
};
|
||||
|
||||
render() {
|
||||
const { items, editField, deleteField } = this.props;
|
||||
const {
|
||||
items,
|
||||
editField,
|
||||
deleteField,
|
||||
euiTablePersist: { pageSize, sorting, onTableChange },
|
||||
} = this.props;
|
||||
|
||||
const columns: Array<EuiBasicTableColumn<ScriptedFieldItem>> = [
|
||||
{
|
||||
|
@ -132,12 +145,26 @@ export class Table extends PureComponent<TableProps> {
|
|||
];
|
||||
|
||||
const pagination = {
|
||||
initialPageSize: 10,
|
||||
pageSizeOptions: [5, 10, 25, 50],
|
||||
pageSize,
|
||||
pageSizeOptions: PAGE_SIZE_OPTIONS,
|
||||
};
|
||||
|
||||
return (
|
||||
<EuiInMemoryTable items={items} columns={columns} pagination={pagination} sorting={true} />
|
||||
<EuiInMemoryTable
|
||||
items={items}
|
||||
columns={columns}
|
||||
pagination={pagination}
|
||||
sorting={sorting}
|
||||
onTableChange={onTableChange}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export const TableWithoutPersist = TableClass; // For testing purposes
|
||||
|
||||
export const Table = withEuiTablePersist(TableClass, {
|
||||
tableId: 'dataViewsScriptedFields',
|
||||
pageSizeOptions: PAGE_SIZE_OPTIONS,
|
||||
initialPageSize: 10,
|
||||
});
|
||||
|
|
|
@ -79,9 +79,10 @@ exports[`Table should render normally 1`] = `
|
|||
]
|
||||
}
|
||||
loading={true}
|
||||
onTableChange={[Function]}
|
||||
pagination={
|
||||
Object {
|
||||
"initialPageSize": 10,
|
||||
"pageSize": 10,
|
||||
"pageSizeOptions": Array [
|
||||
5,
|
||||
10,
|
||||
|
@ -91,7 +92,14 @@ exports[`Table should render normally 1`] = `
|
|||
}
|
||||
}
|
||||
searchFormat="eql"
|
||||
sorting={true}
|
||||
sorting={
|
||||
Object {
|
||||
"sort": Object {
|
||||
"direction": "asc",
|
||||
"field": "clientId",
|
||||
},
|
||||
}
|
||||
}
|
||||
tableLayout="fixed"
|
||||
/>
|
||||
`;
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
import React, { ReactElement } from 'react';
|
||||
import { shallow, ShallowWrapper } from 'enzyme';
|
||||
|
||||
import { Table, TableProps, TableState } from './table';
|
||||
import { TableWithoutPersist as Table } from './table';
|
||||
import { EuiTableFieldDataColumnType, keys } from '@elastic/eui';
|
||||
import { DataView } from '@kbn/data-views-plugin/public';
|
||||
import { SourceFiltersTableFilter } from '../../types';
|
||||
|
@ -20,10 +20,15 @@ const items: SourceFiltersTableFilter[] = [{ value: 'tim*', clientId: '' }];
|
|||
|
||||
const getIndexPatternMock = (mockedFields: any = {}) => ({ ...mockedFields } as DataView);
|
||||
|
||||
const getTableColumnRender = (
|
||||
component: ShallowWrapper<TableProps, TableState, Table>,
|
||||
index: number = 0
|
||||
) => {
|
||||
const baseProps = {
|
||||
euiTablePersist: {
|
||||
pageSize: 10,
|
||||
onTableChange: () => {},
|
||||
sorting: { sort: { direction: 'asc' as const, field: 'clientId' as const } },
|
||||
},
|
||||
};
|
||||
|
||||
const getTableColumnRender = (component: ShallowWrapper<typeof Table>, index: number = 0) => {
|
||||
const columns =
|
||||
component.prop<Array<EuiTableFieldDataColumnType<SourceFiltersTableFilter>>>('columns');
|
||||
return {
|
||||
|
@ -35,6 +40,7 @@ describe('Table', () => {
|
|||
test('should render normally', () => {
|
||||
const component = shallow(
|
||||
<Table
|
||||
{...baseProps}
|
||||
indexPattern={indexPattern}
|
||||
items={items}
|
||||
deleteFilter={() => {}}
|
||||
|
@ -48,8 +54,9 @@ describe('Table', () => {
|
|||
});
|
||||
|
||||
test('should render filter matches', () => {
|
||||
const component = shallow<Table>(
|
||||
const component = shallow<typeof Table>(
|
||||
<Table
|
||||
{...baseProps}
|
||||
indexPattern={getIndexPatternMock({
|
||||
getNonScriptedFields: () => [{ name: 'time' }, { name: 'value' }],
|
||||
})}
|
||||
|
@ -70,11 +77,12 @@ describe('Table', () => {
|
|||
describe('editing', () => {
|
||||
const saveFilter = jest.fn();
|
||||
const clientId = '1';
|
||||
let component: ShallowWrapper<TableProps, TableState, Table>;
|
||||
let component: ShallowWrapper<typeof Table>;
|
||||
|
||||
beforeEach(() => {
|
||||
component = shallow<Table>(
|
||||
component = shallow<typeof Table>(
|
||||
<Table
|
||||
{...baseProps}
|
||||
indexPattern={indexPattern}
|
||||
items={items}
|
||||
deleteFilter={() => {}}
|
||||
|
@ -125,6 +133,7 @@ describe('Table', () => {
|
|||
test('should update the matches dynamically as input value is changed', () => {
|
||||
const localComponent = shallow(
|
||||
<Table
|
||||
{...baseProps}
|
||||
indexPattern={getIndexPatternMock({
|
||||
getNonScriptedFields: () => [{ name: 'time' }, { name: 'value' }],
|
||||
})}
|
||||
|
@ -191,6 +200,7 @@ describe('Table', () => {
|
|||
|
||||
const component = shallow(
|
||||
<Table
|
||||
{...baseProps}
|
||||
indexPattern={indexPattern}
|
||||
items={items}
|
||||
deleteFilter={deleteFilter}
|
||||
|
@ -214,6 +224,7 @@ describe('Table', () => {
|
|||
|
||||
const component = shallow(
|
||||
<Table
|
||||
{...baseProps}
|
||||
indexPattern={indexPattern}
|
||||
items={items}
|
||||
deleteFilter={() => {}}
|
||||
|
@ -251,6 +262,7 @@ describe('Table', () => {
|
|||
|
||||
const component = shallow(
|
||||
<Table
|
||||
{...baseProps}
|
||||
indexPattern={indexPattern}
|
||||
items={items}
|
||||
deleteFilter={() => {}}
|
||||
|
|
|
@ -21,6 +21,11 @@ import {
|
|||
import { i18n } from '@kbn/i18n';
|
||||
import { FormattedMessage } from '@kbn/i18n-react';
|
||||
import { DataView } from '@kbn/data-views-plugin/public';
|
||||
import {
|
||||
withEuiTablePersist,
|
||||
type EuiTablePersistInjectedProps,
|
||||
} from '@kbn/shared-ux-table-persist';
|
||||
|
||||
import { SourceFiltersTableFilter } from '../../types';
|
||||
|
||||
const filterHeader = i18n.translate(
|
||||
|
@ -69,6 +74,8 @@ const cancelAria = i18n.translate(
|
|||
}
|
||||
);
|
||||
|
||||
const PAGE_SIZE_OPTIONS = [5, 10, 25, 50];
|
||||
|
||||
export interface TableProps {
|
||||
indexPattern: DataView;
|
||||
items: SourceFiltersTableFilter[];
|
||||
|
@ -83,8 +90,11 @@ export interface TableState {
|
|||
editingFilterValue: string;
|
||||
}
|
||||
|
||||
export class Table extends Component<TableProps, TableState> {
|
||||
constructor(props: TableProps) {
|
||||
class TableClass extends Component<
|
||||
TableProps & EuiTablePersistInjectedProps<SourceFiltersTableFilter>,
|
||||
TableState
|
||||
> {
|
||||
constructor(props: TableProps & EuiTablePersistInjectedProps<SourceFiltersTableFilter>) {
|
||||
super(props);
|
||||
this.state = {
|
||||
editingFilterId: '',
|
||||
|
@ -227,11 +237,15 @@ export class Table extends Component<TableProps, TableState> {
|
|||
}
|
||||
|
||||
render() {
|
||||
const { items, isSaving } = this.props;
|
||||
const {
|
||||
items,
|
||||
isSaving,
|
||||
euiTablePersist: { pageSize, sorting, onTableChange },
|
||||
} = this.props;
|
||||
const columns = this.getColumns();
|
||||
const pagination = {
|
||||
initialPageSize: 10,
|
||||
pageSizeOptions: [5, 10, 25, 50],
|
||||
pageSize,
|
||||
pageSizeOptions: PAGE_SIZE_OPTIONS,
|
||||
};
|
||||
|
||||
return (
|
||||
|
@ -240,8 +254,17 @@ export class Table extends Component<TableProps, TableState> {
|
|||
items={items}
|
||||
columns={columns}
|
||||
pagination={pagination}
|
||||
sorting={true}
|
||||
sorting={sorting}
|
||||
onTableChange={onTableChange}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export const TableWithoutPersist = TableClass; // For testing purposes
|
||||
|
||||
export const Table = withEuiTablePersist(TableClass, {
|
||||
tableId: 'dataViewsSourceFilters',
|
||||
pageSizeOptions: PAGE_SIZE_OPTIONS,
|
||||
initialPageSize: 10,
|
||||
});
|
||||
|
|
|
@ -30,6 +30,8 @@ import { NoDataViewsPromptComponent, useOnTryESQL } from '@kbn/shared-ux-prompt-
|
|||
import type { SpacesContextProps } from '@kbn/spaces-plugin/public';
|
||||
import { DataViewType } from '@kbn/data-views-plugin/public';
|
||||
import { RollupDeprecationTooltip } from '@kbn/rollup';
|
||||
import { useEuiTablePersist } from '@kbn/shared-ux-table-persist';
|
||||
|
||||
import type { IndexPatternManagmentContext } from '../../types';
|
||||
import { getListBreadcrumbs } from '../breadcrumbs';
|
||||
import { type RemoveDataViewProps, removeDataView } from '../edit_index_pattern';
|
||||
|
@ -42,10 +44,7 @@ import { deleteModalMsg } from './delete_modal_msg';
|
|||
import { NoData } from './no_data';
|
||||
import { SpacesList } from './spaces_list';
|
||||
|
||||
const pagination = {
|
||||
initialPageSize: 10,
|
||||
pageSizeOptions: [5, 10, 25, 50],
|
||||
};
|
||||
const PAGE_SIZE_OPTIONS = [5, 10, 25, 50];
|
||||
|
||||
const sorting = {
|
||||
sort: {
|
||||
|
@ -123,6 +122,12 @@ export const IndexPatternTable = ({
|
|||
};
|
||||
const onTryESQL = useOnTryESQL(useOnTryESQLParams);
|
||||
|
||||
const { pageSize, onTableChange } = useEuiTablePersist<IndexPatternTableItem>({
|
||||
tableId: 'dataViewsIndexPattern',
|
||||
initialPageSize: 10,
|
||||
pageSizeOptions: PAGE_SIZE_OPTIONS,
|
||||
});
|
||||
|
||||
const handleOnChange = ({ queryText, error }: { queryText: string; error: unknown }) => {
|
||||
if (!error) {
|
||||
setQuery(queryText);
|
||||
|
@ -361,8 +366,12 @@ export const IndexPatternTable = ({
|
|||
itemId="id"
|
||||
items={indexPatterns}
|
||||
columns={columns}
|
||||
pagination={pagination}
|
||||
pagination={{
|
||||
pageSize,
|
||||
pageSizeOptions: PAGE_SIZE_OPTIONS,
|
||||
}}
|
||||
sorting={sorting}
|
||||
onTableChange={onTableChange}
|
||||
search={search}
|
||||
selection={dataViews.getCanSaveSync() ? selection : undefined}
|
||||
/>
|
||||
|
|
|
@ -46,6 +46,7 @@
|
|||
"@kbn/react-kibana-mount",
|
||||
"@kbn/rollup",
|
||||
"@kbn/share-plugin",
|
||||
"@kbn/shared-ux-table-persist",
|
||||
],
|
||||
"exclude": [
|
||||
"target/**/*",
|
||||
|
|
|
@ -22,6 +22,7 @@ exports[`OpenSearchPanel render 1`] = `
|
|||
</EuiFlyoutHeader>
|
||||
<EuiFlyoutBody>
|
||||
<SavedObjectFinder
|
||||
id="discoverOpenSearch"
|
||||
noItemsMessage={
|
||||
<Memo(MemoizedFormattedMessage)
|
||||
defaultMessage="No matching searches found."
|
||||
|
|
|
@ -50,6 +50,7 @@ export function OpenSearchPanel(props: OpenSearchPanelProps) {
|
|||
</EuiFlyoutHeader>
|
||||
<EuiFlyoutBody>
|
||||
<SavedObjectFinder
|
||||
id="discoverOpenSearch"
|
||||
services={{
|
||||
savedObjectsTagging,
|
||||
contentClient,
|
||||
|
|
|
@ -197,6 +197,7 @@ export const AddPanelFlyout = ({
|
|||
</EuiFlyoutHeader>
|
||||
<EuiFlyoutBody>
|
||||
<SavedObjectFinder
|
||||
id="embeddableAddPanel"
|
||||
services={{
|
||||
contentClient: contentManagement.client,
|
||||
savedObjectsTagging: savedObjectsTaggingOss?.getTaggingApi(),
|
||||
|
|
|
@ -99,6 +99,7 @@ export const EventAnnotationGroupSavedObjectFinder = ({
|
|||
</EuiFlexGroup>
|
||||
) : (
|
||||
<SavedObjectFinder
|
||||
id="eventAnnotationGroup"
|
||||
key="searchSavedObjectFinder"
|
||||
fixedPageSize={fixedPageSize}
|
||||
onChoose={(id, type, fullName, savedObject) => {
|
||||
|
|
|
@ -12,10 +12,11 @@ import React from 'react';
|
|||
import { SavedObjectsTaggingApi } from '@kbn/saved-objects-tagging-oss-plugin/public';
|
||||
import type { ContentClient } from '@kbn/content-management-plugin/public';
|
||||
import type { IUiSettingsClient } from '@kbn/core-ui-settings-browser';
|
||||
import type { SavedObjectFinderProps } from './saved_object_finder';
|
||||
import type { HOCProps } from '@kbn/shared-ux-table-persist';
|
||||
import type { SavedObjectFinderItem, SavedObjectFinderProps } from './saved_object_finder';
|
||||
|
||||
const LazySavedObjectFinder = React.lazy(() => import('./saved_object_finder'));
|
||||
const SavedObjectFinder = (props: SavedObjectFinderProps) => (
|
||||
const SavedObjectFinder = (props: HOCProps<SavedObjectFinderItem, SavedObjectFinderProps>) => (
|
||||
<React.Suspense
|
||||
fallback={
|
||||
<EuiDelayRender delay={300}>
|
||||
|
@ -32,7 +33,7 @@ export const getSavedObjectFinder = (
|
|||
uiSettings: IUiSettingsClient,
|
||||
savedObjectsTagging?: SavedObjectsTaggingApi
|
||||
) => {
|
||||
return (props: SavedObjectFinderProps) => (
|
||||
return (props: HOCProps<SavedObjectFinderItem, SavedObjectFinderProps>) => (
|
||||
<SavedObjectFinder {...props} services={{ savedObjectsTagging, contentClient, uiSettings }} />
|
||||
);
|
||||
};
|
||||
|
|
|
@ -28,7 +28,10 @@ import { IconType } from '@elastic/eui';
|
|||
import { mount, shallow } from 'enzyme';
|
||||
import React from 'react';
|
||||
import * as sinon from 'sinon';
|
||||
import { SavedObjectFinderUi as SavedObjectFinder } from './saved_object_finder';
|
||||
import {
|
||||
SavedObjectFinderWithoutPersist as SavedObjectFinder,
|
||||
SavedObjectFinderUi,
|
||||
} from './saved_object_finder';
|
||||
import { contentManagementMock } from '@kbn/content-management-plugin/public/mocks';
|
||||
import { findTestSubject } from '@kbn/test-jest-helpers';
|
||||
import { SavedObjectsTaggingApi } from '@kbn/saved-objects-tagging-oss-plugin/public';
|
||||
|
@ -72,6 +75,15 @@ describe('SavedObjectsFinder', () => {
|
|||
},
|
||||
];
|
||||
|
||||
const baseProps = {
|
||||
id: 'foo',
|
||||
euiTablePersist: {
|
||||
pageSize: 10,
|
||||
onTableChange: () => {},
|
||||
sorting: { sort: { direction: 'asc' as const, field: 'title' as const } },
|
||||
},
|
||||
};
|
||||
|
||||
const contentManagement = contentManagementMock.createStartContract();
|
||||
const contentClient = contentManagement.client;
|
||||
beforeEach(() => {
|
||||
|
@ -109,6 +121,7 @@ describe('SavedObjectsFinder', () => {
|
|||
|
||||
const wrapper = shallow(
|
||||
<SavedObjectFinder
|
||||
{...baseProps}
|
||||
services={{
|
||||
uiSettings,
|
||||
contentClient,
|
||||
|
@ -134,6 +147,7 @@ describe('SavedObjectsFinder', () => {
|
|||
|
||||
const wrapper = shallow(
|
||||
<SavedObjectFinder
|
||||
{...baseProps}
|
||||
services={{ uiSettings, contentClient, savedObjectsTagging }}
|
||||
savedObjectMetaData={searchMetaData}
|
||||
/>
|
||||
|
@ -157,6 +171,7 @@ describe('SavedObjectsFinder', () => {
|
|||
|
||||
const wrapper = mount(
|
||||
<SavedObjectFinder
|
||||
{...baseProps}
|
||||
services={{ uiSettings, contentClient, savedObjectsTagging }}
|
||||
onChoose={chooseStub}
|
||||
savedObjectMetaData={searchMetaData}
|
||||
|
@ -179,6 +194,7 @@ describe('SavedObjectsFinder', () => {
|
|||
|
||||
const wrapper = shallow(
|
||||
<SavedObjectFinder
|
||||
{...baseProps}
|
||||
services={{ uiSettings, contentClient, savedObjectsTagging }}
|
||||
savedObjectMetaData={searchMetaData}
|
||||
helpText="This is some description about the action"
|
||||
|
@ -199,6 +215,7 @@ describe('SavedObjectsFinder', () => {
|
|||
const button = <EuiButton>Hello</EuiButton>;
|
||||
const wrapper = shallow(
|
||||
<SavedObjectFinder
|
||||
{...baseProps}
|
||||
services={{ uiSettings, contentClient, savedObjectsTagging }}
|
||||
savedObjectMetaData={searchMetaData}
|
||||
leftChildren={button}
|
||||
|
@ -227,6 +244,7 @@ describe('SavedObjectsFinder', () => {
|
|||
|
||||
const wrapper = mount(
|
||||
<SavedObjectFinder
|
||||
{...baseProps}
|
||||
services={{ uiSettings, contentClient, savedObjectsTagging }}
|
||||
savedObjectMetaData={metaDataConfig}
|
||||
/>
|
||||
|
@ -251,6 +269,7 @@ describe('SavedObjectsFinder', () => {
|
|||
|
||||
const wrapper = mount(
|
||||
<SavedObjectFinder
|
||||
{...baseProps}
|
||||
services={{ uiSettings, contentClient, savedObjectsTagging }}
|
||||
savedObjectMetaData={metaDataConfig}
|
||||
/>
|
||||
|
@ -279,6 +298,7 @@ describe('SavedObjectsFinder', () => {
|
|||
|
||||
const wrapper = mount(
|
||||
<SavedObjectFinder
|
||||
{...baseProps}
|
||||
services={{ uiSettings, contentClient, savedObjectsTagging }}
|
||||
savedObjectMetaData={searchMetaData}
|
||||
/>
|
||||
|
@ -299,6 +319,7 @@ describe('SavedObjectsFinder', () => {
|
|||
|
||||
const wrapper = mount(
|
||||
<SavedObjectFinder
|
||||
{...baseProps}
|
||||
services={{ uiSettings, contentClient, savedObjectsTagging }}
|
||||
savedObjectMetaData={searchMetaData}
|
||||
/>
|
||||
|
@ -322,6 +343,7 @@ describe('SavedObjectsFinder', () => {
|
|||
|
||||
const wrapper = mount(
|
||||
<SavedObjectFinder
|
||||
{...baseProps}
|
||||
services={{ uiSettings, contentClient, savedObjectsTagging }}
|
||||
savedObjectMetaData={metaDataConfig}
|
||||
/>
|
||||
|
@ -346,6 +368,7 @@ describe('SavedObjectsFinder', () => {
|
|||
|
||||
const wrapper = mount(
|
||||
<SavedObjectFinder
|
||||
{...baseProps}
|
||||
services={{ uiSettings, contentClient, savedObjectsTagging }}
|
||||
savedObjectMetaData={metaDataConfig}
|
||||
/>
|
||||
|
@ -375,6 +398,7 @@ describe('SavedObjectsFinder', () => {
|
|||
|
||||
const wrapper = shallow(
|
||||
<SavedObjectFinder
|
||||
{...baseProps}
|
||||
services={{ uiSettings, contentClient, savedObjectsTagging }}
|
||||
savedObjectMetaData={[
|
||||
{
|
||||
|
@ -402,6 +426,7 @@ describe('SavedObjectsFinder', () => {
|
|||
|
||||
const wrapper = mount(
|
||||
<SavedObjectFinder
|
||||
{...baseProps}
|
||||
services={{ uiSettings, contentClient, savedObjectsTagging }}
|
||||
savedObjectMetaData={searchMetaData}
|
||||
/>
|
||||
|
@ -430,6 +455,7 @@ describe('SavedObjectsFinder', () => {
|
|||
|
||||
const wrapper = mount(
|
||||
<SavedObjectFinder
|
||||
{...baseProps}
|
||||
services={{ uiSettings, contentClient, savedObjectsTagging }}
|
||||
savedObjectMetaData={searchMetaData}
|
||||
/>
|
||||
|
@ -453,6 +479,7 @@ describe('SavedObjectsFinder', () => {
|
|||
|
||||
const wrapper = shallow(
|
||||
<SavedObjectFinder
|
||||
{...baseProps}
|
||||
services={{ uiSettings, contentClient, savedObjectsTagging }}
|
||||
savedObjectMetaData={[
|
||||
{
|
||||
|
@ -492,6 +519,7 @@ describe('SavedObjectsFinder', () => {
|
|||
|
||||
const wrapper = mount(
|
||||
<SavedObjectFinder
|
||||
{...baseProps}
|
||||
services={{ uiSettings, contentClient, savedObjectsTagging }}
|
||||
showFilter={true}
|
||||
savedObjectMetaData={metaDataConfig}
|
||||
|
@ -512,6 +540,7 @@ describe('SavedObjectsFinder', () => {
|
|||
|
||||
const wrapper = mount(
|
||||
<SavedObjectFinder
|
||||
{...baseProps}
|
||||
services={{ uiSettings, contentClient, savedObjectsTagging }}
|
||||
showFilter={false}
|
||||
savedObjectMetaData={metaDataConfig}
|
||||
|
@ -530,6 +559,7 @@ describe('SavedObjectsFinder', () => {
|
|||
|
||||
const wrapper = mount(
|
||||
<SavedObjectFinder
|
||||
{...baseProps}
|
||||
services={{ uiSettings, contentClient, savedObjectsTagging }}
|
||||
showFilter={true}
|
||||
savedObjectMetaData={searchMetaData}
|
||||
|
@ -549,6 +579,7 @@ describe('SavedObjectsFinder', () => {
|
|||
|
||||
const wrapper = mount(
|
||||
<SavedObjectFinder
|
||||
{...baseProps}
|
||||
services={{ uiSettings, contentClient, savedObjectsTagging: undefined }}
|
||||
showFilter={true}
|
||||
savedObjectMetaData={metaDataConfig}
|
||||
|
@ -568,6 +599,7 @@ describe('SavedObjectsFinder', () => {
|
|||
|
||||
const wrapper = mount(
|
||||
<SavedObjectFinder
|
||||
{...baseProps}
|
||||
services={{ uiSettings, contentClient, savedObjectsTagging }}
|
||||
showFilter={true}
|
||||
savedObjectMetaData={metaDataConfig}
|
||||
|
@ -608,6 +640,7 @@ describe('SavedObjectsFinder', () => {
|
|||
|
||||
const wrapper = mount(
|
||||
<SavedObjectFinder
|
||||
{...baseProps}
|
||||
services={{ uiSettings, contentClient, savedObjectsTagging }}
|
||||
showFilter={true}
|
||||
savedObjectMetaData={metaDataConfig}
|
||||
|
@ -665,6 +698,7 @@ describe('SavedObjectsFinder', () => {
|
|||
const noItemsMessage = <span id="myNoItemsMessage" />;
|
||||
const wrapper = mount(
|
||||
<SavedObjectFinder
|
||||
{...baseProps}
|
||||
services={{ uiSettings, contentClient, savedObjectsTagging }}
|
||||
noItemsMessage={noItemsMessage}
|
||||
savedObjectMetaData={searchMetaData}
|
||||
|
@ -693,6 +727,11 @@ describe('SavedObjectsFinder', () => {
|
|||
|
||||
const wrapper = mount(
|
||||
<SavedObjectFinder
|
||||
id="foo"
|
||||
euiTablePersist={{
|
||||
...baseProps.euiTablePersist,
|
||||
pageSize: 15,
|
||||
}}
|
||||
services={{ uiSettings, contentClient, savedObjectsTagging }}
|
||||
initialPageSize={15}
|
||||
savedObjectMetaData={searchMetaData}
|
||||
|
@ -715,6 +754,11 @@ describe('SavedObjectsFinder', () => {
|
|||
|
||||
const wrapper = mount(
|
||||
<SavedObjectFinder
|
||||
id="foo"
|
||||
euiTablePersist={{
|
||||
...baseProps.euiTablePersist,
|
||||
pageSize: 5,
|
||||
}}
|
||||
services={{ uiSettings, contentClient, savedObjectsTagging }}
|
||||
initialPageSize={15}
|
||||
savedObjectMetaData={searchMetaData}
|
||||
|
@ -742,14 +786,14 @@ describe('SavedObjectsFinder', () => {
|
|||
);
|
||||
|
||||
const wrapper = mount(
|
||||
<SavedObjectFinder
|
||||
<SavedObjectFinderUi
|
||||
id="foo"
|
||||
services={{ uiSettings, contentClient, savedObjectsTagging }}
|
||||
initialPageSize={15}
|
||||
savedObjectMetaData={searchMetaData}
|
||||
/>
|
||||
);
|
||||
|
||||
wrapper.instance().componentDidMount!();
|
||||
await nextTick();
|
||||
wrapper.update();
|
||||
expect(wrapper.find(EuiInMemoryTable).find('tbody tr')).toHaveLength(15);
|
||||
|
@ -774,6 +818,7 @@ describe('SavedObjectsFinder', () => {
|
|||
|
||||
const wrapper = mount(
|
||||
<SavedObjectFinder
|
||||
{...baseProps}
|
||||
services={{ uiSettings, contentClient, savedObjectsTagging }}
|
||||
fixedPageSize={33}
|
||||
savedObjectMetaData={searchMetaData}
|
||||
|
@ -796,6 +841,7 @@ describe('SavedObjectsFinder', () => {
|
|||
|
||||
const wrapper = mount(
|
||||
<SavedObjectFinder
|
||||
{...baseProps}
|
||||
services={{ uiSettings, contentClient, savedObjectsTagging }}
|
||||
fixedPageSize={33}
|
||||
savedObjectMetaData={searchMetaData}
|
||||
|
@ -827,6 +873,7 @@ describe('SavedObjectsFinder', () => {
|
|||
|
||||
const wrapper = mount(
|
||||
<SavedObjectFinder
|
||||
{...baseProps}
|
||||
services={{ uiSettings, contentClient, savedObjectsTagging }}
|
||||
savedObjectMetaData={searchMetaData}
|
||||
/>
|
||||
|
@ -840,6 +887,7 @@ describe('SavedObjectsFinder', () => {
|
|||
|
||||
const wrapper = mount(
|
||||
<SavedObjectFinder
|
||||
{...baseProps}
|
||||
services={{ uiSettings, contentClient, savedObjectsTagging }}
|
||||
savedObjectMetaData={[
|
||||
{
|
||||
|
@ -862,6 +910,7 @@ describe('SavedObjectsFinder', () => {
|
|||
|
||||
const wrapper = mount(
|
||||
<SavedObjectFinder
|
||||
{...baseProps}
|
||||
services={{ uiSettings, contentClient, savedObjectsTagging }}
|
||||
savedObjectMetaData={searchMetaData}
|
||||
/>
|
||||
|
@ -884,6 +933,7 @@ describe('SavedObjectsFinder', () => {
|
|||
|
||||
const wrapper = mount(
|
||||
<SavedObjectFinder
|
||||
{...baseProps}
|
||||
services={{ uiSettings, contentClient, savedObjectsTagging }}
|
||||
savedObjectMetaData={[
|
||||
{
|
||||
|
@ -912,6 +962,7 @@ describe('SavedObjectsFinder', () => {
|
|||
|
||||
const wrapper = mount(
|
||||
<SavedObjectFinder
|
||||
{...baseProps}
|
||||
services={{ uiSettings, contentClient, savedObjectsTagging }}
|
||||
savedObjectMetaData={metaDataConfig}
|
||||
/>
|
||||
|
@ -933,6 +984,7 @@ describe('SavedObjectsFinder', () => {
|
|||
|
||||
const wrapper = mount(
|
||||
<SavedObjectFinder
|
||||
{...baseProps}
|
||||
services={{ uiSettings, savedObjectsTagging, contentClient }}
|
||||
savedObjectMetaData={searchMetaData}
|
||||
/>
|
||||
|
@ -954,6 +1006,7 @@ describe('SavedObjectsFinder', () => {
|
|||
|
||||
const wrapper = mount(
|
||||
<SavedObjectFinder
|
||||
{...baseProps}
|
||||
services={{ uiSettings, contentClient, savedObjectsTagging: undefined }}
|
||||
savedObjectMetaData={metaDataConfig}
|
||||
/>
|
||||
|
@ -978,6 +1031,7 @@ describe('SavedObjectsFinder', () => {
|
|||
|
||||
render(
|
||||
<SavedObjectFinder
|
||||
{...baseProps}
|
||||
services={{ uiSettings, contentClient, savedObjectsTagging }}
|
||||
savedObjectMetaData={metaDataConfig}
|
||||
getTooltipText={(item) => (item.id === doc3.id ? tooltipText : undefined)}
|
||||
|
@ -990,7 +1044,7 @@ describe('SavedObjectsFinder', () => {
|
|||
|
||||
const tooltip = screen.queryByText(tooltipText);
|
||||
if (show) {
|
||||
expect(tooltip).toBeInTheDocument();
|
||||
expect(tooltip)?.toBeInTheDocument();
|
||||
} else {
|
||||
expect(tooltip).toBeNull();
|
||||
}
|
||||
|
|
|
@ -25,15 +25,21 @@ import {
|
|||
EuiToolTip,
|
||||
EuiIconTip,
|
||||
IconType,
|
||||
PropertySort,
|
||||
Query,
|
||||
SearchFilterConfig,
|
||||
} from '@elastic/eui';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
|
||||
import type { SavedObjectsTaggingApi } from '@kbn/saved-objects-tagging-oss-plugin/public';
|
||||
import {
|
||||
withEuiTablePersist,
|
||||
type EuiTablePersistInjectedProps,
|
||||
} from '@kbn/shared-ux-table-persist/src';
|
||||
|
||||
import { FinderAttributes, SavedObjectCommon, LISTING_LIMIT_SETTING } from '../../common';
|
||||
|
||||
const PAGE_SIZE_OPTIONS = [5, 10, 15, 25];
|
||||
|
||||
export interface SavedObjectMetaData<T extends FinderAttributes = FinderAttributes> {
|
||||
type: string;
|
||||
name: string;
|
||||
|
@ -45,7 +51,7 @@ export interface SavedObjectMetaData<T extends FinderAttributes = FinderAttribut
|
|||
includeFields?: string[];
|
||||
}
|
||||
|
||||
interface SavedObjectFinderItem extends SavedObjectCommon {
|
||||
export interface SavedObjectFinderItem extends SavedObjectCommon {
|
||||
title: string | null;
|
||||
name: string | null;
|
||||
simple: SavedObjectCommon<FinderAttributes>;
|
||||
|
@ -55,7 +61,6 @@ interface SavedObjectFinderState {
|
|||
items: SavedObjectFinderItem[];
|
||||
query: Query;
|
||||
isFetchingItems: boolean;
|
||||
sort?: PropertySort;
|
||||
}
|
||||
|
||||
interface SavedObjectFinderServices {
|
||||
|
@ -65,6 +70,7 @@ interface SavedObjectFinderServices {
|
|||
}
|
||||
|
||||
interface BaseSavedObjectFinder {
|
||||
id: string;
|
||||
services: SavedObjectFinderServices;
|
||||
onChoose?: (
|
||||
id: SavedObjectCommon['id'],
|
||||
|
@ -93,8 +99,8 @@ interface SavedObjectFinderInitialPageSize extends BaseSavedObjectFinder {
|
|||
|
||||
export type SavedObjectFinderProps = SavedObjectFinderFixedPage | SavedObjectFinderInitialPageSize;
|
||||
|
||||
export class SavedObjectFinderUi extends React.Component<
|
||||
SavedObjectFinderProps,
|
||||
class SavedObjectFinderUiClass extends React.Component<
|
||||
SavedObjectFinderProps & EuiTablePersistInjectedProps<SavedObjectFinderItem>,
|
||||
SavedObjectFinderState
|
||||
> {
|
||||
public static propTypes = {
|
||||
|
@ -174,7 +180,7 @@ export class SavedObjectFinderUi extends React.Component<
|
|||
}
|
||||
}, 300);
|
||||
|
||||
constructor(props: SavedObjectFinderProps) {
|
||||
constructor(props: SavedObjectFinderProps & EuiTablePersistInjectedProps<SavedObjectFinderItem>) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
|
@ -211,7 +217,11 @@ export class SavedObjectFinderUi extends React.Component<
|
|||
};
|
||||
|
||||
public render() {
|
||||
const { onChoose, savedObjectMetaData } = this.props;
|
||||
const {
|
||||
onChoose,
|
||||
savedObjectMetaData,
|
||||
euiTablePersist: { pageSize, sorting, onTableChange },
|
||||
} = this.props;
|
||||
const taggingApi = this.props.services.savedObjectsTagging;
|
||||
const originalTagColumn = taggingApi?.ui.getTableColumnDefinition();
|
||||
const tagColumn: EuiTableFieldDataColumnType<SavedObjectCommon> | undefined = originalTagColumn
|
||||
|
@ -320,16 +330,11 @@ export class SavedObjectFinderUi extends React.Component<
|
|||
...(tagColumn ? [tagColumn] : []),
|
||||
];
|
||||
const pagination = {
|
||||
initialPageSize: this.props.initialPageSize || this.props.fixedPageSize || 10,
|
||||
pageSizeOptions: [5, 10, 15, 25],
|
||||
initialPageSize: !!this.props.fixedPageSize ? this.props.fixedPageSize : pageSize ?? 10,
|
||||
pageSize: !!this.props.fixedPageSize ? undefined : pageSize,
|
||||
pageSizeOptions: PAGE_SIZE_OPTIONS,
|
||||
showPerPageOptions: !this.props.fixedPageSize,
|
||||
};
|
||||
const sorting = {
|
||||
sort: this.state.sort ?? {
|
||||
field: this.state.query?.text ? '' : 'title',
|
||||
direction: 'asc',
|
||||
},
|
||||
};
|
||||
const typeFilter: SearchFilterConfig = {
|
||||
type: 'field_value_selection',
|
||||
field: 'type',
|
||||
|
@ -382,10 +387,8 @@ export class SavedObjectFinderUi extends React.Component<
|
|||
message={this.props.noItemsMessage}
|
||||
search={search}
|
||||
pagination={pagination}
|
||||
sorting={sorting}
|
||||
onTableChange={({ sort }) => {
|
||||
this.setState({ sort });
|
||||
}}
|
||||
sorting={!!this.state.query?.text ? undefined : sorting}
|
||||
onTableChange={onTableChange}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
|
@ -393,6 +396,16 @@ export class SavedObjectFinderUi extends React.Component<
|
|||
}
|
||||
}
|
||||
|
||||
export const SavedObjectFinderUi = withEuiTablePersist(SavedObjectFinderUiClass, {
|
||||
get: (props) => ({
|
||||
tableId: `soFinder-${props.id}`,
|
||||
pageSizeOptions: PAGE_SIZE_OPTIONS,
|
||||
initialPageSize: props.initialPageSize ?? props.fixedPageSize ?? 10,
|
||||
}),
|
||||
});
|
||||
|
||||
export const SavedObjectFinderWithoutPersist = SavedObjectFinderUiClass; // For testing
|
||||
|
||||
// Needed for React.lazy
|
||||
// eslint-disable-next-line import/no-default-export
|
||||
export default SavedObjectFinderUi;
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
"@kbn/content-management-plugin",
|
||||
"@kbn/content-management-utils",
|
||||
"@kbn/core-ui-settings-browser",
|
||||
"@kbn/shared-ux-table-persist",
|
||||
],
|
||||
"exclude": [
|
||||
"target/**/*",
|
||||
|
|
|
@ -102,7 +102,6 @@ exports[`Flyout conflicts should allow conflict resolution 1`] = `
|
|||
onTableChange={[Function]}
|
||||
pagination={
|
||||
Object {
|
||||
"pageIndex": 0,
|
||||
"pageSize": 5,
|
||||
"pageSizeOptions": Array [
|
||||
5,
|
||||
|
@ -251,10 +250,6 @@ exports[`Flyout conflicts should allow conflict resolution 2`] = `
|
|||
"newIndexPatternId": "2",
|
||||
},
|
||||
],
|
||||
"unmatchedReferencesTablePagination": Object {
|
||||
"pageIndex": 0,
|
||||
"pageSize": 5,
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
|
|
|
@ -110,7 +110,12 @@ exports[`Relationships should render dashboards normally 1`] = `
|
|||
},
|
||||
]
|
||||
}
|
||||
pagination={true}
|
||||
onTableChange={[Function]}
|
||||
pagination={
|
||||
Object {
|
||||
"pageSize": 10,
|
||||
}
|
||||
}
|
||||
rowProps={[Function]}
|
||||
search={
|
||||
Object {
|
||||
|
@ -310,7 +315,12 @@ exports[`Relationships should render index patterns normally 1`] = `
|
|||
},
|
||||
]
|
||||
}
|
||||
pagination={true}
|
||||
onTableChange={[Function]}
|
||||
pagination={
|
||||
Object {
|
||||
"pageSize": 10,
|
||||
}
|
||||
}
|
||||
rowProps={[Function]}
|
||||
search={
|
||||
Object {
|
||||
|
@ -501,7 +511,12 @@ exports[`Relationships should render invalid relations 1`] = `
|
|||
]
|
||||
}
|
||||
items={Array []}
|
||||
pagination={true}
|
||||
onTableChange={[Function]}
|
||||
pagination={
|
||||
Object {
|
||||
"pageSize": 10,
|
||||
}
|
||||
}
|
||||
rowProps={[Function]}
|
||||
search={
|
||||
Object {
|
||||
|
@ -652,7 +667,12 @@ exports[`Relationships should render searches normally 1`] = `
|
|||
},
|
||||
]
|
||||
}
|
||||
pagination={true}
|
||||
onTableChange={[Function]}
|
||||
pagination={
|
||||
Object {
|
||||
"pageSize": 10,
|
||||
}
|
||||
}
|
||||
rowProps={[Function]}
|
||||
search={
|
||||
Object {
|
||||
|
@ -813,7 +833,12 @@ exports[`Relationships should render visualizations normally 1`] = `
|
|||
},
|
||||
]
|
||||
}
|
||||
pagination={true}
|
||||
onTableChange={[Function]}
|
||||
pagination={
|
||||
Object {
|
||||
"pageSize": 10,
|
||||
}
|
||||
}
|
||||
rowProps={[Function]}
|
||||
search={
|
||||
Object {
|
||||
|
|
|
@ -12,7 +12,7 @@ import { importFileMock, resolveImportErrorsMock } from './flyout.test.mocks';
|
|||
import React from 'react';
|
||||
import { shallowWithI18nProvider } from '@kbn/test-jest-helpers';
|
||||
import { coreMock, httpServiceMock } from '@kbn/core/public/mocks';
|
||||
import { Flyout, FlyoutProps, FlyoutState } from './flyout';
|
||||
import { FlyoutClass as Flyout, FlyoutProps, FlyoutState } from './flyout';
|
||||
import { ShallowWrapper } from 'enzyme';
|
||||
import { dataPluginMock } from '@kbn/data-plugin/public/mocks';
|
||||
|
||||
|
@ -21,15 +21,21 @@ const mockFile = {
|
|||
path: '/home/foo.ndjson',
|
||||
} as unknown as File;
|
||||
|
||||
const baseProps = {
|
||||
euiTablePersist: {
|
||||
pageSize: 5,
|
||||
onTableChange: () => {},
|
||||
sorting: { sort: { direction: 'asc' as const, field: 'foo' as const } },
|
||||
},
|
||||
};
|
||||
|
||||
describe('Flyout', () => {
|
||||
let defaultProps: FlyoutProps;
|
||||
|
||||
const shallowRender = (props: FlyoutProps) => {
|
||||
return shallowWithI18nProvider(<Flyout {...props} />) as unknown as ShallowWrapper<
|
||||
FlyoutProps,
|
||||
FlyoutState,
|
||||
Flyout
|
||||
>;
|
||||
return shallowWithI18nProvider(
|
||||
<Flyout {...baseProps} {...props} />
|
||||
) as unknown as ShallowWrapper<FlyoutProps, FlyoutState, Flyout>;
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
|
|
|
@ -36,6 +36,10 @@ import { FormattedMessage } from '@kbn/i18n-react';
|
|||
import { HttpStart, IBasePath } from '@kbn/core/public';
|
||||
import { ISearchStart } from '@kbn/data-plugin/public';
|
||||
import type { DataViewsContract, DataView } from '@kbn/data-views-plugin/public';
|
||||
import {
|
||||
withEuiTablePersist,
|
||||
type EuiTablePersistInjectedProps,
|
||||
} from '@kbn/shared-ux-table-persist';
|
||||
import type { SavedObjectManagementTypeInfo } from '../../../../common/types';
|
||||
import {
|
||||
importFile,
|
||||
|
@ -50,6 +54,7 @@ import { ImportSummary } from './import_summary';
|
|||
|
||||
const CREATE_NEW_COPIES_DEFAULT = false;
|
||||
const OVERWRITE_ALL_DEFAULT = true;
|
||||
const PAGE_SIZE_OPTIONS = [5, 10, 25];
|
||||
|
||||
export interface FlyoutProps {
|
||||
close: () => void;
|
||||
|
@ -65,7 +70,6 @@ export interface FlyoutProps {
|
|||
|
||||
export interface FlyoutState {
|
||||
unmatchedReferences?: ProcessedImportResponse['unmatchedReferences'];
|
||||
unmatchedReferencesTablePagination: { pageIndex: number; pageSize: number };
|
||||
failedImports?: ProcessedImportResponse['failedImports'];
|
||||
successfulImports?: ProcessedImportResponse['successfulImports'];
|
||||
conflictingRecord?: ConflictingRecord;
|
||||
|
@ -95,16 +99,15 @@ const getErrorMessage = (e: any) => {
|
|||
});
|
||||
};
|
||||
|
||||
export class Flyout extends Component<FlyoutProps, FlyoutState> {
|
||||
constructor(props: FlyoutProps) {
|
||||
export class FlyoutClass extends Component<
|
||||
FlyoutProps & EuiTablePersistInjectedProps<any>,
|
||||
FlyoutState
|
||||
> {
|
||||
constructor(props: FlyoutProps & EuiTablePersistInjectedProps<unknown>) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
unmatchedReferences: undefined,
|
||||
unmatchedReferencesTablePagination: {
|
||||
pageIndex: 0,
|
||||
pageSize: 5,
|
||||
},
|
||||
conflictingRecord: undefined,
|
||||
error: undefined,
|
||||
file: undefined,
|
||||
|
@ -275,7 +278,10 @@ export class Flyout extends Component<FlyoutProps, FlyoutState> {
|
|||
};
|
||||
|
||||
renderUnmatchedReferences() {
|
||||
const { unmatchedReferences, unmatchedReferencesTablePagination: tablePagination } = this.state;
|
||||
const { unmatchedReferences } = this.state;
|
||||
const {
|
||||
euiTablePersist: { pageSize, onTableChange },
|
||||
} = this.props;
|
||||
|
||||
if (!unmatchedReferences) {
|
||||
return null;
|
||||
|
@ -367,8 +373,8 @@ export class Flyout extends Component<FlyoutProps, FlyoutState> {
|
|||
];
|
||||
|
||||
const pagination = {
|
||||
...tablePagination,
|
||||
pageSizeOptions: [5, 10, 25],
|
||||
pageSize,
|
||||
pageSizeOptions: PAGE_SIZE_OPTIONS,
|
||||
};
|
||||
|
||||
return (
|
||||
|
@ -376,16 +382,7 @@ export class Flyout extends Component<FlyoutProps, FlyoutState> {
|
|||
items={unmatchedReferences as any[]}
|
||||
columns={columns}
|
||||
pagination={pagination}
|
||||
onTableChange={({ page }) => {
|
||||
if (page) {
|
||||
this.setState({
|
||||
unmatchedReferencesTablePagination: {
|
||||
pageSize: page.size,
|
||||
pageIndex: page.index,
|
||||
},
|
||||
});
|
||||
}
|
||||
}}
|
||||
onTableChange={onTableChange}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
@ -657,3 +654,9 @@ export class Flyout extends Component<FlyoutProps, FlyoutState> {
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
export const Flyout = withEuiTablePersist(FlyoutClass, {
|
||||
tableId: 'savedObjectsMgmtUnmatchedReferences',
|
||||
pageSizeOptions: PAGE_SIZE_OPTIONS,
|
||||
initialPageSize: 5,
|
||||
});
|
||||
|
|
|
@ -11,7 +11,7 @@ import React from 'react';
|
|||
import { shallowWithI18nProvider } from '@kbn/test-jest-helpers';
|
||||
import { httpServiceMock } from '@kbn/core/public/mocks';
|
||||
import type { SavedObjectManagementTypeInfo } from '../../../../common/types';
|
||||
import { Relationships, RelationshipsProps } from './relationships';
|
||||
import { RelationshipsClass as Relationships, RelationshipsProps } from './relationships';
|
||||
|
||||
jest.mock('../../../lib/fetch_export_by_type_and_search', () => ({
|
||||
fetchExportByTypeAndSearch: jest.fn(),
|
||||
|
@ -21,6 +21,14 @@ jest.mock('../../../lib/fetch_export_objects', () => ({
|
|||
fetchExportObjects: jest.fn(),
|
||||
}));
|
||||
|
||||
const baseProps = {
|
||||
euiTablePersist: {
|
||||
pageSize: 10,
|
||||
onTableChange: () => {},
|
||||
sorting: { sort: { direction: 'asc' as const, field: 'id' as const } },
|
||||
},
|
||||
};
|
||||
|
||||
const allowedTypes: SavedObjectManagementTypeInfo[] = [
|
||||
{
|
||||
name: 'index-pattern',
|
||||
|
@ -86,7 +94,7 @@ describe('Relationships', () => {
|
|||
close: jest.fn(),
|
||||
};
|
||||
|
||||
const component = shallowWithI18nProvider(<Relationships {...props} />);
|
||||
const component = shallowWithI18nProvider(<Relationships {...baseProps} {...props} />);
|
||||
|
||||
// Make sure we are showing loading
|
||||
expect(component.find('EuiLoadingElastic').length).toBe(1);
|
||||
|
@ -155,7 +163,7 @@ describe('Relationships', () => {
|
|||
close: jest.fn(),
|
||||
};
|
||||
|
||||
const component = shallowWithI18nProvider(<Relationships {...props} />);
|
||||
const component = shallowWithI18nProvider(<Relationships {...baseProps} {...props} />);
|
||||
|
||||
// Make sure we are showing loading
|
||||
expect(component.find('EuiLoadingElastic').length).toBe(1);
|
||||
|
@ -223,7 +231,7 @@ describe('Relationships', () => {
|
|||
close: jest.fn(),
|
||||
};
|
||||
|
||||
const component = shallowWithI18nProvider(<Relationships {...props} />);
|
||||
const component = shallowWithI18nProvider(<Relationships {...baseProps} {...props} />);
|
||||
|
||||
// Make sure we are showing loading
|
||||
expect(component.find('EuiLoadingElastic').length).toBe(1);
|
||||
|
@ -292,7 +300,7 @@ describe('Relationships', () => {
|
|||
showPlainSpinner: true,
|
||||
};
|
||||
|
||||
const component = shallowWithI18nProvider(<Relationships {...props} />);
|
||||
const component = shallowWithI18nProvider(<Relationships {...baseProps} {...props} />);
|
||||
|
||||
// Make sure we are showing loading
|
||||
expect(component.find('EuiLoadingSpinner').length).toBe(1);
|
||||
|
@ -332,7 +340,7 @@ describe('Relationships', () => {
|
|||
close: jest.fn(),
|
||||
};
|
||||
|
||||
const component = shallowWithI18nProvider(<Relationships {...props} />);
|
||||
const component = shallowWithI18nProvider(<Relationships {...baseProps} {...props} />);
|
||||
|
||||
// Ensure all promises resolve
|
||||
await new Promise((resolve) => process.nextTick(resolve));
|
||||
|
@ -378,7 +386,7 @@ describe('Relationships', () => {
|
|||
close: jest.fn(),
|
||||
};
|
||||
|
||||
const component = shallowWithI18nProvider(<Relationships {...props} />);
|
||||
const component = shallowWithI18nProvider(<Relationships {...baseProps} {...props} />);
|
||||
|
||||
// Ensure all promises resolve
|
||||
await new Promise((resolve) => process.nextTick(resolve));
|
||||
|
|
|
@ -27,6 +27,10 @@ import { SearchFilterConfig } from '@elastic/eui';
|
|||
import { i18n } from '@kbn/i18n';
|
||||
import { FormattedMessage } from '@kbn/i18n-react';
|
||||
import { IBasePath } from '@kbn/core/public';
|
||||
import {
|
||||
withEuiTablePersist,
|
||||
type EuiTablePersistInjectedProps,
|
||||
} from '@kbn/shared-ux-table-persist';
|
||||
import type { SavedObjectManagementTypeInfo } from '../../../../common/types';
|
||||
import { getDefaultTitle, getSavedObjectLabel } from '../../../lib';
|
||||
import type { v1 } from '../../../../common';
|
||||
|
@ -83,8 +87,11 @@ const relationshipColumn = {
|
|||
},
|
||||
};
|
||||
|
||||
export class Relationships extends Component<RelationshipsProps, RelationshipsState> {
|
||||
constructor(props: RelationshipsProps) {
|
||||
export class RelationshipsClass extends Component<
|
||||
RelationshipsProps & EuiTablePersistInjectedProps<SavedObjectRelation>,
|
||||
RelationshipsState
|
||||
> {
|
||||
constructor(props: RelationshipsProps & EuiTablePersistInjectedProps<SavedObjectRelation>) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
|
@ -218,7 +225,14 @@ export class Relationships extends Component<RelationshipsProps, RelationshipsSt
|
|||
}
|
||||
|
||||
renderRelationshipsTable() {
|
||||
const { goInspectObject, basePath, savedObject, allowedTypes, showPlainSpinner } = this.props;
|
||||
const {
|
||||
goInspectObject,
|
||||
basePath,
|
||||
savedObject,
|
||||
allowedTypes,
|
||||
showPlainSpinner,
|
||||
euiTablePersist: { pageSize, onTableChange },
|
||||
} = this.props;
|
||||
const { relations, isLoading, error } = this.state;
|
||||
|
||||
if (error) {
|
||||
|
@ -385,7 +399,8 @@ export class Relationships extends Component<RelationshipsProps, RelationshipsSt
|
|||
<EuiInMemoryTable
|
||||
items={relations}
|
||||
columns={columns as any}
|
||||
pagination={true}
|
||||
pagination={{ pageSize }}
|
||||
onTableChange={onTableChange}
|
||||
search={search}
|
||||
rowProps={() => ({
|
||||
'data-test-subj': `relationshipsTableRow`,
|
||||
|
@ -420,3 +435,8 @@ export class Relationships extends Component<RelationshipsProps, RelationshipsSt
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
export const Relationships = withEuiTablePersist(RelationshipsClass, {
|
||||
tableId: 'savedObjectsMgmtRelationships',
|
||||
initialPageSize: 10,
|
||||
});
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
"@kbn/shared-ux-link-redirect-app",
|
||||
"@kbn/code-editor",
|
||||
"@kbn/react-kibana-context-render",
|
||||
"@kbn/shared-ux-table-persist",
|
||||
],
|
||||
"exclude": [
|
||||
"target/**/*",
|
||||
|
|
|
@ -49,6 +49,7 @@ export class SearchSelection extends React.Component<SearchSelectionProps> {
|
|||
<DialogNavigation goBack={this.props.goBack} />
|
||||
<SavedObjectFinder
|
||||
key="searchSavedObjectFinder"
|
||||
id="visSearchSelection"
|
||||
onChoose={this.props.onSearchSelected}
|
||||
showFilter
|
||||
noItemsMessage={i18n.translate(
|
||||
|
|
|
@ -179,6 +179,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
await visEditor.setInterval('Second');
|
||||
await visEditor.clickGo();
|
||||
await inspector.open();
|
||||
await inspector.setTablePageSize(20);
|
||||
await inspector.expectTableData(expectedTableData);
|
||||
await inspector.close();
|
||||
});
|
||||
|
@ -211,6 +212,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
await visEditor.toggleScaleMetrics();
|
||||
await visEditor.clickGo();
|
||||
await inspector.open();
|
||||
await inspector.setTablePageSize(20);
|
||||
await inspector.expectTableData(expectedTableData);
|
||||
await inspector.close();
|
||||
});
|
||||
|
@ -245,6 +247,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
await visEditor.selectAggregateWith('average');
|
||||
await visEditor.clickGo();
|
||||
await inspector.open();
|
||||
await inspector.setTablePageSize(20);
|
||||
await inspector.expectTableData(expectedTableData);
|
||||
await inspector.close();
|
||||
});
|
||||
|
|
|
@ -97,8 +97,7 @@ export class InspectorService extends FtrService {
|
|||
* @param size rows count
|
||||
*/
|
||||
public async setTablePageSize(size: number): Promise<void> {
|
||||
const panel = await this.testSubjects.find('inspectorPanel');
|
||||
await this.find.clickByButtonText('Rows per page: 20', panel);
|
||||
await this.testSubjects.click('tablePaginationPopoverButton');
|
||||
// The buttons for setting table page size are in a popover element. This popover
|
||||
// element appears as if it's part of the inspectorPanel but it's really attached
|
||||
// to the body element by a portal.
|
||||
|
|
|
@ -135,6 +135,7 @@ export const AddEmbeddableFlyout: FC<Props> = ({
|
|||
</EuiFlyoutHeader>
|
||||
<EuiFlyoutBody>
|
||||
<SavedObjectFinder
|
||||
id="canvasEmbeddableFlyout"
|
||||
onChoose={onAddPanel}
|
||||
savedObjectMetaData={metaData}
|
||||
showFilter={true}
|
||||
|
|
|
@ -343,6 +343,7 @@ const LensEditorComponent: LensEuiMarkdownEditorUiPlugin['editor'] = ({
|
|||
<EuiModalBody>
|
||||
<SavedObjectFinder
|
||||
key="searchSavedObjectFinder"
|
||||
id="casesMarkdownLens"
|
||||
onChoose={handleChooseLensSO}
|
||||
showFilter={false}
|
||||
noItemsMessage={
|
||||
|
|
|
@ -29,6 +29,7 @@ export function SourcePicker({
|
|||
}: SourcePickerProps) {
|
||||
return (
|
||||
<SavedObjectFinder
|
||||
id="graphSourcePicker"
|
||||
services={{ contentClient: contentManagement.client, uiSettings }}
|
||||
onChoose={(_id, _type, _name, indexPattern) => {
|
||||
onIndexPatternSelected(indexPattern as IndexPatternSavedObject);
|
||||
|
|
|
@ -125,6 +125,7 @@ export const SourceSelection: FC = () => {
|
|||
</>
|
||||
)}
|
||||
<SavedObjectFinder
|
||||
id="mlDFASourceSelection"
|
||||
key="searchSavedObjectFinder"
|
||||
onChoose={onSearchSelected}
|
||||
showFilter
|
||||
|
|
|
@ -53,6 +53,7 @@ export const DataDriftIndexOrSearchRedirect: FC = () => {
|
|||
</MlPageHeader>
|
||||
<EuiPanel hasShadow={false} hasBorder>
|
||||
<SavedObjectFinder
|
||||
id="mlDataDriftDataViewsPicker"
|
||||
key="searchSavedObjectFinder"
|
||||
onChoose={onObjectSelection}
|
||||
showFilter
|
||||
|
|
|
@ -146,6 +146,7 @@ export const ChangeDataViewModal: FC<Props> = ({ onClose }) => {
|
|||
<EuiSpacer size="s" />
|
||||
|
||||
<SavedObjectFinder
|
||||
id="mlJobsDatafeedDataView"
|
||||
key="searchSavedObjectFinder"
|
||||
onChoose={onDataViewSelected}
|
||||
showFilter
|
||||
|
|
|
@ -56,6 +56,7 @@ export const Page: FC<PageProps> = ({
|
|||
</MlPageHeader>
|
||||
<EuiPanel hasShadow={false} hasBorder>
|
||||
<SavedObjectFinder
|
||||
id="mlJobsDatafeedDataView"
|
||||
key="searchSavedObjectFinder"
|
||||
onChoose={onObjectSelection}
|
||||
showFilter
|
||||
|
|
|
@ -48,6 +48,7 @@ export const SearchSelection: FC<SearchSelectionProps> = ({
|
|||
</EuiModalHeader>
|
||||
<EuiModalBody>
|
||||
<SavedObjectFinder
|
||||
id="transformMgtSearchSelection"
|
||||
key="searchSavedObjectFinder"
|
||||
onChoose={onSearchSelected}
|
||||
showFilter
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue