Skip to content

Commit 3536b2b

Browse files
integrations more actions
1 parent 7c291df commit 3536b2b

File tree

9 files changed

+4981
-112
lines changed

9 files changed

+4981
-112
lines changed

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

Lines changed: 166 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, useEffect } from "react";
3+
import React, { useState, useEffect, useRef, useContext } from "react";
44
import {
55
useExternalStoreRuntime,
66
ThreadMessageLike,
@@ -19,6 +19,10 @@ import {
1919
import { MessageHandler } from "../types/chatTypes";
2020
import styled from "styled-components";
2121
import { trans } from "i18n";
22+
import { EditorContext, EditorState } from "@lowcoder-ee/comps/editorState";
23+
import { configureComponentAction } from "../../preLoadComp/actions/componentConfiguration";
24+
import { addComponentAction, moveComponentAction, nestComponentAction, resizeComponentAction } from "../../preLoadComp/actions/componentManagement";
25+
import { applyThemeAction, configureAppMetaAction, setCanvasSettingsAction } from "../../preLoadComp/actions/appConfiguration";
2226

2327
// ============================================================================
2428
// STYLED COMPONENTS (same as your current ChatMain)
@@ -78,6 +82,14 @@ export function ChatCoreMain({
7882
}: ChatCoreMainProps) {
7983
const { state, actions } = useChatContext();
8084
const [isRunning, setIsRunning] = useState(false);
85+
const editorState = useContext(EditorContext);
86+
const editorStateRef = useRef(editorState);
87+
88+
// Keep the ref updated with the latest editorState
89+
useEffect(() => {
90+
// console.log("EDITOR STATE CHANGE ---> ", editorState);
91+
editorStateRef.current = editorState;
92+
}, [editorState]);
8193

8294
// Get messages for current thread
8395
const currentMessages = actions.getCurrentMessages();
@@ -92,6 +104,143 @@ export function ChatCoreMain({
92104
onEvent?.("componentLoad");
93105
}, [onEvent]);
94106

107+
const performAction = async (actions: any[]) => {
108+
if (!editorStateRef.current) {
109+
console.error("No editorStateRef found");
110+
return;
111+
}
112+
113+
const comp = editorStateRef.current.getUIComp().children.comp;
114+
if (!comp) {
115+
console.error("No comp found");
116+
return;
117+
}
118+
// const layout = comp.children.layout.getView();
119+
// console.log("LAYOUT", layout);
120+
121+
for (const actionItem of actions) {
122+
const { action, component, ...action_payload } = actionItem;
123+
124+
switch (action) {
125+
case "place_component":
126+
await addComponentAction.execute({
127+
actionKey: action,
128+
actionValue: "",
129+
actionPayload: action_payload,
130+
selectedComponent: component,
131+
selectedEditorComponent: null,
132+
selectedNestComponent: null,
133+
editorState: editorStateRef.current,
134+
selectedDynamicLayoutIndex: null,
135+
selectedTheme: null,
136+
selectedCustomShortcutAction: null
137+
});
138+
break;
139+
case "nest_component":
140+
await nestComponentAction.execute({
141+
actionKey: action,
142+
actionValue: "",
143+
actionPayload: action_payload,
144+
selectedComponent: component,
145+
selectedEditorComponent: null,
146+
selectedNestComponent: null,
147+
editorState: editorStateRef.current,
148+
selectedDynamicLayoutIndex: null,
149+
selectedTheme: null,
150+
selectedCustomShortcutAction: null
151+
});
152+
break;
153+
case "move_component":
154+
await moveComponentAction.execute({
155+
actionKey: action,
156+
actionValue: "",
157+
actionPayload: action_payload,
158+
selectedComponent: component,
159+
selectedEditorComponent: null,
160+
selectedNestComponent: null,
161+
editorState: editorStateRef.current,
162+
selectedDynamicLayoutIndex: null,
163+
selectedTheme: null,
164+
selectedCustomShortcutAction: null
165+
});
166+
break;
167+
case "resize_component":
168+
await resizeComponentAction.execute({
169+
actionKey: action,
170+
actionValue: "",
171+
actionPayload: action_payload,
172+
selectedComponent: component,
173+
selectedEditorComponent: null,
174+
selectedNestComponent: null,
175+
editorState: editorStateRef.current,
176+
selectedDynamicLayoutIndex: null,
177+
selectedTheme: null,
178+
selectedCustomShortcutAction: null
179+
});
180+
break;
181+
case "set_properties":
182+
await configureComponentAction.execute({
183+
actionKey: action,
184+
actionValue: component,
185+
actionPayload: action_payload,
186+
selectedEditorComponent: null,
187+
selectedComponent: null,
188+
selectedNestComponent: null,
189+
editorState: editorStateRef.current,
190+
selectedDynamicLayoutIndex: null,
191+
selectedTheme: null,
192+
selectedCustomShortcutAction: null
193+
});
194+
break;
195+
case "set_theme":
196+
await applyThemeAction.execute({
197+
actionKey: action,
198+
actionValue: component,
199+
actionPayload: action_payload,
200+
selectedEditorComponent: null,
201+
selectedComponent: null,
202+
selectedNestComponent: null,
203+
editorState: editorStateRef.current,
204+
selectedDynamicLayoutIndex: null,
205+
selectedTheme: null,
206+
selectedCustomShortcutAction: null
207+
});
208+
break;
209+
case "set_app_metadata":
210+
await configureAppMetaAction.execute({
211+
actionKey: action,
212+
actionValue: component,
213+
actionPayload: action_payload,
214+
selectedEditorComponent: null,
215+
selectedComponent: null,
216+
selectedNestComponent: null,
217+
editorState: editorStateRef.current,
218+
selectedDynamicLayoutIndex: null,
219+
selectedTheme: null,
220+
selectedCustomShortcutAction: null
221+
});
222+
break;
223+
case "set_canvas_setting":
224+
await setCanvasSettingsAction.execute({
225+
actionKey: action,
226+
actionValue: component,
227+
actionPayload: action_payload,
228+
selectedEditorComponent: null,
229+
selectedComponent: null,
230+
selectedNestComponent: null,
231+
editorState: editorStateRef.current,
232+
selectedDynamicLayoutIndex: null,
233+
selectedTheme: null,
234+
selectedCustomShortcutAction: null
235+
});
236+
break;
237+
default:
238+
break;
239+
}
240+
await new Promise(resolve => setTimeout(resolve, 1000));
241+
}
242+
};
243+
95244
// Convert custom format to ThreadMessageLike (same as your current implementation)
96245
const convertMessage = (message: ChatMessage): ThreadMessageLike => ({
97246
role: message.role,
@@ -123,9 +272,15 @@ export function ChatCoreMain({
123272
setIsRunning(true);
124273

125274
try {
126-
127275
// Use the message handler (no more complex logic here!)
128-
const response = await messageHandler.sendMessage(userMessage.text);
276+
const response = await messageHandler.sendMessage(
277+
userMessage.text,
278+
state.currentThreadId,
279+
);
280+
281+
if (response?.actions?.length) {
282+
performAction(response.actions);
283+
}
129284

130285
const assistantMessage: ChatMessage = {
131286
id: generateId(),
@@ -182,8 +337,15 @@ export function ChatCoreMain({
182337

183338
try {
184339
// Use the message handler (clean!)
185-
const response = await messageHandler.sendMessage(editedMessage.text);
340+
const response = await messageHandler.sendMessage(
341+
editedMessage.text,
342+
state.currentThreadId,
343+
);
186344

345+
if (response?.actions?.length) {
346+
performAction(response.actions);
347+
}
348+
187349
const assistantMessage: ChatMessage = {
188350
id: generateId(),
189351
role: "assistant",

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

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

3-
import React, { useMemo } from "react";
3+
import { useMemo } from "react";
44
import { ChatCore } from "./ChatCore";
55
import { createChatStorage } from "../utils/storageFactory";
66
import { N8NHandler } from "../handlers/messageHandlers";
@@ -21,7 +21,6 @@ export function ChatPanel({
2121
streaming = true,
2222
onMessageUpdate
2323
}: ChatPanelProps) {
24-
2524
// Create storage instance
2625
const storage = useMemo(() =>
2726
createChatStorage(tableName),

client/packages/lowcoder/src/comps/comps/chatComp/handlers/messageHandlers.ts

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// client/packages/lowcoder/src/comps/comps/chatComp/handlers/messageHandlers.ts
22

33
import { MessageHandler, MessageResponse, N8NHandlerConfig, QueryHandlerConfig } from "../types/chatTypes";
4-
import { CompAction, routeByNameAction, executeQueryAction } from "lowcoder-core";
4+
import { routeByNameAction, executeQueryAction } from "lowcoder-core";
55
import { getPromiseAfterDispatch } from "util/promiseUtils";
66

77
// ============================================================================
@@ -11,7 +11,7 @@ import { getPromiseAfterDispatch } from "util/promiseUtils";
1111
export class N8NHandler implements MessageHandler {
1212
constructor(private config: N8NHandlerConfig) {}
1313

14-
async sendMessage(message: string): Promise<MessageResponse> {
14+
async sendMessage(message: string, sessionId?: string): Promise<MessageResponse> {
1515
const { modelHost, systemPrompt, streaming } = this.config;
1616

1717
if (!modelHost) {
@@ -25,6 +25,7 @@ export class N8NHandler implements MessageHandler {
2525
'Content-Type': 'application/json',
2626
},
2727
body: JSON.stringify({
28+
sessionId,
2829
message,
2930
systemPrompt: systemPrompt || "You are a helpful assistant.",
3031
streaming: streaming || false
@@ -36,7 +37,10 @@ export class N8NHandler implements MessageHandler {
3637
}
3738

3839
const data = await response.json();
39-
40+
if (data.output) {
41+
const { explanation, actions } = JSON.parse(data.output);
42+
return { content: explanation, actions };
43+
}
4044
// Extract content from various possible response formats
4145
const content = data.response || data.message || data.content || data.text || String(data);
4246

@@ -54,7 +58,7 @@ export class N8NHandler implements MessageHandler {
5458
export class QueryHandler implements MessageHandler {
5559
constructor(private config: QueryHandlerConfig) {}
5660

57-
async sendMessage(message: string): Promise<MessageResponse> {
61+
async sendMessage(message: string, sessionId?: string): Promise<MessageResponse> {
5862
const { chatQuery, dispatch} = this.config;
5963

6064
// If no query selected or dispatch unavailable, return mock response
@@ -92,7 +96,7 @@ export class QueryHandler implements MessageHandler {
9296
export class MockHandler implements MessageHandler {
9397
constructor(private delay: number = 1000) {}
9498

95-
async sendMessage(message: string): Promise<MessageResponse> {
99+
async sendMessage(message: string, sessionId?: string): Promise<MessageResponse> {
96100
await new Promise(resolve => setTimeout(resolve, this.delay));
97101
return { content: `Mock response: ${message}` };
98102
}

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
// client/packages/lowcoder/src/comps/comps/chatComp/types/chatTypes.ts
22

3+
import { EditorState } from "@lowcoder-ee/comps/editorState";
4+
35
// ============================================================================
46
// CORE MESSAGE AND THREAD TYPES (cleaned up from your existing types)
57
// ============================================================================
@@ -43,13 +45,14 @@ export interface ChatMessage {
4345
// ============================================================================
4446

4547
export interface MessageHandler {
46-
sendMessage(message: string): Promise<MessageResponse>;
48+
sendMessage(message: string, sessionId?: string): Promise<MessageResponse>;
4749
// Future: sendMessageStream?(message: string): AsyncGenerator<MessageResponse>;
4850
}
4951

5052
export interface MessageResponse {
5153
content: string;
5254
metadata?: any;
55+
actions?: any[];
5356
}
5457

5558
// ============================================================================

0 commit comments

Comments
 (0)