Skip to content

Commit

Permalink
feat: add form experiment badge
Browse files Browse the repository at this point in the history
Signed-off-by: Lin Wang <[email protected]>
  • Loading branch information
wanglam committed Nov 24, 2023
1 parent 15dcaf1 commit 1863729
Show file tree
Hide file tree
Showing 3 changed files with 233 additions and 163 deletions.
49 changes: 49 additions & 0 deletions public/components/chat_experimental_badge.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import React, { useCallback, useState } from 'react';
import {
EuiPopover,
EuiButtonIcon,
EuiTitle,
EuiHorizontalRule,
EuiText,
EuiPopoverProps,
} from '@elastic/eui';

interface ChatExperimentalBadgeProps {
onClick?: React.MouseEventHandler<HTMLDivElement>;
}

export const ChatExperimentalBadge = ({ onClick }: ChatExperimentalBadgeProps) => {
const [visible, setVisible] = useState(false);

const closePopover = useCallback(() => {
setVisible(false);
}, []);

const handleIconClick = useCallback((e) => {
setVisible((flag) => !flag);
}, []);

return (
<EuiPopover
isOpen={visible}
button={<EuiButtonIcon color="text" iconType="beaker" onClick={handleIconClick} />}
closePopover={closePopover}
onClick={onClick}
>
<EuiTitle size="xs">
<h4>Experimental</h4>
</EuiTitle>
<EuiHorizontalRule margin="none" />
<EuiText>
This is an experimental feature.
<br />
Send feedback via <a href="mailto:">Email</a> or <a href="slack:">Slack</a>.
</EuiText>
</EuiPopover>
);
};
127 changes: 127 additions & 0 deletions public/components/chat_window_header_title.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import {
EuiContextMenuItem,
EuiContextMenuPanel,
EuiFlexGroup,
EuiFlexItem,
EuiPopover,
EuiButtonIcon,
} from '@elastic/eui';
import React, { useCallback, useState } from 'react';
import { useChatContext } from '../contexts/chat_context';
import { useChatActions } from '../hooks/use_chat_actions';
import { NotebookNameModal } from './notebook/notebook_name_modal';
import { ChatExperimentalBadge } from './chat_experimental_badge';
import { useCore } from '../contexts/core_context';
import { useChatState } from '../hooks/use_chat_state';
import { useSaveChat } from '../hooks/use_save_chat';
import { EditConversationNameModal } from './edit_conversation_name_modal';

export const ChatWindowHeaderTitle = React.memo(() => {
const chatContext = useChatContext();
const { loadChat } = useChatActions();
const core = useCore();
const [isPopoverOpen, setPopoverOpen] = useState(false);
const [isRenameModelOpen, setRenameModelOpen] = useState(false);
const { chatState } = useChatState();
const { saveChat } = useSaveChat();

const onButtonClick = useCallback(() => {
setPopoverOpen((flag) => !flag);
}, []);

const closePopover = useCallback(() => {
setPopoverOpen(false);
}, []);

const handleEditConversationClose = useCallback(
(status: 'updated' | string, newTitle?: string) => {
if (status === 'updated') {
chatContext.setTitle(newTitle);
}
setRenameModelOpen(false);
},
[chatContext]
);

const button = (
<EuiFlexGroup
style={{ maxWidth: '300px', padding: '0 8px' }}
gutterSize="xs"
alignItems="center"
>
<EuiFlexItem onClick={onButtonClick} style={{ overflow: 'hidden' }}>
<h3 className="eui-textTruncate">
{chatContext.sessionId ? chatContext.title : 'OpenSearch Assistant'}
</h3>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<ChatExperimentalBadge onClick={closePopover} />
</EuiFlexItem>
<EuiFlexItem onClick={onButtonClick} grow={false}>
<EuiButtonIcon color="text" iconType="arrowDown" />
</EuiFlexItem>
</EuiFlexGroup>
);

const items = [
<EuiContextMenuItem
disabled={!chatContext.sessionId}
key="rename-conversation"
onClick={() => {
closePopover();
setRenameModelOpen(true);
}}
>
Rename conversation
</EuiContextMenuItem>,
<EuiContextMenuItem
key="new-conversation"
onClick={() => {
closePopover();
loadChat(undefined);
}}
>
New conversation
</EuiContextMenuItem>,
<EuiContextMenuItem
key="save-as-notebook"
onClick={() => {
const modal = core.overlays.openModal(
<NotebookNameModal onClose={() => modal.close()} saveChat={saveChat} />
);
closePopover();
}}
// User only can save conversation when he send a message at least.
disabled={chatState.messages.filter((item) => item.type === 'input').length < 1}
>
Save to notebook
</EuiContextMenuItem>,
];

return (
<>
<EuiPopover
id="conversationTitle"
button={button}
isOpen={isPopoverOpen}
closePopover={closePopover}
panelPaddingSize="none"
anchorPosition="downRight"
>
<EuiContextMenuPanel size="m" items={items} />
</EuiPopover>
{isRenameModelOpen && (
<EditConversationNameModal
sessionId={chatContext.sessionId!}
onClose={handleEditConversationClose}
defaultTitle={chatContext.title!}
/>
)}
</>
);
});
Loading

0 comments on commit 1863729

Please sign in to comment.