refactor: move dashboard components into app folder

This commit is contained in:
Nicolas Meienberger 2023-09-10 13:59:58 +02:00
parent 944b886148
commit 5b493a79d9
10 changed files with 47 additions and 77 deletions

View File

@ -0,0 +1,28 @@
'use client';
import { IconCircuitResistor, IconCpu, IconDatabase } from '@tabler/icons-react';
import React from 'react';
import { useTranslations } from 'next-intl';
import { SystemStat } from '../SystemStat';
type IProps = {
diskUsed: number;
diskSize: number;
percentUsed: number;
cpuLoad: number;
memoryTotal: number;
percentUsedMemory: number;
};
export const DashboardContainer: React.FC<IProps> = (props) => {
const { diskUsed, diskSize, percentUsed, cpuLoad, memoryTotal, percentUsedMemory } = props;
const t = useTranslations('dashboard');
return (
<div className="row row-deck row-cards">
<SystemStat title={t('cards.disk.title')} metric={`${diskUsed} GB`} subtitle={t('cards.disk.subtitle', { total: diskSize })} icon={IconDatabase} progress={percentUsed} />
<SystemStat title={t('cards.cpu.title')} metric={`${cpuLoad.toFixed(2)}%`} subtitle={t('cards.cpu.subtitle')} icon={IconCpu} progress={cpuLoad} />
<SystemStat title={t('cards.memory.title')} metric={`${percentUsedMemory || 0}%`} subtitle={`${memoryTotal} GB`} icon={IconCircuitResistor} progress={percentUsedMemory} />
</div>
);
};

View File

@ -11,7 +11,7 @@ interface IProps {
isLoading?: boolean;
}
const SystemStat: React.FC<IProps> = ({ icon: IconComponent, progress, title, subtitle, metric, isLoading }) => (
export const SystemStat: React.FC<IProps> = ({ icon: IconComponent, progress, title, subtitle, metric, isLoading }) => (
<div className="col-sm-6 col-lg-4">
<div className="card">
<div className="card-body">
@ -38,5 +38,3 @@ const SystemStat: React.FC<IProps> = ({ icon: IconComponent, progress, title, su
</div>
</div>
);
export default SystemStat;

View File

@ -0,0 +1 @@
export { SystemStat } from './SystemStat';

View File

@ -1,18 +1,30 @@
import { DashboardContainer } from '@/client/modules/Dashboard/containers';
import { useUIStore } from '@/client/state/uiStore';
import { getTranslatorFromCookie } from '@/lib/get-translator';
import { SystemServiceClass } from '@/server/services/system';
import { Metadata } from 'next';
import React from 'react';
import { DashboardContainer } from './components/DashboardContainer';
export async function generateMetadata(): Promise<Metadata> {
const { translator } = useUIStore.getState();
const translator = await getTranslatorFromCookie();
return {
title: `${translator('dashboard.title')} - Tipi`,
};
}
export default async function Page() {
export default async function DashboardPage() {
const data = SystemServiceClass.systemInfo();
const { disk, memory, cpu } = data;
return <DashboardContainer data={data} isLoading={false} />;
// Convert bytes to GB
const diskFree = Math.round(disk.available / 1024 / 1024 / 1024);
const diskSize = Math.round(disk.total / 1024 / 1024 / 1024);
const diskUsed = diskSize - diskFree;
const percentUsed = Math.round((diskUsed / diskSize) * 100);
const memoryTotal = Math.round(Number(memory.total) / 1024 / 1024 / 1024);
const memoryFree = Math.round(Number(memory.available) / 1024 / 1024 / 1024);
const percentUsedMemory = Math.round(((memoryTotal - memoryFree) / memoryTotal) * 100);
return <DashboardContainer diskUsed={diskUsed} diskSize={diskSize} percentUsed={percentUsed} cpuLoad={cpu.load} memoryTotal={memoryTotal} percentUsedMemory={percentUsedMemory} />;
}

View File

@ -1,37 +0,0 @@
'use client';
import { IconCircuitResistor, IconCpu, IconDatabase } from '@tabler/icons-react';
import React from 'react';
import { useTranslations } from 'next-intl';
import { SystemRouterOutput } from '../../../../server/routers/system/system.router';
import SystemStat from '../components/SystemStat';
type IProps = { data?: SystemRouterOutput['systemInfo']; isLoading: boolean };
const defaultData: SystemRouterOutput['systemInfo'] = {
cpu: { load: 0 },
disk: { available: 0, total: 0, used: 0 },
memory: { available: 0, total: 0, used: 0 },
};
export const DashboardContainer: React.FC<IProps> = ({ data = defaultData, isLoading }) => {
const { disk, memory, cpu } = data;
const t = useTranslations('dashboard');
// Convert bytes to GB
const diskFree = Math.round(disk.available / 1024 / 1024 / 1024);
const diskSize = Math.round(disk.total / 1024 / 1024 / 1024);
const diskUsed = diskSize - diskFree;
const percentUsed = Math.round((diskUsed / diskSize) * 100);
const memoryTotal = Math.round(Number(memory.total) / 1024 / 1024 / 1024);
const memoryFree = Math.round(Number(memory.available) / 1024 / 1024 / 1024);
const percentUsedMemory = Math.round(((memoryTotal - memoryFree) / memoryTotal) * 100);
return (
<div className="row row-deck row-cards">
<SystemStat isLoading={isLoading} title={t('cards.disk.title')} metric={`${diskUsed} GB`} subtitle={t('cards.disk.subtitle', { total: diskSize })} icon={IconDatabase} progress={percentUsed} />
<SystemStat isLoading={isLoading} title={t('cards.cpu.title')} metric={`${cpu.load.toFixed(2)}%`} subtitle={t('cards.cpu.subtitle')} icon={IconCpu} progress={cpu.load} />
<SystemStat isLoading={isLoading} title={t('cards.memory.title')} metric={`${percentUsedMemory || 0}%`} subtitle={`${memoryTotal} GB`} icon={IconCircuitResistor} progress={percentUsedMemory} />
</div>
);
};

View File

@ -1,11 +0,0 @@
import React from 'react';
import { render, screen } from '../../../../../../tests/test-utils';
import { DashboardPage } from './DashboardPage';
describe('Test: DashboardPage', () => {
it('should render', async () => {
// Arrange
render(<DashboardPage />);
expect(screen.getByTestId('dashboard-layout')).toBeInTheDocument();
});
});

View File

@ -1,20 +0,0 @@
import React from 'react';
import type { NextPage } from 'next';
import { useTranslations } from 'next-intl';
import type { MessageKey } from '@/server/utils/errors';
import { DashboardContainer } from '../../containers/DashboardContainer';
import { trpc } from '../../../../utils/trpc';
import { Layout } from '../../../../components/Layout';
import { ErrorPage } from '../../../../components/ui/ErrorPage';
export const DashboardPage: NextPage = () => {
const t = useTranslations();
const { data, error, isLoading } = trpc.system.systemInfo.useQuery();
return (
<Layout title={t('dashboard.title')}>
<DashboardContainer data={data} isLoading={isLoading} />
{error && <ErrorPage error={t(error.data?.tError.message as MessageKey, { ...error.data?.tError.variables })} />}
</Layout>
);
};

View File

@ -1 +0,0 @@
export { DashboardPage } from './DashboardPage';