Add "Register new embeddable type" to Embeddable tutorial (#181761)

PR adds "Register new embeddable type" section to Embeddable tutorial
<img width="600" alt="Screenshot 2024-04-25 at 12 25 59 PM"
src="075c534b-0b1b-4600-a057-d601d09da5d1">

PR also groups example embeddables to make them easier to find
<img width="600" alt="Screenshot 2024-04-25 at 12 26 12 PM"
src="82d55fca-bbe8-4b63-a80e-dd052307d7e5">

---------

Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
Nathan Reese 2024-04-26 12:02:48 -06:00 committed by GitHub
parent f21d6e436e
commit 438f623f3d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 103 additions and 10 deletions

View file

@ -21,9 +21,11 @@ import {
EuiTabs,
} from '@elastic/eui';
import { Overview } from './overview';
import { RegisterEmbeddable } from './register_embeddable';
import { RenderExamples } from './render_examples';
const OVERVIEW_TAB_ID = 'overview';
const REGISTER_EMBEDDABLE_TAB_ID = 'register';
const RENDER_TAB_ID = 'render';
const App = () => {
@ -38,6 +40,10 @@ const App = () => {
return <RenderExamples />;
}
if (selectedTabId === REGISTER_EMBEDDABLE_TAB_ID) {
return <RegisterEmbeddable />;
}
return <Overview />;
}
@ -56,6 +62,12 @@ const App = () => {
>
Embeddables overview
</EuiTab>
<EuiTab
onClick={() => onSelectedTabChanged(REGISTER_EMBEDDABLE_TAB_ID)}
isSelected={REGISTER_EMBEDDABLE_TAB_ID === selectedTabId}
>
Register new embeddable type
</EuiTab>
<EuiTab
onClick={() => onSelectedTabChanged(RENDER_TAB_ID)}
isSelected={RENDER_TAB_ID === selectedTabId}

View file

@ -0,0 +1,52 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import React from 'react';
import { EuiCodeBlock, EuiSpacer, EuiText } from '@elastic/eui';
// @ts-ignore
import registerSearchEmbeddableSource from '!!raw-loader!../react_embeddables/search/register_search_embeddable';
// @ts-ignore
import registerAttachActionSource from '!!raw-loader!../react_embeddables/search/register_add_search_panel_action';
export const RegisterEmbeddable = () => {
return (
<>
<EuiText>
<p>
This plugin registers several embeddable types with{' '}
<strong>registerReactEmbeddableFactory</strong> during plugin start. The code example
below shows Search embeddable registration. Notice how the embeddable factory is imported
asynchronously to limit initial page load size.
</p>
</EuiText>
<EuiCodeBlock language="jsx" fontSize="m" paddingSize="m">
{registerSearchEmbeddableSource}
</EuiCodeBlock>
<EuiSpacer size="l" />
<EuiText>
<p>
Run the example embeddables by creating a dashboard, clicking <em>Add panel</em> button,
and then selecting <em>Embeddable examples</em> group.
</p>
<p>
Add your own embeddables to <em>Add panel</em> menu by attaching an action to the{' '}
<strong>ADD_PANEL_TRIGGER</strong> trigger. Notice usage of <strong>grouping</strong> to
nest related panel types and avoid bloating <em>Add panel</em> menu. Please reach out to
@elastic/kibana-presentation team to coordinate menu updates.
</p>
</EuiText>
<EuiCodeBlock language="jsx" fontSize="m" paddingSize="m">
{registerAttachActionSource}
</EuiCodeBlock>
</>
);
};

View file

@ -22,9 +22,9 @@ import { DeveloperExamplesSetup } from '@kbn/developer-examples-plugin/public';
import { registerCreateEuiMarkdownAction } from './react_embeddables/eui_markdown/create_eui_markdown_action';
import { registerCreateFieldListAction } from './react_embeddables/field_list/create_field_list_action';
import { registerAddSearchPanelAction } from './react_embeddables/search/register_add_search_panel_action';
import { registerSearchEmbeddable } from './react_embeddables/search/register_search_embeddable';
import { EUI_MARKDOWN_ID } from './react_embeddables/eui_markdown/constants';
import { FIELD_LIST_ID } from './react_embeddables/field_list/constants';
import { SEARCH_EMBEDDABLE_ID } from './react_embeddables/search/constants';
import { setupApp } from './app/setup_app';
export interface SetupDeps {
@ -65,12 +65,7 @@ export class EmbeddableExamplesPlugin implements Plugin<void, void, SetupDeps, S
});
registerAddSearchPanelAction(deps.uiActions);
registerReactEmbeddableFactory(SEARCH_EMBEDDABLE_ID, async () => {
const { getSearchEmbeddableFactory } = await import(
'./react_embeddables/search/search_react_embeddable'
);
return getSearchEmbeddableFactory(deps);
});
registerSearchEmbeddable(deps);
}
public stop() {}

View file

@ -0,0 +1,12 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
export const addPanelGrouping = {
id: 'embeddableExamples',
getDisplayName: () => 'Embeddable examples',
};

View file

@ -10,6 +10,7 @@ import { i18n } from '@kbn/i18n';
import { apiCanAddNewPanel } from '@kbn/presentation-containers';
import { EmbeddableApiContext } from '@kbn/presentation-publishing';
import { IncompatibleActionError, UiActionsStart } from '@kbn/ui-actions-plugin/public';
import { addPanelGrouping } from '../add_panel_grouping';
import { ADD_EUI_MARKDOWN_ACTION_ID, EUI_MARKDOWN_ID } from './constants';
// -----------------------------------------------------------------------------
@ -19,6 +20,7 @@ import { ADD_EUI_MARKDOWN_ACTION_ID, EUI_MARKDOWN_ID } from './constants';
export const registerCreateEuiMarkdownAction = (uiActions: UiActionsStart) => {
uiActions.registerAction<EmbeddableApiContext>({
id: ADD_EUI_MARKDOWN_ACTION_ID,
grouping: [addPanelGrouping],
getIconType: () => 'editorCodeBlock',
isCompatible: async ({ embeddable }) => {
return apiCanAddNewPanel(embeddable);

View file

@ -12,10 +12,12 @@ import { EmbeddableApiContext } from '@kbn/presentation-publishing';
import { IncompatibleActionError } from '@kbn/ui-actions-plugin/public';
import { UiActionsPublicStart } from '@kbn/ui-actions-plugin/public/plugin';
import { ADD_FIELD_LIST_ACTION_ID, FIELD_LIST_ID } from './constants';
import { addPanelGrouping } from '../add_panel_grouping';
export const registerCreateFieldListAction = (uiActions: UiActionsPublicStart) => {
uiActions.registerAction<EmbeddableApiContext>({
id: ADD_FIELD_LIST_ACTION_ID,
grouping: [addPanelGrouping],
getIconType: () => 'indexOpen',
isCompatible: async ({ embeddable }) => {
return apiCanAddNewPanel(embeddable);

View file

@ -9,14 +9,14 @@
import { apiCanAddNewPanel } from '@kbn/presentation-containers';
import { EmbeddableApiContext } from '@kbn/presentation-publishing';
import { IncompatibleActionError, UiActionsStart } from '@kbn/ui-actions-plugin/public';
import { addPanelGrouping } from '../add_panel_grouping';
import { ADD_SEARCH_ACTION_ID, SEARCH_EMBEDDABLE_ID } from './constants';
export const registerAddSearchPanelAction = (uiActions: UiActionsStart) => {
uiActions.registerAction<EmbeddableApiContext>({
id: ADD_SEARCH_ACTION_ID,
getDisplayName: () => 'Unified search example',
getDisplayNameTooltip: () =>
'Demonstrates how to use global filters, global time range, panel time range, and global query state in an embeddable',
grouping: [addPanelGrouping],
getDisplayName: () => 'Search example',
getIconType: () => 'search',
isCompatible: async ({ embeddable }) => {
return apiCanAddNewPanel(embeddable);

View file

@ -0,0 +1,18 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import { registerReactEmbeddableFactory } from '@kbn/embeddable-plugin/public';
import { SEARCH_EMBEDDABLE_ID } from './constants';
import { Services } from './types';
export function registerSearchEmbeddable(services: Services) {
registerReactEmbeddableFactory(SEARCH_EMBEDDABLE_ID, async () => {
const { getSearchEmbeddableFactory } = await import('./search_react_embeddable');
return getSearchEmbeddableFactory(services);
});
}