From 00093b4cc9304fefda8e873aaa2fdb7644f71f2d Mon Sep 17 00:00:00 2001 From: Matthew Bargar Date: Tue, 7 Jan 2020 16:58:35 -0500 Subject: [PATCH 1/6] Apply label and icon to nested fields in the doc table --- .../discover/np_ready/components/table/table.tsx | 11 +++++++++++ .../discover/np_ready/components/table/table_row.tsx | 4 +++- .../public/directives/field_name/field_type_name.ts | 4 ++++ 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/legacy/core_plugins/kibana/public/discover/np_ready/components/table/table.tsx b/src/legacy/core_plugins/kibana/public/discover/np_ready/components/table/table.tsx index 4bb2f83016c22e..c2d503fca831ef 100644 --- a/src/legacy/core_plugins/kibana/public/discover/np_ready/components/table/table.tsx +++ b/src/legacy/core_plugins/kibana/public/discover/np_ready/components/table/table.tsx @@ -68,11 +68,22 @@ export function DocViewTable({ const displayNoMappingWarning = !mapping(field) && !displayUnderscoreWarning && !isArrayOfObjects; + // Nested fields are not a part of the index pattern but their children are. + // Nested children are not a part of the flattened document but their nested parent is. + // So to detect nested fields we look through the index pattern for nested children + // that have the current field in their path. Knowing which fields are nested allows us + // to label them and apply the correct icon in the table row. + const isNestedField = !!indexPattern.fields.find(patternField => + patternField.subType?.nested?.path.includes(field) + ); + const fieldType = isNestedField ? 'nested' : undefined; + return ( )} - + {isCollapsible && ( diff --git a/src/legacy/ui/public/directives/field_name/field_type_name.ts b/src/legacy/ui/public/directives/field_name/field_type_name.ts index 14376b163d6f01..c8c886015cea32 100644 --- a/src/legacy/ui/public/directives/field_name/field_type_name.ts +++ b/src/legacy/ui/public/directives/field_name/field_type_name.ts @@ -61,6 +61,10 @@ export function getFieldTypeName(type: string) { return i18n.translate('common.ui.directives.fieldNameIcons.stringFieldAriaLabel', { defaultMessage: 'String field', }); + case 'nested': + return i18n.translate('common.ui.directives.fieldNameIcons.nestedFieldAriaLabel', { + defaultMessage: 'Nested field', + }); default: return i18n.translate('common.ui.directives.fieldNameIcons.unknownFieldAriaLabel', { defaultMessage: 'Unknown field', From 830eee6295259ef4e8a24dd4ffbf1a1522d18093 Mon Sep 17 00:00:00 2001 From: Matthew Bargar Date: Wed, 8 Jan 2020 14:54:32 -0500 Subject: [PATCH 2/6] Include nested fields in the index pattern so we can identify them in the Discover UI --- .../discover/np_ready/components/table/table.tsx | 11 ----------- .../discover/np_ready/components/table/table_row.tsx | 4 +--- .../lib/field_capabilities/field_caps_response.ts | 2 +- .../kibana_react/public/field_icon/field_icon.tsx | 2 ++ 4 files changed, 4 insertions(+), 15 deletions(-) diff --git a/src/legacy/core_plugins/kibana/public/discover/np_ready/components/table/table.tsx b/src/legacy/core_plugins/kibana/public/discover/np_ready/components/table/table.tsx index c2d503fca831ef..4bb2f83016c22e 100644 --- a/src/legacy/core_plugins/kibana/public/discover/np_ready/components/table/table.tsx +++ b/src/legacy/core_plugins/kibana/public/discover/np_ready/components/table/table.tsx @@ -68,22 +68,11 @@ export function DocViewTable({ const displayNoMappingWarning = !mapping(field) && !displayUnderscoreWarning && !isArrayOfObjects; - // Nested fields are not a part of the index pattern but their children are. - // Nested children are not a part of the flattened document but their nested parent is. - // So to detect nested fields we look through the index pattern for nested children - // that have the current field in their path. Knowing which fields are nested allows us - // to label them and apply the correct icon in the table row. - const isNestedField = !!indexPattern.fields.find(patternField => - patternField.subType?.nested?.path.includes(field) - ); - const fieldType = isNestedField ? 'nested' : undefined; - return ( )} - + {isCollapsible && ( diff --git a/src/plugins/data/server/index_patterns/fetcher/lib/field_capabilities/field_caps_response.ts b/src/plugins/data/server/index_patterns/fetcher/lib/field_capabilities/field_caps_response.ts index 2215bd8a95a1d0..0c8c2ce48fa844 100644 --- a/src/plugins/data/server/index_patterns/fetcher/lib/field_capabilities/field_caps_response.ts +++ b/src/plugins/data/server/index_patterns/fetcher/lib/field_capabilities/field_caps_response.ts @@ -195,6 +195,6 @@ export function readFieldCapsResponse(fieldCapsResponse: FieldCapsResponse): Fie }); return kibanaFormattedCaps.filter(field => { - return !['object', 'nested'].includes(field.type); + return !['object'].includes(field.type); }); } diff --git a/src/plugins/kibana_react/public/field_icon/field_icon.tsx b/src/plugins/kibana_react/public/field_icon/field_icon.tsx index f9bdf3a25adaa0..4ef9d1e1056a20 100644 --- a/src/plugins/kibana_react/public/field_icon/field_icon.tsx +++ b/src/plugins/kibana_react/public/field_icon/field_icon.tsx @@ -36,6 +36,7 @@ interface FieldIconProps { | 'number' | '_source' | 'string' + | 'nested' | string; label?: string; size?: IconSize; @@ -61,6 +62,7 @@ export const typeToEuiIconMap: Partial> = { number: { icon: 'number', color: colors[0] }, _source: { icon: 'editorCodeBlock', color: colors[3] }, string: { icon: 'string', color: colors[4] }, + nested: { icon: 'nested', color: colors[4] }, }; /** From f7f4357789a911d30c41b9085bc1ce8f048b38af Mon Sep 17 00:00:00 2001 From: Matt Bargar Date: Mon, 13 Jan 2020 17:41:38 -0500 Subject: [PATCH 3/6] use color recommended by design --- src/plugins/kibana_react/public/field_icon/field_icon.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/kibana_react/public/field_icon/field_icon.tsx b/src/plugins/kibana_react/public/field_icon/field_icon.tsx index 4ef9d1e1056a20..5f75bd84e7eef9 100644 --- a/src/plugins/kibana_react/public/field_icon/field_icon.tsx +++ b/src/plugins/kibana_react/public/field_icon/field_icon.tsx @@ -62,7 +62,7 @@ export const typeToEuiIconMap: Partial> = { number: { icon: 'number', color: colors[0] }, _source: { icon: 'editorCodeBlock', color: colors[3] }, string: { icon: 'string', color: colors[4] }, - nested: { icon: 'nested', color: colors[4] }, + nested: { icon: 'nested', color: colors[2] }, }; /** From 0aa9edee1f95940d3b605e57efeacceedde7e350 Mon Sep 17 00:00:00 2001 From: Matt Bargar Date: Mon, 13 Jan 2020 17:50:19 -0500 Subject: [PATCH 4/6] Fix unit tests --- .../field_capabilities/field_caps_response.test.js | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/plugins/data/server/index_patterns/fetcher/lib/field_capabilities/field_caps_response.test.js b/src/plugins/data/server/index_patterns/fetcher/lib/field_capabilities/field_caps_response.test.js index 0d787fa56b400a..35980fb61af266 100644 --- a/src/plugins/data/server/index_patterns/fetcher/lib/field_capabilities/field_caps_response.test.js +++ b/src/plugins/data/server/index_patterns/fetcher/lib/field_capabilities/field_caps_response.test.js @@ -37,7 +37,7 @@ describe('index_patterns/field_capabilities/field_caps_response', () => { describe('conflicts', () => { it('returns a field for each in response, no filtering', () => { const fields = readFieldCapsResponse(esResponse); - expect(fields).toHaveLength(24); + expect(fields).toHaveLength(25); }); it( @@ -68,8 +68,8 @@ describe('index_patterns/field_capabilities/field_caps_response', () => { sandbox.spy(shouldReadFieldFromDocValuesNS, 'shouldReadFieldFromDocValues'); const fields = readFieldCapsResponse(esResponse); const conflictCount = fields.filter(f => f.type === 'conflict').length; - // +2 is for the object and nested fields which get filtered out of the final return value from readFieldCapsResponse - sinon.assert.callCount(shouldReadFieldFromDocValues, fields.length - conflictCount + 2); + // +2 is for the object field which is filtered out of the final return value from readFieldCapsResponse + sinon.assert.callCount(shouldReadFieldFromDocValues, fields.length - conflictCount + 1); }); it('converts es types to kibana types', () => { @@ -159,10 +159,12 @@ describe('index_patterns/field_capabilities/field_caps_response', () => { }); }); - it('does not include the field actually mapped as nested itself', () => { + it('returns the nested parent as not searchable or aggregatable', () => { const fields = readFieldCapsResponse(esResponse); const child = fields.find(f => f.name === 'nested_object_parent'); - expect(child).toBeUndefined(); + expect(child.type).toBe('nested'); + expect(child.aggregatable).toBe(false); + expect(child.searchable).toBe(false); }); it('should not confuse object children for multi or nested field children', () => { From 3b7c31e771aca0374c6f6e56f707c83cdca085ab Mon Sep 17 00:00:00 2001 From: Matt Bargar Date: Tue, 14 Jan 2020 14:48:24 -0500 Subject: [PATCH 5/6] Update api integration test --- .../fields_for_wildcard_route/response.js | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/test/api_integration/apis/index_patterns/fields_for_wildcard_route/response.js b/test/api_integration/apis/index_patterns/fields_for_wildcard_route/response.js index 25a533d39dd81c..555056173ec62f 100644 --- a/test/api_integration/apis/index_patterns/fields_for_wildcard_route/response.js +++ b/test/api_integration/apis/index_patterns/fields_for_wildcard_route/response.js @@ -71,6 +71,14 @@ export default function({ getService }) { name: 'foo', readFromDocValues: true, }, + { + aggregatable: false, + esTypes: ['nested'], + name: 'nestedField', + readFromDocValues: false, + searchable: false, + type: 'nested', + }, { aggregatable: false, esTypes: ['keyword'], @@ -153,6 +161,14 @@ export default function({ getService }) { name: 'foo', readFromDocValues: true, }, + { + aggregatable: false, + esTypes: ['nested'], + name: 'nestedField', + readFromDocValues: false, + searchable: false, + type: 'nested', + }, { aggregatable: false, esTypes: ['keyword'], From b79d2e26aca5143152e4126f29388cb8fe214725 Mon Sep 17 00:00:00 2001 From: Tim Roes Date: Wed, 15 Jan 2020 09:33:32 +0100 Subject: [PATCH 6/6] Fix test comment --- .../fetcher/lib/field_capabilities/field_caps_response.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/data/server/index_patterns/fetcher/lib/field_capabilities/field_caps_response.test.js b/src/plugins/data/server/index_patterns/fetcher/lib/field_capabilities/field_caps_response.test.js index 35980fb61af266..3ec903d5b18e43 100644 --- a/src/plugins/data/server/index_patterns/fetcher/lib/field_capabilities/field_caps_response.test.js +++ b/src/plugins/data/server/index_patterns/fetcher/lib/field_capabilities/field_caps_response.test.js @@ -68,7 +68,7 @@ describe('index_patterns/field_capabilities/field_caps_response', () => { sandbox.spy(shouldReadFieldFromDocValuesNS, 'shouldReadFieldFromDocValues'); const fields = readFieldCapsResponse(esResponse); const conflictCount = fields.filter(f => f.type === 'conflict').length; - // +2 is for the object field which is filtered out of the final return value from readFieldCapsResponse + // +1 is for the object field which is filtered out of the final return value from readFieldCapsResponse sinon.assert.callCount(shouldReadFieldFromDocValues, fields.length - conflictCount + 1); });