Skip to content

Commit 2925949

Browse files
committed
chat component refactor
1 parent 8542399 commit 2925949

File tree

16 files changed

+1458
-1630
lines changed

16 files changed

+1458
-1630
lines changed
Lines changed: 116 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,117 @@
1-
// client/packages/lowcoder/src/comps/comps/chatComp/chatComp.tsx
2-
import { UICompBuilder } from "comps/generators";
3-
import { NameConfig, withExposingConfigs } from "comps/generators/withExposing";
4-
import { chatChildrenMap } from "./chatCompTypes";
5-
import { ChatView } from "./chatView";
6-
import { ChatPropertyView } from "./chatPropertyView";
7-
8-
// Build the component
9-
const ChatTmpComp = new UICompBuilder(
10-
chatChildrenMap,
11-
(props, dispatch) => (
12-
<ChatView
13-
{...props}
14-
chatQuery={props.chatQuery.value}
15-
currentMessage={props.currentMessage.value}
16-
dispatch={dispatch}
17-
/>
18-
)
19-
)
20-
.setPropertyViewFn((children) => <ChatPropertyView children={children} />)
21-
.build();
22-
23-
// Export the component with exposed variables
24-
export const ChatComp = withExposingConfigs(ChatTmpComp, [
25-
new NameConfig("text", "Chat component text"),
26-
new NameConfig("currentMessage", "Current user message"),
1+
// client/packages/lowcoder/src/comps/comps/chatComp/chatComp.tsx
2+
3+
import { UICompBuilder } from "comps/generators";
4+
import { NameConfig, withExposingConfigs } from "comps/generators/withExposing";
5+
import { StringControl } from "comps/controls/codeControl";
6+
import { stringExposingStateControl } from "comps/controls/codeStateControl";
7+
import { withDefault } from "comps/generators";
8+
import { BoolControl } from "comps/controls/boolControl";
9+
import { dropdownControl } from "comps/controls/dropdownControl";
10+
import QuerySelectControl from "comps/controls/querySelectControl";
11+
import { ChatCore } from "./components/ChatCore";
12+
import { ChatPropertyView } from "./chatPropertyView";
13+
import { createChatStorage } from "./utils/storageFactory";
14+
import { QueryHandler, createMessageHandler } from "./handlers/messageHandlers";
15+
import { useMemo } from "react";
16+
import { changeChildAction } from "lowcoder-core";
17+
18+
import "@assistant-ui/styles/index.css";
19+
import "@assistant-ui/styles/markdown.css";
20+
21+
// ============================================================================
22+
// SIMPLIFIED CHILDREN MAP - ONLY ESSENTIAL PROPS
23+
// ============================================================================
24+
25+
const ModelTypeOptions = [
26+
{ label: "Query", value: "query" },
27+
{ label: "N8N Workflow", value: "n8n" },
28+
] as const;
29+
30+
export const chatChildrenMap = {
31+
// Storage
32+
tableName: withDefault(StringControl, "default"),
33+
34+
// Message Handler Configuration
35+
handlerType: dropdownControl(ModelTypeOptions, "query"),
36+
chatQuery: QuerySelectControl, // Only used for "query" type
37+
modelHost: withDefault(StringControl, ""), // Only used for "n8n" type
38+
systemPrompt: withDefault(StringControl, "You are a helpful assistant."),
39+
streaming: BoolControl.DEFAULT_TRUE,
40+
41+
// UI Configuration
42+
placeholder: withDefault(StringControl, "Chat Component"),
43+
44+
// Exposed Variables (not shown in Property View)
45+
currentMessage: stringExposingStateControl("currentMessage", ""),
46+
};
47+
48+
// ============================================================================
49+
// CLEAN CHATCOMP - USES NEW ARCHITECTURE
50+
// ============================================================================
51+
52+
const ChatTmpComp = new UICompBuilder(
53+
chatChildrenMap,
54+
(props, dispatch) => {
55+
// Create storage from tableName
56+
const storage = useMemo(() =>
57+
createChatStorage(props.tableName),
58+
[props.tableName]
59+
);
60+
61+
// Create message handler based on type
62+
const messageHandler = useMemo(() => {
63+
const handlerType = props.handlerType;
64+
65+
if (handlerType === "query") {
66+
return new QueryHandler({
67+
chatQuery: props.chatQuery.value,
68+
dispatch,
69+
streaming: props.streaming
70+
});
71+
} else if (handlerType === "n8n") {
72+
return createMessageHandler("n8n", {
73+
modelHost: props.modelHost,
74+
systemPrompt: props.systemPrompt,
75+
streaming: props.streaming
76+
});
77+
} else {
78+
// Fallback to mock handler
79+
return createMessageHandler("mock", {
80+
chatQuery: props.chatQuery.value,
81+
dispatch,
82+
streaming: props.streaming
83+
});
84+
}
85+
}, [
86+
props.handlerType,
87+
props.chatQuery,
88+
props.modelHost,
89+
props.systemPrompt,
90+
props.streaming,
91+
dispatch
92+
]);
93+
94+
// Handle message updates for exposed variable
95+
const handleMessageUpdate = (message: string) => {
96+
dispatch(changeChildAction("currentMessage", message, false));
97+
};
98+
99+
return (
100+
<ChatCore
101+
storage={storage}
102+
messageHandler={messageHandler}
103+
onMessageUpdate={handleMessageUpdate}
104+
/>
105+
);
106+
}
107+
)
108+
.setPropertyViewFn((children) => <ChatPropertyView children={children} />)
109+
.build();
110+
111+
// ============================================================================
112+
// EXPORT WITH EXPOSED VARIABLES
113+
// ============================================================================
114+
115+
export const ChatComp = withExposingConfigs(ChatTmpComp, [
116+
new NameConfig("currentMessage", "Current user message"),
27117
]);
Lines changed: 26 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,26 @@
1-
// client/packages/lowcoder/src/comps/comps/chatComp/chatCompTypes.ts
2-
import { StringControl, NumberControl } from "comps/controls/codeControl";
3-
import { stringExposingStateControl } from "comps/controls/codeStateControl";
4-
import { withDefault } from "comps/generators";
5-
import { BoolControl } from "comps/controls/boolControl";
6-
import { dropdownControl } from "comps/controls/dropdownControl";
7-
import QuerySelectControl from "comps/controls/querySelectControl";
8-
9-
// Model type dropdown options
10-
const ModelTypeOptions = [
11-
{ label: "Direct LLM", value: "direct-llm" },
12-
{ label: "n8n Workflow", value: "n8n" },
13-
{ label: "Query", value: "query" },
14-
] as const;
15-
16-
export const chatChildrenMap = {
17-
text: withDefault(StringControl, "Chat Component Placeholder"),
18-
chatQuery: QuerySelectControl,
19-
currentMessage: stringExposingStateControl("currentMessage", ""),
20-
modelType: dropdownControl(ModelTypeOptions, "query"),
21-
modelHost: withDefault(StringControl, ""),
22-
streaming: BoolControl.DEFAULT_TRUE,
23-
systemPrompt: withDefault(StringControl, "You are a helpful assistant."),
24-
agent: BoolControl,
25-
maxInteractions: withDefault(NumberControl, 10),
26-
tableName: withDefault(StringControl, "default"),
27-
};
28-
29-
export type ChatCompProps = {
30-
text: string;
31-
chatQuery: string;
32-
currentMessage: string;
33-
modelType: string;
34-
modelHost: string;
35-
streaming: boolean;
36-
systemPrompt: string;
37-
agent: boolean;
38-
maxInteractions: number;
39-
tableName: string;
40-
};
1+
// client/packages/lowcoder/src/comps/comps/chatComp/chatCompTypes.ts
2+
3+
// ============================================================================
4+
// CLEAN CHATCOMP TYPES - SIMPLIFIED AND FOCUSED
5+
// ============================================================================
6+
7+
export type ChatCompProps = {
8+
// Storage
9+
tableName: string;
10+
11+
// Message Handler
12+
handlerType: "query" | "n8n";
13+
chatQuery: string; // Only used when handlerType === "query"
14+
modelHost: string; // Only used when handlerType === "n8n"
15+
systemPrompt: string;
16+
streaming: boolean;
17+
18+
// UI
19+
placeholder: string;
20+
21+
// Exposed Variables
22+
currentMessage: string; // Read-only exposed variable
23+
};
24+
25+
// Legacy export for backwards compatibility (if needed)
26+
export type ChatCompLegacyProps = ChatCompProps;
Lines changed: 68 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,69 @@
1-
// client/packages/lowcoder/src/comps/comps/chatComp/chatPropertyView.tsx
2-
import React from "react";
3-
import { Section, sectionNames } from "lowcoder-design";
4-
import { trans } from "i18n";
5-
6-
export const ChatPropertyView = React.memo((props: any) => {
7-
const { children } = props;
8-
9-
return (
10-
<Section name={sectionNames.basic}>
11-
{children.text.propertyView({ label: "Text" })}
12-
{children.chatQuery.propertyView({ label: "Chat Query" })}
13-
{children.currentMessage.propertyView({
14-
label: "Current Message (Dynamic)",
15-
placeholder: "Shows the current user message",
16-
disabled: true
17-
})}
18-
{children.modelType.propertyView({ label: "Model Type" })}
19-
{children.streaming.propertyView({ label: "Enable Streaming" })}
20-
{children.systemPrompt.propertyView({
21-
label: "System Prompt",
22-
placeholder: "Enter system prompt...",
23-
enableSpellCheck: false,
24-
})}
25-
{children.agent.propertyView({ label: "Enable Agent Mode" })}
26-
{children.maxInteractions.propertyView({
27-
label: "Max Interactions",
28-
placeholder: "10",
29-
})}
30-
</Section>
31-
);
32-
});
33-
1+
// client/packages/lowcoder/src/comps/comps/chatComp/chatPropertyView.tsx
2+
3+
import React from "react";
4+
import { Section, sectionNames } from "lowcoder-design";
5+
6+
// ============================================================================
7+
// CLEAN PROPERTY VIEW - FOCUSED ON ESSENTIAL CONFIGURATION
8+
// ============================================================================
9+
10+
export const ChatPropertyView = React.memo((props: any) => {
11+
const { children } = props;
12+
13+
return (
14+
<>
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.tableName.propertyView({
23+
label: "Storage Table",
24+
placeholder: "default",
25+
tooltip: "Storage identifier - use same value to share conversations between components"
26+
})}
27+
</Section>
28+
29+
{/* Message Handler Configuration */}
30+
<Section name="Message Handler">
31+
{children.handlerType.propertyView({
32+
label: "Handler Type",
33+
tooltip: "How messages are processed"
34+
})}
35+
36+
{/* Show chatQuery field only for "query" handler */}
37+
{children.handlerType.value === "query" && (
38+
children.chatQuery.propertyView({
39+
label: "Chat Query",
40+
placeholder: "Select a query to handle messages"
41+
})
42+
)}
43+
44+
{/* Show modelHost field only for "n8n" handler */}
45+
{children.handlerType.value === "n8n" && (
46+
children.modelHost.propertyView({
47+
label: "N8N Webhook URL",
48+
placeholder: "http://localhost:5678/webhook/...",
49+
tooltip: "N8N webhook endpoint for processing messages"
50+
})
51+
)}
52+
53+
{children.systemPrompt.propertyView({
54+
label: "System Prompt",
55+
placeholder: "You are a helpful assistant...",
56+
tooltip: "Initial instructions for the AI"
57+
})}
58+
59+
{children.streaming.propertyView({
60+
label: "Enable Streaming",
61+
tooltip: "Stream responses in real-time (when supported)"
62+
})}
63+
</Section>
64+
65+
</>
66+
);
67+
});
68+
3469
ChatPropertyView.displayName = 'ChatPropertyView';

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

Lines changed: 0 additions & 46 deletions
This file was deleted.

0 commit comments

Comments
 (0)