diff --git a/internal/controller/dashboard/factory.go b/internal/controller/dashboard/factory.go index 63bb7a82..3fa61961 100644 --- a/internal/controller/dashboard/factory.go +++ b/internal/controller/dashboard/factory.go @@ -174,27 +174,6 @@ func detailsTab(kind, endpoint, schemaJSON string, keysOrder [][]string) map[str }), ) } - if kind == "Info" { - rightColStack = append(rightColStack, - antdFlexVertical("resource-quotas-block", 4, []any{ - antdText("resource-quotas-label", true, "Resource Quotas", map[string]any{ - "fontSize": float64(20), - "marginBottom": float64(12), - }), - map[string]any{ - "type": "EnrichedTable", - "data": map[string]any{ - "id": "resource-quotas-table", - "baseprefix": "/openapi-ui", - "clusterNamePartOfUrl": "{2}", - "customizationId": "factory-resource-quotas", - "fetchUrl": "/api/clusters/{2}/k8s/api/v1/namespaces/{3}/resourcequotas", - "pathToItems": []any{`items`}, - }, - }, - }), - ) - } if kind == "Tenant" { rightColStack = append(rightColStack, antdFlexVertical("resource-quotas-block", 4, []any{ @@ -209,7 +188,7 @@ func detailsTab(kind, endpoint, schemaJSON string, keysOrder [][]string) map[str "baseprefix": "/openapi-ui", "clusterNamePartOfUrl": "{2}", "customizationId": "factory-resource-quotas", - "fetchUrl": "/api/clusters/{2}/k8s/api/v1/namespaces/{3}/resourcequotas", + "fetchUrl": "/api/clusters/{2}/k8s/api/v1/namespaces/{reqsJsonPath[0]['.status.namespace']}/resourcequotas", "pathToItems": []any{`items`}, }, }, diff --git a/internal/controller/dashboard/static_refactored.go b/internal/controller/dashboard/static_refactored.go index 5b3acd61..b2ace34b 100644 --- a/internal/controller/dashboard/static_refactored.go +++ b/internal/controller/dashboard/static_refactored.go @@ -194,7 +194,7 @@ func CreateAllCustomColumnsOverrides() []*dashboardv1alpha1.CustomColumnsOverrid createFlatMapColumn("Data", ".spec.hard"), createStringColumn("Resource", "_flatMapData_Key"), createStringColumn("Hard", "_flatMapData_Value"), - createStringColumn("Used", ".status.used['{_flatMapData_Key}']"), + createStringColumn("Used", ".status.used[_flatMapData_Key]"), }), // Factory ingress details rules diff --git a/packages/system/dashboard/images/openapi-ui/openapi-k8s-toolkit/patches/flatmap-dynamic-key.diff b/packages/system/dashboard/images/openapi-ui/openapi-k8s-toolkit/patches/flatmap-dynamic-key.diff new file mode 100644 index 00000000..03212014 --- /dev/null +++ b/packages/system/dashboard/images/openapi-ui/openapi-k8s-toolkit/patches/flatmap-dynamic-key.diff @@ -0,0 +1,90 @@ +diff --git a/src/components/molecules/EnrichedTable/organisms/EnrichedTableProvider/utils.ts b/src/components/molecules/EnrichedTable/organisms/EnrichedTableProvider/utils.ts +index 87a0f12..fb2e1cc 100644 +--- a/src/components/molecules/EnrichedTable/organisms/EnrichedTableProvider/utils.ts ++++ b/src/components/molecules/EnrichedTable/organisms/EnrichedTableProvider/utils.ts +@@ -134,22 +134,6 @@ export const prepare = ({ + // impossible in k8s + return {} + }) +- if (customFields.length > 0) { +- dataSource = dataSource.map((el: TJSON) => { +- const newFieldsForComplexJsonPath: Record = {} +- customFields.forEach(({ dataIndex, jsonPath }) => { +- const jpQueryResult = jp.query(el, `$${jsonPath}`) +- newFieldsForComplexJsonPath[dataIndex] = +- Array.isArray(jpQueryResult) && jpQueryResult.length === 1 ? jpQueryResult[0] : jpQueryResult +- }) +- if (typeof el === 'object') { +- return { ...el, ...newFieldsForComplexJsonPath } +- } +- // impossible in k8s +- return { ...newFieldsForComplexJsonPath } +- }) +- } +- + // Handle flatMap: expand rows for map objects + // Process all flatMap columns sequentially + if (flatMapColumns.length > 0 && dataSource) { +@@ -204,6 +188,62 @@ export const prepare = ({ + currentDataSource = expandedDataSource + }) + dataSource = currentDataSource ++ } ++ ++ if (customFields.length > 0) { ++ dataSource = dataSource.map((el: TJSON) => { ++ const newFieldsForComplexJsonPath: Record = {} ++ customFields.forEach(({ dataIndex, jsonPath }) => { ++ let fieldValue: TJSON = null ++ let handled = false ++ ++ const flatMapMatch = jsonPath.match(/^(.*)\[(_flatMap[^\]]+_Key)\](.*)$/) ++ if (flatMapMatch && el && typeof el === 'object' && !Array.isArray(el)) { ++ const basePath = flatMapMatch[1] ++ const keyField = flatMapMatch[2] ++ const tailPath = flatMapMatch[3] ++ const keyValue = (el as Record)[keyField] ++ if (keyValue !== null && keyValue !== undefined) { ++ const baseResult = jp.query(el, `$${basePath}`)[0] ++ if (baseResult && typeof baseResult === 'object' && !Array.isArray(baseResult)) { ++ const baseValue = (baseResult as Record)[String(keyValue)] ++ if (tailPath) { ++ const normalizedTailPath = ++ tailPath.startsWith('.') || tailPath.startsWith('[') ? tailPath : `.${tailPath}` ++ const tailResult = jp.query(baseValue, `$${normalizedTailPath}`) ++ fieldValue = Array.isArray(tailResult) && tailResult.length === 1 ? tailResult[0] : tailResult ++ } else { ++ fieldValue = baseValue as TJSON ++ } ++ handled = true ++ } ++ } ++ } ++ ++ if (!handled) { ++ let resolvedJsonPath = jsonPath ++ if (el && typeof el === 'object' && !Array.isArray(el)) { ++ resolvedJsonPath = jsonPath.replace(/\[(_flatMap[^\]]+_Key)\]/g, (match, keyField) => { ++ const keyValue = (el as Record)[keyField] ++ if (keyValue === null || keyValue === undefined) { ++ return match ++ } ++ const escaped = String(keyValue).replace(/'/g, "\\'") ++ return `['${escaped}']` ++ }) ++ } ++ const jpQueryResult = jp.query(el, `$${resolvedJsonPath}`) ++ fieldValue = Array.isArray(jpQueryResult) && jpQueryResult.length === 1 ? jpQueryResult[0] : jpQueryResult ++ } ++ ++ newFieldsForComplexJsonPath[dataIndex] = fieldValue ++ }) ++ if (typeof el === 'object') { ++ return { ...el, ...newFieldsForComplexJsonPath } ++ } ++ // impossible in k8s ++ return { ...newFieldsForComplexJsonPath } ++ }) + } + } else { + dataSource = dataItems.map((el: TJSON) => {