@@ -5,20 +5,31 @@ import type { MultiselectProps, PropertyFilterProps } from 'components';
55
66import {
77 EMPTY_QUERY ,
8+ getNamePatternFilterRequestParams ,
89 requestParamsToArray ,
910 requestParamsToTokens ,
1011 tokensToRequestParams ,
1112 tokensToSearchParams ,
1213} from 'libs/filters' ;
14+ import { useLazyGetProjectFleetsQuery } from 'services/fleet' ;
1315import { useGetProjectsQuery , useLazyGetProjectsQuery } from 'services/project' ;
1416
15- import { getPropertyFilterOptions } from '../helpers' ;
17+ import { getFleetFilterValue , getPropertyFilterOptions } from '../helpers' ;
1618
17- type RequestParamsKeys = 'project_name' | 'gpu_name' | 'gpu_count' | 'gpu_memory' | 'backend' | 'spot_policy' | 'group_by' ;
19+ type RequestParamsKeys =
20+ | 'project_name'
21+ | 'gpu_name'
22+ | 'gpu_count'
23+ | 'gpu_memory'
24+ | 'backend'
25+ | 'fleet'
26+ | 'spot_policy'
27+ | 'group_by' ;
1828
1929export type UseFiltersArgs = {
2030 gpus : IGpu [ ] ;
2131 withSearchParams ?: boolean ;
32+ showFleetFilter ?: boolean ;
2233 permanentFilters ?: Partial < Record < RequestParamsKeys , string > > ;
2334 defaultFilters ?: Partial < Record < RequestParamsKeys , string | string [ ] > > ;
2435} ;
@@ -29,10 +40,11 @@ export const filterKeys: Record<string, RequestParamsKeys> = {
2940 GPU_COUNT : 'gpu_count' ,
3041 GPU_MEMORY : 'gpu_memory' ,
3142 BACKEND : 'backend' ,
43+ FLEET : 'fleet' ,
3244 SPOT_POLICY : 'spot_policy' ,
3345} ;
3446
35- const multipleChoiceKeys : RequestParamsKeys [ ] = [ 'gpu_name' , 'backend' ] ;
47+ const multipleChoiceKeys : RequestParamsKeys [ ] = [ 'gpu_name' , 'backend' , 'fleet' ] ;
3648
3749const spotPolicyOptions = [
3850 {
@@ -80,6 +92,12 @@ const filteringProperties = [
8092 propertyLabel : 'Backend' ,
8193 groupValuesLabel : 'Backend values' ,
8294 } ,
95+ {
96+ key : filterKeys . FLEET ,
97+ operators : [ '=' ] ,
98+ propertyLabel : 'Fleet' ,
99+ groupValuesLabel : 'Fleet values' ,
100+ } ,
83101 {
84102 key : filterKeys . SPOT_POLICY ,
85103 operators : [ '=' ] ,
@@ -93,22 +111,40 @@ const defaultGroupByOptions = [{ ...gpuFilterOption }, { label: 'Backend', value
93111const groupByRequestParamName : RequestParamsKeys = 'group_by' ;
94112const limit = 100 ;
95113
96- export const useFilters = ( { gpus, withSearchParams = true , permanentFilters = { } , defaultFilters } : UseFiltersArgs ) => {
114+ export const useFilters = ( {
115+ gpus,
116+ withSearchParams = true ,
117+ showFleetFilter = false ,
118+ permanentFilters = { } ,
119+ defaultFilters,
120+ } : UseFiltersArgs ) => {
97121 const [ searchParams , setSearchParams ] = useSearchParams ( ) ;
98122 const [ dynamicFilteringOptions , setDynamicFilteringOptions ] = useState < PropertyFilterProps . FilteringOption [ ] > ( [ ] ) ;
99123 const [ filteringStatusType , setFilteringStatusType ] = useState < PropertyFilterProps . StatusType | undefined > ( ) ;
100124 const [ getProjects ] = useLazyGetProjectsQuery ( ) ;
125+ const [ getProjectFleets ] = useLazyGetProjectFleetsQuery ( ) ;
101126 const { data : projectsData } = useGetProjectsQuery ( { limit : 1 } ) ;
102127 const projectNameIsChecked = useRef ( false ) ;
128+ const prevSelectedProjectName = useRef < string | undefined > ( ) ;
103129
104130 const [ propertyFilterQuery , setPropertyFilterQuery ] = useState < PropertyFilterProps . Query > ( ( ) => {
105131 const queryFromSearchParams = requestParamsToTokens < RequestParamsKeys > ( {
106132 searchParams,
107133 filterKeys,
108134 defaultFilterValues : defaultFilters ,
109135 } ) ;
110- if ( queryFromSearchParams . tokens . length > 0 ) {
111- return queryFromSearchParams ;
136+
137+ const tokens = showFleetFilter
138+ ? queryFromSearchParams . tokens
139+ : queryFromSearchParams . tokens . filter ( ( token ) => token . propertyKey !== filterKeys . FLEET ) ;
140+
141+ const query = {
142+ ...queryFromSearchParams ,
143+ tokens,
144+ } ;
145+
146+ if ( query . tokens . length > 0 ) {
147+ return query ;
112148 }
113149
114150 return EMPTY_QUERY ;
@@ -179,8 +215,14 @@ export const useFilters = ({ gpus, withSearchParams = true, permanentFilters = {
179215
180216 const filteringPropertiesForShowing = useMemo ( ( ) => {
181217 const permanentFilterKeys = Object . keys ( permanentFilters ) ;
182- return filteringProperties . filter ( ( { key } ) => ! permanentFilterKeys . includes ( key ) ) ;
183- } , [ permanentFilters ] ) ;
218+ return filteringProperties . filter ( ( { key } ) => {
219+ if ( key === filterKeys . FLEET && ! showFleetFilter ) {
220+ return false ;
221+ }
222+
223+ return ! permanentFilterKeys . includes ( key ) ;
224+ } ) ;
225+ } , [ permanentFilters , showFleetFilter ] ) ;
184226
185227 const setSearchParamsHandle = ( {
186228 tokens,
@@ -252,17 +294,19 @@ export const useFilters = ({ gpus, withSearchParams = true, permanentFilters = {
252294 } ;
253295 } , [ propertyFilterQuery , permanentFilters ] ) ;
254296
297+ const selectedProjectName = useMemo ( ( ) => {
298+ const projectName = filteringRequestParams [ 'project_name' ] ;
299+
300+ return typeof projectName === 'string' ? projectName : undefined ;
301+ } , [ filteringRequestParams ] ) ;
302+
255303 const handleLoadItems : PropertyFilterProps [ 'onLoadItems' ] = async ( { detail : { filteringProperty, filteringText } } ) => {
256304 setDynamicFilteringOptions ( [ ] ) ;
257305
258- if ( ! filteringText . length ) {
259- return Promise . resolve ( ) ;
260- }
261-
262306 setFilteringStatusType ( 'loading' ) ;
263307
264308 if ( filteringProperty ?. key === filterKeys . PROJECT_NAME ) {
265- await getProjects ( { name_pattern : filteringText , limit } )
309+ await getProjects ( getNamePatternFilterRequestParams ( filteringText , limit ) )
266310 . unwrap ( )
267311 . then ( ( { data } ) =>
268312 data . map ( ( { project_name } ) => ( {
@@ -273,6 +317,24 @@ export const useFilters = ({ gpus, withSearchParams = true, permanentFilters = {
273317 . then ( setDynamicFilteringOptions ) ;
274318 }
275319
320+ if ( showFleetFilter && filteringProperty ?. key === filterKeys . FLEET && selectedProjectName ) {
321+ await getProjectFleets ( {
322+ projectName : selectedProjectName ,
323+ includeImported : true ,
324+ } )
325+ . unwrap ( )
326+ . then ( ( fleets ) =>
327+ fleets
328+ . map ( ( fleet ) => ( {
329+ propertyKey : filterKeys . FLEET ,
330+ value : getFleetFilterValue ( fleet , selectedProjectName ) ,
331+ } ) )
332+ . filter ( ( { value } ) => value . toLowerCase ( ) . includes ( filteringText . toLowerCase ( ) ) )
333+ . slice ( 0 , limit ) ,
334+ )
335+ . then ( setDynamicFilteringOptions ) ;
336+ }
337+
276338 setFilteringStatusType ( undefined ) ;
277339 } ;
278340
@@ -296,6 +358,24 @@ export const useFilters = ({ gpus, withSearchParams = true, permanentFilters = {
296358 }
297359 } , [ projectsData ] ) ;
298360
361+ useEffect ( ( ) => {
362+ const prevProjectName = prevSelectedProjectName . current ;
363+ prevSelectedProjectName . current = selectedProjectName ;
364+
365+ if ( ! showFleetFilter || prevProjectName === selectedProjectName ) {
366+ return ;
367+ }
368+
369+ if ( ! propertyFilterQuery . tokens . some ( ( token ) => token . propertyKey === filterKeys . FLEET ) ) {
370+ return ;
371+ }
372+
373+ onChangePropertyFilterHandle ( {
374+ tokens : propertyFilterQuery . tokens . filter ( ( token ) => token . propertyKey !== filterKeys . FLEET ) ,
375+ operation : propertyFilterQuery . operation ,
376+ } ) ;
377+ } , [ propertyFilterQuery , selectedProjectName , showFleetFilter ] ) ;
378+
299379 return {
300380 filteringRequestParams,
301381 clearFilter,
0 commit comments