From f77b36206a73c2339b615fc0731280005530fe3c Mon Sep 17 00:00:00 2001 From: Matt Bargar Date: Wed, 15 Jan 2020 04:56:36 -0500 Subject: [PATCH] Add label and icon to nested fields in the doc table (#54199) * Apply label and icon to nested fields in the doc table * Include nested fields in the index pattern so we can identify them in the Discover UI * use color recommended by design * Fix unit tests * Update api integration test * Fix test comment Co-authored-by: Elastic Machine Co-authored-by: Tim Roes --- .../directives/field_name/field_type_name.ts | 4 ++++ .../field_caps_response.test.js | 12 +++++++----- .../field_capabilities/field_caps_response.ts | 2 +- .../public/field_icon/field_icon.tsx | 2 ++ .../fields_for_wildcard_route/response.js | 16 ++++++++++++++++ 5 files changed, 30 insertions(+), 6 deletions(-) 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', 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..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 @@ -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); + // +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); }); 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', () => { 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 0c5d2b0c24831c..7c44fe89d0e7ff 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[2] }, }; /** 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'],