Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions src/__tests__/dashboard-utils.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { describe, it, expect } from 'vitest';
import { truncateName } from '../ui/WatchDashboard';

describe('WatchDashboard utility functions', () => {
describe('truncateName', () => {
it('should return the original name if it is shorter than or equal to maxLength', () => {
expect(truncateName('my-pod', 10)).toBe('my-pod');
expect(truncateName('my-pod', 6)).toBe('my-pod');
});

it('should truncate and add ellipses if name is longer than maxLength', () => {
expect(truncateName('my-very-long-pod-name', 10)).toBe('my-very...');
expect(truncateName('some-container-name', 15)).toBe('some-contain...');
});

it('should handle small max lengths gracefully', () => {
expect(truncateName('abcde', 4)).toBe('a...');
});
});
});
38 changes: 32 additions & 6 deletions src/ui/WatchDashboard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,30 @@ const StatusBadge = ({ status, type }: { status: string, type: 'pod' | 'containe
);
};

export const truncateName = (name: string, maxLength: number): string => {
if (name.length <= maxLength) return name;
return name.substring(0, maxLength - 3) + '...';
};

export const WatchDashboard = () => {
const [pods, setPods] = useState<PodData[]>([]);
const [containers, setContainers] = useState<ContainerData[]>([]);
const [error, setError] = useState<{ type: string; message: string } | null>(null);
const [columns, setColumns] = useState(process.stdout.columns || 80);

useEffect(() => {
const handleResize = () => {
setColumns(process.stdout.columns || 80);
};
if (process.stdout && typeof process.stdout.on === 'function') {
process.stdout.on('resize', handleResize);
}
return () => {
if (process.stdout && typeof process.stdout.off === 'function') {
process.stdout.off('resize', handleResize);
}
};
}, []);

useEffect(() => {
const fetchPods = async () => {
Expand Down Expand Up @@ -53,9 +73,15 @@ export const WatchDashboard = () => {
return () => clearInterval(interval);
}, []);

const isCompact = columns < 80;
const layoutDirection = isCompact ? 'column' : 'row';
const columnWidth = isCompact ? '100%' : '50%';
const availableWidth = isCompact ? (columns - 8) : (Math.floor(columns / 2) - 8);
const maxNameLength = Math.max(10, availableWidth - 14);

return (
<Box flexDirection="column" padding={1} borderStyle="round" borderColor="cyan">
<Box marginBottom={1} justifyContent="space-between">
<Box marginBottom={1} flexDirection={columns < 50 ? 'column' : 'row'} justifyContent="space-between">
<Box>
<Text color="cyan" bold> 󱔎 KDM Live Dashboard </Text>
</Box>
Expand All @@ -70,8 +96,8 @@ export const WatchDashboard = () => {
</Box>
)}

<Box flexDirection="row">
<Box flexDirection="column" width="50%" paddingRight={2}>
<Box flexDirection={layoutDirection}>
<Box flexDirection="column" width={columnWidth} paddingRight={isCompact ? 0 : 2} marginBottom={isCompact ? 1 : 0}>
<Box borderStyle="single" borderColor="blue" paddingX={1} marginBottom={1}>
<Text color="blue" bold>Kubernetes Pods ({pods.length})</Text>
</Box>
Expand All @@ -80,14 +106,14 @@ export const WatchDashboard = () => {
) : (
pods.map(p => (
<Box key={p.name} flexDirection="row" justifyContent="space-between" marginBottom={0}>
<Text> {p.name.length > 25 ? p.name.substring(0, 22) + '...' : p.name}</Text>
<Text> {truncateName(p.name, maxNameLength)}</Text>
<StatusBadge status={p.status} type="pod" />
</Box>
))
)}
</Box>

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