Clear conversations (#53)
* Add button "Clear Conversations" * custom btn --------- Co-authored-by: Xiangxuan Liu <xiangxuan.liu@rightcapital.com>
This commit is contained in:
parent
cb0fb447a7
commit
b7803cf4ba
|
@ -0,0 +1,50 @@
|
||||||
|
import { IconCheck, IconTrash, IconX } from "@tabler/icons-react";
|
||||||
|
import { FC, useState } from "react";
|
||||||
|
import { SidebarButton } from "./SidebarButton";
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
onClearConversations: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const ClearConversations: FC<Props> = ({ onClearConversations }) => {
|
||||||
|
const [isConfirming, setIsConfirming] = useState<boolean>(false);
|
||||||
|
|
||||||
|
const handleClearConversations = () => {
|
||||||
|
onClearConversations();
|
||||||
|
setIsConfirming(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
return isConfirming ? (
|
||||||
|
<div className="flex hover:bg-[#343541] py-2 px-2 rounded-md cursor-pointer w-full items-center">
|
||||||
|
<IconTrash size={16} />
|
||||||
|
|
||||||
|
<div className="ml-2 flex-1 text-left text-white">Are you sure?</div>
|
||||||
|
|
||||||
|
<div className="flex w-[40px]">
|
||||||
|
<IconCheck
|
||||||
|
className="ml-auto min-w-[20px] text-neutral-400 hover:text-neutral-100"
|
||||||
|
size={18}
|
||||||
|
onClick={(e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
handleClearConversations();
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<IconX
|
||||||
|
className="ml-auto min-w-[20px] text-neutral-400 hover:text-neutral-100"
|
||||||
|
size={18}
|
||||||
|
onClick={(e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
setIsConfirming(false);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<SidebarButton
|
||||||
|
text="Clear conversations"
|
||||||
|
icon={<IconTrash size={16} />}
|
||||||
|
onClick={() => setIsConfirming(true)}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
|
@ -18,9 +18,10 @@ interface Props {
|
||||||
onToggleSidebar: () => void;
|
onToggleSidebar: () => void;
|
||||||
onUpdateConversation: (conversation: Conversation, data: KeyValuePair) => void;
|
onUpdateConversation: (conversation: Conversation, data: KeyValuePair) => void;
|
||||||
onApiKeyChange: (apiKey: string) => void;
|
onApiKeyChange: (apiKey: string) => void;
|
||||||
|
onClearConversations: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const Sidebar: FC<Props> = ({ loading, conversations, lightMode, selectedConversation, apiKey, onNewConversation, onToggleLightMode, onSelectConversation, onDeleteConversation, onToggleSidebar, onUpdateConversation, onApiKeyChange }) => {
|
export const Sidebar: FC<Props> = ({ loading, conversations, lightMode, selectedConversation, apiKey, onNewConversation, onToggleLightMode, onSelectConversation, onDeleteConversation, onToggleSidebar, onUpdateConversation, onApiKeyChange, onClearConversations }) => {
|
||||||
const [searchTerm, setSearchTerm] = useState<string>("");
|
const [searchTerm, setSearchTerm] = useState<string>("");
|
||||||
const [filteredConversations, setFilteredConversations] = useState<Conversation[]>(conversations);
|
const [filteredConversations, setFilteredConversations] = useState<Conversation[]>(conversations);
|
||||||
|
|
||||||
|
@ -85,6 +86,7 @@ export const Sidebar: FC<Props> = ({ loading, conversations, lightMode, selected
|
||||||
apiKey={apiKey}
|
apiKey={apiKey}
|
||||||
onToggleLightMode={onToggleLightMode}
|
onToggleLightMode={onToggleLightMode}
|
||||||
onApiKeyChange={onApiKeyChange}
|
onApiKeyChange={onApiKeyChange}
|
||||||
|
onClearConversations={onClearConversations}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import { IconMoon, IconSun } from "@tabler/icons-react";
|
import { IconMoon, IconSun } from "@tabler/icons-react";
|
||||||
import { FC } from "react";
|
import { FC } from "react";
|
||||||
|
import { ClearConversations } from "./ClearConversations";
|
||||||
import { Key } from "./Key";
|
import { Key } from "./Key";
|
||||||
import { SidebarButton } from "./SidebarButton";
|
import { SidebarButton } from "./SidebarButton";
|
||||||
|
|
||||||
|
@ -8,11 +9,14 @@ interface Props {
|
||||||
apiKey: string;
|
apiKey: string;
|
||||||
onToggleLightMode: (mode: "light" | "dark") => void;
|
onToggleLightMode: (mode: "light" | "dark") => void;
|
||||||
onApiKeyChange: (apiKey: string) => void;
|
onApiKeyChange: (apiKey: string) => void;
|
||||||
|
onClearConversations: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const SidebarSettings: FC<Props> = ({ lightMode, apiKey, onToggleLightMode, onApiKeyChange }) => {
|
export const SidebarSettings: FC<Props> = ({ lightMode, apiKey, onToggleLightMode, onApiKeyChange, onClearConversations }) => {
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col items-center border-t border-neutral-500 px-2 py-4 text-sm space-y-2">
|
<div className="flex flex-col items-center border-t border-neutral-500 px-2 py-4 text-sm space-y-2">
|
||||||
|
<ClearConversations onClearConversations={onClearConversations} />
|
||||||
|
|
||||||
<SidebarButton
|
<SidebarButton
|
||||||
text={lightMode === "light" ? "Dark mode" : "Light mode"}
|
text={lightMode === "light" ? "Dark mode" : "Light mode"}
|
||||||
icon={lightMode === "light" ? <IconMoon size={16} /> : <IconSun size={16} />}
|
icon={lightMode === "light" ? <IconMoon size={16} /> : <IconSun size={16} />}
|
||||||
|
|
|
@ -21,13 +21,6 @@ export default function Home() {
|
||||||
const [messageError, setMessageError] = useState<boolean>(false);
|
const [messageError, setMessageError] = useState<boolean>(false);
|
||||||
const [modelError, setModelError] = useState<boolean>(false);
|
const [modelError, setModelError] = useState<boolean>(false);
|
||||||
|
|
||||||
// Close sidebar when a conversation is selected/created on mobile
|
|
||||||
useEffect(() => {
|
|
||||||
if (window.innerWidth < 640) {
|
|
||||||
setShowSidebar(false);
|
|
||||||
}
|
|
||||||
}, [selectedConversation])
|
|
||||||
|
|
||||||
const handleSend = async (message: Message, isResend: boolean) => {
|
const handleSend = async (message: Message, isResend: boolean) => {
|
||||||
if (selectedConversation) {
|
if (selectedConversation) {
|
||||||
let updatedConversation: Conversation;
|
let updatedConversation: Conversation;
|
||||||
|
@ -247,6 +240,26 @@ export default function Home() {
|
||||||
setConversations(all);
|
setConversations(all);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleClearConversations = () => {
|
||||||
|
setConversations([]);
|
||||||
|
localStorage.removeItem("conversationHistory");
|
||||||
|
|
||||||
|
setSelectedConversation({
|
||||||
|
id: 1,
|
||||||
|
name: "New conversation",
|
||||||
|
messages: [],
|
||||||
|
model: OpenAIModels[OpenAIModelID.GPT_3_5],
|
||||||
|
prompt: DEFAULT_SYSTEM_PROMPT
|
||||||
|
});
|
||||||
|
localStorage.removeItem("selectedConversation");
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (window.innerWidth < 640) {
|
||||||
|
setShowSidebar(false);
|
||||||
|
}
|
||||||
|
}, [selectedConversation]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const theme = localStorage.getItem("theme");
|
const theme = localStorage.getItem("theme");
|
||||||
if (theme) {
|
if (theme) {
|
||||||
|
@ -329,6 +342,7 @@ export default function Home() {
|
||||||
onToggleSidebar={() => setShowSidebar(!showSidebar)}
|
onToggleSidebar={() => setShowSidebar(!showSidebar)}
|
||||||
onUpdateConversation={handleUpdateConversation}
|
onUpdateConversation={handleUpdateConversation}
|
||||||
onApiKeyChange={handleApiKeyChange}
|
onApiKeyChange={handleApiKeyChange}
|
||||||
|
onClearConversations={handleClearConversations}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<IconArrowBarLeft
|
<IconArrowBarLeft
|
||||||
|
|
Loading…
Reference in New Issue