Skip to content

Commit

Permalink
[Security solution] Assistant package assistant/index.tsx cleanup (e…
Browse files Browse the repository at this point in the history
  • Loading branch information
stephmilovic authored Aug 21, 2024
1 parent e3d6cf6 commit 730f8ea
Show file tree
Hide file tree
Showing 79 changed files with 1,348 additions and 2,466 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/*
* 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, { Dispatch, SetStateAction } from 'react';
import { EuiFlexGroup, EuiFlexItem, EuiPanel, EuiText } from '@elastic/eui';
import { css } from '@emotion/react';
import { PromptResponse } from '@kbn/elastic-assistant-common';
import { QueryObserverResult } from '@tanstack/react-query';
import { Conversation } from '../../..';
import { AssistantAnimatedIcon } from '../assistant_animated_icon';
import { SystemPrompt } from '../prompt_editor/system_prompt';
import { SetupKnowledgeBaseButton } from '../../knowledge_base/setup_knowledge_base_button';
import * as i18n from '../translations';

interface Props {
currentConversation: Conversation | undefined;
currentSystemPromptId: string | undefined;
isSettingsModalVisible: boolean;
refetchCurrentUserConversations: () => Promise<
QueryObserverResult<Record<string, Conversation>, unknown>
>;
setIsSettingsModalVisible: Dispatch<SetStateAction<boolean>>;
setCurrentSystemPromptId: Dispatch<SetStateAction<string | undefined>>;
allSystemPrompts: PromptResponse[];
}

export const EmptyConvo: React.FC<Props> = ({
allSystemPrompts,
currentConversation,
currentSystemPromptId,
isSettingsModalVisible,
refetchCurrentUserConversations,
setCurrentSystemPromptId,
setIsSettingsModalVisible,
}) => {
return (
<EuiFlexGroup alignItems="center" justifyContent="center">
<EuiFlexItem grow={false}>
<EuiPanel
hasShadow={false}
css={css`
max-width: 400px;
text-align: center;
`}
>
<EuiFlexGroup alignItems="center" justifyContent="center" direction="column">
<EuiFlexItem grow={false}>
<AssistantAnimatedIcon />
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiText>
<h3>{i18n.EMPTY_SCREEN_TITLE}</h3>
<p>{i18n.EMPTY_SCREEN_DESCRIPTION}</p>
</EuiText>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<SystemPrompt
conversation={currentConversation}
currentSystemPromptId={currentSystemPromptId}
onSystemPromptSelectionChange={setCurrentSystemPromptId}
isSettingsModalVisible={isSettingsModalVisible}
setIsSettingsModalVisible={setIsSettingsModalVisible}
allSystemPrompts={allSystemPrompts}
refetchConversations={refetchCurrentUserConversations}
/>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<SetupKnowledgeBaseButton />
</EuiFlexItem>
</EuiFlexGroup>
</EuiPanel>
</EuiFlexItem>
</EuiFlexGroup>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
/*
* 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, {
Dispatch,
FunctionComponent,
SetStateAction,
useEffect,
useMemo,
useRef,
} from 'react';
import { EuiEmptyPrompt, EuiFlexGroup, EuiFlexItem, EuiPanel, EuiText } from '@elastic/eui';
import { HttpSetup } from '@kbn/core-http-browser';
import { euiThemeVars } from '@kbn/ui-theme';
import { css } from '@emotion/react';
import { PromptResponse } from '@kbn/elastic-assistant-common';
import { QueryObserverResult } from '@tanstack/react-query';
import { AssistantAnimatedIcon } from '../assistant_animated_icon';
import { EmptyConvo } from './empty_convo';
import { WelcomeSetup } from './welcome_setup';
import { Conversation } from '../../..';
import { UpgradeLicenseCallToAction } from '../upgrade_license_cta';
import * as i18n from '../translations';
interface Props {
allSystemPrompts: PromptResponse[];
comments: JSX.Element;
currentConversation: Conversation | undefined;
currentSystemPromptId: string | undefined;
handleOnConversationSelected: ({ cId, cTitle }: { cId: string; cTitle: string }) => Promise<void>;
isAssistantEnabled: boolean;
isSettingsModalVisible: boolean;
isWelcomeSetup: boolean;
isLoading: boolean;
refetchCurrentUserConversations: () => Promise<
QueryObserverResult<Record<string, Conversation>, unknown>
>;
http: HttpSetup;
setCurrentSystemPromptId: Dispatch<SetStateAction<string | undefined>>;
setIsSettingsModalVisible: Dispatch<SetStateAction<boolean>>;
}

export const AssistantBody: FunctionComponent<Props> = ({
allSystemPrompts,
comments,
currentConversation,
currentSystemPromptId,
handleOnConversationSelected,
setCurrentSystemPromptId,
http,
isAssistantEnabled,
isLoading,
isSettingsModalVisible,
isWelcomeSetup,
refetchCurrentUserConversations,
setIsSettingsModalVisible,
}) => {
const isNewConversation = useMemo(
() => currentConversation?.messages.length === 0,
[currentConversation?.messages.length]
);

const disclaimer = useMemo(
() =>
isNewConversation && (
<EuiText
data-test-subj="assistant-disclaimer"
textAlign="center"
color={euiThemeVars.euiColorMediumShade}
size="xs"
css={css`
margin: 0 ${euiThemeVars.euiSizeL} ${euiThemeVars.euiSizeM} ${euiThemeVars.euiSizeL};
`}
>
{i18n.DISCLAIMER}
</EuiText>
),
[isNewConversation]
);

// Start Scrolling
const commentsContainerRef = useRef<HTMLDivElement | null>(null);

useEffect(() => {
const parent = commentsContainerRef.current?.parentElement;

if (!parent) {
return;
}
// when scrollHeight changes, parent is scrolled to bottom
parent.scrollTop = parent.scrollHeight;

(
commentsContainerRef.current?.childNodes[0].childNodes[0] as HTMLElement
).lastElementChild?.scrollIntoView();
});
// End Scrolling

if (!isAssistantEnabled) {
return <UpgradeLicenseCallToAction http={http} />;
}

return (
<EuiFlexGroup direction="column" justifyContent="spaceBetween">
<EuiFlexItem grow={false}>
{isLoading ? (
<EuiEmptyPrompt data-test-subj="animatedLogo" icon={<AssistantAnimatedIcon />} />
) : isWelcomeSetup ? (
<WelcomeSetup
currentConversation={currentConversation}
handleOnConversationSelected={handleOnConversationSelected}
/>
) : currentConversation?.messages.length === 0 ? (
<EmptyConvo
allSystemPrompts={allSystemPrompts}
currentConversation={currentConversation}
currentSystemPromptId={currentSystemPromptId}
isSettingsModalVisible={isSettingsModalVisible}
refetchCurrentUserConversations={refetchCurrentUserConversations}
setCurrentSystemPromptId={setCurrentSystemPromptId}
setIsSettingsModalVisible={setIsSettingsModalVisible}
/>
) : (
<EuiPanel
hasShadow={false}
panelRef={(element) => {
commentsContainerRef.current = (element?.parentElement as HTMLDivElement) || null;
}}
>
{comments}
</EuiPanel>
)}
</EuiFlexItem>
<EuiFlexItem grow={false}>{disclaimer}</EuiFlexItem>
</EuiFlexGroup>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/*
* 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, EuiFlexItem, EuiPanel, EuiText } from '@elastic/eui';
import { css } from '@emotion/react';
import { Conversation } from '../../..';
import { AssistantAnimatedIcon } from '../assistant_animated_icon';
import { ConnectorSetup } from '../../connectorland/connector_setup';
import * as i18n from '../translations';

interface Props {
currentConversation: Conversation | undefined;
handleOnConversationSelected: ({ cId, cTitle }: { cId: string; cTitle: string }) => Promise<void>;
}

export const WelcomeSetup: React.FC<Props> = ({
handleOnConversationSelected,
currentConversation,
}) => {
return (
<EuiFlexGroup alignItems="center" justifyContent="center">
<EuiFlexItem grow={false}>
<EuiPanel
hasShadow={false}
css={css`
text-align: center;
`}
>
<EuiFlexGroup alignItems="center" justifyContent="center" direction="column">
<EuiFlexItem grow={false}>
<AssistantAnimatedIcon />
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiText>
<h3>{i18n.WELCOME_SCREEN_TITLE}</h3>
</EuiText>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiText
color="subdued"
css={css`
max-width: 400px;
`}
>
<p>{i18n.WELCOME_SCREEN_DESCRIPTION}</p>
</EuiText>
</EuiFlexItem>
<EuiFlexItem grow={false} data-test-subj="connector-prompt">
<ConnectorSetup
conversation={currentConversation}
onConversationUpdate={handleOnConversationSelected}
/>
</EuiFlexItem>
</EuiFlexGroup>
</EuiPanel>
</EuiFlexItem>
</EuiFlexGroup>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ const testProps = {
ELASTIC_WEBSITE_URL: 'https://www.elastic.co/',
DOC_LINK_VERSION: 'master',
},
isLoading: false,
isDisabled: false,
isSettingsModalVisible: false,
onConversationSelected,
Expand All @@ -35,7 +36,7 @@ const testProps = {
onChatCleared: jest.fn(),
showAnonymizedValues: false,
conversations: mockConversations,
refetchConversationsState: jest.fn(),
refetchCurrentUserConversations: jest.fn(),
isAssistantEnabled: true,
anonymizationFields: { total: 0, page: 1, perPage: 1000, data: [] },
refetchAnonymizationFieldsResults: jest.fn(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,12 @@ import {
EuiPanel,
EuiConfirmModal,
EuiToolTip,
EuiSkeletonTitle,
} from '@elastic/eui';
import { css } from '@emotion/react';
import { euiThemeVars } from '@kbn/ui-theme';
import { isEmpty } from 'lodash';
import { DataStreamApis } from '../use_data_stream_apis';
import { Conversation } from '../../..';
import { AssistantTitle } from '../assistant_title';
import { ConnectorSelectorInline } from '../../connectorland/connector_selector_inline/connector_selector_inline';
Expand All @@ -32,6 +34,7 @@ interface OwnProps {
selectedConversation: Conversation | undefined;
defaultConnector?: AIConnector;
isDisabled: boolean;
isLoading: boolean;
isSettingsModalVisible: boolean;
onToggleShowAnonymizedValues: () => void;
setIsSettingsModalVisible: React.Dispatch<React.SetStateAction<boolean>>;
Expand All @@ -43,7 +46,7 @@ interface OwnProps {
onConversationSelected: ({ cId, cTitle }: { cId: string; cTitle: string }) => void;
conversations: Record<string, Conversation>;
conversationsLoaded: boolean;
refetchConversationsState: () => Promise<void>;
refetchCurrentUserConversations: DataStreamApis['refetchCurrentUserConversations'];
onConversationCreate: () => Promise<void>;
isAssistantEnabled: boolean;
refetchPrompts?: (
Expand All @@ -61,6 +64,7 @@ export const AssistantHeader: React.FC<Props> = ({
selectedConversation,
defaultConnector,
isDisabled,
isLoading,
isSettingsModalVisible,
onToggleShowAnonymizedValues,
setIsSettingsModalVisible,
Expand All @@ -72,7 +76,7 @@ export const AssistantHeader: React.FC<Props> = ({
onConversationSelected,
conversations,
conversationsLoaded,
refetchConversationsState,
refetchCurrentUserConversations,
onConversationCreate,
isAssistantEnabled,
refetchPrompts,
Expand Down Expand Up @@ -144,6 +148,7 @@ export const AssistantHeader: React.FC<Props> = ({
return (
<>
<FlyoutNavigation
isLoading={isLoading}
isExpanded={!!chatHistoryVisible}
setIsExpanded={setChatHistoryVisible}
onConversationCreate={onConversationCreate}
Expand All @@ -164,7 +169,7 @@ export const AssistantHeader: React.FC<Props> = ({
onConversationSelected={onConversationSelected}
conversations={conversations}
conversationsLoaded={conversationsLoaded}
refetchConversationsState={refetchConversationsState}
refetchCurrentUserConversations={refetchCurrentUserConversations}
refetchPrompts={refetchPrompts}
/>
</EuiFlexItem>
Expand Down Expand Up @@ -196,11 +201,16 @@ export const AssistantHeader: React.FC<Props> = ({
overflow: hidden;
`}
>
<AssistantTitle
title={selectedConversation?.title}
selectedConversation={selectedConversation}
refetchConversationsState={refetchConversationsState}
/>
{isLoading ? (
<EuiSkeletonTitle data-test-subj="skeletonTitle" size="xs" />
) : (
<AssistantTitle
isDisabled={isDisabled}
title={selectedConversation?.title}
selectedConversation={selectedConversation}
refetchCurrentUserConversations={refetchCurrentUserConversations}
/>
)}
</EuiFlexItem>

<EuiFlexItem grow={false}>
Expand Down Expand Up @@ -240,6 +250,7 @@ export const AssistantHeader: React.FC<Props> = ({
button={
<EuiButtonIcon
aria-label="test"
isDisabled={isDisabled}
iconType="boxesVertical"
onClick={onButtonClick}
data-test-subj="chat-context-menu"
Expand Down
Loading

0 comments on commit 730f8ea

Please sign in to comment.