[Security solution] Elastic Assistant adds beta label (#161682)

This commit is contained in:
Steph Milovic 2023-07-11 14:52:45 -06:00 committed by GitHub
parent e58c455c56
commit 6673ffbf18
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 140 additions and 10 deletions

View file

@ -0,0 +1,90 @@
/*
* 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, { FunctionComponent, useMemo, useState } from 'react';
import {
EuiButtonIcon,
EuiFlexGroup,
EuiFlexItem,
EuiIcon,
EuiLink,
EuiModalHeaderTitle,
EuiPopover,
EuiText,
} from '@elastic/eui';
import type { DocLinksStart } from '@kbn/core-doc-links-browser';
import { FormattedMessage } from '@kbn/i18n-react';
import * as i18n from '../translations';
export const AssistantTitle: FunctionComponent<{
currentTitle: { title: string | JSX.Element; titleIcon: string };
docLinks: Omit<DocLinksStart, 'links'>;
}> = ({ currentTitle, docLinks }) => {
const { ELASTIC_WEBSITE_URL, DOC_LINK_VERSION } = docLinks;
const url = `${ELASTIC_WEBSITE_URL}guide/en/security/${DOC_LINK_VERSION}/security-assistant.html`;
const documentationLink = useMemo(
() => (
<EuiLink
aria-label={i18n.TOOLTIP_ARIA_LABEL}
data-test-subj="externalDocumentationLink"
external
href={url}
target="_blank"
>
{i18n.DOCUMENTATION}
</EuiLink>
),
[url]
);
const content = useMemo(
() => (
<FormattedMessage
defaultMessage="The Elastic AI Assistant is currently in beta. For more information on the assistant feature and its usage, please reference the {documentationLink}."
id="xpack.elasticAssistant.assistant.technicalPreview.tooltipContent"
values={{
documentationLink,
}}
/>
),
[documentationLink]
);
const [isPopoverOpen, setIsPopoverOpen] = useState(false);
const onButtonClick = () => setIsPopoverOpen((isOpen: boolean) => !isOpen);
const closePopover = () => setIsPopoverOpen(false);
return (
<EuiModalHeaderTitle>
<EuiFlexGroup gutterSize="xs" alignItems="center">
<EuiFlexItem grow={false}>
<EuiIcon type={currentTitle.titleIcon} size="xl" />
</EuiFlexItem>
<EuiFlexItem grow={false}>{currentTitle.title}</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiPopover
button={
<EuiButtonIcon
aria-label={i18n.TOOLTIP_ARIA_LABEL}
iconSize="l"
iconType="iInCircle"
onClick={onButtonClick}
/>
}
isOpen={isPopoverOpen}
closePopover={closePopover}
anchorPosition="upCenter"
>
<EuiText grow={false} css={{ maxWidth: '400px' }}>
<h4>{i18n.TOOLTIP_TITLE}</h4>
<p>{content}</p>
</EuiText>
</EuiPopover>
</EuiFlexItem>
</EuiFlexGroup>
</EuiModalHeaderTitle>
);
};

View file

@ -17,11 +17,9 @@ import {
EuiSwitchEvent,
EuiSwitch,
EuiCallOut,
EuiIcon,
EuiModalFooter,
EuiModalHeader,
EuiModalBody,
EuiModalHeaderTitle,
} from '@elastic/eui';
import { createPortal } from 'react-dom';
@ -29,6 +27,7 @@ import { css } from '@emotion/react';
import { OpenAiProviderType } from '@kbn/stack-connectors-plugin/common/gen_ai/constants';
import { ActionConnectorProps } from '@kbn/triggers-actions-ui-plugin/public/types';
import { AssistantTitle } from './assistant_title';
import { UpgradeButtons } from '../upgrade/upgrade_buttons';
import { getMessageFromRawResponse } from './helpers';
@ -78,6 +77,7 @@ const AssistantComponent: React.FC<Props> = ({
conversations,
defaultAllow,
defaultAllowReplacement,
docLinks,
getComments,
http,
promptContexts,
@ -452,14 +452,7 @@ const AssistantComponent: React.FC<Props> = ({
justifyContent={'spaceBetween'}
>
<EuiFlexItem grow={false}>
<EuiModalHeaderTitle>
<EuiFlexGroup alignItems={'center'}>
<EuiFlexItem grow={false}>
<EuiIcon type={currentTitle.titleIcon} size="xl" />
</EuiFlexItem>
<EuiFlexItem grow={false}>{currentTitle.title}</EuiFlexItem>
</EuiFlexGroup>
</EuiModalHeaderTitle>
<AssistantTitle currentTitle={currentTitle} docLinks={docLinks} />
</EuiFlexItem>
<EuiFlexItem

View file

@ -80,3 +80,24 @@ export const API_ERROR = i18n.translate('xpack.elasticAssistant.assistant.apiErr
defaultMessage:
'An error occurred sending your message. If the problem persists, please test the connector configuration.',
});
export const TOOLTIP_TITLE = i18n.translate(
'xpack.elasticAssistant.assistant.technicalPreview.tooltipTitle',
{
defaultMessage: 'Beta',
}
);
export const TOOLTIP_ARIA_LABEL = i18n.translate(
'xpack.elasticAssistant.documentationLinks.ariaLabel',
{
defaultMessage: 'Click to open Elastic Assistant documentation in a new tab',
}
);
export const DOCUMENTATION = i18n.translate(
'xpack.elasticAssistant.documentationLinks.documentation',
{
defaultMessage: 'documentation',
}
);

View file

@ -25,6 +25,10 @@ const ContextWrapper: React.FC = ({ children }) => (
baseAllowReplacement={[]}
defaultAllow={[]}
defaultAllowReplacement={[]}
docLinks={{
ELASTIC_WEBSITE_URL: 'https://www.elastic.co/',
DOC_LINK_VERSION: 'current',
}}
getInitialConversations={mockGetInitialConversations}
getComments={mockGetComments}
http={mockHttp}

View file

@ -12,6 +12,7 @@ import React, { useCallback, useEffect, useMemo, useState } from 'react';
import { ActionTypeRegistryContract } from '@kbn/triggers-actions-ui-plugin/public';
import { useLocalStorage } from 'react-use';
import type { DocLinksStart } from '@kbn/core-doc-links-browser';
import { updatePromptContexts } from './helpers';
import type {
PromptContext,
@ -52,6 +53,7 @@ interface AssistantProviderProps {
basePromptContexts?: PromptContextTemplate[];
baseQuickPrompts?: QuickPrompt[];
baseSystemPrompts?: Prompt[];
docLinks: Omit<DocLinksStart, 'links'>;
children: React.ReactNode;
getComments: ({
currentConversation,
@ -78,6 +80,7 @@ interface UseAssistantContext {
allSystemPrompts: Prompt[];
baseAllow: string[];
baseAllowReplacement: string[];
docLinks: Omit<DocLinksStart, 'links'>;
defaultAllow: string[];
defaultAllowReplacement: string[];
basePromptContexts: PromptContextTemplate[];
@ -119,6 +122,7 @@ export const AssistantProvider: React.FC<AssistantProviderProps> = ({
baseAllowReplacement,
defaultAllow,
defaultAllowReplacement,
docLinks,
basePromptContexts = [],
baseQuickPrompts = [],
baseSystemPrompts = BASE_SYSTEM_PROMPTS,
@ -240,6 +244,7 @@ export const AssistantProvider: React.FC<AssistantProviderProps> = ({
conversations,
defaultAllow: uniq(defaultAllow),
defaultAllowReplacement: uniq(defaultAllowReplacement),
docLinks,
getComments,
http,
promptContexts,
@ -267,6 +272,7 @@ export const AssistantProvider: React.FC<AssistantProviderProps> = ({
conversations,
defaultAllow,
defaultAllowReplacement,
docLinks,
getComments,
http,
localStorageQuickPrompts,

View file

@ -38,6 +38,10 @@ export const TestProvidersComponent: React.FC<Props> = ({ children }) => {
baseAllowReplacement={[]}
defaultAllow={[]}
defaultAllowReplacement={[]}
docLinks={{
ELASTIC_WEBSITE_URL: 'https://www.elastic.co/',
DOC_LINK_VERSION: 'current',
}}
getComments={mockGetComments}
getInitialConversations={mockGetInitialConversations}
setConversations={jest.fn()}

View file

@ -27,5 +27,6 @@
"@kbn/core-notifications-browser",
"@kbn/i18n-react",
"@kbn/ui-theme",
"@kbn/core-doc-links-browser",
]
}

View file

@ -39,6 +39,10 @@ export const TestProvidersComponent: React.FC<Props> = ({ children }) => {
baseAllowReplacement={[]}
defaultAllow={[]}
defaultAllowReplacement={[]}
docLinks={{
ELASTIC_WEBSITE_URL: 'https://www.elastic.co/',
DOC_LINK_VERSION: 'current',
}}
getComments={mockGetComments}
getInitialConversations={mockGetInitialConversations}
setConversations={jest.fn()}

View file

@ -76,6 +76,8 @@ const StartAppComponent: FC<StartAppComponent> = ({
const nameSpace = `${APP_ID}.${LOCAL_STORAGE_KEY}`;
const [darkMode] = useUiSetting$<boolean>(DEFAULT_DARK_MODE);
const { ELASTIC_WEBSITE_URL, DOC_LINK_VERSION } = useKibana().services.docLinks;
return (
<EuiErrorBoundary>
<i18n.Context>
@ -88,6 +90,7 @@ const StartAppComponent: FC<StartAppComponent> = ({
augmentMessageCodeBlocks={augmentMessageCodeBlocks}
defaultAllow={defaultAllow}
defaultAllowReplacement={defaultAllowReplacement}
docLinks={{ ELASTIC_WEBSITE_URL, DOC_LINK_VERSION }}
baseAllow={DEFAULT_ALLOW}
baseAllowReplacement={DEFAULT_ALLOW_REPLACEMENT}
basePromptContexts={Object.values(PROMPT_CONTEXTS)}

View file

@ -30,6 +30,10 @@ export const MockAssistantProviderComponent: React.FC<Props> = ({ children }) =>
baseAllow={[]}
baseAllowReplacement={[]}
defaultAllow={[]}
docLinks={{
ELASTIC_WEBSITE_URL: 'https://www.elastic.co/',
DOC_LINK_VERSION: 'current',
}}
defaultAllowReplacement={[]}
getComments={jest.fn(() => [])}
getInitialConversations={jest.fn(() => ({}))}