Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Embeddable clean up #62486

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -31,24 +31,25 @@ 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) {
this.node = node;
if (this.node) {
ReactDOM.unmountComponentAtNode(this.node);
}
ReactDOM.render(<ListContainerComponent embeddable={this} />, node);
ReactDOM.render(
<ListContainerComponent embeddable={this} embeddableServices={this.embeddableServices} />,
node
);
}

public destroy() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand All @@ -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>
);
}
Expand All @@ -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);
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import {
import { LIST_CONTAINER, ListContainer } from './list_container';

interface StartServices {
getEmbeddableFactory: EmbeddableStart['getEmbeddableFactory'];
embeddableServices: EmbeddableStart;
}

export class ListContainerFactory implements EmbeddableFactoryDefinition {
Expand All @@ -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() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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}
Expand All @@ -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>
Expand All @@ -89,6 +88,8 @@ export function MultiTaskTodoEmbeddableComponentInner({
);
}

export const MultiTaskTodoEmbeddableComponent = withEmbeddableSubscription(
MultiTaskTodoEmbeddableComponentInner
);
export const MultiTaskTodoEmbeddableComponent = withEmbeddableSubscription<
MultiTaskTodoInput,
MultiTaskTodoOutput,
MultiTaskTodoEmbeddable
>(MultiTaskTodoEmbeddableComponentInner);
Original file line number Diff line number Diff line change
Expand Up @@ -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<MultiTaskTodoInput, MultiTaskTodoOutput> {
Expand Down
7 changes: 2 additions & 5 deletions examples/embeddable_examples/public/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
}))
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -53,6 +50,7 @@ export class SearchableListContainer extends Container<ChildInput, SearchableCon
return {
id,
search: this.getInput().search,
viewMode: this.input.viewMode,
};
}

Expand All @@ -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() {
Expand Down
Loading