mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -04:00
Remove react references from core Notifications
apis (#49573)
* add reactMount util to kibana_react (kibana-react) properly export reactMount * add MountPoint types and utility * adapt toast API to no longer accept react elements (toast API) properly export new Toast type * adapt calls by using reactMount createNotifications: do not wrap if text * update generated doc * add custom snapshot serializer for reactMount * fix unit tests fix xpack unit tests * adapt non-ts calls * do not add __reactMount__ property in production * remove string check on createNotifications * fix typo and small fix using obj spread * improve react mount snapshot serializer * simplify convertToEui * rename reactMount to toMountPoint * adapt newly added calls * move mount types to proper file * use new Mount types for OverlayBanner apis * fixing typo * adapt new calls * use destructured imports
This commit is contained in:
parent
cd67addf15
commit
e04adbe34b
65 changed files with 597 additions and 339 deletions
|
@ -109,17 +109,18 @@ The plugin integrates with the core system via lifecycle events: `setup`<!-- -->
|
|||
| [HttpStart](./kibana-plugin-public.httpstart.md) | See [HttpServiceBase](./kibana-plugin-public.httpservicebase.md) |
|
||||
| [IContextProvider](./kibana-plugin-public.icontextprovider.md) | A function that returns a context value for a specific key of given context type. |
|
||||
| [IToasts](./kibana-plugin-public.itoasts.md) | Methods for adding and removing global toast messages. See [ToastsApi](./kibana-plugin-public.toastsapi.md)<!-- -->. |
|
||||
| [OverlayBannerMount](./kibana-plugin-public.overlaybannermount.md) | A function that will mount the banner inside the provided element. |
|
||||
| [OverlayBannerUnmount](./kibana-plugin-public.overlaybannerunmount.md) | A function that will unmount the banner from the element. |
|
||||
| [MountPoint](./kibana-plugin-public.mountpoint.md) | A function that should mount DOM content inside the provided container element and return a handler to unmount it. |
|
||||
| [PluginInitializer](./kibana-plugin-public.plugininitializer.md) | The <code>plugin</code> export at the root of a plugin's <code>public</code> directory should conform to this interface. |
|
||||
| [PluginOpaqueId](./kibana-plugin-public.pluginopaqueid.md) | |
|
||||
| [RecursiveReadonly](./kibana-plugin-public.recursivereadonly.md) | |
|
||||
| [SavedObjectAttribute](./kibana-plugin-public.savedobjectattribute.md) | Type definition for a Saved Object attribute value |
|
||||
| [SavedObjectAttributeSingle](./kibana-plugin-public.savedobjectattributesingle.md) | Don't use this type, it's simply a helper type for [SavedObjectAttribute](./kibana-plugin-public.savedobjectattribute.md) |
|
||||
| [SavedObjectsClientContract](./kibana-plugin-public.savedobjectsclientcontract.md) | SavedObjectsClientContract as implemented by the [SavedObjectsClient](./kibana-plugin-public.savedobjectsclient.md) |
|
||||
| [Toast](./kibana-plugin-public.toast.md) | |
|
||||
| [ToastInput](./kibana-plugin-public.toastinput.md) | Inputs for [IToasts](./kibana-plugin-public.itoasts.md) APIs. |
|
||||
| [ToastInputFields](./kibana-plugin-public.toastinputfields.md) | Allowed fields for [ToastInput](./kibana-plugin-public.toastinput.md)<!-- -->. |
|
||||
| [ToastsSetup](./kibana-plugin-public.toastssetup.md) | [IToasts](./kibana-plugin-public.itoasts.md) |
|
||||
| [ToastsStart](./kibana-plugin-public.toastsstart.md) | [IToasts](./kibana-plugin-public.itoasts.md) |
|
||||
| [UiSettingsClientContract](./kibana-plugin-public.uisettingsclientcontract.md) | Client-side client that provides access to the advanced settings stored in elasticsearch. The settings provide control over the behavior of the Kibana application. For example, a user can specify how to display numeric or date fields. Users can adjust the settings via Management UI. [UiSettingsClient](./kibana-plugin-public.uisettingsclient.md) |
|
||||
| [UnmountCallback](./kibana-plugin-public.unmountcallback.md) | A function that will unmount the element previously mounted by the associated [MountPoint](./kibana-plugin-public.mountpoint.md) |
|
||||
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [MountPoint](./kibana-plugin-public.mountpoint.md)
|
||||
|
||||
## MountPoint type
|
||||
|
||||
A function that should mount DOM content inside the provided container element and return a handler to unmount it.
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
export declare type MountPoint = (element: HTMLElement) => UnmountCallback;
|
||||
```
|
|
@ -1,13 +0,0 @@
|
|||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [OverlayBannerMount](./kibana-plugin-public.overlaybannermount.md)
|
||||
|
||||
## OverlayBannerMount type
|
||||
|
||||
A function that will mount the banner inside the provided element.
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
export declare type OverlayBannerMount = (element: HTMLElement) => OverlayBannerUnmount;
|
||||
```
|
|
@ -9,14 +9,14 @@ Add a new banner
|
|||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
add(mount: OverlayBannerMount, priority?: number): string;
|
||||
add(mount: MountPoint, priority?: number): string;
|
||||
```
|
||||
|
||||
## Parameters
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| mount | <code>OverlayBannerMount</code> | |
|
||||
| mount | <code>MountPoint</code> | |
|
||||
| priority | <code>number</code> | |
|
||||
|
||||
<b>Returns:</b>
|
||||
|
|
|
@ -9,7 +9,7 @@ Replace a banner in place
|
|||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
replace(id: string | undefined, mount: OverlayBannerMount, priority?: number): string;
|
||||
replace(id: string | undefined, mount: MountPoint, priority?: number): string;
|
||||
```
|
||||
|
||||
## Parameters
|
||||
|
@ -17,7 +17,7 @@ replace(id: string | undefined, mount: OverlayBannerMount, priority?: number): s
|
|||
| Parameter | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| id | <code>string | undefined</code> | |
|
||||
| mount | <code>OverlayBannerMount</code> | |
|
||||
| mount | <code>MountPoint</code> | |
|
||||
| priority | <code>number</code> | |
|
||||
|
||||
<b>Returns:</b>
|
||||
|
|
|
@ -1,13 +0,0 @@
|
|||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [OverlayBannerUnmount](./kibana-plugin-public.overlaybannerunmount.md)
|
||||
|
||||
## OverlayBannerUnmount type
|
||||
|
||||
A function that will unmount the banner from the element.
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
export declare type OverlayBannerUnmount = () => void;
|
||||
```
|
13
docs/development/core/public/kibana-plugin-public.toast.md
Normal file
13
docs/development/core/public/kibana-plugin-public.toast.md
Normal file
|
@ -0,0 +1,13 @@
|
|||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [Toast](./kibana-plugin-public.toast.md)
|
||||
|
||||
## Toast type
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
export declare type Toast = ToastInputFields & {
|
||||
id: string;
|
||||
};
|
||||
```
|
|
@ -9,5 +9,5 @@ Inputs for [IToasts](./kibana-plugin-public.itoasts.md) APIs.
|
|||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
export declare type ToastInput = string | ToastInputFields | Promise<ToastInputFields>;
|
||||
export declare type ToastInput = string | ToastInputFields;
|
||||
```
|
||||
|
|
|
@ -9,7 +9,10 @@ Allowed fields for [ToastInput](./kibana-plugin-public.toastinput.md)<!-- -->.
|
|||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
export declare type ToastInputFields = Pick<Toast, Exclude<keyof Toast, 'id'>>;
|
||||
export declare type ToastInputFields = Pick<EuiToast, Exclude<keyof EuiToast, 'id' | 'text' | 'title'>> & {
|
||||
title?: string | MountPoint;
|
||||
text?: string | MountPoint;
|
||||
};
|
||||
```
|
||||
|
||||
## Remarks
|
||||
|
|
|
@ -22,5 +22,5 @@ add(toastOrTitle: ToastInput): Toast;
|
|||
|
||||
`Toast`
|
||||
|
||||
a
|
||||
a [Toast](./kibana-plugin-public.toast.md)
|
||||
|
||||
|
|
|
@ -22,5 +22,5 @@ addDanger(toastOrTitle: ToastInput): Toast;
|
|||
|
||||
`Toast`
|
||||
|
||||
a
|
||||
a [Toast](./kibana-plugin-public.toast.md)
|
||||
|
||||
|
|
|
@ -23,5 +23,5 @@ addError(error: Error, options: ErrorToastOptions): Toast;
|
|||
|
||||
`Toast`
|
||||
|
||||
a
|
||||
a [Toast](./kibana-plugin-public.toast.md)
|
||||
|
||||
|
|
|
@ -22,5 +22,5 @@ addSuccess(toastOrTitle: ToastInput): Toast;
|
|||
|
||||
`Toast`
|
||||
|
||||
a
|
||||
a [Toast](./kibana-plugin-public.toast.md)
|
||||
|
||||
|
|
|
@ -22,5 +22,5 @@ addWarning(toastOrTitle: ToastInput): Toast;
|
|||
|
||||
`Toast`
|
||||
|
||||
a
|
||||
a [Toast](./kibana-plugin-public.toast.md)
|
||||
|
||||
|
|
|
@ -28,5 +28,5 @@ export declare class ToastsApi implements IToasts
|
|||
| [addSuccess(toastOrTitle)](./kibana-plugin-public.toastsapi.addsuccess.md) | | Adds a new toast pre-configured with the success color and check icon. |
|
||||
| [addWarning(toastOrTitle)](./kibana-plugin-public.toastsapi.addwarning.md) | | Adds a new toast pre-configured with the warning color and help icon. |
|
||||
| [get$()](./kibana-plugin-public.toastsapi.get_.md) | | Observable of the toast messages to show to the user. |
|
||||
| [remove(toast)](./kibana-plugin-public.toastsapi.remove.md) | | Removes a toast from the current array of toasts if present. |
|
||||
| [remove(toastOrId)](./kibana-plugin-public.toastsapi.remove.md) | | Removes a toast from the current array of toasts if present. |
|
||||
|
||||
|
|
|
@ -9,14 +9,14 @@ Removes a toast from the current array of toasts if present.
|
|||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
remove(toast: Toast): void;
|
||||
remove(toastOrId: Toast | string): void;
|
||||
```
|
||||
|
||||
## Parameters
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| toast | <code>Toast</code> | a returned by |
|
||||
| toastOrId | <code>Toast | string</code> | a [Toast](./kibana-plugin-public.toast.md) returned by [ToastsApi.add()](./kibana-plugin-public.toastsapi.add.md) or its id |
|
||||
|
||||
<b>Returns:</b>
|
||||
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [UnmountCallback](./kibana-plugin-public.unmountcallback.md)
|
||||
|
||||
## UnmountCallback type
|
||||
|
||||
A function that will unmount the element previously mounted by the associated [MountPoint](./kibana-plugin-public.mountpoint.md)
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
export declare type UnmountCallback = () => void;
|
||||
```
|
|
@ -117,13 +117,7 @@ export {
|
|||
InterceptedHttpResponse,
|
||||
} from './http';
|
||||
|
||||
export {
|
||||
OverlayStart,
|
||||
OverlayBannerMount,
|
||||
OverlayBannerUnmount,
|
||||
OverlayBannersStart,
|
||||
OverlayRef,
|
||||
} from './overlays';
|
||||
export { OverlayStart, OverlayBannersStart, OverlayRef } from './overlays';
|
||||
|
||||
export {
|
||||
Toast,
|
||||
|
@ -136,6 +130,8 @@ export {
|
|||
ErrorToastOptions,
|
||||
} from './notifications';
|
||||
|
||||
export { MountPoint, UnmountCallback } from './types';
|
||||
|
||||
/**
|
||||
* Core services exposed to the `Plugin` setup lifecycle
|
||||
*
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
exports[`renders matching snapshot 1`] = `
|
||||
<EuiGlobalToastList
|
||||
data-test-subj="globalToastList"
|
||||
dismissToast={[MockFunction]}
|
||||
dismissToast={[Function]}
|
||||
toastLifeTimeMs={Infinity}
|
||||
toasts={Array []}
|
||||
/>
|
||||
|
|
|
@ -57,9 +57,9 @@ it('subscribes to toasts$ on mount and unsubscribes on unmount', () => {
|
|||
it('passes latest value from toasts$ to <EuiGlobalToastList />', () => {
|
||||
const el = shallow(
|
||||
render({
|
||||
toasts$: Rx.from([[], [1], [1, 2]]) as any,
|
||||
toasts$: Rx.from([[], [{ id: 1 }], [{ id: 1 }, { id: 2 }]]) as any,
|
||||
})
|
||||
);
|
||||
|
||||
expect(el.find(EuiGlobalToastList).prop('toasts')).toEqual([1, 2]);
|
||||
expect(el.find(EuiGlobalToastList).prop('toasts')).toEqual([{ id: 1 }, { id: 2 }]);
|
||||
});
|
||||
|
|
|
@ -17,20 +17,28 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
import { EuiGlobalToastList, EuiGlobalToastListToast as Toast } from '@elastic/eui';
|
||||
|
||||
import { EuiGlobalToastList, EuiGlobalToastListToast as EuiToast } from '@elastic/eui';
|
||||
import React from 'react';
|
||||
import * as Rx from 'rxjs';
|
||||
|
||||
import { MountWrapper } from '../../utils';
|
||||
import { Toast } from './toasts_api';
|
||||
|
||||
interface Props {
|
||||
toasts$: Rx.Observable<Toast[]>;
|
||||
dismissToast: (t: Toast) => void;
|
||||
dismissToast: (toastId: string) => void;
|
||||
}
|
||||
|
||||
interface State {
|
||||
toasts: Toast[];
|
||||
}
|
||||
|
||||
const convertToEui = (toast: Toast): EuiToast => ({
|
||||
...toast,
|
||||
title: typeof toast.title === 'function' ? <MountWrapper mount={toast.title} /> : toast.title,
|
||||
text: typeof toast.text === 'function' ? <MountWrapper mount={toast.text} /> : toast.text,
|
||||
});
|
||||
|
||||
export class GlobalToastList extends React.Component<Props, State> {
|
||||
public state: State = {
|
||||
toasts: [],
|
||||
|
@ -54,8 +62,8 @@ export class GlobalToastList extends React.Component<Props, State> {
|
|||
return (
|
||||
<EuiGlobalToastList
|
||||
data-test-subj="globalToastList"
|
||||
toasts={this.state.toasts}
|
||||
dismissToast={this.props.dismissToast}
|
||||
toasts={this.state.toasts.map(convertToEui)}
|
||||
dismissToast={({ id }) => this.props.dismissToast(id)}
|
||||
/**
|
||||
* This prop is overriden by the individual toasts that are added.
|
||||
* Use `Infinity` here so that it's obvious a timeout hasn't been
|
||||
|
|
|
@ -18,5 +18,11 @@
|
|||
*/
|
||||
|
||||
export { ToastsService, ToastsSetup, ToastsStart } from './toasts_service';
|
||||
export { ErrorToastOptions, ToastsApi, ToastInput, IToasts, ToastInputFields } from './toasts_api';
|
||||
export { EuiGlobalToastListToast as Toast } from '@elastic/eui';
|
||||
export {
|
||||
ErrorToastOptions,
|
||||
ToastsApi,
|
||||
ToastInput,
|
||||
IToasts,
|
||||
ToastInputFields,
|
||||
Toast,
|
||||
} from './toasts_api';
|
||||
|
|
|
@ -91,7 +91,7 @@ describe('#get$()', () => {
|
|||
toasts.add('foo');
|
||||
onToasts.mockClear();
|
||||
|
||||
toasts.remove({ id: 'bar' });
|
||||
toasts.remove('bar');
|
||||
expect(onToasts).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
@ -136,7 +136,7 @@ describe('#remove()', () => {
|
|||
it('ignores unknown toast', async () => {
|
||||
const toasts = new ToastsApi(toastDeps());
|
||||
toasts.add('Test');
|
||||
toasts.remove({ id: 'foo' });
|
||||
toasts.remove('foo');
|
||||
|
||||
const currentToasts = await getCurrentToasts(toasts);
|
||||
expect(currentToasts).toHaveLength(1);
|
||||
|
|
|
@ -17,11 +17,13 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
import { EuiGlobalToastListToast as Toast } from '@elastic/eui';
|
||||
import { EuiGlobalToastListToast as EuiToast } from '@elastic/eui';
|
||||
import React from 'react';
|
||||
import * as Rx from 'rxjs';
|
||||
|
||||
import { ErrorToast } from './error_toast';
|
||||
import { MountPoint } from '../../types';
|
||||
import { mountReactNode } from '../../utils';
|
||||
import { UiSettingsClientContract } from '../../ui_settings';
|
||||
import { OverlayStart } from '../../overlays';
|
||||
|
||||
|
@ -33,13 +35,20 @@ import { OverlayStart } from '../../overlays';
|
|||
*
|
||||
* @public
|
||||
*/
|
||||
export type ToastInputFields = Pick<Toast, Exclude<keyof Toast, 'id'>>;
|
||||
export type ToastInputFields = Pick<EuiToast, Exclude<keyof EuiToast, 'id' | 'text' | 'title'>> & {
|
||||
title?: string | MountPoint;
|
||||
text?: string | MountPoint;
|
||||
};
|
||||
|
||||
export type Toast = ToastInputFields & {
|
||||
id: string;
|
||||
};
|
||||
|
||||
/**
|
||||
* Inputs for {@link IToasts} APIs.
|
||||
* @public
|
||||
*/
|
||||
export type ToastInput = string | ToastInputFields | Promise<ToastInputFields>;
|
||||
export type ToastInput = string | ToastInputFields;
|
||||
|
||||
/**
|
||||
* Options available for {@link IToasts} APIs.
|
||||
|
@ -59,13 +68,12 @@ export interface ErrorToastOptions {
|
|||
toastMessage?: string;
|
||||
}
|
||||
|
||||
const normalizeToast = (toastOrTitle: ToastInput) => {
|
||||
const normalizeToast = (toastOrTitle: ToastInput): ToastInputFields => {
|
||||
if (typeof toastOrTitle === 'string') {
|
||||
return {
|
||||
title: toastOrTitle,
|
||||
};
|
||||
}
|
||||
|
||||
return toastOrTitle;
|
||||
};
|
||||
|
||||
|
@ -123,11 +131,12 @@ export class ToastsApi implements IToasts {
|
|||
|
||||
/**
|
||||
* Removes a toast from the current array of toasts if present.
|
||||
* @param toast - a {@link Toast} returned by {@link ToastApi.add}
|
||||
* @param toastOrId - a {@link Toast} returned by {@link ToastsApi.add} or its id
|
||||
*/
|
||||
public remove(toast: Toast) {
|
||||
public remove(toastOrId: Toast | string) {
|
||||
const toRemove = typeof toastOrId === 'string' ? toastOrId : toastOrId.id;
|
||||
const list = this.toasts$.getValue();
|
||||
const listWithoutToast = list.filter(t => t !== toast);
|
||||
const listWithoutToast = list.filter(t => t.id !== toRemove);
|
||||
if (listWithoutToast.length !== list.length) {
|
||||
this.toasts$.next(listWithoutToast);
|
||||
}
|
||||
|
@ -191,7 +200,7 @@ export class ToastsApi implements IToasts {
|
|||
iconType: 'alert',
|
||||
title: options.title,
|
||||
toastLifeTimeMs: this.uiSettings.get('notifications:lifetime:error'),
|
||||
text: (
|
||||
text: mountReactNode(
|
||||
<ErrorToast
|
||||
openModal={this.openModal.bind(this)}
|
||||
error={error}
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
import React from 'react';
|
||||
import { render, unmountComponentAtNode } from 'react-dom';
|
||||
|
||||
import { EuiGlobalToastListToast as Toast } from '@elastic/eui';
|
||||
import { I18nStart } from '../../i18n';
|
||||
import { UiSettingsClientContract } from '../../ui_settings';
|
||||
import { GlobalToastList } from './global_toast_list';
|
||||
|
@ -65,7 +64,7 @@ export class ToastsService {
|
|||
render(
|
||||
<i18n.Context>
|
||||
<GlobalToastList
|
||||
dismissToast={(toast: Toast) => this.api!.remove(toast)}
|
||||
dismissToast={(toastId: string) => this.api!.remove(toastId)}
|
||||
toasts$={this.api!.get$()}
|
||||
/>
|
||||
</i18n.Context>,
|
||||
|
|
|
@ -25,33 +25,20 @@ import { PriorityMap } from './priority_map';
|
|||
import { BannersList } from './banners_list';
|
||||
import { UiSettingsClientContract } from '../../ui_settings';
|
||||
import { I18nStart } from '../../i18n';
|
||||
import { MountPoint } from '../../types';
|
||||
import { UserBannerService } from './user_banner_service';
|
||||
|
||||
/**
|
||||
* A function that will unmount the banner from the element.
|
||||
* @public
|
||||
*/
|
||||
export type OverlayBannerUnmount = () => void;
|
||||
|
||||
/**
|
||||
* A function that will mount the banner inside the provided element.
|
||||
* @param element an element to render into
|
||||
* @returns a {@link OverlayBannerUnmount}
|
||||
* @public
|
||||
*/
|
||||
export type OverlayBannerMount = (element: HTMLElement) => OverlayBannerUnmount;
|
||||
|
||||
/** @public */
|
||||
export interface OverlayBannersStart {
|
||||
/**
|
||||
* Add a new banner
|
||||
*
|
||||
* @param mount {@link OverlayBannerMount}
|
||||
* @param mount {@link MountPoint}
|
||||
* @param priority optional priority order to display this banner. Higher priority values are shown first.
|
||||
* @returns a unique identifier for the given banner to be used with {@link OverlayBannersStart.remove} and
|
||||
* {@link OverlayBannersStart.replace}
|
||||
*/
|
||||
add(mount: OverlayBannerMount, priority?: number): string;
|
||||
add(mount: MountPoint, priority?: number): string;
|
||||
|
||||
/**
|
||||
* Remove a banner
|
||||
|
@ -65,12 +52,12 @@ export interface OverlayBannersStart {
|
|||
* Replace a banner in place
|
||||
*
|
||||
* @param id the unique identifier for the banner returned by {@link OverlayBannersStart.add}
|
||||
* @param mount {@link OverlayBannerMount}
|
||||
* @param mount {@link MountPoint}
|
||||
* @param priority optional priority order to display this banner. Higher priority values are shown first.
|
||||
* @returns a new identifier for the given banner to be used with {@link OverlayBannersStart.remove} and
|
||||
* {@link OverlayBannersStart.replace}
|
||||
*/
|
||||
replace(id: string | undefined, mount: OverlayBannerMount, priority?: number): string;
|
||||
replace(id: string | undefined, mount: MountPoint, priority?: number): string;
|
||||
|
||||
/** @internal */
|
||||
get$(): Observable<OverlayBanner[]>;
|
||||
|
@ -80,7 +67,7 @@ export interface OverlayBannersStart {
|
|||
/** @internal */
|
||||
export interface OverlayBanner {
|
||||
readonly id: string;
|
||||
readonly mount: OverlayBannerMount;
|
||||
readonly mount: MountPoint;
|
||||
readonly priority: number;
|
||||
}
|
||||
|
||||
|
@ -116,7 +103,7 @@ export class OverlayBannersService {
|
|||
return true;
|
||||
},
|
||||
|
||||
replace(id: string | undefined, mount: OverlayBannerMount, priority = 0) {
|
||||
replace(id: string | undefined, mount: MountPoint, priority = 0) {
|
||||
if (!id || !banners$.value.has(id)) {
|
||||
return this.add(mount, priority);
|
||||
}
|
||||
|
|
|
@ -17,9 +17,4 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
export {
|
||||
OverlayBannerMount,
|
||||
OverlayBannerUnmount,
|
||||
OverlayBannersStart,
|
||||
OverlayBannersService,
|
||||
} from './banners_service';
|
||||
export { OverlayBannersStart, OverlayBannersService } from './banners_service';
|
||||
|
|
|
@ -17,5 +17,5 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
export { OverlayBannerMount, OverlayBannerUnmount, OverlayBannersStart } from './banners';
|
||||
export { OverlayBannersStart } from './banners';
|
||||
export { OverlayService, OverlayStart, OverlayRef } from './overlay_service';
|
||||
|
|
|
@ -5,12 +5,12 @@
|
|||
```ts
|
||||
|
||||
import { Breadcrumb } from '@elastic/eui';
|
||||
import { EuiGlobalToastListToast } from '@elastic/eui';
|
||||
import { IconType } from '@elastic/eui';
|
||||
import { Observable } from 'rxjs';
|
||||
import React from 'react';
|
||||
import * as Rx from 'rxjs';
|
||||
import { ShallowPromise } from '@kbn/utility-types';
|
||||
import { EuiGlobalToastListToast as Toast } from '@elastic/eui';
|
||||
import { UiSettingsParams as UiSettingsParams_2 } from 'src/core/server/types';
|
||||
import { UserProvidedValues as UserProvidedValues_2 } from 'src/core/server/types';
|
||||
|
||||
|
@ -619,6 +619,9 @@ export interface LegacyNavLink {
|
|||
url: string;
|
||||
}
|
||||
|
||||
// @public
|
||||
export type MountPoint = (element: HTMLElement) => UnmountCallback;
|
||||
|
||||
// @public (undocumented)
|
||||
export interface NotificationsSetup {
|
||||
// (undocumented)
|
||||
|
@ -631,12 +634,9 @@ export interface NotificationsStart {
|
|||
toasts: ToastsStart;
|
||||
}
|
||||
|
||||
// @public
|
||||
export type OverlayBannerMount = (element: HTMLElement) => OverlayBannerUnmount;
|
||||
|
||||
// @public (undocumented)
|
||||
export interface OverlayBannersStart {
|
||||
add(mount: OverlayBannerMount, priority?: number): string;
|
||||
add(mount: MountPoint, priority?: number): string;
|
||||
// Warning: (ae-forgotten-export) The symbol "OverlayBanner" needs to be exported by the entry point index.d.ts
|
||||
//
|
||||
// @internal (undocumented)
|
||||
|
@ -644,12 +644,9 @@ export interface OverlayBannersStart {
|
|||
// (undocumented)
|
||||
getComponent(): JSX.Element;
|
||||
remove(id: string): boolean;
|
||||
replace(id: string | undefined, mount: OverlayBannerMount, priority?: number): string;
|
||||
replace(id: string | undefined, mount: MountPoint, priority?: number): string;
|
||||
}
|
||||
|
||||
// @public
|
||||
export type OverlayBannerUnmount = () => void;
|
||||
|
||||
// @public
|
||||
export interface OverlayRef {
|
||||
close(): Promise<void>;
|
||||
|
@ -917,35 +914,36 @@ export class SimpleSavedObject<T extends SavedObjectAttributes> {
|
|||
_version?: SavedObject<T>['version'];
|
||||
}
|
||||
|
||||
export { Toast }
|
||||
// Warning: (ae-missing-release-tag) "Toast" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
//
|
||||
// @public (undocumented)
|
||||
export type Toast = ToastInputFields & {
|
||||
id: string;
|
||||
};
|
||||
|
||||
// @public
|
||||
export type ToastInput = string | ToastInputFields | Promise<ToastInputFields>;
|
||||
export type ToastInput = string | ToastInputFields;
|
||||
|
||||
// @public
|
||||
export type ToastInputFields = Pick<Toast, Exclude<keyof Toast, 'id'>>;
|
||||
export type ToastInputFields = Pick<EuiGlobalToastListToast, Exclude<keyof EuiGlobalToastListToast, 'id' | 'text' | 'title'>> & {
|
||||
title?: string | MountPoint;
|
||||
text?: string | MountPoint;
|
||||
};
|
||||
|
||||
// @public
|
||||
export class ToastsApi implements IToasts {
|
||||
constructor(deps: {
|
||||
uiSettings: UiSettingsClientContract;
|
||||
});
|
||||
// Warning: (ae-unresolved-link) The @link reference could not be resolved: Reexported declarations are not supported
|
||||
add(toastOrTitle: ToastInput): Toast;
|
||||
// Warning: (ae-unresolved-link) The @link reference could not be resolved: Reexported declarations are not supported
|
||||
addDanger(toastOrTitle: ToastInput): Toast;
|
||||
// Warning: (ae-unresolved-link) The @link reference could not be resolved: Reexported declarations are not supported
|
||||
addError(error: Error, options: ErrorToastOptions): Toast;
|
||||
// Warning: (ae-unresolved-link) The @link reference could not be resolved: Reexported declarations are not supported
|
||||
addSuccess(toastOrTitle: ToastInput): Toast;
|
||||
// Warning: (ae-unresolved-link) The @link reference could not be resolved: Reexported declarations are not supported
|
||||
addWarning(toastOrTitle: ToastInput): Toast;
|
||||
get$(): Rx.Observable<Toast[]>;
|
||||
// @internal (undocumented)
|
||||
registerOverlays(overlays: OverlayStart): void;
|
||||
// Warning: (ae-unresolved-link) The @link reference could not be resolved: Reexported declarations are not supported
|
||||
// Warning: (ae-unresolved-link) The @link reference could not be resolved: The package "kibana" does not have an export "ToastApi"
|
||||
remove(toast: Toast): void;
|
||||
remove(toastOrId: Toast | string): void;
|
||||
}
|
||||
|
||||
// @public (undocumented)
|
||||
|
@ -991,5 +989,8 @@ export interface UiSettingsState {
|
|||
[key: string]: UiSettingsParams_2 & UserProvidedValues_2;
|
||||
}
|
||||
|
||||
// @public
|
||||
export type UnmountCallback = () => void;
|
||||
|
||||
|
||||
```
|
||||
|
|
37
src/core/public/types.ts
Normal file
37
src/core/public/types.ts
Normal file
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* A function that should mount DOM content inside the provided container element
|
||||
* and return a handler to unmount it.
|
||||
*
|
||||
* @param element the container element to render into
|
||||
* @returns a {@link UnmountCallback} that unmount the element on call.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export type MountPoint = (element: HTMLElement) => UnmountCallback;
|
||||
|
||||
/**
|
||||
* A function that will unmount the element previously mounted by
|
||||
* the associated {@link MountPoint}
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export type UnmountCallback = () => void;
|
|
@ -19,3 +19,4 @@
|
|||
|
||||
export { shareWeakReplay } from './share_weak_replay';
|
||||
export { Sha256 } from './crypto';
|
||||
export { MountWrapper, mountReactNode } from './mount';
|
||||
|
|
44
src/core/public/utils/mount.tsx
Normal file
44
src/core/public/utils/mount.tsx
Normal file
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import React, { useEffect, useRef } from 'react';
|
||||
import { render, unmountComponentAtNode } from 'react-dom';
|
||||
import { I18nProvider } from '@kbn/i18n/react';
|
||||
import { MountPoint } from '../types';
|
||||
|
||||
/**
|
||||
* MountWrapper is a react component to mount a {@link MountPoint} inside a react tree.
|
||||
*/
|
||||
export const MountWrapper: React.FunctionComponent<{ mount: MountPoint }> = ({ mount }) => {
|
||||
const element = useRef(null);
|
||||
useEffect(() => mount(element.current!), [mount]);
|
||||
return <div className="kbnMountWrapper" ref={element} />;
|
||||
};
|
||||
|
||||
/**
|
||||
* Mount converter for react components.
|
||||
*
|
||||
* @param component to get a mount for
|
||||
*/
|
||||
export const mountReactNode = (component: React.ReactNode): MountPoint => (
|
||||
element: HTMLElement
|
||||
) => {
|
||||
render(<I18nProvider>{component}</I18nProvider>, element);
|
||||
return () => unmountComponentAtNode(element);
|
||||
};
|
|
@ -103,6 +103,7 @@ export default {
|
|||
'packages/kbn-pm/dist/index.js'
|
||||
],
|
||||
snapshotSerializers: [
|
||||
'<rootDir>/src/plugins/kibana_react/public/util/test_helpers/react_mount_serializer.ts',
|
||||
'<rootDir>/node_modules/enzyme-to-json/serializer',
|
||||
],
|
||||
reporters: [
|
||||
|
|
|
@ -42,6 +42,7 @@ import {
|
|||
import {
|
||||
withKibana,
|
||||
KibanaReactContextValue,
|
||||
toMountPoint,
|
||||
} from '../../../../../../../plugins/kibana_react/public';
|
||||
import { IndexPattern, StaticIndexPattern } from '../../../index_patterns';
|
||||
import { Query, getQueryLog } from '../index';
|
||||
|
@ -361,7 +362,7 @@ export class QueryBarInputUI extends Component<Props, State> {
|
|||
id: 'data.query.queryBar.KQLNestedQuerySyntaxInfoTitle',
|
||||
defaultMessage: 'KQL nested query syntax',
|
||||
}),
|
||||
text: (
|
||||
text: toMountPoint(
|
||||
<div>
|
||||
<p>
|
||||
<FormattedMessage
|
||||
|
|
|
@ -36,7 +36,7 @@ import { EuiSuperUpdateButton, OnRefreshProps } from '@elastic/eui';
|
|||
import { FormattedMessage, InjectedIntl, injectI18n } from '@kbn/i18n/react';
|
||||
import { Toast } from 'src/core/public';
|
||||
import { TimeRange, TimeHistoryContract } from 'src/plugins/data/public';
|
||||
import { useKibana } from '../../../../../../../plugins/kibana_react/public';
|
||||
import { useKibana, toMountPoint } from '../../../../../../../plugins/kibana_react/public';
|
||||
import { PersistedLog } from '../../../../../../../plugins/data/public';
|
||||
|
||||
import { IndexPattern } from '../../../index_patterns';
|
||||
|
@ -298,7 +298,7 @@ function QueryBarTopRowUI(props: Props) {
|
|||
id: 'data.query.queryBar.luceneSyntaxWarningTitle',
|
||||
defaultMessage: 'Lucene syntax warning',
|
||||
}),
|
||||
text: (
|
||||
text: toMountPoint(
|
||||
<div>
|
||||
<p>
|
||||
<FormattedMessage
|
||||
|
|
|
@ -40,6 +40,7 @@ import { fatalError } from 'ui/notify';
|
|||
import { capabilities } from 'ui/capabilities';
|
||||
// @ts-ignore
|
||||
import { modifyUrl } from 'ui/url';
|
||||
import { toMountPoint } from '../../../../plugins/kibana_react/public';
|
||||
// @ts-ignore
|
||||
import { UrlOverflowService } from '../error_url_overflow';
|
||||
import { npStart } from '../new_platform';
|
||||
|
@ -329,7 +330,7 @@ const $setupUrlOverflowHandling = (newPlatform: CoreStart) => (
|
|||
title: i18n.translate('common.ui.chrome.bigUrlWarningNotificationTitle', {
|
||||
defaultMessage: 'The URL is big and Kibana might stop working',
|
||||
}),
|
||||
text: (
|
||||
text: toMountPoint(
|
||||
<Fragment>
|
||||
<FormattedMessage
|
||||
id="common.ui.chrome.bigUrlWarningNotificationMessage"
|
||||
|
|
|
@ -24,6 +24,7 @@ import {
|
|||
EuiSpacer,
|
||||
EuiButtonEmpty
|
||||
} from '@elastic/eui';
|
||||
import { toMountPoint } from '../../../../../plugins/kibana_react/public';
|
||||
|
||||
export const createZoomWarningMsg = (function () {
|
||||
let disableZoomMsg = false;
|
||||
|
@ -107,7 +108,7 @@ export const createZoomWarningMsg = (function () {
|
|||
|
||||
const zoomToast = ({
|
||||
title: 'No additional zoom levels',
|
||||
text: <ZoomWarning onChange={setZoomMsg}/>,
|
||||
text: toMountPoint(<ZoomWarning onChange={setZoomMsg}/>),
|
||||
'data-test-subj': 'maxZoomWarning',
|
||||
});
|
||||
|
||||
|
|
|
@ -19,15 +19,9 @@
|
|||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import React from 'react';
|
||||
import {
|
||||
EuiFlyout,
|
||||
EuiFlyoutBody,
|
||||
EuiFlyoutHeader,
|
||||
EuiTitle,
|
||||
EuiGlobalToastListToast as Toast,
|
||||
} from '@elastic/eui';
|
||||
import { EuiFlyout, EuiFlyoutBody, EuiFlyoutHeader, EuiTitle } from '@elastic/eui';
|
||||
import { DashboardPanelState } from '../embeddable';
|
||||
import { NotificationsStart } from '../../../../core/public';
|
||||
import { NotificationsStart, Toast } from '../../../../core/public';
|
||||
import {
|
||||
IContainer,
|
||||
IEmbeddable,
|
||||
|
|
|
@ -24,3 +24,4 @@ export * from './overlays';
|
|||
export * from './ui_settings';
|
||||
export * from './field_icon';
|
||||
export * from './table_list_view';
|
||||
export { toMountPoint } from './util';
|
||||
|
|
|
@ -52,9 +52,20 @@ test('can display string element as title', () => {
|
|||
wrapper.toasts.show({ title: 'foo' });
|
||||
|
||||
expect(notifications.toasts.add).toHaveBeenCalledTimes(1);
|
||||
expect(notifications.toasts.add.mock.calls[0][0]).toMatchObject({
|
||||
title: 'foo',
|
||||
});
|
||||
expect(notifications.toasts.add.mock.calls[0][0]).toMatchInlineSnapshot(`
|
||||
Object {
|
||||
"color": undefined,
|
||||
"iconType": undefined,
|
||||
"onClose": undefined,
|
||||
"text": MountPoint {
|
||||
"reactNode": <React.Fragment />,
|
||||
},
|
||||
"title": MountPoint {
|
||||
"reactNode": "foo",
|
||||
},
|
||||
"toastLifeTimeMs": undefined,
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test('can display React element as title', () => {
|
||||
|
@ -67,10 +78,12 @@ test('can display React element as title', () => {
|
|||
|
||||
expect(notifications.toasts.add).toHaveBeenCalledTimes(1);
|
||||
expect((notifications.toasts.add.mock.calls[0][0] as any).title).toMatchInlineSnapshot(`
|
||||
<div>
|
||||
bar
|
||||
</div>
|
||||
`);
|
||||
MountPoint {
|
||||
"reactNode": <div>
|
||||
bar
|
||||
</div>,
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test('can display React element as toast body', () => {
|
||||
|
@ -81,12 +94,14 @@ test('can display React element as toast body', () => {
|
|||
|
||||
expect(notifications.toasts.add).toHaveBeenCalledTimes(1);
|
||||
expect((notifications.toasts.add.mock.calls[0][0] as any).text).toMatchInlineSnapshot(`
|
||||
<React.Fragment>
|
||||
<div>
|
||||
baz
|
||||
</div>
|
||||
</React.Fragment>
|
||||
`);
|
||||
MountPoint {
|
||||
"reactNode": <React.Fragment>
|
||||
<div>
|
||||
baz
|
||||
</div>
|
||||
</React.Fragment>,
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test('can set toast properties', () => {
|
||||
|
@ -102,17 +117,21 @@ test('can set toast properties', () => {
|
|||
});
|
||||
|
||||
expect(notifications.toasts.add.mock.calls[0][0]).toMatchInlineSnapshot(`
|
||||
Object {
|
||||
"color": "danger",
|
||||
"iconType": "foo",
|
||||
"onClose": undefined,
|
||||
"text": <React.Fragment>
|
||||
1
|
||||
</React.Fragment>,
|
||||
"title": "2",
|
||||
"toastLifeTimeMs": 3,
|
||||
}
|
||||
`);
|
||||
Object {
|
||||
"color": "danger",
|
||||
"iconType": "foo",
|
||||
"onClose": undefined,
|
||||
"text": MountPoint {
|
||||
"reactNode": <React.Fragment>
|
||||
1
|
||||
</React.Fragment>,
|
||||
},
|
||||
"title": MountPoint {
|
||||
"reactNode": "2",
|
||||
},
|
||||
"toastLifeTimeMs": 3,
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test('can display success, warning and danger toasts', () => {
|
||||
|
@ -124,21 +143,48 @@ test('can display success, warning and danger toasts', () => {
|
|||
wrapper.toasts.danger({ title: '3' });
|
||||
|
||||
expect(notifications.toasts.add).toHaveBeenCalledTimes(3);
|
||||
expect(notifications.toasts.add.mock.calls[0][0]).toMatchObject({
|
||||
title: '1',
|
||||
color: 'success',
|
||||
iconType: 'check',
|
||||
});
|
||||
expect(notifications.toasts.add.mock.calls[1][0]).toMatchObject({
|
||||
title: '2',
|
||||
color: 'warning',
|
||||
iconType: 'help',
|
||||
});
|
||||
expect(notifications.toasts.add.mock.calls[2][0]).toMatchObject({
|
||||
title: '3',
|
||||
color: 'danger',
|
||||
iconType: 'alert',
|
||||
});
|
||||
expect(notifications.toasts.add.mock.calls[0][0]).toMatchInlineSnapshot(`
|
||||
Object {
|
||||
"color": "success",
|
||||
"iconType": "check",
|
||||
"onClose": undefined,
|
||||
"text": MountPoint {
|
||||
"reactNode": <React.Fragment />,
|
||||
},
|
||||
"title": MountPoint {
|
||||
"reactNode": "1",
|
||||
},
|
||||
"toastLifeTimeMs": undefined,
|
||||
}
|
||||
`);
|
||||
expect(notifications.toasts.add.mock.calls[1][0]).toMatchInlineSnapshot(`
|
||||
Object {
|
||||
"color": "warning",
|
||||
"iconType": "help",
|
||||
"onClose": undefined,
|
||||
"text": MountPoint {
|
||||
"reactNode": <React.Fragment />,
|
||||
},
|
||||
"title": MountPoint {
|
||||
"reactNode": "2",
|
||||
},
|
||||
"toastLifeTimeMs": undefined,
|
||||
}
|
||||
`);
|
||||
expect(notifications.toasts.add.mock.calls[2][0]).toMatchInlineSnapshot(`
|
||||
Object {
|
||||
"color": "danger",
|
||||
"iconType": "alert",
|
||||
"onClose": undefined,
|
||||
"text": MountPoint {
|
||||
"reactNode": <React.Fragment />,
|
||||
},
|
||||
"title": MountPoint {
|
||||
"reactNode": "3",
|
||||
},
|
||||
"toastLifeTimeMs": undefined,
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test('if body is not set, renders it empty', () => {
|
||||
|
@ -147,7 +193,9 @@ test('if body is not set, renders it empty', () => {
|
|||
|
||||
wrapper.toasts.success({ title: '1' });
|
||||
|
||||
expect((notifications.toasts.add.mock.calls[0][0] as any).text).toMatchInlineSnapshot(
|
||||
`<React.Fragment />`
|
||||
);
|
||||
expect((notifications.toasts.add.mock.calls[0][0] as any).text).toMatchInlineSnapshot(`
|
||||
MountPoint {
|
||||
"reactNode": <React.Fragment />,
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
import * as React from 'react';
|
||||
import { KibanaServices } from '../context/types';
|
||||
import { KibanaReactNotifications } from './types';
|
||||
import { toMountPoint } from '../util';
|
||||
|
||||
export const createNotifications = (services: KibanaServices): KibanaReactNotifications => {
|
||||
const show: KibanaReactNotifications['toasts']['show'] = ({
|
||||
|
@ -34,8 +35,8 @@ export const createNotifications = (services: KibanaServices): KibanaReactNotifi
|
|||
throw new TypeError('Could not show notification as notifications service is not available.');
|
||||
}
|
||||
services.notifications!.toasts.add({
|
||||
title,
|
||||
text: <>{body || null}</>,
|
||||
title: toMountPoint(title),
|
||||
text: toMountPoint(<>{body || null}</>),
|
||||
color,
|
||||
iconType,
|
||||
toastLifeTimeMs,
|
||||
|
|
|
@ -38,6 +38,7 @@ import {
|
|||
EuiCallOut,
|
||||
} from '@elastic/eui';
|
||||
import { ToastsStart, UiSettingsClientContract } from 'kibana/public';
|
||||
import { toMountPoint } from '../util';
|
||||
|
||||
export const EMPTY_FILTER = '';
|
||||
|
||||
|
@ -166,7 +167,7 @@ class TableListView extends React.Component<TableListViewProps, TableListViewSta
|
|||
await this.props.deleteItems(this.state.selectedIds.map(id => itemsById[id]));
|
||||
} catch (error) {
|
||||
this.props.toastNotifications.addDanger({
|
||||
title: (
|
||||
title: toMountPoint(
|
||||
<FormattedMessage
|
||||
id="kibana-react.tableListView.listing.unableToDeleteDangerMessage"
|
||||
defaultMessage="Unable to delete {entityName}(s)"
|
||||
|
|
|
@ -19,3 +19,4 @@
|
|||
|
||||
export * from './use_observable';
|
||||
export * from './use_unmount';
|
||||
export * from './react_mount';
|
||||
|
|
40
src/plugins/kibana_react/public/util/react_mount.tsx
Normal file
40
src/plugins/kibana_react/public/util/react_mount.tsx
Normal file
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import { I18nProvider } from '@kbn/i18n/react';
|
||||
import { MountPoint } from 'kibana/public';
|
||||
|
||||
/**
|
||||
* MountPoint converter for react nodes.
|
||||
*
|
||||
* @param node to get a mount point for
|
||||
*/
|
||||
export const toMountPoint = (node: React.ReactNode): MountPoint => {
|
||||
const mount = (element: HTMLElement) => {
|
||||
ReactDOM.render(<I18nProvider>{node}</I18nProvider>, element);
|
||||
return () => ReactDOM.unmountComponentAtNode(element);
|
||||
};
|
||||
// only used for tests and snapshots serialization
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
mount.__reactMount__ = node;
|
||||
}
|
||||
return mount;
|
||||
};
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
export function test(value: any) {
|
||||
return value && value.__reactMount__;
|
||||
}
|
||||
|
||||
export function print(value: any, serialize: any) {
|
||||
// there is no proper way to correctly indent multiline values
|
||||
// so the trick here is to use the Object representation and rewriting the root object name
|
||||
return serialize({
|
||||
reactNode: value.__reactMount__,
|
||||
}).replace('Object', 'MountPoint');
|
||||
}
|
|
@ -47,7 +47,10 @@ export function createJestConfig({ kibanaDirectory, xPackKibanaDirectory }) {
|
|||
// since ESM modules are not natively supported in Jest yet (https://github.com/facebook/jest/issues/4842)
|
||||
'[/\\\\]node_modules(?![\\/\\\\]@elastic[\\/\\\\]eui)(?![\\/\\\\]monaco-editor)[/\\\\].+\\.js$',
|
||||
],
|
||||
snapshotSerializers: [`${kibanaDirectory}/node_modules/enzyme-to-json/serializer`],
|
||||
snapshotSerializers: [
|
||||
`${kibanaDirectory}/node_modules/enzyme-to-json/serializer`,
|
||||
`${kibanaDirectory}/src/plugins/kibana_react/public/util/test_helpers/react_mount_serializer.ts`
|
||||
],
|
||||
reporters: [
|
||||
'default',
|
||||
[
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import React, { Component } from 'react';
|
||||
import { toMountPoint } from '../../../../../../../../../../src/plugins/kibana_react/public';
|
||||
import { startMLJob } from '../../../../../services/rest/ml';
|
||||
import { IUrlParams } from '../../../../../context/UrlParamsContext/types';
|
||||
import { MLJobLink } from '../../../../shared/Links/MachineLearningLinks/MLJobLink';
|
||||
|
@ -71,7 +72,7 @@ export class MachineLearningFlyout extends Component<Props, State> {
|
|||
defaultMessage: 'Job creation failed'
|
||||
}
|
||||
),
|
||||
text: (
|
||||
text: toMountPoint(
|
||||
<p>
|
||||
{i18n.translate(
|
||||
'xpack.apm.serviceDetails.enableAnomalyDetectionPanel.jobCreationFailedNotificationText',
|
||||
|
@ -105,7 +106,7 @@ export class MachineLearningFlyout extends Component<Props, State> {
|
|||
defaultMessage: 'Job successfully created'
|
||||
}
|
||||
),
|
||||
text: (
|
||||
text: toMountPoint(
|
||||
<p>
|
||||
{i18n.translate(
|
||||
'xpack.apm.serviceDetails.enableAnomalyDetectionPanel.jobCreatedNotificationText',
|
||||
|
|
|
@ -30,6 +30,7 @@ import { padLeft, range } from 'lodash';
|
|||
import moment from 'moment-timezone';
|
||||
import React, { Component } from 'react';
|
||||
import styled from 'styled-components';
|
||||
import { toMountPoint } from '../../../../../../../../../src/plugins/kibana_react/public';
|
||||
import { KibanaCoreContext } from '../../../../../../observability/public';
|
||||
import { IUrlParams } from '../../../../context/UrlParamsContext/types';
|
||||
import { KibanaLink } from '../../../shared/Links/KibanaLink';
|
||||
|
@ -219,7 +220,7 @@ export class WatcherFlyout extends Component<
|
|||
defaultMessage: 'Watch creation failed'
|
||||
}
|
||||
),
|
||||
text: (
|
||||
text: toMountPoint(
|
||||
<p>
|
||||
{i18n.translate(
|
||||
'xpack.apm.serviceDetails.enableErrorReportsPanel.watchCreationFailedNotificationText',
|
||||
|
@ -243,7 +244,7 @@ export class WatcherFlyout extends Component<
|
|||
defaultMessage: 'New watch created!'
|
||||
}
|
||||
),
|
||||
text: (
|
||||
text: toMountPoint(
|
||||
<p>
|
||||
{i18n.translate(
|
||||
'xpack.apm.serviceDetails.enableErrorReportsPanel.watchCreatedNotificationText',
|
||||
|
|
|
@ -9,6 +9,7 @@ import { EuiLink } from '@elastic/eui';
|
|||
import { i18n } from '@kbn/i18n';
|
||||
import React, { useEffect, useMemo } from 'react';
|
||||
import url from 'url';
|
||||
import { toMountPoint } from '../../../../../../../../src/plugins/kibana_react/public';
|
||||
import { useFetcher } from '../../../hooks/useFetcher';
|
||||
import { NoServicesMessage } from './NoServicesMessage';
|
||||
import { ServiceList } from './ServiceList';
|
||||
|
@ -55,7 +56,7 @@ export function ServiceOverview() {
|
|||
defaultMessage:
|
||||
'Legacy data was detected within the selected time range'
|
||||
}),
|
||||
text: (
|
||||
text: toMountPoint(
|
||||
<p>
|
||||
{i18n.translate('xpack.apm.serviceOverview.toastText', {
|
||||
defaultMessage:
|
||||
|
|
|
@ -8,6 +8,7 @@ import React, { useContext, useEffect, useState, useMemo } from 'react';
|
|||
import { idx } from '@kbn/elastic-idx';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { IHttpFetchError } from 'src/core/public';
|
||||
import { toMountPoint } from '../../../../../../src/plugins/kibana_react/public';
|
||||
import { LoadingIndicatorContext } from '../context/LoadingIndicatorContext';
|
||||
import { useComponentId } from './useComponentId';
|
||||
import { useKibanaCore } from '../../../observability/public';
|
||||
|
@ -92,7 +93,7 @@ export function useFetcher<TReturn>(
|
|||
title: i18n.translate('xpack.apm.fetcher.error.title', {
|
||||
defaultMessage: `Error while fetching resource`
|
||||
}),
|
||||
text: (
|
||||
text: toMountPoint(
|
||||
<div>
|
||||
<h5>
|
||||
{i18n.translate('xpack.apm.fetcher.error.status', {
|
||||
|
|
|
@ -10,6 +10,7 @@ import { toastNotifications } from 'ui/notify';
|
|||
import { i18n } from '@kbn/i18n';
|
||||
import { idx } from '@kbn/elastic-idx/target';
|
||||
import { KFetchError } from 'ui/kfetch/kfetch_error';
|
||||
import { toMountPoint } from '../../../../../../src/plugins/kibana_react/public';
|
||||
import { useTrackedPromise } from '../utils/use_tracked_promise';
|
||||
export function useHTTPRequest<Response>(
|
||||
pathname: string,
|
||||
|
@ -36,7 +37,7 @@ export function useHTTPRequest<Response>(
|
|||
title: i18n.translate('xpack.infra.useHTTPRequest.error.title', {
|
||||
defaultMessage: `Error while fetching resource`,
|
||||
}),
|
||||
text: (
|
||||
text: toMountPoint(
|
||||
<div>
|
||||
<h5>
|
||||
{i18n.translate('xpack.infra.useHTTPRequest.error.status', {
|
||||
|
|
|
@ -24,6 +24,7 @@ import { EuiMonitoringTable } from 'plugins/monitoring/components/table';
|
|||
import { AlertsIndicator } from 'plugins/monitoring/components/cluster/listing/alerts_indicator';
|
||||
import { FormattedMessage } from '@kbn/i18n/react';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { toMountPoint } from '../../../../../../../../src/plugins/kibana_react/public';
|
||||
import { STANDALONE_CLUSTER_CLUSTER_UUID } from '../../../../common/constants';
|
||||
|
||||
const IsClusterSupported = ({ isSupported, children }) => {
|
||||
|
@ -271,14 +272,14 @@ const licenseWarning = (scope, { title, text }) => {
|
|||
|
||||
const handleClickIncompatibleLicense = (scope, clusterName) => {
|
||||
licenseWarning(scope, {
|
||||
title: (
|
||||
title: toMountPoint(
|
||||
<FormattedMessage
|
||||
id="xpack.monitoring.cluster.listing.incompatibleLicense.warningMessageTitle"
|
||||
defaultMessage="You can't view the {clusterName} cluster"
|
||||
values={{ clusterName: '"' + clusterName + '"' }}
|
||||
/>
|
||||
),
|
||||
text: (
|
||||
text: toMountPoint(
|
||||
<Fragment>
|
||||
<p>
|
||||
<FormattedMessage
|
||||
|
@ -311,14 +312,14 @@ const handleClickInvalidLicense = (scope, clusterName) => {
|
|||
const licensingPath = `${chrome.getBasePath()}/app/kibana#/management/elasticsearch/license_management/home`;
|
||||
|
||||
licenseWarning(scope, {
|
||||
title: (
|
||||
title: toMountPoint(
|
||||
<FormattedMessage
|
||||
id="xpack.monitoring.cluster.listing.invalidLicense.warningMessageTitle"
|
||||
defaultMessage="You can't view the {clusterName} cluster"
|
||||
values={{ clusterName: '"' + clusterName + '"' }}
|
||||
/>
|
||||
),
|
||||
text: (
|
||||
text: toMountPoint(
|
||||
<Fragment>
|
||||
<p>
|
||||
<FormattedMessage
|
||||
|
|
|
@ -14,6 +14,7 @@ import {
|
|||
EuiText,
|
||||
} from '@elastic/eui';
|
||||
import { FormattedMessage } from '@kbn/i18n/react';
|
||||
import { toMountPoint } from '../../../../../../src/plugins/kibana_react/public';
|
||||
|
||||
export function formatMonitoringError(err) {
|
||||
// TODO: We should stop using Boom for errors and instead write a custom handler to return richer error objects
|
||||
|
@ -47,12 +48,12 @@ export function ajaxErrorHandlersProvider($injector) {
|
|||
kbnUrl.redirect('access-denied');
|
||||
} else if (err.status === 404 && !contains(window.location.hash, 'no-data')) { // pass through if this is a 404 and we're already on the no-data page
|
||||
toastNotifications.addDanger({
|
||||
title: (
|
||||
title: toMountPoint(
|
||||
<FormattedMessage
|
||||
id="xpack.monitoring.ajaxErrorHandler.requestFailedNotificationTitle"
|
||||
defaultMessage="Monitoring Request Failed"
|
||||
/>),
|
||||
text: (
|
||||
text: toMountPoint(
|
||||
<div>
|
||||
{ formatMonitoringError(err) }
|
||||
<EuiSpacer />
|
||||
|
@ -71,12 +72,12 @@ export function ajaxErrorHandlersProvider($injector) {
|
|||
});
|
||||
} else {
|
||||
toastNotifications.addDanger({
|
||||
title: (
|
||||
title: toMountPoint(
|
||||
<FormattedMessage
|
||||
id="xpack.monitoring.ajaxErrorHandler.requestErrorNotificationTitle"
|
||||
defaultMessage="Monitoring Request Error"
|
||||
/>),
|
||||
text: formatMonitoringError(err)
|
||||
text: toMountPoint(formatMonitoringError(err))
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@ import React, { Component, ReactElement } from 'react';
|
|||
import { KFetchError } from 'ui/kfetch/kfetch_error';
|
||||
import { toastNotifications } from 'ui/notify';
|
||||
import url from 'url';
|
||||
import { toMountPoint } from '../../../../../../src/plugins/kibana_react/public';
|
||||
import { reportingClient } from '../lib/reporting_client';
|
||||
|
||||
interface Props {
|
||||
|
@ -209,7 +210,7 @@ class ReportingPanelContentUi extends Component<Props, State> {
|
|||
},
|
||||
{ objectType: this.props.objectType }
|
||||
),
|
||||
text: (
|
||||
text: toMountPoint(
|
||||
<FormattedMessage
|
||||
id="xpack.reporting.panelContent.successfullyQueuedReportNotificationDescription"
|
||||
defaultMessage="Track its progress in Management"
|
||||
|
@ -229,7 +230,7 @@ class ReportingPanelContentUi extends Component<Props, State> {
|
|||
},
|
||||
{ objectType: this.props.objectType }
|
||||
),
|
||||
text: (
|
||||
text: toMountPoint(
|
||||
<FormattedMessage
|
||||
id="xpack.reporting.panelContent.whatCanBeExportedWarningDescription"
|
||||
defaultMessage="Please save your work first"
|
||||
|
@ -256,7 +257,7 @@ class ReportingPanelContentUi extends Component<Props, State> {
|
|||
id: 'xpack.reporting.panelContent.notification.reportingErrorTitle',
|
||||
defaultMessage: 'Reporting error',
|
||||
}),
|
||||
text: kfetchError.message || defaultMessage,
|
||||
text: toMountPoint(kfetchError.message || defaultMessage),
|
||||
'data-test-subj': 'queueReportError',
|
||||
});
|
||||
});
|
||||
|
|
|
@ -8,6 +8,7 @@ import React from 'react';
|
|||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { toastNotifications } from 'ui/notify';
|
||||
import { toMountPoint } from '../../../../../../../src/plugins/kibana_react/public';
|
||||
|
||||
import { TransformListRow, refreshTransformList$, REFRESH_TRANSFORM_LIST_STATE } from '../common';
|
||||
import { ToastNotificationText } from '../components';
|
||||
|
@ -53,7 +54,7 @@ export const useDeleteTransforms = () => {
|
|||
title: i18n.translate('xpack.transform.transformList.deleteTransformGenericErrorMessage', {
|
||||
defaultMessage: 'An error occurred calling the API endpoint to delete transforms.',
|
||||
}),
|
||||
text: <ToastNotificationText text={e} />,
|
||||
text: toMountPoint(<ToastNotificationText text={e} />),
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
|
@ -29,6 +29,7 @@ import {
|
|||
EuiText,
|
||||
} from '@elastic/eui';
|
||||
|
||||
import { toMountPoint } from '../../../../../../../../../../src/plugins/kibana_react/public';
|
||||
import { ToastNotificationText } from '../../../../components';
|
||||
import { useApi } from '../../../../hooks/use_api';
|
||||
import { isKibanaContextInitialized, KibanaContext } from '../../../../lib/kibana';
|
||||
|
@ -114,7 +115,7 @@ export const StepCreateForm: SFC<Props> = React.memo(
|
|||
defaultMessage: 'An error occurred creating the transform {transformId}:',
|
||||
values: { transformId },
|
||||
}),
|
||||
text: <ToastNotificationText text={e} />,
|
||||
text: toMountPoint(<ToastNotificationText text={e} />),
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
@ -144,7 +145,7 @@ export const StepCreateForm: SFC<Props> = React.memo(
|
|||
defaultMessage: 'An error occurred starting the transform {transformId}:',
|
||||
values: { transformId },
|
||||
}),
|
||||
text: <ToastNotificationText text={e} />,
|
||||
text: toMountPoint(<ToastNotificationText text={e} />),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -203,7 +204,7 @@ export const StepCreateForm: SFC<Props> = React.memo(
|
|||
'An error occurred creating the Kibana index pattern {indexPatternName}:',
|
||||
values: { indexPatternName },
|
||||
}),
|
||||
text: <ToastNotificationText text={e} />,
|
||||
text: toMountPoint(<ToastNotificationText text={e} />),
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
@ -234,7 +235,7 @@ export const StepCreateForm: SFC<Props> = React.memo(
|
|||
title: i18n.translate('xpack.transform.stepCreateForm.progressErrorMessage', {
|
||||
defaultMessage: 'An error occurred getting the progress percentage:',
|
||||
}),
|
||||
text: <ToastNotificationText text={e} />,
|
||||
text: toMountPoint(<ToastNotificationText text={e} />),
|
||||
});
|
||||
clearInterval(interval);
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ import { toastNotifications } from 'ui/notify';
|
|||
|
||||
import { EuiLink, EuiSwitch, EuiFieldText, EuiForm, EuiFormRow, EuiSelect } from '@elastic/eui';
|
||||
|
||||
import { toMountPoint } from '../../../../../../../../../../src/plugins/kibana_react/public';
|
||||
import { isKibanaContextInitialized, KibanaContext } from '../../../../lib/kibana';
|
||||
import { isValidIndexName } from '../../../../../../common/utils/es_utils';
|
||||
|
||||
|
@ -91,7 +92,7 @@ export const StepDetailsForm: SFC<Props> = React.memo(({ overrides = {}, onChang
|
|||
title: i18n.translate('xpack.transform.stepDetailsForm.errorGettingTransformList', {
|
||||
defaultMessage: 'An error occurred getting the existing transform IDs:',
|
||||
}),
|
||||
text: <ToastNotificationText text={e} />,
|
||||
text: toMountPoint(<ToastNotificationText text={e} />),
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -102,7 +103,7 @@ export const StepDetailsForm: SFC<Props> = React.memo(({ overrides = {}, onChang
|
|||
title: i18n.translate('xpack.transform.stepDetailsForm.errorGettingIndexNames', {
|
||||
defaultMessage: 'An error occurred getting the existing index names:',
|
||||
}),
|
||||
text: <ToastNotificationText text={e} />,
|
||||
text: toMountPoint(<ToastNotificationText text={e} />),
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -116,7 +117,7 @@ export const StepDetailsForm: SFC<Props> = React.memo(({ overrides = {}, onChang
|
|||
defaultMessage: 'An error occurred getting the existing index pattern titles:',
|
||||
}
|
||||
),
|
||||
text: <ToastNotificationText text={e} />,
|
||||
text: toMountPoint(<ToastNotificationText text={e} />),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,9 +8,10 @@ import React, { Fragment } from 'react';
|
|||
import { FormattedMessage } from '@kbn/i18n/react';
|
||||
import { EuiCallOut, EuiSpacer } from '@elastic/eui';
|
||||
import { ToastInput } from '../../../../../src/core/public';
|
||||
import { toMountPoint } from '../../../../../src/plugins/kibana_react/public';
|
||||
|
||||
export const getGeneralErrorToast = (errorText: string, err: Error): ToastInput => ({
|
||||
text: (
|
||||
text: toMountPoint(
|
||||
<Fragment>
|
||||
<EuiCallOut title={errorText} color="danger" iconType="alert">
|
||||
{err.toString()}
|
||||
|
|
|
@ -9,6 +9,7 @@ import { i18n } from '@kbn/i18n';
|
|||
import { FormattedMessage } from '@kbn/i18n/react';
|
||||
import { EuiCallOut, EuiSpacer } from '@elastic/eui';
|
||||
import { ToastInput } from '../../../../../src/core/public';
|
||||
import { toMountPoint } from '../../../../../src/plugins/kibana_react/public';
|
||||
import { JobSummary, ManagementLinkFn } from '../../index.d';
|
||||
|
||||
export const getFailureToast = (
|
||||
|
@ -17,14 +18,14 @@ export const getFailureToast = (
|
|||
getManagmenetLink: ManagementLinkFn
|
||||
): ToastInput => {
|
||||
return {
|
||||
title: (
|
||||
title: toMountPoint(
|
||||
<FormattedMessage
|
||||
id="xpack.reporting.publicNotifier.error.couldNotCreateReportTitle"
|
||||
defaultMessage="Could not create report for {reportObjectType} '{reportObjectTitle}'."
|
||||
values={{ reportObjectType: job.type, reportObjectTitle: job.title }}
|
||||
/>
|
||||
),
|
||||
text: (
|
||||
text: toMountPoint(
|
||||
<Fragment>
|
||||
<EuiCallOut
|
||||
size="m"
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
import React, { Fragment } from 'react';
|
||||
import { FormattedMessage } from '@kbn/i18n/react';
|
||||
import { ToastInput } from '../../../../../src/core/public';
|
||||
import { toMountPoint } from '../../../../../src/plugins/kibana_react/public';
|
||||
import { JobId, JobSummary } from '../../index.d';
|
||||
import { ReportLink } from './report_link';
|
||||
import { DownloadButton } from './download_button';
|
||||
|
@ -16,7 +17,7 @@ export const getSuccessToast = (
|
|||
getReportLink: () => string,
|
||||
getDownloadLink: (jobId: JobId) => string
|
||||
): ToastInput => ({
|
||||
title: (
|
||||
title: toMountPoint(
|
||||
<FormattedMessage
|
||||
id="xpack.reporting.publicNotifier.successfullyCreatedReportNotificationTitle"
|
||||
defaultMessage="Created report for {reportObjectType} '{reportObjectTitle}'"
|
||||
|
@ -24,7 +25,7 @@ export const getSuccessToast = (
|
|||
/>
|
||||
),
|
||||
color: 'success',
|
||||
text: (
|
||||
text: toMountPoint(
|
||||
<Fragment>
|
||||
<p>
|
||||
<ReportLink getUrl={getReportLink} />
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
import React, { Fragment } from 'react';
|
||||
import { FormattedMessage } from '@kbn/i18n/react';
|
||||
import { ToastInput } from '../../../../../src/core/public';
|
||||
import { toMountPoint } from '../../../../../src/plugins/kibana_react/public';
|
||||
import { JobId, JobSummary } from '../../index.d';
|
||||
import { ReportLink } from './report_link';
|
||||
import { DownloadButton } from './download_button';
|
||||
|
@ -16,14 +17,14 @@ export const getWarningFormulasToast = (
|
|||
getReportLink: () => string,
|
||||
getDownloadLink: (jobId: JobId) => string
|
||||
): ToastInput => ({
|
||||
title: (
|
||||
title: toMountPoint(
|
||||
<FormattedMessage
|
||||
id="xpack.reporting.publicNotifier.csvContainsFormulas.formulaReportTitle"
|
||||
defaultMessage="Report may contain formulas {reportObjectType} '{reportObjectTitle}'"
|
||||
values={{ reportObjectType: job.type, reportObjectTitle: job.title }}
|
||||
/>
|
||||
),
|
||||
text: (
|
||||
text: toMountPoint(
|
||||
<Fragment>
|
||||
<p>
|
||||
<FormattedMessage
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
import React, { Fragment } from 'react';
|
||||
import { FormattedMessage } from '@kbn/i18n/react';
|
||||
import { ToastInput } from '../../../../../src/core/public';
|
||||
import { toMountPoint } from '../../../../../src/plugins/kibana_react/public';
|
||||
import { JobId, JobSummary } from '../../index.d';
|
||||
import { ReportLink } from './report_link';
|
||||
import { DownloadButton } from './download_button';
|
||||
|
@ -16,14 +17,14 @@ export const getWarningMaxSizeToast = (
|
|||
getReportLink: () => string,
|
||||
getDownloadLink: (jobId: JobId) => string
|
||||
): ToastInput => ({
|
||||
title: (
|
||||
title: toMountPoint(
|
||||
<FormattedMessage
|
||||
id="xpack.reporting.publicNotifier.maxSizeReached.partialReportTitle"
|
||||
defaultMessage="Created partial report for {reportObjectType} '{reportObjectTitle}'"
|
||||
values={{ reportObjectType: job.type, reportObjectTitle: job.title }}
|
||||
/>
|
||||
),
|
||||
text: (
|
||||
text: toMountPoint(
|
||||
<Fragment>
|
||||
<p>
|
||||
<FormattedMessage
|
||||
|
|
|
@ -29,42 +29,46 @@ exports[`stream handler showNotifications show csv formulas warning 1`] = `
|
|||
Array [
|
||||
Object {
|
||||
"data-test-subj": "completeReportCsvFormulasWarning",
|
||||
"text": <React.Fragment>
|
||||
<p>
|
||||
<FormattedMessage
|
||||
defaultMessage="The report contains characters which spreadsheet applications can interpret as formulas."
|
||||
id="xpack.reporting.publicNotifier.csvContainsFormulas.formulaReportMessage"
|
||||
values={Object {}}
|
||||
/>
|
||||
</p>
|
||||
<p>
|
||||
<ReportLink
|
||||
"text": MountPoint {
|
||||
"reactNode": <React.Fragment>
|
||||
<p>
|
||||
<FormattedMessage
|
||||
defaultMessage="The report contains characters which spreadsheet applications can interpret as formulas."
|
||||
id="xpack.reporting.publicNotifier.csvContainsFormulas.formulaReportMessage"
|
||||
values={Object {}}
|
||||
/>
|
||||
</p>
|
||||
<p>
|
||||
<ReportLink
|
||||
getUrl={[Function]}
|
||||
/>
|
||||
</p>
|
||||
<DownloadButton
|
||||
getUrl={[Function]}
|
||||
job={
|
||||
Object {
|
||||
"csvContainsFormulas": true,
|
||||
"id": "yas3",
|
||||
"status": "completed",
|
||||
"title": "Yas",
|
||||
"type": "yas",
|
||||
}
|
||||
}
|
||||
/>
|
||||
</p>
|
||||
<DownloadButton
|
||||
getUrl={[Function]}
|
||||
job={
|
||||
</React.Fragment>,
|
||||
},
|
||||
"title": MountPoint {
|
||||
"reactNode": <FormattedMessage
|
||||
defaultMessage="Report may contain formulas {reportObjectType} '{reportObjectTitle}'"
|
||||
id="xpack.reporting.publicNotifier.csvContainsFormulas.formulaReportTitle"
|
||||
values={
|
||||
Object {
|
||||
"csvContainsFormulas": true,
|
||||
"id": "yas3",
|
||||
"status": "completed",
|
||||
"title": "Yas",
|
||||
"type": "yas",
|
||||
"reportObjectTitle": "Yas",
|
||||
"reportObjectType": "yas",
|
||||
}
|
||||
}
|
||||
/>
|
||||
</React.Fragment>,
|
||||
"title": <FormattedMessage
|
||||
defaultMessage="Report may contain formulas {reportObjectType} '{reportObjectTitle}'"
|
||||
id="xpack.reporting.publicNotifier.csvContainsFormulas.formulaReportTitle"
|
||||
values={
|
||||
Object {
|
||||
"reportObjectTitle": "Yas",
|
||||
"reportObjectType": "yas",
|
||||
}
|
||||
}
|
||||
/>,
|
||||
/>,
|
||||
},
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
@ -74,44 +78,48 @@ Array [
|
|||
Object {
|
||||
"data-test-subj": "completeReportFailure",
|
||||
"iconType": undefined,
|
||||
"text": <React.Fragment>
|
||||
<EuiCallOut
|
||||
color="danger"
|
||||
iconType="alert"
|
||||
size="m"
|
||||
title="The reporting job failed"
|
||||
>
|
||||
this is the completed report data
|
||||
</EuiCallOut>
|
||||
<EuiSpacer />
|
||||
<p>
|
||||
<FormattedMessage
|
||||
defaultMessage="More information is available at {path}."
|
||||
id="xpack.reporting.publicNotifier.error.checkManagement"
|
||||
values={
|
||||
Object {
|
||||
"path": <a>
|
||||
<FormattedMessage
|
||||
defaultMessage="Management > Kibana > Reporting"
|
||||
id="xpack.reporting.publicNotifier.error.reportingSectionUrlLinkLabel"
|
||||
values={Object {}}
|
||||
/>
|
||||
</a>,
|
||||
"text": MountPoint {
|
||||
"reactNode": <React.Fragment>
|
||||
<EuiCallOut
|
||||
color="danger"
|
||||
iconType="alert"
|
||||
size="m"
|
||||
title="The reporting job failed"
|
||||
>
|
||||
this is the completed report data
|
||||
</EuiCallOut>
|
||||
<EuiSpacer />
|
||||
<p>
|
||||
<FormattedMessage
|
||||
defaultMessage="More information is available at {path}."
|
||||
id="xpack.reporting.publicNotifier.error.checkManagement"
|
||||
values={
|
||||
Object {
|
||||
"path": <a>
|
||||
<FormattedMessage
|
||||
defaultMessage="Management > Kibana > Reporting"
|
||||
id="xpack.reporting.publicNotifier.error.reportingSectionUrlLinkLabel"
|
||||
values={Object {}}
|
||||
/>
|
||||
</a>,
|
||||
}
|
||||
}
|
||||
/>
|
||||
</p>
|
||||
</React.Fragment>,
|
||||
},
|
||||
"title": MountPoint {
|
||||
"reactNode": <FormattedMessage
|
||||
defaultMessage="Could not create report for {reportObjectType} '{reportObjectTitle}'."
|
||||
id="xpack.reporting.publicNotifier.error.couldNotCreateReportTitle"
|
||||
values={
|
||||
Object {
|
||||
"reportObjectTitle": "Yas 7",
|
||||
"reportObjectType": "yas",
|
||||
}
|
||||
/>
|
||||
</p>
|
||||
</React.Fragment>,
|
||||
"title": <FormattedMessage
|
||||
defaultMessage="Could not create report for {reportObjectType} '{reportObjectTitle}'."
|
||||
id="xpack.reporting.publicNotifier.error.couldNotCreateReportTitle"
|
||||
values={
|
||||
Object {
|
||||
"reportObjectTitle": "Yas 7",
|
||||
"reportObjectType": "yas",
|
||||
}
|
||||
}
|
||||
/>,
|
||||
/>,
|
||||
},
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
@ -120,42 +128,46 @@ exports[`stream handler showNotifications show max length warning 1`] = `
|
|||
Array [
|
||||
Object {
|
||||
"data-test-subj": "completeReportMaxSizeWarning",
|
||||
"text": <React.Fragment>
|
||||
<p>
|
||||
<FormattedMessage
|
||||
defaultMessage="The report reached the max size and contains partial data."
|
||||
id="xpack.reporting.publicNotifier.maxSizeReached.partialReportDescription"
|
||||
values={Object {}}
|
||||
/>
|
||||
</p>
|
||||
<p>
|
||||
<ReportLink
|
||||
"text": MountPoint {
|
||||
"reactNode": <React.Fragment>
|
||||
<p>
|
||||
<FormattedMessage
|
||||
defaultMessage="The report reached the max size and contains partial data."
|
||||
id="xpack.reporting.publicNotifier.maxSizeReached.partialReportDescription"
|
||||
values={Object {}}
|
||||
/>
|
||||
</p>
|
||||
<p>
|
||||
<ReportLink
|
||||
getUrl={[Function]}
|
||||
/>
|
||||
</p>
|
||||
<DownloadButton
|
||||
getUrl={[Function]}
|
||||
job={
|
||||
Object {
|
||||
"id": "yas2",
|
||||
"maxSizeReached": true,
|
||||
"status": "completed",
|
||||
"title": "Yas",
|
||||
"type": "yas",
|
||||
}
|
||||
}
|
||||
/>
|
||||
</p>
|
||||
<DownloadButton
|
||||
getUrl={[Function]}
|
||||
job={
|
||||
</React.Fragment>,
|
||||
},
|
||||
"title": MountPoint {
|
||||
"reactNode": <FormattedMessage
|
||||
defaultMessage="Created partial report for {reportObjectType} '{reportObjectTitle}'"
|
||||
id="xpack.reporting.publicNotifier.maxSizeReached.partialReportTitle"
|
||||
values={
|
||||
Object {
|
||||
"id": "yas2",
|
||||
"maxSizeReached": true,
|
||||
"status": "completed",
|
||||
"title": "Yas",
|
||||
"type": "yas",
|
||||
"reportObjectTitle": "Yas",
|
||||
"reportObjectType": "yas",
|
||||
}
|
||||
}
|
||||
/>
|
||||
</React.Fragment>,
|
||||
"title": <FormattedMessage
|
||||
defaultMessage="Created partial report for {reportObjectType} '{reportObjectTitle}'"
|
||||
id="xpack.reporting.publicNotifier.maxSizeReached.partialReportTitle"
|
||||
values={
|
||||
Object {
|
||||
"reportObjectTitle": "Yas",
|
||||
"reportObjectType": "yas",
|
||||
}
|
||||
}
|
||||
/>,
|
||||
/>,
|
||||
},
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
@ -165,34 +177,38 @@ Array [
|
|||
Object {
|
||||
"color": "success",
|
||||
"data-test-subj": "completeReportSuccess",
|
||||
"text": <React.Fragment>
|
||||
<p>
|
||||
<ReportLink
|
||||
"text": MountPoint {
|
||||
"reactNode": <React.Fragment>
|
||||
<p>
|
||||
<ReportLink
|
||||
getUrl={[Function]}
|
||||
/>
|
||||
</p>
|
||||
<DownloadButton
|
||||
getUrl={[Function]}
|
||||
job={
|
||||
Object {
|
||||
"id": "yas1",
|
||||
"status": "completed",
|
||||
"title": "Yas",
|
||||
"type": "yas",
|
||||
}
|
||||
}
|
||||
/>
|
||||
</p>
|
||||
<DownloadButton
|
||||
getUrl={[Function]}
|
||||
job={
|
||||
</React.Fragment>,
|
||||
},
|
||||
"title": MountPoint {
|
||||
"reactNode": <FormattedMessage
|
||||
defaultMessage="Created report for {reportObjectType} '{reportObjectTitle}'"
|
||||
id="xpack.reporting.publicNotifier.successfullyCreatedReportNotificationTitle"
|
||||
values={
|
||||
Object {
|
||||
"id": "yas1",
|
||||
"status": "completed",
|
||||
"title": "Yas",
|
||||
"type": "yas",
|
||||
"reportObjectTitle": "Yas",
|
||||
"reportObjectType": "yas",
|
||||
}
|
||||
}
|
||||
/>
|
||||
</React.Fragment>,
|
||||
"title": <FormattedMessage
|
||||
defaultMessage="Created report for {reportObjectType} '{reportObjectTitle}'"
|
||||
id="xpack.reporting.publicNotifier.successfullyCreatedReportNotificationTitle"
|
||||
values={
|
||||
Object {
|
||||
"reportObjectTitle": "Yas",
|
||||
"reportObjectType": "yas",
|
||||
}
|
||||
}
|
||||
/>,
|
||||
/>,
|
||||
},
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
|
|
@ -26,9 +26,11 @@ const expectWarningToast = (
|
|||
Array [
|
||||
Object {
|
||||
"color": "warning",
|
||||
"text": <SessionTimeoutWarning
|
||||
onRefreshSession={[Function]}
|
||||
/>,
|
||||
"text": MountPoint {
|
||||
"reactNode": <SessionTimeoutWarning
|
||||
onRefreshSession={[Function]}
|
||||
/>,
|
||||
},
|
||||
"title": "Warning",
|
||||
"toastLifeTimeMs": ${toastLifeTimeMS},
|
||||
},
|
||||
|
@ -103,8 +105,8 @@ describe('warning toast', () => {
|
|||
expect(http.get).not.toHaveBeenCalled();
|
||||
const toastInput = notifications.toasts.add.mock.calls[0][0];
|
||||
expect(toastInput).toHaveProperty('text');
|
||||
const reactComponent = (toastInput as any).text;
|
||||
const wrapper = mountWithIntl(reactComponent);
|
||||
const mountPoint = (toastInput as any).text;
|
||||
const wrapper = mountWithIntl(mountPoint.__reactMount__);
|
||||
wrapper.find('EuiButton[data-test-subj="refreshSessionButton"]').simulate('click');
|
||||
expect(http.get).toHaveBeenCalled();
|
||||
});
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
import { NotificationsSetup, Toast, HttpSetup } from 'src/core/public';
|
||||
import React from 'react';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { toMountPoint } from '../../../../../src/plugins/kibana_react/public';
|
||||
import { SessionTimeoutWarning } from './session_timeout_warning';
|
||||
import { ISessionExpired } from './session_expired';
|
||||
|
||||
|
@ -65,7 +66,7 @@ export class SessionTimeout {
|
|||
private showWarning = () => {
|
||||
this.warningToast = this.notifications.toasts.add({
|
||||
color: 'warning',
|
||||
text: <SessionTimeoutWarning onRefreshSession={this.refreshSession} />,
|
||||
text: toMountPoint(<SessionTimeoutWarning onRefreshSession={this.refreshSession} />),
|
||||
title: i18n.translate('xpack.security.components.sessionTimeoutWarning.title', {
|
||||
defaultMessage: 'Warning',
|
||||
}),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue