Added export button

This commit is contained in:
eduardruzga 2024-11-22 11:51:52 +02:00
parent 60411550a5
commit 9f49c25f96
4 changed files with 38 additions and 5 deletions

View File

@ -12,12 +12,14 @@ import { Messages } from './Messages.client';
import { SendButton } from './SendButton.client'; import { SendButton } from './SendButton.client';
import { APIKeyManager } from './APIKeyManager'; import { APIKeyManager } from './APIKeyManager';
import Cookies from 'js-cookie'; import Cookies from 'js-cookie';
import { importChat } from '~/utils/chatExport'; import { exportChat, importChat } from '~/utils/chatExport';
import { toast } from 'react-toastify'; import { toast } from 'react-toastify';
import * as Tooltip from '@radix-ui/react-tooltip'; import * as Tooltip from '@radix-ui/react-tooltip';
import styles from './BaseChat.module.scss'; import styles from './BaseChat.module.scss';
import type { ProviderInfo } from '~/utils/types'; import type { ProviderInfo } from '~/utils/types';
import WithTooltip from '~/components/ui/Tooltip';
import { ExportChatButton } from '~/components/chat/ExportChatButton';
const EXAMPLE_PROMPTS = [ const EXAMPLE_PROMPTS = [
{ text: 'Build a todo app in React using Tailwind' }, { text: 'Build a todo app in React using Tailwind' },
@ -76,6 +78,7 @@ interface BaseChatProps {
chatStarted?: boolean; chatStarted?: boolean;
isStreaming?: boolean; isStreaming?: boolean;
messages?: Message[]; messages?: Message[];
description?: string;
enhancingPrompt?: boolean; enhancingPrompt?: boolean;
promptEnhanced?: boolean; promptEnhanced?: boolean;
input?: string; input?: string;
@ -101,6 +104,7 @@ export const BaseChat = React.forwardRef<HTMLDivElement, BaseChatProps>(
enhancingPrompt = false, enhancingPrompt = false,
promptEnhanced = false, promptEnhanced = false,
messages, messages,
description,
input = '', input = '',
model, model,
setModel, setModel,
@ -288,6 +292,7 @@ export const BaseChat = React.forwardRef<HTMLDivElement, BaseChatProps>(
</> </>
)} )}
</IconButton> </IconButton>
<ClientOnly>{() => <ExportChatButton description={description} messages={messages}/>}</ClientOnly>
</div> </div>
{input.length > 3 ? ( {input.length > 3 ? (
<div className="text-xs text-bolt-elements-textTertiary"> <div className="text-xs text-bolt-elements-textTertiary">

View File

@ -7,7 +7,7 @@ import { useAnimate } from 'framer-motion';
import { memo, useEffect, useRef, useState } from 'react'; import { memo, useEffect, useRef, useState } from 'react';
import { cssTransition, toast, ToastContainer } from 'react-toastify'; import { cssTransition, toast, ToastContainer } from 'react-toastify';
import { useMessageParser, usePromptEnhancer, useShortcuts, useSnapScroll } from '~/lib/hooks'; import { useMessageParser, usePromptEnhancer, useShortcuts, useSnapScroll } from '~/lib/hooks';
import { useChatHistory } from '~/lib/persistence'; import { description, useChatHistory } from '~/lib/persistence';
import { chatStore } from '~/lib/stores/chat'; import { chatStore } from '~/lib/stores/chat';
import { workbenchStore } from '~/lib/stores/workbench'; import { workbenchStore } from '~/lib/stores/workbench';
import { fileModificationsToHTML } from '~/utils/diff'; import { fileModificationsToHTML } from '~/utils/diff';
@ -29,10 +29,11 @@ export function Chat() {
renderLogger.trace('Chat'); renderLogger.trace('Chat');
const { ready, initialMessages, storeMessageHistory } = useChatHistory(); const { ready, initialMessages, storeMessageHistory } = useChatHistory();
const title = useStore(description);
return ( return (
<> <>
{ready && <ChatImpl initialMessages={initialMessages} storeMessageHistory={storeMessageHistory} />} {ready && <ChatImpl description={title} initialMessages={initialMessages} storeMessageHistory={storeMessageHistory} />}
<ToastContainer <ToastContainer
closeButton={({ closeToast }) => { closeButton={({ closeToast }) => {
return ( return (
@ -69,7 +70,7 @@ interface ChatProps {
storeMessageHistory: (messages: Message[]) => Promise<void>; storeMessageHistory: (messages: Message[]) => Promise<void>;
} }
export const ChatImpl = memo(({ initialMessages, storeMessageHistory }: ChatProps) => { export const ChatImpl = memo(({ description, initialMessages, storeMessageHistory }: ChatProps) => {
useShortcuts(); useShortcuts();
const textareaRef = useRef<HTMLTextAreaElement>(null); const textareaRef = useRef<HTMLTextAreaElement>(null);
@ -252,6 +253,7 @@ export const ChatImpl = memo(({ initialMessages, storeMessageHistory }: ChatProp
scrollRef={scrollRef} scrollRef={scrollRef}
handleInputChange={handleInputChange} handleInputChange={handleInputChange}
handleStop={abort} handleStop={abort}
description={description}
messages={messages.map((message, i) => { messages={messages.map((message, i) => {
if (message.role === 'user') { if (message.role === 'user') {
return message; return message;

View File

@ -0,0 +1,16 @@
import WithTooltip from '~/components/ui/Tooltip';
import { IconButton } from '~/components/ui/IconButton';
import { exportChat } from '~/utils/chatExport';
import React from 'react';
import type { Message } from 'ai';
export const ExportChatButton = ({description, messages}: {description: string, messages: Message[]}) => {
return (<WithTooltip tooltip="Export Chat">
<IconButton
title="Export Chat"
onClick={() => exportChat(messages || [], description)}
>
<div className="i-ph:download-simple text-xl"></div>
</IconButton>
</WithTooltip>);
}

View File

@ -1,7 +1,17 @@
import React from 'react'; import React from 'react';
import * as Tooltip from '@radix-ui/react-tooltip'; import * as Tooltip from '@radix-ui/react-tooltip';
import type {ReactNode} from 'react';
const WithTooltip = ({ tooltip, children, sideOffset = 5, className = '', arrowClassName = '', tooltipStyle = {} }) => { interface ToolTipProps {
tooltip: string,
children: ReactNode | ReactNode[];
sideOffset?: number,
className?: string,
arrowClassName?: string,
tooltipStyle?: any, //TODO better type
}
const WithTooltip = ({ tooltip, children, sideOffset = 5, className = '', arrowClassName = '', tooltipStyle = {} }: ToolTipProps) => {
return ( return (
<Tooltip.Root> <Tooltip.Root>
<Tooltip.Trigger asChild> <Tooltip.Trigger asChild>