Skip to content

Commit

Permalink
Merge branch 'main' into revert-fs-changes
Browse files Browse the repository at this point in the history
  • Loading branch information
tomsonpl authored Apr 25, 2024
2 parents 11b42bb + 2469e64 commit 3a30ee6
Show file tree
Hide file tree
Showing 80 changed files with 1,195 additions and 1,274 deletions.
1 change: 0 additions & 1 deletion .github/CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
Expand Up @@ -384,7 +384,6 @@ test/plugin_functional/plugins/elasticsearch_client_plugin @elastic/kibana-core
x-pack/test/plugin_api_integration/plugins/elasticsearch_client @elastic/kibana-core
x-pack/plugins/embeddable_enhanced @elastic/kibana-presentation
examples/embeddable_examples @elastic/kibana-presentation
examples/embeddable_explorer @elastic/kibana-presentation
src/plugins/embeddable @elastic/kibana-presentation
x-pack/examples/embedded_lens_example @elastic/kibana-visualizations
x-pack/plugins/encrypted_saved_objects @elastic/kibana-security
Expand Down
3 changes: 2 additions & 1 deletion examples/embeddable_examples/kibana.jsonc
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@
"dashboard",
"data",
"charts",
"fieldFormats"
"fieldFormats",
"developerExamples"
],
"requiredBundles": ["presentationUtil"],
"extraPublicDirs": ["public/hello_world"]
Expand Down
81 changes: 81 additions & 0 deletions examples/embeddable_examples/public/app/app.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/*
* 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, { useState } from 'react';
import ReactDOM from 'react-dom';

import { AppMountParameters } from '@kbn/core-application-browser';
import {
EuiPage,
EuiPageBody,
EuiPageHeader,
EuiPageSection,
EuiPageTemplate,
EuiSpacer,
EuiTab,
EuiTabs,
} from '@elastic/eui';
import { Overview } from './overview';
import { RenderExamples } from './render_examples';

const OVERVIEW_TAB_ID = 'overview';
const RENDER_TAB_ID = 'render';

const App = () => {
const [selectedTabId, setSelectedTabId] = useState(OVERVIEW_TAB_ID);

function onSelectedTabChanged(tabId: string) {
setSelectedTabId(tabId);
}

function renderTabContent() {
if (selectedTabId === RENDER_TAB_ID) {
return <RenderExamples />;
}

return <Overview />;
}

return (
<EuiPage>
<EuiPageBody>
<EuiPageSection>
<EuiPageHeader pageTitle="Embeddables" />
</EuiPageSection>
<EuiPageTemplate.Section>
<EuiPageSection>
<EuiTabs>
<EuiTab
onClick={() => onSelectedTabChanged(OVERVIEW_TAB_ID)}
isSelected={OVERVIEW_TAB_ID === selectedTabId}
>
Embeddables overview
</EuiTab>
<EuiTab
onClick={() => onSelectedTabChanged(RENDER_TAB_ID)}
isSelected={RENDER_TAB_ID === selectedTabId}
>
Rendering embeddables in your application
</EuiTab>
</EuiTabs>

<EuiSpacer />

{renderTabContent()}
</EuiPageSection>
</EuiPageTemplate.Section>
</EuiPageBody>
</EuiPage>
);
};

export const renderApp = (element: AppMountParameters['element']) => {
ReactDOM.render(<App />, element);

return () => ReactDOM.unmountComponentAtNode(element);
};
22 changes: 22 additions & 0 deletions examples/embeddable_examples/public/app/overview.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/*
* 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 { EuiText } from '@elastic/eui';

export const Overview = () => {
return (
<EuiText>
<p>
Embeddables are React components that manage their own state, can be serialized and
deserialized, and return an API that can be used to interact with them imperatively.
</p>
</EuiText>
);
};
137 changes: 137 additions & 0 deletions examples/embeddable_examples/public/app/render_examples.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
/*
* 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, { useMemo, useState } from 'react';

import { ReactEmbeddableRenderer } from '@kbn/embeddable-plugin/public';
import {
EuiCodeBlock,
EuiFlexGroup,
EuiFlexItem,
EuiSpacer,
EuiSuperDatePicker,
EuiSwitch,
EuiText,
OnTimeChangeProps,
} from '@elastic/eui';
import { BehaviorSubject, Subject } from 'rxjs';
import { TimeRange } from '@kbn/es-query';
import { useBatchedOptionalPublishingSubjects } from '@kbn/presentation-publishing';
import { SearchEmbeddableRenderer } from '../react_embeddables/search/search_embeddable_renderer';
import { SEARCH_EMBEDDABLE_ID } from '../react_embeddables/search/constants';
import type { Api, State } from '../react_embeddables/search/types';

export const RenderExamples = () => {
const initialState = useMemo(() => {
return {
rawState: {
timeRange: undefined,
},
references: [],
};
// only run onMount
}, []);

const parentApi = useMemo(() => {
return {
reload$: new Subject<void>(),
timeRange$: new BehaviorSubject<TimeRange>({
from: 'now-24h',
to: 'now',
}),
};
// only run onMount
}, []);

const [api, setApi] = useState<Api | null>(null);
const [hidePanelChrome, setHidePanelChrome] = useState<boolean>(false);
const [dataLoading, timeRange] = useBatchedOptionalPublishingSubjects(
api?.dataLoading,
parentApi.timeRange$
);

return (
<div>
<EuiSuperDatePicker
isLoading={dataLoading ? dataLoading : false}
start={timeRange.from}
end={timeRange.to}
onTimeChange={({ start, end }: OnTimeChangeProps) => {
parentApi.timeRange$.next({
from: start,
to: end,
});
}}
onRefresh={() => {
parentApi.reload$.next();
}}
/>

<EuiSpacer size="s" />

<EuiFlexGroup>
<EuiFlexItem>
<EuiText>
<p>
Use <strong>ReactEmbeddableRenderer</strong> to render embeddables.
</p>
</EuiText>

<EuiCodeBlock language="jsx" fontSize="m" paddingSize="m">
{`<ReactEmbeddableRenderer<State, Api>
type={SEARCH_EMBEDDABLE_ID}
state={initialState}
parentApi={parentApi}
onApiAvailable={(newApi) => {
setApi(newApi);
}}
hidePanelChrome={hidePanelChrome}
/>`}
</EuiCodeBlock>

<EuiSpacer size="s" />

<EuiSwitch
label="Set hidePanelChrome to render embeddable without Panel wrapper."
checked={hidePanelChrome}
onChange={(e) => setHidePanelChrome(e.target.checked)}
/>

<EuiSpacer size="s" />

<ReactEmbeddableRenderer<State, Api>
key={hidePanelChrome ? 'hideChrome' : 'showChrome'}
type={SEARCH_EMBEDDABLE_ID}
state={initialState}
parentApi={parentApi}
onApiAvailable={(newApi) => {
setApi(newApi);
}}
hidePanelChrome={hidePanelChrome}
/>
</EuiFlexItem>

<EuiFlexItem>
<EuiText>
<p>To avoid leaking embeddable details, wrap ReactEmbeddableRenderer in a component.</p>
</EuiText>

<EuiCodeBlock language="jsx" fontSize="m" paddingSize="m">
{`<SearchEmbeddableRenderer
timeRange={timeRange}
/>`}
</EuiCodeBlock>

<EuiSpacer size="s" />

<SearchEmbeddableRenderer timeRange={timeRange} />
</EuiFlexItem>
</EuiFlexGroup>
</div>
);
};
31 changes: 31 additions & 0 deletions examples/embeddable_examples/public/app/setup_app.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* 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 { AppMountParameters, CoreSetup } from '@kbn/core/public';
import { DeveloperExamplesSetup } from '@kbn/developer-examples-plugin/public';
import type { StartDeps } from '../plugin';

const APP_ID = 'embeddablesApp';
const title = 'Embeddables';

export function setupApp(core: CoreSetup<StartDeps>, developerExamples: DeveloperExamplesSetup) {
core.application.register({
id: APP_ID,
title,
visibleIn: [],
async mount(params: AppMountParameters) {
const { renderApp } = await import('./app');
return renderApp(params.element);
},
});
developerExamples.register({
appId: APP_ID,
title,
description: `Learn how to create new embeddable types and use embeddables in your application.`,
});
}
39 changes: 15 additions & 24 deletions examples/embeddable_examples/public/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { UiActionsStart } from '@kbn/ui-actions-plugin/public';
import { DataPublicPluginStart } from '@kbn/data-plugin/public';
import { ChartsPluginStart } from '@kbn/charts-plugin/public';
import { FieldFormatsStart } from '@kbn/field-formats-plugin/public';
import { DeveloperExamplesSetup } from '@kbn/developer-examples-plugin/public';
import {
HelloWorldEmbeddableFactory,
HELLO_WORLD_EMBEDDABLE,
Expand Down Expand Up @@ -45,13 +46,15 @@ import { registerAddSearchPanelAction } from './react_embeddables/search/registe
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 EmbeddableExamplesSetupDependencies {
export interface SetupDeps {
developerExamples: DeveloperExamplesSetup;
embeddable: EmbeddableSetup;
uiActions: UiActionsStart;
}

export interface EmbeddableExamplesStartDependencies {
export interface StartDeps {
dataViews: DataViewsPublicPluginStart;
embeddable: EmbeddableStart;
uiActions: UiActionsStart;
Expand All @@ -67,57 +70,45 @@ interface ExampleEmbeddableFactories {
getFilterDebuggerEmbeddableFactory: () => FilterDebuggerEmbeddableFactory;
}

export interface EmbeddableExamplesStart {
export interface StartApi {
createSampleData: () => Promise<void>;
factories: ExampleEmbeddableFactories;
}

export class EmbeddableExamplesPlugin
implements
Plugin<
void,
EmbeddableExamplesStart,
EmbeddableExamplesSetupDependencies,
EmbeddableExamplesStartDependencies
>
{
export class EmbeddableExamplesPlugin implements Plugin<void, StartApi, SetupDeps, StartDeps> {
private exampleEmbeddableFactories: Partial<ExampleEmbeddableFactories> = {};

public setup(
core: CoreSetup<EmbeddableExamplesStartDependencies>,
deps: EmbeddableExamplesSetupDependencies
) {
public setup(core: CoreSetup<StartDeps>, { embeddable, developerExamples }: SetupDeps) {
setupApp(core, developerExamples);

this.exampleEmbeddableFactories.getHelloWorldEmbeddableFactory =
deps.embeddable.registerEmbeddableFactory(
embeddable.registerEmbeddableFactory(
HELLO_WORLD_EMBEDDABLE,
new HelloWorldEmbeddableFactoryDefinition()
);

this.exampleEmbeddableFactories.getMigrationsEmbeddableFactory =
deps.embeddable.registerEmbeddableFactory(
embeddable.registerEmbeddableFactory(
SIMPLE_EMBEDDABLE,
new SimpleEmbeddableFactoryDefinition()
);

this.exampleEmbeddableFactories.getListContainerEmbeddableFactory =
deps.embeddable.registerEmbeddableFactory(
embeddable.registerEmbeddableFactory(
LIST_CONTAINER,
new ListContainerFactoryDefinition(async () => ({
embeddableServices: (await core.getStartServices())[1].embeddable,
}))
);

this.exampleEmbeddableFactories.getFilterDebuggerEmbeddableFactory =
deps.embeddable.registerEmbeddableFactory(
embeddable.registerEmbeddableFactory(
FILTER_DEBUGGER_EMBEDDABLE,
new FilterDebuggerEmbeddableFactoryDefinition()
);
}

public start(
core: CoreStart,
deps: EmbeddableExamplesStartDependencies
): EmbeddableExamplesStart {
public start(core: CoreStart, deps: StartDeps): StartApi {
registerCreateFieldListAction(deps.uiActions);
registerReactEmbeddableFactory(FIELD_LIST_ID, async () => {
const { getFieldListFactory } = await import(
Expand Down
Loading

0 comments on commit 3a30ee6

Please sign in to comment.