[FEAT] Clear all chats button + export button styles updates (#1495)

* implement clear all chats button + export button styles updates

* Hide clear button if no chats are visible
update clear function

---------

Co-authored-by: timothycarambat <rambat1010@gmail.com>
This commit is contained in:
Sean Hatfield 2024-05-22 14:27:56 -07:00 committed by GitHub
parent b4b29550b7
commit acbad2f2cf
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 60 additions and 22 deletions

View File

@ -7,7 +7,7 @@ import useQuery from "@/hooks/useQuery";
import ChatRow from "./ChatRow"; import ChatRow from "./ChatRow";
import showToast from "@/utils/toast"; import showToast from "@/utils/toast";
import System from "@/models/system"; import System from "@/models/system";
import { CaretDown, Download } from "@phosphor-icons/react"; import { CaretDown, Download, Trash } from "@phosphor-icons/react";
import { saveAs } from "file-saver"; import { saveAs } from "file-saver";
const exportOptions = { const exportOptions = {
@ -49,6 +49,12 @@ export default function WorkspaceChats() {
const [showMenu, setShowMenu] = useState(false); const [showMenu, setShowMenu] = useState(false);
const menuRef = useRef(); const menuRef = useRef();
const openMenuButton = useRef(); const openMenuButton = useRef();
const query = useQuery();
const [loading, setLoading] = useState(true);
const [chats, setChats] = useState([]);
const [offset, setOffset] = useState(Number(query.get("offset") || 0));
const [canNext, setCanNext] = useState(false);
const handleDumpChats = async (exportType) => { const handleDumpChats = async (exportType) => {
const chats = await System.exportChats(exportType); const chats = await System.exportChats(exportType);
if (!!chats) { if (!!chats) {
@ -62,6 +68,18 @@ export default function WorkspaceChats() {
} }
}; };
const handleClearAllChats = async () => {
if (
!window.confirm(
`Are you sure you want to clear all chats?\n\nThis action is irreversible.`
)
)
return false;
await System.deleteChat(-1);
setChats([]);
showToast("Cleared all chats.", "success");
};
const toggleMenu = () => { const toggleMenu = () => {
setShowMenu(!showMenu); setShowMenu(!showMenu);
}; };
@ -83,6 +101,16 @@ export default function WorkspaceChats() {
}; };
}, []); }, []);
useEffect(() => {
async function fetchChats() {
const { chats: _chats, hasPages = false } = await System.chats(offset);
setChats(_chats);
setCanNext(hasPages);
setLoading(false);
}
fetchChats();
}, [offset]);
return ( return (
<div className="w-screen h-screen overflow-hidden bg-sidebar flex"> <div className="w-screen h-screen overflow-hidden bg-sidebar flex">
<Sidebar /> <Sidebar />
@ -100,7 +128,7 @@ export default function WorkspaceChats() {
<button <button
ref={openMenuButton} ref={openMenuButton}
onClick={toggleMenu} onClick={toggleMenu}
className="flex items-center gap-x-2 px-4 py-2 rounded-lg bg-[#2C2F36] text-white text-sm hover:bg-[#3D4147] shadow-md border border-[#3D4147]" className="flex items-center gap-x-2 px-4 py-1 rounded-lg bg-[#46C8FF] hover:text-white text-xs font-semibold hover:bg-[#2C2F36] shadow-[0_4px_14px_rgba(0,0,0,0.25)] h-[34px] w-fit"
> >
<Download size={18} weight="bold" /> <Download size={18} weight="bold" />
Export Export
@ -128,26 +156,43 @@ export default function WorkspaceChats() {
</div> </div>
</div> </div>
</div> </div>
{chats.length > 0 && (
<button
onClick={handleClearAllChats}
className="flex items-center gap-x-2 px-4 py-1 border hover:border-transparent border-white/40 text-white/40 rounded-lg bg-transparent hover:text-white text-xs font-semibold hover:bg-red-500 shadow-[0_4px_14px_rgba(0,0,0,0.25)] h-[34px] w-fit"
>
<Trash size={18} weight="bold" />
Clear Chats
</button>
)}
</div> </div>
<p className="text-xs leading-[18px] font-base text-white text-opacity-60"> <p className="text-xs leading-[18px] font-base text-white text-opacity-60">
These are all the recorded chats and messages that have been sent These are all the recorded chats and messages that have been sent
by users ordered by their creation date. by users ordered by their creation date.
</p> </p>
</div> </div>
<ChatsContainer /> <ChatsContainer
loading={loading}
chats={chats}
setChats={setChats}
offset={offset}
setOffset={setOffset}
canNext={canNext}
/>
</div> </div>
</div> </div>
</div> </div>
); );
} }
function ChatsContainer() { function ChatsContainer({
const query = useQuery(); loading,
const [loading, setLoading] = useState(true); chats,
const [chats, setChats] = useState([]); setChats,
const [offset, setOffset] = useState(Number(query.get("offset") || 0)); offset,
const [canNext, setCanNext] = useState(false); setOffset,
canNext,
}) {
const handlePrevious = () => { const handlePrevious = () => {
setOffset(Math.max(offset - 1, 0)); setOffset(Math.max(offset - 1, 0));
}; };
@ -155,20 +200,11 @@ function ChatsContainer() {
setOffset(offset + 1); setOffset(offset + 1);
}; };
const handleDeleteChat = (chatId) => { const handleDeleteChat = async (chatId) => {
await System.deleteChat(chatId);
setChats((prevChats) => prevChats.filter((chat) => chat.id !== chatId)); setChats((prevChats) => prevChats.filter((chat) => chat.id !== chatId));
}; };
useEffect(() => {
async function fetchChats() {
const { chats: _chats, hasPages = false } = await System.chats(offset);
setChats(_chats);
setCanNext(hasPages);
setLoading(false);
}
fetchChats();
}, [offset]);
if (loading) { if (loading) {
return ( return (
<Skeleton.default <Skeleton.default

View File

@ -976,7 +976,9 @@ function systemEndpoints(app) {
async (request, response) => { async (request, response) => {
try { try {
const { id } = request.params; const { id } = request.params;
await WorkspaceChats.delete({ id: Number(id) }); Number(id) === -1
? await WorkspaceChats.delete({}, true)
: await WorkspaceChats.delete({ id: Number(id) });
response.json({ success: true, error: null }); response.json({ success: true, error: null });
} catch (e) { } catch (e) {
console.error(e); console.error(e);