11import React , { useEffect , useState } from 'react' ;
22
33import {
4- Button ,
54 FormGroup ,
65 MenuToggle ,
76 MenuToggleElement ,
87 Select ,
98 SelectList ,
109 SelectOption ,
1110 Spinner ,
12- TextInputGroup ,
13- TextInputGroupMain ,
14- TextInputGroupUtilities ,
1511} from '@patternfly/react-core' ;
16- import { TimesIcon } from '@patternfly/react-icons' ;
1712
1813import {
1914 DistributionProfileItem ,
@@ -31,7 +26,6 @@ import {
3126 changeFscMode ,
3227 clearKernelAppend ,
3328 selectComplianceProfileID ,
34- selectComplianceType ,
3529 selectDistribution ,
3630 setOscapProfile ,
3731} from '@/store/slices/wizard' ;
@@ -65,21 +59,13 @@ const ProfileSelector = ({
6559 const release = removeBetaFromRelease ( useAppSelector ( selectDistribution ) ) ;
6660 const dispatch = useAppDispatch ( ) ;
6761 const [ isOpen , setIsOpen ] = useState ( false ) ;
68- const [ inputValue , setInputValue ] = useState < string > ( '' ) ;
69- const [ filterValue , setFilterValue ] = useState < string > ( '' ) ;
70- const [ selectOptions , setSelectOptions ] = useState <
71- {
72- id : DistributionProfileItem ;
73- name : string | undefined ;
74- } [ ]
75- > ( [ ] ) ;
62+ const [ isApplying , setIsApplying ] = useState ( false ) ;
7663 const [ profileDetails , setProfileDetails ] = useState <
7764 {
7865 id : DistributionProfileItem ;
7966 name : string | undefined ;
8067 } [ ]
8168 > ( [ ] ) ;
82- const complianceType = useAppSelector ( selectComplianceType ) ;
8369 const prefetchProfile = useBackendPrefetch ( 'getOscapCustomizations' ) ;
8470 const {
8571 clearCompliancePackages,
@@ -100,14 +86,6 @@ const ProfileSelector = ({
10086
10187 const [ trigger ] = useLazyGetOscapCustomizationsQuery ( ) ;
10288
103- useEffect ( ( ) => {
104- if ( ! profileID ) {
105- setInputValue ( '' ) ;
106- setFilterValue ( '' ) ;
107- setIsOpen ( false ) ;
108- }
109- } , [ profileID ] ) ;
110-
11189 // prefetch the profiles customizations for on-prem
11290 // and save the results to the cache, since the request
11391 // is quite slow
@@ -145,33 +123,16 @@ const ProfileSelector = ({
145123
146124 const resolvedProfiles = await Promise . all ( promises ) ;
147125 setProfileDetails ( resolvedProfiles ) ;
148- setSelectOptions ( resolvedProfiles ) ;
149126 } ;
150127
151128 fetchProfileDetails ( ) ;
152129 } , [ profiles , release , trigger ] ) ;
153130
154- useEffect ( ( ) => {
155- if ( ! filterValue ) {
156- setSelectOptions ( profileDetails ) ;
157- return ;
158- }
159- const trimmedFilter = filterValue . toLowerCase ( ) . trim ( ) ;
160- const filtered = profileDetails . filter ( ( { name } ) =>
161- name ?. toLowerCase ( ) . includes ( trimmedFilter ) ,
162- ) ;
163-
164- setSelectOptions ( filtered ) ;
165- if ( ! isOpen && filtered . length > 0 ) {
166- setIsOpen ( true ) ;
167- }
168- } , [ filterValue , profileDetails , isOpen ] ) ;
169-
170- const handleToggle = ( ) => {
171- if ( ! isOpen && complianceType === 'openscap' ) {
131+ const handleToggle = ( nextIsOpen : boolean ) => {
132+ if ( nextIsOpen ) {
172133 refetch ( ) ;
173134 }
174- setIsOpen ( ! isOpen ) ;
135+ setIsOpen ( nextIsOpen ) ;
175136 } ;
176137
177138 const handleClear = ( ) => {
@@ -181,53 +142,13 @@ const ProfileSelector = ({
181142 handleServices ( undefined ) ;
182143 dispatch ( clearKernelAppend ( ) ) ;
183144 dispatch ( changeFips ( false ) ) ;
184- setInputValue ( '' ) ;
185- setFilterValue ( '' ) ;
186- } ;
187-
188- const onInputClick = ( ) => {
189- if ( ! isOpen ) {
190- setIsOpen ( true ) ;
191- } else if ( ! inputValue ) {
192- setIsOpen ( false ) ;
193- }
194- } ;
195-
196- const onTextInputChange = ( _event : React . FormEvent , value : string ) => {
197- setInputValue ( value ) ;
198- setFilterValue ( value ) ;
199-
200- if ( value !== profileID ) {
201- dispatch ( setOscapProfile ( undefined ) ) ;
202- }
203- } ;
204-
205- const onKeyDown = ( event : React . KeyboardEvent ) => {
206- if ( event . key === 'Enter' ) {
207- event . preventDefault ( ) ;
208-
209- if ( ! isOpen ) {
210- setIsOpen ( true ) ;
211- } else if ( selectOptions . length === 1 ) {
212- const singleProfile = selectOptions [ 0 ] ;
213- const selection : OScapSelectOptionValueType = {
214- profileID : singleProfile . id ,
215- toString : ( ) => singleProfile . name || '' ,
216- } ;
217-
218- setInputValue ( singleProfile . name || '' ) ;
219- setFilterValue ( '' ) ;
220- applyChanges ( selection ) ;
221- setIsOpen ( false ) ;
222- }
223- }
224145 } ;
225146
226147 const applyChanges = ( selection : OScapSelectOptionValueType ) => {
227148 if ( selection . profileID === undefined ) {
228- // handle user has selected 'None' case
229149 handleClear ( ) ;
230150 } else {
151+ setIsApplying ( true ) ;
231152 const oldOscapPackages = currentProfileData ?. packages || [ ] ;
232153 trigger (
233154 {
@@ -250,7 +171,8 @@ const ProfileSelector = ({
250171 handleKernelAppend ( response . kernel ?. append ) ;
251172 dispatch ( setOscapProfile ( selection . profileID ) ) ;
252173 dispatch ( changeFips ( response . fips ?. enabled || false ) ) ;
253- } ) ;
174+ } )
175+ . finally ( ( ) => setIsApplying ( false ) ) ;
254176 }
255177 } ;
256178
@@ -260,49 +182,56 @@ const ProfileSelector = ({
260182 ) => {
261183 if ( selection === undefined ) return ;
262184
263- setInputValue ( ( selection as OScapSelectOptionValueType [ 'profileID' ] ) || '' ) ;
264- setFilterValue ( '' ) ;
265185 applyChanges ( selection as unknown as OScapSelectOptionValueType ) ;
266186 setIsOpen ( false ) ;
267187 } ;
268188
189+ const selectedProfileName = profileID
190+ ? profileDetails . find ( ( { id } ) => id === profileID ) ?. name || profileID
191+ : undefined ;
192+
193+ const profileOptions = ( ) => {
194+ if ( isFetching ) {
195+ return [
196+ < SelectOption key = 'oscap-loader' value = 'loader' >
197+ < Spinner size = 'lg' />
198+ </ SelectOption > ,
199+ ] ;
200+ }
201+
202+ const res = profileDetails . map ( ( { id, name } ) => (
203+ < SelectOption
204+ key = { id }
205+ value = { {
206+ profileID : id ,
207+ toString : ( ) => name ,
208+ } }
209+ isSelected = { profileID === id }
210+ >
211+ { name }
212+ </ SelectOption >
213+ ) ) ;
214+ return res ;
215+ } ;
216+
269217 const toggleOpenSCAP = ( toggleRef : React . Ref < MenuToggleElement > ) => (
270218 < MenuToggle
271219 data-testid = 'profileSelect'
272220 ref = { toggleRef }
273- variant = 'typeahead'
274- onClick = { ( ) => setIsOpen ( ! isOpen ) }
221+ isPlaceholder = { ! selectedProfileName && ! isApplying }
222+ onClick = { ( ) => handleToggle ( ! isOpen ) }
275223 isExpanded = { isOpen }
276- isDisabled = { isDisabled || ! isSuccess }
224+ isDisabled = { isDisabled || ! isSuccess || isApplying }
277225 isFullWidth
226+ style = { { maxWidth : 'none' } }
278227 >
279- < TextInputGroup isPlain >
280- < TextInputGroupMain
281- value = {
282- profileID
283- ? profileDetails . find ( ( { id } ) => id === profileID ) ?. name ||
284- profileID
285- : inputValue
286- }
287- onClick = { onInputClick }
288- onChange = { onTextInputChange }
289- onKeyDown = { onKeyDown }
290- autoComplete = 'off'
291- placeholder = 'Select a profile'
292- isExpanded = { isOpen }
293- />
294-
295- { profileID && (
296- < TextInputGroupUtilities >
297- < Button
298- icon = { < TimesIcon /> }
299- variant = 'plain'
300- onClick = { handleClear }
301- aria-label = 'Clear input'
302- />
303- </ TextInputGroupUtilities >
304- ) }
305- </ TextInputGroup >
228+ { isApplying ? (
229+ < >
230+ < Spinner size = 'sm' /> Applying profile...
231+ </ >
232+ ) : (
233+ selectedProfileName || 'Select a profile'
234+ ) }
306235 </ MenuToggle >
307236 ) ;
308237
@@ -316,35 +245,8 @@ const ProfileSelector = ({
316245 onOpenChange = { handleToggle }
317246 toggle = { toggleOpenSCAP }
318247 shouldFocusFirstItemOnOpen = { false }
319- popperProps = { {
320- maxWidth : '50vw' ,
321- } }
322248 >
323- < SelectList >
324- { isFetching && (
325- < SelectOption value = 'loader' >
326- < Spinner size = 'lg' />
327- </ SelectOption >
328- ) }
329- { selectOptions . length > 0 &&
330- selectOptions . map ( ( { id, name } ) => (
331- < SelectOption
332- key = { id }
333- value = { {
334- profileID : id ,
335- toString : ( ) => name ,
336- } }
337- isSelected = { profileID === id }
338- >
339- { name }
340- </ SelectOption >
341- ) ) }
342- { isSuccess && selectOptions . length === 0 && (
343- < SelectOption isDisabled >
344- { `No results found for "${ filterValue } "` }
345- </ SelectOption >
346- ) }
347- </ SelectList >
249+ < SelectList > { profileOptions ( ) } </ SelectList >
348250 </ Select >
349251 </ FormGroup >
350252 ) ;
0 commit comments