diff --git a/x-pack/plugins/canvas/public/components/hooks/workpad/use_incoming_embeddable.ts b/x-pack/plugins/canvas/public/components/hooks/workpad/use_incoming_embeddable.ts index 27f68ca15a200..2f8e2503ea57e 100644 --- a/x-pack/plugins/canvas/public/components/hooks/workpad/use_incoming_embeddable.ts +++ b/x-pack/plugins/canvas/public/components/hooks/workpad/use_incoming_embeddable.ts @@ -7,8 +7,10 @@ import { useEffect } from 'react'; import { useDispatch } from 'react-redux'; +import { fromExpression } from '@kbn/interpreter/common'; import { CANVAS_APP } from '../../../../common/lib'; -import { encode } from '../../../../common/lib/embeddable_dataurl'; +import { decode, encode } from '../../../../common/lib/embeddable_dataurl'; +import { CanvasElement, CanvasPage } from '../../../../types'; import { useEmbeddablesService, useLabsService } from '../../../services'; // @ts-expect-error unconverted file import { addElement } from '../../../state/actions/elements'; @@ -21,7 +23,7 @@ import { } from '../../../state/actions/embeddable'; import { clearValue } from '../../../state/actions/resolved_args'; -export const useIncomingEmbeddable = (pageId: string) => { +export const useIncomingEmbeddable = (selectedPage: CanvasPage) => { const embeddablesService = useEmbeddablesService(); const labsService = useLabsService(); const dispatch = useDispatch(); @@ -33,31 +35,52 @@ export const useIncomingEmbeddable = (pageId: string) => { useEffect(() => { if (isByValueEnabled && incomingEmbeddable) { - const { embeddableId, input, type } = incomingEmbeddable; + const { embeddableId, input: incomingInput, type } = incomingEmbeddable; - const config = encode(input); - const expression = `embeddable config="${config}" - type="${type}" -| render`; + // retrieve existing element + const originalElement = selectedPage.elements.find( + ({ id }: CanvasElement) => id === embeddableId + ); + + if (originalElement) { + const originalAst = fromExpression(originalElement!.expression); + + const functionIndex = originalAst.chain.findIndex( + ({ function: fn }) => fn === 'embeddable' + ); + + const originalInput = decode( + originalAst.chain[functionIndex].arguments.config[0] as string + ); - if (embeddableId) { // clear out resolved arg for old embeddable const argumentPath = [embeddableId, 'expressionRenderable']; dispatch(clearValue({ path: argumentPath })); - // update existing embeddable expression + const updatedInput = { ...originalInput, ...incomingInput }; + + const expression = `embeddable config="${encode(updatedInput)}" + type="${type}" +| render`; + dispatch( - updateEmbeddableExpression({ elementId: embeddableId, embeddableExpression: expression }) + updateEmbeddableExpression({ + elementId: originalElement.id, + embeddableExpression: expression, + }) ); // update resolved args - dispatch(fetchEmbeddableRenderable(embeddableId)); + dispatch(fetchEmbeddableRenderable(originalElement.id)); // select new embeddable element dispatch(selectToplevelNodes([embeddableId])); } else { - dispatch(addElement(pageId, { expression })); + const expression = `embeddable config="${encode(incomingInput)}" + type="${type}" +| render`; + dispatch(addElement(selectedPage.id, { expression })); } } - }, [dispatch, pageId, incomingEmbeddable, isByValueEnabled]); + }, [dispatch, selectedPage, incomingEmbeddable, isByValueEnabled]); }; diff --git a/x-pack/plugins/canvas/public/components/workpad/workpad.tsx b/x-pack/plugins/canvas/public/components/workpad/workpad.tsx index bc867333b648f..7cc077203c737 100644 --- a/x-pack/plugins/canvas/public/components/workpad/workpad.tsx +++ b/x-pack/plugins/canvas/public/components/workpad/workpad.tsx @@ -59,8 +59,8 @@ export const Workpad: FC = (props) => { }; }); - const pageId = propsFromState.pages[propsFromState.selectedPageNumber - 1].id; - useIncomingEmbeddable(pageId); + const selectedPage = propsFromState.pages[propsFromState.selectedPageNumber - 1]; + useIncomingEmbeddable(selectedPage); const fetchAllRenderables = useCallback(() => { dispatch(fetchAllRenderablesAction());