Skip to content

Commit 79b5e83

Browse files
kamalqureshiraheeliftikhar5
authored andcommitted
Event handlers for all components.
1 parent 86a12f0 commit 79b5e83

File tree

2 files changed

+170
-8
lines changed

2 files changed

+170
-8
lines changed

client/packages/lowcoder/src/comps/comps/preLoadComp/actionConfigs.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ export const actionCategories: ActionCategory[] = [
3434
{
3535
key: 'layout',
3636
label: 'Layout',
37-
actions: [changeLayoutAction, updateDynamicLayoutAction]
37+
actions: [updateDynamicLayoutAction]
3838
},
3939
{
4040
key: 'events',
Lines changed: 169 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,182 @@
1+
/**
2+
* Event Names:
3+
* - click: Triggered when component is clicked
4+
* - change: Triggered when component value changes
5+
* - focus: Triggered when component gains focus
6+
* - blur: Triggered when component loses focus
7+
* - submit: Triggered when form is submitted
8+
* - refresh: Triggered when component is refreshed
9+
*
10+
* Action Types:
11+
* - executeQuery: Run a data query
12+
* - message: Show a notification message
13+
* - setTempState: Set a temporary state value
14+
* - runScript: Execute JavaScript code
15+
* - executeComp: Control another component
16+
* - goToURL: Navigate to a URL
17+
* - copyToClipboard: Copy data to clipboard
18+
* - download: Download data as file
19+
* - triggerModuleEvent: Trigger a module event
20+
* - openAppPage: Navigate to another app page
21+
*/
22+
123
import { message } from "antd";
224
import { ActionConfig, ActionExecuteParams } from "../types";
25+
import { getEditorComponentInfo } from "../utils";
26+
import { pushAction } from "comps/generators/list";
327

428
export const addEventHandlerAction: ActionConfig = {
529
key: 'add-event-handler',
630
label: 'Add event handler',
731
category: 'events',
832
requiresEditorComponentSelection: true,
933
requiresInput: true,
10-
inputPlaceholder: 'Enter event handler code (JavaScript)',
11-
inputType: 'textarea',
34+
inputPlaceholder: 'Format: eventName: actionType (e.g., "click: message", "change: executeQuery", "focus: setTempState")',
35+
inputType: 'text',
36+
validation: (value: string) => {
37+
const [eventName, actionType] = value.split(':').map(s => s.trim());
38+
if (!eventName || !actionType) {
39+
return 'Please provide both event name and action type separated by colon (e.g., "click: message")';
40+
}
41+
42+
const validActionTypes = [
43+
'executeQuery', 'message', 'setTempState', 'runScript',
44+
'executeComp', 'goToURL', 'copyToClipboard', 'download',
45+
'triggerModuleEvent', 'openAppPage'
46+
];
47+
48+
if (!validActionTypes.includes(actionType)) {
49+
return `Invalid action type. Valid types: ${validActionTypes.join(', ')}`;
50+
}
51+
52+
return null;
53+
},
1254
execute: async (params: ActionExecuteParams) => {
13-
const { selectedEditorComponent, actionValue } = params;
55+
const { selectedEditorComponent, actionValue, editorState } = params;
56+
57+
const componentInfo = getEditorComponentInfo(editorState, selectedEditorComponent as string);
58+
59+
if (!componentInfo) {
60+
message.error(`Component "${selectedEditorComponent}" not found`);
61+
return;
62+
}
63+
64+
const { allAppComponents } = componentInfo;
65+
const targetComponent = allAppComponents.find(comp => comp.name === selectedEditorComponent);
66+
67+
if (!targetComponent?.comp?.children?.onEvent) {
68+
message.error(`Component "${selectedEditorComponent}" does not support event handlers`);
69+
return;
70+
}
71+
72+
// ----- To be Removed after n8n integration ------ //
73+
const [eventName, actionType] = actionValue.split(':').map(s => s.trim());
74+
75+
if (!eventName || !actionType) {
76+
message.error('Please provide event name and action type in format: "eventName: actionType"');
77+
return;
78+
}
79+
const eventConfigs = targetComponent.comp.children.onEvent.getEventNames?.() || [];
80+
const availableEvents = eventConfigs.map((config: any) => config.value);
81+
82+
if (!availableEvents.includes(eventName)) {
83+
const availableEventsList = availableEvents.length > 0 ? availableEvents.join(', ') : 'none';
84+
message.error(`Event "${eventName}" is not available for this component. Available events: ${availableEventsList}`);
85+
return;
86+
}
87+
// ----- To be Removed after n8n integration ------ //
88+
89+
90+
const eventHandler = {
91+
name: eventName,
92+
handler: {
93+
compType: actionType,
94+
comp: getActionConfig(actionType, editorState)
95+
}
96+
};
97+
98+
try {
99+
targetComponent.comp.children.onEvent.dispatch(pushAction(eventHandler));
100+
message.success(`Event handler for "${eventName}" with action "${actionType}" added successfully!`);
101+
} catch (error) {
102+
console.error('Error adding event handler:', error);
103+
message.error('Failed to add event handler. Please try again.');
104+
}
105+
}
106+
};
107+
108+
// A Hardcoded function to get action configuration based on action type
109+
// This will be removed after n8n integration
110+
function getActionConfig(actionType: string, editorState: any) {
111+
switch (actionType) {
112+
case 'executeQuery':
113+
const queryVariables = editorState
114+
?.selectedOrFirstQueryComp()
115+
?.children.variables.toJsonValue();
116+
117+
return {
118+
queryName: editorState
119+
?.selectedOrFirstQueryComp()
120+
?.children.name.getView(),
121+
queryVariables: queryVariables?.map((variable: any) => ({...variable, value: ''})),
122+
};
123+
124+
case 'message':
125+
return {
126+
text: "Event triggered!",
127+
level: "info",
128+
duration: 3000
129+
};
130+
131+
case 'setTempState':
132+
return {
133+
state: "tempState",
134+
value: "{{eventData}}"
135+
};
136+
137+
case 'runScript':
138+
return {
139+
script: "console.log('Event triggered:', eventData);"
140+
};
141+
142+
case 'executeComp':
143+
return {
144+
compName: "",
145+
methodName: "",
146+
params: []
147+
};
148+
149+
case 'goToURL':
150+
return {
151+
url: "https://example.com",
152+
openInNewTab: false
153+
};
154+
155+
case 'copyToClipboard':
156+
return {
157+
value: "{{eventData}}"
158+
};
159+
160+
case 'download':
161+
return {
162+
data: "{{eventData}}",
163+
fileName: "download.txt",
164+
fileType: "text/plain"
165+
};
166+
167+
case 'triggerModuleEvent':
168+
return {
169+
name: "moduleEvent"
170+
};
14171

15-
console.log('Adding event handler to component:', selectedEditorComponent, 'with code:', actionValue);
16-
message.info(`Event handler added to component "${selectedEditorComponent}"`);
172+
case 'openAppPage':
173+
return {
174+
appId: "",
175+
queryParams: [],
176+
hashParams: []
177+
};
17178

18-
// TODO: Implement actual event handler logic
179+
default:
180+
return {};
19181
}
20-
};
182+
}

0 commit comments

Comments
 (0)