From ddc3f392dde30d38d13ec4f6815d0e3971ca8992 Mon Sep 17 00:00:00 2001 From: Candace Park Date: Fri, 26 Jun 2020 17:57:01 -0400 Subject: [PATCH 01/16] add button link to ingest --- .../common/components/empty_page/index.tsx | 20 +++++++++++++++++++ .../components/overview_empty/index.tsx | 3 +++ 2 files changed, 23 insertions(+) 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 a067c1d28f87f..d742b14beb403 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 @@ -23,6 +23,10 @@ interface EmptyPageProps { actionSecondaryLabel?: string; actionSecondaryTarget?: string; actionSecondaryUrl?: string; + actionTertiaryIcon?: IconType; + actionTertiaryLabel?: string; + actionTertiaryTarget?: string; + actionTertiaryUrl?: string; 'data-test-subj'?: string; message?: string; title: string; @@ -38,6 +42,10 @@ export const EmptyPage = React.memo( actionSecondaryLabel, actionSecondaryTarget, actionSecondaryUrl, + actionTertiaryIcon, + actionTertiaryLabel, + actionTertiaryTarget, + actionTertiaryUrl, message, title, ...rest @@ -70,6 +78,18 @@ export const EmptyPage = React.memo( )} + + {actionTertiaryLabel && actionTertiaryUrl && ( + + + {actionTertiaryLabel} + + + )} } {...rest} 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 00db437bce11e..ddf3a703f5dcd 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 @@ -24,6 +24,9 @@ const OverviewEmptyComponent: React.FC = () => { actionSecondaryLabel={i18nCommon.EMPTY_ACTION_SECONDARY} actionSecondaryTarget="_blank" actionSecondaryUrl={docLinks.links.siem.gettingStarted} + actionTertiaryIcon="glasses" + actionTertiaryLabel={i18nCommon.EMPTY_ACTION_SECONDARY} + actionTertiaryUrl={`${basePath}${ADD_DATA_PATH}`} data-test-subj="empty-page" message={i18nCommon.EMPTY_MESSAGE} title={i18nCommon.EMPTY_TITLE} From 1c078cf7114cb99087fffb17429e7410203a3390 Mon Sep 17 00:00:00 2001 From: Candace Park Date: Mon, 29 Jun 2020 16:32:42 -0400 Subject: [PATCH 02/16] link does not do full refresh --- .../common/components/empty_page/index.tsx | 32 +++++++++++-------- .../public/common/translations.ts | 7 ++++ .../pages/endpoint_hosts/view/hooks.ts | 8 +++-- .../components/overview_empty/index.tsx | 14 ++++++-- 4 files changed, 42 insertions(+), 19 deletions(-) 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 d742b14beb403..5e56a8a80fb8e 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 @@ -5,7 +5,7 @@ */ import { EuiButton, EuiEmptyPrompt, EuiFlexGroup, EuiFlexItem, IconType } from '@elastic/eui'; -import React from 'react'; +import React, { MouseEventHandler } from 'react'; import styled from 'styled-components'; const EmptyPrompt = styled(EuiEmptyPrompt)` @@ -27,6 +27,8 @@ interface EmptyPageProps { actionTertiaryLabel?: string; actionTertiaryTarget?: string; actionTertiaryUrl?: string; + actionTertiaryOnClick?: MouseEventHandler; + actionTertiaryFill?: boolean; 'data-test-subj'?: string; message?: string; title: string; @@ -46,6 +48,8 @@ export const EmptyPage = React.memo( actionTertiaryLabel, actionTertiaryTarget, actionTertiaryUrl, + actionTertiaryOnClick, + actionTertiaryFill = false, message, title, ...rest @@ -56,6 +60,20 @@ export const EmptyPage = React.memo( body={message &&

{message}

} actions={ + {actionTertiaryLabel && actionTertiaryOnClick && ( + + {/* eslint-disable-next-line @elastic/eui/href-or-on-click */} + + {actionTertiaryLabel} + + + )} ( )} - - {actionTertiaryLabel && actionTertiaryUrl && ( - - - {actionTertiaryLabel} - - - )} } {...rest} diff --git a/x-pack/plugins/security_solution/public/common/translations.ts b/x-pack/plugins/security_solution/public/common/translations.ts index 677543ec0dba6..1b3c8ab9ff226 100644 --- a/x-pack/plugins/security_solution/public/common/translations.ts +++ b/x-pack/plugins/security_solution/public/common/translations.ts @@ -28,3 +28,10 @@ export const EMPTY_ACTION_SECONDARY = i18n.translate( defaultMessage: 'View getting started guide', } ); + +export const EMPTY_ACTION_ENDPOINT = i18n.translate( + 'xpack.securitySolution.pages.common.emptyActionEndpoint', + { + defaultMessage: 'Add data with Elastic Agent', + } +); diff --git a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/hooks.ts b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/hooks.ts index c072c812edbb5..5c20b00630bc2 100644 --- a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/hooks.ts +++ b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/hooks.ts @@ -40,16 +40,18 @@ export const useHostLogsUrl = (hostId: string): { url: string; appId: string; ap /** * Returns an object that contains Ingest app and URL information */ -export const useHostIngestUrl = (): { url: string; appId: string; appPath: string } => { +export const useHostIngestUrl = ( + subpath: string +): { url: string; appId: string; appPath: string } => { const { services } = useKibana(); return useMemo(() => { - const appPath = `#/fleet`; + const appPath = `#/${subpath}`; return { url: `${services.application.getUrlForApp('ingestManager')}${appPath}`, appId: 'ingestManager', appPath, }; - }, [services.application]); + }, [services.application, subpath]); }; /** 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 ddf3a703f5dcd..addc56fddee8c 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 @@ -10,10 +10,16 @@ import * as i18nCommon from '../../../common/translations'; import { EmptyPage } from '../../../common/components/empty_page'; import { useKibana } from '../../../common/lib/kibana'; import { ADD_DATA_PATH } from '../../../../common/constants'; +import { useHostIngestUrl } from '../../../management/pages/endpoint_hosts/view/hooks'; +import { useNavigateToAppEventHandler } from '../../../common/hooks/endpoint/use_navigate_to_app_event_handler'; const OverviewEmptyComponent: React.FC = () => { const { http, docLinks } = useKibana().services; const basePath = http.basePath.get(); + const { appId: ingestAppId, appPath: ingestPath, url: ingestUrl } = useHostIngestUrl( + 'integrations' + ); + const handleOnClick = useNavigateToAppEventHandler(ingestAppId, { path: ingestPath }); return ( { actionSecondaryLabel={i18nCommon.EMPTY_ACTION_SECONDARY} actionSecondaryTarget="_blank" actionSecondaryUrl={docLinks.links.siem.gettingStarted} - actionTertiaryIcon="glasses" - actionTertiaryLabel={i18nCommon.EMPTY_ACTION_SECONDARY} - actionTertiaryUrl={`${basePath}${ADD_DATA_PATH}`} + actionTertiaryIcon="gear" + actionTertiaryLabel={i18nCommon.EMPTY_ACTION_ENDPOINT} + actionTertiaryUrl={ingestUrl} + actionTertiaryOnClick={handleOnClick} + actionTertiaryFill={true} data-test-subj="empty-page" message={i18nCommon.EMPTY_MESSAGE} title={i18nCommon.EMPTY_TITLE} From 604316a6c095167315065d1a9df075f33e5dda50 Mon Sep 17 00:00:00 2001 From: Candace Park Date: Tue, 30 Jun 2020 18:07:28 -0400 Subject: [PATCH 03/16] use queryparam initially, navigate to correct url --- .../sections/epm/screens/home/index.tsx | 16 +++++++++++++--- .../overview/components/overview_empty/index.tsx | 2 +- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/home/index.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/home/index.tsx index e00b63e29019e..51421da631b85 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/home/index.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/home/index.tsx @@ -5,7 +5,7 @@ */ import React, { useState } from 'react'; -import { useRouteMatch, Switch, Route } from 'react-router-dom'; +import { useRouteMatch, Switch, Route, useLocation, useHistory } from 'react-router-dom'; import { Props as EuiTabProps } from '@elastic/eui/src/components/tabs/tab'; import { i18n } from '@kbn/i18n'; import { PAGE_ROUTING_PATHS } from '../../../../constants'; @@ -114,7 +114,11 @@ function InstalledPackages() { function AvailablePackages() { useBreadcrumbs('integrations_all'); - const [selectedCategory, setSelectedCategory] = useState(''); + const history = useHistory(); + const queryParams = new URLSearchParams(useLocation().search); + const initialCategory = + queryParams.get('category') !== null ? (queryParams.get('category') as string) : ''; + const [selectedCategory, setSelectedCategory] = useState(initialCategory); const { data: categoryPackagesRes, isLoading: isLoadingPackages } = useGetPackages({ category: selectedCategory, }); @@ -141,7 +145,13 @@ function AvailablePackages() { isLoading={isLoadingCategories} categories={categories} selectedCategory={selectedCategory} - onCategoryChange={({ id }: CategorySummaryItem) => setSelectedCategory(id)} + onCategoryChange={({ id }: CategorySummaryItem) => { + // clear category query param in the url + if (queryParams.get('category') !== null) { + history.push({}); + } + setSelectedCategory(id); + }} /> ) : null; 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 addc56fddee8c..186f8ea59f760 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 @@ -17,7 +17,7 @@ const OverviewEmptyComponent: React.FC = () => { const { http, docLinks } = useKibana().services; const basePath = http.basePath.get(); const { appId: ingestAppId, appPath: ingestPath, url: ingestUrl } = useHostIngestUrl( - 'integrations' + 'integrations?category=security' ); const handleOnClick = useNavigateToAppEventHandler(ingestAppId, { path: ingestPath }); From 460c5f84f017726fe85b0b37f55aa8867311c95d Mon Sep 17 00:00:00 2001 From: Candace Park Date: Wed, 1 Jul 2020 12:00:04 -0400 Subject: [PATCH 04/16] hook to check ingest enabled --- .../common/hooks/endpoint/ingest_enabled.ts | 22 +++++++++++++++++++ .../components/overview_empty/index.tsx | 17 +++++++++++++- 2 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 x-pack/plugins/security_solution/public/common/hooks/endpoint/ingest_enabled.ts diff --git a/x-pack/plugins/security_solution/public/common/hooks/endpoint/ingest_enabled.ts b/x-pack/plugins/security_solution/public/common/hooks/endpoint/ingest_enabled.ts new file mode 100644 index 0000000000000..5ed37021e428b --- /dev/null +++ b/x-pack/plugins/security_solution/public/common/hooks/endpoint/ingest_enabled.ts @@ -0,0 +1,22 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { useKibana } from '../../../../../../../src/plugins/kibana_react/public'; + +export const useIngestEnabledCheck = (): boolean => { + const { services } = useKibana(); + + // Check if Ingest Manager is present in the configuration + const show = services.application.capabilities.ingestManager?.show ?? false; + const write = services.application.capabilities.ingestManager?.write ?? false; + const read = services.application.capabilities.ingestManager?.read ?? false; + + // Check if all Ingest Manager permissions are enabled + if (show === false || write === false || read === false) { + return false; + } + return true; +}; 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 186f8ea59f760..97e687fa2437d 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 @@ -12,6 +12,7 @@ import { useKibana } from '../../../common/lib/kibana'; import { ADD_DATA_PATH } from '../../../../common/constants'; import { useHostIngestUrl } from '../../../management/pages/endpoint_hosts/view/hooks'; import { useNavigateToAppEventHandler } from '../../../common/hooks/endpoint/use_navigate_to_app_event_handler'; +import { useIngestEnabledCheck } from '../../../common/hooks/endpoint/ingest_enabled'; const OverviewEmptyComponent: React.FC = () => { const { http, docLinks } = useKibana().services; @@ -20,8 +21,9 @@ const OverviewEmptyComponent: React.FC = () => { 'integrations?category=security' ); const handleOnClick = useNavigateToAppEventHandler(ingestAppId, { path: ingestPath }); + const isIngestEnabled = useIngestEnabledCheck(); - return ( + return isIngestEnabled === true ? ( { message={i18nCommon.EMPTY_MESSAGE} title={i18nCommon.EMPTY_TITLE} /> + ) : ( + ); }; From 2113b992a257ece2acc307d9188a2da646430402 Mon Sep 17 00:00:00 2001 From: Candace Park Date: Wed, 1 Jul 2020 19:24:26 -0400 Subject: [PATCH 05/16] tests --- .../common/components/empty_page/index.tsx | 1 + .../public/overview/pages/overview.test.tsx | 66 ++++++++++++++----- 2 files changed, 49 insertions(+), 18 deletions(-) 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 5e56a8a80fb8e..350adb2597c5b 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 @@ -64,6 +64,7 @@ export const EmptyPage = React.memo( {/* eslint-disable-next-line @elastic/eui/href-or-on-click */} ({ jest.mock('../../common/components/query_bar', () => ({ QueryBar: () => null, })); +jest.mock('../../common/hooks/endpoint/ingest_enabled'); jest.mock('../../common/containers/local_storage/use_messages_storage'); const endpointNoticeMessage = (hasMessageValue: boolean) => { @@ -42,26 +44,54 @@ const endpointNoticeMessage = (hasMessageValue: boolean) => { describe('Overview', () => { describe('rendering', () => { - test('it renders the Setup Instructions text when no index is available', async () => { - (useWithSource as jest.Mock).mockReturnValue({ - indicesExist: false, + describe('when no index is available', () => { + beforeEach(() => { + (useWithSource as jest.Mock).mockReturnValue({ + indicesExist: false, + }); + const mockuseMessagesStorage: jest.Mock = useMessagesStorage as jest.Mock< + UseMessagesStorage + >; + mockuseMessagesStorage.mockImplementation(() => endpointNoticeMessage(false)); }); - const mockuseMessagesStorage: jest.Mock = useMessagesStorage as jest.Mock; - mockuseMessagesStorage.mockImplementation(() => endpointNoticeMessage(false)); + it('renders the Setup Instructions text', () => { + const wrapper = mount( + + + + + + ); + expect(wrapper.find('[data-test-subj="empty-page"]').exists()).toBe(true); + }); - const wrapper = mount( - - - - - - ); + it('does not show Endpoint get ready button when ingest is not enabled', () => { + (useIngestEnabledCheck as jest.Mock).mockReturnValue(false); + const wrapper = mount( + + + + + + ); + expect(wrapper.find('[data-test-subj="empty-page-tertiary-action"]').exists()).toBe(false); + }); - expect(wrapper.find('[data-test-subj="empty-page"]').exists()).toBe(true); + it('shows Endpoint get ready button when ingest is enabled', () => { + (useIngestEnabledCheck as jest.Mock).mockReturnValue(true); + const wrapper = mount( + + + + + + ); + expect(wrapper.find('[data-test-subj="empty-page-tertiary-action"]').exists()).toBe(true); + }); }); - test('it DOES NOT render the Getting started text when an index is available', async () => { + it('it DOES NOT render the Getting started text when an index is available', () => { (useWithSource as jest.Mock).mockReturnValue({ indicesExist: true, indexPattern: {}, @@ -80,7 +110,7 @@ describe('Overview', () => { expect(wrapper.find('[data-test-subj="empty-page"]').exists()).toBe(false); }); - test('it DOES render the Endpoint banner when the endpoint index is NOT available AND storage is NOT set', async () => { + test('it DOES render the Endpoint banner when the endpoint index is NOT available AND storage is NOT set', () => { (useWithSource as jest.Mock).mockReturnValueOnce({ indicesExist: true, indexPattern: {}, @@ -104,7 +134,7 @@ describe('Overview', () => { expect(wrapper.find('[data-test-subj="endpoint-prompt-banner"]').exists()).toBe(true); }); - test('it does NOT render the Endpoint banner when the endpoint index is NOT available but storage is set', async () => { + test('it does NOT render the Endpoint banner when the endpoint index is NOT available but storage is set', () => { (useWithSource as jest.Mock).mockReturnValueOnce({ indicesExist: true, indexPattern: {}, @@ -128,7 +158,7 @@ describe('Overview', () => { expect(wrapper.find('[data-test-subj="endpoint-prompt-banner"]').exists()).toBe(false); }); - test('it does NOT render the Endpoint banner when the endpoint index is available AND storage is set', async () => { + test('it does NOT render the Endpoint banner when the endpoint index is available AND storage is set', () => { (useWithSource as jest.Mock).mockReturnValue({ indicesExist: true, indexPattern: {}, @@ -147,7 +177,7 @@ describe('Overview', () => { expect(wrapper.find('[data-test-subj="endpoint-prompt-banner"]').exists()).toBe(false); }); - test('it does NOT render the Endpoint banner when an index IS available but storage is NOT set', async () => { + test('it does NOT render the Endpoint banner when an index IS available but storage is NOT set', () => { (useWithSource as jest.Mock).mockReturnValue({ indicesExist: true, indexPattern: {}, From 415ae9160e56c053e0311133bef5ee5aadf55199 Mon Sep 17 00:00:00 2001 From: Candace Park Date: Wed, 1 Jul 2020 19:32:29 -0400 Subject: [PATCH 06/16] checks if metadata index is present --- .../server/lib/source_status/elasticsearch_adapter.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/x-pack/plugins/security_solution/server/lib/source_status/elasticsearch_adapter.ts b/x-pack/plugins/security_solution/server/lib/source_status/elasticsearch_adapter.ts index 8872d347da826..ab491f54854e4 100644 --- a/x-pack/plugins/security_solution/server/lib/source_status/elasticsearch_adapter.ts +++ b/x-pack/plugins/security_solution/server/lib/source_status/elasticsearch_adapter.ts @@ -8,6 +8,7 @@ import { FrameworkAdapter, FrameworkRequest } from '../framework'; import { SourceStatusAdapter } from './index'; import { buildQuery } from './query.dsl'; import { ApmServiceNameAgg } from './types'; +import { ENDPOINT_METADATA_INDEX } from '../../../common/constants'; const APM_INDEX_NAME = 'apm-*-transaction*'; @@ -18,6 +19,8 @@ export class ElasticsearchSourceStatusAdapter implements SourceStatusAdapter { // Intended flow to determine app-empty state is to first check siem indices (as this is a quick shard count), and // if no shards exist only then perform the heavier APM query. This optimizes for normal use when siem data exists try { + // Add endpoint metadata index to indices to check + indexNames.push(ENDPOINT_METADATA_INDEX); // Remove APM index if exists, and only query if length > 0 in case it's the only index provided const nonApmIndexNames = indexNames.filter((name) => name !== APM_INDEX_NAME); const indexCheckResponse = await (nonApmIndexNames.length > 0 From ac75c499033b12182e7f0a8786d73ae9bd89b808 Mon Sep 17 00:00:00 2001 From: Candace Park Date: Wed, 1 Jul 2020 19:35:41 -0400 Subject: [PATCH 07/16] modify ingest url hook naming --- .../public/management/pages/endpoint_hosts/view/hooks.ts | 4 +--- .../public/overview/components/overview_empty/index.tsx | 4 ++-- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/hooks.ts b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/hooks.ts index 13bc889465b6c..b048a8f69b5d2 100644 --- a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/hooks.ts +++ b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/hooks.ts @@ -24,9 +24,7 @@ export function useHostSelector(selector: (state: HostState) => TSele /** * Returns an object that contains Ingest app and URL information */ -export const useHostIngestUrl = ( - subpath: string -): { url: string; appId: string; appPath: string } => { +export const useIngestUrl = (subpath: string): { url: string; appId: string; appPath: string } => { const { services } = useKibana(); return useMemo(() => { const appPath = `#/${subpath}`; 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 97e687fa2437d..f57617f9ce967 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 @@ -10,14 +10,14 @@ import * as i18nCommon from '../../../common/translations'; import { EmptyPage } from '../../../common/components/empty_page'; import { useKibana } from '../../../common/lib/kibana'; import { ADD_DATA_PATH } from '../../../../common/constants'; -import { useHostIngestUrl } from '../../../management/pages/endpoint_hosts/view/hooks'; +import { useIngestUrl } from '../../../management/pages/endpoint_hosts/view/hooks'; import { useNavigateToAppEventHandler } from '../../../common/hooks/endpoint/use_navigate_to_app_event_handler'; import { useIngestEnabledCheck } from '../../../common/hooks/endpoint/ingest_enabled'; const OverviewEmptyComponent: React.FC = () => { const { http, docLinks } = useKibana().services; const basePath = http.basePath.get(); - const { appId: ingestAppId, appPath: ingestPath, url: ingestUrl } = useHostIngestUrl( + const { appId: ingestAppId, appPath: ingestPath, url: ingestUrl } = useIngestUrl( 'integrations?category=security' ); const handleOnClick = useNavigateToAppEventHandler(ingestAppId, { path: ingestPath }); From 55261bc3d24c84a311a4a02a5062ac95bdfb358f Mon Sep 17 00:00:00 2001 From: Candace Park Date: Thu, 2 Jul 2020 11:45:07 -0400 Subject: [PATCH 08/16] modify hook to be more robust --- .../common/hooks/endpoint/ingest_enabled.ts | 22 ++++++++++++++----- .../components/overview_empty/index.tsx | 2 +- .../public/overview/pages/overview.test.tsx | 4 ++-- 3 files changed, 20 insertions(+), 8 deletions(-) diff --git a/x-pack/plugins/security_solution/public/common/hooks/endpoint/ingest_enabled.ts b/x-pack/plugins/security_solution/public/common/hooks/endpoint/ingest_enabled.ts index 5ed37021e428b..c201d85a270c0 100644 --- a/x-pack/plugins/security_solution/public/common/hooks/endpoint/ingest_enabled.ts +++ b/x-pack/plugins/security_solution/public/common/hooks/endpoint/ingest_enabled.ts @@ -6,7 +6,15 @@ import { useKibana } from '../../../../../../../src/plugins/kibana_react/public'; -export const useIngestEnabledCheck = (): boolean => { +/** + * Returns an object which ingest permissions are allowed + */ +export const useIngestEnabledCheck = (): { + allEnabled: boolean; + show: boolean; + write: boolean; + read: boolean; +} => { const { services } = useKibana(); // Check if Ingest Manager is present in the configuration @@ -15,8 +23,12 @@ export const useIngestEnabledCheck = (): boolean => { const read = services.application.capabilities.ingestManager?.read ?? false; // Check if all Ingest Manager permissions are enabled - if (show === false || write === false || read === false) { - return false; - } - return true; + const allEnabled = show && read && write ? true : false; + + return { + allEnabled, + show, + write, + read, + }; }; 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 f57617f9ce967..dfa8899070a4b 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 @@ -21,7 +21,7 @@ const OverviewEmptyComponent: React.FC = () => { 'integrations?category=security' ); const handleOnClick = useNavigateToAppEventHandler(ingestAppId, { path: ingestPath }); - const isIngestEnabled = useIngestEnabledCheck(); + const { allEnabled: isIngestEnabled } = useIngestEnabledCheck(); return isIngestEnabled === true ? ( { (useWithSource as jest.Mock).mockReturnValue({ indicesExist: false, }); + (useIngestEnabledCheck as jest.Mock).mockReturnValue({ allEnabled: false }); const mockuseMessagesStorage: jest.Mock = useMessagesStorage as jest.Mock< UseMessagesStorage >; @@ -67,7 +68,6 @@ describe('Overview', () => { }); it('does not show Endpoint get ready button when ingest is not enabled', () => { - (useIngestEnabledCheck as jest.Mock).mockReturnValue(false); const wrapper = mount( @@ -79,7 +79,7 @@ describe('Overview', () => { }); it('shows Endpoint get ready button when ingest is enabled', () => { - (useIngestEnabledCheck as jest.Mock).mockReturnValue(true); + (useIngestEnabledCheck as jest.Mock).mockReturnValue({ allEnabled: true }); const wrapper = mount( From b79f6d76fcd3e52a8ca6ba0317a0d2eb2a5f42f8 Mon Sep 17 00:00:00 2001 From: Candace Park Date: Thu, 2 Jul 2020 11:51:26 -0400 Subject: [PATCH 09/16] add beta to button --- x-pack/plugins/security_solution/public/common/translations.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/security_solution/public/common/translations.ts b/x-pack/plugins/security_solution/public/common/translations.ts index 1b3c8ab9ff226..722be347919da 100644 --- a/x-pack/plugins/security_solution/public/common/translations.ts +++ b/x-pack/plugins/security_solution/public/common/translations.ts @@ -32,6 +32,6 @@ 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', + defaultMessage: 'Add data with Elastic Agent (Beta)', } ); From 7c932c64e16943acc64fdced2e8466815c83cafc Mon Sep 17 00:00:00 2001 From: Candace Park Date: Thu, 2 Jul 2020 15:36:55 -0400 Subject: [PATCH 10/16] remove tertiary action, make secondary action --- .../common/components/empty_page/index.tsx | 40 ++++----------- .../public/common/translations.ts | 8 +++ .../components/overview_empty/index.tsx | 51 +++++++++++++------ .../public/overview/pages/overview.test.tsx | 4 +- 4 files changed, 55 insertions(+), 48 deletions(-) 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 350adb2597c5b..0baad6fda45ca 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 @@ -5,7 +5,7 @@ */ import { EuiButton, EuiEmptyPrompt, EuiFlexGroup, EuiFlexItem, IconType } from '@elastic/eui'; -import React, { MouseEventHandler } from 'react'; +import React, { MouseEventHandler, ReactNode } from 'react'; import styled from 'styled-components'; const EmptyPrompt = styled(EuiEmptyPrompt)` @@ -19,18 +19,14 @@ interface EmptyPageProps { actionPrimaryLabel: string; actionPrimaryTarget?: string; actionPrimaryUrl: string; + actionPrimaryFill?: boolean; actionSecondaryIcon?: IconType; actionSecondaryLabel?: string; actionSecondaryTarget?: string; actionSecondaryUrl?: string; - actionTertiaryIcon?: IconType; - actionTertiaryLabel?: string; - actionTertiaryTarget?: string; - actionTertiaryUrl?: string; - actionTertiaryOnClick?: MouseEventHandler; - actionTertiaryFill?: boolean; + actionSecondaryOnClick?: MouseEventHandler; 'data-test-subj'?: string; - message?: string; + message?: ReactNode; title: string; } @@ -40,16 +36,12 @@ export const EmptyPage = React.memo( actionPrimaryLabel, actionPrimaryTarget, actionPrimaryUrl, + actionPrimaryFill = true, actionSecondaryIcon, actionSecondaryLabel, actionSecondaryTarget, actionSecondaryUrl, - actionTertiaryIcon, - actionTertiaryLabel, - actionTertiaryTarget, - actionTertiaryUrl, - actionTertiaryOnClick, - actionTertiaryFill = false, + actionSecondaryOnClick, message, title, ...rest @@ -60,24 +52,9 @@ export const EmptyPage = React.memo( body={message &&

{message}

} actions={ - {actionTertiaryLabel && actionTertiaryOnClick && ( - - {/* eslint-disable-next-line @elastic/eui/href-or-on-click */} - - {actionTertiaryLabel} - - - )} ( {actionSecondaryLabel && actionSecondaryUrl && ( + {/* eslint-disable-next-line @elastic/eui/href-or-on-click */} {actionSecondaryLabel} diff --git a/x-pack/plugins/security_solution/public/common/translations.ts b/x-pack/plugins/security_solution/public/common/translations.ts index 722be347919da..c49765150d84a 100644 --- a/x-pack/plugins/security_solution/public/common/translations.ts +++ b/x-pack/plugins/security_solution/public/common/translations.ts @@ -15,6 +15,14 @@ export const EMPTY_MESSAGE = i18n.translate('xpack.securitySolution.pages.common 'To begin using security information and event management (Security Solution), you’ll need to add security solution related data, in Elastic Common Schema (ECS) format, to the Elastic Stack. An easy way to get started is by installing and configuring our data shippers, called Beats. Let’s do that now!', }); +export const OVERVIEW_EMPTY_MESSAGE = i18n.translate( + 'xpack.securitySolution.pages.common.overviewEmptyMessage', + { + defaultMessage: + 'To begin using security information and event management (Security Solution), you’ll need to add security solution related data, in Elastic Common Schema (ECS) format, to the Elastic Stack. An easy way to get started is by installing and configuring our data shippers, called Beats. For additional information, you can view our ', + } +); + export const EMPTY_ACTION_PRIMARY = i18n.translate( 'xpack.securitySolution.pages.common.emptyActionPrimary', { 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 dfa8899070a4b..3cca87c613d2f 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 @@ -5,7 +5,9 @@ */ import React from 'react'; - +import { i18n } from '@kbn/i18n'; +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 { useKibana } from '../../../common/lib/kibana'; @@ -28,17 +30,25 @@ const OverviewEmptyComponent: React.FC = () => { actionPrimaryIcon="gear" actionPrimaryLabel={i18nCommon.EMPTY_ACTION_PRIMARY} actionPrimaryUrl={`${basePath}${ADD_DATA_PATH}`} - actionSecondaryIcon="popout" - actionSecondaryLabel={i18nCommon.EMPTY_ACTION_SECONDARY} - actionSecondaryTarget="_blank" - actionSecondaryUrl={docLinks.links.siem.gettingStarted} - actionTertiaryIcon="gear" - actionTertiaryLabel={i18nCommon.EMPTY_ACTION_ENDPOINT} - actionTertiaryUrl={ingestUrl} - actionTertiaryOnClick={handleOnClick} - actionTertiaryFill={true} + actionPrimaryFill={false} + actionSecondaryIcon="gear" + actionSecondaryLabel={i18nCommon.EMPTY_ACTION_ENDPOINT} + actionSecondaryUrl={ingestUrl} + actionSecondaryOnClick={handleOnClick} data-test-subj="empty-page" - message={i18nCommon.EMPTY_MESSAGE} + message={ + <> + + + {i18n.translate('xpack.securitySolution.overview.gettingStartedGuide', { + defaultMessage: 'getting started guide.', + })} + + + } title={i18nCommon.EMPTY_TITLE} /> ) : ( @@ -46,12 +56,21 @@ const OverviewEmptyComponent: React.FC = () => { actionPrimaryIcon="gear" actionPrimaryLabel={i18nCommon.EMPTY_ACTION_PRIMARY} actionPrimaryUrl={`${basePath}${ADD_DATA_PATH}`} - actionSecondaryIcon="popout" - actionSecondaryLabel={i18nCommon.EMPTY_ACTION_SECONDARY} - actionSecondaryTarget="_blank" - actionSecondaryUrl={docLinks.links.siem.gettingStarted} + actionPrimaryFill={true} data-test-subj="empty-page" - message={i18nCommon.EMPTY_MESSAGE} + message={ + <> + + + {i18n.translate('xpack.securitySolution.overview.gettingStartedGuide', { + defaultMessage: 'getting started guide.', + })} + + + } title={i18nCommon.EMPTY_TITLE} /> ); 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 70e59d69707ec..523afed672aa4 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 @@ -75,7 +75,7 @@ describe('Overview', () => {
); - expect(wrapper.find('[data-test-subj="empty-page-tertiary-action"]').exists()).toBe(false); + expect(wrapper.find('[data-test-subj="empty-page-secondary-action"]').exists()).toBe(false); }); it('shows Endpoint get ready button when ingest is enabled', () => { @@ -87,7 +87,7 @@ describe('Overview', () => {
); - expect(wrapper.find('[data-test-subj="empty-page-tertiary-action"]').exists()).toBe(true); + expect(wrapper.find('[data-test-subj="empty-page-secondary-action"]').exists()).toBe(true); }); }); From a65f1a5a968ba6d4d0ea5604b6fff4fd70868e40 Mon Sep 17 00:00:00 2001 From: Candace Park Date: Thu, 2 Jul 2020 16:07:54 -0400 Subject: [PATCH 11/16] comments --- .../ingest_manager/sections/epm/screens/home/index.tsx | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/home/index.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/home/index.tsx index 51421da631b85..c68833c1b2d95 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/home/index.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/home/index.tsx @@ -116,8 +116,7 @@ function AvailablePackages() { useBreadcrumbs('integrations_all'); const history = useHistory(); const queryParams = new URLSearchParams(useLocation().search); - const initialCategory = - queryParams.get('category') !== null ? (queryParams.get('category') as string) : ''; + const initialCategory = queryParams.get('category') || ''; const [selectedCategory, setSelectedCategory] = useState(initialCategory); const { data: categoryPackagesRes, isLoading: isLoadingPackages } = useGetPackages({ category: selectedCategory, @@ -147,7 +146,7 @@ function AvailablePackages() { selectedCategory={selectedCategory} onCategoryChange={({ id }: CategorySummaryItem) => { // clear category query param in the url - if (queryParams.get('category') !== null) { + if (queryParams.get('category')) { history.push({}); } setSelectedCategory(id); From a4438594956b7476c71d6f25e3c0ccc1077ef923 Mon Sep 17 00:00:00 2001 From: Candace Park Date: Thu, 2 Jul 2020 17:14:45 -0400 Subject: [PATCH 12/16] make network, hosts, alerts/detection use overview empty --- .../detection_engine/detection_engine.tsx | 4 +-- .../detection_engine_empty_page.test.tsx | 19 ----------- .../detection_engine_empty_page.tsx | 28 --------------- .../detection_engine/rules/details/index.tsx | 4 +-- .../common/components/empty_page/index.tsx | 2 +- .../public/common/translations.ts | 12 ++----- .../public/hosts/pages/details/index.tsx | 4 +-- .../public/hosts/pages/hosts.tsx | 4 +-- .../public/hosts/pages/hosts_empty_page.tsx | 34 ------------------- .../public/network/pages/ip_details/index.tsx | 4 +-- .../public/network/pages/network.tsx | 4 +-- .../network/pages/network_empty_page.tsx | 34 ------------------- .../components/overview_empty/index.tsx | 12 +++---- 13 files changed, 19 insertions(+), 146 deletions(-) delete mode 100644 x-pack/plugins/security_solution/public/alerts/pages/detection_engine/detection_engine_empty_page.test.tsx delete mode 100644 x-pack/plugins/security_solution/public/alerts/pages/detection_engine/detection_engine_empty_page.tsx delete mode 100644 x-pack/plugins/security_solution/public/hosts/pages/hosts_empty_page.tsx delete mode 100644 x-pack/plugins/security_solution/public/network/pages/network_empty_page.tsx diff --git a/x-pack/plugins/security_solution/public/alerts/pages/detection_engine/detection_engine.tsx b/x-pack/plugins/security_solution/public/alerts/pages/detection_engine/detection_engine.tsx index dc0b22c82af3e..8fe9ae01a17c0 100644 --- a/x-pack/plugins/security_solution/public/alerts/pages/detection_engine/detection_engine.tsx +++ b/x-pack/plugins/security_solution/public/alerts/pages/detection_engine/detection_engine.tsx @@ -31,7 +31,7 @@ import { NoWriteAlertsCallOut } from '../../components/no_write_alerts_callout'; import { AlertsHistogramPanel } from '../../components/alerts_histogram_panel'; import { alertsHistogramOptions } from '../../components/alerts_histogram_panel/config'; import { useUserInfo } from '../../components/user_info'; -import { DetectionEngineEmptyPage } from './detection_engine_empty_page'; +import { OverviewEmpty } from '../../../overview/components/overview_empty'; import { DetectionEngineNoIndex } from './detection_engine_no_signal_index'; import { DetectionEngineHeaderPage } from '../../components/detection_engine_header_page'; import { DetectionEngineUserUnauthenticated } from './detection_engine_user_unauthenticated'; @@ -166,7 +166,7 @@ export const DetectionEnginePageComponent: React.FC = ({ ) : ( - + )} diff --git a/x-pack/plugins/security_solution/public/alerts/pages/detection_engine/detection_engine_empty_page.test.tsx b/x-pack/plugins/security_solution/public/alerts/pages/detection_engine/detection_engine_empty_page.test.tsx deleted file mode 100644 index 039c878b121a0..0000000000000 --- a/x-pack/plugins/security_solution/public/alerts/pages/detection_engine/detection_engine_empty_page.test.tsx +++ /dev/null @@ -1,19 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import React from 'react'; -import { shallow } from 'enzyme'; - -import { DetectionEngineEmptyPage } from './detection_engine_empty_page'; -jest.mock('../../../common/lib/kibana'); - -describe('DetectionEngineEmptyPage', () => { - it('renders correctly', () => { - const wrapper = shallow(); - - expect(wrapper.find('EmptyPage')).toHaveLength(1); - }); -}); diff --git a/x-pack/plugins/security_solution/public/alerts/pages/detection_engine/detection_engine_empty_page.tsx b/x-pack/plugins/security_solution/public/alerts/pages/detection_engine/detection_engine_empty_page.tsx deleted file mode 100644 index 0c58f5620964b..0000000000000 --- a/x-pack/plugins/security_solution/public/alerts/pages/detection_engine/detection_engine_empty_page.tsx +++ /dev/null @@ -1,28 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import React from 'react'; - -import { useKibana } from '../../../common/lib/kibana'; -import { EmptyPage } from '../../../common/components/empty_page'; -import * as i18n from '../../../common/translations'; -import { ADD_DATA_PATH } from '../../../../common/constants'; - -export const DetectionEngineEmptyPage = React.memo(() => ( - -)); -DetectionEngineEmptyPage.displayName = 'DetectionEngineEmptyPage'; diff --git a/x-pack/plugins/security_solution/public/alerts/pages/detection_engine/rules/details/index.tsx b/x-pack/plugins/security_solution/public/alerts/pages/detection_engine/rules/details/index.tsx index 2ec603546983e..df8257c70d656 100644 --- a/x-pack/plugins/security_solution/public/alerts/pages/detection_engine/rules/details/index.tsx +++ b/x-pack/plugins/security_solution/public/alerts/pages/detection_engine/rules/details/index.tsx @@ -43,7 +43,7 @@ import { DetectionEngineHeaderPage } from '../../../../components/detection_engi import { AlertsHistogramPanel } from '../../../../components/alerts_histogram_panel'; import { AlertsTable } from '../../../../components/alerts_table'; import { useUserInfo } from '../../../../components/user_info'; -import { DetectionEngineEmptyPage } from '../../detection_engine_empty_page'; +import { OverviewEmpty } from '../../../../../overview/components/overview_empty'; import { useAlertInfo } from '../../../../components/alerts_info'; import { StepDefineRule } from '../../../../components/rules/step_define_rule'; import { StepScheduleRule } from '../../../../components/rules/step_schedule_rule'; @@ -430,7 +430,7 @@ export const RuleDetailsPageComponent: FC = ({ - + )} 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 0baad6fda45ca..f6d6752729b6d 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 @@ -47,7 +47,7 @@ export const EmptyPage = React.memo( ...rest }) => ( {title}} body={message &&

{message}

} actions={ diff --git a/x-pack/plugins/security_solution/public/common/translations.ts b/x-pack/plugins/security_solution/public/common/translations.ts index c49765150d84a..c1736ff2d1487 100644 --- a/x-pack/plugins/security_solution/public/common/translations.ts +++ b/x-pack/plugins/security_solution/public/common/translations.ts @@ -12,17 +12,9 @@ export const EMPTY_TITLE = i18n.translate('xpack.securitySolution.pages.common.e export const EMPTY_MESSAGE = i18n.translate('xpack.securitySolution.pages.common.emptyMessage', { defaultMessage: - 'To begin using security information and event management (Security Solution), you’ll need to add security solution related data, in Elastic Common Schema (ECS) format, to the Elastic Stack. An easy way to get started is by installing and configuring our data shippers, called Beats. Let’s do that now!', + 'To begin using security information and event management (Security Solution), you’ll need to add security solution related data, in Elastic Common Schema (ECS) format, to the Elastic Stack. An easy way to get started is by installing and configuring our data shippers, called Beats. For additional information, you can view our ', }); -export const OVERVIEW_EMPTY_MESSAGE = i18n.translate( - 'xpack.securitySolution.pages.common.overviewEmptyMessage', - { - defaultMessage: - 'To begin using security information and event management (Security Solution), you’ll need to add security solution related data, in Elastic Common Schema (ECS) format, to the Elastic Stack. An easy way to get started is by installing and configuring our data shippers, called Beats. For additional information, you can view our ', - } -); - export const EMPTY_ACTION_PRIMARY = i18n.translate( 'xpack.securitySolution.pages.common.emptyActionPrimary', { @@ -33,7 +25,7 @@ export const EMPTY_ACTION_PRIMARY = i18n.translate( export const EMPTY_ACTION_SECONDARY = i18n.translate( 'xpack.securitySolution.pages.common.emptyActionSecondary', { - defaultMessage: 'View getting started guide', + defaultMessage: 'getting started guide', } ); diff --git a/x-pack/plugins/security_solution/public/hosts/pages/details/index.tsx b/x-pack/plugins/security_solution/public/hosts/pages/details/index.tsx index 1c66a9edc1947..f8e42898827c6 100644 --- a/x-pack/plugins/security_solution/public/hosts/pages/details/index.tsx +++ b/x-pack/plugins/security_solution/public/hosts/pages/details/index.tsx @@ -37,7 +37,7 @@ import { setAbsoluteRangeDatePicker as dispatchAbsoluteRangeDatePicker } from '. import { SpyRoute } from '../../../common/utils/route/spy_routes'; import { esQuery, Filter } from '../../../../../../../src/plugins/data/public'; -import { HostsEmptyPage } from '../hosts_empty_page'; +import { OverviewEmpty } from '../../../overview/components/overview_empty'; import { HostDetailsTabs } from './details_tabs'; import { navTabsHostDetails } from './nav_tabs'; import { HostDetailsProps } from './types'; @@ -197,7 +197,7 @@ const HostDetailsComponent = React.memo( - + )} diff --git a/x-pack/plugins/security_solution/public/hosts/pages/hosts.tsx b/x-pack/plugins/security_solution/public/hosts/pages/hosts.tsx index f5cc651a30443..051b164c62fe4 100644 --- a/x-pack/plugins/security_solution/public/hosts/pages/hosts.tsx +++ b/x-pack/plugins/security_solution/public/hosts/pages/hosts.tsx @@ -32,7 +32,7 @@ import { setAbsoluteRangeDatePicker as dispatchSetAbsoluteRangeDatePicker } from import { SpyRoute } from '../../common/utils/route/spy_routes'; import { esQuery } from '../../../../../../src/plugins/data/public'; import { useMlCapabilities } from '../../common/components/ml_popover/hooks/use_ml_capabilities'; -import { HostsEmptyPage } from './hosts_empty_page'; +import { OverviewEmpty } from '../../overview/components/overview_empty'; import { HostsTabs } from './hosts_tabs'; import { navTabsHosts } from './nav_tabs'; import * as i18n from './translations'; @@ -149,7 +149,7 @@ export const HostsComponent = React.memo( - + )} diff --git a/x-pack/plugins/security_solution/public/hosts/pages/hosts_empty_page.tsx b/x-pack/plugins/security_solution/public/hosts/pages/hosts_empty_page.tsx deleted file mode 100644 index a01e249561e5c..0000000000000 --- a/x-pack/plugins/security_solution/public/hosts/pages/hosts_empty_page.tsx +++ /dev/null @@ -1,34 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import React from 'react'; - -import { EmptyPage } from '../../common/components/empty_page'; -import { useKibana } from '../../common/lib/kibana'; -import * as i18n from '../../common/translations'; -import { ADD_DATA_PATH } from '../../../common/constants'; - -export const HostsEmptyPage = React.memo(() => { - const { http, docLinks } = useKibana().services; - const basePath = http.basePath.get(); - - return ( - - ); -}); - -HostsEmptyPage.displayName = 'HostsEmptyPage'; diff --git a/x-pack/plugins/security_solution/public/network/pages/ip_details/index.tsx b/x-pack/plugins/security_solution/public/network/pages/ip_details/index.tsx index 162b3a7c158d5..afc9465e819c4 100644 --- a/x-pack/plugins/security_solution/public/network/pages/ip_details/index.tsx +++ b/x-pack/plugins/security_solution/public/network/pages/ip_details/index.tsx @@ -32,7 +32,7 @@ import { State, inputsSelectors } from '../../../common/store'; import { setAbsoluteRangeDatePicker as dispatchAbsoluteRangeDatePicker } from '../../../common/store/inputs/actions'; import { setIpDetailsTablesActivePageToZero as dispatchIpDetailsTablesActivePageToZero } from '../../store/actions'; import { SpyRoute } from '../../../common/utils/route/spy_routes'; -import { NetworkEmptyPage } from '../network_empty_page'; +import { OverviewEmpty } from '../../../overview/components/overview_empty'; import { NetworkHttpQueryTable } from './network_http_query_table'; import { NetworkTopCountriesQueryTable } from './network_top_countries_query_table'; import { NetworkTopNFlowQueryTable } from './network_top_n_flow_query_table'; @@ -266,7 +266,7 @@ export const IPDetailsComponent: React.FC - + )} diff --git a/x-pack/plugins/security_solution/public/network/pages/network.tsx b/x-pack/plugins/security_solution/public/network/pages/network.tsx index 4275c1641f517..c366908e3335e 100644 --- a/x-pack/plugins/security_solution/public/network/pages/network.tsx +++ b/x-pack/plugins/security_solution/public/network/pages/network.tsx @@ -33,7 +33,7 @@ import { SpyRoute } from '../../common/utils/route/spy_routes'; import { networkModel } from '../store'; import { navTabsNetwork, NetworkRoutes, NetworkRoutesLoading } from './navigation'; import { filterNetworkData } from './navigation/alerts_query_tab_body'; -import { NetworkEmptyPage } from './network_empty_page'; +import { OverviewEmpty } from '../../overview/components/overview_empty'; import * as i18n from './translations'; import { NetworkComponentProps } from './types'; import { NetworkRouteType } from './navigation/types'; @@ -166,7 +166,7 @@ const NetworkComponent = React.memo( ) : ( - + )} diff --git a/x-pack/plugins/security_solution/public/network/pages/network_empty_page.tsx b/x-pack/plugins/security_solution/public/network/pages/network_empty_page.tsx deleted file mode 100644 index dce3f85797f12..0000000000000 --- a/x-pack/plugins/security_solution/public/network/pages/network_empty_page.tsx +++ /dev/null @@ -1,34 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import React from 'react'; - -import { useKibana } from '../../common/lib/kibana'; -import { EmptyPage } from '../../common/components/empty_page'; -import * as i18n from '../../common/translations'; -import { ADD_DATA_PATH } from '../../../common/constants'; - -export const NetworkEmptyPage = React.memo(() => { - const { http, docLinks } = useKibana().services; - const basePath = http.basePath.get(); - - return ( - - ); -}); - -NetworkEmptyPage.displayName = 'NetworkEmptyPage'; 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 3cca87c613d2f..ee516edad4e47 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 @@ -40,12 +40,10 @@ const OverviewEmptyComponent: React.FC = () => { <> - {i18n.translate('xpack.securitySolution.overview.gettingStartedGuide', { - defaultMessage: 'getting started guide.', - })} + {i18nCommon.EMPTY_ACTION_SECONDARY} } @@ -62,12 +60,10 @@ const OverviewEmptyComponent: React.FC = () => { <> - {i18n.translate('xpack.securitySolution.overview.gettingStartedGuide', { - defaultMessage: 'getting started guide.', - })} + {i18nCommon.EMPTY_ACTION_SECONDARY} } From e119a7680ab9c5adcaa4913eb7504f1c6adc9431 Mon Sep 17 00:00:00 2001 From: Candace Park Date: Thu, 2 Jul 2020 18:19:52 -0400 Subject: [PATCH 13/16] type check --- .../public/overview/components/overview_empty/index.tsx | 1 - 1 file changed, 1 deletion(-) 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 ee516edad4e47..3506bbc1089ff 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 @@ -5,7 +5,6 @@ */ import React from 'react'; -import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; import { EuiLink } from '@elastic/eui'; import * as i18nCommon from '../../../common/translations'; From 613f90e30840c9a44adda78ad6e2899c6b41bf2d Mon Sep 17 00:00:00 2001 From: Candace Park Date: Mon, 6 Jul 2020 00:41:54 -0400 Subject: [PATCH 14/16] fix tests --- .../components/empty_page/__snapshots__/index.test.tsx.snap | 2 +- .../plugins/security_solution/public/common/translations.ts | 6 ++---- .../pages/ip_details/__snapshots__/index.test.tsx.snap | 2 +- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/x-pack/plugins/security_solution/public/common/components/empty_page/__snapshots__/index.test.tsx.snap b/x-pack/plugins/security_solution/public/common/components/empty_page/__snapshots__/index.test.tsx.snap index 65893f84f5e56..623b15aa76d12 100644 --- a/x-pack/plugins/security_solution/public/common/components/empty_page/__snapshots__/index.test.tsx.snap +++ b/x-pack/plugins/security_solution/public/common/components/empty_page/__snapshots__/index.test.tsx.snap @@ -18,7 +18,7 @@ exports[`renders correctly 1`] = `
} - iconType="securityAnalyticsApp" + iconType="logoSecurity" title={

My Super Title diff --git a/x-pack/plugins/security_solution/public/common/translations.ts b/x-pack/plugins/security_solution/public/common/translations.ts index c1736ff2d1487..7e6a5dc6c7b3b 100644 --- a/x-pack/plugins/security_solution/public/common/translations.ts +++ b/x-pack/plugins/security_solution/public/common/translations.ts @@ -10,10 +10,8 @@ export const EMPTY_TITLE = i18n.translate('xpack.securitySolution.pages.common.e defaultMessage: 'Welcome to Security Solution. Let’s get you started.', }); -export const EMPTY_MESSAGE = i18n.translate('xpack.securitySolution.pages.common.emptyMessage', { - defaultMessage: - 'To begin using security information and event management (Security Solution), you’ll need to add security solution related data, in Elastic Common Schema (ECS) format, to the Elastic Stack. An easy way to get started is by installing and configuring our data shippers, called Beats. For additional information, you can view our ', -}); +export const EMPTY_MESSAGE = + 'To begin using security and event management (Security Solution), you’ll need to add security solution related data, in Elastic Common Schema (ECS) format, to the Elastic Stack. An easy way to get started is by installing and configuring our data shippers, called Beats. For additional information, you can view our '; export const EMPTY_ACTION_PRIMARY = i18n.translate( 'xpack.securitySolution.pages.common.emptyActionPrimary', diff --git a/x-pack/plugins/security_solution/public/network/pages/ip_details/__snapshots__/index.test.tsx.snap b/x-pack/plugins/security_solution/public/network/pages/ip_details/__snapshots__/index.test.tsx.snap index d7af8d6910f45..93dafeff34ce9 100644 --- a/x-pack/plugins/security_solution/public/network/pages/ip_details/__snapshots__/index.test.tsx.snap +++ b/x-pack/plugins/security_solution/public/network/pages/ip_details/__snapshots__/index.test.tsx.snap @@ -9,7 +9,7 @@ exports[`Ip Details it matches the snapshot 1`] = ` border={true} title="123.456.78.90" /> - + Date: Mon, 6 Jul 2020 01:44:23 -0400 Subject: [PATCH 15/16] i18n --- x-pack/plugins/security_solution/public/common/translations.ts | 3 --- .../public/overview/components/overview_empty/index.tsx | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/x-pack/plugins/security_solution/public/common/translations.ts b/x-pack/plugins/security_solution/public/common/translations.ts index 7e6a5dc6c7b3b..a486cd90386b6 100644 --- a/x-pack/plugins/security_solution/public/common/translations.ts +++ b/x-pack/plugins/security_solution/public/common/translations.ts @@ -10,9 +10,6 @@ export const EMPTY_TITLE = i18n.translate('xpack.securitySolution.pages.common.e defaultMessage: 'Welcome to Security Solution. Let’s get you started.', }); -export const EMPTY_MESSAGE = - 'To begin using security and event management (Security Solution), you’ll need to add security solution related data, in Elastic Common Schema (ECS) format, to the Elastic Stack. An easy way to get started is by installing and configuring our data shippers, called Beats. For additional information, you can view our '; - export const EMPTY_ACTION_PRIMARY = i18n.translate( 'xpack.securitySolution.pages.common.emptyActionPrimary', { 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 3506bbc1089ff..f44f3541f66c3 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 @@ -39,7 +39,7 @@ const OverviewEmptyComponent: React.FC = () => { <> {i18nCommon.EMPTY_ACTION_SECONDARY} From 50307f8868ed1fef4fa98901064a60f0219557ef Mon Sep 17 00:00:00 2001 From: Candace Park Date: Mon, 6 Jul 2020 10:44:40 -0400 Subject: [PATCH 16/16] text changes --- .../plugins/security_solution/public/common/translations.ts | 2 +- .../public/overview/components/overview_empty/index.tsx | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/x-pack/plugins/security_solution/public/common/translations.ts b/x-pack/plugins/security_solution/public/common/translations.ts index a486cd90386b6..413119fb40f14 100644 --- a/x-pack/plugins/security_solution/public/common/translations.ts +++ b/x-pack/plugins/security_solution/public/common/translations.ts @@ -20,7 +20,7 @@ export const EMPTY_ACTION_PRIMARY = i18n.translate( export const EMPTY_ACTION_SECONDARY = i18n.translate( 'xpack.securitySolution.pages.common.emptyActionSecondary', { - defaultMessage: 'getting started guide', + defaultMessage: 'getting started guide.', } ); 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 f44f3541f66c3..33413be10079e 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 @@ -39,7 +39,7 @@ const OverviewEmptyComponent: React.FC = () => { <> {i18nCommon.EMPTY_ACTION_SECONDARY} @@ -59,7 +59,7 @@ const OverviewEmptyComponent: React.FC = () => { <> {i18nCommon.EMPTY_ACTION_SECONDARY}