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

[ML] Data Visualizer: Remove duplicated geo examples, support 'version' type, add filters for boolean fields, and add sticky header to Discover #136236

Merged
5 changes: 3 additions & 2 deletions x-pack/plugins/data_visualizer/common/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,16 +29,17 @@ export const FILE_FORMATS = {
// XML: 'xml',
};

export const JOB_FIELD_TYPES = {
export const SUPPORTED_FIELD_TYPES = {
BOOLEAN: 'boolean',
DATE: 'date',
GEO_POINT: 'geo_point',
GEO_SHAPE: 'geo_shape',
HISTOGRAM: 'histogram',
IP: 'ip',
KEYWORD: 'keyword',
NUMBER: 'number',
TEXT: 'text',
HISTOGRAM: 'histogram',
VERSION: 'version',
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit, UNKNOWN should be the last item in this list

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not for this PR, but JOB_FIELD_TYPES should probably be replaced with ES_FIELD_TYPES

Copy link
Member Author

@qn895 qn895 Jul 14, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated here cc5f0fd

UNKNOWN: 'unknown',
} as const;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,16 @@ export interface DocumentCounts {
interval?: number;
}

export interface LatLongExample {
lat: number;
lon: number;
}

export interface GeoPointExample {
coordinates: number[];
type?: string;
}

export interface FieldVisStats {
error?: Error;
cardinality?: number;
Expand Down Expand Up @@ -56,7 +66,7 @@ export interface FieldVisStats {
topValues?: Array<{ key: number | string; doc_count: number }>;
topValuesSampleSize?: number;
topValuesSamplerShardSize?: number;
examples?: Array<string | object>;
examples?: Array<string | GeoPointExample | object>;
timeRangeEarliest?: number;
timeRangeLatest?: number;
}
Expand Down
4 changes: 2 additions & 2 deletions x-pack/plugins/data_visualizer/common/types/job_field_type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@
* 2.0.
*/

import { JOB_FIELD_TYPES } from '../constants';
export type JobFieldType = typeof JOB_FIELD_TYPES[keyof typeof JOB_FIELD_TYPES];
import { SUPPORTED_FIELD_TYPES } from '../constants';
export type JobFieldType = typeof SUPPORTED_FIELD_TYPES[keyof typeof SUPPORTED_FIELD_TYPES];
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,19 @@ import React, { FC } from 'react';
import { EuiListGroup, EuiListGroupItem } from '@elastic/eui';

import { FormattedMessage } from '@kbn/i18n-react';
import { i18n } from '@kbn/i18n';
import { GeoPointExample } from '../../../../../common/types/field_request_config';
import { ExpandedRowFieldHeader } from '../stats_table/components/expanded_row_field_header';
import { ExpandedRowPanel } from '../stats_table/components/field_data_expanded_row/expanded_row_panel';

interface Props {
examples: Array<string | object>;
examples: Array<string | GeoPointExample | object>;
}

const EMPTY_EXAMPLE = i18n.translate(
'xpack.dataVisualizer.dataGrid.field.examplesList.emptyExampleMessage',
{ defaultMessage: '(empty)' }
);
export const ExamplesList: FC<Props> = ({ examples }) => {
if (examples === undefined || examples === null || !Array.isArray(examples)) {
return null;
Expand All @@ -34,7 +41,13 @@ export const ExamplesList: FC<Props> = ({ examples }) => {
<EuiListGroupItem
size="xs"
key={`example_${i}`}
label={typeof example === 'string' ? example : JSON.stringify(example)}
label={
typeof example === 'string'
? example === ''
? EMPTY_EXAMPLE
: example
: JSON.stringify(example)
}
/>
);
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import {
NumberContent,
} from '../stats_table/components/field_data_expanded_row';
import { GeoPointContent } from './geo_point_content/geo_point_content';
import { JOB_FIELD_TYPES } from '../../../../../common/constants';
import { SUPPORTED_FIELD_TYPES } from '../../../../../common/constants';
import type { FileBasedFieldVisConfig } from '../../../../../common/types/field_vis_config';

export const FileBasedDataVisualizerExpandedRow = ({ item }: { item: FileBasedFieldVisConfig }) => {
Expand All @@ -25,25 +25,26 @@ export const FileBasedDataVisualizerExpandedRow = ({ item }: { item: FileBasedFi

function getCardContent() {
switch (type) {
case JOB_FIELD_TYPES.NUMBER:
case SUPPORTED_FIELD_TYPES.NUMBER:
return <NumberContent config={config} />;

case JOB_FIELD_TYPES.BOOLEAN:
case SUPPORTED_FIELD_TYPES.BOOLEAN:
return <BooleanContent config={config} />;

case JOB_FIELD_TYPES.DATE:
case SUPPORTED_FIELD_TYPES.DATE:
return <DateContent config={config} />;

case JOB_FIELD_TYPES.GEO_POINT:
case SUPPORTED_FIELD_TYPES.GEO_POINT:
return <GeoPointContent config={config} />;

case JOB_FIELD_TYPES.IP:
case SUPPORTED_FIELD_TYPES.IP:
return <IpContent config={config} />;

case JOB_FIELD_TYPES.KEYWORD:
case SUPPORTED_FIELD_TYPES.KEYWORD:
case SUPPORTED_FIELD_TYPES.VERSION:
return <KeywordContent config={config} />;

case JOB_FIELD_TYPES.TEXT:
case SUPPORTED_FIELD_TYPES.TEXT:
return <TextContent config={config} />;

default:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

import React, { FC, useEffect, useState } from 'react';
import { DataView } from '@kbn/data-views-plugin/public';
import { ES_GEO_FIELD_TYPE, LayerDescriptor } from '@kbn/maps-plugin/common';
Expand All @@ -14,7 +13,7 @@ import { DocumentStatsTable } from '../../stats_table/components/field_data_expa
import { ExamplesList } from '../../examples_list';
import { FieldVisConfig } from '../../stats_table/types';
import { useDataVisualizerKibana } from '../../../../kibana_context';
import { JOB_FIELD_TYPES } from '../../../../../../common/constants';
import { SUPPORTED_FIELD_TYPES } from '../../../../../../common/constants';
import { EmbeddedMapComponent } from '../../embedded_map';
import { ExpandedRowPanel } from '../../stats_table/components/field_data_expanded_row/expanded_row_panel';

Expand All @@ -36,7 +35,8 @@ export const GeoPointContentWithMap: FC<{
dataView?.id !== undefined &&
config !== undefined &&
config.fieldName !== undefined &&
(config.type === JOB_FIELD_TYPES.GEO_POINT || config.type === JOB_FIELD_TYPES.GEO_SHAPE)
(config.type === SUPPORTED_FIELD_TYPES.GEO_POINT ||
config.type === SUPPORTED_FIELD_TYPES.GEO_SHAPE)
) {
const params = {
indexPatternId: dataView.id,
Expand Down Expand Up @@ -64,7 +64,7 @@ export const GeoPointContentWithMap: FC<{
return (
<ExpandedRowContent dataTestSubj={'dataVisualizerIndexBasedMapContent'}>
<DocumentStatsTable config={config} />
<ExamplesList examples={stats.examples} />
<ExamplesList examples={stats?.examples} />
<ExpandedRowPanel className={'dvPanel__wrapper dvMap__wrapper'} grow={true}>
<EmbeddedMapComponent layerList={layerList} />
</ExpandedRowPanel>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import React from 'react';
import { DataView, DataViewField } from '@kbn/data-views-plugin/public';
import { GeoPointContentWithMap } from './geo_point_content_with_map';
import { JOB_FIELD_TYPES } from '../../../../../common/constants';
import { SUPPORTED_FIELD_TYPES } from '../../../../../common/constants';
import {
BooleanContent,
DateContent,
Expand Down Expand Up @@ -51,17 +51,17 @@ export const IndexBasedDataVisualizerExpandedRow = ({
}

switch (type) {
case JOB_FIELD_TYPES.NUMBER:
case SUPPORTED_FIELD_TYPES.NUMBER:
return <NumberContent config={config} onAddFilter={onAddFilter} />;

case JOB_FIELD_TYPES.BOOLEAN:
return <BooleanContent config={config} />;
case SUPPORTED_FIELD_TYPES.BOOLEAN:
return <BooleanContent config={config} onAddFilter={onAddFilter} />;

case JOB_FIELD_TYPES.DATE:
case SUPPORTED_FIELD_TYPES.DATE:
return <DateContent config={config} />;

case JOB_FIELD_TYPES.GEO_POINT:
case JOB_FIELD_TYPES.GEO_SHAPE:
case SUPPORTED_FIELD_TYPES.GEO_POINT:
case SUPPORTED_FIELD_TYPES.GEO_SHAPE:
return (
<GeoPointContentWithMap
config={config}
Expand All @@ -70,13 +70,14 @@ export const IndexBasedDataVisualizerExpandedRow = ({
/>
);

case JOB_FIELD_TYPES.IP:
case SUPPORTED_FIELD_TYPES.IP:
return <IpContent config={config} onAddFilter={onAddFilter} />;

case JOB_FIELD_TYPES.KEYWORD:
case SUPPORTED_FIELD_TYPES.KEYWORD:
case SUPPORTED_FIELD_TYPES.VERSION:
return <KeywordContent config={config} onAddFilter={onAddFilter} />;

case JOB_FIELD_TYPES.TEXT:
case SUPPORTED_FIELD_TYPES.TEXT:
return <TextContent config={config} />;

default:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import {
dataVisualizerRefresh$,
Refresh,
} from '../../../../index_data_visualizer/services/timefilter_refresh_service';
import { JOB_FIELD_TYPES } from '../../../../../../common/constants';
import { SUPPORTED_FIELD_TYPES } from '../../../../../../common/constants';
import { APP_ID } from '../../../../../../common/constants';

export function getActions(
Expand Down Expand Up @@ -80,7 +80,10 @@ export function getActions(
type: 'icon',
icon: 'gisApp',
available: (item: FieldVisConfig) => {
return item.type === JOB_FIELD_TYPES.GEO_POINT || item.type === JOB_FIELD_TYPES.GEO_SHAPE;
return (
item.type === SUPPORTED_FIELD_TYPES.GEO_POINT ||
item.type === SUPPORTED_FIELD_TYPES.GEO_SHAPE
);
},
onClick: async (item: FieldVisConfig) => {
if (services?.uiActions && dataView) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import type {
import { DOCUMENT_FIELD_NAME as RECORDS_FIELD } from '@kbn/lens-plugin/common/constants';
import type { CombinedQuery } from '../../../../index_data_visualizer/types/combined_query';
import { FieldVisConfig } from '../../stats_table/types';
import { JOB_FIELD_TYPES } from '../../../../../../common/constants';
import { SUPPORTED_FIELD_TYPES } from '../../../../../../common/constants';

interface ColumnsAndLayer {
columns: Record<string, GenericIndexPatternColumn>;
Expand Down Expand Up @@ -200,19 +200,20 @@ export function getBooleanSettings(item: FieldVisConfig) {
export function getCompatibleLensDataType(type: FieldVisConfig['type']): string | undefined {
let lensType: string | undefined;
switch (type) {
case JOB_FIELD_TYPES.KEYWORD:
case SUPPORTED_FIELD_TYPES.KEYWORD:
case SUPPORTED_FIELD_TYPES.VERSION:
lensType = 'string';
break;
case JOB_FIELD_TYPES.DATE:
case SUPPORTED_FIELD_TYPES.DATE:
lensType = 'date';
break;
case JOB_FIELD_TYPES.NUMBER:
case SUPPORTED_FIELD_TYPES.NUMBER:
lensType = 'number';
break;
case JOB_FIELD_TYPES.IP:
case SUPPORTED_FIELD_TYPES.IP:
lensType = 'ip';
break;
case JOB_FIELD_TYPES.BOOLEAN:
case SUPPORTED_FIELD_TYPES.BOOLEAN:
lensType = 'string';
break;
default:
Expand All @@ -228,16 +229,20 @@ function getColumnsAndLayer(
): ColumnsAndLayer | undefined {
if (item.fieldName === undefined) return;

if (fieldType === JOB_FIELD_TYPES.DATE) {
if (fieldType === SUPPORTED_FIELD_TYPES.DATE) {
return getDateSettings(item);
}
if (fieldType === JOB_FIELD_TYPES.NUMBER) {
if (fieldType === SUPPORTED_FIELD_TYPES.NUMBER) {
return getNumberSettings(item, defaultDataView);
}
if (fieldType === JOB_FIELD_TYPES.IP || fieldType === JOB_FIELD_TYPES.KEYWORD) {
if (
fieldType === SUPPORTED_FIELD_TYPES.IP ||
fieldType === SUPPORTED_FIELD_TYPES.KEYWORD ||
fieldType === SUPPORTED_FIELD_TYPES.VERSION
) {
return getKeywordSettings(item);
}
if (fieldType === JOB_FIELD_TYPES.BOOLEAN) {
if (fieldType === SUPPORTED_FIELD_TYPES.BOOLEAN) {
return getBooleanSettings(item);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@ import React from 'react';
import { mount, shallow } from 'enzyme';

import { FieldTypeIcon } from './field_type_icon';
import { JOB_FIELD_TYPES } from '../../../../../common/constants';
import { SUPPORTED_FIELD_TYPES } from '../../../../../common/constants';

describe('FieldTypeIcon', () => {
test(`render component when type matches a field type`, () => {
const typeIconComponent = shallow(
<FieldTypeIcon type={JOB_FIELD_TYPES.KEYWORD} tooltipEnabled={true} />
<FieldTypeIcon type={SUPPORTED_FIELD_TYPES.KEYWORD} tooltipEnabled={true} />
);
expect(typeIconComponent).toMatchSnapshot();
});
Expand All @@ -24,7 +24,7 @@ describe('FieldTypeIcon', () => {
jest.useFakeTimers();

const typeIconComponent = mount(
<FieldTypeIcon type={JOB_FIELD_TYPES.KEYWORD} tooltipEnabled={true} />
<FieldTypeIcon type={SUPPORTED_FIELD_TYPES.KEYWORD} tooltipEnabled={true} />
);

expect(typeIconComponent.find('EuiToolTip').children()).toHaveLength(1);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import { FindFileStructureResponse } from '@kbn/file-upload-plugin/common';
import { getFieldNames, getSupportedFieldType } from './get_field_names';
import { FileBasedFieldVisConfig } from '../stats_table/types';
import { JOB_FIELD_TYPES } from '../../../../../common/constants';
import { SUPPORTED_FIELD_TYPES } from '../../../../../common/constants';
import { roundToDecimalPlace } from '../utils';

export function createFields(results: FindFileStructureResponse) {
Expand All @@ -28,20 +28,20 @@ export function createFields(results: FindFileStructureResponse) {
if (fieldStats[name] !== undefined) {
const field: FileBasedFieldVisConfig = {
fieldName: name,
type: JOB_FIELD_TYPES.UNKNOWN,
type: SUPPORTED_FIELD_TYPES.UNKNOWN,
};
const f = fieldStats[name];
const m = mappings.properties[name];

// sometimes the timestamp field is not in the mappings, and so our
// collection of fields will be missing a time field with a type of date
if (name === timestampField && field.type === JOB_FIELD_TYPES.UNKNOWN) {
field.type = JOB_FIELD_TYPES.DATE;
if (name === timestampField && field.type === SUPPORTED_FIELD_TYPES.UNKNOWN) {
field.type = SUPPORTED_FIELD_TYPES.DATE;
}

if (m !== undefined) {
field.type = getSupportedFieldType(m.type);
if (field.type === JOB_FIELD_TYPES.NUMBER) {
if (field.type === SUPPORTED_FIELD_TYPES.NUMBER) {
numericFieldsCount += 1;
}
if (m.format !== undefined) {
Expand Down Expand Up @@ -71,7 +71,7 @@ export function createFields(results: FindFileStructureResponse) {
}

if (f.top_hits !== undefined) {
if (field.type === JOB_FIELD_TYPES.TEXT) {
if (field.type === SUPPORTED_FIELD_TYPES.TEXT) {
_stats = {
..._stats,
examples: f.top_hits.map((hit) => hit.value),
Expand All @@ -84,7 +84,7 @@ export function createFields(results: FindFileStructureResponse) {
}
}

if (field.type === JOB_FIELD_TYPES.DATE) {
if (field.type === SUPPORTED_FIELD_TYPES.DATE) {
_stats = {
..._stats,
earliest: f.earliest,
Expand All @@ -99,9 +99,9 @@ export function createFields(results: FindFileStructureResponse) {
// this could be the message field for a semi-structured log file or a
// field which the endpoint has not been able to work out any information for
const type =
mappings.properties[name] && mappings.properties[name].type === JOB_FIELD_TYPES.TEXT
? JOB_FIELD_TYPES.TEXT
: JOB_FIELD_TYPES.UNKNOWN;
mappings.properties[name] && mappings.properties[name].type === SUPPORTED_FIELD_TYPES.TEXT
? SUPPORTED_FIELD_TYPES.TEXT
: SUPPORTED_FIELD_TYPES.UNKNOWN;

return {
fieldName: name,
Expand Down
Loading