Skip to content

Commit 8c3bcbe

Browse files
authored
Merge pull request #1306 from lowcoder-org/feature-extension
Feature extension
2 parents 931fd16 + eb119ad commit 8c3bcbe

File tree

2 files changed

+130
-6
lines changed

2 files changed

+130
-6
lines changed

client/packages/lowcoder/src/i18n/locales/en.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,8 @@ export const en = {
141141
"searchNotFound": "Can't find the right component?",
142142
"emptyPlugins": "No Plugins Added",
143143
"contactUs": "Contact Us",
144-
"issueHere": "here."
144+
"issueHere": "here.",
145+
"folderListTitle": "Folders"
145146
},
146147
"prop": {
147148
"expand": "Expand",

client/packages/lowcoder/src/pages/editor/right/ModulePanel.tsx

Lines changed: 128 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
11
import CreateAppButton from "components/CreateAppButton";
22
import { EmptyContent } from "components/EmptyContent";
3-
import { ApplicationMeta, AppTypeEnum } from "constants/applicationConstants";
3+
import { ApplicationMeta, AppTypeEnum, FolderMeta } from "constants/applicationConstants";
44
import { APPLICATION_VIEW_URL } from "constants/routesURL";
55
import {
66
ActiveTextColor,
77
BorderActiveShadowColor,
88
BorderColor,
99
GreyTextColor,
1010
} from "constants/style";
11-
import { ModuleDocIcon } from "lowcoder-design";
11+
import { FolderIcon, ModuleDocIcon } from "lowcoder-design";
1212
import { trans } from "i18n";
1313
import { draggingUtils } from "layout/draggingUtils";
14-
import { useContext, useEffect } from "react";
14+
import { useContext, useEffect, useState } from "react";
1515
import { useDispatch, useSelector } from "react-redux";
1616
import { fetchAllModules } from "redux/reduxActions/applicationActions";
1717
import styled from "styled-components";
@@ -21,6 +21,7 @@ import { formatTimestamp } from "util/dateTimeUtils";
2121
import { RightContext } from "./rightContext";
2222
import { modulesSelector } from "../../../redux/selectors/applicationSelector";
2323
import { ComListTitle, ExtensionContentWrapper } from "./styledComponent";
24+
import { foldersSelector } from "@lowcoder-ee/redux/selectors/folderSelector";
2425

2526
const ItemWrapper = styled.div`
2627
display: flex;
@@ -72,11 +73,62 @@ const ItemWrapper = styled.div`
7273
}
7374
`;
7475

76+
const FolderWrapper = styled.div`
77+
display: flex;
78+
flex-direction: row;
79+
margin-bottom: 12px;
80+
&:last-child {
81+
margin-bottom: 0;
82+
}
83+
&:hover {
84+
box-shadow: 0 0 5px 0 rgba(49, 94, 251, 0.15);
85+
border-color: ${BorderActiveShadowColor};
86+
cursor: pointer;
87+
transform: scale(1.03);
88+
.folder-name {
89+
color: ${ActiveTextColor};
90+
}
91+
}
92+
.folder-icon {
93+
transition: all 200ms linear;
94+
margin-right: 8px;
95+
width: 40px;
96+
height: 40px;
97+
display: flex;
98+
justify-content: center;
99+
align-items: center;
100+
border-radius: 4px;
101+
}
102+
.folder-content {
103+
flex: 1;
104+
display: flex;
105+
flex-direction: column;
106+
justify-content: space-around;
107+
overflow: hidden;
108+
}
109+
.folder-name {
110+
line-height: 1.5;
111+
font-size: 13px;
112+
overflow: hidden;
113+
white-space: nowrap;
114+
text-overflow: ellipsis;
115+
}
116+
.folder-desc {
117+
line-height: 1.5;
118+
font-size: 12px;
119+
color: ${GreyTextColor};
120+
}
121+
`;
122+
75123
interface ModuleItemProps {
76124
meta: ApplicationMeta;
77125
onDrag: (type: string) => void;
78126
}
79127

128+
interface FolderItemProps {
129+
meta: FolderMeta;
130+
}
131+
80132
function ModuleItem(props: ModuleItemProps) {
81133
const compType = "module";
82134
const { meta } = props;
@@ -113,23 +165,74 @@ function ModuleItem(props: ModuleItemProps) {
113165
export default function ModulePanel() {
114166
const dispatch = useDispatch();
115167
const modules = useSelector(modulesSelector);
168+
const folders = useSelector(foldersSelector);
116169
const { onDrag, searchValue } = useContext(RightContext);
117170
const { applicationId } = useContext(ExternalEditorContext);
171+
const [isSubItems, setIsSubItems] = useState(false);
172+
// const [subApplications : ApplicationMeta[], setSubApplications] = useState([]);
173+
const [subModuleApp, setSubModuleApp] = useState<ApplicationMeta[]>([]);
174+
175+
const appArray = () => {
176+
const appIdArray: any[] = [];
177+
folders.map(i => (i.subApplications?.map(p =>(appIdArray.push(p.applicationId)))))
178+
return appIdArray;
179+
}
180+
function FolderItem(props: FolderItemProps) {
181+
const { meta } = props;
182+
183+
const handleClick = () => {
184+
setIsSubItems(true);
185+
setSubModuleApp(meta.subApplications || []);
186+
console.log(meta.subApplications);
187+
};
188+
return (
189+
<FolderWrapper onClick={handleClick}>
190+
<div className="folder-icon">
191+
<FolderIcon width="35px"/>
192+
</div>
193+
<div className="folder-content">
194+
<div className="folder-name">{meta.name}</div>
195+
</div>
196+
</FolderWrapper>
197+
);
198+
}
199+
200+
201+
const appIdArray = appArray();
118202

119203
useEffect(() => {
120204
dispatch(fetchAllModules({}));
121205
}, [dispatch]);
122206

123207
const filteredModules = modules.filter((i) => {
208+
if (appIdArray.includes(i.applicationId))
209+
return false;
124210
if (i.applicationId === applicationId || i.applicationType !== AppTypeEnum.Module) {
125211
return false;
126212
}
127213
return i.name?.toLowerCase()?.includes(searchValue.trim()?.toLowerCase()) || !searchValue?.trim();
128214
});
129215

216+
const subModules = (apps: ApplicationMeta[] | undefined) => apps?.filter((i) => {
217+
if (i.applicationId === applicationId || i.applicationType !== AppTypeEnum.Module) {
218+
return false;
219+
}
220+
return i.name?.toLowerCase()?.includes(searchValue.trim()?.toLowerCase()) || !searchValue?.trim();
221+
});
222+
223+
224+
// @ts-ignore
225+
const subItems = subModules(subModuleApp).map((i) => (
226+
<ModuleItem onDrag={onDrag} key={i.applicationId} meta={i} />
227+
));
228+
130229
const items = filteredModules.map((i) => (
131230
<ModuleItem onDrag={onDrag} key={i.applicationId} meta={i} />
132231
));
232+
233+
const folderItems = folders.map((i) => {
234+
return <FolderItem key={i.folderId} meta={i} />
235+
});
133236
const empty = (
134237
<EmptyContent
135238
text={
@@ -149,8 +252,28 @@ export default function ModulePanel() {
149252
);
150253
return (
151254
<>
152-
<ComListTitle>{trans("rightPanel.moduleListTitle")}</ComListTitle>
153-
<ExtensionContentWrapper>{items.length > 0 ? items : empty}</ExtensionContentWrapper>
255+
{
256+
isSubItems ? <>
257+
<ComListTitle>{trans("rightPanel.moduleListTitle")}</ComListTitle>
258+
<FolderWrapper onClick={() => (setIsSubItems(false))}>
259+
<div className="folder-icon">
260+
<FolderIcon width="35px"/>
261+
</div>
262+
<div className="folder-content">
263+
<div className="folder-name">. . .</div>
264+
</div>
265+
</FolderWrapper>
266+
<ExtensionContentWrapper>{subItems.length > 0 ? subItems : null}</ExtensionContentWrapper>
267+
</> :
268+
<ExtensionContentWrapper>
269+
{folderItems.length > 0 ? <>
270+
<ComListTitle>{trans("rightPanel.folderListTitle")}</ComListTitle>
271+
{folderItems}
272+
</> : null}
273+
<ComListTitle>{trans("rightPanel.moduleListTitle")}</ComListTitle>
274+
{items.length > 0 ? items : empty}
275+
</ExtensionContentWrapper>
276+
}
154277
</>
155278
);
156279
}

0 commit comments

Comments
 (0)