From 127f5809443e0f0f22082477d479f072a07420af Mon Sep 17 00:00:00 2001 From: Ievgen Sorokopud Date: Mon, 20 Jan 2025 18:03:25 +0100 Subject: [PATCH 1/5] [Rules migration] Implement workflow tour - Rule Translation (#11384) --- .../side_nav/src/solution_side_nav.tsx | 4 +- .../security_solution/common/constants.ts | 1 + .../rules/components/header_buttons/index.tsx | 3 + .../rules_table_columns/header/index.tsx | 25 +-- .../components/rules_table_columns/status.tsx | 3 + .../tours/translation_guide/index.tsx | 182 ++++++++++++++++++ .../tours/translation_guide/translations.ts | 108 +++++++++++ .../siem_migrations/rules/pages/index.tsx | 2 + 8 files changed, 315 insertions(+), 13 deletions(-) create mode 100644 x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/tours/translation_guide/index.tsx create mode 100644 x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/tours/translation_guide/translations.ts diff --git a/x-pack/solutions/security/packages/side_nav/src/solution_side_nav.tsx b/x-pack/solutions/security/packages/side_nav/src/solution_side_nav.tsx index 0b06dfd75169a..22f1207a6c01b 100644 --- a/x-pack/solutions/security/packages/side_nav/src/solution_side_nav.tsx +++ b/x-pack/solutions/security/packages/side_nav/src/solution_side_nav.tsx @@ -270,12 +270,12 @@ const SolutionSideNavItem: React.FC = React.memo( return ( {label} - + ); - }, [label, iconType]); + }, [iconType, label, id]); return ( <> diff --git a/x-pack/solutions/security/plugins/security_solution/common/constants.ts b/x-pack/solutions/security/plugins/security_solution/common/constants.ts index aa3f2d0d5c096..fb70250f7d3ef 100644 --- a/x-pack/solutions/security/plugins/security_solution/common/constants.ts +++ b/x-pack/solutions/security/plugins/security_solution/common/constants.ts @@ -423,6 +423,7 @@ export const RULES_TABLE_MAX_PAGE_SIZE = 100; export const NEW_FEATURES_TOUR_STORAGE_KEYS = { RULE_MANAGEMENT_PAGE: 'securitySolution.rulesManagementPage.newFeaturesTour.v8.13', TIMELINES: 'securitySolution.security.timelineFlyoutHeader.saveTimelineTour', + SIEM_RULE_TRANSLATION_PAGE: 'securitySolution.siemMigrations.ruleTranslationGuide.v8.18', }; export const RULE_DETAILS_EXECUTION_LOG_TABLE_SHOW_METRIC_COLUMNS_STORAGE_KEY = diff --git a/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/header_buttons/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/header_buttons/index.tsx index ab9f8cfc5539f..d0bda562aabfa 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/header_buttons/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/header_buttons/index.tsx @@ -12,6 +12,8 @@ import { EuiComboBox, EuiFlexGroup, EuiFlexItem, EuiSpacer, EuiTitle } from '@el import * as i18n from './translations'; import type { RuleMigrationStats } from '../../types'; +export const SIEM_MIGRATIONS_SELECT_MIGRATION_BUTTON_ID = 'siemMigrationsSelectMigrationButton'; + export interface HeaderButtonsProps { /** * Available rule migrations stats @@ -72,6 +74,7 @@ export const HeaderButtons: React.FC = React.memo( = React.memo(({ title, tooltipContent }) => { - return ( - - <> - {title} -   - - - - ); -}); +export const TableHeader: React.FC = React.memo( + ({ id, title, tooltipContent }) => { + return ( + +
+ {title} +   + +
+
+ ); + } +); TableHeader.displayName = 'TableHeader'; diff --git a/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rules_table_columns/status.tsx b/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rules_table_columns/status.tsx index 0a8d78f3aa812..f4add69f11e5c 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rules_table_columns/status.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rules_table_columns/status.tsx @@ -16,11 +16,14 @@ import { StatusBadge } from '../status_badge'; import { TableHeader } from './header'; import { convertTranslationResultIntoText } from '../../utils/translation_results'; +export const SIEM_MIGRATIONS_STATUS_HEADER_ID = 'siemMigrationsStatusHeader'; + export const createStatusColumn = (): TableColumn => { return { field: 'translation_result', name: ( = [ + { + step: 1, + title: i18n.MIGRATION_RULES_SELECTOR_TOUR_STEP_TITLE, + content: i18n.MIGRATION_RULES_SELECTOR_TOUR_STEP_CONTENT, + anchorPosition: 'downCenter', + }, + { + step: 2, + title: i18n.TRANSLATION_STATUS_TOUR_STEP_TITLE, + content: ( + , + install: {i18n.INSTALL_LABEL}, + installed: {i18n.INSTALLED_LABEL}, + view: {i18n.VIEW_LABEL}, + edit: {i18n.EDIT_LABEL}, + translated: {i18n.TRANSLATED_LABEL}, + reprocessed: {i18n.REPROCESSED_LABEL}, + // TODO: Update doc path once available + link: , + }} + /> + ), + anchorPosition: 'rightCenter', + }, + { + step: 3, + title: i18n.MIGRATION_GUIDE_TOUR_STEP_TITLE, + content: i18n.MIGRATION_GUIDE_TOUR_STEP_CONTENT, + anchorPosition: 'rightCenter', + }, +]; + +export const SiemTranslatedRulesTour: React.FC = React.memo(() => { + const { siemMigrations, storage } = useKibana().services; + + const isSelectMigrationAnchorMounted = useIsElementMounted( + SIEM_MIGRATIONS_SELECT_MIGRATION_BUTTON_ID + ); + const isStatusHeaderAnchorMounted = useIsElementMounted(SIEM_MIGRATIONS_STATUS_HEADER_ID); + const isGetStartedNavigationAnchorMounted = useIsElementMounted( + SECURITY_GET_STARTED_BUTTON_ANCHOR + ); + + const [tourState, setTourState] = useState(() => { + const restoredTourState = storage.get( + NEW_FEATURES_TOUR_STORAGE_KEYS.SIEM_RULE_TRANSLATION_PAGE + ); + if (restoredTourState != null) { + return restoredTourState; + } + return tourConfig; + }); + + const onTourFinished = useCallback(() => { + setTourState({ + ...tourState, + isTourActive: false, + }); + }, [tourState]); + + const onTourNext = useCallback(() => { + setTourState({ + ...tourState, + currentTourStep: tourState.currentTourStep + 1, + }); + }, [tourState]); + + useEffect(() => { + storage.set(NEW_FEATURES_TOUR_STORAGE_KEYS.SIEM_RULE_TRANSLATION_PAGE, tourState); + }, [tourState, storage]); + + const isTourActive = useMemo(() => { + return siemMigrations.rules.isAvailable() && tourState.isTourActive; + }, [siemMigrations.rules, tourState]); + + const selectMigrationStepData = tourSteps[0]; + const statusHeaderStepData = tourSteps[1]; + const getStartedStepData = tourSteps[2]; + + return ( + <> + {isSelectMigrationAnchorMounted && ( + + {i18n.NEXT_TOUR_STEP_BUTTON} + + } + /> + )} + {isStatusHeaderAnchorMounted && ( + + {i18n.NEXT_TOUR_STEP_BUTTON} + + } + /> + )} + {isGetStartedNavigationAnchorMounted && ( + + {i18n.FINISH_TOUR_BUTTON} + + } + /> + )} + + ); +}); +SiemTranslatedRulesTour.displayName = 'SiemTranslatedRulesTour'; diff --git a/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/tours/translation_guide/translations.ts b/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/tours/translation_guide/translations.ts new file mode 100644 index 0000000000000..ee57d61dba208 --- /dev/null +++ b/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/tours/translation_guide/translations.ts @@ -0,0 +1,108 @@ +/* + * 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'; + +export const MIGRATION_RULES_SELECTOR_TOUR_STEP_TITLE = i18n.translate( + 'xpack.securitySolution.siemMigrations.rules.tour.setupSiemMigrationTourTitle', + { + defaultMessage: 'Translated rules in one place', + } +); + +export const MIGRATION_RULES_SELECTOR_TOUR_STEP_CONTENT = i18n.translate( + 'xpack.securitySolution.siemMigrations.rules.tour.setupSiemMigrationTourContent', + { + defaultMessage: + 'Each migration’s translated rules appear on its SIEM rule translations page. Switch between your migrations using this dropdown. Start a new migration by clicking “Upload more rules for translation”.', + } +); + +export const TRANSLATION_STATUS_TOUR_STEP_TITLE = i18n.translate( + 'xpack.securitySolution.siemMigrations.rules.tour.translationStatusStepTitle', + { + defaultMessage: 'Translation status', + } +); + +export const MIGRATION_GUIDE_TOUR_STEP_TITLE = i18n.translate( + 'xpack.securitySolution.siemMigrations.rules.tour.migrationGuideStepTitle', + { + defaultMessage: 'SIEM Rule Migration guide', + } +); + +export const MIGRATION_GUIDE_TOUR_STEP_CONTENT = i18n.translate( + 'xpack.securitySolution.siemMigrations.rules.tour.migrationGuideStepContent', + { + defaultMessage: + 'Your guide and migrated rules can always be found in the Onboarding Hub. Use it to review previous rule migrations or start a new one.', + } +); + +export const NEXT_TOUR_STEP_BUTTON = i18n.translate( + 'xpack.securitySolution.siemMigrations.rules.tour.nextStepButton', + { + defaultMessage: 'Next', + } +); + +export const FINISH_TOUR_BUTTON = i18n.translate( + 'xpack.securitySolution.siemMigrations.rules.tour.finishButton', + { + defaultMessage: 'OK', + } +); + +export const INSTALL_LABEL = i18n.translate( + 'xpack.securitySolution.siemMigrations.rules.tour.installLabel', + { + defaultMessage: 'Install', + } +); + +export const INSTALLED_LABEL = i18n.translate( + 'xpack.securitySolution.siemMigrations.rules.tour.installedLabel', + { + defaultMessage: 'Installed', + } +); + +export const VIEW_LABEL = i18n.translate( + 'xpack.securitySolution.siemMigrations.rules.tour.viewLabel', + { + defaultMessage: 'View', + } +); + +export const EDIT_LABEL = i18n.translate( + 'xpack.securitySolution.siemMigrations.rules.tour.editLabel', + { + defaultMessage: 'Edit', + } +); + +export const TRANSLATED_LABEL = i18n.translate( + 'xpack.securitySolution.siemMigrations.rules.tour.translatedLabel', + { + defaultMessage: 'Translated', + } +); + +export const REPROCESSED_LABEL = i18n.translate( + 'xpack.securitySolution.siemMigrations.rules.tour.reprocessedLabel', + { + defaultMessage: 'Reprocessed', + } +); + +export const SIEM_MIGRATIONS_LINK_LABEL = i18n.translate( + 'xpack.securitySolution.siemMigrations.rules.tour.siemMigrationsLinkLabel', + { + defaultMessage: 'AI Translations here', + } +); diff --git a/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/pages/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/pages/index.tsx index c31048bf08bcf..ba6d7e5aa94ac 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/pages/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/pages/index.tsx @@ -30,6 +30,7 @@ import { useInvalidateGetMigrationTranslationStats } from '../logic/use_get_migr import { useGetIntegrations } from '../service/hooks/use_get_integrations'; import { PageTitle } from './page_title'; import { RuleMigrationsUploadMissingPanel } from '../components/migration_status_panels/upload_missing_panel'; +import { SiemTranslatedRulesTour } from '../components/tours/translation_guide'; type MigrationRulesPageProps = RouteComponentProps<{ migrationId?: string }>; @@ -133,6 +134,7 @@ export const MigrationRulesPage: React.FC = React.memo( <> + From cbb99c0e023dc9c8320a699d26f1870063910958 Mon Sep 17 00:00:00 2001 From: Ievgen Sorokopud Date: Tue, 21 Jan 2025 19:02:12 +0100 Subject: [PATCH 2/5] Update SIEM tour component location --- .../siem_migrations/rules/components/rules_table/index.tsx | 3 +++ .../public/siem_migrations/rules/pages/index.tsx | 2 -- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rules_table/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rules_table/index.tsx index 30c2a8e0b538a..4db6ebcbb72af 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rules_table/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rules_table/index.tsx @@ -41,6 +41,7 @@ import { useStartMigration } from '../../service/hooks/use_start_migration'; import type { FilterOptions } from '../../types'; import { MigrationRulesFilter } from './filters'; import { convertFilterOptions } from './utils/filters'; +import { SiemTranslatedRulesTour } from '../tours/translation_guide'; const DEFAULT_PAGE_SIZE = 10; const DEFAULT_SORT_FIELD = 'translation_result'; @@ -299,6 +300,8 @@ export const MigrationRulesTable: React.FC = React.mem return ( <> + {!isStatsLoading && translationStats?.rules.total && } + ; @@ -134,7 +133,6 @@ export const MigrationRulesPage: React.FC = React.memo( <> - From 2a3c89bd4375cfd0f9eefb12bf0bfbfb38c2a3db Mon Sep 17 00:00:00 2001 From: Ievgen Sorokopud Date: Tue, 21 Jan 2025 19:41:23 +0100 Subject: [PATCH 3/5] Fix translations validation --- .../rules/components/tours/translation_guide/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/tours/translation_guide/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/tours/translation_guide/index.tsx index f0967100502f1..17a9e6bddbf41 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/tours/translation_guide/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/tours/translation_guide/index.tsx @@ -46,7 +46,7 @@ const tourSteps: Array<{ title: i18n.TRANSLATION_STATUS_TOUR_STEP_TITLE, content: ( Date: Wed, 22 Jan 2025 15:29:05 +0100 Subject: [PATCH 4/5] Fix translations --- .../tours/setup_guide/translations.ts | 8 +++--- .../tours/translation_guide/translations.ts | 28 +++++++++---------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/tours/setup_guide/translations.ts b/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/tours/setup_guide/translations.ts index e5a57eea15507..825ec2981f289 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/tours/setup_guide/translations.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/tours/setup_guide/translations.ts @@ -8,21 +8,21 @@ import { i18n } from '@kbn/i18n'; export const SETUP_SIEM_MIGRATION_TOUR_TITLE = i18n.translate( - 'xpack.securitySolution.siemMigrations.rules.tour.setupSiemMigrationTourTitle', + 'xpack.securitySolution.siemMigrations.rules.tour.setupSiemMigrationGuide.title', { defaultMessage: 'Streamlined SIEM migration', } ); export const SETUP_SIEM_MIGRATION_TOUR_SUBTITLE = i18n.translate( - 'xpack.securitySolution.siemMigrations.rules.tour.setupSiemMigrationTourTitle', + 'xpack.securitySolution.siemMigrations.rules.tour.setupSiemMigrationGuide.subtitle', { defaultMessage: 'New onboarding guide!', } ); export const SETUP_SIEM_MIGRATION_TOUR_CONTENT = i18n.translate( - 'xpack.securitySolution.siemMigrations.rules.tour.setupSiemMigrationTourContent', + 'xpack.securitySolution.siemMigrations.rules.tour.setupSiemMigrationGuide.content', { defaultMessage: 'This is a step-by-step guide to quickly import your SIEM rules, assets, and data to Elastic Security. Powered by AI.', @@ -30,7 +30,7 @@ export const SETUP_SIEM_MIGRATION_TOUR_CONTENT = i18n.translate( ); export const FINISH_TOUR_BUTTON = i18n.translate( - 'xpack.securitySolution.siemMigrations.rules.tour.finishButton', + 'xpack.securitySolution.siemMigrations.rules.tour.setupSiemMigrationGuide.finishButton', { defaultMessage: 'OK', } diff --git a/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/tours/translation_guide/translations.ts b/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/tours/translation_guide/translations.ts index ee57d61dba208..3ab5a3d3083fb 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/tours/translation_guide/translations.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/tours/translation_guide/translations.ts @@ -8,14 +8,14 @@ import { i18n } from '@kbn/i18n'; export const MIGRATION_RULES_SELECTOR_TOUR_STEP_TITLE = i18n.translate( - 'xpack.securitySolution.siemMigrations.rules.tour.setupSiemMigrationTourTitle', + 'xpack.securitySolution.siemMigrations.rules.tour.translationRuleGuide.title', { defaultMessage: 'Translated rules in one place', } ); export const MIGRATION_RULES_SELECTOR_TOUR_STEP_CONTENT = i18n.translate( - 'xpack.securitySolution.siemMigrations.rules.tour.setupSiemMigrationTourContent', + 'xpack.securitySolution.siemMigrations.rules.tour.translationRuleGuide.content', { defaultMessage: 'Each migration’s translated rules appear on its SIEM rule translations page. Switch between your migrations using this dropdown. Start a new migration by clicking “Upload more rules for translation”.', @@ -23,21 +23,21 @@ export const MIGRATION_RULES_SELECTOR_TOUR_STEP_CONTENT = i18n.translate( ); export const TRANSLATION_STATUS_TOUR_STEP_TITLE = i18n.translate( - 'xpack.securitySolution.siemMigrations.rules.tour.translationStatusStepTitle', + 'xpack.securitySolution.siemMigrations.rules.tour.translationRuleGuide.statusStepTitle', { defaultMessage: 'Translation status', } ); export const MIGRATION_GUIDE_TOUR_STEP_TITLE = i18n.translate( - 'xpack.securitySolution.siemMigrations.rules.tour.migrationGuideStepTitle', + 'xpack.securitySolution.siemMigrations.rules.tour.translationRuleGuide.migrationGuideStepTitle', { defaultMessage: 'SIEM Rule Migration guide', } ); export const MIGRATION_GUIDE_TOUR_STEP_CONTENT = i18n.translate( - 'xpack.securitySolution.siemMigrations.rules.tour.migrationGuideStepContent', + 'xpack.securitySolution.siemMigrations.rules.tour.translationRuleGuide.migrationGuideStepContent', { defaultMessage: 'Your guide and migrated rules can always be found in the Onboarding Hub. Use it to review previous rule migrations or start a new one.', @@ -45,63 +45,63 @@ export const MIGRATION_GUIDE_TOUR_STEP_CONTENT = i18n.translate( ); export const NEXT_TOUR_STEP_BUTTON = i18n.translate( - 'xpack.securitySolution.siemMigrations.rules.tour.nextStepButton', + 'xpack.securitySolution.siemMigrations.rules.tour.translationRuleGuide.nextStepButton', { defaultMessage: 'Next', } ); export const FINISH_TOUR_BUTTON = i18n.translate( - 'xpack.securitySolution.siemMigrations.rules.tour.finishButton', + 'xpack.securitySolution.siemMigrations.rules.tour.translationRuleGuide.finishButton', { defaultMessage: 'OK', } ); export const INSTALL_LABEL = i18n.translate( - 'xpack.securitySolution.siemMigrations.rules.tour.installLabel', + 'xpack.securitySolution.siemMigrations.rules.tour.translationRuleGuide.installLabel', { defaultMessage: 'Install', } ); export const INSTALLED_LABEL = i18n.translate( - 'xpack.securitySolution.siemMigrations.rules.tour.installedLabel', + 'xpack.securitySolution.siemMigrations.rules.tour.translationRuleGuide.installedLabel', { defaultMessage: 'Installed', } ); export const VIEW_LABEL = i18n.translate( - 'xpack.securitySolution.siemMigrations.rules.tour.viewLabel', + 'xpack.securitySolution.siemMigrations.rules.tour.translationRuleGuide.viewLabel', { defaultMessage: 'View', } ); export const EDIT_LABEL = i18n.translate( - 'xpack.securitySolution.siemMigrations.rules.tour.editLabel', + 'xpack.securitySolution.siemMigrations.rules.tour.translationRuleGuide.editLabel', { defaultMessage: 'Edit', } ); export const TRANSLATED_LABEL = i18n.translate( - 'xpack.securitySolution.siemMigrations.rules.tour.translatedLabel', + 'xpack.securitySolution.siemMigrations.rules.tour.translationRuleGuide.translatedLabel', { defaultMessage: 'Translated', } ); export const REPROCESSED_LABEL = i18n.translate( - 'xpack.securitySolution.siemMigrations.rules.tour.reprocessedLabel', + 'xpack.securitySolution.siemMigrations.rules.tour.translationRuleGuide.reprocessedLabel', { defaultMessage: 'Reprocessed', } ); export const SIEM_MIGRATIONS_LINK_LABEL = i18n.translate( - 'xpack.securitySolution.siemMigrations.rules.tour.siemMigrationsLinkLabel', + 'xpack.securitySolution.siemMigrations.rules.tour.translationRuleGuide.siemMigrationsLinkLabel', { defaultMessage: 'AI Translations here', } From 37d58466514d18490f8a976061dd2aba098d3a8e Mon Sep 17 00:00:00 2001 From: Ievgen Sorokopud Date: Sat, 25 Jan 2025 13:05:36 +0100 Subject: [PATCH 5/5] Review feedback --- .../tours/translation_guide/index.tsx | 106 ++++-------------- .../tours/translation_guide/step_config.tsx | 79 +++++++++++++ 2 files changed, 101 insertions(+), 84 deletions(-) create mode 100644 x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/tours/translation_guide/step_config.tsx diff --git a/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/tours/translation_guide/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/tours/translation_guide/index.tsx index 17a9e6bddbf41..14b1f5bf8df2c 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/tours/translation_guide/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/tours/translation_guide/index.tsx @@ -6,83 +6,25 @@ */ import React, { useCallback, useEffect, useMemo, useState } from 'react'; -import type { PopoverAnchorPosition } from '@elastic/eui'; import { EuiButtonEmpty, EuiTourStep } from '@elastic/eui'; import { noop } from 'lodash'; -import { FormattedMessage } from '@kbn/i18n-react'; -import { DocLink } from '../../../../../common/components/links_to_docs/doc_link'; import { useIsElementMounted } from '../../../../../detection_engine/rule_management_ui/components/rules_table/rules_table/guided_onboarding/use_is_element_mounted'; -import { - NEW_FEATURES_TOUR_STORAGE_KEYS, - SecurityPageName, -} from '../../../../../../common/constants'; +import { NEW_FEATURES_TOUR_STORAGE_KEYS } from '../../../../../../common/constants'; import { useKibana } from '../../../../../common/lib/kibana'; -import { SIEM_MIGRATIONS_STATUS_HEADER_ID } from '../../rules_table_columns'; -import { SIEM_MIGRATIONS_SELECT_MIGRATION_BUTTON_ID } from '../../header_buttons'; +import { TourSteps, tourConfig, tourSteps } from './step_config'; import * as i18n from './translations'; -export const SECURITY_GET_STARTED_BUTTON_ANCHOR = `solutionSideNavCustomIconItem-${SecurityPageName.landing}`; - -const tourConfig = { - currentTourStep: 1, - isTourActive: true, - tourPopoverWidth: 360, -}; - -const tourSteps: Array<{ - step: number; - title: string; - content: React.ReactNode; - anchorPosition: PopoverAnchorPosition; -}> = [ - { - step: 1, - title: i18n.MIGRATION_RULES_SELECTOR_TOUR_STEP_TITLE, - content: i18n.MIGRATION_RULES_SELECTOR_TOUR_STEP_CONTENT, - anchorPosition: 'downCenter', - }, - { - step: 2, - title: i18n.TRANSLATION_STATUS_TOUR_STEP_TITLE, - content: ( - , - install: {i18n.INSTALL_LABEL}, - installed: {i18n.INSTALLED_LABEL}, - view: {i18n.VIEW_LABEL}, - edit: {i18n.EDIT_LABEL}, - translated: {i18n.TRANSLATED_LABEL}, - reprocessed: {i18n.REPROCESSED_LABEL}, - // TODO: Update doc path once available - link: , - }} - /> - ), - anchorPosition: 'rightCenter', - }, - { - step: 3, - title: i18n.MIGRATION_GUIDE_TOUR_STEP_TITLE, - content: i18n.MIGRATION_GUIDE_TOUR_STEP_CONTENT, - anchorPosition: 'rightCenter', - }, -]; - export const SiemTranslatedRulesTour: React.FC = React.memo(() => { const { siemMigrations, storage } = useKibana().services; - const isSelectMigrationAnchorMounted = useIsElementMounted( - SIEM_MIGRATIONS_SELECT_MIGRATION_BUTTON_ID - ); - const isStatusHeaderAnchorMounted = useIsElementMounted(SIEM_MIGRATIONS_STATUS_HEADER_ID); - const isGetStartedNavigationAnchorMounted = useIsElementMounted( - SECURITY_GET_STARTED_BUTTON_ANCHOR - ); + const stepsCount = Object.keys(tourSteps).length; + const selectMigrationStepData = tourSteps[TourSteps.MIGRATION_SELECTION]; + const statusHeaderStepData = tourSteps[TourSteps.MIGRATION_RULE_STATUS]; + const getStartedStepData = tourSteps[TourSteps.MIGRATION_ONBOARDING_HUB]; + + const isSelectMigrationAnchorMounted = useIsElementMounted(selectMigrationStepData.anchorId); + const isStatusHeaderAnchorMounted = useIsElementMounted(statusHeaderStepData.anchorId); + const isGetStartedNavigationAnchorMounted = useIsElementMounted(getStartedStepData.anchorId); const [tourState, setTourState] = useState(() => { const restoredTourState = storage.get( @@ -116,10 +58,6 @@ export const SiemTranslatedRulesTour: React.FC = React.memo(() => { return siemMigrations.rules.isAvailable() && tourState.isTourActive; }, [siemMigrations.rules, tourState]); - const selectMigrationStepData = tourSteps[0]; - const statusHeaderStepData = tourSteps[1]; - const getStartedStepData = tourSteps[2]; - return ( <> {isSelectMigrationAnchorMounted && ( @@ -127,10 +65,10 @@ export const SiemTranslatedRulesTour: React.FC = React.memo(() => { title={selectMigrationStepData.title} content={selectMigrationStepData.content} onFinish={noop} - step={1} - stepsTotal={tourSteps.length} - isStepOpen={isTourActive && tourState.currentTourStep === 1} - anchor={`#${SIEM_MIGRATIONS_SELECT_MIGRATION_BUTTON_ID}`} + step={selectMigrationStepData.step} + stepsTotal={stepsCount} + isStepOpen={isTourActive && tourState.currentTourStep === selectMigrationStepData.step} + anchor={`#${selectMigrationStepData.anchorId}`} anchorPosition={selectMigrationStepData.anchorPosition} maxWidth={tourState.tourPopoverWidth} footerAction={ @@ -145,10 +83,10 @@ export const SiemTranslatedRulesTour: React.FC = React.memo(() => { title={statusHeaderStepData.title} content={statusHeaderStepData.content} onFinish={noop} - step={2} - stepsTotal={tourSteps.length} - isStepOpen={isTourActive && tourState.currentTourStep === 2} - anchor={`#${SIEM_MIGRATIONS_STATUS_HEADER_ID}`} + step={statusHeaderStepData.step} + stepsTotal={stepsCount} + isStepOpen={isTourActive && tourState.currentTourStep === statusHeaderStepData.step} + anchor={`#${statusHeaderStepData.anchorId}`} anchorPosition={statusHeaderStepData.anchorPosition} maxWidth={tourState.tourPopoverWidth} footerAction={ @@ -163,10 +101,10 @@ export const SiemTranslatedRulesTour: React.FC = React.memo(() => { title={getStartedStepData.title} content={getStartedStepData.content} onFinish={noop} - step={3} - stepsTotal={tourSteps.length} - isStepOpen={isTourActive && tourState.currentTourStep === 3} - anchor={`#${SECURITY_GET_STARTED_BUTTON_ANCHOR}`} + step={getStartedStepData.step} + stepsTotal={stepsCount} + isStepOpen={isTourActive && tourState.currentTourStep === getStartedStepData.step} + anchor={`#${getStartedStepData.anchorId}`} anchorPosition={getStartedStepData.anchorPosition} maxWidth={tourState.tourPopoverWidth} footerAction={ diff --git a/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/tours/translation_guide/step_config.tsx b/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/tours/translation_guide/step_config.tsx new file mode 100644 index 0000000000000..ff4e4505cef4e --- /dev/null +++ b/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/tours/translation_guide/step_config.tsx @@ -0,0 +1,79 @@ +/* + * 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 { FormattedMessage } from '@kbn/i18n-react'; +import type { PopoverAnchorPosition } from '@elastic/eui'; +import { DocLink } from '../../../../../common/components/links_to_docs/doc_link'; +import { SecurityPageName } from '../../../../../../common/constants'; +import { SIEM_MIGRATIONS_SELECT_MIGRATION_BUTTON_ID } from '../../header_buttons'; +import { SIEM_MIGRATIONS_STATUS_HEADER_ID } from '../../rules_table_columns'; +import * as i18n from './translations'; + +export const SECURITY_GET_STARTED_BUTTON_ANCHOR = `solutionSideNavCustomIconItem-${SecurityPageName.landing}`; + +export enum TourSteps { + MIGRATION_SELECTION, + MIGRATION_RULE_STATUS, + MIGRATION_ONBOARDING_HUB, +} + +export const tourSteps: { + [key in TourSteps]: { + step: number; + title: string; + content: React.ReactNode; + anchorId: string; + anchorPosition: PopoverAnchorPosition; + }; +} = { + [TourSteps.MIGRATION_SELECTION]: { + step: 1, + title: i18n.MIGRATION_RULES_SELECTOR_TOUR_STEP_TITLE, + content: i18n.MIGRATION_RULES_SELECTOR_TOUR_STEP_CONTENT, + anchorId: SIEM_MIGRATIONS_SELECT_MIGRATION_BUTTON_ID, + anchorPosition: 'downCenter', + }, + [TourSteps.MIGRATION_RULE_STATUS]: { + step: 2, + title: i18n.TRANSLATION_STATUS_TOUR_STEP_TITLE, + content: ( + , + install: {i18n.INSTALL_LABEL}, + installed: {i18n.INSTALLED_LABEL}, + view: {i18n.VIEW_LABEL}, + edit: {i18n.EDIT_LABEL}, + translated: {i18n.TRANSLATED_LABEL}, + reprocessed: {i18n.REPROCESSED_LABEL}, + // TODO: Update doc path once available + link: , + }} + /> + ), + anchorId: SIEM_MIGRATIONS_STATUS_HEADER_ID, + anchorPosition: 'rightCenter', + }, + [TourSteps.MIGRATION_ONBOARDING_HUB]: { + step: 3, + title: i18n.MIGRATION_GUIDE_TOUR_STEP_TITLE, + content: i18n.MIGRATION_GUIDE_TOUR_STEP_CONTENT, + anchorId: SECURITY_GET_STARTED_BUTTON_ANCHOR, + anchorPosition: 'rightCenter', + }, +}; + +export const tourConfig = { + currentTourStep: tourSteps[TourSteps.MIGRATION_SELECTION].step, + isTourActive: true, + tourPopoverWidth: 360, +};