@@ -262,111 +349,103 @@ function DiscoverDocumentsComponent({
}
return (
-
-
-
-
-
-
- {!!documentState.interceptedWarnings?.length && (
-
- )}
- {isLegacy && rows && rows.length > 0 && (
- <>
- {!hideAnnouncements && }
-
- >
- )}
- {!isLegacy && (
+ <>
+ {isLegacy && (
<>
- {!hideAnnouncements && !isTextBasedQuery && (
-
-
-
- )}
-
-
-
-
-
+ {viewModeToggle}
+ {callouts}
>
)}
- {isDataLoading && (
-
- )}
-
+
+
+
+
+
+
+ {isLegacy && (
+ <>
+ {rows && rows.length > 0 && (
+ <>
+ {!hideAnnouncements && }
+
+ >
+ )}
+ {loadingIndicator}
+ >
+ )}
+ {!isLegacy && (
+ <>
+
+
+
+
+
+ >
+ )}
+
+ >
);
}
diff --git a/src/plugins/discover/public/application/main/components/layout/discover_layout.scss b/src/plugins/discover/public/application/main/components/layout/discover_layout.scss
index d3978fe1c1d82..55972b4f7f629 100644
--- a/src/plugins/discover/public/application/main/components/layout/discover_layout.scss
+++ b/src/plugins/discover/public/application/main/components/layout/discover_layout.scss
@@ -32,16 +32,6 @@ discover-app {
height: 100%;
}
-.dscSidebarResizeButton {
- background-color: transparent !important;
-
- &:not(:hover):not(:focus) {
- &:before, &:after {
- width: 0;
- }
- }
-}
-
.dscPageContent__wrapper {
overflow: hidden; // Ensures horizontal scroll of table
display: flex;
@@ -53,10 +43,6 @@ discover-app {
position: relative;
overflow: hidden;
height: 100%;
-
- .euiDataGrid__controls {
- border-top: none;
- }
}
.dscPageContent--centered {
diff --git a/src/plugins/discover/public/application/main/components/layout/discover_main_content.test.tsx b/src/plugins/discover/public/application/main/components/layout/discover_main_content.test.tsx
index 2901b49de1586..b12208cc76299 100644
--- a/src/plugins/discover/public/application/main/components/layout/discover_main_content.test.tsx
+++ b/src/plugins/discover/public/application/main/components/layout/discover_main_content.test.tsx
@@ -125,12 +125,17 @@ describe('Discover main content component', () => {
describe('DocumentViewModeToggle', () => {
it('should show DocumentViewModeToggle when isPlainRecord is false', async () => {
const component = await mountComponent();
- expect(component.find(DocumentViewModeToggle).exists()).toBe(true);
+ expect(component.find(DiscoverDocuments).prop('viewModeToggle')).toBeDefined();
});
it('should not show DocumentViewModeToggle when isPlainRecord is true', async () => {
const component = await mountComponent({ isPlainRecord: true });
- expect(component.find(DocumentViewModeToggle).exists()).toBe(false);
+ expect(component.find(DiscoverDocuments).prop('viewModeToggle')).toBeUndefined();
+ });
+
+ it('should show DocumentViewModeToggle for Field Statistics', async () => {
+ const component = await mountComponent({ viewMode: VIEW_MODE.AGGREGATED_LEVEL });
+ expect(component.find(DocumentViewModeToggle).exists()).toBe(true);
});
});
diff --git a/src/plugins/discover/public/application/main/components/layout/discover_main_content.tsx b/src/plugins/discover/public/application/main/components/layout/discover_main_content.tsx
index e241a52b1d259..8b6ff5880d3dc 100644
--- a/src/plugins/discover/public/application/main/components/layout/discover_main_content.tsx
+++ b/src/plugins/discover/public/application/main/components/layout/discover_main_content.tsx
@@ -6,10 +6,9 @@
* Side Public License, v 1.
*/
-import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
+import { EuiFlexGroup, EuiFlexItem, EuiHorizontalRule } from '@elastic/eui';
import { DragDrop, type DropType, DropOverlayWrapper } from '@kbn/dom-drag-drop';
-import useObservable from 'react-use/lib/useObservable';
-import React, { useCallback } from 'react';
+import React, { useCallback, useMemo } from 'react';
import { DataView } from '@kbn/data-views-plugin/common';
import { METRIC_TYPE } from '@kbn/analytics';
import { i18n } from '@kbn/i18n';
@@ -21,9 +20,7 @@ import { DiscoverStateContainer } from '../../services/discover_state';
import { FieldStatisticsTab } from '../field_stats_table';
import { DiscoverDocuments } from './discover_documents';
import { DOCUMENTS_VIEW_CLICK, FIELD_STATISTICS_VIEW_CLICK } from '../field_stats_table/constants';
-import { ErrorCallout } from '../../../../components/common/error_callout';
-import { useDataState } from '../../hooks/use_data_state';
-import { SelectedVSAvailableCallout } from './selected_vs_available_callout';
+import { useAppStateSelector } from '../../services/discover_app_state_container';
const DROP_PROPS = {
value: {
@@ -76,10 +73,16 @@ export const DiscoverMainContent = ({
[trackUiMetric, stateContainer]
);
- const dataState = useDataState(stateContainer.dataState.data$.main$);
- const documents = useObservable(stateContainer.dataState.data$.documents$);
const isDropAllowed = Boolean(onDropFieldToTable);
+ const viewModeToggle = useMemo(() => {
+ return !isPlainRecord ? (
+
+ ) : undefined;
+ }, [viewMode, setDiscoverViewMode, isPlainRecord]);
+
+ const showChart = useAppStateSelector((state) => !state.hideChart);
+
return (
-
- {!isPlainRecord && (
-
- )}
-
- {dataState.error && (
-
- )}
-
-
+ {showChart && }
{viewMode === VIEW_MODE.DOCUMENT_LEVEL ? (
) : (
-
+ <>
+ {viewModeToggle}
+
+ >
)}
diff --git a/src/plugins/discover/public/application/main/components/layout/discover_resizable_layout.tsx b/src/plugins/discover/public/application/main/components/layout/discover_resizable_layout.tsx
index 32491a38d86fd..e0859617f0057 100644
--- a/src/plugins/discover/public/application/main/components/layout/discover_resizable_layout.tsx
+++ b/src/plugins/discover/public/application/main/components/layout/discover_resizable_layout.tsx
@@ -71,7 +71,6 @@ export const DiscoverResizableLayout = ({
minFlexPanelSize={minMainPanelWidth}
fixedPanel={}
flexPanel={}
- resizeButtonClassName="dscSidebarResizeButton"
data-test-subj="discoverLayout"
onFixedPanelSizeChange={setSidebarWidth}
/>
diff --git a/src/plugins/discover/public/components/discover_grid/__snapshots__/render_custom_toolbar.test.tsx.snap b/src/plugins/discover/public/components/discover_grid/__snapshots__/render_custom_toolbar.test.tsx.snap
new file mode 100644
index 0000000000000..9f2af58f1dccb
--- /dev/null
+++ b/src/plugins/discover/public/components/discover_grid/__snapshots__/render_custom_toolbar.test.tsx.snap
@@ -0,0 +1,237 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`renderCustomToolbar should render correctly for smaller screens 1`] = `
+
+
+
+
+
+
+
+
+
+
+ keyboard
+
+
+ display
+
+
+ fullScreen
+
+
+
+
+
+
+
+`;
+
+exports[`renderCustomToolbar should render correctly with an element 1`] = `
+
+
+
+
+ left
+
+
+
+
+
+
+
+ additional
+
+
+
+
+ column
+
+
+
+
+ columnSorting
+
+
+
+
+
+
+ keyboard
+
+
+ display
+
+
+ fullScreen
+
+
+
+
+
+
+
+
+`;
+
+exports[`renderCustomToolbar should render successfully 1`] = `
+
+
+
+
+
+
+
+ column
+
+
+
+
+ columnSorting
+
+
+
+
+ additional
+
+
+
+
+
+
+
+
+
+
+ keyboard
+
+
+ display
+
+
+ fullScreen
+
+
+
+
+
+
+
+`;
diff --git a/src/plugins/discover/public/components/discover_grid/discover_grid.tsx b/src/plugins/discover/public/components/discover_grid/discover_grid.tsx
new file mode 100644
index 0000000000000..fe2586e32f895
--- /dev/null
+++ b/src/plugins/discover/public/components/discover_grid/discover_grid.tsx
@@ -0,0 +1,20 @@
+/*
+ * 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 React from 'react';
+import { UnifiedDataTable, type UnifiedDataTableProps } from '@kbn/unified-data-table';
+import { renderCustomToolbar } from './render_custom_toolbar';
+
+/**
+ * Customized version of the UnifiedDataTable
+ * @param props
+ * @constructor
+ */
+export const DiscoverGrid: React.FC = (props) => {
+ return ;
+};
diff --git a/src/plugins/discover/public/components/discover_grid/index.ts b/src/plugins/discover/public/components/discover_grid/index.ts
new file mode 100644
index 0000000000000..b9057e101ee9e
--- /dev/null
+++ b/src/plugins/discover/public/components/discover_grid/index.ts
@@ -0,0 +1,9 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 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 { DiscoverGrid } from './discover_grid';
diff --git a/src/plugins/discover/public/components/discover_grid/render_custom_toolbar.scss b/src/plugins/discover/public/components/discover_grid/render_custom_toolbar.scss
new file mode 100644
index 0000000000000..e24f7f8c6fcb1
--- /dev/null
+++ b/src/plugins/discover/public/components/discover_grid/render_custom_toolbar.scss
@@ -0,0 +1,61 @@
+.dscGridToolbar {
+ padding: $euiSizeS $euiSizeS $euiSizeXS;
+}
+
+.dscGridToolbarControlButton .euiDataGrid__controlBtn {
+ block-size: $euiSizeXL;
+ border: $euiBorderThin;
+ border-radius: $euiBorderRadiusSmall;
+
+ // making the icons larger than the default size
+ & svg {
+ inline-size: $euiSize;
+ block-size: $euiSize;
+ }
+
+ // cancel default background and font changes
+ &.euiDataGrid__controlBtn--active {
+ font-weight: $euiFontWeightMedium;
+ }
+ &:active, &:focus {
+ background: transparent;
+ }
+
+ // add toolbar control animation
+ transition: transform $euiAnimSpeedNormal ease-in-out;
+ &:hover {
+ transform: translateY(-1px);
+ }
+ &:active {
+ transform: translateY(0);
+ }
+}
+
+.dscGridToolbarControlGroup {
+ box-shadow: inset 0 0 0 $euiBorderWidthThin $euiBorderColor;
+ border-radius: $euiBorderRadiusSmall;
+ display: inline-flex;
+ align-items: stretch;
+ flex-direction: row;
+}
+
+.dscGridToolbarControlIconButton .euiButtonIcon {
+ inline-size: $euiSizeXL;
+ block-size: $euiSizeXL;
+
+ // cancel default behaviour
+ &:hover, &:active, &:focus {
+ background: transparent;
+ animation: none !important;
+ transform: none !important;
+ }
+
+ .dscGridToolbarControlIconButton + & {
+ border-inline-start: $euiBorderThin;
+ border-radius: 0;
+ }
+}
+
+.dscGridToolbarBottom {
+ position: relative; // for placing a loading indicator correctly
+}
diff --git a/src/plugins/discover/public/components/discover_grid/render_custom_toolbar.test.tsx b/src/plugins/discover/public/components/discover_grid/render_custom_toolbar.test.tsx
new file mode 100644
index 0000000000000..3b8a4bb9457f9
--- /dev/null
+++ b/src/plugins/discover/public/components/discover_grid/render_custom_toolbar.test.tsx
@@ -0,0 +1,63 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 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 React from 'react';
+import { renderCustomToolbar, getRenderCustomToolbarWithElements } from './render_custom_toolbar';
+
+describe('renderCustomToolbar', () => {
+ it('should render successfully', () => {
+ expect(
+ renderCustomToolbar({
+ toolbarProps: {
+ hasRoomForGridControls: true,
+ columnControl: 'column',
+ columnSortingControl: 'columnSorting',
+ displayControl: 'display',
+ fullScreenControl: 'fullScreen',
+ keyboardShortcutsControl: 'keyboard',
+ },
+ gridProps: { additionalControls: 'additional' },
+ })
+ ).toMatchSnapshot();
+ });
+
+ it('should render correctly for smaller screens', () => {
+ expect(
+ renderCustomToolbar({
+ toolbarProps: {
+ hasRoomForGridControls: false,
+ columnControl: 'column',
+ columnSortingControl: 'columnSorting',
+ displayControl: 'display',
+ fullScreenControl: 'fullScreen',
+ keyboardShortcutsControl: 'keyboard',
+ },
+ gridProps: { additionalControls: 'additional' },
+ })
+ ).toMatchSnapshot();
+ });
+
+ it('should render correctly with an element', () => {
+ expect(
+ getRenderCustomToolbarWithElements({
+ leftSide: left
,
+ bottomSection: bottom
,
+ })({
+ toolbarProps: {
+ hasRoomForGridControls: true,
+ columnControl: 'column',
+ columnSortingControl: 'columnSorting',
+ displayControl: 'display',
+ fullScreenControl: 'fullScreen',
+ keyboardShortcutsControl: 'keyboard',
+ },
+ gridProps: { additionalControls: 'additional' },
+ })
+ ).toMatchSnapshot();
+ });
+});
diff --git a/src/plugins/discover/public/components/discover_grid/render_custom_toolbar.tsx b/src/plugins/discover/public/components/discover_grid/render_custom_toolbar.tsx
new file mode 100644
index 0000000000000..2baeb4c287a16
--- /dev/null
+++ b/src/plugins/discover/public/components/discover_grid/render_custom_toolbar.tsx
@@ -0,0 +1,129 @@
+/*
+ * 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 React from 'react';
+import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
+import type {
+ UnifiedDataTableRenderCustomToolbarProps,
+ UnifiedDataTableRenderCustomToolbar,
+} from '@kbn/unified-data-table';
+import './render_custom_toolbar.scss';
+
+interface RenderCustomToolbarProps extends UnifiedDataTableRenderCustomToolbarProps {
+ leftSide?: React.ReactElement;
+ bottomSection?: React.ReactElement;
+}
+
+export const renderCustomToolbar = (props: RenderCustomToolbarProps): React.ReactElement => {
+ const {
+ leftSide,
+ bottomSection,
+ toolbarProps: {
+ hasRoomForGridControls,
+ columnControl,
+ columnSortingControl,
+ fullScreenControl,
+ keyboardShortcutsControl,
+ displayControl,
+ },
+ gridProps: { additionalControls },
+ } = props;
+
+ const buttons = hasRoomForGridControls ? (
+ <>
+ {leftSide && additionalControls && (
+
+ {additionalControls}
+
+ )}
+ {columnControl && (
+
+ {columnControl}
+
+ )}
+ {columnSortingControl && (
+
+ {columnSortingControl}
+
+ )}
+ {!leftSide && additionalControls && (
+
+ {additionalControls}
+
+ )}
+ >
+ ) : null;
+
+ return (
+ <>
+
+
+ {leftSide || (
+
+ {buttons}
+
+ )}
+
+
+
+ {Boolean(leftSide) && buttons}
+ {(keyboardShortcutsControl || displayControl || fullScreenControl) && (
+
+
+ {keyboardShortcutsControl && (
+
+ {keyboardShortcutsControl}
+
+ )}
+ {displayControl && (
+
{displayControl}
+ )}
+ {fullScreenControl && (
+
{fullScreenControl}
+ )}
+
+
+ )}
+
+
+
+ {bottomSection ? (
+
+ {bottomSection}
+
+ ) : null}
+ >
+ );
+};
+
+/**
+ * Render custom element on the left side and all controls to the right
+ */
+export const getRenderCustomToolbarWithElements = ({
+ leftSide,
+ bottomSection,
+}: {
+ leftSide?: React.ReactElement;
+ bottomSection?: React.ReactElement;
+}): UnifiedDataTableRenderCustomToolbar => {
+ const reservedSpace = <>>;
+ return (props) =>
+ renderCustomToolbar({
+ ...props,
+ leftSide: leftSide || reservedSpace,
+ bottomSection,
+ });
+};
diff --git a/src/plugins/discover/public/components/doc_table/_doc_table.scss b/src/plugins/discover/public/components/doc_table/_doc_table.scss
index 4553cdc05fdad..8a9b629a9694b 100644
--- a/src/plugins/discover/public/components/doc_table/_doc_table.scss
+++ b/src/plugins/discover/public/components/doc_table/_doc_table.scss
@@ -4,6 +4,7 @@
// stylelint-disable selector-no-qualifying-type
.kbnDocTableWrapper {
@include euiScrollBar;
+ @include euiOverflowShadow;
overflow: auto;
display: flex;
flex: 1 1 100%;
diff --git a/src/plugins/discover/public/components/view_mode_toggle/view_mode_toggle.tsx b/src/plugins/discover/public/components/view_mode_toggle/view_mode_toggle.tsx
index 63fcbcc40db37..79c9213e76395 100644
--- a/src/plugins/discover/public/components/view_mode_toggle/view_mode_toggle.tsx
+++ b/src/plugins/discover/public/components/view_mode_toggle/view_mode_toggle.tsx
@@ -6,11 +6,11 @@
* Side Public License, v 1.
*/
-import React from 'react';
+import React, { useMemo } from 'react';
import { EuiTab, EuiTabs, useEuiTheme } from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n-react';
import { css } from '@emotion/react';
-import { SHOW_FIELD_STATISTICS } from '@kbn/discover-utils';
+import { DOC_TABLE_LEGACY, SHOW_FIELD_STATISTICS } from '@kbn/discover-utils';
import { VIEW_MODE } from '../../../common/constants';
import { useDiscoverServices } from '../../hooks/use_discover_services';
@@ -23,9 +23,16 @@ export const DocumentViewModeToggle = ({
}) => {
const { euiTheme } = useEuiTheme();
const { uiSettings } = useDiscoverServices();
+ const isLegacy = useMemo(() => uiSettings.get(DOC_TABLE_LEGACY), [uiSettings]);
+ const includesNormalTabsStyle = viewMode === VIEW_MODE.AGGREGATED_LEVEL || isLegacy;
+ const tabsPadding = includesNormalTabsStyle ? euiTheme.size.s : 0;
const tabsCss = css`
- padding: 0 ${euiTheme.size.s};
+ padding: ${tabsPadding} ${tabsPadding} 0 ${tabsPadding};
+
+ .euiTab__content {
+ line-height: ${euiTheme.size.xl};
+ }
`;
const showViewModeToggle = uiSettings.get(SHOW_FIELD_STATISTICS) ?? false;
@@ -35,11 +42,10 @@ export const DocumentViewModeToggle = ({
}
return (
-
+
setDiscoverViewMode(VIEW_MODE.DOCUMENT_LEVEL)}
- className="dscViewModeToggle__tab"
data-test-subj="dscViewModeDocumentButton"
>
@@ -47,7 +53,6 @@ export const DocumentViewModeToggle = ({
setDiscoverViewMode(VIEW_MODE.AGGREGATED_LEVEL)}
- className="dscViewModeToggle__tab"
data-test-subj="dscViewModeFieldStatsButton"
>
data-test-subj={dataTestSubj}
>
{isLoading && }
-
-
- {Boolean(prepend) && {prepend}}
- {!!totalHitCount && (
-
-
-
- )}
-
-
+ {Boolean(prepend || totalHitCount) && (
+
+
+ {Boolean(prepend) && {prepend}}
+
+ {!!totalHitCount && (
+
+
+
+ )}
+
+
+ )}
{children}
diff --git a/src/plugins/discover/public/embeddable/saved_search_embeddable_component.tsx b/src/plugins/discover/public/embeddable/saved_search_embeddable_component.tsx
index 43085e3c0902e..b9bd2112f6ee6 100644
--- a/src/plugins/discover/public/embeddable/saved_search_embeddable_component.tsx
+++ b/src/plugins/discover/public/embeddable/saved_search_embeddable_component.tsx
@@ -47,7 +47,6 @@ export function SavedSearchEmbeddableComponent({
sampleSizeState={fetchedSampleSize}
loadingState={searchProps.isLoading ? DataLoadingState.loading : DataLoadingState.loaded}
showFullScreenButton={false}
- showColumnTokens
query={query}
className="unifiedDataTable"
/>
diff --git a/src/plugins/discover/public/embeddable/saved_search_grid.tsx b/src/plugins/discover/public/embeddable/saved_search_grid.tsx
index 1cadf5414f8a3..9b0653bd63352 100644
--- a/src/plugins/discover/public/embeddable/saved_search_grid.tsx
+++ b/src/plugins/discover/public/embeddable/saved_search_grid.tsx
@@ -5,21 +5,22 @@
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
-import React, { useCallback, useState } from 'react';
+import React, { useCallback, useMemo, useState } from 'react';
import type { DataTableRecord } from '@kbn/discover-utils/types';
import { AggregateQuery, Query } from '@kbn/es-query';
import type { SearchResponseInterceptedWarning } from '@kbn/search-response-warnings';
+import { MAX_DOC_FIELDS_DISPLAYED, ROW_HEIGHT_OPTION, SHOW_MULTIFIELDS } from '@kbn/discover-utils';
import {
- DataLoadingState as DiscoverGridLoadingState,
- UnifiedDataTable,
+ type UnifiedDataTableProps,
type DataTableColumnTypes,
+ DataLoadingState as DiscoverGridLoadingState,
} from '@kbn/unified-data-table';
-import type { UnifiedDataTableProps } from '@kbn/unified-data-table';
+import { DiscoverGrid } from '../components/discover_grid';
import './saved_search_grid.scss';
-import { MAX_DOC_FIELDS_DISPLAYED, ROW_HEIGHT_OPTION, SHOW_MULTIFIELDS } from '@kbn/discover-utils';
import { DiscoverGridFlyout } from '../components/discover_grid_flyout';
import { SavedSearchEmbeddableBase } from './saved_search_embeddable_base';
-import { DISCOVER_TOUR_STEP_ANCHOR_IDS } from '../components/discover_tour';
+import { getRenderCustomToolbarWithElements } from '../components/discover_grid/render_custom_toolbar';
+import { TotalDocuments } from '../application/main/components/total_documents/total_documents';
export interface DiscoverGridEmbeddableProps
extends Omit {
@@ -32,7 +33,7 @@ export interface DiscoverGridEmbeddableProps
savedSearchId?: string;
}
-export const DiscoverGridMemoized = React.memo(UnifiedDataTable);
+export const DiscoverGridMemoized = React.memo(DiscoverGrid);
export function DiscoverGridEmbeddable(props: DiscoverGridEmbeddableProps) {
const { interceptedWarnings, ...gridProps } = props;
@@ -71,9 +72,20 @@ export function DiscoverGridEmbeddable(props: DiscoverGridEmbeddableProps) {
]
);
+ const renderCustomToolbar = useMemo(
+ () =>
+ getRenderCustomToolbarWithElements({
+ leftSide:
+ typeof props.totalHitCount === 'number' ? (
+
+ ) : undefined,
+ }),
+ [props.totalHitCount]
+ );
+
return (
);
diff --git a/test/functional/apps/discover/embeddable/_saved_search_embeddable.ts b/test/functional/apps/discover/embeddable/_saved_search_embeddable.ts
index 2fb99d9ebb43f..03f40c5b6ebcf 100644
--- a/test/functional/apps/discover/embeddable/_saved_search_embeddable.ts
+++ b/test/functional/apps/discover/embeddable/_saved_search_embeddable.ts
@@ -145,5 +145,10 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
await addSearchEmbeddableToDashboard();
await testSubjects.missingOrFail('dataGridFullScreenButton');
});
+
+ it('should show the the grid toolbar', async () => {
+ await addSearchEmbeddableToDashboard();
+ await testSubjects.existOrFail('dscGridToolbar');
+ });
});
}
diff --git a/test/functional/apps/discover/group2/_data_grid.ts b/test/functional/apps/discover/group2/_data_grid.ts
index 58052ce6665ca..d869044613873 100644
--- a/test/functional/apps/discover/group2/_data_grid.ts
+++ b/test/functional/apps/discover/group2/_data_grid.ts
@@ -46,5 +46,9 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
await PageObjects.unifiedFieldList.clickFieldListItemRemove('agent');
expect(await getTitles()).to.be('@timestamp Document');
});
+
+ it('should show the the grid toolbar', async () => {
+ await testSubjects.existOrFail('dscGridToolbar');
+ });
});
}
diff --git a/test/functional/apps/discover/group2/_data_grid_context.ts b/test/functional/apps/discover/group2/_data_grid_context.ts
index ae5030f226b82..e8e218625687b 100644
--- a/test/functional/apps/discover/group2/_data_grid_context.ts
+++ b/test/functional/apps/discover/group2/_data_grid_context.ts
@@ -97,6 +97,10 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
expect(disabledFilterCounter).to.be(TEST_FILTER_COLUMN_NAMES.length);
});
+ it('should show the the grid toolbar', async () => {
+ await testSubjects.existOrFail('dscGridToolbar');
+ });
+
it('navigates to context view from embeddable', async () => {
await PageObjects.common.navigateToApp('discover');
await PageObjects.discover.saveSearch('my search');
diff --git a/test/functional/apps/discover/group3/_view_mode_toggle.ts b/test/functional/apps/discover/group3/_view_mode_toggle.ts
new file mode 100644
index 0000000000000..c47aad66c9a01
--- /dev/null
+++ b/test/functional/apps/discover/group3/_view_mode_toggle.ts
@@ -0,0 +1,130 @@
+/*
+ * 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 PageObjects = getPageObjects([
+ 'common',
+ 'discover',
+ 'timePicker',
+ 'dashboard',
+ 'unifiedFieldList',
+ 'header',
+ ]);
+ const esArchiver = getService('esArchiver');
+ const retry = getService('retry');
+ const testSubjects = getService('testSubjects');
+ const queryBar = getService('queryBar');
+ const kibanaServer = getService('kibanaServer');
+ const security = getService('security');
+ const defaultSettings = {
+ defaultIndex: 'logstash-*',
+ };
+
+ describe('discover view mode toggle', function () {
+ before(async () => {
+ await security.testUser.setRoles(['kibana_admin', 'test_logstash_reader']);
+ await esArchiver.loadIfNeeded('test/functional/fixtures/es_archiver/logstash_functional');
+ await kibanaServer.importExport.load('test/functional/fixtures/kbn_archiver/discover');
+ });
+
+ after(async () => {
+ await kibanaServer.importExport.unload('test/functional/fixtures/kbn_archiver/discover');
+ await esArchiver.unload('test/functional/fixtures/es_archiver/logstash_functional');
+ await kibanaServer.savedObjects.cleanStandardList();
+ });
+
+ [true, false].forEach((useLegacyTable) => {
+ describe(`isLegacy: ${useLegacyTable}`, function () {
+ before(async function () {
+ await PageObjects.timePicker.setDefaultAbsoluteRangeViaUiSettings();
+ await kibanaServer.uiSettings.update({
+ ...defaultSettings,
+ 'doc_table:legacy': useLegacyTable,
+ });
+ await PageObjects.common.navigateToApp('discover');
+ await PageObjects.discover.waitUntilSearchingHasFinished();
+ });
+
+ after(async () => {
+ await kibanaServer.uiSettings.replace({});
+ });
+
+ it('should show Documents tab', async () => {
+ await testSubjects.existOrFail('dscViewModeToggle');
+
+ if (!useLegacyTable) {
+ await testSubjects.existOrFail('dscGridToolbar');
+ }
+
+ const documentsTab = await testSubjects.find('dscViewModeDocumentButton');
+ expect(await documentsTab.getAttribute('aria-selected')).to.be('true');
+ });
+
+ it('should show Document Explorer info callout', async () => {
+ await testSubjects.existOrFail(
+ useLegacyTable ? 'dscDocumentExplorerLegacyCallout' : 'dscDocumentExplorerTourCallout'
+ );
+ });
+
+ it('should show an error callout', async () => {
+ await queryBar.setQuery('@message::'); // invalid
+ await queryBar.submitQuery();
+ await PageObjects.header.waitUntilLoadingHasFinished();
+
+ await testSubjects.existOrFail('discoverMainError');
+
+ await queryBar.clearQuery();
+ await queryBar.submitQuery();
+ await PageObjects.header.waitUntilLoadingHasFinished();
+
+ await testSubjects.missingOrFail('discoverMainError');
+ });
+
+ it('should show Field Statistics tab', async () => {
+ await testSubjects.click('dscViewModeFieldStatsButton');
+
+ await retry.try(async () => {
+ const fieldStatsTab = await testSubjects.find('dscViewModeFieldStatsButton');
+ expect(await fieldStatsTab.getAttribute('aria-selected')).to.be('true');
+ });
+
+ await testSubjects.existOrFail('dscViewModeToggle');
+ });
+
+ it('should not show view mode toggle for text-based searches', async () => {
+ await testSubjects.click('dscViewModeDocumentButton');
+
+ await retry.try(async () => {
+ const documentsTab = await testSubjects.find('dscViewModeDocumentButton');
+ expect(await documentsTab.getAttribute('aria-selected')).to.be('true');
+ });
+
+ await testSubjects.existOrFail('dscViewModeToggle');
+
+ await PageObjects.discover.selectTextBaseLang();
+
+ await testSubjects.missingOrFail('dscViewModeToggle');
+
+ if (!useLegacyTable) {
+ await testSubjects.existOrFail('dscGridToolbar');
+ }
+ });
+
+ it('should show text-based columns callout', async () => {
+ await testSubjects.missingOrFail('dscSelectedColumnsCallout');
+ await PageObjects.unifiedFieldList.clickFieldListItemAdd('extension');
+ await PageObjects.header.waitUntilLoadingHasFinished();
+ await testSubjects.existOrFail('dscSelectedColumnsCallout');
+ });
+ });
+ });
+ });
+}
diff --git a/test/functional/apps/discover/group3/index.ts b/test/functional/apps/discover/group3/index.ts
index 9af02c006b14b..5827c1e7ed805 100644
--- a/test/functional/apps/discover/group3/index.ts
+++ b/test/functional/apps/discover/group3/index.ts
@@ -24,5 +24,6 @@ export default function ({ getService, loadTestFile }: FtrProviderContext) {
loadTestFile(require.resolve('./_sidebar'));
loadTestFile(require.resolve('./_request_counts'));
loadTestFile(require.resolve('./_doc_viewer'));
+ loadTestFile(require.resolve('./_view_mode_toggle'));
});
}
diff --git a/x-pack/plugins/translations/translations/fr-FR.json b/x-pack/plugins/translations/translations/fr-FR.json
index 6ed84d45aff89..3b9767376293e 100644
--- a/x-pack/plugins/translations/translations/fr-FR.json
+++ b/x-pack/plugins/translations/translations/fr-FR.json
@@ -2445,7 +2445,6 @@
"unifiedDataTable.tableHeader.timeFieldIconTooltipAriaLabel": "{timeFieldName} – Ce champ représente l'heure à laquelle les événements se sont produits.",
"unifiedDataTable.searchGenerationWithDescription": "Tableau généré par la recherche {searchTitle}",
"unifiedDataTable.searchGenerationWithDescriptionGrid": "Tableau généré par la recherche {searchTitle} ({searchDescription})",
- "unifiedDataTable.selectedDocumentsNumber": "{nr} documents sélectionnés",
"unifiedDataTable.clearSelection": "Effacer la sélection",
"unifiedDataTable.controlColumnHeader": "Colonne de commande",
"unifiedDataTable.copyToClipboardJSON": "Copier les documents dans le presse-papiers (JSON)",
diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json
index 15d66275a00ba..def22f2a7011e 100644
--- a/x-pack/plugins/translations/translations/ja-JP.json
+++ b/x-pack/plugins/translations/translations/ja-JP.json
@@ -2460,7 +2460,6 @@
"unifiedDataTable.tableHeader.timeFieldIconTooltipAriaLabel": "{timeFieldName} - このフィールドはイベントの発生時刻を表します。",
"unifiedDataTable.searchGenerationWithDescription": "検索{searchTitle}で生成されたテーブル",
"unifiedDataTable.searchGenerationWithDescriptionGrid": "検索{searchTitle}で生成されたテーブル({searchDescription})",
- "unifiedDataTable.selectedDocumentsNumber": "{nr}個のドキュメントが選択されました",
"unifiedDataTable.clearSelection": "選択した項目をクリア",
"unifiedDataTable.controlColumnHeader": "列の制御",
"unifiedDataTable.copyToClipboardJSON": "ドキュメントをクリップボードにコピー(JSON)",
diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json
index b3ee160e83978..a7db489a6cbc9 100644
--- a/x-pack/plugins/translations/translations/zh-CN.json
+++ b/x-pack/plugins/translations/translations/zh-CN.json
@@ -2460,7 +2460,6 @@
"unifiedDataTable.tableHeader.timeFieldIconTooltipAriaLabel": "{timeFieldName} - 此字段表示事件发生的时间。",
"unifiedDataTable.searchGenerationWithDescription": "搜索 {searchTitle} 生成的表",
"unifiedDataTable.searchGenerationWithDescriptionGrid": "搜索 {searchTitle} 生成的表({searchDescription})",
- "unifiedDataTable.selectedDocumentsNumber": "{nr} 个文档已选择",
"unifiedDataTable.clearSelection": "清除所选内容",
"unifiedDataTable.controlColumnHeader": "控制列",
"unifiedDataTable.copyToClipboardJSON": "将文档复制到剪贴板 (JSON)",