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:
Raghav Tirumale
2024-07-27 04:42:00 -04:00
committed by GitHub
parent 8503d7a07b
commit 1685c60e3c
33 changed files with 1790 additions and 7771 deletions

View File

@@ -15,6 +15,8 @@ import { InlineLoading } from '../loading/loading';
import { Lightbulb } from "@phosphor-icons/react";
import ProfileCard from '../profileCard/profileCard';
import { getIconFromIconName } from '@/app/common/iconUtils';
import { AgentData } from '@/app/agents/page';
interface ChatResponse {
status: string;
@@ -31,26 +33,26 @@ interface ChatHistoryProps {
incomingMessages?: StreamMessage[];
pendingMessage?: string;
publicConversationSlug?: string;
setAgent: (agent: AgentData) => void;
}
function constructTrainOfThought(trainOfThought: string[], lastMessage: boolean, key: string, completed: boolean = false) {
function constructTrainOfThought(trainOfThought: string[], lastMessage: boolean, agentColor: string, key: string, completed: boolean = false) {
const lastIndex = trainOfThought.length - 1;
return (
<div className={`${styles.trainOfThought}`} key={key}>
<div className={`${styles.trainOfThought} shadow-sm`} key={key}>
{
!completed &&
<InlineLoading className='float-right' />
}
{trainOfThought.map((train, index) => (
<TrainOfThought key={`train-${index}`} message={train} primary={index === lastIndex && lastMessage && !completed} />
<TrainOfThought key={`train-${index}`} message={train} primary={index === lastIndex && lastMessage && !completed} agentColor={agentColor} />
))}
</div>
)
}
export default function ChatHistory(props: ChatHistoryProps) {
const [data, setData] = useState<ChatHistoryData | null>(null);
const [currentPage, setCurrentPage] = useState(0);
@@ -64,7 +66,6 @@ export default function ChatHistory(props: ChatHistoryProps) {
const [fetchingData, setFetchingData] = useState(false);
const [isMobileWidth, setIsMobileWidth] = useState(false);
useEffect(() => {
window.addEventListener('resize', () => {
setIsMobileWidth(window.innerWidth < 768);
@@ -184,6 +185,7 @@ export default function ChatHistory(props: ChatHistoryProps) {
setFetchingData(false);
return;
}
props.setAgent(chatData.response.agent);
setData(chatData.response);
@@ -199,6 +201,7 @@ export default function ChatHistory(props: ChatHistoryProps) {
conversation_id: chatData.response.conversation_id,
slug: chatData.response.slug,
}
props.setAgent(chatData.response.agent);
setData(chatMetadata);
}
@@ -208,6 +211,7 @@ export default function ChatHistory(props: ChatHistoryProps) {
})
.catch(err => {
console.error(err);
window.location.href = "/";
});
};
@@ -234,11 +238,6 @@ export default function ChatHistory(props: ChatHistoryProps) {
return `/agents?agent=${data.agent.slug}`
}
function constructAgentAvatar() {
if (!data || !data.agent || !data.agent.avatar) return `/avatar.png`;
return data.agent.avatar;
}
function constructAgentName() {
if (!data || !data.agent || !data.agent.name) return `Agent`;
return data.agent.name;
@@ -265,7 +264,7 @@ export default function ChatHistory(props: ChatHistoryProps) {
isMobileWidth={isMobileWidth}
chatMessage={chatMessage}
customClassName='fullHistory'
borderLeftColor='orange-500'
borderLeftColor={`${data?.agent.color}-500`}
isLastMessage={index === data.chat.length - 1}
/>
))}
@@ -287,13 +286,14 @@ export default function ChatHistory(props: ChatHistoryProps) {
}
}
customClassName='fullHistory'
borderLeftColor='orange-500'
borderLeftColor={`${data?.agent.color}-500`}
/>
{
message.trainOfThought &&
constructTrainOfThought(
message.trainOfThought,
index === incompleteIncomingMessageIndex,
data?.agent.color || 'orange',
`${index}trainOfThought`, message.completed)
}
<ChatMessage
@@ -311,7 +311,7 @@ export default function ChatHistory(props: ChatHistoryProps) {
}
}
customClassName='fullHistory'
borderLeftColor='orange-500'
borderLeftColor={`${data?.agent.color}-500`}
isLastMessage={true}
/>
</>
@@ -334,7 +334,7 @@ export default function ChatHistory(props: ChatHistoryProps) {
}
}
customClassName='fullHistory'
borderLeftColor='orange-500'
borderLeftColor={`${data?.agent.color}-500`}
isLastMessage={true}
/>
}
@@ -344,7 +344,7 @@ export default function ChatHistory(props: ChatHistoryProps) {
<ProfileCard
name={constructAgentName()}
link={constructAgentLink()}
avatar={<Lightbulb color='orange' weight='fill' />}
avatar={getIconFromIconName(data.agent.icon, data.agent.color) || <Lightbulb />}
description={constructAgentPersona()}
/>
</div>