Skip to content

Commit 5d88dbe

Browse files
iamfaranraheeliftikhar5
authored andcommitted
add event listeners for the chat component
1 parent a349af4 commit 5d88dbe

File tree

6 files changed

+140
-40
lines changed

6 files changed

+140
-40
lines changed

client/packages/lowcoder/src/comps/comps/chatComp/chatComp.tsx

Lines changed: 75 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { withDefault } from "comps/generators";
88
import { BoolControl } from "comps/controls/boolControl";
99
import { dropdownControl } from "comps/controls/dropdownControl";
1010
import QuerySelectControl from "comps/controls/querySelectControl";
11+
import { eventHandlerControl, EventConfigType } from "comps/controls/eventHandlerControl";
1112
import { ChatCore } from "./components/ChatCore";
1213
import { ChatPropertyView } from "./chatPropertyView";
1314
import { createChatStorage } from "./utils/storageFactory";
@@ -19,7 +20,58 @@ import "@assistant-ui/styles/index.css";
1920
import "@assistant-ui/styles/markdown.css";
2021

2122
// ============================================================================
22-
// SIMPLIFIED CHILDREN MAP - ONLY ESSENTIAL PROPS
23+
// CHAT-SPECIFIC EVENTS
24+
// ============================================================================
25+
26+
export const componentLoadEvent: EventConfigType = {
27+
label: "Component Load",
28+
value: "componentLoad",
29+
description: "Triggered when the chat component finishes loading - Load existing data from backend",
30+
};
31+
32+
export const messageSentEvent: EventConfigType = {
33+
label: "Message Sent",
34+
value: "messageSent",
35+
description: "Triggered when a user sends a message - Auto-save user messages",
36+
};
37+
38+
export const messageReceivedEvent: EventConfigType = {
39+
label: "Message Received",
40+
value: "messageReceived",
41+
description: "Triggered when a response is received from the AI - Auto-save AI responses",
42+
};
43+
44+
export const threadCreatedEvent: EventConfigType = {
45+
label: "Thread Created",
46+
value: "threadCreated",
47+
description: "Triggered when a new thread is created - Auto-save new threads",
48+
};
49+
50+
export const threadUpdatedEvent: EventConfigType = {
51+
label: "Thread Updated",
52+
value: "threadUpdated",
53+
description: "Triggered when a thread is updated - Auto-save thread changes",
54+
};
55+
56+
export const threadDeletedEvent: EventConfigType = {
57+
label: "Thread Deleted",
58+
value: "threadDeleted",
59+
description: "Triggered when a thread is deleted - Delete thread from backend",
60+
};
61+
62+
const ChatEventOptions = [
63+
componentLoadEvent,
64+
messageSentEvent,
65+
messageReceivedEvent,
66+
threadCreatedEvent,
67+
threadUpdatedEvent,
68+
threadDeletedEvent,
69+
] as const;
70+
71+
export const ChatEventHandlerControl = eventHandlerControl(ChatEventOptions);
72+
73+
// ============================================================================
74+
// SIMPLIFIED CHILDREN MAP - WITH EVENT HANDLERS
2375
// ============================================================================
2476

2577
function generateUniqueTableName(): string {
@@ -48,6 +100,9 @@ export const chatChildrenMap = {
48100
// Database Information (read-only)
49101
databaseName: withDefault(StringControl, ""),
50102

103+
// Event Handlers
104+
onEvent: ChatEventHandlerControl,
105+
51106
// Exposed Variables (not shown in Property View)
52107
currentMessage: stringExposingStateControl("currentMessage", ""),
53108
conversationHistory: stringExposingStateControl("conversationHistory", "[]"),
@@ -119,6 +174,8 @@ const ChatTmpComp = new UICompBuilder(
119174
// Handle message updates for exposed variable
120175
const handleMessageUpdate = (message: string) => {
121176
dispatch(changeChildAction("currentMessage", message, false));
177+
// Trigger messageSent event
178+
props.onEvent("messageSent");
122179
};
123180

124181
// Handle conversation history updates for exposed variable
@@ -130,26 +187,32 @@ const ChatTmpComp = new UICompBuilder(
130187
timestamp: msg.timestamp
131188
}));
132189
dispatch(changeChildAction("conversationHistory", JSON.stringify(formattedHistory), false));
190+
191+
// Trigger messageReceived event when bot responds
192+
const lastMessage = conversationHistory[conversationHistory.length - 1];
193+
if (lastMessage && lastMessage.role === 'assistant') {
194+
props.onEvent("messageReceived");
195+
}
133196
};
134197

135-
// Cleanup on unmount
136-
useEffect(() => {
137-
console.log("cleanup on unmount");
138-
return () => {
139-
console.log("cleanup on unmount");
140-
const tableName = uniqueTableName.current;
141-
if (tableName) {
142-
storage.cleanup();
143-
}
144-
};
145-
}, []);
198+
// Cleanup on unmount
199+
useEffect(() => {
200+
return () => {
201+
const tableName = uniqueTableName.current;
202+
if (tableName) {
203+
storage.cleanup();
204+
}
205+
};
206+
}, []);
146207

147208
return (
148209
<ChatCore
149210
storage={storage}
150211
messageHandler={messageHandler}
212+
placeholder={props.placeholder}
151213
onMessageUpdate={handleMessageUpdate}
152214
onConversationUpdate={handleConversationUpdate}
215+
onEvent={props.onEvent}
153216
/>
154217
);
155218
}

client/packages/lowcoder/src/comps/comps/chatComp/chatPropertyView.tsx

Lines changed: 22 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
// client/packages/lowcoder/src/comps/comps/chatComp/chatPropertyView.tsx
22

3-
import React from "react";
3+
import React, { useMemo } from "react";
44
import { Section, sectionNames } from "lowcoder-design";
5+
import { placeholderPropertyView } from "../../utils/propertyUtils";
56

67
// ============================================================================
78
// CLEAN PROPERTY VIEW - FOCUSED ON ESSENTIAL CONFIGURATION
@@ -10,24 +11,8 @@ import { Section, sectionNames } from "lowcoder-design";
1011
export const ChatPropertyView = React.memo((props: any) => {
1112
const { children } = props;
1213

13-
return (
14+
return useMemo(() => (
1415
<>
15-
{/* Basic Configuration */}
16-
<Section name={sectionNames.basic}>
17-
{children.placeholder.propertyView({
18-
label: "Placeholder Text",
19-
placeholder: "Enter placeholder text..."
20-
})}
21-
22-
{children.databaseName.propertyView({
23-
label: "Database Name",
24-
placeholder: "Database will be auto-generated...",
25-
tooltip: "Read-only: Auto-generated database name for data persistence. You can reference this in queries if needed.",
26-
disabled: true
27-
})}
28-
29-
</Section>
30-
3116
{/* Message Handler Configuration */}
3217
<Section name="Message Handler">
3318
{children.handlerType.propertyView({
@@ -64,8 +49,26 @@ export const ChatPropertyView = React.memo((props: any) => {
6449
})}
6550
</Section>
6651

52+
{/* UI Configuration */}
53+
<Section name="UI Configuration">
54+
{placeholderPropertyView(children)}
55+
</Section>
56+
57+
{/* Database Information */}
58+
<Section name="Database">
59+
{children.databaseName.propertyView({
60+
label: "Database Name",
61+
tooltip: "Auto-generated database name for this chat component (read-only)"
62+
})}
63+
</Section>
64+
65+
{/* STANDARD EVENT HANDLERS SECTION */}
66+
<Section name={sectionNames.interaction}>
67+
{children.onEvent.getPropertyView()}
68+
</Section>
69+
6770
</>
68-
);
71+
), [children]);
6972
});
7073

7174
ChatPropertyView.displayName = 'ChatPropertyView';

client/packages/lowcoder/src/comps/comps/chatComp/components/ChatCore.tsx

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,22 @@ import { ChatCoreProps } from "../types/chatTypes";
99
// CHAT CORE - THE SHARED FOUNDATION
1010
// ============================================================================
1111

12-
export function ChatCore({ storage, messageHandler, onMessageUpdate, onConversationUpdate }: ChatCoreProps) {
12+
export function ChatCore({
13+
storage,
14+
messageHandler,
15+
placeholder,
16+
onMessageUpdate,
17+
onConversationUpdate,
18+
onEvent
19+
}: ChatCoreProps) {
1320
return (
1421
<ChatProvider storage={storage}>
1522
<ChatCoreMain
1623
messageHandler={messageHandler}
24+
placeholder={placeholder}
1725
onMessageUpdate={onMessageUpdate}
1826
onConversationUpdate={onConversationUpdate}
27+
onEvent={onEvent}
1928
/>
2029
</ChatProvider>
2130
);

client/packages/lowcoder/src/comps/comps/chatComp/components/ChatCoreMain.tsx

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// client/packages/lowcoder/src/comps/comps/chatComp/components/ChatCoreMain.tsx
22

3-
import React, { useState } from "react";
3+
import React, { useState, useEffect } from "react";
44
import {
55
useExternalStoreRuntime,
66
ThreadMessageLike,
@@ -59,13 +59,22 @@ const ChatContainer = styled.div`
5959

6060
interface ChatCoreMainProps {
6161
messageHandler: MessageHandler;
62+
placeholder?: string;
6263
onMessageUpdate?: (message: string) => void;
6364
onConversationUpdate?: (conversationHistory: ChatMessage[]) => void;
65+
// STANDARD LOWCODER EVENT PATTERN - SINGLE CALLBACK (OPTIONAL)
66+
onEvent?: (eventName: string) => void;
6467
}
6568

6669
const generateId = () => Math.random().toString(36).substr(2, 9);
6770

68-
export function ChatCoreMain({ messageHandler, onMessageUpdate, onConversationUpdate }: ChatCoreMainProps) {
71+
export function ChatCoreMain({
72+
messageHandler,
73+
placeholder,
74+
onMessageUpdate,
75+
onConversationUpdate,
76+
onEvent
77+
}: ChatCoreMainProps) {
6978
const { state, actions } = useChatContext();
7079
const [isRunning, setIsRunning] = useState(false);
7180

@@ -78,10 +87,15 @@ export function ChatCoreMain({ messageHandler, onMessageUpdate, onConversationUp
7887
console.log("CURRENT MESSAGES", currentMessages);
7988

8089
// Notify parent component of conversation changes
81-
React.useEffect(() => {
90+
useEffect(() => {
8291
onConversationUpdate?.(currentMessages);
8392
}, [currentMessages]);
8493

94+
// Trigger component load event on mount
95+
useEffect(() => {
96+
onEvent?.("componentLoad");
97+
}, [onEvent]);
98+
8599
// Convert custom format to ThreadMessageLike (same as your current implementation)
86100
const convertMessage = (message: ChatMessage): ThreadMessageLike => ({
87101
role: message.role,
@@ -209,6 +223,7 @@ export function ChatCoreMain({ messageHandler, onMessageUpdate, onConversationUp
209223
onSwitchToNewThread: async () => {
210224
const threadId = await actions.createThread("New Chat");
211225
actions.setCurrentThread(threadId);
226+
onEvent?.("threadCreated");
212227
},
213228

214229
onSwitchToThread: (threadId) => {
@@ -217,14 +232,17 @@ export function ChatCoreMain({ messageHandler, onMessageUpdate, onConversationUp
217232

218233
onRename: async (threadId, newTitle) => {
219234
await actions.updateThread(threadId, { title: newTitle });
235+
onEvent?.("threadUpdated");
220236
},
221237

222238
onArchive: async (threadId) => {
223239
await actions.updateThread(threadId, { status: "archived" });
240+
onEvent?.("threadUpdated");
224241
},
225242

226243
onDelete: async (threadId) => {
227244
await actions.deleteThread(threadId);
245+
onEvent?.("threadDeleted");
228246
},
229247
};
230248

@@ -250,7 +268,7 @@ export function ChatCoreMain({ messageHandler, onMessageUpdate, onConversationUp
250268
<AssistantRuntimeProvider runtime={runtime}>
251269
<ChatContainer>
252270
<ThreadList />
253-
<Thread />
271+
<Thread placeholder={placeholder} />
254272
</ChatContainer>
255273
</AssistantRuntimeProvider>
256274
);

client/packages/lowcoder/src/comps/comps/chatComp/components/assistant-ui/thread.tsx

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,11 @@ import {
2222
import { MarkdownText } from "./markdown-text";
2323
import { TooltipIconButton } from "./tooltip-icon-button";
2424

25-
export const Thread: FC = () => {
25+
interface ThreadProps {
26+
placeholder?: string;
27+
}
28+
29+
export const Thread: FC<ThreadProps> = ({ placeholder = "Write a message..." }) => {
2630
return (
2731
<ThreadPrimitive.Root
2832
className="aui-root aui-thread-root"
@@ -47,7 +51,7 @@ import {
4751

4852
<div className="aui-thread-viewport-footer">
4953
<ThreadScrollToBottom />
50-
<Composer />
54+
<Composer placeholder={placeholder} />
5155
</div>
5256
</ThreadPrimitive.Viewport>
5357
</ThreadPrimitive.Root>
@@ -110,13 +114,13 @@ import {
110114
);
111115
};
112116

113-
const Composer: FC = () => {
117+
const Composer: FC<{ placeholder?: string }> = ({ placeholder = "Write a message..." }) => {
114118
return (
115119
<ComposerPrimitive.Root className="aui-composer-root">
116120
<ComposerPrimitive.Input
117121
rows={1}
118122
autoFocus
119-
placeholder="Write a message..."
123+
placeholder={placeholder}
120124
className="aui-composer-input"
121125
/>
122126
<ComposerAction />

client/packages/lowcoder/src/comps/comps/chatComp/types/chatTypes.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,11 @@ export interface ChatMessage {
7575
export interface ChatCoreProps {
7676
storage: ChatStorage;
7777
messageHandler: MessageHandler;
78+
placeholder?: string;
7879
onMessageUpdate?: (message: string) => void;
7980
onConversationUpdate?: (conversationHistory: ChatMessage[]) => void;
81+
// STANDARD LOWCODER EVENT PATTERN - SINGLE CALLBACK
82+
onEvent?: (eventName: string) => void;
8083
}
8184

8285
export interface ChatPanelProps {

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy