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

[Embeddables rebuild] Support for by reference embeddables #182523

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
da9eb34
initialize saved book example and by align by reference usage
ThomThomson May 1, 2024
9ebb134
Merge remote-tracking branch 'upstream/main' into embeddableRebuild/s…
ThomThomson May 1, 2024
c2766a5
change last saved and unsaved state
ThomThomson May 2, 2024
695e0fc
rename method to getSerializedStateForChild
ThomThomson May 2, 2024
3e2fe12
Merge remote-tracking branch 'upstream/main' into embeddableRebuild/s…
ThomThomson May 2, 2024
914e071
[CI] Auto-commit changed files from 'node scripts/lint_ts_projects --…
kibanamachine May 2, 2024
e57648d
in place versions of link & unlink actions
ThomThomson May 8, 2024
ab59447
Merge remote-tracking branch 'refs/remotes/origin/embeddableRebuild/s…
ThomThomson May 8, 2024
2ecea2f
Merge remote-tracking branch 'upstream/main' into embeddableRebuild/s…
ThomThomson May 8, 2024
45ed235
fix types and jest tests
ThomThomson May 8, 2024
e2e85ab
fix backup service
ThomThomson May 10, 2024
f9371d9
Merge remote-tracking branch 'upstream/main' into embeddableRebuild/s…
ThomThomson May 10, 2024
2c26f49
simplify embeddable start type
ThomThomson May 10, 2024
7c39f71
fix editor types
ThomThomson May 10, 2024
b6de1e7
Merge branch 'main' into embeddableRebuild/standardizeByRef
kibanamachine May 10, 2024
d8986c8
re-export for testing
ThomThomson May 10, 2024
86201f7
Merge remote-tracking branch 'upstream/main' into embeddableRebuild/s…
ThomThomson May 14, 2024
7b77456
fix types and test
ThomThomson May 14, 2024
672f2e4
restore legacy panel add behaviour
ThomThomson May 16, 2024
938a6b6
Merge remote-tracking branch 'upstream/main' into embeddableRebuild/s…
ThomThomson May 16, 2024
4ed52dc
remove some unneeded changes, update APM embeddable rendering
ThomThomson May 17, 2024
234074b
Merge branch 'main' into embeddableRebuild/standardizeByRef
kibanamachine May 17, 2024
129375f
Merge remote-tracking branch 'upstream/main' into embeddableRebuild/s…
ThomThomson May 17, 2024
76f9920
Merge remote-tracking branch 'refs/remotes/origin/embeddableRebuild/s…
ThomThomson May 17, 2024
541b84b
review feedback
ThomThomson May 21, 2024
de7c8c7
Merge remote-tracking branch 'upstream/main' into embeddableRebuild/s…
ThomThomson May 21, 2024
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
21 changes: 7 additions & 14 deletions examples/embeddable_examples/public/app/render_examples.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,19 +27,14 @@ import { SEARCH_EMBEDDABLE_ID } from '../react_embeddables/search/constants';
import type { SearchApi, SearchSerializedState } 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>(),
getSerializedStateForChild: () => ({
rawState: {
timeRange: undefined,
},
}),
timeRange$: new BehaviorSubject<TimeRange>({
from: 'now-24h',
to: 'now',
Expand Down Expand Up @@ -85,8 +80,7 @@ export const RenderExamples = () => {
<EuiCodeBlock language="jsx" fontSize="m" paddingSize="m">
{`<ReactEmbeddableRenderer<State, Api>
type={SEARCH_EMBEDDABLE_ID}
state={initialState}
parentApi={parentApi}
getParentApi={() => parentApi}
onApiAvailable={(newApi) => {
setApi(newApi);
}}
Expand All @@ -107,8 +101,7 @@ export const RenderExamples = () => {
<ReactEmbeddableRenderer<SearchSerializedState, SearchApi>
key={hidePanelChrome ? 'hideChrome' : 'showChrome'}
type={SEARCH_EMBEDDABLE_ID}
state={initialState}
parentApi={parentApi}
getParentApi={() => parentApi}
onApiAvailable={(newApi) => {
setApi(newApi);
}}
Expand Down
14 changes: 13 additions & 1 deletion examples/embeddable_examples/public/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,11 @@ import { DATA_TABLE_ID } from './react_embeddables/data_table/constants';
import { registerCreateDataTableAction } from './react_embeddables/data_table/create_data_table_action';
import { EUI_MARKDOWN_ID } from './react_embeddables/eui_markdown/constants';
import { registerCreateEuiMarkdownAction } from './react_embeddables/eui_markdown/create_eui_markdown_action';
import { registerCreateFieldListAction } from './react_embeddables/field_list/create_field_list_action';
import { FIELD_LIST_ID } from './react_embeddables/field_list/constants';
import { registerCreateFieldListAction } from './react_embeddables/field_list/create_field_list_action';
import { registerFieldListPanelPlacementSetting } from './react_embeddables/field_list/register_field_list_embeddable';
import { SAVED_BOOK_ID } from './react_embeddables/saved_book/constants';
import { registerCreateSavedBookAction } from './react_embeddables/saved_book/create_saved_book_action';
import { registerAddSearchPanelAction } from './react_embeddables/search/register_add_search_panel_action';
import { registerSearchEmbeddable } from './react_embeddables/search/register_search_embeddable';

Expand Down Expand Up @@ -73,6 +75,14 @@ export class EmbeddableExamplesPlugin implements Plugin<void, void, SetupDeps, S
return getDataTableFactory(coreStart, deps);
});

embeddable.registerReactEmbeddableFactory(SAVED_BOOK_ID, async () => {
const { getSavedBookEmbeddableFactory } = await import(
'./react_embeddables/saved_book/saved_book_react_embeddable'
);
const [coreStart] = await startServicesPromise;
return getSavedBookEmbeddableFactory(coreStart);
});

registerSearchEmbeddable(
embeddable,
new Promise((resolve) => startServicesPromise.then(([_, startDeps]) => resolve(startDeps)))
Expand All @@ -88,6 +98,8 @@ export class EmbeddableExamplesPlugin implements Plugin<void, void, SetupDeps, S
registerAddSearchPanelAction(deps.uiActions);

registerCreateDataTableAction(deps.uiActions);

registerCreateSavedBookAction(deps.uiActions, core);
}

public stop() {}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* 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 { BehaviorSubject } from 'rxjs';
import { BookAttributes, BookAttributesManager } from './types';

export const defaultBookAttributes: BookAttributes = {
bookTitle: 'Pillars of the earth',
authorName: 'Ken follett',
numberOfPages: 973,
bookSynopsis:
'A spellbinding epic set in 12th-century England, The Pillars of the Earth tells the story of the struggle to build the greatest Gothic cathedral the world has known.',
};

export const stateManagerFromAttributes = (attributes: BookAttributes): BookAttributesManager => {
const bookTitle = new BehaviorSubject<string>(attributes.bookTitle);
const authorName = new BehaviorSubject<string>(attributes.authorName);
const numberOfPages = new BehaviorSubject<number>(attributes.numberOfPages);
const bookSynopsis = new BehaviorSubject<string | undefined>(attributes.bookSynopsis);

return {
bookTitle,
authorName,
numberOfPages,
bookSynopsis,
comparators: {
bookTitle: [bookTitle, (val) => bookTitle.next(val)],
authorName: [authorName, (val) => authorName.next(val)],
numberOfPages: [numberOfPages, (val) => numberOfPages.next(val)],
bookSynopsis: [bookSynopsis, (val) => bookSynopsis.next(val)],
},
};
};

export const serializeBookAttributes = (stateManager: BookAttributesManager): BookAttributes => ({
bookTitle: stateManager.bookTitle.value,
authorName: stateManager.authorName.value,
numberOfPages: stateManager.numberOfPages.value,
bookSynopsis: stateManager.bookSynopsis.value,
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/*
* 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 SAVED_BOOK_ID = 'book';
export const ADD_SAVED_BOOK_ACTION_ID = 'create_saved_book';
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/*
* 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 { CoreStart } from '@kbn/core/public';
import { i18n } from '@kbn/i18n';
import { apiIsPresentationContainer } from '@kbn/presentation-containers';
import { EmbeddableApiContext } from '@kbn/presentation-publishing';
import { IncompatibleActionError } from '@kbn/ui-actions-plugin/public';
import { UiActionsPublicStart } from '@kbn/ui-actions-plugin/public/plugin';
import { embeddableExamplesGrouping } from '../embeddable_examples_grouping';
import {
defaultBookAttributes,
serializeBookAttributes,
stateManagerFromAttributes,
} from './book_state';
import { ADD_SAVED_BOOK_ACTION_ID, SAVED_BOOK_ID } from './constants';
import { openSavedBookEditor } from './saved_book_editor';
import { saveBookAttributes } from './saved_book_library';
import {
BookByReferenceSerializedState,
BookByValueSerializedState,
BookSerializedState,
} from './types';

export const registerCreateSavedBookAction = (uiActions: UiActionsPublicStart, core: CoreStart) => {
uiActions.registerAction<EmbeddableApiContext>({
id: ADD_SAVED_BOOK_ACTION_ID,
getIconType: () => 'folderClosed',
grouping: [embeddableExamplesGrouping],
isCompatible: async ({ embeddable }) => {
return apiIsPresentationContainer(embeddable);
},
execute: async ({ embeddable }) => {
if (!apiIsPresentationContainer(embeddable)) throw new IncompatibleActionError();
const newPanelStateManager = stateManagerFromAttributes(defaultBookAttributes);

const { addToLibrary } = await openSavedBookEditor(newPanelStateManager, true, core, {
parentApi: embeddable,
});

const initialState: BookSerializedState = await (async () => {
// if we're adding this to the library, we only need to return the by reference state.
if (addToLibrary) {
const savedBookId = await saveBookAttributes(
undefined,
serializeBookAttributes(newPanelStateManager)
);
return { savedBookId } as BookByReferenceSerializedState;
}
return {
attributes: serializeBookAttributes(newPanelStateManager),
} as BookByValueSerializedState;
})();

embeddable.addNewPanel<BookSerializedState>({
panelType: SAVED_BOOK_ID,
initialState,
});
},
getDisplayName: () =>
i18n.translate('embeddableExamples.savedbook.addBookAction.displayName', {
defaultMessage: 'Book',
}),
});
uiActions.attachAction('ADD_PANEL_TRIGGER', ADD_SAVED_BOOK_ACTION_ID);
};
Loading