diff --git a/src/components/layout/Aside.tsx b/src/components/layout/Aside.tsx index 36aad4bbd..c856a4e31 100644 --- a/src/components/layout/Aside.tsx +++ b/src/components/layout/Aside.tsx @@ -1,5 +1,5 @@ import { Aside as MantineAside, Group } from '@mantine/core'; -import { WeatherModule, DateModule, CalendarModule, TotalDownloadsModule } from '../modules'; +import { WeatherModule, DateModule, CalendarModule, TotalDownloadsModule, SystemModule } from '../modules'; import { ModuleWrapper } from '../modules/moduleWrapper'; export default function Aside(props: any) { @@ -20,6 +20,7 @@ export default function Aside(props: any) { + ); diff --git a/src/components/modules/index.ts b/src/components/modules/index.ts index 410bf3b56..f7396ed66 100644 --- a/src/components/modules/index.ts +++ b/src/components/modules/index.ts @@ -4,3 +4,4 @@ export * from './search'; export * from './ping'; export * from './weather'; export * from './downloads'; +export * from './system'; diff --git a/src/components/modules/system/SystemModule.tsx b/src/components/modules/system/SystemModule.tsx new file mode 100644 index 000000000..bcbc179f8 --- /dev/null +++ b/src/components/modules/system/SystemModule.tsx @@ -0,0 +1,46 @@ +import { Center, Group, RingProgress, Title } from '@mantine/core'; +import { Cpu } from 'tabler-icons-react'; +import { useEffect, useState } from 'react'; +import axios from 'axios'; +import si from 'systeminformation'; +import { IModule } from '../modules'; + +export const SystemModule: IModule = { + title: 'System info', + description: 'Show the current CPU usage and memory usage', + icon: Cpu, + component: SystemInfo, +}; + +interface ApiResponse { + cpu: si.Systeminformation.CpuData; + os: si.Systeminformation.OsData; + memory: si.Systeminformation.MemData; + load: si.Systeminformation.CurrentLoadData; +} + +export default function SystemInfo(args: any) { + const [data, setData] = useState(); + // Refresh data every 5 seconds + useEffect(() => { + axios.get('/api/modules/systeminfo').then((res) => setData(res.data)); + setInterval(() => { + axios.get('/api/modules/systeminfo').then((res) => setData(res.data)); + }, 3 * 1000); + }, []); + + return ( +
+ + Current CPU load + {`${data?.load?.currentLoad.toFixed(2)}%`}
} + thickness={12} + roundCaps + sections={[{ value: data?.load?.currentLoad ?? 0, color: 'cyan' }]} + /> + + + ); +} diff --git a/src/components/modules/system/index.ts b/src/components/modules/system/index.ts new file mode 100644 index 000000000..75d1a257e --- /dev/null +++ b/src/components/modules/system/index.ts @@ -0,0 +1 @@ +export { SystemModule } from './SystemModule'; diff --git a/src/pages/api/modules/systeminfo.ts b/src/pages/api/modules/systeminfo.ts new file mode 100644 index 000000000..2e4537e32 --- /dev/null +++ b/src/pages/api/modules/systeminfo.ts @@ -0,0 +1,30 @@ +import { NextApiRequest, NextApiResponse } from 'next'; +import si from 'systeminformation'; + +async function Get(req: NextApiRequest, res: NextApiResponse) { + const [osInfo, cpuInfo, memInfo, cpuLoad] = await Promise.all([ + si.osInfo(), + si.cpu(), + si.mem(), + si.currentLoad(), + ]); + + const sysinfo = { + cpu: cpuInfo, + os: osInfo, + mem: memInfo, + load: cpuLoad, + }; + res.status(200).json(sysinfo); +} + +export default async (req: NextApiRequest, res: NextApiResponse) => { + // Filter out if the reuqest is a POST or a GET + if (req.method === 'GET') { + return Get(req, res); + } + return res.status(405).json({ + statusCode: 405, + message: 'Method not allowed', + }); +};