Skip to content

Commit

Permalink
Nav Menu Upgrades and Minor UX Improvements (#869)
Browse files Browse the repository at this point in the history
* 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>
  • Loading branch information
MythicalCow and sabaimran authored Jul 27, 2024
1 parent 8503d7a commit 1685c60
Show file tree
Hide file tree
Showing 33 changed files with 1,783 additions and 7,764 deletions.
4 changes: 1 addition & 3 deletions src/interface/web/app/agents/agents.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,7 @@ div.sidePanel {
height: 100%;
}

div.chatLayout {
display: grid;
grid-template-columns: auto 1fr;
div.pageLayout {
gap: 1rem;
}

Expand Down
10 changes: 0 additions & 10 deletions src/interface/web/app/agents/agentsLayout.module.css

This file was deleted.

25 changes: 14 additions & 11 deletions src/interface/web/app/agents/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,22 @@ import "../globals.css";
const inter = Noto_Sans({ subsets: ["latin"] });

export const metadata: Metadata = {
title: "Khoj AI - Chat",
description: "Use this page to chat with Khoj AI.",
title: "Khoj AI - Agents",
description: "Find a specialized agent that can help you address more specific needs.",
icons: {
icon: '/static/favicon.ico',
},
};

export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
return (
<html lang="en">
<meta httpEquiv="Content-Security-Policy"
content="default-src 'self' https://assets.khoj.dev;
return (
<html lang="en">
<meta httpEquiv="Content-Security-Policy"
content="default-src 'self' https://assets.khoj.dev;
media-src * blob:;
script-src 'self' https://assets.khoj.dev 'unsafe-inline' 'unsafe-eval';
connect-src 'self' https://ipapi.co/json ws://localhost:42110;
Expand All @@ -26,9 +29,9 @@ export default function RootLayout({
font-src 'self' https://assets.khoj.dev https://fonts.gstatic.com;
child-src 'none';
object-src 'none';"></meta>
<body className={inter.className}>
{children}
</body>
</html>
);
<body className={inter.className}>
{children}
</body>
</html>
);
}
110 changes: 40 additions & 70 deletions src/interface/web/app/agents/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,11 @@ import { useEffect, useState } from 'react';
import { useAuthenticatedData, UserProfile } from '../common/auth';
import { Button } from '@/components/ui/button';
import {
AlertDialog,
AlertDialogAction,
AlertDialogContent,
AlertDialogDescription,
AlertDialogFooter,
AlertDialogHeader,
AlertDialogTitle,
AlertDialogTrigger,
} from "@/components/ui/alert-dialog"
Tooltip,
TooltipContent,
TooltipProvider,
TooltipTrigger,
} from "@/components/ui/tooltip"

import {
PaperPlaneTilt,
Expand All @@ -35,12 +31,13 @@ import SidePanel from '../components/sidePanel/chatHistorySidePanel';
import NavMenu from '../components/navMenu/navMenu';
import { getIconFromIconName } from '../common/iconUtils';
import { convertColorToTextClass } from '../common/colorUtils';
import { Alert, AlertDescription } from '@/components/ui/alert';

export interface AgentData {
slug: string;
avatar: string;
name: string;
personality: string;
persona: string;
color: string;
icon: string;
}
Expand Down Expand Up @@ -123,13 +120,13 @@ function AgentCard(props: AgentCardProps) {
<Button
className={`bg-[hsl(var(--background))] w-14 h-14 rounded-xl border dark:border-neutral-700 shadow-sm hover:bg-stone-100 dark:hover:bg-neutral-900`}
onClick={() => openChat(props.data.slug, userData)}>
<PaperPlaneTilt className='w-6 h-6' color={props.data.color} />
<PaperPlaneTilt className={`w-6 h-6 ${convertColorToTextClass(props.data.color)}`} />
</Button>
) : (
<Button
className={`bg-[hsl(var(--background))] w-14 h-14 rounded-xl border dark:border-neutral-700 shadow-sm hover:bg-stone-100 dark:hover:bg-neutral-900`}
onClick={() => setShowLoginPrompt(true)}>
<PaperPlaneTilt className='w-6 h-6' color={props.data.color} />
<PaperPlaneTilt className={`w-6 h-6 ${convertColorToTextClass(props.data.color)}`} />
</Button>
)}
</div>
Expand All @@ -148,7 +145,7 @@ function AgentCard(props: AgentCardProps) {
</div>
</DialogHeader>
<div className="max-h-[60vh] overflow-y-scroll text-neutral-500 dark:text-white">
{props.data.personality}
{props.data.persona}
</div>
<DialogFooter>
<Button
Expand All @@ -157,7 +154,7 @@ function AgentCard(props: AgentCardProps) {
openChat(props.data.slug, userData);
setShowModal(false);
}}>
<PaperPlaneTilt className='mr-2 w-6 h-6' color={props.data.color} />
<PaperPlaneTilt className={`w-6 h-6 m-2 ${convertColorToTextClass(props.data.color)}`} />
Start Chatting
</Button>
</DialogFooter>
Expand Down Expand Up @@ -188,13 +185,13 @@ function AgentCard(props: AgentCardProps) {
<Button
className={`bg-[hsl(var(--background))] w-14 h-14 rounded-xl border dark:border-neutral-700 shadow-sm hover:bg-stone-100`}
onClick={() => openChat(props.data.slug, userData)}>
<PaperPlaneTilt className='w-6 h-6' color={props.data.color} />
<PaperPlaneTilt className={`w-6 h-6 ${convertColorToTextClass(props.data.color)}`} />
</Button>
) : (
<Button
className={`bg-[hsl(var(--background))] w-14 h-14 rounded-xl border dark:border-neutral-700 shadow-sm`}
onClick={() => setShowLoginPrompt(true)}>
<PaperPlaneTilt className='w-6 h-6' color={props.data.color} />
<PaperPlaneTilt className={`w-6 h-6 ${convertColorToTextClass(props.data.color)}`} />
</Button>
)}
</div>
Expand All @@ -203,7 +200,7 @@ function AgentCard(props: AgentCardProps) {
<DrawerTitle>{props.data.name}</DrawerTitle>
<DrawerDescription>Full Prompt</DrawerDescription>
</DrawerHeader>
{props.data.personality}
{props.data.persona}
<DrawerFooter>
<DrawerClose>
Done
Expand All @@ -217,19 +214,14 @@ function AgentCard(props: AgentCardProps) {
<CardContent>
<div className={styles.agentPersonality}>
<button className={`${styles.infoButton} text-neutral-500 dark:text-white`} onClick={() => setShowModal(true)}>
<p>{props.data.personality}</p>
<p>{props.data.persona}</p>
</button>
</div>
</CardContent>
</Card>
)
}

function createAgent() {
//just show a dialog for now similar to the agent card when the text is pressed
}


export default function Agents() {
const { data, error } = useSWR<AgentData[]>('agents', agentsFetcher, { revalidateOnFocus: false });
const authenticatedData = useAuthenticatedData();
Expand Down Expand Up @@ -273,7 +265,7 @@ export default function Agents() {
}

return (
<main className={`${styles.main} w-full ml-auto mr-auto`}>
<main className={`${styles.main} w-full mx-auto`}>
<div className="float-right w-fit h-fit">
<NavMenu selected="Agents" />
</div>
Expand All @@ -283,7 +275,7 @@ export default function Agents() {
loginRedirectMessage="Sign in to start chatting with a specialized agent"
onOpenChange={setShowLoginPrompt} />
}
<div className={`${styles.chatLayout} w-full ml-auto mr-auto`}>
<div className={`${styles.pageLayout} w-full mx-auto`}>
<div className={`${styles.sidePanel} top-0`}>
<SidePanel
webSocketConnected={true}
Expand All @@ -292,53 +284,31 @@ export default function Agents() {
isMobileWidth={isMobileWidth}
/>
</div>
<div className={`ml-auto mr-auto ${isMobileWidth ? "w-11/12" : "w-1/2"} pt-10`}>
<div className="pt-8 flex">
<h1 className="text-3xl relative top-2">Agents</h1>
<div className="ml-auto float-right">
<AlertDialog>
<AlertDialogTrigger asChild>
<Button
className={`bg-[hsl(var(--background))] rounded-xl border dark:border-neutral-700 shadow-sm h-14 hover:bg-stone-100 dark:hover:bg-neutral-900`}
onClick={() => createAgent()}
>
<Plus className='w-6 h-6' color='gray' />
<p className="text-black dark:text-white ml-2">
<strong>Create Agent</strong>
</p>
</Button>
</AlertDialogTrigger>
<AlertDialogContent>
<AlertDialogHeader>
<AlertDialogTitle>Custom Agents</AlertDialogTitle>
<AlertDialogDescription>
Custom Agents will be coming to Khoj soon!
</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogAction asChild>
<Button className="bg-stone-100 dark:bg-[hsl(var(--background))] text-neutral-500 dark:text-white hover:bg-stone-100 dark:hover:bg-neutral-900" onClick={() => { }}>
Close
</Button>
</AlertDialogAction>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
<div className={`mx-auto ${isMobileWidth ? "w-11/12" : "w-1/2"} pt-4`}>
<div className="pt-8 flex justify-between align-middle w-full">
<h1 className="text-3xl">Agents</h1>
<div className="ml-auto float-right border p-2 pt-3 rounded-xl font-bold hover:bg-stone-100 dark:hover:bg-neutral-900">
<TooltipProvider>
<Tooltip>
<TooltipTrigger>
<div className="flex flex-row">
<Plus className='pr-2 w-6 h-6' />
<p className="pr-2">Create Agent</p>
</div>
</TooltipTrigger>
<TooltipContent>
<p>Coming Soon!</p>
</TooltipContent>
</Tooltip>
</TooltipProvider>
</div>
</div>
<div>
<Card className={`mt-8 mb-6 pt-1 pb-1 bg-stone-100 dark:bg-[hsl(var(--background))]`}>
<CardContent>
<CardDescription className="flex flex-rows">
<Lightning className='w-4 h-4 mr-2 relative top-3' weight="fill" color="#a068f5" />
<p className="relative top-3">
<strong className="text-black dark:text-white pr-2">How it works</strong>
Use any of these specialized agents to tune your conversation to your needs.
</p>
</CardDescription>
</CardContent>
</Card>
</div>
<Alert className='bg-secondary border-none my-4'>
<AlertDescription>
<Lightning weight={'fill'} className='h-4 w-4 text-purple-400 inline' />
<span className='font-bold'>How it works</span> Use any of these specialized personas to tune your conversation to your needs.
</AlertDescription>
</Alert>
<div className={`${styles.agentList}`}>
{data.map(agent => (
<AgentCard key={agent.slug} data={agent} userProfile={authenticatedData} isMobileWidth={isMobileWidth} />
Expand Down
15 changes: 15 additions & 0 deletions src/interface/web/app/automations/automations.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,23 @@ div.automationCard {
grid-template-rows: auto 1fr auto;
}

div.pageLayout {
max-width: 60vw;
margin: auto;
margin-bottom: 2rem;
}

div.sidePanel {
position: fixed;
height: 100%;
}

@media screen and (max-width: 768px) {
div.automationsLayout {
grid-template-columns: 1fr;
}

div.pageLayout {
max-width: 90vw;
}
}
11 changes: 0 additions & 11 deletions src/interface/web/app/automations/automationsLayout.module.css

This file was deleted.

5 changes: 1 addition & 4 deletions src/interface/web/app/automations/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
import type { Metadata } from "next";
import NavMenu from '../components/navMenu/navMenu';
import styles from './automationsLayout.module.css';
import { Toaster } from "@/components/ui/toaster";

import "../globals.css";
Expand All @@ -20,8 +18,7 @@ export default function RootLayout({
children: React.ReactNode;
}>) {
return (
<div className={`${styles.automationsLayout}`}>
<NavMenu selected="Automations" showLogo={true} />
<div>
{children}
<Toaster />
</div>
Expand Down
Loading

0 comments on commit 1685c60

Please sign in to comment.