From fdc99681a74b810da08e84b989620c2804e363c5 Mon Sep 17 00:00:00 2001 From: Vadim Yakhin Date: Mon, 12 Jul 2021 17:20:48 -0300 Subject: [PATCH] [Workplace Search] Port PR 4033 from ent-search to Kibana and update typings (#105054) * Improve typings Custom API Source allow indexing several types of data. We didn't account for all of them. For example, geolocation can be array of arrays of numbers. This commit improves typings. The following commits mostly fix TS errors that appear after this commit. * Remove type castings to account for all possible variable types * Update helper functions to accept new CustomAPIFieldValue * Fix TS error: convert url to string before using it in EuiLink * Update mock and tests to match updated typings Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../__mocks__/content_sources.mock.ts | 9 ++++++-- .../applications/workplace_search/types.ts | 21 +++++++++++++++++-- .../get_as_local_datetime_string.test.ts | 6 ++++++ .../utils/get_as_local_datetime_string.ts | 8 +++++-- .../workplace_search/utils/mime_types.ts | 5 ++++- .../example_result_detail_card.tsx | 2 +- .../example_search_result_group.tsx | 5 ++--- .../example_standout_result.tsx | 4 ++-- .../display_settings/subtitle_field.test.tsx | 8 ++++++- .../display_settings/title_field.test.tsx | 12 +++++++++-- .../components/source_content.tsx | 2 +- 11 files changed, 65 insertions(+), 17 deletions(-) diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/__mocks__/content_sources.mock.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/__mocks__/content_sources.mock.ts index 748dc6a7cbcf..c599a13cc311 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/__mocks__/content_sources.mock.ts +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/__mocks__/content_sources.mock.ts @@ -303,6 +303,7 @@ export const exampleResult = { titleField: 'otherTitle', subtitleField: 'otherSubtitle', urlField: 'myLink', + urlFieldIsLinkable: true, color: '#e3e3e3', descriptionField: 'about', typeField: 'otherType', @@ -314,14 +315,18 @@ export const exampleResult = { { fieldName: 'dogs', label: 'Canines' }, ], }, - titleFieldHover: false, - urlFieldHover: false, exampleDocuments: [ { myLink: 'http://foo', otherTitle: 'foo', + content_source_id: '60e85e7ea2564c265a88a4f0', + external_id: 'doc-60e85eb7a2564c937a88a4f3', + last_updated: '2021-07-09T14:35:35+00:00', + updated_at: '2021-07-09T14:35:35+00:00', + source: 'custom', }, ], + schemaFields: {}, }; export const mostRecentIndexJob = { diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/types.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/types.ts index edc772b36955..e50b12f78194 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/types.ts +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/types.ts @@ -96,7 +96,7 @@ export interface ContentSource { export interface SourceContentItem { id: string; last_updated: string; - [key: string]: string; + [key: string]: string | CustomAPIFieldValue; } export interface ContentSourceDetails extends ContentSource { @@ -186,8 +186,25 @@ export interface CustomSource { id: string; } +// https://www.elastic.co/guide/en/workplace-search/current/workplace-search-custom-sources-api.html#_schema_data_types +type CustomAPIString = string | string[]; +type CustomAPINumber = number | number[]; +type CustomAPIDate = string | string[]; +type CustomAPIGeolocation = string | string[] | number[] | number[][]; + +export type CustomAPIFieldValue = + | CustomAPIString + | CustomAPINumber + | CustomAPIDate + | CustomAPIGeolocation; + export interface Result { - [key: string]: string | string[]; + content_source_id: string; + last_updated: string; + external_id: string; + updated_at: string; + source: string; + [key: string]: CustomAPIFieldValue; } export interface OptionValue { diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/utils/get_as_local_datetime_string.test.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/utils/get_as_local_datetime_string.test.ts index 6475df7f4c39..36df182b99b8 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/utils/get_as_local_datetime_string.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/utils/get_as_local_datetime_string.test.ts @@ -14,6 +14,12 @@ describe('getAsLocalDateTimeString', () => { expect(getAsLocalDateTimeString(date)).toEqual(new Date(Date.parse(date)).toLocaleString()); }); + it('returns null if passed value is not a string', () => { + const date = ['1', '2']; + + expect(getAsLocalDateTimeString(date)).toEqual(null); + }); + it('returns null if string cannot be parsed as date', () => { const date = 'foo'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/utils/get_as_local_datetime_string.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/utils/get_as_local_datetime_string.ts index d5ceb50d4c9a..6350c4e4a409 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/utils/get_as_local_datetime_string.ts +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/utils/get_as_local_datetime_string.ts @@ -5,7 +5,11 @@ * 2.0. */ -export const getAsLocalDateTimeString = (str: string) => { - const dateValue = Date.parse(str); +import { CustomAPIFieldValue } from '../types'; + +export const getAsLocalDateTimeString = (maybeDate: CustomAPIFieldValue) => { + if (typeof maybeDate !== 'string') return null; + + const dateValue = Date.parse(maybeDate); return dateValue ? new Date(dateValue).toLocaleString() : null; }; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/utils/mime_types.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/utils/mime_types.ts index f7664c90d461..7a5020be5986 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/utils/mime_types.ts +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/utils/mime_types.ts @@ -5,6 +5,8 @@ * 2.0. */ +import { CustomAPIFieldValue } from '../types'; + const mimeTypes = { 'application/iwork-keynote-sffkey': 'Keynote', 'application/x-iwork-keynote-sffkey': 'Keynote', @@ -51,4 +53,5 @@ const mimeTypes = { 'video/quicktime': 'MOV', } as { [key: string]: string }; -export const mimeType = (type: string) => mimeTypes[type.toLowerCase()] || type; +export const mimeType = (type: CustomAPIFieldValue) => + mimeTypes[type.toString().toLowerCase()] || type; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/example_result_detail_card.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/example_result_detail_card.tsx index eef508b2e618..8b0a72ac23e3 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/example_result_detail_card.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/example_result_detail_card.tsx @@ -62,7 +62,7 @@ export const ExampleResultDetailCard: React.FC = () => {
{detailFields.length > 0 ? ( detailFields.map(({ fieldName, label }, index) => { - const value = result[fieldName] as string; + const value = result[fieldName]; const dateValue = getAsLocalDateTimeString(value); return ( diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/example_search_result_group.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/example_search_result_group.tsx index 549faf1676a5..3ca5b619c036 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/example_search_result_group.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/example_search_result_group.tsx @@ -117,7 +117,7 @@ export const ExampleSearchResultGroup: React.FC = () => { data-test-subj="MediaTypeField" > - {mimeType(result[mediaTypeField] as string)} + {mimeType(result[mediaTypeField])}
)} @@ -135,8 +135,7 @@ export const ExampleSearchResultGroup: React.FC = () => { by {result[updatedByField]}  )} - {getAsLocalDateTimeString(result.last_updated as string) || - result.last_updated} + {getAsLocalDateTimeString(result.last_updated) || result.last_updated} diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/example_standout_result.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/example_standout_result.tsx index 46b8de678946..b3ba4c6d5097 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/example_standout_result.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/example_standout_result.tsx @@ -109,7 +109,7 @@ export const ExampleStandoutResult: React.FC = () => { data-test-subj="MediaTypeField" > - {mimeType(result[mediaTypeField] as string)} + {mimeType(result[mediaTypeField])} )} @@ -127,7 +127,7 @@ export const ExampleStandoutResult: React.FC = () => { by {result[updatedByField]}  )} - {getAsLocalDateTimeString(result.last_updated as string) || result.last_updated} + {getAsLocalDateTimeString(result.last_updated) || result.last_updated} diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/subtitle_field.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/subtitle_field.test.tsx index 76c28ae3d406..7506c499dff3 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/subtitle_field.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/subtitle_field.test.tsx @@ -5,6 +5,8 @@ * 2.0. */ +import { exampleResult } from '../../../../__mocks__/content_sources.mock'; + import React from 'react'; import { shallow } from 'enzyme'; @@ -12,7 +14,11 @@ import { shallow } from 'enzyme'; import { SubtitleField } from './subtitle_field'; describe('SubtitleField', () => { - const result = { foo: 'bar' }; + const result = { + ...exampleResult.exampleDocuments[0], + foo: 'bar', + }; + it('renders', () => { const props = { result, diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/title_field.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/title_field.test.tsx index 2ed4aa0b0fad..e5681bc7e861 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/title_field.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/title_field.test.tsx @@ -5,6 +5,8 @@ * 2.0. */ +import { exampleResult } from '../../../../__mocks__/content_sources.mock'; + import React from 'react'; import { shallow } from 'enzyme'; @@ -12,7 +14,10 @@ import { shallow } from 'enzyme'; import { TitleField } from './title_field'; describe('TitleField', () => { - const result = { foo: 'bar' }; + const result = { + ...exampleResult.exampleDocuments[0], + foo: 'bar', + }; it('renders', () => { const props = { result, @@ -26,7 +31,10 @@ describe('TitleField', () => { it('handles title when array', () => { const props = { - result: { foo: ['baz', 'bar'] }, + result: { + ...exampleResult.exampleDocuments[0], + foo: ['baz', 'bar'], + }, titleField: 'foo', titleFieldHover: false, }; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/source_content.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/source_content.tsx index a0e3c28f20eb..a97cc85cb822 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/source_content.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/source_content.tsx @@ -137,7 +137,7 @@ export const SourceContent: React.FC = () => { )} {urlFieldIsLinkable && ( - + )}