[Presentation] Migrate all usages of EuiPage*_Deprecated (#161496)

closes https://github.com/elastic/kibana/issues/161428

PR also updates examples title. Instead of naming the embeddable used,
the title now reflects what the example demonstrates.
* "Hello world embeddable" -> "Render embeddable"
* "Todo embeddable" -> "Update embeddable state"
* "List container embeddable" -> "Groups of embeddables"
* "Dynamically adding children to a container" -> "Context menu"

There is a lot more that could be done to enhance these examples, but I
did not want to get more side tracked then I already did.

---------

Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
Nathan Reese 2023-07-10 12:28:30 -06:00 committed by GitHub
parent 9e5844f715
commit d3d0cdba73
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 187 additions and 300 deletions

View file

@ -10,7 +10,7 @@ import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter as Router, withRouter, RouteComponentProps } from 'react-router-dom';
import { Route } from '@kbn/shared-ux-router';
import { EuiPage, EuiPageSideBar_Deprecated as EuiPageSideBar, EuiSideNav } from '@elastic/eui';
import { EuiPageTemplate, EuiSideNav } from '@elastic/eui';
import { EmbeddableStart } from '@kbn/embeddable-plugin/public';
import { UiActionsStart } from '@kbn/ui-actions-plugin/public';
@ -51,7 +51,7 @@ const Nav = withRouter(({ history, navigateToApp, pages }: NavProps) => {
<EuiSideNav
items={[
{
name: 'Embeddable explorer',
name: 'Embeddable examples',
id: 'home',
items: [...navItems],
},
@ -81,7 +81,7 @@ const EmbeddableExplorerApp = ({
}: Props) => {
const pages: PageDef[] = [
{
title: 'Hello world embeddable',
title: 'Render embeddable',
id: 'helloWorldEmbeddableSection',
component: (
<HelloWorldEmbeddableExample
@ -90,7 +90,7 @@ const EmbeddableExplorerApp = ({
),
},
{
title: 'Todo embeddable',
title: 'Update embeddable state',
id: 'todoEmbeddableSection',
component: (
<TodoEmbeddableExample
@ -99,17 +99,16 @@ const EmbeddableExplorerApp = ({
),
},
{
title: 'List container embeddable',
title: 'Groups of embeddables',
id: 'listContainerSection',
component: (
<ListContainerExample
listContainerEmbeddableFactory={embeddableExamples.factories.getListContainerEmbeddableFactory()}
searchableListContainerEmbeddableFactory={embeddableExamples.factories.getSearchableListContainerEmbeddableFactory()}
/>
),
},
{
title: 'Dynamically adding children to a container',
title: 'Context menu',
id: 'embeddablePanelExample',
component: (
<EmbeddablePanelExample
@ -126,12 +125,12 @@ const EmbeddableExplorerApp = ({
return (
<Router basename={basename}>
<EuiPage>
<EuiPageSideBar>
<EuiPageTemplate offset={0}>
<EuiPageTemplate.Sidebar>
<Nav navigateToApp={navigateToApp} pages={pages} />
</EuiPageSideBar>
</EuiPageTemplate.Sidebar>
{routes}
</EuiPage>
</EuiPageTemplate>
</Router>
);
};

View file

@ -7,16 +7,7 @@
*/
import React, { useState, useEffect, useRef } from 'react';
import {
EuiPanel,
EuiPageBody,
EuiPageContent_Deprecated as EuiPageContent,
EuiPageContentBody_Deprecated as EuiPageContentBody,
EuiPageHeader,
EuiPageHeaderSection,
EuiTitle,
EuiText,
} from '@elastic/eui';
import { EuiPanel, EuiText, EuiPageTemplate } from '@elastic/eui';
import { EuiSpacer } from '@elastic/eui';
import { EmbeddableStart, IEmbeddable } from '@kbn/embeddable-plugin/public';
import {
@ -116,16 +107,10 @@ export function EmbeddablePanelExample({ embeddableServices, searchListContainer
});
return (
<EuiPageBody>
<EuiPageHeader>
<EuiPageHeaderSection>
<EuiTitle size="l">
<h1>The embeddable panel component</h1>
</EuiTitle>
</EuiPageHeaderSection>
</EuiPageHeader>
<EuiPageContent>
<EuiPageContentBody>
<>
<EuiPageTemplate.Header pageTitle="Context menu" />
<EuiPageTemplate.Section grow={false}>
<>
<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
@ -142,8 +127,8 @@ export function EmbeddablePanelExample({ embeddableServices, searchListContainer
</EuiPanel>
<EuiSpacer />
</EuiPageContentBody>
</EuiPageContent>
</EuiPageBody>
</>
</EuiPageTemplate.Section>
</>
);
}

View file

@ -8,14 +8,12 @@
import React from 'react';
import {
EuiPageBody,
EuiPageContent_Deprecated as EuiPageContent,
EuiPageContentBody_Deprecated as EuiPageContentBody,
EuiPageHeader,
EuiPageHeaderSection,
EuiPageTemplate,
EuiPanel,
EuiText,
EuiTitle,
EuiCodeBlock,
EuiSpacer,
} from '@elastic/eui';
import { EmbeddableRenderer } from '@kbn/embeddable-plugin/public';
import {
@ -29,40 +27,46 @@ interface Props {
export function HelloWorldEmbeddableExample({ helloWorldEmbeddableFactory }: Props) {
return (
<EuiPageBody>
<EuiPageHeader>
<EuiPageHeaderSection>
<EuiTitle size="l">
<h1>Hello world example</h1>
<>
<EuiPageTemplate.Header pageTitle="Render embeddable" />
<EuiPageTemplate.Section grow={false} bottomBorder="extended">
<>
<EuiTitle size="xs">
<h2>Embeddable prop</h2>
</EuiTitle>
</EuiPageHeaderSection>
</EuiPageHeader>
<EuiPageContent>
<EuiPageContentBody>
<EuiText>
Here the embeddable is rendered without the factory. A developer may use this method if
they want to statically embed a single embeddable into their application or page. Also
`input` prop may be used to declaratively update current embeddable input
Use embeddable constructor to pass embeddable directly to{' '}
<strong>EmbeddableRenderer</strong>. Use <strong>input</strong> prop to declaratively
update embeddable input.
</EuiText>
<EuiPanel data-test-subj="helloWorldEmbeddablePanel" paddingSize="none" role="figure">
<EuiSpacer />
<EuiPanel data-test-subj="helloWorldEmbeddablePanel" role="figure">
<EmbeddableRenderer embeddable={new HelloWorldEmbeddable({ id: 'hello' })} />
</EuiPanel>
<EuiSpacer />
<EuiCodeBlock language="jsx" fontSize="m" paddingSize="m">
{`<EmbeddableRenderer embeddable={new HelloWorldEmbeddable({ id: 'hello' })} />`}
</EuiCodeBlock>
</>
</EuiPageTemplate.Section>
<EuiPageTemplate.Section grow={false}>
<>
<EuiTitle size="xs">
<h2>Factory prop</h2>
</EuiTitle>
<EuiText>
Here the embeddable is rendered using the factory. Internally it creates embeddable
using factory.create(). This method is used programatically when a container embeddable
attempts to initialize it&#39;s children embeddables. This method can be used when you
only have a access to a factory.
Use <strong>factory</strong> prop to programatically instantiate embeddable.
</EuiText>
<EuiPanel
data-test-subj="helloWorldEmbeddableFromFactory"
paddingSize="none"
role="figure"
>
<EuiSpacer />
<EuiPanel data-test-subj="helloWorldEmbeddableFromFactory" role="figure">
<EmbeddableRenderer factory={helloWorldEmbeddableFactory} input={{ id: '1234' }} />
</EuiPanel>
</EuiPageContentBody>
</EuiPageContent>
</EuiPageBody>
<EuiSpacer />
<EuiCodeBlock language="jsx" fontSize="m" paddingSize="m">
{`<EmbeddableRenderer factory={helloWorldEmbeddableFactory} input={{ id: '1234' }} />`}
</EuiCodeBlock>
</>
</EuiPageTemplate.Section>
</>
);
}

View file

@ -7,41 +7,69 @@
*/
import React from 'react';
import {
EuiPageBody,
EuiPageContent_Deprecated as EuiPageContent,
EuiPageContentBody_Deprecated as EuiPageContentBody,
EuiPageHeader,
EuiPageHeaderSection,
EuiPanel,
EuiSpacer,
EuiText,
EuiTitle,
} from '@elastic/eui';
import { EuiPanel, EuiSpacer, EuiText, EuiPageTemplate, EuiCodeBlock } from '@elastic/eui';
import { EmbeddableRenderer, ViewMode } from '@kbn/embeddable-plugin/public';
import {
HELLO_WORLD_EMBEDDABLE,
MULTI_TASK_TODO_EMBEDDABLE,
TODO_EMBEDDABLE,
ListContainerFactory,
SearchableListContainerFactory,
} from '@kbn/embeddable-examples-plugin/public';
import { SearchableContainerInput } from '@kbn/embeddable-examples-plugin/public/searchable_list_container/searchable_list_container';
import { TodoInput } from '@kbn/embeddable-examples-plugin/public/todo';
import { MultiTaskTodoInput } from '@kbn/embeddable-examples-plugin/public/multi_task_todo';
interface Props {
listContainerEmbeddableFactory: ListContainerFactory;
searchableListContainerEmbeddableFactory: SearchableListContainerFactory;
}
export function ListContainerExample({
listContainerEmbeddableFactory,
searchableListContainerEmbeddableFactory,
}: Props) {
const listInput: SearchableContainerInput = {
export function ListContainerExample({ listContainerEmbeddableFactory }: Props) {
return (
<>
<EuiPageTemplate.Header pageTitle="Groups of embeddables" />
<EuiPageTemplate.Section grow={false}>
<>
<EuiText>Use container embeddable to render a group of embeddables.</EuiText>
<EuiSpacer />
<EuiPanel data-test-subj="listContainerEmbeddablePanel" paddingSize="none" role="figure">
<EmbeddableRenderer
factory={listContainerEmbeddableFactory}
input={{
id: 'hello',
title: 'Todo list',
viewMode: ViewMode.VIEW,
panels: {
'1': {
type: HELLO_WORLD_EMBEDDABLE,
explicitInput: {
id: '1',
},
},
'2': {
type: TODO_EMBEDDABLE,
explicitInput: {
id: '2',
task: 'Goes out on Wednesdays!',
icon: 'broom',
title: 'Take out the trash',
} as TodoInput,
},
'3': {
type: TODO_EMBEDDABLE,
explicitInput: {
id: '3',
icon: 'broom',
title: 'Vaccum the floor',
} as TodoInput,
},
},
}}
/>
</EuiPanel>
<EuiSpacer />
<EuiCodeBlock language="jsx" fontSize="m" paddingSize="m">
{`<EmbeddableRenderer
factory={listContainerEmbeddableFactory}
input={{
id: 'hello',
title: 'My todo list',
title: 'Todo list',
viewMode: ViewMode.VIEW,
panels: {
'1': {
@ -68,110 +96,11 @@ export function ListContainerExample({
} as TodoInput,
},
},
};
const searchableInput: SearchableContainerInput = {
id: '1',
title: 'My searchable todo list',
viewMode: ViewMode.VIEW,
panels: {
'1': {
type: HELLO_WORLD_EMBEDDABLE,
explicitInput: {
id: '1',
title: 'Hello',
},
},
'2': {
type: TODO_EMBEDDABLE,
explicitInput: {
id: '2',
task: 'Goes out on Wednesdays!',
icon: 'broom',
title: 'Take out the trash',
} as TodoInput,
},
'3': {
type: MULTI_TASK_TODO_EMBEDDABLE,
explicitInput: {
id: '3',
icon: 'searchProfilerApp',
title: 'Learn more',
tasks: ['Go to school', 'Watch planet earth', 'Read the encyclopedia'],
} as MultiTaskTodoInput,
},
},
};
return (
<EuiPageBody>
<EuiPageHeader>
<EuiPageHeaderSection>
<EuiTitle size="l">
<h1>List container example</h1>
</EuiTitle>
</EuiPageHeaderSection>
</EuiPageHeader>
<EuiPageContent>
<EuiPageContentBody>
<EuiText>
Here is a container embeddable that contains other embeddables and displays them in a
list.
</EuiText>
<EuiPanel data-test-subj="listContainerEmbeddablePanel" paddingSize="none" role="figure">
<EmbeddableRenderer input={listInput} factory={listContainerEmbeddableFactory} />
</EuiPanel>
<EuiSpacer />
<EuiText>
<p>
The reason to use a container embeddable instead of just a custom react component is
because it comes with helpful methods to store the state of all its children
embeddables, listeners to clean up the input state when an embeddable is added or
removed, and a way to pass down the container embeddable&#39;s own input to its
children. In the above example, the container did not take any input. Let&#39;s modify
it so it does.
</p>
<p>
In this Searchable List Container, the container takes in a search string as input and
passes that down to all its children. It also listens to its children that output
`hasMatch`, and removes them from the list when there is a search string and the child
doesn&#39;t match.
</p>
<p>
The first HelloWorldEmbeddable does not emit the hasMatch output variable, so the
container chooses to hide it.
</p>
<p>
Check out the &quot;Dynamically adding children&quot; section, to see how to add
children to this container, and see it rendered inside an `EmbeddablePanel` component.
</p>
</EuiText>
<EuiSpacer />
<EuiPanel
data-test-subj="searchableListContainerEmbeddablePanel"
paddingSize="none"
role="figure"
>
<EmbeddableRenderer
input={searchableInput}
factory={searchableListContainerEmbeddableFactory}
/>{' '}
</EuiPanel>
<EuiSpacer />
<EuiText>
<p>
There currently is no formal way to limit what children can be added to a container.
If the use case arose, it wouldn&#39;t be difficult. In the mean time, it&#39;s good
to understand that children may ignore input they don&#39;t care about. Likewise the
container will have to choose what to do when it encounters children that are missing
certain output variables.
</p>
</EuiText>
</EuiPageContentBody>
</EuiPageContent>
</EuiPageBody>
}}
/>`}
</EuiCodeBlock>
</>
</EuiPageTemplate.Section>
</>
);
}

View file

@ -8,22 +8,17 @@
import React from 'react';
import {
EuiButton,
EuiCodeBlock,
EuiFieldText,
EuiFlexGroup,
EuiFlexItem,
EuiForm,
EuiFormRow,
EuiPageBody,
EuiPageContent_Deprecated as EuiPageContent,
EuiPageContentBody_Deprecated as EuiPageContentBody,
EuiPageHeader,
EuiPageHeaderSection,
EuiPanel,
EuiText,
EuiTextArea,
EuiTitle,
EuiPageTemplate,
EuiSpacer,
EuiSelect,
} from '@elastic/eui';
import { TodoInput } from '@kbn/embeddable-examples-plugin/public/todo';
import { TodoEmbeddableFactory } from '@kbn/embeddable-examples-plugin/public';
import { EmbeddableRenderer } from '@kbn/embeddable-plugin/public';
@ -32,96 +27,94 @@ interface Props {
}
interface State {
task?: string;
title?: string;
icon?: string;
loading: boolean;
input: TodoInput;
task: string;
title: string;
icon: string;
}
const ICON_OPTIONS = [
{ value: 'beaker', text: 'beaker' },
{ value: 'bell', text: 'bell' },
{ value: 'bolt', text: 'bolt' },
{ value: 'broom', text: 'broom' },
{ value: 'bug', text: 'bug' },
{ value: 'bullseye', text: 'bullseye' },
];
export class TodoEmbeddableExample extends React.Component<Props, State> {
constructor(props: Props) {
super(props);
this.state = {
loading: true,
input: {
id: '1',
task: 'Take out the trash',
icon: 'broom',
title: 'Trash',
},
icon: 'broom',
task: 'Take out the trash',
title: 'Trash',
};
}
private onUpdateEmbeddableInput = () => {
const { task, title, icon, input } = this.state;
this.setState({ input: { ...input, task: task ?? '', title, icon } });
};
public render() {
return (
<EuiPageBody>
<EuiPageHeader>
<EuiPageHeaderSection>
<EuiTitle size="l">
<h1>Todo example</h1>
</EuiTitle>
</EuiPageHeaderSection>
</EuiPageHeader>
<EuiPageContent>
<EuiPageContentBody>
<>
<EuiPageTemplate.Header pageTitle="Update embeddable state" />
<EuiPageTemplate.Section grow={false}>
<>
<EuiText>
This embeddable takes input parameters, task, title and icon. You can update them
using this form. Input changes will be passed inside `EmbeddableRenderer` as a prop
Use <strong>input</strong> prop to update embeddable state.
</EuiText>
<EuiFlexGroup>
<EuiFlexItem grow={true}>
<EuiFormRow label="Title">
<EuiFieldText
data-test-subj="titleTodo"
onChange={(ev) => this.setState({ title: ev.target.value })}
/>
</EuiFormRow>
</EuiFlexItem>
<EuiFlexItem grow={true}>
<EuiFormRow label="Icon">
<EuiFieldText
data-test-subj="iconTodo"
onChange={(ev) => this.setState({ icon: ev.target.value })}
/>
</EuiFormRow>
</EuiFlexItem>
<EuiFlexItem>
<EuiFormRow label="Task">
<EuiTextArea
fullWidth
resize="horizontal"
data-test-subj="taskTodo"
onChange={(ev) => this.setState({ task: ev.target.value })}
/>
</EuiFormRow>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiFormRow hasEmptyLabelSpace>
<EuiButton
data-test-subj="updateTodoButton"
onClick={this.onUpdateEmbeddableInput}
>
Update
</EuiButton>
</EuiFormRow>
</EuiFlexItem>
</EuiFlexGroup>
<EuiPanel data-test-subj="todoEmbeddable" paddingSize="none" role="figure">
<EuiSpacer />
<EuiForm>
<EuiFormRow label="Title">
<EuiFieldText
data-test-subj="titleTodo"
value={this.state.title}
onChange={(ev) => this.setState({ title: ev.target.value })}
/>
</EuiFormRow>
<EuiFormRow label="Icon">
<EuiSelect
data-test-subj="iconTodo"
value={this.state.icon}
options={ICON_OPTIONS}
onChange={(ev) => this.setState({ icon: ev.target.value })}
/>
</EuiFormRow>
<EuiFormRow label="Task">
<EuiTextArea
fullWidth
resize="horizontal"
data-test-subj="taskTodo"
value={this.state.task}
onChange={(ev) => this.setState({ task: ev.target.value })}
/>
</EuiFormRow>
</EuiForm>
<EuiSpacer />
<EuiPanel data-test-subj="todoEmbeddable" role="figure">
<EmbeddableRenderer
factory={this.props.todoEmbeddableFactory}
input={this.state.input}
input={{
id: '1',
task: this.state.task,
title: this.state.title,
icon: this.state.icon,
}}
/>
</EuiPanel>
</EuiPageContentBody>
</EuiPageContent>
</EuiPageBody>
<EuiSpacer />
<EuiCodeBlock language="jsx" fontSize="m" paddingSize="m">
{`<EmbeddableRenderer
factory={this.props.todoEmbeddableFactory}
input={{
id: '1',
task: this.state.task,
title: this.state.title,
icon: this.state.icon,
}}
/>`}
</EuiCodeBlock>
</>
</EuiPageTemplate.Section>
</>
);
}
}