Compare commits

...

1 Commits

Author SHA1 Message Date
pablodanswer
444a109da9 v1s 2024-12-08 12:55:21 -08:00
6 changed files with 907 additions and 737 deletions

View File

@@ -2361,7 +2361,8 @@ export function ChatPage({
id={`message-${message.messageId}`}
key={messageReactComponentKey}
>
<HumanMessage
<AIMessage humanText={message.message} />
{/* <HumanMessage
stopGenerating={stopGenerating}
content={message.message}
files={message.files}
@@ -2406,7 +2407,7 @@ export function ChatPage({
// and so it sticks around on page reload
setMessageAsLatest(messageId);
}}
/>
/> */}
</div>
);
} else if (message.type === "assistant") {
@@ -2446,7 +2447,8 @@ export function ChatPage({
: null
}
>
<AIMessage
{/* <AIMessage
humanText={message.message}
setPresentingDocument={
setPresentingDocument
}
@@ -2614,13 +2616,13 @@ export function ChatPage({
)
: !retrievalEnabled
}
/>
/> */}
</div>
);
} else {
return (
<div key={messageReactComponentKey}>
<AIMessage
{/* <AIMessage
currentPersona={liveAssistant}
messageId={message.messageId}
content={
@@ -2640,13 +2642,13 @@ export function ChatPage({
)}
</p>
}
/>
/> */}
</div>
);
}
})}
{(currentSessionChatState == "loading" ||
{/* {(currentSessionChatState == "loading" ||
(loadingError &&
!currentSessionRegenerationState?.regenerating &&
messageHistory[messageHistory.length - 1]
@@ -2656,13 +2658,13 @@ export function ChatPage({
messageId={-1}
content={submittedMessage}
/>
)}
)} */}
{currentSessionChatState == "loading" && (
<div
key={`${messageHistory.length}-${chatSessionIdRef.current}`}
>
<AIMessage
{/* <AIMessage
key={-3}
currentPersona={liveAssistant}
alternativeAssistant={
@@ -2680,13 +2682,13 @@ export function ChatPage({
</span>
</div>
}
/>
/> */}
</div>
)}
{loadingError && (
<div key={-1}>
<AIMessage
{/* <AIMessage
currentPersona={liveAssistant}
messageId={-1}
content={
@@ -2694,7 +2696,7 @@ export function ChatPage({
{loadingError}
</p>
}
/>
/> */}
</div>
)}
{messageHistory.length > 0 && (

File diff suppressed because it is too large Load Diff

View File

@@ -4,7 +4,6 @@ import { useRouter } from "next/navigation";
import { ChatSession } from "../interfaces";
import { useState, useEffect, useContext } from "react";
import { getChatRetentionInfo, renameChatSession } from "../lib";
import { BasicSelectable } from "@/components/BasicClickable";
import Link from "next/link";
import {
FiCheck,
@@ -34,8 +33,6 @@ export function ChatSessionDisplay({
chatSession: ChatSession;
isSelected: boolean;
search?: boolean;
// needed when the parent is trying to apply some background effect
// if not set, the gradient will still be applied and cause weirdness
skipGradient?: boolean;
closeSidebar?: () => void;
showShareModal?: (chatSession: ChatSession) => void;
@@ -73,7 +70,7 @@ export function ChatSessionDisplay({
};
if (!settings) {
return <></>;
return null;
}
const { daysUntilExpiration, showRetentionWarning } = getChatRetentionInfo(
@@ -92,7 +89,11 @@ export function ChatSessionDisplay({
)}
<Link
className="flex my-1 group relative"
className={`flex my-1 group relative font-['KH Teka TRIAL'] ${
isSelected
? "bg-[#e6e3dd] rounded"
: "hover:bg-[#e6e3dd] hover:rounded"
} transition-all duration-150`}
key={chatSession.id}
onMouseEnter={() => setIsHovering(true)}
onMouseLeave={() => {
@@ -122,147 +123,135 @@ export function ChatSessionDisplay({
);
}}
>
<BasicSelectable padding="extra" fullWidth selected={isSelected}>
<>
<div className="flex relative">
{isRenamingChat ? (
<input
value={chatName}
onChange={(e) => setChatName(e.target.value)}
onKeyDown={(event) => {
if (event.key === "Enter") {
onRename();
event.preventDefault();
}
}}
className="-my-px px-1 mr-1 w-full rounded"
/>
) : (
<p className="break-all overflow-hidden whitespace-nowrap w-full mr-3 relative">
{chatName || `Chat ${chatSession.id}`}
<span
className={`absolute right-0 top-0 h-full w-8 bg-gradient-to-r from-transparent
${
isSelected
? "to-background-chat-selected"
: "group-hover:to-background-chat-hover"
} `}
/>
</p>
)}
{isHovering &&
(isRenamingChat ? (
<div className="ml-auto my-auto items-center flex">
<div
onClick={onRename}
className={`hover:bg-black/10 p-1 -m-1 rounded`}
>
<FiCheck size={16} />
</div>
<div
onClick={() => {
setChatName(chatSession.name);
setIsRenamingChat(false);
}}
className={`hover:bg-black/10 p-1 -m-1 rounded ml-2`}
>
<FiX size={16} />
</div>
</div>
) : (
<div className="ml-auto my-auto justify-end flex z-30">
{!showShareModal && showRetentionWarning && (
<CustomTooltip
line
content={
<p>
This chat will expire{" "}
{daysUntilExpiration < 1
? "today"
: `in ${daysUntilExpiration} day${
daysUntilExpiration !== 1 ? "s" : ""
}`}
</p>
}
>
<div className="mr-1 hover:bg-black/10 p-1 -m-1 rounded z-50">
<WarningCircle className="text-warning" />
</div>
</CustomTooltip>
)}
<div>
{search ? (
showDeleteModal && (
<div
onClick={(e) => {
e.preventDefault();
showDeleteModal(chatSession);
}}
className={`p-1 -m-1 rounded ml-1`}
>
<FiTrash size={16} />
</div>
)
) : (
<div
onClick={(e) => {
e.preventDefault();
setIsMoreOptionsDropdownOpen(
!isMoreOptionsDropdownOpen
);
}}
className="-my-1"
>
<Popover
open={isMoreOptionsDropdownOpen}
onOpenChange={(open: boolean) =>
setIsMoreOptionsDropdownOpen(open)
}
content={
<div className="p-1 rounded">
<FiMoreHorizontal size={16} />
</div>
}
popover={
<div className="border border-border rounded-lg bg-background z-50 w-32">
{showShareModal && (
<DefaultDropdownElement
name="Share"
icon={FiShare2}
onSelect={() => showShareModal(chatSession)}
/>
)}
{!search && (
<DefaultDropdownElement
name="Rename"
icon={FiEdit2}
onSelect={() => setIsRenamingChat(true)}
/>
)}
{showDeleteModal && (
<DefaultDropdownElement
name="Delete"
icon={FiTrash}
onSelect={() =>
showDeleteModal(chatSession)
}
/>
)}
</div>
}
requiresContentPadding
sideOffset={6}
triggerMaxWidth
/>
</div>
)}
</div>
</div>
))}
<div className="flex items-center w-full p-1">
{isRenamingChat ? (
<input
value={chatName}
onChange={(e) => setChatName(e.target.value)}
onKeyDown={(event) => {
if (event.key === "Enter") {
onRename();
event.preventDefault();
}
}}
className="px-1 mr-1 w-full rounded text-base font-normal leading-normal text-black border border-[#dcdad4]"
/>
) : (
<div className="flex-1 text-base font-normal text-black break-all whitespace-nowrap overflow-hidden mr-3">
{chatName || `Chat ${chatSession.id}`}
</div>
</>
</BasicSelectable>
)}
{isHovering && (
<div className="flex items-center ml-auto">
{isRenamingChat ? (
<>
<div
onClick={onRename}
className="hover:bg-black/10 p-1 rounded cursor-pointer"
>
<FiCheck size={16} />
</div>
<div
onClick={() => {
setChatName(chatSession.name);
setIsRenamingChat(false);
}}
className="hover:bg-black/10 p-1 rounded ml-2 cursor-pointer"
>
<FiX size={16} />
</div>
</>
) : (
<>
{!showShareModal && showRetentionWarning && (
<CustomTooltip
line
content={
<p>
This chat will expire{" "}
{daysUntilExpiration < 1
? "today"
: `in ${daysUntilExpiration} day${
daysUntilExpiration !== 1 ? "s" : ""
}`}
</p>
}
>
<div className="mr-1 hover:bg-black/10 p-1 rounded cursor-pointer">
<WarningCircle className="text-warning" size={16} />
</div>
</CustomTooltip>
)}
{search ? (
showDeleteModal && (
<div
onClick={(e) => {
e.preventDefault();
showDeleteModal(chatSession);
}}
className="p-1 rounded ml-1 cursor-pointer hover:bg-black/10"
>
<FiTrash size={16} />
</div>
)
) : (
<div
onClick={(e) => {
e.preventDefault();
setIsMoreOptionsDropdownOpen(
!isMoreOptionsDropdownOpen
);
}}
className="-my-1 cursor-pointer"
>
<Popover
open={isMoreOptionsDropdownOpen}
onOpenChange={(open: boolean) =>
setIsMoreOptionsDropdownOpen(open)
}
content={
<div className="p-1 rounded">
<FiMoreHorizontal size={16} />
</div>
}
popover={
<div className="border border-[#dcdad4] rounded-lg bg-white z-50 w-32 shadow-lg">
{showShareModal && (
<DefaultDropdownElement
name="Share"
icon={FiShare2}
onSelect={() => showShareModal(chatSession)}
/>
)}
{!search && (
<DefaultDropdownElement
name="Rename"
icon={FiEdit2}
onSelect={() => setIsRenamingChat(true)}
/>
)}
{showDeleteModal && (
<DefaultDropdownElement
name="Delete"
icon={FiTrash}
onSelect={() => showDeleteModal(chatSession)}
/>
)}
</div>
}
requiresContentPadding
sideOffset={6}
triggerMaxWidth
/>
</div>
)}
</>
)}
</div>
)}
</div>
</Link>
</>
);

View File

@@ -10,7 +10,6 @@ import { Folder } from "../folders/interfaces";
import { createFolder } from "../folders/FolderManagement";
import { usePopup } from "@/components/admin/connectors/Popup";
import { SettingsContext } from "@/components/settings/SettingsProvider";
import {
AssistantsIconSkeleton,
ClosedBookIcon,
@@ -58,19 +57,10 @@ export const HistorySidebar = forwardRef<HTMLDivElement, HistorySidebarProps>(
) => {
const router = useRouter();
const { popup, setPopup } = usePopup();
// For determining intial focus state
const [newFolderId, setNewFolderId] = useState<number | null>(null);
const currentChatId = currentChatSession?.id;
// NOTE: do not do something like the below - assume that the parent
// will handle properly refreshing the existingChats
// useEffect(() => {
// router.refresh();
// }, [currentChatId]);
const combinedSettings = useContext(SettingsContext);
if (!combinedSettings) {
return null;
}
@@ -91,17 +81,14 @@ export const HistorySidebar = forwardRef<HTMLDivElement, HistorySidebarProps>(
<div
ref={ref}
className={`
flex
flex-none
bg-background-sidebar
w-full
border-r
border-sidebar-border
flex
flex-col relative
h-screen
transition-transform
pt-2`}
flex flex-col h-screen w-full
bg-[#f1eee8]
border-r border-[#dcdad4]
font-['KH Teka TRIAL']
relative
pt-2
shadow-md
`}
>
<LogoType
showArrow={true}
@@ -109,29 +96,27 @@ export const HistorySidebar = forwardRef<HTMLDivElement, HistorySidebarProps>(
page={page}
toggleSidebar={toggleSidebar}
explicitlyUntoggle={explicitlyUntoggle}
// Customize LogoType if needed to match final design
/>
{page == "chat" && (
<div className="mx-3 mt-4 gap-y-1 flex-col text-text-history-sidebar-button flex gap-x-1.5 items-center items-center">
{page === "chat" && (
<div className="mx-3 mt-4 flex flex-col gap-y-2 text-black">
<Link
className=" w-full p-2 bg-white border-border border rounded items-center hover:bg-background-200 cursor-pointer transition-all duration-150 flex gap-x-2"
className="w-full p-2 bg-white border border-[#dcdad4] rounded hover:bg-[#fffcf4] cursor-pointer transition-all duration-150 flex items-center gap-x-2"
href={
`/${page}` +
(NEXT_PUBLIC_NEW_CHAT_DIRECTS_TO_SAME_PERSONA &&
currentChatSession?.persona_id
? `?assistantId=${currentChatSession?.persona_id}`
? `?assistantId=${currentChatSession.persona_id}`
: "")
}
onClick={(e) => {
if (e.metaKey || e.ctrlKey) {
return;
}
if (handleNewChat) {
handleNewChat();
}
if (e.metaKey || e.ctrlKey) return;
handleNewChat();
}}
>
<FiEdit className="flex-none text-text-history-sidebar-button" />
<p className="my-auto flex items-center text-sm">New Chat</p>
<FiEdit className="text-black" />
<p className="text-base font-medium leading-normal">New Chat</p>
</Link>
<button
onClick={() =>
@@ -148,33 +133,37 @@ export const HistorySidebar = forwardRef<HTMLDivElement, HistorySidebarProps>(
});
})
}
className="w-full p-2 bg-white border-border border rounded items-center hover:bg-background-history-sidebar-button-hover cursor-pointer transition-all duration-150 flex gap-x-2"
className="w-full p-2 bg-white border border-[#dcdad4] rounded hover:bg-[#fffcf4] cursor-pointer transition-all duration-150 flex items-center gap-x-2"
>
<FiFolderPlus className="my-auto text-text-history-sidebar-button" />
<p className="my-auto flex items-center text-sm">New Folder</p>
<FiFolderPlus className="text-black" />
<p className="text-base font-medium leading-normal">
New Folder
</p>
</button>
<Link
href="/assistants/mine"
className="w-full p-2 bg-white border-border border rounded items-center hover:bg-background-history-sidebar-button-hover cursor-pointer transition-all duration-150 flex gap-x-2"
className="w-full p-2 bg-white border border-[#dcdad4] rounded hover:bg-[#fffcf4] cursor-pointer transition-all duration-150 flex items-center gap-x-2"
>
<AssistantsIconSkeleton className="h-4 w-4 my-auto text-text-history-sidebar-button" />
<p className="my-auto flex items-center text-sm">
<AssistantsIconSkeleton className="h-4 w-4 text-black" />
<p className="text-base font-medium leading-normal">
Manage Assistants
</p>
</Link>
<Link
href="/prompts"
className="w-full p-2 bg-white border-border border rounded items-center hover:bg-background-history-sidebar-button-hover cursor-pointer transition-all duration-150 flex gap-x-2"
className="w-full p-2 bg-white border border-[#dcdad4] rounded hover:bg-[#fffcf4] cursor-pointer transition-all duration-150 flex items-center gap-x-2"
>
<ClosedBookIcon className="h-4 w-4 my-auto text-text-history-sidebar-button" />
<p className="my-auto flex items-center text-sm ">
<ClosedBookIcon className="h-4 w-4 text-black" />
<p className="text-base font-medium leading-normal">
Manage Prompts
</p>
</Link>
</div>
)}
<div className="border-b border-divider-history-sidebar-bar pb-4 mx-3" />
<div className="border-b border-[#dcdad4] pb-4 mx-3 mt-4" />
<PagesTab
newFolderId={newFolderId}
showDeleteModal={showDeleteModal}

View File

@@ -34,7 +34,6 @@ export function PagesTab({
const groupedChatSessions = existingChats
? groupSessionsByDateRange(existingChats)
: [];
const { setPopup } = usePopup();
const router = useRouter();
const [isDragOver, setIsDragOver] = useState<boolean>(false);
@@ -43,14 +42,14 @@ export function PagesTab({
event: React.DragEvent<HTMLDivElement>
) => {
event.preventDefault();
setIsDragOver(false); // Reset drag over state on drop
setIsDragOver(false);
const chatSessionId = event.dataTransfer.getData(CHAT_SESSION_ID_KEY);
const folderId = event.dataTransfer.getData(FOLDER_ID_KEY);
if (folderId) {
try {
await removeChatFromFolder(parseInt(folderId, 10), chatSessionId);
router.refresh(); // Refresh the page to reflect the changes
router.refresh();
} catch (error) {
setPopup({
message: "Failed to remove chat from folder",
@@ -63,10 +62,13 @@ export function PagesTab({
const isHistoryEmpty = !existingChats || existingChats.length === 0;
return (
<div className="mb-1 text-text-sidebar ml-3 relative miniscroll mobile:pb-40 overflow-y-auto h-full">
<div
className="mb-1 ml-3 relative overflow-y-auto h-full pr-3 font-['KH Teka TRIAL'] text-black"
style={{ scrollbarGutter: "stable" }}
>
{folders && folders.length > 0 && (
<div className="py-2 border-b border-border">
<div className="text-xs text-subtle flex pb-0.5 mb-1.5 mt-2 font-bold">
<div className="py-2 border-b border-[#dcdad4]">
<div className="text-xs text-[#6c6c6c] font-medium mb-1.5 mt-2">
Chat Folders
</div>
<FolderList
@@ -79,6 +81,7 @@ export function PagesTab({
/>
</div>
)}
<div
onDragOver={(event) => {
event.preventDefault();
@@ -86,19 +89,17 @@ export function PagesTab({
}}
onDragLeave={() => setIsDragOver(false)}
onDrop={handleDropToRemoveFromFolder}
className={`pt-1 transition duration-300 ease-in-out mr-3 ${
isDragOver ? "bg-hover" : ""
} rounded-md`}
className={`pt-3 pb-40 transition duration-300 ease-in-out ${
isDragOver ? "bg-[#e6e3dd] rounded-md" : ""
}`}
>
{(page == "chat" || page == "search") && (
<p className="my-2 text-xs text-sidebar-subtle flex font-bold">
{page == "chat" && "Chat "}
{page == "search" && "Search "}
History
{(page === "chat" || page === "search") && (
<p className="my-2 text-xs text-[#6c6c6c] font-medium">
{page === "chat" ? "Chat History" : "Search History"}
</p>
)}
{isHistoryEmpty ? (
<p className="text-sm mt-2 w-[250px]">
<p className="text-sm mt-2 w-[250px] text-[#6c6c6c] font-normal">
{page === "search"
? "Try running a search! Your search history will appear here."
: "Try sending a message! Your chat history will appear here."}
@@ -106,34 +107,31 @@ export function PagesTab({
) : (
Object.entries(groupedChatSessions).map(
([dateRange, chatSessions], ind) => {
if (chatSessions.length > 0) {
const filteredSessions = chatSessions.filter(
(chat) => chat.folder_id === null
);
if (filteredSessions.length > 0) {
return (
<div key={dateRange}>
<div
className={`text-xs text-text-sidebar-subtle ${
ind != 0 && "mt-5"
} flex pb-0.5 mb-1.5 font-medium`}
>
<div key={dateRange} className={`${ind !== 0 ? "mt-5" : ""}`}>
<div className="text-xs text-[#6c6c6c] font-medium mb-1.5">
{dateRange}
</div>
{chatSessions
.filter((chat) => chat.folder_id === null)
.map((chat) => {
const isSelected = currentChatId === chat.id;
return (
<div key={`${chat.id}-${chat.name}`}>
<ChatSessionDisplay
showDeleteModal={showDeleteModal}
showShareModal={showShareModal}
closeSidebar={closeSidebar}
search={page == "search"}
chatSession={chat}
isSelected={isSelected}
skipGradient={isDragOver}
/>
</div>
);
})}
{filteredSessions.map((chat) => {
const isSelected = currentChatId === chat.id;
return (
<div key={`${chat.id}-${chat.name}`}>
<ChatSessionDisplay
showDeleteModal={showDeleteModal}
showShareModal={showShareModal}
closeSidebar={closeSidebar}
search={page === "search"}
chatSession={chat}
isSelected={isSelected}
skipGradient={isDragOver}
/>
</div>
);
})}
</div>
);
}

View File

@@ -57,7 +57,7 @@ export default function FunctionalWrapper({
return (
<>
{" "}
<div className="overscroll-y-contain overflow-y-scroll overscroll-contain left-0 top-0 w-full h-svh">
<div className="overscroll-y-contain bg-[#fffcf4] overflow-y-scroll overscroll-contain left-0 top-0 w-full h-svh">
{content(toggledSidebar, toggle)}
</div>
</>