diff --git a/examples/embeddable_examples/public/list_container/embeddable_list_item.tsx b/examples/embeddable_examples/public/list_container/embeddable_list_item.tsx
deleted file mode 100644
index 2c80cef8a6364..0000000000000
--- a/examples/embeddable_examples/public/list_container/embeddable_list_item.tsx
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Licensed to Elasticsearch B.V. under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch B.V. licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-import React from 'react';
-import { EuiPanel, EuiLoadingSpinner, EuiFlexItem } from '@elastic/eui';
-import { IEmbeddable } from '../../../../src/plugins/embeddable/public';
-
-interface Props {
- embeddable: IEmbeddable;
-}
-
-export class EmbeddableListItem extends React.Component {
- private embeddableRoot: React.RefObject;
- private rendered = false;
-
- constructor(props: Props) {
- super(props);
- this.embeddableRoot = React.createRef();
- }
-
- public componentDidMount() {
- if (this.embeddableRoot.current && this.props.embeddable) {
- this.props.embeddable.render(this.embeddableRoot.current);
- this.rendered = true;
- }
- }
-
- public componentDidUpdate() {
- if (this.embeddableRoot.current && this.props.embeddable && !this.rendered) {
- this.props.embeddable.render(this.embeddableRoot.current);
- this.rendered = true;
- }
- }
-
- public render() {
- return (
-
-
- {this.props.embeddable ? (
-
- ) : (
-
- )}
-
-
- );
- }
-}
diff --git a/examples/embeddable_examples/public/list_container/list_container.tsx b/examples/embeddable_examples/public/list_container/list_container.tsx
index bbbd0d6e32304..9e7bec7a1c951 100644
--- a/examples/embeddable_examples/public/list_container/list_container.tsx
+++ b/examples/embeddable_examples/public/list_container/list_container.tsx
@@ -31,16 +31,14 @@ export class ListContainer extends Container<{}, ContainerInput> {
public readonly type = LIST_CONTAINER;
private node?: HTMLElement;
- constructor(
- input: ContainerInput,
- getEmbeddableFactory: EmbeddableStart['getEmbeddableFactory']
- ) {
- super(input, { embeddableLoaded: {} }, getEmbeddableFactory);
+ constructor(input: ContainerInput, private embeddableServices: EmbeddableStart) {
+ super(input, { embeddableLoaded: {} }, embeddableServices.getEmbeddableFactory);
}
- // This container has no input itself.
- getInheritedInput(id: string) {
- return {};
+ getInheritedInput() {
+ return {
+ viewMode: this.input.viewMode,
+ };
}
public render(node: HTMLElement) {
@@ -48,7 +46,10 @@ export class ListContainer extends Container<{}, ContainerInput> {
if (this.node) {
ReactDOM.unmountComponentAtNode(this.node);
}
- ReactDOM.render(, node);
+ ReactDOM.render(
+ ,
+ node
+ );
}
public destroy() {
diff --git a/examples/embeddable_examples/public/list_container/list_container_component.tsx b/examples/embeddable_examples/public/list_container/list_container_component.tsx
index f6e04933ee897..da27889a27603 100644
--- a/examples/embeddable_examples/public/list_container/list_container_component.tsx
+++ b/examples/embeddable_examples/public/list_container/list_container_component.tsx
@@ -24,30 +24,35 @@ import {
withEmbeddableSubscription,
ContainerInput,
ContainerOutput,
+ EmbeddableStart,
} from '../../../../src/plugins/embeddable/public';
-import { EmbeddableListItem } from './embeddable_list_item';
interface Props {
embeddable: IContainer;
input: ContainerInput;
output: ContainerOutput;
+ embeddableServices: EmbeddableStart;
}
-function renderList(embeddable: IContainer, panels: ContainerInput['panels']) {
+function renderList(
+ embeddable: IContainer,
+ panels: ContainerInput['panels'],
+ embeddableServices: EmbeddableStart
+) {
let number = 0;
const list = Object.values(panels).map(panel => {
const child = embeddable.getChild(panel.explicitInput.id);
number++;
return (
-
+
{number}
-
+
@@ -56,12 +61,12 @@ function renderList(embeddable: IContainer, panels: ContainerInput['panels']) {
return list;
}
-export function ListContainerComponentInner(props: Props) {
+export function ListContainerComponentInner({ embeddable, input, embeddableServices }: Props) {
return (
-
{props.embeddable.getTitle()}
+ {embeddable.getTitle()}
- {renderList(props.embeddable, props.input.panels)}
+ {renderList(embeddable, input.panels, embeddableServices)}
);
}
@@ -71,4 +76,9 @@ export function ListContainerComponentInner(props: Props) {
// anything on input or output state changes. If you don't want that to happen (for example
// if you expect something on input or output state to change frequently that your react
// component does not care about, then you should probably hook this up manually).
-export const ListContainerComponent = withEmbeddableSubscription(ListContainerComponentInner);
+export const ListContainerComponent = withEmbeddableSubscription<
+ ContainerInput,
+ ContainerOutput,
+ IContainer,
+ { embeddableServices: EmbeddableStart }
+>(ListContainerComponentInner);
diff --git a/examples/embeddable_examples/public/list_container/list_container_factory.ts b/examples/embeddable_examples/public/list_container/list_container_factory.ts
index 1fde254110c62..02a024b95349f 100644
--- a/examples/embeddable_examples/public/list_container/list_container_factory.ts
+++ b/examples/embeddable_examples/public/list_container/list_container_factory.ts
@@ -26,7 +26,7 @@ import {
import { LIST_CONTAINER, ListContainer } from './list_container';
interface StartServices {
- getEmbeddableFactory: EmbeddableStart['getEmbeddableFactory'];
+ embeddableServices: EmbeddableStart;
}
export class ListContainerFactory implements EmbeddableFactoryDefinition {
@@ -40,8 +40,8 @@ export class ListContainerFactory implements EmbeddableFactoryDefinition {
}
public create = async (initialInput: ContainerInput) => {
- const { getEmbeddableFactory } = await this.getStartServices();
- return new ListContainer(initialInput, getEmbeddableFactory);
+ const { embeddableServices } = await this.getStartServices();
+ return new ListContainer(initialInput, embeddableServices);
};
public getDisplayName() {
diff --git a/examples/embeddable_examples/public/multi_task_todo/multi_task_todo_component.tsx b/examples/embeddable_examples/public/multi_task_todo/multi_task_todo_component.tsx
index e33dfab0eaf4a..b2882c97ef501 100644
--- a/examples/embeddable_examples/public/multi_task_todo/multi_task_todo_component.tsx
+++ b/examples/embeddable_examples/public/multi_task_todo/multi_task_todo_component.tsx
@@ -54,7 +54,7 @@ function wrapSearchTerms(task: string, search?: string) {
);
}
-function renderTasks(tasks: MultiTaskTodoOutput['tasks'], search?: string) {
+function renderTasks(tasks: MultiTaskTodoInput['tasks'], search?: string) {
return tasks.map(task => (
+
{icon ? : }
-
+
{wrapSearchTerms(title, search)}
@@ -89,6 +88,8 @@ export function MultiTaskTodoEmbeddableComponentInner({
);
}
-export const MultiTaskTodoEmbeddableComponent = withEmbeddableSubscription(
- MultiTaskTodoEmbeddableComponentInner
-);
+export const MultiTaskTodoEmbeddableComponent = withEmbeddableSubscription<
+ MultiTaskTodoInput,
+ MultiTaskTodoOutput,
+ MultiTaskTodoEmbeddable
+>(MultiTaskTodoEmbeddableComponentInner);
diff --git a/examples/embeddable_examples/public/multi_task_todo/multi_task_todo_embeddable.tsx b/examples/embeddable_examples/public/multi_task_todo/multi_task_todo_embeddable.tsx
index a2197c9c06fe9..a9e58c5538107 100644
--- a/examples/embeddable_examples/public/multi_task_todo/multi_task_todo_embeddable.tsx
+++ b/examples/embeddable_examples/public/multi_task_todo/multi_task_todo_embeddable.tsx
@@ -36,30 +36,27 @@ export interface MultiTaskTodoInput extends EmbeddableInput {
title: string;
}
-// This embeddable has output! It's the tasks list that is filtered.
-// Output state is something only the embeddable itself can update. It
-// can be something completely internal, or it can be state that is
+// This embeddable has output! Output state is something only the embeddable itself
+// can update. It can be something completely internal, or it can be state that is
// derived from input state and updates when input does.
export interface MultiTaskTodoOutput extends EmbeddableOutput {
- tasks: string[];
+ hasMatch: boolean;
}
-function getFilteredTasks(tasks: string[], search?: string) {
- const filteredTasks: string[] = [];
- if (search === undefined) return tasks;
+function getHasMatch(tasks: string[], title?: string, search?: string) {
+ if (search === undefined || search === '') return false;
- tasks.forEach(task => {
- if (task.match(search)) {
- filteredTasks.push(task);
- }
- });
+ if (title && title.match(search)) return true;
+
+ const match = tasks.find(task => task.match(search));
+ if (match) return true;
- return filteredTasks;
+ return false;
}
function getOutput(input: MultiTaskTodoInput) {
- const tasks = getFilteredTasks(input.tasks, input.search);
- return { tasks, hasMatch: tasks.length > 0 || (input.search && input.title.match(input.search)) };
+ const hasMatch = getHasMatch(input.tasks, input.title, input.search);
+ return { hasMatch };
}
export class MultiTaskTodoEmbeddable extends Embeddable {
diff --git a/examples/embeddable_examples/public/plugin.ts b/examples/embeddable_examples/public/plugin.ts
index 5c202d96ceb1a..31a3037332dda 100644
--- a/examples/embeddable_examples/public/plugin.ts
+++ b/examples/embeddable_examples/public/plugin.ts
@@ -53,20 +53,17 @@ export class EmbeddableExamplesPlugin
new MultiTaskTodoEmbeddableFactory()
);
- // These are registered in the start method because `getEmbeddableFactory `
- // is only available in start. We could reconsider this I think and make it
- // available in both.
deps.embeddable.registerEmbeddableFactory(
SEARCHABLE_LIST_CONTAINER,
new SearchableListContainerFactory(async () => ({
- getEmbeddableFactory: (await core.getStartServices())[1].embeddable.getEmbeddableFactory,
+ embeddableServices: (await core.getStartServices())[1].embeddable,
}))
);
deps.embeddable.registerEmbeddableFactory(
LIST_CONTAINER,
new ListContainerFactory(async () => ({
- getEmbeddableFactory: (await core.getStartServices())[1].embeddable.getEmbeddableFactory,
+ embeddableServices: (await core.getStartServices())[1].embeddable,
}))
);
diff --git a/examples/embeddable_examples/public/searchable_list_container/searchable_list_container.tsx b/examples/embeddable_examples/public/searchable_list_container/searchable_list_container.tsx
index 06462937c768d..f6efb0b722c4c 100644
--- a/examples/embeddable_examples/public/searchable_list_container/searchable_list_container.tsx
+++ b/examples/embeddable_examples/public/searchable_list_container/searchable_list_container.tsx
@@ -40,11 +40,8 @@ export class SearchableListContainer extends Container, node);
+ ReactDOM.render(
+ ,
+ node
+ );
}
public destroy() {
diff --git a/examples/embeddable_examples/public/searchable_list_container/searchable_list_container_component.tsx b/examples/embeddable_examples/public/searchable_list_container/searchable_list_container_component.tsx
index b79f86e2a0192..49dbce74788bf 100644
--- a/examples/embeddable_examples/public/searchable_list_container/searchable_list_container_component.tsx
+++ b/examples/embeddable_examples/public/searchable_list_container/searchable_list_container_component.tsx
@@ -34,14 +34,15 @@ import {
withEmbeddableSubscription,
ContainerOutput,
EmbeddableOutput,
+ EmbeddableStart,
} from '../../../../src/plugins/embeddable/public';
-import { EmbeddableListItem } from '../list_container/embeddable_list_item';
import { SearchableListContainer, SearchableContainerInput } from './searchable_list_container';
interface Props {
embeddable: SearchableListContainer;
input: SearchableContainerInput;
output: ContainerOutput;
+ embeddableServices: EmbeddableStart;
}
interface State {
@@ -111,13 +112,27 @@ export class SearchableListContainerComponentInner extends Component {
+ const { input, embeddable } = this.props;
+ const checked: { [key: string]: boolean } = {};
+ Object.values(input.panels).map(panel => {
+ const child = embeddable.getChild(panel.explicitInput.id);
+ const output = child.getOutput();
+ if (hasHasMatchOutput(output) && output.hasMatch) {
+ checked[panel.explicitInput.id] = true;
+ }
+ });
+ this.setState({ checked });
+ };
+
private toggleCheck = (isChecked: boolean, id: string) => {
this.setState(prevState => ({ checked: { ...prevState.checked, [id]: isChecked } }));
};
public renderControls() {
+ const { input } = this.props;
return (
-
+
this.deleteChecked()}>
@@ -125,6 +140,17 @@ export class SearchableListContainerComponentInner extends Component
+
+
+ this.checkMatching()}
+ >
+ Check matching
+
+
+
- {embeddable.getTitle()}
-
- {this.renderControls()}
-
- {this.renderList()}
-
+
+
+ {embeddable.getTitle()}
+
+ {this.renderControls()}
+
+ {this.renderList()}
+
+
);
}
private renderList() {
+ const { embeddableServices, input, embeddable } = this.props;
let id = 0;
- const list = Object.values(this.props.input.panels).map(panel => {
- const embeddable = this.props.embeddable.getChild(panel.explicitInput.id);
- if (this.props.input.search && !this.state.hasMatch[panel.explicitInput.id]) return;
+ const list = Object.values(input.panels).map(panel => {
+ const childEmbeddable = embeddable.getChild(panel.explicitInput.id);
id++;
- return embeddable ? (
-
-
+ return childEmbeddable ? (
+
+
this.toggleCheck(e.target.checked, embeddable.id)}
+ data-test-subj={`todoCheckBox-${childEmbeddable.id}`}
+ disabled={!childEmbeddable}
+ id={childEmbeddable ? childEmbeddable.id : ''}
+ checked={this.state.checked[childEmbeddable.id]}
+ onChange={e => this.toggleCheck(e.target.checked, childEmbeddable.id)}
/>
-
+
@@ -183,6 +211,9 @@ export class SearchableListContainerComponentInner extends Component(SearchableListContainerComponentInner);
diff --git a/examples/embeddable_examples/public/searchable_list_container/searchable_list_container_factory.ts b/examples/embeddable_examples/public/searchable_list_container/searchable_list_container_factory.ts
index 382bb65e769ef..34ea43c29462a 100644
--- a/examples/embeddable_examples/public/searchable_list_container/searchable_list_container_factory.ts
+++ b/examples/embeddable_examples/public/searchable_list_container/searchable_list_container_factory.ts
@@ -29,7 +29,7 @@ import {
} from './searchable_list_container';
interface StartServices {
- getEmbeddableFactory: EmbeddableStart['getEmbeddableFactory'];
+ embeddableServices: EmbeddableStart;
}
export class SearchableListContainerFactory implements EmbeddableFactoryDefinition {
@@ -43,8 +43,8 @@ export class SearchableListContainerFactory implements EmbeddableFactoryDefiniti
}
public create = async (initialInput: SearchableContainerInput) => {
- const { getEmbeddableFactory } = await this.getStartServices();
- return new SearchableListContainer(initialInput, getEmbeddableFactory);
+ const { embeddableServices } = await this.getStartServices();
+ return new SearchableListContainer(initialInput, embeddableServices);
};
public getDisplayName() {
diff --git a/examples/embeddable_examples/public/todo/todo_component.tsx b/examples/embeddable_examples/public/todo/todo_component.tsx
index fbebfc98627b5..a4593bea3cc5e 100644
--- a/examples/embeddable_examples/public/todo/todo_component.tsx
+++ b/examples/embeddable_examples/public/todo/todo_component.tsx
@@ -51,12 +51,12 @@ function wrapSearchTerms(task: string, search?: string) {
export function TodoEmbeddableComponentInner({ input: { icon, title, task, search } }: Props) {
return (
-
+
{icon ? : }
-
+
{wrapSearchTerms(title || '', search)}
@@ -71,4 +71,8 @@ export function TodoEmbeddableComponentInner({ input: { icon, title, task, searc
);
}
-export const TodoEmbeddableComponent = withEmbeddableSubscription(TodoEmbeddableComponentInner);
+export const TodoEmbeddableComponent = withEmbeddableSubscription<
+ TodoInput,
+ EmbeddableOutput,
+ TodoEmbeddable
+>(TodoEmbeddableComponentInner);
diff --git a/examples/embeddable_explorer/public/app.tsx b/examples/embeddable_explorer/public/app.tsx
index 9c8568454855d..e18012b4b3d80 100644
--- a/examples/embeddable_explorer/public/app.tsx
+++ b/examples/embeddable_explorer/public/app.tsx
@@ -117,18 +117,7 @@ const EmbeddableExplorerApp = ({
{
title: 'Dynamically adding children to a container',
id: 'embeddablePanelExamplae',
- component: (
-
- ),
+ component: ,
},
];
diff --git a/examples/embeddable_explorer/public/embeddable_panel_example.tsx b/examples/embeddable_explorer/public/embeddable_panel_example.tsx
index b26111bed7ff2..54cd7c5b5b2c0 100644
--- a/examples/embeddable_explorer/public/embeddable_panel_example.tsx
+++ b/examples/embeddable_explorer/public/embeddable_panel_example.tsx
@@ -29,43 +29,19 @@ import {
EuiText,
} from '@elastic/eui';
import { EuiSpacer } from '@elastic/eui';
-import { OverlayStart, CoreStart, SavedObjectsStart, IUiSettingsClient } from 'kibana/public';
-import {
- EmbeddablePanel,
- EmbeddableStart,
- IEmbeddable,
-} from '../../../src/plugins/embeddable/public';
+import { EmbeddableStart, IEmbeddable } from '../../../src/plugins/embeddable/public';
import {
HELLO_WORLD_EMBEDDABLE,
TODO_EMBEDDABLE,
MULTI_TASK_TODO_EMBEDDABLE,
SEARCHABLE_LIST_CONTAINER,
} from '../../embeddable_examples/public';
-import { UiActionsStart } from '../../../src/plugins/ui_actions/public';
-import { Start as InspectorStartContract } from '../../../src/plugins/inspector/public';
-import { getSavedObjectFinder } from '../../../src/plugins/saved_objects/public';
interface Props {
- getAllEmbeddableFactories: EmbeddableStart['getEmbeddableFactories'];
- getEmbeddableFactory: EmbeddableStart['getEmbeddableFactory'];
- uiActionsApi: UiActionsStart;
- overlays: OverlayStart;
- notifications: CoreStart['notifications'];
- inspector: InspectorStartContract;
- savedObject: SavedObjectsStart;
- uiSettingsClient: IUiSettingsClient;
+ embeddableServices: EmbeddableStart;
}
-export function EmbeddablePanelExample({
- inspector,
- notifications,
- overlays,
- getAllEmbeddableFactories,
- getEmbeddableFactory,
- uiActionsApi,
- savedObject,
- uiSettingsClient,
-}: Props) {
+export function EmbeddablePanelExample({ embeddableServices }: Props) {
const searchableInput = {
id: '1',
title: 'My searchable todo list',
@@ -105,7 +81,7 @@ export function EmbeddablePanelExample({
useEffect(() => {
ref.current = true;
if (!embeddable) {
- const factory = getEmbeddableFactory(SEARCHABLE_LIST_CONTAINER);
+ const factory = embeddableServices.getEmbeddableFactory(SEARCHABLE_LIST_CONTAINER);
const promise = factory?.create(searchableInput);
if (promise) {
promise.then(e => {
@@ -134,22 +110,13 @@ export function EmbeddablePanelExample({
You can render your embeddable inside the EmbeddablePanel component. This adds some
extra rendering and offers a context menu with pluggable actions. Using EmbeddablePanel
- to render your embeddable means you get access to the "e;Add panel flyout"e;.
- Now you can see how to add embeddables to your container, and how
- "e;getExplicitInput"e; is used to grab input not provided by the container.
+ to render your embeddable means you get access to the "Add panel flyout". Now
+ you can see how to add embeddables to your container, and how
+ "getExplicitInput" is used to grab input not provided by the container.
{embeddable ? (
-
+
) : (
Loading...
)}
diff --git a/examples/embeddable_explorer/public/list_container_example.tsx b/examples/embeddable_explorer/public/list_container_example.tsx
index 969fdb0ca46db..98ad50418d3fe 100644
--- a/examples/embeddable_explorer/public/list_container_example.tsx
+++ b/examples/embeddable_explorer/public/list_container_example.tsx
@@ -29,7 +29,11 @@ import {
EuiText,
} from '@elastic/eui';
import { EuiSpacer } from '@elastic/eui';
-import { EmbeddableFactoryRenderer, EmbeddableStart } from '../../../src/plugins/embeddable/public';
+import {
+ EmbeddableFactoryRenderer,
+ EmbeddableStart,
+ ViewMode,
+} from '../../../src/plugins/embeddable/public';
import {
HELLO_WORLD_EMBEDDABLE,
TODO_EMBEDDABLE,
@@ -46,6 +50,7 @@ export function ListContainerExample({ getEmbeddableFactory }: Props) {
const listInput = {
id: 'hello',
title: 'My todo list',
+ viewMode: ViewMode.VIEW,
panels: {
'1': {
type: HELLO_WORLD_EMBEDDABLE,
@@ -76,6 +81,7 @@ export function ListContainerExample({ getEmbeddableFactory }: Props) {
const searchableInput = {
id: '1',
title: 'My searchable todo list',
+ viewMode: ViewMode.VIEW,
panels: {
'1': {
type: HELLO_WORLD_EMBEDDABLE,
@@ -150,7 +156,7 @@ export function ListContainerExample({ getEmbeddableFactory }: Props) {
- Check out the "e;Dynamically adding children"e; section, to see how to add
+ Check out the "Dynamically adding children" section, to see how to add
children to this container, and see it rendered inside an `EmbeddablePanel` component.
diff --git a/src/plugins/embeddable/public/lib/containers/embeddable_child_panel.test.tsx b/src/plugins/embeddable/public/lib/containers/embeddable_child_panel.test.tsx
index 9e47da5cea032..2a0ffd723850b 100644
--- a/src/plugins/embeddable/public/lib/containers/embeddable_child_panel.test.tsx
+++ b/src/plugins/embeddable/public/lib/containers/embeddable_child_panel.test.tsx
@@ -29,7 +29,7 @@ import {
ContactCardEmbeddable,
} from '../test_samples/embeddables/contact_card/contact_card_embeddable';
// eslint-disable-next-line
-import { inspectorPluginMock } from 'src/plugins/inspector/public/mocks';
+import { inspectorPluginMock } from '../../../../inspector/public/mocks';
import { mount } from 'enzyme';
import { embeddablePluginMock } from '../../mocks';
diff --git a/src/plugins/embeddable/public/lib/embeddables/with_subscription.tsx b/src/plugins/embeddable/public/lib/embeddables/with_subscription.tsx
index 47b8001961cf5..9bc5889715c76 100644
--- a/src/plugins/embeddable/public/lib/embeddables/with_subscription.tsx
+++ b/src/plugins/embeddable/public/lib/embeddables/with_subscription.tsx
@@ -23,18 +23,19 @@ import { IEmbeddable, EmbeddableInput, EmbeddableOutput } from './i_embeddable';
export const withEmbeddableSubscription = <
I extends EmbeddableInput,
O extends EmbeddableOutput,
- E extends IEmbeddable = IEmbeddable
+ E extends IEmbeddable = IEmbeddable,
+ ExtraProps = {}
>(
- WrappedComponent: React.ComponentType<{ input: I; output: O; embeddable: E }>
-): React.ComponentType<{ embeddable: E }> =>
+ WrappedComponent: React.ComponentType<{ input: I; output: O; embeddable: E } & ExtraProps>
+): React.ComponentType<{ embeddable: E } & ExtraProps> =>
class WithEmbeddableSubscription extends React.Component<
- { embeddable: E },
+ { embeddable: E } & ExtraProps,
{ input: I; output: O }
> {
private subscription?: Rx.Subscription;
private mounted: boolean = false;
- constructor(props: { embeddable: E }) {
+ constructor(props: { embeddable: E } & ExtraProps) {
super(props);
this.state = {
input: this.props.embeddable.getInput(),
@@ -71,6 +72,7 @@ export const withEmbeddableSubscription = <
input={this.state.input}
output={this.state.output}
embeddable={this.props.embeddable}
+ {...this.props}
/>
);
}
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 649677dc67c7d..1e7cbb2f3dafc 100644
--- a/src/plugins/embeddable/public/lib/panel/embeddable_panel.test.tsx
+++ b/src/plugins/embeddable/public/lib/panel/embeddable_panel.test.tsx
@@ -25,7 +25,7 @@ import { nextTick } from 'test_utils/enzyme_helpers';
import { findTestSubject } from '@elastic/eui/lib/test';
import { I18nProvider } from '@kbn/i18n/react';
import { CONTEXT_MENU_TRIGGER } from '../triggers';
-import { Action, UiActionsStart, ActionType } from 'src/plugins/ui_actions/public';
+import { Action, UiActionsStart, ActionType } from '../../../../ui_actions/public';
import { Trigger, ViewMode } from '../types';
import { isErrorEmbeddable } from '../embeddables';
import { EmbeddablePanel } from './embeddable_panel';
@@ -41,7 +41,7 @@ import {
ContactCardEmbeddableOutput,
} from '../test_samples/embeddables/contact_card/contact_card_embeddable';
// eslint-disable-next-line
-import { inspectorPluginMock } from 'src/plugins/inspector/public/mocks';
+import { inspectorPluginMock } from '../../../../inspector/public/mocks';
import { EuiBadge } from '@elastic/eui';
import { embeddablePluginMock } from '../../mocks';
diff --git a/src/plugins/embeddable/public/lib/panel/panel_header/panel_actions/inspect_panel_action.test.tsx b/src/plugins/embeddable/public/lib/panel/panel_header/panel_actions/inspect_panel_action.test.tsx
index ee31127cb5a40..491eaad9faefa 100644
--- a/src/plugins/embeddable/public/lib/panel/panel_header/panel_actions/inspect_panel_action.test.tsx
+++ b/src/plugins/embeddable/public/lib/panel/panel_header/panel_actions/inspect_panel_action.test.tsx
@@ -27,7 +27,7 @@ import {
ContactCardEmbeddable,
} from '../../../test_samples';
// eslint-disable-next-line
-import { inspectorPluginMock } from 'src/plugins/inspector/public/mocks';
+import { inspectorPluginMock } from '../../../../../../../plugins/inspector/public/mocks';
import { EmbeddableOutput, isErrorEmbeddable, ErrorEmbeddable } from '../../../embeddables';
import { of } from '../../../../tests/helpers';
import { esFilters } from '../../../../../../../plugins/data/public';
diff --git a/src/plugins/embeddable/public/mocks.ts b/src/plugins/embeddable/public/mocks.ts
index 2ee05d8316ace..65b15f3a7614f 100644
--- a/src/plugins/embeddable/public/mocks.ts
+++ b/src/plugins/embeddable/public/mocks.ts
@@ -16,11 +16,12 @@
* specific language governing permissions and limitations
* under the License.
*/
-
import { EmbeddableStart, EmbeddableSetup } from '.';
import { EmbeddablePublicPlugin } from './plugin';
import { coreMock } from '../../../core/public/mocks';
+// eslint-disable-next-line
+import { inspectorPluginMock } from '../../inspector/public/mocks';
// eslint-disable-next-line
import { uiActionsPluginMock } from '../../ui_actions/public/mocks';
@@ -39,6 +40,7 @@ const createStartContract = (): Start => {
const startContract: Start = {
getEmbeddableFactories: jest.fn(),
getEmbeddableFactory: jest.fn(),
+ EmbeddablePanel: jest.fn(),
};
return startContract;
};
@@ -48,7 +50,11 @@ const createInstance = () => {
const setup = plugin.setup(coreMock.createSetup(), {
uiActions: uiActionsPluginMock.createSetupContract(),
});
- const doStart = () => plugin.start(coreMock.createStart());
+ const doStart = () =>
+ plugin.start(coreMock.createStart(), {
+ uiActions: uiActionsPluginMock.createStartContract(),
+ inspector: inspectorPluginMock.createStartContract(),
+ });
return {
plugin,
setup,
diff --git a/src/plugins/embeddable/public/plugin.ts b/src/plugins/embeddable/public/plugin.tsx
similarity index 76%
rename from src/plugins/embeddable/public/plugin.ts
rename to src/plugins/embeddable/public/plugin.tsx
index a483f90f76dde..01fbf52c80182 100644
--- a/src/plugins/embeddable/public/plugin.ts
+++ b/src/plugins/embeddable/public/plugin.tsx
@@ -16,7 +16,10 @@
* specific language governing permissions and limitations
* under the License.
*/
-import { UiActionsSetup } from 'src/plugins/ui_actions/public';
+import React from 'react';
+import { getSavedObjectFinder } from '../../saved_objects/public';
+import { UiActionsSetup, UiActionsStart } from '../../ui_actions/public';
+import { Start as InspectorStart } from '../../inspector/public';
import { PluginInitializerContext, CoreSetup, CoreStart, Plugin } from '../../../core/public';
import { EmbeddableFactoryRegistry, EmbeddableFactoryProvider } from './types';
import { bootstrap } from './bootstrap';
@@ -26,6 +29,7 @@ import {
EmbeddableOutput,
defaultEmbeddableFactoryProvider,
IEmbeddable,
+ EmbeddablePanel,
} from './lib';
import { EmbeddableFactoryDefinition } from './lib/embeddables/embeddable_factory_definition';
@@ -33,6 +37,11 @@ export interface EmbeddableSetupDependencies {
uiActions: UiActionsSetup;
}
+export interface EmbeddableStartDependencies {
+ uiActions: UiActionsStart;
+ inspector: InspectorStart;
+}
+
export interface EmbeddableSetup {
registerEmbeddableFactory: (
id: string,
@@ -50,6 +59,7 @@ export interface EmbeddableStart {
embeddableFactoryId: string
) => EmbeddableFactory | undefined;
getEmbeddableFactories: () => IterableIterator;
+ EmbeddablePanel: React.FC<{ embeddable: IEmbeddable; hideHeader?: boolean }>;
}
export class EmbeddablePublicPlugin implements Plugin {
@@ -78,7 +88,10 @@ export class EmbeddablePublicPlugin implements Plugin {
this.embeddableFactories.set(
def.type,
@@ -89,15 +102,36 @@ export class EmbeddablePublicPlugin implements Plugin {
- this.ensureFactoriesExist();
- return this.embeddableFactories.values();
- },
+ getEmbeddableFactories: this.getEmbeddableFactories,
+ EmbeddablePanel: ({
+ embeddable,
+ hideHeader,
+ }: {
+ embeddable: IEmbeddable;
+ hideHeader?: boolean;
+ }) => (
+
+ ),
};
}
public stop() {}
+ private getEmbeddableFactories = () => {
+ this.ensureFactoriesExist();
+ return this.embeddableFactories.values();
+ };
+
private registerEmbeddableFactory = (
embeddableFactoryId: string,
factory: EmbeddableFactoryDefinition
@@ -130,11 +164,11 @@ export class EmbeddablePublicPlugin implements Plugin {
this.embeddableFactoryDefinitions.forEach(def => this.ensureFactoryExists(def.type));
- }
+ };
- private ensureFactoryExists(type: string) {
+ private ensureFactoryExists = (type: string) => {
if (!this.embeddableFactories.get(type)) {
const def = this.embeddableFactoryDefinitions.get(type);
if (!def) return;
@@ -145,5 +179,5 @@ export class EmbeddablePublicPlugin implements Plugin {
diff --git a/src/plugins/embeddable/public/tests/test_plugin.ts b/src/plugins/embeddable/public/tests/test_plugin.ts
index e199ef193aa1c..e13a906e30338 100644
--- a/src/plugins/embeddable/public/tests/test_plugin.ts
+++ b/src/plugins/embeddable/public/tests/test_plugin.ts
@@ -18,9 +18,11 @@
*/
import { CoreSetup, CoreStart } from 'src/core/public';
+import { UiActionsStart } from '../../../ui_actions/public';
// eslint-disable-next-line
-import { uiActionsPluginMock } from 'src/plugins/ui_actions/public/mocks';
-import { UiActionsStart } from 'src/plugins/ui_actions/public';
+import { uiActionsPluginMock } from '../../../ui_actions/public/mocks';
+// eslint-disable-next-line
+import { inspectorPluginMock } from '../../../inspector/public/mocks';
import { coreMock } from '../../../../core/public/mocks';
import { EmbeddablePublicPlugin, EmbeddableSetup, EmbeddableStart } from '../plugin';
@@ -48,7 +50,10 @@ export const testPlugin = (
coreStart,
setup,
doStart: (anotherCoreStart: CoreStart = coreStart) => {
- const start = plugin.start(anotherCoreStart);
+ const start = plugin.start(anotherCoreStart, {
+ uiActions: uiActionsPluginMock.createStartContract(),
+ inspector: inspectorPluginMock.createStartContract(),
+ });
return start;
},
uiActions: uiActions.doStart(coreStart),
diff --git a/test/examples/embeddables/list_container.ts b/test/examples/embeddables/list_container.ts
index b1b91ad2c37f1..9e93d479471e8 100644
--- a/test/examples/embeddables/list_container.ts
+++ b/test/examples/embeddables/list_container.ts
@@ -57,13 +57,12 @@ export default function({ getService }: PluginFunctionalProviderContext) {
expect(text).to.eql(['HELLO WORLD!']);
});
- it('searchable container filters multi-task children', async () => {
+ it('searchable container finds matches in multi-task children', async () => {
await testSubjects.setValue('filterTodos', 'earth');
+ await testSubjects.click('checkMatchingTodos');
+ await testSubjects.click('deleteCheckedTodos');
- await retry.try(async () => {
- const tasks = await testSubjects.getVisibleTextAll('multiTaskTodoTask');
- expect(tasks).to.eql(['Watch planet earth']);
- });
+ await testSubjects.missingOrFail('multiTaskTodoTask');
});
});
}
diff --git a/test/plugin_functional/plugins/kbn_tp_embeddable_explorer/public/np_ready/public/app/app.tsx b/test/plugin_functional/plugins/kbn_tp_embeddable_explorer/public/np_ready/public/app/app.tsx
index 54d13efe4d790..2ecde823dc4df 100644
--- a/test/plugin_functional/plugins/kbn_tp_embeddable_explorer/public/np_ready/public/app/app.tsx
+++ b/test/plugin_functional/plugins/kbn_tp_embeddable_explorer/public/np_ready/public/app/app.tsx
@@ -18,21 +18,11 @@
*/
import { EuiTab } from '@elastic/eui';
import React, { Component } from 'react';
-import { CoreStart } from 'src/core/public';
import { EmbeddableStart } from 'src/plugins/embeddable/public';
-import { UiActionsService } from '../../../../../../../../src/plugins/ui_actions/public';
import { DashboardContainerExample } from './dashboard_container_example';
-import { Start as InspectorStartContract } from '../../../../../../../../src/plugins/inspector/public';
export interface AppProps {
- getActions: UiActionsService['getTriggerCompatibleActions'];
- getEmbeddableFactory: EmbeddableStart['getEmbeddableFactory'];
- getAllEmbeddableFactories: EmbeddableStart['getEmbeddableFactories'];
- overlays: CoreStart['overlays'];
- notifications: CoreStart['notifications'];
- inspector: InspectorStartContract;
- SavedObjectFinder: React.ComponentType;
- I18nContext: CoreStart['i18n']['Context'];
+ embeddableServices: EmbeddableStart;
}
export class App extends Component {
@@ -72,29 +62,17 @@ export class App extends Component {
public render() {
return (
-
-
-
{this.renderTabs()}
- {this.getContentsForTab()}
-
-
+
+
{this.renderTabs()}
+ {this.getContentsForTab()}
+
);
}
private getContentsForTab() {
switch (this.state.selectedTabId) {
case 'dashboardContainer': {
- return (
-
- );
+ return ;
}
}
}
diff --git a/test/plugin_functional/plugins/kbn_tp_embeddable_explorer/public/np_ready/public/app/dashboard_container_example.tsx b/test/plugin_functional/plugins/kbn_tp_embeddable_explorer/public/np_ready/public/app/dashboard_container_example.tsx
index fd07416cadbc5..16c2840d6a32e 100644
--- a/test/plugin_functional/plugins/kbn_tp_embeddable_explorer/public/np_ready/public/app/dashboard_container_example.tsx
+++ b/test/plugin_functional/plugins/kbn_tp_embeddable_explorer/public/np_ready/public/app/dashboard_container_example.tsx
@@ -19,32 +19,17 @@
import React from 'react';
import { EuiButton, EuiLoadingChart } from '@elastic/eui';
import { ContainerOutput } from 'src/plugins/embeddable/public';
-import {
- ErrorEmbeddable,
- ViewMode,
- isErrorEmbeddable,
- EmbeddablePanel,
- EmbeddableStart,
-} from '../embeddable_api';
+import { ErrorEmbeddable, ViewMode, isErrorEmbeddable, EmbeddableStart } from '../embeddable_api';
import {
DASHBOARD_CONTAINER_TYPE,
DashboardContainer,
DashboardContainerInput,
} from '../../../../../../../../src/plugins/dashboard/public';
-import { CoreStart } from '../../../../../../../../src/core/public';
import { dashboardInput } from './dashboard_input';
-import { Start as InspectorStartContract } from '../../../../../../../../src/plugins/inspector/public';
-import { UiActionsService } from '../../../../../../../../src/plugins/ui_actions/public';
interface Props {
- getActions: UiActionsService['getTriggerCompatibleActions'];
- getEmbeddableFactory: EmbeddableStart['getEmbeddableFactory'];
- getAllEmbeddableFactories: EmbeddableStart['getEmbeddableFactories'];
- overlays: CoreStart['overlays'];
- notifications: CoreStart['notifications'];
- inspector: InspectorStartContract;
- SavedObjectFinder: React.ComponentType;
+ embeddableServices: EmbeddableStart;
}
interface State {
@@ -67,7 +52,7 @@ export class DashboardContainerExample extends React.Component {
public async componentDidMount() {
this.mounted = true;
- const dashboardFactory = this.props.getEmbeddableFactory<
+ const dashboardFactory = this.props.embeddableServices.getEmbeddableFactory<
DashboardContainerInput,
ContainerOutput,
DashboardContainer
@@ -99,6 +84,7 @@ export class DashboardContainerExample extends React.Component {
};
public render() {
+ const { embeddableServices } = this.props;
return (
Dashboard Container
@@ -108,16 +94,7 @@ export class DashboardContainerExample extends React.Component
{
{!this.state.loaded || !this.container ? (
) : (
-
+
)}
);
diff --git a/test/plugin_functional/plugins/kbn_tp_embeddable_explorer/public/np_ready/public/plugin.tsx b/test/plugin_functional/plugins/kbn_tp_embeddable_explorer/public/np_ready/public/plugin.tsx
index 18ceec652392d..e5f5faa6ac361 100644
--- a/test/plugin_functional/plugins/kbn_tp_embeddable_explorer/public/np_ready/public/plugin.tsx
+++ b/test/plugin_functional/plugins/kbn_tp_embeddable_explorer/public/np_ready/public/plugin.tsx
@@ -33,7 +33,6 @@ const REACT_ROOT_ID = 'embeddableExplorerRoot';
import { SayHelloAction, createSendMessageAction } from './embeddable_api';
import { App } from './app';
-import { getSavedObjectFinder } from '../../../../../../../src/plugins/saved_objects/public';
import {
EmbeddableStart,
EmbeddableSetup,
@@ -78,19 +77,7 @@ export class EmbeddableExplorerPublicPlugin
plugins.__LEGACY.onRenderComplete(() => {
const root = document.getElementById(REACT_ROOT_ID);
- ReactDOM.render(
- ,
- root
- );
+ ReactDOM.render(, root);
});
}