feat(greenhouse): new Clusters dashboard#1634
Conversation
|
There was a problem hiding this comment.
Pull request overview
Adds a new Greenhouse “Clusters” dashboard flow under /admin/clusters, including an overview grid with filtering and a new cluster detail page that links into plugin-instance details.
Changes:
- Replaced the legacy
/admin/clustersroute with nested routes for clusters list and cluster detail (/admin/clusters/$clusterName). - Added new UI components for clusters overview (filters + grid) and cluster detail (overview/YAML + plugin instances).
- Added new API helpers and types for fetching clusters and plugins-by-cluster, plus shared utility updates.
Reviewed changes
Copilot reviewed 29 out of 30 changed files in this pull request and generated 28 comments.
Show a summary per file
| File | Description |
|---|---|
| apps/greenhouse/src/routeTree.gen.ts | Updates generated route tree to reflect new nested clusters routes. |
| apps/greenhouse/src/routes/admin/clusters/route.tsx | Adds parent “Clusters” route with breadcrumb + Outlet. |
| apps/greenhouse/src/routes/admin/clusters/index.tsx | Adds clusters index route with search validation and default filter redirect. |
| apps/greenhouse/src/routes/admin/clusters/$clusterName/route.tsx | Adds cluster-name route with crumb label based on param. |
| apps/greenhouse/src/routes/admin/clusters/$clusterName/index.tsx | Adds cluster detail index route to render ClusterDetail. |
| apps/greenhouse/src/routes/admin/clusters.tsx | Removes legacy clusters route implementation. |
| apps/greenhouse/src/components/admin/utils.ts | Expands readiness helpers to clusters and adds formatAge. |
| apps/greenhouse/src/components/admin/types/schema.d.ts | Updates Cluster schema typing (note: file is auto-generated). |
| apps/greenhouse/src/components/admin/types/k8sTypes.ts | Adds Cluster type alias alongside existing types. |
| apps/greenhouse/src/components/admin/Layout/Breadcrumb.test.tsx | Updates breadcrumb test for nested routes (currently mismatched path). |
| apps/greenhouse/src/components/admin/constants.ts | Adds cluster-related label keys and filter IDs. |
| apps/greenhouse/src/components/admin/Clusters/index.tsx | Implements clusters overview page (counts, refresh, filters, grid). |
| apps/greenhouse/src/components/admin/Clusters/ClustersGrid/index.tsx | Adds clusters overview data grid header + suspense/error handling. |
| apps/greenhouse/src/components/admin/Clusters/ClustersGrid/index.test.tsx | Adds tests for clusters grid rendering and error state. |
| apps/greenhouse/src/components/admin/Clusters/ClustersGrid/DataRows/index.tsx | Adds suspense data rows fetching clusters and navigating to detail. |
| apps/greenhouse/src/components/admin/Clusters/ClustersFilters.tsx | Adds filter UI (select + chips + search) for clusters. |
| apps/greenhouse/src/components/admin/ClusterDetail/Overview/PluginInstances.tsx | Adds cluster-scoped plugin instances table with navigation to plugin instance detail. |
| apps/greenhouse/src/components/admin/ClusterDetail/Overview/PluginInstances.test.tsx | Adds tests for plugin instances view (currently mismatched route/expectations). |
| apps/greenhouse/src/components/admin/ClusterDetail/Overview/index.tsx | Adds cluster detail “Overview” composition (conditions/details/plugins). |
| apps/greenhouse/src/components/admin/ClusterDetail/Overview/Details.tsx | Adds cluster detail “Details” panel, including age + node status. |
| apps/greenhouse/src/components/admin/ClusterDetail/Overview/Details.test.tsx | Adds tests for Details (currently mismatched props/types/expectations). |
| apps/greenhouse/src/components/admin/ClusterDetail/Overview/Conditions.tsx | Adds cluster readiness conditions section. |
| apps/greenhouse/src/components/admin/ClusterDetail/Overview/Conditions.test.tsx | Adds tests for Conditions (currently mismatched props/types). |
| apps/greenhouse/src/components/admin/ClusterDetail/index.tsx | Adds cluster detail page with tabs and data fetching. |
| apps/greenhouse/src/components/admin/ClusterDetail/index.test.tsx | Adds tests for cluster detail page (currently imports/route mismatches). |
| apps/greenhouse/src/components/admin/api/plugins/fetchPluginsByCluster.ts | Adds API helper to fetch plugins filtered by cluster label. |
| apps/greenhouse/src/components/admin/api/clusters/fetchClustersFilters.ts | Adds API helper to derive filter values from clusters list. |
| apps/greenhouse/src/components/admin/api/clusters/fetchClusters.ts | Adds API helper to fetch clusters and apply client-side filtering/sorting. |
| apps/greenhouse/src/components/admin/api/clusters/fetchCluster.ts | Adds API helper to fetch a single cluster by name. |
| apps/greenhouse/src/components/admin/mocks/pluginPresets.ts | Refactors mocks to provide cluster mock data (file name now misleading). |
Signed-off-by: I531348 <guoda.puidokaite@sap.com>
Signed-off-by: I531348 <guoda.puidokaite@sap.com>
Signed-off-by: I531348 <guoda.puidokaite@sap.com>
Signed-off-by: I531348 <guoda.puidokaite@sap.com>
Signed-off-by: I531348 <guoda.puidokaite@sap.com>
4c56b7a to
ccceb1d
Compare
| ) | ||
| } | ||
|
|
||
| export const PluginInstances = () => { |
There was a problem hiding this comment.
I'd suggest to make it a reusable component as in putting in common and reusing in both PluginPresetDetail and ClusterDetail view.
ArtieReus
left a comment
There was a problem hiding this comment.
Please add a change set
|
First 2 rows from Plugin Instances can be clicked. The Details Button also doesn't work. Screen.Recording.2026-05-18.at.14.31.58.mov |
|
This content can't be read if the screen is small. The 2 columns should be transformed into two rows: |
| filterSettings?: FilterSettings | ||
| }): Promise<Cluster[]> => { | ||
| const response = await apiClient.get(`/apis/greenhouse.sap/v1alpha1/namespaces/${namespace}/clusters`) | ||
| return Array.isArray(response?.items) ? applySorting(applyFilterSettings(response.items, filterSettings)) : [] |
There was a problem hiding this comment.
Looks like you are mutating here the original array. Since response.items comes straight from the API result and may also be cached/reused by React Query, mutating it in place can create subtle bugs or stale-cache surprises.
ArtieReus
left a comment
There was a problem hiding this comment.
Great! very cool!! I like it 💪
Just left comments with minor fixes to be done before merging. Thx!!!
| }} | ||
| /> | ||
| </InputGroup> | ||
| <Button |
There was a problem hiding this comment.
Please use the new pattern of adding an xs button directly after the filter pills for the "Clear all filters" functionality. Also this button should only be visible if there are filters to be cleared.
| <DataGridCell nowrap> | ||
| <PopupMenu onClick={(e) => e.stopPropagation()}> | ||
| <PopupMenuOptions> | ||
| <PopupMenuItem label="View Details" onClick={canNavigateToDetails ? navigateToDetails : undefined} /> |
There was a problem hiding this comment.
In the case of the onClick handler on the Row this is fine but the problem here is that the "View Details" action is still visible even if no details exist. It just doesn't do anything on click in this case.
Instead the whole PopupMenu shouldn't be rendered if there are no actions that can be taken.
| {/* Support Group */} | ||
| <DataGridCell>{preset.metadata?.labels?.[SUPPORT_GROUP_LABEL] || NO_VALUE_DEFAULT}</DataGridCell> | ||
| {/* Actions */} | ||
| <DataGridCell nowrap> |
There was a problem hiding this comment.
Please ensure that the PopupMenu kebap icon is aligned all the way to the right of the row (easiest way to do this is to set the cell as a minWidthColumn in the DataGrid).
| const navigateToDetails = () => { | ||
| if (!pluginPresetName) return | ||
| navigate({ | ||
| to: "/admin/plugin-presets/$pluginPresetName/plugin-instances/$pluginInstance", |
There was a problem hiding this comment.
This links from the cluster detail view to the plugin instance detail view. However from there you can't navigate back to the cluster detail view. The cluster the plugin instance is running on is shown in the metadata section but it's not clickable. Please make it clickable :)
| </DataGridCell> | ||
| <DataGridCell>{plugin.metadata?.name || NO_VALUE_DEFAULT}</DataGridCell> | ||
| <DataGridCell>{pluginPresetName || NO_VALUE_DEFAULT}</DataGridCell> | ||
| <DataGridCell>{ready ? "Ready" : "Not Ready"}</DataGridCell> |
There was a problem hiding this comment.
Please move this directly after the cell containing the status icon. Icon and text belong next to each other
| <DataGridHeadCell>Version</DataGridHeadCell> | ||
| <DataGridHeadCell>Cluster Type</DataGridHeadCell> | ||
| <DataGridHeadCell>Region</DataGridHeadCell> | ||
| <DataGridHeadCell>Connectivity</DataGridHeadCell> |
There was a problem hiding this comment.
It would be nice if already on the list view we could see how many total/running/failing plugin instances the respective cluster has. Looking at the fetch functions you have defined I assume this would cause an n+1 problem. But maybe we can check with the backend colleagues if they'll consider adding this info in the status of the cluster resource.
| <DataGridHeadCell className="align-center"> | ||
| <Icon icon="monitorHeart" /> | ||
| </DataGridHeadCell> | ||
| <DataGridHeadCell>Name</DataGridHeadCell> |
There was a problem hiding this comment.
IMO, column order should be status -> name -> region -> cluster type -> support group -> (plugin counts if possible, see below), connectivity -> message -> action



Summary
Changes Made
Other agreed on ACs:
Cluster TypeandRegionfields and allowed to filter by themDesign guidelines:
https://www.figma.com/design/xsRjypqDB8lGT8LsrxIFKs/%F0%9F%AB%9F--Greenhouse-UX-work?node-id=984-5344&p=f&t=R89RR3K513x3o3rM-0
Related Issues
Testing Instructions
pnpm ipnpm TASKChecklist
PR Manifesto
Review the PR Manifesto for best practises.