Deployments
This commit is contained in:
+27
-140
@@ -12,95 +12,37 @@ import {
|
|||||||
Plus,
|
Plus,
|
||||||
GitBranch,
|
GitBranch,
|
||||||
} from "lucide-react";
|
} from "lucide-react";
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
const deployments = [
|
import { Deployment } from "@/lib/types";
|
||||||
{
|
import { getDeployments } from "@/core/server/deployment";
|
||||||
id: "dep-001",
|
import { getApplications } from "@/core/application";
|
||||||
app: "api-gateway",
|
|
||||||
version: "v2.4.1",
|
|
||||||
previousVersion: "v2.4.0",
|
|
||||||
status: "running" as const,
|
|
||||||
deployedAt: "2024-01-15 14:32:18",
|
|
||||||
deployedBy: "ci/github-actions",
|
|
||||||
duration: "45s",
|
|
||||||
replicas: "3/3",
|
|
||||||
strategy: "rolling",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "dep-002",
|
|
||||||
app: "auth-service",
|
|
||||||
version: "v1.8.0",
|
|
||||||
previousVersion: "v1.7.9",
|
|
||||||
status: "running" as const,
|
|
||||||
deployedAt: "2024-01-15 14:18:42",
|
|
||||||
deployedBy: "[email protected]",
|
|
||||||
duration: "32s",
|
|
||||||
replicas: "2/2",
|
|
||||||
strategy: "rolling",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "dep-003",
|
|
||||||
app: "worker-queue",
|
|
||||||
version: "v3.1.2",
|
|
||||||
previousVersion: "v3.1.1",
|
|
||||||
status: "pending" as const,
|
|
||||||
deployedAt: "2024-01-15 13:58:05",
|
|
||||||
deployedBy: "ci/github-actions",
|
|
||||||
duration: "—",
|
|
||||||
replicas: "3/4",
|
|
||||||
strategy: "rolling",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "dep-004",
|
|
||||||
app: "metrics-collector",
|
|
||||||
version: "v1.2.0",
|
|
||||||
previousVersion: "v1.1.8",
|
|
||||||
status: "error" as const,
|
|
||||||
deployedAt: "2024-01-15 13:42:11",
|
|
||||||
deployedBy: "ci/github-actions",
|
|
||||||
duration: "—",
|
|
||||||
replicas: "0/2",
|
|
||||||
strategy: "rolling",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "dep-005",
|
|
||||||
app: "postgres-db",
|
|
||||||
version: "15-alpine",
|
|
||||||
previousVersion: "14-alpine",
|
|
||||||
status: "running" as const,
|
|
||||||
deployedAt: "2024-01-10 09:15:33",
|
|
||||||
deployedBy: "[email protected]",
|
|
||||||
duration: "2m 18s",
|
|
||||||
replicas: "1/1",
|
|
||||||
strategy: "recreate",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "dep-006",
|
|
||||||
app: "redis-cache",
|
|
||||||
version: "7-alpine",
|
|
||||||
previousVersion: "7-alpine",
|
|
||||||
status: "running" as const,
|
|
||||||
deployedAt: "2024-01-08 16:45:22",
|
|
||||||
deployedBy: "[email protected]",
|
|
||||||
duration: "18s",
|
|
||||||
replicas: "1/1",
|
|
||||||
strategy: "recreate",
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
export default function DeploymentsPage() {
|
export default function DeploymentsPage() {
|
||||||
|
const [deployments, setDeployments] = useState<Deployment[]>([]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const fetch = async () => {
|
||||||
|
setDeployments(
|
||||||
|
(await getDeployments(await getApplications())).filter(
|
||||||
|
(d) => d !== null
|
||||||
|
)
|
||||||
|
);
|
||||||
|
};
|
||||||
|
fetch();
|
||||||
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DashboardLayout
|
<DashboardLayout
|
||||||
title="Deployments"
|
title="Deployments"
|
||||||
subtitle="Deployment history and management"
|
subtitle="Deployment history and management"
|
||||||
>
|
>
|
||||||
{/* Header */}
|
{/* Header */}
|
||||||
<div className="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between mb-6">
|
<div className="flex flex-row gap-3 items-center justify-between mb-6">
|
||||||
<Badge>{deployments.length} deployments</Badge>
|
<Badge>{deployments.length} deployments</Badge>
|
||||||
|
|
||||||
<Button size="sm" className="gap-2 self-start sm:self-auto">
|
<Button size="sm" className="gap-2 self-auto">
|
||||||
<Plus className="w-4 h-4" />
|
<Plus className="w-4 h-4" />
|
||||||
<span className="hidden sm:inline">New Deployment</span>
|
New Deployment
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -111,16 +53,7 @@ export default function DeploymentsPage() {
|
|||||||
<table className="w-full">
|
<table className="w-full">
|
||||||
<thead>
|
<thead>
|
||||||
<tr className="border-b border-border">
|
<tr className="border-b border-border">
|
||||||
{[
|
{["Application", "Status", "Actions"].map((h) => (
|
||||||
"Application",
|
|
||||||
"Version",
|
|
||||||
"Status",
|
|
||||||
"Replicas",
|
|
||||||
"Deployed",
|
|
||||||
"Duration",
|
|
||||||
"Deployed By",
|
|
||||||
"Actions",
|
|
||||||
].map((h) => (
|
|
||||||
<th
|
<th
|
||||||
key={h}
|
key={h}
|
||||||
className={`text-left text-xs text-muted-foreground uppercase tracking-wider py-3 px-4 ${
|
className={`text-left text-xs text-muted-foreground uppercase tracking-wider py-3 px-4 ${
|
||||||
@@ -134,42 +67,16 @@ export default function DeploymentsPage() {
|
|||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{deployments.map((dep) => (
|
{deployments.map((dep) => (
|
||||||
<tr key={dep.id} className="data-table-row">
|
<tr key={dep.image} className="data-table-row">
|
||||||
<td className="py-3 px-4">
|
<td className="py-3 px-4">
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<Rocket className="w-4 h-4 text-muted-foreground" />
|
<Rocket className="w-4 h-4 text-muted-foreground" />
|
||||||
<span className="font-mono text-sm">{dep.app}</span>
|
<span className="font-mono text-sm">{dep.image}</span>
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
|
|
||||||
<td className="py-3 px-4">
|
|
||||||
<div className="flex items-center gap-2">
|
|
||||||
<GitBranch className="w-3 h-3 text-muted-foreground" />
|
|
||||||
<span className="font-mono text-sm">{dep.version}</span>
|
|
||||||
<span className="text-[10px] text-muted-foreground">
|
|
||||||
← {dep.previousVersion}
|
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
<td className="py-3 px-4">{dep.status}</td>
|
<td className="py-3 px-4">{dep.status}</td>
|
||||||
|
|
||||||
<td className="py-3 px-4 font-mono text-sm">
|
|
||||||
{dep.replicas}
|
|
||||||
</td>
|
|
||||||
|
|
||||||
<td className="py-3 px-4 font-mono text-xs text-muted-foreground">
|
|
||||||
{dep.deployedAt}
|
|
||||||
</td>
|
|
||||||
|
|
||||||
<td className="py-3 px-4 font-mono text-xs">
|
|
||||||
{dep.duration}
|
|
||||||
</td>
|
|
||||||
|
|
||||||
<td className="py-3 px-4 text-xs text-muted-foreground">
|
|
||||||
{dep.deployedBy}
|
|
||||||
</td>
|
|
||||||
|
|
||||||
<td className="py-3 px-4">
|
<td className="py-3 px-4">
|
||||||
<div className="flex items-center justify-end gap-1">
|
<div className="flex items-center justify-end gap-1">
|
||||||
<Button variant="ghost" size="icon-sm">
|
<Button variant="ghost" size="icon-sm">
|
||||||
@@ -192,41 +99,21 @@ export default function DeploymentsPage() {
|
|||||||
{/* Mobile cards */}
|
{/* Mobile cards */}
|
||||||
<div className="md:hidden divide-y divide-border">
|
<div className="md:hidden divide-y divide-border">
|
||||||
{deployments.map((dep) => (
|
{deployments.map((dep) => (
|
||||||
<div key={dep.id} className="p-4 space-y-3">
|
<div key={dep.image} className="p-4 space-y-3">
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<Rocket className="w-4 h-4 text-muted-foreground" />
|
<Rocket className="w-4 h-4 text-muted-foreground" />
|
||||||
<span className="font-mono text-sm">{dep.app}</span>
|
<span className="font-mono text-sm">{dep.image}</span>
|
||||||
</div>
|
</div>
|
||||||
{dep.status}
|
{dep.status}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex items-center gap-2 text-xs">
|
{/* <div className="grid grid-cols-2 gap-2 text-xs">
|
||||||
<GitBranch className="w-3 h-3 text-muted-foreground" />
|
|
||||||
<span className="font-mono">{dep.version}</span>
|
|
||||||
<span className="text-muted-foreground">
|
|
||||||
← {dep.previousVersion}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="grid grid-cols-2 gap-2 text-xs">
|
|
||||||
<div>
|
|
||||||
<span className="text-muted-foreground">Replicas</span>
|
|
||||||
<div className="font-mono">{dep.replicas}</div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<span className="text-muted-foreground">Duration</span>
|
|
||||||
<div className="font-mono">{dep.duration}</div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<span className="text-muted-foreground">Deployed</span>
|
|
||||||
<div className="font-mono">{dep.deployedAt}</div>
|
|
||||||
</div>
|
|
||||||
<div>
|
<div>
|
||||||
<span className="text-muted-foreground">By</span>
|
<span className="text-muted-foreground">By</span>
|
||||||
<div className="truncate">{dep.deployedBy}</div>
|
<div className="truncate">{dep.deployedBy}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div> */}
|
||||||
|
|
||||||
<div className="flex justify-end gap-1 pt-2">
|
<div className="flex justify-end gap-1 pt-2">
|
||||||
<Button variant="ghost" size="icon-sm">
|
<Button variant="ghost" size="icon-sm">
|
||||||
|
|||||||
Reference in New Issue
Block a user