[Fleet] Remove usage of deprecated modules for mounting React (#182064)

## Summary

Partially addresses https://github.com/elastic/kibana-team/issues/805

These changes come up from searching in the code and finding where
certain kinds of deprecated AppEx-SharedUX modules are imported.
**Reviewers: Please interact with critical paths through the UI
components touched in this PR, ESPECIALLY in terms of testing dark mode
and i18n.**

This PR focuses on code within the **Fleet** domain.

<img width="1196" alt="image"
src="7f8d3707-94f0-4746-8dd5-dd858ce027f9">

Note: this also makes inclusion of `i18n` and `analytics` dependencies
consistent. Analytics is an optional dependency for the SharedUX
modules, which wrap `KibanaErrorBoundaryProvider` and is designed to
capture telemetry about errors that are caught in the error boundary.

### Checklist

Delete any items that are not applicable to this PR.

- [x] [Unit or functional
tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)
were updated or added to match the most common scenarios
- [ ] This renders correctly on smaller devices using a responsive
layout. (You can test this [in your
browser](https://www.browserstack.com/guide/responsive-testing-on-local-server))
- [ ] This was checked for [cross-browser
compatibility](https://www.elastic.co/support/matrix#matrix_browsers)
This commit is contained in:
Tim Sullivan 2024-05-03 09:15:43 -07:00 committed by GitHub
parent 72ac7413c9
commit 81cab806c8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
18 changed files with 171 additions and 202 deletions

View file

@ -7,10 +7,11 @@
import React, { memo, useEffect, useState } from 'react';
import type { AppMountParameters } from '@kbn/core/public';
import { EuiErrorBoundary, EuiPortal } from '@elastic/eui';
import { EuiPortal } from '@elastic/eui';
import type { History } from 'history';
import { Redirect, useRouteMatch } from 'react-router-dom';
import { Router, Routes, Route } from '@kbn/shared-ux-router';
import { KibanaRenderContextProvider } from '@kbn/react-kibana-context-render';
import { FormattedMessage } from '@kbn/i18n-react';
import { i18n } from '@kbn/i18n';
import useObservable from 'react-use/lib/useObservable';
@ -19,8 +20,6 @@ import { ReactQueryDevtools } from '@tanstack/react-query-devtools';
import type { TopNavMenuData } from '@kbn/navigation-plugin/public';
import { KibanaThemeProvider } from '@kbn/kibana-react-plugin/public';
import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public';
import { RedirectAppLinks } from '@kbn/shared-ux-link-redirect-app';
import { EuiThemeProvider } from '@kbn/kibana-react-plugin/common';
@ -171,7 +170,6 @@ export const FleetAppContext: React.FC<{
history: AppMountParameters['history'];
kibanaVersion: string;
extensions: UIExtensionsStorage;
theme$: AppMountParameters['theme$'];
/** For testing purposes only */
routerHistory?: History<any>;
fleetStatus?: FleetStatusProviderProps;
@ -184,49 +182,41 @@ export const FleetAppContext: React.FC<{
history,
kibanaVersion,
extensions,
routerHistory,
theme$,
routerHistory: _routerHistory,
fleetStatus,
}) => {
const darkModeObservable = useObservable(theme$);
const darkModeObservable = useObservable(startServices.theme.theme$);
const isDarkMode = darkModeObservable && darkModeObservable.darkMode;
return (
<RedirectAppLinks
coreStart={{
application: startServices.application,
}}
>
<startServices.i18n.Context>
<KibanaContextProvider services={{ ...startServices, theme: { theme$ } }}>
<EuiErrorBoundary>
<ConfigContext.Provider value={config}>
<KibanaVersionContext.Provider value={kibanaVersion}>
<KibanaThemeProvider theme$={theme$}>
<EuiThemeProvider darkMode={isDarkMode}>
<QueryClientProvider client={queryClient}>
<ReactQueryDevtools initialIsOpen={false} />
<UIExtensionsContext.Provider value={extensions}>
<FleetStatusProvider defaultFleetStatus={fleetStatus}>
<Router history={history}>
<PackageInstallProvider
notifications={startServices.notifications}
theme$={theme$}
>
<FlyoutContextProvider>{children}</FlyoutContextProvider>
</PackageInstallProvider>
</Router>
</FleetStatusProvider>
</UIExtensionsContext.Provider>
</QueryClientProvider>
</EuiThemeProvider>
</KibanaThemeProvider>
</KibanaVersionContext.Provider>
</ConfigContext.Provider>
</EuiErrorBoundary>
<KibanaRenderContextProvider {...startServices}>
<RedirectAppLinks
coreStart={{
application: startServices.application,
}}
>
<KibanaContextProvider services={{ ...startServices }}>
<ConfigContext.Provider value={config}>
<KibanaVersionContext.Provider value={kibanaVersion}>
<EuiThemeProvider darkMode={isDarkMode}>
<QueryClientProvider client={queryClient}>
<ReactQueryDevtools initialIsOpen={false} />
<UIExtensionsContext.Provider value={extensions}>
<FleetStatusProvider defaultFleetStatus={fleetStatus}>
<Router history={history}>
<PackageInstallProvider startServices={startServices}>
<FlyoutContextProvider>{children}</FlyoutContextProvider>
</PackageInstallProvider>
</Router>
</FleetStatusProvider>
</UIExtensionsContext.Provider>
</QueryClientProvider>
</EuiThemeProvider>
</KibanaVersionContext.Provider>
</ConfigContext.Provider>
</KibanaContextProvider>
</startServices.i18n.Context>
</RedirectAppLinks>
</RedirectAppLinks>
</KibanaRenderContextProvider>
);
}
);

View file

@ -39,7 +39,6 @@ interface FleetAppProps {
kibanaVersion: string;
extensions: UIExtensionsStorage;
setHeaderActionMenu: AppMountParameters['setHeaderActionMenu'];
theme$: AppMountParameters['theme$'];
}
const FleetApp = ({
startServices,
@ -48,7 +47,6 @@ const FleetApp = ({
kibanaVersion,
extensions,
setHeaderActionMenu,
theme$,
}: FleetAppProps) => {
return (
<FleetAppContext
@ -57,7 +55,6 @@ const FleetApp = ({
history={history}
kibanaVersion={kibanaVersion}
extensions={extensions}
theme$={theme$}
>
<WithPermissionsAndSetup>
<AppRoutes setHeaderActionMenu={setHeaderActionMenu} />
@ -68,7 +65,7 @@ const FleetApp = ({
export function renderApp(
startServices: FleetStartServices,
{ element, history, setHeaderActionMenu, theme$ }: AppMountParameters,
{ element, history, setHeaderActionMenu }: AppMountParameters,
config: FleetConfigType,
kibanaVersion: string,
extensions: UIExtensionsStorage
@ -81,7 +78,6 @@ export function renderApp(
kibanaVersion={kibanaVersion}
extensions={extensions}
setHeaderActionMenu={setHeaderActionMenu}
theme$={theme$}
/>,
element
);

View file

@ -355,7 +355,7 @@ describe('edit package policy page', () => {
render();
await waitFor(() => {
expect(renderResult.getByTestId('euiErrorBoundary')).toBeVisible();
expect(renderResult.getByTestId('errorBoundaryFatalHeader')).toBeVisible();
});
});

View file

@ -7,7 +7,7 @@
import React, { memo } from 'react';
import type { AppMountParameters } from '@kbn/core/public';
import { EuiErrorBoundary, EuiPortal } from '@elastic/eui';
import { EuiPortal } from '@elastic/eui';
import type { History } from 'history';
import { Redirect } from 'react-router-dom';
import { Router, Routes, Route } from '@kbn/shared-ux-router';
@ -16,11 +16,10 @@ import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { ReactQueryDevtools } from '@tanstack/react-query-devtools';
import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public';
import { KibanaRenderContextProvider } from '@kbn/react-kibana-context-render';
import { RedirectAppLinks } from '@kbn/shared-ux-link-redirect-app';
import { EuiThemeProvider } from '@kbn/kibana-react-plugin/common';
import { KibanaThemeProvider } from '@kbn/kibana-react-plugin/public';
import type { FleetConfigType, FleetStartServices } from '../../plugin';
import {
@ -59,7 +58,6 @@ export const IntegrationsAppContext: React.FC<{
kibanaVersion: string;
extensions: UIExtensionsStorage;
setHeaderActionMenu: AppMountParameters['setHeaderActionMenu'];
theme$: AppMountParameters['theme$'];
/** For testing purposes only */
routerHistory?: History<any>; // TODO remove
fleetStatus?: FleetStatusProviderProps;
@ -73,59 +71,53 @@ export const IntegrationsAppContext: React.FC<{
kibanaVersion,
extensions,
setHeaderActionMenu,
theme$,
fleetStatus,
}) => {
const theme = useObservable(theme$);
const theme = useObservable(startServices.theme.theme$);
const isDarkMode = theme && theme.darkMode;
const CloudContext = startServices.cloud?.CloudContextProvider || EmptyContext;
return (
<RedirectAppLinks
coreStart={{
application: startServices.application,
}}
>
<startServices.i18n.Context>
<KibanaRenderContextProvider {...startServices}>
<RedirectAppLinks
coreStart={{
application: startServices.application,
}}
>
<KibanaContextProvider services={{ ...startServices }}>
<EuiErrorBoundary>
<ConfigContext.Provider value={config}>
<KibanaVersionContext.Provider value={kibanaVersion}>
<KibanaThemeProvider theme$={theme$}>
<EuiThemeProvider darkMode={isDarkMode}>
<QueryClientProvider client={queryClient}>
<ReactQueryDevtools initialIsOpen={false} />
<UIExtensionsContext.Provider value={extensions}>
<FleetStatusProvider defaultFleetStatus={fleetStatus}>
<startServices.customIntegrations.ContextProvider>
<CloudContext>
<Router history={history}>
<AgentPolicyContextProvider>
<PackageInstallProvider
notifications={startServices.notifications}
theme$={theme$}
>
<FlyoutContextProvider>
<IntegrationsHeader {...{ setHeaderActionMenu, theme$ }} />
{children}
</FlyoutContextProvider>
</PackageInstallProvider>
</AgentPolicyContextProvider>
</Router>
</CloudContext>
</startServices.customIntegrations.ContextProvider>
</FleetStatusProvider>
</UIExtensionsContext.Provider>
</QueryClientProvider>
</EuiThemeProvider>
</KibanaThemeProvider>
</KibanaVersionContext.Provider>
</ConfigContext.Provider>
</EuiErrorBoundary>
<ConfigContext.Provider value={config}>
<KibanaVersionContext.Provider value={kibanaVersion}>
<EuiThemeProvider darkMode={isDarkMode}>
<QueryClientProvider client={queryClient}>
<ReactQueryDevtools initialIsOpen={false} />
<UIExtensionsContext.Provider value={extensions}>
<FleetStatusProvider defaultFleetStatus={fleetStatus}>
<startServices.customIntegrations.ContextProvider>
<CloudContext>
<Router history={history}>
<AgentPolicyContextProvider>
<PackageInstallProvider startServices={startServices}>
<FlyoutContextProvider>
<IntegrationsHeader
{...{ setHeaderActionMenu, startServices }}
/>
{children}
</FlyoutContextProvider>
</PackageInstallProvider>
</AgentPolicyContextProvider>
</Router>
</CloudContext>
</startServices.customIntegrations.ContextProvider>
</FleetStatusProvider>
</UIExtensionsContext.Provider>
</QueryClientProvider>
</EuiThemeProvider>
</KibanaVersionContext.Provider>
</ConfigContext.Provider>
</KibanaContextProvider>
</startServices.i18n.Context>
</RedirectAppLinks>
</RedirectAppLinks>
</KibanaRenderContextProvider>
);
}
);

View file

@ -10,18 +10,20 @@ import { EuiHeaderSectionItem, EuiHeaderSection, EuiHeaderLinks } from '@elastic
import type { AppMountParameters } from '@kbn/core/public';
import type { FleetStartServices } from '../../../../plugin';
import { HeaderPortal } from './header_portal';
import { DeploymentDetails } from './deployment_details';
export const IntegrationsHeader = ({
setHeaderActionMenu,
theme$,
startServices,
}: {
setHeaderActionMenu: AppMountParameters['setHeaderActionMenu'];
theme$: AppMountParameters['theme$'];
startServices: Pick<FleetStartServices, 'analytics' | 'i18n' | 'theme'>;
}) => {
return (
<HeaderPortal {...{ setHeaderActionMenu, theme$ }}>
<HeaderPortal {...{ setHeaderActionMenu, startServices }}>
<EuiHeaderSection grow={false}>
<EuiHeaderSectionItem>
<EuiHeaderLinks>

View file

@ -10,20 +10,22 @@ import type { FC } from 'react';
import React, { useEffect, useMemo } from 'react';
import { createHtmlPortalNode, InPortal, OutPortal } from 'react-reverse-portal';
import { toMountPoint } from '@kbn/kibana-react-plugin/public';
import { toMountPoint } from '@kbn/react-kibana-mount';
import type { FleetStartServices } from '../../../../plugin';
export interface Props {
children: React.ReactNode;
setHeaderActionMenu: AppMountParameters['setHeaderActionMenu'];
theme$: AppMountParameters['theme$'];
startServices: Pick<FleetStartServices, 'analytics' | 'i18n' | 'theme'>;
}
export const HeaderPortal: FC<Props> = ({ children, setHeaderActionMenu, theme$ }) => {
export const HeaderPortal: FC<Props> = ({ children, setHeaderActionMenu, startServices }) => {
const portalNode = useMemo(() => createHtmlPortalNode(), []);
useEffect(() => {
setHeaderActionMenu((element) => {
const mount = toMountPoint(<OutPortal node={portalNode} />, { theme$ });
const mount = toMountPoint(<OutPortal node={portalNode} />, startServices);
return mount(element);
});
@ -31,7 +33,7 @@ export const HeaderPortal: FC<Props> = ({ children, setHeaderActionMenu, theme$
portalNode.unmount();
setHeaderActionMenu(undefined);
};
}, [portalNode, setHeaderActionMenu, theme$]);
}, [portalNode, setHeaderActionMenu, startServices]);
return <InPortal node={portalNode}>{children}</InPortal>;
};

View file

@ -5,8 +5,8 @@
* 2.0.
*/
import type { DocLinksStart, OverlayStart } from '@kbn/core/public';
import { toMountPoint } from '@kbn/kibana-react-plugin/public';
import type { CoreStart } from '@kbn/core/public';
import { toMountPoint } from '@kbn/react-kibana-mount';
import React, { useCallback } from 'react';
@ -15,15 +15,13 @@ import { ConfirmForceInstallModal } from '../components';
const confirmForceInstall = ({
pkg,
overlays,
docLinks,
core,
}: {
pkg: { name: string; version: string };
overlays: OverlayStart;
docLinks: DocLinksStart;
core: CoreStart;
}): Promise<boolean> =>
new Promise((resolve) => {
const session = overlays.openModal(
const session = core.overlays.openModal(
toMountPoint(
<ConfirmForceInstallModal
pkg={pkg}
@ -35,17 +33,18 @@ const confirmForceInstall = ({
session.close();
resolve(false);
}}
docLinks={docLinks}
/>
docLinks={core.docLinks}
/>,
core
)
);
});
export const useConfirmForceInstall = () => {
const { overlays, docLinks } = useStartServices();
const core = useStartServices();
return useCallback(
(pkg: { name: string; version: string }) => confirmForceInstall({ pkg, overlays, docLinks }),
[docLinks, overlays]
(pkg: { name: string; version: string }) => confirmForceInstall({ pkg, core }),
[core]
);
};

View file

@ -5,26 +5,31 @@
* 2.0.
*/
import type { DocLinksStart, OverlayStart } from '@kbn/core/public';
import { toMountPoint } from '@kbn/kibana-react-plugin/public';
import { toMountPoint } from '@kbn/react-kibana-mount';
import React, { useCallback } from 'react';
// Direct imports are important here, importing all hooks breaks unit tests
// and increases bundle size because this is imported on first page load
import type { FleetStartServices } from '../../../plugin';
import { useStartServices } from '../../../hooks/use_core';
import { ConfirmOpenUnverifiedModal } from '../components/confirm_open_unverified_modal';
type StartServicesConfirmOpen = Pick<
FleetStartServices,
'docLinks' | 'overlays' | 'analytics' | 'i18n' | 'theme'
>;
const confirmOpenUnverified = ({
pkgName,
overlays,
docLinks,
fleetServices,
}: {
pkgName: string;
overlays: OverlayStart;
docLinks: DocLinksStart;
fleetServices: StartServicesConfirmOpen;
}): Promise<boolean> =>
new Promise((resolve) => {
const { overlays, docLinks, ...startServices } = fleetServices;
const session = overlays.openModal(
toMountPoint(
<ConfirmOpenUnverifiedModal
@ -38,16 +43,17 @@ const confirmOpenUnverified = ({
resolve(false);
}}
docLinks={docLinks}
/>
/>,
startServices
)
);
});
export const useConfirmOpenUnverified = () => {
const { overlays, docLinks } = useStartServices();
const fleetServices = useStartServices();
return useCallback(
(pkgName: string) => confirmOpenUnverified({ pkgName, overlays, docLinks }),
[docLinks, overlays]
(pkgName: string) => confirmOpenUnverified({ pkgName, fleetServices }),
[fleetServices]
);
};

View file

@ -7,14 +7,22 @@
import React from 'react';
import { act, type WrapperComponent } from '@testing-library/react-hooks';
import { coreMock } from '@kbn/core/public/mocks';
import { createIntegrationsTestRendererMock } from '../../../mock';
import { useInstallPackage, PackageInstallProvider } from './use_package_install';
describe('usePackageInstall', () => {
const coreStart = coreMock.createStart();
const addErrorSpy = jest.spyOn(coreStart.notifications.toasts, 'addError');
const addSuccessSpy = jest.spyOn(coreStart.notifications.toasts, 'addSuccess');
beforeEach(() => {
createIntegrationsTestRendererMock();
addErrorSpy.mockReset();
addSuccessSpy.mockReset();
});
describe('useInstallPackage', () => {
@ -40,14 +48,8 @@ describe('usePackageInstall', () => {
throw error;
}) as any);
const notifications = renderer.startServices.notifications;
const wrapper: WrapperComponent<any> = ({ children }) => (
<PackageInstallProvider
notifications={notifications}
theme$={renderer.startServices.theme.theme$}
>
{children}
</PackageInstallProvider>
<PackageInstallProvider startServices={coreStart}>{children}</PackageInstallProvider>
);
const { result } = renderer.renderHook(() => useInstallPackage(), wrapper);
@ -55,12 +57,11 @@ describe('usePackageInstall', () => {
return {
installPackage,
notifications,
};
}
it('should work for install', async () => {
const { notifications, installPackage } = createRenderer();
const { installPackage } = createRenderer();
let res: boolean | undefined;
await act(async () => {
res = await installPackage({
@ -70,14 +71,14 @@ describe('usePackageInstall', () => {
});
});
expect(notifications.toasts.addError).not.toBeCalled();
expect(notifications.toasts.addSuccess).toBeCalled();
expect(addErrorSpy).not.toBeCalled();
expect(addSuccessSpy).toBeCalled();
expect(res).toBeTruthy();
});
it('should work for upgrade', async () => {
const { notifications, installPackage } = createRenderer();
const { installPackage } = createRenderer();
let res: boolean | undefined;
await act(async () => {
res = await installPackage({
@ -88,14 +89,14 @@ describe('usePackageInstall', () => {
});
});
expect(notifications.toasts.addError).not.toBeCalled();
expect(notifications.toasts.addSuccess).toBeCalled();
expect(addErrorSpy).not.toBeCalled();
expect(addSuccessSpy).toBeCalled();
expect(res).toBeTruthy();
});
it('should handle install error', async () => {
const { notifications, installPackage } = createRenderer();
const { installPackage } = createRenderer();
let res: boolean | undefined;
await act(async () => {
@ -106,8 +107,8 @@ describe('usePackageInstall', () => {
});
});
expect(notifications.toasts.addSuccess).not.toBeCalled();
expect(notifications.toasts.addError).toBeCalled();
expect(addSuccessSpy).not.toBeCalled();
expect(addErrorSpy).toBeCalled();
expect(res).toBeFalsy();
});

View file

@ -13,13 +13,10 @@ import React, { useCallback, useState } from 'react';
import { useHistory } from 'react-router-dom';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n-react';
import type { NotificationsStart } from '@kbn/core/public';
import type { Observable } from 'rxjs';
import type { CoreTheme } from '@kbn/core/public';
import { toMountPoint } from '@kbn/kibana-react-plugin/public';
import { toMountPoint } from '@kbn/react-kibana-mount';
import type { PackageInfo } from '../../../types';
import type { FleetStartServices } from '../../../plugin';
import { sendInstallPackage, sendRemovePackage, useLink } from '../../../hooks';
import { InstallStatus } from '../../../types';
@ -27,6 +24,8 @@ import { isVerificationError } from '../services';
import { useConfirmForceInstall } from '.';
type StartServices = Pick<FleetStartServices, 'notifications' | 'analytics' | 'i18n' | 'theme'>;
interface PackagesInstall {
[key: string]: PackageInstallItem;
}
@ -43,13 +42,7 @@ type InstallPackageProps = Pick<PackageInfo, 'name' | 'version' | 'title'> & {
};
type SetPackageInstallStatusProps = Pick<PackageInfo, 'name'> & PackageInstallItem;
function usePackageInstall({
notifications,
theme$,
}: {
notifications: NotificationsStart;
theme$: Observable<CoreTheme>;
}) {
function usePackageInstall({ startServices }: { startServices: StartServices }) {
const history = useHistory();
const { getPath } = useLink();
const [packages, setPackage] = useState<PackagesInstall>({});
@ -68,6 +61,8 @@ function usePackageInstall({
[]
);
const { notifications } = startServices;
const getPackageInstallStatus = useCallback(
(pkg: string): PackageInstallItem => {
return packages[pkg];
@ -115,7 +110,7 @@ function usePackageInstall({
defaultMessage="Reinstalled {title}"
values={{ title }}
/>,
{ theme$ }
startServices
),
text: toMountPoint(
<FormattedMessage
@ -123,7 +118,7 @@ function usePackageInstall({
defaultMessage="Successfully reinstalled {title}"
values={{ title }}
/>,
{ theme$ }
startServices
),
});
} else if (isUpgrade) {
@ -134,7 +129,7 @@ function usePackageInstall({
defaultMessage="Upgraded {title}"
values={{ title }}
/>,
{ theme$ }
startServices
),
text: toMountPoint(
<FormattedMessage
@ -142,7 +137,7 @@ function usePackageInstall({
defaultMessage="Successfully upgraded {title}"
values={{ title }}
/>,
{ theme$ }
startServices
),
});
} else {
@ -153,7 +148,7 @@ function usePackageInstall({
defaultMessage="Installed {title}"
values={{ title }}
/>,
{ theme$ }
startServices
),
text: toMountPoint(
<FormattedMessage
@ -161,7 +156,7 @@ function usePackageInstall({
defaultMessage="Successfully installed {title}"
values={{ title }}
/>,
{ theme$ }
startServices
),
});
}
@ -192,14 +187,7 @@ function usePackageInstall({
return true;
},
// eslint-disable-next-line react-hooks/exhaustive-deps
[
getPackageInstallStatus,
setPackageInstallStatus,
notifications.toasts,
theme$,
getPath,
history,
]
[getPackageInstallStatus, setPackageInstallStatus, startServices, getPath, history]
);
const uninstallPackage = useCallback(
@ -221,14 +209,14 @@ function usePackageInstall({
defaultMessage="Failed to uninstall {title} package"
values={{ title }}
/>,
{ theme$ }
startServices
),
text: toMountPoint(
<FormattedMessage
id="xpack.fleet.integrations.packageUninstallErrorDescription"
defaultMessage="Something went wrong while trying to uninstall this package. Please try again later."
/>,
{ theme$ }
startServices
),
iconType: 'error',
});
@ -242,7 +230,7 @@ function usePackageInstall({
defaultMessage="Uninstalled {title}"
values={{ title }}
/>,
{ theme$ }
startServices
),
text: toMountPoint(
<FormattedMessage
@ -250,7 +238,7 @@ function usePackageInstall({
defaultMessage="Successfully uninstalled {title}"
values={{ title }}
/>,
{ theme$ }
startServices
),
});
if (redirectToVersion !== version) {
@ -261,7 +249,7 @@ function usePackageInstall({
}
}
},
[notifications.toasts, setPackageInstallStatus, getPath, history, theme$]
[notifications.toasts, setPackageInstallStatus, getPath, history, startServices]
);
return {

View file

@ -40,7 +40,6 @@ interface IntegrationsAppProps {
kibanaVersion: string;
extensions: UIExtensionsStorage;
setHeaderActionMenu: AppMountParameters['setHeaderActionMenu'];
theme$: AppMountParameters['theme$'];
}
const IntegrationsApp = ({
basepath,
@ -50,7 +49,6 @@ const IntegrationsApp = ({
kibanaVersion,
extensions,
setHeaderActionMenu,
theme$,
}: IntegrationsAppProps) => {
return (
<IntegrationsAppContext
@ -61,7 +59,6 @@ const IntegrationsApp = ({
kibanaVersion={kibanaVersion}
extensions={extensions}
setHeaderActionMenu={setHeaderActionMenu}
theme$={theme$}
>
<AppRoutes />
</IntegrationsAppContext>
@ -70,7 +67,7 @@ const IntegrationsApp = ({
export function renderApp(
startServices: FleetStartServices,
{ element, appBasePath, history, setHeaderActionMenu, theme$ }: AppMountParameters,
{ element, appBasePath, history, setHeaderActionMenu }: AppMountParameters,
config: FleetConfigType,
kibanaVersion: string,
extensions: UIExtensionsStorage,
@ -86,7 +83,6 @@ export function renderApp(
kibanaVersion={kibanaVersion}
extensions={extensions}
setHeaderActionMenu={setHeaderActionMenu}
theme$={theme$}
/>
</UsageTracker>,
element

View file

@ -783,7 +783,7 @@ export function Detail() {
/>
</Route>
<Route path={INTEGRATIONS_ROUTING_PATHS.integration_details_settings}>
<SettingsPage packageInfo={packageInfo} theme$={services.theme.theme$} />
<SettingsPage packageInfo={packageInfo} startServices={services} />
</Route>
<Route path={INTEGRATIONS_ROUTING_PATHS.integration_details_assets}>
<AssetsPage packageInfo={packageInfo} refetchPackageInfo={refetchPackageInfo} />

View file

@ -23,14 +23,12 @@ import {
import { i18n } from '@kbn/i18n';
import type { Observable } from 'rxjs';
import type { CoreTheme } from '@kbn/core/public';
import {
getNumTransformAssets,
TransformInstallWithCurrentUserPermissionCallout,
} from '../../../../../../../components/transform_install_as_current_user_callout';
import type { FleetStartServices } from '../../../../../../../plugin';
import type { PackageInfo } from '../../../../../types';
import { InstallStatus } from '../../../../../types';
import {
@ -117,10 +115,10 @@ const LatestVersionLink = ({ name, version }: { name: string; version: string })
interface Props {
packageInfo: PackageInfo;
theme$: Observable<CoreTheme>;
startServices: Pick<FleetStartServices, 'analytics' | 'i18n' | 'theme'>;
}
export const SettingsPage: React.FC<Props> = memo(({ packageInfo, theme$ }: Props) => {
export const SettingsPage: React.FC<Props> = memo(({ packageInfo, startServices }: Props) => {
const { name, title, latestVersion, version, keepPoliciesUpToDate } = packageInfo;
const [isUpgradingPackagePolicies, setIsUpgradingPackagePolicies] = useState<boolean>(false);
const [isChangelogModalOpen, setIsChangelogModalOpen] = useState(false);
@ -339,7 +337,7 @@ export const SettingsPage: React.FC<Props> = memo(({ packageInfo, theme$ }: Prop
dryRunData={dryRunData}
isUpgradingPackagePolicies={isUpgradingPackagePolicies}
setIsUpgradingPackagePolicies={setIsUpgradingPackagePolicies}
theme$={theme$}
startServices={startServices}
/>
</p>
</>

View file

@ -18,11 +18,10 @@ import {
EuiConfirmModal,
EuiSpacer,
} from '@elastic/eui';
import type { Observable } from 'rxjs';
import type { CoreTheme } from '@kbn/core/public';
import { toMountPoint } from '@kbn/kibana-react-plugin/public';
import { toMountPoint } from '@kbn/react-kibana-mount';
import type { FleetStartServices } from '../../../../../../../plugin';
import type {
PackageInfo,
UpgradePackagePolicyDryRunResponse,
@ -45,7 +44,7 @@ interface UpdateButtonProps extends Pick<PackageInfo, 'name' | 'title' | 'versio
agentPolicyIds: string[];
isUpgradingPackagePolicies?: boolean;
setIsUpgradingPackagePolicies?: React.Dispatch<React.SetStateAction<boolean>>;
theme$: Observable<CoreTheme>;
startServices: Pick<FleetStartServices, 'analytics' | 'i18n' | 'theme'>;
}
/*
@ -77,7 +76,7 @@ export const UpdateButton: React.FunctionComponent<UpdateButtonProps> = ({
setIsUpgradingPackagePolicies = () => {},
title,
version,
theme$,
startServices,
}) => {
const history = useHistory();
const { getPath } = useLink();
@ -185,7 +184,7 @@ export const UpdateButton: React.FunctionComponent<UpdateButtonProps> = ({
defaultMessage="Updated {title} and upgraded policies"
values={{ title }}
/>,
{ theme$ }
startServices
),
text: toMountPoint(
<FormattedMessage
@ -193,7 +192,7 @@ export const UpdateButton: React.FunctionComponent<UpdateButtonProps> = ({
defaultMessage="Successfully updated {title} and upgraded policies"
values={{ title }}
/>,
{ theme$ }
startServices
),
});
@ -230,7 +229,7 @@ export const UpdateButton: React.FunctionComponent<UpdateButtonProps> = ({
packagePolicyIds,
dryRunData,
notifications.toasts,
theme$,
startServices,
navigateToNewSettingsPage,
]);

View file

@ -12,7 +12,8 @@ import type { EuiButtonEmptyProps } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n-react';
import { ViewApiRequestFlyout } from '@kbn/es-ui-shared-plugin/public';
import { KibanaContextProvider, toMountPoint } from '@kbn/kibana-react-plugin/public';
import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public';
import { toMountPoint } from '@kbn/react-kibana-mount';
import { useStartServices } from '../../hooks';
@ -41,7 +42,7 @@ export const DevtoolsRequestFlyoutButton: React.FunctionComponent<
description={description}
/>
</KibanaContextProvider>,
{ theme$: services.theme.theme$ }
services
)
);

View file

@ -15,8 +15,6 @@ import type { RenderHookResult } from '@testing-library/react-hooks';
import { Router } from '@kbn/shared-ux-router';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { themeServiceMock } from '@kbn/core/public/mocks';
import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public';
import type { ScopedHistory } from '@kbn/core/public';
import { CoreScopedHistory } from '@kbn/core/public';
@ -103,7 +101,6 @@ export const createFleetTestRendererMock = (): TestRenderer => {
kibanaVersion={testRendererMocks.kibanaVersion}
extensions={extensions}
routerHistory={testRendererMocks.history}
theme$={themeServiceMock.createTheme$()}
fleetStatus={{
enabled: true,
isLoading: false,
@ -167,7 +164,6 @@ export const createIntegrationsTestRendererMock = (): TestRenderer => {
kibanaVersion={testRendererMocks.kibanaVersion}
extensions={extensions}
routerHistory={testRendererMocks.history}
theme$={themeServiceMock.createTheme$()}
setHeaderActionMenu={() => {}}
fleetStatus={{
enabled: true,

View file

@ -51,6 +51,8 @@ import type { GuidedOnboardingPluginStart } from '@kbn/guided-onboarding-plugin/
import type { DashboardStart } from '@kbn/dashboard-plugin/public';
import { Subject } from 'rxjs';
import type { FleetAuthz } from '../common';
import { appRoutesService, INTEGRATIONS_PLUGIN_ID, PLUGIN_ID, setupRouteService } from '../common';
import {
@ -85,7 +87,6 @@ import type {
import { LazyCustomLogsAssetsExtension } from './lazy_custom_logs_assets_extension';
import { setCustomIntegrations, setCustomIntegrationsStart } from './services/custom_integrations';
import { getFleetDeepLinks } from './deep_links';
import { Subject } from 'rxjs';
export type { FleetConfigType } from '../common/types';
@ -193,7 +194,7 @@ export class FleetPlugin implements Plugin<FleetSetup, FleetStart, FleetSetupDep
...startDepsServices,
storage: this.storage,
cloud,
authz: await fleetStart.authz,
authz: fleetStart.authz,
};
const { renderApp, teardownIntegrations } = await import('./applications/integrations');
@ -236,7 +237,7 @@ export class FleetPlugin implements Plugin<FleetSetup, FleetStart, FleetSetupDep
...startDepsServices,
storage: this.storage,
cloud,
authz: await fleetStart.authz,
authz: fleetStart.authz,
};
const { renderApp, teardownFleet } = await import('./applications/fleet');
const unmount = renderApp(startServices, params, config, kibanaVersion, extensions);

View file

@ -106,5 +106,7 @@
"@kbn/code-editor",
"@kbn/core-test-helpers-model-versions",
"@kbn/zod-helpers",
"@kbn/react-kibana-mount",
"@kbn/react-kibana-context-render",
]
}