Skip to content

Commit

Permalink
Replace legacy MapEmbeddable with MapComponent in Obs UX solution (#1…
Browse files Browse the repository at this point in the history
…82841)

## 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 #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)
  • Loading branch information
nickpeihl authored May 9, 2024
1 parent 99e7bd3 commit 49a5d5e
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 109 deletions.
6 changes: 6 additions & 0 deletions x-pack/plugins/maps/public/embeddable/map_component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -25,6 +26,7 @@ export interface Props {
isLayerTOCOpen?: boolean;
mapCenter?: MapCenterAndZoom;
onInitialRenderComplete?: () => void;
getTooltipRenderer?: () => RenderToolTipContent;
/*
* Set to false to exclude sharing attributes 'data-*'.
*/
Expand Down Expand Up @@ -65,6 +67,10 @@ export class MapComponent extends Component<Props> {
timeRange: this.props.timeRange,
});

if (this.props.getTooltipRenderer) {
this._mapEmbeddable.setRenderTooltipContent(this.props.getTooltipRenderer());
}

if (this.props.onInitialRenderComplete) {
this._mapEmbeddable
.getOnRenderComplete$()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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', () => {
Expand All @@ -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(() => <div data-test-subj="mockMap" />),
};

const mockCore: () => any[] = () => {
const core = {
embeddable: mockEmbeddable,
maps: mockMapsStartService,
};

return [core];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand All @@ -38,43 +34,15 @@ const EmbeddedPanel = styled.div`
`;

export function EmbeddedMapComponent() {
const { rangeId, urlParams } = useLegacyUrlParams();
const { urlParams } = useLegacyUrlParams();

const { start, end, serviceName } = urlParams;

const mapFilters = useMapFilters();

const layerList = useLayerList();

const [embeddable, setEmbeddable] = useState<MapEmbeddable | ErrorEmbeddable | undefined>();

const embeddableRoot: React.RefObject<HTMLDivElement> = useRef<HTMLDivElement>(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,
Expand All @@ -95,71 +63,30 @@ export function EmbeddedMapComponent() {
return <MapToolTip {...props} features={features} />;
}

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 (
<EmbeddedPanel>
<div
data-test-subj="xpack.ux.regionMap.embeddedPanel"
className="embPanel__content"
ref={embeddableRoot}
/>
<div data-test-subj="xpack.ux.regionMap.embeddedPanel" className="embPanel__content">
{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,
})}
</div>
</EmbeddedPanel>
);
}
Expand Down

0 comments on commit 49a5d5e

Please sign in to comment.