apps/overlay-sandbox/app/cases/components/chatOverlayWrapper.tsx (176 lines of code) (raw):
'use client';
import { ChatOverlay, ChatOverlayOptions } from '@epam/ai-dial-overlay';
import React, { useCallback, useEffect, useRef, useState } from 'react';
interface ChatOverlayWrapperProps {
overlayOptions: Omit<ChatOverlayOptions, 'hostDomain'>;
}
export const ChatOverlayWrapper: React.FC<ChatOverlayWrapperProps> = ({
overlayOptions,
}) => {
const containerRef = useRef<HTMLDivElement>(null);
const overlay = useRef<ChatOverlay | null>(null);
const dialogRef = useRef<HTMLDialogElement | null>(null);
const [dialogInfo, setDialogInfo] = useState('');
const [conversationIdInputValue, setConversationIdInputValue] = useState('');
const handleDisplayInformation = useCallback((textToShow: string) => {
dialogRef.current?.showModal();
setDialogInfo(textToShow);
}, []);
const handleSelectConversation = useCallback(async () => {
const selectResult = await overlay.current?.selectConversation(
conversationIdInputValue,
);
handleDisplayInformation(
JSON.stringify(selectResult?.conversation, null, 2),
);
}, [conversationIdInputValue, handleDisplayInformation]);
useEffect(() => {
if (!overlay.current) {
overlay.current = new ChatOverlay(containerRef.current!, {
...overlayOptions,
hostDomain: window.location.origin,
});
}
}, [overlayOptions]);
useEffect(() => {
overlay.current?.subscribe('@DIAL_OVERLAY/GPT_END_GENERATING', () =>
console.info('END GENERATING'),
);
overlay.current?.subscribe('@DIAL_OVERLAY/GPT_START_GENERATING', () =>
console.info('START GENERATING'),
);
overlay.current?.subscribe(
'@DIAL_OVERLAY/SELECTED_CONVERSATION_LOADED',
async (info) => {
console.info('Conversation selected - ');
const { messages } = await overlay.current!.getMessages();
console.info('messages', messages);
console.info(JSON.stringify(info, null, 2));
},
);
overlay.current?.getMessages().then((messages) => {
console.info(messages);
});
}, [overlay]);
return (
<div className="flex gap-2 p-2">
<dialog ref={dialogRef} className="rounded p-5">
<div className="flex justify-end">
<button
className="rounded bg-gray-200 p-2"
autoFocus
onClick={() => dialogRef.current?.close()}
>
X
</button>
</div>
<p className="whitespace-pre-wrap">{dialogInfo}</p>
</dialog>
<div
ref={containerRef}
style={{
height: 700,
width: 500,
}}
></div>
<div className="flex max-w-[300px] flex-col gap-2">
<details>
<summary>Chat actions</summary>
<div className="flex flex-col gap-2">
<button
className="rounded bg-gray-200 p-2"
onClick={() => {
overlay.current?.sendMessage('Hello');
}}
>
Send 'Hello' to Chat
</button>
<button
className="rounded bg-gray-200 p-2"
onClick={() => {
overlay.current?.setSystemPrompt(
'End each word with string "!?!?!"',
);
}}
>
Set system prompt: End each word with string "!?!?!"
</button>
<button
className="rounded bg-gray-200 p-2"
onClick={async () => {
const messages = await overlay.current?.getMessages();
handleDisplayInformation(JSON.stringify(messages, null, 2));
}}
>
Get messages
</button>
<button
className="rounded bg-gray-200 p-2"
onClick={async () => {
const conversations = await overlay.current?.getConversations();
handleDisplayInformation(
JSON.stringify(conversations, null, 2),
);
}}
>
Get conversations
</button>
<button
className="rounded bg-gray-200 p-2"
onClick={async () => {
const conversation =
await overlay.current?.createConversation();
handleDisplayInformation(JSON.stringify(conversation, null, 2));
}}
>
Create conversation
</button>
<button
className="rounded bg-gray-200 p-2"
onClick={async () => {
const conversation =
await overlay.current?.createConversation(
'test-inner-folder',
);
handleDisplayInformation(JSON.stringify(conversation, null, 2));
}}
>
Create conversation in inner folder
</button>
<div className="flex flex-col gap-1 border p-1">
<button
className="rounded bg-gray-200 p-2"
onClick={handleSelectConversation}
>
Select conversation by ID
</button>
<textarea
className="border"
placeholder="Type conversation ID"
value={conversationIdInputValue}
onChange={(e) => setConversationIdInputValue(e.target.value)}
/>
</div>
</div>
</details>
<details>
<summary>Overlay configuration</summary>
<div>
<button
className="rounded bg-gray-200 p-2"
onClick={() => {
const newOptions = {
...overlayOptions,
hostDomain: window.location.origin,
};
newOptions.theme = 'dark';
newOptions.modelId = 'stability.stable-diffusion-xl';
overlay.current?.setOverlayOptions(newOptions);
}}
>
Set dark theme and new model
</button>
</div>
</details>
</div>
</div>
);
};