@@ -29,6 +29,7 @@ import {
2929 ColumnLayout ,
3030 OnFilterChange ,
3131 FilterValue ,
32+ RowSearchFilter ,
3233} from '@console/dynamic-plugin-sdk' ;
3334import {
3435 Dropdown as DropdownInternal ,
@@ -43,6 +44,7 @@ import { TextFilter } from './factory';
4344import { filterList } from '@console/dynamic-plugin-sdk/src/app/k8s/actions/k8s' ;
4445import useRowFilterFix from './useRowFilterFix' ;
4546import useLabelSelectionFix from './useLabelSelectionFix' ;
47+ import useSearchFilters from './useSearchFilters' ;
4648
4749/**
4850 * Housing both the row filter and name/label filter in the same file.
@@ -82,6 +84,7 @@ export const FilterToolbar: React.FC<FilterToolbarProps> = ({
8284 reduxIDs,
8385 onFilterChange,
8486 labelPath,
87+ rowSearchFilters = [ ] ,
8588} ) => {
8689 const dispatch = useDispatch ( ) ;
8790 const location = useLocation ( ) ;
@@ -90,36 +93,61 @@ export const FilterToolbar: React.FC<FilterToolbarProps> = ({
9093
9194 const translatedNameFilterTitle = nameFilterTitle ?? t ( 'public~Name' ) ;
9295
96+ const { searchFiltersObject, searchFiltersState, changeSearchFiltersState } = useSearchFilters (
97+ rowSearchFilters ,
98+ uniqueFilterName ,
99+ ) ;
100+
93101 const translateFilterType = ( value : string ) => {
94102 switch ( value ) {
95103 case 'Name' :
96104 return translatedNameFilterTitle ;
97105 case 'Label' :
98106 return t ( 'public~Label' ) ;
99107 default :
100- return value ;
108+ return searchFiltersObject ?. [ value ] ?. filterGroupName || value ;
101109 }
102110 } ;
103- const filterDropdownItems = {
104- NAME : translatedNameFilterTitle ,
105- LABEL : t ( 'public~Label' ) ,
111+
112+ const filterDropdownItems : Record < string , string > = {
113+ ...Object . keys ( searchFiltersObject || { } ) . reduce (
114+ ( acc , key ) => ( {
115+ ...acc ,
116+ [ key ] : searchFiltersObject [ key ] . filterGroupName ,
117+ } ) ,
118+ { } ,
119+ ) ,
106120 } ;
107121
122+ if ( ! hideLabelFilter && ! hideNameLabelFilters ) {
123+ filterDropdownItems . LABEL = t ( 'public~Label' ) ;
124+ }
125+
126+ if ( ! hideNameLabelFilters ) {
127+ filterDropdownItems . NAME = translatedNameFilterTitle ;
128+ }
129+
108130 // use unique name only when only when more than 1 table is in the view
109131 const nameFilterQueryArgumentKey = uniqueFilterName
110132 ? `${ uniqueFilterName } -${ textFilter } `
111133 : textFilter ;
112134 const labelFilterQueryArgumentKey = uniqueFilterName
113135 ? `${ uniqueFilterName } -${ labelFilter } `
114136 : labelFilter ;
137+
115138 const params = new URLSearchParams ( location . search ) ;
116- const [ filterType , setFilterType ] = React . useState ( FilterType . NAME ) ;
117139 const [ isOpen , setOpen ] = React . useState ( false ) ;
118140 const [ nameInputText , setNameInputText ] = React . useState (
119141 params . get ( nameFilterQueryArgumentKey ) ?? '' ,
120142 ) ;
121143 const [ labelInputText , setLabelInputText ] = React . useState ( '' ) ;
122144
145+ const [ filterType , setFilterType ] = React . useState (
146+ nameInputText || ! hideNameLabelFilters
147+ ? FilterType . NAME
148+ : Object . keys ( searchFiltersState ) ?. [ 0 ] || rowSearchFilters ?. [ 0 ] ?. type ,
149+ ) ;
150+
123151 // Generate rowFilter items and counts. Memoize to minimize re-renders.
124152 const generatedRowFilters = useDeepCompareMemoize (
125153 ( rowFilters ?? [ ] ) . map ( ( rowFilter ) => ( {
@@ -213,6 +241,27 @@ export const FilterToolbar: React.FC<FilterToolbarProps> = ({
213241 [ onFilterChange , reduxIDs , dispatch ] ,
214242 ) ;
215243
244+ const applyTextFilter = React . useCallback (
245+ ( value : string , filterName : string ) => {
246+ applyFilters ( filterName , { selected : [ value ] } ) ;
247+ } ,
248+ [ applyFilters ] ,
249+ ) ;
250+
251+ const searchRowFilters = rowSearchFilters . map ( ( searchFilter ) => (
252+ < ToolbarFilter
253+ key = { searchFilter . type }
254+ categoryName = { translateFilterType ( searchFilter . type ) }
255+ deleteChip = { ( ) => {
256+ changeSearchFiltersState ( searchFilter . type , '' ) ;
257+ applyTextFilter ( '' , searchFilter . type ) ;
258+ } }
259+ chips = { searchFiltersState [ searchFilter . type ] ? [ searchFiltersState [ searchFilter . type ] ] : [ ] }
260+ >
261+ < > </ >
262+ </ ToolbarFilter >
263+ ) ) ;
264+
216265 const applyRowFilter = ( selected : string [ ] ) => {
217266 generatedRowFilters ?. forEach ?.( ( { items, type } ) => {
218267 const all = items ?. map ?.( ( { id } ) => id ) ?? [ ] ;
@@ -250,6 +299,7 @@ export const FilterToolbar: React.FC<FilterToolbarProps> = ({
250299 ) ;
251300
252301 const debounceApplyNameFilter = useDebounceCallback ( applyNameFilter , 250 ) ;
302+ const debounceApplyTextFilter = useDebounceCallback ( applyTextFilter , 250 ) ;
253303
254304 const clearAll = ( ) => {
255305 updateRowFilterSelected ( selectedRowFilters ) ;
@@ -261,6 +311,13 @@ export const FilterToolbar: React.FC<FilterToolbarProps> = ({
261311 setLabelInputText ( '' ) ;
262312 applyLabelFilters ( [ ] ) ;
263313 }
314+
315+ if ( rowSearchFilters . length > 0 ) {
316+ Object . keys ( searchFiltersState ) . forEach ( ( key ) => {
317+ changeSearchFiltersState ( key , '' ) ;
318+ applyTextFilter ( '' , key ) ;
319+ } ) ;
320+ }
264321 } ;
265322
266323 // Run once on mount to apply filters from query params
@@ -271,6 +328,12 @@ export const FilterToolbar: React.FC<FilterToolbarProps> = ({
271328 if ( ! hideNameLabelFilters ) {
272329 applyFilters ( textFilter , { selected : [ nameInputText ] } ) ;
273330 }
331+
332+ if ( rowSearchFilters . length > 0 ) {
333+ Object . keys ( searchFiltersState ) . forEach ( ( key ) => {
334+ applyFilters ( key , { selected : [ searchFiltersState [ key ] ] } ) ;
335+ } ) ;
336+ }
274337 // eslint-disable-next-line react-hooks/exhaustive-deps
275338 } , [ ] ) ;
276339
@@ -287,6 +350,9 @@ export const FilterToolbar: React.FC<FilterToolbarProps> = ({
287350 // eslint-disable-next-line react-hooks/exhaustive-deps
288351 } , [ rowFiltersInitialized , labelSelectionInitialized ] ) ;
289352
353+ const showSearchFilters = Object . keys ( filterDropdownItems ) . length !== 0 ;
354+
355+ const showSearchFiltersDropdown = Object . keys ( filterDropdownItems ) . length > 1 ;
290356 return (
291357 < Toolbar
292358 className = "co-toolbar-no-padding pf-m-toggle-group-container"
@@ -347,8 +413,9 @@ export const FilterToolbar: React.FC<FilterToolbarProps> = ({
347413 ) }
348414 </ ToolbarItem >
349415 ) }
350- { ! hideNameLabelFilters && (
416+ { showSearchFilters && (
351417 < ToolbarItem className = "co-filter-search--full-width" >
418+ { searchRowFilters }
352419 < ToolbarFilter
353420 deleteChipGroup = { ( ) => {
354421 setLabelInputText ( '' ) ;
@@ -370,15 +437,15 @@ export const FilterToolbar: React.FC<FilterToolbarProps> = ({
370437 categoryName = { translatedNameFilterTitle }
371438 >
372439 < div className = "pf-v5-c-input-group co-filter-group" >
373- { ! hideLabelFilter && (
440+ { showSearchFiltersDropdown && (
374441 < DropdownInternal
375442 items = { filterDropdownItems }
376- onChange = { ( type ) => setFilterType ( FilterType [ type ] ) }
443+ onChange = { ( type ) => setFilterType ( FilterType [ type ] || type ) }
377444 selectedKey = { filterType }
378445 title = { translateFilterType ( filterType ) }
379446 />
380447 ) }
381- { filterType === FilterType . LABEL ? (
448+ { filterType === FilterType . LABEL && (
382449 < AutocompleteInput
383450 className = "co-text-node"
384451 onSuggestionSelect = { ( selected ) => {
@@ -391,7 +458,9 @@ export const FilterToolbar: React.FC<FilterToolbarProps> = ({
391458 data = { data }
392459 labelPath = { labelPath }
393460 />
394- ) : (
461+ ) }
462+
463+ { filterType === FilterType . NAME && (
395464 < TextFilter
396465 data-test = "name-filter-input"
397466 value = { nameInputText }
@@ -402,6 +471,18 @@ export const FilterToolbar: React.FC<FilterToolbarProps> = ({
402471 placeholder = { nameFilterPlaceholder ?? t ( 'public~Search by name...' ) }
403472 />
404473 ) }
474+
475+ { searchFiltersObject [ filterType ] && (
476+ < TextFilter
477+ data-test = { `${ filterType } -filter-input` }
478+ value = { searchFiltersState [ filterType ] }
479+ onChange = { ( _event , value : string ) => {
480+ changeSearchFiltersState ( filterType , value ) ;
481+ debounceApplyTextFilter ( value , filterType ) ;
482+ } }
483+ placeholder = { searchFiltersObject [ filterType ] . placeholder }
484+ />
485+ ) }
405486 </ div >
406487 </ ToolbarFilter >
407488 </ ToolbarFilter >
@@ -471,6 +552,7 @@ type FilterToolbarProps = {
471552 // Used when multiple tables are in the same page
472553 uniqueFilterName ?: string ;
473554 onFilterChange ?: OnFilterChange ;
555+ rowSearchFilters ?: RowSearchFilter [ ] ;
474556} ;
475557
476558FilterToolbar . displayName = 'FilterToolbar' ;
0 commit comments