Add a ride hand side bar for chat controls

This commit is contained in:
sabaimran
2025-01-17 16:45:50 -08:00
parent 00843f4f24
commit 2fa212061d
15 changed files with 465 additions and 51 deletions

View File

@@ -184,7 +184,7 @@ interface FilesMenuProps {
isMobileWidth: boolean;
}
function FilesMenu(props: FilesMenuProps) {
export function FilesMenu(props: FilesMenuProps) {
// Use SWR to fetch files
const { data: files, error } = useSWR<string[]>("/api/content/computer", fetcher);
const { data: selectedFiles, error: selectedFilesError } = useSWR(
@@ -981,13 +981,6 @@ export default function AllConversations(props: SidePanelProps) {
sideBarOpen={props.sideBarOpen}
/>
</div>
{props.sideBarOpen && (
<FilesMenu
conversationId={props.conversationId}
uploadedFiles={props.uploadedFiles}
isMobileWidth={props.isMobileWidth}
/>
)}
</>
)}
</div>

View File

@@ -8,6 +8,7 @@ import {
SidebarMenu,
SidebarMenuButton,
SidebarMenuItem,
SidebarRail,
} from "@/components/ui/sidebar";
import {
KhojAgentLogo,
@@ -150,6 +151,7 @@ export function AppSidebar(props: AppSidebarProps) {
<SidebarFooter>
<FooterMenu sideBarIsOpen={open} />
</SidebarFooter>
<SidebarRail />
</Sidebar>
);
}

View File

@@ -314,7 +314,15 @@ export default function ChatHistory(props: ChatHistoryProps) {
}
return (
<ScrollArea className={`h-[73vh] relative`} ref={scrollAreaRef}>
<ScrollArea
className={`
h-[calc(100svh-theme(spacing.44))]
sm:h-[calc(100svh-theme(spacing.44))]
md:h-[calc(100svh-theme(spacing.44))]
lg:h-[calc(100svh-theme(spacing.72))]
`}
ref={scrollAreaRef}>
<div>
<div className={`${styles.chatHistory} ${props.customClassName}`}>
<div ref={sentinelRef} style={{ height: "1px" }}>
@@ -343,12 +351,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}

View File

@@ -0,0 +1,148 @@
"use client"
import * as React from "react"
import { Bell } from "@phosphor-icons/react";
import { Button } from "@/components/ui/button";
import { Sidebar, SidebarContent, SidebarGroup, SidebarGroupContent, SidebarHeader, SidebarMenu, SidebarMenuButton, SidebarMenuItem } from "@/components/ui/sidebar";
import { DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuTrigger } from "@/components/ui/dropdown-menu";
import { Textarea } from "@/components/ui/textarea";
import { ModelSelector } from "@/app/common/modelSelector";
import { FilesMenu } from "../allConversations/allConversations";
import { AgentConfigurationOptions } from "@/app/agents/page";
import useSWR from "swr";
import { Sheet, SheetContent } from "@/components/ui/sheet";
interface ChatSideBarProps {
conversationId: string;
isOpen: boolean;
isMobileWidth?: boolean;
onOpenChange: (open: boolean) => void;
}
const fetcher = (url: string) => fetch(url).then((res) => res.json());
export function ChatSidebar({ ...props }: ChatSideBarProps) {
const { data: agentConfigurationOptions, error: agentConfigurationOptionsError } =
useSWR<AgentConfigurationOptions>("/api/agents/options", fetcher);
if (props.isMobileWidth) {
return (
<Sheet
open={props.isOpen}
onOpenChange={props.onOpenChange}>
<SheetContent
className="w-[300px] bg-sidebar p-0 text-sidebar-foreground [&>button]:hidden"
>
<ChatSidebarInternal {...props} />
</SheetContent>
</Sheet>
);
}
return (
<ChatSidebarInternal {...props} />
);
}
function ChatSidebarInternal({ ...props }: ChatSideBarProps) {
const { data: agentConfigurationOptions, error: agentConfigurationOptionsError } =
useSWR<AgentConfigurationOptions>("/api/agents/options", fetcher);
return (
<Sidebar
collapsible="none"
className={`ml-auto rounded-lg p-2 transition-all transform duration-300 ease-in-out
${props.isOpen
? "translate-x-0 opacity-100 w-[300px]"
: "translate-x-full opacity-0 w-0"}
`}
variant="floating">
<SidebarContent>
<SidebarHeader>
Chat Options
</SidebarHeader>
<SidebarGroup key={"test"} className="border-b last:border-none">
<SidebarGroupContent className="gap-0">
<SidebarMenu className="p-0 m-0">
<SidebarMenuItem key={"item4"} className="list-none">
<span>Custom Instructions</span>
<Textarea className="w-full h-32" />
</SidebarMenuItem>
<SidebarMenuItem key={"item"} className="list-none">
<SidebarMenuButton>
<Bell /> <span>Model</span>
</SidebarMenuButton>
<ModelSelector />
</SidebarMenuItem>
<SidebarMenuItem key={"item1"} className="list-none">
<SidebarMenuButton>
<Bell /> <span>Input Tools</span>
</SidebarMenuButton>
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="outline">Input Tools</Button>
</DropdownMenuTrigger>
<DropdownMenuContent className="w-56">
<DropdownMenuLabel>Input Tool Options</DropdownMenuLabel>
<DropdownMenuSeparator />
{
Object.entries(agentConfigurationOptions?.input_tools ?? {}).map(([key, value]) => {
return (
<DropdownMenuCheckboxItem
checked={true}
onCheckedChange={() => { }}
>
{key}
</DropdownMenuCheckboxItem>
);
}
)
}
</DropdownMenuContent>
</DropdownMenu>
</SidebarMenuItem>
<SidebarMenuItem key={"item2"} className="list-none">
<SidebarMenuButton>
<Bell /> <span>Output Tools</span>
</SidebarMenuButton>
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="outline">Output Tools</Button>
</DropdownMenuTrigger>
<DropdownMenuContent className="w-56">
<DropdownMenuLabel>Output Tool Options</DropdownMenuLabel>
<DropdownMenuSeparator />
{
Object.entries(agentConfigurationOptions?.output_modes ?? {}).map(([key, value]) => {
return (
<DropdownMenuCheckboxItem
checked={true}
onCheckedChange={() => { }}
>
{key}
</DropdownMenuCheckboxItem>
);
}
)
}
</DropdownMenuContent>
</DropdownMenu>
</SidebarMenuItem>
<SidebarMenuItem key={"item3"} className="list-none">
<FilesMenu
conversationId={props.conversationId}
uploadedFiles={[]}
isMobileWidth={props.isMobileWidth ?? false}
/>
</SidebarMenuItem>
</SidebarMenu>
</SidebarGroupContent>
</SidebarGroup>
</SidebarContent>
</Sidebar>
)
}