@@ -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" ; 
910import  styled  from  "styled-components" ; 
11+ import  {  debounce  }  from  "lodash" ; 
1012import  ProfileImage  from  "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" ; 
1615import  { 
1716  PermissionItemName , 
1817  RoleSelectOption , 
@@ -27,6 +26,8 @@ import { getUser } from "redux/selectors/usersSelectors";
2726import  {  EmptyContent  }  from  "pages/common/styledComponent" ; 
2827import  {  trans  }  from  "i18n" ; 
2928import  {  PermissionItem  }  from  "./PermissionList" ; 
29+ import  {  currentApplication  }  from  "@lowcoder-ee/redux/selectors/applicationSelector" ; 
30+ import  {  fetchAvailableGroupsMembers  }  from  "@lowcoder-ee/util/pagination/axios" ; 
3031
3132const  AddAppUserContent  =  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: 1px solid  #8b8fa3; 
98+     outline: 1px dashed  #8b8fa3; 
9999  } 
100100
101101  &:focus-within { 
102-     outline: 1px solid #315efb ; 
102+     outline: 1px dashed 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+ function  isGroup ( data : GroupsMembersPermission )  { 
203+   return  data ?. type  ===  "Group" 
204+ } 
205+ 
210206function  getPermissionOptionView ( 
211-   orgGroups : OrgGroup [ ] , 
212-   orgUsers : OrgUser [ ] , 
213-   currentUser : User , 
207+   groupsMembers : GroupsMembersPermission [ ] , 
214208  filterItems : PermissionItem [ ] 
215209) : AddAppOptionView [ ]  { 
216-   let  permissionViews : AddAppOptionView [ ]  =  orgGroups . map ( ( group )  =>  { 
210+ 
211+   let  permissionsViews  =  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 . type  as  ApplicationPermissionType , 
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-   return  permissionViews ; 
223+ 
224+   return  permissionsViews . filter ( ( v )  =>  v . id  &&  v . name )  as  AddAppOptionView [ ] ; 
239225} 
240226
241227function  PermissionSelectorOption ( props : {  optionView : AddAppOptionView  } )  { 
242228  const  {  optionView }  =  props ; 
243-   const  groupIcon  =  optionView . type  ===  "GROUP "  &&  ( 
229+   const  groupIcon  =  optionView . type  ===  "Group "  &&  ( 
244230    < StyledGroupIcon  $color = { getInitialsAndColorCode ( optionView . name ) [ 1 ] }  /> 
245231  ) ; 
246232  return  ( 
@@ -258,7 +244,7 @@ function PermissionSelectorOption(props: { optionView: AddAppOptionView }) {
258244
259245function  PermissionSelectorLabel ( props : {  view : AddAppOptionView  } )  { 
260246  const  {  view }  =  props ; 
261-   const  groupIcon  =  view . type  ===  "GROUP "  &&  ( 
247+   const  groupIcon  =  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-   const  orgGroups  =  useSelector ( getOrgGroups ) ; 
313-   const  orgUsers  =  useSelector ( getOrgUsers ) ; 
314298  const  {  selectedItems,  setSelectRole,  setSelectedItems,  user }  =  props ; 
315-   const  optionViews  =  getPermissionOptionView ( orgGroups ,  orgUsers ,  user ,  props . filterItems ) ; 
316299  const  [ roleSelectVisible ,  setRoleSelectVisible ]  =  useState ( false ) ; 
317300  const  selectRef  =  useRef < HTMLDivElement > ( null ) ; 
301+   const  [ optionViews ,  setOptionViews ]  =  useState < AddAppOptionView [ ] > ( ) 
302+   const  [ searchValue ,  setSearchValue ]  =  useState ( "" ) ; 
303+   const  [ isLoading ,  setIsLoading ]  =  useState ( false ) ; 
304+   const  application  =  useSelector ( currentApplication ) 
305+ 
306+   const  debouncedUserSearch  =  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-   const  dispatch  =  useDispatch ( ) ; 
399430  const  user  =  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      < CommonTextLabel  style = { {  marginTop : "16px"  } } > 
@@ -426,10 +452,10 @@ export const Permission = (props: {
426452          buttonType = "primary" 
427453          onClick = { ( )  =>  { 
428454            const  uids  =  selectedItems 
429-               . filter ( ( item )  =>  item . type  ===  "USER " ) 
455+               . filter ( ( item )  =>  item . type  ===  "User " ) 
430456              . map ( ( item )  =>  item . id ) ; 
431457            const  gids  =  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 ( ) ; 
0 commit comments