mirror of
https://github.com/elastic/kibana.git
synced 2025-04-25 02:09:32 -04:00
* [Discover] Hide multifields from doc table * Fix failing type check * Fix eslint * Fix faulty logic * Fix linting error * Add memoization to the function * Move getFieldsToShow a bit higher up * Extracting getFieldsToShow logic higher up * Fix linting error / table logic * Move fieldsToShow to doc_table_wrapper Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
a0fd8e2089
commit
aa7680e3c1
11 changed files with 210 additions and 30 deletions
|
@ -35,6 +35,7 @@ export interface TableRowProps {
|
||||||
hideTimeColumn: boolean;
|
hideTimeColumn: boolean;
|
||||||
filterManager: FilterManager;
|
filterManager: FilterManager;
|
||||||
addBasePath: (path: string) => string;
|
addBasePath: (path: string) => string;
|
||||||
|
fieldsToShow: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export const TableRow = ({
|
export const TableRow = ({
|
||||||
|
@ -43,6 +44,7 @@ export const TableRow = ({
|
||||||
row,
|
row,
|
||||||
indexPattern,
|
indexPattern,
|
||||||
useNewFieldsApi,
|
useNewFieldsApi,
|
||||||
|
fieldsToShow,
|
||||||
hideTimeColumn,
|
hideTimeColumn,
|
||||||
onAddColumn,
|
onAddColumn,
|
||||||
onRemoveColumn,
|
onRemoveColumn,
|
||||||
|
@ -125,7 +127,7 @@ export const TableRow = ({
|
||||||
}
|
}
|
||||||
|
|
||||||
if (columns.length === 0 && useNewFieldsApi) {
|
if (columns.length === 0 && useNewFieldsApi) {
|
||||||
const formatted = formatRow(row, indexPattern);
|
const formatted = formatRow(row, indexPattern, fieldsToShow);
|
||||||
|
|
||||||
rowCells.push(
|
rowCells.push(
|
||||||
<TableCell
|
<TableCell
|
||||||
|
|
|
@ -14,12 +14,14 @@ import { FORMATS_UI_SETTINGS } from '../../../../../../../field_formats/common';
|
||||||
import {
|
import {
|
||||||
DOC_HIDE_TIME_COLUMN_SETTING,
|
DOC_HIDE_TIME_COLUMN_SETTING,
|
||||||
SAMPLE_SIZE_SETTING,
|
SAMPLE_SIZE_SETTING,
|
||||||
|
SHOW_MULTIFIELDS,
|
||||||
SORT_DEFAULT_ORDER_SETTING,
|
SORT_DEFAULT_ORDER_SETTING,
|
||||||
} from '../../../../../../common';
|
} from '../../../../../../common';
|
||||||
import { getServices, IndexPattern } from '../../../../../kibana_services';
|
import { getServices, IndexPattern, IndexPatternField } from '../../../../../kibana_services';
|
||||||
import { SortOrder } from './components/table_header/helpers';
|
import { SortOrder } from './components/table_header/helpers';
|
||||||
import { DocTableRow, TableRow } from './components/table_row';
|
import { DocTableRow, TableRow } from './components/table_row';
|
||||||
import { DocViewFilterFn } from '../../../../doc_views/doc_views_types';
|
import { DocViewFilterFn } from '../../../../doc_views/doc_views_types';
|
||||||
|
import { getFieldsToShow } from '../../../../helpers/get_fields_to_show';
|
||||||
|
|
||||||
export interface DocTableProps {
|
export interface DocTableProps {
|
||||||
/**
|
/**
|
||||||
|
@ -120,6 +122,7 @@ export const DocTableWrapper = ({
|
||||||
hideTimeColumn,
|
hideTimeColumn,
|
||||||
isShortDots,
|
isShortDots,
|
||||||
sampleSize,
|
sampleSize,
|
||||||
|
showMultiFields,
|
||||||
filterManager,
|
filterManager,
|
||||||
addBasePath,
|
addBasePath,
|
||||||
] = useMemo(() => {
|
] = useMemo(() => {
|
||||||
|
@ -129,6 +132,7 @@ export const DocTableWrapper = ({
|
||||||
services.uiSettings.get(DOC_HIDE_TIME_COLUMN_SETTING, false),
|
services.uiSettings.get(DOC_HIDE_TIME_COLUMN_SETTING, false),
|
||||||
services.uiSettings.get(FORMATS_UI_SETTINGS.SHORT_DOTS_ENABLE),
|
services.uiSettings.get(FORMATS_UI_SETTINGS.SHORT_DOTS_ENABLE),
|
||||||
services.uiSettings.get(SAMPLE_SIZE_SETTING, 500),
|
services.uiSettings.get(SAMPLE_SIZE_SETTING, 500),
|
||||||
|
services.uiSettings.get(SHOW_MULTIFIELDS, false),
|
||||||
services.filterManager,
|
services.filterManager,
|
||||||
services.addBasePath,
|
services.addBasePath,
|
||||||
];
|
];
|
||||||
|
@ -149,6 +153,16 @@ export const DocTableWrapper = ({
|
||||||
bottomMarker!.blur();
|
bottomMarker!.blur();
|
||||||
}, [setMinimumVisibleRows, rows]);
|
}, [setMinimumVisibleRows, rows]);
|
||||||
|
|
||||||
|
const fieldsToShow = useMemo(
|
||||||
|
() =>
|
||||||
|
getFieldsToShow(
|
||||||
|
indexPattern.fields.map((field: IndexPatternField) => field.name),
|
||||||
|
indexPattern,
|
||||||
|
showMultiFields
|
||||||
|
),
|
||||||
|
[indexPattern, showMultiFields]
|
||||||
|
);
|
||||||
|
|
||||||
const renderHeader = useCallback(
|
const renderHeader = useCallback(
|
||||||
() => (
|
() => (
|
||||||
<TableHeader
|
<TableHeader
|
||||||
|
@ -193,6 +207,7 @@ export const DocTableWrapper = ({
|
||||||
onRemoveColumn={onRemoveColumn}
|
onRemoveColumn={onRemoveColumn}
|
||||||
filterManager={filterManager}
|
filterManager={filterManager}
|
||||||
addBasePath={addBasePath}
|
addBasePath={addBasePath}
|
||||||
|
fieldsToShow={fieldsToShow}
|
||||||
/>
|
/>
|
||||||
));
|
));
|
||||||
},
|
},
|
||||||
|
@ -206,6 +221,7 @@ export const DocTableWrapper = ({
|
||||||
onRemoveColumn,
|
onRemoveColumn,
|
||||||
filterManager,
|
filterManager,
|
||||||
addBasePath,
|
addBasePath,
|
||||||
|
fieldsToShow,
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -45,6 +45,8 @@ describe('Row formatter', () => {
|
||||||
|
|
||||||
const indexPattern = createIndexPattern();
|
const indexPattern = createIndexPattern();
|
||||||
|
|
||||||
|
const fieldsToShow = indexPattern.fields.getAll().map((fld) => fld.name);
|
||||||
|
|
||||||
// Realistic response with alphabetical insertion order
|
// Realistic response with alphabetical insertion order
|
||||||
const formatHitReturnValue = {
|
const formatHitReturnValue = {
|
||||||
also: 'with \\"quotes\\" or 'single qoutes'',
|
also: 'with \\"quotes\\" or 'single qoutes'',
|
||||||
|
@ -69,7 +71,7 @@ describe('Row formatter', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('formats document properly', () => {
|
it('formats document properly', () => {
|
||||||
expect(formatRow(hit, indexPattern)).toMatchInlineSnapshot(`
|
expect(formatRow(hit, indexPattern, fieldsToShow)).toMatchInlineSnapshot(`
|
||||||
<TemplateComponent
|
<TemplateComponent
|
||||||
defPairs={
|
defPairs={
|
||||||
Array [
|
Array [
|
||||||
|
@ -113,7 +115,7 @@ describe('Row formatter', () => {
|
||||||
get: () => 1,
|
get: () => 1,
|
||||||
},
|
},
|
||||||
} as unknown) as DiscoverServices);
|
} as unknown) as DiscoverServices);
|
||||||
expect(formatRow(hit, indexPattern)).toMatchInlineSnapshot(`
|
expect(formatRow(hit, indexPattern, [])).toMatchInlineSnapshot(`
|
||||||
<TemplateComponent
|
<TemplateComponent
|
||||||
defPairs={
|
defPairs={
|
||||||
Array [
|
Array [
|
||||||
|
@ -128,7 +130,8 @@ describe('Row formatter', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('formats document with highlighted fields first', () => {
|
it('formats document with highlighted fields first', () => {
|
||||||
expect(formatRow({ ...hit, highlight: { number: '42' } }, indexPattern)).toMatchInlineSnapshot(`
|
expect(formatRow({ ...hit, highlight: { number: '42' } }, indexPattern, fieldsToShow))
|
||||||
|
.toMatchInlineSnapshot(`
|
||||||
<TemplateComponent
|
<TemplateComponent
|
||||||
defPairs={
|
defPairs={
|
||||||
Array [
|
Array [
|
||||||
|
|
|
@ -29,8 +29,12 @@ const TemplateComponent = ({ defPairs }: Props) => {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const formatRow = (
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
export const formatRow = (hit: Record<string, any>, indexPattern: IndexPattern) => {
|
hit: Record<string, any>,
|
||||||
|
indexPattern: IndexPattern,
|
||||||
|
fieldsToShow: string[]
|
||||||
|
) => {
|
||||||
const highlights = hit?.highlight ?? {};
|
const highlights = hit?.highlight ?? {};
|
||||||
// Keys are sorted in the hits object
|
// Keys are sorted in the hits object
|
||||||
const formatted = indexPattern.formatHit(hit);
|
const formatted = indexPattern.formatHit(hit);
|
||||||
|
@ -40,7 +44,13 @@ export const formatRow = (hit: Record<string, any>, indexPattern: IndexPattern)
|
||||||
Object.entries(formatted).forEach(([key, val]) => {
|
Object.entries(formatted).forEach(([key, val]) => {
|
||||||
const displayKey = fields.getByName ? fields.getByName(key)?.displayName : undefined;
|
const displayKey = fields.getByName ? fields.getByName(key)?.displayName : undefined;
|
||||||
const pairs = highlights[key] ? highlightPairs : sourcePairs;
|
const pairs = highlights[key] ? highlightPairs : sourcePairs;
|
||||||
pairs.push([displayKey ? displayKey : key, val]);
|
if (displayKey) {
|
||||||
|
if (fieldsToShow.includes(displayKey)) {
|
||||||
|
pairs.push([displayKey, val]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
pairs.push([key, val]);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
const maxEntries = getServices().uiSettings.get(MAX_DOC_FIELDS_DISPLAYED);
|
const maxEntries = getServices().uiSettings.get(MAX_DOC_FIELDS_DISPLAYED);
|
||||||
return <TemplateComponent defPairs={[...highlightPairs, ...sourcePairs].slice(0, maxEntries)} />;
|
return <TemplateComponent defPairs={[...highlightPairs, ...sourcePairs].slice(0, maxEntries)} />;
|
||||||
|
|
|
@ -37,9 +37,10 @@ import { defaultPageSize, gridStyle, pageSizeArr, toolbarVisibility } from './co
|
||||||
import { DiscoverServices } from '../../../build_services';
|
import { DiscoverServices } from '../../../build_services';
|
||||||
import { getDisplayedColumns } from '../../helpers/columns';
|
import { getDisplayedColumns } from '../../helpers/columns';
|
||||||
import { KibanaContextProvider } from '../../../../../kibana_react/public';
|
import { KibanaContextProvider } from '../../../../../kibana_react/public';
|
||||||
import { MAX_DOC_FIELDS_DISPLAYED } from '../../../../common';
|
import { MAX_DOC_FIELDS_DISPLAYED, SHOW_MULTIFIELDS } from '../../../../common';
|
||||||
import { DiscoverGridDocumentToolbarBtn, getDocId } from './discover_grid_document_selection';
|
import { DiscoverGridDocumentToolbarBtn, getDocId } from './discover_grid_document_selection';
|
||||||
import { SortPairArr } from '../../apps/main/components/doc_table/lib/get_sort';
|
import { SortPairArr } from '../../apps/main/components/doc_table/lib/get_sort';
|
||||||
|
import { getFieldsToShow } from '../../helpers/get_fields_to_show';
|
||||||
|
|
||||||
interface SortObj {
|
interface SortObj {
|
||||||
id: string;
|
id: string;
|
||||||
|
@ -256,6 +257,13 @@ export const DiscoverGrid = ({
|
||||||
[onSort, isSortEnabled]
|
[onSort, isSortEnabled]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const showMultiFields = services.uiSettings.get(SHOW_MULTIFIELDS);
|
||||||
|
|
||||||
|
const fieldsToShow = useMemo(() => {
|
||||||
|
const indexPatternFields = indexPattern.fields.getAll().map((fld) => fld.name);
|
||||||
|
return getFieldsToShow(indexPatternFields, indexPattern, showMultiFields);
|
||||||
|
}, [indexPattern, showMultiFields]);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cell rendering
|
* Cell rendering
|
||||||
*/
|
*/
|
||||||
|
@ -266,9 +274,10 @@ export const DiscoverGrid = ({
|
||||||
displayedRows,
|
displayedRows,
|
||||||
displayedRows ? displayedRows.map((hit) => indexPattern.flattenHit(hit)) : [],
|
displayedRows ? displayedRows.map((hit) => indexPattern.flattenHit(hit)) : [],
|
||||||
useNewFieldsApi,
|
useNewFieldsApi,
|
||||||
|
fieldsToShow,
|
||||||
services.uiSettings.get(MAX_DOC_FIELDS_DISPLAYED)
|
services.uiSettings.get(MAX_DOC_FIELDS_DISPLAYED)
|
||||||
),
|
),
|
||||||
[displayedRows, indexPattern, useNewFieldsApi, services.uiSettings]
|
[indexPattern, displayedRows, useNewFieldsApi, fieldsToShow, services.uiSettings]
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -75,6 +75,7 @@ describe('Discover grid cell rendering', function () {
|
||||||
rowsSource,
|
rowsSource,
|
||||||
rowsSource.map((row) => indexPatternMock.flattenHit(row)),
|
rowsSource.map((row) => indexPatternMock.flattenHit(row)),
|
||||||
false,
|
false,
|
||||||
|
[],
|
||||||
100
|
100
|
||||||
);
|
);
|
||||||
const component = shallow(
|
const component = shallow(
|
||||||
|
@ -96,6 +97,7 @@ describe('Discover grid cell rendering', function () {
|
||||||
rowsSource,
|
rowsSource,
|
||||||
rowsSource.map((row) => indexPatternMock.flattenHit(row)),
|
rowsSource.map((row) => indexPatternMock.flattenHit(row)),
|
||||||
false,
|
false,
|
||||||
|
[],
|
||||||
100
|
100
|
||||||
);
|
);
|
||||||
const component = shallow(
|
const component = shallow(
|
||||||
|
@ -146,6 +148,7 @@ describe('Discover grid cell rendering', function () {
|
||||||
rowsSource,
|
rowsSource,
|
||||||
rowsSource.map((row) => indexPatternMock.flattenHit(row)),
|
rowsSource.map((row) => indexPatternMock.flattenHit(row)),
|
||||||
false,
|
false,
|
||||||
|
[],
|
||||||
100
|
100
|
||||||
);
|
);
|
||||||
const component = shallow(
|
const component = shallow(
|
||||||
|
@ -188,6 +191,7 @@ describe('Discover grid cell rendering', function () {
|
||||||
rowsFields,
|
rowsFields,
|
||||||
rowsFields.map((row) => indexPatternMock.flattenHit(row)),
|
rowsFields.map((row) => indexPatternMock.flattenHit(row)),
|
||||||
true,
|
true,
|
||||||
|
[],
|
||||||
100
|
100
|
||||||
);
|
);
|
||||||
const component = shallow(
|
const component = shallow(
|
||||||
|
@ -242,6 +246,7 @@ describe('Discover grid cell rendering', function () {
|
||||||
rowsFields,
|
rowsFields,
|
||||||
rowsFields.map((row) => indexPatternMock.flattenHit(row)),
|
rowsFields.map((row) => indexPatternMock.flattenHit(row)),
|
||||||
true,
|
true,
|
||||||
|
[],
|
||||||
// this is the number of rendered items
|
// this is the number of rendered items
|
||||||
1
|
1
|
||||||
);
|
);
|
||||||
|
@ -284,6 +289,7 @@ describe('Discover grid cell rendering', function () {
|
||||||
rowsFields,
|
rowsFields,
|
||||||
rowsFields.map((row) => indexPatternMock.flattenHit(row)),
|
rowsFields.map((row) => indexPatternMock.flattenHit(row)),
|
||||||
true,
|
true,
|
||||||
|
[],
|
||||||
100
|
100
|
||||||
);
|
);
|
||||||
const component = shallow(
|
const component = shallow(
|
||||||
|
@ -331,6 +337,7 @@ describe('Discover grid cell rendering', function () {
|
||||||
rowsFieldsWithTopLevelObject,
|
rowsFieldsWithTopLevelObject,
|
||||||
rowsFieldsWithTopLevelObject.map((row) => indexPatternMock.flattenHit(row)),
|
rowsFieldsWithTopLevelObject.map((row) => indexPatternMock.flattenHit(row)),
|
||||||
true,
|
true,
|
||||||
|
[],
|
||||||
100
|
100
|
||||||
);
|
);
|
||||||
const component = shallow(
|
const component = shallow(
|
||||||
|
@ -371,6 +378,7 @@ describe('Discover grid cell rendering', function () {
|
||||||
rowsFieldsWithTopLevelObject,
|
rowsFieldsWithTopLevelObject,
|
||||||
rowsFieldsWithTopLevelObject.map((row) => indexPatternMock.flattenHit(row)),
|
rowsFieldsWithTopLevelObject.map((row) => indexPatternMock.flattenHit(row)),
|
||||||
true,
|
true,
|
||||||
|
[],
|
||||||
100
|
100
|
||||||
);
|
);
|
||||||
const component = shallow(
|
const component = shallow(
|
||||||
|
@ -410,6 +418,7 @@ describe('Discover grid cell rendering', function () {
|
||||||
rowsFieldsWithTopLevelObject,
|
rowsFieldsWithTopLevelObject,
|
||||||
rowsFieldsWithTopLevelObject.map((row) => indexPatternMock.flattenHit(row)),
|
rowsFieldsWithTopLevelObject.map((row) => indexPatternMock.flattenHit(row)),
|
||||||
true,
|
true,
|
||||||
|
[],
|
||||||
100
|
100
|
||||||
);
|
);
|
||||||
const component = shallow(
|
const component = shallow(
|
||||||
|
@ -440,6 +449,7 @@ describe('Discover grid cell rendering', function () {
|
||||||
rowsFieldsWithTopLevelObject,
|
rowsFieldsWithTopLevelObject,
|
||||||
rowsFieldsWithTopLevelObject.map((row) => indexPatternMock.flattenHit(row)),
|
rowsFieldsWithTopLevelObject.map((row) => indexPatternMock.flattenHit(row)),
|
||||||
true,
|
true,
|
||||||
|
[],
|
||||||
100
|
100
|
||||||
);
|
);
|
||||||
const component = shallow(
|
const component = shallow(
|
||||||
|
@ -469,6 +479,7 @@ describe('Discover grid cell rendering', function () {
|
||||||
rowsSource,
|
rowsSource,
|
||||||
rowsSource.map((row) => indexPatternMock.flattenHit(row)),
|
rowsSource.map((row) => indexPatternMock.flattenHit(row)),
|
||||||
false,
|
false,
|
||||||
|
[],
|
||||||
100
|
100
|
||||||
);
|
);
|
||||||
const component = shallow(
|
const component = shallow(
|
||||||
|
@ -490,6 +501,7 @@ describe('Discover grid cell rendering', function () {
|
||||||
rowsSource,
|
rowsSource,
|
||||||
rowsSource.map((row) => indexPatternMock.flattenHit(row)),
|
rowsSource.map((row) => indexPatternMock.flattenHit(row)),
|
||||||
false,
|
false,
|
||||||
|
[],
|
||||||
100
|
100
|
||||||
);
|
);
|
||||||
const component = shallow(
|
const component = shallow(
|
||||||
|
|
|
@ -28,6 +28,7 @@ export const getRenderCellValueFn = (
|
||||||
rows: ElasticSearchHit[] | undefined,
|
rows: ElasticSearchHit[] | undefined,
|
||||||
rowsFlattened: Array<Record<string, unknown>>,
|
rowsFlattened: Array<Record<string, unknown>>,
|
||||||
useNewFieldsApi: boolean,
|
useNewFieldsApi: boolean,
|
||||||
|
fieldsToShow: string[],
|
||||||
maxDocFieldsDisplayed: number
|
maxDocFieldsDisplayed: number
|
||||||
) => ({ rowIndex, columnId, isDetails, setCellProps }: EuiDataGridCellValueElementProps) => {
|
) => ({ rowIndex, columnId, isDetails, setCellProps }: EuiDataGridCellValueElementProps) => {
|
||||||
const row = rows ? rows[rowIndex] : undefined;
|
const row = rows ? rows[rowIndex] : undefined;
|
||||||
|
@ -99,7 +100,13 @@ export const getRenderCellValueFn = (
|
||||||
)
|
)
|
||||||
.join(', ');
|
.join(', ');
|
||||||
const pairs = highlights[key] ? highlightPairs : sourcePairs;
|
const pairs = highlights[key] ? highlightPairs : sourcePairs;
|
||||||
pairs.push([displayKey ? displayKey : key, formatted]);
|
if (displayKey) {
|
||||||
|
if (fieldsToShow.includes(displayKey)) {
|
||||||
|
pairs.push([displayKey, formatted]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
pairs.push([key, formatted]);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -137,13 +144,18 @@ export const getRenderCellValueFn = (
|
||||||
const highlights: Record<string, unknown> = (row.highlight as Record<string, unknown>) ?? {};
|
const highlights: Record<string, unknown> = (row.highlight as Record<string, unknown>) ?? {};
|
||||||
const highlightPairs: Array<[string, string]> = [];
|
const highlightPairs: Array<[string, string]> = [];
|
||||||
const sourcePairs: Array<[string, string]> = [];
|
const sourcePairs: Array<[string, string]> = [];
|
||||||
|
|
||||||
Object.entries(formatted).forEach(([key, val]) => {
|
Object.entries(formatted).forEach(([key, val]) => {
|
||||||
const pairs = highlights[key] ? highlightPairs : sourcePairs;
|
const pairs = highlights[key] ? highlightPairs : sourcePairs;
|
||||||
const displayKey = indexPattern.fields.getByName
|
const displayKey = indexPattern.fields.getByName
|
||||||
? indexPattern.fields.getByName(key)?.displayName
|
? indexPattern.fields.getByName(key)?.displayName
|
||||||
: undefined;
|
: undefined;
|
||||||
pairs.push([displayKey ? displayKey : key, val as string]);
|
if (displayKey) {
|
||||||
|
if (fieldsToShow.includes(displayKey)) {
|
||||||
|
pairs.push([displayKey, val as string]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
pairs.push([key, val as string]);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -475,11 +475,13 @@ describe('DocViewTable at Discover Doc with Fields API', () => {
|
||||||
.length
|
.length
|
||||||
).toBe(0);
|
).toBe(0);
|
||||||
|
|
||||||
|
expect(findTestSubject(component, 'tableDocViewRow-customer_first_name').length).toBe(1);
|
||||||
expect(
|
expect(
|
||||||
findTestSubject(component, 'tableDocViewRow-customer_first_name.nickname-multifieldBadge')
|
findTestSubject(component, 'tableDocViewRow-customer_first_name.nickname-multifieldBadge')
|
||||||
.length
|
.length
|
||||||
).toBe(0);
|
).toBe(0);
|
||||||
|
|
||||||
|
expect(findTestSubject(component, 'tableDocViewRow-city').length).toBe(0);
|
||||||
expect(findTestSubject(component, 'tableDocViewRow-city.raw').length).toBe(1);
|
expect(findTestSubject(component, 'tableDocViewRow-city.raw').length).toBe(1);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
* Side Public License, v 1.
|
* Side Public License, v 1.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React, { useCallback, useMemo, useState } from 'react';
|
import React, { useCallback, useMemo } from 'react';
|
||||||
import { EuiInMemoryTable } from '@elastic/eui';
|
import { EuiInMemoryTable } from '@elastic/eui';
|
||||||
import { IndexPattern, IndexPatternField } from '../../../../../data/public';
|
import { IndexPattern, IndexPatternField } from '../../../../../data/public';
|
||||||
import { SHOW_MULTIFIELDS } from '../../../../common';
|
import { SHOW_MULTIFIELDS } from '../../../../common';
|
||||||
|
@ -18,6 +18,7 @@ import {
|
||||||
DocViewRenderProps,
|
DocViewRenderProps,
|
||||||
} from '../../doc_views/doc_views_types';
|
} from '../../doc_views/doc_views_types';
|
||||||
import { ACTIONS_COLUMN, MAIN_COLUMNS } from './table_columns';
|
import { ACTIONS_COLUMN, MAIN_COLUMNS } from './table_columns';
|
||||||
|
import { getFieldsToShow } from '../../helpers/get_fields_to_show';
|
||||||
|
|
||||||
export interface DocViewerTableProps {
|
export interface DocViewerTableProps {
|
||||||
columns?: string[];
|
columns?: string[];
|
||||||
|
@ -61,8 +62,6 @@ export const DocViewerTable = ({
|
||||||
indexPattern?.fields,
|
indexPattern?.fields,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const [childParentFieldsMap] = useState({} as Record<string, string>);
|
|
||||||
|
|
||||||
const formattedHit = useMemo(() => indexPattern?.formatHit(hit, 'html'), [hit, indexPattern]);
|
const formattedHit = useMemo(() => indexPattern?.formatHit(hit, 'html'), [hit, indexPattern]);
|
||||||
|
|
||||||
const tableColumns = useMemo(() => {
|
const tableColumns = useMemo(() => {
|
||||||
|
@ -95,22 +94,12 @@ export const DocViewerTable = ({
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const flattened = indexPattern.flattenHit(hit);
|
const flattened = indexPattern?.flattenHit(hit);
|
||||||
Object.keys(flattened).forEach((key) => {
|
const fieldsToShow = getFieldsToShow(Object.keys(flattened), indexPattern, showMultiFields);
|
||||||
const field = mapping(key);
|
|
||||||
if (field && field.spec?.subType?.multi?.parent) {
|
|
||||||
childParentFieldsMap[field.name] = field.spec.subType.multi.parent;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
const items: FieldRecord[] = Object.keys(flattened)
|
const items: FieldRecord[] = Object.keys(flattened)
|
||||||
.filter((fieldName) => {
|
.filter((fieldName) => {
|
||||||
const fieldMapping = mapping(fieldName);
|
return fieldsToShow.includes(fieldName);
|
||||||
const isMultiField = !!fieldMapping?.spec?.subType?.multi;
|
|
||||||
if (!isMultiField) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
const parent = childParentFieldsMap[fieldName];
|
|
||||||
return showMultiFields || (parent && !flattened.hasOwnProperty(parent));
|
|
||||||
})
|
})
|
||||||
.sort((fieldA, fieldB) => {
|
.sort((fieldA, fieldB) => {
|
||||||
const mappingA = mapping(fieldA);
|
const mappingA = mapping(fieldA);
|
||||||
|
|
|
@ -0,0 +1,93 @@
|
||||||
|
/*
|
||||||
|
* 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 { IndexPattern, IndexPatternField } from '../../../../data/common';
|
||||||
|
import { getFieldsToShow } from './get_fields_to_show';
|
||||||
|
|
||||||
|
describe('get fields to show', () => {
|
||||||
|
let indexPattern: IndexPattern;
|
||||||
|
const indexPatternFields: Record<string, IndexPatternField> = {
|
||||||
|
'machine.os': {
|
||||||
|
name: 'machine.os',
|
||||||
|
esTypes: ['text'],
|
||||||
|
type: 'string',
|
||||||
|
aggregatable: false,
|
||||||
|
searchable: false,
|
||||||
|
filterable: true,
|
||||||
|
} as IndexPatternField,
|
||||||
|
'machine.os.raw': {
|
||||||
|
name: 'machine.os.raw',
|
||||||
|
type: 'string',
|
||||||
|
esTypes: ['keyword'],
|
||||||
|
aggregatable: true,
|
||||||
|
searchable: true,
|
||||||
|
filterable: true,
|
||||||
|
spec: {
|
||||||
|
subType: {
|
||||||
|
multi: {
|
||||||
|
parent: 'machine.os',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
} as IndexPatternField,
|
||||||
|
acknowledged: {
|
||||||
|
name: 'acknowledged',
|
||||||
|
type: 'boolean',
|
||||||
|
esTypes: ['boolean'],
|
||||||
|
aggregatable: true,
|
||||||
|
searchable: true,
|
||||||
|
filterable: true,
|
||||||
|
} as IndexPatternField,
|
||||||
|
bytes: {
|
||||||
|
name: 'bytes',
|
||||||
|
type: 'number',
|
||||||
|
esTypes: ['long'],
|
||||||
|
aggregatable: true,
|
||||||
|
searchable: true,
|
||||||
|
filterable: true,
|
||||||
|
} as IndexPatternField,
|
||||||
|
clientip: {
|
||||||
|
name: 'clientip',
|
||||||
|
type: 'ip',
|
||||||
|
esTypes: ['ip'],
|
||||||
|
aggregatable: true,
|
||||||
|
searchable: true,
|
||||||
|
filterable: true,
|
||||||
|
} as IndexPatternField,
|
||||||
|
};
|
||||||
|
const stubIndexPattern = {
|
||||||
|
id: 'logstash-*',
|
||||||
|
fields: Object.keys(indexPatternFields).map((key) => indexPatternFields[key]),
|
||||||
|
title: 'logstash-*',
|
||||||
|
timeFieldName: '@timestamp',
|
||||||
|
getTimeField: () => ({ name: '@timestamp', type: 'date' }),
|
||||||
|
};
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
indexPattern = stubIndexPattern as IndexPattern;
|
||||||
|
indexPattern.fields.getByName = (name) => indexPatternFields[name];
|
||||||
|
});
|
||||||
|
|
||||||
|
it('shows multifields when showMultiFields is true', () => {
|
||||||
|
const fieldsToShow = getFieldsToShow(
|
||||||
|
['machine.os', 'machine.os.raw', 'clientip'],
|
||||||
|
indexPattern,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
expect(fieldsToShow).toEqual(['machine.os', 'machine.os.raw', 'clientip']);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('do not show multifields when showMultiFields is false', () => {
|
||||||
|
const fieldsToShow = getFieldsToShow(
|
||||||
|
['machine.os', 'machine.os.raw', 'acknowledged', 'clientip'],
|
||||||
|
indexPattern,
|
||||||
|
false
|
||||||
|
);
|
||||||
|
expect(fieldsToShow).toEqual(['machine.os', 'acknowledged', 'clientip']);
|
||||||
|
});
|
||||||
|
});
|
|
@ -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 { IndexPattern } from '../../../../data/common';
|
||||||
|
|
||||||
|
export const getFieldsToShow = (
|
||||||
|
fields: string[],
|
||||||
|
indexPattern: IndexPattern,
|
||||||
|
showMultiFields: boolean
|
||||||
|
) => {
|
||||||
|
const childParentFieldsMap = {} as Record<string, string>;
|
||||||
|
const mapping = (name: string) => indexPattern.fields.getByName(name);
|
||||||
|
fields.forEach((key) => {
|
||||||
|
const mapped = mapping(key);
|
||||||
|
if (mapped && mapped.spec?.subType?.multi?.parent) {
|
||||||
|
childParentFieldsMap[mapped.name] = mapped.spec.subType.multi.parent;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return fields.filter((key: string) => {
|
||||||
|
const fieldMapping = mapping(key);
|
||||||
|
const isMultiField = !!fieldMapping?.spec?.subType?.multi;
|
||||||
|
if (!isMultiField) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
const parent = childParentFieldsMap[key];
|
||||||
|
return showMultiFields || (parent && !fields.includes(parent));
|
||||||
|
});
|
||||||
|
};
|
Loading…
Add table
Add a link
Reference in a new issue