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

[SIEM] [Maps] Fixes Network Map empty tooltip #66828

Merged
merged 4 commits into from
May 18, 2020
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
2 changes: 1 addition & 1 deletion x-pack/plugins/maps/public/classes/fields/es_agg_field.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ export class ESAggField implements IESAggField {
return this._esDocField ? this._esDocField.getName() : '';
}

async createTooltipProperty(value: string | undefined): Promise<ITooltipProperty> {
async createTooltipProperty(value: string | string[] | undefined): Promise<ITooltipProperty> {
spong marked this conversation as resolved.
Show resolved Hide resolved
const indexPattern = await this._source.getIndexPattern();
const tooltipProperty = new TooltipProperty(this.getName(), await this.getLabel(), value);
return new ESAggTooltipProperty(tooltipProperty, indexPattern, this, this.getAggType());
Expand Down
2 changes: 1 addition & 1 deletion x-pack/plugins/maps/public/classes/fields/es_doc_field.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ export class ESDocField extends AbstractField implements IField {
: indexPatternField;
}

async createTooltipProperty(value: string | undefined): Promise<ITooltipProperty> {
async createTooltipProperty(value: string | string[] | undefined): Promise<ITooltipProperty> {
const indexPattern = await this._source.getIndexPattern();
const tooltipProperty = new TooltipProperty(this.getName(), await this.getLabel(), value);
return new ESTooltipProperty(tooltipProperty, indexPattern, this as IField);
Expand Down
4 changes: 2 additions & 2 deletions x-pack/plugins/maps/public/classes/fields/field.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export interface IField {
canValueBeFormatted(): boolean;
getLabel(): Promise<string>;
getDataType(): Promise<string>;
createTooltipProperty(value: string | undefined): Promise<ITooltipProperty>;
createTooltipProperty(value: string | string[] | undefined): Promise<ITooltipProperty>;
getSource(): IVectorSource;
getOrigin(): FIELD_ORIGIN;
isValid(): boolean;
Expand Down Expand Up @@ -60,7 +60,7 @@ export class AbstractField implements IField {
return this._fieldName;
}

async createTooltipProperty(value: string | undefined): Promise<ITooltipProperty> {
async createTooltipProperty(value: string | string[] | undefined): Promise<ITooltipProperty> {
const label = await this.getLabel();
return new TooltipProperty(this.getName(), label, value);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ export class TopTermPercentageField implements IESAggField {
return 'number';
}

async createTooltipProperty(value: string | undefined): Promise<ITooltipProperty> {
async createTooltipProperty(value: string | string[] | undefined): Promise<ITooltipProperty> {
return new TooltipProperty(this.getName(), await this.getLabel(), value);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export class ESTooltipProperty implements ITooltipProperty {
return this._tooltipProperty.getPropertyName();
}

getRawValue(): string | undefined {
getRawValue(): string | string[] | undefined {
return this._tooltipProperty.getRawValue();
}

Expand All @@ -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());
spong marked this conversation as resolved.
Show resolved Hide resolved
} else {
return _.escape(rawValue);
}
}

const htmlConverter = indexPatternField.format.getConverterFor('html');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export class JoinTooltipProperty implements ITooltipProperty {
return this._tooltipProperty.getPropertyName();
}

getRawValue(): string | undefined {
getRawValue(): string | string[] | undefined {
return this._tooltipProperty.getRawValue();
}

Expand Down
10 changes: 5 additions & 5 deletions x-pack/plugins/maps/public/classes/tooltips/tooltip_property.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export interface ITooltipProperty {
getPropertyKey(): string;
getPropertyName(): string;
getHtmlDisplayValue(): string;
getRawValue(): string | undefined;
getRawValue(): string | string[] | undefined;
isFilterable(): boolean;
getESFilters(): Promise<Filter[]>;
}
Expand Down Expand Up @@ -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;
Expand All @@ -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);
spong marked this conversation as resolved.
Show resolved Hide resolved
}

getRawValue(): string | undefined {
getRawValue(): string | string[] | undefined {
return this._rawValue;
}

Expand Down
1 change: 1 addition & 0 deletions x-pack/plugins/maps/public/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,4 @@ export const plugin: PluginInitializer<MapsPluginSetup, MapsPluginStart> = () =>
};

export { MAP_SAVED_OBJECT_TYPE } from '../common/constants';
export { ITooltipProperty } from './classes/tooltips/tooltip_property';

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -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', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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<Record<string, string[]>>(
(acc, f) => ({
const lineProps = featureProps.reduce<Record<string, string[]>>((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);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -31,7 +32,7 @@ export const MapToolTipComponent = ({
const [isLoadingNextFeature, setIsLoadingNextFeature] = useState<boolean>(false);
const [isError, setIsError] = useState<boolean>(false);
const [featureIndex, setFeatureIndex] = useState<number>(0);
const [featureProps, setFeatureProps] = useState<FeatureProperty[]>([]);
const [featureProps, setFeatureProps] = useState<ITooltipProperty[]>([]);
const [featureGeometry, setFeatureGeometry] = useState<FeatureGeometry | null>(null);
const [, setLayerName] = useState<string>('');

Expand Down Expand Up @@ -64,7 +65,7 @@ export const MapToolTipComponent = ({
getLayerName(layerId),
]);

setFeatureProps((featureProperties as unknown) as FeatureProperty[]);
setFeatureProps(featureProperties);
setFeatureGeometry(featureGeo);
setLayerName(layerNameString);
} catch (e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,29 +6,17 @@

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 mockFeaturePropsArrayValue: FeatureProperty[] = [
{
_propertyKey: 'host.name',
_rawValue: ['testPropValue1', 'testPropValue2'],
},
const mockFeatureProps: ITooltipProperty[] = [
new TooltipProperty('host.name', 'host.name', 'testPropValue'),
];

test('renders correctly against snapshot', () => {
Expand All @@ -46,32 +34,6 @@ describe('PointToolTipContent', () => {
expect(wrapper.find('PointToolTipContentComponent')).toMatchSnapshot();
});

test('renders array filter correctly', () => {
const closeTooltip = jest.fn();

const wrapper = mount(
<TestProviders>
<PointToolTipContentComponent
contextId={'contextId'}
featureProps={mockFeaturePropsArrayValue}
closeTooltip={closeTooltip}
/>
</TestProviders>
);
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' } } },
});
});

spong marked this conversation as resolved.
Show resolved Hide resolved
describe('#getRenderedFieldValue', () => {
test('it returns empty tag if value is empty', () => {
expect(getRenderedFieldValue('host.name', '')).toStrictEqual(getEmptyStringTag());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand All @@ -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: (
<AddFilterToGlobalSearchBar
filter={createFilter(key, Array.isArray(value) ? value[0] : value)}
onFilterAdded={closeTooltip}
data-test-subj={`add-to-kql-${key}`}
>
<>
{value != null ? (
<DefaultFieldRenderer
rowItems={Array.isArray(value) ? value : [value]}
Expand All @@ -50,10 +45,10 @@ export const PointToolTipContentComponent = ({
) : (
getEmptyTagValue()
)}
</AddFilterToGlobalSearchBar>
</>
),
})
);
};
});

return <DescriptionListStyled listItems={featureDescriptionListItems} />;
};
Expand Down
10 changes: 0 additions & 10 deletions x-pack/plugins/siem/public/network/components/embeddables/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down