[Stack mgt apps] Wrap all apps with KibanaThemeProvider (#120003)

This commit is contained in:
Sébastien Loix 2021-12-08 12:18:15 +00:00 committed by GitHub
parent b1a038ddc3
commit b5e8b126d8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
53 changed files with 369 additions and 202 deletions

View file

@ -7,7 +7,7 @@
*/
import { notificationServiceMock } from '../../../../../core/public/mocks';
import { httpServiceMock } from '../../../../../core/public/mocks';
import { httpServiceMock, themeServiceMock } from '../../../../../core/public/mocks';
import type { ObjectStorageClient } from '../../../common/types';
import { HistoryMock } from '../../services/history.mock';
@ -35,6 +35,7 @@ export const serviceContextMock = {
objectStorageClient: {} as unknown as ObjectStorageClient,
},
docLinkVersion: 'NA',
theme$: themeServiceMock.create().start().theme$,
};
},
};

View file

@ -7,7 +7,9 @@
*/
import React, { createContext, useContext, useEffect } from 'react';
import { NotificationsSetup } from 'kibana/public';
import { Observable } from 'rxjs';
import { NotificationsSetup, CoreTheme } from 'kibana/public';
import { History, Settings, Storage } from '../../services';
import { ObjectStorageClient } from '../../../common/types';
import { MetricsTracker } from '../../types';
@ -26,6 +28,7 @@ interface ContextServices {
export interface ContextValue {
services: ContextServices;
docLinkVersion: string;
theme$: Observable<CoreTheme>;
}
interface ContextProps {

View file

@ -8,20 +8,21 @@
import { i18n } from '@kbn/i18n';
import { useCallback } from 'react';
import { isQuotaExceededError } from '../../../services/history';
import { instance as registry } from '../../contexts/editor_context/editor_registry';
import { useRequestActionContext, useServicesContext } from '../../contexts';
import { sendRequestToES } from './send_request_to_es';
import { track } from './track';
import { toMountPoint } from '../../../../../kibana_react/public';
import { toMountPoint } from '../../../shared_imports';
import { isQuotaExceededError } from '../../../services/history';
// @ts-ignore
import { retrieveAutoCompleteInfo } from '../../../lib/mappings/mappings';
import { instance as registry } from '../../contexts/editor_context/editor_registry';
import { useRequestActionContext, useServicesContext } from '../../contexts';
import { StorageQuotaError } from '../../components/storage_quota_error';
import { sendRequestToES } from './send_request_to_es';
import { track } from './track';
export const useSendCurrentRequestToES = () => {
const {
services: { history, settings, notifications, trackUiMetric },
theme$,
} = useServicesContext();
const dispatch = useRequestActionContext();
@ -83,7 +84,8 @@ export const useSendCurrentRequestToES = () => {
settings.setHistoryDisabled(true);
notifications.toasts.remove(toast);
},
})
}),
{ theme$ }
),
});
} else {
@ -127,5 +129,5 @@ export const useSendCurrentRequestToES = () => {
});
}
}
}, [dispatch, settings, history, notifications, trackUiMetric]);
}, [dispatch, settings, history, notifications, trackUiMetric, theme$]);
};

View file

@ -8,13 +8,16 @@
import React from 'react';
import { render, unmountComponentAtNode } from 'react-dom';
import { HttpSetup, NotificationsSetup, I18nStart } from 'src/core/public';
import { ServicesContextProvider, EditorContextProvider, RequestContextProvider } from './contexts';
import { Main } from './containers';
import { createStorage, createHistory, createSettings } from '../services';
import * as localStorageObjectClient from '../lib/local_storage_object_client';
import { createUsageTracker } from '../services/tracker';
import { Observable } from 'rxjs';
import { HttpSetup, NotificationsSetup, I18nStart, CoreTheme } from 'src/core/public';
import { UsageCollectionSetup } from '../../../usage_collection/public';
import { KibanaThemeProvider } from '../shared_imports';
import { createStorage, createHistory, createSettings } from '../services';
import { createUsageTracker } from '../services/tracker';
import * as localStorageObjectClient from '../lib/local_storage_object_client';
import { Main } from './containers';
import { ServicesContextProvider, EditorContextProvider, RequestContextProvider } from './contexts';
import { createApi, createEsHostService } from './lib';
export interface BootDependencies {
@ -24,6 +27,7 @@ export interface BootDependencies {
notifications: NotificationsSetup;
usageCollection?: UsageCollectionSetup;
element: HTMLElement;
theme$: Observable<CoreTheme>;
}
export function renderApp({
@ -33,6 +37,7 @@ export function renderApp({
usageCollection,
element,
http,
theme$,
}: BootDependencies) {
const trackUiMetric = createUsageTracker(usageCollection);
trackUiMetric.load('opened_app');
@ -49,26 +54,29 @@ export function renderApp({
render(
<I18nContext>
<ServicesContextProvider
value={{
docLinkVersion,
services: {
esHostService,
storage,
history,
settings,
notifications,
trackUiMetric,
objectStorageClient,
},
}}
>
<RequestContextProvider>
<EditorContextProvider settings={settings.toJSON()}>
<Main />
</EditorContextProvider>
</RequestContextProvider>
</ServicesContextProvider>
<KibanaThemeProvider theme$={theme$}>
<ServicesContextProvider
value={{
docLinkVersion,
services: {
esHostService,
storage,
history,
settings,
notifications,
trackUiMetric,
objectStorageClient,
},
theme$,
}}
>
<RequestContextProvider>
<EditorContextProvider settings={settings.toJSON()}>
<Main />
</EditorContextProvider>
</RequestContextProvider>
</ServicesContextProvider>
</KibanaThemeProvider>
</I18nContext>,
element
);

View file

@ -52,7 +52,7 @@ export class ConsoleUIPlugin implements Plugin<void, void, AppSetupUIPluginDepen
defaultMessage: 'Console',
}),
enableRouting: false,
mount: async ({ element }) => {
mount: async ({ element, theme$ }) => {
const [core] = await getStartServices();
const {
@ -69,6 +69,7 @@ export class ConsoleUIPlugin implements Plugin<void, void, AppSetupUIPluginDepen
notifications,
usageCollection,
element,
theme$,
});
},
});

View file

@ -11,3 +11,5 @@ import { sendRequest, XJson } from '../../es_ui_shared/public';
const { collapseLiteralStrings, expandLiteralStrings } = XJson;
export { sendRequest, collapseLiteralStrings, expandLiteralStrings };
export { KibanaThemeProvider, toMountPoint } from '../../kibana_react/public';

View file

@ -7,5 +7,6 @@
"name": "Stack Management",
"githubTeam": "kibana-stack-management"
},
"requiredPlugins": ["urlForwarding"]
"requiredPlugins": ["urlForwarding"],
"requiredBundles": ["kibanaReact"]
}

View file

@ -16,6 +16,7 @@ import { i18n } from '@kbn/i18n';
import { euiThemeVars } from '@kbn/ui-shared-deps-src/theme';
import { ApplicationStart, ChromeStart, ScopedHistory, CoreTheme } from 'src/core/public';
import { KibanaThemeProvider } from '../../kibana_react/public';
import type { DocTitleService, BreadcrumbService } from './services';
import { DevToolApp } from './dev_tool';
@ -177,32 +178,34 @@ export function renderApp(
ReactDOM.render(
<I18nProvider>
<Router>
<Switch>
{devTools
// Only create routes for devtools that are not disabled
.filter((devTool) => !devTool.isDisabled())
.map((devTool) => (
<Route
key={devTool.id}
path={`/${devTool.id}`}
exact={!devTool.enableRouting}
render={(props) => (
<DevToolsWrapper
updateRoute={props.history.push}
activeDevTool={devTool}
devTools={devTools}
theme$={theme$}
appServices={appServices}
/>
)}
/>
))}
<Route path="/">
<Redirect to={`/${devTools[0].id}`} />
</Route>
</Switch>
</Router>
<KibanaThemeProvider theme$={theme$}>
<Router>
<Switch>
{devTools
// Only create routes for devtools that are not disabled
.filter((devTool) => !devTool.isDisabled())
.map((devTool) => (
<Route
key={devTool.id}
path={`/${devTool.id}`}
exact={!devTool.enableRouting}
render={(props) => (
<DevToolsWrapper
updateRoute={props.history.push}
activeDevTool={devTool}
devTools={devTools}
theme$={theme$}
appServices={appServices}
/>
)}
/>
))}
<Route path="/">
<Redirect to={`/${devTools[0].id}`} />
</Route>
</Switch>
</Router>
</KibanaThemeProvider>
</I18nProvider>,
element
);

View file

@ -8,17 +8,18 @@
import './management_app.scss';
import React, { useState, useEffect, useCallback } from 'react';
import { AppMountParameters, ChromeBreadcrumb, ScopedHistory } from 'kibana/public';
import { I18nProvider } from '@kbn/i18n-react';
import { i18n } from '@kbn/i18n';
import { ManagementSection, MANAGEMENT_BREADCRUMB } from '../../utils';
import { AppMountParameters, ChromeBreadcrumb, ScopedHistory } from 'kibana/public';
import { ManagementSection, MANAGEMENT_BREADCRUMB } from '../../utils';
import { ManagementRouter } from './management_router';
import { managementSidebarNav } from '../management_sidebar_nav/management_sidebar_nav';
import {
KibanaPageTemplate,
KibanaPageTemplateProps,
reactRouterNavigate,
KibanaThemeProvider,
} from '../../../../kibana_react/public';
import { SectionsServiceStart } from '../../types';
@ -83,24 +84,26 @@ export const ManagementApp = ({ dependencies, history, theme$ }: ManagementAppPr
return (
<I18nProvider>
<KibanaPageTemplate
restrictWidth={false}
// EUI TODO
// The different template options need to be manually recreated by the individual pages.
// These classes help enforce the layouts.
pageContentProps={{ className: 'kbnAppWrapper' }}
pageContentBodyProps={{ className: 'kbnAppWrapper' }}
solutionNav={solution}
>
<ManagementRouter
history={history}
theme$={theme$}
setBreadcrumbs={setBreadcrumbsScoped}
onAppMounted={onAppMounted}
sections={sections}
dependencies={dependencies}
/>
</KibanaPageTemplate>
<KibanaThemeProvider theme$={theme$}>
<KibanaPageTemplate
restrictWidth={false}
// EUI TODO
// The different template options need to be manually recreated by the individual pages.
// These classes help enforce the layouts.
pageContentProps={{ className: 'kbnAppWrapper' }}
pageContentBodyProps={{ className: 'kbnAppWrapper' }}
solutionNav={solution}
>
<ManagementRouter
history={history}
theme$={theme$}
setBreadcrumbs={setBreadcrumbsScoped}
onAppMounted={onAppMounted}
sections={sections}
dependencies={dependencies}
/>
</KibanaPageTemplate>
</KibanaThemeProvider>
</I18nProvider>
);
};

View file

@ -8,9 +8,17 @@
import React from 'react';
import { render, unmountComponentAtNode } from 'react-dom';
import { Provider } from 'react-redux';
import { I18nStart, ScopedHistory, ApplicationStart } from 'kibana/public';
import { UnmountCallback } from 'src/core/public';
import { DocLinksStart } from 'kibana/public';
import { Observable } from 'rxjs';
import {
UnmountCallback,
I18nStart,
ScopedHistory,
ApplicationStart,
DocLinksStart,
CoreTheme,
} from 'src/core/public';
import { KibanaThemeProvider } from '../shared_imports';
import { init as initBreadcrumbs, SetBreadcrumbs } from './services/breadcrumbs';
import { init as initDocumentation } from './services/documentation_links';
import { App } from './app';
@ -20,13 +28,16 @@ const renderApp = (
element: Element,
I18nContext: I18nStart['Context'],
history: ScopedHistory,
getUrlForApp: ApplicationStart['getUrlForApp']
getUrlForApp: ApplicationStart['getUrlForApp'],
theme$: Observable<CoreTheme>
): UnmountCallback => {
render(
<I18nContext>
<Provider store={ccrStore}>
<App history={history} getUrlForApp={getUrlForApp} />
</Provider>
<KibanaThemeProvider theme$={theme$}>
<Provider store={ccrStore}>
<App history={history} getUrlForApp={getUrlForApp} />
</Provider>
</KibanaThemeProvider>
</I18nContext>,
element
);
@ -41,6 +52,7 @@ export async function mountApp({
docLinks,
history,
getUrlForApp,
theme$,
}: {
element: Element;
setBreadcrumbs: SetBreadcrumbs;
@ -48,11 +60,12 @@ export async function mountApp({
docLinks: DocLinksStart;
history: ScopedHistory;
getUrlForApp: ApplicationStart['getUrlForApp'];
theme$: Observable<CoreTheme>;
}): Promise<UnmountCallback> {
// Import and initialize additional services here instead of in plugin.ts to reduce the size of the
// initial bundle as much as possible.
initBreadcrumbs(setBreadcrumbs);
initDocumentation(docLinks);
return renderApp(element, I18nContext, history, getUrlForApp);
return renderApp(element, I18nContext, history, getUrlForApp, theme$);
}

View file

@ -41,7 +41,7 @@ export class CrossClusterReplicationPlugin implements Plugin {
id: MANAGEMENT_ID,
title: PLUGIN.TITLE,
order: 6,
mount: async ({ element, setBreadcrumbs, history }) => {
mount: async ({ element, setBreadcrumbs, history, theme$ }) => {
const { mountApp } = await import('./app');
const [coreStart] = await getStartServices();
@ -61,6 +61,7 @@ export class CrossClusterReplicationPlugin implements Plugin {
docLinks,
history,
getUrlForApp,
theme$,
});
return () => {

View file

@ -13,4 +13,6 @@ export {
PageLoading,
} from '../../../../src/plugins/es_ui_shared/public';
export { KibanaThemeProvider } from '../../../../src/plugins/kibana_react/public';
export { APP_WRAPPER_CLASS } from '../../../../src/core/public';

View file

@ -22,11 +22,11 @@ export class GrokDebuggerUIPlugin {
}),
id: PLUGIN.ID,
enableRouting: false,
async mount({ element }) {
async mount({ element, theme$ }) {
const [coreStart] = await coreSetup.getStartServices();
const license = await plugins.licensing.license$.pipe(first()).toPromise();
const { renderApp } = await import('./render_app');
return renderApp(license, element, coreStart);
return renderApp(license, element, coreStart, theme$);
},
});

View file

@ -7,23 +7,27 @@
import React from 'react';
import { render, unmountComponentAtNode } from 'react-dom';
import { I18nProvider } from '@kbn/i18n-react';
import { KibanaContextProvider, KibanaThemeProvider } from './shared_imports';
import { GrokDebugger } from './components/grok_debugger';
import { GrokdebuggerService } from './services/grokdebugger/grokdebugger_service';
import { I18nProvider } from '@kbn/i18n-react';
import { KibanaContextProvider } from '../../../../src/plugins/kibana_react/public';
import { InactiveLicenseSlate } from './components/inactive_license';
export function renderApp(license, element, coreStart) {
export function renderApp(license, element, coreStart, theme$) {
const content = license.isActive ? (
<KibanaContextProvider services={{ ...coreStart }}>
<I18nProvider>
<GrokDebugger grokdebuggerService={new GrokdebuggerService(coreStart.http)} />
<KibanaThemeProvider theme$={theme$}>
<GrokDebugger grokdebuggerService={new GrokdebuggerService(coreStart.http)} />
</KibanaThemeProvider>
</I18nProvider>
</KibanaContextProvider>
) : (
<I18nProvider>
<InactiveLicenseSlate license={license} />
<KibanaThemeProvider theme$={theme$}>
<InactiveLicenseSlate license={license} />
</KibanaThemeProvider>
</I18nProvider>
);

View file

@ -6,3 +6,8 @@
*/
export { EuiCodeEditor } from '../../../../src/plugins/es_ui_shared/public';
export {
KibanaContextProvider,
KibanaThemeProvider,
} from '../../../../src/plugins/kibana_react/public';

View file

@ -7,17 +7,25 @@
import React from 'react';
import { render, unmountComponentAtNode } from 'react-dom';
import { I18nStart, ScopedHistory, ApplicationStart } from 'kibana/public';
import { UnmountCallback } from 'src/core/public';
import { CloudSetup } from '../../../cloud/public';
import { ILicense } from '../../../licensing/public';
import { KibanaContextProvider, APP_WRAPPER_CLASS } from '../shared_imports';
import { Observable } from 'rxjs';
import {
I18nStart,
ScopedHistory,
ApplicationStart,
UnmountCallback,
CoreTheme,
} from 'src/core/public';
import {
CloudSetup,
ILicense,
KibanaContextProvider,
APP_WRAPPER_CLASS,
RedirectAppLinks,
KibanaThemeProvider,
} from '../shared_imports';
import { App } from './app';
import { BreadcrumbService } from './services/breadcrumbs';
import { RedirectAppLinks } from '../../../../../src/plugins/kibana_react/public';
export const renderApp = (
element: Element,
@ -26,15 +34,18 @@ export const renderApp = (
application: ApplicationStart,
breadcrumbService: BreadcrumbService,
license: ILicense,
theme$: Observable<CoreTheme>,
cloud?: CloudSetup
): UnmountCallback => {
const { getUrlForApp } = application;
render(
<RedirectAppLinks application={application} className={APP_WRAPPER_CLASS}>
<I18nContext>
<KibanaContextProvider services={{ cloud, breadcrumbService, license, getUrlForApp }}>
<App history={history} />
</KibanaContextProvider>
<KibanaThemeProvider theme$={theme$}>
<KibanaContextProvider services={{ cloud, breadcrumbService, license, getUrlForApp }}>
<App history={history} />
</KibanaContextProvider>
</KibanaThemeProvider>
</I18nContext>
</RedirectAppLinks>,
element

View file

@ -50,7 +50,7 @@ export class IndexLifecycleManagementPlugin
id: PLUGIN.ID,
title: PLUGIN.TITLE,
order: 2,
mount: async ({ element, history, setBreadcrumbs }) => {
mount: async ({ element, history, setBreadcrumbs, theme$ }) => {
const [coreStart, { licensing }] = await getStartServices();
const {
chrome: { docTitle },
@ -78,6 +78,7 @@ export class IndexLifecycleManagementPlugin
application,
this.breadcrumbService,
license,
theme$,
cloud
);

View file

@ -20,6 +20,7 @@ export type {
ValidationConfig,
ValidationError,
} from '../../../../src/plugins/es_ui_shared/static/forms/hook_form_lib';
export {
useForm,
useFormData,
@ -43,8 +44,16 @@ export {
export { attemptToURIDecode } from '../../../../src/plugins/es_ui_shared/public';
export { KibanaContextProvider } from '../../../../src/plugins/kibana_react/public';
export {
KibanaContextProvider,
KibanaThemeProvider,
RedirectAppLinks,
} from '../../../../src/plugins/kibana_react/public';
export { APP_WRAPPER_CLASS } from '../../../../src/core/public';
export const useKibana = () => _useKibana<AppServicesContext>();
export type { CloudSetup } from '../../cloud/public';
export type { ILicense } from '../../licensing/public';

View file

@ -6,15 +6,15 @@
*/
import React, { createContext, useContext } from 'react';
import { ScopedHistory } from 'kibana/public';
import { Observable } from 'rxjs';
import SemVer from 'semver/classes/semver';
import { ManagementAppMountParams } from 'src/plugins/management/public';
import { UsageCollectionSetup } from 'src/plugins/usage_collection/public';
import { CoreSetup, CoreStart, CoreTheme, ScopedHistory } from 'src/core/public';
import { SharePluginStart } from 'src/plugins/share/public';
import { CoreSetup, CoreStart } from '../../../../../src/core/public';
import { UiMetricService, NotificationService, HttpService } from './services';
import { ExtensionsService } from '../services';
import { SharePluginStart } from '../../../../../src/plugins/share/public';
import { UiMetricService, NotificationService, HttpService } from './services';
const AppContext = createContext<AppDependencies | undefined>(undefined);
@ -39,6 +39,7 @@ export interface AppDependencies {
url: SharePluginStart['url'];
docLinks: CoreStart['docLinks'];
kibanaVersion: SemVer;
theme$: Observable<CoreTheme>;
}
export const AppContextProvider = ({

View file

@ -17,6 +17,7 @@ import {
createKibanaReactContext,
GlobalFlyout,
useKibana as useKibanaReactPlugin,
KibanaThemeProvider,
} from '../shared_imports';
import { AppContextProvider, AppDependencies } from './app_context';
@ -36,7 +37,7 @@ export const renderApp = (
const { i18n, docLinks, notifications, application } = core;
const { Context: I18nContext } = i18n;
const { services, history, setBreadcrumbs, uiSettings, kibanaVersion } = dependencies;
const { services, history, setBreadcrumbs, uiSettings, kibanaVersion, theme$ } = dependencies;
// uiSettings is required by the CodeEditor component used to edit runtime field Painless scripts.
const { Provider: KibanaReactContextProvider } =
@ -59,19 +60,21 @@ export const renderApp = (
render(
<I18nContext>
<KibanaReactContextProvider>
<Provider store={indexManagementStore(services)}>
<AppContextProvider value={dependencies}>
<MappingsEditorProvider>
<ComponentTemplatesProvider value={componentTemplateProviderValues}>
<GlobalFlyoutProvider>
<App history={history} />
</GlobalFlyoutProvider>
</ComponentTemplatesProvider>
</MappingsEditorProvider>
</AppContextProvider>
</Provider>
</KibanaReactContextProvider>
<KibanaThemeProvider theme$={theme$}>
<KibanaReactContextProvider>
<Provider store={indexManagementStore(services)}>
<AppContextProvider value={dependencies}>
<MappingsEditorProvider>
<ComponentTemplatesProvider value={componentTemplateProviderValues}>
<GlobalFlyoutProvider>
<App history={history} />
</GlobalFlyoutProvider>
</ComponentTemplatesProvider>
</MappingsEditorProvider>
</AppContextProvider>
</Provider>
</KibanaReactContextProvider>
</KibanaThemeProvider>
</I18nContext>,
elem
);

View file

@ -54,7 +54,7 @@ export async function mountManagementSection(
isFleetEnabled: boolean,
kibanaVersion: SemVer
) {
const { element, setBreadcrumbs, history } = params;
const { element, setBreadcrumbs, history, theme$ } = params;
const [core, startDependencies] = await coreSetup.getStartServices();
const {
docLinks,
@ -91,6 +91,7 @@ export async function mountManagementSection(
url,
docLinks,
kibanaVersion,
theme$,
};
const unmountAppCallback = renderApp(element, { core, dependencies: appDependencies });

View file

@ -14,6 +14,7 @@ export type {
UseRequestResponse,
Error,
} from '../../../../src/plugins/es_ui_shared/public';
export {
sendRequest,
useRequest,
@ -31,6 +32,7 @@ export type {
FormSchema,
FieldConfig,
} from '../../../../src/plugins/es_ui_shared/static/forms/hook_form_lib';
export {
FIELD_TYPES,
VALIDATION_TYPES,
@ -61,4 +63,5 @@ export {
createKibanaReactContext,
reactRouterNavigate,
useKibana,
KibanaThemeProvider,
} from '../../../../src/plugins/kibana_react/public';

View file

@ -8,11 +8,13 @@
import { HttpSetup } from 'kibana/public';
import React, { ReactNode } from 'react';
import { render, unmountComponentAtNode } from 'react-dom';
import { NotificationsSetup, IUiSettingsClient } from 'kibana/public';
import { Observable } from 'rxjs';
import { NotificationsSetup, IUiSettingsClient, CoreTheme } from 'kibana/public';
import { ManagementAppMountParams } from 'src/plugins/management/public';
import { SharePluginStart } from 'src/plugins/share/public';
import type { FileUploadPluginStart } from '../../../file_upload/public';
import { KibanaContextProvider } from '../../../../../src/plugins/kibana_react/public';
import { KibanaContextProvider, KibanaThemeProvider } from '../shared_imports';
import { API_BASE_PATH } from '../../common/constants';
@ -48,7 +50,8 @@ export const renderApp = (
element: HTMLElement,
I18nContext: ({ children }: { children: ReactNode }) => JSX.Element,
services: AppServices,
coreServices: CoreServices
coreServices: CoreServices,
{ theme$ }: { theme$: Observable<CoreTheme> }
) => {
render(
<AuthorizationProvider
@ -56,9 +59,11 @@ export const renderApp = (
httpClient={coreServices.http}
>
<I18nContext>
<KibanaContextProvider services={services}>
<App />
</KibanaContextProvider>
<KibanaThemeProvider theme$={theme$}>
<KibanaContextProvider services={services}>
<App />
</KibanaContextProvider>
</KibanaThemeProvider>
</I18nContext>
</AuthorizationProvider>,
element

View file

@ -22,7 +22,7 @@ export async function mountManagementSection(
{ http, getStartServices, notifications }: CoreSetup<StartDependencies>,
params: ManagementAppMountParams
) {
const { element, setBreadcrumbs, history } = params;
const { element, setBreadcrumbs, history, theme$ } = params;
const [coreStart, depsStart] = await getStartServices();
const {
docLinks,
@ -45,5 +45,5 @@ export async function mountManagementSection(
fileUpload: depsStart.fileUpload,
};
return renderApp(element, I18nContext, services, { http });
return renderApp(element, I18nContext, services, { http }, { theme$ });
}

View file

@ -17,6 +17,7 @@ export type {
UseRequestConfig,
OnJsonEditorUpdateHandler,
} from '../../../../src/plugins/es_ui_shared/public/';
export {
AuthorizationProvider,
NotAuthorizedSection,
@ -46,6 +47,7 @@ export type {
FormOptions,
SerializerFunc,
} from '../../../../src/plugins/es_ui_shared/static/forms/hook_form_lib';
export {
FIELD_TYPES,
useForm,
@ -84,6 +86,9 @@ export {
isEmptyString,
} from '../../../../src/plugins/es_ui_shared/static/validators/string';
export { KibanaContextProvider } from '../../../../src/plugins/kibana_react/public';
export {
KibanaContextProvider,
KibanaThemeProvider,
} from '../../../../src/plugins/kibana_react/public';
export const useKibana = () => _useKibana<AppServices>();

View file

@ -6,9 +6,9 @@
*/
import React, { createContext, useContext } from 'react';
import { ScopedHistory } from 'kibana/public';
import { Observable } from 'rxjs';
import { CoreStart } from '../../../../../src/core/public';
import { CoreStart, ScopedHistory, CoreTheme } from '../../../../../src/core/public';
import { LicensingPluginSetup, ILicense } from '../../../licensing/public';
import { TelemetryPluginStart } from '../../../../../src/plugins/telemetry/public';
import { ClientConfigType } from '../types';
@ -33,6 +33,7 @@ export interface AppDependencies {
initialLicense: ILicense;
};
config: ClientConfigType;
theme$: Observable<CoreTheme>;
}
export const AppContextProvider = ({

View file

@ -8,6 +8,7 @@
import React from 'react';
import { Provider } from 'react-redux';
import { KibanaThemeProvider } from '../shared_imports';
import { AppContextProvider, AppDependencies } from './app_context';
// @ts-ignore
import { licenseManagementStore } from './store';
@ -23,6 +24,7 @@ export const AppProviders = ({ appDependencies, children }: Props) => {
plugins,
services,
store: { initialLicense },
theme$,
} = appDependencies;
const {
@ -46,9 +48,11 @@ export const AppProviders = ({ appDependencies, children }: Props) => {
return (
<I18nContext>
<Provider store={store}>
<AppContextProvider value={appDependencies}>{children}</AppContextProvider>
</Provider>
<KibanaThemeProvider theme$={theme$}>
<Provider store={store}>
<AppContextProvider value={appDependencies}>{children}</AppContextProvider>
</Provider>
</KibanaThemeProvider>
</I18nContext>
);
};

View file

@ -57,7 +57,7 @@ export class LicenseManagementUIPlugin
id: PLUGIN.id,
title: PLUGIN.title,
order: 0,
mount: async ({ element, setBreadcrumbs, history }) => {
mount: async ({ element, setBreadcrumbs, history, theme$ }) => {
const [coreStart, { telemetry }] = await getStartServices();
const initialLicense = await plugins.licensing.license$.pipe(first()).toPromise();
@ -90,6 +90,7 @@ export class LicenseManagementUIPlugin
initialLicense,
},
docLinks: appDocLinks,
theme$,
};
const { renderApp } = await import('./application');

View file

@ -6,3 +6,5 @@
*/
export { SectionLoading } from '../../../../src/plugins/es_ui_shared/public/';
export { KibanaThemeProvider } from '../../../../src/plugins/kibana_react/public';

View file

@ -7,9 +7,10 @@
import React from 'react';
import { render, unmountComponentAtNode } from 'react-dom';
import { CoreSetup, CoreStart } from 'kibana/public';
import { HttpSetup, ChromeStart } from 'src/core/public';
import { createKibanaReactContext } from '../../../../../src/plugins/kibana_react/public';
import { Observable } from 'rxjs';
import { CoreSetup, CoreStart, HttpSetup, ChromeStart, CoreTheme } from 'src/core/public';
import { createKibanaReactContext, KibanaThemeProvider } from '../shared_imports';
import { Links } from '../links';
import { AppContextProvider } from './context';
@ -21,11 +22,12 @@ interface AppDependencies {
uiSettings: CoreSetup['uiSettings'];
links: Links;
chrome: ChromeStart;
theme$: Observable<CoreTheme>;
}
export function renderApp(
element: HTMLElement | null,
{ http, I18nContext, uiSettings, links, chrome }: AppDependencies
{ http, I18nContext, uiSettings, links, chrome, theme$ }: AppDependencies
) {
if (!element) {
return () => undefined;
@ -35,11 +37,13 @@ export function renderApp(
});
render(
<I18nContext>
<KibanaReactContextProvider>
<AppContextProvider value={{ http, links, chrome }}>
<Main />
</AppContextProvider>
</KibanaReactContextProvider>
<KibanaThemeProvider theme$={theme$}>
<KibanaReactContextProvider>
<AppContextProvider value={{ http, links, chrome }}>
<Main />
</AppContextProvider>
</KibanaReactContextProvider>
</KibanaThemeProvider>
</I18nContext>,
element
);

View file

@ -50,7 +50,7 @@ export class PainlessLabUIPlugin implements Plugin<void, void, PluginDependencie
}),
enableRouting: false,
disabled: false,
mount: async ({ element }) => {
mount: async ({ element, theme$ }) => {
const [core] = await getStartServices();
const {
@ -76,6 +76,7 @@ export class PainlessLabUIPlugin implements Plugin<void, void, PluginDependencie
uiSettings,
links: getLinks(docLinks),
chrome,
theme$,
});
return () => {

View file

@ -0,0 +1,11 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
export {
createKibanaReactContext,
KibanaThemeProvider,
} from '../../../../src/plugins/kibana_react/public';

View file

@ -4,8 +4,9 @@
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import { Observable } from 'rxjs';
import { ScopedHistory } from 'kibana/public';
import { ScopedHistory, CoreTheme } from 'kibana/public';
import { RegisterManagementAppArgs, I18nStart } from '../types';
export declare const renderApp: (
@ -15,5 +16,6 @@ export declare const renderApp: (
isCloudEnabled: boolean;
cloudBaseUrl: string;
},
history: ScopedHistory
history: ScopedHistory,
theme$: Observable<CoreTheme>
) => ReturnType<RegisterManagementAppArgs['mount']>;

View file

@ -9,20 +9,23 @@ import React from 'react';
import { render, unmountComponentAtNode } from 'react-dom';
import { Provider } from 'react-redux';
import { KibanaThemeProvider } from '../shared_imports';
import { App } from './app';
import { remoteClustersStore } from './store';
import { AppContextProvider } from './app_context';
import './_hacks.scss';
export const renderApp = (elem, I18nContext, appDependencies, history) => {
export const renderApp = (elem, I18nContext, appDependencies, history, theme$) => {
render(
<I18nContext>
<Provider store={remoteClustersStore}>
<AppContextProvider context={appDependencies}>
<App history={history} />
</AppContextProvider>
</Provider>
<KibanaThemeProvider theme$={theme$}>
<Provider store={remoteClustersStore}>
<AppContextProvider context={appDependencies}>
<App history={history} />
</AppContextProvider>
</Provider>
</KibanaThemeProvider>
</I18nContext>,
elem
);

View file

@ -43,7 +43,7 @@ export class RemoteClustersUIPlugin
defaultMessage: 'Remote Clusters',
}),
order: 7,
mount: async ({ element, setBreadcrumbs, history }) => {
mount: async ({ element, setBreadcrumbs, history, theme$ }) => {
const [core] = await getStartServices();
const {
chrome: { docTitle },
@ -69,7 +69,8 @@ export class RemoteClustersUIPlugin
element,
i18nContext,
{ isCloudEnabled, cloudBaseUrl },
history
history,
theme$
);
return () => {

View file

@ -10,3 +10,5 @@ export {
indices,
SectionLoading,
} from '../../../../src/plugins/es_ui_shared/public';
export { KibanaThemeProvider } from '../../../../src/plugins/kibana_react/public';

View file

@ -6,10 +6,11 @@
*/
import React from 'react';
import { CoreSetup } from 'kibana/public';
import { render, unmountComponentAtNode } from 'react-dom';
import { Provider } from 'react-redux';
import { KibanaContextProvider } from '../../../../src/plugins/kibana_react/public';
import { CoreSetup } from 'kibana/public';
import { KibanaContextProvider, KibanaThemeProvider } from './shared_imports';
// @ts-ignore
import { rollupJobsStore } from './crud_app/store';
// @ts-ignore
@ -24,7 +25,7 @@ import { ManagementAppMountParams } from '../../../../src/plugins/management/pub
*/
export const renderApp = async (
core: CoreSetup,
{ history, element, setBreadcrumbs }: ManagementAppMountParams
{ history, element, setBreadcrumbs, theme$ }: ManagementAppMountParams
) => {
const [coreStart] = await core.getStartServices();
const I18nContext = coreStart.i18n.Context;
@ -36,11 +37,13 @@ export const renderApp = async (
render(
<I18nContext>
<KibanaContextProvider services={services}>
<Provider store={rollupJobsStore}>
<App history={history} />
</Provider>
</KibanaContextProvider>
<KibanaThemeProvider theme$={theme$}>
<KibanaContextProvider services={services}>
<Provider store={rollupJobsStore}>
<App history={history} />
</Provider>
</KibanaContextProvider>
</KibanaThemeProvider>
</I18nContext>,
element
);

View file

@ -11,3 +11,8 @@ export {
SectionLoading,
EuiCodeEditor,
} from '../../../../src/plugins/es_ui_shared/public';
export {
KibanaContextProvider,
KibanaThemeProvider,
} from '../../../../src/plugins/kibana_react/public';

View file

@ -10,5 +10,5 @@
"githubTeam": "kibana-stack-management"
},
"requiredPlugins": ["devTools", "home", "licensing"],
"requiredBundles": ["esUiShared"]
"requiredBundles": ["esUiShared", "kibanaReact"]
}

View file

@ -7,9 +7,11 @@
import React from 'react';
import { render, unmountComponentAtNode } from 'react-dom';
import { HttpStart as Http, ToastsSetup } from 'kibana/public';
import { Observable } from 'rxjs';
import { HttpStart as Http, ToastsSetup, CoreTheme } from 'kibana/public';
import { LicenseStatus } from '../../common';
import { KibanaThemeProvider } from '../shared_imports';
import { App } from './app';
import { AppContextProvider } from './contexts/app_context';
import { ProfileContextProvider } from './contexts/profiler_context';
@ -20,6 +22,7 @@ interface AppDependencies {
I18nContext: any;
notifications: ToastsSetup;
initialLicenseStatus: LicenseStatus;
theme$: Observable<CoreTheme>;
}
export const renderApp = ({
@ -28,14 +31,17 @@ export const renderApp = ({
I18nContext,
notifications,
initialLicenseStatus,
theme$,
}: AppDependencies) => {
render(
<I18nContext>
<AppContextProvider args={{ initialLicenseStatus, notifications, http }}>
<ProfileContextProvider>
<App />
</ProfileContextProvider>
</AppContextProvider>
<KibanaThemeProvider theme$={theme$}>
<AppContextProvider args={{ initialLicenseStatus, notifications, http }}>
<ProfileContextProvider>
<App />
</ProfileContextProvider>
</AppContextProvider>
</KibanaThemeProvider>
</I18nContext>,
el
);

View file

@ -60,6 +60,7 @@ export class SearchProfilerUIPlugin implements Plugin<void, void, AppPublicPlugi
el: params.element,
I18nContext: i18nDep.Context,
notifications: notifications.toasts,
theme$: params.theme$,
});
},
});

View file

@ -6,3 +6,5 @@
*/
export { ace } from '../../../../src/plugins/es_ui_shared/public';
export { KibanaThemeProvider } from '../../../../src/plugins/kibana_react/public';

View file

@ -7,8 +7,9 @@
import React, { createContext, useContext } from 'react';
import { i18n } from '@kbn/i18n';
import { Observable } from 'rxjs';
import { CoreStart, ScopedHistory } from '../../../../../src/core/public';
import { CoreStart, ScopedHistory, CoreTheme } from '../../../../../src/core/public';
import { ClientConfigType } from '../types';
import { HttpService, UiMetricService } from './services';
@ -23,6 +24,7 @@ export interface AppDependencies {
history: ScopedHistory;
};
config: ClientConfigType;
theme$: Observable<CoreTheme>;
}
export const AppContextProvider = ({

View file

@ -8,7 +8,7 @@
import React from 'react';
import { API_BASE_PATH } from '../../common';
import { AuthorizationProvider } from '../shared_imports';
import { AuthorizationProvider, KibanaThemeProvider } from '../shared_imports';
import { AppContextProvider, AppDependencies } from './app_context';
interface Props {
@ -17,7 +17,7 @@ interface Props {
}
export const AppProviders = ({ appDependencies, children }: Props) => {
const { core } = appDependencies;
const { core, theme$ } = appDependencies;
const {
i18n: { Context: I18nContext },
http,
@ -26,7 +26,9 @@ export const AppProviders = ({ appDependencies, children }: Props) => {
return (
<AuthorizationProvider httpClient={http} privilegesEndpoint={`${API_BASE_PATH}privileges`}>
<I18nContext>
<AppContextProvider value={appDependencies}>{children}</AppContextProvider>
<KibanaThemeProvider theme$={theme$}>
<AppContextProvider value={appDependencies}>{children}</AppContextProvider>
</KibanaThemeProvider>
</I18nContext>
</AuthorizationProvider>
);

View file

@ -24,7 +24,7 @@ export async function mountManagementSection(
config: ClientConfigType,
params: ManagementAppMountParams
) {
const { element, setBreadcrumbs, history } = params;
const { element, setBreadcrumbs, history, theme$ } = params;
const [core] = await coreSetup.getStartServices();
const {
chrome: { docTitle },
@ -42,6 +42,7 @@ export async function mountManagementSection(
i18n,
history,
},
theme$,
};
const unmountAppCallback = renderApp(element, appDependencies);

View file

@ -13,6 +13,7 @@ export type {
UseRequestResponse,
UseRequestConfig,
} from '../../../../src/plugins/es_ui_shared/public';
export {
AuthorizationProvider,
CronEditor,
@ -29,4 +30,7 @@ export {
export { APP_WRAPPER_CLASS } from '../../../../src/core/public';
export { reactRouterNavigate } from '../../../../src/plugins/kibana_react/public';
export {
reactRouterNavigate,
KibanaThemeProvider,
} from '../../../../src/plugins/kibana_react/public';

View file

@ -11,10 +11,15 @@ import { FormattedMessage } from '@kbn/i18n-react';
import { EuiEmptyPrompt, EuiPageContent, EuiLoadingSpinner } from '@elastic/eui';
import { ScopedHistory } from 'src/core/public';
import { RedirectAppLinks } from '../../../../../src/plugins/kibana_react/public';
import { API_BASE_PATH } from '../../common/constants';
import { ClusterUpgradeState } from '../../common/types';
import { APP_WRAPPER_CLASS, GlobalFlyout, AuthorizationProvider } from '../shared_imports';
import {
APP_WRAPPER_CLASS,
GlobalFlyout,
AuthorizationProvider,
RedirectAppLinks,
KibanaThemeProvider,
} from '../shared_imports';
import { AppDependencies } from '../types';
import { AppContextProvider, useAppContext } from './app_context';
import {
@ -170,11 +175,13 @@ export const RootComponent = (dependencies: AppDependencies) => {
<RedirectAppLinks application={application} className={APP_WRAPPER_CLASS}>
<AuthorizationProvider httpClient={http} privilegesEndpoint={`${API_BASE_PATH}/privileges`}>
<i18n.Context>
<AppContextProvider value={dependencies}>
<GlobalFlyoutProvider>
<App history={history} />
</GlobalFlyoutProvider>
</AppContextProvider>
<KibanaThemeProvider theme$={dependencies.theme$}>
<AppContextProvider value={dependencies}>
<GlobalFlyoutProvider>
<App history={history} />
</GlobalFlyoutProvider>
</AppContextProvider>
</KibanaThemeProvider>
</i18n.Context>
</AuthorizationProvider>
</RedirectAppLinks>

View file

@ -77,6 +77,7 @@ export class UpgradeAssistantUIPlugin
api: apiService,
breadcrumbs: breadcrumbService,
},
theme$: params.theme$,
};
const { mountManagementSection } = await import('./application/mount_management_section');

View file

@ -13,6 +13,7 @@ export type {
MissingPrivileges,
Authorization,
} from '../../../../src/plugins/es_ui_shared/public/';
export {
sendRequest,
useRequest,
@ -28,6 +29,8 @@ export { Storage } from '../../../../src/plugins/kibana_utils/public';
export {
KibanaContextProvider,
reactRouterNavigate,
RedirectAppLinks,
KibanaThemeProvider,
} from '../../../../src/plugins/kibana_react/public';
export type { DataPublicPluginStart } from '../../../../src/plugins/data/public';

View file

@ -4,12 +4,12 @@
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import { ScopedHistory } from 'kibana/public';
import { Observable } from 'rxjs';
import { ManagementSetup } from 'src/plugins/management/public';
import { DataPublicPluginStart } from 'src/plugins/data/public';
import { SharePluginSetup } from 'src/plugins/share/public';
import { CoreStart } from 'src/core/public';
import { CoreStart, ScopedHistory, CoreTheme } from 'src/core/public';
import { UsageCollectionSetup } from 'src/plugins/usage_collection/public';
import { CloudSetup } from '../../cloud/public';
import { LicensingPluginStart } from '../../licensing/public';
@ -56,4 +56,5 @@ export interface AppDependencies {
history: ScopedHistory;
api: ApiService;
};
theme$: Observable<CoreTheme>;
}

View file

@ -7,8 +7,10 @@
import React from 'react';
import { render, unmountComponentAtNode } from 'react-dom';
import { SavedObjectsClientContract } from 'kibana/public';
import { Observable } from 'rxjs';
import { SavedObjectsClientContract, CoreTheme } from 'kibana/public';
import { KibanaThemeProvider } from './shared_imports';
import { App, AppDeps } from './app';
import { setHttpClient, setSavedObjectsClient } from './lib/api';
@ -16,17 +18,20 @@ interface BootDeps extends AppDeps {
element: HTMLElement;
savedObjects: SavedObjectsClientContract;
I18nContext: any;
theme$: Observable<CoreTheme>;
}
export const renderApp = (bootDeps: BootDeps) => {
const { I18nContext, element, savedObjects, ...appDeps } = bootDeps;
const { I18nContext, element, savedObjects, theme$, ...appDeps } = bootDeps;
setHttpClient(appDeps.http);
setSavedObjectsClient(savedObjects);
render(
<I18nContext>
<App {...appDeps} />
<KibanaThemeProvider theme$={theme$}>
<App {...appDeps} />
</KibanaThemeProvider>
</I18nContext>,
element
);

View file

@ -10,6 +10,7 @@ export type {
SendRequestResponse,
UseRequestConfig,
} from '../../../../../src/plugins/es_ui_shared/public';
export {
sendRequest,
useRequest,
@ -17,3 +18,5 @@ export {
PageError,
EuiCodeEditor,
} from '../../../../../src/plugins/es_ui_shared/public';
export { KibanaThemeProvider } from '../../../../../src/plugins/kibana_react/public';

View file

@ -42,7 +42,7 @@ export class WatcherUIPlugin implements Plugin<void, void, Dependencies, any> {
id: 'watcher',
title: pluginName,
order: 3,
mount: async ({ element, setBreadcrumbs, history }) => {
mount: async ({ element, setBreadcrumbs, history, theme$ }) => {
const [coreStart] = await getStartServices();
const {
chrome: { docTitle },
@ -73,6 +73,7 @@ export class WatcherUIPlugin implements Plugin<void, void, Dependencies, any> {
createTimeBuckets: () => new TimeBuckets(uiSettings, data),
history,
getUrlForApp: application.getUrlForApp,
theme$,
});
return () => {