diff --git a/src/interface/web/app/components/chatHistory/chatHistory.tsx b/src/interface/web/app/components/chatHistory/chatHistory.tsx index 67af2ddb..c1cd923e 100644 --- a/src/interface/web/app/components/chatHistory/chatHistory.tsx +++ b/src/interface/web/app/components/chatHistory/chatHistory.tsx @@ -42,6 +42,7 @@ interface ChatHistoryProps { setAgent: (agent: AgentData) => void; customClassName?: string; setIsChatSideBarOpen?: (isOpen: boolean) => void; + setIsOwner?: (isOwner: boolean) => void; } interface TrainOfThoughtComponentProps { @@ -60,13 +61,13 @@ function TrainOfThoughtComponent(props: TrainOfThoughtComponentProps) { open: { height: "auto", opacity: 1, - transition: { duration: 0.3, ease: "easeOut" } + transition: { duration: 0.3, ease: "easeOut" }, }, closed: { height: 0, opacity: 0, - transition: { duration: 0.3, ease: "easeIn" } - } + transition: { duration: 0.3, ease: "easeIn" }, + }, }; useEffect(() => { @@ -103,17 +104,14 @@ function TrainOfThoughtComponent(props: TrainOfThoughtComponentProps) { ))} {!collapsed && ( - + {props.trainOfThought.map((train, index) => ( ))} @@ -174,7 +172,6 @@ export default function ChatHistory(props: ChatHistoryProps) { latestUserMessageRef.current?.scrollIntoView({ behavior: "auto", block: "start" }); }); } - }, [data, currentPage]); useEffect(() => { @@ -247,6 +244,7 @@ export default function ChatHistory(props: ChatHistoryProps) { .then((response) => response.json()) .then((chatData: ChatResponse) => { props.setTitle(chatData.response.slug); + props.setIsOwner && props.setIsOwner(chatData?.response?.is_owner); if ( chatData && chatData.response && @@ -274,6 +272,7 @@ export default function ChatHistory(props: ChatHistoryProps) { agent: chatData.response.agent, conversation_id: chatData.response.conversation_id, slug: chatData.response.slug, + is_owner: chatData.response.is_owner, }; props.setAgent(chatData.response.agent); setData(chatMetadata); @@ -312,7 +311,7 @@ export default function ChatHistory(props: ChatHistoryProps) { function constructAgentName() { if (!data || !data.agent || !data.agent?.name) return `Agent`; - if (data.agent.is_hidden) return 'Khoj'; + if (data.agent.is_hidden) return "Khoj"; return data.agent?.name; } @@ -359,8 +358,8 @@ export default function ChatHistory(props: ChatHistoryProps) { md:h-[calc(100svh-theme(spacing.44))] lg:h-[calc(100svh-theme(spacing.72))] `} - ref={scrollAreaRef}> - + ref={scrollAreaRef} + >
@@ -389,12 +388,12 @@ export default function ChatHistory(props: ChatHistoryProps) { index === data.chat.length - 2 ? latestUserMessageRef : // attach ref to the newest fetched message to handle scroll on fetch - // note: stabilize index selection against last page having less messages than fetchMessageCount - index === + // note: stabilize index selection against last page having less messages than fetchMessageCount + index === data.chat.length - - (currentPage - 1) * fetchMessageCount - ? latestFetchedMessageRef - : null + (currentPage - 1) * fetchMessageCount + ? latestFetchedMessageRef + : null } isMobileWidth={isMobileWidth} chatMessage={chatMessage} @@ -472,7 +471,7 @@ export default function ChatHistory(props: ChatHistoryProps) { onDeleteMessage={handleDeleteMessage} customClassName="fullHistory" borderLeftColor={`${data?.agent?.color}-500`} - isLastMessage={index === (props.incomingMessages!.length - 1)} + isLastMessage={index === props.incomingMessages!.length - 1} /> ); diff --git a/src/interface/web/app/components/chatMessage/chatMessage.tsx b/src/interface/web/app/components/chatMessage/chatMessage.tsx index 8c76c551..5d87f7ea 100644 --- a/src/interface/web/app/components/chatMessage/chatMessage.tsx +++ b/src/interface/web/app/components/chatMessage/chatMessage.tsx @@ -196,6 +196,7 @@ export interface ChatHistoryData { agent: AgentData; conversation_id: string; slug: string; + is_owner: boolean; } function sendFeedback(uquery: string, kquery: string, sentiment: string) { diff --git a/src/interface/web/app/share/chat/page.tsx b/src/interface/web/app/share/chat/page.tsx index b9b51966..5cb3cee0 100644 --- a/src/interface/web/app/share/chat/page.tsx +++ b/src/interface/web/app/share/chat/page.tsx @@ -22,6 +22,8 @@ import { SidebarInset, SidebarProvider, SidebarTrigger } from "@/components/ui/s import { AppSidebar } from "@/app/components/appSidebar/appSidebar"; import { Separator } from "@/components/ui/separator"; import { KhojLogoType } from "@/app/components/logo/khojLogo"; +import { Button } from "@/components/ui/button"; +import { Trash } from "@phosphor-icons/react"; interface ChatBodyDataProps { chatOptionsData: ChatOptions | null; @@ -34,6 +36,37 @@ interface ChatBodyDataProps { conversationId?: string; setQueryToProcess: (query: string) => void; setImages: (images: string[]) => void; + setIsOwner: (isOwner: boolean) => void; +} + +function UnshareButton({ slug, className }: { slug: string; className?: string }) { + const handleUnshare = async () => { + try { + const response = await fetch(`/api/chat/share?public_conversation_slug=${slug}`, { + method: "DELETE", + }); + + if (response.redirected) { + window.location.reload(); + } else { + console.error("Failed to unshare conversation"); + } + } catch (error) { + console.error("Error unsharing conversation:", error); + } + }; + + return ( +
+ +
+ ); } function ChatBodyData(props: ChatBodyDataProps) { @@ -87,6 +120,7 @@ function ChatBodyData(props: ChatBodyDataProps) { conversationId={props.conversationId || ""} setAgent={setAgentMetadata} setTitle={props.setTitle} + setIsOwner={props.setIsOwner} pendingMessage={processingMessage ? message : ""} incomingMessages={props.streamedMessages} customClassName={chatHistoryCustomClassName} @@ -105,7 +139,7 @@ function ChatBodyData(props: ChatBodyDataProps) { agentColor={agentMetadata?.color} isMobileWidth={props.isMobileWidth} setUploadedFiles={props.setUploadedFiles} - setTriggeredAbort={() => { }} + setTriggeredAbort={() => {}} ref={chatInputRef} />
@@ -124,6 +158,7 @@ export default function SharedChat() { const [uploadedFiles, setUploadedFiles] = useState(null); const [paramSlug, setParamSlug] = useState(undefined); const [images, setImages] = useState([]); + const [isOwner, setIsOwner] = useState(false); const { data: authenticatedData, @@ -215,6 +250,12 @@ export default function SharedChat() { > {title} + {isOwner && authenticatedData && ( + + )} ) )} @@ -237,6 +278,7 @@ export default function SharedChat() { setUploadedFiles={setUploadedFiles} isMobileWidth={isMobileWidth} setImages={setImages} + setIsOwner={setIsOwner} />
diff --git a/src/interface/web/app/share/chat/sharedChat.module.css b/src/interface/web/app/share/chat/sharedChat.module.css index d147502b..359277a5 100644 --- a/src/interface/web/app/share/chat/sharedChat.module.css +++ b/src/interface/web/app/share/chat/sharedChat.module.css @@ -93,10 +93,8 @@ div.agentIndicator { padding: 10px; } -@media (max-width: 768px) { - div.chatBody { - grid-template-columns: 0fr 1fr; - } +div.chatTitleWrapper { + grid-template-columns: 1fr auto; } @media screen and (max-width: 768px) { @@ -108,6 +106,15 @@ div.agentIndicator { width: 100%; } + div.chatBody { + grid-template-columns: 0fr 1fr; + } + + div.chatBox { + padding: 0; + height: 100%; + } + div.chatLayout { gap: 0; grid-template-columns: 1fr;