From 791ee1488ee0bedebed98616c67ee51d6e1a63aa Mon Sep 17 00:00:00 2001 From: Jake Turner Date: Wed, 20 Aug 2025 20:54:39 -0700 Subject: [PATCH] feat(Settings): display system information --- admin/app/controllers/settings_controller.ts | 8 +- admin/app/controllers/system_controller.ts | 4 + admin/app/services/system_service.ts | 24 ++ admin/inertia/pages/settings/system.tsx | 356 ++++--------------- admin/package-lock.json | 27 ++ admin/package.json | 1 + admin/start/routes.ts | 1 + admin/types/system.ts | 9 + 8 files changed, 130 insertions(+), 300 deletions(-) create mode 100644 admin/types/system.ts diff --git a/admin/app/controllers/settings_controller.ts b/admin/app/controllers/settings_controller.ts index eb8a165..3eee416 100644 --- a/admin/app/controllers/settings_controller.ts +++ b/admin/app/controllers/settings_controller.ts @@ -9,11 +9,11 @@ export default class SettingsController { ) { } async system({ inertia }: HttpContext) { - // const services = await this.systemService.getServices(); + const systemInfo = await this.systemService.getSystemInfo(); return inertia.render('settings/system', { - // system: { - // services - // } + system: { + info: systemInfo + } }); } diff --git a/admin/app/controllers/system_controller.ts b/admin/app/controllers/system_controller.ts index 1d75388..6dd26d2 100644 --- a/admin/app/controllers/system_controller.ts +++ b/admin/app/controllers/system_controller.ts @@ -11,6 +11,10 @@ export default class SystemController { private dockerService: DockerService ) { } + async getSystemInfo({ }: HttpContext) { + return await this.systemService.getSystemInfo(); + } + async getServices({ }: HttpContext) { return await this.systemService.getServices({ installedOnly: true }); } diff --git a/admin/app/services/system_service.ts b/admin/app/services/system_service.ts index 027cc62..7e5305c 100644 --- a/admin/app/services/system_service.ts +++ b/admin/app/services/system_service.ts @@ -2,6 +2,9 @@ import Service from "#models/service" import { inject } from "@adonisjs/core"; import { DockerService } from "#services/docker_service"; import { ServiceSlim } from "../../types/services.js"; +import logger from "@adonisjs/core/services/logger"; +import si from 'systeminformation'; +import { SystemInformationResponse } from "../../types/system.js"; @inject() export class SystemService { @@ -41,4 +44,25 @@ export class SystemService { return toReturn; } + + async getSystemInfo(): Promise { + try { + const [cpu, mem, os, disk] = await Promise.all([ + si.cpu(), + si.mem(), + si.osInfo(), + si.diskLayout() + ]);; + + return { + cpu, + mem, + os, + disk + }; + } catch (error) { + logger.error('Error getting system info:', error); + return undefined; + } + } } \ No newline at end of file diff --git a/admin/inertia/pages/settings/system.tsx b/admin/inertia/pages/settings/system.tsx index 06cf09f..f664c2d 100644 --- a/admin/inertia/pages/settings/system.tsx +++ b/admin/inertia/pages/settings/system.tsx @@ -1,307 +1,71 @@ -import { useState } from 'react' -import { Bars3Icon, MagnifyingGlassIcon } from '@heroicons/react/20/solid' -import { ChevronDownIcon } from '@heroicons/react/16/solid' import { Head } from '@inertiajs/react' import SettingsLayout from '~/layouts/SettingsLayout' +import { SystemInformationResponse } from '../../../types/system' +import { IconPaperclip } from '@tabler/icons-react' +import { formatBytes } from '~/lib/util' -export default function SettingsPage() { +const Section = ({ title, children }: { title: string; children: React.ReactNode }) => { + return ( +
+

{title}

+
+
{children}
+
+
+ ) +} + +const Row = ({ label, value }: { label: string; value: string | number | undefined }) => { + return ( +
+
{label}
+
{value}
+
+ ) +} + +export default function SettingsPage(props: { + system: { info: SystemInformationResponse | undefined } +}) { + console.log(props.system.info) return ( -
- {/* Sticky search header */} - {/*
- - -
-
- +
+

System Information

+
+
+ + + + +
+
+ + + + -
-
*/} - -
-

Settings

- {/* Settings forms */} -
-
-
-

Personal Information

-

- Use a permanent address where you can receive mail. -

-
- -
-
-
- -
- -

JPG, GIF or PNG. 1MB max.

-
-
- -
- -
- -
-
- -
- -
- -
-
- -
- -
- -
-
- -
- -
-
-
- example.com/ -
- -
-
-
- -
- -
- -
-
+ +
+ + + + + +
+
+ {props.system.info?.disk.map((disk, index) => ( +
+ + +
- -
- -
- -
- -
-
-

Change password

-

- Update your password associated with your account. -

-
- -
-
-
- -
- -
-
- -
- -
- -
-
- -
- -
- -
-
-
- -
- -
-
-
- -
-
-

Log out other sessions

-

- Please enter your password to confirm you would like to log out of your other - sessions across all of your devices. -

-
- -
-
-
- -
- -
-
-
- -
- -
-
-
- -
-
-

Delete account

-

- No longer want to use our service? You can delete your account here. This action - is not reversible. All information related to this account will be deleted - permanently. -

-
- -
- -
-
+ ))} +
diff --git a/admin/package-lock.json b/admin/package-lock.json index f225f8a..3dc258d 100644 --- a/admin/package-lock.json +++ b/admin/package-lock.json @@ -46,6 +46,7 @@ "react-adonis-transmit": "^1.0.1", "react-dom": "^19.1.0", "reflect-metadata": "^0.2.2", + "systeminformation": "^5.27.7", "tailwindcss": "^4.1.10", "yaml": "^2.8.0" }, @@ -10494,6 +10495,32 @@ "url": "https://opencollective.com/synckit" } }, + "node_modules/systeminformation": { + "version": "5.27.7", + "resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.27.7.tgz", + "integrity": "sha512-saaqOoVEEFaux4v0K8Q7caiauRwjXC4XbD2eH60dxHXbpKxQ8kH9Rf7Jh+nryKpOUSEFxtCdBlSUx0/lO6rwRg==", + "license": "MIT", + "os": [ + "darwin", + "linux", + "win32", + "freebsd", + "openbsd", + "netbsd", + "sunos", + "android" + ], + "bin": { + "systeminformation": "lib/cli.js" + }, + "engines": { + "node": ">=8.0.0" + }, + "funding": { + "type": "Buy me a coffee", + "url": "https://www.buymeacoffee.com/systeminfo" + } + }, "node_modules/tabbable": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.2.0.tgz", diff --git a/admin/package.json b/admin/package.json index 757fc37..e1a1ad5 100644 --- a/admin/package.json +++ b/admin/package.json @@ -92,6 +92,7 @@ "react-adonis-transmit": "^1.0.1", "react-dom": "^19.1.0", "reflect-metadata": "^0.2.2", + "systeminformation": "^5.27.7", "tailwindcss": "^4.1.10", "yaml": "^2.8.0" }, diff --git a/admin/start/routes.ts b/admin/start/routes.ts index 3d6f650..9c9054b 100644 --- a/admin/start/routes.ts +++ b/admin/start/routes.ts @@ -43,6 +43,7 @@ router.group(() => { }).prefix('/api/docs') router.group(() => { + router.get('/info', [SystemController, 'getSystemInfo']) router.get('/services', [SystemController, 'getServices']) router.post('/services/affect', [SystemController, 'affectService']) router.post('/services/install', [SystemController, 'installService']) diff --git a/admin/types/system.ts b/admin/types/system.ts new file mode 100644 index 0000000..6bbf251 --- /dev/null +++ b/admin/types/system.ts @@ -0,0 +1,9 @@ +import { Systeminformation } from "systeminformation" + + +export type SystemInformationResponse = { + cpu: Systeminformation.CpuData + mem: Systeminformation.MemData + os: Systeminformation.OsData + disk: Systeminformation.DiskLayoutData[] +} \ No newline at end of file