Skip to content

Commit 0bc7f5b

Browse files
author
FalkWolsky
committed
Control of Component Properties
1 parent b174385 commit 0bc7f5b

File tree

3 files changed

+163
-38
lines changed

3 files changed

+163
-38
lines changed

client/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "lowcoder-root",
3-
"version": "2.2.0",
3+
"version": "2.3.0",
44
"type": "module",
55
"private": true,
66
"workspaces": [

client/packages/lowcoder/src/pages/editor/LeftLayersContent.tsx

Lines changed: 154 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,21 @@
11
import { CompInfo, EditorContext } from "comps/editorState";
22
import {
33
BaseSection,
4-
Collapse,
54
CollapseLabel as Label,
65
CollapseTitle as Title,
76
FoldedIcon,
87
LeftCommon,
98
ScrollBar,
10-
Tooltip,
119
UnfoldIcon,
12-
LeftLayersIcon,
13-
GridIcon,
1410
LeftShow,
15-
LeftHide,
16-
LeftLock,
17-
LeftUnlock,
1811
} from "lowcoder-design";
19-
import React, { ReactNode, useCallback, useContext, useMemo, useState, useEffect } from "react";
12+
import React, { useCallback, useContext, useMemo, useState, useEffect, useRef } from "react";
2013
import _, { get } from "lodash";
2114
import styled from "styled-components";
2215
import { leftCompListClassName } from "pages/tutorials/tutorialsConstant";
2316
import UIComp from "comps/comps/uiComp";
24-
import { getParentNodeKeysByKey, getTreeNodeByKey, safeJSONStringify } from "util/objectUtils";
25-
import { BackgroundColor, TopHeaderHeight } from "constants/style";
17+
import { getTreeNodeByKey } from "util/objectUtils";
18+
import { TopHeaderHeight } from "constants/style";
2619
import { trans } from "i18n";
2720
import { CompTree } from "comps/comps/containerBase";
2821
import { CompStateIcon } from "./editorConstants";
@@ -32,7 +25,6 @@ import { isAggregationApp } from "util/appUtils";
3225
import cloneDeep from 'lodash/cloneDeep';
3326
import { useDispatch } from "react-redux";
3427
import { useApplicationId } from "util/hooks";
35-
import { updateApplication } from "redux/reduxActions/applicationActions";
3628
import { Button, Divider, Dropdown, Flex, Input, Menu, MenuProps, Space } from "antd";
3729
import { Switch } from "antd";
3830
import {
@@ -42,6 +34,7 @@ import {
4234
import { check, withViewFn } from "@lowcoder-ee/index.sdk";
4335
import { DownOutlined } from "@ant-design/icons";
4436
import { ItemType } from "antd/es/menu/hooks/useItems";
37+
import ColorPicker, { configChangeParams } from "components/ColorPicker";
4538

4639

4740
export type DisabledCollisionStatus = "true" | "false"; // "true" means collision is not enabled - Layering works, "false" means collision is enabled - Layering does not work
@@ -246,10 +239,47 @@ export const LeftLayersContent = (props: LeftLayersContentProps) => {
246239

247240
const [checkedKeys, setCheckedKeys] = useState<string[]>([]);
248241
const [actionValue, setActionValue] = useState<string>("");
242+
const [selectedActionKey, setSelectedActionKey] = useState<string | null>(null);
243+
const [placeholderText, setPlaceholderText] = useState<string>("");
244+
const [color, setColor] = useState<string>("");
249245

250-
const handleActionValueChange = (e: any) => {
246+
const handleColorChange = (color: string | undefined, actionType: string) => {
247+
const newColor = color || '#ffffff';
248+
249+
for (let key of getCheckedKeys()) {
250+
const node = getTreeNodeByKey(componentTreeData, key);
251+
const comp = editorState.getUICompByName(node.title);
252+
if(comp) {
253+
const { children } = comp.children.comp;
254+
const compType = comp.children.compType.getView();
255+
const types = actionType.split('.');
256+
if(types.length === 1) { // e.g hidden, disabled
257+
children[types[0]]?.dispatchChangeValueAction(color);
258+
}
259+
else if(types.length === 2) { // nested object e.g. style.background
260+
console.log(children[types[0]]);
261+
if (!children[types[0]]) {
262+
if (children[compType].children[types[0]]?.children[types[1]]) {
263+
children[compType].children[types[0]].children[types[1]]?.dispatchChangeValueAction(color);
264+
}
265+
}
266+
else {
267+
if (children[types[0]].children[types[1]]) {
268+
children[types[0]].children[types[1]]?.dispatchChangeValueAction(color);
269+
}
270+
else {
271+
children[types[0]][types[1]]?.dispatchChangeValueAction(color);
272+
}
273+
}
274+
}
275+
}
276+
}
277+
};
278+
279+
280+
/* const handleActionValueChange = (e: any) => {
251281
setActionValue(e.target.value);
252-
}
282+
} */
253283

254284
// sync selected components with checked keys
255285
useEffect(() => {
@@ -267,6 +297,12 @@ export const LeftLayersContent = (props: LeftLayersContentProps) => {
267297
setCheckedKeys(selectedComponentsOnCanvas);
268298
}, [editorState]);
269299

300+
// make sure to handle the selectedActionKey for the changed input fields
301+
useEffect(() => {
302+
setActionValue('');
303+
setColor('#ffffff');
304+
}, [selectedActionKey, placeholderText]);
305+
270306
const onCheck = (checkedKeys: any, e: any) => {
271307
setCheckedKeys(checkedKeys);
272308
const checkedComponents = new Set<string>();
@@ -290,29 +326,36 @@ export const LeftLayersContent = (props: LeftLayersContentProps) => {
290326
const node = getTreeNodeByKey(componentTreeData, key);
291327
const comp = editorState.getUICompByName(node.title);
292328
if(comp) {
293-
const { children } = comp.children.comp
329+
const { children } = comp.children.comp;
330+
const compType = comp.children.compType.getView();
294331
const types = actionType.split('.');
295-
296332
if(types.length === 1) { // e.g hidden, disabled
297333
children[types[0]]?.dispatchChangeValueAction(value);
298334
}
299335
else if(types.length === 2) { // nested object e.g. style.background
300-
children[types[0]][types[1]]?.dispatchChangeValueAction(value);
336+
console.log(children[types[0]]);
337+
if (!children[types[0]]) {
338+
if (children[compType].children[types[0]]?.children[types[1]]) {
339+
children[compType].children[types[0]].children[types[1]]?.dispatchChangeValueAction(value);
340+
}
341+
}
342+
else {
343+
if (children[types[0]].children[types[1]]) {
344+
children[types[0]].children[types[1]]?.dispatchChangeValueAction(value);
345+
}
346+
else {
347+
children[types[0]][types[1]]?.dispatchChangeValueAction(value);
348+
}
349+
}
301350
}
302351
}
303352
}
304353
}, [getActionValue, getCheckedKeys]);
305354

306-
/*
307-
308-
dispatch(
309-
multiChangeAction({
310-
width: changeValueAction(width, true),
311-
autoWidth: changeValueAction("fixed", true),
312-
})
313-
);
314-
315-
*/
355+
const handleActionSelection = useCallback((key: string) => {
356+
setSelectedActionKey(key);
357+
setPlaceholderText(getPlaceholderText(key));
358+
}, [handleComponentsActions]);
316359

317360
const layerActions: ItemType[] = [
318361
{
@@ -324,15 +367,63 @@ export const LeftLayersContent = (props: LeftLayersContentProps) => {
324367
key: 'disable',
325368
},
326369
{
327-
label: 'Component Background',
328-
key: 'style.background',
370+
label: 'Margin',
371+
key: 'style.margin',
372+
},
373+
{
374+
label: 'Padding',
375+
key: 'style.padding',
376+
},
377+
{
378+
label: 'Border Radius',
379+
key: 'style.radius',
329380
},
330381
{
331-
label: 'Unlock',
332-
key: '4',
382+
label: 'Border Width',
383+
key: 'style.borderWidth',
333384
},
385+
{
386+
label: 'Font Size',
387+
key: 'style.textSize',
388+
},
389+
{
390+
label: 'Font Weight',
391+
key: 'style.textWeight',
392+
},
393+
{
394+
label: 'Font Family',
395+
key: 'style.fontFamily',
396+
}
334397
];
335398

399+
400+
const getPlaceholderText = (key: string) => {
401+
switch (key) {
402+
case 'hidden':
403+
case 'disable':
404+
return 'true | false';
405+
case 'style.background':
406+
case 'style.text':
407+
case 'style.border':
408+
return 'e.g., #ffffff'; // Indicate example format
409+
case 'style.radius':
410+
return 'e.g., 4px'; // Indicate example format
411+
case 'style.borderWidth':
412+
return 'e.g., 2px'; // Indicate example format
413+
case 'style.textSize':
414+
return 'e.g., 16px'; // Indicate example format
415+
case 'style.textWeight':
416+
return 'bold | 900';
417+
case 'style.fontFamily':
418+
return 'Arial, sans-serif';
419+
case 'style.margin':
420+
case 'style.padding':
421+
return 'e.g., 4px 8px 16px 32px'; // Indicate example format
422+
default:
423+
return 'Action Value';
424+
}
425+
};
426+
336427
const getTreeUI = () => {
337428
// here the components get sorted by name
338429
// TODO: sort by category
@@ -367,7 +458,7 @@ export const LeftLayersContent = (props: LeftLayersContentProps) => {
367458
onDrop={(info) => handleDrop(info)}
368459
treeData={componentTreeData}
369460
icon={(props: any) => props.type && (
370-
<div style={{ margin: '3px 0 0 -3px'}}> {/* Adjust the margin as needed */}
461+
<div style={{ margin: '3px 4px 0 -4px'}}> {/* Adjust the margin as needed */}
371462
{CompStateIcon[props.type as UICompType] || <LeftCommon />}
372463
</div>
373464
)}
@@ -379,14 +470,11 @@ export const LeftLayersContent = (props: LeftLayersContentProps) => {
379470

380471
<div style={{margin:"10px 0px"}}>
381472
<Flex gap="small" vertical>
382-
{trans("leftPanel.selectedComponents")}<br/>
383-
{trans("leftPanel.displayComponents")}
384-
<Input placeholder="Action Value" onChange={handleActionValueChange}/>
385473
<CustomDropdown
386474
dropdownRender={() => (
387475
<Menu
388476
items={layerActions}
389-
onClick={({key}) => handleComponentsActions(key)}
477+
onClick={({key}) => handleActionSelection(key)}
390478
/>
391479
)}
392480
>
@@ -397,6 +485,37 @@ export const LeftLayersContent = (props: LeftLayersContentProps) => {
397485
</Space>
398486
</Button>
399487
</CustomDropdown>
488+
<Input
489+
value={actionValue} // Use actionValue for the default case as well
490+
onChange={(e) => setActionValue(e.target.value)} // Handle changes to update actionValue
491+
placeholder={placeholderText}
492+
/>
493+
<Button
494+
type="primary"
495+
disabled={!selectedActionKey}
496+
onClick={() => selectedActionKey && handleComponentsActions(selectedActionKey)}
497+
>
498+
Apply Action
499+
</Button>
500+
<br/>
501+
<ColorPicker
502+
colorKey={"background"}
503+
name={trans("componentDoc.styleBackgroundColor")}
504+
color={"#ffffff"}
505+
configChange={(params) => handleColorChange(params.color, "style.background")}
506+
/>
507+
<ColorPicker
508+
colorKey={"border"}
509+
name={trans("componentDoc.styleBorderColor")}
510+
color={"#ffffff"}
511+
configChange={(params) => handleColorChange(params.color, "style.border")}
512+
/>
513+
<ColorPicker
514+
colorKey={"text"}
515+
name={trans("style.textColor")}
516+
color={"#ffffff"}
517+
configChange={(params) => handleColorChange(params.color, "style.text")}
518+
/>
400519
</Flex>
401520
</div>
402521
</div>

client/packages/lowcoder/src/pages/editor/styledComponents.tsx

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,17 @@ export const DirectoryTreeStyle = styled(DirectoryTree)`
2525
position: unset;
2626
.ant-tree-iconEle {
2727
width: 16px;
28-
height: 26px;
29-
margin-right: 4px;
28+
height: 16px;
29+
margin: 0px 0px 0px 4px;
3030
display: flex;
3131
align-items: center;
32+
svg {
33+
width: 16px;
34+
height: 16px;
35+
stroke: #000;
36+
}
3237
}
38+
3339
}
3440
.ant-tree-checkbox+span {
3541
padding-left: 0;

0 commit comments

Comments
 (0)