mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 17:28:26 -04:00
[Discover] Allow for custom number of rows in the results and save the specified number with a Saved Search (#135726)
* [Discover] Persist rowsPerPage in app state and URL * [Discover] Persist rowsPerPage in saved search objects * [Discover] Make sure that rowsPerPage is persisted in saved search objects * [Discover] Support rowsPerPage in embeddables * [Discover] Allow to save a custom rowsPerPage option * [Discover] Reflect custom size in the grid dropdown * [Discover] Fix changing rowsPerPage on Dashboard page * [Discover] Skip saving rowsPerPage for legacy view * [Discover] Fix sample size for rendering an embeddable * [Discover] Update tests * [Discover] Update tests * [Discover] Update mapping * [Discover] Revert setting a default state * [Discover] Remove rowsPerPage input from SaveSearch modal * [Discover] Update tests * [Discover] Ignore the setting for legacy view * [Discover] Add `discover:sampleRowsPerPage` setting to Advaced Settings * [Discover] Allow to save rowsPerPage on Dashboard for legacy view too * [Discover] Add tests * [Discover] Add tests * [Discover] Extend "select" type to return values as numbers too * [Discover] Fix values changes * [Discover] Update types to support also lists with numbers * [Discover] Fix disclaimer updates * [Discover] Update setting copy * [Discover] Simplify saving of rowsPerPage * [Discover] Extend number of rowsPerPage options for the legacy view too * [Discover] Move to utils * [Discover] Fix deps * [Discover] Add tests * [Discover] Update settings copy * [Discover] Limit max number of rows per page for an embedded legacy table * [Discover] Prevent invalid values for a custom rows per page * [Discover] Add tests Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
1904b61b87
commit
92a46f5344
42 changed files with 485 additions and 57 deletions
|
@ -298,6 +298,9 @@ When enabled, removes the columns that are not in the new data view.
|
|||
[[discover-sample-size]]`discover:sampleSize`::
|
||||
Specifies the number of rows to display in the *Discover* table.
|
||||
|
||||
[[discover-sampleRowsPerPage]]`discover:sampleRowsPerPage`::
|
||||
Specifies the number of rows to display per page in the *Discover* table.
|
||||
|
||||
[[discover-searchFieldsFromSource]]`discover:searchFieldsFromSource`::
|
||||
Load fields from the original JSON {ref}/mapping-source-field.html[`_source`].
|
||||
When disabled, *Discover* loads fields using the {es} search API's
|
||||
|
|
|
@ -50,7 +50,7 @@ export interface UiSettingsParams<T = unknown> {
|
|||
/** used to group the configured setting in the UI */
|
||||
category?: string[];
|
||||
/** array of permitted values for this setting */
|
||||
options?: string[];
|
||||
options?: string[] | number[];
|
||||
/** text labels for 'select' type UI element */
|
||||
optionLabels?: Record<string, string>;
|
||||
/** a flag indicating whether new value applying requires page reloading */
|
||||
|
|
|
@ -156,7 +156,7 @@ export class Field extends PureComponent<FieldProps> {
|
|||
this.onFieldChange(e.target.value);
|
||||
|
||||
onFieldChange = (targetValue: any) => {
|
||||
const { type, value, defVal } = this.props.setting;
|
||||
const { type, value, defVal, options } = this.props.setting;
|
||||
let newUnsavedValue;
|
||||
|
||||
switch (type) {
|
||||
|
@ -170,6 +170,13 @@ export class Field extends PureComponent<FieldProps> {
|
|||
case 'number':
|
||||
newUnsavedValue = Number(targetValue);
|
||||
break;
|
||||
case 'select':
|
||||
if (typeof options?.[0] === 'number') {
|
||||
newUnsavedValue = Number(targetValue);
|
||||
} else {
|
||||
newUnsavedValue = targetValue;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
newUnsavedValue = targetValue;
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ export interface FieldSetting {
|
|||
name: string;
|
||||
value: unknown;
|
||||
description?: string | ReactElement;
|
||||
options?: string[];
|
||||
options?: string[] | number[];
|
||||
optionLabels?: Record<string, string>;
|
||||
requiresPageReload: boolean;
|
||||
type: UiSettingsType;
|
||||
|
|
10
src/plugins/discover/common/constants.ts
Normal file
10
src/plugins/discover/common/constants.ts
Normal file
|
@ -0,0 +1,10 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0 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 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
export const DEFAULT_ROWS_PER_PAGE = 100;
|
||||
export const ROWS_PER_PAGE_OPTIONS = [10, 25, 50, DEFAULT_ROWS_PER_PAGE, 250, 500];
|
|
@ -10,6 +10,7 @@ export const PLUGIN_ID = 'discover';
|
|||
export const APP_ICON = 'discoverApp';
|
||||
export const DEFAULT_COLUMNS_SETTING = 'defaultColumns';
|
||||
export const SAMPLE_SIZE_SETTING = 'discover:sampleSize';
|
||||
export const SAMPLE_ROWS_PER_PAGE_SETTING = 'discover:sampleRowsPerPage';
|
||||
export const SORT_DEFAULT_ORDER_SETTING = 'discover:sort:defaultOrder';
|
||||
export const SEARCH_ON_PAGE_LOAD_SETTING = 'discover:searchOnPageLoad';
|
||||
export const DOC_HIDE_TIME_COLUMN_SETTING = 'doc_table:hideTimeColumn';
|
||||
|
|
|
@ -15,6 +15,7 @@ import {
|
|||
DOC_HIDE_TIME_COLUMN_SETTING,
|
||||
MAX_DOC_FIELDS_DISPLAYED,
|
||||
SAMPLE_SIZE_SETTING,
|
||||
SAMPLE_ROWS_PER_PAGE_SETTING,
|
||||
SORT_DEFAULT_ORDER_SETTING,
|
||||
HIDE_ANNOUNCEMENTS,
|
||||
} from '../../common';
|
||||
|
@ -67,6 +68,8 @@ export const discoverServiceMock = {
|
|||
return false;
|
||||
} else if (key === SAMPLE_SIZE_SETTING) {
|
||||
return 250;
|
||||
} else if (key === SAMPLE_ROWS_PER_PAGE_SETTING) {
|
||||
return 150;
|
||||
} else if (key === MAX_DOC_FIELDS_DISPLAYED) {
|
||||
return 50;
|
||||
} else if (key === HIDE_ANNOUNCEMENTS) {
|
||||
|
|
|
@ -12,6 +12,7 @@ import {
|
|||
DEFAULT_COLUMNS_SETTING,
|
||||
DOC_TABLE_LEGACY,
|
||||
SAMPLE_SIZE_SETTING,
|
||||
SAMPLE_ROWS_PER_PAGE_SETTING,
|
||||
SHOW_MULTIFIELDS,
|
||||
SEARCH_FIELDS_FROM_SOURCE,
|
||||
ROW_HEIGHT_OPTION,
|
||||
|
@ -21,6 +22,8 @@ export const uiSettingsMock = {
|
|||
get: (key: string) => {
|
||||
if (key === SAMPLE_SIZE_SETTING) {
|
||||
return 10;
|
||||
} else if (key === SAMPLE_ROWS_PER_PAGE_SETTING) {
|
||||
return 100;
|
||||
} else if (key === DEFAULT_COLUMNS_SETTING) {
|
||||
return ['default_column'];
|
||||
} else if (key === DOC_TABLE_LEGACY) {
|
||||
|
|
|
@ -19,6 +19,7 @@ import {
|
|||
MAX_DOC_FIELDS_DISPLAYED,
|
||||
ROW_HEIGHT_OPTION,
|
||||
SAMPLE_SIZE_SETTING,
|
||||
SAMPLE_ROWS_PER_PAGE_SETTING,
|
||||
SEARCH_FIELDS_FROM_SOURCE,
|
||||
SHOW_MULTIFIELDS,
|
||||
} from '../../../../../../common';
|
||||
|
@ -32,6 +33,8 @@ export const uiSettingsMock = {
|
|||
return 3;
|
||||
} else if (key === SAMPLE_SIZE_SETTING) {
|
||||
return 10;
|
||||
} else if (key === SAMPLE_ROWS_PER_PAGE_SETTING) {
|
||||
return 100;
|
||||
} else if (key === DEFAULT_COLUMNS_SETTING) {
|
||||
return ['default_column'];
|
||||
} else if (key === DOC_TABLE_LEGACY) {
|
||||
|
|
|
@ -86,8 +86,8 @@ function DiscoverDocumentsComponent({
|
|||
|
||||
const onResize = useCallback(
|
||||
(colSettings: { columnId: string; width: number }) => {
|
||||
const grid = { ...state.grid } || {};
|
||||
const newColumns = { ...grid.columns } || {};
|
||||
const grid = { ...(state.grid || {}) };
|
||||
const newColumns = { ...(grid.columns || {}) };
|
||||
newColumns[colSettings.columnId] = {
|
||||
width: colSettings.width,
|
||||
};
|
||||
|
@ -97,6 +97,13 @@ function DiscoverDocumentsComponent({
|
|||
[stateContainer, state]
|
||||
);
|
||||
|
||||
const onUpdateRowsPerPage = useCallback(
|
||||
(rowsPerPage: number) => {
|
||||
stateContainer.setAppState({ rowsPerPage });
|
||||
},
|
||||
[stateContainer]
|
||||
);
|
||||
|
||||
const onSort = useCallback(
|
||||
(sort: string[][]) => {
|
||||
stateContainer.setAppState({ sort });
|
||||
|
@ -190,6 +197,8 @@ function DiscoverDocumentsComponent({
|
|||
useNewFieldsApi={useNewFieldsApi}
|
||||
rowHeightState={state.rowHeight}
|
||||
onUpdateRowHeight={onUpdateRowHeight}
|
||||
rowsPerPageState={state.rowsPerPage}
|
||||
onUpdateRowsPerPage={onUpdateRowsPerPage}
|
||||
onFieldEdited={onFieldEdited}
|
||||
/>
|
||||
</div>
|
||||
|
|
|
@ -22,7 +22,13 @@ test('onSaveSearch', async () => {
|
|||
i18n: i18nServiceMock.create(),
|
||||
},
|
||||
} as unknown as DiscoverServices;
|
||||
const stateMock = {} as unknown as GetStateReturn;
|
||||
const stateMock = {
|
||||
appStateContainer: {
|
||||
getState: () => ({
|
||||
rowsPerPage: 250,
|
||||
}),
|
||||
},
|
||||
} as unknown as GetStateReturn;
|
||||
|
||||
await onSaveSearch({
|
||||
indexPattern: indexPatternMock,
|
||||
|
|
|
@ -8,13 +8,14 @@
|
|||
|
||||
import React from 'react';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { SavedObjectSaveModal, showSaveModal } from '@kbn/saved-objects-plugin/public';
|
||||
import { SavedObjectSaveModal, showSaveModal, OnSaveProps } from '@kbn/saved-objects-plugin/public';
|
||||
import { DataView } from '@kbn/data-views-plugin/public';
|
||||
import { SavedSearch, SaveSavedSearchOptions } from '../../../../services/saved_searches';
|
||||
import { DiscoverServices } from '../../../../build_services';
|
||||
import { GetStateReturn } from '../../services/discover_state';
|
||||
import { setBreadcrumbsTitle } from '../../../../utils/breadcrumbs';
|
||||
import { persistSavedSearch } from '../../utils/persist_saved_search';
|
||||
import { DOC_TABLE_LEGACY } from '../../../../../common';
|
||||
|
||||
async function saveDataSource({
|
||||
indexPattern,
|
||||
|
@ -97,6 +98,7 @@ export async function onSaveSearch({
|
|||
state: GetStateReturn;
|
||||
onClose?: () => void;
|
||||
}) {
|
||||
const { uiSettings } = services;
|
||||
const onSave = async ({
|
||||
newTitle,
|
||||
newCopyOnSave,
|
||||
|
@ -111,8 +113,12 @@ export async function onSaveSearch({
|
|||
onTitleDuplicate: () => void;
|
||||
}) => {
|
||||
const currentTitle = savedSearch.title;
|
||||
const currentRowsPerPage = savedSearch.rowsPerPage;
|
||||
savedSearch.title = newTitle;
|
||||
savedSearch.description = newDescription;
|
||||
savedSearch.rowsPerPage = uiSettings.get(DOC_TABLE_LEGACY)
|
||||
? currentRowsPerPage
|
||||
: state.appStateContainer.getState().rowsPerPage;
|
||||
const saveOptions: SaveSavedSearchOptions = {
|
||||
onTitleDuplicate,
|
||||
copyOnSave: newCopyOnSave,
|
||||
|
@ -129,6 +135,7 @@ export async function onSaveSearch({
|
|||
// If the save wasn't successful, put the original values back.
|
||||
if (!response.id || response.error) {
|
||||
savedSearch.title = currentTitle;
|
||||
savedSearch.rowsPerPage = currentRowsPerPage;
|
||||
} else {
|
||||
state.resetInitialAppState();
|
||||
}
|
||||
|
@ -136,17 +143,39 @@ export async function onSaveSearch({
|
|||
};
|
||||
|
||||
const saveModal = (
|
||||
<SavedObjectSaveModal
|
||||
onSave={onSave}
|
||||
onClose={onClose ?? (() => {})}
|
||||
<SaveSearchObjectModal
|
||||
title={savedSearch.title ?? ''}
|
||||
showCopyOnSave={!!savedSearch.id}
|
||||
description={savedSearch.description}
|
||||
objectType={i18n.translate('discover.localMenu.saveSaveSearchObjectType', {
|
||||
defaultMessage: 'search',
|
||||
})}
|
||||
showDescription={true}
|
||||
onSave={onSave}
|
||||
onClose={onClose ?? (() => {})}
|
||||
/>
|
||||
);
|
||||
showSaveModal(saveModal, services.core.i18n.Context);
|
||||
}
|
||||
|
||||
const SaveSearchObjectModal: React.FC<{
|
||||
title: string;
|
||||
showCopyOnSave: boolean;
|
||||
description?: string;
|
||||
onSave: (props: OnSaveProps & { newRowsPerPage?: number }) => void;
|
||||
onClose: () => void;
|
||||
}> = ({ title, description, showCopyOnSave, onSave, onClose }) => {
|
||||
const onModalSave = (params: OnSaveProps) => {
|
||||
onSave(params);
|
||||
};
|
||||
|
||||
return (
|
||||
<SavedObjectSaveModal
|
||||
title={title}
|
||||
showCopyOnSave={showCopyOnSave}
|
||||
description={description}
|
||||
objectType={i18n.translate('discover.localMenu.saveSaveSearchObjectType', {
|
||||
defaultMessage: 'search',
|
||||
})}
|
||||
showDescription={true}
|
||||
onSave={onModalSave}
|
||||
onClose={onClose}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -90,6 +90,10 @@ export interface AppState {
|
|||
* Document explorer row height option
|
||||
*/
|
||||
rowHeight?: number;
|
||||
/**
|
||||
* Number of rows in the grid per page
|
||||
*/
|
||||
rowsPerPage?: number;
|
||||
}
|
||||
|
||||
export interface AppStateUrl extends Omit<AppState, 'sort'> {
|
||||
|
|
|
@ -55,4 +55,29 @@ describe('cleanupUrlState', () => {
|
|||
} as AppStateUrl;
|
||||
expect(cleanupUrlState(state)).toMatchInlineSnapshot(`Object {}`);
|
||||
});
|
||||
|
||||
test('should keep a valid rowsPerPage', async () => {
|
||||
const state = {
|
||||
rowsPerPage: 50,
|
||||
} as AppStateUrl;
|
||||
expect(cleanupUrlState(state)).toMatchInlineSnapshot(`
|
||||
Object {
|
||||
"rowsPerPage": 50,
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test('should remove a negative rowsPerPage', async () => {
|
||||
const state = {
|
||||
rowsPerPage: -50,
|
||||
} as AppStateUrl;
|
||||
expect(cleanupUrlState(state)).toMatchInlineSnapshot(`Object {}`);
|
||||
});
|
||||
|
||||
test('should remove an invalid rowsPerPage', async () => {
|
||||
const state = {
|
||||
rowsPerPage: 'test',
|
||||
} as unknown as AppStateUrl;
|
||||
expect(cleanupUrlState(state)).toMatchInlineSnapshot(`Object {}`);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -31,5 +31,14 @@ export function cleanupUrlState(appStateFromUrl: AppStateUrl): AppState {
|
|||
// This allows the sort prop to be overwritten with the default sorting
|
||||
delete appStateFromUrl.sort;
|
||||
}
|
||||
|
||||
if (
|
||||
appStateFromUrl?.rowsPerPage &&
|
||||
!(typeof appStateFromUrl.rowsPerPage === 'number' && appStateFromUrl.rowsPerPage > 0)
|
||||
) {
|
||||
// remove the param if it's invalid
|
||||
delete appStateFromUrl.rowsPerPage;
|
||||
}
|
||||
|
||||
return appStateFromUrl as AppState;
|
||||
}
|
||||
|
|
|
@ -37,6 +37,7 @@ describe('getStateDefaults', () => {
|
|||
"interval": "auto",
|
||||
"query": undefined,
|
||||
"rowHeight": undefined,
|
||||
"rowsPerPage": undefined,
|
||||
"savedQuery": undefined,
|
||||
"sort": Array [
|
||||
Array [
|
||||
|
@ -70,6 +71,7 @@ describe('getStateDefaults', () => {
|
|||
"interval": "auto",
|
||||
"query": undefined,
|
||||
"rowHeight": undefined,
|
||||
"rowsPerPage": undefined,
|
||||
"savedQuery": undefined,
|
||||
"sort": Array [],
|
||||
"viewMode": undefined,
|
||||
|
|
|
@ -51,7 +51,7 @@ export function getStateDefaults({
|
|||
const columns = getDefaultColumns(savedSearch, config);
|
||||
const chartHidden = storage.get(CHART_HIDDEN_KEY);
|
||||
|
||||
const defaultState = {
|
||||
const defaultState: AppState = {
|
||||
query,
|
||||
sort: !sort.length
|
||||
? getDefaultSort(
|
||||
|
@ -63,13 +63,14 @@ export function getStateDefaults({
|
|||
columns,
|
||||
index: indexPattern?.id,
|
||||
interval: 'auto',
|
||||
filters: cloneDeep(searchSource.getOwnField('filter')),
|
||||
filters: cloneDeep(searchSource.getOwnField('filter')) as AppState['filters'],
|
||||
hideChart: typeof chartHidden === 'boolean' ? chartHidden : undefined,
|
||||
viewMode: undefined,
|
||||
hideAggregatedPreview: undefined,
|
||||
savedQuery: undefined,
|
||||
rowHeight: undefined,
|
||||
} as AppState;
|
||||
rowsPerPage: undefined,
|
||||
};
|
||||
if (savedSearch.grid) {
|
||||
defaultState.grid = savedSearch.grid;
|
||||
}
|
||||
|
@ -82,10 +83,12 @@ export function getStateDefaults({
|
|||
if (savedSearch.viewMode) {
|
||||
defaultState.viewMode = savedSearch.viewMode;
|
||||
}
|
||||
|
||||
if (savedSearch.hideAggregatedPreview) {
|
||||
defaultState.hideAggregatedPreview = savedSearch.hideAggregatedPreview;
|
||||
}
|
||||
if (savedSearch.rowsPerPage) {
|
||||
defaultState.rowsPerPage = savedSearch.rowsPerPage;
|
||||
}
|
||||
|
||||
return defaultState;
|
||||
}
|
||||
|
|
|
@ -17,8 +17,6 @@ export const GRID_STYLE = {
|
|||
rowHover: 'none',
|
||||
} as EuiDataGridStyle;
|
||||
|
||||
export const pageSizeArr = [25, 50, 100, 250];
|
||||
export const defaultPageSize = 100;
|
||||
export const defaultTimeColumnWidth = 210;
|
||||
export const toolbarVisibility = {
|
||||
showColumnSelector: {
|
||||
|
|
|
@ -34,12 +34,7 @@ import {
|
|||
getLeadControlColumns,
|
||||
getVisibleColumns,
|
||||
} from './discover_grid_columns';
|
||||
import {
|
||||
defaultPageSize,
|
||||
GRID_STYLE,
|
||||
pageSizeArr,
|
||||
toolbarVisibility as toolbarVisibilityDefaults,
|
||||
} from './constants';
|
||||
import { GRID_STYLE, toolbarVisibility as toolbarVisibilityDefaults } from './constants';
|
||||
import { getDisplayedColumns } from '../../utils/columns';
|
||||
import {
|
||||
DOC_HIDE_TIME_COLUMN_SETTING,
|
||||
|
@ -54,6 +49,7 @@ import type { DataTableRecord, ValueToStringConverter } from '../../types';
|
|||
import { useRowHeightsOptions } from '../../hooks/use_row_heights_options';
|
||||
import { useDiscoverServices } from '../../hooks/use_discover_services';
|
||||
import { convertValueToString } from '../../utils/convert_value_to_string';
|
||||
import { getRowsPerPageOptions, getDefaultRowsPerPage } from '../../utils/rows_per_page';
|
||||
|
||||
interface SortObj {
|
||||
id: string;
|
||||
|
@ -166,6 +162,14 @@ export interface DiscoverGridProps {
|
|||
* Update row height state
|
||||
*/
|
||||
onUpdateRowHeight?: (rowHeight: number) => void;
|
||||
/**
|
||||
* Current state value for rowsPerPage
|
||||
*/
|
||||
rowsPerPageState?: number;
|
||||
/**
|
||||
* Update rows per page state
|
||||
*/
|
||||
onUpdateRowsPerPage?: (rowsPerPage: number) => void;
|
||||
/**
|
||||
* Callback to execute on edit runtime field
|
||||
*/
|
||||
|
@ -203,6 +207,8 @@ export const DiscoverGrid = ({
|
|||
className,
|
||||
rowHeightState,
|
||||
onUpdateRowHeight,
|
||||
rowsPerPageState,
|
||||
onUpdateRowsPerPage,
|
||||
onFieldEdited,
|
||||
}: DiscoverGridProps) => {
|
||||
const dataGridRef = useRef<EuiDataGridRefProps>(null);
|
||||
|
@ -256,17 +262,28 @@ export const DiscoverGrid = ({
|
|||
/**
|
||||
* Pagination
|
||||
*/
|
||||
const [pagination, setPagination] = useState({ pageIndex: 0, pageSize: defaultPageSize });
|
||||
const defaultRowsPerPage = useMemo(
|
||||
() => getDefaultRowsPerPage(services.uiSettings),
|
||||
[services.uiSettings]
|
||||
);
|
||||
const currentPageSize =
|
||||
typeof rowsPerPageState === 'number' && rowsPerPageState > 0
|
||||
? rowsPerPageState
|
||||
: defaultRowsPerPage;
|
||||
const [pagination, setPagination] = useState({
|
||||
pageIndex: 0,
|
||||
pageSize: currentPageSize,
|
||||
});
|
||||
const rowCount = useMemo(() => (displayedRows ? displayedRows.length : 0), [displayedRows]);
|
||||
const pageCount = useMemo(
|
||||
() => Math.ceil(rowCount / pagination.pageSize),
|
||||
[rowCount, pagination]
|
||||
);
|
||||
const isOnLastPage = pagination.pageIndex === pageCount - 1;
|
||||
|
||||
const paginationObj = useMemo(() => {
|
||||
const onChangeItemsPerPage = (pageSize: number) =>
|
||||
setPagination((paginationData) => ({ ...paginationData, pageSize }));
|
||||
const onChangeItemsPerPage = (pageSize: number) => {
|
||||
onUpdateRowsPerPage?.(pageSize);
|
||||
};
|
||||
|
||||
const onChangePage = (pageIndex: number) =>
|
||||
setPagination((paginationData) => ({ ...paginationData, pageIndex }));
|
||||
|
@ -277,10 +294,20 @@ export const DiscoverGrid = ({
|
|||
onChangePage,
|
||||
pageIndex: pagination.pageIndex > pageCount - 1 ? 0 : pagination.pageIndex,
|
||||
pageSize: pagination.pageSize,
|
||||
pageSizeOptions: pageSizeArr,
|
||||
pageSizeOptions: getRowsPerPageOptions(pagination.pageSize),
|
||||
}
|
||||
: undefined;
|
||||
}, [pagination, pageCount, isPaginationEnabled]);
|
||||
}, [pagination, pageCount, isPaginationEnabled, onUpdateRowsPerPage]);
|
||||
|
||||
const isOnLastPage = paginationObj ? paginationObj.pageIndex === pageCount - 1 : false;
|
||||
|
||||
useEffect(() => {
|
||||
setPagination((paginationData) =>
|
||||
paginationData.pageSize === currentPageSize
|
||||
? paginationData
|
||||
: { ...paginationData, pageSize: currentPageSize }
|
||||
);
|
||||
}, [currentPageSize, setPagination]);
|
||||
|
||||
/**
|
||||
* Sorting
|
||||
|
|
|
@ -19,6 +19,9 @@ import {
|
|||
import { FormattedMessage } from '@kbn/i18n-react';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { euiLightVars } from '@kbn/ui-theme';
|
||||
import { getRowsPerPageOptions } from '../../../../utils/rows_per_page';
|
||||
|
||||
export const MAX_ROWS_PER_PAGE_OPTION = 100;
|
||||
|
||||
interface ToolBarPaginationProps {
|
||||
pageSize: number;
|
||||
|
@ -53,18 +56,20 @@ export const ToolBarPagination = ({
|
|||
return size === pageSize ? 'check' : 'empty';
|
||||
};
|
||||
|
||||
const rowsPerPageOptions = [25, 50, 100].map((cur) => (
|
||||
<EuiContextMenuItem
|
||||
key={`${cur} rows`}
|
||||
icon={getIconType(cur)}
|
||||
onClick={() => {
|
||||
closePopover();
|
||||
onPageSizeChange(cur);
|
||||
}}
|
||||
>
|
||||
{cur} {rowsWord}
|
||||
</EuiContextMenuItem>
|
||||
));
|
||||
const rowsPerPageOptions = getRowsPerPageOptions(pageSize)
|
||||
.filter((option) => option <= MAX_ROWS_PER_PAGE_OPTION) // legacy table is not optimized well for rendering more rows at once
|
||||
.map((cur) => (
|
||||
<EuiContextMenuItem
|
||||
key={`${cur} rows`}
|
||||
icon={getIconType(cur)}
|
||||
onClick={() => {
|
||||
closePopover();
|
||||
onPageSizeChange(cur);
|
||||
}}
|
||||
>
|
||||
{cur} {rowsWord}
|
||||
</EuiContextMenuItem>
|
||||
));
|
||||
|
||||
return (
|
||||
<EuiFlexGroup alignItems="center" gutterSize="xs" responsive={false}>
|
||||
|
|
|
@ -16,6 +16,8 @@ export function DiscoverDocTableEmbeddable(renderProps: DocTableEmbeddableProps)
|
|||
<DocTableEmbeddable
|
||||
columns={renderProps.columns}
|
||||
rows={renderProps.rows}
|
||||
rowsPerPageState={renderProps.rowsPerPageState}
|
||||
onUpdateRowsPerPage={renderProps.onUpdateRowsPerPage}
|
||||
totalHitCount={renderProps.totalHitCount}
|
||||
indexPattern={renderProps.indexPattern}
|
||||
onSort={renderProps.onSort}
|
||||
|
|
|
@ -12,19 +12,25 @@ import { FormattedMessage } from '@kbn/i18n-react';
|
|||
import { EuiFlexGroup, EuiFlexItem, EuiText } from '@elastic/eui';
|
||||
import { SAMPLE_SIZE_SETTING } from '../../../common';
|
||||
import { usePager } from '../../hooks/use_pager';
|
||||
import { ToolBarPagination } from './components/pager/tool_bar_pagination';
|
||||
import {
|
||||
ToolBarPagination,
|
||||
MAX_ROWS_PER_PAGE_OPTION,
|
||||
} from './components/pager/tool_bar_pagination';
|
||||
import { DocTableProps, DocTableRenderProps, DocTableWrapper } from './doc_table_wrapper';
|
||||
import { TotalDocuments } from '../../application/main/components/total_documents/total_documents';
|
||||
import { useDiscoverServices } from '../../hooks/use_discover_services';
|
||||
|
||||
export interface DocTableEmbeddableProps extends DocTableProps {
|
||||
totalHitCount: number;
|
||||
rowsPerPageState?: number;
|
||||
onUpdateRowsPerPage?: (rowsPerPage?: number) => void;
|
||||
}
|
||||
|
||||
const DocTableWrapperMemoized = memo(DocTableWrapper);
|
||||
|
||||
export const DocTableEmbeddable = (props: DocTableEmbeddableProps) => {
|
||||
const services = useDiscoverServices();
|
||||
const onUpdateRowsPerPage = props.onUpdateRowsPerPage;
|
||||
const tableWrapperRef = useRef<HTMLDivElement>(null);
|
||||
const {
|
||||
curPageIndex,
|
||||
|
@ -35,7 +41,10 @@ export const DocTableEmbeddable = (props: DocTableEmbeddableProps) => {
|
|||
changePageIndex,
|
||||
changePageSize,
|
||||
} = usePager({
|
||||
initialPageSize: 50,
|
||||
initialPageSize:
|
||||
typeof props.rowsPerPageState === 'number' && props.rowsPerPageState > 0
|
||||
? Math.min(props.rowsPerPageState, MAX_ROWS_PER_PAGE_OPTION)
|
||||
: 50,
|
||||
totalItems: props.rows.length,
|
||||
});
|
||||
const showPagination = totalPages !== 0;
|
||||
|
@ -63,8 +72,9 @@ export const DocTableEmbeddable = (props: DocTableEmbeddableProps) => {
|
|||
(size: number) => {
|
||||
scrollTop();
|
||||
changePageSize(size);
|
||||
onUpdateRowsPerPage?.(size); // to update `rowsPerPage` input param for the embeddable
|
||||
},
|
||||
[changePageSize, scrollTop]
|
||||
[changePageSize, scrollTop, onUpdateRowsPerPage]
|
||||
);
|
||||
|
||||
const shouldShowLimitedResultsWarning = useMemo(
|
||||
|
|
|
@ -65,6 +65,7 @@ export type SearchProps = Partial<DiscoverGridProps> &
|
|||
totalHitCount?: number;
|
||||
onMoveColumn?: (column: string, index: number) => void;
|
||||
onUpdateRowHeight?: (rowHeight?: number) => void;
|
||||
onUpdateRowsPerPage?: (rowsPerPage?: number) => void;
|
||||
};
|
||||
|
||||
interface SearchEmbeddableConfig {
|
||||
|
@ -139,7 +140,12 @@ export class SavedSearchEmbeddable
|
|||
if (titleChanged) {
|
||||
this.panelTitle = this.output.title || '';
|
||||
}
|
||||
if (this.searchProps && (titleChanged || this.isFetchRequired(this.searchProps))) {
|
||||
if (
|
||||
this.searchProps &&
|
||||
(titleChanged ||
|
||||
this.isFetchRequired(this.searchProps) ||
|
||||
this.isInputChangedAndRerenderRequired(this.searchProps))
|
||||
) {
|
||||
this.pushContainerStateParamsToProps(this.searchProps);
|
||||
}
|
||||
});
|
||||
|
@ -302,7 +308,7 @@ export class SavedSearchEmbeddable
|
|||
});
|
||||
this.updateInput({ sort: sortOrderArr });
|
||||
},
|
||||
sampleSize: 500,
|
||||
sampleSize: this.services.uiSettings.get(SAMPLE_SIZE_SETTING),
|
||||
onFilter: async (field, value, operator) => {
|
||||
let filters = generateFilters(
|
||||
this.filterManager,
|
||||
|
@ -329,6 +335,10 @@ export class SavedSearchEmbeddable
|
|||
onUpdateRowHeight: (rowHeight) => {
|
||||
this.updateInput({ rowHeight });
|
||||
},
|
||||
rowsPerPageState: this.input.rowsPerPage || this.savedSearch.rowsPerPage,
|
||||
onUpdateRowsPerPage: (rowsPerPage) => {
|
||||
this.updateInput({ rowsPerPage });
|
||||
},
|
||||
};
|
||||
|
||||
const timeRangeSearchSource = searchSource.create();
|
||||
|
@ -364,6 +374,13 @@ export class SavedSearchEmbeddable
|
|||
);
|
||||
}
|
||||
|
||||
private isInputChangedAndRerenderRequired(searchProps?: SearchProps) {
|
||||
if (!searchProps) {
|
||||
return false;
|
||||
}
|
||||
return this.input.rowsPerPage !== searchProps.rowsPerPageState;
|
||||
}
|
||||
|
||||
private async pushContainerStateParamsToProps(
|
||||
searchProps: SearchProps,
|
||||
{ forceFetch = false }: { forceFetch: boolean } = { forceFetch: false }
|
||||
|
@ -384,6 +401,7 @@ export class SavedSearchEmbeddable
|
|||
searchProps.sort = this.input.sort || savedSearchSort;
|
||||
searchProps.sharedItemTitle = this.panelTitle;
|
||||
searchProps.rowHeightState = this.input.rowHeight || this.savedSearch.rowHeight;
|
||||
searchProps.rowsPerPageState = this.input.rowsPerPage || this.savedSearch.rowsPerPage;
|
||||
if (forceFetch || isFetchRequired) {
|
||||
this.filtersSearchSource.setField('filter', this.input.filters);
|
||||
this.filtersSearchSource.setField('query', this.input.query);
|
||||
|
|
|
@ -25,6 +25,7 @@ export interface SearchInput extends EmbeddableInput {
|
|||
columns?: string[];
|
||||
sort?: SortOrder[];
|
||||
rowHeight?: number;
|
||||
rowsPerPage?: number;
|
||||
}
|
||||
|
||||
export interface SearchOutput extends EmbeddableOutput {
|
||||
|
|
|
@ -105,6 +105,7 @@ describe('getSavedSearch', () => {
|
|||
"hideChart": false,
|
||||
"id": "ccf1af80-2297-11ec-86e0-1155ffb9c7a7",
|
||||
"rowHeight": undefined,
|
||||
"rowsPerPage": undefined,
|
||||
"searchSource": Object {
|
||||
"create": [MockFunction],
|
||||
"createChild": [MockFunction],
|
||||
|
|
|
@ -42,6 +42,7 @@ describe('saved_searches_utils', () => {
|
|||
"hideChart": true,
|
||||
"id": "id",
|
||||
"rowHeight": undefined,
|
||||
"rowsPerPage": undefined,
|
||||
"searchSource": SearchSource {
|
||||
"dependencies": Object {
|
||||
"aggs": Object {
|
||||
|
@ -119,6 +120,7 @@ describe('saved_searches_utils', () => {
|
|||
"searchSourceJSON": "{}",
|
||||
},
|
||||
"rowHeight": undefined,
|
||||
"rowsPerPage": undefined,
|
||||
"sort": Array [
|
||||
Array [
|
||||
"a",
|
||||
|
|
|
@ -45,6 +45,7 @@ export const fromSavedSearchAttributes = (
|
|||
viewMode: attributes.viewMode,
|
||||
hideAggregatedPreview: attributes.hideAggregatedPreview,
|
||||
rowHeight: attributes.rowHeight,
|
||||
rowsPerPage: attributes.rowsPerPage,
|
||||
});
|
||||
|
||||
export const toSavedSearchAttributes = (
|
||||
|
@ -61,4 +62,5 @@ export const toSavedSearchAttributes = (
|
|||
viewMode: savedSearch.viewMode,
|
||||
hideAggregatedPreview: savedSearch.hideAggregatedPreview,
|
||||
rowHeight: savedSearch.rowHeight,
|
||||
rowsPerPage: savedSearch.rowsPerPage,
|
||||
});
|
||||
|
|
|
@ -27,6 +27,7 @@ export interface SavedSearchAttributes {
|
|||
viewMode?: VIEW_MODE;
|
||||
hideAggregatedPreview?: boolean;
|
||||
rowHeight?: number;
|
||||
rowsPerPage?: number;
|
||||
}
|
||||
|
||||
/** @internal **/
|
||||
|
@ -53,4 +54,5 @@ export interface SavedSearch {
|
|||
viewMode?: VIEW_MODE;
|
||||
hideAggregatedPreview?: boolean;
|
||||
rowHeight?: number;
|
||||
rowsPerPage?: number;
|
||||
}
|
||||
|
|
42
src/plugins/discover/public/utils/rows_per_page.test.ts
Normal file
42
src/plugins/discover/public/utils/rows_per_page.test.ts
Normal file
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* 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 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 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { discoverServiceMock } from '../__mocks__/services';
|
||||
import { SAMPLE_ROWS_PER_PAGE_SETTING } from '../../common';
|
||||
import { getRowsPerPageOptions, getDefaultRowsPerPage } from './rows_per_page';
|
||||
|
||||
const SORTED_OPTIONS = [10, 25, 50, 100, 250, 500];
|
||||
|
||||
describe('rows per page', () => {
|
||||
describe('getRowsPerPageOptions', () => {
|
||||
it('should return default options if not provided', () => {
|
||||
expect(getRowsPerPageOptions()).toEqual(SORTED_OPTIONS);
|
||||
});
|
||||
|
||||
it('should return default options if current value is one of them', () => {
|
||||
expect(getRowsPerPageOptions(250)).toEqual(SORTED_OPTIONS);
|
||||
});
|
||||
|
||||
it('should return extended options if current value is not one of them', () => {
|
||||
expect(getRowsPerPageOptions(350)).toEqual([10, 25, 50, 100, 250, 350, 500]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getDefaultRowsPerPage', () => {
|
||||
it('should return a value from settings', () => {
|
||||
expect(getDefaultRowsPerPage(discoverServiceMock.uiSettings)).toEqual(150);
|
||||
expect(discoverServiceMock.uiSettings.get).toHaveBeenCalledWith(SAMPLE_ROWS_PER_PAGE_SETTING);
|
||||
});
|
||||
|
||||
it('should return a default value', () => {
|
||||
expect(getDefaultRowsPerPage({ ...discoverServiceMock.uiSettings, get: jest.fn() })).toEqual(
|
||||
100
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
26
src/plugins/discover/public/utils/rows_per_page.ts
Normal file
26
src/plugins/discover/public/utils/rows_per_page.ts
Normal file
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* 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 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 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { sortBy, uniq } from 'lodash';
|
||||
import { DEFAULT_ROWS_PER_PAGE, ROWS_PER_PAGE_OPTIONS } from '../../common/constants';
|
||||
import { SAMPLE_ROWS_PER_PAGE_SETTING } from '../../common';
|
||||
import { DiscoverServices } from '../build_services';
|
||||
|
||||
export const getRowsPerPageOptions = (currentRowsPerPage?: number): number[] => {
|
||||
return sortBy(
|
||||
uniq(
|
||||
typeof currentRowsPerPage === 'number' && currentRowsPerPage > 0
|
||||
? [...ROWS_PER_PAGE_OPTIONS, currentRowsPerPage]
|
||||
: ROWS_PER_PAGE_OPTIONS
|
||||
)
|
||||
);
|
||||
};
|
||||
|
||||
export const getDefaultRowsPerPage = (uiSettings: DiscoverServices['uiSettings']): number => {
|
||||
return parseInt(uiSettings.get(SAMPLE_ROWS_PER_PAGE_SETTING), 10) || DEFAULT_ROWS_PER_PAGE;
|
||||
};
|
|
@ -50,6 +50,7 @@ export function getSavedSearchObjectType(
|
|||
grid: { type: 'object', enabled: false },
|
||||
version: { type: 'integer' },
|
||||
rowHeight: { type: 'text' },
|
||||
rowsPerPage: { type: 'integer', index: false, doc_values: false },
|
||||
},
|
||||
},
|
||||
migrations: () => getAllMigrations(getSearchSourceMigrations()),
|
||||
|
|
|
@ -14,6 +14,7 @@ import { METRIC_TYPE } from '@kbn/analytics';
|
|||
import {
|
||||
DEFAULT_COLUMNS_SETTING,
|
||||
SAMPLE_SIZE_SETTING,
|
||||
SAMPLE_ROWS_PER_PAGE_SETTING,
|
||||
SORT_DEFAULT_ORDER_SETTING,
|
||||
SEARCH_ON_PAGE_LOAD_SETTING,
|
||||
DOC_HIDE_TIME_COLUMN_SETTING,
|
||||
|
@ -30,6 +31,7 @@ import {
|
|||
SHOW_FIELD_STATISTICS,
|
||||
ROW_HEIGHT_OPTION,
|
||||
} from '../common';
|
||||
import { DEFAULT_ROWS_PER_PAGE, ROWS_PER_PAGE_OPTIONS } from '../common/constants';
|
||||
|
||||
export const getUiSettings: (docLinks: DocLinksServiceSetup) => Record<string, UiSettingsParams> = (
|
||||
docLinks: DocLinksServiceSetup
|
||||
|
@ -59,11 +61,24 @@ export const getUiSettings: (docLinks: DocLinksServiceSetup) => Record<string, U
|
|||
},
|
||||
[SAMPLE_SIZE_SETTING]: {
|
||||
name: i18n.translate('discover.advancedSettings.sampleSizeTitle', {
|
||||
defaultMessage: 'Number of rows',
|
||||
defaultMessage: 'Maximum rows per table',
|
||||
}),
|
||||
value: 500,
|
||||
description: i18n.translate('discover.advancedSettings.sampleSizeText', {
|
||||
defaultMessage: 'The number of rows to show in the table',
|
||||
defaultMessage: 'Sets the maximum number of rows for the entire document table.',
|
||||
}),
|
||||
category: ['discover'],
|
||||
schema: schema.number(),
|
||||
},
|
||||
[SAMPLE_ROWS_PER_PAGE_SETTING]: {
|
||||
name: i18n.translate('discover.advancedSettings.sampleRowsPerPageTitle', {
|
||||
defaultMessage: 'Rows per page',
|
||||
}),
|
||||
value: DEFAULT_ROWS_PER_PAGE,
|
||||
options: ROWS_PER_PAGE_OPTIONS,
|
||||
type: 'select',
|
||||
description: i18n.translate('discover.advancedSettings.sampleRowsPerPageText', {
|
||||
defaultMessage: 'Limits the number of rows per page in the document table.',
|
||||
}),
|
||||
category: ['discover'],
|
||||
schema: schema.number(),
|
||||
|
|
|
@ -171,6 +171,10 @@ export const stackManagementSchema: MakeSchemaFrom<UsageStats> = {
|
|||
type: 'long',
|
||||
_meta: { description: 'Non-default value of setting.' },
|
||||
},
|
||||
'discover:sampleRowsPerPage': {
|
||||
type: 'long',
|
||||
_meta: { description: 'Non-default value of setting.' },
|
||||
},
|
||||
'discover:maxDocFieldsDisplayed': {
|
||||
type: 'long',
|
||||
_meta: { description: 'Non-default value of setting.' },
|
||||
|
|
|
@ -73,6 +73,7 @@ export interface UsageStats {
|
|||
'discover:searchOnPageLoad': boolean;
|
||||
'doc_table:hideTimeColumn': boolean;
|
||||
'discover:sampleSize': number;
|
||||
'discover:sampleRowsPerPage': number;
|
||||
defaultColumns: string[];
|
||||
'context:defaultSize': number;
|
||||
'context:tieBreakerFields': string[];
|
||||
|
|
|
@ -8020,6 +8020,12 @@
|
|||
"description": "Non-default value of setting."
|
||||
}
|
||||
},
|
||||
"discover:sampleRowsPerPage": {
|
||||
"type": "long",
|
||||
"_meta": {
|
||||
"description": "Non-default value of setting."
|
||||
}
|
||||
},
|
||||
"discover:maxDocFieldsDisplayed": {
|
||||
"type": "long",
|
||||
"_meta": {
|
||||
|
|
|
@ -10,6 +10,7 @@ import expect from '@kbn/expect';
|
|||
import { FtrProviderContext } from '../../ftr_provider_context';
|
||||
|
||||
export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||
const browser = getService('browser');
|
||||
const esArchiver = getService('esArchiver');
|
||||
const kibanaServer = getService('kibanaServer');
|
||||
const dataGrid = getService('dataGrid');
|
||||
|
@ -20,6 +21,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
|
||||
describe('discover data grid pagination', function describeIndexTests() {
|
||||
before(async () => {
|
||||
await browser.setWindowSize(1200, 2000);
|
||||
await esArchiver.loadIfNeeded('test/functional/fixtures/es_archiver/logstash_functional');
|
||||
await kibanaServer.importExport.load('test/functional/fixtures/kbn_archiver/discover');
|
||||
});
|
||||
|
@ -27,6 +29,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
after(async () => {
|
||||
await kibanaServer.importExport.unload('test/functional/fixtures/kbn_archiver/discover');
|
||||
await kibanaServer.uiSettings.replace({});
|
||||
await kibanaServer.savedObjects.clean({ types: ['search'] });
|
||||
});
|
||||
|
||||
beforeEach(async function () {
|
||||
|
@ -62,5 +65,55 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
await testSubjects.existOrFail('discoverTableSampleSizeSettingsLink');
|
||||
});
|
||||
});
|
||||
|
||||
it('should update pagination when rows per page is changed', async () => {
|
||||
const rows = await dataGrid.getDocTableRows();
|
||||
expect(rows.length).to.be.above(0);
|
||||
await testSubjects.existOrFail('pagination-button-0'); // first page
|
||||
await testSubjects.existOrFail('pagination-button-4'); // last page
|
||||
await testSubjects.click('tablePaginationPopoverButton');
|
||||
await retry.try(async function () {
|
||||
return testSubjects.exists('tablePagination-500-rows');
|
||||
});
|
||||
await testSubjects.click('tablePagination-500-rows');
|
||||
await retry.try(async function () {
|
||||
return !testSubjects.exists('pagination-button-1'); // only page 0 is left
|
||||
});
|
||||
await testSubjects.existOrFail('discoverTableFooter');
|
||||
});
|
||||
|
||||
it('should render exact number of rows which where configured in the saved search or in settings', async () => {
|
||||
await kibanaServer.uiSettings.update({
|
||||
...defaultSettings,
|
||||
'discover:sampleSize': 12,
|
||||
'discover:sampleRowsPerPage': 6,
|
||||
hideAnnouncements: true,
|
||||
});
|
||||
|
||||
// first render is based on settings value
|
||||
await PageObjects.common.navigateToApp('discover');
|
||||
await PageObjects.discover.waitUntilSearchingHasFinished();
|
||||
expect((await dataGrid.getDocTableRows()).length).to.be(6);
|
||||
await dataGrid.checkCurrentRowsPerPageToBe(6);
|
||||
|
||||
// now we change it via popover
|
||||
await dataGrid.changeRowsPerPageTo(10);
|
||||
|
||||
// save as a new search
|
||||
const savedSearchTitle = 'search with saved rowsPerPage';
|
||||
await PageObjects.discover.saveSearch(savedSearchTitle);
|
||||
|
||||
// start a new search session
|
||||
await testSubjects.click('discoverNewButton');
|
||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||
expect((await dataGrid.getDocTableRows()).length).to.be(6); // as in settings
|
||||
await dataGrid.checkCurrentRowsPerPageToBe(6);
|
||||
|
||||
// open the saved search
|
||||
await PageObjects.discover.loadSavedSearch(savedSearchTitle);
|
||||
await PageObjects.discover.waitUntilSearchingHasFinished();
|
||||
expect((await dataGrid.getDocTableRows()).length).to.be(10); // as in the saved search
|
||||
await dataGrid.checkCurrentRowsPerPageToBe(10);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
@ -0,0 +1,81 @@
|
|||
/*
|
||||
* 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 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 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
import expect from '@kbn/expect';
|
||||
import { FtrProviderContext } from '../../../ftr_provider_context';
|
||||
|
||||
export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||
const browser = getService('browser');
|
||||
const dataGrid = getService('dataGrid');
|
||||
const dashboardAddPanel = getService('dashboardAddPanel');
|
||||
const filterBar = getService('filterBar');
|
||||
const esArchiver = getService('esArchiver');
|
||||
const kibanaServer = getService('kibanaServer');
|
||||
const PageObjects = getPageObjects(['common', 'dashboard', 'header', 'timePicker', 'discover']);
|
||||
|
||||
describe('discover saved search embeddable', () => {
|
||||
before(async () => {
|
||||
await esArchiver.loadIfNeeded('test/functional/fixtures/es_archiver/logstash_functional');
|
||||
await esArchiver.loadIfNeeded('test/functional/fixtures/es_archiver/dashboard/current/data');
|
||||
await kibanaServer.savedObjects.cleanStandardList();
|
||||
await kibanaServer.importExport.load(
|
||||
'test/functional/fixtures/kbn_archiver/dashboard/current/kibana'
|
||||
);
|
||||
await kibanaServer.uiSettings.replace({
|
||||
defaultIndex: '0bf35f60-3dc9-11e8-8660-4d65aa086b3c',
|
||||
});
|
||||
await PageObjects.common.navigateToApp('dashboard');
|
||||
await filterBar.ensureFieldEditorModalIsClosed();
|
||||
await PageObjects.dashboard.gotoDashboardLandingPage();
|
||||
await PageObjects.dashboard.clickNewDashboard();
|
||||
await PageObjects.timePicker.setAbsoluteRange(
|
||||
'Sep 22, 2015 @ 00:00:00.000',
|
||||
'Sep 23, 2015 @ 00:00:00.000'
|
||||
);
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
await kibanaServer.savedObjects.cleanStandardList();
|
||||
});
|
||||
|
||||
const addSearchEmbeddableToDashboard = async () => {
|
||||
await dashboardAddPanel.addSavedSearch('Rendering-Test:-saved-search');
|
||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||
await PageObjects.dashboard.waitForRenderComplete();
|
||||
const rows = await dataGrid.getDocTableRows();
|
||||
expect(rows.length).to.be.above(0);
|
||||
};
|
||||
|
||||
const refreshDashboardPage = async () => {
|
||||
await browser.refresh();
|
||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||
await PageObjects.dashboard.waitForRenderComplete();
|
||||
};
|
||||
|
||||
it('can save a search embeddable with a defined rows per page number', async function () {
|
||||
const dashboardName = 'Dashboard with a Paginated Saved Search';
|
||||
await addSearchEmbeddableToDashboard();
|
||||
await dataGrid.checkCurrentRowsPerPageToBe(100);
|
||||
|
||||
await PageObjects.dashboard.saveDashboard(dashboardName, {
|
||||
waitDialogIsClosed: true,
|
||||
exitFromEditMode: false,
|
||||
});
|
||||
|
||||
await refreshDashboardPage();
|
||||
|
||||
await dataGrid.checkCurrentRowsPerPageToBe(100);
|
||||
|
||||
await dataGrid.changeRowsPerPageTo(10);
|
||||
|
||||
await PageObjects.dashboard.saveDashboard(dashboardName);
|
||||
await refreshDashboardPage();
|
||||
|
||||
await dataGrid.checkCurrentRowsPerPageToBe(10);
|
||||
});
|
||||
});
|
||||
}
|
|
@ -68,6 +68,7 @@ export default function ({ getService, loadTestFile }: FtrProviderContext) {
|
|||
loadTestFile(require.resolve('./_data_view_editor'));
|
||||
loadTestFile(require.resolve('./_hide_announcements'));
|
||||
loadTestFile(require.resolve('./classic/_hide_announcements'));
|
||||
loadTestFile(require.resolve('./embeddable/saved_search_embeddable'));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -325,4 +325,23 @@ export class DataGridService extends FtrService {
|
|||
public async hasNoResults() {
|
||||
return await this.find.existsByCssSelector('.euiDataGrid__noResults');
|
||||
}
|
||||
|
||||
public async checkCurrentRowsPerPageToBe(value: number) {
|
||||
await this.retry.try(async () => {
|
||||
return (
|
||||
(await this.testSubjects.getVisibleText('tablePaginationPopoverButton')) ===
|
||||
`Rows per page: ${value}`
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
public async changeRowsPerPageTo(newValue: number) {
|
||||
await this.testSubjects.click('tablePaginationPopoverButton');
|
||||
const option = `tablePagination-${newValue}-rows`;
|
||||
await this.retry.try(async () => {
|
||||
return this.testSubjects.exists(option);
|
||||
});
|
||||
await this.testSubjects.click(option);
|
||||
await this.checkCurrentRowsPerPageToBe(newValue);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2896,8 +2896,6 @@
|
|||
"discover.advancedSettings.params.maxCellHeightTitle": "Hauteur de cellule maximale dans le tableau classique",
|
||||
"discover.advancedSettings.params.rowHeightText": "Nombre de sous-lignes à autoriser dans une ligne. La valeur -1 ajuste automatiquement la hauteur de ligne selon le contenu. La valeur 0 affiche le contenu en une seule ligne.",
|
||||
"discover.advancedSettings.params.rowHeightTitle": "Hauteur de ligne dans l'explorateur de documents",
|
||||
"discover.advancedSettings.sampleSizeText": "Le nombre de lignes à afficher dans le tableau",
|
||||
"discover.advancedSettings.sampleSizeTitle": "Nombre de lignes",
|
||||
"discover.advancedSettings.searchOnPageLoadText": "Détermine si une recherche est exécutée lors du premier chargement de Discover. Ce paramètre n'a pas d'effet lors du chargement d’une recherche enregistrée.",
|
||||
"discover.advancedSettings.searchOnPageLoadTitle": "Recherche au chargement de la page",
|
||||
"discover.advancedSettings.sortDefaultOrderText": "Détermine le sens de tri par défaut pour les vues de données temporelles dans l'application Discover.",
|
||||
|
|
|
@ -2896,8 +2896,6 @@
|
|||
"discover.advancedSettings.params.maxCellHeightTitle": "クラシック表の最大セル高さ",
|
||||
"discover.advancedSettings.params.rowHeightText": "行に追加できる線数。値-1は、コンテンツに合わせて、行の高さを自動的に調整します。値0はコンテンツが1行に表示されます。",
|
||||
"discover.advancedSettings.params.rowHeightTitle": "ドキュメントエクスプローラーの行高さ",
|
||||
"discover.advancedSettings.sampleSizeText": "表に表示する行数です",
|
||||
"discover.advancedSettings.sampleSizeTitle": "行数",
|
||||
"discover.advancedSettings.searchOnPageLoadText": "Discover の最初の読み込み時に検索を実行するかを制御します。この設定は、保存された検索の読み込み時には影響しません。",
|
||||
"discover.advancedSettings.searchOnPageLoadTitle": "ページの読み込み時の検索",
|
||||
"discover.advancedSettings.sortDefaultOrderText": "Discover アプリのデータビューに基づく時刻のデフォルトの並べ替え方向をコントロールします。",
|
||||
|
|
|
@ -2898,8 +2898,6 @@
|
|||
"discover.advancedSettings.params.maxCellHeightTitle": "经典表中的最大单元格高度",
|
||||
"discover.advancedSettings.params.rowHeightText": "一行中允许的文本行数。值为 -1 时,会自动调整行高以适应内容。值为 0 时,会在单文本行中显示内容。",
|
||||
"discover.advancedSettings.params.rowHeightTitle": "Document Explorer 中的行高",
|
||||
"discover.advancedSettings.sampleSizeText": "要在表中显示的行数目",
|
||||
"discover.advancedSettings.sampleSizeTitle": "行数目",
|
||||
"discover.advancedSettings.searchOnPageLoadText": "控制在 Discover 首次加载时是否执行搜索。加载已保存搜索时,此设置无效。",
|
||||
"discover.advancedSettings.searchOnPageLoadTitle": "在页面加载时搜索",
|
||||
"discover.advancedSettings.sortDefaultOrderText": "在 Discover 应用中控制基于时间的数据视图的默认排序方向。",
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue