import React, { useCallback, useEffect, useState } from "react"; import { MoreHorizontal, RefreshCw } from "lucide-react"; import { Button, Badge, Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter, Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from "@/components/ui"; import { helmListReleasesCmd, helmRollbackCmd, helmUninstallCmd } from "@/lib/tauriCommands"; import type { HelmRelease } from "@/lib/tauriCommands"; interface HelmReleaseListProps { clusterId: string; namespace: string; } type ConfirmAction = | { type: "rollback"; release: HelmRelease } | { type: "uninstall"; release: HelmRelease }; function statusVariant( status: string ): "success" | "destructive" | "secondary" | "default" { switch (status.toLowerCase()) { case "deployed": return "success"; case "failed": return "destructive"; case "pending-install": case "pending-upgrade": case "pending-rollback": return "default"; case "superseded": return "secondary"; default: return "secondary"; } } function statusLabel(status: string): string { return status .split("-") .map((w) => w.charAt(0).toUpperCase() + w.slice(1)) .join(" "); } export function HelmReleaseList({ clusterId, namespace }: HelmReleaseListProps) { const [releases, setReleases] = useState([]); const [loading, setLoading] = useState(false); const [error, setError] = useState(null); const [openMenuId, setOpenMenuId] = useState(null); const [confirmAction, setConfirmAction] = useState(null); const [actionInProgress, setActionInProgress] = useState(false); const [actionError, setActionError] = useState(null); const loadReleases = useCallback(async () => { setLoading(true); setError(null); try { const data = await helmListReleasesCmd(clusterId, namespace); setReleases(data); } catch (err) { setError(err instanceof Error ? err.message : String(err)); } finally { setLoading(false); } }, [clusterId, namespace]); useEffect(() => { void loadReleases(); }, [loadReleases]); const handleConfirm = async () => { if (!confirmAction) return; setActionInProgress(true); setActionError(null); try { const { release } = confirmAction; if (confirmAction.type === "rollback") { await helmRollbackCmd(clusterId, release.namespace, release.name); } else { await helmUninstallCmd(clusterId, release.namespace, release.name); setReleases((prev) => prev.filter((r) => r.name !== release.name)); } setConfirmAction(null); if (confirmAction.type === "rollback") { await loadReleases(); } } catch (err) { setActionError(err instanceof Error ? err.message : String(err)); } finally { setActionInProgress(false); } }; if (loading) { return (
Loading releases…
); } return (
{releases.length} release{releases.length !== 1 ? "s" : ""}
{error && (
{error}
)}
Name Namespace Chart Chart Version App Version Status Updated {releases.length === 0 ? ( No releases found ) : ( releases.map((release) => { const menuKey = `${release.namespace}/${release.name}`; return ( {release.name} {release.namespace} {release.chart} {release.chart_version} {release.app_version || "—"} {statusLabel(release.status)} {release.updated}
{openMenuId === menuKey && (
setOpenMenuId(null)} >
)}
); }) )}
{/* Confirm dialog */} { if (!o) setConfirmAction(null); }}> {confirmAction?.type === "rollback" ? "Rollback Release" : "Uninstall Release"}

{confirmAction?.type === "rollback" ? ( <> Roll back {confirmAction.release.name} to the previous revision? This cannot be undone without a re-deploy. ) : ( <> Permanently uninstall {confirmAction?.release.name}? All Kubernetes resources created by this release will be removed. )}

{actionError && (
{actionError}
)}
); }