mirror of
https://github.com/CyberL1/dlinux-dashboard.git
synced 2025-01-22 01:19:18 -05:00
feat(frontend): start doing container page
This commit is contained in:
parent
f4161b4f47
commit
9fa7f57a14
221
frontend/package-lock.json
generated
221
frontend/package-lock.json
generated
@ -12,6 +12,7 @@
|
||||
"@emotion/styled": "^11.13.5",
|
||||
"@fontsource/roboto": "^5.1.0",
|
||||
"@mui/icons-material": "^6.1.8",
|
||||
"@mui/lab": "^6.0.0-beta.23",
|
||||
"@mui/material": "^6.1.8",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
@ -19,6 +20,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@biomejs/biome": "^1.9.4",
|
||||
"@types/dockerode": "^3.3.34",
|
||||
"@types/node": "^22.9.3",
|
||||
"@types/react": "^18.2.66",
|
||||
"@types/react-dom": "^18.2.22",
|
||||
@ -1154,6 +1156,44 @@
|
||||
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@floating-ui/core": {
|
||||
"version": "1.6.9",
|
||||
"resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.9.tgz",
|
||||
"integrity": "sha512-uMXCuQ3BItDUbAMhIXw7UPXRfAlOAvZzdK9BWpE60MCn+Svt3aLn9jsPTi/WNGlRUu2uI0v5S7JiIUsbsvh3fw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@floating-ui/utils": "^0.2.9"
|
||||
}
|
||||
},
|
||||
"node_modules/@floating-ui/dom": {
|
||||
"version": "1.6.13",
|
||||
"resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.13.tgz",
|
||||
"integrity": "sha512-umqzocjDgNRGTuO7Q8CU32dkHkECqI8ZdMZ5Swb6QAM0t5rnlrN3lGo1hdpscRd3WS8T6DKYK4ephgIH9iRh3w==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@floating-ui/core": "^1.6.0",
|
||||
"@floating-ui/utils": "^0.2.9"
|
||||
}
|
||||
},
|
||||
"node_modules/@floating-ui/react-dom": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.2.tgz",
|
||||
"integrity": "sha512-06okr5cgPzMNBy+Ycse2A6udMi4bqwW/zgBF/rwjcNqWkyr82Mcg8b0vjX8OJpZFy/FKjJmw6wV7t44kK6kW7A==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@floating-ui/dom": "^1.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": ">=16.8.0",
|
||||
"react-dom": ">=16.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@floating-ui/utils": {
|
||||
"version": "0.2.9",
|
||||
"resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.9.tgz",
|
||||
"integrity": "sha512-MDWhGtE+eHw5JW7lq4qhc5yRLS11ERl1c7Z6Xd0a58DozHES6EnNNwUWbMiG4J9Cgj053Bhk8zvlhFYKVhULwg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@fontsource/roboto": {
|
||||
"version": "5.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@fontsource/roboto/-/roboto-5.1.1.tgz",
|
||||
@ -1275,10 +1315,42 @@
|
||||
"@jridgewell/sourcemap-codec": "^1.4.14"
|
||||
}
|
||||
},
|
||||
"node_modules/@mui/base": {
|
||||
"version": "5.0.0-beta.68",
|
||||
"resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-beta.68.tgz",
|
||||
"integrity": "sha512-F1JMNeLS9Qhjj3wN86JUQYBtJoXyQvknxlzwNl6eS0ZABo1MiohMONj3/WQzYPSXIKC2bS/ZbyBzdHhi2GnEpA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.26.0",
|
||||
"@floating-ui/react-dom": "^2.1.1",
|
||||
"@mui/types": "^7.2.20",
|
||||
"@mui/utils": "^6.3.0",
|
||||
"@popperjs/core": "^2.11.8",
|
||||
"clsx": "^2.1.1",
|
||||
"prop-types": "^15.8.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/mui-org"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0",
|
||||
"react": "^17.0.0 || ^18.0.0 || ^19.0.0",
|
||||
"react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@mui/core-downloads-tracker": {
|
||||
"version": "6.3.1",
|
||||
"resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-6.3.1.tgz",
|
||||
"integrity": "sha512-2OmnEyoHpj5//dJJpMuxOeLItCCHdf99pjMFfUFdBteCunAK9jW+PwEo4mtdGcLs7P+IgZ+85ypd52eY4AigoQ==",
|
||||
"version": "6.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-6.4.0.tgz",
|
||||
"integrity": "sha512-6u74wi+9zeNlukrCtYYET8Ed/n9AS27DiaXCZKAD3TRGFaqiyYSsQgN2disW83pI/cM1Q2lJY1JX4YfwvNtlNw==",
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
@ -1311,17 +1383,62 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@mui/material": {
|
||||
"version": "6.3.1",
|
||||
"resolved": "https://registry.npmjs.org/@mui/material/-/material-6.3.1.tgz",
|
||||
"integrity": "sha512-ynG9ayhxgCsHJ/dtDcT1v78/r2GwQyP3E0hPz3GdPRl0uFJz/uUTtI5KFYwadXmbC+Uv3bfB8laZ6+Cpzh03gA==",
|
||||
"node_modules/@mui/lab": {
|
||||
"version": "6.0.0-beta.23",
|
||||
"resolved": "https://registry.npmjs.org/@mui/lab/-/lab-6.0.0-beta.23.tgz",
|
||||
"integrity": "sha512-fqiC33bhhRifYgLD0mFef5fBM+OydZNK33ddwHwubDyrYzXz58OpSm4lXQJh2d6YHL7wXpOFKSot1CbgbItyYg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.26.0",
|
||||
"@mui/core-downloads-tracker": "^6.3.1",
|
||||
"@mui/system": "^6.3.1",
|
||||
"@mui/base": "5.0.0-beta.68",
|
||||
"@mui/system": "^6.4.0",
|
||||
"@mui/types": "^7.2.21",
|
||||
"@mui/utils": "^6.3.1",
|
||||
"@mui/utils": "^6.4.0",
|
||||
"clsx": "^2.1.1",
|
||||
"prop-types": "^15.8.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/mui-org"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@emotion/react": "^11.5.0",
|
||||
"@emotion/styled": "^11.3.0",
|
||||
"@mui/material": "^6.4.0",
|
||||
"@mui/material-pigment-css": "^6.4.0",
|
||||
"@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0",
|
||||
"react": "^17.0.0 || ^18.0.0 || ^19.0.0",
|
||||
"react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@emotion/react": {
|
||||
"optional": true
|
||||
},
|
||||
"@emotion/styled": {
|
||||
"optional": true
|
||||
},
|
||||
"@mui/material-pigment-css": {
|
||||
"optional": true
|
||||
},
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@mui/material": {
|
||||
"version": "6.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@mui/material/-/material-6.4.0.tgz",
|
||||
"integrity": "sha512-hNIgwdM9U3DNmowZ8mU59oFmWoDKjc92FqQnQva3Pxh6xRKWtD2Ej7POUHMX8Dwr1OpcSUlT2+tEMeLb7WYsIg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.26.0",
|
||||
"@mui/core-downloads-tracker": "^6.4.0",
|
||||
"@mui/system": "^6.4.0",
|
||||
"@mui/types": "^7.2.21",
|
||||
"@mui/utils": "^6.4.0",
|
||||
"@popperjs/core": "^2.11.8",
|
||||
"@types/react-transition-group": "^4.4.12",
|
||||
"clsx": "^2.1.1",
|
||||
@ -1340,7 +1457,7 @@
|
||||
"peerDependencies": {
|
||||
"@emotion/react": "^11.5.0",
|
||||
"@emotion/styled": "^11.3.0",
|
||||
"@mui/material-pigment-css": "^6.3.1",
|
||||
"@mui/material-pigment-css": "^6.4.0",
|
||||
"@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0",
|
||||
"react": "^17.0.0 || ^18.0.0 || ^19.0.0",
|
||||
"react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0"
|
||||
@ -1361,13 +1478,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@mui/private-theming": {
|
||||
"version": "6.3.1",
|
||||
"resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-6.3.1.tgz",
|
||||
"integrity": "sha512-g0u7hIUkmXmmrmmf5gdDYv9zdAig0KoxhIQn1JN8IVqApzf/AyRhH3uDGx5mSvs8+a1zb4+0W6LC260SyTTtdQ==",
|
||||
"version": "6.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-6.4.0.tgz",
|
||||
"integrity": "sha512-rNHci8MP6NOdEWAfZ/RBMO5Rhtp1T6fUDMSmingg9F1T6wiUeodIQ+NuTHh2/pMoUSeP9GdHdgMhMmfsXxOMuw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.26.0",
|
||||
"@mui/utils": "^6.3.1",
|
||||
"@mui/utils": "^6.4.0",
|
||||
"prop-types": "^15.8.1"
|
||||
},
|
||||
"engines": {
|
||||
@ -1388,9 +1505,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@mui/styled-engine": {
|
||||
"version": "6.3.1",
|
||||
"resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-6.3.1.tgz",
|
||||
"integrity": "sha512-/7CC0d2fIeiUxN5kCCwYu4AWUDd9cCTxWCyo0v/Rnv6s8uk6hWgJC3VLZBoDENBHf/KjqDZuYJ2CR+7hD6QYww==",
|
||||
"version": "6.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-6.4.0.tgz",
|
||||
"integrity": "sha512-ek/ZrDujrger12P6o4luQIfRd2IziH7jQod2WMbLqGE03Iy0zUwYmckRTVhRQTLPNccpD8KXGcALJF+uaUQlbg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.26.0",
|
||||
@ -1422,16 +1539,16 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@mui/system": {
|
||||
"version": "6.3.1",
|
||||
"resolved": "https://registry.npmjs.org/@mui/system/-/system-6.3.1.tgz",
|
||||
"integrity": "sha512-AwqQ3EAIT2np85ki+N15fF0lFXX1iFPqenCzVOSl3QXKy2eifZeGd9dGtt7pGMoFw5dzW4dRGGzRpLAq9rkl7A==",
|
||||
"version": "6.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@mui/system/-/system-6.4.0.tgz",
|
||||
"integrity": "sha512-wTDyfRlaZCo2sW2IuOsrjeE5dl0Usrs6J7DxE3GwNCVFqS5wMplM2YeNiV3DO7s53RfCqbho+gJY6xaB9KThUA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.26.0",
|
||||
"@mui/private-theming": "^6.3.1",
|
||||
"@mui/styled-engine": "^6.3.1",
|
||||
"@mui/private-theming": "^6.4.0",
|
||||
"@mui/styled-engine": "^6.4.0",
|
||||
"@mui/types": "^7.2.21",
|
||||
"@mui/utils": "^6.3.1",
|
||||
"@mui/utils": "^6.4.0",
|
||||
"clsx": "^2.1.1",
|
||||
"csstype": "^3.1.3",
|
||||
"prop-types": "^15.8.1"
|
||||
@ -1476,9 +1593,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@mui/utils": {
|
||||
"version": "6.3.1",
|
||||
"resolved": "https://registry.npmjs.org/@mui/utils/-/utils-6.3.1.tgz",
|
||||
"integrity": "sha512-sjGjXAngoio6lniQZKJ5zGfjm+LD2wvLwco7FbKe1fu8A7VIFmz2SwkLb+MDPLNX1lE7IscvNNyh1pobtZg2tw==",
|
||||
"version": "6.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@mui/utils/-/utils-6.4.0.tgz",
|
||||
"integrity": "sha512-woOTATWNsTNR3YBh2Ixkj3l5RaxSiGoC9G8gOpYoFw1mZM77LWJeuMHFax7iIW4ahK0Cr35TF9DKtrafJmOmNQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.26.0",
|
||||
@ -1870,6 +1987,29 @@
|
||||
"integrity": "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/docker-modem": {
|
||||
"version": "3.0.6",
|
||||
"resolved": "https://registry.npmjs.org/@types/docker-modem/-/docker-modem-3.0.6.tgz",
|
||||
"integrity": "sha512-yKpAGEuKRSS8wwx0joknWxsmLha78wNMe9R2S3UNsVOkZded8UqOrV8KoeDXoXsjndxwyF3eIhyClGbO1SEhEg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/node": "*",
|
||||
"@types/ssh2": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/dockerode": {
|
||||
"version": "3.3.34",
|
||||
"resolved": "https://registry.npmjs.org/@types/dockerode/-/dockerode-3.3.34.tgz",
|
||||
"integrity": "sha512-mH9SuIb8NuTDsMus5epcbTzSbEo52fKLBMo0zapzYIAIyfDqoIFn7L3trekHLKC8qmxGV++pPUP4YqQ9n5v2Zg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/docker-modem": "*",
|
||||
"@types/node": "*",
|
||||
"@types/ssh2": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/estree": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz",
|
||||
@ -1928,6 +2068,33 @@
|
||||
"@types/react": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/ssh2": {
|
||||
"version": "1.15.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/ssh2/-/ssh2-1.15.4.tgz",
|
||||
"integrity": "sha512-9JTQgVBWSgq6mAen6PVnrAmty1lqgCMvpfN+1Ck5WRUsyMYPa6qd50/vMJ0y1zkGpOEgLzm8m8Dx/Y5vRouLaA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/node": "^18.11.18"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/ssh2/node_modules/@types/node": {
|
||||
"version": "18.19.70",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.70.tgz",
|
||||
"integrity": "sha512-RE+K0+KZoEpDUbGGctnGdkrLFwi1eYKTlIHNl2Um98mUkGsm1u2Ff6Ltd0e8DktTtC98uy7rSj+hO8t/QuLoVQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"undici-types": "~5.26.4"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/ssh2/node_modules/undici-types": {
|
||||
"version": "5.26.5",
|
||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
|
||||
"integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@typescript-eslint/eslint-plugin": {
|
||||
"version": "7.18.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.18.0.tgz",
|
||||
|
@ -14,6 +14,7 @@
|
||||
"@emotion/styled": "^11.13.5",
|
||||
"@fontsource/roboto": "^5.1.0",
|
||||
"@mui/icons-material": "^6.1.8",
|
||||
"@mui/lab": "^6.0.0-beta.23",
|
||||
"@mui/material": "^6.1.8",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
@ -21,6 +22,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@biomejs/biome": "^1.9.4",
|
||||
"@types/dockerode": "^3.3.34",
|
||||
"@types/node": "^22.9.3",
|
||||
"@types/react": "^18.2.66",
|
||||
"@types/react-dom": "^18.2.22",
|
||||
|
@ -6,6 +6,9 @@ import { createBrowserRouter, RouterProvider } from "react-router";
|
||||
import Containers, {
|
||||
Loader as ContainersLoader,
|
||||
} from "./pages/containers/index.tsx";
|
||||
import ContainerPage, {
|
||||
Loader as ContainerPageLoader,
|
||||
} from "./pages/containers/[name].tsx";
|
||||
|
||||
const router = createBrowserRouter([
|
||||
{
|
||||
@ -18,6 +21,11 @@ const router = createBrowserRouter([
|
||||
element: <Containers />,
|
||||
loader: ContainersLoader,
|
||||
},
|
||||
{
|
||||
path: "/containers/:name",
|
||||
element: <ContainerPage />,
|
||||
loader: ContainerPageLoader,
|
||||
},
|
||||
],
|
||||
},
|
||||
]);
|
||||
|
88
frontend/src/pages/containers/[name].tsx
Normal file
88
frontend/src/pages/containers/[name].tsx
Normal file
@ -0,0 +1,88 @@
|
||||
import { useLoaderData, useRevalidator } from "react-router";
|
||||
import { Container } from "../../types";
|
||||
import { Button, ButtonGroup, Paper, Typography } from "@mui/material";
|
||||
import { useEffect, useState } from "react";
|
||||
import { ContainerStats } from "dockerode";
|
||||
|
||||
interface Params {
|
||||
name: string;
|
||||
}
|
||||
|
||||
export async function Loader({ params }: { params: Params }) {
|
||||
const container = await fetch(`/api/containers/${params.name}`);
|
||||
|
||||
const data = await container.json();
|
||||
return data;
|
||||
}
|
||||
|
||||
export default function ContainerPage() {
|
||||
const container = useLoaderData() as Container & { statusCode: number };
|
||||
|
||||
if (container.statusCode === 404) {
|
||||
return "Container not found";
|
||||
}
|
||||
|
||||
const [stats, setStats] = useState<ContainerStats>();
|
||||
|
||||
useEffect(() => {
|
||||
const statsSource = new EventSource(
|
||||
`/api/containers/${container.name}/stats`,
|
||||
);
|
||||
|
||||
statsSource.onmessage = ({ data }) => {
|
||||
const parsed = JSON.parse(data);
|
||||
setStats(parsed);
|
||||
};
|
||||
|
||||
return () => {
|
||||
statsSource.close();
|
||||
};
|
||||
}, []);
|
||||
|
||||
console.log("stats", stats);
|
||||
const revalidator = useRevalidator();
|
||||
const [isPowerStateLocked, setPowerStateLocked] = useState<boolean>();
|
||||
|
||||
return (
|
||||
<Paper square sx={{ padding: 1 }}>
|
||||
<Paper sx={{ display: "flex" }} variant="outlined">
|
||||
<Typography variant="h6" sx={{ flexGrow: 1 }}>
|
||||
Managing: {container.name}
|
||||
</Typography>
|
||||
<ButtonGroup>
|
||||
<Button
|
||||
loading={isPowerStateLocked}
|
||||
onClick={async () => {
|
||||
await switchPowerState(
|
||||
container.status === "running" ? "stop" : "start",
|
||||
);
|
||||
}}
|
||||
>
|
||||
Power {container.status === "running" ? "off" : "on"}
|
||||
</Button>
|
||||
<Button
|
||||
onClick={async () => await switchPowerState("restart")}
|
||||
loading={isPowerStateLocked}
|
||||
disabled={container.status === "exited"}
|
||||
>
|
||||
Restart
|
||||
</Button>
|
||||
</ButtonGroup>
|
||||
</Paper>
|
||||
CPU Usage: {stats?.cpu_stats.cpu_usage.total_usage}
|
||||
</Paper>
|
||||
);
|
||||
|
||||
async function switchPowerState(state: string) {
|
||||
setPowerStateLocked(true);
|
||||
|
||||
const res = await fetch(`/api/containers/${container.name}/${state}`, {
|
||||
method: "PUT",
|
||||
});
|
||||
|
||||
if (res.ok) {
|
||||
setPowerStateLocked(false);
|
||||
revalidator.revalidate();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
import { useLoaderData, useNavigate } from "react-router";
|
||||
import { useLoaderData } from "react-router";
|
||||
import { Container } from "../../types";
|
||||
import {
|
||||
Button,
|
||||
@ -18,7 +18,6 @@ export async function Loader() {
|
||||
|
||||
export default function Containers() {
|
||||
const containers = useLoaderData() as Container[];
|
||||
const navigate = useNavigate();
|
||||
|
||||
return (
|
||||
<>
|
||||
@ -39,16 +38,7 @@ export default function Containers() {
|
||||
Status: {container.status}
|
||||
</CardContent>
|
||||
<CardActions>
|
||||
<Button
|
||||
onClick={async () =>
|
||||
await switchPower(
|
||||
container.id,
|
||||
container.status === "running" ? "stop" : "start",
|
||||
)
|
||||
}
|
||||
>
|
||||
Power {container.status === "running" ? "off" : "on"}
|
||||
</Button>
|
||||
<Button href={`/containers/${container.name}`}>Manage</Button>
|
||||
<Button
|
||||
href={`//${container.name}.${document.location.host}`}
|
||||
target="_blank"
|
||||
@ -62,9 +52,4 @@ export default function Containers() {
|
||||
</Grid>
|
||||
</>
|
||||
);
|
||||
|
||||
async function switchPower(id: string, state: string) {
|
||||
await fetch(`/api/containers/${id}/${state}`, { method: "PUT" });
|
||||
navigate(".", { replace: true });
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user