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
2 changes: 1 addition & 1 deletion client/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "lowcoder-root",
"version": "2.2.0",
"version": "2.3.0",
"type": "module",
"private": true,
"workspaces": [
Expand Down
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
53 changes: 30 additions & 23 deletions client/packages/lowcoder-design/src/icons/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -214,8 +214,9 @@ export { ReactComponent as ClickHouseIcon } from "./icon-query-ClickHouse.svg";
export { ReactComponent as ResetIcon } from "./icon-style-reset.svg";
export { ReactComponent as EditIcon } from "./icon-edit.svg";
export { ReactComponent as EditableIcon } from "./icon-editable.svg";
export { ReactComponent as LeftStateIcon } from "./icon-left-state.svg";
export { ReactComponent as LeftSettingIcon } from "./icon-left-setting.svg";
export { ReactComponent as LeftStateIcon } from "./remix/node-tree.svg";
export { ReactComponent as LeftSettingIcon } from "./remix/tools-fill.svg";
export { ReactComponent as LeftLayersIcon } from "./remix/stack-line.svg";
export { ReactComponent as LeftHelpIcon } from "./icon-left-help.svg";
export { ReactComponent as LeftPreloadIcon } from "./icon-left-preload.svg";
export { ReactComponent as CollapsibleContainerCompIcon } from "./icon-collapsible-container.svg";
Expand Down Expand Up @@ -277,31 +278,37 @@ export { ReactComponent as SignatureIcon } from "./icon-signature.svg";
export { ReactComponent as ManualIcon } from "./icon-manual.svg";
export { ReactComponent as WarnIcon } from "./icon-warn.svg";
export { ReactComponent as SyncManualIcon } from "./icon-sync-manual.svg";
export { ReactComponent as DangerIcon } from "icons/icon-danger.svg";
export { ReactComponent as TableMinusIcon } from "icons/icon-table-minus.svg";
export { ReactComponent as TablePlusIcon } from "icons/icon-table-plus.svg";
export { ReactComponent as MobileAppIcon } from "icons/icon-mobile-app.svg";
export { ReactComponent as MobileNavIcon } from "icons/icon-navigation-mobile.svg";
export { ReactComponent as PcNavIcon } from "icons/icon-navigation-pc.svg";
export { ReactComponent as UnLockIcon } from "icons/icon-unlock.svg";
export { ReactComponent as CalendarDeleteIcon } from "icons/icon-calendar-delete.svg";
export { ReactComponent as TableCheckedIcon } from "icons/icon-table-checked.svg";
export { ReactComponent as TableUnCheckedIcon } from "icons/icon-table-boolean-false.svg";
export { ReactComponent as FileFolderIcon } from "icons/icon-editor-folder.svg";
export { ReactComponent as ExpandIcon } from "icons/icon-expand.svg";
export { ReactComponent as CompressIcon } from "icons/icon-compress.svg";
export { ReactComponent as TableCellsIcon } from "icons/icon-table-cells.svg"; // Added By Aqib Mirza
export { ReactComponent as TimeLineIcon } from "icons/icon-timeline-comp.svg"
export { ReactComponent as LottieIcon } from "icons/icon-lottie.svg";
export { ReactComponent as CommentIcon } from "icons/icon-comment-comp.svg";
export { ReactComponent as MentionIcon } from "icons/icon-mention-comp.svg";
export { ReactComponent as AutoCompleteCompIcon } from "icons/icon-autocomplete-comp.svg";
export { ReactComponent as WidthIcon } from "icons/icon-width.svg";
export { ReactComponent as ResponsiveLayoutCompIcon } from "icons/icon-responsive-layout-comp.svg";
export { ReactComponent as DangerIcon } from "./icon-danger.svg";
export { ReactComponent as TableMinusIcon } from "./icon-table-minus.svg";
export { ReactComponent as TablePlusIcon } from "./icon-table-plus.svg";
export { ReactComponent as MobileAppIcon } from "./icon-mobile-app.svg";
export { ReactComponent as MobileNavIcon } from "./icon-navigation-mobile.svg";
export { ReactComponent as PcNavIcon } from "./icon-navigation-pc.svg";
export { ReactComponent as UnLockIcon } from "./icon-unlock.svg";
export { ReactComponent as CalendarDeleteIcon } from "./icon-calendar-delete.svg";
export { ReactComponent as TableCheckedIcon } from "./icon-table-checked.svg";
export { ReactComponent as TableUnCheckedIcon } from "./icon-table-boolean-false.svg";
export { ReactComponent as FileFolderIcon } from "./icon-editor-folder.svg";
export { ReactComponent as ExpandIcon } from "./icon-expand.svg";
export { ReactComponent as CompressIcon } from "./icon-compress.svg";
export { ReactComponent as TableCellsIcon } from "./icon-table-cells.svg"; // Added By Aqib Mirza
export { ReactComponent as TimeLineIcon } from "./icon-timeline-comp.svg"
export { ReactComponent as LottieIcon } from "./icon-lottie.svg";
export { ReactComponent as CommentIcon } from "./icon-comment-comp.svg";
export { ReactComponent as MentionIcon } from "./icon-mention-comp.svg";
export { ReactComponent as AutoCompleteCompIcon } from "./icon-autocomplete-comp.svg";
export { ReactComponent as WidthIcon } from "./icon-width.svg";
export { ReactComponent as ResponsiveLayoutCompIcon } from "./icon-responsive-layout-comp.svg";
export { ReactComponent as TextSizeIcon } from "./remix/font-size-2.svg";
export { ReactComponent as FontFamilyIcon } from "./remix/font-sans-serif.svg";
export { ReactComponent as TextWeigthIcon } from "./remix/bold.svg";
export { ReactComponent as BorderWidthIcon } from "./remix/expand-width-line.svg";
export { ReactComponent as LeftInfoLine } from "./remix/information-line.svg";
export { ReactComponent as LeftInfoFill } from "./remix/information-fill.svg";
export { ReactComponent as LeftShow } from "./remix/eye-off-line.svg";
export { ReactComponent as LeftHide } from "./remix/eye-line.svg";
export { ReactComponent as LeftLock } from "./remix/lock-line.svg";
export { ReactComponent as LeftUnlock } from "./remix/lock-unlock-line.svg";


// new
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -230,14 +230,27 @@ const onDrop = (
};
const key = genRandomKey();
const layoutItem = Object.values(items)[0];
// calculate postion of newly added comp
// should have last position in the comps list
let itemPos = 0;
if (!Object.keys(layout).length) {
itemPos = 0;
} else {
itemPos = Math.max(...Object.values(layout).map(l => l.pos || 0)) + 1;
}
// log.debug("layout: onDrop. widgetValue: ", widgetValue, " layoutItem: ", layoutItem);
dispatch(
wrapActionExtraInfo(
multiChangeAction({
layout: changeValueAction(
{
...layout,
[key]: { ...layoutItem, i: key, placeholder: undefined },
[key]: {
...layoutItem,
i: key,
placeholder: undefined,
pos: itemPos,
},
},
true
),
Expand Down Expand Up @@ -463,6 +476,7 @@ export function InnerGrid(props: ViewPropsWithSelect) {
layout={props.layout}
extraLayout={extraLayout}
onDropDragOver={(e) => {

const compType = draggingUtils.getData<UICompType>("compType");
const compLayout = draggingUtils.getData<UICompLayoutInfo>("compLayout");
if (compType) {
Expand Down
2 changes: 1 addition & 1 deletion client/packages/lowcoder/src/comps/comps/textComp.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ const getStyle = (style: TextStyleType) => {
margin: ${style.margin} !important;
padding: ${style.padding};
width: ${widthCalculator(style.margin)};
height: ${heightCalculator(style.margin)};
// height: ${heightCalculator(style.margin)};
h1 {
line-height: 1.5;
}
Expand Down
83 changes: 66 additions & 17 deletions client/packages/lowcoder/src/comps/editorState.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,11 @@ import { RootComp as RootCompTmp } from "comps/comps/rootComp";
import { PositionParams } from "layout";
import _ from "lodash";
import React, { ReactNode } from "react";
import { BottomResComp, BottomResListComp, BottomResTypeEnum } from "types/bottomRes";
import {
BottomResComp,
BottomResListComp,
BottomResTypeEnum,
} from "types/bottomRes";
import { setFields } from "util/objectUtils";
import { OptionalComp, renameAction } from "lowcoder-core";
import { GridItemComp } from "./comps/gridItemComp";
Expand All @@ -13,7 +17,7 @@ import { NameAndExposingInfo } from "./utils/exposingTypes";
import { checkName } from "./utils/rename";
import { trans } from "i18n";
import { UiLayoutType } from "./comps/uiComp";
import { getEditorModeStatus } from "util/localStorageUtil";
import { getCollisionStatus, getEditorModeStatus } from "util/localStorageUtil";

type RootComp = InstanceType<typeof RootCompTmp>;

Expand Down Expand Up @@ -43,6 +47,7 @@ export class EditorState {
readonly showPropertyPane: boolean = false;
readonly selectedCompNames: Set<string> = new Set();
readonly editorModeStatus: string = "";
readonly collisionStatus: string = "";
readonly isDragging: boolean = false;
readonly draggingCompType: string = "button";
readonly forceShowGrid: boolean = false; // show grid lines
Expand All @@ -52,16 +57,20 @@ export class EditorState {
readonly showResultCompName: string = "";
readonly selectSource?: SelectSourceType; // the source of select type

private readonly setEditorState: (fn: (editorState: EditorState) => EditorState) => void;
private readonly setEditorState: (
fn: (editorState: EditorState) => EditorState
) => void;

constructor(
rootComp: RootComp,
setEditorState: (fn: (editorState: EditorState) => EditorState) => void,
initialEditorModeStatus: string = getEditorModeStatus()
initialEditorModeStatus: string = getEditorModeStatus(),
initialCollisionStatus: string = getCollisionStatus()
) {
this.rootComp = rootComp;
this.setEditorState = setEditorState;
this.editorModeStatus = initialEditorModeStatus;
this.collisionStatus = initialCollisionStatus;
}

/**
Expand All @@ -79,7 +88,10 @@ export class EditorState {
}

getAllCompMap() {
return { ...this.getAllHooksCompMap(), ...this.getUIComp().getAllCompItems() };
return {
...this.getAllHooksCompMap(),
...this.getUIComp().getAllCompItems(),
};
}

getAllUICompMap() {
Expand All @@ -104,7 +116,9 @@ export class EditorState {
*/
getUICompByName(name: string) {
const compMap = this.getAllUICompMap();
return Object.values(compMap).find((item) => item.children.name.getView() === name);
return Object.values(compMap).find(
(item) => item.children.name.getView() === name
);
}

getNameGenerator() {
Expand All @@ -120,17 +134,22 @@ 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,
};
});
}

getCompInfo(nameAndExposingInfo: NameAndExposingInfo, name: string, type: string): CompInfo {
getCompInfo(
nameAndExposingInfo: NameAndExposingInfo,
name: string,
type: string
): CompInfo {
return {
name,
type,
Expand All @@ -157,7 +176,11 @@ export class EditorState {
const exposingInfo = listComp.nameAndExposingInfo();
return listComp.getView().map((item) => {
const name = item.children.name.getView();
return this.getCompInfo(exposingInfo, name, BottomResTypeEnum.DateResponder);
return this.getCompInfo(
exposingInfo,
name,
BottomResTypeEnum.DateResponder
);
});
}

Expand All @@ -175,7 +198,11 @@ export class EditorState {
const exposingInfo = listComp.nameAndExposingInfo();
return listComp.getView().map((item) => {
const name = item.children.name.getView();
return this.getCompInfo(exposingInfo, name, BottomResTypeEnum.Transformer);
return this.getCompInfo(
exposingInfo,
name,
BottomResTypeEnum.Transformer
);
});
}

Expand Down Expand Up @@ -222,7 +249,10 @@ export class EditorState {
}

selectedQueryComp() {
if (this.selectedBottomResType !== BottomResTypeEnum.Query || !this.selectedBottomResName) {
if (
this.selectedBottomResType !== BottomResTypeEnum.Query ||
!this.selectedBottomResName
) {
return undefined;
}
return this.getQueriesComp()
Expand All @@ -233,7 +263,9 @@ export class EditorState {
}

showResultComp(): BottomResComp | undefined {
const bottomResComps = Object.values(BottomResTypeEnum).reduce<BottomResComp[]>((a, b) => {
const bottomResComps = Object.values(BottomResTypeEnum).reduce<
BottomResComp[]
>((a, b) => {
const items = this.getBottomResListComp(b).items();
return a.concat(items);
}, []);
Expand Down Expand Up @@ -279,7 +311,10 @@ export class EditorState {
return this.getUIComp().getComp();
}
const [key, comp] = _.toPairs(selectedComps)[0];
if (_.size(selectedComps) === 1 && isContainer((comp as GridItemComp)?.children?.comp)) {
if (
_.size(selectedComps) === 1 &&
isContainer((comp as GridItemComp)?.children?.comp)
) {
return comp.children.comp;
}

Expand Down Expand Up @@ -307,7 +342,9 @@ export class EditorState {
isCompSelected(compName: string): OptionalComp {
const compMap = this.getAllCompMap();
return Object.values(compMap).find(
(item) => item.children.name.getView() === compName && this.selectedCompNames.has(compName)
(item) =>
item.children.name.getView() === compName &&
this.selectedCompNames.has(compName)
);
}

Expand All @@ -319,6 +356,10 @@ export class EditorState {
this.changeState({ editorModeStatus: newEditorModeStatus });
}

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

setDragging(dragging: boolean) {
if (this.isDragging === dragging) {
return;
Expand Down Expand Up @@ -356,7 +397,10 @@ export class EditorState {
});
}

setSelectedCompNames(selectedCompNames: Set<string>, selectSource?: SelectSourceType) {
setSelectedCompNames(
selectedCompNames: Set<string>,
selectSource?: SelectSourceType
) {
if (selectedCompNames.size === 0 && this.selectedCompNames.size === 0) {
return;
}
Expand Down Expand Up @@ -406,7 +450,9 @@ export class EditorState {
}

getBottomResComp(name: string): BottomResComp | undefined {
const bottomResComps = Object.values(BottomResTypeEnum).reduce<BottomResComp[]>((a, b) => {
const bottomResComps = Object.values(BottomResTypeEnum).reduce<
BottomResComp[]
>((a, b) => {
const items = this.getBottomResListComp(b).items();
return a.concat(items);
}, []);
Expand Down Expand Up @@ -467,8 +513,11 @@ export class EditorState {
getAppType(): UiLayoutType {
return this.getUIComp().children.compType.getView();
}
getCollisionStatus(): string {
return this.collisionStatus;
}

}

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

// current comp name
Expand Down
2 changes: 1 addition & 1 deletion client/packages/lowcoder/src/constants/Layers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export const Layers = {
// comp selection wrapper
dragSelectBox: 399,
//
compHover: 300,
compHover: 100,
//
compSelected: 200,
//
Expand Down
7 changes: 6 additions & 1 deletion client/packages/lowcoder/src/i18n/locales/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,12 @@ export const en = {
"components": "Active Components",
"modals": "in-App Modals",
"expandTip": "Click to Expand {component}'s Data",
"collapseTip": "Click to Collapse {component}'s Data"
"collapseTip": "Click to Collapse {component}'s Data",
"layers": "Layers",
"activatelayers": "Use Layers in this App",
"selectedComponents": "Selected Components...",
"displayComponents": "control Display",
"lockComponents": "control Position",
},

// second part
Expand Down
5 changes: 4 additions & 1 deletion client/packages/lowcoder/src/i18n/locales/zh.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,10 @@ leftPanel: {
components: "组件",
modals: "对话框",
expandTip: "点击展开 {component} 的数据",
collapseTip: "点击折叠 {component} 的数据"
collapseTip: "点击折叠 {component} 的数据",
layers: "图层",
activatelayers: "激活图层",
selectedComponents: "已选组件",
},
bottomPanel: {
title: "查询",
Expand Down
Loading