mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 09:19:04 -04:00
[SecuritySolution] Get started page (#158461)
This commit is contained in:
parent
96e4a83dcb
commit
3bf3e13bc6
11 changed files with 204 additions and 7 deletions
|
@ -69,6 +69,7 @@
|
|||
"xpack.server": "legacy/server",
|
||||
"xpack.serverless": "plugins/serverless",
|
||||
"xpack.serverlessSearch": "plugins/serverless_search",
|
||||
"xpack.serverlessSecurity": "plugins/serverless_security",
|
||||
"xpack.securitySolution": "plugins/security_solution",
|
||||
"xpack.sessionView": "plugins/session_view",
|
||||
"xpack.snapshotRestore": "plugins/snapshot_restore",
|
||||
|
|
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
import React from 'react';
|
||||
import { render } from '@testing-library/react';
|
||||
import { LandingPage } from './landing';
|
||||
import { useKibana } from '../../common/lib/kibana';
|
||||
import { Router } from 'react-router-dom';
|
||||
import { createBrowserHistory } from 'history';
|
||||
import { TestProviders } from '../../common/mock/test_providers';
|
||||
|
||||
jest.mock('../../common/lib/kibana', () => ({
|
||||
useKibana: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.mock('../../common/components/landing_page', () => ({
|
||||
LandingPageComponent: jest
|
||||
.fn()
|
||||
.mockReturnValue(<div data-test-subj="default-get-started-page" />),
|
||||
}));
|
||||
|
||||
describe('LandingPage', () => {
|
||||
const mockGetStartedComponent = jest.fn();
|
||||
const history = createBrowserHistory();
|
||||
const mockSecuritySolutionTemplateWrapper = jest
|
||||
.fn()
|
||||
.mockImplementation(({ children }) => <div>{children}</div>);
|
||||
|
||||
const renderPage = () =>
|
||||
render(
|
||||
<Router history={history}>
|
||||
<LandingPage />
|
||||
</Router>,
|
||||
{ wrapper: TestProviders }
|
||||
);
|
||||
|
||||
beforeAll(() => {
|
||||
(useKibana as jest.Mock).mockReturnValue({
|
||||
services: {
|
||||
securityLayout: {
|
||||
getPluginWrapper: jest.fn().mockReturnValue(mockSecuritySolutionTemplateWrapper),
|
||||
},
|
||||
getStartedComponent: mockGetStartedComponent,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
it('renders the default component', () => {
|
||||
const { queryByTestId } = renderPage();
|
||||
expect(queryByTestId('default-get-started-page')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('renders the get started component', () => {
|
||||
mockGetStartedComponent.mockReturnValue(<div data-test-subj="get-started" />);
|
||||
const { queryByTestId } = renderPage();
|
||||
|
||||
expect(queryByTestId('default-get-started-page')).not.toBeInTheDocument();
|
||||
expect(queryByTestId('get-started')).toBeInTheDocument();
|
||||
});
|
||||
});
|
|
@ -5,15 +5,23 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import React, { memo } from 'react';
|
||||
import React, { memo, useMemo } from 'react';
|
||||
import { SpyRoute } from '../../common/utils/route/spy_routes';
|
||||
import { SecurityPageName } from '../../../common/constants';
|
||||
import { LandingPageComponent } from '../../common/components/landing_page';
|
||||
import { useKibana } from '../../common/lib/kibana';
|
||||
import { PluginTemplateWrapper } from '../../common/components/plugin_template_wrapper';
|
||||
|
||||
export const LandingPage = memo(() => {
|
||||
const { getStartedComponent } = useKibana().services;
|
||||
const GetStartedComponent = useMemo(() => getStartedComponent?.(), [getStartedComponent]);
|
||||
return (
|
||||
<>
|
||||
<LandingPageComponent />
|
||||
{GetStartedComponent ?? (
|
||||
<PluginTemplateWrapper>
|
||||
<LandingPageComponent />
|
||||
</PluginTemplateWrapper>
|
||||
)}
|
||||
<SpyRoute pageName={SecurityPageName.landing} />
|
||||
</>
|
||||
);
|
||||
|
|
|
@ -41,11 +41,9 @@ const DetectionResponseRoutes = () => (
|
|||
);
|
||||
|
||||
const LandingRoutes = () => (
|
||||
<PluginTemplateWrapper>
|
||||
<TrackApplicationView viewId={SecurityPageName.landing}>
|
||||
<LandingPage />
|
||||
</TrackApplicationView>
|
||||
</PluginTemplateWrapper>
|
||||
<TrackApplicationView viewId={SecurityPageName.landing}>
|
||||
<LandingPage />
|
||||
</TrackApplicationView>
|
||||
);
|
||||
|
||||
const EntityAnalyticsRoutes = () => (
|
||||
|
|
|
@ -29,6 +29,7 @@ import type {
|
|||
SubPlugins,
|
||||
StartedSubPlugins,
|
||||
StartPluginsDependencies,
|
||||
GetStartedComponent,
|
||||
} from './types';
|
||||
import { initTelemetry, TelemetryService } from './common/lib/telemetry';
|
||||
import { KibanaServices } from './common/lib/kibana/services';
|
||||
|
@ -88,6 +89,7 @@ export class Plugin implements IPlugin<PluginSetup, PluginStart, SetupPlugins, S
|
|||
|
||||
readonly experimentalFeatures: ExperimentalFeatures;
|
||||
private isSidebarEnabled$: BehaviorSubject<boolean>;
|
||||
private getStartedComponent?: GetStartedComponent;
|
||||
|
||||
constructor(private readonly initializerContext: PluginInitializerContext) {
|
||||
this.config = this.initializerContext.config.get<SecuritySolutionUiConfigType>();
|
||||
|
@ -171,6 +173,7 @@ export class Plugin implements IPlugin<PluginSetup, PluginStart, SetupPlugins, S
|
|||
},
|
||||
savedObjectsManagement: startPluginsDeps.savedObjectsManagement,
|
||||
isSidebarEnabled$: this.isSidebarEnabled$,
|
||||
getStartedComponent: this.getStartedComponent,
|
||||
telemetry: this.telemetry.start(),
|
||||
};
|
||||
return services;
|
||||
|
@ -313,6 +316,9 @@ export class Plugin implements IPlugin<PluginSetup, PluginStart, SetupPlugins, S
|
|||
getNavLinks$: () => navLinks$,
|
||||
setIsSidebarEnabled: (isSidebarEnabled: boolean) =>
|
||||
this.isSidebarEnabled$.next(isSidebarEnabled),
|
||||
setGetStartedPage: (getStartedComponent: GetStartedComponent) => {
|
||||
this.getStartedComponent = getStartedComponent;
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -132,6 +132,7 @@ export type StartServices = CoreStart &
|
|||
};
|
||||
savedObjectsManagement: SavedObjectsManagementPluginStart;
|
||||
isSidebarEnabled$: BehaviorSubject<boolean>;
|
||||
getStartedComponent: GetStartedComponent | undefined;
|
||||
telemetry: TelemetryClientStart;
|
||||
};
|
||||
|
||||
|
@ -139,9 +140,15 @@ export interface PluginSetup {
|
|||
resolver: () => Promise<ResolverPluginSetup>;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/consistent-type-definitions
|
||||
export type GetStartedComponentProps = {};
|
||||
|
||||
export type GetStartedComponent = (props?: GetStartedComponentProps) => JSX.Element;
|
||||
|
||||
export interface PluginStart {
|
||||
getNavLinks$: () => Observable<NavigationLink[]>;
|
||||
setIsSidebarEnabled: (isSidebarEnabled: boolean) => void;
|
||||
setGetStartedPage: (getStartedComponent: GetStartedComponent) => void;
|
||||
}
|
||||
|
||||
export interface AppObservableLibs {
|
||||
|
|
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import {
|
||||
EuiCard,
|
||||
EuiFlexGroup,
|
||||
EuiFlexItem,
|
||||
EuiIcon,
|
||||
EuiSpacer,
|
||||
EuiText,
|
||||
EuiTitle,
|
||||
} from '@elastic/eui';
|
||||
import React, { useMemo } from 'react';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { KibanaPageTemplate } from '@kbn/shared-ux-page-kibana-template';
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-interface
|
||||
interface Props {}
|
||||
|
||||
const icons = ['Kibana', 'Kibana', 'Kibana'];
|
||||
|
||||
export const GetStartedComponent: React.FC<Props> = ({}) => {
|
||||
const cardNodes = useMemo(
|
||||
() =>
|
||||
icons.map(function (item, index) {
|
||||
return (
|
||||
<EuiFlexItem key={index}>
|
||||
<EuiCard icon={<EuiIcon size="xxl" type={`logo${item}`} />} title={`Elastic ${item}`} />
|
||||
</EuiFlexItem>
|
||||
);
|
||||
}),
|
||||
[]
|
||||
);
|
||||
return (
|
||||
<KibanaPageTemplate restrictWidth={false}>
|
||||
<KibanaPageTemplate.Header
|
||||
paddingSize="m"
|
||||
pageTitle={i18n.translate('xpack.serverlessSecurity.getStarted.title', {
|
||||
defaultMessage: `Welcome`,
|
||||
})}
|
||||
description={
|
||||
<>
|
||||
<EuiTitle size="xs">
|
||||
<h3>
|
||||
{i18n.translate('xpack.serverlessSecurity.getStarted.subTitle', {
|
||||
defaultMessage: `Let’s get started`,
|
||||
})}
|
||||
</h3>
|
||||
</EuiTitle>
|
||||
<EuiText size="m">
|
||||
{i18n.translate('xpack.serverlessSecurity.getStarted.description', {
|
||||
defaultMessage: `Set up your Elastic Security workspace. Use the toggles below to curate a list of tasks that best fits your environment`,
|
||||
})}
|
||||
</EuiText>
|
||||
</>
|
||||
}
|
||||
>
|
||||
<EuiFlexGroup gutterSize="l">{cardNodes}</EuiFlexGroup>
|
||||
</KibanaPageTemplate.Header>
|
||||
<KibanaPageTemplate.Section>
|
||||
<EuiSpacer size="m" />
|
||||
</KibanaPageTemplate.Section>
|
||||
</KibanaPageTemplate>
|
||||
);
|
||||
};
|
||||
|
||||
export const GetStarted = React.memo(GetStartedComponent);
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import { CoreStart } from '@kbn/core/public';
|
||||
import type { GetStartedComponentProps, GetStartedComponent } from './types';
|
||||
import { GetStarted } from './get_started';
|
||||
import { KibanaServicesProvider } from '../../services';
|
||||
import { ServerlessSecurityPluginStartDependencies } from '../../types';
|
||||
|
||||
export const getSecurityGetStartedComponent = (
|
||||
core: CoreStart,
|
||||
pluginsStart: ServerlessSecurityPluginStartDependencies
|
||||
): GetStartedComponent => {
|
||||
return (_props?: GetStartedComponentProps) => (
|
||||
<KibanaServicesProvider core={core} pluginsStart={pluginsStart}>
|
||||
<GetStarted />
|
||||
</KibanaServicesProvider>
|
||||
);
|
||||
};
|
|
@ -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.
|
||||
*/
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/consistent-type-definitions
|
||||
export type GetStartedComponentProps = {};
|
||||
|
||||
export type GetStartedComponent = (props?: GetStartedComponentProps) => JSX.Element;
|
|
@ -6,6 +6,7 @@
|
|||
*/
|
||||
|
||||
import { CoreSetup, CoreStart, Plugin } from '@kbn/core/public';
|
||||
import { getSecurityGetStartedComponent } from './components/get_started';
|
||||
import { getSecuritySideNavComponent } from './components/side_navigation';
|
||||
import {
|
||||
ServerlessSecurityPluginSetup,
|
||||
|
@ -37,6 +38,7 @@ export class ServerlessSecurityPlugin
|
|||
const { securitySolution, serverless } = startDeps;
|
||||
|
||||
securitySolution.setIsSidebarEnabled(false);
|
||||
securitySolution.setGetStartedPage(getSecurityGetStartedComponent(core, startDeps));
|
||||
serverless.setSideNavComponent(getSecuritySideNavComponent(core, startDeps));
|
||||
|
||||
return {};
|
||||
|
|
|
@ -25,5 +25,7 @@
|
|||
"@kbn/kibana-react-plugin",
|
||||
"@kbn/core-chrome-browser",
|
||||
"@kbn/i18n-react",
|
||||
"@kbn/i18n",
|
||||
"@kbn/shared-ux-page-kibana-template",
|
||||
]
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue