feat: cluster page ui

Signed-off-by: allanice001 <allanice001@gmail.com>
This commit is contained in:
allanice001
2025-11-17 18:21:48 +00:00
parent d163a050d8
commit 56f86a11b4
24 changed files with 1864 additions and 68 deletions

View File

@@ -2,22 +2,23 @@ import { AppShell } from "@/layouts/app-shell.tsx"
import { Route, Routes } from "react-router-dom"
import { ProtectedRoute } from "@/components/protected-route.tsx"
import { AnnotationPage } from "@/pages/annotations/annotation-page.tsx"
import { Login } from "@/pages/auth/login.tsx"
import { CredentialPage } from "@/pages/credentials/credential-page.tsx"
import { DnsPage } from "@/pages/dns/dns-page.tsx"
import { DocsPage } from "@/pages/docs/docs-page.tsx"
import { JobsPage } from "@/pages/jobs/jobs-page.tsx"
import { LabelsPage } from "@/pages/labels/labels-page.tsx"
import { LoadBalancersPage } from "@/pages/loadbalancers/load-balancers-page"
import { MePage } from "@/pages/me/me-page.tsx"
import { NodePoolsPage } from "@/pages/nodepools/node-pools-page.tsx"
import { AnnotationPage } from "@/pages/annotation-page.tsx"
import { ClustersPage } from "@/pages/cluster-page"
import { CredentialPage } from "@/pages/credential-page.tsx"
import { DnsPage } from "@/pages/dns-page.tsx"
import { DocsPage } from "@/pages/docs-page.tsx"
import { JobsPage } from "@/pages/jobs-page.tsx"
import { LabelsPage } from "@/pages/labels-page.tsx"
import { LoadBalancersPage } from "@/pages/load-balancers-page"
import { Login } from "@/pages/login.tsx"
import { MePage } from "@/pages/me-page.tsx"
import { NodePoolsPage } from "@/pages/node-pools-page.tsx"
import { OrgApiKeys } from "@/pages/org/api-keys.tsx"
import { OrgMembers } from "@/pages/org/members.tsx"
import { OrgSettings } from "@/pages/org/settings.tsx"
import { ServerPage } from "@/pages/servers/server-page.tsx"
import { SshPage } from "@/pages/ssh/ssh-page.tsx"
import { TaintsPage } from "@/pages/taints/taints-page.tsx"
import { ServerPage } from "@/pages/server-page.tsx"
import { SshPage } from "@/pages/ssh-page.tsx"
import { TaintsPage } from "@/pages/taints-page.tsx"
export default function App() {
return (
@@ -42,6 +43,7 @@ export default function App() {
<Route path="/credentials" element={<CredentialPage />} />
<Route path="/dns" element={<DnsPage />} />
<Route path="/load-balancers" element={<LoadBalancersPage />} />
<Route path="/clusters" element={<ClustersPage />} />
<Route path="/admin/jobs" element={<JobsPage />} />
</Route>

150
ui/src/api/clusters.ts Normal file
View File

@@ -0,0 +1,150 @@
import { withRefresh } from "@/api/with-refresh"
import type {
DtoAttachBastionRequest,
DtoAttachCaptainDomainRequest,
DtoAttachLoadBalancerRequest,
DtoAttachRecordSetRequest,
DtoCreateClusterRequest,
DtoSetKubeconfigRequest,
DtoUpdateClusterRequest,
} from "@/sdk"
import { makeClusterApi } from "@/sdkClient"
const clusters = makeClusterApi()
export const clustersApi = {
// --- basic CRUD ---
listClusters: (q?: string) =>
withRefresh(async () => {
return await clusters.listClusters(q ? { q } : {})
}),
getCluster: (id: string) =>
withRefresh(async () => {
return await clusters.getCluster({ clusterID: id })
}),
createCluster: (body: DtoCreateClusterRequest) =>
withRefresh(async () => {
return await clusters.createCluster({
dtoCreateClusterRequest: body,
})
}),
updateCluster: (id: string, body: DtoUpdateClusterRequest) =>
withRefresh(async () => {
return await clusters.updateCluster({
clusterID: id,
dtoUpdateClusterRequest: body,
})
}),
deleteCluster: (id: string) =>
withRefresh(async () => {
return await clusters.deleteCluster({ clusterID: id })
}),
// --- kubeconfig ---
setKubeconfig: (clusterID: string, body: DtoSetKubeconfigRequest) =>
withRefresh(async () => {
return await clusters.setClusterKubeconfig({
clusterID,
dtoSetKubeconfigRequest: body,
})
}),
clearKubeconfig: (clusterID: string) =>
withRefresh(async () => {
return await clusters.clearClusterKubeconfig({ clusterID })
}),
// --- captain domain ---
attachCaptainDomain: (clusterID: string, body: DtoAttachCaptainDomainRequest) =>
withRefresh(async () => {
return await clusters.attachCaptainDomain({
clusterID,
dtoAttachCaptainDomainRequest: body,
})
}),
detachCaptainDomain: (clusterID: string) =>
withRefresh(async () => {
return await clusters.detachCaptainDomain({ clusterID })
}),
// --- control plane record set ---
attachControlPlaneRecordSet: (clusterID: string, body: DtoAttachRecordSetRequest) =>
withRefresh(async () => {
return await clusters.attachControlPlaneRecordSet({
clusterID,
dtoAttachRecordSetRequest: body,
})
}),
detachControlPlaneRecordSet: (clusterID: string) =>
withRefresh(async () => {
return await clusters.detachControlPlaneRecordSet({ clusterID })
}),
// --- load balancers ---
attachAppsLoadBalancer: (clusterID: string, body: DtoAttachLoadBalancerRequest) =>
withRefresh(async () => {
return await clusters.attachAppsLoadBalancer({
clusterID,
dtoAttachLoadBalancerRequest: body,
})
}),
detachAppsLoadBalancer: (clusterID: string) =>
withRefresh(async () => {
return await clusters.detachAppsLoadBalancer({ clusterID })
}),
attachGlueOpsLoadBalancer: (clusterID: string, body: DtoAttachLoadBalancerRequest) =>
withRefresh(async () => {
return await clusters.attachGlueOpsLoadBalancer({
clusterID,
dtoAttachLoadBalancerRequest: body,
})
}),
detachGlueOpsLoadBalancer: (clusterID: string) =>
withRefresh(async () => {
return await clusters.detachGlueOpsLoadBalancer({ clusterID })
}),
// --- bastion ---
attachBastion: (clusterID: string, body: DtoAttachBastionRequest) =>
withRefresh(async () => {
return await clusters.attachBastionServer({
clusterID,
dtoAttachBastionRequest: body,
})
}),
detachBastion: (clusterID: string) =>
withRefresh(async () => {
return await clusters.detachBastionServer({ clusterID })
}),
// -- node-pools
attachNodePool: (clusterID: string, nodePoolID: string) =>
withRefresh(async () => {
return await clusters.attachNodePool({
clusterID,
dtoAttachNodePoolRequest: { node_pool_id: nodePoolID },
})
}),
detachNodePool: (clusterID: string, nodePoolID: string) =>
withRefresh(async () => {
return await clusters.detachNodePool({ clusterID, nodePoolID })
}),
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,28 +1,66 @@
import { useMemo, useState } from "react";
import { credentialsApi } from "@/api/credentials";
import { zodResolver } from "@hookform/resolvers/zod";
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { AlertTriangle, Eye, Loader2, MoreHorizontal, Pencil, Plus, Search, Trash2 } from "lucide-react";
import { Controller, useForm } from "react-hook-form";
import { toast } from "sonner";
import { z } from "zod";
import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, AlertDialogTrigger } from "@/components/ui/alert-dialog";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle, DialogTrigger } from "@/components/ui/dialog";
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from "@/components/ui/dropdown-menu";
import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "@/components/ui/form";
import { Input } from "@/components/ui/input";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { Switch } from "@/components/ui/switch";
import { Textarea } from "@/components/ui/textarea";
import { useMemo, useState } from "react"
import { credentialsApi } from "@/api/credentials"
import { zodResolver } from "@hookform/resolvers/zod"
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"
import {
AlertTriangle,
Eye,
Loader2,
MoreHorizontal,
Pencil,
Plus,
Search,
Trash2,
} from "lucide-react"
import { Controller, useForm } from "react-hook-form"
import { toast } from "sonner"
import { z } from "zod"
import {
AlertDialog,
AlertDialogAction,
AlertDialogCancel,
AlertDialogContent,
AlertDialogDescription,
AlertDialogFooter,
AlertDialogHeader,
AlertDialogTitle,
AlertDialogTrigger,
} from "@/components/ui/alert-dialog"
import { Badge } from "@/components/ui/badge"
import { Button } from "@/components/ui/button"
import {
Dialog,
DialogContent,
DialogFooter,
DialogHeader,
DialogTitle,
DialogTrigger,
} from "@/components/ui/dialog"
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu"
import {
Form,
FormControl,
FormField,
FormItem,
FormLabel,
FormMessage,
} from "@/components/ui/form"
import { Input } from "@/components/ui/input"
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/components/ui/select"
import { Switch } from "@/components/ui/switch"
import { Textarea } from "@/components/ui/textarea"
// -------------------- Constants --------------------