diff --git a/src/plugins/discover/public/application/angular/discover.js b/src/plugins/discover/public/application/angular/discover.js
index d492d7438695e..dcf86babaa5e1 100644
--- a/src/plugins/discover/public/application/angular/discover.js
+++ b/src/plugins/discover/public/application/angular/discover.js
@@ -24,7 +24,6 @@ import {
import { getSortArray } from './doc_table';
import * as columnActions from './doc_table/actions/columns';
import indexTemplateLegacy from './discover_legacy.html';
-import indexTemplateGrid from './discover_datagrid.html';
import { addHelpMenuToAppChrome } from '../components/help_menu/help_menu_util';
import { discoverResponseHandler } from './response_handler';
import {
@@ -112,9 +111,7 @@ app.config(($routeProvider) => {
};
const discoverRoute = {
...defaults,
- template: getServices().uiSettings.get('doc_table:legacy', true)
- ? indexTemplateLegacy
- : indexTemplateGrid,
+ template: indexTemplateLegacy,
reloadOnSearch: false,
resolve: {
savedObjects: function ($route, Promise) {
diff --git a/src/plugins/discover/public/application/angular/discover_legacy.html b/src/plugins/discover/public/application/angular/discover_legacy.html
index 9383980fd9fd6..76e5c568ffde6 100644
--- a/src/plugins/discover/public/application/angular/discover_legacy.html
+++ b/src/plugins/discover/public/application/angular/discover_legacy.html
@@ -1,5 +1,5 @@
-
-
+
diff --git a/src/plugins/discover/public/application/angular/doc_table/create_doc_table_react.tsx b/src/plugins/discover/public/application/angular/doc_table/create_doc_table_react.tsx
index 06b6e504832e4..cbd93feb835a0 100644
--- a/src/plugins/discover/public/application/angular/doc_table/create_doc_table_react.tsx
+++ b/src/plugins/discover/public/application/angular/doc_table/create_doc_table_react.tsx
@@ -9,8 +9,11 @@
import angular, { auto, ICompileService, IScope } from 'angular';
import { render } from 'react-dom';
import React, { useRef, useEffect } from 'react';
+import { EuiButtonEmpty } from '@elastic/eui';
+import { FormattedMessage } from '@kbn/i18n/react';
import { getServices, IIndexPattern } from '../../../kibana_services';
import { IndexPatternField } from '../../../../../data/common/index_patterns';
+
export type AngularScope = IScope;
export interface AngularDirective {
@@ -83,9 +86,11 @@ export interface DocTableLegacyProps {
indexPattern: IIndexPattern;
minimumVisibleRows: number;
onAddColumn?: (column: string) => void;
+ onBackToTop: () => void;
onSort?: (sort: string[][]) => void;
onMoveColumn?: (columns: string, newIdx: number) => void;
onRemoveColumn?: (column: string) => void;
+ sampleSize: number;
sort?: string[][];
useNewFieldsApi?: boolean;
}
@@ -120,5 +125,31 @@ export function DocTableLegacy(renderProps: DocTableLegacyProps) {
return renderFn(ref.current, renderProps);
}
}, [renderFn, renderProps]);
- return
;
+ return (
+
+
+ {renderProps.rows.length === renderProps.sampleSize ? (
+
+
+
+
+
+
+ ) : (
+
+
+
+ )}
+
+ );
}
diff --git a/src/plugins/discover/public/application/components/create_discover_directive.ts b/src/plugins/discover/public/application/components/create_discover_directive.ts
index 42b99b635a791..10439488f4bc7 100644
--- a/src/plugins/discover/public/application/components/create_discover_directive.ts
+++ b/src/plugins/discover/public/application/components/create_discover_directive.ts
@@ -17,18 +17,21 @@ export function createDiscoverDirective(reactDirective: any) {
['histogramData', { watchDepth: 'reference' }],
['hits', { watchDepth: 'reference' }],
['indexPattern', { watchDepth: 'reference' }],
+ ['minimumVisibleRows', { watchDepth: 'reference' }],
['onAddColumn', { watchDepth: 'reference' }],
['onAddFilter', { watchDepth: 'reference' }],
['onChangeInterval', { watchDepth: 'reference' }],
+ ['onMoveColumn', { watchDepth: 'reference' }],
['onRemoveColumn', { watchDepth: 'reference' }],
['onSetColumns', { watchDepth: 'reference' }],
+ ['onSkipBottomButtonClick', { watchDepth: 'reference' }],
['onSort', { watchDepth: 'reference' }],
['opts', { watchDepth: 'reference' }],
['resetQuery', { watchDepth: 'reference' }],
['resultState', { watchDepth: 'reference' }],
['rows', { watchDepth: 'reference' }],
+ ['savedSearch', { watchDepth: 'reference' }],
['searchSource', { watchDepth: 'reference' }],
- ['setColumns', { watchDepth: 'reference' }],
['setIndexPattern', { watchDepth: 'reference' }],
['showSaveQuery', { watchDepth: 'reference' }],
['state', { watchDepth: 'reference' }],
diff --git a/src/plugins/discover/public/application/components/create_discover_legacy_directive.ts b/src/plugins/discover/public/application/components/create_discover_legacy_directive.ts
deleted file mode 100644
index b2b9fd38f73b1..0000000000000
--- a/src/plugins/discover/public/application/components/create_discover_legacy_directive.ts
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * and the Server Side Public License, v 1; you may not use this file except in
- * compliance with, at your election, the Elastic License or the Server Side
- * Public License, v 1.
- */
-
-import { DiscoverLegacy } from './discover_legacy';
-
-export function createDiscoverLegacyDirective(reactDirective: any) {
- return reactDirective(DiscoverLegacy, [
- ['fetch', { watchDepth: 'reference' }],
- ['fetchCounter', { watchDepth: 'reference' }],
- ['fetchError', { watchDepth: 'reference' }],
- ['fieldCounts', { watchDepth: 'reference' }],
- ['histogramData', { watchDepth: 'reference' }],
- ['hits', { watchDepth: 'reference' }],
- ['indexPattern', { watchDepth: 'reference' }],
- ['minimumVisibleRows', { watchDepth: 'reference' }],
- ['onAddColumn', { watchDepth: 'reference' }],
- ['onAddFilter', { watchDepth: 'reference' }],
- ['onChangeInterval', { watchDepth: 'reference' }],
- ['onMoveColumn', { watchDepth: 'reference' }],
- ['onRemoveColumn', { watchDepth: 'reference' }],
- ['onSetColumns', { watchDepth: 'reference' }],
- ['onSkipBottomButtonClick', { watchDepth: 'reference' }],
- ['onSort', { watchDepth: 'reference' }],
- ['opts', { watchDepth: 'reference' }],
- ['resetQuery', { watchDepth: 'reference' }],
- ['resultState', { watchDepth: 'reference' }],
- ['rows', { watchDepth: 'reference' }],
- ['savedSearch', { watchDepth: 'reference' }],
- ['searchSource', { watchDepth: 'reference' }],
- ['setIndexPattern', { watchDepth: 'reference' }],
- ['showSaveQuery', { watchDepth: 'reference' }],
- ['state', { watchDepth: 'reference' }],
- ['timefilterUpdateHandler', { watchDepth: 'reference' }],
- ['timeRange', { watchDepth: 'reference' }],
- ['topNavMenu', { watchDepth: 'reference' }],
- ['updateQuery', { watchDepth: 'reference' }],
- ['updateSavedQueryId', { watchDepth: 'reference' }],
- ['useNewFieldsApi', { watchDepth: 'reference' }],
- ]);
-}
diff --git a/src/plugins/discover/public/application/components/discover_legacy.test.tsx b/src/plugins/discover/public/application/components/discover.test.tsx
similarity index 89%
rename from src/plugins/discover/public/application/components/discover_legacy.test.tsx
rename to src/plugins/discover/public/application/components/discover.test.tsx
index 04f294912d49e..3088ca45f7941 100644
--- a/src/plugins/discover/public/application/components/discover_legacy.test.tsx
+++ b/src/plugins/discover/public/application/components/discover.test.tsx
@@ -8,7 +8,7 @@
import React from 'react';
import { shallowWithIntl } from '@kbn/test/jest';
-import { DiscoverLegacy } from './discover_legacy';
+import { Discover } from './discover';
import { inspectorPluginMock } from '../../../../inspector/public/mocks';
import { esHits } from '../../__mocks__/es_hits';
import { indexPatternMock } from '../../__mocks__/index_pattern';
@@ -19,7 +19,7 @@ import { savedSearchMock } from '../../__mocks__/saved_search';
import { createSearchSourceMock } from '../../../../data/common/search/search_source/mocks';
import { dataPluginMock } from '../../../../data/public/mocks';
import { createFilterManagerMock } from '../../../../data/public/query/filter_manager/filter_manager.mock';
-import { uiSettingsMock } from '../../__mocks__/ui_settings';
+import { uiSettingsMock as mockUiSettings } from '../../__mocks__/ui_settings';
import { IndexPattern, IndexPatternAttributes } from '../../../../data/common/index_patterns';
import { SavedObject } from '../../../../../core/types';
import { navigationPluginMock } from '../../../../navigation/public/mocks';
@@ -40,6 +40,7 @@ jest.mock('../../kibana_services', () => {
},
},
navigation: mockNavigation,
+ uiSettings: mockUiSettings,
}),
};
});
@@ -53,6 +54,7 @@ function getProps(indexPattern: IndexPattern) {
save: true,
},
},
+ uiSettings: mockUiSettings,
} as unknown) as DiscoverServices;
return {
@@ -72,7 +74,7 @@ function getProps(indexPattern: IndexPattern) {
onSkipBottomButtonClick: jest.fn(),
onSort: jest.fn(),
opts: {
- config: uiSettingsMock,
+ config: mockUiSettings,
data: dataPluginMock.createStartContract(),
fixedScroll: jest.fn(),
filterManager: createFilterManagerMock(),
@@ -105,15 +107,13 @@ function getProps(indexPattern: IndexPattern) {
};
}
-describe('Descover legacy component', () => {
+describe('Discover component', () => {
test('selected index pattern without time field displays no chart toggle', () => {
- const component = shallowWithIntl();
+ const component = shallowWithIntl();
expect(component.find('[data-test-subj="discoverChartToggle"]').length).toBe(0);
});
test('selected index pattern with time field displays chart toggle', () => {
- const component = shallowWithIntl(
-
- );
+ const component = shallowWithIntl();
expect(component.find('[data-test-subj="discoverChartToggle"]').length).toBe(1);
});
});
diff --git a/src/plugins/discover/public/application/components/discover.tsx b/src/plugins/discover/public/application/components/discover.tsx
index 704e7a9c02e1b..5653ef4f57435 100644
--- a/src/plugins/discover/public/application/components/discover.tsx
+++ b/src/plugins/discover/public/application/components/discover.tsx
@@ -26,25 +26,30 @@ import classNames from 'classnames';
import { HitsCounter } from './hits_counter';
import { TimechartHeader } from './timechart_header';
import { getServices } from '../../kibana_services';
-import { DiscoverUninitialized, DiscoverHistogram } from '../angular/directives';
+import { DiscoverHistogram, DiscoverUninitialized } from '../angular/directives';
import { DiscoverNoResults } from './no_results';
import { LoadingSpinner } from './loading_spinner/loading_spinner';
+import { DocTableLegacy, DocTableLegacyProps } from '../angular/doc_table/create_doc_table_react';
+import { SkipBottomButton } from './skip_bottom_button';
import { search } from '../../../../data/public';
import {
DiscoverSidebarResponsive,
DiscoverSidebarResponsiveProps,
} from './sidebar/discover_sidebar_responsive';
-import { DiscoverProps } from './discover_legacy';
+import { DiscoverProps } from './types';
+import { getDisplayedColumns } from '../helpers/columns';
import { SortPairArr } from '../angular/doc_table/lib/get_sort';
import { DiscoverGrid, DiscoverGridProps } from './discover_grid/discover_grid';
+import { SEARCH_FIELDS_FROM_SOURCE } from '../../../common';
-export const SidebarMemoized = React.memo((props: DiscoverSidebarResponsiveProps) => (
+const DocTableLegacyMemoized = React.memo((props: DocTableLegacyProps) => (
+
+));
+const SidebarMemoized = React.memo((props: DiscoverSidebarResponsiveProps) => (
));
-export const DataGridMemoized = React.memo((props: DiscoverGridProps) => (
-
-));
+const DataGridMemoized = React.memo((props: DiscoverGridProps) => );
export function Discover({
fetch,
@@ -54,11 +59,14 @@ export function Discover({
histogramData,
hits,
indexPattern,
+ minimumVisibleRows,
onAddColumn,
onAddFilter,
onChangeInterval,
+ onMoveColumn,
onRemoveColumn,
onSetColumns,
+ onSkipBottomButtonClick,
onSort,
opts,
resetQuery,
@@ -66,7 +74,6 @@ export function Discover({
rows,
searchSource,
setIndexPattern,
- showSaveQuery,
state,
timefilterUpdateHandler,
timeRange,
@@ -76,6 +83,11 @@ export function Discover({
}: DiscoverProps) {
const scrollableDesktop = useRef(null);
const collapseIcon = useRef(null);
+ const isMobile = () => {
+ // collapse icon isn't displayed in mobile view, use it to detect which view is displayed
+ return collapseIcon && !collapseIcon.current;
+ };
+
const [toggleOn, toggleChart] = useState(true);
const [isSidebarClosed, setIsSidebarClosed] = useState(false);
const services = getServices();
@@ -88,18 +100,8 @@ export function Discover({
? bucketAggConfig.buckets?.getInterval()
: undefined;
const contentCentered = resultState === 'uninitialized';
- const showTimeCol = !config.get('doc_table:hideTimeColumn', false) && indexPattern.timeFieldName;
- const columns =
- state.columns &&
- state.columns.length > 0 &&
- // check if all columns where removed except the configured timeField (this can't be removed)
- !(state.columns.length === 1 && state.columns[0] === indexPattern.timeFieldName)
- ? state.columns
- : ['_source'];
- // if columns include _source this is considered as default view, so you can't remove columns
- // until you add a column using Discover's sidebar
- const defaultColumns = columns.includes('_source');
-
+ const isLegacy = services.uiSettings.get('doc_table:legacy');
+ const useNewFieldsApi = !services.uiSettings.get(SEARCH_FIELDS_FROM_SOURCE);
return (
@@ -114,7 +116,7 @@ export function Discover({
savedQueryId={state.savedQuery}
screenTitle={savedSearch.title}
showDatePicker={indexPattern.isTimeBased()}
- showSaveQuery={showSaveQuery}
+ showSaveQuery={!!services.capabilities.discover.saveQuery}
showSearchBar={true}
useDefaultBehaviors={true}
/>
@@ -137,6 +139,7 @@ export function Discover({
setIndexPattern={setIndexPattern}
isClosed={isSidebarClosed}
trackUiMetric={trackUiMetric}
+ useNewFieldsApi={useNewFieldsApi}
/>
@@ -207,24 +210,28 @@ export function Discover({
/>
)}
-
- {
- toggleChart(!toggleOn);
- }}
- >
- {toggleOn
- ? i18n.translate('discover.hideChart', {
- defaultMessage: 'Hide chart',
- })
- : i18n.translate('discover.showChart', {
- defaultMessage: 'Show chart',
- })}
-
-
+ {opts.timefield && (
+
+ {
+ toggleChart(!toggleOn);
+ }}
+ data-test-subj="discoverChartToggle"
+ >
+ {toggleOn
+ ? i18n.translate('discover.hideChart', {
+ defaultMessage: 'Hide chart',
+ })
+ : i18n.translate('discover.showChart', {
+ defaultMessage: 'Show chart',
+ })}
+
+
+ )}
+ {isLegacy && }
{toggleOn && opts.timefield && (
@@ -238,7 +245,10 @@ export function Discover({
className="dscTimechart"
>
{opts.chartAggConfigs && histogramData && rows.length !== 0 && (
-
+
- {rows && rows.length && (
+ {isLegacy && rows && rows.length && (
+
{
+ if (scrollableDesktop && scrollableDesktop.current) {
+ scrollableDesktop.current.focus();
+ }
+ // Only the desktop one needs to target a specific container
+ if (!isMobile() && scrollableDesktop.current) {
+ scrollableDesktop.current.scrollTo(0, 0);
+ } else if (window) {
+ window.scrollTo(0, 0);
+ }
+ }}
+ onFilter={onAddFilter}
+ onMoveColumn={onMoveColumn}
+ onRemoveColumn={onRemoveColumn}
+ onSort={onSort}
+ sampleSize={opts.sampleSize}
+ useNewFieldsApi={useNewFieldsApi}
+ />
+ )}
+ {!isLegacy && rows && rows.length && (
{
export const DiscoverGrid = ({
ariaLabelledBy,
columns,
- defaultColumns,
indexPattern,
onAddColumn,
onFilter,
@@ -144,6 +137,7 @@ export const DiscoverGrid = ({
sort,
}: DiscoverGridProps) => {
const [expanded, setExpanded] = useState(undefined);
+ const defaultColumns = columns.includes('_source');
/**
* Pagination
diff --git a/src/plugins/discover/public/application/components/discover_grid/discover_grid_columns.tsx b/src/plugins/discover/public/application/components/discover_grid/discover_grid_columns.tsx
index 481d308cf88a9..6a247ad951c9b 100644
--- a/src/plugins/discover/public/application/components/discover_grid/discover_grid_columns.tsx
+++ b/src/plugins/discover/public/application/components/discover_grid/discover_grid_columns.tsx
@@ -48,7 +48,12 @@ export function buildEuiGridColumn(
id: columnName,
schema: getSchemaByKbnType(indexPatternField?.type),
isSortable: indexPatternField?.sortable,
- display: indexPatternField?.displayName,
+ display:
+ columnName === '_source'
+ ? i18n.translate('discover.grid.documentHeader', {
+ defaultMessage: 'Document',
+ })
+ : indexPatternField?.displayName,
actions: {
showHide:
defaultColumns || columnName === indexPattern.timeFieldName
diff --git a/src/plugins/discover/public/application/components/discover_legacy.tsx b/src/plugins/discover/public/application/components/discover_legacy.tsx
deleted file mode 100644
index 1b90b845a8fff..0000000000000
--- a/src/plugins/discover/public/application/components/discover_legacy.tsx
+++ /dev/null
@@ -1,517 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * and the Server Side Public License, v 1; you may not use this file except in
- * compliance with, at your election, the Elastic License or the Server Side
- * Public License, v 1.
- */
-
-import './discover.scss';
-
-import React, { useState, useRef } from 'react';
-import {
- EuiButtonEmpty,
- EuiButtonIcon,
- EuiFlexGroup,
- EuiFlexItem,
- EuiHideFor,
- EuiPage,
- EuiPageBody,
- EuiPageContent,
-} from '@elastic/eui';
-import { i18n } from '@kbn/i18n';
-import { FormattedMessage, I18nProvider } from '@kbn/i18n/react';
-import { IUiSettingsClient, MountPoint } from 'kibana/public';
-import classNames from 'classnames';
-import { HitsCounter } from './hits_counter';
-import { TimechartHeader } from './timechart_header';
-import { getServices, IndexPattern } from '../../kibana_services';
-import { DiscoverUninitialized, DiscoverHistogram } from '../angular/directives';
-import { DiscoverNoResults } from './no_results';
-import { LoadingSpinner } from './loading_spinner/loading_spinner';
-import { DocTableLegacy, DocTableLegacyProps } from '../angular/doc_table/create_doc_table_react';
-import { SkipBottomButton } from './skip_bottom_button';
-import {
- search,
- ISearchSource,
- TimeRange,
- Query,
- IndexPatternAttributes,
- DataPublicPluginStart,
- AggConfigs,
- FilterManager,
-} from '../../../../data/public';
-import { Chart } from '../angular/helpers/point_series';
-import { AppState } from '../angular/discover_state';
-import { SavedSearch } from '../../saved_searches';
-import { SavedObject } from '../../../../../core/types';
-import { TopNavMenuData } from '../../../../navigation/public';
-import {
- DiscoverSidebarResponsive,
- DiscoverSidebarResponsiveProps,
-} from './sidebar/discover_sidebar_responsive';
-import { DocViewFilterFn, ElasticSearchHit } from '../doc_views/doc_views_types';
-
-export interface DiscoverProps {
- /**
- * Function to fetch documents from Elasticsearch
- */
- fetch: () => void;
- /**
- * Counter how often data was fetched (used for testing)
- */
- fetchCounter: number;
- /**
- * Error in case of a failing document fetch
- */
- fetchError?: Error;
- /**
- * Statistics by fields calculated using the fetched documents
- */
- fieldCounts: Record;
- /**
- * Histogram aggregation data
- */
- histogramData?: Chart;
- /**
- * Number of documents found by recent fetch
- */
- hits: number;
- /**
- * Current IndexPattern
- */
- indexPattern: IndexPattern;
- /**
- * Value needed for legacy "infinite" loading functionality
- * Determins how much records are rendered using the legacy table
- * Increased when scrolling down
- */
- minimumVisibleRows: number;
- /**
- * Function to add a column to state
- */
- onAddColumn: (column: string) => void;
- /**
- * Function to add a filter to state
- */
- onAddFilter: DocViewFilterFn;
- /**
- * Function to change the used time interval of the date histogram
- */
- onChangeInterval: (interval: string) => void;
- /**
- * Function to move a given column to a given index, used in legacy table
- */
- onMoveColumn: (columns: string, newIdx: number) => void;
- /**
- * Function to remove a given column from state
- */
- onRemoveColumn: (column: string) => void;
- /**
- * Function to replace columns in state
- */
- onSetColumns: (columns: string[]) => void;
- /**
- * Function to scroll down the legacy table to the bottom
- */
- onSkipBottomButtonClick: () => void;
- /**
- * Function to change sorting of the table, triggers a fetch
- */
- onSort: (sort: string[][]) => void;
- opts: {
- /**
- * Date histogram aggregation config
- */
- chartAggConfigs?: AggConfigs;
- /**
- * Client of uiSettings
- */
- config: IUiSettingsClient;
- /**
- * Data plugin
- */
- data: DataPublicPluginStart;
- /**
- * Data plugin filter manager
- */
- filterManager: FilterManager;
- /**
- * List of available index patterns
- */
- indexPatternList: Array>;
- /**
- * The number of documents that can be displayed in the table/grid
- */
- sampleSize: number;
- /**
- * Current instance of SavedSearch
- */
- savedSearch: SavedSearch;
- /**
- * Function to set the header menu
- */
- setHeaderActionMenu: (menuMount: MountPoint | undefined) => void;
- /**
- * Timefield of the currently used index pattern
- */
- timefield: string;
- /**
- * Function to set the current state
- */
- setAppState: (state: Partial) => void;
- };
- /**
- * Function to reset the current query
- */
- resetQuery: () => void;
- /**
- * Current state of the actual query, one of 'uninitialized', 'loading' ,'ready', 'none'
- */
- resultState: string;
- /**
- * Array of document of the recent successful search request
- */
- rows: ElasticSearchHit[];
- /**
- * Instance of SearchSource, the high level search API
- */
- searchSource: ISearchSource;
- /**
- * Function to change the current index pattern
- */
- setIndexPattern: (id: string) => void;
- /**
- * Determines whether the user should be able to use the save query feature
- */
- showSaveQuery: boolean;
- /**
- * Current app state of URL
- */
- state: AppState;
- /**
- * Function to update the time filter
- */
- timefilterUpdateHandler: (ranges: { from: number; to: number }) => void;
- /**
- * Currently selected time range
- */
- timeRange?: { from: string; to: string };
- /**
- * Menu data of top navigation (New, save ...)
- */
- topNavMenu: TopNavMenuData[];
- /**
- * Function to update the actual query
- */
- updateQuery: (payload: { dateRange: TimeRange; query?: Query }, isUpdate?: boolean) => void;
- /**
- * Function to update the actual savedQuery id
- */
- updateSavedQueryId: (savedQueryId?: string) => void;
- useNewFieldsApi?: boolean;
-}
-
-export const DocTableLegacyMemoized = React.memo((props: DocTableLegacyProps) => (
-
-));
-export const SidebarMemoized = React.memo((props: DiscoverSidebarResponsiveProps) => (
-
-));
-
-export function DiscoverLegacy({
- fetch,
- fetchCounter,
- fieldCounts,
- fetchError,
- histogramData,
- hits,
- indexPattern,
- minimumVisibleRows,
- onAddColumn,
- onAddFilter,
- onChangeInterval,
- onMoveColumn,
- onRemoveColumn,
- onSkipBottomButtonClick,
- onSort,
- opts,
- resetQuery,
- resultState,
- rows,
- searchSource,
- setIndexPattern,
- showSaveQuery,
- state,
- timefilterUpdateHandler,
- timeRange,
- topNavMenu,
- updateQuery,
- updateSavedQueryId,
- useNewFieldsApi,
-}: DiscoverProps) {
- const scrollableDesktop = useRef(null);
- const collapseIcon = useRef(null);
- const isMobile = () => {
- // collapse icon isn't displayed in mobile view, use it to detect which view is displayed
- return collapseIcon && !collapseIcon.current;
- };
-
- const [toggleOn, toggleChart] = useState(true);
- const [isSidebarClosed, setIsSidebarClosed] = useState(false);
- const services = getServices();
- const { TopNavMenu } = services.navigation.ui;
- const { trackUiMetric } = services;
- const { savedSearch, indexPatternList } = opts;
- const bucketAggConfig = opts.chartAggConfigs?.aggs[1];
- const bucketInterval =
- bucketAggConfig && search.aggs.isDateHistogramBucketAggConfig(bucketAggConfig)
- ? bucketAggConfig.buckets?.getInterval()
- : undefined;
- const contentCentered = resultState === 'uninitialized';
-
- const getDisplayColumns = () => {
- if (!state.columns) {
- return [];
- }
- const columns = [...state.columns];
- if (useNewFieldsApi) {
- return columns.filter((column) => column !== '_source');
- }
- return columns.length === 0 ? ['_source'] : columns;
- };
-
- return (
-
-
-
-
-
- {savedSearch.title}
-
-
-
-
-
-
-
- setIsSidebarClosed(!isSidebarClosed)}
- data-test-subj="collapseSideBarButton"
- aria-controls="discover-sidebar"
- aria-expanded={isSidebarClosed ? 'false' : 'true'}
- aria-label="Toggle sidebar"
- buttonRef={collapseIcon}
- />
-
-
-
-
- {resultState === 'none' && (
-
- )}
- {resultState === 'uninitialized' && }
- {resultState === 'loading' && }
- {resultState === 'ready' && (
-
-
-
-
- 0 ? hits : 0}
- showResetButton={!!(savedSearch && savedSearch.id)}
- onResetQuery={resetQuery}
- />
-
- {toggleOn && (
-
-
-
- )}
- {opts.timefield && (
-
- {
- toggleChart(!toggleOn);
- }}
- data-test-subj="discoverChartToggle"
- >
- {toggleOn
- ? i18n.translate('discover.hideChart', {
- defaultMessage: 'Hide chart',
- })
- : i18n.translate('discover.showChart', {
- defaultMessage: 'Show chart',
- })}
-
-
- )}
-
-
-
- {toggleOn && opts.timefield && (
-
-
- {opts.chartAggConfigs && rows.length !== 0 && histogramData && (
-
-
-
- )}
-
-
- )}
-
-
-
-
-
-
- {rows && rows.length && (
-
-
- {rows.length === opts.sampleSize ? (
-
-
-
- {
- if (scrollableDesktop && scrollableDesktop.current) {
- scrollableDesktop.current.focus();
- }
- // Only the desktop one needs to target a specific container
- if (!isMobile() && scrollableDesktop.current) {
- scrollableDesktop.current.scrollTo(0, 0);
- } else if (window) {
- window.scrollTo(0, 0);
- }
- }}
- >
-
-
-
- ) : (
-
-
-
- )}
-
- )}
-
-
-
- )}
-
-
-
-
-
-
- );
-}
diff --git a/src/plugins/discover/public/application/components/types.ts b/src/plugins/discover/public/application/components/types.ts
new file mode 100644
index 0000000000000..fe0d40f222f23
--- /dev/null
+++ b/src/plugins/discover/public/application/components/types.ts
@@ -0,0 +1,179 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * and the Server Side Public License, v 1; you may not use this file except in
+ * compliance with, at your election, the Elastic License or the Server Side
+ * Public License, v 1.
+ */
+import { IUiSettingsClient, MountPoint, SavedObject } from 'kibana/public';
+import { Chart } from '../angular/helpers/point_series';
+import { IndexPattern } from '../../../../data/common/index_patterns/index_patterns';
+import { DocViewFilterFn, ElasticSearchHit } from '../doc_views/doc_views_types';
+import { AggConfigs } from '../../../../data/common/search/aggs';
+
+import {
+ DataPublicPluginStart,
+ FilterManager,
+ IndexPatternAttributes,
+ ISearchSource,
+ Query,
+ TimeRange,
+} from '../../../../data/public';
+import { SavedSearch } from '../../saved_searches';
+import { AppState } from '../angular/discover_state';
+import { TopNavMenuData } from '../../../../navigation/public';
+
+export interface DiscoverProps {
+ /**
+ * Function to fetch documents from Elasticsearch
+ */
+ fetch: () => void;
+ /**
+ * Counter how often data was fetched (used for testing)
+ */
+ fetchCounter: number;
+ /**
+ * Error in case of a failing document fetch
+ */
+ fetchError?: Error;
+ /**
+ * Statistics by fields calculated using the fetched documents
+ */
+ fieldCounts: Record;
+ /**
+ * Histogram aggregation data
+ */
+ histogramData?: Chart;
+ /**
+ * Number of documents found by recent fetch
+ */
+ hits: number;
+ /**
+ * Current IndexPattern
+ */
+ indexPattern: IndexPattern;
+ /**
+ * Value needed for legacy "infinite" loading functionality
+ * Determins how much records are rendered using the legacy table
+ * Increased when scrolling down
+ */
+ minimumVisibleRows: number;
+ /**
+ * Function to add a column to state
+ */
+ onAddColumn: (column: string) => void;
+ /**
+ * Function to add a filter to state
+ */
+ onAddFilter: DocViewFilterFn;
+ /**
+ * Function to change the used time interval of the date histogram
+ */
+ onChangeInterval: (interval: string) => void;
+ /**
+ * Function to move a given column to a given index, used in legacy table
+ */
+ onMoveColumn: (columns: string, newIdx: number) => void;
+ /**
+ * Function to remove a given column from state
+ */
+ onRemoveColumn: (column: string) => void;
+ /**
+ * Function to replace columns in state
+ */
+ onSetColumns: (columns: string[]) => void;
+ /**
+ * Function to scroll down the legacy table to the bottom
+ */
+ onSkipBottomButtonClick: () => void;
+ /**
+ * Function to change sorting of the table, triggers a fetch
+ */
+ onSort: (sort: string[][]) => void;
+ opts: {
+ /**
+ * Date histogram aggregation config
+ */
+ chartAggConfigs?: AggConfigs;
+ /**
+ * Client of uiSettings
+ */
+ config: IUiSettingsClient;
+ /**
+ * Data plugin
+ */
+ data: DataPublicPluginStart;
+ /**
+ * Data plugin filter manager
+ */
+ filterManager: FilterManager;
+ /**
+ * List of available index patterns
+ */
+ indexPatternList: Array>;
+ /**
+ * The number of documents that can be displayed in the table/grid
+ */
+ sampleSize: number;
+ /**
+ * Current instance of SavedSearch
+ */
+ savedSearch: SavedSearch;
+ /**
+ * Function to set the header menu
+ */
+ setHeaderActionMenu: (menuMount: MountPoint | undefined) => void;
+ /**
+ * Timefield of the currently used index pattern
+ */
+ timefield: string;
+ /**
+ * Function to set the current state
+ */
+ setAppState: (state: Partial) => void;
+ };
+ /**
+ * Function to reset the current query
+ */
+ resetQuery: () => void;
+ /**
+ * Current state of the actual query, one of 'uninitialized', 'loading' ,'ready', 'none'
+ */
+ resultState: string;
+ /**
+ * Array of document of the recent successful search request
+ */
+ rows: ElasticSearchHit[];
+ /**
+ * Instance of SearchSource, the high level search API
+ */
+ searchSource: ISearchSource;
+ /**
+ * Function to change the current index pattern
+ */
+ setIndexPattern: (id: string) => void;
+ /**
+ * Current app state of URL
+ */
+ state: AppState;
+ /**
+ * Function to update the time filter
+ */
+ timefilterUpdateHandler: (ranges: { from: number; to: number }) => void;
+ /**
+ * Currently selected time range
+ */
+ timeRange?: { from: string; to: string };
+ /**
+ * Menu data of top navigation (New, save ...)
+ */
+ topNavMenu: TopNavMenuData[];
+ /**
+ * Function to update the actual query
+ */
+ updateQuery: (payload: { dateRange: TimeRange; query?: Query }, isUpdate?: boolean) => void;
+ /**
+ * Function to update the actual savedQuery id
+ */
+ updateSavedQueryId: (savedQueryId?: string) => void;
+}
diff --git a/src/plugins/discover/public/application/helpers/columns.test.ts b/src/plugins/discover/public/application/helpers/columns.test.ts
new file mode 100644
index 0000000000000..d455fd1f42c6d
--- /dev/null
+++ b/src/plugins/discover/public/application/helpers/columns.test.ts
@@ -0,0 +1,46 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * and the Server Side Public License, v 1; you may not use this file except in
+ * compliance with, at your election, the Elastic License or the Server Side
+ * Public License, v 1.
+ */
+
+import { getDisplayedColumns } from './columns';
+import { indexPatternWithTimefieldMock } from '../../__mocks__/index_pattern_with_timefield';
+import { indexPatternMock } from '../../__mocks__/index_pattern';
+
+describe('getDisplayedColumns', () => {
+ test('returns default columns given a index pattern without timefield', async () => {
+ const result = getDisplayedColumns([], indexPatternMock);
+ expect(result).toMatchInlineSnapshot(`
+ Array [
+ "_source",
+ ]
+ `);
+ });
+ test('returns default columns given a index pattern with timefield', async () => {
+ const result = getDisplayedColumns([], indexPatternWithTimefieldMock);
+ expect(result).toMatchInlineSnapshot(`
+ Array [
+ "_source",
+ ]
+ `);
+ });
+ test('returns default columns when just timefield is in state', async () => {
+ const result = getDisplayedColumns(['timestamp'], indexPatternWithTimefieldMock);
+ expect(result).toMatchInlineSnapshot(`
+ Array [
+ "_source",
+ ]
+ `);
+ });
+ test('returns columns given by argument, no fallback ', async () => {
+ const result = getDisplayedColumns(['test'], indexPatternWithTimefieldMock);
+ expect(result).toMatchInlineSnapshot(`
+ Array [
+ "test",
+ ]
+ `);
+ });
+});
diff --git a/src/plugins/discover/public/application/helpers/columns.ts b/src/plugins/discover/public/application/helpers/columns.ts
new file mode 100644
index 0000000000000..d2d47c932b7bd
--- /dev/null
+++ b/src/plugins/discover/public/application/helpers/columns.ts
@@ -0,0 +1,22 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * and the Server Side Public License, v 1; you may not use this file except in
+ * compliance with, at your election, the Elastic License or the Server Side
+ * Public License, v 1.
+ */
+import { IndexPattern } from '../../../../data/common';
+
+/**
+ * Function to provide fallback when
+ * 1) no columns are given
+ * 2) Just one column is given, which is the configured timefields
+ */
+export function getDisplayedColumns(stateColumns: string[] = [], indexPattern: IndexPattern) {
+ return stateColumns &&
+ stateColumns.length > 0 &&
+ // check if all columns where removed except the configured timeField (this can't be removed)
+ !(stateColumns.length === 1 && stateColumns[0] === indexPattern.timeFieldName)
+ ? stateColumns
+ : ['_source'];
+}
diff --git a/src/plugins/discover/public/get_inner_angular.ts b/src/plugins/discover/public/get_inner_angular.ts
index b27426a6c0621..4eda742d967f4 100644
--- a/src/plugins/discover/public/get_inner_angular.ts
+++ b/src/plugins/discover/public/get_inner_angular.ts
@@ -42,7 +42,6 @@ import {
} from '../../kibana_legacy/public';
import { DiscoverStartPlugins } from './plugin';
import { getScopedHistory } from './kibana_services';
-import { createDiscoverLegacyDirective } from './application/components/create_discover_legacy_directive';
import { createDiscoverDirective } from './application/components/create_discover_directive';
/**
@@ -124,7 +123,6 @@ export function initializeInnerAngularModule(
.config(watchMultiDecorator)
.run(registerListenEventListener)
.directive('renderComplete', createRenderCompleteDirective)
- .directive('discoverLegacy', createDiscoverLegacyDirective)
.directive('discover', createDiscoverDirective);
}
diff --git a/test/functional/apps/discover/_data_grid.ts b/test/functional/apps/discover/_data_grid.ts
index 3bac05c5b18fc..1329e7657ad9c 100644
--- a/test/functional/apps/discover/_data_grid.ts
+++ b/test/functional/apps/discover/_data_grid.ts
@@ -38,7 +38,7 @@ export default function ({
const getTitles = async () =>
(await testSubjects.getVisibleText('dataGridHeader')).replace(/\s|\r?\n|\r/g, ' ');
- expect(await getTitles()).to.be('Time (@timestamp) _source');
+ expect(await getTitles()).to.be('Time (@timestamp) Document');
await PageObjects.discover.clickFieldListItemAdd('bytes');
expect(await getTitles()).to.be('Time (@timestamp) bytes');
@@ -50,7 +50,7 @@ export default function ({
expect(await getTitles()).to.be('Time (@timestamp) agent');
await PageObjects.discover.clickFieldListItemAdd('agent');
- expect(await getTitles()).to.be('Time (@timestamp) _source');
+ expect(await getTitles()).to.be('Time (@timestamp) Document');
});
});
}
diff --git a/test/functional/apps/discover/_data_grid_field_data.ts b/test/functional/apps/discover/_data_grid_field_data.ts
index b3f68f2832c79..fb654059aa417 100644
--- a/test/functional/apps/discover/_data_grid_field_data.ts
+++ b/test/functional/apps/discover/_data_grid_field_data.ts
@@ -61,7 +61,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
});
it('doc view should show Time and _source columns', async function () {
- const expectedHeader = 'Time (@timestamp) _source';
+ const expectedHeader = 'Time (@timestamp) Document';
const DocHeader = await dataGrid.getHeaderFields();
expect(DocHeader.join(' ')).to.be(expectedHeader);
});