From 8781e4c349e03390b2a9033b974287d27d42df09 Mon Sep 17 00:00:00 2001 From: Diana Derevyankina <54894989+DziyanaDzeraviankina@users.noreply.github.com> Date: Wed, 17 Mar 2021 13:44:23 +0300 Subject: [PATCH] Replace EuiCodeBlock with JsonCodeEditor in DiscoverGrid (#92442) (#94780) * Replace EuiCodeBlock with JsonCodeEditor in DiscoverGrid * Add optional "hasLineNumbers" property to JsonCodeEditor and removed line numbers from the popover * Update json_code_editor snapshot * Add functional test for cell expanded content popover * Remove unused code * Fix geo point case and refactor some code Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../components/discover_grid/constants.ts | 2 + .../discover_grid/discover_grid.tsx | 59 +++++++------ ...rid_schema.tsx => discover_grid_schema.ts} | 17 ---- .../get_render_cell_value.test.tsx | 88 ++++++++++++------- .../discover_grid/get_render_cell_value.tsx | 16 +++- .../json_code_editor.test.tsx.snap | 9 +- .../json_code_editor.test.tsx | 2 +- .../json_code_editor/json_code_editor.tsx | 17 ++-- .../discover/public/{plugin.ts => plugin.tsx} | 3 +- .../apps/discover/_data_grid_doc_table.ts | 20 +++++ test/functional/apps/visualize/_inspector.ts | 3 +- test/functional/page_objects/tile_map_page.ts | 3 +- test/functional/services/index.ts | 2 + test/functional/services/inspector.ts | 13 --- test/functional/services/monaco_editor.ts | 28 ++++++ .../maps/documents_source/docvalue_fields.js | 3 +- 16 files changed, 176 insertions(+), 109 deletions(-) rename src/plugins/discover/public/application/components/discover_grid/{discover_grid_schema.tsx => discover_grid_schema.ts} (72%) rename src/plugins/discover/public/{plugin.ts => plugin.tsx} (99%) create mode 100644 test/functional/services/monaco_editor.ts diff --git a/src/plugins/discover/public/application/components/discover_grid/constants.ts b/src/plugins/discover/public/application/components/discover_grid/constants.ts index 015d0b65246f..de2781cf159c 100644 --- a/src/plugins/discover/public/application/components/discover_grid/constants.ts +++ b/src/plugins/discover/public/application/components/discover_grid/constants.ts @@ -24,3 +24,5 @@ export const toolbarVisibility = { }, showStyleSelector: false, }; + +export const defaultMonacoEditorWidth = 370; diff --git a/src/plugins/discover/public/application/components/discover_grid/discover_grid.tsx b/src/plugins/discover/public/application/components/discover_grid/discover_grid.tsx index a0dcc2c2af46..380b4dc5e8e9 100644 --- a/src/plugins/discover/public/application/components/discover_grid/discover_grid.tsx +++ b/src/plugins/discover/public/application/components/discover_grid/discover_grid.tsx @@ -22,7 +22,7 @@ import { } from '@elastic/eui'; import { IndexPattern } from '../../../kibana_services'; import { DocViewFilterFn, ElasticSearchHit } from '../../doc_views/doc_views_types'; -import { getPopoverContents, getSchemaDetectors } from './discover_grid_schema'; +import { getSchemaDetectors } from './discover_grid_schema'; import { DiscoverGridFlyout } from './discover_grid_flyout'; import { DiscoverGridContext } from './discover_grid_context'; import { getRenderCellValueFn } from './get_render_cell_value'; @@ -36,6 +36,7 @@ import { import { defaultPageSize, gridStyle, pageSizeArr, toolbarVisibility } from './constants'; import { DiscoverServices } from '../../../build_services'; import { getDisplayedColumns } from '../../helpers/columns'; +import { KibanaContextProvider } from '../../../../../kibana_react/public'; interface SortObj { id: string; @@ -219,7 +220,6 @@ export const DiscoverGrid = ({ [displayedColumns, indexPattern, showTimeCol, settings, defaultColumns] ); const schemaDetectors = useMemo(() => getSchemaDetectors(), []); - const popoverContents = useMemo(() => getPopoverContents(), []); const columnsVisibility = useMemo( () => ({ visibleColumns: getVisibleColumns(displayedColumns, indexPattern, showTimeCol) as string[], @@ -259,34 +259,35 @@ export const DiscoverGrid = ({ }} > <> - { - if (onResize) { - onResize(col); + + { + if (onResize) { + onResize(col); + } + }} + pagination={paginationObj} + renderCellValue={renderCellValue} + rowCount={rowCount} + schemaDetectors={schemaDetectors} + sorting={sorting as EuiDataGridSorting} + toolbarVisibility={ + defaultColumns + ? { + ...toolbarVisibility, + showColumnSelector: false, + } + : toolbarVisibility } - }} - pagination={paginationObj} - popoverContents={popoverContents} - renderCellValue={renderCellValue} - rowCount={rowCount} - schemaDetectors={schemaDetectors} - sorting={sorting as EuiDataGridSorting} - toolbarVisibility={ - defaultColumns - ? { - ...toolbarVisibility, - showColumnSelector: false, - } - : toolbarVisibility - } - /> + /> + {showDisclaimer && (

diff --git a/src/plugins/discover/public/application/components/discover_grid/discover_grid_schema.tsx b/src/plugins/discover/public/application/components/discover_grid/discover_grid_schema.ts similarity index 72% rename from src/plugins/discover/public/application/components/discover_grid/discover_grid_schema.tsx rename to src/plugins/discover/public/application/components/discover_grid/discover_grid_schema.ts index ca5b2c9f1991..0aa6dadd633e 100644 --- a/src/plugins/discover/public/application/components/discover_grid/discover_grid_schema.tsx +++ b/src/plugins/discover/public/application/components/discover_grid/discover_grid_schema.ts @@ -6,8 +6,6 @@ * Side Public License, v 1. */ -import React from 'react'; -import { EuiCodeBlock, EuiDataGridPopoverContents } from '@elastic/eui'; import { kibanaJSON } from './constants'; import { KBN_FIELD_TYPES } from '../../../../../data/common'; @@ -43,18 +41,3 @@ export function getSchemaDetectors() { }, ]; } - -/** - * Returns custom popover content for certain schemas - */ -export function getPopoverContents(): EuiDataGridPopoverContents { - return { - [kibanaJSON]: ({ children }) => { - return ( - - {children} - - ); - }, - }; -} diff --git a/src/plugins/discover/public/application/components/discover_grid/get_render_cell_value.test.tsx b/src/plugins/discover/public/application/components/discover_grid/get_render_cell_value.test.tsx index a1447a9a8367..f1025a0881d1 100644 --- a/src/plugins/discover/public/application/components/discover_grid/get_render_cell_value.test.tsx +++ b/src/plugins/discover/public/application/components/discover_grid/get_render_cell_value.test.tsx @@ -7,10 +7,25 @@ */ import React from 'react'; -import { shallow } from 'enzyme'; +import { ReactWrapper, shallow } from 'enzyme'; import { getRenderCellValueFn } from './get_render_cell_value'; import { indexPatternMock } from '../../../__mocks__/index_pattern'; +jest.mock('../../../../../kibana_react/public', () => ({ + useUiSetting: () => true, + withKibana: (comp: ReactWrapper) => { + return comp; + }, +})); + +jest.mock('../../../kibana_services', () => ({ + getServices: () => ({ + uiSettings: { + get: jest.fn(), + }, + }), +})); + const rowsSource = [ { _id: '1', @@ -139,20 +154,25 @@ describe('Discover grid cell rendering', function () { setCellProps={jest.fn()} /> ); - expect(component.html()).toMatchInlineSnapshot(` - "{ - "_id": "1", - "_index": "test", - "_type": "test", - "_score": 1, - "_source": { - "bytes": 100, - "extension": ".gz" - }, - "highlight": { - "extension": "@kibana-highlighted-field.gz@/kibana-highlighted-field" + expect(component).toMatchInlineSnapshot(` + " + width={370} + /> `); }); @@ -226,24 +246,30 @@ describe('Discover grid cell rendering', function () { setCellProps={jest.fn()} /> ); - expect(component.html()).toMatchInlineSnapshot(` - "{ - "_id": "1", - "_index": "test", - "_type": "test", - "_score": 1, - "fields": { - "bytes": [ - 100 - ], - "extension": [ - ".gz" - ] - }, - "highlight": { - "extension": "@kibana-highlighted-field.gz@/kibana-highlighted-field" + expect(component).toMatchInlineSnapshot(` + " + width={370} + /> `); }); diff --git a/src/plugins/discover/public/application/components/discover_grid/get_render_cell_value.tsx b/src/plugins/discover/public/application/components/discover_grid/get_render_cell_value.tsx index b1eb5eb9ada0..dce0a82934c2 100644 --- a/src/plugins/discover/public/application/components/discover_grid/get_render_cell_value.tsx +++ b/src/plugins/discover/public/application/components/discover_grid/get_render_cell_value.tsx @@ -19,6 +19,8 @@ import { import { IndexPattern } from '../../../kibana_services'; import { ElasticSearchHit } from '../../doc_views/doc_views_types'; import { DiscoverGridContext } from './discover_grid_context'; +import { JsonCodeEditor } from '../json_code_editor/json_code_editor'; +import { defaultMonacoEditorWidth } from './constants'; export const getRenderCellValueFn = ( indexPattern: IndexPattern, @@ -26,7 +28,7 @@ export const getRenderCellValueFn = ( rowsFlattened: Array>, useNewFieldsApi: boolean ) => ({ rowIndex, columnId, isDetails, setCellProps }: EuiDataGridCellValueElementProps) => { - const row = rows ? (rows[rowIndex] as Record) : undefined; + const row = rows ? rows[rowIndex] : undefined; const rowFlattened = rowsFlattened ? (rowsFlattened[rowIndex] as Record) : undefined; @@ -106,10 +108,18 @@ export const getRenderCellValueFn = ( ); } + if (typeof rowFlattened[columnId] === 'object' && isDetails) { + return ( + } + width={defaultMonacoEditorWidth} + /> + ); + } + if (field && field.type === '_source') { if (isDetails) { - // nicely formatted JSON for the expanded view - return {JSON.stringify(row, null, 2)}; + return ; } const formatted = indexPattern.formatHit(row); diff --git a/src/plugins/discover/public/application/components/json_code_editor/__snapshots__/json_code_editor.test.tsx.snap b/src/plugins/discover/public/application/components/json_code_editor/__snapshots__/json_code_editor.test.tsx.snap index 4f27158eee04..8f0761481349 100644 --- a/src/plugins/discover/public/application/components/json_code_editor/__snapshots__/json_code_editor.test.tsx.snap +++ b/src/plugins/discover/public/application/components/json_code_editor/__snapshots__/json_code_editor.test.tsx.snap @@ -6,9 +6,7 @@ exports[`returns the \`JsonCodeEditor\` component 1`] = ` direction="column" gutterSize="s" > - + @@ -31,9 +29,7 @@ exports[`returns the \`JsonCodeEditor\` component 1`] = ` - + { _score: 1, _source: { test: 123 }, }; - expect(shallow()).toMatchSnapshot(); + expect(shallow()).toMatchSnapshot(); }); diff --git a/src/plugins/discover/public/application/components/json_code_editor/json_code_editor.tsx b/src/plugins/discover/public/application/components/json_code_editor/json_code_editor.tsx index 85d6aad75525..50a29dde8589 100644 --- a/src/plugins/discover/public/application/components/json_code_editor/json_code_editor.tsx +++ b/src/plugins/discover/public/application/components/json_code_editor/json_code_editor.tsx @@ -13,7 +13,6 @@ import { i18n } from '@kbn/i18n'; import { monaco, XJsonLang } from '@kbn/monaco'; import { EuiButtonEmpty, EuiCopy, EuiFlexGroup, EuiFlexItem, EuiSpacer } from '@elastic/eui'; import { CodeEditor } from '../../../../../kibana_react/public'; -import { DocViewRenderProps } from '../../../application/doc_views/doc_views_types'; const codeEditorAriaLabel = i18n.translate('discover.json.codeEditorAriaLabel', { defaultMessage: 'Read only JSON view of an elasticsearch document', @@ -22,8 +21,14 @@ const copyToClipboardLabel = i18n.translate('discover.json.copyToClipboardLabel' defaultMessage: 'Copy to clipboard', }); -export const JsonCodeEditor = ({ hit }: DocViewRenderProps) => { - const jsonValue = JSON.stringify(hit, null, 2); +interface JsonCodeEditorProps { + json: Record; + width?: string | number; + hasLineNumbers?: boolean; +} + +export const JsonCodeEditor = ({ json, width, hasLineNumbers }: JsonCodeEditorProps) => { + const jsonValue = JSON.stringify(json, null, 2); // setting editor height based on lines height and count to stretch and fit its content const setEditorCalculatedHeight = useCallback((editor) => { @@ -43,7 +48,7 @@ export const JsonCodeEditor = ({ hit }: DocViewRenderProps) => { return ( - +

@@ -55,9 +60,10 @@ export const JsonCodeEditor = ({ hit }: DocViewRenderProps) => {
- + {}} editorDidMount={setEditorCalculatedHeight} @@ -65,6 +71,7 @@ export const JsonCodeEditor = ({ hit }: DocViewRenderProps) => { options={{ automaticLayout: true, fontSize: 12, + lineNumbers: hasLineNumbers ? 'on' : 'off', minimap: { enabled: false, }, diff --git a/src/plugins/discover/public/plugin.ts b/src/plugins/discover/public/plugin.tsx similarity index 99% rename from src/plugins/discover/public/plugin.ts rename to src/plugins/discover/public/plugin.tsx index 47161c2b8298..0e0836e3d957 100644 --- a/src/plugins/discover/public/plugin.ts +++ b/src/plugins/discover/public/plugin.tsx @@ -7,6 +7,7 @@ */ import { i18n } from '@kbn/i18n'; +import React from 'react'; import angular, { auto } from 'angular'; import { BehaviorSubject } from 'rxjs'; import { filter, map } from 'rxjs/operators'; @@ -187,7 +188,7 @@ export class DiscoverPlugin defaultMessage: 'JSON', }), order: 20, - component: JsonCodeEditor, + component: ({ hit }) => , }); const { diff --git a/test/functional/apps/discover/_data_grid_doc_table.ts b/test/functional/apps/discover/_data_grid_doc_table.ts index 5eeafc4d78f6..fb19111d92c6 100644 --- a/test/functional/apps/discover/_data_grid_doc_table.ts +++ b/test/functional/apps/discover/_data_grid_doc_table.ts @@ -10,11 +10,13 @@ import expect from '@kbn/expect'; import { FtrProviderContext } from '../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { + const find = getService('find'); const dataGrid = getService('dataGrid'); const log = getService('log'); const retry = getService('retry'); const esArchiver = getService('esArchiver'); const kibanaServer = getService('kibanaServer'); + const monacoEditor = getService('monacoEditor'); const PageObjects = getPageObjects(['common', 'discover', 'header', 'timePicker']); const defaultSettings = { defaultIndex: 'logstash-*', @@ -56,6 +58,24 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await PageObjects.timePicker.setDefaultAbsoluteRange(); }); + it('should show popover with expanded cell content by click on expand button', async () => { + log.debug('open popover with expanded cell content to get json from the editor'); + const documentCell = await dataGrid.getCellElement(1, 3); + await documentCell.click(); + const expandCellContentButton = await documentCell.findByClassName( + 'euiDataGridRowCell__expandButtonIcon' + ); + await expandCellContentButton.click(); + const popoverJson = await monacoEditor.getCodeEditorValue(); + + log.debug('open expanded document flyout to get json'); + await dataGrid.clickRowToggle(); + await find.clickByCssSelectorWhenNotDisabled('#kbn_doc_viewer_tab_1'); + const flyoutJson = await monacoEditor.getCodeEditorValue(); + + expect(popoverJson).to.be(flyoutJson); + }); + describe('expand a document row', function () { const rowToInspect = 1; diff --git a/test/functional/apps/visualize/_inspector.ts b/test/functional/apps/visualize/_inspector.ts index 47fcc6e64d0b..edb2f87aab13 100644 --- a/test/functional/apps/visualize/_inspector.ts +++ b/test/functional/apps/visualize/_inspector.ts @@ -14,6 +14,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const log = getService('log'); const inspector = getService('inspector'); const filterBar = getService('filterBar'); + const monacoEditor = getService('monacoEditor'); const testSubjects = getService('testSubjects'); const PageObjects = getPageObjects(['visualize', 'visEditor', 'visChart', 'timePicker']); @@ -42,7 +43,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await inspector.openInspectorRequestsView(); const requestTab = await inspector.getOpenRequestDetailRequestButton(); await requestTab.click(); - const requestJSON = JSON.parse(await inspector.getCodeEditorValue()); + const requestJSON = JSON.parse(await monacoEditor.getCodeEditorValue()); expect(requestJSON.aggs['2'].max).property('missing', 10); }); diff --git a/test/functional/page_objects/tile_map_page.ts b/test/functional/page_objects/tile_map_page.ts index c11e4f1558be..db17268f20a1 100644 --- a/test/functional/page_objects/tile_map_page.ts +++ b/test/functional/page_objects/tile_map_page.ts @@ -14,6 +14,7 @@ export function TileMapPageProvider({ getService, getPageObjects }: FtrProviderC const retry = getService('retry'); const log = getService('log'); const inspector = getService('inspector'); + const monacoEditor = getService('monacoEditor'); const { header } = getPageObjects(['header']); class TileMapPage { @@ -40,7 +41,7 @@ export function TileMapPageProvider({ getService, getPageObjects }: FtrProviderC await testSubjects.click('inspectorViewChooserRequests'); await testSubjects.click('inspectorRequestDetailRequest'); - return await inspector.getCodeEditorValue(); + return await monacoEditor.getCodeEditorValue(); } public async getMapBounds(): Promise { diff --git a/test/functional/services/index.ts b/test/functional/services/index.ts index 94d7b71c640c..07d5ef950d21 100644 --- a/test/functional/services/index.ts +++ b/test/functional/services/index.ts @@ -46,6 +46,7 @@ import { ListingTableProvider } from './listing_table'; import { SavedQueryManagementComponentProvider } from './saved_query_management_component'; import { KibanaSupertestProvider } from './supertest'; import { MenuToggleProvider } from './menu_toggle'; +import { MonacoEditorProvider } from './monaco_editor'; export const services = { ...commonServiceProviders, @@ -81,5 +82,6 @@ export const services = { elasticChart: ElasticChartProvider, supertest: KibanaSupertestProvider, managementMenu: ManagementMenuProvider, + monacoEditor: MonacoEditorProvider, MenuToggle: MenuToggleProvider, }; diff --git a/test/functional/services/inspector.ts b/test/functional/services/inspector.ts index 4dc248116ccf..c9cf159d0d38 100644 --- a/test/functional/services/inspector.ts +++ b/test/functional/services/inspector.ts @@ -12,7 +12,6 @@ import { FtrProviderContext } from '../ftr_provider_context'; export function InspectorProvider({ getService }: FtrProviderContext) { const log = getService('log'); const retry = getService('retry'); - const browser = getService('browser'); const renderable = getService('renderable'); const flyout = getService('flyout'); const testSubjects = getService('testSubjects'); @@ -235,18 +234,6 @@ export function InspectorProvider({ getService }: FtrProviderContext) { public getOpenRequestDetailResponseButton() { return testSubjects.find('inspectorRequestDetailResponse'); } - - public async getCodeEditorValue() { - let request: string = ''; - - await retry.try(async () => { - request = await browser.execute( - () => (window as any).MonacoEnvironment.monaco.editor.getModels()[0].getValue() as string - ); - }); - - return request; - } } return new Inspector(); diff --git a/test/functional/services/monaco_editor.ts b/test/functional/services/monaco_editor.ts new file mode 100644 index 000000000000..e0763659be9c --- /dev/null +++ b/test/functional/services/monaco_editor.ts @@ -0,0 +1,28 @@ +/* + * 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 { FtrProviderContext } from '../ftr_provider_context'; + +export function MonacoEditorProvider({ getService }: FtrProviderContext) { + const retry = getService('retry'); + const browser = getService('browser'); + + return new (class MonacoEditor { + public async getCodeEditorValue() { + let request: string = ''; + + await retry.try(async () => { + request = await browser.execute( + () => (window as any).MonacoEnvironment.monaco.editor.getModels()[0].getValue() as string + ); + }); + + return request; + } + })(); +} diff --git a/x-pack/test/functional/apps/maps/documents_source/docvalue_fields.js b/x-pack/test/functional/apps/maps/documents_source/docvalue_fields.js index 5886fcdcb135..c0ea9a5c73da 100644 --- a/x-pack/test/functional/apps/maps/documents_source/docvalue_fields.js +++ b/x-pack/test/functional/apps/maps/documents_source/docvalue_fields.js @@ -10,6 +10,7 @@ import expect from '@kbn/expect'; export default function ({ getPageObjects, getService }) { const PageObjects = getPageObjects(['maps']); const inspector = getService('inspector'); + const monacoEditor = getService('monacoEditor'); const testSubjects = getService('testSubjects'); const security = getService('security'); @@ -27,7 +28,7 @@ export default function ({ getPageObjects, getService }) { await inspector.open(); await inspector.openInspectorRequestsView(); await testSubjects.click('inspectorRequestDetailResponse'); - const responseBody = await inspector.getCodeEditorValue(); + const responseBody = await monacoEditor.getCodeEditorValue(); await inspector.close(); return JSON.parse(responseBody); }