Skip to content

Commit

Permalink
Assorted fixes (#165039)
Browse files Browse the repository at this point in the history
Co-authored-by: kibanamachine <[email protected]>
  • Loading branch information
CoenWarmer and kibanamachine authored Aug 30, 2023
1 parent 5266327 commit 58cf152
Show file tree
Hide file tree
Showing 26 changed files with 1,381 additions and 103 deletions.
16 changes: 14 additions & 2 deletions x-pack/plugins/observability_ai_assistant/kibana.jsonc
Original file line number Diff line number Diff line change
Expand Up @@ -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": []
}
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -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<typeof Component> = (
props: HideExpandConversationListButtonProps
) => <Component {...props} />;

const defaultProps = {
isExpanded: true,
};

export const HideExpandConversationListButton = Template.bind({});
HideExpandConversationListButton.args = defaultProps;
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,11 @@ import React from 'react';
import { EuiButtonEmpty } from '@elastic/eui';
import { i18n } from '@kbn/i18n';

export function HideExpandConversationListButton(
props: React.ComponentProps<typeof EuiButtonEmpty> & { isExpanded: boolean }
) {
export type HideExpandConversationListButtonProps = React.ComponentProps<typeof EuiButtonEmpty> & {
isExpanded: boolean;
};

export function HideExpandConversationListButton(props: HideExpandConversationListButtonProps) {
return (
<EuiButtonEmpty iconType={props.isExpanded ? 'menuLeft' : 'menuRight'} size="xs" {...props}>
{props.isExpanded
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
* 2.0.
*/

import React, { useEffect, useRef } from 'react';
import { last } from 'lodash';
import {
EuiFlexGroup,
EuiFlexItem,
Expand All @@ -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`
Expand All @@ -40,13 +44,19 @@ const loadingSpinnerContainerClassName = css`
align-self: center;
`;

const incorrectLicenseContainer = css`
height: 100%;
padding: ${euiThemeVars.euiPanelPaddingModifiers.paddingMedium};
`;

export function ChatBody({
title,
loading,
messages,
connectors,
knowledgeBase,
connectorsManagementHref,
conversationId,
currentUser,
onChatUpdate,
onChatComplete,
Expand All @@ -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({
Expand Down Expand Up @@ -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 = (
<>
<EuiFlexItem grow className={incorrectLicenseContainer}>
<IncorrectLicensePanel />
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiHorizontalRule margin="none" />
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiPanel hasBorder={false} hasShadow={false} paddingSize="m">
<ChatPromptEditor loading={isLoading} disabled onSubmit={timeline.onSubmit} />
<EuiSpacer size="s" />
</EuiPanel>
</EuiFlexItem>
</>
);
} else if (connectors.loading || knowledgeBase.status.loading) {
footer = (
<EuiFlexItem className={loadingSpinnerContainerClassName}>
<EuiLoadingSpinner />
Expand Down Expand Up @@ -162,7 +192,7 @@ export function ChatBody({
<EuiPanel hasBorder={false} hasShadow={false} paddingSize="m">
<ChatPromptEditor
loading={isLoading}
disabled={!connectors.selectedConnector}
disabled={!connectors.selectedConnector || !hasCorrectLicense}
onSubmit={timeline.onSubmit}
/>
<EuiSpacer size="s" />
Expand All @@ -174,12 +204,16 @@ export function ChatBody({

return (
<EuiFlexGroup direction="column" gutterSize="none" className={containerClassName}>
<EuiFlexItem grow={false}>
<ExperimentalFeatureBanner />
</EuiFlexItem>
<EuiFlexItem grow={false}>
<ChatHeader
title={title}
connectors={connectors}
licenseInvalid={!hasCorrectLicense && !conversationId}
knowledgeBase={knowledgeBase}
loading={loading}
title={title}
onSaveTitle={onSaveTitle}
/>
</EuiFlexItem>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,33 +17,35 @@ 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;
`;

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();

Expand All @@ -55,53 +57,46 @@ export function ChatHeader({

return (
<EuiPanel paddingSize="m" hasBorder={false} hasShadow={false} borderRadius="none">
<EuiFlexGroup alignItems="flexStart" gutterSize="m" responsive={false}>
<EuiFlexGroup gutterSize="m" responsive={false}>
<EuiFlexItem grow={false}>
{loading ? <EuiLoadingSpinner size="xl" /> : <AssistantAvatar size="m" />}
{loading ? <EuiLoadingSpinner size="l" /> : <AssistantAvatar size="s" />}
</EuiFlexItem>

<EuiFlexItem grow className={minWidthClassName}>
<EuiFlexGroup direction="column" gutterSize="none" className={minWidthClassName}>
<EuiFlexItem grow={false} className={minWidthClassName}>
<EuiFlexGroup
direction="row"
gutterSize="m"
className={minWidthClassName}
alignItems="center"
>
<EuiFlexItem grow className={minWidthClassName}>
{shouldRender ? (
<EuiInlineEditTitle
heading="h2"
size="s"
defaultValue={displayedTitle}
className={css`
color: ${hasTitle
? theme.euiTheme.colors.text
: theme.euiTheme.colors.subduedText};
`}
inputAriaLabel={i18n.translate(
'xpack.observabilityAiAssistant.chatHeader.editConversationInput',
{ defaultMessage: 'Edit conversation' }
)}
editModeProps={{ inputProps: { inputRef } }}
isReadOnly={!Boolean(onSaveTitle)}
onSave={onSaveTitle}
/>
) : null}
<EuiFlexItem className={minWidthClassName}>
{shouldRender ? (
<EuiInlineEditTitle
heading="h2"
size="s"
defaultValue={displayedTitle}
className={css`
color: ${hasTitle
? theme.euiTheme.colors.text
: theme.euiTheme.colors.subduedText};
`}
inputAriaLabel={i18n.translate(
'xpack.observabilityAiAssistant.chatHeader.editConversationInput',
{ defaultMessage: 'Edit conversation' }
)}
editModeProps={{ inputProps: { inputRef } }}
isReadOnly={licenseInvalid || !Boolean(onSaveTitle)}
onSave={onSaveTitle}
/>
) : null}
</EuiFlexItem>
<EuiFlexItem>
<EuiFlexGroup>
<EuiFlexItem grow>
<ConnectorSelectorBase {...connectors} />
</EuiFlexItem>
<EuiFlexItem grow={false} className={minWidthClassName}>
<TechnicalPreviewBadge />
<EuiFlexItem grow={false}>
{!licenseInvalid ? <KnowledgeBaseCallout knowledgeBase={knowledgeBase} /> : null}
</EuiFlexItem>
</EuiFlexGroup>
</EuiFlexItem>
<EuiFlexItem>
<KnowledgeBaseCallout knowledgeBase={knowledgeBase} />
</EuiFlexItem>
</EuiFlexGroup>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<ConnectorSelectorBase {...connectors} />
</EuiFlexItem>
</EuiFlexGroup>
</EuiPanel>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ export function ChatPromptEditor({
<FunctionListPopover
selectedFunctionName={selectedFunctionName}
onSelectFunction={handleSelectFunction}
disabled={loading}
disabled={loading || disabled}
/>
</EuiFlexItem>
<EuiFlexItem grow={false}>
Expand All @@ -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', {
Expand Down Expand Up @@ -238,6 +238,7 @@ export function ChatPromptEditor({
</EuiPanel>
) : (
<EuiTextArea
disabled={disabled}
fullWidth
inputRef={textAreaRef}
placeholder={i18n.translate('xpack.observabilityAiAssistant.prompt.placeholder', {
Expand Down
Loading

0 comments on commit 58cf152

Please sign in to comment.