@@ -30,7 +30,8 @@ import { TimesIcon } from '@patternfly/react-icons';
3030
3131import { HttpClient } from '../../services/http' ;
3232import { Settings } from '../../settings' ;
33- import { dashboardToOption } from '../../utilities.js' ;
33+ import { dashboardToOption , toAPIFilter } from '../../utilities.js' ;
34+ import useUserFilter from '../../components/user-filter.js' ;
3435
3536const userToOption = ( user ) => {
3637 if ( ! user ) {
@@ -65,11 +66,8 @@ const ProjectEdit = () => {
6566
6667 // owner selection state
6768 const [ filteredUsers , setFilteredUsers ] = useState ( [ ] ) ;
68- const [ users , setUsers ] = useState ( [ ] ) ;
6969 const [ isOwnerOpen , setIsOwnerOpen ] = useState ( false ) ;
7070 const [ selectedOwner , setSelectedOwner ] = useState ( { } ) ;
71- const [ filterValueOwner , setFilterValueOwner ] = useState ( '' ) ;
72- const [ inputValueOwner , setInputValueOwner ] = useState ( '' ) ;
7371
7472 // dashboard selection state
7573 const [ filteredDashboards , setFilteredDashboards ] = useState ( [ ] ) ;
@@ -88,8 +86,8 @@ const ProjectEdit = () => {
8886 let project = {
8987 title : title ,
9088 name : name ,
91- owner_id : selectedOwner ? selectedOwner . id : null ,
92- default_dashboard_id : selectedDashboard ? selectedDashboard . id : null ,
89+ owner_id : selectedOwner ? .id || null ,
90+ default_dashboard_id : selectedDashboard ? .id || null ,
9391 } ;
9492
9593 let request = null ;
@@ -111,25 +109,12 @@ const ProjectEdit = () => {
111109 . catch ( ( error ) => console . error ( error ) ) ;
112110 } ;
113111
114- const onOwnerInputChange = ( _ , value ) => {
115- setInputValueOwner ( value ) ;
116- setFilterValueOwner ( value ) ;
117- } ;
118-
119- const onOwnerSelect = ( event , value ) => {
112+ const onOwnerSelect = ( _ , value ) => {
120113 setSelectedOwner ( value . user ) ;
121114 setIsOwnerOpen ( false ) ;
122- setFilterValueOwner ( value . user . name ) ;
123- setInputValueOwner ( value . user . name ) ;
124- } ;
125-
126- const onOwnerClear = ( ) => {
127- setSelectedOwner ( null ) ;
128- setFilterValueOwner ( '' ) ;
129- setInputValueOwner ( '' ) ;
130115 } ;
131116
132- const onDashboardSelect = ( event , value ) => {
117+ const onDashboardSelect = ( _ , value ) => {
133118 setSelectedDashboard ( value . dashboard ) ;
134119 setIsDashboardOpen ( false ) ;
135120 setFilterValueDashboard ( value . dashboard . title ) ;
@@ -147,16 +132,22 @@ const ProjectEdit = () => {
147132 setFilterValueDashboard ( value ) ;
148133 } ;
149134
150- // fetch the admin users once
135+ const { filterComponents, activeFilterComponents, activeFilters } =
136+ useUserFilter ( ) ;
137+
138+ // fetch the admin users with the active filter
151139 useEffect ( ( ) => {
152- HttpClient . get ( [ Settings . serverUrl , 'admin' , 'user' ] )
140+ HttpClient . get ( [ Settings . serverUrl , 'admin' , 'user' ] , {
141+ ...( Object . keys ( activeFilters ) ?. length === 0
142+ ? { }
143+ : { filter : toAPIFilter ( activeFilters ) } ) ,
144+ } )
153145 . then ( ( response ) => HttpClient . handleResponse ( response ) )
154146 . then ( ( data ) => {
155- setUsers ( data . users ) ;
156147 setFilteredUsers ( data . users ) ;
157148 } )
158149 . catch ( ( error ) => console . error ( error ) ) ;
159- } , [ ] ) ;
150+ } , [ activeFilters ] ) ;
160151
161152 // fetch the project if needed
162153 useEffect ( ( ) => {
@@ -171,7 +162,6 @@ const ProjectEdit = () => {
171162 setCrumbTitle ( data . title ) ;
172163 setName ( data . name ) ;
173164 setSelectedOwner ( data . owner ) ;
174- setInputValueOwner ( data . owner ?. name ) ;
175165 setSelectedDashboard ( data . defaultDashboard ) ;
176166 setInputValueDashboard ( data . defaultDashboard ?. title ) ;
177167 } )
@@ -229,65 +219,19 @@ const ProjectEdit = () => {
229219 setFilteredDashboards ( newSelectOptionsDashboard ) ;
230220 } , [ dashboards , filterValueDashboard , inputValueDashboard , isDashboardOpen ] ) ;
231221
232- // update owner filtering and selection items
233- useEffect ( ( ) => {
234- let newSelectOptionsUser = [ ...users ] ;
235- if ( inputValueOwner ) {
236- newSelectOptionsUser = users . filter ( ( menuItem ) =>
237- String ( menuItem . name )
238- . toLowerCase ( )
239- . includes ( filterValueOwner . toLowerCase ( ) ) ,
240- ) ;
241- if ( newSelectOptionsUser . length === 0 ) {
242- newSelectOptionsUser = [
243- {
244- isDisabled : true ,
245- value : { } ,
246- name : `No results found for "${ filterValueOwner } "` ,
247- } ,
248- ] ;
249- }
250- }
251- setFilteredUsers ( newSelectOptionsUser ) ;
252- } , [ filterValueOwner , inputValueOwner , isOwnerOpen , users ] ) ;
253-
254222 const toggleOwner = ( toggleRef ) => (
255223 < MenuToggle
256224 innerRef = { toggleRef }
257- variant = "typeahead "
258- aria-label = "Typeahead menu toggle"
225+ variant = "secondary "
226+ aria-label = "Owner selection toggle"
259227 onClick = { ( ) => {
260228 setIsOwnerOpen ( ! isOwnerOpen ) ;
261229 } }
262230 isExpanded = { isOwnerOpen }
263- isFullWidth
264231 >
265- < TextInputGroup isPlain >
266- < TextInputGroupMain
267- value = { inputValueOwner }
268- onClick = { ( ) => {
269- setIsOwnerOpen ( ! isOwnerOpen ) ;
270- } }
271- onChange = { onOwnerInputChange }
272- id = "typeahead-select-input"
273- autoComplete = "off"
274- placeholder = "Select project owner"
275- role = "combobox"
276- isExpanded = { isOwnerOpen }
277- aria-controls = "select-typeahead-listbox"
278- />
279- < TextInputGroupUtilities >
280- { ! ! inputValueOwner && (
281- < Button
282- variant = "plain"
283- onClick = { onOwnerClear }
284- aria-label = "Clear input value"
285- >
286- < TimesIcon aria-hidden />
287- </ Button >
288- ) }
289- </ TextInputGroupUtilities >
290- </ TextInputGroup >
232+ { selectedOwner ?. name ||
233+ selectedOwner ?. email ||
234+ 'Use a filter to select an owner' }
291235 </ MenuToggle >
292236 ) ;
293237
@@ -300,7 +244,6 @@ const ProjectEdit = () => {
300244 setIsDashboardOpen ( ! isDashboardOpen ) ;
301245 } }
302246 isExpanded = { isDashboardOpen }
303- isFullWidth
304247 isDisabled = { filteredDashboards . length === 0 ? true : false }
305248 >
306249 < TextInputGroup isPlain >
@@ -335,7 +278,7 @@ const ProjectEdit = () => {
335278 return (
336279 < React . Fragment >
337280 < PageSection variant = { PageSectionVariants . light } >
338- < Title headingLevel = "h1" size = "2xl" className = "pf-v5-c-title" >
281+ < Title headingLevel = "h1" size = "2xl" >
339282 Projects / { crumbTitle }
340283 </ Title >
341284 </ PageSection >
@@ -388,34 +331,36 @@ const ProjectEdit = () => {
388331 </ FormGroup >
389332 < FormGroup fieldId = "owner" label = "Owner" >
390333 < Select
391- id = "typeahead-select-owner"
334+ id = "projectOwner"
335+ ouiaId = "project-edit-owner-select"
392336 isOpen = { isOwnerOpen }
393337 selected = { selectedOwner }
394338 onSelect = { onOwnerSelect }
395339 onOpenChange = { ( ) => setIsOwnerOpen ( false ) }
396340 toggle = { toggleOwner }
397341 isScrollable = { true }
398- maxMenuHeight = "300px "
342+ variant = "default "
399343 >
400- < SelectList id = "select-typeahead-listbox" >
401- { filteredUsers ?. map ( ( user , index ) => (
402- < SelectOption
403- key = { user . id || index }
404- onClick = { ( ) => setSelectedOwner ( user ) }
405- value = { userToOption ( user ) }
406- description = { user . email }
407- isDisabled = { user . isDisabled }
408- ref = { null }
409- >
410- { user . name }
411- </ SelectOption >
412- ) ) }
413- </ SelectList >
344+ { filteredUsers ?. map ( ( user , index ) => (
345+ < SelectOption
346+ key = { user . id || index }
347+ onClick = { ( ) => setSelectedOwner ( user ) }
348+ value = { userToOption ( user ) }
349+ description = { user . email }
350+ isDisabled = { user . isDisabled }
351+ ref = { null }
352+ >
353+ { user . name || user . email }
354+ </ SelectOption >
355+ ) ) }
414356 </ Select >
415357 < FormHelperText >
416358 < HelperText >
417359 < HelperTextItem >
418- The user who owns the project
360+ The user who owns the project. Use the filter to narrow
361+ the selection options above.
362+ { filterComponents }
363+ { activeFilterComponents }
419364 </ HelperTextItem >
420365 </ HelperText >
421366 </ FormHelperText >
@@ -429,7 +374,7 @@ const ProjectEdit = () => {
429374 onOpenChange = { ( ) => setIsDashboardOpen ( false ) }
430375 toggle = { toggleDashboard }
431376 isScrollable = { true }
432- maxMenuHeight = "300px "
377+ variant = "typeahead "
433378 >
434379 < SelectList id = "select-typeahead-listbox" >
435380 { filteredDashboards . map ( ( dashboard , index ) => (
0 commit comments