Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit552bbff

Browse files
committed
Search in Publish Permission Dialog
1 parent48d6d7b commit552bbff

File tree

5 files changed

+118
-58
lines changed

5 files changed

+118
-58
lines changed

‎client/packages/lowcoder/src/api/applicationApi.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ class ApplicationApi extends Api {
9999
staticpublicToMarketplaceURL=(applicationId:string)=>`/applications/${applicationId}/public-to-marketplace`;
100100
staticgetMarketplaceAppURL=(applicationId:string)=>`/applications/${applicationId}/view_marketplace`;
101101
staticsetAppEditingStateURL=(applicationId:string)=>`/applications/editState/${applicationId}`;
102+
staticgetAvailableGroupsMembersURL=(applicationId:string)=>`/applications/${applicationId}/groups-members/available`;
102103
staticserverSettingsURL=()=>`/serverSettings`;
103104

104105
staticfetchHomeData(request:HomeDataPayload):AxiosPromise<HomeDataResponse>{
@@ -217,6 +218,10 @@ class ApplicationApi extends Api {
217218
});
218219
}
219220

221+
staticgetAvailableGroupsMembers(applicationId:string,search:string):AxiosPromise<any>{
222+
returnApi.get(ApplicationApi.getAvailableGroupsMembersURL(applicationId),{search})
223+
}
224+
220225
/**
221226
* set app as public
222227
*/

‎client/packages/lowcoder/src/components/PermissionDialog/Permission.tsx

Lines changed: 83 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,15 @@ import {
33
CloseIcon,
44
CommonTextLabel,
55
CustomSelect,
6+
Search,
67
TacoButton,
78
}from"lowcoder-design";
8-
import{useEffect,useRef,useState}from"react";
9+
import{useEffect,useRef,useState,useCallback}from"react";
910
importstyledfrom"styled-components";
11+
import{debounce}from"lodash";
1012
importProfileImagefrom"pages/common/profileImage";
11-
import{useDispatch,useSelector}from"react-redux";
12-
import{fetchGroupsAction,fetchOrgUsersAction}from"redux/reduxActions/orgActions";
13-
import{getOrgGroups,getOrgUsers}from"redux/selectors/orgSelectors";
14-
import{OrgGroup,OrgUser}from"constants/orgConstants";
15-
import{ApplicationPermissionType,ApplicationRoleType}from"constants/applicationConstants";
13+
import{useSelector}from"react-redux";
14+
import{ApplicationPermissionType,ApplicationRoleType,GroupsMembersPermission}from"constants/applicationConstants";
1615
import{
1716
PermissionItemName,
1817
RoleSelectOption,
@@ -27,6 +26,8 @@ import { getUser } from "redux/selectors/usersSelectors";
2726
import{EmptyContent}from"pages/common/styledComponent";
2827
import{trans}from"i18n";
2928
import{PermissionItem}from"./PermissionList";
29+
import{currentApplication}from"@lowcoder-ee/redux/selectors/applicationSelector";
30+
import{fetchAvailableGroupsMembers}from"@lowcoder-ee/util/pagination/axios";
3031

3132
constAddAppUserContent=styled.div`
3233
display: flex;
@@ -86,20 +87,19 @@ const PermissionSelectWrapper = styled.div`
8687
padding: 4px 8px;
8788
margin-top: 8px;
8889
background: #fdfdfd;
89-
outline: 1px solid #d7d9e0;
90-
border-radius: 4px;
90+
outline: 1px dashed #d7d9e0;
9191
9292
.ant-select {
9393
font-size: 13px;
9494
line-height: 13px;
9595
}
9696
9797
&:hover {
98-
outline: 1pxsolid #8b8fa3;
98+
outline: 1pxdashed #8b8fa3;
9999
}
100100
101101
&:focus-within {
102-
outline: 1pxsolid #315efb;
102+
outline: 1pxdashed rgb(203, 212, 245);
103103
border-radius: 4px;
104104
box-shadow: 0 0 0 3px rgb(24 144 255 / 20%);
105105
}
@@ -199,48 +199,34 @@ type PermissionAddEntity = {
199199
key:string;
200200
};
201201

202-
/**
203-
* compose users and groups's permissions, filter the data
204-
*
205-
*@param orgGroups groups
206-
*@param orgUsers users
207-
*@param currentUser currentUser
208-
*@param filterItems filterItems
209-
*/
202+
functionisGroup(data:GroupsMembersPermission){
203+
returndata?.type==="Group"
204+
}
205+
210206
functiongetPermissionOptionView(
211-
orgGroups:OrgGroup[],
212-
orgUsers:OrgUser[],
213-
currentUser:User,
207+
groupsMembers:GroupsMembersPermission[],
214208
filterItems:PermissionItem[]
215209
):AddAppOptionView[]{
216-
letpermissionViews:AddAppOptionView[]=orgGroups.map((group)=>{
210+
211+
letpermissionsViews=groupsMembers?.map((user)=>{
217212
return{
218-
type:"GROUP",
219-
id:group.groupId,
220-
name:group.groupName,
221-
};
222-
});
223-
permissionViews=permissionViews.concat(
224-
orgUsers.map((user)=>{
225-
return{
226-
type:"USER",
227-
id:user.userId,
228-
name:user.name,
229-
avatarUrl:user.avatarUrl,
230-
};
231-
})
232-
);
233-
permissionViews=permissionViews.filter(
234-
(v)=>
235-
!filterItems.find((i)=>i.id===v.id&&i.type===v.type)&&
236-
!(v.type==="USER"&&v.id===currentUser.id)
213+
type:user.typeasApplicationPermissionType,
214+
id:isGroup(user) ?user.data.groupId :user.data.userId,
215+
name:isGroup(user) ?user.data.groupName :user.data.name,
216+
...(isGroup(user) ?{} :{avatarUrl:user.data.avatarUrl})
217+
}
218+
})
219+
220+
permissionsViews=permissionsViews.filter((v)=>
221+
!filterItems.find((i)=>i.id===v.id&&i.type===v.type)
237222
);
238-
returnpermissionViews;
223+
224+
returnpermissionsViews.filter((v)=>v.id&&v.name)asAddAppOptionView[];
239225
}
240226

241227
functionPermissionSelectorOption(props:{optionView:AddAppOptionView}){
242228
const{ optionView}=props;
243-
constgroupIcon=optionView.type==="GROUP"&&(
229+
constgroupIcon=optionView.type==="Group"&&(
244230
<StyledGroupIcon$color={getInitialsAndColorCode(optionView.name)[1]}/>
245231
);
246232
return(
@@ -258,7 +244,7 @@ function PermissionSelectorOption(props: { optionView: AddAppOptionView }) {
258244

259245
functionPermissionSelectorLabel(props:{view:AddAppOptionView}){
260246
const{ view}=props;
261-
constgroupIcon=view.type==="GROUP"&&(
247+
constgroupIcon=view.type==="Group"&&(
262248
<StyledGroupIcon$color={getInitialsAndColorCode(view.name)[1]}$side={9}/>
263249
);
264250
return(
@@ -309,12 +295,52 @@ const PermissionSelector = (props: {
309295
filterItems:PermissionItem[];
310296
supportRoles:{label:string;value:PermissionRole}[];
311297
})=>{
312-
constorgGroups=useSelector(getOrgGroups);
313-
constorgUsers=useSelector(getOrgUsers);
314298
const{ selectedItems, setSelectRole, setSelectedItems, user}=props;
315-
constoptionViews=getPermissionOptionView(orgGroups,orgUsers,user,props.filterItems);
316299
const[roleSelectVisible,setRoleSelectVisible]=useState(false);
317300
constselectRef=useRef<HTMLDivElement>(null);
301+
const[optionViews,setOptionViews]=useState<AddAppOptionView[]>()
302+
const[searchValue,setSearchValue]=useState("");
303+
const[isLoading,setIsLoading]=useState(false);
304+
constapplication=useSelector(currentApplication)
305+
306+
constdebouncedUserSearch=useCallback(
307+
debounce((searchTerm:string)=>{
308+
if(!application)return;
309+
310+
setIsLoading(true);
311+
fetchAvailableGroupsMembers(application.applicationId,searchTerm).then(res=>{
312+
if(res.success){
313+
setOptionViews(getPermissionOptionView(res.data,props.filterItems))
314+
}
315+
setIsLoading(false);
316+
}).catch(()=>{
317+
setIsLoading(false);
318+
});
319+
},500),
320+
[application,props.filterItems]
321+
);
322+
323+
useEffect(()=>{
324+
debouncedUserSearch(searchValue);
325+
326+
return()=>{
327+
debouncedUserSearch.cancel();
328+
};
329+
},[searchValue,debouncedUserSearch]);
330+
331+
useEffect(()=>{
332+
if(!application)return;
333+
334+
setIsLoading(true);
335+
fetchAvailableGroupsMembers(application.applicationId,"").then(res=>{
336+
if(res.success){
337+
setOptionViews(getPermissionOptionView(res.data,props.filterItems))
338+
}
339+
setIsLoading(false);
340+
}).catch(()=>{
341+
setIsLoading(false);
342+
});
343+
},[application,props.filterItems]);
318344

319345
useEffect(()=>{
320346
setRoleSelectVisible(selectedItems.length>0);
@@ -325,12 +351,18 @@ const PermissionSelector = (props: {
325351

326352
return(
327353
<>
354+
<Search
355+
placeholder={trans("home.addPermissionPlaceholder")}
356+
value={searchValue}
357+
onChange={(e)=>setSearchValue(e.target.value)}
358+
/>
328359
<PermissionSelectWrapper>
329360
<AddPermissionsSelect
330361
open
331362
ref={selectRef}
332-
placeholder={trans("home.addPermissionPlaceholder")}
363+
placeholder={trans("home.selectedUsersAndGroups")}
333364
mode="multiple"
365+
showSearch={false}
334366
getPopupContainer={()=>document.getElementById("add-app-user-permission-dropdown")!}
335367
optionLabelProp="label"
336368
tagRender={PermissionTagRender}
@@ -350,7 +382,7 @@ const PermissionSelector = (props: {
350382
setSelectedItems(selectedItems.filter((item)=>item.key!==option.key));
351383
}}
352384
>
353-
{optionViews.map((view)=>{
385+
{optionViews?.map((view)=>{
354386
return(
355387
<CustomSelect.Option
356388
key={`${view.type}-${view.id}`}
@@ -395,16 +427,10 @@ export const Permission = (props: {
395427
addPermission:(userIds:string[],groupIds:string[],role:string)=>void;
396428
})=>{
397429
const{ onCancel}=props;
398-
constdispatch=useDispatch();
399430
constuser=useSelector(getUser);
400431
const[selectRole,setSelectRole]=useState<ApplicationRoleType>("viewer");
401432
const[selectedItems,setSelectedItems]=useState<PermissionAddEntity[]>([]);
402433

403-
useEffect(()=>{
404-
dispatch(fetchOrgUsersAction(user.currentOrgId));
405-
dispatch(fetchGroupsAction(user.currentOrgId));
406-
},[]);
407-
408434
return(
409435
<AddAppUserContent>
410436
<CommonTextLabelstyle={{marginTop:"16px"}}>
@@ -426,10 +452,10 @@ export const Permission = (props: {
426452
buttonType="primary"
427453
onClick={()=>{
428454
constuids=selectedItems
429-
.filter((item)=>item.type==="USER")
455+
.filter((item)=>item.type==="User")
430456
.map((item)=>item.id);
431457
constgids=selectedItems
432-
.filter((item)=>item.type==="GROUP")
458+
.filter((item)=>item.type==="Group")
433459
.map((item)=>item.id);
434460
if(uids.length===0&&gids.length===0){
435461
onCancel();

‎client/packages/lowcoder/src/constants/applicationConstants.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,14 +62,26 @@ export const AppUILayoutType: Record<AppTypeEnum, UiLayoutType> = {
6262

6363
exporttypeApplicationDSLType="editing"|"published"|"view_marketplace";
6464
exporttypeApplicationRoleType="viewer"|"editor"|"owner";
65-
exporttypeApplicationPermissionType="USER"|"GROUP"|"ORG_ADMIN";
65+
exporttypeApplicationPermissionType="User"|"Group"|"ORG_ADMIN"|"USER"|"GROUP";
6666

6767
exportinterfaceApplicationExtra{
6868
moduleHeight?:number;
6969
moduleWidth?:number;
7070
layers?:boolean;
7171
}
7272

73+
exporttypeGroupsMembersPermission={
74+
type:string
75+
data:{
76+
groupGid?:string
77+
groupId?:string
78+
userId?:string
79+
groupName?:string
80+
name?:string
81+
avatarUrl?:string
82+
}
83+
}
84+
7385
exportinterfaceApplicationMeta{
7486
name:string;
7587
applicationType:AppTypeEnum;

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4010,6 +4010,7 @@ export const en = {
40104010
"orgName":"{orgName} admins",
40114011
"addMember":"Add members",
40124012
"addPermissionPlaceholder":"Please enter a name to search members",
4013+
"selectedUsersAndGroups":"Selected Users and Groups",
40134014
"searchMemberOrGroup":"Search for members or groups: ",
40144015
"addPermissionErrorMessage":"Failed to add permission, {message}",
40154016
"copyModalTitle":'Clone "{name}"',

‎client/packages/lowcoder/src/util/pagination/axios.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,22 @@ export const fetchGroupUsrPagination = async (request: fetchGroupUserRequestType
102102
}
103103
}
104104

105+
exportconstfetchAvailableGroupsMembers=async(applicationId:string,search:string)=>{
106+
try{
107+
constresponse=awaitApplicationApi.getAvailableGroupsMembers(applicationId,search)
108+
return{
109+
success:true,
110+
data:response.data.data
111+
}
112+
}catch(error:any){
113+
console.error('Failed to fetch data: ',error)
114+
return{
115+
success:false,
116+
error:error
117+
}
118+
}
119+
}
120+
105121
exportconstfetchOrgUsrPagination=async(request:fetchOrgUserRequestType)=>{
106122
try{
107123
constresponse=awaitOrgApi.fetchOrgUsersPagination(request);

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp