diff --git a/x-pack/platform/plugins/private/translations/translations/de-DE.json b/x-pack/platform/plugins/private/translations/translations/de-DE.json
index a12ec63389baa..688f52e4240f9 100644
--- a/x-pack/platform/plugins/private/translations/translations/de-DE.json
+++ b/x-pack/platform/plugins/private/translations/translations/de-DE.json
@@ -36914,7 +36914,6 @@
"xpack.securitySolution.onboarding.cardBadge.techPreview": "Technische Vorschau",
"xpack.securitySolution.onboarding.cardBadge.techPreviewTooltip": "Dieses Feature befindet sich in der technischen Vorschau und kann sich ändern.",
"xpack.securitySolution.onboarding.cardComplete": "Abgeschlossen",
- "xpack.securitySolution.onboarding.configure.title": "Konfigurieren",
"xpack.securitySolution.onboarding.dashboardsCard.calloutIntegrationsButton": "Integrationsschritt hinzufügen",
"xpack.securitySolution.onboarding.dashboardsCard.calloutIntegrationsText": "Um Dashboards anzuzeigen, müssen Sie zuerst Integrationen hinzufügen.",
"xpack.securitySolution.onboarding.dashboardsCard.custom.description": "Per Drag-and-Drop zu einer benutzerdefinierten Visualisierung",
@@ -36951,7 +36950,6 @@
"xpack.securitySolution.onboarding.integrationsCard.checkComplete.fetchAgents.errorTitle": "Fehler beim Abrufen von Agentendaten",
"xpack.securitySolution.onboarding.integrationsCard.checkComplete.fetchIntegrations.errorTitle": "Fehler beim Abrufen von Integrationsdaten",
"xpack.securitySolution.onboarding.integrationsCard.title": "Daten mit Integrationen hinzufügen",
- "xpack.securitySolution.onboarding.migrate.title": "Regeln migrieren und Daten hinzufügen",
"xpack.securitySolution.onboarding.rulesCard.addRulesButton": "Elastic-Regeln hinzufügen",
"xpack.securitySolution.onboarding.rulesCard.calloutIntegrationsButton": "Integrationsschritt hinzufügen",
"xpack.securitySolution.onboarding.rulesCard.calloutIntegrationsText": "Um Elastic-Regeln hinzuzufügen, fügen Sie zuerst Integrationen hinzu.",
diff --git a/x-pack/platform/plugins/private/translations/translations/fr-FR.json b/x-pack/platform/plugins/private/translations/translations/fr-FR.json
index f61aec35efbbd..0ac247f52af96 100644
--- a/x-pack/platform/plugins/private/translations/translations/fr-FR.json
+++ b/x-pack/platform/plugins/private/translations/translations/fr-FR.json
@@ -37296,7 +37296,6 @@
"xpack.securitySolution.onboarding.cardBadge.techPreviewTooltip": "Cette fonctionnalité est en version d'évaluation technique. Elle est donc susceptible d'être modifiée.",
"xpack.securitySolution.onboarding.cardComplete": "Terminé",
"xpack.securitySolution.onboarding.common.startMigration.connectorMissingText": "Paramétrer le connecteur d'IA",
- "xpack.securitySolution.onboarding.configure.title": "Configurer",
"xpack.securitySolution.onboarding.dashboardsCard.calloutIntegrationsButton": "Ajouter des étapes d'intégration",
"xpack.securitySolution.onboarding.dashboardsCard.calloutIntegrationsText": "Pour afficher les tableaux de bord, ajoutez d'abord des intégrations.",
"xpack.securitySolution.onboarding.dashboardsCard.custom.description": "Personnalisez votre visualisation grâce à des cliquer-glisser",
@@ -37334,7 +37333,6 @@
"xpack.securitySolution.onboarding.integrationsCard.checkComplete.fetchAgents.errorTitle": "Erreur lors de la récupération des données des agents",
"xpack.securitySolution.onboarding.integrationsCard.checkComplete.fetchIntegrations.errorTitle": "Erreur lors de la récupération des données d'intégration",
"xpack.securitySolution.onboarding.integrationsCard.title": "Ajouter des données avec des intégrations",
- "xpack.securitySolution.onboarding.migrate.title": "Migrer les règles et ajouter des données",
"xpack.securitySolution.onboarding.rules.startMigration.title": "Migrez vos règles SIEM Splunk® vers Elastic",
"xpack.securitySolution.onboarding.rules.startMigration.upload.button": "Charger les règles",
"xpack.securitySolution.onboarding.rules.startMigration.upload.description": "Chargez vos règles avant d'importer des données pour identifier les intégrations, les flux de données, et les détails disponibles de toutes vos règles SIEM. Cliquez sur \"Charger les règles\" pour afficher des instructions étape par étape pour l'exportation et le chargement des règles.",
diff --git a/x-pack/platform/plugins/private/translations/translations/ja-JP.json b/x-pack/platform/plugins/private/translations/translations/ja-JP.json
index 43f6e8eea8a9a..e13a1732ceec8 100644
--- a/x-pack/platform/plugins/private/translations/translations/ja-JP.json
+++ b/x-pack/platform/plugins/private/translations/translations/ja-JP.json
@@ -37355,7 +37355,6 @@
"xpack.securitySolution.onboarding.cardBadge.techPreviewTooltip": "この機能はテクニカルプレビュー中であるため、変更される可能性があります。",
"xpack.securitySolution.onboarding.cardComplete": "完了",
"xpack.securitySolution.onboarding.common.startMigration.connectorMissingText": "AIコネクターを設定",
- "xpack.securitySolution.onboarding.configure.title": "構成",
"xpack.securitySolution.onboarding.dashboardsCard.calloutIntegrationsButton": "統合ステップの追加",
"xpack.securitySolution.onboarding.dashboardsCard.calloutIntegrationsText": "ダッシュボードを表示するには、最初に統合を追加してください。",
"xpack.securitySolution.onboarding.dashboardsCard.custom.description": "カスタムビジュアライゼーションまでドラッグしてドロップ",
@@ -37393,7 +37392,6 @@
"xpack.securitySolution.onboarding.integrationsCard.checkComplete.fetchAgents.errorTitle": "エージェントデータの取り込みエラー",
"xpack.securitySolution.onboarding.integrationsCard.checkComplete.fetchIntegrations.errorTitle": "統合データの取り込みエラー",
"xpack.securitySolution.onboarding.integrationsCard.title": "統合によってデータを追加",
- "xpack.securitySolution.onboarding.migrate.title": "ルールを移行してデータを追加",
"xpack.securitySolution.onboarding.rules.startMigration.title": "既存のSplunk® SIEMルールをElasticに移行",
"xpack.securitySolution.onboarding.rules.startMigration.upload.button": "ルールのアップロード",
"xpack.securitySolution.onboarding.rules.startMigration.upload.description": "データをインポートする前にルールをアップロードし、SIEMルールの統合、データストリーム、利用可能な詳細を特定します。[ルールのアップロード]をクリックすると、ルールのエクスポートとアップロードの手順が段階的に表示されます。",
diff --git a/x-pack/platform/plugins/private/translations/translations/zh-CN.json b/x-pack/platform/plugins/private/translations/translations/zh-CN.json
index 1831bb0711fb0..48932270521d8 100644
--- a/x-pack/platform/plugins/private/translations/translations/zh-CN.json
+++ b/x-pack/platform/plugins/private/translations/translations/zh-CN.json
@@ -37335,7 +37335,6 @@
"xpack.securitySolution.onboarding.cardBadge.techPreviewTooltip": "此功能处于技术预览状态,可能会进行更改。",
"xpack.securitySolution.onboarding.cardComplete": "已完成",
"xpack.securitySolution.onboarding.common.startMigration.connectorMissingText": "设置 AI 连接器",
- "xpack.securitySolution.onboarding.configure.title": "配置",
"xpack.securitySolution.onboarding.dashboardsCard.calloutIntegrationsButton": "添加集成步骤",
"xpack.securitySolution.onboarding.dashboardsCard.calloutIntegrationsText": "要查看仪表板,请先添加集成。",
"xpack.securitySolution.onboarding.dashboardsCard.custom.description": "拖放以进行定制可视化",
@@ -37373,7 +37372,6 @@
"xpack.securitySolution.onboarding.integrationsCard.checkComplete.fetchAgents.errorTitle": "获取代理数据时出错",
"xpack.securitySolution.onboarding.integrationsCard.checkComplete.fetchIntegrations.errorTitle": "获取集成数据时出错",
"xpack.securitySolution.onboarding.integrationsCard.title": "通过集成添加数据",
- "xpack.securitySolution.onboarding.migrate.title": "迁移规则并添加数据",
"xpack.securitySolution.onboarding.rules.startMigration.title": "将现有 Splunk® SIEM 规则迁移到 Elastic",
"xpack.securitySolution.onboarding.rules.startMigration.upload.button": "上传规则",
"xpack.securitySolution.onboarding.rules.startMigration.upload.description": "在导入数据之前上传规则,以识别集成、数据流和 SIEM 规则的可用详情。单击“上传规则”以查看导出和上传规则的分步说明。",
diff --git a/x-pack/solutions/security/plugins/security_solution/public/onboarding/components/onboarding_body/body_config.ts b/x-pack/solutions/security/plugins/security_solution/public/onboarding/components/onboarding_body/body_config.ts
index d7ef6146dcb32..ff2c8859601ad 100644
--- a/x-pack/solutions/security/plugins/security_solution/public/onboarding/components/onboarding_body/body_config.ts
+++ b/x-pack/solutions/security/plugins/security_solution/public/onboarding/components/onboarding_body/body_config.ts
@@ -14,10 +14,6 @@ import { alertsCardConfig } from './cards/alerts';
import { assistantCardConfig } from './cards/assistant';
import { integrationsExternalDetectionsCardConfig } from './cards/integrations_external_detections';
import { knowledgeSourceCardConfig } from './cards/knowledge_source';
-import { aiConnectorCardConfig } from './cards/siem_migrations/ai_connector';
-import { startRuleMigrationCardConfig } from './cards/siem_migrations/start_migration/rules';
-import { startDashboardMigrationCardConfig } from './cards/siem_migrations/start_migration/dashboards';
-import { siemMigrationIntegrationsCardConfig } from './cards/siem_migrations/integrations';
export const defaultBodyConfig: OnboardingGroupConfig[] = [
{
@@ -58,22 +54,3 @@ export const defaultExternalDetectionsBodyConfig: OnboardingGroupConfig[] = [
cards: [assistantCardConfig],
},
];
-
-export const siemMigrationsBodyConfig: OnboardingGroupConfig[] = [
- {
- title: i18n.translate('xpack.securitySolution.onboarding.configure.title', {
- defaultMessage: 'Configure',
- }),
- cards: [aiConnectorCardConfig],
- },
- {
- title: i18n.translate('xpack.securitySolution.onboarding.migrate.title', {
- defaultMessage: 'Migrate rules & dashboards',
- }),
- cards: [
- startRuleMigrationCardConfig,
- siemMigrationIntegrationsCardConfig,
- startDashboardMigrationCardConfig,
- ],
- },
-];
diff --git a/x-pack/solutions/security/plugins/security_solution/public/onboarding/components/onboarding_body/hooks/use_body_config.test.ts b/x-pack/solutions/security/plugins/security_solution/public/onboarding/components/onboarding_body/hooks/use_body_config.test.ts
index 16ff462c4592d..5ed1653066af6 100644
--- a/x-pack/solutions/security/plugins/security_solution/public/onboarding/components/onboarding_body/hooks/use_body_config.test.ts
+++ b/x-pack/solutions/security/plugins/security_solution/public/onboarding/components/onboarding_body/hooks/use_body_config.test.ts
@@ -8,10 +8,19 @@
import { renderHook } from '@testing-library/react';
import { useBodyConfig } from './use_body_config';
import { mockOnboardingContext, onboardingContext } from '../../__mocks__/mocks';
-import { OnboardingTopicId } from '../../../constants';
+
+const topicId = 'topic-id';
+const mockUseTopicId = jest.fn(() => topicId);
+jest.mock('../../hooks/use_topic_id', () => ({
+ useTopicId: () => mockUseTopicId(),
+}));
const defaultBodyConfig = [{ title: 'Default Group 1', cards: [] }];
-const config = new Map([[OnboardingTopicId.default, { body: defaultBodyConfig }]]);
+const bodyConfig = [{ title: 'Group 1', cards: [] }];
+const config = new Map([
+ ['default', { body: defaultBodyConfig }],
+ [topicId, { body: bodyConfig }],
+]);
jest.mock('../../onboarding_context');
@@ -26,7 +35,7 @@ describe('useBodyConfig', () => {
});
it('should return an empty array', () => {
- const { result } = renderHook(() => useBodyConfig(OnboardingTopicId.default));
+ const { result } = renderHook(() => useBodyConfig());
expect(result.current).toEqual([]);
});
});
@@ -37,8 +46,20 @@ describe('useBodyConfig', () => {
});
it('should return the body config for the selected topic', () => {
- const { result } = renderHook(() => useBodyConfig(OnboardingTopicId.default));
- expect(result.current).toEqual(defaultBodyConfig);
+ const { result } = renderHook(() => useBodyConfig());
+ expect(result.current).toEqual(bodyConfig);
+ });
+ });
+
+ describe('when the selected topic does not exist (not expected)', () => {
+ beforeEach(() => {
+ mockUseTopicId.mockReturnValue('non-existent-topic');
+ mockOnboardingContext.mockReturnValue({ ...onboardingContext, config });
+ });
+
+ it('should return the body config for the selected topic', () => {
+ const { result } = renderHook(() => useBodyConfig());
+ expect(result.current).toEqual([]);
});
});
});
diff --git a/x-pack/solutions/security/plugins/security_solution/public/onboarding/components/onboarding_body/hooks/use_body_config.ts b/x-pack/solutions/security/plugins/security_solution/public/onboarding/components/onboarding_body/hooks/use_body_config.ts
index a676664c462d1..0d6a26a3439d6 100644
--- a/x-pack/solutions/security/plugins/security_solution/public/onboarding/components/onboarding_body/hooks/use_body_config.ts
+++ b/x-pack/solutions/security/plugins/security_solution/public/onboarding/components/onboarding_body/hooks/use_body_config.ts
@@ -7,13 +7,14 @@
import { useMemo } from 'react';
import { useOnboardingContext } from '../../onboarding_context';
-import type { OnboardingTopicId } from '../../../constants';
+import { useTopicId } from '../../hooks/use_topic_id';
import type { OnboardingGroupConfig } from '../../../types';
/**
* Hook that returns the body config for the selected topic
*/
-export const useBodyConfig = (topicId: OnboardingTopicId): OnboardingGroupConfig[] => {
+export const useBodyConfig = (): OnboardingGroupConfig[] => {
+ const topicId = useTopicId();
const { config } = useOnboardingContext();
const topicBodyConfig = useMemo(() => {
let bodyConfig: OnboardingGroupConfig[] = [];
diff --git a/x-pack/solutions/security/plugins/security_solution/public/onboarding/components/onboarding_body/onboarding_body.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/onboarding/components/onboarding_body/onboarding_body.test.tsx
index 316a9623a1eff..3cdad1bf552f9 100644
--- a/x-pack/solutions/security/plugins/security_solution/public/onboarding/components/onboarding_body/onboarding_body.test.tsx
+++ b/x-pack/solutions/security/plugins/security_solution/public/onboarding/components/onboarding_body/onboarding_body.test.tsx
@@ -6,7 +6,6 @@
*/
import React from 'react';
import { render, screen, fireEvent, act } from '@testing-library/react';
-import { OnboardingTopicId } from '../../constants';
import { OnboardingBody } from './onboarding_body';
import { useBodyConfig } from './hooks/use_body_config';
import { useExpandedCard } from './hooks/use_expanded_card';
@@ -60,14 +59,14 @@ describe('OnboardingBody Component', () => {
});
it('should render the OnboardingBody component with the correct content', () => {
- render(, { wrapper: TestProviders });
+ render(, { wrapper: TestProviders });
expect(screen.getByText('Group 1')).toBeInTheDocument();
expect(screen.getByText('Card 1')).toBeInTheDocument();
});
describe('when the card is expanded', () => {
beforeEach(() => {
- render(, { wrapper: TestProviders });
+ render(, { wrapper: TestProviders });
fireEvent.click(screen.getByText('Card 1'));
});
@@ -87,7 +86,7 @@ describe('OnboardingBody Component', () => {
setExpandedCardId: mockSetExpandedCardId,
});
- render(, { wrapper: TestProviders });
+ render(, { wrapper: TestProviders });
fireEvent.click(screen.getByText('Card 1'));
});
@@ -114,7 +113,7 @@ describe('OnboardingBody Component', () => {
setExpandedCardId: mockSetExpandedCardId,
});
- render(, { wrapper: TestProviders });
+ render(, { wrapper: TestProviders });
act(() => {
fireEvent.click(screen.getByText('Card 1'));
});
@@ -138,7 +137,7 @@ describe('OnboardingBody Component', () => {
setExpandedCardId: mockSetExpandedCardId,
});
- render(, { wrapper: TestProviders });
+ render(, { wrapper: TestProviders });
act(() => {
fireEvent.click(screen.getByText('Card 1'));
});
diff --git a/x-pack/solutions/security/plugins/security_solution/public/onboarding/components/onboarding_body/onboarding_body.tsx b/x-pack/solutions/security/plugins/security_solution/public/onboarding/components/onboarding_body/onboarding_body.tsx
index 48fa60746fcf2..8f759b31c8e67 100644
--- a/x-pack/solutions/security/plugins/security_solution/public/onboarding/components/onboarding_body/onboarding_body.tsx
+++ b/x-pack/solutions/security/plugins/security_solution/public/onboarding/components/onboarding_body/onboarding_body.tsx
@@ -8,7 +8,7 @@
import React, { Suspense, useCallback } from 'react';
import { EuiFlexGroup, EuiFlexItem, EuiSpacer } from '@elastic/eui';
import { CenteredLoadingSpinner } from '../../../common/components/centered_loading_spinner';
-import type { OnboardingCardId, OnboardingTopicId } from '../../constants';
+import type { OnboardingCardId } from '../../constants';
import { useBodyConfig } from './hooks/use_body_config';
import { OnboardingCardGroup } from './onboarding_card_group';
import { OnboardingCardPanel } from './onboarding_card_panel';
@@ -16,8 +16,8 @@ import { useExpandedCard } from './hooks/use_expanded_card';
import { useCompletedCards } from './hooks/use_completed_cards';
import type { IsCardAvailable } from '../../types';
-export const OnboardingBody = React.memo<{ topicId: OnboardingTopicId }>(({ topicId }) => {
- const bodyConfig = useBodyConfig(topicId);
+export const OnboardingBody = React.memo(() => {
+ const bodyConfig = useBodyConfig();
const { expandedCardId, setExpandedCardId } = useExpandedCard();
const { isCardComplete, setCardComplete, getCardCheckCompleteResult, checkCardComplete } =
useCompletedCards(bodyConfig);
diff --git a/x-pack/solutions/security/plugins/security_solution/public/onboarding/components/onboarding_header/constants.ts b/x-pack/solutions/security/plugins/security_solution/public/onboarding/components/onboarding_header/constants.ts
deleted file mode 100644
index 5862eadb32051..0000000000000
--- a/x-pack/solutions/security/plugins/security_solution/public/onboarding/components/onboarding_header/constants.ts
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- * 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 const TELEMETRY_HEADER_CARD = `header_card`;
-
-export enum OnboardingHeaderCardId {
- video = 'video',
- teammates = 'teammates',
- demo = 'demo',
-}
diff --git a/x-pack/solutions/security/plugins/security_solution/public/onboarding/components/onboarding_header/onboarding_header.tsx b/x-pack/solutions/security/plugins/security_solution/public/onboarding/components/onboarding_header/onboarding_header.tsx
index d6353526548ca..6ed74ad57bdcf 100644
--- a/x-pack/solutions/security/plugins/security_solution/public/onboarding/components/onboarding_header/onboarding_header.tsx
+++ b/x-pack/solutions/security/plugins/security_solution/public/onboarding/components/onboarding_header/onboarding_header.tsx
@@ -10,6 +10,7 @@ import { EuiFlexGroup, EuiFlexItem, EuiImage, EuiSpacer, EuiText, EuiTitle } fro
import { useKibanaIsDarkMode } from '@kbn/react-kibana-context-theme';
import { useCurrentUser } from '../../../common/lib/kibana/hooks';
+import { OnboardingHeaderTopicSelector } from './onboarding_header_topic_selector';
import { useOnboardingHeaderStyles } from './onboarding_header.styles';
import rocketImage from './images/header_rocket.png';
import rocketDarkImage from './images/header_rocket_dark.png';
@@ -62,9 +63,9 @@ export const OnboardingHeader = React.memo(() => {
{filteredHeaderConfig.description}
+
-
>
);
});
diff --git a/x-pack/solutions/security/plugins/security_solution/public/onboarding/components/onboarding_header/onboarding_header_topic_selector.tsx b/x-pack/solutions/security/plugins/security_solution/public/onboarding/components/onboarding_header/onboarding_header_topic_selector.tsx
new file mode 100644
index 0000000000000..a09105943d6f1
--- /dev/null
+++ b/x-pack/solutions/security/plugins/security_solution/public/onboarding/components/onboarding_header/onboarding_header_topic_selector.tsx
@@ -0,0 +1,44 @@
+/*
+ * 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, { useMemo } from 'react';
+import { EuiButtonGroup } from '@elastic/eui';
+import type { OnboardingTopicId } from '../../constants';
+import { useOnboardingContext } from '../onboarding_context';
+import { useUrlDetail } from '../hooks/use_url_detail';
+
+export const OnboardingHeaderTopicSelector = React.memo(() => {
+ const { config } = useOnboardingContext();
+ const { topicId, setTopic } = useUrlDetail();
+
+ const selectorOptions = useMemo(
+ () =>
+ [...config.values()].map((topicConfig) => ({
+ id: topicConfig.id,
+ label: topicConfig.title,
+ })),
+ [config]
+ );
+
+ if (selectorOptions.length < 2) {
+ return null;
+ }
+
+ return (
+ setTopic(id as OnboardingTopicId)}
+ isFullWidth
+ />
+ );
+});
+OnboardingHeaderTopicSelector.displayName = 'OnboardingHeaderTopicSelector';
diff --git a/x-pack/solutions/security/plugins/security_solution/public/onboarding/components/onboarding_router.tsx b/x-pack/solutions/security/plugins/security_solution/public/onboarding/components/onboarding_router.tsx
index c111ceda8c169..d95da145a4a24 100644
--- a/x-pack/solutions/security/plugins/security_solution/public/onboarding/components/onboarding_router.tsx
+++ b/x-pack/solutions/security/plugins/security_solution/public/onboarding/components/onboarding_router.tsx
@@ -37,9 +37,9 @@ export const OnboardingRouter = React.memo(() => {
{
- return ;
- }}
+ render={({ location }) => (
+
+ )}
/>
} />
@@ -55,6 +55,7 @@ const OnboardingRoute = React.memo(({ match: { params }, l
pathTopicId: params.topicId || null,
hashCardId: getCardIdFromHash(location.hash),
});
+
if (isLoading) {
return ;
}
@@ -62,7 +63,7 @@ const OnboardingRoute = React.memo(({ match: { params }, l
return (
<>
-
+
>
);
});
diff --git a/x-pack/solutions/security/plugins/security_solution/public/onboarding/config.ts b/x-pack/solutions/security/plugins/security_solution/public/onboarding/config.ts
index 8c395213cabb3..19b70d6d6f589 100644
--- a/x-pack/solutions/security/plugins/security_solution/public/onboarding/config.ts
+++ b/x-pack/solutions/security/plugins/security_solution/public/onboarding/config.ts
@@ -15,7 +15,6 @@ import { OnboardingTopicId } from './constants';
import {
defaultBodyConfig,
defaultExternalDetectionsBodyConfig,
- siemMigrationsBodyConfig,
} from './components/onboarding_body/body_config';
import type { TopicConfig } from './types';
@@ -37,13 +36,4 @@ export const onboardingConfig: TopicConfig[] = [
capabilitiesRequired: RULES_UI_EXTERNAL_DETECTIONS_PRIVILEGE,
body: defaultExternalDetectionsBodyConfig,
},
- {
- id: OnboardingTopicId.siemMigrations,
- title: i18n.translate('xpack.securitySolution.onboarding.topic.automaticMigration', {
- defaultMessage: 'Automatic migration',
- }),
- body: siemMigrationsBodyConfig,
- disabledExperimentalFlagRequired: 'siemMigrationsDisabled',
- capabilitiesRequired: [[`dashboard_v2.show`], [RULES_UI_DETECTIONS_PRIVILEGE]],
- },
];
diff --git a/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/common/components/header_buttons/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/common/components/header_buttons/index.tsx
index de081b12f04bc..9ed272a6263a1 100644
--- a/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/common/components/header_buttons/index.tsx
+++ b/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/common/components/header_buttons/index.tsx
@@ -79,7 +79,7 @@ export const HeaderButtons: React.FC = React.memo(
{i18n.SIEM_MIGRATIONS_ADD_ANOTHER_MIGRATION_TITLE}
diff --git a/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/components/body.tsx b/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/components/body.tsx
new file mode 100644
index 0000000000000..c87592e8c11c0
--- /dev/null
+++ b/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/components/body.tsx
@@ -0,0 +1,144 @@
+/*
+ * 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, { Suspense, useCallback, useEffect, useMemo, useState } from 'react';
+import { useHistory, useLocation } from 'react-router-dom';
+import { EuiFlexGroup, EuiFlexItem, EuiSpacer } from '@elastic/eui';
+import { CenteredLoadingSpinner } from '../../common/components/centered_loading_spinner';
+import type { OnboardingCardId } from '../../onboarding/constants';
+import type { IsCardAvailable, SetExpandedCardId } from '../../onboarding/types';
+import { OnboardingCardGroup } from '../../onboarding/components/onboarding_body/onboarding_card_group';
+import { OnboardingCardPanel } from '../../onboarding/components/onboarding_body/onboarding_card_panel';
+import { useCompletedCards } from '../../onboarding/components/onboarding_body/hooks/use_completed_cards';
+import { siemMigrationsBodyConfig } from './body_config';
+
+const HEIGHT_ANIMATION_DURATION = 250;
+
+const scrollToCard = (cardId: OnboardingCardId) => {
+ setTimeout(() => {
+ const element = document.getElementById(cardId);
+ if (element) {
+ element.focus({ preventScroll: true });
+ window.scrollTo({ top: element.offsetTop - 40, behavior: 'smooth' });
+ }
+ }, HEIGHT_ANIMATION_DURATION);
+};
+
+/**
+ * Thin wrapper that reuses the onboarding card framework to render
+ * the SIEM migrations body config on a standalone page (outside the onboarding router).
+ */
+const getCardIdFromHash = (hash: string): OnboardingCardId | null =>
+ (hash.split('?')[0].replace('#', '') as OnboardingCardId) || null;
+
+export const SiemMigrationsBody = React.memo(() => {
+ const bodyConfig = siemMigrationsBodyConfig;
+ const history = useHistory();
+ const { hash } = useLocation();
+ const cardIdFromHash = useMemo(() => getCardIdFromHash(hash), [hash]);
+
+ const [expandedCardId, _setExpandedCardId] = useState(null);
+
+ useEffect(() => {
+ if (cardIdFromHash) {
+ _setExpandedCardId(cardIdFromHash);
+ scrollToCard(cardIdFromHash);
+ }
+ }, [cardIdFromHash]);
+
+ const { isCardComplete, setCardComplete, getCardCheckCompleteResult, checkCardComplete } =
+ useCompletedCards(bodyConfig);
+
+ const setExpandedCardId = useCallback(
+ (newCardId, options) => {
+ _setExpandedCardId(newCardId);
+ history.replace({ hash: newCardId ? `#${newCardId}` : undefined });
+ if (newCardId != null && options?.scroll) {
+ scrollToCard(newCardId);
+ }
+ },
+ [history]
+ );
+
+ const createOnToggleExpanded = useCallback(
+ (cardId: OnboardingCardId) => () => {
+ if (expandedCardId === cardId) {
+ setExpandedCardId(null);
+ } else {
+ setExpandedCardId(cardId);
+ checkCardComplete(cardId);
+ }
+ },
+ [expandedCardId, setExpandedCardId, checkCardComplete]
+ );
+
+ const createSetCardComplete = useCallback(
+ (cardId: OnboardingCardId) => (complete: boolean) => {
+ setCardComplete(cardId, complete);
+ },
+ [setCardComplete]
+ );
+
+ const createCheckCardComplete = useCallback(
+ (cardId: OnboardingCardId) => () => {
+ checkCardComplete(cardId);
+ },
+ [checkCardComplete]
+ );
+
+ const isCardAvailable = useCallback(
+ (cardId: OnboardingCardId) =>
+ bodyConfig.some((group) => group.cards.some((card) => card.id === cardId)),
+ [bodyConfig]
+ );
+
+ return (
+
+ {bodyConfig.map((group, index) => (
+
+
+
+
+ {group.cards.map((card) => {
+ const { id, title, icon, iconDark, badge, Component: LazyCardComponent } = card;
+ const cardCheckCompleteResult = getCardCheckCompleteResult(id);
+ return (
+
+
+ }>
+
+
+
+
+ );
+ })}
+
+
+
+ ))}
+
+ );
+});
+
+SiemMigrationsBody.displayName = 'SiemMigrationsOnboardingBody';
diff --git a/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/components/body_config.ts b/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/components/body_config.ts
new file mode 100644
index 0000000000000..f91da276c38de
--- /dev/null
+++ b/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/components/body_config.ts
@@ -0,0 +1,32 @@
+/*
+ * 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 { i18n } from '@kbn/i18n';
+import type { OnboardingGroupConfig } from '../../onboarding/types';
+import { aiConnectorCardConfig } from '../../onboarding/components/onboarding_body/cards/siem_migrations/ai_connector';
+import { startRuleMigrationCardConfig } from '../../onboarding/components/onboarding_body/cards/siem_migrations/start_migration/rules';
+import { startDashboardMigrationCardConfig } from '../../onboarding/components/onboarding_body/cards/siem_migrations/start_migration/dashboards';
+import { siemMigrationIntegrationsCardConfig } from '../../onboarding/components/onboarding_body/cards/siem_migrations/integrations';
+
+export const siemMigrationsBodyConfig: OnboardingGroupConfig[] = [
+ {
+ title: i18n.translate('xpack.securitySolution.siemMigrations.onboarding.configure.title', {
+ defaultMessage: 'Configure',
+ }),
+ cards: [aiConnectorCardConfig],
+ },
+ {
+ title: i18n.translate('xpack.securitySolution.siemMigrations.onboarding.migrate.title', {
+ defaultMessage: 'Migrate rules & dashboards',
+ }),
+ cards: [
+ startRuleMigrationCardConfig,
+ siemMigrationIntegrationsCardConfig,
+ startDashboardMigrationCardConfig,
+ ],
+ },
+];
diff --git a/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/create.tsx b/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/create.tsx
index 6bc504e1e3ef3..14a637a454b90 100644
--- a/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/create.tsx
+++ b/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/create.tsx
@@ -10,11 +10,10 @@ import { EuiSpacer, EuiPageBody } from '@elastic/eui';
import { SecuritySolutionPageWrapper } from '../common/components/page_wrapper';
import { PageTitle } from './common/components/page_title';
import { useSpaceId } from '../common/hooks/use_space_id';
-import { OnboardingBody } from '../onboarding/components/onboarding_body/onboarding_body';
-import { OnboardingTopicId } from '../onboarding/constants';
import { CenteredLoadingSpinner } from '../common/components/centered_loading_spinner';
import { OnboardingContextProvider } from '../onboarding/components/onboarding_context';
import { HeaderPage } from '../common/components/header_page';
+import { SiemMigrationsBody } from './components/body';
const SIEM_MIGRATIONS_PAGE_TITLE = i18n.translate(
'xpack.securitySolution.siemMigrations.create.pageTitle',
@@ -36,7 +35,7 @@ export const SiemMigrationsCreatePage = () => {
} border />
-
+
diff --git a/x-pack/solutions/security/test/security_solution_cypress/cypress/e2e/investigations/siem_migrations/dashboards/onboarding.cy.ts b/x-pack/solutions/security/test/security_solution_cypress/cypress/e2e/investigations/siem_migrations/dashboards/onboarding.cy.ts
index 844c22c3c9998..7a665a7acb8ad 100644
--- a/x-pack/solutions/security/test/security_solution_cypress/cypress/e2e/investigations/siem_migrations/dashboards/onboarding.cy.ts
+++ b/x-pack/solutions/security/test/security_solution_cypress/cypress/e2e/investigations/siem_migrations/dashboards/onboarding.cy.ts
@@ -24,7 +24,7 @@ import {
toggleMigrateDashboardsCard,
uploadDashboards,
} from '../../../../tasks/siem_migrations';
-import { GET_STARTED_URL } from '../../../../urls/navigation';
+import { SIEM_MIGRATIONS_URL } from '../../../../urls/navigation';
import { role } from '../common/role';
export const SPLUNK_TEST_DASHBOARDS = [
@@ -106,7 +106,7 @@ describe(
},
{ interval: 500, timeout: 12000 }
);
- visit(GET_STARTED_URL);
+ visit(SIEM_MIGRATIONS_URL);
});
after(() => {
diff --git a/x-pack/solutions/security/test/security_solution_cypress/cypress/e2e/investigations/siem_migrations/dashboards/translated_dashboards_page.cy.ts b/x-pack/solutions/security/test/security_solution_cypress/cypress/e2e/investigations/siem_migrations/dashboards/translated_dashboards_page.cy.ts
index 6cd6585c1c247..fb09fe127ba15 100644
--- a/x-pack/solutions/security/test/security_solution_cypress/cypress/e2e/investigations/siem_migrations/dashboards/translated_dashboards_page.cy.ts
+++ b/x-pack/solutions/security/test/security_solution_cypress/cypress/e2e/investigations/siem_migrations/dashboards/translated_dashboards_page.cy.ts
@@ -23,7 +23,7 @@ import {
reprocessDashboards,
selectMigrationConnector,
} from '../../../../tasks/siem_migrations';
-import { GET_STARTED_URL } from '../../../../urls/navigation';
+import { SIEM_MIGRATIONS_URL } from '../../../../urls/navigation';
import { role } from '../common/role';
let bedrockConnectorId: string | null = null;
@@ -61,7 +61,7 @@ describe.skip(
);
role.login();
- visit(GET_STARTED_URL);
+ visit(SIEM_MIGRATIONS_URL);
selectMigrationConnector();
goToTranslatedDashboardsPageFromOnboarding();
});
diff --git a/x-pack/solutions/security/test/security_solution_cypress/cypress/e2e/investigations/siem_migrations/rules/onboarding.cy.ts b/x-pack/solutions/security/test/security_solution_cypress/cypress/e2e/investigations/siem_migrations/rules/onboarding.cy.ts
index 70790e15b39d8..b0857128a66d7 100644
--- a/x-pack/solutions/security/test/security_solution_cypress/cypress/e2e/investigations/siem_migrations/rules/onboarding.cy.ts
+++ b/x-pack/solutions/security/test/security_solution_cypress/cypress/e2e/investigations/siem_migrations/rules/onboarding.cy.ts
@@ -24,7 +24,7 @@ import {
saveDefaultMigrationName,
renameMigration,
} from '../../../../tasks/siem_migrations';
-import { GET_STARTED_URL } from '../../../../urls/navigation';
+import { SIEM_MIGRATIONS_URL } from '../../../../urls/navigation';
import { role } from '../common/role';
export const SPLUNK_TEST_RULES = [
@@ -93,7 +93,7 @@ describe(
role.login();
createBedrockConnector();
- visit(GET_STARTED_URL);
+ visit(SIEM_MIGRATIONS_URL);
});
after(() => {
diff --git a/x-pack/solutions/security/test/security_solution_cypress/cypress/e2e/investigations/siem_migrations/rules/qradar_onboarding.cy.ts b/x-pack/solutions/security/test/security_solution_cypress/cypress/e2e/investigations/siem_migrations/rules/qradar_onboarding.cy.ts
index 934bc403e92c3..b53fdb26ba997 100644
--- a/x-pack/solutions/security/test/security_solution_cypress/cypress/e2e/investigations/siem_migrations/rules/qradar_onboarding.cy.ts
+++ b/x-pack/solutions/security/test/security_solution_cypress/cypress/e2e/investigations/siem_migrations/rules/qradar_onboarding.cy.ts
@@ -24,7 +24,7 @@ import {
selectQRadarMigrationSource,
uploadQRadarRules,
} from '../../../../tasks/siem_migrations';
-import { GET_STARTED_URL } from '../../../../urls/navigation';
+import { SIEM_MIGRATIONS_URL } from '../../../../urls/navigation';
import { role } from '../common/role';
import {
QRADAR_TEST_RULES_XML,
@@ -42,21 +42,18 @@ describe(
});
beforeEach(() => {
+ cleanMigrationData();
deleteConnectors();
createBedrockConnector();
role.login();
cy.log('Creating Bedrock connector');
- visit(GET_STARTED_URL);
+ visit(SIEM_MIGRATIONS_URL);
selectMigrationConnector();
openUploadRulesFlyout();
selectQRadarMigrationSource();
setMigrationName();
});
- afterEach(() => {
- cleanMigrationData();
- });
-
after(() => {
role.teardown();
});
diff --git a/x-pack/solutions/security/test/security_solution_cypress/cypress/e2e/investigations/siem_migrations/rules/translated_rules_page.cy.ts b/x-pack/solutions/security/test/security_solution_cypress/cypress/e2e/investigations/siem_migrations/rules/translated_rules_page.cy.ts
index df1111be0be60..2153f2bf2a865 100644
--- a/x-pack/solutions/security/test/security_solution_cypress/cypress/e2e/investigations/siem_migrations/rules/translated_rules_page.cy.ts
+++ b/x-pack/solutions/security/test/security_solution_cypress/cypress/e2e/investigations/siem_migrations/rules/translated_rules_page.cy.ts
@@ -25,7 +25,7 @@ import {
openReprocessDialog,
reprocessWithoutPrebuiltRulesMatching,
} from '../../../../tasks/siem_migrations';
-import { GET_STARTED_URL } from '../../../../urls/navigation';
+import { SIEM_MIGRATIONS_URL } from '../../../../urls/navigation';
import { role } from '../common/role';
// TODO: https://github.com/elastic/kibana/issues/228940 remove @skipInServerlessMKI tag when privileges issue is fixed
@@ -50,7 +50,7 @@ describe(
createBedrockConnector();
role.login();
- visit(GET_STARTED_URL);
+ visit(SIEM_MIGRATIONS_URL);
selectMigrationConnector();
navigateToTranslatedRulesPage();
});
diff --git a/x-pack/solutions/security/test/security_solution_cypress/cypress/screens/siem_migrations.ts b/x-pack/solutions/security/test/security_solution_cypress/cypress/screens/siem_migrations.ts
index 27888194126fa..ccf615483c132 100644
--- a/x-pack/solutions/security/test/security_solution_cypress/cypress/screens/siem_migrations.ts
+++ b/x-pack/solutions/security/test/security_solution_cypress/cypress/screens/siem_migrations.ts
@@ -8,8 +8,6 @@
import { getDataTestSubjectSelector, getDataTestSubjectSelectorStartWith } from '../helpers/common';
import { bedrockConnectorAPIPayload } from '../tasks/api_calls/connectors';
-export const ONBOARDING_SIEM_MIGRATION_TOPIC = getDataTestSubjectSelector('siem_migrations');
-
export const ONBOARDING_SIEM_MIGRATION_CARDS = {
AI_CONNECTORS: '#ai_connectors',
SELECT_CONNECTORS: getDataTestSubjectSelector('connector-selector'),
diff --git a/x-pack/solutions/security/test/security_solution_cypress/cypress/tasks/siem_migrations.ts b/x-pack/solutions/security/test/security_solution_cypress/cypress/tasks/siem_migrations.ts
index add185fb0c939..2645248e5964e 100644
--- a/x-pack/solutions/security/test/security_solution_cypress/cypress/tasks/siem_migrations.ts
+++ b/x-pack/solutions/security/test/security_solution_cypress/cypress/tasks/siem_migrations.ts
@@ -37,12 +37,7 @@ export const toggleSiemMigrationsCard = () => {
cy.get(SELECTORS.ONBOARDING_SIEM_MIGRATION_CARDS.AI_CONNECTORS).click();
};
-export const selectAutomaticMigrationTopic = () => {
- cy.get(SELECTORS.ONBOARDING_SIEM_MIGRATION_TOPIC).click();
-};
-
export const selectMigrationConnector = () => {
- selectAutomaticMigrationTopic();
toggleSiemMigrationsCard();
cy.get(SELECTORS.ONBOARDING_SIEM_MIGRATION_CARDS.SELECT_CONNECTORS).click();
cy.get(SELECTORS.FAKE_BEDROCK_SELECTOR).click();
diff --git a/x-pack/solutions/security/test/security_solution_cypress/cypress/urls/navigation.ts b/x-pack/solutions/security/test/security_solution_cypress/cypress/urls/navigation.ts
index a2ea4377da90d..92d4f6a9fd1c8 100644
--- a/x-pack/solutions/security/test/security_solution_cypress/cypress/urls/navigation.ts
+++ b/x-pack/solutions/security/test/security_solution_cypress/cypress/urls/navigation.ts
@@ -10,6 +10,7 @@ export const LOGOUT_URL = '/logout';
// Common
export const GET_STARTED_URL = '/app/security/get_started';
+export const SIEM_MIGRATIONS_URL = '/app/security/siem_migrations/create';
export const MANAGE_URL = '/app/security/manage';
export const DASHBOARDS_URL = '/app/security/dashboards';