Skip to content

[Feat] Layer Feature & Bulk Property Settings #681

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 12 commits into from
Feb 15, 2024
Prev Previous commit
Next Next commit
Sortable Display of Components
  • Loading branch information
FalkWolsky committed Jan 25, 2024
commit 875bdfdc71bad0fff4706aebfea77a3542f61090
2 changes: 1 addition & 1 deletion client/packages/lowcoder-core/lib/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -454,7 +454,7 @@ declare enum CompActionTypes {
* broadcast other actions in comp tree structure.
* used for encapsulate MultiBaseComp
*/
BROADCAST = "BROADCAST"
BROADCAST = "BROADCAST",
}
type ExtraActionType = "layout" | "delete" | "add" | "modify" | "rename" | "recover" | "upgrade";
type ActionExtraInfo = {
Expand Down
20 changes: 11 additions & 9 deletions client/packages/lowcoder/src/comps/editorState.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import { NameAndExposingInfo } from "./utils/exposingTypes";
import { checkName } from "./utils/rename";
import { trans } from "i18n";
import { UiLayoutType } from "./comps/uiComp";
import { getCollissionStatus, getEditorModeStatus } from "util/localStorageUtil";
import { getCollisionStatus, getEditorModeStatus } from "util/localStorageUtil";

type RootComp = InstanceType<typeof RootCompTmp>;

Expand Down Expand Up @@ -47,7 +47,7 @@ export class EditorState {
readonly showPropertyPane: boolean = false;
readonly selectedCompNames: Set<string> = new Set();
readonly editorModeStatus: string = "";
readonly collissionStatus: string = "";
readonly collisionStatus: string = "";
readonly isDragging: boolean = false;
readonly draggingCompType: string = "button";
readonly forceShowGrid: boolean = false; // show grid lines
Expand All @@ -65,12 +65,12 @@ export class EditorState {
rootComp: RootComp,
setEditorState: (fn: (editorState: EditorState) => EditorState) => void,
initialEditorModeStatus: string = getEditorModeStatus(),
initialCollissionStatus: string = getCollissionStatus()
initialCollisionStatus: string = getCollisionStatus()
) {
this.rootComp = rootComp;
this.setEditorState = setEditorState;
this.editorModeStatus = initialEditorModeStatus;
this.collissionStatus = initialCollissionStatus;
this.collisionStatus = initialCollisionStatus;
}

/**
Expand Down Expand Up @@ -134,12 +134,13 @@ export class EditorState {

uiCompInfoList(): Array<CompInfo> {
const compMap = this.getAllUICompMap();
return Object.values(compMap).map((item) => {
return Object.entries(compMap).map(([key, item]) => {
return {
name: item.children.name.getView(),
type: item.children.compType.getView(),
data: item.children.comp.exposingValues,
dataDesc: item.children.comp.exposingInfo().propertyDesc,
key: key,
};
});
}
Expand Down Expand Up @@ -355,8 +356,8 @@ export class EditorState {
this.changeState({ editorModeStatus: newEditorModeStatus });
}

setCollissionStatus(newCollissionStatus: string) {
this.changeState({ collissionStatus: newCollissionStatus });
setCollisionStatus(newCollisionStatus: string) {
this.changeState({ collisionStatus: newCollisionStatus });
}

setDragging(dragging: boolean) {
Expand Down Expand Up @@ -512,9 +513,10 @@ export class EditorState {
getAppType(): UiLayoutType {
return this.getUIComp().children.compType.getView();
}
getCollissionStatus(): string {
return this.collissionStatus;
getCollisionStatus(): string {
return this.collisionStatus;
}

}
export const EditorContext = React.createContext<EditorState>(undefined as any);

Expand Down
11 changes: 9 additions & 2 deletions client/packages/lowcoder/src/layout/utils.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import { UICompType } from "comps/uiCompRegistry";
import _ from "lodash";
import React, { ReactElement, SyntheticEvent } from "react";
import React, { ReactElement, SyntheticEvent, useContext } from "react";
import { DraggableEvent } from "react-draggable";
import { PositionParams } from "./calculateUtils";
import { draggingUtils } from "./draggingUtils";
import { GridLayoutProps, ResizeHandleAxis } from "./gridLayoutPropTypes";

import { getCollisionStatus } from "util/localStorageUtil";

export type LayoutItem = {
w: number;
h: number;
Expand Down Expand Up @@ -169,7 +171,12 @@ export function collides(l1: LayoutItem, l2: LayoutItem): boolean {
if (l1.y + l1.h <= l2.y) return false; // l1 is above l2
if (l1.y >= l2.y + l2.h) return false; // l1 is below l2

return true; // boxes overlap
if (getCollisionStatus() === "true") {
return false;
}
else {
return true; // boxes overlap
}
}

/**
Expand Down
30 changes: 0 additions & 30 deletions client/packages/lowcoder/src/pages/common/header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import {
preview,
} from "constants/routesURL";
import { User } from "constants/userConstants";
import { Switch } from "antd";
import {
CommonTextLabel,
CustomModal,
Expand Down Expand Up @@ -54,7 +53,6 @@ import { AppPermissionDialog } from "../../components/PermissionDialog/AppPermis
import { getBrandingConfig } from "../../redux/selectors/configSelectors";
import { messageInstance } from "lowcoder-design";
import { EditorContext } from "../../comps/editorState";
import { SwitchChangeEventHandler } from "antd/es/switch";

const StyledLink = styled.a`
display: flex;
Expand Down Expand Up @@ -293,28 +291,18 @@ export type ToggleEditorModeStatus = (
editorModeStatus?: EditorModeStatus
) => void;

/*
// export type EnabledCollissionStatus = "true" | "false";
export type ToggleCollissionStatus = (
collissionStatus?: EnabledCollissionStatus
) => void;
*/

type HeaderProps = {
panelStatus: PanelStatus;
togglePanel: TogglePanel;
editorModeStatus: EditorModeStatus;
toggleEditorModeStatus: ToggleEditorModeStatus;
// collissionStatus: EnabledCollissionStatus;
// toggleCollissionStatus: ToggleCollissionStatus;
};

// header in editor page
export default function Header(props: HeaderProps) {
const editorState = useContext(EditorContext);
const { togglePanel } = props;
const { toggleEditorModeStatus } = props;
// const { toggleCollissionStatus } = props;
const { left, bottom, right } = props.panelStatus;
const user = useSelector(getUser);
const application = useSelector(currentApplication);
Expand Down Expand Up @@ -347,24 +335,6 @@ export default function Header(props: HeaderProps) {
},
];

// const collissionOptions = [
// {
// label: trans("header.editorMode_layout"),
// key: "editorModeSelector_layout",
// value: "tru",
// },
// {
// label: trans("header.editorMode_logic"),
// key: "editorModeSelector_logic",
// value: "logic",
// },
// {
// label: trans("header.editorMode_both"),
// key: "editorModeSelector_both",
// value: "both",
// },
// ];

const onEditorStateValueChange = ({
target: { value },
}: RadioChangeEvent) => {
Expand Down
107 changes: 92 additions & 15 deletions client/packages/lowcoder/src/pages/editor/LeftContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import {
UnfoldIcon,
UnShow,
} from "lowcoder-design";
import React, { ReactNode, useCallback, useContext, useMemo, useState } from "react";
import React, { ReactNode, useCallback, useContext, useMemo, useState, useEffect } from "react";
import { hookCompCategory } from "comps/hooks/hookCompTypes";
import _ from "lodash";
import styled from "styled-components";
Expand All @@ -32,6 +32,7 @@ import { UICompType } from "comps/uiCompRegistry";
import { CollapseWrapper, DirectoryTreeStyle, Node } from "./styledComponents";
import { DataNode, EventDataNode } from "antd/lib/tree";
import { isAggregationApp } from "util/appUtils";
import cloneDeep from 'lodash/cloneDeep';

const CollapseTitleWrapper = styled.div`
display: flex;
Expand Down Expand Up @@ -408,17 +409,94 @@ export const LeftContent = (props: LeftContentProps) => {
);
};

const getTreeUI = (type: TreeUIKey) => {
const uiCompInfos = _.sortBy(editorState.uiCompInfoList(), [(x) => x.name]);
const [componentTreeData, setComponentTreeData] = useState<NodeItem[]>([]);
const [modalsTreeData, setModalsTreeData] = useState<NodeItem[]>([]);

useEffect(() => {
const compData = getTreeUIData(TreeUIKey.Components);
setComponentTreeData(compData);
}, [editorState]);

useEffect(() => {
const modalsData = getTreeUIData(TreeUIKey.Modals);
setModalsTreeData(modalsData);
}, [editorState]);

const getTreeUIData = (type: TreeUIKey) => {
const tree =
type === TreeUIKey.Components
? editorState.getUIComp().getTree()
: editorState.getHooksComp().getUITree();
const explorerData: NodeItem[] = getTree(tree, []);
return explorerData;
}

interface DropInfo {
node: { key: string; pos: string };
dragNode: { key: string; pos: string };
}

const handleDragEnter = (info: { node?: any; expandedKeys?: any; }) => {
// Assuming 'info' has a property 'expandedKeys' which is an array of keys
const { expandedKeys } = info;
if (!expandedKeys.includes(info.node.key)) {
setExpandedKeys(expandedKeys);
}
};

const handleDrop = (info: { node: { key: any; pos: string; }; dragNode: { key: any; pos: string; }; }, type: TreeUIKey) => {
const dropPos = info.node.pos.split('-');
const dragPos = info.dragNode.pos.split('-');

if (dropPos.length === dragPos.length) {
setComponentTreeData(prevData => {
let newTreeData = cloneDeep(prevData);
const dropIndex = Number(dropPos[dropPos.length - 1]);
const dragIndex = Number(dragPos[dragPos.length - 1]);
const parentNodePos = dropPos.slice(0, -1).join('-');

// TODO: handle drag and drop for childen of root (container components for example)
// findNodeByPos does not work yet
const parentNode = parentNodePos === "0" ? { children: newTreeData } : findNodeByPos(newTreeData, parentNodePos);

console.log('parentNode', parentNode);

if (parentNode && parentNode.children) {
const draggedNodeIndex = parentNode.children.findIndex(node => node.key === info.dragNode.key);
if (draggedNodeIndex !== -1) {
const [draggedNode] = parentNode.children.splice(draggedNodeIndex, 1);
parentNode.children.splice(dropIndex > dragIndex ? dropIndex - 1 : dropIndex, 0, draggedNode);
}
}

return newTreeData;
});
}
};

const findNodeByPos = (nodes: NodeItem[], pos: string): { children: NodeItem[] } => {
const posArr = pos.split('-').map(p => Number(p));
let currentNode = { children: nodes };
for (let i = 0; i < posArr.length; i++) {
currentNode = currentNode.children[posArr[i]];
}
return currentNode;
};

const getTreeUI = (type: TreeUIKey) => {
// here the components get sorted by name
// TODO: sort by category
// TODO: sort by Types etc.
const uiCompInfos = _.sortBy(editorState.uiCompInfoList(), [(x) => x.name]);
/* const tree =
type === TreeUIKey.Components
? editorState.getUIComp().getTree()
: editorState.getHooksComp().getUITree();
const explorerData: NodeItem[] = getTree(tree, []); */
let selectedKeys = [];
if (editorState.selectedCompNames.size === 1) {
const key = Object.keys(editorState.selectedComps())[0];
const parentKeys = getParentNodeKeysByKey(explorerData, key);
const parentKeys = getParentNodeKeysByKey(type === TreeUIKey.Components ? componentTreeData : modalsTreeData, key);
if (parentKeys && parentKeys.length) {
let needSet = false;
parentKeys.forEach((key) => {
Expand All @@ -433,12 +511,11 @@ export const LeftContent = (props: LeftContentProps) => {

return (
<DirectoryTreeStyle
treeData={explorerData}
// icon={(props: NodeItem) => props.type && (CompStateIcon[props.type] || <LeftCommon />)}
draggable={type === TreeUIKey.Components ? true : false}
onDragEnter={handleDragEnter}
onDrop={(info) => handleDrop(info, type)}
treeData={type === TreeUIKey.Components ? componentTreeData : modalsTreeData}
icon={(props: any) => props.type && (CompStateIcon[props.type as UICompType] || <LeftCommon />)}
// switcherIcon={({ expanded }: { expanded: boolean }) =>
// expanded ? <FoldedIcon /> : <UnfoldIcon />
// }
switcherIcon={(props: any) =>
props.expanded ? <FoldedIcon /> : <UnfoldIcon />
}
Expand All @@ -455,15 +532,15 @@ export const LeftContent = (props: LeftContentProps) => {
if (isAggregationApp(editorState.getAppType())) {
return;
}
return getTreeUI(TreeUIKey.Components);
}, [editorState, uiCollapseClick, expandedKeys, showData]);

return getTreeUI(TreeUIKey.Components); // Pass componentTreeData
}, [editorState, uiCollapseClick, expandedKeys, showData, componentTreeData]);
const modalsCollapse = useMemo(() => {
if (isAggregationApp(editorState.getAppType())) {
return;
}
return getTreeUI(TreeUIKey.Modals);
}, [editorState, uiCollapseClick, expandedKeys, showData]);
return getTreeUI(TreeUIKey.Modals); // Pass modalsTreeData
}, [editorState, uiCollapseClick, expandedKeys, showData, modalsTreeData]);

const bottomResCollapse = useMemo(() => {
return editorState
Expand Down Expand Up @@ -549,4 +626,4 @@ export const LeftContent = (props: LeftContentProps) => {
</LeftContentTabs>
</LeftContentWrapper>
);
};
};
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
LeftPanel,
MiddlePanel,
} from "pages/common/styledComponent";
import { getPanelStatus, getEditorModeStatus, getPanelStyle, getCollissionStatus } from "util/localStorageUtil";
import { getPanelStatus, getEditorModeStatus, getPanelStyle, getCollisionStatus } from "util/localStorageUtil";
import { BottomSkeleton } from "pages/editor/bottom/BottomContent";
import RightPanel from "pages/editor/right/RightPanel";
import _ from "lodash";
Expand Down Expand Up @@ -48,7 +48,7 @@ export const EditorLoadingSpin = (props: { height?: string | number }) => {
export default function EditorSkeletonView() {
const panelStatus = getPanelStatus();
const editorModeStatus = getEditorModeStatus();
const collissionStatus = getCollissionStatus();
const collisionStatus = getCollisionStatus();
const panelStyle = getPanelStyle();
const isUserViewMode = useUserViewMode();
const isTemplate = useTemplateViewMode();
Expand All @@ -70,8 +70,8 @@ export default function EditorSkeletonView() {
<SiderStyled />
{panelStatus.left && (
<LeftPanel
collissionStatus={collissionStatus}
toggleCollissionStatus={_.noop}
collisionStatus={collisionStatus}
toggleCollisionStatus={_.noop}
>
<StyledSkeleton active paragraph={{ rows: 10 }} />
</LeftPanel>
Expand Down
Loading