diff --git a/src/plugins/discover/public/__mocks__/index_patterns.ts b/src/plugins/discover/public/__mocks__/index_patterns.ts
index 88447eacc884d..b90338e895623 100644
--- a/src/plugins/discover/public/__mocks__/index_patterns.ts
+++ b/src/plugins/discover/public/__mocks__/index_patterns.ts
@@ -10,12 +10,14 @@ import { IndexPatternsService } from '../../../data/common';
import { indexPatternMock } from './index_pattern';
export const indexPatternsMock = {
- getCache: () => {
+ getCache: async () => {
return [indexPatternMock];
},
- get: (id: string) => {
+ get: async (id: string) => {
if (id === 'the-index-pattern-id') {
- return indexPatternMock;
+ return Promise.resolve(indexPatternMock);
+ } else if (id === 'invalid-index-pattern-id') {
+ return Promise.reject('Invald');
}
},
updateSavedObject: jest.fn(),
diff --git a/src/plugins/discover/public/application/apps/context/context_app_route.tsx b/src/plugins/discover/public/application/apps/context/context_app_route.tsx
index d124fd6cfa395..6c4722418be14 100644
--- a/src/plugins/discover/public/application/apps/context/context_app_route.tsx
+++ b/src/plugins/discover/public/application/apps/context/context_app_route.tsx
@@ -8,6 +8,8 @@
import React, { useEffect } from 'react';
import { useParams } from 'react-router-dom';
import { i18n } from '@kbn/i18n';
+import { EuiEmptyPrompt } from '@elastic/eui';
+import { FormattedMessage } from '@kbn/i18n/react';
import { DiscoverServices } from '../../../build_services';
import { ContextApp } from './context_app';
import { getRootBreadcrumbs } from '../../helpers/breadcrumbs';
@@ -43,7 +45,29 @@ export function ContextAppRoute(props: ContextAppProps) {
]);
}, [chrome]);
- const indexPattern = useIndexPattern(services.indexPatterns, indexPatternId);
+ const { indexPattern, error } = useIndexPattern(services.indexPatterns, indexPatternId);
+
+ if (error) {
+ return (
+
+ }
+ body={
+
+ }
+ />
+ );
+ }
if (!indexPattern) {
return ;
diff --git a/src/plugins/discover/public/application/apps/doc/components/doc.test.tsx b/src/plugins/discover/public/application/apps/doc/components/doc.test.tsx
index 31ff39ea6b577..68c012ddd92e9 100644
--- a/src/plugins/discover/public/application/apps/doc/components/doc.test.tsx
+++ b/src/plugins/discover/public/application/apps/doc/components/doc.test.tsx
@@ -14,6 +14,7 @@ import { ReactWrapper } from 'enzyme';
import { findTestSubject } from '@elastic/eui/lib/test';
import { Doc, DocProps } from './doc';
import { SEARCH_FIELDS_FROM_SOURCE as mockSearchFieldsFromSource } from '../../../../../common';
+import { indexPatternMock } from '../../../../__mocks__/index_pattern';
const mockSearchApi = jest.fn();
@@ -74,21 +75,11 @@ const waitForPromises = async () =>
* this works but logs ugly error messages until we're using React 16.9
* should be adapted when we upgrade
*/
-// eslint-disable-next-line @typescript-eslint/no-explicit-any
-async function mountDoc(update = false, indexPatternGetter: any = null) {
- const indexPattern = {
- getComputedFields: () => [],
- };
- const indexPatternService = {
- get: indexPatternGetter ? indexPatternGetter : jest.fn(() => Promise.resolve(indexPattern)),
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- } as any;
-
+async function mountDoc(update = false) {
const props = {
id: '1',
index: 'index1',
- indexPatternId: 'xyz',
- indexPatternService,
+ indexPattern: indexPatternMock,
} as DocProps;
let comp!: ReactWrapper;
await act(async () => {
@@ -108,12 +99,6 @@ describe('Test of of Discover', () => {
expect(findTestSubject(comp, 'doc-msg-loading').length).toBe(1);
});
- test('renders IndexPattern notFound msg', async () => {
- const indexPatternGetter = jest.fn(() => Promise.reject({ savedObjectId: '007' }));
- const comp = await mountDoc(true, indexPatternGetter);
- expect(findTestSubject(comp, 'doc-msg-notFoundIndexPattern').length).toBe(1);
- });
-
test('renders notFound msg', async () => {
mockSearchApi.mockImplementation(() => throwError({ status: 404 }));
const comp = await mountDoc(true);
diff --git a/src/plugins/discover/public/application/apps/doc/components/doc.tsx b/src/plugins/discover/public/application/apps/doc/components/doc.tsx
index f33ffe561e490..c6cfad3953e95 100644
--- a/src/plugins/discover/public/application/apps/doc/components/doc.tsx
+++ b/src/plugins/discover/public/application/apps/doc/components/doc.tsx
@@ -9,7 +9,7 @@
import React from 'react';
import { FormattedMessage } from '@kbn/i18n/react';
import { EuiCallOut, EuiLink, EuiLoadingSpinner, EuiPageContent, EuiPage } from '@elastic/eui';
-import { IndexPatternsContract } from 'src/plugins/data/public';
+import { IndexPattern } from 'src/plugins/data/public';
import { getServices } from '../../../../kibana_services';
import { DocViewer } from '../../../components/doc_viewer/doc_viewer';
import { ElasticRequestState } from '../types';
@@ -25,14 +25,9 @@ export interface DocProps {
*/
index: string;
/**
- * IndexPattern ID used to get IndexPattern entity
- * that's used for adding additional fields (stored_fields, script_fields, docvalue_fields)
+ * IndexPattern entity
*/
- indexPatternId: string;
- /**
- * IndexPatternService to get a given index pattern by ID
- */
- indexPatternService: IndexPatternsContract;
+ indexPattern: IndexPattern;
/**
* If set, will always request source, regardless of the global `fieldsFromSource` setting
*/
@@ -40,7 +35,8 @@ export interface DocProps {
}
export function Doc(props: DocProps) {
- const [reqState, hit, indexPattern] = useEsDocSearch(props);
+ const { indexPattern } = props;
+ const [reqState, hit] = useEsDocSearch(props);
const indexExistsLink = getServices().docLinks.links.apis.indexExists;
return (
@@ -54,7 +50,7 @@ export function Doc(props: DocProps) {
}
/>
diff --git a/src/plugins/discover/public/application/apps/doc/single_doc_route.tsx b/src/plugins/discover/public/application/apps/doc/single_doc_route.tsx
index 8398f6255e0f9..aef928d523515 100644
--- a/src/plugins/discover/public/application/apps/doc/single_doc_route.tsx
+++ b/src/plugins/discover/public/application/apps/doc/single_doc_route.tsx
@@ -7,6 +7,8 @@
*/
import React, { useEffect } from 'react';
import { useLocation, useParams } from 'react-router-dom';
+import { EuiEmptyPrompt } from '@elastic/eui';
+import { FormattedMessage } from '@kbn/i18n/react';
import { DiscoverServices } from '../../../build_services';
import { getRootBreadcrumbs } from '../../helpers/breadcrumbs';
import { Doc } from './components/doc';
@@ -31,7 +33,7 @@ function useQuery() {
export function SingleDocRoute(props: SingleDocRouteProps) {
const { services } = props;
- const { chrome, timefilter, indexPatterns } = services;
+ const { chrome, timefilter } = services;
const { indexPatternId, index } = useParams();
@@ -52,7 +54,29 @@ export function SingleDocRoute(props: SingleDocRouteProps) {
timefilter.disableTimeRangeSelector();
});
- const indexPattern = useIndexPattern(services.indexPatterns, indexPatternId);
+ const { indexPattern, error } = useIndexPattern(services.indexPatterns, indexPatternId);
+
+ if (error) {
+ return (
+
+ }
+ body={
+
+ }
+ />
+ );
+ }
if (!indexPattern) {
return ;
@@ -60,12 +84,7 @@ export function SingleDocRoute(props: SingleDocRouteProps) {
return (
-
+
);
}
diff --git a/src/plugins/discover/public/application/components/doc_viewer/doc_viewer_tab.test.tsx b/src/plugins/discover/public/application/components/doc_viewer/doc_viewer_tab.test.tsx
index a2434170acdd7..188deba755445 100644
--- a/src/plugins/discover/public/application/components/doc_viewer/doc_viewer_tab.test.tsx
+++ b/src/plugins/discover/public/application/components/doc_viewer/doc_viewer_tab.test.tsx
@@ -10,6 +10,7 @@ import React from 'react';
import { shallow } from 'enzyme';
import { DocViewerTab } from './doc_viewer_tab';
import { ElasticSearchHit } from '../../doc_views/doc_views_types';
+import { indexPatternMock } from '../../../__mocks__/index_pattern';
describe('DocViewerTab', () => {
test('changing columns triggers an update', () => {
@@ -21,6 +22,7 @@ describe('DocViewerTab', () => {
renderProps: {
hit: {} as ElasticSearchHit,
columns: ['test'],
+ indexPattern: indexPatternMock,
},
};
@@ -31,6 +33,7 @@ describe('DocViewerTab', () => {
renderProps: {
hit: {} as ElasticSearchHit,
columns: ['test2'],
+ indexPattern: indexPatternMock,
},
};
diff --git a/src/plugins/discover/public/application/components/source_viewer/__snapshots__/source_viewer.test.tsx.snap b/src/plugins/discover/public/application/components/source_viewer/__snapshots__/source_viewer.test.tsx.snap
index 82d9183f3d394..761263ee861b9 100644
--- a/src/plugins/discover/public/application/components/source_viewer/__snapshots__/source_viewer.test.tsx.snap
+++ b/src/plugins/discover/public/application/components/source_viewer/__snapshots__/source_viewer.test.tsx.snap
@@ -5,7 +5,11 @@ exports[`Source Viewer component renders error state 1`] = `
hasLineNumbers={true}
id="1"
index="index1"
- indexPatternId="xyz"
+ indexPattern={
+ Object {
+ "getComputedFields": [Function],
+ }
+ }
intl={
Object {
"defaultFormats": Object {},
@@ -264,7 +268,11 @@ exports[`Source Viewer component renders json code editor 1`] = `
hasLineNumbers={true}
id="1"
index="index1"
- indexPatternId="xyz"
+ indexPattern={
+ Object {
+ "getComputedFields": [Function],
+ }
+ }
intl={
Object {
"defaultFormats": Object {},
@@ -619,7 +627,11 @@ exports[`Source Viewer component renders loading state 1`] = `
hasLineNumbers={true}
id="1"
index="index1"
- indexPatternId="xyz"
+ indexPattern={
+ Object {
+ "getComputedFields": [Function],
+ }
+ }
intl={
Object {
"defaultFormats": Object {},
diff --git a/src/plugins/discover/public/application/components/source_viewer/source_viewer.test.tsx b/src/plugins/discover/public/application/components/source_viewer/source_viewer.test.tsx
index 7895c1025dda9..a98c2de6197d8 100644
--- a/src/plugins/discover/public/application/components/source_viewer/source_viewer.test.tsx
+++ b/src/plugins/discover/public/application/components/source_viewer/source_viewer.test.tsx
@@ -43,13 +43,13 @@ const mockIndexPatternService = {
}));
describe('Source Viewer component', () => {
test('renders loading state', () => {
- jest.spyOn(hooks, 'useEsDocSearch').mockImplementation(() => [0, null, null, () => {}]);
+ jest.spyOn(hooks, 'useEsDocSearch').mockImplementation(() => [0, null, () => {}]);
const comp = mountWithIntl(
@@ -60,13 +60,13 @@ describe('Source Viewer component', () => {
});
test('renders error state', () => {
- jest.spyOn(hooks, 'useEsDocSearch').mockImplementation(() => [3, null, null, () => {}]);
+ jest.spyOn(hooks, 'useEsDocSearch').mockImplementation(() => [3, null, () => {}]);
const comp = mountWithIntl(
@@ -97,9 +97,7 @@ describe('Source Viewer component', () => {
_underscore: 123,
},
} as never;
- jest
- .spyOn(hooks, 'useEsDocSearch')
- .mockImplementation(() => [2, mockHit, mockIndexPattern, () => {}]);
+ jest.spyOn(hooks, 'useEsDocSearch').mockImplementation(() => [2, mockHit, () => {}]);
jest.spyOn(useUiSettingHook, 'useUiSetting').mockImplementation(() => {
return false;
});
@@ -107,7 +105,7 @@ describe('Source Viewer component', () => {
diff --git a/src/plugins/discover/public/application/components/source_viewer/source_viewer.tsx b/src/plugins/discover/public/application/components/source_viewer/source_viewer.tsx
index 9e37ae8f8bf93..31d4d866df21e 100644
--- a/src/plugins/discover/public/application/components/source_viewer/source_viewer.tsx
+++ b/src/plugins/discover/public/application/components/source_viewer/source_viewer.tsx
@@ -17,11 +17,12 @@ import { getServices } from '../../../kibana_services';
import { SEARCH_FIELDS_FROM_SOURCE } from '../../../../common';
import { ElasticRequestState } from '../../apps/doc/types';
import { useEsDocSearch } from '../../services/use_es_doc_search';
+import { IndexPattern } from '../../../../../data_views/common';
interface SourceViewerProps {
id: string;
index: string;
- indexPatternId: string;
+ indexPattern: IndexPattern;
hasLineNumbers: boolean;
width?: number;
}
@@ -29,19 +30,17 @@ interface SourceViewerProps {
export const SourceViewer = ({
id,
index,
- indexPatternId,
+ indexPattern,
width,
hasLineNumbers,
}: SourceViewerProps) => {
const [editor, setEditor] = useState();
const [jsonValue, setJsonValue] = useState('');
- const indexPatternService = getServices().data.indexPatterns;
const useNewFieldsApi = !getServices().uiSettings.get(SEARCH_FIELDS_FROM_SOURCE);
- const [reqState, hit, , requestData] = useEsDocSearch({
+ const [reqState, hit, requestData] = useEsDocSearch({
id,
index,
- indexPatternId,
- indexPatternService,
+ indexPattern,
requestSource: useNewFieldsApi,
});
@@ -106,11 +105,7 @@ export const SourceViewer = ({
);
- if (
- reqState === ElasticRequestState.Error ||
- reqState === ElasticRequestState.NotFound ||
- reqState === ElasticRequestState.NotFoundIndexPattern
- ) {
+ if (reqState === ElasticRequestState.Error || reqState === ElasticRequestState.NotFound) {
return errorState;
}
diff --git a/src/plugins/discover/public/application/components/table/table.tsx b/src/plugins/discover/public/application/components/table/table.tsx
index 7f597d846f88f..e64dbd10f7855 100644
--- a/src/plugins/discover/public/application/components/table/table.tsx
+++ b/src/plugins/discover/public/application/components/table/table.tsx
@@ -25,7 +25,7 @@ export interface DocViewerTableProps {
columns?: string[];
filter?: DocViewFilterFn;
hit: ElasticSearchHit;
- indexPattern?: IndexPattern;
+ indexPattern: IndexPattern;
onAddColumn?: (columnName: string) => void;
onRemoveColumn?: (columnName: string) => void;
}
diff --git a/src/plugins/discover/public/application/doc_views/doc_views_types.ts b/src/plugins/discover/public/application/doc_views/doc_views_types.ts
index 48bebec22b9b5..d3e482c0f2e1d 100644
--- a/src/plugins/discover/public/application/doc_views/doc_views_types.ts
+++ b/src/plugins/discover/public/application/doc_views/doc_views_types.ts
@@ -32,7 +32,7 @@ export interface DocViewRenderProps {
columns?: string[];
filter?: DocViewFilterFn;
hit: ElasticSearchHit;
- indexPattern?: IndexPattern;
+ indexPattern: IndexPattern;
onAddColumn?: (columnName: string) => void;
onRemoveColumn?: (columnName: string) => void;
}
diff --git a/src/plugins/discover/public/application/helpers/use_index_pattern.test.tsx b/src/plugins/discover/public/application/helpers/use_index_pattern.test.tsx
index 85282afb6fc37..dfc54d8630742 100644
--- a/src/plugins/discover/public/application/helpers/use_index_pattern.test.tsx
+++ b/src/plugins/discover/public/application/helpers/use_index_pattern.test.tsx
@@ -8,12 +8,24 @@
import { useIndexPattern } from './use_index_pattern';
import { indexPatternMock } from '../../__mocks__/index_pattern';
import { indexPatternsMock } from '../../__mocks__/index_patterns';
-import { renderHook, act } from '@testing-library/react-hooks';
+import { renderHook } from '@testing-library/react-hooks';
describe('Use Index Pattern', () => {
test('returning a valid index pattern', async () => {
- const { result } = renderHook(() => useIndexPattern(indexPatternsMock, 'the-index-pattern-id'));
- await act(() => Promise.resolve());
- expect(result.current).toBe(indexPatternMock);
+ const { result, waitForNextUpdate } = renderHook(() =>
+ useIndexPattern(indexPatternsMock, 'the-index-pattern-id')
+ );
+ await waitForNextUpdate();
+ expect(result.current.indexPattern).toBe(indexPatternMock);
+ expect(result.current.error).toBe(undefined);
+ });
+
+ test('returning an error', async () => {
+ const { result, waitForNextUpdate } = renderHook(() =>
+ useIndexPattern(indexPatternsMock, 'invalid-index-pattern-id')
+ );
+ await waitForNextUpdate();
+ expect(result.current.indexPattern).toBe(undefined);
+ expect(result.current.error).toBeTruthy();
});
});
diff --git a/src/plugins/discover/public/application/helpers/use_index_pattern.tsx b/src/plugins/discover/public/application/helpers/use_index_pattern.tsx
index f53d131920c5c..374f83cbbfe72 100644
--- a/src/plugins/discover/public/application/helpers/use_index_pattern.tsx
+++ b/src/plugins/discover/public/application/helpers/use_index_pattern.tsx
@@ -10,13 +10,18 @@ import { IndexPattern, IndexPatternsContract } from '../../../../data/common';
export const useIndexPattern = (indexPatterns: IndexPatternsContract, indexPatternId: string) => {
const [indexPattern, setIndexPattern] = useState(undefined);
+ const [error, setError] = useState();
useEffect(() => {
async function loadIndexPattern() {
- const ip = await indexPatterns.get(indexPatternId);
- setIndexPattern(ip);
+ try {
+ const item = await indexPatterns.get(indexPatternId);
+ setIndexPattern(item);
+ } catch (e) {
+ setError(e);
+ }
}
loadIndexPattern();
- });
- return indexPattern;
+ }, [indexPatternId, indexPatterns]);
+ return { indexPattern, error };
};
diff --git a/src/plugins/discover/public/application/services/use_es_doc_search.test.tsx b/src/plugins/discover/public/application/services/use_es_doc_search.test.tsx
index af7d189e62882..ca57b470b471a 100644
--- a/src/plugins/discover/public/application/services/use_es_doc_search.test.tsx
+++ b/src/plugins/discover/public/application/services/use_es_doc_search.test.tsx
@@ -6,7 +6,7 @@
* Side Public License, v 1.
*/
-import { renderHook, act } from '@testing-library/react-hooks';
+import { renderHook } from '@testing-library/react-hooks';
import { buildSearchBody, useEsDocSearch } from './use_es_doc_search';
import { Observable } from 'rxjs';
import { IndexPattern } from 'src/plugins/data/common';
@@ -175,26 +175,14 @@ describe('Test of helper / hook', () => {
const indexPattern = {
getComputedFields: () => [],
};
- const getMock = jest.fn(() => Promise.resolve(indexPattern));
- const indexPatternService = {
- get: getMock,
- } as unknown as IndexPattern;
const props = {
id: '1',
index: 'index1',
- indexPatternId: 'xyz',
- indexPatternService,
- } as unknown as DocProps;
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- let hook: any;
- await act(async () => {
- hook = renderHook((p: DocProps) => useEsDocSearch(p), { initialProps: props });
- });
- expect(hook.result.current.slice(0, 3)).toEqual([
- ElasticRequestState.Loading,
- null,
indexPattern,
- ]);
- expect(getMock).toHaveBeenCalled();
+ } as unknown as DocProps;
+
+ const { result } = renderHook((p: DocProps) => useEsDocSearch(p), { initialProps: props });
+
+ expect(result.current.slice(0, 2)).toEqual([ElasticRequestState.Loading, null]);
});
});
diff --git a/src/plugins/discover/public/application/services/use_es_doc_search.ts b/src/plugins/discover/public/application/services/use_es_doc_search.ts
index a2f0cd6f8442b..16a24ff27292b 100644
--- a/src/plugins/discover/public/application/services/use_es_doc_search.ts
+++ b/src/plugins/discover/public/application/services/use_es_doc_search.ts
@@ -64,11 +64,9 @@ export function buildSearchBody(
export function useEsDocSearch({
id,
index,
- indexPatternId,
- indexPatternService,
+ indexPattern,
requestSource,
-}: DocProps): [ElasticRequestState, ElasticSearchHit | null, IndexPattern | null, () => void] {
- const [indexPattern, setIndexPattern] = useState(null);
+}: DocProps): [ElasticRequestState, ElasticSearchHit | null | null, () => void] {
const [status, setStatus] = useState(ElasticRequestState.Loading);
const [hit, setHit] = useState(null);
const { data, uiSettings } = useMemo(() => getServices(), []);
@@ -76,14 +74,11 @@ export function useEsDocSearch({
const requestData = useCallback(async () => {
try {
- const indexPatternEntity = await indexPatternService.get(indexPatternId);
- setIndexPattern(indexPatternEntity);
-
const { rawResponse } = await data.search
.search({
params: {
index,
- body: buildSearchBody(id, indexPatternEntity, useNewFieldsApi, requestSource)?.body,
+ body: buildSearchBody(id, indexPattern, useNewFieldsApi, requestSource)?.body,
},
})
.toPromise();
@@ -105,11 +100,11 @@ export function useEsDocSearch({
setStatus(ElasticRequestState.Error);
}
}
- }, [id, index, indexPatternId, indexPatternService, data.search, useNewFieldsApi, requestSource]);
+ }, [id, index, indexPattern, data.search, useNewFieldsApi, requestSource]);
useEffect(() => {
requestData();
}, [requestData]);
- return [status, hit, indexPattern, requestData];
+ return [status, hit, requestData];
}
diff --git a/src/plugins/discover/public/plugin.tsx b/src/plugins/discover/public/plugin.tsx
index d86e5f363630c..6d30e6fd9e8a9 100644
--- a/src/plugins/discover/public/plugin.tsx
+++ b/src/plugins/discover/public/plugin.tsx
@@ -267,7 +267,7 @@ export class DiscoverPlugin