diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.md
index b875b1fce4288..444132024596e 100644
--- a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.md
+++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.md
@@ -36,6 +36,7 @@
| [isSavedObjectEmbeddableInput(input)](./kibana-plugin-plugins-embeddable-public.issavedobjectembeddableinput.md) | |
| [openAddPanelFlyout(options)](./kibana-plugin-plugins-embeddable-public.openaddpanelflyout.md) | |
| [plugin(initializerContext)](./kibana-plugin-plugins-embeddable-public.plugin.md) | |
+| [useEmbeddableFactory({ input, factory, onInputUpdated, })](./kibana-plugin-plugins-embeddable-public.useembeddablefactory.md) | |
## Interfaces
diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.useembeddablefactory.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.useembeddablefactory.md
new file mode 100644
index 0000000000000..9af20cacc2cee
--- /dev/null
+++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.useembeddablefactory.md
@@ -0,0 +1,22 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [useEmbeddableFactory](./kibana-plugin-plugins-embeddable-public.useembeddablefactory.md)
+
+## useEmbeddableFactory() function
+
+Signature:
+
+```typescript
+export declare function useEmbeddableFactory({ input, factory, onInputUpdated, }: EmbeddableRendererWithFactory): readonly [ErrorEmbeddable | IEmbeddable | undefined, boolean, string | undefined];
+```
+
+## Parameters
+
+| Parameter | Type | Description |
+| --- | --- | --- |
+| { input, factory, onInputUpdated, } | EmbeddableRendererWithFactory<I>
| |
+
+Returns:
+
+`readonly [ErrorEmbeddable | IEmbeddable | undefined, boolean, string | undefined]`
+
diff --git a/src/plugins/embeddable/public/index.ts b/src/plugins/embeddable/public/index.ts
index 25d080dbfd546..80171e1ad2fab 100644
--- a/src/plugins/embeddable/public/index.ts
+++ b/src/plugins/embeddable/public/index.ts
@@ -69,6 +69,7 @@ export {
EmbeddablePackageState,
EmbeddableRenderer,
EmbeddableRendererProps,
+ useEmbeddableFactory,
} from './lib';
export { AttributeService, ATTRIBUTE_SERVICE_KEY } from './lib/attribute_service';
diff --git a/src/plugins/embeddable/public/lib/embeddables/embeddable_renderer.test.tsx b/src/plugins/embeddable/public/lib/embeddables/embeddable_renderer.test.tsx
index 457852c48ed77..b919672ad01e3 100644
--- a/src/plugins/embeddable/public/lib/embeddables/embeddable_renderer.test.tsx
+++ b/src/plugins/embeddable/public/lib/embeddables/embeddable_renderer.test.tsx
@@ -9,14 +9,39 @@
import React from 'react';
import { waitFor } from '@testing-library/dom';
import { render } from '@testing-library/react';
+import { renderHook } from '@testing-library/react-hooks';
import {
HelloWorldEmbeddable,
HelloWorldEmbeddableFactoryDefinition,
HELLO_WORLD_EMBEDDABLE,
} from '../../tests/fixtures';
-import { EmbeddableRenderer } from './embeddable_renderer';
+import { EmbeddableRenderer, useEmbeddableFactory } from './embeddable_renderer';
import { embeddablePluginMock } from '../../mocks';
+describe('useEmbeddableFactory', () => {
+ it('should update upstream value changes', async () => {
+ const { setup, doStart } = embeddablePluginMock.createInstance();
+ const getFactory = setup.registerEmbeddableFactory(
+ HELLO_WORLD_EMBEDDABLE,
+ new HelloWorldEmbeddableFactoryDefinition()
+ );
+ doStart();
+
+ const { result, waitForNextUpdate } = renderHook(() =>
+ useEmbeddableFactory({ factory: getFactory(), input: { id: 'hello' } })
+ );
+
+ const [, loading] = result.current;
+
+ expect(loading).toBe(true);
+
+ await waitForNextUpdate();
+
+ const [embeddable] = result.current;
+ expect(embeddable).toBeDefined();
+ });
+});
+
describe('', () => {
test('Render embeddable', () => {
const embeddable = new HelloWorldEmbeddable({ id: 'hello' });
diff --git a/src/plugins/embeddable/public/lib/embeddables/embeddable_renderer.tsx b/src/plugins/embeddable/public/lib/embeddables/embeddable_renderer.tsx
index 153564187d4b5..433b21e92cce5 100644
--- a/src/plugins/embeddable/public/lib/embeddables/embeddable_renderer.tsx
+++ b/src/plugins/embeddable/public/lib/embeddables/embeddable_renderer.tsx
@@ -28,12 +28,6 @@ interface EmbeddableRendererPropsWithEmbeddable {
embeddable: IEmbeddable;
}
-function isWithEmbeddable(
- props: EmbeddableRendererProps
-): props is EmbeddableRendererPropsWithEmbeddable {
- return 'embeddable' in props;
-}
-
interface EmbeddableRendererWithFactory {
input: I;
onInputUpdated?: (newInput: I) => void;
@@ -46,6 +40,72 @@ function isWithFactory(
return 'factory' in props;
}
+export function useEmbeddableFactory({
+ input,
+ factory,
+ onInputUpdated,
+}: EmbeddableRendererWithFactory) {
+ const [embeddable, setEmbeddable] = useState | ErrorEmbeddable | undefined>(
+ undefined
+ );
+ const [loading, setLoading] = useState(false);
+ const [error, setError] = useState();
+ const latestInput = React.useRef(input);
+ useEffect(() => {
+ latestInput.current = input;
+ }, [input]);
+
+ useEffect(() => {
+ let canceled = false;
+
+ // keeping track of embeddables created by this component to be able to destroy them
+ let createdEmbeddableRef: IEmbeddable | ErrorEmbeddable | undefined;
+ setEmbeddable(undefined);
+ setLoading(true);
+ factory
+ .create(latestInput.current!)
+ .then((createdEmbeddable) => {
+ if (canceled) {
+ if (createdEmbeddable) {
+ createdEmbeddable.destroy();
+ }
+ } else {
+ createdEmbeddableRef = createdEmbeddable;
+ setEmbeddable(createdEmbeddable);
+ }
+ })
+ .catch((err) => {
+ if (canceled) return;
+ setError(err?.message);
+ })
+ .finally(() => {
+ if (canceled) return;
+ setLoading(false);
+ });
+
+ return () => {
+ canceled = true;
+ if (createdEmbeddableRef) {
+ createdEmbeddableRef.destroy();
+ }
+ };
+ }, [factory]);
+
+ useEffect(() => {
+ if (!embeddable) return;
+ if (isErrorEmbeddable(embeddable)) return;
+ if (!onInputUpdated) return;
+ const sub = embeddable.getInput$().subscribe((newInput) => {
+ onInputUpdated(newInput);
+ });
+ return () => {
+ sub.unsubscribe();
+ };
+ }, [embeddable, onInputUpdated]);
+
+ return [embeddable, loading, error] as const;
+}
+
/**
* Helper react component to render an embeddable
* Can be used if you have an embeddable object or an embeddable factory
@@ -82,72 +142,22 @@ function isWithFactory(
export const EmbeddableRenderer = (
props: EmbeddableRendererProps
) => {
- const { input, onInputUpdated } = props;
- const [embeddable, setEmbeddable] = useState | ErrorEmbeddable | undefined>(
- isWithEmbeddable(props) ? props.embeddable : undefined
- );
- const [loading, setLoading] = useState(!isWithEmbeddable(props));
- const [error, setError] = useState();
- const latestInput = React.useRef(props.input);
- useEffect(() => {
- latestInput.current = input;
- }, [input]);
-
- const factoryFromProps = isWithFactory(props) ? props.factory : undefined;
- const embeddableFromProps = isWithEmbeddable(props) ? props.embeddable : undefined;
- useEffect(() => {
- let canceled = false;
- if (embeddableFromProps) {
- setEmbeddable(embeddableFromProps);
- return;
- }
-
- // keeping track of embeddables created by this component to be able to destroy them
- let createdEmbeddableRef: IEmbeddable | ErrorEmbeddable | undefined;
- if (factoryFromProps) {
- setEmbeddable(undefined);
- setLoading(true);
- factoryFromProps
- .create(latestInput.current!)
- .then((createdEmbeddable) => {
- if (canceled) {
- if (createdEmbeddable) {
- createdEmbeddable.destroy();
- }
- } else {
- createdEmbeddableRef = createdEmbeddable;
- setEmbeddable(createdEmbeddable);
- }
- })
- .catch((err) => {
- if (canceled) return;
- setError(err?.message);
- })
- .finally(() => {
- if (canceled) return;
- setLoading(false);
- });
- }
-
- return () => {
- canceled = true;
- if (createdEmbeddableRef) {
- createdEmbeddableRef.destroy();
- }
- };
- }, [factoryFromProps, embeddableFromProps]);
-
- useEffect(() => {
- if (!embeddable) return;
- if (isErrorEmbeddable(embeddable)) return;
- if (!onInputUpdated) return;
- const sub = embeddable.getInput$().subscribe((newInput) => {
- onInputUpdated(newInput);
- });
- return () => {
- sub.unsubscribe();
- };
- }, [embeddable, onInputUpdated]);
+ if (isWithFactory(props)) {
+ return ;
+ }
+ return ;
+};
+//
+const EmbeddableByFactory = ({
+ factory,
+ input,
+ onInputUpdated,
+}: EmbeddableRendererWithFactory) => {
+ const [embeddable, loading, error] = useEmbeddableFactory({
+ factory,
+ input,
+ onInputUpdated,
+ });
return ;
};
diff --git a/src/plugins/embeddable/public/lib/embeddables/index.ts b/src/plugins/embeddable/public/lib/embeddables/index.ts
index 71dfd73e534e7..eede745f31794 100644
--- a/src/plugins/embeddable/public/lib/embeddables/index.ts
+++ b/src/plugins/embeddable/public/lib/embeddables/index.ts
@@ -16,4 +16,8 @@ export { ErrorEmbeddable, isErrorEmbeddable } from './error_embeddable';
export { withEmbeddableSubscription } from './with_subscription';
export { EmbeddableRoot } from './embeddable_root';
export * from '../../../common/lib/saved_object_embeddable';
-export { EmbeddableRenderer, EmbeddableRendererProps } from './embeddable_renderer';
+export {
+ EmbeddableRenderer,
+ EmbeddableRendererProps,
+ useEmbeddableFactory,
+} from './embeddable_renderer';
diff --git a/src/plugins/embeddable/public/lib/panel/embeddable_panel.test.tsx b/src/plugins/embeddable/public/lib/panel/embeddable_panel.test.tsx
index 22001608f63ab..1b3e0388e9bb0 100644
--- a/src/plugins/embeddable/public/lib/panel/embeddable_panel.test.tsx
+++ b/src/plugins/embeddable/public/lib/panel/embeddable_panel.test.tsx
@@ -542,3 +542,40 @@ test('Check when hide header option is true', async () => {
const title = findTestSubject(component, `embeddablePanelHeading-HelloAryaStark`);
expect(title.length).toBe(0);
});
+
+test('Should work in minimal way rendering only the inspector action', async () => {
+ const inspector = inspectorPluginMock.createStartContract();
+ inspector.isAvailable = jest.fn(() => true);
+
+ const container = new HelloWorldContainer({ id: '123', panels: {}, viewMode: ViewMode.VIEW }, {
+ getEmbeddableFactory,
+ } as any);
+
+ const embeddable = await container.addNewEmbeddable<
+ ContactCardEmbeddableInput,
+ ContactCardEmbeddableOutput,
+ ContactCardEmbeddable
+ >(CONTACT_CARD_EMBEDDABLE, {
+ firstName: 'Arya',
+ lastName: 'Stark',
+ });
+
+ const component = mount(
+
+ Promise.resolve([])}
+ inspector={inspector}
+ hideHeader={false}
+ />
+
+ );
+
+ findTestSubject(component, 'embeddablePanelToggleMenuIcon').simulate('click');
+ expect(findTestSubject(component, `embeddablePanelContextMenuOpen`).length).toBe(1);
+ await nextTick();
+ component.update();
+ expect(findTestSubject(component, `embeddablePanelAction-openInspector`).length).toBe(1);
+ const action = findTestSubject(component, `embeddablePanelAction-ACTION_CUSTOMIZE_PANEL`);
+ expect(action.length).toBe(0);
+});
diff --git a/src/plugins/embeddable/public/lib/panel/embeddable_panel.tsx b/src/plugins/embeddable/public/lib/panel/embeddable_panel.tsx
index 8cf2de8c80743..b66950c170d69 100644
--- a/src/plugins/embeddable/public/lib/panel/embeddable_panel.tsx
+++ b/src/plugins/embeddable/public/lib/panel/embeddable_panel.tsx
@@ -54,16 +54,20 @@ const removeById = (disabledActions: string[]) => ({ id }: { id: string }) =>
interface Props {
embeddable: IEmbeddable;
getActions: UiActionsService['getTriggerCompatibleActions'];
- getEmbeddableFactory: EmbeddableStart['getEmbeddableFactory'];
- getAllEmbeddableFactories: EmbeddableStart['getEmbeddableFactories'];
- overlays: CoreStart['overlays'];
- notifications: CoreStart['notifications'];
- application: CoreStart['application'];
- inspector: InspectorStartContract;
- SavedObjectFinder: React.ComponentType;
+ getEmbeddableFactory?: EmbeddableStart['getEmbeddableFactory'];
+ getAllEmbeddableFactories?: EmbeddableStart['getEmbeddableFactories'];
+ overlays?: CoreStart['overlays'];
+ notifications?: CoreStart['notifications'];
+ application?: CoreStart['application'];
+ inspector?: InspectorStartContract;
+ SavedObjectFinder?: React.ComponentType;
stateTransfer?: EmbeddableStateTransfer;
hideHeader?: boolean;
+ actionPredicate?: (actionId: string) => boolean;
reportUiCounter?: UsageCollectionStart['reportUiCounter'];
+ showShadow?: boolean;
+ showBadges?: boolean;
+ showNotifications?: boolean;
}
interface State {
@@ -80,7 +84,11 @@ interface State {
errorEmbeddable?: ErrorEmbeddable;
}
-interface PanelUniversalActions {
+interface InspectorPanelAction {
+ inspectPanel: InspectPanelAction;
+}
+
+interface BasePanelActions {
customizePanelTitle: CustomizePanelTitleAction;
addPanel: AddPanelAction;
inspectPanel: InspectPanelAction;
@@ -88,6 +96,15 @@ interface PanelUniversalActions {
editPanel: EditPanelAction;
}
+const emptyObject = {};
+type EmptyObject = typeof emptyObject;
+
+type PanelUniversalActions =
+ | BasePanelActions
+ | InspectorPanelAction
+ | (BasePanelActions & InspectorPanelAction)
+ | EmptyObject;
+
export class EmbeddablePanel extends React.Component {
private embeddableRoot: React.RefObject;
private parentSubscription?: Subscription;
@@ -117,10 +134,15 @@ export class EmbeddablePanel extends React.Component {
}
private async refreshBadges() {
+ if (!this.mounted) {
+ return;
+ }
+ if (this.props.showBadges === false) {
+ return;
+ }
let badges = await this.props.getActions(PANEL_BADGE_TRIGGER, {
embeddable: this.props.embeddable,
});
- if (!this.mounted) return;
const { disabledActions } = this.props.embeddable.getInput();
if (disabledActions) {
@@ -135,10 +157,15 @@ export class EmbeddablePanel extends React.Component {
}
private async refreshNotifications() {
+ if (!this.mounted) {
+ return;
+ }
+ if (this.props.showNotifications === false) {
+ return;
+ }
let notifications = await this.props.getActions(PANEL_NOTIFICATION_TRIGGER, {
embeddable: this.props.embeddable,
});
- if (!this.mounted) return;
const { disabledActions } = this.props.embeddable.getInput();
if (disabledActions) {
@@ -229,13 +256,18 @@ export class EmbeddablePanel extends React.Component {
paddingSize="none"
role="figure"
aria-labelledby={headerId}
+ hasShadow={this.props.showShadow}
>
{!this.props.hideHeader && (
{
};
private getUniversalActions = (): PanelUniversalActions => {
+ let actions = {};
+ if (this.props.inspector) {
+ actions = {
+ inspectPanel: new InspectPanelAction(this.props.inspector),
+ };
+ }
+ if (
+ !this.props.getEmbeddableFactory ||
+ !this.props.getAllEmbeddableFactories ||
+ !this.props.overlays ||
+ !this.props.notifications ||
+ !this.props.SavedObjectFinder ||
+ !this.props.application
+ ) {
+ return actions;
+ }
+
const createGetUserData = (overlays: OverlayStart) =>
async function getUserData(context: { embeddable: IEmbeddable }) {
return new Promise<{ title: string | undefined; hideTitle?: boolean }>((resolve) => {
@@ -308,6 +357,7 @@ export class EmbeddablePanel extends React.Component {
// Universal actions are exposed on the context menu for every embeddable, they bypass the trigger
// registry.
return {
+ ...actions,
customizePanelTitle: new CustomizePanelTitleAction(createGetUserData(this.props.overlays)),
addPanel: new AddPanelAction(
this.props.getEmbeddableFactory,
@@ -317,7 +367,6 @@ export class EmbeddablePanel extends React.Component {
this.props.SavedObjectFinder,
this.props.reportUiCounter
),
- inspectPanel: new InspectPanelAction(this.props.inspector),
removePanel: new RemovePanelAction(),
editPanel: new EditPanelAction(
this.props.getEmbeddableFactory,
@@ -338,9 +387,13 @@ export class EmbeddablePanel extends React.Component {
regularActions = regularActions.filter(removeDisabledActions);
}
- const sortedActions = [...regularActions, ...Object.values(this.state.universalActions)].sort(
- sortByOrderField
- );
+ let sortedActions = regularActions
+ .concat(Object.values(this.state.universalActions || {}) as Array>)
+ .sort(sortByOrderField);
+
+ if (this.props.actionPredicate) {
+ sortedActions = sortedActions.filter(({ id }) => this.props.actionPredicate!(id));
+ }
return await buildContextMenuForActions({
actions: sortedActions.map((action) => ({
diff --git a/src/plugins/embeddable/public/lib/panel/panel_header/panel_header.tsx b/src/plugins/embeddable/public/lib/panel/panel_header/panel_header.tsx
index 403aa3e3f4c9f..742a2d1909941 100644
--- a/src/plugins/embeddable/public/lib/panel/panel_header/panel_header.tsx
+++ b/src/plugins/embeddable/public/lib/panel/panel_header/panel_header.tsx
@@ -36,7 +36,7 @@ export interface PanelHeaderProps {
embeddable: IEmbeddable;
headerId?: string;
showPlaceholderTitle?: boolean;
- customizeTitle: CustomizePanelTitleAction;
+ customizeTitle?: CustomizePanelTitleAction;
}
function renderBadges(badges: Array>, embeddable: IEmbeddable) {
@@ -177,7 +177,7 @@ export function PanelHeader({
>
{title || placeholderTitle}
- ) : (
+ ) : customizeTitle ? (
{title || placeholderTitle}
- );
+ ) : null;
}
return description ? (
({ input, factory, onInputUpdated, }: EmbeddableRendererWithFactory): readonly [ErrorEmbeddable | IEmbeddable | undefined, boolean, string | undefined];
+
// Warning: (ae-missing-release-tag) "VALUE_CLICK_TRIGGER" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
diff --git a/x-pack/examples/embedded_lens_example/kibana.json b/x-pack/examples/embedded_lens_example/kibana.json
index 5e4caead90bc3..be38e5bf3e761 100644
--- a/x-pack/examples/embedded_lens_example/kibana.json
+++ b/x-pack/examples/embedded_lens_example/kibana.json
@@ -8,6 +8,7 @@
"requiredPlugins": [
"lens",
"data",
+ "embeddable",
"developerExamples"
],
"optionalPlugins": [],
diff --git a/x-pack/examples/embedded_lens_example/public/app.tsx b/x-pack/examples/embedded_lens_example/public/app.tsx
index 6a39951ad4958..a13ddbbd79ef0 100644
--- a/x-pack/examples/embedded_lens_example/public/app.tsx
+++ b/x-pack/examples/embedded_lens_example/public/app.tsx
@@ -20,6 +20,7 @@ import {
} from '@elastic/eui';
import { IndexPattern } from 'src/plugins/data/public';
import { CoreStart } from 'kibana/public';
+import { ViewMode } from '../../../../src/plugins/embeddable/public';
import {
TypedLensByValueInput,
PersistedIndexPatternLayer,
@@ -193,6 +194,7 @@ export const App = (props: {
{
// call back event for on table row click event
}}
+ viewMode={ViewMode.VIEW}
/>
{isSaveModalVisible && (
& {
| LensAttributes<'lnsMetric', MetricState>;
};
-export type EmbeddableComponentProps = TypedLensByValueInput | LensByReferenceInput;
+export type EmbeddableComponentProps = (TypedLensByValueInput | LensByReferenceInput) & {
+ withActions?: boolean;
+};
+
+interface PluginsStartDependencies {
+ uiActions: UiActionsStart;
+ embeddable: EmbeddableStart;
+ inspector: InspectorStartContract;
+}
-export function getEmbeddableComponent(embeddableStart: EmbeddableStart) {
+export function getEmbeddableComponent(core: CoreStart, plugins: PluginsStartDependencies) {
return (props: EmbeddableComponentProps) => {
+ const { embeddable: embeddableStart, uiActions, inspector } = plugins;
const factory = embeddableStart.getEmbeddableFactory('lens')!;
- return ;
+ const input = { ...props };
+ const [embeddable, loading, error] = useEmbeddableFactory({ factory, input });
+ const hasActions = props.withActions === true;
+
+ if (embeddable && hasActions) {
+ return (
+ }
+ uiActions={uiActions}
+ inspector={inspector}
+ actionPredicate={() => hasActions}
+ input={input}
+ />
+ );
+ }
+
+ return ;
};
}
+
+interface EmbeddablePanelWrapperProps {
+ embeddable: IEmbeddable;
+ uiActions: PluginsStartDependencies['uiActions'];
+ inspector: PluginsStartDependencies['inspector'];
+ actionPredicate: (id: string) => boolean;
+ input: EmbeddableComponentProps;
+}
+
+const EmbeddablePanelWrapper: FC = ({
+ embeddable,
+ uiActions,
+ actionPredicate,
+ inspector,
+ input,
+}) => {
+ useEffect(() => {
+ embeddable.updateInput(input);
+ }, [embeddable, input]);
+
+ return (
+ }
+ getActions={uiActions.getTriggerCompatibleActions}
+ inspector={inspector}
+ actionPredicate={actionPredicate}
+ showShadow={false}
+ showBadges={false}
+ showNotifications={false}
+ />
+ );
+};
diff --git a/x-pack/plugins/lens/public/index.ts b/x-pack/plugins/lens/public/index.ts
index 98e0198b9d0fa..a82bc0b9c0d3d 100644
--- a/x-pack/plugins/lens/public/index.ts
+++ b/x-pack/plugins/lens/public/index.ts
@@ -7,7 +7,7 @@
import { LensPlugin } from './plugin';
-export {
+export type {
EmbeddableComponentProps,
TypedLensByValueInput,
} from './editor_frame_service/embeddable/embeddable_component';
diff --git a/x-pack/plugins/lens/public/plugin.ts b/x-pack/plugins/lens/public/plugin.ts
index 328bea5def557..ad81413e21345 100644
--- a/x-pack/plugins/lens/public/plugin.ts
+++ b/x-pack/plugins/lens/public/plugin.ts
@@ -6,6 +6,7 @@
*/
import { AppMountParameters, CoreSetup, CoreStart } from 'kibana/public';
+import type { Start as InspectorStartContract } from 'src/plugins/inspector/public';
import { UsageCollectionSetup, UsageCollectionStart } from 'src/plugins/usage_collection/public';
import { DataPublicPluginSetup, DataPublicPluginStart } from '../../../../src/plugins/data/public';
import { EmbeddableSetup, EmbeddableStart } from '../../../../src/plugins/embeddable/public';
@@ -81,6 +82,7 @@ export interface LensPluginStartDependencies {
savedObjectsTagging?: SavedObjectTaggingPluginStart;
presentationUtil: PresentationUtilPluginStart;
indexPatternFieldEditor: IndexPatternFieldEditorStart;
+ inspector: InspectorStartContract;
usageCollection?: UsageCollectionStart;
}
@@ -256,7 +258,7 @@ export class LensPlugin {
);
return {
- EmbeddableComponent: getEmbeddableComponent(startDependencies.embeddable),
+ EmbeddableComponent: getEmbeddableComponent(core, startDependencies),
SaveModalComponent: getSaveModalComponent(core, startDependencies, this.attributeService!),
navigateToPrefilledEditor: (input: LensEmbeddableInput, openInNewTab?: boolean) => {
// for openInNewTab, we set the time range in url via getEditPath below
diff --git a/x-pack/plugins/ui_actions_enhanced/public/custom_time_range_action.tsx b/x-pack/plugins/ui_actions_enhanced/public/custom_time_range_action.tsx
index 6cdb01a992034..5b1ba3bcc206b 100644
--- a/x-pack/plugins/ui_actions_enhanced/public/custom_time_range_action.tsx
+++ b/x-pack/plugins/ui_actions_enhanced/public/custom_time_range_action.tsx
@@ -78,7 +78,9 @@ export class CustomTimeRangeAction implements Action {
const isMarkdown =
isVisualizeEmbeddable(embeddable) &&
(embeddable as VisualizeEmbeddable).getOutput().visTypeName === 'markdown';
- return Boolean(embeddable && hasTimeRange(embeddable) && !isInputControl && !isMarkdown);
+ return Boolean(
+ embeddable && embeddable.parent && hasTimeRange(embeddable) && !isInputControl && !isMarkdown
+ );
}
public async execute({ embeddable }: TimeRangeActionContext) {