Skip to content

Commit 2014590

Browse files
Merge pull request #1853 from kamalqureshi/actions_js_console
Actions JS Console
2 parents 6d5fbfd + a380978 commit 2014590

File tree

11 files changed

+1328
-91
lines changed

11 files changed

+1328
-91
lines changed

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

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,20 @@ import {
55
renameComponentAction,
66
deleteComponentAction,
77
resizeComponentAction,
8-
configureComponentAction,
9-
changeLayoutAction,
8+
configureAppMetaAction,
109
addEventHandlerAction,
1110
applyStyleAction,
12-
nestComponentAction
11+
nestComponentAction,
12+
updateDynamicLayoutAction,
13+
publishAppAction,
14+
shareAppAction,
15+
testAllDatasourcesAction,
16+
applyGlobalJSAction,
17+
applyCSSAction,
18+
applyThemeAction,
19+
setCanvasSettingsAction,
20+
setCustomShortcutsAction,
21+
alignComponentAction
1322
} from "./actions";
1423

1524
export const actionCategories: ActionCategory[] = [
@@ -26,14 +35,24 @@ export const actionCategories: ActionCategory[] = [
2635
]
2736
},
2837
{
29-
key: 'component-configuration',
30-
label: 'Component Configuration',
31-
actions: [configureComponentAction]
38+
key: 'app-configuration',
39+
label: 'App Configuration',
40+
actions: [
41+
configureAppMetaAction,
42+
publishAppAction,
43+
shareAppAction,
44+
testAllDatasourcesAction,
45+
applyGlobalJSAction,
46+
applyCSSAction,
47+
applyThemeAction,
48+
setCanvasSettingsAction,
49+
setCustomShortcutsAction
50+
]
3251
},
3352
{
3453
key: 'layout',
3554
label: 'Layout',
36-
actions: [changeLayoutAction]
55+
actions: [updateDynamicLayoutAction, alignComponentAction]
3756
},
3857
{
3958
key: 'events',

client/packages/lowcoder/src/comps/comps/preLoadComp/actionInputSection.tsx

Lines changed: 192 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,21 @@ import { default as Space } from "antd/es/space";
1212
import { default as Flex } from "antd/es/flex";
1313
import type { InputRef } from 'antd';
1414
import { default as DownOutlined } from "@ant-design/icons/DownOutlined";
15-
import { BaseSection } from "lowcoder-design";
15+
import { BaseSection, Dropdown } from "lowcoder-design";
1616
import { EditorContext } from "comps/editorState";
1717
import { message } from "antd";
1818
import { CustomDropdown } from "./styled";
19-
import { generateComponentActionItems, getComponentCategories } from "./utils";
19+
import {
20+
generateComponentActionItems,
21+
getComponentCategories,
22+
getEditorComponentInfo,
23+
getLayoutItemsOrder
24+
} from "./utils";
2025
import { actionRegistry, getAllActionItems } from "./actionConfigs";
26+
import { getThemeList } from "@lowcoder-ee/redux/selectors/commonSettingSelectors";
27+
import { useSelector } from "react-redux";
28+
import { ActionOptions } from "comps/controls/actionSelector/actionSelectorControl";
29+
import { eventToShortcut, readableShortcut } from "util/keyUtils";
2130

2231
export function ActionInputSection() {
2332
const [actionValue, setActionValue] = useState<string>("");
@@ -31,8 +40,22 @@ export function ActionInputSection() {
3140
const [showStylingInput, setShowStylingInput] = useState<boolean>(false);
3241
const [selectedEditorComponent, setSelectedEditorComponent] = useState<string | null>(null);
3342
const [validationError, setValidationError] = useState<string | null>(null);
43+
const [showDynamicLayoutDropdown, setShowDynamicLayoutDropdown] = useState<boolean>(false);
44+
const [selectedDynamicLayoutIndex, setSelectedDynamicLayoutIndex] = useState<string | null>(null);
45+
const [showThemeDropdown, setShowThemeDropdown] = useState<boolean>(false);
46+
const [selectedTheme, setSelectedTheme] = useState<string | null>(null);
47+
const [showCustomShortcutsActionDropdown, setShowCustomShortcutsActionDropdown] = useState<boolean>(false);
48+
const [selectedCustomShortcutAction, setSelectedCustomShortcutAction] = useState<string | null>(null);
3449
const inputRef = useRef<InputRef>(null);
3550
const editorState = useContext(EditorContext);
51+
const themeList = useSelector(getThemeList) || [];
52+
53+
const THEME_OPTIONS = useMemo(() => {
54+
return themeList.map((theme) => ({
55+
label: theme.name,
56+
value: theme.id + "",
57+
}));
58+
}, [themeList]);
3659

3760
const categories = useMemo(() => {
3861
return getComponentCategories();
@@ -56,6 +79,25 @@ export function ActionInputSection() {
5679
}));
5780
}, [editorState]);
5881

82+
const simpleLayoutItems = useMemo(() => {
83+
if(!editorComponents) return [];
84+
85+
const editorComponentInfo = getEditorComponentInfo(editorState);
86+
if(!editorComponentInfo) return [];
87+
88+
const currentLayout = editorComponentInfo.currentLayout;
89+
const items = editorComponentInfo.items;
90+
91+
return Object.keys(currentLayout).map((key) => {
92+
const item = items ? items[key] : null;
93+
const componentName = item ? (item as any).children.name.getView() : key;
94+
return {
95+
label: componentName,
96+
key: componentName
97+
};
98+
});
99+
}, [editorState]);
100+
59101
const currentAction = useMemo(() => {
60102
return selectedActionKey ? actionRegistry.get(selectedActionKey) : null;
61103
}, [selectedActionKey]);
@@ -81,8 +123,14 @@ export function ActionInputSection() {
81123
setSelectedEditorComponent(null);
82124
setIsNestedComponent(false);
83125
setSelectedNestComponent(null);
126+
setShowDynamicLayoutDropdown(false);
84127
setActionValue("");
85-
128+
setSelectedDynamicLayoutIndex(null);
129+
setShowThemeDropdown(false);
130+
setSelectedTheme(null);
131+
setShowCustomShortcutsActionDropdown(false);
132+
setSelectedCustomShortcutAction(null);
133+
86134
if (action.requiresComponentSelection) {
87135
setShowComponentDropdown(true);
88136
setPlaceholderText("Select a component to add");
@@ -103,6 +151,15 @@ export function ActionInputSection() {
103151
if (action.isNested) {
104152
setIsNestedComponent(true);
105153
}
154+
if(action.dynamicLayout) {
155+
setShowDynamicLayoutDropdown(true);
156+
}
157+
if(action.isTheme) {
158+
setShowThemeDropdown(true);
159+
}
160+
if(action.isCustomShortcuts) {
161+
setShowCustomShortcutsActionDropdown(true);
162+
}
106163
}, []);
107164

108165
const handleComponentSelection = useCallback((key: string) => {
@@ -168,13 +225,26 @@ export function ActionInputSection() {
168225
return;
169226
}
170227

228+
if(currentAction.isTheme && !selectedTheme) {
229+
message.error('Please select a theme');
230+
return;
231+
}
232+
233+
if(currentAction.isCustomShortcuts && !selectedCustomShortcutAction) {
234+
message.error('Please select a custom shortcut action');
235+
return;
236+
}
237+
171238
try {
172239
await currentAction.execute({
173240
actionKey: selectedActionKey,
174241
actionValue,
175242
selectedComponent,
176243
selectedEditorComponent,
177244
selectedNestComponent,
245+
selectedDynamicLayoutIndex,
246+
selectedTheme,
247+
selectedCustomShortcutAction,
178248
editorState
179249
});
180250

@@ -189,7 +259,12 @@ export function ActionInputSection() {
189259
setValidationError(null);
190260
setIsNestedComponent(false);
191261
setSelectedNestComponent(null);
192-
262+
setShowDynamicLayoutDropdown(false);
263+
setSelectedDynamicLayoutIndex(null);
264+
setShowThemeDropdown(false);
265+
setSelectedTheme(null);
266+
setShowCustomShortcutsActionDropdown(false);
267+
setSelectedCustomShortcutAction(null);
193268
} catch (error) {
194269
console.error('Error executing action:', error);
195270
message.error('Failed to execute action. Please try again.');
@@ -200,6 +275,9 @@ export function ActionInputSection() {
200275
selectedComponent,
201276
selectedEditorComponent,
202277
selectedNestComponent,
278+
selectedDynamicLayoutIndex,
279+
selectedTheme,
280+
selectedCustomShortcutAction,
203281
editorState,
204282
currentAction,
205283
validateInput
@@ -213,7 +291,16 @@ export function ActionInputSection() {
213291
if (currentAction.requiresInput && !actionValue.trim()) return true;
214292

215293
return false;
216-
}, [selectedActionKey, currentAction, selectedComponent, selectedEditorComponent, actionValue]);
294+
}, [
295+
selectedActionKey,
296+
currentAction,
297+
selectedComponent,
298+
selectedEditorComponent,
299+
actionValue,
300+
selectedCustomShortcutAction,
301+
selectedTheme,
302+
selectedNestComponent
303+
]);
217304

218305
const shouldShowInput = useMemo(() => {
219306
if (!currentAction) return false;
@@ -299,7 +386,7 @@ export function ActionInputSection() {
299386
popupRender={() => (
300387
<Menu
301388
items={editorComponents}
302-
onClick={({ key }) => {
389+
onClick={({key}) => {
303390
handleEditorComponentSelection(key);
304391
}}
305392
/>
@@ -314,24 +401,111 @@ export function ActionInputSection() {
314401
</CustomDropdown>
315402
)}
316403

317-
{shouldShowInput && (
318-
showStylingInput ? (
319-
<Input.TextArea
320-
ref={inputRef}
321-
value={actionValue}
322-
onChange={handleInputChange}
323-
placeholder={placeholderText}
324-
status={validationError ? 'error' : undefined}
325-
autoSize={{ minRows: 1 }}
404+
{showDynamicLayoutDropdown && (
405+
<CustomDropdown
406+
overlayStyle={{
407+
maxHeight: '400px',
408+
overflow: 'auto',
409+
zIndex: 9999
410+
}}
411+
popupRender={() => (
412+
<Menu
413+
items={simpleLayoutItems}
414+
onClick={({key}) => {
415+
handleEditorComponentSelection(key);
416+
}}
326417
/>
327-
) : (
418+
)}
419+
>
420+
<Button size={"small"}>
421+
<Space>
422+
{selectedEditorComponent ? selectedEditorComponent : 'Layout'}
423+
<DownOutlined />
424+
</Space>
425+
</Button>
426+
</CustomDropdown>
427+
)}
428+
429+
{showDynamicLayoutDropdown && (
430+
<Dropdown
431+
options={getLayoutItemsOrder(simpleLayoutItems)}
432+
onChange={(value) => {
433+
setSelectedDynamicLayoutIndex(value);
434+
}}
435+
>
436+
<Button size={"small"}>
437+
<Space>
438+
{selectedEditorComponent ? selectedEditorComponent : 'Layout'}
439+
<DownOutlined />
440+
</Space>
441+
</Button>
442+
</Dropdown>
443+
)}
444+
445+
{showThemeDropdown && (
446+
<Dropdown
447+
options={THEME_OPTIONS}
448+
onChange={(value) => {
449+
setSelectedTheme(value);
450+
}}
451+
>
452+
<Button size={"small"}>
453+
<Space>
454+
{selectedTheme ? selectedTheme : 'Select Theme'}
455+
</Space>
456+
</Button>
457+
</Dropdown>
458+
)}
459+
460+
{showCustomShortcutsActionDropdown && (
461+
<Dropdown
462+
options={ActionOptions}
463+
onChange={(value) => {
464+
setSelectedCustomShortcutAction(value);
465+
}}
466+
>
467+
<Button size={"small"}>
468+
<Space>
469+
{selectedCustomShortcutAction ? selectedCustomShortcutAction : 'Select Action'}
470+
</Space>
471+
</Button>
472+
</Dropdown>
473+
)}
474+
475+
{shouldShowInput && (
476+
currentAction?.isCustomShortcuts ? (
328477
<Input
329478
ref={inputRef}
330-
value={actionValue}
331-
onChange={handleInputChange}
479+
value={readableShortcut(actionValue)}
332480
placeholder={placeholderText}
333481
status={validationError ? 'error' : undefined}
482+
onKeyDownCapture={(e) => {
483+
setActionValue(eventToShortcut(e));
484+
e.preventDefault();
485+
e.stopPropagation();
486+
}}
487+
onChange={() => {}}
488+
readOnly
334489
/>
490+
) : (
491+
showStylingInput ? (
492+
<Input.TextArea
493+
ref={inputRef}
494+
value={actionValue}
495+
onChange={handleInputChange}
496+
placeholder={placeholderText}
497+
status={validationError ? 'error' : undefined}
498+
autoSize={{ minRows: 1 }}
499+
/>
500+
) : (
501+
<Input
502+
ref={inputRef}
503+
value={actionValue}
504+
onChange={handleInputChange}
505+
placeholder={placeholderText}
506+
status={validationError ? 'error' : undefined}
507+
/>
508+
)
335509
)
336510
)}
337511

0 commit comments

Comments
 (0)