From 06513b14340ca93abefb5f5ce0c9afc96199395c Mon Sep 17 00:00:00 2001 From: Sloane Perrault Date: Wed, 29 Mar 2023 07:46:19 -0400 Subject: [PATCH] [Enterprise Search] Search Applications - Icons for Document Flyout (#153899) ## Summary - Updates document flyout to include icon for the field types image ### Checklist Delete any items that are not applicable to this PR. - [x] Any UI touched in this PR is usable by keyboard only (learn more about [keyboard accessibility](https://webaim.org/techniques/keyboard/)) - [x] Any UI touched in this PR does not create any new axe failures (run axe in browser: [FF](https://addons.mozilla.org/en-US/firefox/addon/axe-devtools/), [Chrome](https://chrome.google.com/webstore/detail/axe-web-accessibility-tes/lhdoppojpmngadmnindnejefpokejbdd?hl=en-US)) - [x] This renders correctly on smaller devices using a responsive layout. (You can test this [in your browser](https://www.browserstack.com/guide/responsive-testing-on-local-server)) - [x] This was checked for [cross-browser compatibility](https://www.elastic.co/support/matrix#matrix_browsers) --- .../components/engine/engine_schema.tsx | 3 +- .../engine_search_preview/convert_results.ts | 14 +++++++ .../engine_search_preview/document_flyout.tsx | 37 ++++++++++++------- .../engine_search_preview_logic.ts | 22 +++++++++++ .../components/engine/field_icon.tsx | 31 ++++++++++++++++ 5 files changed, 92 insertions(+), 15 deletions(-) create mode 100644 x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/engine/field_icon.tsx diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/engine/engine_schema.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/engine/engine_schema.tsx index a5ec5aa7a05575..8a5bae680e34e8 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/engine/engine_schema.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/engine/engine_schema.tsx @@ -24,8 +24,6 @@ import { import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; -import { FieldIcon } from '@kbn/react-field'; - import { SchemaField } from '../../../../../common/types/engines'; import { docLinks } from '../../../shared/doc_links'; import { generateEncodedPath } from '../../../shared/encode_path_params'; @@ -37,6 +35,7 @@ import { EnterpriseSearchEnginesPageTemplate } from '../layout/engines_page_temp import { EngineIndicesLogic } from './engine_indices_logic'; import { EngineViewLogic } from './engine_view_logic'; +import { FieldIcon } from './field_icon'; const SchemaFieldDetails: React.FC<{ schemaField: SchemaField }> = ({ schemaField }) => { const { navigateToUrl } = useValues(KibanaLogic); diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/engine/engine_search_preview/convert_results.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/engine/engine_search_preview/convert_results.ts index 8d00549c6554ca..c55200e7917ce3 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/engine/engine_search_preview/convert_results.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/engine/engine_search_preview/convert_results.ts @@ -28,6 +28,10 @@ export interface ConvertedResult { value: string; } +export interface ConvertedResultWithType extends ConvertedResult { + type: string; +} + export const convertResults = (result: Record): ConvertedResult[] => { const flattenedResult = flattenObject(result); const unsortedFields = Object.entries(flattenedResult).map( @@ -39,3 +43,13 @@ export const convertResults = (result: Record): ConvertedResult const sortedFields = unsortedFields.sort((a, b) => a.field.localeCompare(b.field)); return sortedFields; }; + +export const addTypeToResults = ( + results: ConvertedResult[], + fieldTypes: Record +): ConvertedResultWithType[] => { + return results.map((result) => { + const type = fieldTypes[result.field]; + return { ...result, type }; + }); +}; diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/engine/engine_search_preview/document_flyout.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/engine/engine_search_preview/document_flyout.tsx index ee7c7f55244193..0d1151cc8db9df 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/engine/engine_search_preview/document_flyout.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/engine/engine_search_preview/document_flyout.tsx @@ -7,6 +7,8 @@ import React, { useMemo } from 'react'; +import { useValues } from 'kea'; + import { EuiBasicTableColumn, EuiFlexGroup, @@ -21,14 +23,21 @@ import { import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; -import { ConvertedResult, convertResults } from './convert_results'; +import { FieldIcon } from '../field_icon'; + +import { addTypeToResults, ConvertedResultWithType, convertResults } from './convert_results'; import { useSelectedDocument } from './document_context'; +import { EngineSearchPreviewLogic } from './engine_search_preview_logic'; export const DocumentFlyout: React.FC = () => { + const { fieldTypesByIndex } = useValues(EngineSearchPreviewLogic); const { selectedDocument, setSelectedDocument } = useSelectedDocument(); - const [id, items] = useMemo((): [string | null, ConvertedResult[]] => { - if (!selectedDocument) return [null, []]; + const index = selectedDocument?._meta.rawHit._index; + + const [id, items] = useMemo((): [string | null, ConvertedResultWithType[]] => { + const fieldTypes = fieldTypesByIndex[index]; + if (!selectedDocument || !fieldTypes) return [null, []]; const { _meta: { id: encodedId }, id: _id, @@ -41,24 +50,26 @@ export const DocumentFlyout: React.FC = () => { ), id: parsedId, }; - return [parsedId, convertResults(fields)]; - }, [selectedDocument]); + return [parsedId, addTypeToResults(convertResults(fields), fieldTypes)]; + }, [fieldTypesByIndex, index, selectedDocument]); if (selectedDocument === null) return null; - const columns: Array> = [ + const columns: Array> = [ { - field: 'field', name: i18n.translate( 'xpack.enterpriseSearch.content.engine.searchPreview.documentFlyout.fieldLabel', { defaultMessage: 'Field' } ), - render: (key: string) => ( - - - {key} - - + render: ({ field: key, type }: ConvertedResultWithType) => ( + + + + + {key} + + + ), truncateText: false, }, diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/engine/engine_search_preview/engine_search_preview_logic.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/engine/engine_search_preview/engine_search_preview_logic.ts index be453e046225a9..e7ac955827d474 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/engine/engine_search_preview/engine_search_preview_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/engine/engine_search_preview/engine_search_preview_logic.ts @@ -19,6 +19,7 @@ interface EngineSearchPreviewActions { export interface EngineSearchPreviewValues { engineFieldCapabilitiesData: typeof FetchEngineFieldCapabilitiesApiLogic.values.data; engineName: typeof EngineNameLogic.values.engineName; + fieldTypesByIndex: Record>; resultFields: Record; searchableFields: Record; sortableFields: string[]; @@ -50,6 +51,27 @@ export const EngineSearchPreviewLogic = kea< }), path: ['enterprise_search', 'content', 'engine_search_preview_logic'], selectors: ({ selectors }) => ({ + fieldTypesByIndex: [ + () => [selectors.engineFieldCapabilitiesData], + (data: EngineSearchPreviewValues['engineFieldCapabilitiesData']) => { + if (!data) return {}; + + return data.fields.reduce( + (out: Record>, field) => + field.indices.reduce( + (acc: Record>, index) => ({ + ...acc, + [index.name]: { + ...(acc[index.name] || {}), + [field.name]: index.type, + }, + }), + out + ), + {} + ); + }, + ], resultFields: [ () => [selectors.engineFieldCapabilitiesData], (data: EngineSearchPreviewValues['engineFieldCapabilitiesData']) => { diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/engine/field_icon.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/engine/field_icon.tsx new file mode 100644 index 00000000000000..614b0582ba07b4 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/engine/field_icon.tsx @@ -0,0 +1,31 @@ +/* + * 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 React from 'react'; + +import { EuiTokenProps } from '@elastic/eui'; +import { FieldIcon as KbnFieldIcon } from '@kbn/react-field'; + +// Remappings from type to a supported `FieldIcon` type +const typeToFieldIconType: Partial> = { + integer: 'number', +}; + +// Mappings for types missing from `FieldIcon` +const typeToEuiIconMap: Partial> = { + object: { color: 'euiColorVis3', iconType: 'tokenObject' }, +}; + +export interface FieldIconProps { + type: string; +} + +export const FieldIcon: React.FC = (props) => { + const type = typeToFieldIconType[props.type] || props.type; + const overrides = typeToEuiIconMap[type] || {}; + return ; +};