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 1d04504cdcbc..748dc6a7cbcf 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 @@ -305,6 +305,10 @@ export const exampleResult = { urlField: 'myLink', color: '#e3e3e3', descriptionField: 'about', + typeField: 'otherType', + mediaTypeField: 'otherMediaType', + createdByField: 'otherCreatedBy', + updatedByField: 'otherUpdatedBy', detailFields: [ { fieldName: 'cats', label: 'Felines' }, { fieldName: 'dogs', label: 'Canines' }, 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 bce778f90436..edc772b36955 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 @@ -204,6 +204,10 @@ export interface SearchResultConfig { titleField: string | null; subtitleField: string | null; descriptionField: string | null; + typeField: string | null; + mediaTypeField: string | null; + createdByField: string | null; + updatedByField: string | null; urlField: string | null; color: string; detailFields: DetailField[]; 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 new file mode 100644 index 000000000000..6475df7f4c39 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/utils/get_as_local_datetime_string.test.ts @@ -0,0 +1,22 @@ +/* + * 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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { getAsLocalDateTimeString } from './'; + +describe('getAsLocalDateTimeString', () => { + it('returns localized date if string can be parsed as date', () => { + const date = '2021-06-28'; + + expect(getAsLocalDateTimeString(date)).toEqual(new Date(Date.parse(date)).toLocaleString()); + }); + + it('returns null if string cannot be parsed as date', () => { + const date = 'foo'; + + expect(getAsLocalDateTimeString(date)).toEqual(null); + }); +}); 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 new file mode 100644 index 000000000000..d5ceb50d4c9a --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/utils/get_as_local_datetime_string.ts @@ -0,0 +1,11 @@ +/* + * 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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export const getAsLocalDateTimeString = (str: string) => { + const dateValue = Date.parse(str); + return dateValue ? new Date(dateValue).toLocaleString() : null; +}; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/utils/index.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/utils/index.ts index 37228cf9e702..2d15d6ce407b 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/utils/index.ts +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/utils/index.ts @@ -6,3 +6,4 @@ */ export { toSentenceSerial } from './to_sentence_serial'; +export { getAsLocalDateTimeString } from './get_as_local_datetime_string'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/display_settings.scss b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/display_settings.scss index 027f36a5c551..e5b680c5edec 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/display_settings.scss +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/display_settings.scss @@ -22,6 +22,23 @@ 0 0 20px $euiColorLightestShade; } +@mixin searchResultTag { + height: 20px; + border-radius: 2px; + display: inline-flex; + align-items: center; + padding: 0 .25rem; + background: #E9EDF2; + color: #647487; + font-size: 10px; + font-weight: 600; + text-transform: uppercase; + letter-spacing: .075em; + white-space: nowrap; + z-index: 1; + margin-right: 5px; +} + // Wrapper .custom-source-display-settings { font-size: 16px; @@ -73,6 +90,28 @@ color: $euiColorDarkShade; } } + + &__tag { + @include searchResultTag; + } + + &__tag-content { + display: inline-flex; + height: 20px; + flex-shrink: 0; + align-items: center; + } + + &__meta { + position: relative; + z-index: 1; + display: flex; + flex-flow: row nowrap; + align-items: center; + margin-top: .5rem; + font-size: .8em; + overflow: hidden; + } } .example-result-content-placeholder { diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/display_settings_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/display_settings_logic.test.ts index 10c715c80b3d..3e409fb9f614 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/display_settings_logic.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/display_settings_logic.test.ts @@ -52,6 +52,10 @@ describe('DisplaySettingsLogic', () => { urlFieldHover: false, subtitleFieldHover: false, descriptionFieldHover: false, + typeFieldHover: false, + mediaTypeFieldHover: false, + createdByFieldHover: false, + updatedByFieldHover: false, fieldOptions: [], optionalFieldOptions: [ { @@ -182,6 +186,50 @@ describe('DisplaySettingsLogic', () => { }); }); + it('setTypeField', () => { + const TYPE = 'new type'; + DisplaySettingsLogic.actions.setServerResponseData(serverProps); + DisplaySettingsLogic.actions.setTypeField(TYPE); + + expect(DisplaySettingsLogic.values.searchResultConfig).toEqual({ + ...searchResultConfig, + typeField: TYPE, + }); + }); + + it('setMediaTypeField', () => { + const MEDIA_TYPE = 'new media type'; + DisplaySettingsLogic.actions.setServerResponseData(serverProps); + DisplaySettingsLogic.actions.setMediaTypeField(MEDIA_TYPE); + + expect(DisplaySettingsLogic.values.searchResultConfig).toEqual({ + ...searchResultConfig, + mediaTypeField: MEDIA_TYPE, + }); + }); + + it('setCreatedByField', () => { + const CREATED_BY = 'new created by'; + DisplaySettingsLogic.actions.setServerResponseData(serverProps); + DisplaySettingsLogic.actions.setCreatedByField(CREATED_BY); + + expect(DisplaySettingsLogic.values.searchResultConfig).toEqual({ + ...searchResultConfig, + createdByField: CREATED_BY, + }); + }); + + it('setUpdatedByField', () => { + const UPDATED_BY = 'new updated by'; + DisplaySettingsLogic.actions.setServerResponseData(serverProps); + DisplaySettingsLogic.actions.setUpdatedByField(UPDATED_BY); + + expect(DisplaySettingsLogic.values.searchResultConfig).toEqual({ + ...searchResultConfig, + updatedByField: UPDATED_BY, + }); + }); + it('setDetailFields', () => { const result = { destination: { @@ -286,6 +334,36 @@ describe('DisplaySettingsLogic', () => { expect(DisplaySettingsLogic.values.urlFieldHover).toEqual(!defaultValues.urlFieldHover); }); + + it('toggleTypeFieldHover', () => { + DisplaySettingsLogic.actions.toggleTypeFieldHover(); + + expect(DisplaySettingsLogic.values.typeFieldHover).toEqual(!defaultValues.typeFieldHover); + }); + + it('toggleMediaTypeFieldHover', () => { + DisplaySettingsLogic.actions.toggleMediaTypeFieldHover(); + + expect(DisplaySettingsLogic.values.mediaTypeFieldHover).toEqual( + !defaultValues.mediaTypeFieldHover + ); + }); + + it('toggleCreatedByFieldHover', () => { + DisplaySettingsLogic.actions.toggleCreatedByFieldHover(); + + expect(DisplaySettingsLogic.values.createdByFieldHover).toEqual( + !defaultValues.createdByFieldHover + ); + }); + + it('toggleUpdatedByFieldHover', () => { + DisplaySettingsLogic.actions.toggleUpdatedByFieldHover(); + + expect(DisplaySettingsLogic.values.updatedByFieldHover).toEqual( + !defaultValues.updatedByFieldHover + ); + }); }); describe('listeners', () => { diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/display_settings_logic.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/display_settings_logic.ts index 38424df724bd..556507d891dc 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/display_settings_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/display_settings_logic.ts @@ -55,6 +55,10 @@ interface DisplaySettingsActions { setUrlField(urlField: string): string; setSubtitleField(subtitleField: string | null): string | null; setDescriptionField(descriptionField: string | null): string | null; + setTypeField(typeField: string | null): string | null; + setMediaTypeField(mediaTypeField: string | null): string | null; + setCreatedByField(createdByField: string | null): string | null; + setUpdatedByField(updatedByField: string | null): string | null; setColorField(hex: string): string; setDetailFields(result: DropResult): { result: DropResult }; openEditDetailField(editFieldIndex: number | null): number | null; @@ -70,6 +74,10 @@ interface DisplaySettingsActions { toggleTitleFieldHover(): void; toggleSubtitleFieldHover(): void; toggleDescriptionFieldHover(): void; + toggleTypeFieldHover(): void; + toggleMediaTypeFieldHover(): void; + toggleCreatedByFieldHover(): void; + toggleUpdatedByFieldHover(): void; toggleUrlFieldHover(): void; } @@ -89,6 +97,10 @@ interface DisplaySettingsValues { urlFieldHover: boolean; subtitleFieldHover: boolean; descriptionFieldHover: boolean; + typeFieldHover: boolean; + mediaTypeFieldHover: boolean; + createdByFieldHover: boolean; + updatedByFieldHover: boolean; fieldOptions: OptionValue[]; optionalFieldOptions: OptionValue[]; availableFieldOptions: OptionValue[]; @@ -100,6 +112,10 @@ export const defaultSearchResultConfig = { subtitleField: '', descriptionField: '', urlField: '', + typeField: '', + mediaTypeField: '', + createdByField: '', + updatedByField: '', color: '#000000', detailFields: [], }; @@ -115,7 +131,11 @@ export const DisplaySettingsLogic = kea< setTitleField: (titleField: string) => titleField, setUrlField: (urlField: string) => urlField, setSubtitleField: (subtitleField: string | null) => subtitleField, - setDescriptionField: (descriptionField: string) => descriptionField, + setDescriptionField: (descriptionField: string | null) => descriptionField, + setTypeField: (typeField: string | null) => typeField, + setMediaTypeField: (mediaTypeField: string | null) => mediaTypeField, + setCreatedByField: (createdByField: string | null) => createdByField, + setUpdatedByField: (updatedByField: string | null) => updatedByField, setColorField: (hex: string) => hex, setDetailFields: (result: DropResult) => ({ result }), openEditDetailField: (editFieldIndex: number | null) => editFieldIndex, @@ -128,6 +148,10 @@ export const DisplaySettingsLogic = kea< toggleTitleFieldHover: () => true, toggleSubtitleFieldHover: () => true, toggleDescriptionFieldHover: () => true, + toggleTypeFieldHover: () => true, + toggleMediaTypeFieldHover: () => true, + toggleCreatedByFieldHover: () => true, + toggleUpdatedByFieldHover: () => true, toggleUrlFieldHover: () => true, initializeDisplaySettings: () => true, setServerData: () => true, @@ -181,6 +205,19 @@ export const DisplaySettingsLogic = kea< ...searchResultConfig, descriptionField, }), + setTypeField: (searchResultConfig, typeField) => ({ ...searchResultConfig, typeField }), + setMediaTypeField: (searchResultConfig, mediaTypeField) => ({ + ...searchResultConfig, + mediaTypeField, + }), + setCreatedByField: (searchResultConfig, createdByField) => ({ + ...searchResultConfig, + createdByField, + }), + setUpdatedByField: (searchResultConfig, updatedByField) => ({ + ...searchResultConfig, + updatedByField, + }), setColorField: (searchResultConfig, color) => ({ ...searchResultConfig, color }), setDetailFields: (searchResultConfig, { result: { destination, source } }) => { const detailFields = cloneDeep(searchResultConfig.detailFields); @@ -273,7 +310,31 @@ export const DisplaySettingsLogic = kea< descriptionFieldHover: [ false, { - toggleDescriptionFieldHover: (addFieldModalVisible) => !addFieldModalVisible, + toggleDescriptionFieldHover: (descriptionFieldHover) => !descriptionFieldHover, + }, + ], + typeFieldHover: [ + false, + { + toggleTypeFieldHover: (typeFieldHover) => !typeFieldHover, + }, + ], + mediaTypeFieldHover: [ + false, + { + toggleMediaTypeFieldHover: (mediaTypeFieldHover) => !mediaTypeFieldHover, + }, + ], + createdByFieldHover: [ + false, + { + toggleCreatedByFieldHover: (createdByFieldHover) => !createdByFieldHover, + }, + ], + updatedByFieldHover: [ + false, + { + toggleUpdatedByFieldHover: (updatedByFieldHover) => !updatedByFieldHover, }, ], }, 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 c3d56949d0fe..eef508b2e618 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 @@ -13,16 +13,12 @@ import { useValues } from 'kea'; import { EuiFlexGroup, EuiFlexItem, EuiSpacer, EuiText, EuiTitle } from '@elastic/eui'; import { URL_LABEL } from '../../../../constants'; +import { getAsLocalDateTimeString } from '../../../../utils'; import { CustomSourceIcon } from './custom_source_icon'; import { DisplaySettingsLogic } from './display_settings_logic'; import { TitleField } from './title_field'; -const getAsLocalDateTimeString = (str: string) => { - const dateValue = Date.parse(str); - return dateValue ? new Date(dateValue).toLocaleString() : null; -}; - export const ExampleResultDetailCard: React.FC = () => { const { sourceName, diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/example_search_result_group.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/example_search_result_group.test.tsx index 7139ea30be13..1835d8485664 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/example_search_result_group.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/example_search_result_group.test.tsx @@ -41,4 +41,26 @@ describe('ExampleSearchResultGroup', () => { expect(wrapper.find('[data-test-subj="DefaultDescriptionLabel"]')).toHaveLength(1); }); + + it('renders optional fields if they exist in result', () => { + setMockValues({ + ...exampleResult, + exampleDocuments: [ + { + myLink: 'http://foo', + otherTitle: 'foo', + otherType: 'File', + otherMediaType: 'PDF', + otherCreatedBy: 'bar', + otherUpdatedBy: 'baz', + }, + ], + }); + const wrapper = shallow(); + + expect(wrapper.find('[data-test-subj="CreatedByField"]')).toHaveLength(1); + expect(wrapper.find('[data-test-subj="UpdatedByField"]')).toHaveLength(1); + expect(wrapper.find('[data-test-subj="TypeField"]')).toHaveLength(1); + expect(wrapper.find('[data-test-subj="MediaTypeField"]')).toHaveLength(1); + }); }); 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 df89eed38ae9..95a62b06515c 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 @@ -13,6 +13,7 @@ import { useValues } from 'kea'; import { isColorDark, hexToRgb } from '@elastic/eui'; import { DESCRIPTION_LABEL } from '../../../../constants'; +import { getAsLocalDateTimeString } from '../../../../utils'; import { CustomSourceIcon } from './custom_source_icon'; import { DisplaySettingsLogic } from './display_settings_logic'; @@ -22,10 +23,23 @@ import { TitleField } from './title_field'; export const ExampleSearchResultGroup: React.FC = () => { const { sourceName, - searchResultConfig: { titleField, subtitleField, descriptionField, color }, + searchResultConfig: { + titleField, + subtitleField, + descriptionField, + typeField, + mediaTypeField, + createdByField, + updatedByField, + color, + }, titleFieldHover, subtitleFieldHover, descriptionFieldHover, + typeFieldHover, + mediaTypeFieldHover, + createdByFieldHover, + updatedByFieldHover, exampleDocuments, } = useValues(DisplaySettingsLogic); @@ -72,6 +86,60 @@ export const ExampleSearchResultGroup: React.FC = () => { )} + {createdByField && result[createdByField] && ( +
+ Created by {result[createdByField]} +
+ )} +
+ {typeField && result[typeField] && ( +
+ + {result[typeField]} + +
+ )} + {mediaTypeField && result[mediaTypeField] && ( +
+ + {result[mediaTypeField]} + +
+ )} +
+ + Last updated  + {updatedByField && result[updatedByField] && ( + + {' '} + by {result[updatedByField]}  + + )} + {getAsLocalDateTimeString(result.last_updated as string) || + result.last_updated} + +
+
))} diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/example_standout_result.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/example_standout_result.test.tsx index a38e0ce82490..0c40db0c5a8e 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/example_standout_result.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/example_standout_result.test.tsx @@ -41,4 +41,26 @@ describe('ExampleStandoutResult', () => { expect(wrapper.find('[data-test-subj="DefaultDescriptionLabel"]')).toHaveLength(1); }); + + it('renders optional fields if they exist in result', () => { + setMockValues({ + ...exampleResult, + exampleDocuments: [ + { + myLink: 'http://foo', + otherTitle: 'foo', + otherType: 'File', + otherMediaType: 'PDF', + otherCreatedBy: 'bar', + otherUpdatedBy: 'baz', + }, + ], + }); + const wrapper = shallow(); + + expect(wrapper.find('[data-test-subj="CreatedByField"]')).toHaveLength(1); + expect(wrapper.find('[data-test-subj="UpdatedByField"]')).toHaveLength(1); + expect(wrapper.find('[data-test-subj="TypeField"]')).toHaveLength(1); + expect(wrapper.find('[data-test-subj="MediaTypeField"]')).toHaveLength(1); + }); }); 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 48c3149e622b..b6aa180eb65d 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 @@ -13,6 +13,7 @@ import { useValues } from 'kea'; import { isColorDark, hexToRgb } from '@elastic/eui'; import { DESCRIPTION_LABEL } from '../../../../constants'; +import { getAsLocalDateTimeString } from '../../../../utils'; import { CustomSourceIcon } from './custom_source_icon'; import { DisplaySettingsLogic } from './display_settings_logic'; @@ -22,10 +23,23 @@ import { TitleField } from './title_field'; export const ExampleStandoutResult: React.FC = () => { const { sourceName, - searchResultConfig: { titleField, subtitleField, descriptionField, color }, + searchResultConfig: { + titleField, + subtitleField, + descriptionField, + typeField, + mediaTypeField, + createdByField, + updatedByField, + color, + }, titleFieldHover, subtitleFieldHover, descriptionFieldHover, + typeFieldHover, + mediaTypeFieldHover, + createdByFieldHover, + updatedByFieldHover, exampleDocuments, } = useValues(DisplaySettingsLogic); @@ -66,6 +80,55 @@ export const ExampleStandoutResult: React.FC = () => { )} + {createdByField && result[createdByField] && ( +
+ Created by {result[createdByField]} +
+ )} +
+ {typeField && result[typeField] && ( +
+ {result[typeField]} +
+ )} + {mediaTypeField && result[mediaTypeField] && ( +
+ {result[mediaTypeField]} +
+ )} +
+ + Last updated  + {updatedByField && result[updatedByField] && ( + + {' '} + by {result[updatedByField]}  + + )} + {getAsLocalDateTimeString(result.last_updated as string) || result.last_updated} + +
+
diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/search_results.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/search_results.test.tsx index cc0378b4b70d..24ecb94df2aa 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/search_results.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/search_results.test.tsx @@ -41,6 +41,10 @@ describe('SearchResults', () => { const setDescriptionField = jest.fn(); const setUrlField = jest.fn(); const setColorField = jest.fn(); + const setTypeField = jest.fn(); + const setMediaTypeField = jest.fn(); + const setCreatedByField = jest.fn(); + const setUpdatedByField = jest.fn(); beforeEach(() => { setMockActions({ @@ -52,6 +56,10 @@ describe('SearchResults', () => { setDescriptionField, setUrlField, setColorField, + setTypeField, + setMediaTypeField, + setCreatedByField, + setUpdatedByField, }); setMockValues({ searchResultConfig, @@ -103,6 +111,42 @@ describe('SearchResults', () => { expect(setDescriptionField).toHaveBeenCalledWith(searchResultConfig.descriptionField); }); + it('calls setTypeField on change', () => { + const wrapper = shallow(); + wrapper + .find('[data-test-subj="TypeFieldSelect"]') + .simulate('change', { target: { value: searchResultConfig.typeField } }); + + expect(setTypeField).toHaveBeenCalledWith(searchResultConfig.typeField); + }); + + it('calls setMediaTypeField on change', () => { + const wrapper = shallow(); + wrapper + .find('[data-test-subj="MediaTypeFieldSelect"]') + .simulate('change', { target: { value: searchResultConfig.mediaTypeField } }); + + expect(setMediaTypeField).toHaveBeenCalledWith(searchResultConfig.mediaTypeField); + }); + + it('calls setCreatedByField on change', () => { + const wrapper = shallow(); + wrapper + .find('[data-test-subj="CreatedByFieldSelect"]') + .simulate('change', { target: { value: searchResultConfig.createdByField } }); + + expect(setCreatedByField).toHaveBeenCalledWith(searchResultConfig.createdByField); + }); + + it('calls setUpdatedByField on change', () => { + const wrapper = shallow(); + wrapper + .find('[data-test-subj="UpdatedByFieldSelect"]') + .simulate('change', { target: { value: searchResultConfig.updatedByField } }); + + expect(setUpdatedByField).toHaveBeenCalledWith(searchResultConfig.updatedByField); + }); + it('handles blank fallbacks', () => { setMockValues({ searchResultConfig: { detailFields: [] }, @@ -116,9 +160,25 @@ describe('SearchResults', () => { wrapper .find('[data-test-subj="DescriptionFieldSelect"]') .simulate('change', { target: { value: LEAVE_UNASSIGNED_FIELD } }); + wrapper + .find('[data-test-subj="TypeFieldSelect"]') + .simulate('change', { target: { value: LEAVE_UNASSIGNED_FIELD } }); + wrapper + .find('[data-test-subj="MediaTypeFieldSelect"]') + .simulate('change', { target: { value: LEAVE_UNASSIGNED_FIELD } }); + wrapper + .find('[data-test-subj="CreatedByFieldSelect"]') + .simulate('change', { target: { value: LEAVE_UNASSIGNED_FIELD } }); + wrapper + .find('[data-test-subj="UpdatedByFieldSelect"]') + .simulate('change', { target: { value: LEAVE_UNASSIGNED_FIELD } }); expect(wrapper.find('[data-test-subj="UrlFieldSelect"]').prop('value')).toEqual(''); expect(setSubtitleField).toHaveBeenCalledWith(null); expect(setDescriptionField).toHaveBeenCalledWith(null); + expect(setTypeField).toHaveBeenCalledWith(null); + expect(setMediaTypeField).toHaveBeenCalledWith(null); + expect(setCreatedByField).toHaveBeenCalledWith(null); + expect(setUpdatedByField).toHaveBeenCalledWith(null); }); }); diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/search_results.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/search_results.tsx index 859fb2d5d2a2..a6a0fcda0dd6 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/search_results.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/search_results.tsx @@ -42,15 +42,33 @@ export const SearchResults: React.FC = () => { toggleTitleFieldHover, toggleSubtitleFieldHover, toggleDescriptionFieldHover, + toggleTypeFieldHover, + toggleMediaTypeFieldHover, + toggleCreatedByFieldHover, + toggleUpdatedByFieldHover, setTitleField, setSubtitleField, setDescriptionField, + setTypeField, + setMediaTypeField, + setCreatedByField, + setUpdatedByField, setUrlField, setColorField, } = useActions(DisplaySettingsLogic); const { - searchResultConfig: { titleField, descriptionField, subtitleField, urlField, color }, + searchResultConfig: { + titleField, + descriptionField, + subtitleField, + typeField, + mediaTypeField, + createdByField, + updatedByField, + urlField, + color, + }, fieldOptions, optionalFieldOptions, } = useValues(DisplaySettingsLogic); @@ -136,6 +154,82 @@ export const SearchResults: React.FC = () => { } /> + + + setTypeField(value === LEAVE_UNASSIGNED_FIELD ? null : value) + } + /> + + + + setMediaTypeField(value === LEAVE_UNASSIGNED_FIELD ? null : value) + } + /> + + + + setCreatedByField(value === LEAVE_UNASSIGNED_FIELD ? null : value) + } + /> + + + + setUpdatedByField(value === LEAVE_UNASSIGNED_FIELD ? null : value) + } + /> + diff --git a/x-pack/plugins/enterprise_search/server/routes/workplace_search/sources.ts b/x-pack/plugins/enterprise_search/server/routes/workplace_search/sources.ts index 044393f65dc5..b393ab9d1f26 100644 --- a/x-pack/plugins/enterprise_search/server/routes/workplace_search/sources.ts +++ b/x-pack/plugins/enterprise_search/server/routes/workplace_search/sources.ts @@ -45,9 +45,13 @@ const displayFieldSchema = schema.object({ const displaySettingsSchema = schema.object({ titleField: schema.maybe(schema.string()), - subtitleField: schema.maybe(schema.string()), - descriptionField: schema.maybe(schema.string()), + subtitleField: schema.nullable(schema.string()), + descriptionField: schema.nullable(schema.string()), urlField: schema.maybe(schema.string()), + typeField: schema.nullable(schema.string()), + mediaTypeField: schema.nullable(schema.string()), + createdByField: schema.nullable(schema.string()), + updatedByField: schema.nullable(schema.string()), color: schema.string(), urlFieldIsLinkable: schema.boolean(), detailFields: schema.oneOf([schema.arrayOf(displayFieldSchema), displayFieldSchema]),