feat: use translation keys for the dashboard
This commit is contained in:
parent
f19508bdf2
commit
17dd675035
5 changed files with 36 additions and 15 deletions
|
@ -5,6 +5,7 @@ import clsx from 'clsx';
|
|||
import Link from 'next/link';
|
||||
import { useRouter } from 'next/router';
|
||||
import { Tooltip } from 'react-tooltip';
|
||||
import { useTranslations } from 'next-intl';
|
||||
import { getUrl } from '../../../core/helpers/url-helpers';
|
||||
import { useUIStore } from '../../../state/uiStore';
|
||||
import { NavBar } from '../NavBar';
|
||||
|
@ -24,6 +25,7 @@ export const Header: React.FC<IProps> = ({ isUpdateAvailable }) => {
|
|||
router.push('/login');
|
||||
},
|
||||
});
|
||||
const t = useTranslations('header');
|
||||
|
||||
return (
|
||||
<header className="navbar navbar-expand-md navbar-dark navbar-overlap d-print-none">
|
||||
|
@ -54,24 +56,24 @@ export const Header: React.FC<IProps> = ({ isUpdateAvailable }) => {
|
|||
<div className="btn-list">
|
||||
<a href="https://github.com/meienberger/runtipi" target="_blank" rel="noreferrer" className="btn btn-dark">
|
||||
<IconBrandGithub data-testid="icon-github" className="me-1 icon" size={24} />
|
||||
Source code
|
||||
{t('source-code')}
|
||||
</a>
|
||||
<a href="https://github.com/meienberger/runtipi?sponsor=1" target="_blank" rel="noreferrer" className="btn btn-dark">
|
||||
<IconHeart className="me-1 icon text-pink" size={24} />
|
||||
Sponsor
|
||||
{t('sponsor')}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div style={{ zIndex: 1 }} className="d-flex">
|
||||
<Tooltip anchorSelect=".darkMode">Dark mode</Tooltip>
|
||||
<Tooltip anchorSelect=".darkMode">{t('dark-mode')}</Tooltip>
|
||||
<div onClick={() => setDarkMode(true)} role="button" aria-hidden="true" className="darkMode nav-link px-0 hide-theme-dark cursor-pointer" data-testid="dark-mode-toggle">
|
||||
<IconMoon data-testid="icon-moon" size={20} />
|
||||
</div>
|
||||
<Tooltip anchorSelect=".lightMode">Light mode</Tooltip>
|
||||
<Tooltip anchorSelect=".lightMode">{t('light-mode')}</Tooltip>
|
||||
<div onClick={() => setDarkMode(false)} aria-hidden="true" className="lightMode nav-link px-0 hide-theme-light cursor-pointer" data-testid="light-mode-toggle">
|
||||
<IconSun data-testid="icon-sun" size={20} />
|
||||
</div>
|
||||
<Tooltip anchorSelect=".logOut">Log out</Tooltip>
|
||||
<Tooltip anchorSelect=".logOut">{t('logout')}</Tooltip>
|
||||
<div onClick={() => logout.mutate()} tabIndex={0} onKeyPress={() => logout.mutate()} role="button" className="logOut nav-link px-0 cursor-pointer" data-testid="logout-button">
|
||||
<IconLogout size={20} />
|
||||
</div>
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import { IconApps, IconBrandAppstore, IconHome, IconSettings, Icon } from '@tabler/icons-react';
|
||||
import clsx from 'clsx';
|
||||
import { useTranslations } from 'next-intl';
|
||||
import Link from 'next/link';
|
||||
import { useRouter } from 'next/router';
|
||||
import React from 'react';
|
||||
|
@ -9,6 +10,7 @@ interface IProps {
|
|||
}
|
||||
|
||||
export const NavBar: React.FC<IProps> = ({ isUpdateAvailable }) => {
|
||||
const t = useTranslations('header');
|
||||
const router = useRouter();
|
||||
const path = router.pathname.split('/')[1];
|
||||
|
||||
|
@ -32,12 +34,12 @@ export const NavBar: React.FC<IProps> = ({ isUpdateAvailable }) => {
|
|||
<div id="navbar-menu" className="collapse navbar-collapse" style={{}}>
|
||||
<div className="d-flex flex-column flex-md-row flex-fill align-items-stretch align-items-md-center">
|
||||
<ul className="navbar-nav">
|
||||
{renderItem('Dashboard', '', IconHome)}
|
||||
{renderItem('My Apps', 'apps', IconApps)}
|
||||
{renderItem('App Store', 'app-store', IconBrandAppstore)}
|
||||
{renderItem('Settings', 'settings', IconSettings)}
|
||||
{renderItem(t('dashboard'), '', IconHome)}
|
||||
{renderItem(t('my-apps'), 'apps', IconApps)}
|
||||
{renderItem(t('app-store'), 'app-store', IconBrandAppstore)}
|
||||
{renderItem(t('settings'), 'settings', IconSettings)}
|
||||
</ul>
|
||||
{Boolean(isUpdateAvailable) && <span className="ms-2 badge bg-green d-none d-lg-block">Update available</span>}
|
||||
{Boolean(isUpdateAvailable) && <span className="ms-2 badge bg-green d-none d-lg-block">{t('update-available')}</span>}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -87,5 +87,17 @@
|
|||
"subtitle": "Uninstall apps to reduce load"
|
||||
}
|
||||
}
|
||||
},
|
||||
"header": {
|
||||
"dashboard": "Dashboard",
|
||||
"my-apps": "My Apps",
|
||||
"app-store": "App Store",
|
||||
"settings": "Settings",
|
||||
"logout": "Logout",
|
||||
"dark-mode": "Dark Mode",
|
||||
"light-mode": "Light Mode",
|
||||
"sponsor": "Sponsor",
|
||||
"source-code": "Source code",
|
||||
"update-available": "Update available"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
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';
|
||||
|
||||
|
@ -7,6 +8,7 @@ type IProps = { data: SystemRouterOutput['systemInfo'] };
|
|||
|
||||
export const DashboardContainer: React.FC<IProps> = ({ data }) => {
|
||||
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);
|
||||
|
@ -19,9 +21,9 @@ export const DashboardContainer: React.FC<IProps> = ({ data }) => {
|
|||
|
||||
return (
|
||||
<div className="row row-deck row-cards">
|
||||
<SystemStat title="Disk space" metric={`${diskUsed} GB`} subtitle={`Used out of ${diskSize} GB`} icon={IconDatabase} progress={percentUsed} />
|
||||
<SystemStat title="CPU Load" metric={`${cpu.load.toFixed(2)}%`} subtitle="Uninstall apps if there is to much load" icon={IconCpu} progress={cpu.load} />
|
||||
<SystemStat title="Memory Used" metric={`${percentUsedMemory || 0}%`} subtitle={`${memoryTotal} GB`} icon={IconCircuitResistor} progress={percentUsedMemory} />
|
||||
<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={`${cpu.load.toFixed(2)}%`} subtitle={t('cards.cpu.subtitle')} icon={IconCpu} progress={cpu.load} />
|
||||
<SystemStat title={t('cards.memory.title')} metric={`${percentUsedMemory || 0}%`} subtitle={`${memoryTotal} GB`} icon={IconCircuitResistor} progress={percentUsedMemory} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -1,17 +1,20 @@
|
|||
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 } = trpc.system.systemInfo.useQuery();
|
||||
|
||||
return (
|
||||
<Layout title="Dashboard">
|
||||
<Layout title={t('dashboard.title')}>
|
||||
{data && <DashboardContainer data={data} />}
|
||||
{error && <ErrorPage error={error.message} />}
|
||||
{error && <ErrorPage error={t(error.data?.translatedError || (error.message as MessageKey))} />}
|
||||
</Layout>
|
||||
);
|
||||
};
|
||||
|
|
Loading…
Add table
Reference in a new issue