From 74cbeffb34b0f260f191ab1426fe77d4e2b3b6fa Mon Sep 17 00:00:00 2001 From: Garrett Spong Date: Fri, 15 May 2020 15:33:00 -0600 Subject: [PATCH 1/2] Fixes empty map tool tip --- .../public/classes/fields/es_agg_field.ts | 2 +- .../public/classes/fields/es_doc_field.ts | 2 +- .../maps/public/classes/fields/field.ts | 4 +- .../fields/top_term_percentage_field.ts | 2 +- .../classes/tooltips/es_tooltip_property.ts | 9 +++- .../classes/tooltips/join_tooltip_property.ts | 2 +- .../classes/tooltips/tooltip_property.ts | 10 ++--- x-pack/plugins/maps/public/index.ts | 1 + .../point_tool_tip_content.test.tsx.snap | 3 +- .../line_tool_tip_content.test.tsx | 27 ++++-------- .../map_tool_tip/line_tool_tip_content.tsx | 19 ++++---- .../embeddables/map_tool_tip/map_tool_tip.tsx | 7 +-- .../point_tool_tip_content.test.tsx | 43 +++---------------- .../map_tool_tip/point_tool_tip_content.tsx | 27 +++++------- .../network/components/embeddables/types.ts | 10 ----- 15 files changed, 61 insertions(+), 107 deletions(-) diff --git a/x-pack/plugins/maps/public/classes/fields/es_agg_field.ts b/x-pack/plugins/maps/public/classes/fields/es_agg_field.ts index 4a3ac6390c5a7..60d437d2321b5 100644 --- a/x-pack/plugins/maps/public/classes/fields/es_agg_field.ts +++ b/x-pack/plugins/maps/public/classes/fields/es_agg_field.ts @@ -87,7 +87,7 @@ export class ESAggField implements IESAggField { return this._esDocField ? this._esDocField.getName() : ''; } - async createTooltipProperty(value: string | undefined): Promise { + async createTooltipProperty(value: string | string[] | undefined): Promise { const indexPattern = await this._source.getIndexPattern(); const tooltipProperty = new TooltipProperty(this.getName(), await this.getLabel(), value); return new ESAggTooltipProperty(tooltipProperty, indexPattern, this, this.getAggType()); diff --git a/x-pack/plugins/maps/public/classes/fields/es_doc_field.ts b/x-pack/plugins/maps/public/classes/fields/es_doc_field.ts index 670b3ba32888b..9faa33fae5a43 100644 --- a/x-pack/plugins/maps/public/classes/fields/es_doc_field.ts +++ b/x-pack/plugins/maps/public/classes/fields/es_doc_field.ts @@ -45,7 +45,7 @@ export class ESDocField extends AbstractField implements IField { : indexPatternField; } - async createTooltipProperty(value: string | undefined): Promise { + async createTooltipProperty(value: string | string[] | undefined): Promise { const indexPattern = await this._source.getIndexPattern(); const tooltipProperty = new TooltipProperty(this.getName(), await this.getLabel(), value); return new ESTooltipProperty(tooltipProperty, indexPattern, this as IField); diff --git a/x-pack/plugins/maps/public/classes/fields/field.ts b/x-pack/plugins/maps/public/classes/fields/field.ts index 04daedc59c032..dfd5dc05f7b83 100644 --- a/x-pack/plugins/maps/public/classes/fields/field.ts +++ b/x-pack/plugins/maps/public/classes/fields/field.ts @@ -14,7 +14,7 @@ export interface IField { canValueBeFormatted(): boolean; getLabel(): Promise; getDataType(): Promise; - createTooltipProperty(value: string | undefined): Promise; + createTooltipProperty(value: string | string[] | undefined): Promise; getSource(): IVectorSource; getOrigin(): FIELD_ORIGIN; isValid(): boolean; @@ -60,7 +60,7 @@ export class AbstractField implements IField { return this._fieldName; } - async createTooltipProperty(value: string | undefined): Promise { + async createTooltipProperty(value: string | string[] | undefined): Promise { const label = await this.getLabel(); return new TooltipProperty(this.getName(), label, value); } diff --git a/x-pack/plugins/maps/public/classes/fields/top_term_percentage_field.ts b/x-pack/plugins/maps/public/classes/fields/top_term_percentage_field.ts index 84bade4d94490..6c504daf3e192 100644 --- a/x-pack/plugins/maps/public/classes/fields/top_term_percentage_field.ts +++ b/x-pack/plugins/maps/public/classes/fields/top_term_percentage_field.ts @@ -48,7 +48,7 @@ export class TopTermPercentageField implements IESAggField { return 'number'; } - async createTooltipProperty(value: string | undefined): Promise { + async createTooltipProperty(value: string | string[] | undefined): Promise { return new TooltipProperty(this.getName(), await this.getLabel(), value); } diff --git a/x-pack/plugins/maps/public/classes/tooltips/es_tooltip_property.ts b/x-pack/plugins/maps/public/classes/tooltips/es_tooltip_property.ts index d2fdcfaab476c..516ad25f933f6 100644 --- a/x-pack/plugins/maps/public/classes/tooltips/es_tooltip_property.ts +++ b/x-pack/plugins/maps/public/classes/tooltips/es_tooltip_property.ts @@ -33,7 +33,7 @@ export class ESTooltipProperty implements ITooltipProperty { return this._tooltipProperty.getPropertyName(); } - getRawValue(): string | undefined { + getRawValue(): string | string[] | undefined { return this._tooltipProperty.getRawValue(); } @@ -48,7 +48,12 @@ export class ESTooltipProperty implements ITooltipProperty { const indexPatternField = this._getIndexPatternField(); if (!indexPatternField || !this._field.canValueBeFormatted()) { - return _.escape(this.getRawValue()); + const rawValue = this.getRawValue(); + if (Array.isArray(rawValue)) { + return _.escape(rawValue.join()); + } else { + return _.escape(rawValue); + } } const htmlConverter = indexPatternField.format.getConverterFor('html'); diff --git a/x-pack/plugins/maps/public/classes/tooltips/join_tooltip_property.ts b/x-pack/plugins/maps/public/classes/tooltips/join_tooltip_property.ts index cc95c12ef630f..fad6d6b84f77f 100644 --- a/x-pack/plugins/maps/public/classes/tooltips/join_tooltip_property.ts +++ b/x-pack/plugins/maps/public/classes/tooltips/join_tooltip_property.ts @@ -29,7 +29,7 @@ export class JoinTooltipProperty implements ITooltipProperty { return this._tooltipProperty.getPropertyName(); } - getRawValue(): string | undefined { + getRawValue(): string | string[] | undefined { return this._tooltipProperty.getRawValue(); } diff --git a/x-pack/plugins/maps/public/classes/tooltips/tooltip_property.ts b/x-pack/plugins/maps/public/classes/tooltips/tooltip_property.ts index 8da2ed795943b..7149fe29f90ec 100644 --- a/x-pack/plugins/maps/public/classes/tooltips/tooltip_property.ts +++ b/x-pack/plugins/maps/public/classes/tooltips/tooltip_property.ts @@ -12,7 +12,7 @@ export interface ITooltipProperty { getPropertyKey(): string; getPropertyName(): string; getHtmlDisplayValue(): string; - getRawValue(): string | undefined; + getRawValue(): string | string[] | undefined; isFilterable(): boolean; getESFilters(): Promise; } @@ -41,10 +41,10 @@ export type RenderToolTipContent = (params: RenderTooltipContentParams) => JSX.E export class TooltipProperty implements ITooltipProperty { private readonly _propertyKey: string; - private readonly _rawValue: string | undefined; + private readonly _rawValue: string | string[] | undefined; private readonly _propertyName: string; - constructor(propertyKey: string, propertyName: string, rawValue: string | undefined) { + constructor(propertyKey: string, propertyName: string, rawValue: string | string[] | undefined) { this._propertyKey = propertyKey; this._propertyName = propertyName; this._rawValue = rawValue; @@ -59,10 +59,10 @@ export class TooltipProperty implements ITooltipProperty { } getHtmlDisplayValue(): string { - return _.escape(this._rawValue); + return _.escape(Array.isArray(this._rawValue) ? this._rawValue.join() : this._rawValue); } - getRawValue(): string | undefined { + getRawValue(): string | string[] | undefined { return this._rawValue; } diff --git a/x-pack/plugins/maps/public/index.ts b/x-pack/plugins/maps/public/index.ts index e3feb47691877..79953e35d51e5 100644 --- a/x-pack/plugins/maps/public/index.ts +++ b/x-pack/plugins/maps/public/index.ts @@ -12,3 +12,4 @@ export const plugin: PluginInitializer = () => }; export { MAP_SAVED_OBJECT_TYPE } from '../common/constants'; +export { ITooltipProperty } from './classes/tooltips/tooltip_property'; diff --git a/x-pack/plugins/siem/public/network/components/embeddables/map_tool_tip/__snapshots__/point_tool_tip_content.test.tsx.snap b/x-pack/plugins/siem/public/network/components/embeddables/map_tool_tip/__snapshots__/point_tool_tip_content.test.tsx.snap index 9d39b6e59365f..8927e492993d0 100644 --- a/x-pack/plugins/siem/public/network/components/embeddables/map_tool_tip/__snapshots__/point_tool_tip_content.test.tsx.snap +++ b/x-pack/plugins/siem/public/network/components/embeddables/map_tool_tip/__snapshots__/point_tool_tip_content.test.tsx.snap @@ -6,8 +6,9 @@ exports[`PointToolTipContent renders correctly against snapshot 1`] = ` contextId="contextId" featureProps={ Array [ - Object { + TooltipProperty { "_propertyKey": "host.name", + "_propertyName": "host.name", "_rawValue": "testPropValue", }, ] diff --git a/x-pack/plugins/siem/public/network/components/embeddables/map_tool_tip/line_tool_tip_content.test.tsx b/x-pack/plugins/siem/public/network/components/embeddables/map_tool_tip/line_tool_tip_content.test.tsx index a0e57a2e850c1..aef41ddaef5ae 100644 --- a/x-pack/plugins/siem/public/network/components/embeddables/map_tool_tip/line_tool_tip_content.test.tsx +++ b/x-pack/plugins/siem/public/network/components/embeddables/map_tool_tip/line_tool_tip_content.test.tsx @@ -7,35 +7,24 @@ import { shallow } from 'enzyme'; import React from 'react'; import { LineToolTipContentComponent } from './line_tool_tip_content'; -import { FeatureProperty } from '../types'; import { SUM_OF_CLIENT_BYTES, SUM_OF_DESTINATION_BYTES, SUM_OF_SERVER_BYTES, SUM_OF_SOURCE_BYTES, } from '../map_config'; +import { ITooltipProperty } from '../../../../../../maps/public'; +import { TooltipProperty } from '../../../../../../maps/public/classes/tooltips/tooltip_property'; describe('LineToolTipContent', () => { - const mockFeatureProps: FeatureProperty[] = [ - { - _propertyKey: SUM_OF_DESTINATION_BYTES, - _rawValue: 'testPropValue', - }, - { - _propertyKey: SUM_OF_SOURCE_BYTES, - _rawValue: 'testPropValue', - }, + const mockFeatureProps: ITooltipProperty[] = [ + new TooltipProperty(SUM_OF_DESTINATION_BYTES, SUM_OF_DESTINATION_BYTES, 'testPropValue'), + new TooltipProperty(SUM_OF_SOURCE_BYTES, SUM_OF_SOURCE_BYTES, 'testPropValue'), ]; - const mockClientServerFeatureProps: FeatureProperty[] = [ - { - _propertyKey: SUM_OF_SERVER_BYTES, - _rawValue: 'testPropValue', - }, - { - _propertyKey: SUM_OF_CLIENT_BYTES, - _rawValue: 'testPropValue', - }, + const mockClientServerFeatureProps: ITooltipProperty[] = [ + new TooltipProperty(SUM_OF_SERVER_BYTES, SUM_OF_SERVER_BYTES, 'testPropValue'), + new TooltipProperty(SUM_OF_CLIENT_BYTES, SUM_OF_CLIENT_BYTES, 'testPropValue'), ]; test('renders correctly against snapshot', () => { diff --git a/x-pack/plugins/siem/public/network/components/embeddables/map_tool_tip/line_tool_tip_content.tsx b/x-pack/plugins/siem/public/network/components/embeddables/map_tool_tip/line_tool_tip_content.tsx index 7c2d5e51d813f..9238f7ec65a20 100644 --- a/x-pack/plugins/siem/public/network/components/embeddables/map_tool_tip/line_tool_tip_content.tsx +++ b/x-pack/plugins/siem/public/network/components/embeddables/map_tool_tip/line_tool_tip_content.tsx @@ -14,8 +14,9 @@ import { SUM_OF_SERVER_BYTES, SUM_OF_SOURCE_BYTES, } from '../map_config'; -import { FeatureProperty } from '../types'; + import * as i18n from '../translations'; +import { ITooltipProperty } from '../../../../../../maps/public'; const FlowBadge = (styled(EuiBadge)` height: 45px; @@ -28,20 +29,22 @@ const EuiFlexGroupStyled = styled(EuiFlexGroup)` interface LineToolTipContentProps { contextId: string; - featureProps: FeatureProperty[]; + featureProps: ITooltipProperty[]; } export const LineToolTipContentComponent = ({ contextId, featureProps, }: LineToolTipContentProps) => { - const lineProps = featureProps.reduce>( - (acc, f) => ({ + const lineProps = featureProps.reduce>((acc, f) => { + const rawValue = f.getRawValue() ?? []; + return { ...acc, - ...{ [f._propertyKey]: Array.isArray(f._rawValue) ? f._rawValue : [f._rawValue] }, - }), - {} - ); + ...{ + [f.getPropertyKey()]: Array.isArray(rawValue) ? rawValue : [rawValue], + }, + }; + }, {}); const isSrcDest = Object.keys(lineProps).includes(SUM_OF_SOURCE_BYTES); diff --git a/x-pack/plugins/siem/public/network/components/embeddables/map_tool_tip/map_tool_tip.tsx b/x-pack/plugins/siem/public/network/components/embeddables/map_tool_tip/map_tool_tip.tsx index 0f38c350986b4..10267d398848e 100644 --- a/x-pack/plugins/siem/public/network/components/embeddables/map_tool_tip/map_tool_tip.tsx +++ b/x-pack/plugins/siem/public/network/components/embeddables/map_tool_tip/map_tool_tip.tsx @@ -11,12 +11,13 @@ import { EuiLoadingSpinner, EuiOutsideClickDetector, } from '@elastic/eui'; -import { FeatureGeometry, FeatureProperty, MapToolTipProps } from '../types'; +import { FeatureGeometry, MapToolTipProps } from '../types'; import { ToolTipFooter } from './tooltip_footer'; import { LineToolTipContent } from './line_tool_tip_content'; import { PointToolTipContent } from './point_tool_tip_content'; import { Loader } from '../../../../common/components/loader'; import * as i18n from '../translations'; +import { ITooltipProperty } from '../../../../../../maps/public'; export const MapToolTipComponent = ({ addFilters, @@ -31,7 +32,7 @@ export const MapToolTipComponent = ({ const [isLoadingNextFeature, setIsLoadingNextFeature] = useState(false); const [isError, setIsError] = useState(false); const [featureIndex, setFeatureIndex] = useState(0); - const [featureProps, setFeatureProps] = useState([]); + const [featureProps, setFeatureProps] = useState([]); const [featureGeometry, setFeatureGeometry] = useState(null); const [, setLayerName] = useState(''); @@ -64,7 +65,7 @@ export const MapToolTipComponent = ({ getLayerName(layerId), ]); - setFeatureProps((featureProperties as unknown) as FeatureProperty[]); + setFeatureProps(featureProperties); setFeatureGeometry(featureGeo); setLayerName(layerNameString); } catch (e) { diff --git a/x-pack/plugins/siem/public/network/components/embeddables/map_tool_tip/point_tool_tip_content.test.tsx b/x-pack/plugins/siem/public/network/components/embeddables/map_tool_tip/point_tool_tip_content.test.tsx index d5a7c51ccdeb8..79d5c0d43cde6 100644 --- a/x-pack/plugins/siem/public/network/components/embeddables/map_tool_tip/point_tool_tip_content.test.tsx +++ b/x-pack/plugins/siem/public/network/components/embeddables/map_tool_tip/point_tool_tip_content.test.tsx @@ -6,29 +6,24 @@ import { shallow } from 'enzyme'; import React from 'react'; -import { FeatureProperty } from '../types'; import { getRenderedFieldValue, PointToolTipContentComponent } from './point_tool_tip_content'; import { TestProviders } from '../../../../common/mock'; import { getEmptyStringTag } from '../../../../common/components/empty_value'; import { HostDetailsLink, IPDetailsLink } from '../../../../common/components/links'; import { useMountAppended } from '../../../../common/utils/use_mount_appended'; import { FlowTarget } from '../../../../graphql/types'; +import { ITooltipProperty } from '../../../../../../maps/public'; +import { TooltipProperty } from '../../../../../../maps/public/classes/tooltips/tooltip_property'; describe('PointToolTipContent', () => { const mount = useMountAppended(); - const mockFeatureProps: FeatureProperty[] = [ - { - _propertyKey: 'host.name', - _rawValue: 'testPropValue', - }, + const mockFeatureProps: ITooltipProperty[] = [ + new TooltipProperty('host.name', 'host.name', 'testPropValue'), ]; - const mockFeaturePropsArrayValue: FeatureProperty[] = [ - { - _propertyKey: 'host.name', - _rawValue: ['testPropValue1', 'testPropValue2'], - }, + const mockFeaturePropsArrayValue: ITooltipProperty[] = [ + new TooltipProperty('host.name', 'host.name', ['testPropValue1', 'testPropValue2']), ]; test('renders correctly against snapshot', () => { @@ -46,32 +41,6 @@ describe('PointToolTipContent', () => { expect(wrapper.find('PointToolTipContentComponent')).toMatchSnapshot(); }); - test('renders array filter correctly', () => { - const closeTooltip = jest.fn(); - - const wrapper = mount( - - - - ); - expect(wrapper.find('[data-test-subj="add-to-kql-host.name"]').prop('filter')).toEqual({ - meta: { - alias: null, - disabled: false, - key: 'host.name', - negate: false, - params: { query: 'testPropValue1' }, - type: 'phrase', - value: 'testPropValue1', - }, - query: { match: { 'host.name': { query: 'testPropValue1', type: 'phrase' } } }, - }); - }); - describe('#getRenderedFieldValue', () => { test('it returns empty tag if value is empty', () => { expect(getRenderedFieldValue('host.name', '')).toStrictEqual(getEmptyStringTag()); diff --git a/x-pack/plugins/siem/public/network/components/embeddables/map_tool_tip/point_tool_tip_content.tsx b/x-pack/plugins/siem/public/network/components/embeddables/map_tool_tip/point_tool_tip_content.tsx index c691407f6166e..16494c01ac280 100644 --- a/x-pack/plugins/siem/public/network/components/embeddables/map_tool_tip/point_tool_tip_content.tsx +++ b/x-pack/plugins/siem/public/network/components/embeddables/map_tool_tip/point_tool_tip_content.tsx @@ -6,23 +6,19 @@ import React from 'react'; import { sourceDestinationFieldMappings } from '../map_config'; -import { - AddFilterToGlobalSearchBar, - createFilter, -} from '../../../../common/components/add_filter_to_global_search_bar'; import { getEmptyTagValue, getOrEmptyTagFromValue, } from '../../../../common/components/empty_value'; import { DescriptionListStyled } from '../../../../common/components/page'; -import { FeatureProperty } from '../types'; import { HostDetailsLink, IPDetailsLink } from '../../../../common/components/links'; import { DefaultFieldRenderer } from '../../../../timelines/components/field_renderers/field_renderers'; import { FlowTarget } from '../../../../graphql/types'; +import { ITooltipProperty } from '../../../../../../maps/public'; interface PointToolTipContentProps { contextId: string; - featureProps: FeatureProperty[]; + featureProps: ITooltipProperty[]; closeTooltip?(): void; } @@ -31,15 +27,14 @@ export const PointToolTipContentComponent = ({ featureProps, closeTooltip, }: PointToolTipContentProps) => { - const featureDescriptionListItems = featureProps.map( - ({ _propertyKey: key, _rawValue: value }) => ({ + const featureDescriptionListItems = featureProps.map(featureProp => { + const key = featureProp.getPropertyKey(); + const value = featureProp.getRawValue() ?? []; + + return { title: sourceDestinationFieldMappings[key], description: ( - + <> {value != null ? ( + ), - }) - ); + }; + }); return ; }; diff --git a/x-pack/plugins/siem/public/network/components/embeddables/types.ts b/x-pack/plugins/siem/public/network/components/embeddables/types.ts index e111c2728ba7e..9a49046634c3b 100644 --- a/x-pack/plugins/siem/public/network/components/embeddables/types.ts +++ b/x-pack/plugins/siem/public/network/components/embeddables/types.ts @@ -40,16 +40,6 @@ export interface MapFeature { layerId: string; } -export interface LoadFeatureProps { - layerId: string; - featureId: number; -} - -export interface FeatureProperty { - _propertyKey: string; - _rawValue: string | string[]; -} - export interface FeatureGeometry { coordinates: [number]; type: string; From cb2e96d3de08e0e08882527db0c9130819e17a36 Mon Sep 17 00:00:00 2001 From: Garrett Spong Date: Fri, 15 May 2020 17:54:55 -0600 Subject: [PATCH 2/2] Fixing lingering type issue --- .../map_tool_tip/point_tool_tip_content.test.tsx | 7 ------- 1 file changed, 7 deletions(-) diff --git a/x-pack/plugins/siem/public/network/components/embeddables/map_tool_tip/point_tool_tip_content.test.tsx b/x-pack/plugins/siem/public/network/components/embeddables/map_tool_tip/point_tool_tip_content.test.tsx index 79d5c0d43cde6..36b9f44e19630 100644 --- a/x-pack/plugins/siem/public/network/components/embeddables/map_tool_tip/point_tool_tip_content.test.tsx +++ b/x-pack/plugins/siem/public/network/components/embeddables/map_tool_tip/point_tool_tip_content.test.tsx @@ -10,22 +10,15 @@ import { getRenderedFieldValue, PointToolTipContentComponent } from './point_too import { TestProviders } from '../../../../common/mock'; import { getEmptyStringTag } from '../../../../common/components/empty_value'; import { HostDetailsLink, IPDetailsLink } from '../../../../common/components/links'; -import { useMountAppended } from '../../../../common/utils/use_mount_appended'; import { FlowTarget } from '../../../../graphql/types'; import { ITooltipProperty } from '../../../../../../maps/public'; import { TooltipProperty } from '../../../../../../maps/public/classes/tooltips/tooltip_property'; describe('PointToolTipContent', () => { - const mount = useMountAppended(); - const mockFeatureProps: ITooltipProperty[] = [ new TooltipProperty('host.name', 'host.name', 'testPropValue'), ]; - const mockFeaturePropsArrayValue: ITooltipProperty[] = [ - new TooltipProperty('host.name', 'host.name', ['testPropValue1', 'testPropValue2']), - ]; - test('renders correctly against snapshot', () => { const closeTooltip = jest.fn();