Skip to content

Commit 35c2b5d

Browse files
committed
feat: show entity description as the label when available
Prefer an entity's description (e.g. a component's host OS string 'Ubuntu 24.04.4 LTS on x86_64') over the raw name/hostname for the tree node label and the component detail header. The hostname/id stays discoverable via the tree node tooltip and the detail path. Falls back to the name when there is no description.
1 parent 3b1b1e7 commit 35c2b5d

4 files changed

Lines changed: 45 additions & 3 deletions

File tree

src/components/EntityDetailPanel.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -778,7 +778,9 @@ export function EntityDetailPanel({ onConnectClick, viewMode = 'entity', onEntit
778778
{getEntityTypeIcon()}
779779
</div>
780780
<div>
781-
<CardTitle className="text-xl">{selectedEntity.name}</CardTitle>
781+
<CardTitle className="text-xl">
782+
{selectedEntity.description || selectedEntity.name}
783+
</CardTitle>
782784
<CardDescription className="flex items-center gap-2">
783785
<Badge variant="outline">{selectedEntity.type}</Badge>
784786
<span className="text-muted-foreground"></span>

src/components/EntityTreeNode.test.tsx

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,3 +70,40 @@ describe('EntityTreeNode lifecycle lamp', () => {
7070
expect(screen.queryByLabelText(/status:/i)).not.toBeInTheDocument();
7171
});
7272
});
73+
74+
describe('EntityTreeNode label', () => {
75+
beforeEach(() => {
76+
useAppStore.setState({ statusByEntity: {}, expandedPaths: [], loadingPaths: [], selectedPath: null });
77+
});
78+
afterEach(() => cleanup());
79+
80+
it('shows the entity description as the label when present', () => {
81+
useAppStore.setState({ fetchEntityStatus: vi.fn() } as never);
82+
render(
83+
<EntityTreeNode
84+
node={
85+
{
86+
id: 'a3d9',
87+
name: 'a3d9',
88+
type: 'component',
89+
path: '/server/a3d9',
90+
description: 'Ubuntu 24.04.4 LTS on x86_64',
91+
} as never
92+
}
93+
depth={0}
94+
/>
95+
);
96+
expect(screen.getByText('Ubuntu 24.04.4 LTS on x86_64')).toBeInTheDocument();
97+
});
98+
99+
it('falls back to the name when there is no description', () => {
100+
useAppStore.setState({ fetchEntityStatus: vi.fn() } as never);
101+
render(
102+
<EntityTreeNode
103+
node={{ id: 'talker', name: 'talker', type: 'app', path: '/x/talker' } as never}
104+
depth={0}
105+
/>
106+
);
107+
expect(screen.getByText('talker')).toBeInTheDocument();
108+
});
109+
});

src/components/EntityTreeNode.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -261,8 +261,9 @@ export function EntityTreeNode({ node, depth }: EntityTreeNodeProps) {
261261
/>
262262
)}
263263

264-
<span className="text-sm truncate flex-1">
265-
{typeof node.name === 'string' ? node.name : String(node.name || node.id || '')}
264+
<span className="text-sm truncate flex-1" title={typeof node.name === 'string' ? node.name : node.id}>
265+
{(typeof node.description === 'string' && node.description) ||
266+
(typeof node.name === 'string' ? node.name : String(node.name || node.id || ''))}
266267
</span>
267268

268269
{/* Topic direction indicators */}

src/lib/types.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,8 @@ export interface SovdEntity {
126126
id: string;
127127
/** Display name */
128128
name: string;
129+
/** Optional human-friendly description (e.g. the host OS for a component). */
130+
description?: string;
129131
/** Entity type (e.g., "component", "application", "signal") */
130132
type: string;
131133
/** API path for this entity */

0 commit comments

Comments
 (0)