Skip to content

Commit 3e0efb9

Browse files
[dashboards as code] move map embeddable reference handling to server (#234806)
PR moves map embeddable reference handling to the server. dashboard CRUD APIs no longer contain references from map panels. In the screen shot below, notice how `indexPatternId` contain saved object ids and are not references. Notice how the reference array for the dashboard is empty. <img width="2041" height="1014" alt="Screenshot 2025-09-11 at 6 59 55 PM" src="https://github.com/user-attachments/assets/44a7c26c-b189-4c04-9f19-2159068ecc74" /> References are extracted on server and stored in dashboard saved object. In the screen shot below, notice how `indexPatternId` has been replaced with `indexPatternRefName` and points to a reference that contains the saved objec tid. <img width="2046" height="999" alt="Screenshot 2025-09-11 at 7 01 41 PM" src="https://github.com/user-attachments/assets/ecbe6c80-21fb-4a88-8233-5555153d9430" /> --------- Co-authored-by: Elastic Machine <[email protected]>
1 parent 41845d9 commit 3e0efb9

File tree

27 files changed

+331
-232
lines changed

27 files changed

+331
-232
lines changed

x-pack/platform/plugins/private/canvas/canvas_plugin_src/renderers/embeddable/input_type_to_expression/map.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,14 @@
55
* 2.0.
66
*/
77

8-
import type { MapSerializedState } from '@kbn/maps-plugin/public';
8+
import type { MapByReferenceState, MapEmbeddableState } from '@kbn/maps-plugin/common';
99

10-
export function toExpression(input: MapSerializedState & { id: string }): string {
10+
export function toExpression(input: MapEmbeddableState & { id: string }): string {
1111
const expressionParts = [] as string[];
1212

1313
expressionParts.push('savedMap');
1414

15-
expressionParts.push(`id="${input.savedObjectId}"`);
15+
expressionParts.push(`id="${(input as MapByReferenceState).savedObjectId}"`);
1616

1717
if (input.title !== undefined) {
1818
expressionParts.push(`title="${input.title}"`);
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License
4+
* 2.0; you may not use this file except in compliance with the Elastic License
5+
* 2.0.
6+
*/
7+
8+
import type { EnhancementsRegistry } from '@kbn/embeddable-plugin/common/enhancements/registry';
9+
import type { Reference } from '@kbn/content-management-utils';
10+
import type { MapByReferenceState, MapByValueState, MapEmbeddableState } from '../types';
11+
import type { StoredMapEmbeddableState } from './types';
12+
import { MAP_SAVED_OBJECT_TYPE } from '../../constants';
13+
import { extractReferences } from '../../migrations/references';
14+
15+
export const MAP_SAVED_OBJECT_REF_NAME = 'savedObjectRef';
16+
17+
export function getTransformIn(transformEnhancementsIn: EnhancementsRegistry['transformIn']) {
18+
function transformIn(state: MapEmbeddableState): {
19+
state: StoredMapEmbeddableState;
20+
references: Reference[];
21+
} {
22+
const { enhancementsState, enhancementsReferences } = state.enhancements
23+
? transformEnhancementsIn(state.enhancements)
24+
: { enhancementsState: undefined, enhancementsReferences: [] };
25+
26+
// by ref
27+
if ((state as MapByReferenceState).savedObjectId) {
28+
const { savedObjectId, ...rest } = state as MapByReferenceState;
29+
return {
30+
state: {
31+
...rest,
32+
...(enhancementsState ? { enhancements: enhancementsState } : {}),
33+
} as StoredMapEmbeddableState,
34+
references: [
35+
{
36+
name: MAP_SAVED_OBJECT_REF_NAME,
37+
type: MAP_SAVED_OBJECT_TYPE,
38+
id: savedObjectId!,
39+
},
40+
...enhancementsReferences,
41+
],
42+
};
43+
}
44+
45+
// by value
46+
if ((state as MapByValueState).attributes) {
47+
const { attributes, references } = extractReferences({
48+
attributes: (state as MapByValueState).attributes,
49+
});
50+
51+
return {
52+
state: {
53+
...state,
54+
...(enhancementsState ? { enhancements: enhancementsState } : {}),
55+
attributes,
56+
} as MapByValueState,
57+
references: [...references, ...enhancementsReferences],
58+
};
59+
}
60+
61+
throw new Error('Unable to extract references from Map state, unexpected state');
62+
}
63+
return transformIn;
64+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License
4+
* 2.0; you may not use this file except in compliance with the Elastic License
5+
* 2.0.
6+
*/
7+
8+
import type { Reference } from '@kbn/content-management-utils/src/types';
9+
import type { EnhancementsRegistry } from '@kbn/embeddable-plugin/common/enhancements/registry';
10+
import type { StoredMapEmbeddableState } from './types';
11+
import { MAP_SAVED_OBJECT_REF_NAME } from './get_transform_in';
12+
import type { MapByValueState } from '../types';
13+
import { injectReferences } from '../../migrations/references';
14+
import { MAP_SAVED_OBJECT_TYPE } from '../../constants';
15+
16+
export function getTransformOut(transformEnhancementsOut: EnhancementsRegistry['transformOut']) {
17+
function transformOut(state: StoredMapEmbeddableState, references?: Reference[]) {
18+
const enhancementsState = state.enhancements
19+
? transformEnhancementsOut(state.enhancements, references ?? [])
20+
: undefined;
21+
22+
// by ref
23+
const savedObjectRef = (references ?? []).find(
24+
(ref) => MAP_SAVED_OBJECT_TYPE === ref.type && ref.name === MAP_SAVED_OBJECT_REF_NAME
25+
);
26+
if (savedObjectRef) {
27+
return {
28+
...state,
29+
...(enhancementsState ? { enhancements: enhancementsState } : {}),
30+
savedObjectId: savedObjectRef.id,
31+
};
32+
}
33+
34+
// by value
35+
if ((state as MapByValueState).attributes) {
36+
return {
37+
...state,
38+
...(enhancementsState ? { enhancements: enhancementsState } : {}),
39+
attributes: injectReferences({
40+
attributes: (state as MapByValueState).attributes,
41+
references: references ?? [],
42+
}).attributes,
43+
};
44+
}
45+
46+
throw new Error('Unable to inject references from Map state, unexpected state');
47+
}
48+
return transformOut;
49+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License
4+
* 2.0; you may not use this file except in compliance with the Elastic License
5+
* 2.0.
6+
*/
7+
8+
import type { EnhancementsRegistry } from '@kbn/embeddable-plugin/common/enhancements/registry';
9+
import { getTransformIn } from './get_transform_in';
10+
import { getTransformOut } from './get_transform_out';
11+
12+
export function getTransforms(
13+
transformEnhancementsIn: EnhancementsRegistry['transformIn'],
14+
transformEnhancementsOut: EnhancementsRegistry['transformOut']
15+
) {
16+
return {
17+
transformIn: getTransformIn(transformEnhancementsIn),
18+
transformOut: getTransformOut(transformEnhancementsOut),
19+
};
20+
}

x-pack/platform/plugins/shared/maps/common/embeddable/index.ts renamed to x-pack/platform/plugins/shared/maps/common/embeddable/transforms/types.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
* 2.0.
66
*/
77

8-
export type { MapEmbeddablePersistableState } from './types';
9-
export { extract } from './extract';
10-
export { inject } from './inject';
8+
import type { MapByReferenceState, MapByValueState } from '../types';
9+
10+
export type StoredMapByReferenceState = Omit<MapByReferenceState, 'savedObjectId'>;
11+
12+
export type StoredMapEmbeddableState = StoredMapByReferenceState | MapByValueState;

x-pack/platform/plugins/shared/maps/common/embeddable/types.ts

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,30 @@
55
* 2.0.
66
*/
77

8-
import type { SerializableRecord } from '@kbn/utility-types';
9-
import type { EmbeddableStateWithType } from '@kbn/embeddable-plugin/common';
8+
import type { DynamicActionsSerializedState } from '@kbn/embeddable-enhanced-plugin/public';
9+
import type { SerializedTimeRange, SerializedTitles } from '@kbn/presentation-publishing';
10+
import type { MapCenterAndZoom, MapExtent, MapSettings } from '../descriptor_types';
11+
import type { MapAttributes } from '../content_management';
1012

11-
export type MapEmbeddablePersistableState = EmbeddableStateWithType & {
12-
attributes: SerializableRecord;
13+
export type MapEmbeddableBaseState = SerializedTimeRange &
14+
SerializedTitles &
15+
Partial<DynamicActionsSerializedState> & {
16+
isLayerTOCOpen?: boolean;
17+
openTOCDetails?: string[];
18+
mapCenter?: MapCenterAndZoom;
19+
mapBuffer?: MapExtent;
20+
mapSettings?: Partial<MapSettings>;
21+
hiddenLayers?: string[];
22+
filterByMapExtent?: boolean;
23+
isMovementSynchronized?: boolean;
24+
};
25+
26+
export type MapByReferenceState = MapEmbeddableBaseState & {
27+
savedObjectId: string;
28+
};
29+
30+
export type MapByValueState = MapEmbeddableBaseState & {
31+
attributes: MapAttributes;
1332
};
33+
34+
export type MapEmbeddableState = MapByReferenceState | MapByValueState;

x-pack/platform/plugins/shared/maps/common/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,3 +42,5 @@ export type {
4242
VectorStyleDescriptor,
4343
VectorSourceRequestMeta,
4444
} from './descriptor_types';
45+
46+
export type { MapEmbeddableState, MapByReferenceState, MapByValueState } from './embeddable/types';

x-pack/platform/plugins/shared/maps/public/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ export type {
2929
export type { MapsSetupApi, MapsStartApi } from './api';
3030
export type { CreateLayerDescriptorParams } from './classes/sources/es_search_source/create_layer_descriptor';
3131

32-
export { type MapApi, type MapSerializedState, isMapApi } from './react_embeddable/types';
32+
export { type MapApi, isMapApi } from './react_embeddable/types';
3333

3434
export type { EMSTermJoinConfig, SampleValuesConfig } from './ems_autosuggest';
3535

x-pack/platform/plugins/shared/maps/public/lens/passive_map.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,10 @@ import useMountedState from 'react-use/lib/useMountedState';
1010
import type { Subscription } from 'rxjs';
1111
import { EmbeddableRenderer } from '@kbn/embeddable-plugin/public';
1212
import type { LayerDescriptor } from '../../common/descriptor_types';
13+
import type { MapEmbeddableState } from '../../common';
1314
import { INITIAL_LOCATION, MAP_SAVED_OBJECT_TYPE } from '../../common';
1415
import { createBasemapLayerDescriptor } from '../classes/layers/create_basemap_layer_descriptor';
15-
import type { MapApi, MapSerializedState } from '../react_embeddable/types';
16+
import type { MapApi } from '../react_embeddable/types';
1617

1718
export interface Props {
1819
passiveLayer: LayerDescriptor;
@@ -50,7 +51,7 @@ export function PassiveMap(props: Props) {
5051

5152
return (
5253
<div className="mapEmbeddableContainer">
53-
<EmbeddableRenderer<MapSerializedState, MapApi>
54+
<EmbeddableRenderer<MapEmbeddableState, MapApi>
5455
type={MAP_SAVED_OBJECT_TYPE}
5556
getParentApi={() => ({
5657
hideFilterActions: true,

x-pack/platform/plugins/shared/maps/public/react_embeddable/embeddable_module.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,4 @@
88
export { MapRenderer } from './map_renderer/map_renderer';
99
export { PassiveMap } from '../lens/passive_map';
1010
export { mapEmbeddableFactory } from './map_react_embeddable';
11+
export { getTransforms } from '../../common/embeddable/transforms/get_transforms';

0 commit comments

Comments
 (0)