Skip to content

Commit

Permalink
migrate openFlyout / flyout service
Browse files Browse the repository at this point in the history
Signed-off-by: pgayvallet <pierre.gayvallet@elastic.co>
  • Loading branch information
pgayvallet committed Oct 23, 2019
1 parent 5b1f4ce commit c2b90c9
Show file tree
Hide file tree
Showing 12 changed files with 90 additions and 62 deletions.
22 changes: 13 additions & 9 deletions src/core/public/overlays/__snapshots__/flyout.test.tsx.snap

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

29 changes: 20 additions & 9 deletions src/core/public/overlays/flyout.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
*/
import { mockReactDomRender, mockReactDomUnmount } from './flyout.test.mocks';

import React from 'react';
import { mount } from 'enzyme';
import { i18nServiceMock } from '../i18n/i18n_service.mock';
import { FlyoutRef, FlyoutService } from './flyout';

Expand All @@ -29,14 +29,23 @@ beforeEach(() => {
mockReactDomUnmount.mockClear();
});

const mountText = (text: string) => (container: HTMLElement) => {
const content = document.createElement('span');
content.textContent = text;
container.append(content);
return () => {};
};

describe('FlyoutService', () => {
describe('openFlyout()', () => {
it('renders a flyout to the DOM', () => {
const target = document.createElement('div');
const flyoutService = new FlyoutService(target);
expect(mockReactDomRender).not.toHaveBeenCalled();
flyoutService.openFlyout(i18nMock, <span>Flyout content</span>);
flyoutService.openFlyout(i18nMock, mountText('Flyout content'));
expect(mockReactDomRender.mock.calls).toMatchSnapshot();
const modalContent = mount(mockReactDomRender.mock.calls[0][0]);
expect(modalContent.html()).toMatchSnapshot();
});
describe('with a currently active flyout', () => {
let target: HTMLElement;
Expand All @@ -45,19 +54,21 @@ describe('FlyoutService', () => {
beforeEach(() => {
target = document.createElement('div');
flyoutService = new FlyoutService(target);
ref1 = flyoutService.openFlyout(i18nMock, <span>Flyout content 1</span>);
ref1 = flyoutService.openFlyout(i18nMock, mountText('Flyout content'));
});
it('replaces the current flyout with a new one', () => {
flyoutService.openFlyout(i18nMock, <span>Flyout content 2</span>);
flyoutService.openFlyout(i18nMock, mountText('Flyout content 2'));
expect(mockReactDomRender.mock.calls).toMatchSnapshot();
expect(mockReactDomUnmount).toHaveBeenCalledTimes(1);
const modalContent = mount(mockReactDomRender.mock.calls[1][0]);
expect(modalContent.html()).toMatchSnapshot();
expect(() => ref1.close()).not.toThrowError();
expect(mockReactDomUnmount).toHaveBeenCalledTimes(1);
});
it('resolves onClose on the previous ref', async () => {
const onCloseComplete = jest.fn();
ref1.onClose.then(onCloseComplete);
flyoutService.openFlyout(i18nMock, <span>Flyout content 2</span>);
flyoutService.openFlyout(i18nMock, mountText('Flyout content 2'));
await ref1.onClose;
expect(onCloseComplete).toBeCalledTimes(1);
});
Expand All @@ -67,7 +78,7 @@ describe('FlyoutService', () => {
it('resolves the onClose Promise', async () => {
const target = document.createElement('div');
const flyoutService = new FlyoutService(target);
const ref = flyoutService.openFlyout(i18nMock, <span>Flyout content</span>);
const ref = flyoutService.openFlyout(i18nMock, mountText('Flyout content'));

const onCloseComplete = jest.fn();
ref.onClose.then(onCloseComplete);
Expand All @@ -78,7 +89,7 @@ describe('FlyoutService', () => {
it('can be called multiple times on the same FlyoutRef', async () => {
const target = document.createElement('div');
const flyoutService = new FlyoutService(target);
const ref = flyoutService.openFlyout(i18nMock, <span>Flyout content</span>);
const ref = flyoutService.openFlyout(i18nMock, mountText('Flyout content'));
expect(mockReactDomUnmount).not.toHaveBeenCalled();
await ref.close();
expect(mockReactDomUnmount.mock.calls).toMatchSnapshot();
Expand All @@ -88,8 +99,8 @@ describe('FlyoutService', () => {
it("on a stale FlyoutRef doesn't affect the active flyout", async () => {
const target = document.createElement('div');
const flyoutService = new FlyoutService(target);
const ref1 = flyoutService.openFlyout(i18nMock, <span>Flyout content 1</span>);
const ref2 = flyoutService.openFlyout(i18nMock, <span>Flyout content 2</span>);
const ref1 = flyoutService.openFlyout(i18nMock, mountText('Flyout content 1'));
const ref2 = flyoutService.openFlyout(i18nMock, mountText('Flyout content 2'));
const onCloseComplete = jest.fn();
ref2.onClose.then(onCloseComplete);
mockReactDomUnmount.mockClear();
Expand Down
8 changes: 5 additions & 3 deletions src/core/public/overlays/flyout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ import { render, unmountComponentAtNode } from 'react-dom';
import { Subject } from 'rxjs';
import { I18nStart } from '../i18n';
import { OverlayRef } from './overlay_service';
import { MountPoint } from './types';
import { MountWrapper } from './utils';

/**
* A FlyoutRef is a reference to an opened flyout panel. It offers methods to
Expand Down Expand Up @@ -76,12 +78,12 @@ export class FlyoutService {
* Opens a flyout panel with the given component inside. You can use
* `close()` on the returned FlyoutRef to close the flyout.
*
* @param flyoutChildren - Mounts the children inside a flyout panel
* @param flyoutMount - Mounts the children inside a flyout panel
* @return {FlyoutRef} A reference to the opened flyout panel.
*/
public openFlyout = (
i18n: I18nStart,
flyoutChildren: React.ReactNode,
flyoutMount: MountPoint,
flyoutProps: {
closeButtonAriaLabel?: string;
'data-test-subj'?: string;
Expand All @@ -107,7 +109,7 @@ export class FlyoutService {
render(
<i18n.Context>
<EuiFlyout {...flyoutProps} onClose={() => flyout.close()}>
{flyoutChildren}
<MountWrapper mount={flyoutMount} />
</EuiFlyout>
</i18n.Context>,
this.targetDomElement
Expand Down
4 changes: 1 addition & 3 deletions src/core/public/overlays/overlay_service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@
* under the License.
*/

import React from 'react';

import { FlyoutService } from './flyout';
import { ModalService } from './modal';
import { I18nStart } from '../i18n';
Expand Down Expand Up @@ -77,7 +75,7 @@ export interface OverlayStart {
/** {@link OverlayBannersStart} */
banners: OverlayBannersStart;
openFlyout: (
flyoutChildren: React.ReactNode,
flyoutChildren: MountPoint,
flyoutProps?: {
closeButtonAriaLabel?: string;
'data-test-subj'?: string;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
*/
import React from 'react';
import { NotificationsStart, OverlayStart } from 'src/core/public';
import { mountForComponent } from '../../../../../../../kibana_react/public';
import { IContainer } from '../../../../containers';
import { AddPanelFlyout } from './add_panel_flyout';
import { GetEmbeddableFactory, GetEmbeddableFactories } from '../../../../types';
Expand All @@ -39,18 +40,20 @@ export async function openAddPanelFlyout(options: {
SavedObjectFinder,
} = options;
const flyoutSession = overlays.openFlyout(
<AddPanelFlyout
container={embeddable}
onClose={() => {
if (flyoutSession) {
flyoutSession.close();
}
}}
getFactory={getFactory}
getAllFactories={getAllFactories}
notifications={notifications}
SavedObjectFinder={SavedObjectFinder}
/>,
mountForComponent(
<AddPanelFlyout
container={embeddable}
onClose={() => {
if (flyoutSession) {
flyoutSession.close();
}
}}
getFactory={getFactory}
getAllFactories={getAllFactories}
notifications={notifications}
SavedObjectFinder={SavedObjectFinder}
/>
),
{
'data-test-subj': 'addPanelFlyout',
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ export function createSendMessageAction(overlays: CoreStart['overlays']) {
const greeting = `Hello, ${context.embeddable.getOutput().fullName}`;

const content = message ? `${greeting}. ${message}` : greeting;
overlays.openFlyout(<EuiFlyoutBody>{content}</EuiFlyoutBody>);
overlays.openFlyout(mountForComponent(<EuiFlyoutBody>{content}</EuiFlyoutBody>));
};

return createAction<ActionContext>({
Expand Down
5 changes: 4 additions & 1 deletion src/plugins/inspector/public/plugin.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import { i18n } from '@kbn/i18n';
import * as React from 'react';
import { PluginInitializerContext, CoreSetup, CoreStart, Plugin } from '../../../core/public';
import { mountForComponent } from '../../kibana_react/public';
import { InspectorViewRegistry } from './view_registry';
import { Adapters, InspectorOptions, InspectorSession } from './types';
import { InspectorPanel } from './ui/inspector_panel';
Expand Down Expand Up @@ -99,7 +100,9 @@ export class InspectorPublicPlugin implements Plugin<Setup, Start> {
}

return core.overlays.openFlyout(
<InspectorPanel views={views} adapters={adapters} title={options.title} />,
mountForComponent(
<InspectorPanel views={views} adapters={adapters} title={options.title} />
),
{
'data-test-subj': 'inspectorPanel',
closeButtonAriaLabel: closeButtonLabel,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,11 @@ test('can open flyout with React element', () => {
overlays.openFlyout(<div>foo</div>);

expect(coreOverlays.openFlyout).toHaveBeenCalledTimes(1);
expect(coreOverlays.openFlyout.mock.calls[0][0]).toMatchInlineSnapshot(`
<React.Fragment>
<div>
foo
</div>
</React.Fragment>
`);

const container = document.createElement('div');
const mount = coreOverlays.openFlyout.mock.calls[0][0];
mount(container);
expect(container.innerHTML).toMatchInlineSnapshot(`"<div>foo</div>"`);
});

test('can open modal with React element', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export const createReactOverlays = (services: KibanaServices): KibanaReactOverla

const openFlyout: KibanaReactOverlays['openFlyout'] = (node, options?) => {
checkCoreService();
return services.overlays!.openFlyout(<>{node}</>, options);
return services.overlays!.openFlyout(mountForComponent(<>{node}</>), options);
};

const openModal: KibanaReactOverlays['openModal'] = (node, options?) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import React from 'react';
import { EuiFlyout } from '@elastic/eui';
import { CoreStart } from 'src/core/public';
import { createAction, IAction } from '../../actions';
import { mountForComponent } from '../../../../kibana_react/public';

export const HELLO_WORLD_ACTION_ID = 'HELLO_WORLD_ACTION_ID';

Expand All @@ -29,9 +30,11 @@ export function createHelloWorldAction(overlays: CoreStart['overlays']): IAction
type: HELLO_WORLD_ACTION_ID,
execute: async () => {
const flyoutSession = overlays.openFlyout(
<EuiFlyout ownFocus onClose={() => flyoutSession && flyoutSession.close()}>
Hello World, I am a hello world action!
</EuiFlyout>,
mountForComponent(
<EuiFlyout ownFocus onClose={() => flyoutSession && flyoutSession.close()}>
Hello World, I am a hello world action!
</EuiFlyout>
),
{
'data-test-subj': 'helloWorldAction',
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import React from 'react';
import { EuiFlyout } from '@elastic/eui';
import { CoreStart } from 'src/core/public';
import { IAction, createAction } from '../../actions';
import { mountForComponent } from '../../../../kibana_react/public';

export const SAY_HELLO_ACTION = 'SAY_HELLO_ACTION';

Expand All @@ -31,9 +32,11 @@ export function createSayHelloAction(overlays: CoreStart['overlays']): IAction<{
isCompatible: async ({ name }) => name !== undefined,
execute: async context => {
const flyoutSession = overlays.openFlyout(
<EuiFlyout ownFocus onClose={() => flyoutSession && flyoutSession.close()}>
this.getDisplayName(context)
</EuiFlyout>,
mountForComponent(
<EuiFlyout ownFocus onClose={() => flyoutSession && flyoutSession.close()}>
this.getDisplayName(context)
</EuiFlyout>
),
{
'data-test-subj': 'sayHelloAction',
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import { npStart, npSetup } from 'ui/new_platform';

import { CONTEXT_MENU_TRIGGER, IEmbeddable } from '../../../../../src/plugins/embeddable/public';
import { createAction } from '../../../../../src/plugins/ui_actions/public';
import { mountForComponent } from '../../../../../src/plugins/kibana_react/public';

interface ActionContext {
embeddable: IEmbeddable;
Expand All @@ -36,16 +37,18 @@ function createSamplePanelAction() {
return;
}
npStart.core.overlays.openFlyout(
<React.Fragment>
<EuiFlyoutHeader>
<EuiTitle size="m" data-test-subj="samplePanelActionTitle">
<h1>{embeddable.getTitle()}</h1>
</EuiTitle>
</EuiFlyoutHeader>
<EuiFlyoutBody>
<h3 data-test-subj="samplePanelActionBody">This is a sample action</h3>
</EuiFlyoutBody>
</React.Fragment>,
mountForComponent(
<React.Fragment>
<EuiFlyoutHeader>
<EuiTitle size="m" data-test-subj="samplePanelActionTitle">
<h1>{embeddable.getTitle()}</h1>
</EuiTitle>
</EuiFlyoutHeader>
<EuiFlyoutBody>
<h3 data-test-subj="samplePanelActionBody">This is a sample action</h3>
</EuiFlyoutBody>
</React.Fragment>
),
{
'data-test-subj': 'samplePanelActionFlyout',
}
Expand Down

0 comments on commit c2b90c9

Please sign in to comment.