mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 17:28:26 -04:00
Prep for embed saved object refactor + helper (#62486)
This commit is contained in:
parent
0ebfe76b3f
commit
dfa083dc60
26 changed files with 234 additions and 303 deletions
|
@ -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<Props> {
|
||||
private embeddableRoot: React.RefObject<HTMLDivElement>;
|
||||
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 (
|
||||
<EuiFlexItem>
|
||||
<EuiPanel>
|
||||
{this.props.embeddable ? (
|
||||
<div ref={this.embeddableRoot} />
|
||||
) : (
|
||||
<EuiLoadingSpinner size="s" />
|
||||
)}
|
||||
</EuiPanel>
|
||||
</EuiFlexItem>
|
||||
);
|
||||
}
|
||||
}
|
|
@ -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(<ListContainerComponent embeddable={this} />, node);
|
||||
ReactDOM.render(
|
||||
<ListContainerComponent embeddable={this} embeddableServices={this.embeddableServices} />,
|
||||
node
|
||||
);
|
||||
}
|
||||
|
||||
public destroy() {
|
||||
|
|
|
@ -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 (
|
||||
<EuiPanel key={number.toString()}>
|
||||
<EuiFlexGroup>
|
||||
<EuiFlexGroup gutterSize="none">
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiText>
|
||||
<h3>{number}</h3>
|
||||
</EuiText>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EmbeddableListItem embeddable={child} />
|
||||
<embeddableServices.EmbeddablePanel embeddable={child} />
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
</EuiPanel>
|
||||
|
@ -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 (
|
||||
<div>
|
||||
<h2 data-test-subj="listContainerTitle">{props.embeddable.getTitle()}</h2>
|
||||
<h2 data-test-subj="listContainerTitle">{embeddable.getTitle()}</h2>
|
||||
<EuiSpacer size="l" />
|
||||
{renderList(props.embeddable, props.input.panels)}
|
||||
{renderList(embeddable, input.panels, embeddableServices)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -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);
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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 => (
|
||||
<EuiListGroupItem
|
||||
key={task}
|
||||
|
@ -65,16 +65,15 @@ function renderTasks(tasks: MultiTaskTodoOutput['tasks'], search?: string) {
|
|||
}
|
||||
|
||||
export function MultiTaskTodoEmbeddableComponentInner({
|
||||
input: { title, icon, search },
|
||||
output: { tasks },
|
||||
input: { title, icon, search, tasks },
|
||||
}: Props) {
|
||||
return (
|
||||
<EuiFlexGroup>
|
||||
<EuiFlexGroup gutterSize="none">
|
||||
<EuiFlexItem grow={false}>
|
||||
{icon ? <EuiIcon type={icon} size="l" /> : <EuiAvatar name={title} size="l" />}
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EuiFlexGrid columns={1}>
|
||||
<EuiFlexGrid columns={1} gutterSize="none">
|
||||
<EuiFlexItem>
|
||||
<EuiText data-test-subj="multiTaskTodoTitle">
|
||||
<h3>{wrapSearchTerms(title, search)}</h3>
|
||||
|
@ -89,6 +88,8 @@ export function MultiTaskTodoEmbeddableComponentInner({
|
|||
);
|
||||
}
|
||||
|
||||
export const MultiTaskTodoEmbeddableComponent = withEmbeddableSubscription(
|
||||
MultiTaskTodoEmbeddableComponentInner
|
||||
);
|
||||
export const MultiTaskTodoEmbeddableComponent = withEmbeddableSubscription<
|
||||
MultiTaskTodoInput,
|
||||
MultiTaskTodoOutput,
|
||||
MultiTaskTodoEmbeddable
|
||||
>(MultiTaskTodoEmbeddableComponentInner);
|
||||
|
|
|
@ -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;
|
||||
|
||||
return filteredTasks;
|
||||
const match = tasks.find(task => task.match(search));
|
||||
if (match) return true;
|
||||
|
||||
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<MultiTaskTodoInput, MultiTaskTodoOutput> {
|
||||
|
|
|
@ -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,
|
||||
}))
|
||||
);
|
||||
|
||||
|
|
|
@ -40,11 +40,8 @@ export class SearchableListContainer extends Container<ChildInput, SearchableCon
|
|||
public readonly type = SEARCHABLE_LIST_CONTAINER;
|
||||
private node?: HTMLElement;
|
||||
|
||||
constructor(
|
||||
input: SearchableContainerInput,
|
||||
getEmbeddableFactory: EmbeddableStart['getEmbeddableFactory']
|
||||
) {
|
||||
super(input, { embeddableLoaded: {} }, getEmbeddableFactory);
|
||||
constructor(input: SearchableContainerInput, private embeddableServices: EmbeddableStart) {
|
||||
super(input, { embeddableLoaded: {} }, embeddableServices.getEmbeddableFactory);
|
||||
}
|
||||
|
||||
// TODO: add a more advanced example here where inherited child input is derived from container
|
||||
|
@ -53,6 +50,7 @@ export class SearchableListContainer extends Container<ChildInput, SearchableCon
|
|||
return {
|
||||
id,
|
||||
search: this.getInput().search,
|
||||
viewMode: this.input.viewMode,
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -61,7 +59,13 @@ export class SearchableListContainer extends Container<ChildInput, SearchableCon
|
|||
ReactDOM.unmountComponentAtNode(this.node);
|
||||
}
|
||||
this.node = node;
|
||||
ReactDOM.render(<SearchableListContainerComponent embeddable={this} />, node);
|
||||
ReactDOM.render(
|
||||
<SearchableListContainerComponent
|
||||
embeddable={this}
|
||||
embeddableServices={this.embeddableServices}
|
||||
/>,
|
||||
node
|
||||
);
|
||||
}
|
||||
|
||||
public destroy() {
|
||||
|
|
|
@ -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<Props, Stat
|
|||
});
|
||||
};
|
||||
|
||||
private checkMatching = () => {
|
||||
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 (
|
||||
<EuiFlexGroup>
|
||||
<EuiFlexGroup gutterSize="s">
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiFormRow hasEmptyLabelSpace>
|
||||
<EuiButton data-test-subj="deleteCheckedTodos" onClick={() => this.deleteChecked()}>
|
||||
|
@ -125,6 +140,17 @@ export class SearchableListContainerComponentInner extends Component<Props, Stat
|
|||
</EuiButton>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiFormRow hasEmptyLabelSpace>
|
||||
<EuiButton
|
||||
data-test-subj="checkMatchingTodos"
|
||||
disabled={input.search === ''}
|
||||
onClick={() => this.checkMatching()}
|
||||
>
|
||||
Check matching
|
||||
</EuiButton>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EuiFormRow label="Filter">
|
||||
<EuiFieldText
|
||||
|
@ -142,36 +168,38 @@ export class SearchableListContainerComponentInner extends Component<Props, Stat
|
|||
public render() {
|
||||
const { embeddable } = this.props;
|
||||
return (
|
||||
<div>
|
||||
<h2 data-test-subj="searchableListContainerTitle">{embeddable.getTitle()}</h2>
|
||||
<EuiSpacer size="l" />
|
||||
{this.renderControls()}
|
||||
<EuiSpacer size="l" />
|
||||
{this.renderList()}
|
||||
</div>
|
||||
<EuiFlexGroup gutterSize="none">
|
||||
<EuiFlexItem>
|
||||
<h2 data-test-subj="searchableListContainerTitle">{embeddable.getTitle()}</h2>
|
||||
<EuiSpacer size="l" />
|
||||
{this.renderControls()}
|
||||
<EuiSpacer size="l" />
|
||||
{this.renderList()}
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
);
|
||||
}
|
||||
|
||||
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 ? (
|
||||
<EuiPanel key={embeddable.id}>
|
||||
<EuiFlexGroup>
|
||||
return childEmbeddable ? (
|
||||
<EuiPanel key={childEmbeddable.id}>
|
||||
<EuiFlexGroup gutterSize="none">
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiCheckbox
|
||||
data-test-subj={`todoCheckBox-${embeddable.id}`}
|
||||
disabled={!embeddable}
|
||||
id={embeddable ? embeddable.id : ''}
|
||||
checked={this.state.checked[embeddable.id]}
|
||||
onChange={e => 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)}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EmbeddableListItem embeddable={embeddable} />
|
||||
<embeddableServices.EmbeddablePanel embeddable={childEmbeddable} />
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
</EuiPanel>
|
||||
|
@ -183,6 +211,9 @@ export class SearchableListContainerComponentInner extends Component<Props, Stat
|
|||
}
|
||||
}
|
||||
|
||||
export const SearchableListContainerComponent = withEmbeddableSubscription(
|
||||
SearchableListContainerComponentInner
|
||||
);
|
||||
export const SearchableListContainerComponent = withEmbeddableSubscription<
|
||||
SearchableContainerInput,
|
||||
ContainerOutput,
|
||||
SearchableListContainer,
|
||||
{ embeddableServices: EmbeddableStart }
|
||||
>(SearchableListContainerComponentInner);
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -51,12 +51,12 @@ function wrapSearchTerms(task: string, search?: string) {
|
|||
|
||||
export function TodoEmbeddableComponentInner({ input: { icon, title, task, search } }: Props) {
|
||||
return (
|
||||
<EuiFlexGroup>
|
||||
<EuiFlexGroup gutterSize="none">
|
||||
<EuiFlexItem grow={false}>
|
||||
{icon ? <EuiIcon type={icon} size="l" /> : <EuiAvatar name={title || task} size="l" />}
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EuiFlexGrid columns={1}>
|
||||
<EuiFlexGrid columns={1} gutterSize="none">
|
||||
<EuiFlexItem>
|
||||
<EuiText data-test-subj="todoEmbeddableTitle">
|
||||
<h3>{wrapSearchTerms(title || '', search)}</h3>
|
||||
|
@ -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);
|
||||
|
|
|
@ -117,18 +117,7 @@ const EmbeddableExplorerApp = ({
|
|||
{
|
||||
title: 'Dynamically adding children to a container',
|
||||
id: 'embeddablePanelExamplae',
|
||||
component: (
|
||||
<EmbeddablePanelExample
|
||||
uiActionsApi={uiActionsApi}
|
||||
getAllEmbeddableFactories={embeddableApi.getEmbeddableFactories}
|
||||
getEmbeddableFactory={embeddableApi.getEmbeddableFactory}
|
||||
overlays={overlays}
|
||||
uiSettingsClient={uiSettingsClient}
|
||||
savedObject={savedObject}
|
||||
notifications={notifications}
|
||||
inspector={inspector}
|
||||
/>
|
||||
),
|
||||
component: <EmbeddablePanelExample embeddableServices={embeddableApi} />,
|
||||
},
|
||||
];
|
||||
|
||||
|
|
|
@ -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({
|
|||
<EuiText>
|
||||
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.
|
||||
</EuiText>
|
||||
<EuiPanel data-test-subj="embeddedPanelExample" paddingSize="none" role="figure">
|
||||
{embeddable ? (
|
||||
<EmbeddablePanel
|
||||
embeddable={embeddable}
|
||||
getActions={uiActionsApi.getTriggerCompatibleActions}
|
||||
getEmbeddableFactory={getEmbeddableFactory}
|
||||
getAllEmbeddableFactories={getAllEmbeddableFactories}
|
||||
overlays={overlays}
|
||||
notifications={notifications}
|
||||
inspector={inspector}
|
||||
SavedObjectFinder={getSavedObjectFinder(savedObject, uiSettingsClient)}
|
||||
/>
|
||||
<embeddableServices.EmbeddablePanel embeddable={embeddable} />
|
||||
) : (
|
||||
<EuiText>Loading...</EuiText>
|
||||
)}
|
||||
|
|
|
@ -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) {
|
|||
</p>
|
||||
|
||||
<p>
|
||||
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.
|
||||
</p>
|
||||
</EuiText>
|
||||
|
|
|
@ -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';
|
||||
|
||||
|
|
|
@ -23,18 +23,19 @@ import { IEmbeddable, EmbeddableInput, EmbeddableOutput } from './i_embeddable';
|
|||
export const withEmbeddableSubscription = <
|
||||
I extends EmbeddableInput,
|
||||
O extends EmbeddableOutput,
|
||||
E extends IEmbeddable<I, O> = IEmbeddable<I, O>
|
||||
E extends IEmbeddable<I, O> = IEmbeddable<I, O>,
|
||||
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}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -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';
|
||||
|
||||
|
|
|
@ -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';
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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: <I extends EmbeddableInput, O extends EmbeddableOutput>(
|
||||
id: string,
|
||||
|
@ -50,6 +59,7 @@ export interface EmbeddableStart {
|
|||
embeddableFactoryId: string
|
||||
) => EmbeddableFactory<I, O, E> | undefined;
|
||||
getEmbeddableFactories: () => IterableIterator<EmbeddableFactory>;
|
||||
EmbeddablePanel: React.FC<{ embeddable: IEmbeddable; hideHeader?: boolean }>;
|
||||
}
|
||||
|
||||
export class EmbeddablePublicPlugin implements Plugin<EmbeddableSetup, EmbeddableStart> {
|
||||
|
@ -78,7 +88,10 @@ export class EmbeddablePublicPlugin implements Plugin<EmbeddableSetup, Embeddabl
|
|||
};
|
||||
}
|
||||
|
||||
public start(core: CoreStart): EmbeddableStart {
|
||||
public start(
|
||||
core: CoreStart,
|
||||
{ uiActions, inspector }: EmbeddableStartDependencies
|
||||
): EmbeddableStart {
|
||||
this.embeddableFactoryDefinitions.forEach(def => {
|
||||
this.embeddableFactories.set(
|
||||
def.type,
|
||||
|
@ -89,15 +102,36 @@ export class EmbeddablePublicPlugin implements Plugin<EmbeddableSetup, Embeddabl
|
|||
});
|
||||
return {
|
||||
getEmbeddableFactory: this.getEmbeddableFactory,
|
||||
getEmbeddableFactories: () => {
|
||||
this.ensureFactoriesExist();
|
||||
return this.embeddableFactories.values();
|
||||
},
|
||||
getEmbeddableFactories: this.getEmbeddableFactories,
|
||||
EmbeddablePanel: ({
|
||||
embeddable,
|
||||
hideHeader,
|
||||
}: {
|
||||
embeddable: IEmbeddable;
|
||||
hideHeader?: boolean;
|
||||
}) => (
|
||||
<EmbeddablePanel
|
||||
hideHeader={hideHeader}
|
||||
embeddable={embeddable}
|
||||
getActions={uiActions.getTriggerCompatibleActions}
|
||||
getEmbeddableFactory={this.getEmbeddableFactory}
|
||||
getAllEmbeddableFactories={this.getEmbeddableFactories}
|
||||
overlays={core.overlays}
|
||||
notifications={core.notifications}
|
||||
inspector={inspector}
|
||||
SavedObjectFinder={getSavedObjectFinder(core.savedObjects, core.uiSettings)}
|
||||
/>
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
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<EmbeddableSetup, Embeddabl
|
|||
};
|
||||
|
||||
// These two functions are only to support legacy plugins registering factories after the start lifecycle.
|
||||
private ensureFactoriesExist() {
|
||||
private ensureFactoriesExist = () => {
|
||||
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<EmbeddableSetup, Embeddabl
|
|||
: defaultEmbeddableFactoryProvider(def)
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
|
@ -31,7 +31,7 @@ import {
|
|||
FilterableEmbeddableInput,
|
||||
} from '../lib/test_samples';
|
||||
// eslint-disable-next-line
|
||||
import { inspectorPluginMock } from 'src/plugins/inspector/public/mocks';
|
||||
import { inspectorPluginMock } from '../../../../plugins/inspector/public/mocks';
|
||||
import { esFilters } from '../../../../plugins/data/public';
|
||||
|
||||
test('ApplyFilterAction applies the filter to the root of the container tree', async () => {
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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');
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
@ -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<any>;
|
||||
I18nContext: CoreStart['i18n']['Context'];
|
||||
embeddableServices: EmbeddableStart;
|
||||
}
|
||||
|
||||
export class App extends Component<AppProps, { selectedTabId: string }> {
|
||||
|
@ -72,29 +62,17 @@ export class App extends Component<AppProps, { selectedTabId: string }> {
|
|||
|
||||
public render() {
|
||||
return (
|
||||
<this.props.I18nContext>
|
||||
<div id="dashboardViewport" style={{ flex: '1', display: 'flex', flexDirection: 'column' }}>
|
||||
<div>{this.renderTabs()}</div>
|
||||
{this.getContentsForTab()}
|
||||
</div>
|
||||
</this.props.I18nContext>
|
||||
<div id="dashboardViewport" style={{ flex: '1', display: 'flex', flexDirection: 'column' }}>
|
||||
<div>{this.renderTabs()}</div>
|
||||
{this.getContentsForTab()}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
private getContentsForTab() {
|
||||
switch (this.state.selectedTabId) {
|
||||
case 'dashboardContainer': {
|
||||
return (
|
||||
<DashboardContainerExample
|
||||
getActions={this.props.getActions}
|
||||
getEmbeddableFactory={this.props.getEmbeddableFactory}
|
||||
getAllEmbeddableFactories={this.props.getAllEmbeddableFactories}
|
||||
overlays={this.props.overlays}
|
||||
notifications={this.props.notifications}
|
||||
inspector={this.props.inspector}
|
||||
SavedObjectFinder={this.props.SavedObjectFinder}
|
||||
/>
|
||||
);
|
||||
return <DashboardContainerExample embeddableServices={this.props.embeddableServices} />;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<any>;
|
||||
embeddableServices: EmbeddableStart;
|
||||
}
|
||||
|
||||
interface State {
|
||||
|
@ -67,7 +52,7 @@ export class DashboardContainerExample extends React.Component<Props, State> {
|
|||
|
||||
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<Props, State> {
|
|||
};
|
||||
|
||||
public render() {
|
||||
const { embeddableServices } = this.props;
|
||||
return (
|
||||
<div className="app-container dshAppContainer">
|
||||
<h1>Dashboard Container</h1>
|
||||
|
@ -108,16 +94,7 @@ export class DashboardContainerExample extends React.Component<Props, State> {
|
|||
{!this.state.loaded || !this.container ? (
|
||||
<EuiLoadingChart size="l" mono />
|
||||
) : (
|
||||
<EmbeddablePanel
|
||||
embeddable={this.container}
|
||||
getActions={this.props.getActions}
|
||||
getEmbeddableFactory={this.props.getEmbeddableFactory}
|
||||
getAllEmbeddableFactories={this.props.getAllEmbeddableFactories}
|
||||
overlays={this.props.overlays}
|
||||
notifications={this.props.notifications}
|
||||
inspector={this.props.inspector}
|
||||
SavedObjectFinder={this.props.SavedObjectFinder}
|
||||
/>
|
||||
<embeddableServices.EmbeddablePanel embeddable={this.container} />
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -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(
|
||||
<App
|
||||
getActions={plugins.uiActions.getTriggerCompatibleActions}
|
||||
getAllEmbeddableFactories={plugins.embeddable.getEmbeddableFactories}
|
||||
getEmbeddableFactory={plugins.embeddable.getEmbeddableFactory}
|
||||
notifications={core.notifications}
|
||||
overlays={core.overlays}
|
||||
inspector={plugins.inspector}
|
||||
SavedObjectFinder={getSavedObjectFinder(core.savedObjects, core.uiSettings)}
|
||||
I18nContext={core.i18n.Context}
|
||||
/>,
|
||||
root
|
||||
);
|
||||
ReactDOM.render(<App embeddableServices={plugins.embeddable} />, root);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue