From 58cf152dccf661a912156fc51d1c9e46029c97a6 Mon Sep 17 00:00:00 2001 From: Coen Warmer Date: Wed, 30 Aug 2023 12:46:32 +0200 Subject: [PATCH] Assorted fixes (#165039) Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> --- .../observability_ai_assistant/kibana.jsonc | 16 +- .../public/assets/elastic_ai_assistant.png | Bin 0 -> 70328 bytes .../public/assets/illustration.svg | 920 ++++++++++++++++++ ...xpand_conversation_list_button.stories.tsx | 37 + .../hide_expand_conversation_list_button.tsx | 8 +- .../public/components/chat/chat_body.tsx | 46 +- .../public/components/chat/chat_header.tsx | 79 +- .../components/chat/chat_prompt_editor.tsx | 5 +- .../public/components/chat/chat_timeline.tsx | 40 +- .../components/chat/chat_welcome_panel.tsx | 48 + .../components/chat/conversation_list.tsx | 5 +- .../chat/experimental_feature_banner.tsx | 57 ++ .../chat/incorrect_license_panel.tsx | 77 ++ .../chat/knowledge_base_callout.tsx | 2 +- .../components/insight/insight_base.tsx | 6 +- .../public/hooks/use_license.ts | 35 + .../hooks/use_license_management_locator.ts | 26 + .../public/hooks/use_timeline.ts | 10 + .../observability_ai_assistant/public/i18n.ts | 7 + .../public/plugin.tsx | 2 + .../conversations/conversation_view.tsx | 8 - .../public/service/create_service.ts | 14 +- .../public/types.ts | 22 +- .../get_timeline_items_from_conversation.tsx | 3 +- .../public/utils/storybook_decorator.tsx | 7 + .../observability_ai_assistant/tsconfig.json | 4 +- 26 files changed, 1381 insertions(+), 103 deletions(-) create mode 100644 x-pack/plugins/observability_ai_assistant/public/assets/elastic_ai_assistant.png create mode 100644 x-pack/plugins/observability_ai_assistant/public/assets/illustration.svg create mode 100644 x-pack/plugins/observability_ai_assistant/public/components/buttons/hide_expand_conversation_list_button.stories.tsx create mode 100644 x-pack/plugins/observability_ai_assistant/public/components/chat/chat_welcome_panel.tsx create mode 100644 x-pack/plugins/observability_ai_assistant/public/components/chat/experimental_feature_banner.tsx create mode 100644 x-pack/plugins/observability_ai_assistant/public/components/chat/incorrect_license_panel.tsx create mode 100644 x-pack/plugins/observability_ai_assistant/public/hooks/use_license.ts create mode 100644 x-pack/plugins/observability_ai_assistant/public/hooks/use_license_management_locator.ts diff --git a/x-pack/plugins/observability_ai_assistant/kibana.jsonc b/x-pack/plugins/observability_ai_assistant/kibana.jsonc index e0299246377a3..ebe28df3a1141 100644 --- a/x-pack/plugins/observability_ai_assistant/kibana.jsonc +++ b/x-pack/plugins/observability_ai_assistant/kibana.jsonc @@ -7,8 +7,20 @@ "server": true, "browser": true, "configPath": ["xpack", "observabilityAIAssistant"], - "requiredPlugins": ["triggersActionsUi", "actions", "security", "features", "observabilityShared", "taskManager", "lens", "dataViews", "ruleRegistry"], - "requiredBundles": ["kibanaReact", "kibanaUtils", "fieldFormats"], + "requiredPlugins": [ + "actions", + "dataViews", + "features", + "lens", + "licensing", + "observabilityShared", + "ruleRegistry", + "security", + "share", + "taskManager", + "triggersActionsUi" + ], + "requiredBundles": ["fieldFormats", "kibanaReact", "kibanaUtils"], "optionalPlugins": [], "extraPublicDirs": [] } diff --git a/x-pack/plugins/observability_ai_assistant/public/assets/elastic_ai_assistant.png b/x-pack/plugins/observability_ai_assistant/public/assets/elastic_ai_assistant.png new file mode 100644 index 0000000000000000000000000000000000000000..63bd19136f512c4086db86fbfc6d10fdd1709f10 GIT binary patch literal 70328 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 literal 0 HcmV?d00001 diff --git a/x-pack/plugins/observability_ai_assistant/public/assets/illustration.svg b/x-pack/plugins/observability_ai_assistant/public/assets/illustration.svg new file mode 100644 index 0000000000000..363c492fec84b --- /dev/null +++ b/x-pack/plugins/observability_ai_assistant/public/assets/illustration.svg @@ -0,0 +1,920 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/x-pack/plugins/observability_ai_assistant/public/components/buttons/hide_expand_conversation_list_button.stories.tsx b/x-pack/plugins/observability_ai_assistant/public/components/buttons/hide_expand_conversation_list_button.stories.tsx new file mode 100644 index 0000000000000..d49ccdfb3823d --- /dev/null +++ b/x-pack/plugins/observability_ai_assistant/public/components/buttons/hide_expand_conversation_list_button.stories.tsx @@ -0,0 +1,37 @@ +/* + * 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 from 'react'; +import { ComponentStory } from '@storybook/react'; + +import { + HideExpandConversationListButton as Component, + HideExpandConversationListButtonProps, +} from './hide_expand_conversation_list_button'; + +export default { + component: Component, + title: 'app/Atoms/HideExpandConversationListButton', + argTypes: { + isExpanded: { + control: { + type: 'boolean', + }, + }, + }, +}; + +const Template: ComponentStory = ( + props: HideExpandConversationListButtonProps +) => ; + +const defaultProps = { + isExpanded: true, +}; + +export const HideExpandConversationListButton = Template.bind({}); +HideExpandConversationListButton.args = defaultProps; diff --git a/x-pack/plugins/observability_ai_assistant/public/components/buttons/hide_expand_conversation_list_button.tsx b/x-pack/plugins/observability_ai_assistant/public/components/buttons/hide_expand_conversation_list_button.tsx index 8921380c801e1..b23e4a9abb713 100644 --- a/x-pack/plugins/observability_ai_assistant/public/components/buttons/hide_expand_conversation_list_button.tsx +++ b/x-pack/plugins/observability_ai_assistant/public/components/buttons/hide_expand_conversation_list_button.tsx @@ -8,9 +8,11 @@ import React from 'react'; import { EuiButtonEmpty } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -export function HideExpandConversationListButton( - props: React.ComponentProps & { isExpanded: boolean } -) { +export type HideExpandConversationListButtonProps = React.ComponentProps & { + isExpanded: boolean; +}; + +export function HideExpandConversationListButton(props: HideExpandConversationListButtonProps) { return ( {props.isExpanded diff --git a/x-pack/plugins/observability_ai_assistant/public/components/chat/chat_body.tsx b/x-pack/plugins/observability_ai_assistant/public/components/chat/chat_body.tsx index 0f1039f1c5c93..5cdd3c096fc29 100644 --- a/x-pack/plugins/observability_ai_assistant/public/components/chat/chat_body.tsx +++ b/x-pack/plugins/observability_ai_assistant/public/components/chat/chat_body.tsx @@ -5,6 +5,8 @@ * 2.0. */ +import React, { useEffect, useRef } from 'react'; +import { last } from 'lodash'; import { EuiFlexGroup, EuiFlexItem, @@ -14,22 +16,24 @@ import { EuiSpacer, } from '@elastic/eui'; import { css } from '@emotion/css'; +import { euiThemeVars } from '@kbn/ui-theme'; import type { AuthenticatedUser } from '@kbn/security-plugin/common'; -import React, { useEffect, useRef } from 'react'; -import { last } from 'lodash'; import type { Message } from '../../../common/types'; import type { UseGenAIConnectorsResult } from '../../hooks/use_genai_connectors'; import type { UseKnowledgeBaseResult } from '../../hooks/use_knowledge_base'; import { useTimeline } from '../../hooks/use_timeline'; +import { useLicense } from '../../hooks/use_license'; import { useObservabilityAIAssistantChatService } from '../../hooks/use_observability_ai_assistant_chat_service'; import { MissingCredentialsCallout } from '../missing_credentials_callout'; +import { ExperimentalFeatureBanner } from './experimental_feature_banner'; +import { IncorrectLicensePanel } from './incorrect_license_panel'; import { ChatHeader } from './chat_header'; import { ChatPromptEditor } from './chat_prompt_editor'; import { ChatTimeline } from './chat_timeline'; const containerClassName = css` max-height: 100%; - max-width: 800px; + max-width: ${1200 - 250}px; // page template max width - conversation list width. `; const timelineClassName = css` @@ -40,6 +44,11 @@ const loadingSpinnerContainerClassName = css` align-self: center; `; +const incorrectLicenseContainer = css` + height: 100%; + padding: ${euiThemeVars.euiPanelPaddingModifiers.paddingMedium}; +`; + export function ChatBody({ title, loading, @@ -47,6 +56,7 @@ export function ChatBody({ connectors, knowledgeBase, connectorsManagementHref, + conversationId, currentUser, onChatUpdate, onChatComplete, @@ -64,6 +74,9 @@ export function ChatBody({ onChatComplete: (messages: Message[]) => void; onSaveTitle: (title: string) => void; }) { + const license = useLicense(); + const hasCorrectLicense = license?.hasAtLeast('enterprise'); + const chatService = useObservabilityAIAssistantChatService(); const timeline = useTimeline({ @@ -126,7 +139,24 @@ export function ChatBody({ // eslint-disable-next-line react-hooks/exhaustive-deps }, [timelineContainerRef.current]); - if (connectors.loading || knowledgeBase.status.loading) { + if (!hasCorrectLicense && !conversationId) { + footer = ( + <> + + + + + + + + + + + + + + ); + } else if (connectors.loading || knowledgeBase.status.loading) { footer = ( @@ -162,7 +192,7 @@ export function ChatBody({ @@ -174,12 +204,16 @@ export function ChatBody({ return ( + + + diff --git a/x-pack/plugins/observability_ai_assistant/public/components/chat/chat_header.tsx b/x-pack/plugins/observability_ai_assistant/public/components/chat/chat_header.tsx index ea410160408a9..0314380a87657 100644 --- a/x-pack/plugins/observability_ai_assistant/public/components/chat/chat_header.tsx +++ b/x-pack/plugins/observability_ai_assistant/public/components/chat/chat_header.tsx @@ -17,13 +17,13 @@ import { i18n } from '@kbn/i18n'; import { css } from '@emotion/css'; import { AssistantAvatar } from '../assistant_avatar'; import { ConnectorSelectorBase } from '../connector_selector/connector_selector_base'; -import { EMPTY_CONVERSATION_TITLE } from '../../i18n'; +import { EMPTY_CONVERSATION_TITLE, UPGRADE_LICENSE_TITLE } from '../../i18n'; import { KnowledgeBaseCallout } from './knowledge_base_callout'; -import { TechnicalPreviewBadge } from '../technical_preview_badge'; import { useUnmountAndRemountWhenPropChanges } from '../../hooks/use_unmount_and_remount_when_prop_changes'; import type { UseGenAIConnectorsResult } from '../../hooks/use_genai_connectors'; import type { UseKnowledgeBaseResult } from '../../hooks/use_knowledge_base'; +// needed to prevent InlineTextEdit component from expanding container const minWidthClassName = css` min-width: 0; `; @@ -31,19 +31,21 @@ const minWidthClassName = css` export function ChatHeader({ title, loading, - knowledgeBase, + licenseInvalid, connectors, + knowledgeBase, onSaveTitle, }: { title: string; loading: boolean; - knowledgeBase: UseKnowledgeBaseResult; + licenseInvalid: boolean; connectors: UseGenAIConnectorsResult; + knowledgeBase: UseKnowledgeBaseResult; onSaveTitle?: (title: string) => void; }) { const hasTitle = !!title; - const displayedTitle = title || EMPTY_CONVERSATION_TITLE; + const displayedTitle = licenseInvalid ? UPGRADE_LICENSE_TITLE : title || EMPTY_CONVERSATION_TITLE; const theme = useEuiTheme(); @@ -55,53 +57,46 @@ export function ChatHeader({ return ( - + - {loading ? : } + {loading ? : } + - - - - {shouldRender ? ( - - ) : null} + + {shouldRender ? ( + + ) : null} + + + + + - - + + {!licenseInvalid ? : null} - - - - - - ); diff --git a/x-pack/plugins/observability_ai_assistant/public/components/chat/chat_prompt_editor.tsx b/x-pack/plugins/observability_ai_assistant/public/components/chat/chat_prompt_editor.tsx index b3c5b6daca72a..3b2ad1cdf292c 100644 --- a/x-pack/plugins/observability_ai_assistant/public/components/chat/chat_prompt_editor.tsx +++ b/x-pack/plugins/observability_ai_assistant/public/components/chat/chat_prompt_editor.tsx @@ -168,7 +168,7 @@ export function ChatPromptEditor({ @@ -177,7 +177,7 @@ export function ChatPromptEditor({ iconType="cross" iconSide="right" size="xs" - disabled={loading} + disabled={loading || disabled} onClick={handleClearSelection} > {i18n.translate('xpack.observabilityAiAssistant.prompt.emptySelection', { @@ -238,6 +238,7 @@ export function ChatPromptEditor({ ) : ( !item.display.hide); + return ( {compact( - items.map((item, index) => - !item.display.hide ? ( - { - onFeedback(item, feedback); - }} - onRegenerateClick={() => { - onRegenerate(item); - }} - onEditSubmit={(message) => { - return onEdit(item, message); - }} - onStopGeneratingClick={onStopGenerating} - /> - ) : null - ) + filteredItems.map((item, index) => ( + { + onFeedback(item, feedback); + }} + onRegenerateClick={() => { + onRegenerate(item); + }} + onEditSubmit={(message) => { + return onEdit(item, message); + }} + onStopGeneratingClick={onStopGenerating} + /> + )) )} + {filteredItems.length === 1 ? : null} ); } diff --git a/x-pack/plugins/observability_ai_assistant/public/components/chat/chat_welcome_panel.tsx b/x-pack/plugins/observability_ai_assistant/public/components/chat/chat_welcome_panel.tsx new file mode 100644 index 0000000000000..32fba0b72a828 --- /dev/null +++ b/x-pack/plugins/observability_ai_assistant/public/components/chat/chat_welcome_panel.tsx @@ -0,0 +1,48 @@ +/* + * 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 from 'react'; +import { EuiFlexGroup, EuiImage, EuiPanel, EuiText, EuiTitle } from '@elastic/eui'; +import { css } from '@emotion/css'; +import { i18n } from '@kbn/i18n'; +import { euiThemeVars } from '@kbn/ui-theme'; +import ctaImage from '../../assets/elastic_ai_assistant.png'; + +const incorrectLicenseContainer = css` + height: 100%; + padding: ${euiThemeVars.euiPanelPaddingModifiers.paddingMedium}; +`; + +export function ChatWelcomePanel() { + return ( + + + + +

+ {i18n.translate('xpack.observabilityAiAssistant.chatWelcomePanel.title', { + defaultMessage: "Let's work on this together", + })} +

+
+ +

+ {i18n.translate('xpack.observabilityAiAssistant.chatWelcomePanel.body', { + defaultMessage: + 'Elastic AI Assistant is an experimental feature. Make sure to provide feedback when you interact with it.', + })} +

+
+
+
+ ); +} diff --git a/x-pack/plugins/observability_ai_assistant/public/components/chat/conversation_list.tsx b/x-pack/plugins/observability_ai_assistant/public/components/chat/conversation_list.tsx index a230a49c5a9fb..08cb45387a9ef 100644 --- a/x-pack/plugins/observability_ai_assistant/public/components/chat/conversation_list.tsx +++ b/x-pack/plugins/observability_ai_assistant/public/components/chat/conversation_list.tsx @@ -5,6 +5,7 @@ * 2.0. */ +import React from 'react'; import { EuiFlexGroup, EuiFlexItem, @@ -18,7 +19,6 @@ import { } from '@elastic/eui'; import { css } from '@emotion/css'; import { i18n } from '@kbn/i18n'; -import React from 'react'; import { NewChatButton } from '../buttons/new_chat_button'; const containerClassName = css` @@ -43,17 +43,16 @@ const newChatButtonWrapperClassName = css` export function ConversationList({ selected, - onClickNewChat, loading, error, conversations, + onClickNewChat, onClickDeleteConversation, }: { selected: string; loading: boolean; error?: any; conversations?: Array<{ id: string; label: string; href?: string }>; - onClickConversation: (conversationId: string) => void; onClickNewChat: () => void; onClickDeleteConversation: (id: string) => void; }) { diff --git a/x-pack/plugins/observability_ai_assistant/public/components/chat/experimental_feature_banner.tsx b/x-pack/plugins/observability_ai_assistant/public/components/chat/experimental_feature_banner.tsx new file mode 100644 index 0000000000000..48935a49ccf02 --- /dev/null +++ b/x-pack/plugins/observability_ai_assistant/public/components/chat/experimental_feature_banner.tsx @@ -0,0 +1,57 @@ +/* + * 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 from 'react'; +import { + EuiButton, + EuiFlexGroup, + EuiFlexItem, + EuiHorizontalRule, + EuiImage, + EuiPanel, +} from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n-react'; +import illustration from '../../assets/illustration.svg'; + +export function ExperimentalFeatureBanner() { + return ( + <> + + + + + + + + Tech Preview }} + /> + + + + + {i18n.translate( + 'xpack.observabilityAiAssistant.experimentalFunctionBanner.feedbackButton', + { defaultMessage: 'Give feedback' } + )} + + + + + + + ); +} diff --git a/x-pack/plugins/observability_ai_assistant/public/components/chat/incorrect_license_panel.tsx b/x-pack/plugins/observability_ai_assistant/public/components/chat/incorrect_license_panel.tsx new file mode 100644 index 0000000000000..d728507e1e362 --- /dev/null +++ b/x-pack/plugins/observability_ai_assistant/public/components/chat/incorrect_license_panel.tsx @@ -0,0 +1,77 @@ +/* + * 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 from 'react'; +import { + EuiButton, + EuiButtonEmpty, + EuiFlexGroup, + EuiFlexItem, + EuiImage, + EuiPanel, + EuiText, + EuiTitle, +} from '@elastic/eui'; +import { css } from '@emotion/css'; +import { i18n } from '@kbn/i18n'; +import { euiThemeVars } from '@kbn/ui-theme'; +import { UPGRADE_LICENSE_TITLE } from '../../i18n'; +import ctaImage from '../../assets/elastic_ai_assistant.png'; +import { useLicenseManagementLocator } from '../../hooks/use_license_management_locator'; + +const incorrectLicenseContainer = css` + height: 100%; + padding: ${euiThemeVars.euiPanelPaddingModifiers.paddingMedium}; +`; + +export function IncorrectLicensePanel() { + const handleNavigateToLicenseManagement = useLicenseManagementLocator(); + + return ( + + + + +

{UPGRADE_LICENSE_TITLE}

+
+ +

+ {i18n.translate('xpack.observabilityAiAssistant.incorrectLicense.body', { + defaultMessage: 'You need a Platinum license to use the Elastic AI Assistant.', + })} +

+
+ + + + + {i18n.translate( + 'xpack.observabilityAiAssistant.incorrectLicense.subscriptionPlansButton', + { + defaultMessage: 'Subscription plans', + } + )} + + + + + {i18n.translate('xpack.observabilityAiAssistant.incorrectLicense.manageLicense', { + defaultMessage: 'Manage license', + })} + + + + +
+
+ ); +} diff --git a/x-pack/plugins/observability_ai_assistant/public/components/chat/knowledge_base_callout.tsx b/x-pack/plugins/observability_ai_assistant/public/components/chat/knowledge_base_callout.tsx index e5eee16503235..b8f3b8bd7ef82 100644 --- a/x-pack/plugins/observability_ai_assistant/public/components/chat/knowledge_base_callout.tsx +++ b/x-pack/plugins/observability_ai_assistant/public/components/chat/knowledge_base_callout.tsx @@ -111,7 +111,7 @@ export function KnowledgeBaseCallout({ knowledgeBase }: { knowledgeBase: UseKnow hasShadow={false} borderRadius="none" color={color} - paddingSize={knowledgeBase.status.value?.ready ? 'none' : 's'} + paddingSize="s" css={{ width: 'max-content' }} > {content} diff --git a/x-pack/plugins/observability_ai_assistant/public/components/insight/insight_base.tsx b/x-pack/plugins/observability_ai_assistant/public/components/insight/insight_base.tsx index ff22f15b7c948..bef2c2730a553 100644 --- a/x-pack/plugins/observability_ai_assistant/public/components/insight/insight_base.tsx +++ b/x-pack/plugins/observability_ai_assistant/public/components/insight/insight_base.tsx @@ -21,7 +21,7 @@ import { import { i18n } from '@kbn/i18n'; import React, { useState } from 'react'; import { AssistantAvatar } from '../assistant_avatar'; -import { TechnicalPreviewBadge } from '../technical_preview_badge'; +import { ExperimentalFeatureBanner } from '../chat/experimental_feature_banner'; export interface InsightBaseProps { title: string; @@ -117,15 +117,13 @@ export function InsightBase({
) : null} - - - ) : null } onToggle={onToggle} > + {children} diff --git a/x-pack/plugins/observability_ai_assistant/public/hooks/use_license.ts b/x-pack/plugins/observability_ai_assistant/public/hooks/use_license.ts new file mode 100644 index 0000000000000..c28e7da132569 --- /dev/null +++ b/x-pack/plugins/observability_ai_assistant/public/hooks/use_license.ts @@ -0,0 +1,35 @@ +/* + * 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 { useCallback } from 'react'; +import { Observable } from 'rxjs'; +import useObservable from 'react-use/lib/useObservable'; +import type { ILicense, LicenseType } from '@kbn/licensing-plugin/public'; +import { useObservabilityAIAssistant } from './use_observability_ai_assistant'; + +interface UseLicenseReturnValue { + getLicense: () => ILicense | null; + hasAtLeast: (level: LicenseType) => boolean | undefined; +} + +export const useLicense = (): UseLicenseReturnValue => { + const service = useObservabilityAIAssistant(); + + const license = useObservable(service.getLicense() ?? new Observable(), null); + + return { + getLicense: () => license, + hasAtLeast: useCallback( + (level: LicenseType) => { + if (!license) return; + + return !!license && license.isAvailable && license.isActive && license.hasAtLeast(level); + }, + [license] + ), + }; +}; diff --git a/x-pack/plugins/observability_ai_assistant/public/hooks/use_license_management_locator.ts b/x-pack/plugins/observability_ai_assistant/public/hooks/use_license_management_locator.ts new file mode 100644 index 0000000000000..fe6c636e5286e --- /dev/null +++ b/x-pack/plugins/observability_ai_assistant/public/hooks/use_license_management_locator.ts @@ -0,0 +1,26 @@ +/* + * 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 { useObservabilityAIAssistant } from './use_observability_ai_assistant'; + +const LICENSE_MANAGEMENT_LOCATOR = 'LICENSE_MANAGEMENT_LOCATOR'; + +export const useLicenseManagementLocator = () => { + const service = useObservabilityAIAssistant(); + + const locators = service.getLicenseManagementLocator(); + + const locator = locators.url.locators.get(LICENSE_MANAGEMENT_LOCATOR); + + // license management does not exist on serverless + if (!locator) return; + + return () => + locator.navigate({ + page: 'dashboard', + }); +}; diff --git a/x-pack/plugins/observability_ai_assistant/public/hooks/use_timeline.ts b/x-pack/plugins/observability_ai_assistant/public/hooks/use_timeline.ts index bd4b158fee0c1..9bc3ea8a4e90b 100644 --- a/x-pack/plugins/observability_ai_assistant/public/hooks/use_timeline.ts +++ b/x-pack/plugins/observability_ai_assistant/public/hooks/use_timeline.ts @@ -10,6 +10,7 @@ import type { AuthenticatedUser } from '@kbn/security-plugin/common'; import { last } from 'lodash'; import { useEffect, useMemo, useRef, useState } from 'react'; import type { Subscription } from 'rxjs'; +import usePrevious from 'react-use/lib/usePrevious'; import { i18n } from '@kbn/i18n'; import { ContextDefinition, @@ -52,12 +53,14 @@ export type UseTimelineResult = Pick< export function useTimeline({ messages, connectors, + conversationId, currentUser, chatService, onChatUpdate, onChatComplete, }: { messages: Message[]; + conversationId?: string; connectors: UseGenAIConnectorsResult; currentUser?: Pick; chatService: ObservabilityAIAssistantChatService; @@ -89,6 +92,13 @@ export function useTimeline({ const [pendingMessage, setPendingMessage] = useState(); + const prevConversationId = usePrevious(conversationId); + useEffect(() => { + if (prevConversationId !== conversationId && pendingMessage?.error) { + setPendingMessage(undefined); + } + }, [conversationId, pendingMessage?.error, prevConversationId]); + function chat(nextMessages: Message[]): Promise { const controller = new AbortController(); diff --git a/x-pack/plugins/observability_ai_assistant/public/i18n.ts b/x-pack/plugins/observability_ai_assistant/public/i18n.ts index 393d4ae7e8f10..533e0fff950b9 100644 --- a/x-pack/plugins/observability_ai_assistant/public/i18n.ts +++ b/x-pack/plugins/observability_ai_assistant/public/i18n.ts @@ -11,3 +11,10 @@ export const EMPTY_CONVERSATION_TITLE = i18n.translate( 'xpack.observabilityAiAssistant.emptyConversationTitle', { defaultMessage: 'New conversation' } ); + +export const UPGRADE_LICENSE_TITLE = i18n.translate( + 'xpack.observabilityAiAssistant.incorrectLicense.title', + { + defaultMessage: 'Upgrade your license', + } +); diff --git a/x-pack/plugins/observability_ai_assistant/public/plugin.tsx b/x-pack/plugins/observability_ai_assistant/public/plugin.tsx index 965a97e4a0a87..6e9eb6dc73196 100644 --- a/x-pack/plugins/observability_ai_assistant/public/plugin.tsx +++ b/x-pack/plugins/observability_ai_assistant/public/plugin.tsx @@ -97,6 +97,8 @@ export class ObservabilityAIAssistantPlugin const service = (this.service = createService({ coreStart, securityStart: pluginsStart.security, + licenseStart: pluginsStart.licensing, + shareStart: pluginsStart.share, enabled: coreStart.application.capabilities.observabilityAIAssistant.show === true, })); diff --git a/x-pack/plugins/observability_ai_assistant/public/routes/conversations/conversation_view.tsx b/x-pack/plugins/observability_ai_assistant/public/routes/conversations/conversation_view.tsx index 557b04bb1fa88..c9331f75244b7 100644 --- a/x-pack/plugins/observability_ai_assistant/public/routes/conversations/conversation_view.tsx +++ b/x-pack/plugins/observability_ai_assistant/public/routes/conversations/conversation_view.tsx @@ -134,14 +134,6 @@ export function ConversationView() { loading={conversations.loading || isUpdatingList} error={conversations.error} conversations={displayedConversations} - onClickConversation={(nextConversationId) => { - observabilityAIAssistantRouter.push('/conversations/{conversationId}', { - path: { - conversationId: nextConversationId, - }, - query: {}, - }); - }} onClickNewChat={() => { observabilityAIAssistantRouter.push('/conversations/new', { path: {}, diff --git a/x-pack/plugins/observability_ai_assistant/public/service/create_service.ts b/x-pack/plugins/observability_ai_assistant/public/service/create_service.ts index af932be474de4..5e7356250d515 100644 --- a/x-pack/plugins/observability_ai_assistant/public/service/create_service.ts +++ b/x-pack/plugins/observability_ai_assistant/public/service/create_service.ts @@ -6,18 +6,24 @@ */ import type { CoreStart } from '@kbn/core/public'; -import { SecurityPluginStart } from '@kbn/security-plugin/public'; +import type { LicensingPluginStart } from '@kbn/licensing-plugin/public'; +import type { SecurityPluginStart } from '@kbn/security-plugin/public'; +import type { SharePluginStart } from '@kbn/share-plugin/public'; import { createCallObservabilityAIAssistantAPI } from '../api'; import type { ChatRegistrationFunction, ObservabilityAIAssistantService } from '../types'; export function createService({ coreStart, - securityStart, enabled, + licenseStart, + securityStart, + shareStart, }: { coreStart: CoreStart; - securityStart: SecurityPluginStart; enabled: boolean; + licenseStart: LicensingPluginStart; + securityStart: SecurityPluginStart; + shareStart: SharePluginStart; }): ObservabilityAIAssistantService & { register: (fn: ChatRegistrationFunction) => void } { const client = createCallObservabilityAIAssistantAPI(coreStart); @@ -37,5 +43,7 @@ export function createService({ callApi: client, getCurrentUser: () => securityStart.authc.getCurrentUser(), + getLicense: () => licenseStart.license$, + getLicenseManagementLocator: () => shareStart, }; } diff --git a/x-pack/plugins/observability_ai_assistant/public/types.ts b/x-pack/plugins/observability_ai_assistant/public/types.ts index 909a6f348eaec..6883a33309fcb 100644 --- a/x-pack/plugins/observability_ai_assistant/public/types.ts +++ b/x-pack/plugins/observability_ai_assistant/public/types.ts @@ -29,6 +29,8 @@ import type { DataViewsPublicPluginSetup, DataViewsPublicPluginStart, } from '@kbn/data-views-plugin/public'; +import type { LicensingPluginStart, ILicense } from '@kbn/licensing-plugin/public'; +import type { SharePluginStart } from '@kbn/share-plugin/public'; import type { ContextDefinition, FunctionDefinition, @@ -85,6 +87,8 @@ export interface ObservabilityAIAssistantService { isEnabled: () => boolean; callApi: ObservabilityAIAssistantAPIClient; getCurrentUser: () => Promise; + getLicense: () => Observable; + getLicenseManagementLocator: () => SharePluginStart; start: ({}: { signal: AbortSignal }) => Promise; } @@ -94,20 +98,22 @@ export interface ObservabilityAIAssistantPluginStart extends ObservabilityAIAssi export interface ObservabilityAIAssistantPluginSetup {} export interface ObservabilityAIAssistantPluginSetupDependencies { - triggersActionsUi: TriggersAndActionsUIPublicPluginSetup; - security: SecurityPluginSetup; + dataViews: DataViewsPublicPluginSetup; features: FeaturesPluginSetup; - observabilityShared: ObservabilitySharedPluginSetup; lens: LensPublicSetup; - dataViews: DataViewsPublicPluginSetup; + observabilityShared: ObservabilitySharedPluginSetup; + security: SecurityPluginSetup; + triggersActionsUi: TriggersAndActionsUIPublicPluginSetup; } export interface ObservabilityAIAssistantPluginStartDependencies { - security: SecurityPluginStart; - triggersActionsUi: TriggersAndActionsUIPublicPluginStart; - observabilityShared: ObservabilitySharedPluginStart; + dataViews: DataViewsPublicPluginStart; features: FeaturesPluginStart; lens: LensPublicStart; - dataViews: DataViewsPublicPluginStart; + licensing: LicensingPluginStart; + observabilityShared: ObservabilitySharedPluginStart; + security: SecurityPluginStart; + share: SharePluginStart; + triggersActionsUi: TriggersAndActionsUIPublicPluginStart; } export interface ConfigSchema {} diff --git a/x-pack/plugins/observability_ai_assistant/public/utils/get_timeline_items_from_conversation.tsx b/x-pack/plugins/observability_ai_assistant/public/utils/get_timeline_items_from_conversation.tsx index e8aad76b7abda..e535f6c1a059c 100644 --- a/x-pack/plugins/observability_ai_assistant/public/utils/get_timeline_items_from_conversation.tsx +++ b/x-pack/plugins/observability_ai_assistant/public/utils/get_timeline_items_from_conversation.tsx @@ -123,7 +123,8 @@ export function getTimelineItemsfromConversation({ parsedContent = message.message.content; } - const isError = typeof parsedContent === 'object' && 'error' in parsedContent; + const isError = + parsedContent && typeof parsedContent === 'object' && 'error' in parsedContent; title = !isError ? ( new Observable(), + getLicenseManagementLocator: () => + ({ + url: {}, + navigate: () => {}, + } as unknown as SharePluginStart), }; export function KibanaReactStorybookDecorator(Story: ComponentType) { diff --git a/x-pack/plugins/observability_ai_assistant/tsconfig.json b/x-pack/plugins/observability_ai_assistant/tsconfig.json index ddbd38c21bc5d..afdc9a4a89243 100644 --- a/x-pack/plugins/observability_ai_assistant/tsconfig.json +++ b/x-pack/plugins/observability_ai_assistant/tsconfig.json @@ -44,7 +44,9 @@ "@kbn/data-views-plugin", "@kbn/task-manager-plugin", "@kbn/es-query", - "@kbn/rule-registry-plugin" + "@kbn/rule-registry-plugin", + "@kbn/licensing-plugin", + "@kbn/share-plugin" ], "exclude": ["target/**/*"] }