Skip to content

Commit

Permalink
[ML] Add popup for field type help
Browse files Browse the repository at this point in the history
  • Loading branch information
qn895 committed Jul 25, 2022
1 parent 2e6a967 commit 69cd035
Show file tree
Hide file tree
Showing 16 changed files with 359 additions and 41 deletions.
120 changes: 120 additions & 0 deletions x-pack/plugins/data_visualizer/common/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

import { i18n } from '@kbn/i18n';
import { KBN_FIELD_TYPES } from '@kbn/data-plugin/common';
import { DocLinksStart } from '@kbn/core/public';

export const APP_ID = 'data_visualizer';
export const UI_SETTING_MAX_FILE_SIZE = 'fileUpload:maxFileSize';
Expand All @@ -31,13 +32,19 @@ export const FILE_FORMATS = {

export const SUPPORTED_FIELD_TYPES = {
BOOLEAN: 'boolean',
CONFLICT: 'conflict',
DATE: 'date',
DATE_RANGE: 'date_range',
GEO_POINT: 'geo_point',
GEO_SHAPE: 'geo_shape',
HISTOGRAM: 'histogram',
IP: 'ip',
IP_RANGE: 'ip_range',
KEYWORD: 'keyword',
MURMUR3: 'murmur3',
NUMBER: 'number',
NESTED: 'nested',
STRING: 'string',
TEXT: 'text',
VERSION: 'version',
UNKNOWN: 'unknown',
Expand All @@ -56,3 +63,116 @@ export const featureTitle = i18n.translate('xpack.dataVisualizer.title', {
defaultMessage: 'Upload a file',
});
export const featureId = `file_data_visualizer`;

const UNKNOWN_FIELD_TYPE_DESC = i18n.translate(
'xpack.dataVisualizer.index.fieldNameDescription.unknownField',
{
defaultMessage: 'Unknown field',
}
);

export function getFieldTypeDescription(type: string, docLinks: DocLinksStart) {
switch (type) {
case SUPPORTED_FIELD_TYPES.BOOLEAN:
return i18n.translate('xpack.dataVisualizer.index.fieldNameDescription.booleanField', {
defaultMessage: 'True and false values.',
});
case SUPPORTED_FIELD_TYPES.CONFLICT:
return i18n.translate('xpack.dataVisualizer.index.fieldNameDescription.conflictField', {
defaultMessage: 'Field has values of different types. Resolve in Management > Data Views.',
});
case SUPPORTED_FIELD_TYPES.DATE:
return i18n.translate('xpack.dataVisualizer.index.fieldNameDescription.dateField', {
defaultMessage: 'A date string or the number of seconds or milliseconds since 1/1/1970.',
});
case SUPPORTED_FIELD_TYPES.DATE_RANGE:
return i18n.translate('xpack.dataVisualizer.index.fieldNameDescription.dateRangeField', {
defaultMessage: 'Range of {dateFieldTypeLink} values. {viewSupportedDateFormatsLink}',
values: {
dateFieldTypeLink:
`<a href=${docLinks.links.discover.dateFieldTypeDocs}
target="_blank" rel="noopener">` +
i18n.translate(
'xpack.dataVisualizer.index.fieldNameDescription.dateRangeFieldLinkText',
{
defaultMessage: 'date',
}
) +
'</a>',
viewSupportedDateFormatsLink:
`<a href=${docLinks.links.discover.dateFormatsDocs}
target="_blank" rel="noopener">` +
i18n.translate(
'xpack.dataVisualizer.index.fieldNameDescription.viewSupportedDateFormatsLinkText',
{
defaultMessage: 'View supported date formats.',
}
) +
'</a>',
},
});
case SUPPORTED_FIELD_TYPES.GEO_POINT:
return i18n.translate('xpack.dataVisualizer.index.fieldNameDescription.geoPointField', {
defaultMessage: 'Latitude and longitude points.',
});
case SUPPORTED_FIELD_TYPES.GEO_SHAPE:
return i18n.translate('xpack.dataVisualizer.index.fieldNameDescription.geoShapeField', {
defaultMessage: 'Complex shapes, such as polygons.',
});
case SUPPORTED_FIELD_TYPES.HISTOGRAM:
return i18n.translate('xpack.dataVisualizer.index.fieldNameDescription.histogramField', {
defaultMessage: 'Pre-aggregated numerical values in the form of a histogram.',
});
case SUPPORTED_FIELD_TYPES.IP:
return i18n.translate('xpack.dataVisualizer.index.fieldNameDescription.ipAddressField', {
defaultMessage: 'IPv4 and IPv6 addresses.',
});
case SUPPORTED_FIELD_TYPES.IP_RANGE:
return i18n.translate('xpack.dataVisualizer.index.fieldNameDescription.ipAddressRangeField', {
defaultMessage: 'Range of ip values supporting either IPv4 or IPv6 (or mixed) addresses.',
});
case SUPPORTED_FIELD_TYPES.MURMUR3:
return i18n.translate('xpack.dataVisualizer.index.fieldNameDescription.murmur3Field', {
defaultMessage: 'Field that computes and stores hashes of values.',
});
case SUPPORTED_FIELD_TYPES.NESTED:
return i18n.translate('xpack.dataVisualizer.index.fieldNameDescription.nestedField', {
defaultMessage: 'JSON object that preserves the relationship between its subfields.',
});
case SUPPORTED_FIELD_TYPES.NUMBER:
return i18n.translate('xpack.dataVisualizer.index.fieldNameDescription.numberField', {
defaultMessage: 'Long, integer, short, byte, double, and float values.',
});
case SUPPORTED_FIELD_TYPES.STRING:
return i18n.translate('xpack.dataVisualizer.index.fieldNameDescription.stringField', {
defaultMessage: 'Full text such as the body of an email or a product description.',
});
case SUPPORTED_FIELD_TYPES.TEXT:
return i18n.translate('xpack.dataVisualizer.index.fieldNameDescription.textField', {
defaultMessage: 'Full text such as the body of an email or a product description.',
});
case SUPPORTED_FIELD_TYPES.KEYWORD:
return i18n.translate('xpack.dataVisualizer.index.fieldNameDescription.keywordField', {
defaultMessage:
'Structured content such as an ID, email address, hostname, status code, or tag.',
});
case SUPPORTED_FIELD_TYPES.VERSION:
return i18n.translate('xpack.dataVisualizer.index.fieldNameDescription.versionField', {
defaultMessage: 'Software versions. Supports {SemanticVersioningLink} precedence rules.',
values: {
SemanticVersioningLink:
`<a href="https://semver.org/"
target="_blank" rel="noopener">` +
i18n.translate(
'xpack.dataVisualizer.index.advancedSettings.discover.fieldNameDescription.versionFieldLinkText',
{
defaultMessage: 'Semantic Versioning',
}
) +
'</a>',
},
});
default:
return UNKNOWN_FIELD_TYPE_DESC;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* 2.0.
*/

import type { JobFieldType } from '.';
import type { SupportedFieldType } from '.';

export interface Percentile {
percent: number;
Expand All @@ -15,7 +15,7 @@ export interface Percentile {

export interface FieldRequestConfig {
fieldName: string;
type: JobFieldType;
type: SupportedFieldType;
cardinality: number;
existsInDocs: boolean;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* 2.0.
*/

import type { Percentile, JobFieldType, FieldVisStats } from '.';
import type { Percentile, SupportedFieldType, FieldVisStats } from '.';
export interface MetricFieldVisStats {
avg?: number;
distribution?: {
Expand All @@ -21,7 +21,7 @@ export interface MetricFieldVisStats {
// The internal representation of the configuration used to build the visuals
// which display the field information.
export interface FieldVisConfig {
type: JobFieldType;
type: SupportedFieldType;
fieldName: string;
displayName?: string;
existsInDocs: boolean;
Expand All @@ -34,7 +34,7 @@ export interface FieldVisConfig {
}

export interface FileBasedFieldVisConfig {
type: JobFieldType;
type: SupportedFieldType;
fieldName?: string;
displayName?: string;
stats?: FieldVisStats;
Expand Down
2 changes: 1 addition & 1 deletion x-pack/plugins/data_visualizer/common/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

import type { SimpleSavedObject } from '@kbn/core/public';
import { isPopulatedObject } from '@kbn/ml-is-populated-object';
export type { JobFieldType } from './job_field_type';
export type { SupportedFieldType } from './job_field_type';
export type {
FieldRequestConfig,
DocumentCountBuckets,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@
*/

import { SUPPORTED_FIELD_TYPES } from '../constants';
export type JobFieldType = typeof SUPPORTED_FIELD_TYPES[keyof typeof SUPPORTED_FIELD_TYPES];
export type SupportedFieldType = typeof SUPPORTED_FIELD_TYPES[keyof typeof SUPPORTED_FIELD_TYPES];
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@ import { EuiToolTip } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { FieldIcon } from '@kbn/react-field';
import { getJobTypeLabel } from '../../util/field_types_utils';
import type { JobFieldType } from '../../../../../common/types';
import type { SupportedFieldType } from '../../../../../common/types';
import './_index.scss';

interface FieldTypeIconProps {
tooltipEnabled: boolean;
type: JobFieldType;
type: SupportedFieldType;
}

export const FieldTypeIcon: FC<FieldTypeIconProps> = ({ tooltipEnabled = false, type }) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import React, { FC, useMemo } from 'react';
import { i18n } from '@kbn/i18n';
import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
import { FieldTypesHelpPopover } from './field_types_help_popover';
import { MultiSelectPicker, Option } from '../multi_select_picker';
import type {
FileBasedFieldVisConfig,
Expand Down Expand Up @@ -67,6 +68,7 @@ export const DataVisualizerFieldTypesFilter: FC<Props> = ({
onChange={setVisibleFieldTypes}
checkedOptions={visibleFieldTypes}
dataTestSubj={'dataVisualizerFieldTypeSelect'}
postfix={<FieldTypesHelpPopover fieldTypes={options.map((f) => f.value)} />}
/>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
/*
* 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 {
EuiBasicTable,
EuiFilterButton,
EuiFlexGroup,
EuiFlexItem,
EuiIcon,
EuiLink,
EuiPanel,
EuiPopover,
EuiPopoverTitle,
EuiText,
useEuiTheme,
} from '@elastic/eui';
import React, { FC, useMemo, useState } from 'react';
import { i18n } from '@kbn/i18n';
import { FieldIcon } from '@kbn/react-field';
import { FormattedMessage } from '@kbn/i18n-react';
import { getFieldTypeDescription } from '../../../../../common/constants';
import { useDataVisualizerKibana } from '../../../kibana_context';

interface FieldTypeTableItem {
id: number;
dataType: string;
description: string;
}

export const FieldTypesHelpPopover: FC<{
fieldTypes: string[];
}> = ({ fieldTypes }) => {
{
const { services } = useDataVisualizerKibana();
const { docLinks } = services;
const { euiTheme } = useEuiTheme();

const [isHelpOpen, setIsHelpOpen] = useState(false);

const onHelpClick = () => setIsHelpOpen((prevIsHelpOpen) => !prevIsHelpOpen);
const closeHelp = () => setIsHelpOpen(false);

const items: FieldTypeTableItem[] = useMemo(() => {
return fieldTypes.map((type, index) => ({
id: index,
dataType: type,
description: getFieldTypeDescription(type, docLinks),
}));
}, [fieldTypes, docLinks]);

const columnsSidebar = [
{
field: 'dataType',
name: i18n.translate('xpack.dataVisualizer.fieldTypesPopover.dataTypeColumnTitle', {
defaultMessage: 'Data type',
}),
width: '110px',
render: (name: string) => (
<EuiFlexGroup alignItems="center" responsive={false} gutterSize="xs">
<EuiFlexItem grow={false}>
<FieldIcon type={name} />
</EuiFlexItem>
<EuiFlexItem>{name}</EuiFlexItem>
</EuiFlexGroup>
),
},
{
field: 'description',
name: i18n.translate('xpack.dataVisualizer.fieldTypesPopover.descriptionColumnTitle', {
defaultMessage: 'Description',
}),
// eslint-disable-next-line react/no-danger
render: (description: string) => <div dangerouslySetInnerHTML={{ __html: description }} />,
},
];

const helpButton = (
<EuiFilterButton
grow={false}
onClick={onHelpClick}
data-test-subj="fieldTypesHelpButton"
className="dataVisualizerFieldTypesHelp__button"
aria-label={i18n.translate('xpack.dataVisualizer.fieldTypesPopover.buttonAriaLabel', {
defaultMessage: 'Filter type help',
})}
>
<EuiIcon
type="iInCircle"
color="primary"
title={i18n.translate('xpack.dataVisualizer.fieldTypesPopover.iconTitle', {
defaultMessage: 'Filter type help',
})}
/>
</EuiFilterButton>
);
return (
<EuiPopover
anchorPosition="downLeft"
display="block"
button={helpButton}
isOpen={isHelpOpen}
panelPaddingSize="none"
closePopover={closeHelp}
initialFocus="dataVisualizerFieldTypesHelpBasicTableId"
>
<EuiPopoverTitle paddingSize="s">
{i18n.translate('xpack.dataVisualizer.fieldChooser.popoverTitle', {
defaultMessage: 'Field types',
})}
</EuiPopoverTitle>
<EuiPanel
className="eui-yScroll"
style={{ maxHeight: '50vh', maxWidth: `calc(${euiTheme.size.base}*22)` }}
color="transparent"
paddingSize="s"
>
<EuiBasicTable<FieldTypeTableItem>
id="dataVisualizerFieldTypesHelpBasicTableId"
tableCaption={i18n.translate('xpack.dataVisualizer.fieldTypesPopover.tableTitle', {
defaultMessage: 'Description of field types',
})}
items={items}
compressed={true}
rowHeader="firstName"
columns={columnsSidebar}
responsive={false}
/>
</EuiPanel>
<EuiPanel color="transparent" paddingSize="s">
<EuiText color="subdued" size="xs">
<p>
{i18n.translate('xpack.dataVisualizer.fieldTypesPopover.learnMoreText', {
defaultMessage: 'Learn more about',
})}
&nbsp;
<EuiLink href={docLinks.links.discover.fieldTypeHelp} target="_blank" external>
<FormattedMessage
id="xpack.dataVisualizer.fieldTypesPopover.fieldTypesDocLinkLabel"
defaultMessage="field types"
/>
</EuiLink>
</p>
</EuiText>
</EuiPanel>
</EuiPopover>
);
}
};
Loading

0 comments on commit 69cd035

Please sign in to comment.