1
- import { makeStyles } from "@mui/styles" ;
1
+ import { useState } from "react" ;
2
+ import { useTheme } from "@emotion/react" ;
2
3
import { type User , type Role } from "api/typesGenerated" ;
3
- import { combineClasses } from "utils/combineClasses" ;
4
4
5
5
import { EditRolesButton } from "./EditRolesButton" ;
6
6
import { Pill } from "components/Pill/Pill" ;
7
7
import TableCell from "@mui/material/TableCell" ;
8
8
import Stack from "@mui/material/Stack" ;
9
9
10
- const useStyles = makeStyles ( ( theme ) => ( {
11
- rolePill : {
12
- backgroundColor : theme . palette . background . paperLight ,
13
- borderColor : theme . palette . divider ,
14
- } ,
15
- rolePillOwner : {
16
- backgroundColor : theme . palette . info . dark ,
17
- borderColor : theme . palette . info . light ,
18
- } ,
19
- } ) ) ;
10
+ const roleNameDisplayOrder : readonly string [ ] = [
11
+ "owner" ,
12
+ "user-admin" ,
13
+ "template-admin" ,
14
+ "auditor" ,
15
+ ] ;
20
16
21
- const roleOrder = [ "owner" , "user-admin" , "template-admin" , "auditor" ] ;
17
+ const fallbackRole : Role = {
18
+ name : "member" ,
19
+ display_name : "Member" ,
20
+ } as const ;
21
+
22
+ function getPillRoleList ( userRoles : readonly Role [ ] ) : readonly Role [ ] {
23
+ if ( userRoles . length === 0 ) {
24
+ return [ fallbackRole ] ;
25
+ }
26
+
27
+ const matchedOwnerRole = userRoles . find ( ( role ) => role . name === "owner" ) ;
28
+ if ( matchedOwnerRole !== undefined ) {
29
+ return [ matchedOwnerRole ] ;
30
+ }
31
+
32
+ return [ ...userRoles ] . sort ( ( r1 , r2 ) => {
33
+ if ( r1 . name === r2 . name ) {
34
+ return 0 ;
35
+ }
36
+
37
+ return r1 . name < r2 . name ? - 1 : 1 ;
38
+ } ) ;
39
+ }
40
+
41
+ function getSelectedRoleNames ( roles : readonly Role [ ] ) {
42
+ const roleNameSet = new Set ( roles . map ( ( role ) => role . name ) ) ;
43
+ if ( roleNameSet . size === 0 ) {
44
+ roleNameSet . add ( fallbackRole . name ) ;
45
+ }
46
+
47
+ return roleNameSet ;
48
+ }
22
49
23
- const sortRoles = ( roles : readonly Role [ ] ) => {
50
+ function sortRolesByAccessLevel ( roles : readonly Role [ ] ) {
24
51
return [ ...roles ] . sort (
25
- ( a , b ) => roleOrder . indexOf ( a . name ) - roleOrder . indexOf ( b . name ) ,
52
+ ( r1 , r2 ) =>
53
+ roleNameDisplayOrder . indexOf ( r1 . name ) -
54
+ roleNameDisplayOrder . indexOf ( r2 . name ) ,
26
55
) ;
27
- } ;
56
+ }
28
57
29
58
type Props = {
30
59
canEditUsers : boolean ;
@@ -35,12 +64,6 @@ type Props = {
35
64
onUserRolesUpdate : ( user : User , newRoleNames : string [ ] ) => void ;
36
65
} ;
37
66
38
- // When the user has no role we want to show they are a Member
39
- const fallbackRole : Role = {
40
- name : "member" ,
41
- display_name : "Member" ,
42
- } as const ;
43
-
44
67
export function UserRoleCell ( {
45
68
canEditUsers,
46
69
roles,
@@ -49,18 +72,20 @@ export function UserRoleCell({
49
72
oidcRoleSyncEnabled,
50
73
onUserRolesUpdate,
51
74
} : Props ) {
52
- const styles = useStyles ( ) ;
75
+ const theme = useTheme ( ) ;
53
76
54
- const userRoles =
55
- user . roles . length === 0 ? [ fallbackRole ] : sortRoles ( user . roles ) ;
77
+ const pillRoleList = getPillRoleList ( user . roles ) ;
78
+ const [ rolesTruncated , setRolesTruncated ] = useState (
79
+ user . roles . length - pillRoleList . length ,
80
+ ) ;
56
81
57
82
return (
58
83
< TableCell >
59
84
< Stack direction = "row" spacing = { 1 } >
60
85
{ canEditUsers && (
61
86
< EditRolesButton
62
- roles = { roles ? sortRoles ( roles ) : [ ] }
63
- selectedRoles = { userRoles }
87
+ roles = { sortRolesByAccessLevel ( roles ?? [ ] ) }
88
+ selectedRoleNames = { getSelectedRoleNames ( user . roles ) }
64
89
isLoading = { isLoading }
65
90
userLoginType = { user . login_type }
66
91
oidcRoleSync = { oidcRoleSyncEnabled }
@@ -69,21 +94,29 @@ export function UserRoleCell({
69
94
const rolesWithoutFallback = roles . filter (
70
95
( role ) => role !== fallbackRole . name ,
71
96
) ;
97
+
72
98
onUserRolesUpdate ( user , rolesWithoutFallback ) ;
73
99
} }
74
100
/>
75
101
) }
76
102
77
- { userRoles . map ( ( role ) => (
78
- < Pill
79
- key = { role . name }
80
- text = { role . display_name }
81
- className = { combineClasses ( {
82
- [ styles . rolePill ] : true ,
83
- [ styles . rolePillOwner ] : role . name === "owner" ,
84
- } ) }
85
- />
86
- ) ) }
103
+ { pillRoleList . map ( ( role ) => {
104
+ const isOwnerRole = role . name === "owner" ;
105
+ const { palette } = theme ;
106
+
107
+ return (
108
+ < Pill
109
+ key = { role . name }
110
+ text = { role . display_name }
111
+ css = { {
112
+ backgroundColor : isOwnerRole
113
+ ? palette . info . dark
114
+ : palette . background . paperLight ,
115
+ borderColor : isOwnerRole ? palette . info . light : palette . divider ,
116
+ } }
117
+ />
118
+ ) ;
119
+ } ) }
87
120
</ Stack >
88
121
</ TableCell >
89
122
) ;
0 commit comments