diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablestart.getembeddablepanel.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablestart.getembeddablepanel.md
deleted file mode 100644
index 7ba24a62a3893..0000000000000
--- a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablestart.getembeddablepanel.md
+++ /dev/null
@@ -1,11 +0,0 @@
-
-
-[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [EmbeddableStart](./kibana-plugin-plugins-embeddable-public.embeddablestart.md) > [getEmbeddablePanel](./kibana-plugin-plugins-embeddable-public.embeddablestart.getembeddablepanel.md)
-
-## EmbeddableStart.getEmbeddablePanel property
-
-Signature:
-
-```typescript
-getEmbeddablePanel: (stateTransfer?: EmbeddableStateTransfer) => EmbeddablePanelHOC;
-```
diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablestart.getstatetransfer.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablestart.getstatetransfer.md
index dafc66b1a6e15..a07021ee456e0 100644
--- a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablestart.getstatetransfer.md
+++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablestart.getstatetransfer.md
@@ -7,5 +7,5 @@
Signature:
```typescript
-getStateTransfer: (history?: ScopedHistory) => EmbeddableStateTransfer;
+getStateTransfer: (storage?: Storage) => EmbeddableStateTransfer;
```
diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablestart.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablestart.md
index f500196d850a2..2b04d4502e8a8 100644
--- a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablestart.md
+++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablestart.md
@@ -18,6 +18,5 @@ export interface EmbeddableStart extends PersistableStateService<A extends {
title: string;
}, V extends EmbeddableInput & {
[ATTRIBUTE_SERVICE_KEY]: A;
} = EmbeddableInput & {
[ATTRIBUTE_SERVICE_KEY]: A;
}, R extends SavedObjectEmbeddableInput = SavedObjectEmbeddableInput>(type: string, options: AttributeServiceOptions<A>) => AttributeService<A, V, R>
| |
| [getEmbeddableFactories](./kibana-plugin-plugins-embeddable-public.embeddablestart.getembeddablefactories.md) | () => IterableIterator<EmbeddableFactory>
| |
| [getEmbeddableFactory](./kibana-plugin-plugins-embeddable-public.embeddablestart.getembeddablefactory.md) | <I extends EmbeddableInput = EmbeddableInput, O extends EmbeddableOutput = EmbeddableOutput, E extends IEmbeddable<I, O> = IEmbeddable<I, O>>(embeddableFactoryId: string) => EmbeddableFactory<I, O, E> | undefined
| |
-| [getEmbeddablePanel](./kibana-plugin-plugins-embeddable-public.embeddablestart.getembeddablepanel.md) | (stateTransfer?: EmbeddableStateTransfer) => EmbeddablePanelHOC
| |
-| [getStateTransfer](./kibana-plugin-plugins-embeddable-public.embeddablestart.getstatetransfer.md) | (history?: ScopedHistory) => EmbeddableStateTransfer
| |
+| [getStateTransfer](./kibana-plugin-plugins-embeddable-public.embeddablestart.getstatetransfer.md) | (storage?: Storage) => EmbeddableStateTransfer
| |
diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablestatetransfer._constructor_.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablestatetransfer._constructor_.md
index 323ed5e38bde1..276499b435e1f 100644
--- a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablestatetransfer._constructor_.md
+++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablestatetransfer._constructor_.md
@@ -9,7 +9,7 @@ Constructs a new instance of the `EmbeddableStateTransfer` class
Signature:
```typescript
-constructor(navigateToApp: ApplicationStart['navigateToApp'], scopedHistory?: ScopedHistory | undefined, appList?: ReadonlyMap | undefined);
+constructor(navigateToApp: ApplicationStart['navigateToApp'], appList?: ReadonlyMap | undefined, customStorage?: Storage);
```
## Parameters
@@ -17,6 +17,6 @@ constructor(navigateToApp: ApplicationStart['navigateToApp'], scopedHistory?: Sc
| Parameter | Type | Description |
| --- | --- | --- |
| navigateToApp | ApplicationStart['navigateToApp']
| |
-| scopedHistory | ScopedHistory<unknown> | undefined
| |
| appList | ReadonlyMap<string, PublicAppInfo> | undefined
| |
+| customStorage | Storage
| |
diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablestatetransfer.cleareditorstate.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablestatetransfer.cleareditorstate.md
new file mode 100644
index 0000000000000..5c1a6a0393c2e
--- /dev/null
+++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablestatetransfer.cleareditorstate.md
@@ -0,0 +1,15 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-embeddable-public](./kibana-plugin-plugins-embeddable-public.md) > [EmbeddableStateTransfer](./kibana-plugin-plugins-embeddable-public.embeddablestatetransfer.md) > [clearEditorState](./kibana-plugin-plugins-embeddable-public.embeddablestatetransfer.cleareditorstate.md)
+
+## EmbeddableStateTransfer.clearEditorState() method
+
+Signature:
+
+```typescript
+clearEditorState(): void;
+```
+Returns:
+
+`void`
+
diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablestatetransfer.getincomingeditorstate.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablestatetransfer.getincomingeditorstate.md
index 2a0823a9bf835..1434de2c9870e 100644
--- a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablestatetransfer.getincomingeditorstate.md
+++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablestatetransfer.getincomingeditorstate.md
@@ -4,21 +4,19 @@
## EmbeddableStateTransfer.getIncomingEditorState() method
-Fetches an [originating app](./kibana-plugin-plugins-embeddable-public.embeddableeditorstate.md) argument from the scoped history's location state.
+Fetches an [originating app](./kibana-plugin-plugins-embeddable-public.embeddableeditorstate.md) argument from the sessionStorage
Signature:
```typescript
-getIncomingEditorState(options?: {
- keysToRemoveAfterFetch?: string[];
- }): EmbeddableEditorState | undefined;
+getIncomingEditorState(removeAfterFetch?: boolean): EmbeddableEditorState | undefined;
```
## Parameters
| Parameter | Type | Description |
| --- | --- | --- |
-| options | {
keysToRemoveAfterFetch?: string[];
}
| |
+| removeAfterFetch | boolean
| Whether to remove the package state after fetch to prevent duplicates. |
Returns:
diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablestatetransfer.getincomingembeddablepackage.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablestatetransfer.getincomingembeddablepackage.md
index 2069f0ce084f9..9ead71f0bb22c 100644
--- a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablestatetransfer.getincomingembeddablepackage.md
+++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablestatetransfer.getincomingembeddablepackage.md
@@ -4,21 +4,19 @@
## EmbeddableStateTransfer.getIncomingEmbeddablePackage() method
-Fetches an [embeddable package](./kibana-plugin-plugins-embeddable-public.embeddablepackagestate.md) argument from the scoped history's location state.
+Fetches an [embeddable package](./kibana-plugin-plugins-embeddable-public.embeddablepackagestate.md) argument from the sessionStorage
Signature:
```typescript
-getIncomingEmbeddablePackage(options?: {
- keysToRemoveAfterFetch?: string[];
- }): EmbeddablePackageState | undefined;
+getIncomingEmbeddablePackage(removeAfterFetch?: boolean): EmbeddablePackageState | undefined;
```
## Parameters
| Parameter | Type | Description |
| --- | --- | --- |
-| options | {
keysToRemoveAfterFetch?: string[];
}
| |
+| removeAfterFetch | boolean
| Whether to remove the package state after fetch to prevent duplicates. |
Returns:
diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablestatetransfer.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablestatetransfer.md
index 2b44693e14846..3676b744b8cc9 100644
--- a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablestatetransfer.md
+++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablestatetransfer.md
@@ -4,7 +4,7 @@
## EmbeddableStateTransfer class
-A wrapper around the state object in which provides strongly typed helper methods for common incoming and outgoing states used by the embeddable infrastructure.
+A wrapper around the session storage which provides strongly typed helper methods for common incoming and outgoing states used by the embeddable infrastructure.
Signature:
@@ -16,7 +16,7 @@ export declare class EmbeddableStateTransfer
| Constructor | Modifiers | Description |
| --- | --- | --- |
-| [(constructor)(navigateToApp, scopedHistory, appList)](./kibana-plugin-plugins-embeddable-public.embeddablestatetransfer._constructor_.md) | | Constructs a new instance of the EmbeddableStateTransfer
class |
+| [(constructor)(navigateToApp, appList, customStorage)](./kibana-plugin-plugins-embeddable-public.embeddablestatetransfer._constructor_.md) | | Constructs a new instance of the EmbeddableStateTransfer
class |
## Properties
@@ -28,8 +28,9 @@ export declare class EmbeddableStateTransfer
| Method | Modifiers | Description |
| --- | --- | --- |
-| [getIncomingEditorState(options)](./kibana-plugin-plugins-embeddable-public.embeddablestatetransfer.getincomingeditorstate.md) | | Fetches an [originating app](./kibana-plugin-plugins-embeddable-public.embeddableeditorstate.md) argument from the scoped history's location state. |
-| [getIncomingEmbeddablePackage(options)](./kibana-plugin-plugins-embeddable-public.embeddablestatetransfer.getincomingembeddablepackage.md) | | Fetches an [embeddable package](./kibana-plugin-plugins-embeddable-public.embeddablepackagestate.md) argument from the scoped history's location state. |
+| [clearEditorState()](./kibana-plugin-plugins-embeddable-public.embeddablestatetransfer.cleareditorstate.md) | | |
+| [getIncomingEditorState(removeAfterFetch)](./kibana-plugin-plugins-embeddable-public.embeddablestatetransfer.getincomingeditorstate.md) | | Fetches an [originating app](./kibana-plugin-plugins-embeddable-public.embeddableeditorstate.md) argument from the sessionStorage |
+| [getIncomingEmbeddablePackage(removeAfterFetch)](./kibana-plugin-plugins-embeddable-public.embeddablestatetransfer.getincomingembeddablepackage.md) | | Fetches an [embeddable package](./kibana-plugin-plugins-embeddable-public.embeddablepackagestate.md) argument from the sessionStorage |
| [navigateToEditor(appId, options)](./kibana-plugin-plugins-embeddable-public.embeddablestatetransfer.navigatetoeditor.md) | | A wrapper around the method which navigates to the specified appId with [embeddable editor state](./kibana-plugin-plugins-embeddable-public.embeddableeditorstate.md) |
| [navigateToWithEmbeddablePackage(appId, options)](./kibana-plugin-plugins-embeddable-public.embeddablestatetransfer.navigatetowithembeddablepackage.md) | | A wrapper around the method which navigates to the specified appId with [embeddable package state](./kibana-plugin-plugins-embeddable-public.embeddablepackagestate.md) |
diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablestatetransfer.navigatetoeditor.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablestatetransfer.navigatetoeditor.md
index fa24784d9aac5..4bd5f44084a33 100644
--- a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablestatetransfer.navigatetoeditor.md
+++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablestatetransfer.navigatetoeditor.md
@@ -12,7 +12,6 @@ A wrapper around the method which navigates to the specified appId with [embedd
navigateToEditor(appId: string, options?: {
path?: string;
state: EmbeddableEditorState;
- appendToExistingState?: boolean;
}): Promise;
```
@@ -21,7 +20,7 @@ navigateToEditor(appId: string, options?: {
| Parameter | Type | Description |
| --- | --- | --- |
| appId | string
| |
-| options | {
path?: string;
state: EmbeddableEditorState;
appendToExistingState?: boolean;
}
| |
+| options | {
path?: string;
state: EmbeddableEditorState;
}
| |
Returns:
diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablestatetransfer.navigatetowithembeddablepackage.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablestatetransfer.navigatetowithembeddablepackage.md
index 7173bc8b127cd..0fd82167805ab 100644
--- a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablestatetransfer.navigatetowithembeddablepackage.md
+++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablestatetransfer.navigatetowithembeddablepackage.md
@@ -12,7 +12,6 @@ A wrapper around the method which navigates to the specified appId with [embedd
navigateToWithEmbeddablePackage(appId: string, options?: {
path?: string;
state: EmbeddablePackageState;
- appendToExistingState?: boolean;
}): Promise;
```
@@ -21,7 +20,7 @@ navigateToWithEmbeddablePackage(appId: string, options?: {
| Parameter | Type | Description |
| --- | --- | --- |
| appId | string
| |
-| options | {
path?: string;
state: EmbeddablePackageState;
appendToExistingState?: boolean;
}
| |
+| options | {
path?: string;
state: EmbeddablePackageState;
}
| |
Returns:
diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.md
index f1ea605703e59..a6aeba23cd280 100644
--- a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.md
+++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.md
@@ -17,7 +17,7 @@
| [EmbeddableFactoryNotFoundError](./kibana-plugin-plugins-embeddable-public.embeddablefactorynotfounderror.md) | |
| [EmbeddablePanel](./kibana-plugin-plugins-embeddable-public.embeddablepanel.md) | |
| [EmbeddableRoot](./kibana-plugin-plugins-embeddable-public.embeddableroot.md) | |
-| [EmbeddableStateTransfer](./kibana-plugin-plugins-embeddable-public.embeddablestatetransfer.md) | A wrapper around the state object in which provides strongly typed helper methods for common incoming and outgoing states used by the embeddable infrastructure. |
+| [EmbeddableStateTransfer](./kibana-plugin-plugins-embeddable-public.embeddablestatetransfer.md) | A wrapper around the session storage which provides strongly typed helper methods for common incoming and outgoing states used by the embeddable infrastructure. |
| [ErrorEmbeddable](./kibana-plugin-plugins-embeddable-public.errorembeddable.md) | |
| [PanelNotFoundError](./kibana-plugin-plugins-embeddable-public.panelnotfounderror.md) | |
diff --git a/src/plugins/dashboard/public/application/embeddable/dashboard_container.tsx b/src/plugins/dashboard/public/application/embeddable/dashboard_container.tsx
index a4a79a5d183ae..01b4e81fc484c 100644
--- a/src/plugins/dashboard/public/application/embeddable/dashboard_container.tsx
+++ b/src/plugins/dashboard/public/application/embeddable/dashboard_container.tsx
@@ -36,7 +36,6 @@ import {
EmbeddableStart,
EmbeddableOutput,
EmbeddableFactory,
- EmbeddableStateTransfer,
} from '../../services/embeddable';
import { DASHBOARD_CONTAINER_TYPE } from './dashboard_constants';
import { createPanelState } from './panel';
@@ -111,8 +110,6 @@ const defaultCapabilities = {
export class DashboardContainer extends Container {
public readonly type = DASHBOARD_CONTAINER_TYPE;
-
- private embeddablePanel: EmbeddableStart['EmbeddablePanel'];
public switchViewMode?: (newViewMode: ViewMode) => void;
public getPanelCount = () => {
@@ -122,7 +119,6 @@ export class DashboardContainer extends Container
-
+
,
dom
diff --git a/src/plugins/dashboard/public/application/embeddable/dashboard_container_factory.tsx b/src/plugins/dashboard/public/application/embeddable/dashboard_container_factory.tsx
index 98b4947066c00..0e1ee5bf82eac 100644
--- a/src/plugins/dashboard/public/application/embeddable/dashboard_container_factory.tsx
+++ b/src/plugins/dashboard/public/application/embeddable/dashboard_container_factory.tsx
@@ -18,7 +18,6 @@
*/
import { i18n } from '@kbn/i18n';
-import { ScopedHistory } from 'src/core/public';
import {
Container,
ErrorEmbeddable,
@@ -44,10 +43,7 @@ export class DashboardContainerFactoryDefinition
public readonly isContainerType = true;
public readonly type = DASHBOARD_CONTAINER_TYPE;
- constructor(
- private readonly getStartServices: () => Promise,
- private getHistory: () => ScopedHistory
- ) {}
+ constructor(private readonly getStartServices: () => Promise) {}
public isEditable = async () => {
// Currently unused for dashboards
@@ -74,7 +70,6 @@ export class DashboardContainerFactoryDefinition
parent?: Container
): Promise => {
const services = await this.getStartServices();
- const stateTransfer = services.embeddable.getStateTransfer(this.getHistory());
- return new DashboardContainer(initialInput, services, stateTransfer, parent);
+ return new DashboardContainer(initialInput, services, parent);
};
}
diff --git a/src/plugins/dashboard/public/application/embeddable/grid/dashboard_grid.test.tsx b/src/plugins/dashboard/public/application/embeddable/grid/dashboard_grid.test.tsx
index fb29ef7b3c036..ef23c636ad482 100644
--- a/src/plugins/dashboard/public/application/embeddable/grid/dashboard_grid.test.tsx
+++ b/src/plugins/dashboard/public/application/embeddable/grid/dashboard_grid.test.tsx
@@ -83,7 +83,6 @@ function prepare(props?: Partial) {
dashboardContainer = new DashboardContainer(initialInput, options);
const defaultTestProps: DashboardGridProps = {
container: dashboardContainer,
- PanelComponent: () => ,
kibana: null as any,
intl: null as any,
};
diff --git a/src/plugins/dashboard/public/application/embeddable/grid/dashboard_grid.tsx b/src/plugins/dashboard/public/application/embeddable/grid/dashboard_grid.tsx
index c2e8661e2ab12..c5929c5d85dbb 100644
--- a/src/plugins/dashboard/public/application/embeddable/grid/dashboard_grid.tsx
+++ b/src/plugins/dashboard/public/application/embeddable/grid/dashboard_grid.tsx
@@ -30,7 +30,7 @@ import React from 'react';
import { Subscription } from 'rxjs';
import ReactGridLayout, { Layout } from 'react-grid-layout';
import { GridData } from '../../../../common';
-import { ViewMode, EmbeddableChildPanel, EmbeddableStart } from '../../../services/embeddable';
+import { ViewMode, EmbeddableChildPanel } from '../../../services/embeddable';
import { DASHBOARD_GRID_COLUMN_COUNT, DASHBOARD_GRID_HEIGHT } from '../dashboard_constants';
import { DashboardPanelState } from '../types';
import { withKibana } from '../../../services/kibana_react';
@@ -115,7 +115,6 @@ const ResponsiveSizedGrid = sizeMe(config)(ResponsiveGrid);
export interface DashboardGridProps extends ReactIntl.InjectedIntlProps {
kibana: DashboardReactContextValue;
- PanelComponent: EmbeddableStart['EmbeddablePanel'];
container: DashboardContainer;
}
@@ -277,7 +276,7 @@ class DashboardGridUi extends React.Component {
key={panel.type}
embeddableId={panel.explicitInput.id}
container={this.props.container}
- PanelComponent={this.props.PanelComponent}
+ PanelComponent={this.props.kibana.services.embeddable.EmbeddablePanel}
/>
);
diff --git a/src/plugins/dashboard/public/application/embeddable/viewport/dashboard_viewport.test.tsx b/src/plugins/dashboard/public/application/embeddable/viewport/dashboard_viewport.test.tsx
index e5a1852fa61a5..925687a07bb42 100644
--- a/src/plugins/dashboard/public/application/embeddable/viewport/dashboard_viewport.test.tsx
+++ b/src/plugins/dashboard/public/application/embeddable/viewport/dashboard_viewport.test.tsx
@@ -92,7 +92,6 @@ function getProps(
dashboardContainer = new DashboardContainer(input, options);
const defaultTestProps: DashboardViewportProps = {
container: dashboardContainer,
- PanelComponent: () => ,
};
return {
diff --git a/src/plugins/dashboard/public/application/embeddable/viewport/dashboard_viewport.tsx b/src/plugins/dashboard/public/application/embeddable/viewport/dashboard_viewport.tsx
index 558867ba50091..2d8b2566358a1 100644
--- a/src/plugins/dashboard/public/application/embeddable/viewport/dashboard_viewport.tsx
+++ b/src/plugins/dashboard/public/application/embeddable/viewport/dashboard_viewport.tsx
@@ -21,7 +21,6 @@ import React from 'react';
import { Subscription } from 'rxjs';
import {
PanelState,
- EmbeddableStart,
ViewMode,
isErrorEmbeddable,
openAddPanelFlyout,
@@ -33,7 +32,6 @@ import { context } from '../../../services/kibana_react';
import { DashboardEmptyScreen } from '../empty_screen/dashboard_empty_screen';
export interface DashboardViewportProps {
- PanelComponent: EmbeddableStart['EmbeddablePanel'];
switchViewMode?: (newViewMode: ViewMode) => void;
container: DashboardContainer;
}
@@ -131,7 +129,7 @@ export class DashboardViewport extends React.Component
)}
-
+
);
diff --git a/src/plugins/dashboard/public/application/hooks/use_dashboard_container.ts b/src/plugins/dashboard/public/application/hooks/use_dashboard_container.ts
index a331871ea7e36..319794bae8847 100644
--- a/src/plugins/dashboard/public/application/hooks/use_dashboard_container.ts
+++ b/src/plugins/dashboard/public/application/hooks/use_dashboard_container.ts
@@ -79,9 +79,7 @@ export const useDashboardContainer = (
searchSession.restore(searchSessionIdFromURL);
}
- const incomingEmbeddable = embeddable
- .getStateTransfer(scopedHistory())
- .getIncomingEmbeddablePackage();
+ const incomingEmbeddable = embeddable.getStateTransfer().getIncomingEmbeddablePackage(true);
(async function createContainer() {
const newContainer = await dashboardFactory.create(
diff --git a/src/plugins/dashboard/public/plugin.tsx b/src/plugins/dashboard/public/plugin.tsx
index 97e3174fba098..4dff423098c5a 100644
--- a/src/plugins/dashboard/public/plugin.tsx
+++ b/src/plugins/dashboard/public/plugin.tsx
@@ -280,11 +280,8 @@ export class DashboardPlugin
getHistory: () => this.currentHistory!,
});
- const factory = new DashboardContainerFactoryDefinition(
- getStartServices,
- () => this.currentHistory!
- );
- embeddable.registerEmbeddableFactory(factory.type, factory);
+ const dashboardContainerFactory = new DashboardContainerFactoryDefinition(getStartServices);
+ embeddable.registerEmbeddableFactory(dashboardContainerFactory.type, dashboardContainerFactory);
const placeholderFactory = new PlaceholderEmbeddableFactory();
embeddable.registerEmbeddableFactory(placeholderFactory.type, placeholderFactory);
diff --git a/src/plugins/embeddable/public/lib/state_transfer/embeddable_state_transfer.test.ts b/src/plugins/embeddable/public/lib/state_transfer/embeddable_state_transfer.test.ts
index 4155cb4d3b60c..cbaeddf472d52 100644
--- a/src/plugins/embeddable/public/lib/state_transfer/embeddable_state_transfer.test.ts
+++ b/src/plugins/embeddable/public/lib/state_transfer/embeddable_state_transfer.test.ts
@@ -17,24 +17,45 @@
* under the License.
*/
-import { coreMock, scopedHistoryMock } from '../../../../../core/public/mocks';
+import { coreMock } from '../../../../../core/public/mocks';
+import { Storage } from '../../../../kibana_utils/public';
import { EmbeddableStateTransfer } from '.';
import { ApplicationStart, PublicAppInfo } from '../../../../../core/public';
-
-function mockHistoryState(state: unknown) {
- return scopedHistoryMock.create({ state });
-}
+import { EMBEDDABLE_EDITOR_STATE_KEY, EMBEDDABLE_PACKAGE_STATE_KEY } from './types';
+import { EMBEDDABLE_STATE_TRANSFER_STORAGE_KEY } from './embeddable_state_transfer';
+
+const createStorage = (): Storage => {
+ const createMockStore = () => {
+ let innerStore: Record = {};
+ return {
+ getItem: jest.fn().mockImplementation((key) => innerStore[key]),
+ setItem: jest.fn().mockImplementation((key, value) => (innerStore[key] = value)),
+ removeItem: jest.fn().mockImplementation((key: string) => delete innerStore[key]),
+ clear: jest.fn().mockImplementation(() => (innerStore = {})),
+ };
+ };
+ const store = createMockStore();
+ const storage = new Storage(store);
+ storage.get = jest.fn().mockImplementation((key) => store.getItem(key));
+ storage.set = jest.fn().mockImplementation((key, value) => store.setItem(key, value));
+ storage.remove = jest.fn().mockImplementation((key: string) => store.removeItem(key));
+ storage.clear = jest.fn().mockImplementation(() => store.clear());
+ return storage;
+};
describe('embeddable state transfer', () => {
let application: jest.Mocked;
let stateTransfer: EmbeddableStateTransfer;
+ let store: Storage;
+
const destinationApp = 'superUltraVisualize';
const originatingApp = 'superUltraTestDashboard';
beforeEach(() => {
const core = coreMock.createStart();
application = core.application;
- stateTransfer = new EmbeddableStateTransfer(application.navigateToApp);
+ store = createStorage();
+ stateTransfer = new EmbeddableStateTransfer(application.navigateToApp, undefined, store);
});
it('cannot fetch app name when given no app list', async () => {
@@ -46,7 +67,7 @@ describe('embeddable state transfer', () => {
['testId', { title: 'State Transfer Test App Hello' } as PublicAppInfo],
['testId2', { title: 'State Transfer Test App Goodbye' } as PublicAppInfo],
]);
- stateTransfer = new EmbeddableStateTransfer(application.navigateToApp, undefined, appsList);
+ stateTransfer = new EmbeddableStateTransfer(application.navigateToApp, appsList);
expect(stateTransfer.getAppNameFromId('kibanana')).toBeUndefined();
});
@@ -55,31 +76,34 @@ describe('embeddable state transfer', () => {
['testId', { title: 'State Transfer Test App Hello' } as PublicAppInfo],
['testId2', { title: 'State Transfer Test App Goodbye' } as PublicAppInfo],
]);
- stateTransfer = new EmbeddableStateTransfer(application.navigateToApp, undefined, appsList);
+ stateTransfer = new EmbeddableStateTransfer(application.navigateToApp, appsList);
expect(stateTransfer.getAppNameFromId('testId')).toBe('State Transfer Test App Hello');
expect(stateTransfer.getAppNameFromId('testId2')).toBe('State Transfer Test App Goodbye');
});
- it('can send an outgoing originating app state', async () => {
+ it('can send an outgoing editor state', async () => {
await stateTransfer.navigateToEditor(destinationApp, { state: { originatingApp } });
+ expect(store.set).toHaveBeenCalledWith(EMBEDDABLE_STATE_TRANSFER_STORAGE_KEY, {
+ [EMBEDDABLE_EDITOR_STATE_KEY]: { originatingApp: 'superUltraTestDashboard' },
+ });
expect(application.navigateToApp).toHaveBeenCalledWith('superUltraVisualize', {
- state: { originatingApp: 'superUltraTestDashboard' },
+ path: undefined,
});
});
- it('can send an outgoing originating app state in append mode', async () => {
- const historyMock = mockHistoryState({ kibanaIsNowForSports: 'extremeSportsKibana' });
- stateTransfer = new EmbeddableStateTransfer(application.navigateToApp, historyMock);
+ it('can send an outgoing editor state and retain other embeddable state keys', async () => {
+ store.set(EMBEDDABLE_STATE_TRANSFER_STORAGE_KEY, {
+ kibanaIsNowForSports: 'extremeSportsKibana',
+ });
await stateTransfer.navigateToEditor(destinationApp, {
state: { originatingApp },
- appendToExistingState: true,
+ });
+ expect(store.set).toHaveBeenCalledWith(EMBEDDABLE_STATE_TRANSFER_STORAGE_KEY, {
+ kibanaIsNowForSports: 'extremeSportsKibana',
+ [EMBEDDABLE_EDITOR_STATE_KEY]: { originatingApp: 'superUltraTestDashboard' },
});
expect(application.navigateToApp).toHaveBeenCalledWith('superUltraVisualize', {
path: undefined,
- state: {
- kibanaIsNowForSports: 'extremeSportsKibana',
- originatingApp: 'superUltraTestDashboard',
- },
});
});
@@ -87,87 +111,81 @@ describe('embeddable state transfer', () => {
await stateTransfer.navigateToWithEmbeddablePackage(destinationApp, {
state: { type: 'coolestType', input: { savedObjectId: '150' } },
});
+ expect(store.set).toHaveBeenCalledWith(EMBEDDABLE_STATE_TRANSFER_STORAGE_KEY, {
+ [EMBEDDABLE_PACKAGE_STATE_KEY]: { type: 'coolestType', input: { savedObjectId: '150' } },
+ });
expect(application.navigateToApp).toHaveBeenCalledWith('superUltraVisualize', {
- state: { type: 'coolestType', input: { savedObjectId: '150' } },
+ path: undefined,
});
});
- it('can send an outgoing embeddable package state in append mode', async () => {
- const historyMock = mockHistoryState({ kibanaIsNowForSports: 'extremeSportsKibana' });
- stateTransfer = new EmbeddableStateTransfer(application.navigateToApp, historyMock);
+ it('can send an outgoing embeddable and retain other embeddable state keys', async () => {
+ store.set(EMBEDDABLE_STATE_TRANSFER_STORAGE_KEY, {
+ kibanaIsNowForSports: 'extremeSportsKibana',
+ });
await stateTransfer.navigateToWithEmbeddablePackage(destinationApp, {
state: { type: 'coolestType', input: { savedObjectId: '150' } },
- appendToExistingState: true,
+ });
+ expect(store.set).toHaveBeenCalledWith(EMBEDDABLE_STATE_TRANSFER_STORAGE_KEY, {
+ kibanaIsNowForSports: 'extremeSportsKibana',
+ [EMBEDDABLE_PACKAGE_STATE_KEY]: { type: 'coolestType', input: { savedObjectId: '150' } },
});
expect(application.navigateToApp).toHaveBeenCalledWith('superUltraVisualize', {
path: undefined,
- state: {
- kibanaIsNowForSports: 'extremeSportsKibana',
- type: 'coolestType',
- input: { savedObjectId: '150' },
- },
});
});
- it('can fetch an incoming originating app state', async () => {
- const historyMock = mockHistoryState({ originatingApp: 'extremeSportsKibana' });
- stateTransfer = new EmbeddableStateTransfer(application.navigateToApp, historyMock);
+ it('can fetch an incoming editor state', async () => {
+ store.set(EMBEDDABLE_STATE_TRANSFER_STORAGE_KEY, {
+ [EMBEDDABLE_EDITOR_STATE_KEY]: { originatingApp: 'superUltraTestDashboard' },
+ });
const fetchedState = stateTransfer.getIncomingEditorState();
- expect(fetchedState).toEqual({ originatingApp: 'extremeSportsKibana' });
+ expect(fetchedState).toEqual({ originatingApp: 'superUltraTestDashboard' });
});
- it('returns undefined with originating app state is not in the right shape', async () => {
- const historyMock = mockHistoryState({ kibanaIsNowForSports: 'extremeSportsKibana' });
- stateTransfer = new EmbeddableStateTransfer(application.navigateToApp, historyMock);
+ it('incoming editor state returns undefined when state is not in the right shape', async () => {
+ store.set(EMBEDDABLE_STATE_TRANSFER_STORAGE_KEY, {
+ [EMBEDDABLE_EDITOR_STATE_KEY]: { helloSportsKibana: 'superUltraTestDashboard' },
+ });
const fetchedState = stateTransfer.getIncomingEditorState();
expect(fetchedState).toBeUndefined();
});
it('can fetch an incoming embeddable package state', async () => {
- const historyMock = mockHistoryState({
- type: 'skisEmbeddable',
- input: { savedObjectId: '123' },
+ store.set(EMBEDDABLE_STATE_TRANSFER_STORAGE_KEY, {
+ [EMBEDDABLE_PACKAGE_STATE_KEY]: { type: 'skisEmbeddable', input: { savedObjectId: '123' } },
});
- stateTransfer = new EmbeddableStateTransfer(application.navigateToApp, historyMock);
const fetchedState = stateTransfer.getIncomingEmbeddablePackage();
expect(fetchedState).toEqual({ type: 'skisEmbeddable', input: { savedObjectId: '123' } });
});
- it('returns undefined when embeddable package is not in the right shape', async () => {
- const historyMock = mockHistoryState({ kibanaIsNowForSports: 'extremeSportsKibana' });
- stateTransfer = new EmbeddableStateTransfer(application.navigateToApp, historyMock);
+ it('embeddable package state returns undefined when state is not in the right shape', async () => {
+ store.set(EMBEDDABLE_STATE_TRANSFER_STORAGE_KEY, {
+ [EMBEDDABLE_PACKAGE_STATE_KEY]: { kibanaIsFor: 'sports' },
+ });
const fetchedState = stateTransfer.getIncomingEmbeddablePackage();
expect(fetchedState).toBeUndefined();
});
- it('removes all keys in the keysToRemoveAfterFetch array', async () => {
- const historyMock = mockHistoryState({
- type: 'skisEmbeddable',
- input: { savedObjectId: '123' },
- test1: 'test1',
- test2: 'test2',
- });
- stateTransfer = new EmbeddableStateTransfer(application.navigateToApp, historyMock);
- stateTransfer.getIncomingEmbeddablePackage({ keysToRemoveAfterFetch: ['type', 'input'] });
- expect(historyMock.replace).toHaveBeenCalledWith(
- expect.objectContaining({ state: { test1: 'test1', test2: 'test2' } })
- );
+ it('removes embeddable package key when removeAfterFetch is true', async () => {
+ store.set(EMBEDDABLE_STATE_TRANSFER_STORAGE_KEY, {
+ [EMBEDDABLE_PACKAGE_STATE_KEY]: { type: 'coolestType', input: { savedObjectId: '150' } },
+ iSHouldStillbeHere: 'doing the sports thing',
+ });
+ stateTransfer.getIncomingEmbeddablePackage(true);
+ expect(store.get(EMBEDDABLE_STATE_TRANSFER_STORAGE_KEY)).toEqual({
+ iSHouldStillbeHere: 'doing the sports thing',
+ });
});
- it('leaves state as is when no keysToRemove are supplied', async () => {
- const historyMock = mockHistoryState({
- type: 'skisEmbeddable',
- input: { savedObjectId: '123' },
- test1: 'test1',
- test2: 'test2',
- });
- stateTransfer = new EmbeddableStateTransfer(application.navigateToApp, historyMock);
- stateTransfer.getIncomingEmbeddablePackage();
- expect(historyMock.location.state).toEqual({
- type: 'skisEmbeddable',
- input: { savedObjectId: '123' },
- test1: 'test1',
- test2: 'test2',
+ it('removes editor state key when removeAfterFetch is true', async () => {
+ store.set(EMBEDDABLE_STATE_TRANSFER_STORAGE_KEY, {
+ [EMBEDDABLE_EDITOR_STATE_KEY]: { originatingApp: 'superCoolFootballDashboard' },
+ iSHouldStillbeHere: 'doing the sports thing',
+ });
+ stateTransfer.getIncomingEditorState(true);
+ expect(store.get(EMBEDDABLE_STATE_TRANSFER_STORAGE_KEY)).toEqual({
+ iSHouldStillbeHere: 'doing the sports thing',
});
});
});
diff --git a/src/plugins/embeddable/public/lib/state_transfer/embeddable_state_transfer.ts b/src/plugins/embeddable/public/lib/state_transfer/embeddable_state_transfer.ts
index 184178ba80e84..0b34bea810520 100644
--- a/src/plugins/embeddable/public/lib/state_transfer/embeddable_state_transfer.ts
+++ b/src/plugins/embeddable/public/lib/state_transfer/embeddable_state_transfer.ts
@@ -18,26 +18,35 @@
*/
import { cloneDeep } from 'lodash';
-import { ScopedHistory, ApplicationStart, PublicAppInfo } from '../../../../../core/public';
+import { Storage } from '../../../../kibana_utils/public';
+import { ApplicationStart, PublicAppInfo } from '../../../../../core/public';
import {
EmbeddableEditorState,
isEmbeddableEditorState,
EmbeddablePackageState,
isEmbeddablePackageState,
+ EMBEDDABLE_PACKAGE_STATE_KEY,
+ EMBEDDABLE_EDITOR_STATE_KEY,
} from './types';
+export const EMBEDDABLE_STATE_TRANSFER_STORAGE_KEY = 'EMBEDDABLE_STATE_TRANSFER';
+
/**
- * A wrapper around the state object in {@link ScopedHistory | core scoped history} which provides
- * strongly typed helper methods for common incoming and outgoing states used by the embeddable infrastructure.
+ * A wrapper around the session storage which provides strongly typed helper methods
+ * for common incoming and outgoing states used by the embeddable infrastructure.
*
* @public
*/
export class EmbeddableStateTransfer {
+ private storage: Storage;
+
constructor(
private navigateToApp: ApplicationStart['navigateToApp'],
- private scopedHistory?: ScopedHistory,
- private appList?: ReadonlyMap | undefined
- ) {}
+ private appList?: ReadonlyMap | undefined,
+ customStorage?: Storage
+ ) {
+ this.storage = customStorage ? customStorage : new Storage(sessionStorage);
+ }
/**
* Fetches an internationalized app title when given an appId.
@@ -46,33 +55,43 @@ export class EmbeddableStateTransfer {
public getAppNameFromId = (appId: string): string | undefined => this.appList?.get(appId)?.title;
/**
- * Fetches an {@link EmbeddableEditorState | originating app} argument from the scoped
- * history's location state.
+ * Fetches an {@link EmbeddableEditorState | originating app} argument from the sessionStorage
*
- * @param history - the scoped history to fetch from
- * @param options.keysToRemoveAfterFetch - an array of keys to be removed from the state after they are retrieved
+ * @param removeAfterFetch - Whether to remove the package state after fetch to prevent duplicates.
*/
- public getIncomingEditorState(options?: {
- keysToRemoveAfterFetch?: string[];
- }): EmbeddableEditorState | undefined {
- return this.getIncomingState(isEmbeddableEditorState, {
- keysToRemoveAfterFetch: options?.keysToRemoveAfterFetch,
- });
+ public getIncomingEditorState(removeAfterFetch?: boolean): EmbeddableEditorState | undefined {
+ return this.getIncomingState(
+ isEmbeddableEditorState,
+ EMBEDDABLE_EDITOR_STATE_KEY,
+ {
+ keysToRemoveAfterFetch: removeAfterFetch ? [EMBEDDABLE_EDITOR_STATE_KEY] : undefined,
+ }
+ );
+ }
+
+ public clearEditorState() {
+ const currentState = this.storage.get(EMBEDDABLE_STATE_TRANSFER_STORAGE_KEY);
+ if (currentState) {
+ delete currentState[EMBEDDABLE_EDITOR_STATE_KEY];
+ this.storage.set(EMBEDDABLE_STATE_TRANSFER_STORAGE_KEY, currentState);
+ }
}
/**
- * Fetches an {@link EmbeddablePackageState | embeddable package} argument from the scoped
- * history's location state.
+ * Fetches an {@link EmbeddablePackageState | embeddable package} argument from the sessionStorage
*
- * @param history - the scoped history to fetch from
- * @param options.keysToRemoveAfterFetch - an array of keys to be removed from the state after they are retrieved
+ * @param removeAfterFetch - Whether to remove the package state after fetch to prevent duplicates.
*/
- public getIncomingEmbeddablePackage(options?: {
- keysToRemoveAfterFetch?: string[];
- }): EmbeddablePackageState | undefined {
- return this.getIncomingState(isEmbeddablePackageState, {
- keysToRemoveAfterFetch: options?.keysToRemoveAfterFetch,
- });
+ public getIncomingEmbeddablePackage(
+ removeAfterFetch?: boolean
+ ): EmbeddablePackageState | undefined {
+ return this.getIncomingState(
+ isEmbeddablePackageState,
+ EMBEDDABLE_PACKAGE_STATE_KEY,
+ {
+ keysToRemoveAfterFetch: removeAfterFetch ? [EMBEDDABLE_PACKAGE_STATE_KEY] : undefined,
+ }
+ );
}
/**
@@ -84,10 +103,12 @@ export class EmbeddableStateTransfer {
options?: {
path?: string;
state: EmbeddableEditorState;
- appendToExistingState?: boolean;
}
): Promise {
- await this.navigateToWithState(appId, options);
+ await this.navigateToWithState(appId, EMBEDDABLE_EDITOR_STATE_KEY, {
+ ...options,
+ appendToExistingState: true,
+ });
}
/**
@@ -96,44 +117,46 @@ export class EmbeddableStateTransfer {
*/
public async navigateToWithEmbeddablePackage(
appId: string,
- options?: { path?: string; state: EmbeddablePackageState; appendToExistingState?: boolean }
+ options?: { path?: string; state: EmbeddablePackageState }
): Promise {
- await this.navigateToWithState(appId, options);
+ await this.navigateToWithState(appId, EMBEDDABLE_PACKAGE_STATE_KEY, {
+ ...options,
+ appendToExistingState: true,
+ });
}
private getIncomingState(
guard: (state: unknown) => state is IncomingStateType,
+ key: string,
options?: {
keysToRemoveAfterFetch?: string[];
}
): IncomingStateType | undefined {
- if (!this.scopedHistory) {
- throw new TypeError('ScopedHistory is required to fetch incoming state');
- }
- const incomingState = this.scopedHistory.location?.state;
+ const incomingState = this.storage.get(EMBEDDABLE_STATE_TRANSFER_STORAGE_KEY)?.[key];
const castState =
!guard || guard(incomingState) ? (cloneDeep(incomingState) as IncomingStateType) : undefined;
if (castState && options?.keysToRemoveAfterFetch) {
- const stateReplace = { ...(this.scopedHistory.location.state as { [key: string]: unknown }) };
- options.keysToRemoveAfterFetch.forEach((key: string) => {
- delete stateReplace[key];
+ const stateReplace = { ...this.storage.get(EMBEDDABLE_STATE_TRANSFER_STORAGE_KEY) };
+ options.keysToRemoveAfterFetch.forEach((keyToRemove: string) => {
+ delete stateReplace[keyToRemove];
});
- this.scopedHistory.replace({ ...this.scopedHistory.location, state: stateReplace });
+ this.storage.set(EMBEDDABLE_STATE_TRANSFER_STORAGE_KEY, stateReplace);
}
return castState;
}
private async navigateToWithState(
appId: string,
+ key: string,
options?: { path?: string; state?: OutgoingStateType; appendToExistingState?: boolean }
): Promise {
- const stateObject =
- options?.appendToExistingState && this.scopedHistory
- ? {
- ...(this.scopedHistory?.location.state as { [key: string]: unknown }),
- ...options.state,
- }
- : options?.state;
- await this.navigateToApp(appId, { path: options?.path, state: stateObject });
+ const stateObject = options?.appendToExistingState
+ ? {
+ ...this.storage.get(EMBEDDABLE_STATE_TRANSFER_STORAGE_KEY),
+ [key]: options.state,
+ }
+ : { [key]: options?.state };
+ this.storage.set(EMBEDDABLE_STATE_TRANSFER_STORAGE_KEY, stateObject);
+ await this.navigateToApp(appId, { path: options?.path });
}
}
diff --git a/src/plugins/embeddable/public/lib/state_transfer/types.ts b/src/plugins/embeddable/public/lib/state_transfer/types.ts
index d36954528dbf0..3ce62a6acb35b 100644
--- a/src/plugins/embeddable/public/lib/state_transfer/types.ts
+++ b/src/plugins/embeddable/public/lib/state_transfer/types.ts
@@ -20,6 +20,8 @@
import { Optional } from '@kbn/utility-types';
import { EmbeddableInput, SavedObjectEmbeddableInput } from '..';
+export const EMBEDDABLE_EDITOR_STATE_KEY = 'embeddable_editor_state';
+
/**
* A state package that contains information an editor will need to create or edit an embeddable then redirect back.
* @public
@@ -34,6 +36,8 @@ export function isEmbeddableEditorState(state: unknown): state is EmbeddableEdit
return ensureFieldOfTypeExists('originatingApp', state, 'string');
}
+export const EMBEDDABLE_PACKAGE_STATE_KEY = 'embeddable_package_state';
+
/**
* A state package that contains all fields necessary to create or update an embeddable by reference or by value in a container.
* @public
diff --git a/src/plugins/embeddable/public/mocks.tsx b/src/plugins/embeddable/public/mocks.tsx
index c5a9860498117..df24d9c0393fe 100644
--- a/src/plugins/embeddable/public/mocks.tsx
+++ b/src/plugins/embeddable/public/mocks.tsx
@@ -81,6 +81,7 @@ export const createEmbeddablePanelMock = ({
export const createEmbeddableStateTransferMock = (): Partial => {
return {
+ clearEditorState: jest.fn(),
getIncomingEditorState: jest.fn(),
getIncomingEmbeddablePackage: jest.fn(),
navigateToEditor: jest.fn(),
@@ -125,7 +126,6 @@ const createStartContract = (): Start => {
inject: jest.fn(),
migrate: jest.fn(),
EmbeddablePanel: jest.fn(),
- getEmbeddablePanel: jest.fn(),
getStateTransfer: jest.fn(() => createEmbeddableStateTransferMock() as EmbeddableStateTransfer),
getAttributeService: jest.fn(),
};
diff --git a/src/plugins/embeddable/public/plugin.tsx b/src/plugins/embeddable/public/plugin.tsx
index 4f3de0425579c..5118a1a8818c0 100644
--- a/src/plugins/embeddable/public/plugin.tsx
+++ b/src/plugins/embeddable/public/plugin.tsx
@@ -28,7 +28,6 @@ import {
CoreSetup,
CoreStart,
Plugin,
- ScopedHistory,
PublicAppInfo,
} from '../../../core/public';
import {
@@ -50,6 +49,7 @@ import {
} from './lib';
import { EmbeddableFactoryDefinition } from './lib/embeddables/embeddable_factory_definition';
import { EmbeddableStateTransfer } from './lib/state_transfer';
+import { Storage } from '../../kibana_utils/public';
import { PersistableStateService, SerializableState } from '../../kibana_utils/common';
import { ATTRIBUTE_SERVICE_KEY, AttributeService } from './lib/attribute_service';
import { AttributeServiceOptions } from './lib/attribute_service/attribute_service';
@@ -95,8 +95,7 @@ export interface EmbeddableStart extends PersistableStateService EmbeddableFactory | undefined;
getEmbeddableFactories: () => IterableIterator;
EmbeddablePanel: EmbeddablePanelHOC;
- getEmbeddablePanel: (stateTransfer?: EmbeddableStateTransfer) => EmbeddablePanelHOC;
- getStateTransfer: (history?: ScopedHistory) => EmbeddableStateTransfer;
+ getStateTransfer: (storage?: Storage) => EmbeddableStateTransfer;
getAttributeService: <
A extends { title: string },
V extends EmbeddableInput & { [ATTRIBUTE_SERVICE_KEY]: A } = EmbeddableInput & {
@@ -119,7 +118,7 @@ export class EmbeddablePublicPlugin implements Plugin;
private appListSubscription?: Subscription;
@@ -160,14 +159,13 @@ export class EmbeddablePublicPlugin implements Plugin ({
+ const getEmbeddablePanelHoc = () => ({
embeddable,
hideHeader,
}: {
@@ -177,7 +175,7 @@ export class EmbeddablePublicPlugin implements Plugin {
- return history
- ? new EmbeddableStateTransfer(core.application.navigateToApp, history, this.appList)
- : this.outgoingOnlyStateTransfer;
- },
+ getStateTransfer: (storage?: Storage) =>
+ storage
+ ? new EmbeddableStateTransfer(core.application.navigateToApp, this.appList, storage)
+ : this.stateTransferService,
EmbeddablePanel: getEmbeddablePanelHoc(),
- getEmbeddablePanel: getEmbeddablePanelHoc,
telemetry: getTelemetryFunction(commonContract),
extract: getExtractFunction(commonContract),
inject: getInjectFunction(commonContract),
diff --git a/src/plugins/embeddable/public/public.api.md b/src/plugins/embeddable/public/public.api.md
index 4b7d60b4dc9ec..fc9454d7f77ed 100644
--- a/src/plugins/embeddable/public/public.api.md
+++ b/src/plugins/embeddable/public/public.api.md
@@ -39,7 +39,7 @@ import { I18nStart as I18nStart_2 } from 'src/core/public';
import { IconType } from '@elastic/eui';
import { ISearchOptions } from 'src/plugins/data/public';
import { ISearchSource } from 'src/plugins/data/public';
-import { IStorageWrapper } from 'src/plugins/kibana_utils/public';
+import { IStorageWrapper as IStorageWrapper_2 } from 'src/plugins/kibana_utils/public';
import { IUiSettingsClient as IUiSettingsClient_2 } from 'src/core/public';
import { KibanaClient } from '@elastic/elasticsearch/api/kibana';
import { KibanaConfigType } from 'src/core/server/kibana_config';
@@ -604,12 +604,10 @@ export interface EmbeddableStart extends PersistableStateService IterableIterator;
// (undocumented)
getEmbeddableFactory: = IEmbeddable>(embeddableFactoryId: string) => EmbeddableFactory | undefined;
- // (undocumented)
- getEmbeddablePanel: (stateTransfer?: EmbeddableStateTransfer) => EmbeddablePanelHOC;
- // Warning: (ae-forgotten-export) The symbol "ScopedHistory" needs to be exported by the entry point index.d.ts
+ // Warning: (ae-forgotten-export) The symbol "Storage" needs to be exported by the entry point index.d.ts
//
// (undocumented)
- getStateTransfer: (history?: ScopedHistory) => EmbeddableStateTransfer;
+ getStateTransfer: (storage?: Storage) => EmbeddableStateTransfer;
}
// Warning: (ae-missing-release-tag) "EmbeddableStartDependencies" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
@@ -630,31 +628,25 @@ export interface EmbeddableStartDependencies {
uiActions: UiActionsStart;
}
-// Warning: (ae-unresolved-link) The @link reference could not be resolved: The package "kibana" does not have an export "ScopedHistory"
-//
// @public
export class EmbeddableStateTransfer {
// Warning: (ae-forgotten-export) The symbol "ApplicationStart" needs to be exported by the entry point index.d.ts
// Warning: (ae-forgotten-export) The symbol "PublicAppInfo" needs to be exported by the entry point index.d.ts
- constructor(navigateToApp: ApplicationStart['navigateToApp'], scopedHistory?: ScopedHistory | undefined, appList?: ReadonlyMap | undefined);
+ constructor(navigateToApp: ApplicationStart['navigateToApp'], appList?: ReadonlyMap | undefined, customStorage?: Storage);
+ // (undocumented)
+ clearEditorState(): void;
getAppNameFromId: (appId: string) => string | undefined;
- getIncomingEditorState(options?: {
- keysToRemoveAfterFetch?: string[];
- }): EmbeddableEditorState | undefined;
- getIncomingEmbeddablePackage(options?: {
- keysToRemoveAfterFetch?: string[];
- }): EmbeddablePackageState | undefined;
+ getIncomingEditorState(removeAfterFetch?: boolean): EmbeddableEditorState | undefined;
+ getIncomingEmbeddablePackage(removeAfterFetch?: boolean): EmbeddablePackageState | undefined;
// Warning: (ae-unresolved-link) The @link reference could not be resolved: The package "kibana" does not have an export "ApplicationStart"
navigateToEditor(appId: string, options?: {
path?: string;
state: EmbeddableEditorState;
- appendToExistingState?: boolean;
}): Promise;
// Warning: (ae-unresolved-link) The @link reference could not be resolved: The package "kibana" does not have an export "ApplicationStart"
navigateToWithEmbeddablePackage(appId: string, options?: {
path?: string;
state: EmbeddablePackageState;
- appendToExistingState?: boolean;
}): Promise;
}
diff --git a/src/plugins/visualize/public/application/components/visualize_byvalue_editor.tsx b/src/plugins/visualize/public/application/components/visualize_byvalue_editor.tsx
index 1c1eb9956a329..e4577cb76ab06 100644
--- a/src/plugins/visualize/public/application/components/visualize_byvalue_editor.tsx
+++ b/src/plugins/visualize/public/application/components/visualize_byvalue_editor.tsx
@@ -45,10 +45,7 @@ export const VisualizeByValueEditor = ({ onAppLeave }: VisualizeAppProps) => {
useEffect(() => {
const { originatingApp: value, embeddableId: embeddableIdValue, valueInput: valueInputValue } =
- services.embeddable
- .getStateTransfer(services.scopedHistory)
- .getIncomingEditorState({ keysToRemoveAfterFetch: ['id', 'embeddableId', 'valueInput'] }) ||
- {};
+ services.embeddable.getStateTransfer().getIncomingEditorState() || {};
setOriginatingApp(value);
setValueInput(valueInputValue);
setEmbeddableId(embeddableIdValue);
diff --git a/src/plugins/visualize/public/application/components/visualize_editor.tsx b/src/plugins/visualize/public/application/components/visualize_editor.tsx
index 7c0fa065c3a71..b13169d4b62ec 100644
--- a/src/plugins/visualize/public/application/components/visualize_editor.tsx
+++ b/src/plugins/visualize/public/application/components/visualize_editor.tsx
@@ -65,9 +65,7 @@ export const VisualizeEditor = ({ onAppLeave }: VisualizeAppProps) => {
useEffect(() => {
const { originatingApp: value } =
- services.embeddable
- .getStateTransfer(services.scopedHistory)
- .getIncomingEditorState({ keysToRemoveAfterFetch: ['id', 'input'] }) || {};
+ services.embeddable.getStateTransfer().getIncomingEditorState() || {};
setOriginatingApp(value);
}, [services]);
diff --git a/src/plugins/visualize/public/application/components/visualize_listing.tsx b/src/plugins/visualize/public/application/components/visualize_listing.tsx
index b2ca784162623..5720eca57e7a5 100644
--- a/src/plugins/visualize/public/application/components/visualize_listing.tsx
+++ b/src/plugins/visualize/public/application/components/visualize_listing.tsx
@@ -45,6 +45,7 @@ export const VisualizeListing = () => {
savedVisualizations,
toastNotifications,
visualizations,
+ embeddable,
savedObjects,
savedObjectsPublic,
savedObjectsTagging,
@@ -72,6 +73,8 @@ export const VisualizeListing = () => {
}, [history, pathname, visualizations]);
useMount(() => {
+ // Reset editor state if the visualize listing page is loaded.
+ embeddable.getStateTransfer().clearEditorState();
chrome.setBreadcrumbs([
{
text: i18n.translate('visualize.visualizeListingBreadcrumbsTitle', {
diff --git a/src/plugins/visualize/public/application/utils/get_top_nav_config.tsx b/src/plugins/visualize/public/application/utils/get_top_nav_config.tsx
index dbdef182d419d..6ebe65fd960b4 100644
--- a/src/plugins/visualize/public/application/utils/get_top_nav_config.tsx
+++ b/src/plugins/visualize/public/application/utils/get_top_nav_config.tsx
@@ -77,6 +77,7 @@ export const getTopNavConfig = (
{
application,
chrome,
+ embeddable,
history,
share,
setActiveUrl,
@@ -137,6 +138,8 @@ export const getTopNavConfig = (
} else {
if (setOriginatingApp && originatingApp && newlyCreated) {
setOriginatingApp(undefined);
+ // remove editor state so the connection is still broken after reload
+ stateTransfer.clearEditorState();
}
chrome.docTitle.change(savedVis.lastSavedTitle);
chrome.setBreadcrumbs(getEditBreadcrumbs(savedVis.lastSavedTitle));
diff --git a/x-pack/plugins/lens/public/app_plugin/app.test.tsx b/x-pack/plugins/lens/public/app_plugin/app.test.tsx
index 7e7156793e18b..1496b0c335322 100644
--- a/x-pack/plugins/lens/public/app_plugin/app.test.tsx
+++ b/x-pack/plugins/lens/public/app_plugin/app.test.tsx
@@ -37,9 +37,13 @@ import {
LensByReferenceInput,
} from '../editor_frame_service/embeddable/embeddable';
import { SavedObjectReference } from '../../../../../src/core/types';
-import { mockAttributeService } from '../../../../../src/plugins/embeddable/public/mocks';
+import {
+ mockAttributeService,
+ createEmbeddableStateTransferMock,
+} from '../../../../../src/plugins/embeddable/public/mocks';
import { LensAttributeService } from '../lens_attribute_service';
import { KibanaContextProvider } from '../../../../../src/plugins/kibana_react/public';
+import { EmbeddableStateTransfer } from '../../../../../src/plugins/embeddable/public';
jest.mock('../editor_frame_service/editor_frame/expression_helpers');
jest.mock('src/core/public');
@@ -181,6 +185,7 @@ describe('Lens App', () => {
attributeService: makeAttributeService(),
savedObjectsClient: core.savedObjects.client,
dashboardFeatureFlag: { allowByValueEmbeddables: false },
+ stateTransfer: createEmbeddableStateTransferMock() as EmbeddableStateTransfer,
getOriginatingAppName: jest.fn(() => 'defaultOriginatingApp'),
application: {
...core.application,
diff --git a/x-pack/plugins/lens/public/app_plugin/app.tsx b/x-pack/plugins/lens/public/app_plugin/app.tsx
index 931e0df2cd50e..bb77c5998519d 100644
--- a/x-pack/plugins/lens/public/app_plugin/app.tsx
+++ b/x-pack/plugins/lens/public/app_plugin/app.tsx
@@ -59,6 +59,7 @@ export function App({
navigation,
uiSettings,
application,
+ stateTransfer,
notifications,
attributeService,
savedObjectsClient,
@@ -463,6 +464,9 @@ export function App({
isSaveModalVisible: false,
isLinkedToOriginatingApp: false,
}));
+ // remove editor state so the connection is still broken after reload
+ stateTransfer.clearEditorState();
+
redirectTo(newInput.savedObjectId);
return;
}
diff --git a/x-pack/plugins/lens/public/app_plugin/mounter.tsx b/x-pack/plugins/lens/public/app_plugin/mounter.tsx
index 3bc2a8956e61a..b09ecfdcd5553 100644
--- a/x-pack/plugins/lens/public/app_plugin/mounter.tsx
+++ b/x-pack/plugins/lens/public/app_plugin/mounter.tsx
@@ -46,7 +46,7 @@ export async function mountApp(
const instance = await createEditorFrame();
const storage = new Storage(localStorage);
- const stateTransfer = embeddable?.getStateTransfer(params.history);
+ const stateTransfer = embeddable?.getStateTransfer();
const historyLocationState = params.history.location.state as HistoryLocationState;
const embeddableEditorIncomingState = stateTransfer?.getIncomingEditorState();
@@ -54,6 +54,7 @@ export async function mountApp(
data,
storage,
navigation,
+ stateTransfer,
savedObjectsTagging,
attributeService: await attributeService(),
http: coreStart.http,
@@ -86,14 +87,15 @@ export async function mountApp(
);
const getInitialInput = (
- routeProps: RouteComponentProps<{ id?: string }>
+ routeProps: RouteComponentProps<{ id?: string }>,
+ editByValue?: boolean
): LensEmbeddableInput | undefined => {
+ if (editByValue) {
+ return embeddableEditorIncomingState?.valueInput as LensByValueInput;
+ }
if (routeProps.match.params.id) {
return { savedObjectId: routeProps.match.params.id } as LensByReferenceInput;
}
- if (embeddableEditorIncomingState?.valueInput) {
- return embeddableEditorIncomingState?.valueInput as LensByValueInput;
- }
};
const redirectTo = (routeProps: RouteComponentProps<{ id?: string }>, savedObjectId?: string) => {
@@ -142,14 +144,16 @@ export async function mountApp(
}
};
- // const featureFlagConfig = await getByValueFeatureFlag();
- const renderEditor = (routeProps: RouteComponentProps<{ id?: string }>) => {
+ const renderEditor = (
+ routeProps: RouteComponentProps<{ id?: string }>,
+ editByValue?: boolean
+ ) => {
trackUiEvent('loaded');
return (
redirectTo(routeProps, savedObjectId)}
redirectToOrigin={redirectToOrigin}
redirectToDashboard={redirectToDashboard}
@@ -182,7 +186,11 @@ export async function mountApp(
-
+ renderEditor(routeProps, true)}
+ />
diff --git a/x-pack/plugins/lens/public/app_plugin/types.ts b/x-pack/plugins/lens/public/app_plugin/types.ts
index e09d7389b9d46..869ccf52fb0bd 100644
--- a/x-pack/plugins/lens/public/app_plugin/types.ts
+++ b/x-pack/plugins/lens/public/app_plugin/types.ts
@@ -33,7 +33,10 @@ import {
VisualizeFieldContext,
ACTION_VISUALIZE_LENS_FIELD,
} from '../../../../../src/plugins/ui_actions/public';
-import { EmbeddableEditorState } from '../../../../../src/plugins/embeddable/public';
+import {
+ EmbeddableEditorState,
+ EmbeddableStateTransfer,
+} from '../../../../../src/plugins/embeddable/public';
import { TableInspectorAdapter } from '../editor_frame_service/types';
import { EditorFrameInstance } from '..';
@@ -100,6 +103,7 @@ export interface LensAppServices {
uiSettings: IUiSettingsClient;
application: ApplicationStart;
notifications: NotificationsStart;
+ stateTransfer: EmbeddableStateTransfer;
navigation: NavigationPublicPluginStart;
attributeService: LensAttributeService;
savedObjectsClient: SavedObjectsStart['client'];
diff --git a/x-pack/plugins/maps/public/render_app.tsx b/x-pack/plugins/maps/public/render_app.tsx
index 68b74211ee273..a20649f8ebe1e 100644
--- a/x-pack/plugins/maps/public/render_app.tsx
+++ b/x-pack/plugins/maps/public/render_app.tsx
@@ -76,12 +76,10 @@ export async function renderApp({
setAppChrome();
function renderMapApp(routeProps: RouteComponentProps<{ savedMapId?: string }>) {
- const stateTransfer = getEmbeddableService()?.getStateTransfer(
- history as AppMountParameters['history']
- );
+ const stateTransfer = getEmbeddableService()?.getStateTransfer();
const { embeddableId, originatingApp, valueInput } =
- stateTransfer?.getIncomingEditorState({ keysToRemoveAfterFetch: ['originatingApp'] }) || {};
+ stateTransfer?.getIncomingEditorState() || {};
let mapEmbeddableInput;
if (routeProps.match.params.savedMapId) {
diff --git a/x-pack/plugins/maps/public/routes/map_page/saved_map/saved_map.ts b/x-pack/plugins/maps/public/routes/map_page/saved_map/saved_map.ts
index 43f9e47aa8677..3930b57b32280 100644
--- a/x-pack/plugins/maps/public/routes/map_page/saved_map/saved_map.ts
+++ b/x-pack/plugins/maps/public/routes/map_page/saved_map/saved_map.ts
@@ -329,6 +329,10 @@ export class SavedMap {
this._mapEmbeddableInput = updatedMapEmbeddableInput;
// break connection to originating application
this._originatingApp = undefined;
+
+ // remove editor state so the connection is still broken after reload
+ this._getStateTransfer().clearEditorState();
+
getToasts().addSuccess({
title: i18n.translate('xpack.maps.topNav.saveSuccessMessage', {
defaultMessage: `Saved '{title}'`,