Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Enterprise Search] Search Applications - Icons for Document Flyout #153899

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand All @@ -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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ export interface ConvertedResult {
value: string;
}

export interface ConvertedResultWithType extends ConvertedResult {
type: string;
}

export const convertResults = (result: Record<string, unknown>): ConvertedResult[] => {
const flattenedResult = flattenObject(result);
const unsortedFields = Object.entries(flattenedResult).map(
Expand All @@ -39,3 +43,13 @@ export const convertResults = (result: Record<string, unknown>): ConvertedResult
const sortedFields = unsortedFields.sort((a, b) => a.field.localeCompare(b.field));
return sortedFields;
};

export const addTypeToResults = (
results: ConvertedResult[],
fieldTypes: Record<string, string>
): ConvertedResultWithType[] => {
return results.map((result) => {
const type = fieldTypes[result.field];
return { ...result, type };
});
};
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@

import React, { useMemo } from 'react';

import { useValues } from 'kea';

import {
EuiBasicTableColumn,
EuiFlexGroup,
Expand All @@ -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,
Expand All @@ -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<EuiBasicTableColumn<ConvertedResult>> = [
const columns: Array<EuiBasicTableColumn<ConvertedResultWithType>> = [
{
field: 'field',
name: i18n.translate(
'xpack.enterpriseSearch.content.engine.searchPreview.documentFlyout.fieldLabel',
{ defaultMessage: 'Field' }
),
render: (key: string) => (
<EuiText>
<EuiTextColor color="subdued">
<code>{key}</code>
</EuiTextColor>
</EuiText>
render: ({ field: key, type }: ConvertedResultWithType) => (
<EuiFlexGroup direction="row" gutterSize="s" alignItems="center">
<FieldIcon type={type} />
<EuiText>
<EuiTextColor color="subdued">
<code>{key}</code>
</EuiTextColor>
</EuiText>
</EuiFlexGroup>
),
truncateText: false,
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ interface EngineSearchPreviewActions {
export interface EngineSearchPreviewValues {
engineFieldCapabilitiesData: typeof FetchEngineFieldCapabilitiesApiLogic.values.data;
engineName: typeof EngineNameLogic.values.engineName;
fieldTypesByIndex: Record<string, Record<string, string>>;
resultFields: Record<string, FieldConfiguration>;
searchableFields: Record<string, SearchFieldConfiguration>;
sortableFields: string[];
Expand Down Expand Up @@ -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<string, Record<string, string>>, field) =>
field.indices.reduce(
(acc: Record<string, Record<string, string>>, index) => ({
...acc,
[index.name]: {
...(acc[index.name] || {}),
[field.name]: index.type,
},
}),
out
),
{}
);
},
],
resultFields: [
() => [selectors.engineFieldCapabilitiesData],
(data: EngineSearchPreviewValues['engineFieldCapabilitiesData']) => {
Expand Down
Original file line number Diff line number Diff line change
@@ -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<Record<string, string>> = {
integer: 'number',
};

// Mappings for types missing from `FieldIcon`
const typeToEuiIconMap: Partial<Record<string, EuiTokenProps>> = {
object: { color: 'euiColorVis3', iconType: 'tokenObject' },
};

export interface FieldIconProps {
type: string;
}

export const FieldIcon: React.FC<FieldIconProps> = (props) => {
const type = typeToFieldIconType[props.type] || props.type;
const overrides = typeToEuiIconMap[type] || {};
return <KbnFieldIcon type={type} {...overrides} />;
};