From 774d3591c083e14bdd56339f2a93eb27e1d531f5 Mon Sep 17 00:00:00 2001 From: Angela Chuang <6295984+angorayc@users.noreply.github.com> Date: Wed, 29 Jul 2020 01:03:45 +0100 Subject: [PATCH] [Security Solution] Update security overview splash (#73050) ## Summary https://github.com/elastic/endpoint-app-team/issues/591 How to verify: 1. go to: x-pack/test/security_solution_cypress/runner.ts 2. comment line 20 (await esArchiver.load('auditbeat');) 3. in line 25 change cypress:run for cypress:open 4. then in our directory run yarn cypress:run-as-ci when the cypress is open, 5. you can access the Kibana instance in port 5620 with username elastic and password changeme Screenshot 2020-07-23 at 14 48 34 ### Checklist Delete any items that are not applicable to this PR. - [x] Any text added follows [EUI's writing guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses sentence case text and includes [i18n support](https://github.com/elastic/kibana/blob/master/packages/kbn-i18n/README.md) - [ ] ~[Documentation](https://github.com/elastic/kibana/blob/master/CONTRIBUTING.md#writing-documentation) was added for features that require explanation or tutorials~ - [ ] ~[Unit or functional tests](https://github.com/elastic/kibana/blob/master/CONTRIBUTING.md#cross-browser-compatibility) were updated or added to match the most common scenarios~ - [ ] ~This was checked for [keyboard-only and screenreader accessibility](https://developer.mozilla.org/en-US/docs/Learn/Tools_and_testing/Cross_browser_testing/Accessibility#Accessibility_testing_checklist)~ - [ ] ~This renders correctly on smaller devices using a responsive layout. (You can test this [in your browser](https://www.browserstack.com/guide/responsive-testing-on-local-server)~ - [ ] ~This was checked for [cross-browser compatibility](https://www.elastic.co/support/matrix#matrix_browsers)~ ### For maintainers - [ ] ~This was checked for breaking API changes and was [labeled appropriately](https://github.com/elastic/kibana/blob/master/CONTRIBUTING.md#release-notes-process)~ --- .../public/doc_links/doc_links_service.ts | 2 +- .../pages/saved_object_no_permissions.tsx | 18 +- .../__snapshots__/index.test.tsx.snap | 24 ++- .../components/empty_page/index.test.tsx | 14 +- .../common/components/empty_page/index.tsx | 157 +++++++++++------- .../public/common/translations.ts | 39 ++++- .../detection_engine.test.tsx | 3 + .../detection_engine_no_signal_index.tsx | 19 ++- .../detection_engine_user_unauthenticated.tsx | 19 ++- .../pages/detection_engine/translations.ts | 4 +- .../components/overview_empty/index.test.tsx | 83 +++++++++ .../components/overview_empty/index.tsx | 53 ++++-- .../public/overview/pages/overview.test.tsx | 4 +- .../public/overview/pages/overview.tsx | 2 +- .../translations/translations/ja-JP.json | 4 +- .../translations/translations/zh-CN.json | 4 +- 16 files changed, 331 insertions(+), 118 deletions(-) create mode 100644 x-pack/plugins/security_solution/public/overview/components/overview_empty/index.test.tsx diff --git a/src/core/public/doc_links/doc_links_service.ts b/src/core/public/doc_links/doc_links_service.ts index 70b25cb78787a..eb54983d0be13 100644 --- a/src/core/public/doc_links/doc_links_service.ts +++ b/src/core/public/doc_links/doc_links_service.ts @@ -112,7 +112,7 @@ export class DocLinksService { kibana: `${ELASTIC_WEBSITE_URL}guide/en/kibana/${DOC_LINK_VERSION}/index.html`, siem: { guide: `${ELASTIC_WEBSITE_URL}guide/en/security/${DOC_LINK_VERSION}/index.html`, - gettingStarted: `${ELASTIC_WEBSITE_URL}guide/en/security/${DOC_LINK_VERSION}/install-siem.html`, + gettingStarted: `${ELASTIC_WEBSITE_URL}guide/en/security/${DOC_LINK_VERSION}/index.html`, }, query: { luceneQuerySyntax: `${ELASTICSEARCH_DOCS}query-dsl-query-string-query.html#query-string-syntax`, diff --git a/x-pack/plugins/security_solution/public/cases/pages/saved_object_no_permissions.tsx b/x-pack/plugins/security_solution/public/cases/pages/saved_object_no_permissions.tsx index 7129aa04bdf69..c61ff6d18caab 100644 --- a/x-pack/plugins/security_solution/public/cases/pages/saved_object_no_permissions.tsx +++ b/x-pack/plugins/security_solution/public/cases/pages/saved_object_no_permissions.tsx @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import React from 'react'; +import React, { useMemo } from 'react'; import { EmptyPage } from '../../common/components/empty_page'; import * as i18n from './translations'; @@ -12,13 +12,21 @@ import { useKibana } from '../../common/lib/kibana'; export const CaseSavedObjectNoPermissions = React.memo(() => { const docLinks = useKibana().services.docLinks; + const actions = useMemo( + () => ({ + savedObject: { + icon: 'documents', + label: i18n.GO_TO_DOCUMENTATION, + url: `${docLinks.ELASTIC_WEBSITE_URL}guide/en/security/${docLinks.DOC_LINK_VERSION}s`, + target: '_blank', + }, + }), + [docLinks] + ); return ( - - Do Something - + + Do Something + + } + title={false} + /> } diff --git a/x-pack/plugins/security_solution/public/common/components/empty_page/index.test.tsx b/x-pack/plugins/security_solution/public/common/components/empty_page/index.test.tsx index 6a14c12cee0f8..8e025faefeabe 100644 --- a/x-pack/plugins/security_solution/public/common/components/empty_page/index.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/empty_page/index.test.tsx @@ -10,12 +10,12 @@ import React from 'react'; import { EmptyPage } from './index'; test('renders correctly', () => { - const EmptyComponent = shallow( - - ); + const actions = { + actions: { + label: 'Do Something', + url: 'my/url/from/nowwhere', + }, + }; + const EmptyComponent = shallow(); expect(EmptyComponent).toMatchSnapshot(); }); diff --git a/x-pack/plugins/security_solution/public/common/components/empty_page/index.tsx b/x-pack/plugins/security_solution/public/common/components/empty_page/index.tsx index f6d6752729b6d..89f4b125e930c 100644 --- a/x-pack/plugins/security_solution/public/common/components/empty_page/index.tsx +++ b/x-pack/plugins/security_solution/public/common/components/empty_page/index.tsx @@ -4,84 +4,123 @@ * you may not use this file except in compliance with the Elastic License. */ -import { EuiButton, EuiEmptyPrompt, EuiFlexGroup, EuiFlexItem, IconType } from '@elastic/eui'; -import React, { MouseEventHandler, ReactNode } from 'react'; +import { + EuiButton, + EuiEmptyPrompt, + EuiFlexGroup, + EuiFlexItem, + IconType, + EuiCard, +} from '@elastic/eui'; +import React, { MouseEventHandler, ReactNode, useMemo } from 'react'; import styled from 'styled-components'; const EmptyPrompt = styled(EuiEmptyPrompt)` align-self: center; /* Corrects horizontal centering in IE11 */ + max-width: 60em; `; EmptyPrompt.displayName = 'EmptyPrompt'; +interface EmptyPageActions { + icon?: IconType; + label: string; + target?: string; + url: string; + descriptionTitle?: string; + description?: string; + fill?: boolean; + onClick?: MouseEventHandler; +} + +export type EmptyPageActionsProps = Record; + interface EmptyPageProps { - actionPrimaryIcon?: IconType; - actionPrimaryLabel: string; - actionPrimaryTarget?: string; - actionPrimaryUrl: string; - actionPrimaryFill?: boolean; - actionSecondaryIcon?: IconType; - actionSecondaryLabel?: string; - actionSecondaryTarget?: string; - actionSecondaryUrl?: string; - actionSecondaryOnClick?: MouseEventHandler; + actions: EmptyPageActionsProps; 'data-test-subj'?: string; message?: ReactNode; title: string; } -export const EmptyPage = React.memo( - ({ - actionPrimaryIcon, - actionPrimaryLabel, - actionPrimaryTarget, - actionPrimaryUrl, - actionPrimaryFill = true, - actionSecondaryIcon, - actionSecondaryLabel, - actionSecondaryTarget, - actionSecondaryUrl, - actionSecondaryOnClick, - message, - title, - ...rest - }) => ( +const EmptyPageComponent = React.memo(({ actions, message, title, ...rest }) => { + const titles = Object.keys(actions); + const maxItemWidth = 283; + const renderActions = useMemo( + () => + Object.values(actions) + .filter((a) => a.label && a.url) + .map( + ( + { + icon, + label, + target, + url, + descriptionTitle = false, + description = false, + onClick, + fill = true, + }, + idx + ) => + descriptionTitle != null || description != null ? ( + + + {label} + + } + /> + + ) : ( + + {/* eslint-disable-next-line @elastic/eui/href-or-on-click */} + + {label} + + + ) + ), + [actions, titles] + ); + + return ( {title}} body={message &&

{message}

} - actions={ - - - - {actionPrimaryLabel} - - - - {actionSecondaryLabel && actionSecondaryUrl && ( - - {/* eslint-disable-next-line @elastic/eui/href-or-on-click */} - - {actionSecondaryLabel} - - - )} - - } + actions={{renderActions}} {...rest} /> - ) -); + ); +}); + +EmptyPageComponent.displayName = 'EmptyPageComponent'; +export const EmptyPage = React.memo(EmptyPageComponent); EmptyPage.displayName = 'EmptyPage'; diff --git a/x-pack/plugins/security_solution/public/common/translations.ts b/x-pack/plugins/security_solution/public/common/translations.ts index 413119fb40f14..3b94ac8959496 100644 --- a/x-pack/plugins/security_solution/public/common/translations.ts +++ b/x-pack/plugins/security_solution/public/common/translations.ts @@ -7,16 +7,39 @@ import { i18n } from '@kbn/i18n'; export const EMPTY_TITLE = i18n.translate('xpack.securitySolution.pages.common.emptyTitle', { - defaultMessage: 'Welcome to Security Solution. Let’s get you started.', + defaultMessage: 'Welcome to Elastic Security. Let’s get you started.', }); -export const EMPTY_ACTION_PRIMARY = i18n.translate( - 'xpack.securitySolution.pages.common.emptyActionPrimary', +export const EMPTY_ACTION_ELASTIC_AGENT = i18n.translate( + 'xpack.securitySolution.pages.common.emptyActionElasticAgent', + { + defaultMessage: 'Add data with Elastic Agent', + } +); + +export const EMPTY_ACTION_ELASTIC_AGENT_DESCRIPTION = i18n.translate( + 'xpack.securitySolution.pages.common.emptyActionElasticAgentDescription', + { + defaultMessage: + 'The Elastic Agent provides a simple, unified way to add monitoring to your hosts.', + } +); + +export const EMPTY_ACTION_BEATS = i18n.translate( + 'xpack.securitySolution.pages.common.emptyActionBeats', { defaultMessage: 'Add data with Beats', } ); +export const EMPTY_ACTION_BEATS_DESCRIPTION = i18n.translate( + 'xpack.securitySolution.pages.common.emptyActionBeatsDescription', + { + defaultMessage: + 'Lightweight Beats can send data from hundreds or thousands of machines and systems', + } +); + export const EMPTY_ACTION_SECONDARY = i18n.translate( 'xpack.securitySolution.pages.common.emptyActionSecondary', { @@ -27,6 +50,14 @@ export const EMPTY_ACTION_SECONDARY = i18n.translate( export const EMPTY_ACTION_ENDPOINT = i18n.translate( 'xpack.securitySolution.pages.common.emptyActionEndpoint', { - defaultMessage: 'Add data with Elastic Agent (Beta)', + defaultMessage: 'Add Elastic Endpoint Security', + } +); + +export const EMPTY_ACTION_ENDPOINT_DESCRIPTION = i18n.translate( + 'xpack.securitySolution.pages.common.emptyActionEndpointDescription', + { + defaultMessage: + 'Protect your hosts with threat prevention, detection, and deep security data visibility.', } ); diff --git a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/detection_engine.test.tsx b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/detection_engine.test.tsx index 110620fad7eba..982712cbe9797 100644 --- a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/detection_engine.test.tsx +++ b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/detection_engine.test.tsx @@ -53,6 +53,9 @@ jest.mock('react-router-dom', () => { useHistory: jest.fn(), }; }); +jest.mock('../../components/alerts_info', () => ({ + useAlertInfo: jest.fn().mockReturnValue([]), +})); const state: State = { ...mockGlobalState, diff --git a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/detection_engine_no_signal_index.tsx b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/detection_engine_no_signal_index.tsx index 32ae585aec191..c315361b294c7 100644 --- a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/detection_engine_no_signal_index.tsx +++ b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/detection_engine_no_signal_index.tsx @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import React from 'react'; +import React, { useMemo } from 'react'; import { EmptyPage } from '../../../common/components/empty_page'; import * as i18n from './translations'; @@ -12,12 +12,21 @@ import { useKibana } from '../../../common/lib/kibana'; export const DetectionEngineNoIndex = React.memo(() => { const docLinks = useKibana().services.docLinks; + const actions = useMemo( + () => ({ + detections: { + icon: 'documents', + label: i18n.GO_TO_DOCUMENTATION, + url: `${docLinks.ELASTIC_WEBSITE_URL}guide/en/security/${docLinks.DOC_LINK_VERSION}/detection-engine-overview.html#detections-permissions`, + target: '_blank', + }, + }), + [docLinks] + ); + return ( { const docLinks = useKibana().services.docLinks; - + const actions = useMemo( + () => ({ + detectionUnauthenticated: { + icon: 'documents', + label: i18n.GO_TO_DOCUMENTATION, + url: `${docLinks.ELASTIC_WEBSITE_URL}guide/en/security/${docLinks.DOC_LINK_VERSION}/detection-engine-overview.html#detections-permissions`, + target: '_blank', + }, + }), + [docLinks] + ); return ( ({ + useIngestUrl: jest + .fn() + .mockReturnValue({ appId: 'ingestAppId', appPath: 'ingestPath', url: 'ingestUrl' }), +})); + +jest.mock('../../../common/hooks/endpoint/ingest_enabled', () => ({ + useIngestEnabledCheck: jest.fn().mockReturnValue({ allEnabled: true }), +})); + +jest.mock('../../../common/hooks/endpoint/use_navigate_to_app_event_handler', () => ({ + useNavigateToAppEventHandler: jest.fn(), +})); + +describe('OverviewEmpty', () => { + describe('When isIngestEnabled = true', () => { + let wrapper: ShallowWrapper; + beforeAll(() => { + wrapper = shallow(); + }); + + afterAll(() => { + (useIngestEnabledCheck as jest.Mock).mockReset(); + }); + + test('render with correct actions ', () => { + expect(wrapper.find('[data-test-subj="empty-page"]').prop('actions')).toEqual({ + beats: { + description: + 'Lightweight Beats can send data from hundreds or thousands of machines and systems', + fill: false, + label: 'Add data with Beats', + url: '/app/home#/tutorial_directory/security', + }, + elasticAgent: { + description: + 'The Elastic Agent provides a simple, unified way to add monitoring to your hosts.', + fill: false, + label: 'Add data with Elastic Agent', + url: 'ingestUrl', + }, + endpoint: { + description: + 'Protect your hosts with threat prevention, detection, and deep security data visibility.', + fill: false, + label: 'Add Elastic Endpoint Security', + onClick: undefined, + url: '/app/home#/tutorial_directory/security', + }, + }); + }); + }); + + describe('When isIngestEnabled = false', () => { + let wrapper: ShallowWrapper; + beforeAll(() => { + (useIngestEnabledCheck as jest.Mock).mockReturnValue({ allEnabled: false }); + wrapper = shallow(); + }); + + test('render with correct actions ', () => { + expect(wrapper.find('[data-test-subj="empty-page"]').prop('actions')).toEqual({ + beats: { + description: + 'Lightweight Beats can send data from hundreds or thousands of machines and systems', + fill: false, + label: 'Add data with Beats', + url: '/app/home#/tutorial_directory/security', + }, + }); + }); + }); +}); diff --git a/x-pack/plugins/security_solution/public/overview/components/overview_empty/index.tsx b/x-pack/plugins/security_solution/public/overview/components/overview_empty/index.tsx index 33413be10079e..1d2c6889213f1 100644 --- a/x-pack/plugins/security_solution/public/overview/components/overview_empty/index.tsx +++ b/x-pack/plugins/security_solution/public/overview/components/overview_empty/index.tsx @@ -4,11 +4,13 @@ * you may not use this file except in compliance with the Elastic License. */ -import React from 'react'; +import React, { useMemo } from 'react'; +import { omit } from 'lodash/fp'; + import { FormattedMessage } from '@kbn/i18n/react'; import { EuiLink } from '@elastic/eui'; import * as i18nCommon from '../../../common/translations'; -import { EmptyPage } from '../../../common/components/empty_page'; +import { EmptyPage, EmptyPageActionsProps } from '../../../common/components/empty_page'; import { useKibana } from '../../../common/lib/kibana'; import { ADD_DATA_PATH } from '../../../../common/constants'; import { useIngestUrl } from '../../../management/pages/endpoint_hosts/view/hooks'; @@ -23,23 +25,45 @@ const OverviewEmptyComponent: React.FC = () => { ); const handleOnClick = useNavigateToAppEventHandler(ingestAppId, { path: ingestPath }); const { allEnabled: isIngestEnabled } = useIngestEnabledCheck(); + const emptyPageActions: EmptyPageActionsProps = useMemo( + () => ({ + elasticAgent: { + label: i18nCommon.EMPTY_ACTION_ELASTIC_AGENT, + url: ingestUrl, + description: i18nCommon.EMPTY_ACTION_ELASTIC_AGENT_DESCRIPTION, + fill: false, + }, + beats: { + label: i18nCommon.EMPTY_ACTION_BEATS, + url: `${basePath}${ADD_DATA_PATH}`, + description: i18nCommon.EMPTY_ACTION_BEATS_DESCRIPTION, + fill: false, + }, + endpoint: { + label: i18nCommon.EMPTY_ACTION_ENDPOINT, + url: `${basePath}${ADD_DATA_PATH}`, + description: i18nCommon.EMPTY_ACTION_ENDPOINT_DESCRIPTION, + onClick: handleOnClick, + fill: false, + }, + }), + [basePath, ingestUrl, handleOnClick] + ); + + const emptyPageIngestDisabledActions = useMemo( + () => omit(['elasticAgent', 'endpoint'], emptyPageActions), + [emptyPageActions] + ); return isIngestEnabled === true ? ( {i18nCommon.EMPTY_ACTION_SECONDARY} @@ -50,16 +74,13 @@ const OverviewEmptyComponent: React.FC = () => { /> ) : ( {i18nCommon.EMPTY_ACTION_SECONDARY} diff --git a/x-pack/plugins/security_solution/public/overview/pages/overview.test.tsx b/x-pack/plugins/security_solution/public/overview/pages/overview.test.tsx index 286cc870378e1..74225c4e4f823 100644 --- a/x-pack/plugins/security_solution/public/overview/pages/overview.test.tsx +++ b/x-pack/plugins/security_solution/public/overview/pages/overview.test.tsx @@ -83,7 +83,7 @@ describe('Overview', () => { ); - expect(wrapper.find('[data-test-subj="empty-page-secondary-action"]').exists()).toBe(false); + expect(wrapper.find('[data-test-subj="empty-page-endpoint-action"]').exists()).toBe(false); }); it('shows Endpoint get ready button when ingest is enabled', () => { @@ -95,7 +95,7 @@ describe('Overview', () => { ); - expect(wrapper.find('[data-test-subj="empty-page-secondary-action"]').exists()).toBe(true); + expect(wrapper.find('[data-test-subj="empty-page-endpoint-action"]').exists()).toBe(true); }); }); diff --git a/x-pack/plugins/security_solution/public/overview/pages/overview.tsx b/x-pack/plugins/security_solution/public/overview/pages/overview.tsx index 423aa597a0129..1b743c259555a 100644 --- a/x-pack/plugins/security_solution/public/overview/pages/overview.tsx +++ b/x-pack/plugins/security_solution/public/overview/pages/overview.tsx @@ -17,6 +17,7 @@ import { SiemSearchBar } from '../../common/components/search_bar'; import { WrapperPage } from '../../common/components/wrapper_page'; import { useGlobalTime } from '../../common/containers/use_global_time'; import { useWithSource } from '../../common/containers/source'; + import { EventsByDataset } from '../components/events_by_dataset'; import { EventCounts } from '../components/event_counts'; import { OverviewEmpty } from '../components/overview_empty'; @@ -66,7 +67,6 @@ const OverviewComponent: React.FC = ({ addMessage('management', 'dismissEndpointNotice'); }, [addMessage]); const { allEnabled: isIngestEnabled } = useIngestEnabledCheck(); - return ( <> {indicesExist ? ( diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index b6aaa2065c795..8fbcb3f1122cc 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -13572,7 +13572,7 @@ "xpack.securitySolution.detectionEngine.editRule.errorMsgDescription": "申し訳ありません", "xpack.securitySolution.detectionEngine.editRule.pageTitle": "ルール設定の編集", "xpack.securitySolution.detectionEngine.editRule.saveChangeTitle": "変更を保存", - "xpack.securitySolution.detectionEngine.emptyActionPrimary": "セットアップの手順を表示", + "xpack.securitySolution.detectionEngine.emptyActionBeats": "セットアップの手順を表示", "xpack.securitySolution.detectionEngine.emptyActionSecondary": "ドキュメントに移動", "xpack.securitySolution.detectionEngine.emptyTitle": "Securityアプリケーションの検出エンジンに関連したインデックスがないようです", "xpack.securitySolution.detectionEngine.goToDocumentationButton": "ドキュメンテーションを表示", @@ -14349,7 +14349,7 @@ "xpack.securitySolution.overview.viewEventsButtonLabel": "イベントを表示", "xpack.securitySolution.overview.winlogbeatMWSysmonOperational": "Microsoft-Windows-Sysmon/Operational", "xpack.securitySolution.overview.winlogbeatSecurityTitle": "セキュリティ", - "xpack.securitySolution.pages.common.emptyActionPrimary": "Beatsでデータを表示", + "xpack.securitySolution.pages.common.emptyActionBeats": "Beatsでデータを表示", "xpack.securitySolution.pages.common.emptyActionSecondary": "入門ガイドを表示", "xpack.securitySolution.pages.common.emptyTitle": "SIEMへようこそ。始めましょう。", "xpack.securitySolution.pages.fourohfour.noContentFoundDescription": "コンテンツがありません", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index dcbcda120587f..b69763449a06f 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -13578,7 +13578,7 @@ "xpack.securitySolution.detectionEngine.editRule.errorMsgDescription": "抱歉", "xpack.securitySolution.detectionEngine.editRule.pageTitle": "编辑规则设置", "xpack.securitySolution.detectionEngine.editRule.saveChangeTitle": "保存更改", - "xpack.securitySolution.detectionEngine.emptyActionPrimary": "查看设置说明", + "xpack.securitySolution.detectionEngine.emptyActionBeats": "查看设置说明", "xpack.securitySolution.detectionEngine.emptyActionSecondary": "前往文档", "xpack.securitySolution.detectionEngine.emptyTitle": "似乎您没有与 Security 应用程序的检测引擎相关的索引", "xpack.securitySolution.detectionEngine.goToDocumentationButton": "查看文档", @@ -14355,7 +14355,7 @@ "xpack.securitySolution.overview.viewEventsButtonLabel": "查看事件", "xpack.securitySolution.overview.winlogbeatMWSysmonOperational": "Microsoft-Windows-Sysmon/Operational", "xpack.securitySolution.overview.winlogbeatSecurityTitle": "安全", - "xpack.securitySolution.pages.common.emptyActionPrimary": "使用 Beats 添加数据", + "xpack.securitySolution.pages.common.emptyActionBeats": "使用 Beats 添加数据", "xpack.securitySolution.pages.common.emptyActionSecondary": "查看入门指南", "xpack.securitySolution.pages.common.emptyTitle": "欢迎使用 SIEM。让我们教您如何入门。", "xpack.securitySolution.pages.fourohfour.noContentFoundDescription": "未找到任何内容",