Skip to content

Commit f18eeb1

Browse files
committed
fix: sample messages
1 parent 388b923 commit f18eeb1

File tree

5 files changed

+92
-85
lines changed

5 files changed

+92
-85
lines changed

frontend/src/components/chat/chat-input.tsx

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ interface ChatInputProps {
1111
onAbort?: () => void;
1212
loading?: boolean;
1313
disabled?: boolean;
14+
sampleMessages?: string[];
1415
className?: string;
1516
}
1617

@@ -19,6 +20,7 @@ export const ChatInput = ({
1920
onAbort,
2021
loading,
2122
disabled,
23+
sampleMessages,
2224
className,
2325
}: ChatInputProps) => {
2426
const [message, setMessage] = useState('');
@@ -55,9 +57,29 @@ export const ChatInput = ({
5557
onChange={(e) => setMessage(e.target.value)}
5658
onKeyDown={handleKeyDown}
5759
placeholder="Enter message to start chat ..."
58-
className="min-h-[64px] w-full resize-none rounded-xl shadow-xl"
60+
className={cn(
61+
'min-h-[100px] w-full resize-none border border-primary/50 rounded-xl shadow-xl bg-primary-foreground',
62+
disabled && 'bg-muted',
63+
sampleMessages && 'pt-10'
64+
)}
5965
disabled={disabled}
6066
/>
67+
{sampleMessages && (
68+
<div className="absolute top-2 left-2 flex gap-2 right-0">
69+
{sampleMessages.slice(0, 3).map((message, index) => (
70+
<Button
71+
key={index}
72+
variant="outline"
73+
size="sm"
74+
onClick={() => setMessage(message)}
75+
className="h-6 text-xs text-muted-foreground w-1/3 line-clamp-1 flex items-center justify-start"
76+
>
77+
<Icons.messageSquare className="w-3 h-3" />
78+
{message}
79+
</Button>
80+
))}
81+
</div>
82+
)}
6183
<div className="absolute bottom-2 right-2 flex items-center gap-2">
6284
{loading && (
6385
<Button

frontend/src/components/chat/chat-list.tsx

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ export const ChatList = ({ className }: ChatListProps) => {
8686
key={chat.id}
8787
onClick={() => router.push(`/chat?id=${chat.id}`)}
8888
className={cn(
89-
'flex items-center gap-2 p-2 border-transparent hover:bg-muted rounded-md group cursor-pointer',
89+
'relative flex items-center gap-2 p-2 border-transparent hover:bg-muted rounded-md group cursor-pointer',
9090
activeChatId === chat.id &&
9191
'bg-primary text-primary-foreground hover:bg-primary/90'
9292
)}
@@ -104,7 +104,7 @@ export const ChatList = ({ className }: ChatListProps) => {
104104
setEditingName('');
105105
}
106106
}}
107-
className="h-8 w-full"
107+
className="h-7 w-full text-xs outline-none"
108108
autoFocus
109109
/>
110110
<Button
@@ -117,16 +117,16 @@ export const ChatList = ({ className }: ChatListProps) => {
117117
</Button>
118118
</div>
119119
) : (
120-
<div className="group relative flex-1 justify-start">
120+
<div className="group flex-1 justify-start">
121121
<span className="text-sm line-clamp-1">
122122
{chat.name ||
123123
`Chat with ${chat.from_project || chat.from_template}`}
124124
</span>
125-
<div className="hidden group-hover:flex absolute right-0 top-0 items-center gap-1">
125+
<div className="hidden group-hover:flex absolute p-1 justify-end right-0 top-0 bottom-0 items-center gap-1">
126126
<Button
127-
variant="secondary"
127+
variant="outline"
128128
size="icon"
129-
className="w-5 h-5 text-muted-foreground"
129+
className="w-6 h-6 text-muted-foreground"
130130
onClick={() => {
131131
setEditingId(chat.id);
132132
setEditingName(chat.name || '');
@@ -141,7 +141,7 @@ export const ChatList = ({ className }: ChatListProps) => {
141141
<Button
142142
variant="secondary"
143143
size="icon"
144-
className="w-5 h-5"
144+
className="w-6 h-6"
145145
onClick={() => handleDeleteChat(chat.id)}
146146
>
147147
{isDeleting ? (

frontend/src/components/chat/chat-pane.tsx

Lines changed: 27 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -10,34 +10,10 @@ import { useToast } from '@/hooks/use-toast';
1010
import { RealtimeChannel } from '@supabase/supabase-js';
1111
import { genId } from '@/lib/id';
1212
import supabase from '@/lib/supabase/client';
13-
import { cn } from '@/lib/utils';
1413
import { Loading } from '../loading';
1514
import { isArray } from 'lodash-es';
1615
import { ScrollArea } from '@/components/ui/scroll-area';
1716

18-
const SampleMessagePanel = ({ flow, className, onSelect }: any) => {
19-
const config = flow?.nodes?.find((node: any) => node.type === 'initializer');
20-
if (!config?.data?.sample_messages || !isArray(config.data.sample_messages)) {
21-
return null;
22-
}
23-
const sampleMessages = config.data.sample_messages as string[];
24-
return (
25-
<div className={cn(className, 'flex items-center gap-1')}>
26-
{sampleMessages.map((msg, i) => (
27-
<Button
28-
key={i}
29-
variant="secondary"
30-
size="sm"
31-
onClick={() => onSelect(msg)}
32-
className="text-xs max-w-[240px] truncate px-1 py-0"
33-
>
34-
<span className="line-clamp-2 text-right">{msg}</span>
35-
</Button>
36-
))}
37-
</div>
38-
);
39-
};
40-
4117
interface ChatPaneProps {
4218
projectId: number;
4319
chatId: number;
@@ -260,47 +236,41 @@ export const ChatPane = ({ projectId, chatId }: ChatPaneProps) => {
260236
);
261237
}
262238

239+
const config = chatSource?.flow?.nodes?.find(
240+
(node: any) => node.type === 'initializer'
241+
);
242+
if (!config?.data?.sample_messages || !isArray(config.data.sample_messages)) {
243+
return null;
244+
}
245+
const sampleMessages = config.data.sample_messages as string[];
246+
263247
return (
264-
<div className="flex flex-col w-full h-full">
265-
<ScrollArea className="relative flex flex-col items-center w-full flex-1 gap-1">
266-
<MessageList chat={chat} messages={messages} onSend={handleSend} />
267-
<div className="absolute bottom-1 right-1 flex items-center gap-2">
268-
<Button
269-
variant="outline"
270-
size="icon"
271-
disabled={isCleaning}
272-
onClick={handleClean}
273-
className="w-7 h-7"
274-
>
275-
{isCleaning ? (
276-
<Icons.spinner className="w-4 h-4 animate-spin" />
277-
) : (
278-
<Icons.trash className="w-4 h-4" />
279-
)}
280-
</Button>
281-
<Button
282-
variant="outline"
283-
size="icon"
284-
className="w-7 h-7"
285-
onClick={handleAdd}
286-
>
287-
<Icons.add className="w-4 h-4" />
288-
</Button>
248+
<div className="flex flex-col w-full h-full bg-muted">
249+
{messages.length > 0 ? (
250+
<ScrollArea className="flex flex-col w-full flex-1 p-2 pb-0">
251+
<MessageList
252+
chat={chat}
253+
messages={messages}
254+
onSend={handleSend}
255+
className="max-w-4xl mx-auto mb-1"
256+
/>
257+
258+
<div ref={messagesEndRef} />
259+
</ScrollArea>
260+
) : (
261+
<div className="flex flex-col items-center justify-center h-full gap-2 text-muted-foreground/50">
262+
<Icons.node className="w-10 h-10" />
263+
<p>Let&apos;s start chatting!</p>
289264
</div>
290-
<div ref={messagesEndRef} />
291-
</ScrollArea>
292-
<div className="relative flex flex-col gap-1 w-full max-w-4xl mx-auto">
265+
)}
266+
<div className="relative flex flex-col gap-1 w-full max-w-4xl mx-auto p-2 pt-0">
293267
<ChatInput
294268
onSubmit={handleSend}
295269
onAbort={handleAbort}
296270
loading={status === 'running'}
297271
disabled={status === 'failed' || currentChatId === -1}
298272
className="w-full"
299-
/>
300-
<SampleMessagePanel
301-
flow={chatSource?.flow}
302-
onSelect={handleSend}
303-
className="absolute bottom-2 left-2"
273+
sampleMessages={sampleMessages}
304274
/>
305275
</div>
306276
</div>

frontend/src/components/chat/message-list.tsx

Lines changed: 34 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,21 @@ import { Card } from '../ui/card';
1717
import { Avatar, AvatarFallback, AvatarImage } from '../ui/avatar';
1818
import { Markdown } from '@/components/markdown';
1919
import { ScrollArea } from '../ui/scroll-area';
20+
import { cn } from '@/lib/utils';
2021

2122
interface MessageBubbleProps {
2223
chat: any;
2324
message: Message;
2425
onSend: (content: string) => void;
26+
className?: string;
2527
}
2628

27-
const MessageBubble = ({ chat, message, onSend }: MessageBubbleProps) => {
29+
const MessageBubble = ({
30+
chat,
31+
message,
32+
onSend,
33+
className,
34+
}: MessageBubbleProps) => {
2835
const { chatSource } = useChat(chat.id);
2936
const { user } = useUser();
3037

@@ -50,7 +57,11 @@ const MessageBubble = ({ chat, message, onSend }: MessageBubbleProps) => {
5057

5158
return (
5259
<Card
53-
className={`flex items-center gap-2 shadow-sm px-3 py-1 rounded-md ${resultClass}`}
60+
className={cn(
61+
'flex items-center gap-2 shadow-sm px-3 py-1 rounded-md',
62+
resultClass,
63+
className
64+
)}
5465
>
5566
{success ? (
5667
<Icons.checkCircle className="w-4 h-4" />
@@ -64,7 +75,12 @@ const MessageBubble = ({ chat, message, onSend }: MessageBubbleProps) => {
6475
);
6576
} else if (message.content.startsWith(StatusMessage.running)) {
6677
return (
67-
<Card className="flex items-center gap-2 shadow-sm px-3 py-1 bg-blue-500/20 text-blue-500 rounded-md">
78+
<Card
79+
className={cn(
80+
'flex items-center gap-2 shadow-sm px-3 py-1 bg-blue-500/20 text-blue-500 rounded-md',
81+
className
82+
)}
83+
>
6884
<Icons.node className="w-4 h-4" />
6985
<span className="text-sm font-semibold">
7086
Collaboration started... Please wait for the conclusion.
@@ -86,7 +102,7 @@ const MessageBubble = ({ chat, message, onSend }: MessageBubbleProps) => {
86102
? 'bg-yellow-600/20 text-yellow-600'
87103
: message.role === 'assistant'
88104
? 'bg-primary text-primary-foreground'
89-
: 'bg-muted/20 text-muted-foreground';
105+
: 'bg-primary-foreground text-primary-content';
90106

91107
let avatarIcon = <Icons.node className="w-4 h-4" />;
92108
if (message.role === 'user') {
@@ -119,15 +135,17 @@ const MessageBubble = ({ chat, message, onSend }: MessageBubbleProps) => {
119135
</>
120136
)}
121137
</div>
122-
<div className="text-muted-foreground/20 text-xs">
138+
<div className="text-muted-foreground text-xs">
123139
{new Date(message.created_at).toLocaleString()}
124140
</div>
125141
</div>
126142
);
127143
}
128144

129145
return (
130-
<Card className={`${messageClass} p-1 w-full mx-auto shadow-sm max-w-4xl `}>
146+
<Card
147+
className={cn(messageClass, 'p-1 w-full mx-auto shadow-sm', className)}
148+
>
131149
<div className="flex items-center gap-2">
132150
<div
133151
className={`w-8 h-8 rounded-full text-sm flex items-center justify-center`}
@@ -180,31 +198,27 @@ const MessageBubble = ({ chat, message, onSend }: MessageBubbleProps) => {
180198
interface MessageListProps {
181199
chat: any;
182200
messages: Message[];
201+
className?: string;
183202
onSend: (content: string) => void;
184203
}
185204

186-
export const MessageList = ({ chat, messages, onSend }: MessageListProps) => {
187-
if (!messages.length) {
188-
return (
189-
<div className="flex flex-col items-center justify-center h-full text-muted-foreground/50">
190-
<div className="flex flex-col items-center gap-4">
191-
<Icons.node className="w-10 h-10" />
192-
<p>Let&apos;s start chatting!</p>
193-
</div>
194-
</div>
195-
);
196-
}
197-
205+
export const MessageList = ({
206+
chat,
207+
messages,
208+
onSend,
209+
className,
210+
}: MessageListProps) => {
198211
return (
199-
<div className="flex flex-col gap-1 w-full max-w-4xl mx-auto">
212+
<>
200213
{messages.map((message, index) => (
201214
<MessageBubble
202215
key={message.id || index}
203216
chat={chat}
204217
message={message}
205218
onSend={onSend}
219+
className={className}
206220
/>
207221
))}
208-
</div>
222+
</>
209223
);
210224
};

frontend/src/components/icons.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ import { Logo } from './logo';
8686
export type Icon = LucideIcon;
8787

8888
export const Icons = {
89+
messageSquare: MessageSquare,
8990
chevronDown: ChevronDown,
9091
chevronRight: ChevronRight,
9192
chevronLeft: ChevronLeft,

0 commit comments

Comments
 (0)