fix: render SOVD resources for subcomponent entity type#73
Conversation
Subcomponent entities served via /api/v1/components/{id} expose the
full resource set (data, operations, configurations, faults, logs) but
EntityDetailPanel and refreshSelectedEntity only branched on
type === 'component', leaving subcomponents with a bare header and the
"No detailed information available" fallback. Treat 'subcomponent' the
same as 'component' for resource fetching, tab rendering, type-icon /
background, and refresh routing.
There was a problem hiding this comment.
Pull request overview
Fixes the entity detail view so subcomponent entities render and fetch SOVD resources the same way as component entities, aligning UI behavior with how the gateway serves subcomponent resources (via the components API namespace).
Changes:
- Map
subcomponent→componentsfor refresh and API entity-type routing. - Treat
subcomponentas a component inEntityDetailPanelso the resource tab bar renders and resource counts/data are fetched. - Add a regression test ensuring subcomponents prefetch counts as
componentsand render the full resource tab set.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
src/lib/store.ts |
Ensures Refresh re-fetches subcomponents using the components API type mapping. |
src/components/EntityDetailPanel.tsx |
Enables resource fetching + tab rendering + header styling for subcomponent entities. |
src/components/EntityDetailPanel.test.tsx |
Adds a regression test covering the subcomponent tab bar and counts prefetch behavior. |
| case 'area': | ||
| return <Layers className="w-6 h-6 text-cyan-500" />; | ||
| case 'component': | ||
| case 'subcomponent': | ||
| return <Box className="w-6 h-6 text-indigo-500" />; |
|
|
||
| const entityId = selectedEntity.id; | ||
| const isComponent = selectedEntity.type === 'component'; | ||
| const isComponent = selectedEntity.type === 'component' || selectedEntity.type === 'subcomponent'; |
There was a problem hiding this comment.
subarea has the same bug, not fixed. isArea at L450 (and L559) still checks only === 'area'. handleAreaSelection (src/lib/store.ts:484) accepts node.type === 'subarea' and sets selectedEntity.type = 'subarea', and EntityTreeNode.tsx:48,91 renders subarea as clickable. Selecting a subarea hits the same 'No detailed information available' fallback that this PR fixes for subcomponent. Extend isArea, getEntityTypeForApi (case 'subarea': return 'areas'), icon (Layers) and bg (cyan) for symmetry, and add a subarea test.
| case 'app': | ||
| return 'apps'; | ||
| case 'component': | ||
| case 'subcomponent': |
There was a problem hiding this comment.
SearchCommand.tsx not extended. PR claims subcomponent is treated identically to component, but src/components/SearchCommand.tsx:38-52 (getEntityIcon / getEntityColorClass) has no subcomponent case, and the grouping at :157 is hard-coded to ['area', 'component', 'app', 'function']. Subcomponent (and subarea) are filtered out of search results entirely - a user searching for a subcomponent by name will not find it. Either include in this PR for consistency, or note as known-remaining in #74.
| case 'area': | ||
| return <Layers className="w-6 h-6 text-cyan-500" />; | ||
| case 'component': | ||
| case 'subcomponent': |
There was a problem hiding this comment.
breadcrumb icon missing for subcomponent. Header icon helper (here) and bg helper (L651) get the subcomponent case, but getBreadcrumbIcon at L70-85 in the same file does not - subcomponent renders without an icon in the breadcrumb trail. Also relevant: breadcrumb type inference at L660-679 is position-based (index === 2 → component, else app), so a path like /server/area/component/subcomponent labels the subcomponent segment as app. Add subcomponent/subarea to getBreadcrumbIcon at minimum.
Summary
Subcomponent entities (served via
/api/v1/components/{id}after peer aggregation) expose the full SOVD resource set (data, operations, configurations, faults, logs), but the UI rendered only the entity header for them, then fell through to "No detailed information available for this entity." with no tab bar and no fetch.This change treats
'subcomponent'identically to'component'for:fetchEntityDatainEntityDetailPanel<ComponentTabContent>render branchgetEntityTypeForApimappingtypeMapinrefreshSelectedEntity(so the Refresh button actually re-fetches)Issue
Type
Testing
EntityDetailPanel.test.tsxmounts the panel withselectedEntity.type === 'subcomponent'and asserts thatprefetchResourceCountsis called with'components'and that the Data / Operations / Config / Faults / Logs buttons render. The test fails onmain.npm test(404 passed).npm run lintandnpm run typecheckare clean.npm run buildsucceeds; Docker image builds.Checklist
npm run lint)npm run build)