@@ -16,7 +16,9 @@ import {
16
16
PopoverContent ,
17
17
PopoverTrigger ,
18
18
} from "components/deprecated/Popover/Popover" ;
19
- import type { FC } from "react" ;
19
+ import { ChevronDownIcon , ChevronRightIcon } from "lucide-react" ;
20
+ import { type FC , useEffect , useState } from "react" ;
21
+ import { cn } from "utils/cn" ;
20
22
21
23
const roleDescriptions : Record < string , string > = {
22
24
owner :
@@ -57,7 +59,7 @@ const Option: FC<OptionProps> = ({
57
59
} }
58
60
/>
59
61
< div className = "flex flex-col" >
60
- < strong > { name } </ strong >
62
+ < strong className = "text-sm" > { name } </ strong >
61
63
< span className = "text-xs text-content-secondary" > { description } </ span >
62
64
</ div >
63
65
</ div >
@@ -91,6 +93,7 @@ export const EditRolesButton: FC<EditRolesButtonProps> = ({
91
93
92
94
onChange ( [ ...selectedRoleNames , roleName ] ) ;
93
95
} ;
96
+ const [ isAdvancedOpen , setIsAdvancedOpen ] = useState ( false ) ;
94
97
95
98
const canSetRoles =
96
99
userLoginType !== "oidc" || ( userLoginType === "oidc" && ! oidcRoleSync ) ;
@@ -109,6 +112,20 @@ export const EditRolesButton: FC<EditRolesButtonProps> = ({
109
112
) ;
110
113
}
111
114
115
+ const filteredRoles = roles . filter (
116
+ ( role ) => role . name !== "organization-workspace-creation-ban" ,
117
+ ) ;
118
+ const advancedRoles = roles . filter (
119
+ ( role ) => role . name === "organization-workspace-creation-ban" ,
120
+ ) ;
121
+
122
+ // make sure the advanced roles are always visible if the user has one of these roles
123
+ useEffect ( ( ) => {
124
+ if ( selectedRoleNames . has ( "organization-workspace-creation-ban" ) ) {
125
+ setIsAdvancedOpen ( true ) ;
126
+ }
127
+ } , [ selectedRoleNames ] ) ;
128
+
112
129
return (
113
130
< Popover >
114
131
< PopoverTrigger >
@@ -131,7 +148,7 @@ export const EditRolesButton: FC<EditRolesButtonProps> = ({
131
148
title = "Available roles"
132
149
>
133
150
< div className = "flex flex-col gap-4 p-6" >
134
- { roles . map ( ( role ) => (
151
+ { filteredRoles . map ( ( role ) => (
135
152
< Option
136
153
key = { role . name }
137
154
onChange = { handleChange }
@@ -141,6 +158,43 @@ export const EditRolesButton: FC<EditRolesButtonProps> = ({
141
158
description = { roleDescriptions [ role . name ] ?? "" }
142
159
/>
143
160
) ) }
161
+ { advancedRoles . length > 0 && (
162
+ < >
163
+ < button
164
+ className = { cn ( [
165
+ "flex items-center gap-1 p-0 bg-transparent border-0 text-inherit text-sm cursor-pointer" ,
166
+ "transition-colors text-content-secondary hover:text-content-primary font-medium whitespace-nowrap" ,
167
+ isAdvancedOpen && "text-content-primary" ,
168
+ ] ) }
169
+ type = "button"
170
+ onClick = { ( ) => {
171
+ setIsAdvancedOpen ( ( v ) => ! v ) ;
172
+ } }
173
+ >
174
+ { isAdvancedOpen ? (
175
+ < ChevronDownIcon className = "size-icon-sm p-0.5" />
176
+ ) : (
177
+ < ChevronRightIcon className = "size-icon-sm p-0.5" />
178
+ ) }
179
+ < span className = "sr-only" >
180
+ ({ isAdvancedOpen ? "Hide" : "Show advanced" } )
181
+ </ span >
182
+ < span className = "[&:first-letter]:uppercase" > Advanced</ span >
183
+ </ button >
184
+
185
+ { isAdvancedOpen &&
186
+ advancedRoles . map ( ( role ) => (
187
+ < Option
188
+ key = { role . name }
189
+ onChange = { handleChange }
190
+ isChecked = { selectedRoleNames . has ( role . name ) }
191
+ value = { role . name }
192
+ name = { role . display_name || role . name }
193
+ description = { roleDescriptions [ role . name ] ?? "" }
194
+ />
195
+ ) ) }
196
+ </ >
197
+ ) }
144
198
</ div >
145
199
</ fieldset >
146
200
< div className = "p-6 border-t-1 border-solid border-border text-sm" >
0 commit comments