[9.0] [Discover][ES|QL] Fix JSON view for ES|QL record in DocViewer (#216642) (#216885)

# Backport

This will backport the following commits from `main` to `9.0`:
- [[Discover][ES|QL] Fix JSON view for ES|QL record in DocViewer
(#216642)](https://github.com/elastic/kibana/pull/216642)

<!--- Backport version: 9.6.6 -->

### Questions ?
Please refer to the [Backport tool
documentation](https://github.com/sorenlouv/backport)

<!--BACKPORT [{"author":{"name":"Julia
Rechkunova","email":"julia.rechkunova@elastic.co"},"sourceCommit":{"committedDate":"2025-04-02T15:59:03Z","message":"[Discover][ES|QL]
Fix JSON view for ES|QL record in DocViewer (#216642)\n\n- Closes
https://github.com/elastic/kibana/issues/214805\n\n## Summary\n\nBy
default ES|QL records don't have `_id` unless it's requested via
the\nquery `METADATA`.\nThis PR fixes the JSON view inside DocViewer for
ES|QL records.\nPreviously it was relying on `textBasedHits` which gets
updated when\nquery changes hence there is a possibility of loosing the
reference to\nthe last viewed record.\n\n## Testing\n\nExample
queries:\n```\nFROM kibana_sample_data_ecommerce METADATA _index\nFROM
kibana_sample_data_ecommerce METADATA _index, _id\n```\n\n###
Checklist\n\n\n- [x] [Unit or
functional\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\nwere
updated or added to match the most common
scenarios","sha":"43b6cc4c1df1aee03f7d3a52fbab3133c459ea43","branchLabelMapping":{"^v9.1.0$":"main","^v8.19.0$":"8.x","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["release_note:fix","v9.0.0","Team:DataDiscovery","backport:version","v8.18.0","v9.1.0","v8.19.0"],"title":"[Discover][ES|QL]
Fix JSON view for ES|QL record in
DocViewer","number":216642,"url":"https://github.com/elastic/kibana/pull/216642","mergeCommit":{"message":"[Discover][ES|QL]
Fix JSON view for ES|QL record in DocViewer (#216642)\n\n- Closes
https://github.com/elastic/kibana/issues/214805\n\n## Summary\n\nBy
default ES|QL records don't have `_id` unless it's requested via
the\nquery `METADATA`.\nThis PR fixes the JSON view inside DocViewer for
ES|QL records.\nPreviously it was relying on `textBasedHits` which gets
updated when\nquery changes hence there is a possibility of loosing the
reference to\nthe last viewed record.\n\n## Testing\n\nExample
queries:\n```\nFROM kibana_sample_data_ecommerce METADATA _index\nFROM
kibana_sample_data_ecommerce METADATA _index, _id\n```\n\n###
Checklist\n\n\n- [x] [Unit or
functional\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\nwere
updated or added to match the most common
scenarios","sha":"43b6cc4c1df1aee03f7d3a52fbab3133c459ea43"}},"sourceBranch":"main","suggestedTargetBranches":["9.0","8.18","8.x"],"targetPullRequestStates":[{"branch":"9.0","label":"v9.0.0","branchLabelMappingKey":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"},{"branch":"8.18","label":"v8.18.0","branchLabelMappingKey":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"},{"branch":"main","label":"v9.1.0","branchLabelMappingKey":"^v9.1.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/216642","number":216642,"mergeCommit":{"message":"[Discover][ES|QL]
Fix JSON view for ES|QL record in DocViewer (#216642)\n\n- Closes
https://github.com/elastic/kibana/issues/214805\n\n## Summary\n\nBy
default ES|QL records don't have `_id` unless it's requested via
the\nquery `METADATA`.\nThis PR fixes the JSON view inside DocViewer for
ES|QL records.\nPreviously it was relying on `textBasedHits` which gets
updated when\nquery changes hence there is a possibility of loosing the
reference to\nthe last viewed record.\n\n## Testing\n\nExample
queries:\n```\nFROM kibana_sample_data_ecommerce METADATA _index\nFROM
kibana_sample_data_ecommerce METADATA _index, _id\n```\n\n###
Checklist\n\n\n- [x] [Unit or
functional\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\nwere
updated or added to match the most common
scenarios","sha":"43b6cc4c1df1aee03f7d3a52fbab3133c459ea43"}},{"branch":"8.x","label":"v8.19.0","branchLabelMappingKey":"^v8.19.0$","isSourceBranch":false,"state":"NOT_CREATED"}]}]
BACKPORT-->

Co-authored-by: Julia Rechkunova <julia.rechkunova@elastic.co>
This commit is contained in:
Kibana Machine 2025-04-02 20:19:43 +02:00 committed by GitHub
parent d1ba622e36
commit c46210f690
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 58 additions and 25 deletions

View file

@ -16,6 +16,10 @@ import * as useUiSettingHook from '@kbn/kibana-react-plugin/public/ui_settings/u
import { EuiButton, EuiEmptyPrompt, EuiLoadingSpinner } from '@elastic/eui';
import { JsonCodeEditorCommon } from '../json_code_editor';
import { buildDataTableRecord } from '@kbn/discover-utils';
import { mockUnifiedDocViewerServices } from '../../__mocks__';
import { setUnifiedDocViewerServices } from '../../plugin';
setUnifiedDocViewerServices(mockUnifiedDocViewerServices);
const mockDataView = {
getComputedFields: () => [],
@ -94,4 +98,35 @@ describe('Source Viewer component', () => {
expect(jsonCodeEditor.props().hasLineNumbers).toBe(true);
expect(jsonCodeEditor.props().enableFindAction).toBe(true);
});
test('renders json code editor for ES|QL record', () => {
const record = {
_index: 'logstash-2014.09.09',
_id: 'id123',
message: 'Lorem ipsum dolor sit amet',
extension: 'html',
};
const mockHit = {
id: '22',
raw: record,
flattened: record,
};
jest.spyOn(useUiSettingHook, 'useUiSetting').mockImplementation(() => {
return false;
});
const comp = mountWithIntl(
<DocViewerSource
id={mockHit.id}
index={'index1'}
dataView={mockDataView}
esqlHit={mockHit}
width={123}
onRefresh={() => {}}
/>
);
const jsonCodeEditor = comp.find(JsonCodeEditorCommon);
expect(jsonCodeEditor).not.toBe(null);
expect(jsonCodeEditor.props().jsonValue).toContain('message');
expect(jsonCodeEditor.props().jsonValue).toContain('_id');
});
});

View file

@ -26,7 +26,7 @@ interface SourceViewerProps {
id: string;
index: string | undefined;
dataView: DataView;
textBasedHits?: DataTableRecord[];
esqlHit?: DataTableRecord;
width?: number;
decreaseAvailableHeightBy?: number;
onRefresh: () => void;
@ -39,7 +39,7 @@ export const DocViewerSource = ({
id,
index,
dataView,
textBasedHits,
esqlHit,
width,
decreaseAvailableHeightBy,
onRefresh,
@ -51,7 +51,7 @@ export const DocViewerSource = ({
id,
index,
dataView,
textBasedHits,
esqlHit,
});
useEffect(() => {

View file

@ -12,7 +12,7 @@ import { type EsDocSearchProps, buildSearchBody, useEsDocSearch } from './use_es
import { Subject } from 'rxjs';
import type { DataView } from '@kbn/data-views-plugin/public';
import { ElasticRequestState } from '@kbn/unified-doc-viewer';
import { buildDataTableRecord } from '@kbn/discover-utils';
import { buildDataTableRecord, DataTableRecord } from '@kbn/discover-utils';
import { setUnifiedDocViewerServices } from '../plugin';
import { UnifiedDocViewerServices } from '../types';
@ -206,18 +206,16 @@ describe('Test of <Doc /> helper / hook', () => {
getComputedFields: () => [],
getIndexPattern: () => index,
};
const props = {
const props: EsDocSearchProps = {
id: '1',
index: 'index1',
dataView,
textBasedHits: [
{
id: '1',
raw: { field1: 1, field2: 2 },
flattened: { field1: 1, field2: 2 },
},
],
} as unknown as EsDocSearchProps;
dataView: dataView as unknown as EsDocSearchProps['dataView'],
esqlHit: {
id: '1',
raw: { field1: 1, field2: 2 },
flattened: { field1: 1, field2: 2 },
} as DataTableRecord,
};
const hook = renderHook((p: EsDocSearchProps) => useEsDocSearch(p), {
initialProps: props,

View file

@ -33,9 +33,9 @@ export interface EsDocSearchProps {
*/
dataView: DataView;
/**
* Records fetched from text based query
* Record fetched from ES|QL query
*/
textBasedHits?: DataTableRecord[];
esqlHit?: DataTableRecord;
/**
* An optional callback that will be called before fetching the doc
*/
@ -54,7 +54,7 @@ export function useEsDocSearch({
id,
index,
dataView,
textBasedHits,
esqlHit,
onBeforeFetch,
onProcessRecord,
}: EsDocSearchProps): [ElasticRequestState, DataTableRecord | null, () => void] {
@ -111,16 +111,13 @@ export function useEsDocSearch({
}, [analytics, data.search, dataView, id, index, onBeforeFetch, onProcessRecord]);
useEffect(() => {
if (textBasedHits) {
const selectedHit = textBasedHits?.find((r) => r.id === id);
if (selectedHit) {
setStatus(ElasticRequestState.Found);
setHit(selectedHit);
}
if (esqlHit) {
setStatus(ElasticRequestState.Found);
setHit(esqlHit);
} else {
requestData();
}
}, [id, requestData, textBasedHits]);
}, [id, requestData, esqlHit]);
return [status, hit, requestData];
}

View file

@ -77,7 +77,10 @@ export class UnifiedDocViewerPublicPlugin
index={hit.raw._index}
id={hit.raw._id ?? hit.id}
dataView={dataView}
textBasedHits={textBasedHits}
// If ES|QL query changes, then textBasedHits will update too.
// This is a workaround to reuse the previously referred hit
// so the doc viewer preserves the state even after the record disappears from hits list.
esqlHit={Array.isArray(textBasedHits) ? hit : undefined}
decreaseAvailableHeightBy={decreaseAvailableHeightBy}
onRefresh={() => {}}
/>