Skip to content

Commit d1ddd09

Browse files
committed
fix(watch): add responsive layout and dynamic name truncation to Live Dashboard
1 parent 0974cf6 commit d1ddd09

2 files changed

Lines changed: 52 additions & 6 deletions

File tree

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { describe, it, expect } from 'vitest';
2+
import { truncateName } from '../ui/WatchDashboard';
3+
4+
describe('WatchDashboard utility functions', () => {
5+
describe('truncateName', () => {
6+
it('should return the original name if it is shorter than or equal to maxLength', () => {
7+
expect(truncateName('my-pod', 10)).toBe('my-pod');
8+
expect(truncateName('my-pod', 6)).toBe('my-pod');
9+
});
10+
11+
it('should truncate and add ellipses if name is longer than maxLength', () => {
12+
expect(truncateName('my-very-long-pod-name', 10)).toBe('my-very...');
13+
expect(truncateName('some-container-name', 15)).toBe('some-contain...');
14+
});
15+
16+
it('should handle small max lengths gracefully', () => {
17+
expect(truncateName('abcde', 4)).toBe('a...');
18+
});
19+
});
20+
});

src/ui/WatchDashboard.tsx

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,30 @@ const StatusBadge = ({ status, type }: { status: string, type: 'pod' | 'containe
1717
);
1818
};
1919

20+
export const truncateName = (name: string, maxLength: number): string => {
21+
if (name.length <= maxLength) return name;
22+
return name.substring(0, maxLength - 3) + '...';
23+
};
24+
2025
export const WatchDashboard = () => {
2126
const [pods, setPods] = useState<PodData[]>([]);
2227
const [containers, setContainers] = useState<ContainerData[]>([]);
2328
const [error, setError] = useState<{ type: string; message: string } | null>(null);
29+
const [columns, setColumns] = useState(process.stdout.columns || 80);
30+
31+
useEffect(() => {
32+
const handleResize = () => {
33+
setColumns(process.stdout.columns || 80);
34+
};
35+
if (process.stdout && typeof process.stdout.on === 'function') {
36+
process.stdout.on('resize', handleResize);
37+
}
38+
return () => {
39+
if (process.stdout && typeof process.stdout.off === 'function') {
40+
process.stdout.off('resize', handleResize);
41+
}
42+
};
43+
}, []);
2444

2545
useEffect(() => {
2646
const fetchPods = async () => {
@@ -53,9 +73,15 @@ export const WatchDashboard = () => {
5373
return () => clearInterval(interval);
5474
}, []);
5575

76+
const isCompact = columns < 80;
77+
const layoutDirection = isCompact ? 'column' : 'row';
78+
const columnWidth = isCompact ? '100%' : '50%';
79+
const availableWidth = isCompact ? (columns - 8) : (Math.floor(columns / 2) - 8);
80+
const maxNameLength = Math.max(10, availableWidth - 14);
81+
5682
return (
5783
<Box flexDirection="column" padding={1} borderStyle="round" borderColor="cyan">
58-
<Box marginBottom={1} justifyContent="space-between">
84+
<Box marginBottom={1} flexDirection={columns < 50 ? 'column' : 'row'} justifyContent="space-between">
5985
<Box>
6086
<Text color="cyan" bold> 󱔎 KDM Live Dashboard </Text>
6187
</Box>
@@ -70,8 +96,8 @@ export const WatchDashboard = () => {
7096
</Box>
7197
)}
7298

73-
<Box flexDirection="row">
74-
<Box flexDirection="column" width="50%" paddingRight={2}>
99+
<Box flexDirection={layoutDirection}>
100+
<Box flexDirection="column" width={columnWidth} paddingRight={isCompact ? 0 : 2} marginBottom={isCompact ? 1 : 0}>
75101
<Box borderStyle="single" borderColor="blue" paddingX={1} marginBottom={1}>
76102
<Text color="blue" bold>Kubernetes Pods ({pods.length})</Text>
77103
</Box>
@@ -80,14 +106,14 @@ export const WatchDashboard = () => {
80106
) : (
81107
pods.map(p => (
82108
<Box key={p.name} flexDirection="row" justifyContent="space-between" marginBottom={0}>
83-
<Text> {p.name.length > 25 ? p.name.substring(0, 22) + '...' : p.name}</Text>
109+
<Text> {truncateName(p.name, maxNameLength)}</Text>
84110
<StatusBadge status={p.status} type="pod" />
85111
</Box>
86112
))
87113
)}
88114
</Box>
89115

90-
<Box flexDirection="column" width="50%">
116+
<Box flexDirection="column" width={columnWidth}>
91117
<Box borderStyle="single" borderColor="blue" paddingX={1} marginBottom={1}>
92118
<Text color="blue" bold>Docker Containers ({containers.length})</Text>
93119
</Box>
@@ -96,7 +122,7 @@ export const WatchDashboard = () => {
96122
) : (
97123
containers.map(c => (
98124
<Box key={c.id} flexDirection="row" justifyContent="space-between" marginBottom={0}>
99-
<Text> {c.name.length > 25 ? c.name.substring(0, 22) + '...' : c.name}</Text>
125+
<Text> {truncateName(c.name, maxNameLength)}</Text>
100126
<StatusBadge status={c.state} type="container" />
101127
</Box>
102128
))

0 commit comments

Comments
 (0)