diff --git a/x-pack/plugins/security_solution/public/common/components/navigation/tab_navigation/tab_navigation.tsx b/x-pack/plugins/security_solution/public/common/components/navigation/tab_navigation/tab_navigation.tsx index 3efdc20bae5f3..0f38ff32cfefa 100644 --- a/x-pack/plugins/security_solution/public/common/components/navigation/tab_navigation/tab_navigation.tsx +++ b/x-pack/plugins/security_solution/public/common/components/navigation/tab_navigation/tab_navigation.tsx @@ -25,7 +25,6 @@ const TabNavigationItemComponent = ({ isSelected, isBeta, betaOptions, - tourAnchor, }: TabNavigationItemProps) => { const { getAppUrl, navigateTo } = useNavigation(); @@ -51,7 +50,7 @@ const TabNavigationItemComponent = ({ href={appHref} onClick={handleClick} append={isBeta && {betaOptions?.text ?? BETA}} - id={tourAnchor} + id={id} > {name} @@ -98,7 +97,6 @@ export const TabNavigationComponent: React.FC = ({ navTabs } isSelected={isSelected} isBeta={tab.isBeta} betaOptions={tab.betaOptions} - tourAnchor={tab.tourAnchor} /> ); }), diff --git a/x-pack/plugins/security_solution/public/common/components/navigation/tab_navigation/types.ts b/x-pack/plugins/security_solution/public/common/components/navigation/tab_navigation/types.ts index 5fb6a7a7c4c31..eda6b0c70caec 100644 --- a/x-pack/plugins/security_solution/public/common/components/navigation/tab_navigation/types.ts +++ b/x-pack/plugins/security_solution/public/common/components/navigation/tab_navigation/types.ts @@ -21,5 +21,4 @@ export interface TabNavigationItemProps { betaOptions?: { text: string; }; - tourAnchor?: string; } diff --git a/x-pack/plugins/security_solution/public/common/components/navigation/types.ts b/x-pack/plugins/security_solution/public/common/components/navigation/types.ts index f04dfbd9dfbc9..5091246fd451f 100644 --- a/x-pack/plugins/security_solution/public/common/components/navigation/types.ts +++ b/x-pack/plugins/security_solution/public/common/components/navigation/types.ts @@ -42,5 +42,4 @@ export interface NavTab { betaOptions?: { text: string; }; - tourAnchor?: string; } diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/json_diff/translations.ts b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/json_diff/translations.ts index b03c3f0a2085a..45aa87f1964f2 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/json_diff/translations.ts +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/json_diff/translations.ts @@ -17,20 +17,6 @@ export const EXPAND_UNCHANGED_LINES = (linesCount: number) => } ); -export const BASE_VERSION = i18n.translate( - 'xpack.securitySolution.detectionEngine.rules.upgradeRules.baseVersionLabel', - { - defaultMessage: 'Base version', - } -); - -export const BASE_VERSION_DESCRIPTION = i18n.translate( - 'xpack.securitySolution.detectionEngine.rules.upgradeRules.baseVersionDescriptionLabel', - { - defaultMessage: 'Shows currently installed rule', - } -); - export const CURRENT_RULE_VERSION = i18n.translate( 'xpack.securitySolution.detectionEngine.rules.upgradeRules.currentVersionLabel', { diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/rule_diff_tab.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/rule_diff_tab.tsx index d801f46e85696..52277d1cbad15 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/rule_diff_tab.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/rule_diff_tab.tsx @@ -150,13 +150,13 @@ export const RuleDiffTab = ({ oldRule, newRule }: RuleDiffTabProps) => { -
{i18n.BASE_VERSION}
+
{i18n.CURRENT_RULE_VERSION}
diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/feature_tour/rules_feature_tour.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/feature_tour/rules_feature_tour.tsx index d2f64ec882840..c12d254fc18d0 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/feature_tour/rules_feature_tour.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/feature_tour/rules_feature_tour.tsx @@ -22,9 +22,10 @@ import { } from '@elastic/eui'; import { noop } from 'lodash'; import type { FC } from 'react'; -import React, { useEffect, useMemo, useState } from 'react'; +import React, { useEffect, useMemo } from 'react'; import { NEW_FEATURES_TOUR_STORAGE_KEYS } from '../../../../../../common/constants'; import { useKibana } from '../../../../../common/lib/kibana'; +import { useIsElementMounted } from '../rules_table/guided_onboarding/use_is_element_mounted'; import * as i18n from './translations'; export interface RulesFeatureTourContextType { @@ -32,7 +33,8 @@ export interface RulesFeatureTourContextType { actions: EuiTourActions; } -export const SEARCH_CAPABILITIES_TOUR_ANCHOR = 'search-capabilities-tour-anchor'; +export const PER_FIELD_UPGRADE_TOUR_ANCHOR = 'updates'; +export const PREBUILT_RULE_UPDATE_FLYOUT_ANCHOR = 'updatePrebuiltRulePreview'; const TOUR_STORAGE_KEY = NEW_FEATURES_TOUR_STORAGE_KEYS.RULE_MANAGEMENT_PAGE; const TOUR_POPOVER_WIDTH = 400; @@ -41,14 +43,14 @@ const tourConfig: EuiTourState = { currentTourStep: 1, isTourActive: true, tourPopoverWidth: TOUR_POPOVER_WIDTH, - tourSubtitle: i18n.TOUR_TITLE, + tourSubtitle: '', }; const stepsConfig: EuiStatelessTourStep[] = [ { step: 1, - title: i18n.SEARCH_CAPABILITIES_TITLE, - content: {i18n.SEARCH_CAPABILITIES_DESCRIPTION}, + title: i18n.UPDATE_TOUR_TITLE, + content: {i18n.UPDATE_TOUR_DESCRIPTION}, stepsTotal: 1, children: <>, onFinish: noop, @@ -56,7 +58,7 @@ const stepsConfig: EuiStatelessTourStep[] = [ }, ]; -export const RulesFeatureTour: FC = () => { +export const RuleFeatureTour: FC = () => { const { storage } = useKibana().services; const restoredState = useMemo( @@ -74,28 +76,9 @@ export const RulesFeatureTour: FC = () => { storage.set(TOUR_STORAGE_KEY, { isTourActive, currentTourStep }); }, [tourState, storage]); - const [shouldShowSearchCapabilitiesTour, setShouldShowSearchCapabilitiesTour] = useState(false); - - useEffect(() => { - /** - * Wait until the tour target elements are visible on the page and mount - * EuiTourStep components only after that. Otherwise, the tours would never - * show up on the page. - */ - const observer = new MutationObserver(() => { - if (document.querySelector(`#${SEARCH_CAPABILITIES_TOUR_ANCHOR}`)) { - setShouldShowSearchCapabilitiesTour(true); - observer.disconnect(); - } - }); - - observer.observe(document.body, { - childList: true, - subtree: true, - }); - - return () => observer.disconnect(); - }, []); + const isTourAnchorMounted = useIsElementMounted(PER_FIELD_UPGRADE_TOUR_ANCHOR); + const isFlyoutOpen = useIsElementMounted(PREBUILT_RULE_UPDATE_FLYOUT_ANCHOR); + const shouldShowRuleUpgradeTour = isTourAnchorMounted && !isFlyoutOpen; const enhancedSteps = useMemo( () => @@ -135,7 +118,7 @@ export const RulesFeatureTour: FC = () => { [tourSteps, tourActions] ); - return shouldShowSearchCapabilitiesTour ? ( + return shouldShowRuleUpgradeTour ? ( { */ // eslint-disable-next-line react/no-children-prop children={undefined} - anchor={`#${SEARCH_CAPABILITIES_TOUR_ANCHOR}`} + anchor={`#${PER_FIELD_UPGRADE_TOUR_ANCHOR}`} anchorPosition="downCenter" /> ) : null; diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/feature_tour/translations.ts b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/feature_tour/translations.ts index 45715c6ca76d8..6c7a3f6b37de6 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/feature_tour/translations.ts +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/feature_tour/translations.ts @@ -28,17 +28,17 @@ export const NEXT_STEP_LABEL = i18n.translate( } ); -export const SEARCH_CAPABILITIES_TITLE = i18n.translate( - 'xpack.securitySolution.detectionEngine.rules.allRules.featureTour.searchCapabilitiesTitle', +export const UPDATE_TOUR_TITLE = i18n.translate( + 'xpack.securitySolution.detectionEngine.ruleDetails.updateTourTitle', { - defaultMessage: 'Enhanced search capabilities', + defaultMessage: 'New field view of updates', } ); -export const SEARCH_CAPABILITIES_DESCRIPTION = i18n.translate( - 'xpack.securitySolution.detectionEngine.rules.allRules.featureTour.searchCapabilitiesDescription', +export const UPDATE_TOUR_DESCRIPTION = i18n.translate( + 'xpack.securitySolution.detectionEngine.ruleDetails.updateTourDescription', { defaultMessage: - 'It is now possible to search rules by index patterns, like "filebeat-*", or by MITRE ATT&CK™ tactics or techniques, like "Defense Evasion" or "TA0005".', + 'You can now view the diff of updates in the flyout by clicking on the rule name.', } ); diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/rules_table_toolbar.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/rules_table_toolbar.tsx index 691aeb812cd51..fb2c17ddb2fa1 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/rules_table_toolbar.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/rules_table_toolbar.tsx @@ -17,7 +17,6 @@ import { getPromptContextFromDetectionRules } from '../../../../assistant/helper import { useRulesTableContext } from './rules_table/rules_table_context'; import { useAssistantAvailability } from '../../../../assistant/use_assistant_availability'; import * as i18nAssistant from '../../../../detections/pages/detection_engine/rules/translations'; -import { PER_FIELD_UPGRADE_TOUR_ANCHOR } from './upgrade_prebuilt_rules_table/upgrade_prebuilt_rules_tour'; export enum AllRulesTabs { management = 'management', @@ -71,7 +70,6 @@ export const RulesTableToolbar = React.memo(() => { betaOptions: { text: `${updateTotal}`, }, - tourAnchor: PER_FIELD_UPGRADE_TOUR_ANCHOR, }, } : {}), diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table/translations.ts b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table/translations.ts index c3c72fbbe718a..264002464a03e 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table/translations.ts +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table/translations.ts @@ -38,21 +38,6 @@ export const UPDATE_BUTTON_LABEL = i18n.translate( } ); -export const UPDATE_TOUR_TITLE = i18n.translate( - 'xpack.securitySolution.detectionEngine.ruleDetails.updateTourTitle', - { - defaultMessage: 'New field view of updates', - } -); - -export const UPDATE_TOUR_DESCRIPTION = i18n.translate( - 'xpack.securitySolution.detectionEngine.ruleDetails.updateTourDescription', - { - defaultMessage: - 'You can now view the diff of updates in the flyout by clicking on the rule name.', - } -); - export const UPDATE_FLYOUT_PER_FIELD_TOOLTIP_DESCRIPTION = i18n.translate( 'xpack.securitySolution.detectionEngine.ruleDetails.perFieldTooltip', { diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table/upgrade_prebuilt_rules_table_context.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table/upgrade_prebuilt_rules_table_context.tsx index dde8a74de1a93..925679c423e9f 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table/upgrade_prebuilt_rules_table_context.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table/upgrade_prebuilt_rules_table_context.tsx @@ -35,7 +35,7 @@ import { MlJobUpgradeModal } from '../../../../../detections/components/modals/m import { useIsExperimentalFeatureEnabled } from '../../../../../common/hooks/use_experimental_features'; import * as ruleDetailsI18n from '../../../../rule_management/components/rule_details/translations'; import * as i18n from './translations'; -import { PREBUILT_RULE_UPDATE_FLYOUT_ANCHOR } from './upgrade_prebuilt_rules_tour'; +import { PREBUILT_RULE_UPDATE_FLYOUT_ANCHOR } from '../feature_tour/rules_feature_tour'; export interface UpgradePrebuiltRulesTableState { /** diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table/upgrade_prebuilt_rules_tour.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table/upgrade_prebuilt_rules_tour.tsx deleted file mode 100644 index cfb2d7bade30d..0000000000000 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table/upgrade_prebuilt_rules_tour.tsx +++ /dev/null @@ -1,97 +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. - */ - -import type { - EuiStatelessTourStep, - EuiTourActions, - EuiTourState, - EuiTourStepProps, -} from '@elastic/eui'; -import { EuiText, EuiTourStep, useEuiTour } from '@elastic/eui'; -import { noop } from 'lodash'; -import type { FC } from 'react'; -import React, { useEffect, useMemo } from 'react'; -import { NEW_FEATURES_TOUR_STORAGE_KEYS } from '../../../../../../common/constants'; -import { useKibana } from '../../../../../common/lib/kibana'; -import { useIsElementMounted } from '../rules_table/guided_onboarding/use_is_element_mounted'; -import * as i18n from './translations'; - -export interface RulesFeatureTourContextType { - steps: EuiTourStepProps[]; - actions: EuiTourActions; -} - -export const PER_FIELD_UPGRADE_TOUR_ANCHOR = 'perFieldUpgradeTour'; -export const PREBUILT_RULE_UPDATE_FLYOUT_ANCHOR = 'updatePrebuiltRulePreview'; - -const TOUR_STORAGE_KEY = NEW_FEATURES_TOUR_STORAGE_KEYS.RULE_MANAGEMENT_PAGE; -const TOUR_POPOVER_WIDTH = 400; - -const tourConfig: EuiTourState = { - currentTourStep: 1, - isTourActive: true, - tourPopoverWidth: TOUR_POPOVER_WIDTH, - tourSubtitle: '', -}; - -const stepsConfig: EuiStatelessTourStep[] = [ - { - step: 1, - title: i18n.UPDATE_TOUR_TITLE, - content: {i18n.UPDATE_TOUR_DESCRIPTION}, - stepsTotal: 1, - children: <>, - onFinish: noop, - maxWidth: TOUR_POPOVER_WIDTH, - }, -]; - -export const PrebuiltRulesUpgradeTour: FC = () => { - const { storage } = useKibana().services; - - const restoredState = useMemo( - () => ({ - ...tourConfig, - ...storage.get(TOUR_STORAGE_KEY), - }), - [storage] - ); - - const [tourSteps, , tourState] = useEuiTour(stepsConfig, restoredState); - - useEffect(() => { - const { isTourActive, currentTourStep } = tourState; - storage.set(TOUR_STORAGE_KEY, { isTourActive, currentTourStep }); - }, [tourState, storage]); - - const isTourAnchorMounted = useIsElementMounted(PER_FIELD_UPGRADE_TOUR_ANCHOR); - const isFlyoutOpen = useIsElementMounted(PREBUILT_RULE_UPDATE_FLYOUT_ANCHOR); - const shouldShowRuleUpgradeTour = isTourAnchorMounted && !isFlyoutOpen; - - const enhancedSteps = useMemo( - () => - tourSteps.map((item) => ({ - ...item, - content: item.content, - })), - [tourSteps] - ); - - return shouldShowRuleUpgradeTour ? ( - - ) : null; -}; diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/pages/rule_management/index.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/pages/rule_management/index.tsx index 020333ea804b4..6567d3e2ee248 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/pages/rule_management/index.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/pages/rule_management/index.tsx @@ -9,6 +9,7 @@ import { EuiButtonEmpty, EuiFlexGroup, EuiFlexItem, EuiToolTip } from '@elastic/ import { MaintenanceWindowCallout } from '@kbn/alerts-ui-shared'; import React, { useCallback } from 'react'; import { DEFAULT_APP_CATEGORIES } from '@kbn/core-application-common'; +import { useIsExperimentalFeatureEnabled } from '../../../../common/hooks/use_experimental_features'; import { APP_UI_ID } from '../../../../../common/constants'; import { SecurityPageName } from '../../../../app/types'; import { ImportDataModal } from '../../../../common/components/import_data_modal'; @@ -35,7 +36,7 @@ import { AllRules } from '../../components/rules_table'; import { RulesTableContextProvider } from '../../components/rules_table/rules_table/rules_table_context'; import { useInvalidateFetchCoverageOverviewQuery } from '../../../rule_management/api/hooks/use_fetch_coverage_overview_query'; import { HeaderPage } from '../../../../common/components/header_page'; -import { PrebuiltRulesUpgradeTour } from '../../components/rules_table/upgrade_prebuilt_rules_table/upgrade_prebuilt_rules_tour'; +import { RuleFeatureTour } from '../../components/rules_table/feature_tour/rules_feature_tour'; const RulesPageComponent: React.FC = () => { const [isImportModalVisible, showImportModal, hideImportModal] = useBoolState(); @@ -54,6 +55,9 @@ const RulesPageComponent: React.FC = () => { invalidateFetchRuleManagementFilters, invalidateFetchCoverageOverviewQuery, ]); + const isPerFieldPrebuiltRulesDiffingEnabled = useIsExperimentalFeatureEnabled( + 'perFieldPrebuiltRulesDiffingEnabled' + ); const [ { @@ -173,7 +177,7 @@ const RulesPageComponent: React.FC = () => { kibanaServices={kibanaServices} categories={[DEFAULT_APP_CATEGORIES.security.id]} /> - + {isPerFieldPrebuiltRulesDiffingEnabled && }