diff --git a/src/app/applications/page.tsx b/src/app/applications/page.tsx new file mode 100644 index 0000000..2b71156 --- /dev/null +++ b/src/app/applications/page.tsx @@ -0,0 +1,87 @@ +"use client"; + +import { DashboardLayout } from "@/components/dashboard/DashboardLayout"; +import { + Card, + CardContent, + CardDescription, + CardFooter, + CardHeader, + CardTitle, +} from "@/components/ui/card"; +import { Badge } from "@/components/ui/badge"; +import { Button } from "@/components/ui/button"; +import { MoreVertical, Plus, Rocket } from "lucide-react"; +import InstallApplicationDialog from "@/components/dialogs/InstallApplication"; +import { getApplications, removeApp } from "@/lib/dockship/application"; +import RemoveDialog from "@/components/dialogs/Remove"; +import DeployAppDialog from "@/components/dialogs/DeployApp"; +import { useAsyncInterval } from "@/hooks/use-async"; + +export default function ApplicationsPage() { + const { value: applications, setValue: setApplications } = useAsyncInterval( + [], + getApplications, + 3000 + ); + + const remove = async (appId: string) => { + await removeApp(appId); + setApplications((prev) => prev.filter((app) => app.id !== appId)); + }; + + return ( + + {/* Header */} +
+
+ {applications.length} apps +
+ + + +
+
+ {applications.map((app) => ( + + + {app.name} + {app.repo} + + + + {/* Deployments */} +
+ + Deployments + + + {app.deployments?.length ?? 0} + +
+
+ + + + + + + remove(app.id)} /> + + + +
+ ))} +
+
+ ); +} diff --git a/src/lib/dockship/application.ts b/src/lib/dockship/application.ts index 9ac56ea..479af46 100644 --- a/src/lib/dockship/application.ts +++ b/src/lib/dockship/application.ts @@ -4,6 +4,7 @@ import { verifySession } from "../../core/auth/session"; import { getNodes } from "@/lib/dockship/node"; import axios from "axios"; import { Env, EnvVariable, Application } from "@/lib/types"; +import { read, write } from "@/app/api/file"; export async function installApp(name: string, repo: string, nodeId: string) { if (await verifySession()) { @@ -26,63 +27,53 @@ export async function installApp(name: string, repo: string, nodeId: string) { } export async function getApplications(): Promise { - const nodes = await getNodes(); + if (await verifySession()) { + throw new Error("Unauthorized"); + } - return ( - await Promise.all( - nodes.map( - async (n) => - await ( - await axios.get(`http://${n.ip}:3000/api/applications`, { - headers: { Authorization: `ApiKey ${n.key}` }, - }) - ).data.applications - ) - ) - ).flat(); + return read(() => [], "data", "apps.json"); } export async function getEnv(): Promise> { - const nodes = await getNodes(); + const apps = await getApplications(); - const envRecords = await Promise.all( - nodes.map(async (n) => { - const response = await axios.get(`http://${n.ip}:3000/api/env`, { - headers: { Authorization: `ApiKey ${n.key}` }, - }); - return response.data as Record; - }) - ); + return apps.reduce>((acc, app) => { + acc[app.id] = { + id: app.id, + name: app.name, + variables: app.env, + }; - const merged: Record = Object.assign({}, ...envRecords); - - return merged; + return acc; + }, {}); } export async function setEnv( appId: string, variables: Record ) { - const nodes = await getNodes(); + if (await verifySession()) { + throw new Error("Unauthorized"); + } - nodes.forEach(async (n) => { - await axios.post( - `http://${n.ip}:3000/api/env`, - { appId, variables }, - { - headers: { Authorization: `ApiKey ${n.key}` }, - } - ); - }); + const apps = await getApplications(); + const app = apps.find((app) => app.id === appId); + if (!app) throw new Error("App not found"); + editApp(appId, { ...app, env: variables }); } export async function removeApp(appId: string) { - const nodes = await getNodes(); + const apps = await getApplications(); - nodes.forEach(async (n) => { - await axios.delete(`http://${n.ip}:3000/api/applications`, { - params: { appId }, - headers: { Authorization: `ApiKey ${n.key}` }, - }); - }); + const nextApps = apps.filter((app) => app.id !== appId); + + await write(nextApps, "data", "apps.json"); +} + +export async function editApp(appId: string, updatedApp: Application) { + const apps = await getApplications(); + + const nextApps = apps.map((app) => (app.id === appId ? updatedApp : app)); + + await write(nextApps, "data", "apps.json"); } diff --git a/src/lib/types.ts b/src/lib/types.ts index 0691c4a..7853d2d 100644 --- a/src/lib/types.ts +++ b/src/lib/types.ts @@ -55,6 +55,7 @@ export interface Application { nodeId: string; createdAt: string; deployments: string[]; + env: Record; } export interface Deployment {