diff --git a/src/plugins/discover/public/services/doc_views/components/doc_viewer_source/get_height.test.tsx b/src/plugins/discover/public/services/doc_views/components/doc_viewer_source/get_height.test.tsx new file mode 100644 index 000000000000..5b641cced516 --- /dev/null +++ b/src/plugins/discover/public/services/doc_views/components/doc_viewer_source/get_height.test.tsx @@ -0,0 +1,50 @@ +/* + * 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 { monaco } from '@kbn/monaco'; +import { getHeight } from './get_height'; + +describe('getHeight', () => { + window.innerHeight = 500; + const getMonacoMock = (lineCount: number) => { + return { + getDomNode: jest.fn(() => { + return { + getBoundingClientRect: jest.fn(() => { + return { + top: 200, + }; + }), + }; + }), + getOption: jest.fn(() => 10), + getModel: jest.fn(() => ({ getLineCount: jest.fn(() => lineCount) })), + getTopForLineNumber: jest.fn((line) => line * 10), + } as unknown as monaco.editor.IStandaloneCodeEditor; + }; + test('when using document explorer, returning the available height in the flyout', () => { + const monacoMock = getMonacoMock(500); + + const height = getHeight(monacoMock, true); + expect(height).toBe(275); + }); + + test('when using classic table, its displayed inline without scrolling', () => { + const monacoMock = getMonacoMock(100); + + const height = getHeight(monacoMock, false); + expect(height).toBe(1020); + }); + + test('when using classic table, limited height > 500 lines to allow scrolling', () => { + const monacoMock = getMonacoMock(1000); + + const height = getHeight(monacoMock, false); + expect(height).toBe(5020); + }); +}); diff --git a/src/plugins/discover/public/services/doc_views/components/doc_viewer_source/get_height.tsx b/src/plugins/discover/public/services/doc_views/components/doc_viewer_source/get_height.tsx new file mode 100644 index 000000000000..0dcabc8ae951 --- /dev/null +++ b/src/plugins/discover/public/services/doc_views/components/doc_viewer_source/get_height.tsx @@ -0,0 +1,32 @@ +/* + * 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 { monaco } from '@kbn/monaco'; +import { MARGIN_BOTTOM, MAX_LINES_CLASSIC_TABLE } from './source'; + +export function getHeight(editor: monaco.editor.IStandaloneCodeEditor, useDocExplorer: boolean) { + const editorElement = editor?.getDomNode(); + if (!editorElement) { + return 0; + } + + let result; + if (useDocExplorer) { + // assign a good height filling the available space of the document flyout + const position = editorElement.getBoundingClientRect(); + result = window.innerHeight - position.top - MARGIN_BOTTOM; + } else { + // takes care of the classic table, display a maximum of 500 lines + // why not display it all? Due to performance issues when the browser needs to render it all + const lineHeight = editor.getOption(monaco.editor.EditorOption.lineHeight); + const lineCount = editor.getModel()?.getLineCount() || 1; + const displayedLineCount = + lineCount > MAX_LINES_CLASSIC_TABLE ? MAX_LINES_CLASSIC_TABLE : lineCount; + result = editor.getTopForLineNumber(displayedLineCount + 1) + lineHeight; + } + return result > 0 ? result : 0; +} diff --git a/src/plugins/discover/public/services/doc_views/components/doc_viewer_source/source.tsx b/src/plugins/discover/public/services/doc_views/components/doc_viewer_source/source.tsx index 9f1cbb706971..9ec266adedb4 100644 --- a/src/plugins/discover/public/services/doc_views/components/doc_viewer_source/source.tsx +++ b/src/plugins/discover/public/services/doc_views/components/doc_viewer_source/source.tsx @@ -14,10 +14,11 @@ import { EuiButton, EuiEmptyPrompt, EuiLoadingSpinner, EuiSpacer, EuiText } from import { i18n } from '@kbn/i18n'; import { useDiscoverServices } from '../../../../utils/use_discover_services'; import { JSONCodeEditorCommonMemoized } from '../../../../components/json_code_editor/json_code_editor_common'; -import { SEARCH_FIELDS_FROM_SOURCE } from '../../../../../common'; +import { DOC_TABLE_LEGACY, SEARCH_FIELDS_FROM_SOURCE } from '../../../../../common'; import { useEsDocSearch } from '../../../../utils/use_es_doc_search'; import { DataView } from '../../../../../../data_views/common'; import { ElasticRequestState } from '../../../../application/doc/types'; +import { getHeight } from './get_height'; interface SourceViewerProps { id: string; @@ -27,6 +28,12 @@ interface SourceViewerProps { width?: number; } +// Ihe number of lines displayed without scrolling used for classic table, which renders the component +// inline limitation was necessary to enable virtualized scrolling, which improves performance +export const MAX_LINES_CLASSIC_TABLE = 500; +// Displayed margin of the code editor to the window bottom when rendered in the document explorer flyout +export const MARGIN_BOTTOM = 25; + export const DocViewerSource = ({ id, index, @@ -38,6 +45,7 @@ export const DocViewerSource = ({ const [jsonValue, setJsonValue] = useState(''); const { uiSettings } = useDiscoverServices(); const useNewFieldsApi = !uiSettings.get(SEARCH_FIELDS_FROM_SOURCE); + const useDocExplorer = !uiSettings.get(DOC_TABLE_LEGACY); const [reqState, hit, requestData] = useEsDocSearch({ id, index, @@ -62,16 +70,18 @@ export const DocViewerSource = ({ return; } - const lineHeight = editor.getOption(monaco.editor.EditorOption.lineHeight); - const lineCount = editor.getModel()?.getLineCount() || 1; - const height = editor.getTopForLineNumber(lineCount + 1) + lineHeight; + const height = getHeight(editor, useDocExplorer); + if (height === 0) { + return; + } + if (!jsonValue || jsonValue === '') { editorElement.style.height = '0px'; } else { editorElement.style.height = `${height}px`; } editor.layout(); - }, [editor, jsonValue]); + }, [editor, jsonValue, useDocExplorer]); const loadingState = (