@@ -3,16 +3,15 @@ import {
3
3
CloseIcon ,
4
4
CommonTextLabel ,
5
5
CustomSelect ,
6
+ Search ,
6
7
TacoButton ,
7
8
} from "lowcoder-design" ;
8
- import { useEffect , useRef , useState } from "react" ;
9
+ import { useEffect , useRef , useState , useCallback } from "react" ;
9
10
import styled from "styled-components" ;
11
+ import { debounce } from "lodash" ;
10
12
import 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" ;
16
15
import {
17
16
PermissionItemName ,
18
17
RoleSelectOption ,
@@ -27,6 +26,8 @@ import { getUser } from "redux/selectors/usersSelectors";
27
26
import { EmptyContent } from "pages/common/styledComponent" ;
28
27
import { trans } from "i18n" ;
29
28
import { PermissionItem } from "./PermissionList" ;
29
+ import { currentApplication } from "@lowcoder-ee/redux/selectors/applicationSelector" ;
30
+ import { fetchAvailableGroupsMembers } from "@lowcoder-ee/util/pagination/axios" ;
30
31
31
32
const AddAppUserContent = styled . div `
32
33
display: flex;
@@ -86,20 +87,19 @@ const PermissionSelectWrapper = styled.div`
86
87
padding: 4px 8px;
87
88
margin-top: 8px;
88
89
background: #fdfdfd;
89
- outline: 1px solid #d7d9e0;
90
- border-radius: 4px;
90
+ outline: 1px dashed #d7d9e0;
91
91
92
92
.ant-select {
93
93
font-size: 13px;
94
94
line-height: 13px;
95
95
}
96
96
97
97
&:hover {
98
- outline: 1px solid #8b8fa3;
98
+ outline: 1px dashed #8b8fa3;
99
99
}
100
100
101
101
&:focus-within {
102
- outline: 1px solid #315efb ;
102
+ outline: 1px dashed rgb(203, 212, 245) ;
103
103
border-radius: 4px;
104
104
box-shadow: 0 0 0 3px rgb(24 144 255 / 20%);
105
105
}
@@ -199,48 +199,34 @@ type PermissionAddEntity = {
199
199
key : string ;
200
200
} ;
201
201
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
+
210
206
function getPermissionOptionView (
211
- orgGroups : OrgGroup [ ] ,
212
- orgUsers : OrgUser [ ] ,
213
- currentUser : User ,
207
+ groupsMembers : GroupsMembersPermission [ ] ,
214
208
filterItems : PermissionItem [ ]
215
209
) : AddAppOptionView [ ] {
216
- let permissionViews : AddAppOptionView [ ] = orgGroups . map ( ( group ) => {
210
+
211
+ let permissionsViews = groupsMembers ?. map ( ( user ) => {
217
212
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 )
237
222
) ;
238
- return permissionViews ;
223
+
224
+ return permissionsViews . filter ( ( v ) => v . id && v . name ) as AddAppOptionView [ ] ;
239
225
}
240
226
241
227
function PermissionSelectorOption ( props : { optionView : AddAppOptionView } ) {
242
228
const { optionView } = props ;
243
- const groupIcon = optionView . type === "GROUP " && (
229
+ const groupIcon = optionView . type === "Group " && (
244
230
< StyledGroupIcon $color = { getInitialsAndColorCode ( optionView . name ) [ 1 ] } />
245
231
) ;
246
232
return (
@@ -258,7 +244,7 @@ function PermissionSelectorOption(props: { optionView: AddAppOptionView }) {
258
244
259
245
function PermissionSelectorLabel ( props : { view : AddAppOptionView } ) {
260
246
const { view } = props ;
261
- const groupIcon = view . type === "GROUP " && (
247
+ const groupIcon = view . type === "Group " && (
262
248
< StyledGroupIcon $color = { getInitialsAndColorCode ( view . name ) [ 1 ] } $side = { 9 } />
263
249
) ;
264
250
return (
@@ -309,12 +295,52 @@ const PermissionSelector = (props: {
309
295
filterItems : PermissionItem [ ] ;
310
296
supportRoles : { label : string ; value : PermissionRole } [ ] ;
311
297
} ) => {
312
- const orgGroups = useSelector ( getOrgGroups ) ;
313
- const orgUsers = useSelector ( getOrgUsers ) ;
314
298
const { selectedItems, setSelectRole, setSelectedItems, user } = props ;
315
- const optionViews = getPermissionOptionView ( orgGroups , orgUsers , user , props . filterItems ) ;
316
299
const [ roleSelectVisible , setRoleSelectVisible ] = useState ( false ) ;
317
300
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 ] ) ;
318
344
319
345
useEffect ( ( ) => {
320
346
setRoleSelectVisible ( selectedItems . length > 0 ) ;
@@ -325,12 +351,18 @@ const PermissionSelector = (props: {
325
351
326
352
return (
327
353
< >
354
+ < Search
355
+ placeholder = { trans ( "home.addPermissionPlaceholder" ) }
356
+ value = { searchValue }
357
+ onChange = { ( e ) => setSearchValue ( e . target . value ) }
358
+ />
328
359
< PermissionSelectWrapper >
329
360
< AddPermissionsSelect
330
361
open
331
362
ref = { selectRef }
332
- placeholder = { trans ( "home.addPermissionPlaceholder " ) }
363
+ placeholder = { trans ( "home.selectedUsersAndGroups " ) }
333
364
mode = "multiple"
365
+ showSearch = { false }
334
366
getPopupContainer = { ( ) => document . getElementById ( "add-app-user-permission-dropdown" ) ! }
335
367
optionLabelProp = "label"
336
368
tagRender = { PermissionTagRender }
@@ -350,7 +382,7 @@ const PermissionSelector = (props: {
350
382
setSelectedItems ( selectedItems . filter ( ( item ) => item . key !== option . key ) ) ;
351
383
} }
352
384
>
353
- { optionViews . map ( ( view ) => {
385
+ { optionViews ? .map ( ( view ) => {
354
386
return (
355
387
< CustomSelect . Option
356
388
key = { `${ view . type } -${ view . id } ` }
@@ -395,16 +427,10 @@ export const Permission = (props: {
395
427
addPermission : ( userIds : string [ ] , groupIds : string [ ] , role : string ) => void ;
396
428
} ) => {
397
429
const { onCancel } = props ;
398
- const dispatch = useDispatch ( ) ;
399
430
const user = useSelector ( getUser ) ;
400
431
const [ selectRole , setSelectRole ] = useState < ApplicationRoleType > ( "viewer" ) ;
401
432
const [ selectedItems , setSelectedItems ] = useState < PermissionAddEntity [ ] > ( [ ] ) ;
402
433
403
- useEffect ( ( ) => {
404
- dispatch ( fetchOrgUsersAction ( user . currentOrgId ) ) ;
405
- dispatch ( fetchGroupsAction ( user . currentOrgId ) ) ;
406
- } , [ ] ) ;
407
-
408
434
return (
409
435
< AddAppUserContent >
410
436
< CommonTextLabel style = { { marginTop : "16px" } } >
@@ -426,10 +452,10 @@ export const Permission = (props: {
426
452
buttonType = "primary"
427
453
onClick = { ( ) => {
428
454
const uids = selectedItems
429
- . filter ( ( item ) => item . type === "USER " )
455
+ . filter ( ( item ) => item . type === "User " )
430
456
. map ( ( item ) => item . id ) ;
431
457
const gids = selectedItems
432
- . filter ( ( item ) => item . type === "GROUP " )
458
+ . filter ( ( item ) => item . type === "Group " )
433
459
. map ( ( item ) => item . id ) ;
434
460
if ( uids . length === 0 && gids . length === 0 ) {
435
461
onCancel ( ) ;
0 commit comments