mirror of
https://github.com/khoaliber/khoj.git
synced 2026-03-03 05:29:12 +00:00
Nav Menu Upgrades and Minor UX Improvements (#869)
* Converted navigation menu into a dropdown menu * Moved collapsed side panel menu icons into top row * Auto refresh when conversation is deleted to update side panel and route back to main page if deletion is on current conversation * Highlight the current conversation in the side panel * Dynamic homepage messages with current day and time of day. * `colorutils` upgraded to have more expansive tailwind color options and dynamic class name generation. * Converted create agent button alert into shadcn `ToolTip` * Colored lines and icons for agents in chat window * Cleaned up border styling in dark mode * fixed three dot menu in side panel to be more easier to click * Add the KhojLogo import in the nav menu and use a default user profile icon when not authenticated * Get rid of custom --box-shadow CSS variable * Pass the agent metadat through the chat body data in order to style the send button * Add login to the unauthenticated login view, redirecto to home if conversation history not loaded * Set a max height for the input text area * Simplify tailwind class names --------- Co-authored-by: sabaimran <narmiabas@gmail.com>
This commit is contained in:
@@ -8,6 +8,7 @@ import { UserProfile, useAuthenticatedData } from "@/app/common/auth";
|
||||
import { Avatar, AvatarImage, AvatarFallback } from "@/components/ui/avatar";
|
||||
import Link from "next/link";
|
||||
import useSWR from "swr";
|
||||
import Image from "next/image";
|
||||
|
||||
import {
|
||||
Command,
|
||||
@@ -77,6 +78,7 @@ import { Label } from "@/components/ui/label";
|
||||
import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, AlertDialogTrigger } from "@/components/ui/alert-dialog";
|
||||
import { modifyFileFilterForConversation } from "@/app/common/chatFunctions";
|
||||
import { ScrollAreaScrollbar } from "@radix-ui/react-scroll-area";
|
||||
import { KhojLogo } from "../logo/khogLogo";
|
||||
|
||||
// Define a fetcher function
|
||||
const fetcher = (url: string) => fetch(url).then((res) => res.json());
|
||||
@@ -364,9 +366,7 @@ function SessionsAndFiles(props: SessionsAndFilesProps) {
|
||||
}
|
||||
</div>
|
||||
<FilesMenu conversationId={props.conversationId} uploadedFiles={props.uploadedFiles} isMobileWidth={props.isMobileWidth} />
|
||||
{props.userProfile &&
|
||||
<UserProfileComponent userProfile={props.userProfile} webSocketConnected={props.webSocketConnected} collapsed={false} />
|
||||
}</>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -487,6 +487,15 @@ function ChatSessionActionMenu(props: ChatSessionActionMenuProps) {
|
||||
onClick={() => {
|
||||
deleteConversation(props.conversationId);
|
||||
setIsDeleting(false);
|
||||
var currConversationId = parseInt(new URLSearchParams(window.location.search).get('conversationId') || "0");
|
||||
//edge case for deleting current conversation
|
||||
if (currConversationId === parseInt(props.conversationId)) {
|
||||
window.location.href = '/';
|
||||
}
|
||||
//reload side panel
|
||||
setTimeout(() => {
|
||||
window.location.reload();
|
||||
}, 1000);
|
||||
}}
|
||||
className="bg-rose-500 hover:bg-rose-600">Delete</AlertDialogAction>
|
||||
</AlertDialogFooter>
|
||||
@@ -523,13 +532,13 @@ function ChatSessionActionMenu(props: ChatSessionActionMenuProps) {
|
||||
|
||||
function ChatSession(props: ChatHistory) {
|
||||
const [isHovered, setIsHovered] = useState(false);
|
||||
|
||||
var currConversationId = parseInt(new URLSearchParams(window.location.search).get('conversationId') || "-1");
|
||||
return (
|
||||
<div
|
||||
onMouseEnter={() => setIsHovered(true)}
|
||||
onMouseLeave={() => setIsHovered(false)}
|
||||
key={props.conversation_id}
|
||||
className={`${styles.session} ${props.compressed ? styles.compressed : '!max-w-full'} ${isHovered ? `${styles.sessionHover}` : ''}`}>
|
||||
className={`${styles.session} ${props.compressed ? styles.compressed : '!max-w-full'} ${isHovered ? `${styles.sessionHover}` : ''} ${currConversationId === parseInt(props.conversation_id) && currConversationId != -1 ? "dark:bg-neutral-800 bg-white" : ""}`}>
|
||||
<Link href={`/chat?conversationId=${props.conversation_id}`} onClick={() => props.showSidePanel(false)}>
|
||||
<p className={styles.session}>{props.slug || "New Conversation 🌱"}</p>
|
||||
</Link>
|
||||
@@ -588,45 +597,6 @@ interface UserProfileProps {
|
||||
collapsed: boolean;
|
||||
}
|
||||
|
||||
function UserProfileComponent(props: UserProfileProps) {
|
||||
if (props.collapsed) {
|
||||
return (
|
||||
<div className={styles.profile}>
|
||||
<Avatar className="h-7 w-7">
|
||||
<AvatarImage src={props.userProfile.photo} alt="user profile" />
|
||||
<AvatarFallback>
|
||||
{props.userProfile.username[0]}
|
||||
</AvatarFallback>
|
||||
</Avatar>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={styles.profile}>
|
||||
<Link href="/settings">
|
||||
<Avatar>
|
||||
<AvatarImage src={props.userProfile.photo} alt="user profile" />
|
||||
<AvatarFallback>
|
||||
{props.userProfile.username[0]}
|
||||
</AvatarFallback>
|
||||
</Avatar>
|
||||
</Link>
|
||||
<div className={styles.profileDetails}>
|
||||
<p>{props.userProfile?.username}</p>
|
||||
{/* Connected Indicator */}
|
||||
<div className="flex gap-2 items-center">
|
||||
<div className={`inline-flex h-4 w-4 rounded-full opacity-75 ${props.webSocketConnected ? 'bg-green-500' : 'bg-rose-500'}`}></div>
|
||||
<p className="text-muted-foreground text-sm">
|
||||
{props.webSocketConnected ? "Connected" : "Disconnected"}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
const fetchChatHistory = async (url: string) => {
|
||||
const response = await fetch(url, {
|
||||
method: 'GET',
|
||||
@@ -700,19 +670,11 @@ export default function SidePanel(props: SidePanelProps) {
|
||||
}
|
||||
}, [chatSessions]);
|
||||
|
||||
function newConvo() {
|
||||
window.location.href = '/';
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={`${styles.panel} ${enabled ? styles.expanded : styles.collapsed}`}>
|
||||
<div className={`flex items-center justify-between ${(enabled || props.isMobileWidth) ? 'flex-row' : 'flex-col'}`}>
|
||||
<div className={`${styles.panel} ${enabled ? styles.expanded : styles.collapsed} mt-1`}>
|
||||
<div className={`flex justify-between flex-row`}>
|
||||
<Link href='/'>
|
||||
<img
|
||||
src="/khoj-logo.svg"
|
||||
alt="khoj logo"
|
||||
width={52}
|
||||
height={52} />
|
||||
<KhojLogo />
|
||||
</Link>
|
||||
{
|
||||
authenticatedData && props.isMobileWidth ?
|
||||
@@ -748,8 +710,8 @@ export default function SidePanel(props: SidePanelProps) {
|
||||
</DrawerContent>
|
||||
</Drawer>
|
||||
:
|
||||
<div className={`flex items-center ${enabled ? 'flex-row gap-2' : 'flex-col pt-2'}`}>
|
||||
<Link className={` ${enabled ? 'ml-2' : ''}`} href="/">
|
||||
<div className={`${enabled ? 'flex items-center flex-row gap-2' : 'flex'}`}>
|
||||
<Link className={`ml-4 mr-4`} href="/">
|
||||
{enabled ? <NotePencil className="h-6 w-6" /> : <NotePencil className="h-6 w-6" color="gray" />}
|
||||
</Link>
|
||||
<button className={styles.button} onClick={() => setEnabled(!enabled)}>
|
||||
|
||||
@@ -7,7 +7,7 @@ div.session {
|
||||
font-size: medium;
|
||||
display: grid;
|
||||
grid-template-columns: minmax(auto, 400px) 1fr;
|
||||
gap: 1rem;
|
||||
gap: 0rem;
|
||||
}
|
||||
|
||||
div.compressed {
|
||||
|
||||
Reference in New Issue
Block a user