tftsr-devops_investigation/src/components/Kubernetes/Hotbar.tsx

71 lines
2.2 KiB
TypeScript
Raw Normal View History

import React from "react";
import { Button } from "@/components/ui";
import { Settings, Bell, User, Search, Plus, RefreshCw } from "lucide-react";
import { Badge } from "@/components/ui";
interface HotbarProps {
onRefresh: () => void;
onAddResource: () => void;
onSettings: () => void;
fix(kube): bridge kubeconfig storage to in-memory cluster map and fix UI issues Resolves four bugs in the Kubernetes management interface: 1. **Cluster not found error** - commands/kube.rs::list_nodes (and all other kube resource commands) look up clusters from state.clusters (in-memory map) which was never populated from the kubeconfig_files table. Add a new connect_cluster_from_kubeconfig Tauri command that reads the encrypted kubeconfig from the DB, decrypts it, and inserts a ClusterClient into state.clusters. Wire it into KubernetesPage on initial load and cluster change so the in-memory map is always populated before any kube command runs. 2. **Dropdown selection has no effect** - same root cause as #1; activating a kubeconfig only updated the DB flag but never loaded the client into memory. handleClusterChange now calls connectClusterFromKubeconfigCmd after activation. 3. **GUID shown instead of cluster name** - ClusterOverview displayed the raw internal UUID as the page subtitle. Now accepts a clusterName prop (populated from kubeconfig.context) and renders that instead. ClusterDetails similarly changed to show kubeconfig.context in the header, not the UUID. 4. **Bell icon not clickable** - Hotbar bell button had no onClick handler. Add optional onNotifications / notificationCount props; badge count is now dynamic rather than hardcoded. KubernetesPage wires up a notifications dialog showing active cluster context and a link to the Events section. All changes follow TDD: failing tests written first, then implementation.
2026-06-07 22:39:07 +00:00
onNotifications?: () => void;
notificationCount?: number;
clusterName?: string;
}
export function Hotbar({
onRefresh,
onAddResource,
onSettings,
onNotifications,
notificationCount = 0,
clusterName,
}: HotbarProps) {
return (
<div className="h-12 bg-background border-b flex items-center justify-between px-4">
<div className="flex items-center gap-2">
<div className="flex items-center gap-1">
<Button variant="ghost" size="sm" onClick={onRefresh} className="text-foreground">
<RefreshCw className="w-4 h-4" />
</Button>
<Button variant="ghost" size="sm" onClick={onAddResource} className="text-foreground">
<Plus className="w-4 h-4" />
</Button>
</div>
<div className="h-6 w-px bg-border mx-2" />
<div className="flex items-center gap-2">
<Search className="w-4 h-4 text-muted-foreground" />
<span className="text-sm text-muted-foreground">
{clusterName ?? "No cluster selected"}
</span>
</div>
</div>
<div className="flex items-center gap-2">
<Button
variant="ghost"
size="sm"
onClick={onNotifications}
aria-label="Notifications"
className="text-foreground"
>
<Bell className="w-4 h-4" />
{notificationCount > 0 && (
<Badge
variant="destructive"
className="h-4 w-4 flex items-center justify-center p-0 text-[10px]"
>
{notificationCount}
</Badge>
)}
</Button>
<Button variant="ghost" size="sm" onClick={onSettings} className="text-foreground">
<Settings className="w-4 h-4" />
</Button>
<Button variant="ghost" size="sm" className="text-foreground">
<User className="w-4 h-4" />
</Button>
</div>
</div>
);
}