Skip to content

Commit

Permalink
prep state transfer for passing embeddables by value to editor and ba…
Browse files Browse the repository at this point in the history
…ck (#69991)

Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
  • Loading branch information
ThomThomson and elasticmachine committed Jun 26, 2020
1 parent 3aa59e9 commit 5ad865e
Show file tree
Hide file tree
Showing 13 changed files with 61 additions and 37 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ import {
ViewMode,
SavedObjectEmbeddableInput,
ContainerOutput,
EmbeddableInput,
} from '../../../embeddable/public';
import { NavAction, SavedDashboardPanel } from '../types';

Expand Down Expand Up @@ -430,9 +431,16 @@ export class DashboardAppController {
.getStateTransfer(scopedHistory())
.getIncomingEmbeddablePackage();
if (incomingState) {
container.addNewEmbeddable<SavedObjectEmbeddableInput>(incomingState.type, {
savedObjectId: incomingState.id,
});
if ('id' in incomingState) {
container.addNewEmbeddable<SavedObjectEmbeddableInput>(incomingState.type, {
savedObjectId: incomingState.id,
});
} else if ('input' in incomingState) {
container.addNewEmbeddable<EmbeddableInput>(
incomingState.type,
incomingState.input
);
}
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/plugins/embeddable/public/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ export {
isRangeSelectTriggerContext,
isValueClickTriggerContext,
EmbeddableStateTransfer,
EmbeddableOriginatingAppState,
EmbeddableEditorState,
EmbeddablePackageState,
EmbeddableRenderer,
EmbeddableRendererProps,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ test('redirects to app using state transfer', async () => {
const embeddable = new EditableEmbeddable({ id: '123', viewMode: ViewMode.EDIT }, true);
embeddable.getOutput = jest.fn(() => ({ editApp: 'ultraVisualize', editPath: '/123' }));
await action.execute({ embeddable });
expect(stateTransferMock.navigateToWithOriginatingApp).toHaveBeenCalledWith('ultraVisualize', {
expect(stateTransferMock.navigateToEditor).toHaveBeenCalledWith('ultraVisualize', {
path: '/123',
state: { originatingApp: 'superCoolCurrentApp' },
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import { take } from 'rxjs/operators';
import { ViewMode } from '../types';
import { EmbeddableFactoryNotFoundError } from '../errors';
import { EmbeddableStart } from '../../plugin';
import { IEmbeddable, EmbeddableOriginatingAppState, EmbeddableStateTransfer } from '../..';
import { IEmbeddable, EmbeddableEditorState, EmbeddableStateTransfer } from '../..';

export const ACTION_EDIT_PANEL = 'editPanel';

Expand All @@ -35,7 +35,7 @@ interface ActionContext {
interface NavigationContext {
app: string;
path: string;
state?: EmbeddableOriginatingAppState;
state?: EmbeddableEditorState;
}

export class EditPanelAction implements Action<ActionContext> {
Expand Down Expand Up @@ -88,7 +88,7 @@ export class EditPanelAction implements Action<ActionContext> {
const appTarget = this.getAppTarget(context);
if (appTarget) {
if (this.stateTransfer && appTarget.state) {
await this.stateTransfer.navigateToWithOriginatingApp(appTarget.app, {
await this.stateTransfer.navigateToEditor(appTarget.app, {
path: appTarget.path,
state: appTarget.state,
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ describe('embeddable state transfer', () => {
});

it('can send an outgoing originating app state', async () => {
await stateTransfer.navigateToWithOriginatingApp(destinationApp, { state: { originatingApp } });
await stateTransfer.navigateToEditor(destinationApp, { state: { originatingApp } });
expect(application.navigateToApp).toHaveBeenCalledWith('superUltraVisualize', {
state: { originatingApp: 'superUltraTestDashboard' },
});
Expand All @@ -50,7 +50,7 @@ describe('embeddable state transfer', () => {
application.navigateToApp,
(historyMock as unknown) as ScopedHistory
);
await stateTransfer.navigateToWithOriginatingApp(destinationApp, {
await stateTransfer.navigateToEditor(destinationApp, {
state: { originatingApp },
appendToExistingState: true,
});
Expand Down Expand Up @@ -94,7 +94,7 @@ describe('embeddable state transfer', () => {
application.navigateToApp,
(historyMock as unknown) as ScopedHistory
);
const fetchedState = stateTransfer.getIncomingOriginatingApp();
const fetchedState = stateTransfer.getIncomingEditorState();
expect(fetchedState).toEqual({ originatingApp: 'extremeSportsKibana' });
});

Expand All @@ -104,7 +104,7 @@ describe('embeddable state transfer', () => {
application.navigateToApp,
(historyMock as unknown) as ScopedHistory
);
const fetchedState = stateTransfer.getIncomingOriginatingApp();
const fetchedState = stateTransfer.getIncomingEditorState();
expect(fetchedState).toBeUndefined();
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@
import { cloneDeep } from 'lodash';
import { ScopedHistory, ApplicationStart } from '../../../../../core/public';
import {
EmbeddableOriginatingAppState,
isEmbeddableOriginatingAppState,
EmbeddableEditorState,
isEmbeddableEditorState,
EmbeddablePackageState,
isEmbeddablePackageState,
} from './types';
Expand All @@ -39,16 +39,16 @@ export class EmbeddableStateTransfer {
) {}

/**
* Fetches an {@link EmbeddableOriginatingAppState | originating app} argument from the scoped
* Fetches an {@link EmbeddableEditorState | originating app} argument from the scoped
* history's location state.
*
* @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
*/
public getIncomingOriginatingApp(options?: {
public getIncomingEditorState(options?: {
keysToRemoveAfterFetch?: string[];
}): EmbeddableOriginatingAppState | undefined {
return this.getIncomingState<EmbeddableOriginatingAppState>(isEmbeddableOriginatingAppState, {
}): EmbeddableEditorState | undefined {
return this.getIncomingState<EmbeddableEditorState>(isEmbeddableEditorState, {
keysToRemoveAfterFetch: options?.keysToRemoveAfterFetch,
});
}
Expand All @@ -70,17 +70,17 @@ export class EmbeddableStateTransfer {

/**
* A wrapper around the {@link ApplicationStart.navigateToApp} method which navigates to the specified appId
* with {@link EmbeddableOriginatingAppState | originating app state}
* with {@link EmbeddableEditorState | embeddable editor state}
*/
public async navigateToWithOriginatingApp(
public async navigateToEditor(
appId: string,
options?: {
path?: string;
state: EmbeddableOriginatingAppState;
state: EmbeddableEditorState;
appendToExistingState?: boolean;
}
): Promise<void> {
await this.navigateToWithState<EmbeddableOriginatingAppState>(appId, options);
await this.navigateToWithState<EmbeddableEditorState>(appId, options);
}

/**
Expand Down
2 changes: 1 addition & 1 deletion src/plugins/embeddable/public/lib/state_transfer/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,4 @@
*/

export { EmbeddableStateTransfer } from './embeddable_state_transfer';
export { EmbeddableOriginatingAppState, EmbeddablePackageState } from './types';
export { EmbeddableEditorState, EmbeddablePackageState } from './types';
32 changes: 24 additions & 8 deletions src/plugins/embeddable/public/lib/state_transfer/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,33 +17,49 @@
* under the License.
*/

import { EmbeddableInput } from '..';

/**
* Represents a state package that contains the last active app id.
* @public
*/
export interface EmbeddableOriginatingAppState {
export interface EmbeddableEditorState {
originatingApp: string;
byValueMode?: boolean;
valueInput?: EmbeddableInput;
}

export function isEmbeddableOriginatingAppState(
state: unknown
): state is EmbeddableOriginatingAppState {
export function isEmbeddableEditorState(state: unknown): state is EmbeddableEditorState {
return ensureFieldOfTypeExists('originatingApp', state, 'string');
}

/**
* Represents a state package that contains all fields necessary to create an embeddable in a container.
* Represents a state package that contains all fields necessary to create an embeddable by reference in a container.
* @public
*/
export interface EmbeddablePackageState {
export interface EmbeddablePackageByReferenceState {
type: string;
id: string;
}

/**
* Represents a state package that contains all fields necessary to create an embeddable by value in a container.
* @public
*/
export interface EmbeddablePackageByValueState {
type: string;
input: EmbeddableInput;
}

export type EmbeddablePackageState =
| EmbeddablePackageByReferenceState
| EmbeddablePackageByValueState;

export function isEmbeddablePackageState(state: unknown): state is EmbeddablePackageState {
return (
ensureFieldOfTypeExists('type', state, 'string') &&
ensureFieldOfTypeExists('id', state, 'string')
(ensureFieldOfTypeExists('type', state, 'string') &&
ensureFieldOfTypeExists('id', state, 'string')) ||
ensureFieldOfTypeExists('input', state, 'object')
);
}

Expand Down
4 changes: 2 additions & 2 deletions src/plugins/embeddable/public/mocks.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,9 @@ export const createEmbeddablePanelMock = ({

export const createEmbeddableStateTransferMock = (): Partial<EmbeddableStateTransfer> => {
return {
getIncomingOriginatingApp: jest.fn(),
getIncomingEditorState: jest.fn(),
getIncomingEmbeddablePackage: jest.fn(),
navigateToWithOriginatingApp: jest.fn(),
navigateToEditor: jest.fn(),
navigateToWithEmbeddablePackage: jest.fn(),
};
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ describe('NewVisModal', () => {
);
const visButton = wrapper.find('button[data-test-subj="visType-visWithAliasUrl"]');
visButton.simulate('click');
expect(stateTransfer.navigateToWithOriginatingApp).toBeCalledWith('otherApp', {
expect(stateTransfer.navigateToEditor).toBeCalledWith('otherApp', {
path: '#/aliasUrl',
state: { originatingApp: 'coolJestTestApp' },
});
Expand Down
2 changes: 1 addition & 1 deletion src/plugins/visualizations/public/wizard/new_vis_modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ class NewVisModal extends React.Component<TypeSelectionProps, TypeSelectionState

private navigate(appId: string, params: string) {
if (this.props.stateTransfer && this.props.originatingApp) {
this.props.stateTransfer.navigateToWithOriginatingApp(appId, {
this.props.stateTransfer.navigateToEditor(appId, {
path: params,
state: { originatingApp: this.props.originatingApp },
});
Expand Down
2 changes: 1 addition & 1 deletion src/plugins/visualize/public/application/editor/editor.js
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ function VisualizeAppController($scope, $route, $injector, $timeout, kbnUrlState
};

const { originatingApp } =
embeddable.getStateTransfer(scopedHistory()).getIncomingOriginatingApp() || {};
embeddable.getStateTransfer(scopedHistory()).getIncomingEditorState() || {};
$scope.getOriginatingApp = () => originatingApp;

const visStateToEditorState = () => {
Expand Down
2 changes: 1 addition & 1 deletion x-pack/plugins/lens/public/app_plugin/mounter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export async function mountApp(

const stateTransfer = embeddable?.getStateTransfer(params.history);
const { originatingApp } =
stateTransfer?.getIncomingOriginatingApp({ keysToRemoveAfterFetch: ['originatingApp'] }) || {};
stateTransfer?.getIncomingEditorState({ keysToRemoveAfterFetch: ['originatingApp'] }) || {};

const instance = await createEditorFrame();

Expand Down

0 comments on commit 5ad865e

Please sign in to comment.