diff --git a/README.md b/README.md index a95d5d8..f99cd06 100644 --- a/README.md +++ b/README.md @@ -2,5 +2,7 @@ This is the frontend of a web wrapper for Coop Clouds abra CLI, letting users set up and manage VPSs and docker images through a web UI. +## Still a work in progess! + ## This is built with react, typescript, scss, and vite diff --git a/src/App.tsx b/src/App.tsx index 4a4fe47..eea1522 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -6,6 +6,7 @@ import { Dashboard } from './routes/Authenticated/Dashboard/Dashboard'; import { Apps } from './routes/Authenticated/Apps/Apps'; import { AppDetail } from './routes/Authenticated/Apps/App'; import { Servers } from './routes/Authenticated/Servers/Servers'; +import { Server} from './routes/Authenticated/Servers/Server'; function App() { return ( @@ -52,6 +53,15 @@ function App() { } /> + + + + } + /> + {/* Redirect root to dashboard */} } /> diff --git a/src/routes/Authenticated/Apps/App.tsx b/src/routes/Authenticated/Apps/App.tsx index 77fc491..a71b48d 100644 --- a/src/routes/Authenticated/Apps/App.tsx +++ b/src/routes/Authenticated/Apps/App.tsx @@ -102,7 +102,7 @@ export const AppDetail: React.FC = () => {
{error || 'App not found'}
@@ -130,7 +130,7 @@ export const AppDetail: React.FC = () => { {app.recipe} {app.status} {app.chaos === 'true' && ( - πŸ”¬ Chaos + Chaos )} @@ -254,7 +254,7 @@ export const AppDetail: React.FC = () => { {app.upgrade === 'latest' && (
- βœ… Running latest version + Running latest version
)} @@ -272,7 +272,6 @@ export const AppDetail: React.FC = () => { onClick={() => handleAction('start')} disabled={actionLoading === 'start'} > - ▢️ Start Application @@ -281,27 +280,22 @@ export const AppDetail: React.FC = () => { onClick={() => handleAction('stop')} disabled={actionLoading === 'stop'} > - ⏸️ Stop Application diff --git a/src/routes/Authenticated/Apps/Apps.tsx b/src/routes/Authenticated/Apps/Apps.tsx index fafe941..f0aadb0 100644 --- a/src/routes/Authenticated/Apps/Apps.tsx +++ b/src/routes/Authenticated/Apps/Apps.tsx @@ -200,9 +200,9 @@ export const Apps: React.FC = () => { ) : ( - filteredApps.map((app, index) => ( + filteredApps.map((app) => ( navigate(`/apps/${app.server}/${app.appName}`)} style={{ cursor: 'pointer' }} > @@ -234,7 +234,7 @@ export const Apps: React.FC = () => {
{app.version} {app.chaos === 'true' && ( - ☠️ + )} {app.upgrade !== 'latest' && ( diff --git a/src/routes/Authenticated/Dashboard/Dashboard.tsx b/src/routes/Authenticated/Dashboard/Dashboard.tsx index 67cd754..96b3317 100644 --- a/src/routes/Authenticated/Dashboard/Dashboard.tsx +++ b/src/routes/Authenticated/Dashboard/Dashboard.tsx @@ -90,7 +90,7 @@ export const Dashboard: React.FC = () => {
- + + + ); + } + + const chaosApps = server.apps.filter(app => app.chaos === 'true'); + const runningApps = server.apps.filter(app => app.status === 'deployed' || app.status === 'running'); + + return ( +
+
+
+
+ + / + {server.name} +
+ +
+
+

{server.name}

+
+ {server.host} + {server.upgradeCount > 0 && ( + + {server.upgradeCount} upgrade{server.upgradeCount !== 1 ? 's' : ''} + + )} +
+
+ +
+ + +
+
+ +
+ {/* Left Column - Main Info */} +
+
+

Server Details

+ +
+
+ + {server.name} +
+ +
+ + {server.host} +
+ +
+ + {server.appCount} +
+ +
+ + {runningApps.length} +
+ +
+ + 0 ? 'stat-value warning' : 'stat-value'}> + {server.upgradeCount} + +
+ +
+ + 0 ? 'stat-value chaos' : 'stat-value'}> + {chaosApps.length} + +
+ +
+ + {server.latestCount} +
+ +
+ + {server.versionCount} +
+
+
+ +
+

Applications on this Server

+ + {server.apps.length === 0 ? ( +
No applications deployed on this server
+ ) : ( +
+ {server.apps.map((app, idx) => ( +
navigate(`/apps/${server.name}/${app.appName}`)} + > +
+ {app.appName} +
+ {app.recipe} + + {app.status} + + {app.chaos === 'true' && ( + + )} + {app.upgrade !== 'latest' && ( + + )} +
+
+
+ v{app.version} + {app.domain && ( + e.stopPropagation()} + > + {app.domain} + + )} +
+
+ ))} +
+ )} +
+
+ + {/* Right Column - Actions & Stats */} +
+
+

Quick Actions

+ +
+ + + + + + + + + + + + + +
+
+ +
+

Server Health

+
+
+ Status + Online +
+
+ CPU Usage + β€” +
+
+ Memory + β€” +
+
+ Disk Space + β€” +
+
+ Uptime + β€” +
+
+
+
+
+
+
+ ); +}; \ No newline at end of file diff --git a/src/routes/Authenticated/Servers/Servers.tsx b/src/routes/Authenticated/Servers/Servers.tsx index b7c1cbb..95c369a 100644 --- a/src/routes/Authenticated/Servers/Servers.tsx +++ b/src/routes/Authenticated/Servers/Servers.tsx @@ -1,4 +1,5 @@ import React, { useEffect, useMemo, useState } from 'react'; +import { useNavigate } from 'react-router-dom'; import { Header } from '../../../components/Header/Header'; import { apiService } from '../../../services/api'; import type { AbraServer, ServerAppsResponse } from '../../../types'; @@ -13,6 +14,7 @@ interface ServerWithStats extends AbraServer { } export const Servers: React.FC = () => { + const navigate = useNavigate(); const [servers, setServers] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(''); @@ -199,7 +201,12 @@ export const Servers: React.FC = () => {
No servers found matching your search
) : ( filteredServers.map((server) => ( -
+
navigate(`/servers/${server.name}`)} + style={{ cursor: 'pointer' }} + >

{server.name}

@@ -226,7 +233,7 @@ export const Servers: React.FC = () => { {server.upgradeCount > 0 && (
- Need Upgrade + ⬆️ Need Upgrade {server.upgradeCount}
@@ -242,13 +249,29 @@ export const Servers: React.FC = () => {
- - + +
{server.upgradeCount > 0 && (
- + ⚠️ {server.upgradeCount} app{server.upgradeCount > 1 ? 's' : ''} can be upgraded diff --git a/src/services/mockApi.ts b/src/services/mockApi.ts index c2fb09d..0d12c80 100644 --- a/src/services/mockApi.ts +++ b/src/services/mockApi.ts @@ -27,17 +27,6 @@ export const mockAppsData: ServerAppsResponse = { version: "3.4.2+v3.4.5", upgrade: "3.6.2+v3.4.5\n3.6.1+v3.4.5" }, - { - server: "mydomain.com", - recipe: "authentik", - appName: "accounts.mydomain.com", - domain: "accounts.mydomain.com", - status: "deployed", - chaos: "false", - chaosVersion: "unknown", - version: "7.4.0+2025.6.3", - upgrade: "9.0.1+2025.8.1\n9.0.0+2025.8.1" - }, { server: "mydomain.com", recipe: "authentik", @@ -72,21 +61,10 @@ export const mockAppsData: ServerAppsResponse = { upgrade: "4.0.0+25.04.4.1.1\n3.3.0+24.04.13.3.1" }, { - server: "mydomain.com", - recipe: "nextcloud", - appName: "nc.mydomain.com", - domain: "nc.mydomain.com", - status: "deployed", - chaos: "false", - chaosVersion: "unknown", - version: "12.0.1+31.0.6-fpm", - upgrade: "latest" - }, - { - server: "mydomain.com", + server: "myotherdomain.com", recipe: "traefik", - appName: "traefik.mydomain.com", - domain: "traefik.mydomain.com", + appName: "traefik.myotherdomain.com", + domain: "traefik.myotherdomain.com", status: "deployed", chaos: "false", chaosVersion: "unknown", @@ -134,10 +112,6 @@ export const mockAppsData: ServerAppsResponse = { }; export const mockServers: AbraServer[] = [ - { - name: 'mydomain.com', - host: 'mydomain.com', - }, { name: 'test.coop', host: 'test.coop',