@@ -83,6 +83,130 @@ function getDateRangeText(timeRange: string): string {
8383 return `${ monthName } 1-${ lastDay } ` ;
8484}
8585
86+ /**
87+ * Configuration for building query parameters
88+ */
89+ interface QueryParamsConfig {
90+ groupBy : string ;
91+ selectedTag : string ;
92+ overheadDistribution : string ;
93+ timeRange : string ;
94+ currency : string ;
95+ showPlatformSum : boolean ;
96+ filterBy : string ;
97+ filterValue : string ;
98+ filterOperation : string ;
99+ selectedTagKey : string ;
100+ selectedTagValue : string ;
101+ sortField : string | null ;
102+ sortDirection : 'asc' | 'desc' ;
103+ }
104+
105+ /**
106+ * Options for building query parameters
107+ */
108+ interface BuildQueryParamsOptions {
109+ /** Pagination limit - omit for download (uses 0) */
110+ limit ?: number ;
111+ /** Pagination offset - omit for download */
112+ offset ?: number ;
113+ /** Specific item name to filter by (for row-level download) */
114+ specificItemName ?: string ;
115+ }
116+
117+ /**
118+ * Builds query parameters for cost management API requests
119+ * Shared between data fetching and download functionality
120+ */
121+ function buildCostManagementQueryParams (
122+ config : QueryParamsConfig ,
123+ options : BuildQueryParamsOptions = { } ,
124+ ) : Record < string , string | number > {
125+ const {
126+ groupBy,
127+ selectedTag,
128+ overheadDistribution,
129+ timeRange,
130+ currency,
131+ showPlatformSum,
132+ filterBy,
133+ filterValue,
134+ filterOperation,
135+ selectedTagKey,
136+ selectedTagValue,
137+ sortField,
138+ sortDirection,
139+ } = config ;
140+
141+ const { limit, offset, specificItemName } = options ;
142+
143+ // Build group by parameter
144+ const groupByParam =
145+ groupBy === 'tag' ? `group_by[tag:${ selectedTag } ]` : `group_by[${ groupBy } ]` ;
146+
147+ // Determine delta parameter
148+ const deltaParam =
149+ groupBy === 'project' && overheadDistribution === 'distribute'
150+ ? 'distributed_cost'
151+ : 'cost' ;
152+
153+ const timeScopeValue = timeRange === 'month-to-date' ? - 1 : - 2 ;
154+
155+ const queryParams : Record < string , string | number > = {
156+ currency,
157+ delta : deltaParam ,
158+ 'filter[resolution]' : 'monthly' ,
159+ 'filter[time_scope_units]' : 'month' ,
160+ 'filter[time_scope_value]' : timeScopeValue ,
161+ } ;
162+
163+ // Add pagination if provided
164+ if ( limit !== undefined ) {
165+ queryParams [ 'filter[limit]' ] = limit ;
166+ }
167+ if ( offset !== undefined ) {
168+ queryParams [ 'filter[offset]' ] = offset ;
169+ }
170+
171+ // Add category parameter when showPlatformSum is enabled
172+ if ( showPlatformSum ) {
173+ queryParams . category = 'Platform' ;
174+ }
175+
176+ queryParams [ groupByParam ] = '*' ;
177+
178+ // Handle filtering
179+ if ( specificItemName ) {
180+ // Filter for specific item (row-level download)
181+ queryParams [ `filter[${ groupBy } ]` ] = specificItemName ;
182+ } else if ( filterBy === 'tag' && selectedTagKey && selectedTagValue ) {
183+ // Tag filtering
184+ const filterPrefix = filterOperation === 'excludes' ? 'exclude' : 'filter' ;
185+ queryParams [ `${ filterPrefix } [tag:${ selectedTagKey } ]` ] = selectedTagValue ;
186+ } else if ( filterValue ) {
187+ // Regular filtering
188+ const filterPrefix = filterOperation === 'excludes' ? 'exclude' : 'filter' ;
189+ queryParams [ `${ filterPrefix } [${ filterBy } ]` ] = filterValue ;
190+ }
191+
192+ // Add sorting
193+ let apiSortField : string ;
194+ if ( sortField ) {
195+ if ( sortField === 'cost' ) {
196+ apiSortField = deltaParam ;
197+ } else if ( sortField === 'projectName' ) {
198+ apiSortField = groupBy ;
199+ } else {
200+ apiSortField = deltaParam ;
201+ }
202+ queryParams [ `order_by[${ apiSortField } ]` ] = sortDirection ;
203+ } else {
204+ queryParams [ `order_by[${ deltaParam } ]` ] = 'desc' ;
205+ }
206+
207+ return queryParams ;
208+ }
209+
86210/** @public */
87211export function OpenShiftPage ( ) {
88212 const api = useApi ( optimizationsApiRef ) ;
@@ -128,6 +252,40 @@ export function OpenShiftPage() {
128252 }
129253 } , [ api , timeRange ] ) ;
130254
255+ // Build config object for query params builder (memoized to prevent unnecessary re-renders)
256+ const queryParamsConfig : QueryParamsConfig = useMemo (
257+ ( ) => ( {
258+ groupBy,
259+ selectedTag,
260+ overheadDistribution,
261+ timeRange,
262+ currency,
263+ showPlatformSum,
264+ filterBy,
265+ filterValue,
266+ filterOperation,
267+ selectedTagKey,
268+ selectedTagValue,
269+ sortField,
270+ sortDirection,
271+ } ) ,
272+ [
273+ groupBy ,
274+ selectedTag ,
275+ overheadDistribution ,
276+ timeRange ,
277+ currency ,
278+ showPlatformSum ,
279+ filterBy ,
280+ filterValue ,
281+ filterOperation ,
282+ selectedTagKey ,
283+ selectedTagValue ,
284+ sortField ,
285+ sortDirection ,
286+ ] ,
287+ ) ;
288+
131289 const {
132290 value : costData ,
133291 loading,
@@ -139,71 +297,11 @@ export function OpenShiftPage() {
139297 }
140298
141299 try {
142- let groupByParam : string ;
143- if ( groupBy === 'tag' ) {
144- groupByParam = `group_by[tag:${ selectedTag } ]` ;
145- } else {
146- groupByParam = `group_by[${ groupBy } ]` ;
147- }
148-
149- let deltaParam = 'cost' ;
150- if ( groupBy === 'project' && overheadDistribution === 'distribute' ) {
151- deltaParam = 'distributed_cost' ;
152- }
153-
154- const timeScopeValue = timeRange === 'month-to-date' ? - 1 : - 2 ;
155- const timeScopeUnits = 'month' ;
156-
157300 const offset = currentPage * pageSize ;
158- const queryParams : Record < string , string | number > = {
159- currency,
160- delta : deltaParam ,
161- 'filter[limit]' : pageSize ,
162- 'filter[offset]' : offset ,
163- 'filter[resolution]' : 'monthly' ,
164- 'filter[time_scope_units]' : timeScopeUnits ,
165- 'filter[time_scope_value]' : timeScopeValue ,
166- } ;
167-
168- // Add category parameter when showPlatformSum is enabled
169- if ( showPlatformSum ) {
170- queryParams . category = 'Platform' ;
171- }
172-
173- queryParams [ groupByParam ] = '*' ;
174-
175- // Handle filtering based on operation (includes/excludes)
176- if ( filterBy === 'tag' && selectedTagKey && selectedTagValue ) {
177- // Tag filtering uses filter[tag:key] or exclude[tag:key]
178- if ( filterOperation === 'excludes' ) {
179- queryParams [ `exclude[tag:${ selectedTagKey } ]` ] = selectedTagValue ;
180- } else {
181- queryParams [ `filter[tag:${ selectedTagKey } ]` ] = selectedTagValue ;
182- }
183- } else if ( filterValue ) {
184- // Regular filtering uses filter[field] or exclude[field]
185- if ( filterOperation === 'excludes' ) {
186- queryParams [ `exclude[${ filterBy } ]` ] = filterValue ;
187- } else {
188- queryParams [ `filter[${ filterBy } ]` ] = filterValue ;
189- }
190- }
191-
192- if ( sortField ) {
193- let apiSortField : string ;
194- if ( sortField === 'cost' ) {
195- apiSortField = deltaParam ;
196- } else if ( sortField === 'projectName' ) {
197- apiSortField = groupBy ;
198- } else {
199- apiSortField = deltaParam ;
200- }
201- const orderByParam = `order_by[${ apiSortField } ]` ;
202- queryParams [ orderByParam ] = sortDirection ;
203- } else {
204- const orderByParam = `order_by[${ deltaParam } ]` ;
205- queryParams [ orderByParam ] = 'desc' ;
206- }
301+ const queryParams = buildCostManagementQueryParams ( queryParamsConfig , {
302+ limit : pageSize ,
303+ offset,
304+ } ) ;
207305
208306 const response = await api . getCostManagementReport ( {
209307 query : queryParams ,
@@ -384,88 +482,11 @@ export function OpenShiftPage() {
384482 */
385483 const buildDownloadQueryParams = useCallback (
386484 ( specificItemName ?: string ) : Record < string , string | number > => {
387- let groupByParam : string ;
388- if ( groupBy === 'tag' ) {
389- groupByParam = `group_by[tag:${ selectedTag } ]` ;
390- } else {
391- groupByParam = `group_by[${ groupBy } ]` ;
392- }
393-
394- let deltaParam = 'cost' ;
395- if ( groupBy === 'project' && overheadDistribution === 'distribute' ) {
396- deltaParam = 'distributed_cost' ;
397- }
398-
399- const timeScopeValue = timeRange === 'month-to-date' ? - 1 : - 2 ;
400- const timeScopeUnits = 'month' ;
401-
402- const queryParams : Record < string , string | number > = {
403- currency,
404- delta : deltaParam ,
405- 'filter[resolution]' : 'monthly' ,
406- 'filter[time_scope_units]' : timeScopeUnits ,
407- 'filter[time_scope_value]' : timeScopeValue ,
408- } ;
409-
410- // Add category parameter when showPlatformSum is enabled
411- if ( showPlatformSum ) {
412- queryParams . category = 'Platform' ;
413- }
414-
415- queryParams [ groupByParam ] = '*' ;
416-
417- // If downloading a specific row, add filter for that item
418- if ( specificItemName ) {
419- queryParams [ `filter[${ groupBy } ]` ] = specificItemName ;
420- } else {
421- // Apply current filters for header download (all data)
422- if ( filterBy === 'tag' && selectedTagKey && selectedTagValue ) {
423- if ( filterOperation === 'excludes' ) {
424- queryParams [ `exclude[tag:${ selectedTagKey } ]` ] = selectedTagValue ;
425- } else {
426- queryParams [ `filter[tag:${ selectedTagKey } ]` ] = selectedTagValue ;
427- }
428- } else if ( filterValue ) {
429- if ( filterOperation === 'excludes' ) {
430- queryParams [ `exclude[${ filterBy } ]` ] = filterValue ;
431- } else {
432- queryParams [ `filter[${ filterBy } ]` ] = filterValue ;
433- }
434- }
435- }
436-
437- // Add sorting
438- if ( sortField ) {
439- let apiSortField : string ;
440- if ( sortField === 'cost' ) {
441- apiSortField = deltaParam ;
442- } else if ( sortField === 'projectName' ) {
443- apiSortField = groupBy ;
444- } else {
445- apiSortField = deltaParam ;
446- }
447- queryParams [ `order_by[${ apiSortField } ]` ] = sortDirection ;
448- } else {
449- queryParams [ `order_by[${ deltaParam } ]` ] = 'desc' ;
450- }
451-
452- return queryParams ;
485+ return buildCostManagementQueryParams ( queryParamsConfig , {
486+ specificItemName,
487+ } ) ;
453488 } ,
454- [
455- groupBy ,
456- selectedTag ,
457- overheadDistribution ,
458- timeRange ,
459- currency ,
460- showPlatformSum ,
461- filterBy ,
462- filterValue ,
463- filterOperation ,
464- selectedTagKey ,
465- selectedTagValue ,
466- sortField ,
467- sortDirection ,
468- ] ,
489+ [ queryParamsConfig ] ,
469490 ) ;
470491
471492 /**
0 commit comments