From ee7bc7ed83850150df72d82fc2c50d248ccf8636 Mon Sep 17 00:00:00 2001 From: Nikita Indik Date: Mon, 14 Oct 2024 23:10:21 +0200 Subject: [PATCH] [Security Solution] Add callout to promote blog post (#195943) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit **Resolves: #195423** ## Summary This PR adds a callout to the Rule Management page. This callout displays a [link](https://www.elastic.co/blog/elastic-security-detection-engineering) to a post in Elastic blog. Once a user clicks on "x" in the top-right corner the callout will be dismissed forever. Dismissal state is saved in `localStorage`. This is only for ESS v8.16.0 and beyond. Not for Serverless. ⚠️ Currently the [link](https://www.elastic.co/blog/elastic-security-detection-engineering) leads to a 404 page because the blog post is not yet created. It'll be published in time for 8.16 release. ⚠️ UI copy is not final. It'll be reviewed by the Docs folks on Monday. I'll change it to their suggestion once they review it on Monday. ### Screenshot Scherm­afbeelding 2024-10-11 om 16 43 59 --------- Co-authored-by: Joe Peeples --- .../pages/rule_management/index.tsx | 2 + .../index.tsx | 72 +++++++++++++++++++ .../translations.ts | 29 ++++++++ 3 files changed, 103 insertions(+) create mode 100644 x-pack/plugins/security_solution/public/detections/components/callouts/blog_post_detection_engineering_callout/index.tsx create mode 100644 x-pack/plugins/security_solution/public/detections/components/callouts/blog_post_detection_engineering_callout/translations.ts 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 7033785b20052..afdc0e5ff276a 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 @@ -22,6 +22,7 @@ import { SpyRoute } from '../../../../common/utils/route/spy_routes'; import { MissingPrivilegesCallOut } from '../../../../detections/components/callouts/missing_privileges_callout'; import { MlJobCompatibilityCallout } from '../../../../detections/components/callouts/ml_job_compatibility_callout'; import { NeedAdminForUpdateRulesCallOut } from '../../../../detections/components/callouts/need_admin_for_update_callout'; +import { BlogPostDetectionEngineeringCallout } from '../../../../detections/components/callouts/blog_post_detection_engineering_callout'; import { AddElasticRulesButton } from '../../../../detections/components/rules/pre_packaged_rules/add_elastic_rules_button'; import { ValueListsFlyout } from '../../../../detections/components/value_lists_management_flyout'; import { useUserData } from '../../../../detections/components/user_info'; @@ -173,6 +174,7 @@ const RulesPageComponent: React.FC = () => { kibanaServices={kibanaServices} categories={[DEFAULT_APP_CATEGORIES.security.id]} /> + diff --git a/x-pack/plugins/security_solution/public/detections/components/callouts/blog_post_detection_engineering_callout/index.tsx b/x-pack/plugins/security_solution/public/detections/components/callouts/blog_post_detection_engineering_callout/index.tsx new file mode 100644 index 0000000000000..ec5595f86bb19 --- /dev/null +++ b/x-pack/plugins/security_solution/public/detections/components/callouts/blog_post_detection_engineering_callout/index.tsx @@ -0,0 +1,72 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { useCallback } from 'react'; +import { css } from '@emotion/css'; +import avcBannerBackground from '@kbn/avc-banner/src/avc_banner_background.svg'; +import { EuiSpacer, EuiButton, EuiCallOut, useEuiTheme } from '@elastic/eui'; +import { type CallOutMessage } from '../../../../common/components/callouts'; +import { useCallOutStorage } from '../../../../common/components/callouts/use_callout_storage'; +import * as i18n from './translations'; + +const BLOG_POST_URL = 'https://www.elastic.co/blog/elastic-security-detection-engineering'; + +const calloutMessage: CallOutMessage = { + type: 'success', + id: 'blog-post-elastic-security-detection-engineering', + title: i18n.NEW_FEATURES_BLOG_POST_CALLOUT_TITLE, + description: , +}; + +export function BlogPostDetectionEngineeringCallout() { + const { euiTheme } = useEuiTheme(); + + const { isVisible, dismiss } = useCallOutStorage([calloutMessage], 'detections'); + + const calloutStyles = css({ + paddingLeft: `${euiTheme.size.xl}`, + backgroundImage: `url(${avcBannerBackground})`, + backgroundRepeat: 'no-repeat', + backgroundPositionX: 'right', + backgroundPositionY: 'bottom', + }); + + const handleDismiss = useCallback(() => { + dismiss(calloutMessage); + }, [dismiss]); + + if (!isVisible(calloutMessage)) { + return null; + } + + return ( + <> + + {calloutMessage.description} + + + + ); +} + +function Description() { + return ( + <> + {i18n.NEW_FEATURES_BLOG_POST_CALLOUT_DESCRIPTION} + + + {i18n.NEW_FEATURES_BLOG_POST_CALLOUT_BUTTON_LABEL} + + + ); +} diff --git a/x-pack/plugins/security_solution/public/detections/components/callouts/blog_post_detection_engineering_callout/translations.ts b/x-pack/plugins/security_solution/public/detections/components/callouts/blog_post_detection_engineering_callout/translations.ts new file mode 100644 index 0000000000000..17b79200db7a3 --- /dev/null +++ b/x-pack/plugins/security_solution/public/detections/components/callouts/blog_post_detection_engineering_callout/translations.ts @@ -0,0 +1,29 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { i18n } from '@kbn/i18n'; + +export const NEW_FEATURES_BLOG_POST_CALLOUT_TITLE = i18n.translate( + 'xpack.securitySolution.detectionEngine.newFeaturesBlogPostCallout.calloutTitle', + { + defaultMessage: `Discover the power of Elastic's threat detection!`, + } +); + +export const NEW_FEATURES_BLOG_POST_CALLOUT_DESCRIPTION = i18n.translate( + 'xpack.securitySolution.detectionEngine.newFeaturesBlogPostCallout.calloutDescription', + { + defaultMessage: 'Learn about new and existing detection capabilities of Elastic Security.', + } +); + +export const NEW_FEATURES_BLOG_POST_CALLOUT_BUTTON_LABEL = i18n.translate( + 'xpack.securitySolution.detectionEngine.newFeaturesBlogPostCallout.calloutButtonLabel', + { + defaultMessage: 'Read the blog', + } +);