Skip to content

Commit

Permalink
Remove react references from core OverlayService apis (#48431)
Browse files Browse the repository at this point in the history
* move/rename overlay mount and unmount types from banner to parent module

Signed-off-by: pgayvallet <[email protected]>

* migrate openModal / modalService

Signed-off-by: pgayvallet <[email protected]>

fix I18nProvider import path

Signed-off-by: pgayvallet <[email protected]>

* updates core doc

Signed-off-by: pgayvallet <[email protected]>

update doc bis

Signed-off-by: pgayvallet <[email protected]>

* migrate openFlyout / flyout service

Signed-off-by: pgayvallet <[email protected]>

* remove CoreStart export from kibana-react

Signed-off-by: pgayvallet <[email protected]>

* adapt some calls to new signature

Signed-off-by: pgayvallet <[email protected]>

* adapt new calls

Signed-off-by: pgayvallet <[email protected]>

* adapt js call

Signed-off-by: pgayvallet <[email protected]>

* add flex layout on mountWrapper component to avoid losing scroll on overlays

Signed-off-by: pgayvallet <[email protected]>

* create proper flyout/modal services

* update generated doc

* update snapshot on data/query_bar

* use ReactNode instead of ReactElement

* rename mountForComponent to reactMount

* change reactMount usages to toMountPoint

* remove duplicate MountPoint type in overlays

* remove duplicate mount utilities from overlays

* allow to specify custom class name to MountWrapper

* Allow to specialize MountPoint on HTMLElement subtypes

* updates generated doc

* undeprecates openFlyout/openModal & remove direct subservice access from overlayService

* adapt toast api to get i18n context from service

* use MountPoint instead of inline definition
  • Loading branch information
pgayvallet authored Nov 19, 2019
1 parent 600862e commit 01bbbf4
Show file tree
Hide file tree
Showing 63 changed files with 1,027 additions and 671 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,6 @@ export interface ChromeNavControl

| Property | Type | Description |
| --- | --- | --- |
| [mount](./kibana-plugin-public.chromenavcontrol.mount.md) | <code>MountPoint</code> | |
| [order](./kibana-plugin-public.chromenavcontrol.order.md) | <code>number</code> | |

## Methods

| Method | Description |
| --- | --- |
| [mount(targetDomElement)](./kibana-plugin-public.chromenavcontrol.mount.md) | |

Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,10 @@

[Home](./index.md) &gt; [kibana-plugin-public](./kibana-plugin-public.md) &gt; [ChromeNavControl](./kibana-plugin-public.chromenavcontrol.md) &gt; [mount](./kibana-plugin-public.chromenavcontrol.mount.md)

## ChromeNavControl.mount() method
## ChromeNavControl.mount property

<b>Signature:</b>

```typescript
mount(targetDomElement: HTMLElement): () => void;
mount: MountPoint;
```

## Parameters

| Parameter | Type | Description |
| --- | --- | --- |
| targetDomElement | <code>HTMLElement</code> | |

<b>Returns:</b>

`() => void`

Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@ A function that should mount DOM content inside the provided container element a
<b>Signature:</b>

```typescript
export declare type MountPoint = (element: HTMLElement) => UnmountCallback;
export declare type MountPoint<T extends HTMLElement = HTMLElement> = (element: T) => UnmountCallback;
```
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,6 @@ export interface OverlayStart
| Property | Type | Description |
| --- | --- | --- |
| [banners](./kibana-plugin-public.overlaystart.banners.md) | <code>OverlayBannersStart</code> | [OverlayBannersStart](./kibana-plugin-public.overlaybannersstart.md) |
| [openFlyout](./kibana-plugin-public.overlaystart.openflyout.md) | <code>(flyoutChildren: React.ReactNode, flyoutProps?: {</code><br/><code> closeButtonAriaLabel?: string;</code><br/><code> 'data-test-subj'?: string;</code><br/><code> }) =&gt; OverlayRef</code> | |
| [openModal](./kibana-plugin-public.overlaystart.openmodal.md) | <code>(modalChildren: React.ReactNode, modalProps?: {</code><br/><code> className?: string;</code><br/><code> closeButtonAriaLabel?: string;</code><br/><code> 'data-test-subj'?: string;</code><br/><code> }) =&gt; OverlayRef</code> | |
| [openFlyout](./kibana-plugin-public.overlaystart.openflyout.md) | <code>OverlayFlyoutStart['open']</code> | |
| [openModal](./kibana-plugin-public.overlaystart.openmodal.md) | <code>OverlayModalStart['open']</code> | |

Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,9 @@

## OverlayStart.openFlyout property


<b>Signature:</b>

```typescript
openFlyout: (flyoutChildren: React.ReactNode, flyoutProps?: {
closeButtonAriaLabel?: string;
'data-test-subj'?: string;
}) => OverlayRef;
openFlyout: OverlayFlyoutStart['open'];
```
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,9 @@

## OverlayStart.openModal property


<b>Signature:</b>

```typescript
openModal: (modalChildren: React.ReactNode, modalProps?: {
className?: string;
closeButtonAriaLabel?: string;
'data-test-subj'?: string;
}) => OverlayRef;
openModal: OverlayModalStart['open'];
```
3 changes: 2 additions & 1 deletion src/core/public/chrome/nav_controls/nav_controls_service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,12 @@
import { sortBy } from 'lodash';
import { BehaviorSubject, ReplaySubject, Observable } from 'rxjs';
import { map, takeUntil } from 'rxjs/operators';
import { MountPoint } from '../../types';

/** @public */
export interface ChromeNavControl {
order?: number;
mount(targetDomElement: HTMLElement): () => void;
mount: MountPoint;
}

/**
Expand Down
3 changes: 2 additions & 1 deletion src/core/public/chrome/ui/header/header_extension.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,10 @@
*/

import React from 'react';
import { MountPoint } from '../../../types';

interface Props {
extension?: (el: HTMLDivElement) => () => void;
extension?: MountPoint<HTMLDivElement>;
}

export class HeaderExtension extends React.Component<Props> {
Expand Down
4 changes: 2 additions & 2 deletions src/core/public/legacy/legacy_service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@

import angular from 'angular';
import { InternalCoreSetup, InternalCoreStart } from '../core_system';
import { LegacyCoreSetup, LegacyCoreStart } from '../';
import { LegacyCoreSetup, LegacyCoreStart, MountPoint } from '../';

/** @internal */
export interface LegacyPlatformParams {
Expand All @@ -40,7 +40,7 @@ interface StartDeps {
}

interface BootstrapModule {
bootstrap: (targetDomElement: HTMLElement) => void;
bootstrap: MountPoint;
}

/**
Expand Down
1 change: 1 addition & 0 deletions src/core/public/notifications/toasts/error_toast.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ function render(props: ErrorToastProps = {}) {
error={props.error || new Error('error message')}
title={props.title || 'An error occured'}
toastMessage={props.toastMessage || 'This is the toast message'}
i18nContext={() => ({ children }) => <React.Fragment>{children}</React.Fragment>}
/>
);
}
Expand Down
71 changes: 47 additions & 24 deletions src/core/public/notifications/toasts/error_toast.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
*/

import React from 'react';
import ReactDOM from 'react-dom';

import {
EuiButton,
Expand All @@ -32,12 +33,14 @@ import { EuiSpacer } from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n/react';

import { OverlayStart } from '../../overlays';
import { I18nStart } from '../../i18n';

interface ErrorToastProps {
title: string;
error: Error;
toastMessage: string;
openModal: OverlayStart['openModal'];
i18nContext: () => I18nStart['Context'];
}

/**
Expand All @@ -50,41 +53,56 @@ function showErrorDialog({
title,
error,
openModal,
}: Pick<ErrorToastProps, 'error' | 'title' | 'openModal'>) {
i18nContext,
}: Pick<ErrorToastProps, 'error' | 'title' | 'openModal' | 'i18nContext'>) {
const I18nContext = i18nContext();
const modal = openModal(
<React.Fragment>
<EuiModalHeader>
<EuiModalHeaderTitle>{title}</EuiModalHeaderTitle>
</EuiModalHeader>
<EuiModalBody>
<EuiCallOut size="s" color="danger" iconType="alert" title={error.message} />
{error.stack && (
<React.Fragment>
<EuiSpacer size="s" />
<EuiCodeBlock isCopyable={true} paddingSize="s">
{error.stack}
</EuiCodeBlock>
</React.Fragment>
)}
</EuiModalBody>
<EuiModalFooter>
<EuiButton onClick={() => modal.close()} fill>
<FormattedMessage id="core.notifications.errorToast.closeModal" defaultMessage="Close" />
</EuiButton>
</EuiModalFooter>
</React.Fragment>
mount(
<React.Fragment>
<I18nContext>
<EuiModalHeader>
<EuiModalHeaderTitle>{title}</EuiModalHeaderTitle>
</EuiModalHeader>
<EuiModalBody>
<EuiCallOut size="s" color="danger" iconType="alert" title={error.message} />
{error.stack && (
<React.Fragment>
<EuiSpacer size="s" />
<EuiCodeBlock isCopyable={true} paddingSize="s">
{error.stack}
</EuiCodeBlock>
</React.Fragment>
)}
</EuiModalBody>
<EuiModalFooter>
<EuiButton onClick={() => modal.close()} fill>
<FormattedMessage
id="core.notifications.errorToast.closeModal"
defaultMessage="Close"
/>
</EuiButton>
</EuiModalFooter>
</I18nContext>
</React.Fragment>
)
);
}

export function ErrorToast({ title, error, toastMessage, openModal }: ErrorToastProps) {
export function ErrorToast({
title,
error,
toastMessage,
openModal,
i18nContext,
}: ErrorToastProps) {
return (
<React.Fragment>
<p data-test-subj="errorToastMessage">{toastMessage}</p>
<div className="eui-textRight">
<EuiButton
size="s"
color="danger"
onClick={() => showErrorDialog({ title, error, openModal })}
onClick={() => showErrorDialog({ title, error, openModal, i18nContext })}
>
<FormattedMessage
id="core.toasts.errorToast.seeFullError"
Expand All @@ -95,3 +113,8 @@ export function ErrorToast({ title, error, toastMessage, openModal }: ErrorToast
</React.Fragment>
);
}

const mount = (component: React.ReactElement) => (container: HTMLElement) => {
ReactDOM.render(component, container);
return () => ReactDOM.unmountComponentAtNode(container);
};
7 changes: 6 additions & 1 deletion src/core/public/notifications/toasts/toasts_api.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,13 @@ function uiSettingsMock() {
function toastDeps() {
return {
uiSettings: uiSettingsMock(),
i18n: i18nServiceMock.createStartContract(),
};
}

function startDeps() {
return { overlays: {} as any, i18n: i18nServiceMock.createStartContract() };
}

describe('#get$()', () => {
it('returns observable that emits NEW toast list when something added or removed', () => {
const toasts = new ToastsApi(toastDeps());
Expand Down Expand Up @@ -188,13 +191,15 @@ describe('#addDanger()', () => {
describe('#addError', () => {
it('adds an error toast', async () => {
const toasts = new ToastsApi(toastDeps());
toasts.start(startDeps());
const toast = toasts.addError(new Error('unexpected error'), { title: 'Something went wrong' });
expect(toast).toHaveProperty('color', 'danger');
expect(toast).toHaveProperty('title', 'Something went wrong');
});

it('returns the created toast', async () => {
const toasts = new ToastsApi(toastDeps());
toasts.start(startDeps());
const toast = toasts.addError(new Error('unexpected error'), { title: 'Something went wrong' });
const currentToasts = await getCurrentToasts(toasts);
expect(currentToasts[0]).toBe(toast);
Expand Down
6 changes: 5 additions & 1 deletion src/core/public/notifications/toasts/toasts_api.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import { MountPoint } from '../../types';
import { mountReactNode } from '../../utils';
import { UiSettingsClientContract } from '../../ui_settings';
import { OverlayStart } from '../../overlays';
import { I18nStart } from '../../i18n';

/**
* Allowed fields for {@link ToastInput}.
Expand Down Expand Up @@ -96,14 +97,16 @@ export class ToastsApi implements IToasts {
private uiSettings: UiSettingsClientContract;

private overlays?: OverlayStart;
private i18n?: I18nStart;

constructor(deps: { uiSettings: UiSettingsClientContract }) {
this.uiSettings = deps.uiSettings;
}

/** @internal */
public registerOverlays(overlays: OverlayStart) {
public start({ overlays, i18n }: { overlays: OverlayStart; i18n: I18nStart }) {
this.overlays = overlays;
this.i18n = i18n;
}

/** Observable of the toast messages to show to the user. */
Expand Down Expand Up @@ -206,6 +209,7 @@ export class ToastsApi implements IToasts {
error={error}
title={options.title}
toastMessage={message}
i18nContext={() => this.i18n!.Context}
/>
),
});
Expand Down
2 changes: 1 addition & 1 deletion src/core/public/notifications/toasts/toasts_service.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ export class ToastsService {
}

public start({ i18n, overlays, targetDomElement }: StartDeps) {
this.api!.registerOverlays(overlays);
this.api!.start({ overlays, i18n });
this.targetDomElement = targetDomElement;

render(
Expand Down
70 changes: 0 additions & 70 deletions src/core/public/overlays/__snapshots__/flyout.test.tsx.snap

This file was deleted.

Loading

0 comments on commit 01bbbf4

Please sign in to comment.