mirror of
https://github.com/elastic/kibana.git
synced 2025-06-29 03:24:45 -04:00
Closes https://github.com/elastic/kibana/issues/205531 Closes #219877. Closes https://github.com/elastic/kibana/issues/213153 Closes https://github.com/elastic/kibana/issues/150920 Closes https://github.com/elastic/kibana/issues/203130 ### Overview The embeddable framework has two types of state: `SerializedState` and `RuntimeState`. `SerializedState` is the form of the state when saved into a Dashboard saved object. I.e. the References are extracted, and state saved externally (by reference) is removed. In contrast `RuntimeState` is an exact snapshot of the state used by the embeddable to render. <b>Exposing SerializedState and RuntimeState was a mistake</b> that caused numerous regressions and architectural complexities. This PR simplifies the embeddable framework by only exposing `SerializedState`. `RuntimeState` stays localized to the embeddable implementation and is never leaked to the embeddable framework. ### Whats changed * `ReactEmbeddableFactory<SerializedState, RuntimeState, Api>` => `EmbeddableFactory<SerializedState, Api>` * `deserializeState` removed from embeddable factory. Instead, `SerializedState` is passed directly into `buildEmbeddable`. * `buildEmbeddable` parameter `buildApi` replaced with `finalizeApi`. `buildApi({ api, comparators })` => `finalizeApi(api)`. * The embeddable framework previously used its knowledge of `RuntimeState` to setup and monitor unsaved changes. Now, unsaved changes setup is pushed down to the embeddable implementation since the embeddable framework no longer has knowledge of embeddable RuntimeState. ### Reviewer instructions <b>Please prioritize reviews.</b> This is a large effort from our team and is blocking many other initiatives. Getting this merged is a top priority. This is a large change that would best be reviewed by manually testing the changes * adding/editing your embeddable types * Ensuring dashboard shows unsaved changes as expected * Ensuring dashboard resets unsaved changes as expected * Ensuring dashboard does not show unsaved changes after save and reset * Returning to a dashboard with unsaved changes renders embeddables with those unsaved changes --------- Co-authored-by: Hannah Mudge <Heenawter@users.noreply.github.com> Co-authored-by: Nathan Reese <reese.nathan@elastic.co> Co-authored-by: Nick Peihl <nick.peihl@elastic.co> Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com> Co-authored-by: Catherine Liu <catherine.liu@elastic.co> Co-authored-by: Ola Pawlus <98127445+olapawlus@users.noreply.github.com>
107 lines
4.7 KiB
TypeScript
107 lines
4.7 KiB
TypeScript
/*
|
|
* 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", the "GNU Affero General Public License v3.0 only", 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", the "GNU Affero General Public
|
|
* License v3.0 only", or the "Server Side Public License, v 1".
|
|
*/
|
|
|
|
import { ChartsPluginStart } from '@kbn/charts-plugin/public';
|
|
import { CoreSetup, CoreStart, Plugin } from '@kbn/core/public';
|
|
import { DashboardStart } from '@kbn/dashboard-plugin/public';
|
|
import { DataPublicPluginStart } from '@kbn/data-plugin/public';
|
|
import { DataViewFieldEditorStart } from '@kbn/data-view-field-editor-plugin/public';
|
|
import { DataViewsPublicPluginStart } from '@kbn/data-views-plugin/public';
|
|
import { DeveloperExamplesSetup } from '@kbn/developer-examples-plugin/public';
|
|
import { EmbeddableSetup, EmbeddableStart } from '@kbn/embeddable-plugin/public';
|
|
import { FieldFormatsStart } from '@kbn/field-formats-plugin/public';
|
|
import { UiActionsStart } from '@kbn/ui-actions-plugin/public';
|
|
import { setupApp } from './app/setup_app';
|
|
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 { 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';
|
|
|
|
export interface SetupDeps {
|
|
developerExamples: DeveloperExamplesSetup;
|
|
embeddable: EmbeddableSetup;
|
|
uiActions: UiActionsStart;
|
|
}
|
|
|
|
export interface StartDeps {
|
|
dataViews: DataViewsPublicPluginStart;
|
|
dataViewFieldEditor: DataViewFieldEditorStart;
|
|
embeddable: EmbeddableStart;
|
|
uiActions: UiActionsStart;
|
|
data: DataPublicPluginStart;
|
|
charts: ChartsPluginStart;
|
|
fieldFormats: FieldFormatsStart;
|
|
dashboard: DashboardStart;
|
|
}
|
|
|
|
export class EmbeddableExamplesPlugin implements Plugin<void, void, SetupDeps, StartDeps> {
|
|
public setup(core: CoreSetup<StartDeps>, { embeddable, developerExamples }: SetupDeps) {
|
|
setupApp(core, developerExamples);
|
|
|
|
const startServicesPromise = core.getStartServices();
|
|
|
|
embeddable.registerReactEmbeddableFactory(FIELD_LIST_ID, async () => {
|
|
const { getFieldListFactory } = await import(
|
|
'./react_embeddables/field_list/field_list_embeddable'
|
|
);
|
|
const [coreStart, deps] = await startServicesPromise;
|
|
return getFieldListFactory(coreStart, deps);
|
|
});
|
|
|
|
embeddable.registerReactEmbeddableFactory(EUI_MARKDOWN_ID, async () => {
|
|
const { markdownEmbeddableFactory } = await import(
|
|
'./react_embeddables/eui_markdown/eui_markdown_react_embeddable'
|
|
);
|
|
return markdownEmbeddableFactory;
|
|
});
|
|
|
|
embeddable.registerReactEmbeddableFactory(DATA_TABLE_ID, async () => {
|
|
const { getDataTableFactory } = await import(
|
|
'./react_embeddables/data_table/data_table_react_embeddable'
|
|
);
|
|
const [coreStart, deps] = await startServicesPromise;
|
|
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)))
|
|
);
|
|
}
|
|
|
|
public start(core: CoreStart, deps: StartDeps) {
|
|
registerCreateFieldListAction(deps.uiActions);
|
|
registerFieldListPanelPlacementSetting(deps.dashboard);
|
|
|
|
registerCreateEuiMarkdownAction(deps.uiActions);
|
|
|
|
registerAddSearchPanelAction(deps.uiActions);
|
|
|
|
registerCreateDataTableAction(deps.uiActions);
|
|
|
|
registerCreateSavedBookAction(deps.uiActions, core);
|
|
}
|
|
|
|
public stop() {}
|
|
}
|