[EuiProvider] Fix Kibana-Core code (#183873)

Fixes needed for https://github.com/elastic/kibana/pull/180819
This commit is contained in:
Tim Sullivan 2024-05-23 13:19:40 -07:00 committed by GitHub
parent 47ed7e672c
commit 66182b451b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
31 changed files with 291 additions and 118 deletions

View file

@ -16,6 +16,7 @@ import {
EuiHorizontalRule,
EuiListGroup,
} from '@elastic/eui';
import { KibanaRenderContextProvider } from '@kbn/react-kibana-context-render';
import { RandomNumberRouteExample } from './random_number_example';
import { RandomNumberBetweenRouteExample } from './random_number_between_example';
import { Services } from './services';
@ -30,56 +31,59 @@ function RoutingExplorer({
addSuccessToast,
postMessage,
getMessageById,
startServices,
}: Props) {
return (
<EuiPageTemplate>
<EuiPageTemplate.Header>
<EuiText>
<h1>Routing examples</h1>
</EuiText>
</EuiPageTemplate.Header>
<EuiPageTemplate.Section>
<EuiPageSection>
<KibanaRenderContextProvider {...startServices}>
<EuiPageTemplate>
<EuiPageTemplate.Header>
<EuiText>
<EuiListGroup
listItems={[
{
label: 'IRouter API docs',
href: 'https://github.com/elastic/kibana/blob/main/docs/development/core/server/kibana-plugin-core-server.irouter.md',
iconType: 'logoGithub',
target: '_blank',
size: 's',
},
{
label: 'HttpHandler (core.http.fetch) API docs',
href: 'https://github.com/elastic/kibana/blob/main/docs/development/core/public/kibana-plugin-core-public.httphandler.md',
iconType: 'logoGithub',
target: '_blank',
size: 's',
},
{
label: 'Conventions',
href: 'https://github.com/elastic/kibana/tree/main/STYLEGUIDE.mdx#api-endpoints',
iconType: 'logoGithub',
target: '_blank',
size: 's',
},
]}
/>
<h1>Routing examples</h1>
</EuiText>
<EuiHorizontalRule />
<RandomNumberRouteExample fetchRandomNumber={fetchRandomNumber} />
<EuiHorizontalRule />
<RandomNumberBetweenRouteExample fetchRandomNumberBetween={fetchRandomNumberBetween} />
</EuiPageTemplate.Header>
<EuiPageTemplate.Section>
<EuiPageSection>
<EuiText>
<EuiListGroup
listItems={[
{
label: 'IRouter API docs',
href: 'https://github.com/elastic/kibana/blob/main/docs/development/core/server/kibana-plugin-core-server.irouter.md',
iconType: 'logoGithub',
target: '_blank',
size: 's',
},
{
label: 'HttpHandler (core.http.fetch) API docs',
href: 'https://github.com/elastic/kibana/blob/main/docs/development/core/public/kibana-plugin-core-public.httphandler.md',
iconType: 'logoGithub',
target: '_blank',
size: 's',
},
{
label: 'Conventions',
href: 'https://github.com/elastic/kibana/tree/main/STYLEGUIDE.mdx#api-endpoints',
iconType: 'logoGithub',
target: '_blank',
size: 's',
},
]}
/>
</EuiText>
<EuiHorizontalRule />
<RandomNumberRouteExample fetchRandomNumber={fetchRandomNumber} />
<EuiHorizontalRule />
<RandomNumberBetweenRouteExample fetchRandomNumberBetween={fetchRandomNumberBetween} />
<EuiHorizontalRule />
<PostMessageRouteExample addSuccessToast={addSuccessToast} postMessage={postMessage} />
<EuiHorizontalRule />
<PostMessageRouteExample addSuccessToast={addSuccessToast} postMessage={postMessage} />
<EuiHorizontalRule />
<GetMessageRouteExample getMessageById={getMessageById} />
</EuiPageSection>
</EuiPageTemplate.Section>
</EuiPageTemplate>
<EuiHorizontalRule />
<GetMessageRouteExample getMessageById={getMessageById} />
</EuiPageSection>
</EuiPageTemplate.Section>
</EuiPageTemplate>
</KibanaRenderContextProvider>
);
}

View file

@ -6,7 +6,12 @@
* Side Public License, v 1.
*/
import type { CoreStart } from '@kbn/core/public';
import type {
AnalyticsServiceStart,
CoreStart,
I18nStart,
ThemeServiceStart,
} from '@kbn/core/public';
import type { IHttpFetchError } from '@kbn/core-http-browser';
import {
RANDOM_NUMBER_ROUTE_PATH,
@ -15,7 +20,14 @@ import {
INTERNAL_GET_MESSAGE_BY_ID_ROUTE,
} from '../common';
interface StartServices {
analytics: Pick<AnalyticsServiceStart, 'reportEvent'>;
i18n: I18nStart;
theme: Pick<ThemeServiceStart, 'theme$'>;
}
export interface Services {
startServices: StartServices;
fetchRandomNumber: () => Promise<number | IHttpFetchError>;
fetchRandomNumberBetween: (max: number) => Promise<number | IHttpFetchError>;
postMessage: (message: string, id: string) => Promise<undefined | IHttpFetchError>;
@ -24,7 +36,11 @@ export interface Services {
}
export function getServices(core: CoreStart): Services {
const { analytics, i18n, theme } = core;
const startServices = { analytics, i18n, theme };
return {
startServices,
addSuccessToast: (message: string) => core.notifications.toasts.addSuccess(message),
fetchRandomNumber: async () => {
try {

View file

@ -19,5 +19,6 @@
"@kbn/developer-examples-plugin",
"@kbn/core-http-browser",
"@kbn/config-schema",
"@kbn/react-kibana-context-render",
]
}

View file

@ -13,13 +13,13 @@ import type { SharePluginStart } from '@kbn/share-plugin/public';
export interface ConnectionDetailsGlobalDependencies {
start: {
core: {
analytics: CoreStart['analytics'];
i18n: CoreStart['i18n'];
docLinks: CoreStart['docLinks'];
theme: CoreStart['theme'];
http: CoreStart['http'];
application: CoreStart['application'];
overlays: CoreStart['overlays'];
analytics?: CoreStart['analytics'];
};
plugins: {
cloud?: CloudStart;

View file

@ -8,6 +8,7 @@
import * as React from 'react';
import ReactDOM from 'react-dom';
import { KibanaRenderContextProvider } from '@kbn/react-kibana-context-render';
import type { CoreStart } from '@kbn/core-lifecycle-browser';
import * as conn from '..';
@ -16,6 +17,9 @@ export interface OpenConnectionDetailsParams {
start: {
core: {
overlays: CoreStart['overlays'];
i18n: CoreStart['i18n'];
analytics?: CoreStart['analytics'];
theme: CoreStart['theme'];
};
};
}
@ -23,14 +27,16 @@ export interface OpenConnectionDetailsParams {
export const openConnectionDetails = async ({ props, start }: OpenConnectionDetailsParams) => {
const mount = (element: HTMLElement) => {
const reactElement = (
<conn.KibanaConnectionDetailsProvider
{...props}
onNavigation={() => {
flyoutRef?.close();
}}
>
<conn.ConnectionDetailsFlyoutContent />
</conn.KibanaConnectionDetailsProvider>
<KibanaRenderContextProvider {...start.core}>
<conn.KibanaConnectionDetailsProvider
{...props}
onNavigation={() => {
flyoutRef?.close();
}}
>
<conn.ConnectionDetailsFlyoutContent />
</conn.KibanaConnectionDetailsProvider>
</KibanaRenderContextProvider>
);
ReactDOM.render(reactElement, element);

View file

@ -22,5 +22,6 @@
"@kbn/cloud-plugin",
"@kbn/share-plugin",
"@kbn/security-plugin-types-server",
"@kbn/react-kibana-context-render",
]
}

View file

@ -18,12 +18,15 @@ import type {
InternalApplicationSetup,
InternalApplicationStart,
} from '@kbn/core-application-browser-internal';
import type { AnalyticsServiceStart } from '@kbn/core-analytics-browser';
import type { I18nStart } from '@kbn/core-i18n-browser';
import type { ThemeServiceStart } from '@kbn/core-theme-browser';
import { renderApp as renderStatusApp } from './status';
import {
renderApp as renderErrorApp,
setupPublicBaseUrlConfigWarning,
setupUrlOverflowDetection,
} from './errors';
import { renderApp as renderStatusApp } from './status';
export interface CoreAppsServiceSetupDeps {
application: InternalApplicationSetup;
@ -38,6 +41,9 @@ export interface CoreAppsServiceStartDeps {
http: InternalHttpStart;
notifications: NotificationsStart;
uiSettings: IUiSettingsClient;
analytics: AnalyticsServiceStart;
i18n: I18nStart;
theme: ThemeServiceStart;
}
export class CoreAppsService {
@ -79,6 +85,9 @@ export class CoreAppsService {
http,
notifications,
uiSettings,
analytics,
i18n,
theme,
}: CoreAppsServiceStartDeps) {
if (!application.history) {
return;
@ -91,7 +100,7 @@ export class CoreAppsService {
uiSettings,
});
setupPublicBaseUrlConfigWarning({ docLinks, http, notifications });
setupPublicBaseUrlConfigWarning({ docLinks, http, notifications, analytics, i18n, theme });
}
public stop() {

View file

@ -6,15 +6,28 @@
* Side Public License, v 1.
*/
import { analyticsServiceMock } from '@kbn/core-analytics-browser-mocks';
import { docLinksServiceMock } from '@kbn/core-doc-links-browser-mocks';
import { httpServiceMock } from '@kbn/core-http-browser-mocks';
import { i18nServiceMock } from '@kbn/core-i18n-browser-mocks';
import { notificationServiceMock } from '@kbn/core-notifications-browser-mocks';
import { themeServiceMock } from '@kbn/core-theme-browser-mocks';
import { setupPublicBaseUrlConfigWarning } from './public_base_url';
describe('publicBaseUrl warning', () => {
const docLinks = docLinksServiceMock.createStartContract();
const notifications = notificationServiceMock.createStartContract();
const i18nStart = i18nServiceMock.createStartContract();
const analytics = analyticsServiceMock.createAnalyticsServiceStart();
const theme = themeServiceMock.createStartContract();
const startServices = {
notifications,
analytics,
i18n: i18nStart,
theme,
};
const addWarningToastSpy = jest.spyOn(notifications.toasts, 'addWarning');
beforeEach(() => {
jest.resetAllMocks();
@ -24,38 +37,38 @@ describe('publicBaseUrl warning', () => {
const http = httpServiceMock.createStartContract();
setupPublicBaseUrlConfigWarning({
...startServices,
docLinks,
notifications,
http,
location: {
hostname: 'localhost',
} as Location,
});
expect(notifications.toasts.addWarning).not.toHaveBeenCalled();
expect(addWarningToastSpy).not.toHaveBeenCalled();
});
it('does not show any toast on 127.0.0.1', () => {
const http = httpServiceMock.createStartContract();
setupPublicBaseUrlConfigWarning({
...startServices,
docLinks,
notifications,
http,
location: {
hostname: '127.0.0.1',
} as Location,
});
expect(notifications.toasts.addWarning).not.toHaveBeenCalled();
expect(addWarningToastSpy).not.toHaveBeenCalled();
});
it('does not show toast if configured correctly', () => {
const http = httpServiceMock.createStartContract({ publicBaseUrl: 'http://myhost.com' });
setupPublicBaseUrlConfigWarning({
...startServices,
docLinks,
notifications,
http,
location: {
hostname: 'myhost.com',
@ -65,7 +78,7 @@ describe('publicBaseUrl warning', () => {
} as Location,
});
expect(notifications.toasts.addWarning).not.toHaveBeenCalled();
expect(addWarningToastSpy).not.toHaveBeenCalled();
});
describe('config missing toast', () => {
@ -73,8 +86,8 @@ describe('publicBaseUrl warning', () => {
const http = httpServiceMock.createStartContract({ publicBaseUrl: undefined });
setupPublicBaseUrlConfigWarning({
...startServices,
docLinks,
notifications,
http,
location: {
hostname: 'myhost.com',
@ -84,7 +97,7 @@ describe('publicBaseUrl warning', () => {
} as Location,
});
expect(notifications.toasts.addWarning).toHaveBeenCalledWith({
expect(addWarningToastSpy).toHaveBeenCalledWith({
title: 'Configuration recommended',
text: expect.any(Function),
});
@ -94,8 +107,8 @@ describe('publicBaseUrl warning', () => {
const http = httpServiceMock.createStartContract({ publicBaseUrl: undefined });
setupPublicBaseUrlConfigWarning({
...startServices,
docLinks,
notifications,
http,
location: {
hostname: 'myhost.com',
@ -104,11 +117,11 @@ describe('publicBaseUrl warning', () => {
},
} as Location,
storage: {
getItem: (id: string) => 'true',
getItem: (_id: string) => 'true',
} as Storage,
});
expect(notifications.toasts.addWarning).not.toHaveBeenCalled();
expect(addWarningToastSpy).not.toHaveBeenCalled();
});
});
});

View file

@ -12,9 +12,13 @@ import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n-react';
import type { DocLinksStart } from '@kbn/core-doc-links-browser';
import type { AnalyticsServiceStart } from '@kbn/core-analytics-browser';
import type { I18nStart } from '@kbn/core-i18n-browser';
import type { ThemeServiceStart } from '@kbn/core-theme-browser';
import type { InternalHttpStart } from '@kbn/core-http-browser-internal';
import type { NotificationsStart } from '@kbn/core-notifications-browser';
import { mountReactNode } from '@kbn/core-mount-utils-browser-internal';
import { KibanaRenderContextProvider } from '@kbn/react-kibana-context-render';
/** Only exported for tests */
export const MISSING_CONFIG_STORAGE_KEY = `core.warnings.publicBaseUrlMissingDismissed`;
@ -26,6 +30,10 @@ interface Deps {
// Exposed for easier testing
storage?: Storage;
location?: Location;
// For KibanaRenderContextProvider
analytics: AnalyticsServiceStart;
i18n: I18nStart;
theme: ThemeServiceStart;
}
export const setupPublicBaseUrlConfigWarning = ({
@ -34,6 +42,7 @@ export const setupPublicBaseUrlConfigWarning = ({
notifications,
storage = window.localStorage,
location = window.location,
...renderContextDeps
}: Deps) => {
if (location.hostname === 'localhost' || location.hostname === '127.0.0.1') {
return;
@ -49,7 +58,7 @@ export const setupPublicBaseUrlConfigWarning = ({
defaultMessage: 'Configuration recommended',
}),
text: mountReactNode(
<>
<KibanaRenderContextProvider {...renderContextDeps}>
<p>
<FormattedMessage
id="core.ui.publicBaseUrlWarning.configRecommendedDescription"
@ -87,7 +96,7 @@ export const setupPublicBaseUrlConfigWarning = ({
</EuiButton>
</EuiFlexItem>
</EuiFlexGroup>
</>
</KibanaRenderContextProvider>
),
});
};

View file

@ -10,7 +10,7 @@
},
"include": [
"**/*.ts",
"**/*.tsx",
"**/*.tsx"
],
"kbn_references": [
"@kbn/i18n",
@ -35,8 +35,15 @@
"@kbn/core-doc-links-browser-mocks",
"@kbn/test-jest-helpers",
"@kbn/react-kibana-context-theme",
"@kbn/core-analytics-browser",
"@kbn/core-i18n-browser",
"@kbn/core-theme-browser",
"@kbn/react-kibana-context-render",
"@kbn/core-analytics-browser-mocks",
"@kbn/core-i18n-browser-mocks",
"@kbn/core-theme-browser-mocks"
],
"exclude": [
"target/**/*",
"target/**/*"
]
}

View file

@ -1,7 +1,35 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`renders matching snapshot 1`] = `
<Fragment>
<KibanaRenderContextProvider
analytics={
Object {
"optIn": [MockFunction],
"reportEvent": [MockFunction],
"telemetryCounter$": Subject {
"closed": false,
"currentObservers": null,
"hasError": false,
"isStopped": false,
"observers": Array [],
"thrownError": null,
},
}
}
i18n={
Object {
"Context": [MockFunction],
}
}
theme={
Object {
"getTheme": [MockFunction],
"theme$": Observable {
"_subscribe": [Function],
},
}
}
>
<p
data-test-subj="errorToastMessage"
>
@ -23,5 +51,5 @@ exports[`renders matching snapshot 1`] = `
/>
</EuiButton>
</div>
</Fragment>
</KibanaRenderContextProvider>
`;

View file

@ -111,7 +111,7 @@ export function ErrorToast({
...startServices
}: ErrorToastProps) {
return (
<React.Fragment>
<KibanaRenderContextProvider {...startServices}>
<p data-test-subj="errorToastMessage">{toastMessage}</p>
<div className="eui-textRight">
<EuiButton
@ -126,7 +126,7 @@ export function ErrorToast({
/>
</EuiButton>
</div>
</React.Fragment>
</KibanaRenderContextProvider>
);
}

View file

@ -291,14 +291,14 @@ export class CoreSystem {
const analytics = this.analytics.start();
const security = this.security.start();
const userProfile = this.userProfile.start();
const injectedMetadata = await this.injectedMetadata.start();
const uiSettings = await this.uiSettings.start();
const settings = await this.settings.start();
const injectedMetadata = this.injectedMetadata.start();
const uiSettings = this.uiSettings.start();
const settings = this.settings.start();
const docLinks = this.docLinks.start({ injectedMetadata });
const http = await this.http.start();
const http = this.http.start();
const savedObjects = await this.savedObjects.start({ http });
const i18n = await this.i18n.start();
const fatalErrors = await this.fatalErrors.start();
const i18n = this.i18n.start();
const fatalErrors = this.fatalErrors.start();
const theme = this.theme.start();
await this.integrations.start({ uiSettings });
@ -345,7 +345,16 @@ export class CoreSystem {
});
const deprecations = this.deprecations.start({ http });
this.coreApp.start({ application, docLinks, http, notifications, uiSettings });
this.coreApp.start({
application,
docLinks,
http,
notifications,
uiSettings,
analytics,
i18n,
theme,
});
const core: InternalCoreStart = {
analytics,

View file

@ -8,6 +8,7 @@
import React from 'react';
import { render, unmountComponentAtNode } from 'react-dom';
import { KibanaRenderContextProvider } from '@kbn/react-kibana-context-render';
import {
EuiPage,
EuiPageBody,
@ -17,7 +18,7 @@ import {
EuiTitle,
} from '@elastic/eui';
import { AppMountParameters } from '@kbn/core/public';
import { AppMountParameters, CoreStart } from '@kbn/core/public';
const AppStatusApp = ({ appId }: { appId: string }) => (
<EuiPage>
@ -41,8 +42,17 @@ const AppStatusApp = ({ appId }: { appId: string }) => (
</EuiPage>
);
export const renderApp = (appId: string, { element }: AppMountParameters) => {
render(<AppStatusApp appId={appId} />, element);
export const renderApp = async (
appId: string,
{ element }: AppMountParameters,
core: CoreStart
) => {
render(
<KibanaRenderContextProvider {...core}>
<AppStatusApp appId={appId} />
</KibanaRenderContextProvider>,
element
);
return () => unmountComponentAtNode(element);
};

View file

@ -26,7 +26,8 @@ export class CoreAppStatusPlugin implements Plugin<{}, CoreAppStatusPluginStart>
id: 'app_status_start',
title: 'App Status Start Page',
async mount(params: AppMountParameters) {
return renderApp('app_status_start', params);
const [coreStart] = await core.getStartServices();
return renderApp('app_status_start', params, coreStart);
},
});
@ -36,7 +37,8 @@ export class CoreAppStatusPlugin implements Plugin<{}, CoreAppStatusPluginStart>
euiIconType: 'snowflake',
updater$: this.appUpdater,
async mount(params: AppMountParameters) {
return renderApp('app_status', params);
const [coreStart] = await core.getStartServices();
return renderApp('app_status', params, coreStart);
},
});

View file

@ -14,5 +14,6 @@
],
"kbn_references": [
"@kbn/core",
"@kbn/react-kibana-context-render",
],
}

View file

@ -10,6 +10,7 @@ import { History } from 'history';
import React from 'react';
import ReactDOM from 'react-dom';
import { withRouter, RouteComponentProps, Redirect } from 'react-router-dom';
import { KibanaRenderContextProvider } from '@kbn/react-kibana-context-render';
import { Router, Route } from '@kbn/shared-ux-router';
import {
@ -100,16 +101,18 @@ const Nav = withRouter(({ history, navigateToApp }: NavProps) => (
));
const FooApp = ({ history, coreStart }: { history: History; coreStart: CoreStart }) => (
<Router history={history}>
<EuiPage>
<EuiPageSidebar>
<Nav navigateToApp={coreStart.application.navigateToApp} />
</EuiPageSidebar>
<Route path="/" exact render={() => <Redirect to="/home" />} />
<Route path="/home" exact component={Home} />
<Route path="/page-a" component={PageA} />
</EuiPage>
</Router>
<KibanaRenderContextProvider {...coreStart}>
<Router history={history}>
<EuiPage>
<EuiPageSidebar>
<Nav navigateToApp={coreStart.application.navigateToApp} />
</EuiPageSidebar>
<Route path="/" exact render={() => <Redirect to="/home" />} />
<Route path="/home" exact component={Home} />
<Route path="/page-a" component={PageA} />
</EuiPage>
</Router>
</KibanaRenderContextProvider>
);
export const renderApp = (coreStart: CoreStart, { history, element }: AppMountParameters) => {

View file

@ -15,6 +15,7 @@
],
"kbn_references": [
"@kbn/core",
"@kbn/shared-ux-router"
"@kbn/shared-ux-router",
"@kbn/react-kibana-context-render"
]
}

View file

@ -16,8 +16,8 @@ import {
EuiPageHeaderSection,
EuiTitle,
} from '@elastic/eui';
import { AppMountParameters } from '@kbn/core/public';
import { KibanaRenderContextProvider } from '@kbn/react-kibana-context-render';
import { AppMountParameters, CoreStart } from '@kbn/core/public';
const App = ({ appName }: { appName: string }) => (
<EuiPage>
@ -41,7 +41,12 @@ const App = ({ appName }: { appName: string }) => (
</EuiPage>
);
export const renderApp = (appName: string, { element }: AppMountParameters) => {
render(<App appName={appName} />, element);
export const renderApp = (appName: string, { element }: AppMountParameters, core: CoreStart) => {
render(
<KibanaRenderContextProvider {...core}>
<App appName={appName} />
</KibanaRenderContextProvider>,
element
);
return () => unmountComponentAtNode(element);
};

View file

@ -19,8 +19,9 @@ export class CoreAppLeavePlugin
category: DEFAULT_APP_CATEGORIES.kibana,
async mount(params) {
const { renderApp } = await import('./application');
const [coreStart] = await core.getStartServices();
params.onAppLeave((actions) => actions.confirm('confirm-message', 'confirm-title'));
return renderApp('AppLeave 1', params);
return renderApp('AppLeave 1', params, coreStart);
},
});
core.application.register({
@ -30,8 +31,9 @@ export class CoreAppLeavePlugin
category: DEFAULT_APP_CATEGORIES.kibana,
async mount(params) {
const { renderApp } = await import('./application');
const [coreStart] = await core.getStartServices();
params.onAppLeave((actions) => actions.confirm('confirm-message', 'confirm-title'));
return renderApp('AppLeave 2', params);
return renderApp('AppLeave 2', params, coreStart);
},
});

View file

@ -13,6 +13,7 @@
"target/**/*",
],
"kbn_references": [
"@kbn/core"
"@kbn/core",
"@kbn/react-kibana-context-render"
]
}

View file

@ -10,6 +10,7 @@ import { History } from 'history';
import React from 'react';
import ReactDOM from 'react-dom';
import { withRouter, RouteComponentProps } from 'react-router-dom';
import { KibanaRenderContextProvider } from '@kbn/react-kibana-context-render';
import { Router, Route } from '@kbn/shared-ux-router';
import {
@ -119,7 +120,12 @@ const BarApp = ({ history, coreStart }: { history: History; coreStart: CoreStart
);
export const renderApp = (coreStart: CoreStart, { history, element }: AppMountParameters) => {
ReactDOM.render(<BarApp history={history} coreStart={coreStart} />, element);
ReactDOM.render(
<KibanaRenderContextProvider {...coreStart}>
<BarApp history={history} coreStart={coreStart} />
</KibanaRenderContextProvider>,
element
);
return () => ReactDOM.unmountComponentAtNode(element);
};

View file

@ -18,5 +18,6 @@
"@kbn/core-plugin-a-plugin",
"@kbn/config-schema",
"@kbn/shared-ux-router",
"@kbn/react-kibana-context-render",
]
}

View file

@ -9,6 +9,7 @@
import React from 'react';
import { render, unmountComponentAtNode } from 'react-dom';
import { BrowserRouter as Router } from 'react-router-dom';
import { KibanaRenderContextProvider } from '@kbn/react-kibana-context-render';
import { Route } from '@kbn/shared-ux-router';
import {
EuiPage,
@ -19,7 +20,7 @@ import {
EuiTitle,
} from '@elastic/eui';
import { AppMountParameters } from '@kbn/core/public';
import { AppMountParameters, CoreStart } from '@kbn/core/public';
const Home = () => (
<EuiPageBody data-test-subj="chromelessAppHome">
@ -49,8 +50,13 @@ const ChromelessApp = ({ basename }: { basename: string }) => (
</Router>
);
export const renderApp = ({ appBasePath, element }: AppMountParameters) => {
render(<ChromelessApp basename={appBasePath} />, element);
export const renderApp = async ({ appBasePath, element }: AppMountParameters, core: CoreStart) => {
render(
<KibanaRenderContextProvider {...core}>
<ChromelessApp basename={appBasePath} />
</KibanaRenderContextProvider>,
element
);
return () => unmountComponentAtNode(element);
};

View file

@ -17,8 +17,9 @@ export class CorePluginChromelessPlugin
title: 'Chromeless',
chromeless: true,
async mount(params) {
const [coreStart] = await core.getStartServices();
const { renderApp } = await import('./application');
return renderApp(params);
return renderApp(params, coreStart);
},
});
}

View file

@ -15,5 +15,6 @@
"kbn_references": [
"@kbn/core",
"@kbn/shared-ux-router",
"@kbn/react-kibana-context-render",
]
}

View file

@ -10,6 +10,7 @@ import { History } from 'history';
import React from 'react';
import ReactDOM from 'react-dom';
import { withRouter, RouteComponentProps, Redirect } from 'react-router-dom';
import { KibanaRenderContextProvider } from '@kbn/react-kibana-context-render';
import { Router, Route } from '@kbn/shared-ux-router';
import {
@ -144,7 +145,12 @@ const DlApp = ({ history, coreStart }: { history: History; coreStart: CoreStart
);
export const renderApp = (coreStart: CoreStart, { history, element }: AppMountParameters) => {
ReactDOM.render(<DlApp history={history} coreStart={coreStart} />, element);
ReactDOM.render(
<KibanaRenderContextProvider {...coreStart}>
<DlApp history={history} coreStart={coreStart} />
</KibanaRenderContextProvider>,
element
);
return () => ReactDOM.unmountComponentAtNode(element);
};

View file

@ -15,6 +15,7 @@
"kbn_references": [
"@kbn/core",
"@kbn/shared-ux-router",
"@kbn/core-application-browser-internal"
"@kbn/core-application-browser-internal",
"@kbn/react-kibana-context-render"
]
}

View file

@ -16,6 +16,16 @@ import {
EuiPageHeaderSection,
EuiTitle,
} from '@elastic/eui';
import type { AnalyticsServiceStart } from '@kbn/core-analytics-browser';
import type { I18nStart } from '@kbn/core-i18n-browser';
import type { ThemeServiceStart } from '@kbn/core-theme-browser';
import { KibanaRenderContextProvider } from '@kbn/react-kibana-context-render';
interface StartServices {
analytics: Pick<AnalyticsServiceStart, 'reportEvent'>;
i18n: I18nStart;
theme: Pick<ThemeServiceStart, 'theme$'>;
}
import { AppMountParameters } from '@kbn/core/public';
@ -41,7 +51,16 @@ const App = ({ appName }: { appName: string }) => (
</EuiPage>
);
export const renderApp = (appName: string, { element }: AppMountParameters) => {
render(<App appName={appName} />, element);
export const renderApp = (
appName: string,
{ element }: AppMountParameters,
startServices: StartServices
) => {
render(
<KibanaRenderContextProvider {...startServices}>
<App appName={appName} />
</KibanaRenderContextProvider>,
element
);
return () => unmountComponentAtNode(element);
};

View file

@ -16,7 +16,7 @@ export class CoreHelpMenuPlugin
id: 'core_help_menu',
title: 'Help Menu Test App',
async mount(params) {
const [{ chrome, http }] = await core.getStartServices();
const [{ chrome, http, ...startServices }] = await core.getStartServices();
chrome.setHelpExtension({
appName: 'HelpMenuTestApp',
@ -31,7 +31,7 @@ export class CoreHelpMenuPlugin
});
const { renderApp } = await import('./application');
return renderApp('Help Menu Test App', params);
return renderApp('Help Menu Test App', params, startServices);
},
});

View file

@ -13,6 +13,10 @@
"target/**/*",
],
"kbn_references": [
"@kbn/core"
"@kbn/core",
"@kbn/core-analytics-browser",
"@kbn/core-i18n-browser",
"@kbn/core-theme-browser",
"@kbn/react-kibana-context-render"
]
}