From 2a84b428b5fdca7d3447b30074b35cac19472891 Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Tue, 18 May 2021 17:17:42 -0600 Subject: [PATCH] [Maps] convert TooltipControl to typescript (#100059) * [Maps] convert ToolbarControl to typescript * fix scss import * remove unused function from APM map tooltip * apm tslint * pass loadFeatureGeometry to renderTooltipContent * security_solution: pass mbProperties to loadFeatureProperties * security_solution tslint Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../VisitorBreakdownMap/EmbeddedMap.tsx | 2 - .../VisitorBreakdownMap/MapToolTip.tsx | 6 +- .../common/descriptor_types/map_descriptor.ts | 2 +- .../classes/tooltips/tooltip_property.ts | 32 +++- .../public/connected_components/_index.scss | 2 +- .../connected_components/mb_map/mb_map.tsx | 1 - ....js.snap => tooltip_control.test.tsx.snap} | 8 +- ....js.snap => tooltip_popover.test.tsx.snap} | 13 +- .../feature_properties.test.tsx.snap | 0 .../__snapshots__/footer.test.tsx.snap | 0 .../__snapshots__/header.test.tsx.snap | 0 .../features_tooltip/_index.scss | 0 .../feature_geometry_filter_form.tsx | 12 +- .../feature_properties.test.tsx | 4 +- .../features_tooltip/feature_properties.tsx | 8 +- .../features_tooltip/features_tooltip.tsx | 19 +- .../features_tooltip/footer.test.tsx | 4 +- .../features_tooltip/footer.tsx | 8 +- .../features_tooltip/header.test.tsx | 4 +- .../features_tooltip/header.tsx | 4 +- .../features_tooltip/index.ts | 0 .../tooltip_control/{index.js => index.ts} | 14 +- ...ntrol.test.js => tooltip_control.test.tsx} | 44 +++-- ...tooltip_control.js => tooltip_control.tsx} | 171 +++++++++++++----- ...pover.test.js => tooltip_popover.test.tsx} | 50 ++--- ...tooltip_popover.js => tooltip_popover.tsx} | 71 ++++++-- .../embeddables/map_tool_tip/map_tool_tip.tsx | 11 +- 27 files changed, 320 insertions(+), 170 deletions(-) rename x-pack/plugins/maps/public/connected_components/mb_map/tooltip_control/__snapshots__/{tooltip_control.test.js.snap => tooltip_control.test.tsx.snap} (85%) rename x-pack/plugins/maps/public/connected_components/mb_map/tooltip_control/__snapshots__/{tooltip_popover.test.js.snap => tooltip_popover.test.tsx.snap} (84%) rename x-pack/plugins/maps/public/connected_components/mb_map/{ => tooltip_control}/features_tooltip/__snapshots__/feature_properties.test.tsx.snap (100%) rename x-pack/plugins/maps/public/connected_components/mb_map/{ => tooltip_control}/features_tooltip/__snapshots__/footer.test.tsx.snap (100%) rename x-pack/plugins/maps/public/connected_components/mb_map/{ => tooltip_control}/features_tooltip/__snapshots__/header.test.tsx.snap (100%) rename x-pack/plugins/maps/public/connected_components/mb_map/{ => tooltip_control}/features_tooltip/_index.scss (100%) rename x-pack/plugins/maps/public/connected_components/mb_map/{ => tooltip_control}/features_tooltip/feature_geometry_filter_form.tsx (92%) rename x-pack/plugins/maps/public/connected_components/mb_map/{ => tooltip_control}/features_tooltip/feature_properties.test.tsx (97%) rename x-pack/plugins/maps/public/connected_components/mb_map/{ => tooltip_control}/features_tooltip/feature_properties.tsx (97%) rename x-pack/plugins/maps/public/connected_components/mb_map/{ => tooltip_control}/features_tooltip/features_tooltip.tsx (92%) rename x-pack/plugins/maps/public/connected_components/mb_map/{ => tooltip_control}/features_tooltip/footer.test.tsx (97%) rename x-pack/plugins/maps/public/connected_components/mb_map/{ => tooltip_control}/features_tooltip/footer.tsx (95%) rename x-pack/plugins/maps/public/connected_components/mb_map/{ => tooltip_control}/features_tooltip/header.test.tsx (93%) rename x-pack/plugins/maps/public/connected_components/mb_map/{ => tooltip_control}/features_tooltip/header.tsx (95%) rename x-pack/plugins/maps/public/connected_components/mb_map/{ => tooltip_control}/features_tooltip/index.ts (100%) rename x-pack/plugins/maps/public/connected_components/mb_map/tooltip_control/{index.js => index.ts} (71%) rename x-pack/plugins/maps/public/connected_components/mb_map/tooltip_control/{tooltip_control.test.js => tooltip_control.test.tsx} (87%) rename x-pack/plugins/maps/public/connected_components/mb_map/tooltip_control/{tooltip_control.js => tooltip_control.tsx} (64%) rename x-pack/plugins/maps/public/connected_components/mb_map/tooltip_control/{tooltip_popover.test.js => tooltip_popover.test.tsx} (81%) rename x-pack/plugins/maps/public/connected_components/mb_map/tooltip_control/{tooltip_popover.js => tooltip_popover.tsx} (63%) diff --git a/x-pack/plugins/apm/public/components/app/RumDashboard/VisitorBreakdownMap/EmbeddedMap.tsx b/x-pack/plugins/apm/public/components/app/RumDashboard/VisitorBreakdownMap/EmbeddedMap.tsx index 1e368b2eb5368..11bc6796c87b7 100644 --- a/x-pack/plugins/apm/public/components/app/RumDashboard/VisitorBreakdownMap/EmbeddedMap.tsx +++ b/x-pack/plugins/apm/public/components/app/RumDashboard/VisitorBreakdownMap/EmbeddedMap.tsx @@ -109,7 +109,6 @@ export function EmbeddedMapComponent() { isLocked, getLayerName, loadFeatureProperties, - loadFeatureGeometry, }: RenderTooltipContentParams) { const props = { addFilters, @@ -117,7 +116,6 @@ export function EmbeddedMapComponent() { isLocked, getLayerName, loadFeatureProperties, - loadFeatureGeometry, }; return ; diff --git a/x-pack/plugins/apm/public/components/app/RumDashboard/VisitorBreakdownMap/MapToolTip.tsx b/x-pack/plugins/apm/public/components/app/RumDashboard/VisitorBreakdownMap/MapToolTip.tsx index 7501d5bfaa2c5..f6f8c336720e7 100644 --- a/x-pack/plugins/apm/public/components/app/RumDashboard/VisitorBreakdownMap/MapToolTip.tsx +++ b/x-pack/plugins/apm/public/components/app/RumDashboard/VisitorBreakdownMap/MapToolTip.tsx @@ -59,7 +59,11 @@ function MapToolTipComponent({ useEffect(() => { const loadRegionInfo = async () => { if (loadFeatureProperties) { - const items = await loadFeatureProperties({ layerId, featureId }); + const items = await loadFeatureProperties({ + layerId, + featureId, + mbProperties: {}, + }); items.forEach((item) => { if ( item.getPropertyKey() === COUNTRY_NAME || diff --git a/x-pack/plugins/maps/common/descriptor_types/map_descriptor.ts b/x-pack/plugins/maps/common/descriptor_types/map_descriptor.ts index 0bb9c7cc6f02b..102434ffda161 100644 --- a/x-pack/plugins/maps/common/descriptor_types/map_descriptor.ts +++ b/x-pack/plugins/maps/common/descriptor_types/map_descriptor.ts @@ -63,7 +63,7 @@ export type TooltipState = { features: TooltipFeature[]; id: string; isLocked: boolean; - location: number[]; // 0 index is lon, 1 index is lat + location: [number, number]; // 0 index is lon, 1 index is lat }; export type DrawState = { 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 a8bc5b9a821f0..27325baab8dcc 100644 --- a/x-pack/plugins/maps/public/classes/tooltips/tooltip_property.ts +++ b/x-pack/plugins/maps/public/classes/tooltips/tooltip_property.ts @@ -6,7 +6,10 @@ */ import _ from 'lodash'; -import { Filter } from '../../../../../../src/plugins/data/public'; +import { GeoJsonProperties, Geometry } from 'geojson'; +import { Filter } from 'src/plugins/data/public'; +import { ActionExecutionContext, Action } from 'src/plugins/ui_actions/public'; +import { RawValue } from '../../../../../plugins/maps/common/constants'; import type { TooltipFeature } from '../../../../../plugins/maps/common/descriptor_types'; export interface ITooltipProperty { @@ -29,13 +32,30 @@ export interface FeatureGeometry { } export interface RenderTooltipContentParams { - addFilters(filter: object, actionId: string): void; - closeTooltip(): void; + addFilters: ((filters: Filter[], actionId: string) => Promise) | null; + closeTooltip: () => void; features: TooltipFeature[]; + getActionContext?: () => ActionExecutionContext; + getFilterActions?: () => Promise; + getLayerName: (layerId: string) => Promise; isLocked: boolean; - getLayerName(layerId: string): Promise; - loadFeatureProperties({ layerId, featureId }: LoadFeatureProps): Promise; - loadFeatureGeometry({ layerId, featureId }: LoadFeatureProps): FeatureGeometry; + loadFeatureProperties: ({ + layerId, + featureId, + mbProperties, + }: { + layerId: string; + featureId?: string | number; + mbProperties: GeoJsonProperties; + }) => Promise; + loadFeatureGeometry: ({ + layerId, + featureId, + }: { + layerId: string; + featureId?: string | number; + }) => Geometry | null; + onSingleValueTrigger?: (actionId: string, key: string, value: RawValue) => void; } export type RenderToolTipContent = (params: RenderTooltipContentParams) => JSX.Element; diff --git a/x-pack/plugins/maps/public/connected_components/_index.scss b/x-pack/plugins/maps/public/connected_components/_index.scss index 2a6e1a8982e63..c4438a9312bce 100644 --- a/x-pack/plugins/maps/public/connected_components/_index.scss +++ b/x-pack/plugins/maps/public/connected_components/_index.scss @@ -2,5 +2,5 @@ @import 'layer_panel/index'; @import 'right_side_controls/index'; @import 'toolbar_overlay/index'; -@import 'mb_map/features_tooltip/index'; +@import 'mb_map/tooltip_control/features_tooltip/index'; @import 'mb_map/scale_control/index'; diff --git a/x-pack/plugins/maps/public/connected_components/mb_map/mb_map.tsx b/x-pack/plugins/maps/public/connected_components/mb_map/mb_map.tsx index 9ec6cbcb5d4ac..ac3e72545033f 100644 --- a/x-pack/plugins/maps/public/connected_components/mb_map/mb_map.tsx +++ b/x-pack/plugins/maps/public/connected_components/mb_map/mb_map.tsx @@ -19,7 +19,6 @@ import { Filter } from 'src/plugins/data/public'; import { ActionExecutionContext, Action } from 'src/plugins/ui_actions/public'; import { DrawFilterControl } from './draw_control'; import { ScaleControl } from './scale_control'; -// @ts-expect-error import { TooltipControl } from './tooltip_control'; import { clampToLatBounds, clampToLonBounds } from '../../../common/elasticsearch_util'; import { getInitialView } from './get_initial_view'; diff --git a/x-pack/plugins/maps/public/connected_components/mb_map/tooltip_control/__snapshots__/tooltip_control.test.js.snap b/x-pack/plugins/maps/public/connected_components/mb_map/tooltip_control/__snapshots__/tooltip_control.test.tsx.snap similarity index 85% rename from x-pack/plugins/maps/public/connected_components/mb_map/tooltip_control/__snapshots__/tooltip_control.test.js.snap rename to x-pack/plugins/maps/public/connected_components/mb_map/tooltip_control/__snapshots__/tooltip_control.test.tsx.snap index 030de04987ede..c5784cf9a309a 100644 --- a/x-pack/plugins/maps/public/connected_components/mb_map/tooltip_control/__snapshots__/tooltip_control.test.js.snap +++ b/x-pack/plugins/maps/public/connected_components/mb_map/tooltip_control/__snapshots__/tooltip_control.test.tsx.snap @@ -9,9 +9,10 @@ exports[`TooltipControl render should render hover tooltip 1`] = ` features={ Array [ Object { - "geometry": Object {}, + "actions": Array [], "id": 1, "layerId": "tfi3f", + "mbProperties": Object {}, }, ] } @@ -19,6 +20,7 @@ exports[`TooltipControl render should render hover tooltip 1`] = ` index={0} isLocked={false} key="1" + loadFeatureGeometry={[Function]} location={ Array [ -120, @@ -43,9 +45,10 @@ exports[`TooltipControl render should render locked tooltip 1`] = ` features={ Array [ Object { - "geometry": Object {}, + "actions": Array [], "id": 1, "layerId": "tfi3f", + "mbProperties": Object {}, }, ] } @@ -53,6 +56,7 @@ exports[`TooltipControl render should render locked tooltip 1`] = ` index={0} isLocked={true} key="2" + loadFeatureGeometry={[Function]} location={ Array [ -120, diff --git a/x-pack/plugins/maps/public/connected_components/mb_map/tooltip_control/__snapshots__/tooltip_popover.test.js.snap b/x-pack/plugins/maps/public/connected_components/mb_map/tooltip_control/__snapshots__/tooltip_popover.test.tsx.snap similarity index 84% rename from x-pack/plugins/maps/public/connected_components/mb_map/tooltip_control/__snapshots__/tooltip_popover.test.js.snap rename to x-pack/plugins/maps/public/connected_components/mb_map/tooltip_control/__snapshots__/tooltip_popover.test.tsx.snap index 3887d44bb5e72..5cf2cca4dfd80 100644 --- a/x-pack/plugins/maps/public/connected_components/mb_map/tooltip_control/__snapshots__/tooltip_popover.test.js.snap +++ b/x-pack/plugins/maps/public/connected_components/mb_map/tooltip_control/__snapshots__/tooltip_popover.test.tsx.snap @@ -24,7 +24,7 @@ exports[`TooltipPopover render should render tooltip popover 1`] = ` style={ Object { "pointerEvents": "none", - "transform": "translate(NaNpx, 2987px)", + "transform": "translate(11987px, 2987px)", } } > @@ -42,14 +42,17 @@ exports[`TooltipPopover render should render tooltip popover 1`] = ` features={ Array [ Object { - "geometry": Object {}, + "actions": Array [], "id": 1, "layerId": "tfi3f", + "mbProperties": Object {}, }, ] } + findLayerById={[Function]} getLayerName={[Function]} isLocked={false} + loadFeatureGeometry={[Function]} loadFeatureProperties={[Function]} /> @@ -80,7 +83,7 @@ exports[`TooltipPopover render should render tooltip popover with custom tooltip style={ Object { "pointerEvents": "none", - "transform": "translate(NaNpx, 2987px)", + "transform": "translate(11987px, 2987px)", } } > @@ -90,14 +93,16 @@ exports[`TooltipPopover render should render tooltip popover with custom tooltip features={ Array [ Object { - "geometry": Object {}, + "actions": Array [], "id": 1, "layerId": "tfi3f", + "mbProperties": Object {}, }, ] } getLayerName={[Function]} isLocked={false} + loadFeatureGeometry={[Function]} loadFeatureProperties={[Function]} > Custom tooltip content diff --git a/x-pack/plugins/maps/public/connected_components/mb_map/features_tooltip/__snapshots__/feature_properties.test.tsx.snap b/x-pack/plugins/maps/public/connected_components/mb_map/tooltip_control/features_tooltip/__snapshots__/feature_properties.test.tsx.snap similarity index 100% rename from x-pack/plugins/maps/public/connected_components/mb_map/features_tooltip/__snapshots__/feature_properties.test.tsx.snap rename to x-pack/plugins/maps/public/connected_components/mb_map/tooltip_control/features_tooltip/__snapshots__/feature_properties.test.tsx.snap diff --git a/x-pack/plugins/maps/public/connected_components/mb_map/features_tooltip/__snapshots__/footer.test.tsx.snap b/x-pack/plugins/maps/public/connected_components/mb_map/tooltip_control/features_tooltip/__snapshots__/footer.test.tsx.snap similarity index 100% rename from x-pack/plugins/maps/public/connected_components/mb_map/features_tooltip/__snapshots__/footer.test.tsx.snap rename to x-pack/plugins/maps/public/connected_components/mb_map/tooltip_control/features_tooltip/__snapshots__/footer.test.tsx.snap diff --git a/x-pack/plugins/maps/public/connected_components/mb_map/features_tooltip/__snapshots__/header.test.tsx.snap b/x-pack/plugins/maps/public/connected_components/mb_map/tooltip_control/features_tooltip/__snapshots__/header.test.tsx.snap similarity index 100% rename from x-pack/plugins/maps/public/connected_components/mb_map/features_tooltip/__snapshots__/header.test.tsx.snap rename to x-pack/plugins/maps/public/connected_components/mb_map/tooltip_control/features_tooltip/__snapshots__/header.test.tsx.snap diff --git a/x-pack/plugins/maps/public/connected_components/mb_map/features_tooltip/_index.scss b/x-pack/plugins/maps/public/connected_components/mb_map/tooltip_control/features_tooltip/_index.scss similarity index 100% rename from x-pack/plugins/maps/public/connected_components/mb_map/features_tooltip/_index.scss rename to x-pack/plugins/maps/public/connected_components/mb_map/tooltip_control/features_tooltip/_index.scss diff --git a/x-pack/plugins/maps/public/connected_components/mb_map/features_tooltip/feature_geometry_filter_form.tsx b/x-pack/plugins/maps/public/connected_components/mb_map/tooltip_control/features_tooltip/feature_geometry_filter_form.tsx similarity index 92% rename from x-pack/plugins/maps/public/connected_components/mb_map/features_tooltip/feature_geometry_filter_form.tsx rename to x-pack/plugins/maps/public/connected_components/mb_map/tooltip_control/features_tooltip/feature_geometry_filter_form.tsx index 61732d1c268c2..04e564943fa39 100644 --- a/x-pack/plugins/maps/public/connected_components/mb_map/features_tooltip/feature_geometry_filter_form.tsx +++ b/x-pack/plugins/maps/public/connected_components/mb_map/tooltip_control/features_tooltip/feature_geometry_filter_form.tsx @@ -12,16 +12,16 @@ import { Filter } from 'src/plugins/data/public'; import { ActionExecutionContext, Action } from 'src/plugins/ui_actions/public'; import { Geometry, Polygon } from 'geojson'; import rison, { RisonObject } from 'rison-node'; -import { URL_MAX_LENGTH } from '../../../../../../../src/core/public'; -import { ACTION_GLOBAL_APPLY_FILTER } from '../../../../../../../src/plugins/data/public'; +import { URL_MAX_LENGTH } from '../../../../../../../../src/core/public'; +import { ACTION_GLOBAL_APPLY_FILTER } from '../../../../../../../../src/plugins/data/public'; import { createSpatialFilterWithGeometry, PreIndexedShape, -} from '../../../../common/elasticsearch_util'; -import { ES_SPATIAL_RELATIONS, GEO_JSON_TYPE } from '../../../../common/constants'; +} from '../../../../../common/elasticsearch_util'; +import { ES_SPATIAL_RELATIONS, GEO_JSON_TYPE } from '../../../../../common/constants'; // @ts-expect-error -import { GeometryFilterForm } from '../../../components/geometry_filter_form'; -import { GeoFieldWithIndex } from '../../../components/geo_field_with_index'; +import { GeometryFilterForm } from '../../../../components/geometry_filter_form'; +import { GeoFieldWithIndex } from '../../../../components/geo_field_with_index'; // over estimated and imprecise value to ensure filter has additional room for any meta keys added when filter is mapped. const META_OVERHEAD = 100; diff --git a/x-pack/plugins/maps/public/connected_components/mb_map/features_tooltip/feature_properties.test.tsx b/x-pack/plugins/maps/public/connected_components/mb_map/tooltip_control/features_tooltip/feature_properties.test.tsx similarity index 97% rename from x-pack/plugins/maps/public/connected_components/mb_map/features_tooltip/feature_properties.test.tsx rename to x-pack/plugins/maps/public/connected_components/mb_map/tooltip_control/features_tooltip/feature_properties.test.tsx index c999e9e6705cc..ec77a1ff450d3 100644 --- a/x-pack/plugins/maps/public/connected_components/mb_map/features_tooltip/feature_properties.test.tsx +++ b/x-pack/plugins/maps/public/connected_components/mb_map/tooltip_control/features_tooltip/feature_properties.test.tsx @@ -8,8 +8,8 @@ import React from 'react'; import { shallow } from 'enzyme'; import { FeatureProperties } from './feature_properties'; -import { ACTION_GLOBAL_APPLY_FILTER } from '../../../../../../../src/plugins/data/public'; -import { ITooltipProperty } from '../../../classes/tooltips/tooltip_property'; +import { ACTION_GLOBAL_APPLY_FILTER } from '../../../../../../../../src/plugins/data/public'; +import { ITooltipProperty } from '../../../../classes/tooltips/tooltip_property'; import { ActionExecutionContext, Action } from 'src/plugins/ui_actions/public'; class MockTooltipProperty { diff --git a/x-pack/plugins/maps/public/connected_components/mb_map/features_tooltip/feature_properties.tsx b/x-pack/plugins/maps/public/connected_components/mb_map/tooltip_control/features_tooltip/feature_properties.tsx similarity index 97% rename from x-pack/plugins/maps/public/connected_components/mb_map/features_tooltip/feature_properties.tsx rename to x-pack/plugins/maps/public/connected_components/mb_map/tooltip_control/features_tooltip/feature_properties.tsx index d221d4d5b1ca5..92f8a5dd17382 100644 --- a/x-pack/plugins/maps/public/connected_components/mb_map/features_tooltip/feature_properties.tsx +++ b/x-pack/plugins/maps/public/connected_components/mb_map/tooltip_control/features_tooltip/feature_properties.tsx @@ -18,10 +18,10 @@ import { i18n } from '@kbn/i18n'; import { ActionExecutionContext, Action } from 'src/plugins/ui_actions/public'; import { GeoJsonProperties } from 'geojson'; import { Filter } from 'src/plugins/data/public'; -import { ACTION_GLOBAL_APPLY_FILTER } from '../../../../../../../src/plugins/data/public'; -import { isUrlDrilldown } from '../../../trigger_actions/trigger_utils'; -import { RawValue } from '../../../../common/constants'; -import { ITooltipProperty } from '../../../classes/tooltips/tooltip_property'; +import { ACTION_GLOBAL_APPLY_FILTER } from '../../../../../../../../src/plugins/data/public'; +import { isUrlDrilldown } from '../../../../trigger_actions/trigger_utils'; +import { RawValue } from '../../../../../common/constants'; +import { ITooltipProperty } from '../../../../classes/tooltips/tooltip_property'; interface Props { featureId?: string | number; diff --git a/x-pack/plugins/maps/public/connected_components/mb_map/features_tooltip/features_tooltip.tsx b/x-pack/plugins/maps/public/connected_components/mb_map/tooltip_control/features_tooltip/features_tooltip.tsx similarity index 92% rename from x-pack/plugins/maps/public/connected_components/mb_map/features_tooltip/features_tooltip.tsx rename to x-pack/plugins/maps/public/connected_components/mb_map/tooltip_control/features_tooltip/features_tooltip.tsx index f85b1c5de3619..c0f792f626989 100644 --- a/x-pack/plugins/maps/public/connected_components/mb_map/features_tooltip/features_tooltip.tsx +++ b/x-pack/plugins/maps/public/connected_components/mb_map/tooltip_control/features_tooltip/features_tooltip.tsx @@ -9,15 +9,15 @@ import React, { Component, Fragment, ReactNode } from 'react'; import { EuiIcon, EuiLink } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { ActionExecutionContext, Action } from 'src/plugins/ui_actions/public'; -import { GeoJsonProperties, Geometry } from 'geojson'; +import { GeoJsonProperties } from 'geojson'; import { Filter } from 'src/plugins/data/public'; import { FeatureProperties } from './feature_properties'; -import { RawValue } from '../../../../common/constants'; +import { RawValue } from '../../../../../common/constants'; import { Footer } from './footer'; import { Header } from './header'; -import { GEOMETRY_FILTER_ACTION, TooltipFeature } from '../../../../common/descriptor_types'; -import { ITooltipProperty } from '../../../classes/tooltips/tooltip_property'; -import { ILayer } from '../../../classes/layers/layer'; +import { GEOMETRY_FILTER_ACTION, TooltipFeature } from '../../../../../common/descriptor_types'; +import { ITooltipProperty } from '../../../../classes/tooltips/tooltip_property'; +import { IVectorLayer } from '../../../../classes/layers/vector_layer'; const PROPERTIES_VIEW = 'PROPERTIES_VIEW'; const FILTER_ACTIONS_VIEW = 'FILTER_ACTIONS_VIEW'; @@ -41,15 +41,8 @@ interface Props { featureId?: string | number; mbProperties: GeoJsonProperties; }) => Promise; - loadFeatureGeometry: ({ - layerId, - featureId, - }: { - layerId: string; - featureId?: string | number; - }) => Geometry | null; getLayerName: (layerId: string) => Promise; - findLayerById: (layerId: string) => ILayer | undefined; + findLayerById: (layerId: string) => IVectorLayer | undefined; } interface State { diff --git a/x-pack/plugins/maps/public/connected_components/mb_map/features_tooltip/footer.test.tsx b/x-pack/plugins/maps/public/connected_components/mb_map/tooltip_control/features_tooltip/footer.test.tsx similarity index 97% rename from x-pack/plugins/maps/public/connected_components/mb_map/features_tooltip/footer.test.tsx rename to x-pack/plugins/maps/public/connected_components/mb_map/tooltip_control/features_tooltip/footer.test.tsx index 96ecba4fa0243..15702096817dd 100644 --- a/x-pack/plugins/maps/public/connected_components/mb_map/features_tooltip/footer.test.tsx +++ b/x-pack/plugins/maps/public/connected_components/mb_map/tooltip_control/features_tooltip/footer.test.tsx @@ -8,7 +8,7 @@ import React from 'react'; import { shallow } from 'enzyme'; import { Footer } from './footer'; -import { ILayer } from '../../../classes/layers/layer'; +import { IVectorLayer } from '../../../../classes/layers/vector_layer'; const defaultProps = { isLocked: false, @@ -20,7 +20,7 @@ const defaultProps = { getId() { return id; }, - } as unknown) as ILayer; + } as unknown) as IVectorLayer; }, setCurrentFeature: () => {}, }; diff --git a/x-pack/plugins/maps/public/connected_components/mb_map/features_tooltip/footer.tsx b/x-pack/plugins/maps/public/connected_components/mb_map/tooltip_control/features_tooltip/footer.tsx similarity index 95% rename from x-pack/plugins/maps/public/connected_components/mb_map/features_tooltip/footer.tsx rename to x-pack/plugins/maps/public/connected_components/mb_map/tooltip_control/features_tooltip/footer.tsx index 3ad19a7901b09..7eff2f303d3ed 100644 --- a/x-pack/plugins/maps/public/connected_components/mb_map/features_tooltip/footer.tsx +++ b/x-pack/plugins/maps/public/connected_components/mb_map/tooltip_control/features_tooltip/footer.tsx @@ -18,8 +18,8 @@ import { } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; -import { TooltipFeature } from '../../../../common/descriptor_types'; -import { ILayer } from '../../../classes/layers/layer'; +import { TooltipFeature } from '../../../../../common/descriptor_types'; +import { IVectorLayer } from '../../../../classes/layers/vector_layer'; const ALL_LAYERS = '_ALL_LAYERS_'; const DEFAULT_PAGE_NUMBER = 0; @@ -27,7 +27,7 @@ const DEFAULT_PAGE_NUMBER = 0; interface Props { features: TooltipFeature[]; isLocked: boolean; - findLayerById: (layerId: string) => ILayer | undefined; + findLayerById: (layerId: string) => IVectorLayer | undefined; setCurrentFeature: (feature: TooltipFeature) => void; } @@ -78,7 +78,7 @@ export class Footer extends Component { countByLayerId.set(this.props.features[i].layerId, count); } - const layers: ILayer[] = []; + const layers: IVectorLayer[] = []; countByLayerId.forEach((count, layerId) => { const layer = this.props.findLayerById(layerId); if (layer) { diff --git a/x-pack/plugins/maps/public/connected_components/mb_map/features_tooltip/header.test.tsx b/x-pack/plugins/maps/public/connected_components/mb_map/tooltip_control/features_tooltip/header.test.tsx similarity index 93% rename from x-pack/plugins/maps/public/connected_components/mb_map/features_tooltip/header.test.tsx rename to x-pack/plugins/maps/public/connected_components/mb_map/tooltip_control/features_tooltip/header.test.tsx index a52ee48d38b97..8a8bbeb1b7db6 100644 --- a/x-pack/plugins/maps/public/connected_components/mb_map/features_tooltip/header.test.tsx +++ b/x-pack/plugins/maps/public/connected_components/mb_map/tooltip_control/features_tooltip/header.test.tsx @@ -8,7 +8,7 @@ import React from 'react'; import { shallow } from 'enzyme'; import { Header } from './header'; -import { ILayer } from '../../../classes/layers/layer'; +import { IVectorLayer } from '../../../../classes/layers/vector_layer'; const layerMock = ({ getDisplayName: async () => { @@ -19,7 +19,7 @@ const layerMock = ({ icon: mockIcon, }; }, -} as unknown) as ILayer; +} as unknown) as IVectorLayer; const defaultProps = { findLayerById: (layerId: string) => { diff --git a/x-pack/plugins/maps/public/connected_components/mb_map/features_tooltip/header.tsx b/x-pack/plugins/maps/public/connected_components/mb_map/tooltip_control/features_tooltip/header.tsx similarity index 95% rename from x-pack/plugins/maps/public/connected_components/mb_map/features_tooltip/header.tsx rename to x-pack/plugins/maps/public/connected_components/mb_map/tooltip_control/features_tooltip/header.tsx index 4fe9c3b4e8550..0ac0f57b259a2 100644 --- a/x-pack/plugins/maps/public/connected_components/mb_map/features_tooltip/header.tsx +++ b/x-pack/plugins/maps/public/connected_components/mb_map/tooltip_control/features_tooltip/header.tsx @@ -14,10 +14,10 @@ import { EuiFlexItem, EuiTextColor, } from '@elastic/eui'; -import { ILayer } from '../../../classes/layers/layer'; +import { IVectorLayer } from '../../../../classes/layers/vector_layer'; interface Props { - findLayerById: (layerId: string) => ILayer | undefined; + findLayerById: (layerId: string) => IVectorLayer | undefined; isLocked: boolean; layerId: string; onClose: () => void; diff --git a/x-pack/plugins/maps/public/connected_components/mb_map/features_tooltip/index.ts b/x-pack/plugins/maps/public/connected_components/mb_map/tooltip_control/features_tooltip/index.ts similarity index 100% rename from x-pack/plugins/maps/public/connected_components/mb_map/features_tooltip/index.ts rename to x-pack/plugins/maps/public/connected_components/mb_map/tooltip_control/features_tooltip/index.ts diff --git a/x-pack/plugins/maps/public/connected_components/mb_map/tooltip_control/index.js b/x-pack/plugins/maps/public/connected_components/mb_map/tooltip_control/index.ts similarity index 71% rename from x-pack/plugins/maps/public/connected_components/mb_map/tooltip_control/index.js rename to x-pack/plugins/maps/public/connected_components/mb_map/tooltip_control/index.ts index 7c40405839594..28510815d1a2e 100644 --- a/x-pack/plugins/maps/public/connected_components/mb_map/tooltip_control/index.js +++ b/x-pack/plugins/maps/public/connected_components/mb_map/tooltip_control/index.ts @@ -5,7 +5,10 @@ * 2.0. */ +import { AnyAction } from 'redux'; +import { ThunkDispatch } from 'redux-thunk'; import { connect } from 'react-redux'; +import { TooltipState } from '../../../../common/descriptor_types'; import { TooltipControl } from './tooltip_control'; import { closeOnClickTooltip, @@ -19,8 +22,9 @@ import { getHasLockedTooltips, isDrawingFilter, } from '../../../selectors/map_selectors'; +import { MapStoreState } from '../../../reducers/store'; -function mapStateToProps(state = {}) { +function mapStateToProps(state: MapStoreState) { return { layerList: getLayerList(state), hasLockedTooltips: getHasLockedTooltips(state), @@ -29,18 +33,18 @@ function mapStateToProps(state = {}) { }; } -function mapDispatchToProps(dispatch) { +function mapDispatchToProps(dispatch: ThunkDispatch) { return { - closeOnClickTooltip(tooltipId) { + closeOnClickTooltip(tooltipId: string) { dispatch(closeOnClickTooltip(tooltipId)); }, - openOnClickTooltip(tooltipState) { + openOnClickTooltip(tooltipState: TooltipState) { dispatch(openOnClickTooltip(tooltipState)); }, closeOnHoverTooltip() { dispatch(closeOnHoverTooltip()); }, - openOnHoverTooltip(tooltipState) { + openOnHoverTooltip(tooltipState: TooltipState) { dispatch(openOnHoverTooltip(tooltipState)); }, }; diff --git a/x-pack/plugins/maps/public/connected_components/mb_map/tooltip_control/tooltip_control.test.js b/x-pack/plugins/maps/public/connected_components/mb_map/tooltip_control/tooltip_control.test.tsx similarity index 87% rename from x-pack/plugins/maps/public/connected_components/mb_map/tooltip_control/tooltip_control.test.js rename to x-pack/plugins/maps/public/connected_components/mb_map/tooltip_control/tooltip_control.test.tsx index e33d83e2837fe..451150fabb064 100644 --- a/x-pack/plugins/maps/public/connected_components/mb_map/tooltip_control/tooltip_control.test.js +++ b/x-pack/plugins/maps/public/connected_components/mb_map/tooltip_control/tooltip_control.test.tsx @@ -14,14 +14,16 @@ jest.mock('./tooltip_popover', () => ({ import sinon from 'sinon'; import React from 'react'; import { mount, shallow } from 'enzyme'; +import { Map as MbMap, MapMouseEvent, MapboxGeoJSONFeature } from 'mapbox-gl'; import { TooltipControl } from './tooltip_control'; +import { IVectorLayer } from '../../../classes/layers/vector_layer'; // mutable map state -let featuresAtLocation; +let featuresAtLocation: MapboxGeoJSONFeature[] = []; const layerId = 'tfi3f'; const mbLayerId = 'tfi3f_circle'; -const mockLayer = { +const mockLayer = ({ getMbLayerIds: () => { return [mbLayerId]; }, @@ -50,21 +52,21 @@ const mockLayer = { }, }; }, -}; +} as unknown) as IVectorLayer; -const mockMbMapHandlers = {}; -const mockMBMap = { - on: (eventName, callback) => { +const mockMbMapHandlers: { [key: string]: (event?: MapMouseEvent) => void } = {}; +const mockMBMap = ({ + on: (eventName: string, callback: (event?: MapMouseEvent) => void) => { mockMbMapHandlers[eventName] = callback; }, - off: (eventName) => { + off: (eventName: string) => { delete mockMbMapHandlers[eventName]; }, getLayer: () => {}, queryRenderedFeatures: () => { return featuresAtLocation; }, -}; +} as unknown) as MbMap; const defaultProps = { mbMap: mockMBMap, @@ -74,8 +76,8 @@ const defaultProps = { openOnHoverTooltip: () => {}, layerList: [mockLayer], isDrawingFilter: false, - addFilters: () => {}, - geoFields: [{}], + addFilters: async () => {}, + geoFields: [], openTooltips: [], hasLockedTooltips: false, }; @@ -83,12 +85,13 @@ const defaultProps = { const hoverTooltipState = { id: '1', isLocked: false, - location: [-120, 30], + location: [-120, 30] as [number, number], features: [ { id: 1, - layerId: layerId, - geometry: {}, + layerId, + mbProperties: {}, + actions: [], }, ], }; @@ -96,12 +99,13 @@ const hoverTooltipState = { const lockedTooltipState = { id: '2', isLocked: true, - location: [-120, 30], + location: [-120, 30] as [number, number], features: [ { id: 1, - layerId: layerId, - geometry: {}, + layerId, + mbProperties: {}, + actions: [], }, ], }; @@ -186,10 +190,10 @@ describe('TooltipControl', () => { }); describe('on click', () => { - const mockMapMouseEvent = { + const mockMapMouseEvent = ({ point: { x: 0, y: 0 }, lngLat: { lng: 0, lat: 0 }, - }; + } as unknown) as MapMouseEvent; const openOnClickTooltipStub = sinon.stub(); const closeOnClickTooltipStub = sinon.stub(); @@ -231,7 +235,7 @@ describe('TooltipControl', () => { }); test('should set tooltip state when there are features at clicked location and remove duplicate features', () => { - const feature = { + const feature = ({ geometry: { type: 'Point', coordinates: [100, 30], @@ -242,7 +246,7 @@ describe('TooltipControl', () => { properties: { __kbn__feature_id__: 1, }, - }; + } as unknown) as MapboxGeoJSONFeature; featuresAtLocation = [feature, feature]; mount( Promise) | null; + closeOnClickTooltip: (tooltipId: string) => void; + closeOnHoverTooltip: () => void; + getActionContext?: () => ActionExecutionContext; + getFilterActions?: () => Promise; + geoFields: GeoFieldWithIndex[]; + hasLockedTooltips: boolean; + isDrawingFilter: boolean; + layerList: ILayer[]; + mbMap: MbMap; + openOnClickTooltip: (tooltipState: TooltipState) => void; + openOnHoverTooltip: (tooltipState: TooltipState) => void; + onSingleValueTrigger?: (actionId: string, key: string, value: RawValue) => void; + openTooltips: TooltipState[]; + renderTooltipContent?: RenderToolTipContent; +} + +export class TooltipControl extends Component { componentDidMount() { this.props.mbMap.on('mouseout', this._onMouseout); this.props.mbMap.on('mousemove', this._updateHoverTooltipState); @@ -57,15 +102,21 @@ export class TooltipControl extends React.Component { } }; - _findLayerById = (layerId) => { + _findLayerById = (layerId: string) => { return this.props.layerList.find((layer) => { - return layer.getId() === layerId; - }); + return layer.getId() === layerId && isVectorLayer(layer); + }) as IVectorLayer; }; // Must load original geometry instead of using geometry from mapbox feature. // Mapbox feature geometry is from vector tile and is not the same as the original geometry. - _getFeatureGeometry = ({ layerId, featureId }) => { + _getFeatureGeometry = ({ + layerId, + featureId, + }: { + layerId: string; + featureId?: string | number; + }): Geometry | null => { const tooltipLayer = this._findLayerById(layerId); if (!tooltipLayer || featureId === undefined) { return null; @@ -79,14 +130,14 @@ export class TooltipControl extends React.Component { return targetFeature.geometry; }; - _getLayerByMbLayerId(mbLayerId) { + _getLayerByMbLayerId(mbLayerId: string): IVectorLayer | undefined { return this.props.layerList.find((layer) => { const mbLayerIds = layer.getMbLayerIds(); - return mbLayerIds.indexOf(mbLayerId) > -1; - }); + return isVectorLayer(layer) && mbLayerIds.indexOf(mbLayerId) > -1; + }) as IVectorLayer; } - _loadPreIndexedShape = async ({ layerId, featureId }) => { + _loadPreIndexedShape = async ({ layerId, featureId }: { layerId: string; featureId: string }) => { const tooltipLayer = this._findLayerById(layerId); if (!tooltipLayer || typeof featureId === 'undefined') { return null; @@ -100,17 +151,25 @@ export class TooltipControl extends React.Component { return await tooltipLayer.getSource().getPreIndexedShape(targetFeature.properties); }; - _getFeatureActions({ layerId, featureId, tooltipId }) { + _getFeatureActions({ + layerId, + featureId, + tooltipId, + }: { + layerId: string; + featureId: string; + tooltipId: string; + }): TooltipFeatureAction[] { const actions = []; const geometry = this._getFeatureGeometry({ layerId, featureId }); const geoFieldsForFeature = this._filterGeoFieldsByFeatureGeometry(geometry); - if (geoFieldsForFeature.length && this.props.addFilters) { + if (geometry && geoFieldsForFeature.length && this.props.addFilters) { actions.push({ label: i18n.translate('xpack.maps.tooltip.action.filterByGeometryLabel', { defaultMessage: 'Filter by geometry', }), - id: GEOMETRY_FILTER_ACTION, + id: GEOMETRY_FILTER_ACTION as typeof GEOMETRY_FILTER_ACTION, form: ( { @@ -132,7 +191,7 @@ export class TooltipControl extends React.Component { return actions; } - _filterGeoFieldsByFeatureGeometry(geometry) { + _filterGeoFieldsByFeatureGeometry(geometry: Geometry | null) { if (!geometry) { return []; } @@ -155,15 +214,22 @@ export class TooltipControl extends React.Component { return this.props.geoFields; } - _getTooltipFeatures(mbFeatures, isLocked, tooltipId) { - const uniqueFeatures = []; - //there may be duplicates in the results from mapbox - //this is because mapbox returns the results per tile - //for polygons or lines, it might return multiple features, one for each tile + _getTooltipFeatures( + mbFeatures: MapboxGeoJSONFeature[], + isLocked: boolean, + tooltipId: string + ): TooltipFeature[] { + const uniqueFeatures: TooltipFeature[] = []; + // there may be duplicates in the results from mapbox + // this is because mapbox returns the results per tile + // for polygons or lines, it might return multiple features, one for each tile for (let i = 0; i < mbFeatures.length; i++) { const mbFeature = mbFeatures[i]; const layer = this._getLayerByMbLayerId(mbFeature.layer.id); - const featureId = mbFeature.properties[FEATURE_ID_PROPERTY_NAME]; + if (!layer) { + break; + } + const featureId = mbFeature.properties?.[FEATURE_ID_PROPERTY_NAME]; const layerId = layer.getId(); let match = false; for (let j = 0; j < uniqueFeatures.length; j++) { @@ -181,14 +247,16 @@ export class TooltipControl extends React.Component { // - As empty object literal // To avoid ambiguity, normalize properties to empty object literal. const mbProperties = mbFeature.properties ? mbFeature.properties : {}; - const actions = isLocked ? this._getFeatureActions({ layerId, featureId, tooltipId }) : []; + const actions: TooltipFeatureAction[] = isLocked + ? this._getFeatureActions({ layerId, featureId, tooltipId }) + : []; const hasActions = isLocked && actions.length; if (hasActions || layer.canShowTooltip()) { - //This keeps track of first feature (assuming these will be identical for features in different tiles) + // This keeps track of first feature (assuming these will be identical for features in different tiles) uniqueFeatures.push({ id: featureId, - layerId: layerId, + layerId, mbProperties, actions, }); @@ -198,13 +266,13 @@ export class TooltipControl extends React.Component { return uniqueFeatures; } - _lockTooltip = (e) => { + _lockTooltip = (e: MapMouseEvent) => { if (this.props.isDrawingFilter) { // ignore click events when in draw mode return; } - this._updateHoverTooltipState.cancel(); //ignore any possible moves + this._updateHoverTooltipState.cancel(); // ignore any possible moves const mbFeatures = this._getMbFeaturesUnderPointer(e.point); if (!mbFeatures.length) { @@ -229,7 +297,7 @@ export class TooltipControl extends React.Component { }); }; - _updateHoverTooltipState = _.debounce((e) => { + _updateHoverTooltipState = _.debounce((e: MapMouseEvent) => { if (this.props.isDrawingFilter || this.props.hasLockedTooltips) { // ignore hover events when in draw mode or when there are locked tooltips return; @@ -244,7 +312,7 @@ export class TooltipControl extends React.Component { const targetMbFeature = mbFeatures[0]; if (this.props.openTooltips[0] && this.props.openTooltips[0].features.length) { const firstFeature = this.props.openTooltips[0].features[0]; - if (targetMbFeature.properties[FEATURE_ID_PROPERTY_NAME] === firstFeature.id) { + if (targetMbFeature.properties?.[FEATURE_ID_PROPERTY_NAME] === firstFeature.id) { // ignore hover events when hover tooltip is all ready opened for feature return; } @@ -258,7 +326,7 @@ export class TooltipControl extends React.Component { return; } this.props.openOnHoverTooltip({ - features: features, + features, location: popupAnchorLocation, isLocked, id: tooltipId, @@ -266,31 +334,33 @@ export class TooltipControl extends React.Component { }, 100); _getMbLayerIdsForTooltips() { - const mbLayerIds = this.props.layerList.reduce((mbLayerIds, layer) => { - // tooltips are only supported for vector layers, filter out all other layer types - const isVectorLayer = layer.canShowTooltip !== undefined; - return layer.isVisible() && isVectorLayer - ? mbLayerIds.concat(layer.getMbLayerIds()) - : mbLayerIds; - }, []); - - //Ensure that all layers are actually on the map. - //The raw list may contain layer-ids that have not been added to the map yet. - //For example: - //a vector or heatmap layer will not add a source and layer to the mapbox-map, until that data is available. - //during that data-fetch window, the app should not query for layers that do not exist. + const mbLayerIds: string[] = this.props.layerList.reduce( + (accumulator: string[], layer: ILayer) => { + // tooltips are only supported for vector layers, filter out all other layer types + return layer.isVisible() && isVectorLayer(layer) + ? accumulator.concat(layer.getMbLayerIds()) + : accumulator; + }, + [] + ); + + // Ensure that all layers are actually on the map. + // The raw list may contain layer-ids that have not been added to the map yet. + // For example: + // a vector or heatmap layer will not add a source and layer to the mapbox-map, until that data is available. + // during that data-fetch window, the app should not query for layers that do not exist. return mbLayerIds.filter((mbLayerId) => { return !!this.props.mbMap.getLayer(mbLayerId); }); } - _getMbFeaturesUnderPointer(mbLngLatPoint) { + _getMbFeaturesUnderPointer(mbLngLatPoint: MbPoint) { if (!this.props.mbMap) { return []; } const mbLayerIds = this._getMbLayerIdsForTooltips(); - const PADDING = 2; //in pixels + const PADDING = 2; // in pixels const mbBbox = [ { x: mbLngLatPoint.x - PADDING, @@ -300,7 +370,7 @@ export class TooltipControl extends React.Component { x: mbLngLatPoint.x + PADDING, y: mbLngLatPoint.y + PADDING, }, - ]; + ] as [MbPoint, MbPoint]; return this.props.mbMap.queryRenderedFeatures(mbBbox, { layers: mbLayerIds, filter: EXCLUDE_TOO_MANY_FEATURES_BOX, @@ -333,6 +403,7 @@ export class TooltipControl extends React.Component { closeTooltip={closeTooltip} isLocked={isLocked} index={index} + loadFeatureGeometry={this._getFeatureGeometry} /> ); }); diff --git a/x-pack/plugins/maps/public/connected_components/mb_map/tooltip_control/tooltip_popover.test.js b/x-pack/plugins/maps/public/connected_components/mb_map/tooltip_control/tooltip_popover.test.tsx similarity index 81% rename from x-pack/plugins/maps/public/connected_components/mb_map/tooltip_control/tooltip_popover.test.js rename to x-pack/plugins/maps/public/connected_components/mb_map/tooltip_control/tooltip_popover.test.tsx index cb90d1f50bcd5..22223df366011 100644 --- a/x-pack/plugins/maps/public/connected_components/mb_map/tooltip_control/tooltip_popover.test.js +++ b/x-pack/plugins/maps/public/connected_components/mb_map/tooltip_control/tooltip_popover.test.tsx @@ -5,7 +5,7 @@ * 2.0. */ -jest.mock('../features_tooltip/features_tooltip', () => ({ +jest.mock('./features_tooltip/features_tooltip', () => ({ FeaturesTooltip: () => { return
mockFeaturesTooltip
; }, @@ -14,17 +14,24 @@ jest.mock('../features_tooltip/features_tooltip', () => ({ import sinon from 'sinon'; import React from 'react'; import { mount, shallow } from 'enzyme'; +import { Map as MbMap } from 'mapbox-gl'; import { TooltipPopover } from './tooltip_popover'; // mutable map state -let mapCenter; -let mockMbMapBounds; +let mapCenter = [0, 0]; + +const mockMbMapBounds = { + west: -180, + east: 180, + north: 90, + south: -90, +}; const layerId = 'tfi3f'; -const mockMbMapHandlers = {}; -const mockMBMap = { - project: (lonLatArray) => { +const mockMbMapHandlers: { [key: string]: () => void } = {}; +const mockMBMap = ({ + project: (lonLatArray: [number, number]) => { const lonDistanceFromCenter = Math.abs(lonLatArray[0] - mapCenter[0]); const latDistanceFromCenter = Math.abs(lonLatArray[1] - mapCenter[1]); return { @@ -32,10 +39,10 @@ const mockMBMap = { y: latDistanceFromCenter * 100, }; }, - on: (eventName, callback) => { + on: (eventName: string, callback: () => void) => { mockMbMapHandlers[eventName] = callback; }, - off: (eventName) => { + off: (eventName: string) => { delete mockMbMapHandlers[eventName]; }, getBounds: () => { @@ -54,35 +61,34 @@ const mockMBMap = { }, }; }, -}; +} as unknown) as MbMap; const defaultProps = { mbMap: mockMBMap, closeTooltip: () => {}, - layerList: [], - isDrawingFilter: false, - addFilters: () => {}, - geoFields: [{}], - location: [-120, 30], + addFilters: async () => {}, + location: [-120, 30] as [number, number], features: [ { id: 1, - layerId: layerId, - geometry: {}, + layerId, + mbProperties: {}, + actions: [], }, ], isLocked: false, + findLayerById: () => { + return undefined; + }, + index: 0, + loadFeatureGeometry: () => { + return null; + }, }; describe('TooltipPopover', () => { beforeEach(() => { mapCenter = [0, 0]; - mockMbMapBounds = { - west: -180, - east: 180, - north: 90, - south: -90, - }; }); describe('render', () => { diff --git a/x-pack/plugins/maps/public/connected_components/mb_map/tooltip_control/tooltip_popover.js b/x-pack/plugins/maps/public/connected_components/mb_map/tooltip_control/tooltip_popover.tsx similarity index 63% rename from x-pack/plugins/maps/public/connected_components/mb_map/tooltip_control/tooltip_popover.js rename to x-pack/plugins/maps/public/connected_components/mb_map/tooltip_control/tooltip_popover.tsx index 58084a498d7fb..a3fcc0ea6a07a 100644 --- a/x-pack/plugins/maps/public/connected_components/mb_map/tooltip_control/tooltip_popover.js +++ b/x-pack/plugins/maps/public/connected_components/mb_map/tooltip_control/tooltip_popover.tsx @@ -5,25 +5,55 @@ * 2.0. */ -import React, { Component } from 'react'; -import { LAT_INDEX, LON_INDEX } from '../../../../common/constants'; -import { FeaturesTooltip } from '../features_tooltip'; +import React, { Component, RefObject } from 'react'; import { EuiPopover, EuiText } from '@elastic/eui'; +import { Map as MbMap } from 'mapbox-gl'; +import { GeoJsonProperties, Geometry } from 'geojson'; +import { Filter } from 'src/plugins/data/public'; +import { ActionExecutionContext, Action } from 'src/plugins/ui_actions/public'; +import { FeaturesTooltip } from './features_tooltip'; +import { LAT_INDEX, LON_INDEX, RawValue } from '../../../../common/constants'; +import { IVectorLayer } from '../../../classes/layers/vector_layer'; +import { TooltipFeature } from '../../../../common/descriptor_types'; +import { RenderToolTipContent } from '../../../classes/tooltips/tooltip_property'; const noop = () => {}; -export class TooltipPopover extends Component { - state = { - x: undefined, - y: undefined, +interface Props { + addFilters: ((filters: Filter[], actionId: string) => Promise) | null; + closeTooltip: () => void; + features: TooltipFeature[]; + findLayerById: (layerId: string) => IVectorLayer | undefined; + getActionContext?: () => ActionExecutionContext; + getFilterActions?: () => Promise; + index: number; + isLocked: boolean; + loadFeatureGeometry: ({ + layerId, + featureId, + }: { + layerId: string; + featureId?: string | number; + }) => Geometry | null; + location: [number, number]; + mbMap: MbMap; + onSingleValueTrigger?: (actionId: string, key: string, value: RawValue) => void; + renderTooltipContent?: RenderToolTipContent; +} + +interface State { + x?: number; + y?: number; + isVisible: boolean; +} + +export class TooltipPopover extends Component { + private readonly _popoverRef: RefObject = React.createRef(); + + state: State = { isVisible: true, }; - constructor(props) { - super(props); - this._popoverRef = React.createRef(); - } - componentDidMount() { this._updatePopoverPosition(); this.props.mbMap.on('move', this._updatePopoverPosition); @@ -55,7 +85,15 @@ export class TooltipPopover extends Component { }); }; - _loadFeatureProperties = async ({ layerId, featureId, mbProperties }) => { + _loadFeatureProperties = async ({ + layerId, + featureId, + mbProperties, + }: { + layerId: string; + featureId?: string | number; + mbProperties?: GeoJsonProperties; + }) => { const tooltipLayer = this.props.findLayerById(layerId); if (!tooltipLayer) { return []; @@ -67,10 +105,10 @@ export class TooltipPopover extends Component { } const properties = targetFeature ? targetFeature.properties : mbProperties; - return await tooltipLayer.getPropertiesForTooltip(properties); + return await tooltipLayer.getPropertiesForTooltip(properties ? properties : {}); }; - _getLayerName = async (layerId) => { + _getLayerName = async (layerId: string) => { const layer = this.props.findLayerById(layerId); if (!layer) { return null; @@ -89,6 +127,7 @@ export class TooltipPopover extends Component { features: this.props.features, isLocked: this.props.isLocked, loadFeatureProperties: this._loadFeatureProperties, + loadFeatureGeometry: this.props.loadFeatureGeometry, getLayerName: this._getLayerName, }; @@ -104,7 +143,7 @@ export class TooltipPopover extends Component { }; render() { - if (!this.state.isVisible) { + if (!this.state.isVisible || this.state.x === undefined || this.state.y === undefined) { return null; } diff --git a/x-pack/plugins/security_solution/public/network/components/embeddables/map_tool_tip/map_tool_tip.tsx b/x-pack/plugins/security_solution/public/network/components/embeddables/map_tool_tip/map_tool_tip.tsx index d34fd7f068b7c..9d8a1455ba99f 100644 --- a/x-pack/plugins/security_solution/public/network/components/embeddables/map_tool_tip/map_tool_tip.tsx +++ b/x-pack/plugins/security_solution/public/network/components/embeddables/map_tool_tip/map_tool_tip.tsx @@ -12,7 +12,8 @@ import { EuiLoadingSpinner, EuiOutsideClickDetector, } from '@elastic/eui'; -import { FeatureGeometry, MapToolTipProps } from '../types'; +import { Geometry } from 'geojson'; +import { MapToolTipProps } from '../types'; import { ToolTipFooter } from './tooltip_footer'; import { LineToolTipContent } from './line_tool_tip_content'; import { PointToolTipContent } from './point_tool_tip_content'; @@ -33,7 +34,7 @@ export const MapToolTipComponent = ({ const [isError, setIsError] = useState(false); const [featureIndex, setFeatureIndex] = useState(0); const [featureProps, setFeatureProps] = useState([]); - const [featureGeometry, setFeatureGeometry] = useState(null); + const [featureGeometry, setFeatureGeometry] = useState(null); const [, setLayerName] = useState(''); const handleCloseTooltip = useCallback(() => { @@ -133,13 +134,15 @@ export const MapToolTipComponent = ({ try { const featureGeo = loadFeatureGeometry({ layerId, featureId }); const [featureProperties, layerNameString] = await Promise.all([ - loadFeatureProperties({ layerId, featureId }), + loadFeatureProperties({ layerId, featureId, mbProperties: {} }), getLayerName(layerId), ]); setFeatureProps(featureProperties); setFeatureGeometry(featureGeo); - setLayerName(layerNameString); + if (layerNameString) { + setLayerName(layerNameString); + } } catch (e) { setIsError(true); } finally {