From 49a5d5ecd0504c93b82ff2bd1ab445d443a8a9ea Mon Sep 17 00:00:00 2001 From: Nick Peihl Date: Thu, 9 May 2024 15:20:50 -0400 Subject: [PATCH] Replace legacy MapEmbeddable with MapComponent in Obs UX solution (#182841) ## Summary Replaces the Maps embeddable with a new MapComponent in the Observability UX solution. The Maps plugin now provides an easier to use MapComponent for consumers. The legacy MapEmbeddable factory is also being removed as part of https://github.com/elastic/kibana/issues/174960 which requires making changes to consumers. ### For maintainers - [ ] This was checked for breaking API changes and was [labeled appropriately](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process) --- .../maps/public/embeddable/map_component.tsx | 6 + .../embedded_map.test.tsx | 15 +-- .../visitor_breakdown_map/embedded_map.tsx | 123 ++++-------------- 3 files changed, 35 insertions(+), 109 deletions(-) diff --git a/x-pack/plugins/maps/public/embeddable/map_component.tsx b/x-pack/plugins/maps/public/embeddable/map_component.tsx index a9f3fe4afbc0b..a6590703a547b 100644 --- a/x-pack/plugins/maps/public/embeddable/map_component.tsx +++ b/x-pack/plugins/maps/public/embeddable/map_component.tsx @@ -13,6 +13,7 @@ import { ViewMode } from '@kbn/embeddable-plugin/public'; import type { LayerDescriptor, MapCenterAndZoom, MapSettings } from '../../common/descriptor_types'; import { MapEmbeddable } from './map_embeddable'; import { createBasemapLayerDescriptor } from '../classes/layers/create_basemap_layer_descriptor'; +import { RenderToolTipContent } from '../classes/tooltips/tooltip_property'; export interface Props { title?: string; @@ -25,6 +26,7 @@ export interface Props { isLayerTOCOpen?: boolean; mapCenter?: MapCenterAndZoom; onInitialRenderComplete?: () => void; + getTooltipRenderer?: () => RenderToolTipContent; /* * Set to false to exclude sharing attributes 'data-*'. */ @@ -65,6 +67,10 @@ export class MapComponent extends Component { timeRange: this.props.timeRange, }); + if (this.props.getTooltipRenderer) { + this._mapEmbeddable.setRenderTooltipContent(this.props.getTooltipRenderer()); + } + if (this.props.onInitialRenderComplete) { this._mapEmbeddable .getOnRenderComplete$() diff --git a/x-pack/plugins/observability_solution/ux/public/components/app/rum_dashboard/visitor_breakdown_map/embedded_map.test.tsx b/x-pack/plugins/observability_solution/ux/public/components/app/rum_dashboard/visitor_breakdown_map/embedded_map.test.tsx index b2ba69ff8bc94..77b05fa7170b0 100644 --- a/x-pack/plugins/observability_solution/ux/public/components/app/rum_dashboard/visitor_breakdown_map/embedded_map.test.tsx +++ b/x-pack/plugins/observability_solution/ux/public/components/app/rum_dashboard/visitor_breakdown_map/embedded_map.test.tsx @@ -10,7 +10,6 @@ import React from 'react'; import { EmbeddedMap } from './embedded_map'; import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public'; -import { embeddablePluginMock } from '@kbn/embeddable-plugin/public/mocks'; describe('Embedded Map', () => { test('it renders', () => { @@ -26,19 +25,13 @@ describe('Embedded Map', () => { }); }); -const mockEmbeddable = embeddablePluginMock.createStartContract(); - -mockEmbeddable.getEmbeddableFactory = jest.fn().mockImplementation(() => ({ - create: () => ({ - reload: jest.fn(), - setRenderTooltipContent: jest.fn(), - setLayerList: jest.fn(), - }), -})); +const mockMapsStartService = { + Map: jest.fn().mockImplementation(() =>
), +}; const mockCore: () => any[] = () => { const core = { - embeddable: mockEmbeddable, + maps: mockMapsStartService, }; return [core]; diff --git a/x-pack/plugins/observability_solution/ux/public/components/app/rum_dashboard/visitor_breakdown_map/embedded_map.tsx b/x-pack/plugins/observability_solution/ux/public/components/app/rum_dashboard/visitor_breakdown_map/embedded_map.tsx index e00f7ff7c7112..cfd68881416af 100644 --- a/x-pack/plugins/observability_solution/ux/public/components/app/rum_dashboard/visitor_breakdown_map/embedded_map.tsx +++ b/x-pack/plugins/observability_solution/ux/public/components/app/rum_dashboard/visitor_breakdown_map/embedded_map.tsx @@ -5,13 +5,9 @@ * 2.0. */ -import React, { useEffect, useState, useRef } from 'react'; -import { v4 as uuidv4 } from 'uuid'; +import React from 'react'; import styled from 'styled-components'; -import { MapEmbeddable, MapEmbeddableInput } from '@kbn/maps-plugin/public'; -import { MAP_SAVED_OBJECT_TYPE } from '@kbn/maps-plugin/common'; -import { ErrorEmbeddable, ViewMode, isErrorEmbeddable } from '@kbn/embeddable-plugin/public'; import type { RenderTooltipContentParams } from '@kbn/maps-plugin/public'; import { useLayerList } from './use_layer_list'; import { useLegacyUrlParams } from '../../../../context/url_params_context/use_url_params'; @@ -38,7 +34,7 @@ const EmbeddedPanel = styled.div` `; export function EmbeddedMapComponent() { - const { rangeId, urlParams } = useLegacyUrlParams(); + const { urlParams } = useLegacyUrlParams(); const { start, end, serviceName } = urlParams; @@ -46,35 +42,7 @@ export function EmbeddedMapComponent() { const layerList = useLayerList(); - const [embeddable, setEmbeddable] = useState(); - - const embeddableRoot: React.RefObject = useRef(null); - - const { embeddable: embeddablePlugin, maps } = useKibanaServices(); - - if (!embeddablePlugin) { - throw new Error('Embeddable start plugin not found'); - } - const factory = embeddablePlugin.getEmbeddableFactory(MAP_SAVED_OBJECT_TYPE); - - const input: MapEmbeddableInput = { - attributes: { title: '' }, - id: uuidv4(), - filters: mapFilters, - viewMode: ViewMode.VIEW, - isLayerTOCOpen: false, - query: { - query: 'transaction.type : "page-load"', - language: 'kuery', - }, - ...(start && { - timeRange: { - from: new Date(start!).toISOString(), - to: new Date(end!).toISOString(), - }, - }), - hideFilterActions: true, - }; + const { maps } = useKibanaServices(); function renderTooltipContent({ addFilters, @@ -95,71 +63,30 @@ export function EmbeddedMapComponent() { return ; } - useEffect(() => { - if (embeddable != null && serviceName) { - embeddable.updateInput({ filters: mapFilters }); - embeddable.reload(); - } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [mapFilters]); - - // DateRange updated useEffect - useEffect(() => { - if (embeddable != null && start != null && end != null) { - const timeRange = { - from: new Date(start).toISOString(), - to: new Date(end).toISOString(), - }; - embeddable.updateInput({ timeRange }); - embeddable.reload(); - } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [start, end, rangeId]); - - useEffect(() => { - async function setupEmbeddable() { - if (!factory) { - throw new Error('Map embeddable not found.'); - } - const embeddableObject: any = await factory.create({ - ...input, - title: 'Visitors by region', - }); - - if (embeddableObject && !isErrorEmbeddable(embeddableObject)) { - embeddableObject.setRenderTooltipContent(renderTooltipContent); - const basemapLayerDescriptor = maps - ? await maps.createLayerDescriptors.createBasemapLayerDescriptor() - : null; - if (basemapLayerDescriptor) { - layerList.unshift(basemapLayerDescriptor); - } - await embeddableObject.setLayerList(layerList); - } - - setEmbeddable(embeddableObject); - } - - setupEmbeddable(); - - // we want this effect to execute exactly once after the component mounts - // eslint-disable-next-line react-hooks/exhaustive-deps - }, []); - - // We can only render after embeddable has already initialized - useEffect(() => { - if (embeddableRoot.current && embeddable && serviceName) { - embeddable.render(embeddableRoot.current); - } - }, [embeddable, embeddableRoot, serviceName]); - return ( -
+
+ {serviceName && + maps && + maps.Map({ + title: 'Visitors by region', + filters: mapFilters, + isLayerTOCOpen: false, + query: { + query: 'transaction.type : "page-load"', + language: 'kuery', + }, + ...(start && { + timeRange: { + from: new Date(start!).toISOString(), + to: new Date(end!).toISOString(), + }, + }), + hideFilterActions: true, + layerList, + getTooltipRenderer: () => renderTooltipContent, + })} +
); }