Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[SecuritySolution] Share getStartedPage between ESS and serverless #174867

Merged
merged 28 commits into from
Jan 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
a2511ac
init
angorayc Jan 15, 2024
ccdb648
getStartedPageService
angorayc Jan 16, 2024
c2eef03
ess
angorayc Jan 16, 2024
5cd0568
[CI] Auto-commit changed files from 'node scripts/eslint --no-cache -…
kibanamachine Jan 16, 2024
cf49acf
clean up
angorayc Jan 16, 2024
54191d3
Merge branch 'issue-174742' of github.com:angorayc/kibana into issue-…
angorayc Jan 16, 2024
6dfffb2
update unit tests
angorayc Jan 16, 2024
2507291
fix i18n
angorayc Jan 16, 2024
4567381
i18n
angorayc Jan 17, 2024
3694b8a
types
angorayc Jan 17, 2024
e81f963
lazy load
angorayc Jan 17, 2024
ae6df18
unit tests
angorayc Jan 17, 2024
637388a
Merge branch 'main' into issue-174742
angorayc Jan 17, 2024
57af4f3
mv onboarding page service
angorayc Jan 18, 2024
283cb77
rename to onboarding
angorayc Jan 18, 2024
4c2e05a
unit tests
angorayc Jan 18, 2024
a6d48c7
Merge branch 'issue-174742' of github.com:angorayc/kibana into issue-…
angorayc Jan 18, 2024
51a4714
[CI] Auto-commit changed files from 'node scripts/lint_ts_projects --…
kibanamachine Jan 18, 2024
e909486
css
angorayc Jan 18, 2024
3dee4eb
Merge branch 'issue-174742' of github.com:angorayc/kibana into issue-…
angorayc Jan 18, 2024
f306840
onboarding service
angorayc Jan 18, 2024
075f7f4
styles
angorayc Jan 21, 2024
14e6527
css
angorayc Jan 21, 2024
4facddc
Merge branch 'main' into issue-174742
angorayc Jan 21, 2024
6c453f7
types
angorayc Jan 23, 2024
f4d577d
remove getters from OnboardingPageService
angorayc Jan 23, 2024
9d81489
Merge branch 'main' into issue-174742
angorayc Jan 24, 2024
d77de1e
rm nesting KibanaPageTemplate
angorayc Jan 24, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*
* 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 type { Observable } from 'rxjs';
import { BehaviorSubject } from 'rxjs';
import type { SecurityProductTypes } from '../../../common/components/landing_page/onboarding/configs';
import type { StepId } from '../../../common/components/landing_page/onboarding/types';

export class OnboardingPageService {
private productTypesSubject$: BehaviorSubject<SecurityProductTypes | undefined>;
private projectsUrlSubject$: BehaviorSubject<string | undefined>;
private projectFeaturesUrlSubject$: BehaviorSubject<string | undefined>;
private availableStepsSubject$: BehaviorSubject<StepId[]>;

public productTypes$: Observable<SecurityProductTypes | undefined>;
public projectsUrl$: Observable<string | undefined>;
public projectFeaturesUrl$: Observable<string | undefined>;
public availableSteps$: Observable<StepId[]>;

constructor() {
this.productTypesSubject$ = new BehaviorSubject<SecurityProductTypes | undefined>(undefined);
this.projectsUrlSubject$ = new BehaviorSubject<string | undefined>(undefined);
this.projectFeaturesUrlSubject$ = new BehaviorSubject<string | undefined>(undefined);
this.availableStepsSubject$ = new BehaviorSubject<StepId[]>([]);

this.productTypes$ = this.productTypesSubject$.asObservable();
this.projectsUrl$ = this.projectsUrlSubject$.asObservable();
this.projectFeaturesUrl$ = this.projectFeaturesUrlSubject$.asObservable();
this.availableSteps$ = this.availableStepsSubject$.asObservable();
}

setProductTypes(productTypes: SecurityProductTypes) {
this.productTypesSubject$.next(productTypes);
}
setProjectFeaturesUrl(projectFeaturesUrl: string | undefined) {
this.projectFeaturesUrlSubject$.next(projectFeaturesUrl);
}
setProjectsUrl(projectsUrl: string | undefined) {
this.projectsUrlSubject$.next(projectsUrl);
}
setAvailableSteps(availableSteps: StepId[]) {
this.availableStepsSubject$.next(availableSteps);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,24 +8,19 @@ import React from 'react';
import { render } from '@testing-library/react';
import { LandingPageComponent } from '.';

const mockUseContractComponents = jest.fn(() => ({}));
jest.mock('../../hooks/use_contract_component', () => ({
useContractComponents: () => mockUseContractComponents(),
}));
jest.mock('../../containers/sourcerer', () => ({
useSourcererDataView: jest.fn().mockReturnValue({ indicesExist: false }),
}));
jest.mock('./onboarding');

describe('LandingPageComponent', () => {
beforeEach(() => {
jest.clearAllMocks();
});

it('renders the get started component', () => {
const GetStarted = () => <div data-test-subj="get-started-mock" />;
mockUseContractComponents.mockReturnValue({ GetStarted });
it('renders the onboarding component', () => {
const { queryByTestId } = render(<LandingPageComponent />);

expect(queryByTestId('get-started-mock')).toBeInTheDocument();
expect(queryByTestId('onboarding-with-settings')).toBeInTheDocument();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@
* 2.0.
*/

import React, { memo } from 'react';
import React, { memo, useMemo } from 'react';
import { useSourcererDataView } from '../../containers/sourcerer';
import { useContractComponents } from '../../hooks/use_contract_component';
import { getOnboardingComponent } from './onboarding';

export const LandingPageComponent = memo(() => {
const { GetStarted } = useContractComponents();
const { indicesExist } = useSourcererDataView();
return GetStarted ? <GetStarted indicesExist={indicesExist} /> : null;
const OnBoarding = useMemo(() => getOnboardingComponent(), []);
return <OnBoarding indicesExist={indicesExist} />;
});

LandingPageComponent.displayName = 'LandingPageComponent';
Original file line number Diff line number Diff line change
@@ -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.
*/
import React from 'react';

export const getOnboardingComponent = jest
.fn()
.mockReturnValue(() => <div data-test-subj="onboarding-with-settings" />);
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/*
* 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';

export const OnboardingWithSettingsComponent = () => (
<div data-test-subj="onboarding-with-settings" />
);
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* 2.0.
*/

export const getStartedStorage = {
export const onboardingStorage = {
getAllFinishedStepsFromStorage: jest.fn(() => ({})),
getFinishedStepsFromStorageByCardId: jest.fn(() => []),
getActiveProductsFromStorage: jest.fn(() => []),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@
* 2.0.
*/

import type { FetchRulesResponse } from '@kbn/security-solution-plugin/public';
import { DETECTION_ENGINE_RULES_URL_FIND } from '@kbn/security-solution-plugin/common';
import type { HttpSetup } from '@kbn/core/public';
import { DETECTION_ENGINE_RULES_URL_FIND } from '../../../../../../common/constants';
import type { FetchRulesResponse } from '../../../../../detection_engine/rule_management/logic/types';

export const fetchRuleManagementFilters = async ({
http,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* 2.0.
*/

import { ProductLine } from '../../common/product';
import { ProductLine } from './configs';
import { PRODUCT_BADGE_ANALYTICS, PRODUCT_BADGE_CLOUD, PRODUCT_BADGE_EDR } from './translations';
import type { Badge } from './types';
import { BadgeId } from './types';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
* 2.0.
*/

import { ProductLine } from '../../common/product';
import { analyticsBadge, cloudBadge, edrBadge, getProductBadges } from './badge';
import { ProductLine } from './configs';

describe('getProductBadges', () => {
test('should return all badges if no productLineRequired is passed', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@
*/

import { EuiFlexGroup, EuiFlexItem, EuiPanel } from '@elastic/eui';

import React, { useMemo, useCallback } from 'react';

import classnames from 'classnames';
import type {
CardId,
Expand All @@ -20,6 +22,8 @@ import { getCard } from './helpers';
import { CardStep } from './card_step';
import { useCardItemStyles } from './styles/card_item.styles';

export const SHADOW_ANIMATION_DURATION = 350;

const CardItemComponent: React.FC<{
activeStepIds: StepId[] | undefined;
cardId: CardId;
Expand All @@ -44,12 +48,16 @@ const CardItemComponent: React.FC<{
() => new Set(expandedCardSteps[cardId]?.expandedSteps ?? []),
[cardId, expandedCardSteps]
);
const cardItemPanelStyle = useCardItemStyles();

const cardClassNames = classnames('card-item', {
'card-expanded': isExpandedCard,
});
const cardClassNames = classnames(
'card-item',
{
'card-expanded': isExpandedCard,
},
cardItemPanelStyle
);

const cardItemPanelStyle = useCardItemStyles();
const getCardStep = useCallback(
(stepId: StepId) => cardItem?.steps?.find((step) => step.id === stepId),
[cardItem?.steps]
Expand Down Expand Up @@ -91,7 +99,6 @@ const CardItemComponent: React.FC<{
className={cardClassNames}
hasBorder
paddingSize="none"
css={cardItemPanelStyle}
borderRadius="none"
data-test-subj={cardId}
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
* 2.0.
*/

import classnames from 'classnames';
import React from 'react';
import { useStepContentStyles } from '../../styles/step_content.styles';

Expand All @@ -14,12 +15,8 @@ const ContentWrapperComponent: React.FC<{ children: React.ReactElement; shadow?:
}) => {
const { getRightContentStyles } = useStepContentStyles();
const rightContentStyles = getRightContentStyles({ shadow });

return (
<div className="right-panel-content" css={rightContentStyles}>
{children}
</div>
);
const rightPanelContentClassNames = classnames('right-panel-content', rightContentStyles);
return <div className={rightPanelContentClassNames}>{children}</div>;
};

export const ContentWrapper = React.memo(ContentWrapperComponent);
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ jest.mock('@elastic/eui', () => ({
EuiFlexItem: ({ children }: { children: React.ReactElement }) => <div>{children}</div>,
EuiIcon: () => <span data-test-subj="mock-play-icon" />,
useEuiTheme: () => ({ euiTheme: { colors: { fullShade: '#000', emptyShade: '#fff' } } }),
EuiCodeBlock: () => <span data-test-subj="mock-code-block" />,
}));

describe('Video Component', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@

import type { MutableRefObject } from 'react';
import type { HttpSetup } from '@kbn/core/public';
import { ENABLED_FIELD } from '@kbn/security-solution-plugin/common';
import { fetchRuleManagementFilters } from '../apis';
import { ENABLED_FIELD } from '../../../../../../common/detection_engine/rule_management/rule_fields';

export const autoCheckPrebuildRuleStepCompleted = async ({
abortSignal,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,7 @@ jest.mock('./step_content', () => ({
jest.mock('../context/step_context');
jest.mock('../apis');

jest.mock('../../common/services');

jest.mock('@kbn/security-solution-plugin/public', () => ({
useSourcererDataView: jest.fn().mockReturnValue({ indicesExist: false }),
}));
jest.mock('../../../../lib/kibana');

jest.mock('@kbn/security-solution-navigation', () => ({
useNavigateTo: jest.fn().mockReturnValue({ navigateTo: jest.fn() }),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,14 +103,21 @@ const CardStepComponent: React.FC<{
} = useCardStepStyles();
const stepGroundStyles = getStepGroundStyles({ hasStepContent });

const panelClassNames = classnames({
'step-panel-collapsed': !isExpandedStep,
});
const panelClassNames = classnames(
{
'step-panel-collapsed': !isExpandedStep,
},
stepPanelStyles
);

const stepIconClassNames = classnames('step-icon', {
'step-icon-done': isDone,
stepIconStyles,
});

const stepTitleClassNames = classnames('step-title', stepTitleStyles);
const allDoneTextNames = classnames('all-done-badge', allDoneTextStyles);

return (
<EuiPanel
color="plain"
Expand All @@ -120,23 +127,20 @@ const CardStepComponent: React.FC<{
paddingSize="none"
className={panelClassNames}
id={stepId}
css={stepPanelStyles}
>
<EuiFlexGroup gutterSize="none" css={stepGroundStyles}>
<EuiFlexItem grow={false} onClick={toggleStep} css={stepItemStyles}>
<span className={stepIconClassNames} css={stepIconStyles}>
<EuiFlexGroup gutterSize="none" className={stepGroundStyles}>
<EuiFlexItem grow={false} onClick={toggleStep} className={stepItemStyles}>
<span className={stepIconClassNames}>
{icon && <EuiIcon {...icon} size="l" className="eui-alignMiddle" />}
</span>
</EuiFlexItem>
<EuiFlexItem grow={1} onClick={toggleStep} css={stepItemStyles}>
<span className="step-title" css={stepTitleStyles}>
{title}
</span>
<EuiFlexItem grow={1} onClick={toggleStep} className={stepItemStyles}>
<span className={stepTitleClassNames}>{title}</span>
</EuiFlexItem>
<EuiFlexItem grow={false} css={stepItemStyles}>
<EuiFlexItem grow={false} className={stepItemStyles}>
<div>
{isDone && (
<EuiBadge className="all-done-badge" css={allDoneTextStyles} color="success">
<EuiBadge className={allDoneTextNames} color="success">
{ALL_DONE_TEXT}
</EuiBadge>
)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { QuickStartSectionCardsId, SectionId } from '../types';
import { overviewVideoSteps } from '../sections';

jest.mock('../context/step_context');
jest.mock('../../common/services');
jest.mock('../../../../lib/kibana');

describe('StepContent', () => {
const toggleTaskCompleteStatus = jest.fn();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@
*/

import { EuiFlexGroup, EuiFlexItem, EuiText } from '@elastic/eui';
import classnames from 'classnames';
import React from 'react';

import { useCheckStepCompleted } from '../hooks/use_check_step_completed';
import { useStepContentStyles } from '../styles/step_content.styles';
import type {
Expand Down Expand Up @@ -51,24 +53,34 @@ const StepContentComponent = ({
toggleTaskCompleteStatus,
});

const stepContentGroupClassName = classnames('step-content-group', stepContentGroupStyles);
const leftContentClassNames = classnames('left-panel', leftContentStyles);

const descriptionClassNames = classnames(
'step-content-description',
'eui-displayBlock',
descriptionStyles
);

const rightPanelClassNames = classnames('right-panel', rightPanelStyles);

const rightPanelContentClassNames = classnames('right-panel-wrapper', rightPanelContentStyles);
return (
<EuiFlexGroup
color="plain"
className="step-content-group"
css={stepContentGroupStyles}
className={stepContentGroupClassName}
data-test-subj={`${stepId}-content`}
direction="row"
gutterSize="none"
>
{step.description && (
<EuiFlexItem grow={false} css={leftContentStyles} className="left-panel">
<EuiFlexItem grow={false} className={leftContentClassNames}>
<EuiText size="s">
{step.description.map((desc, index) => (
<div
data-test-subj={`${stepId}-description-${index}`}
key={`${stepId}-description-${index}`}
className="eui-displayBlock step-content-description"
css={descriptionStyles}
className={descriptionClassNames}
>
{desc}
</div>
Expand All @@ -77,17 +89,8 @@ const StepContentComponent = ({
</EuiFlexItem>
)}
{splitPanel && (
<EuiFlexItem
grow={false}
data-test-subj="split-panel"
className="right-panel"
css={rightPanelStyles}
>
{splitPanel && (
<div className="right-panel-wrapper" css={rightPanelContentStyles}>
{splitPanel}
</div>
)}
<EuiFlexItem grow={false} data-test-subj="split-panel" className={rightPanelClassNames}>
{splitPanel && <div className={rightPanelContentClassNames}>{splitPanel}</div>}
</EuiFlexItem>
)}
</EuiFlexGroup>
Expand Down
Loading