From f5fb9bd0e2e996b8e5ce5cd64129c1e35959c305 Mon Sep 17 00:00:00 2001 From: Shaun Arman Date: Sat, 6 Jun 2026 12:46:33 -0500 Subject: [PATCH] feat(kube): add Kubernetes management GUI components - Add ClusterList, PortForwardList, AddClusterModal, PortForwardForm components - Add KubernetesPage component with cluster and port forward management - Add TypeScript types for Kubernetes management (ClusterInfo, PortForwardRequest, PortForwardResponse) - Add 6 IPC commands to tauriCommands.ts for cluster and port forward management - Write unit tests for Kubernetes IPC commands (6 tests) - All 308 Rust tests passing - All 98 frontend tests passing - TypeScript type check passing - Project builds successfully --- src/components/Kubernetes/AddClusterModal.tsx | 130 +++++++++++++ src/components/Kubernetes/ClusterList.tsx | 79 ++++++++ src/components/Kubernetes/PortForwardForm.tsx | 180 ++++++++++++++++++ src/components/Kubernetes/PortForwardList.tsx | 117 ++++++++++++ src/components/Kubernetes/index.tsx | 4 + src/lib/tauriCommands.ts | 46 +++++ src/pages/Kubernetes/KubernetesPage.tsx | 117 ++++++++++++ tests/unit/kubernetesCommands.test.ts | 141 ++++++++++++++ 8 files changed, 814 insertions(+) create mode 100644 src/components/Kubernetes/AddClusterModal.tsx create mode 100644 src/components/Kubernetes/ClusterList.tsx create mode 100644 src/components/Kubernetes/PortForwardForm.tsx create mode 100644 src/components/Kubernetes/PortForwardList.tsx create mode 100644 src/components/Kubernetes/index.tsx create mode 100644 src/pages/Kubernetes/KubernetesPage.tsx create mode 100644 tests/unit/kubernetesCommands.test.ts diff --git a/src/components/Kubernetes/AddClusterModal.tsx b/src/components/Kubernetes/AddClusterModal.tsx new file mode 100644 index 00000000..f09c98de --- /dev/null +++ b/src/components/Kubernetes/AddClusterModal.tsx @@ -0,0 +1,130 @@ +import React, { useState } from "react"; +import { X, Loader2 } from "lucide-react"; +import { Button } from "@/components/ui"; +import type { ClusterInfo } from "@/lib/tauriCommands"; +import { addClusterCmd } from "@/lib/tauriCommands"; + +interface AddClusterModalProps { + isOpen: boolean; + onClose: () => void; + onAdd: (cluster: ClusterInfo) => void; +} + +export function AddClusterModal({ isOpen, onClose, onAdd }: AddClusterModalProps) { + const [id, setId] = useState(""); + const [name, setName] = useState(""); + const [kubeconfig, setKubeconfig] = useState(""); + const [isLoading, setIsLoading] = useState(false); + const [error, setError] = useState(""); + + if (!isOpen) return null; + + const handleSubmit = async (e: React.FormEvent) => { + e.preventDefault(); + setError(""); + + if (!id.trim() || !name.trim() || !kubeconfig.trim()) { + setError("All fields are required"); + return; + } + + setIsLoading(true); + + try { + const cluster = await addClusterCmd(id, name, kubeconfig); + onAdd(cluster); + onClose(); + setId(""); + setName(""); + setKubeconfig(""); + } catch (err) { + setError(err instanceof Error ? err.message : "Failed to add cluster"); + } finally { + setIsLoading(false); + } + }; + + return ( +
+
+
+

Add Kubernetes Cluster

+ +
+ +
+ {error && ( +
+ {error} +
+ )} + +
+ + setId(e.target.value)} + placeholder="e.g., prod-cluster-01" + className="flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50" + disabled={isLoading} + /> +
+ +
+ + setName(e.target.value)} + placeholder="e.g., Production Cluster" + className="flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50" + disabled={isLoading} + /> +
+ +
+ +