mirror of https://github.com/msgbyte/tailchat
feat: admin 增加dashboard
parent
4f51ec4aa8
commit
867fbd3223
@ -0,0 +1,70 @@
|
||||
import * as React from 'react';
|
||||
import { FC, createElement } from 'react';
|
||||
import { Card, Box, Typography, Divider } from '@mui/material';
|
||||
import { Link, To } from 'react-router-dom';
|
||||
import { ReactNode } from 'react';
|
||||
import { LoadingIndicator } from 'react-admin';
|
||||
|
||||
import cartouche from './cartouche.png';
|
||||
import cartoucheDark from './cartoucheDark.png';
|
||||
|
||||
interface Props {
|
||||
icon: FC<any>;
|
||||
to: To;
|
||||
title?: string;
|
||||
subtitle?: string | number;
|
||||
children?: ReactNode;
|
||||
}
|
||||
|
||||
const CardWithIcon = (props: Props) => {
|
||||
const { icon, title, subtitle, to, children } = props;
|
||||
|
||||
return (
|
||||
<Card
|
||||
sx={{
|
||||
minHeight: 52,
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
flex: '1',
|
||||
'& a': {
|
||||
textDecoration: 'none',
|
||||
color: 'inherit',
|
||||
},
|
||||
}}
|
||||
>
|
||||
<Link to={to}>
|
||||
<Box
|
||||
sx={{
|
||||
overflow: 'inherit',
|
||||
padding: '16px',
|
||||
background: (theme) =>
|
||||
`url(${
|
||||
theme.palette.mode === 'dark' ? cartoucheDark : cartouche
|
||||
}) no-repeat`,
|
||||
display: 'flex',
|
||||
justifyContent: 'space-between',
|
||||
alignItems: 'center',
|
||||
'& .icon': {
|
||||
color: (theme) =>
|
||||
theme.palette.mode === 'dark' ? 'inherit' : '#dc2440',
|
||||
},
|
||||
}}
|
||||
>
|
||||
<Box width="3em" className="icon">
|
||||
{createElement(icon, { fontSize: 'large' })}
|
||||
</Box>
|
||||
<Box textAlign="right">
|
||||
<Typography color="textSecondary">{title}</Typography>
|
||||
<Typography variant="h5" component="h2">
|
||||
{subtitle || <LoadingIndicator />}
|
||||
</Typography>
|
||||
</Box>
|
||||
</Box>
|
||||
</Link>
|
||||
{children && <Divider />}
|
||||
{children}
|
||||
</Card>
|
||||
);
|
||||
};
|
||||
|
||||
export default CardWithIcon;
|
@ -0,0 +1,77 @@
|
||||
import React from 'react';
|
||||
import { Card, Box, Typography, CardActions, Button } from '@mui/material';
|
||||
import HomeIcon from '@mui/icons-material/Home';
|
||||
import CodeIcon from '@mui/icons-material/Code';
|
||||
import logoSvg from './logo.svg';
|
||||
|
||||
export const Welcome: React.FC = React.memo(() => {
|
||||
return (
|
||||
<Card
|
||||
sx={{
|
||||
background: (theme) =>
|
||||
theme.palette.mode === 'dark'
|
||||
? '#535353'
|
||||
: `linear-gradient(to right, #1a1d26 0%, #232c50 35%)`,
|
||||
|
||||
color: '#fff',
|
||||
padding: '20px',
|
||||
marginTop: 2,
|
||||
marginBottom: '1em',
|
||||
}}
|
||||
>
|
||||
<Box display="flex">
|
||||
<Box flex="1">
|
||||
<Typography variant="h5" component="h2" gutterBottom>
|
||||
欢迎使用 Tailchat 后台管理程序
|
||||
</Typography>
|
||||
<Box maxWidth="40em">
|
||||
<Typography variant="body1" component="p" gutterBottom>
|
||||
Tailchat 是一个完全开源的即时通讯应用
|
||||
</Typography>
|
||||
</Box>
|
||||
<CardActions
|
||||
sx={{
|
||||
padding: { xs: 0, xl: null },
|
||||
flexWrap: { xs: 'wrap', xl: null },
|
||||
'& a': {
|
||||
marginTop: { xs: '1em', xl: null },
|
||||
marginLeft: { xs: '0!important', xl: null },
|
||||
marginRight: { xs: '1em', xl: null },
|
||||
},
|
||||
}}
|
||||
>
|
||||
<Button
|
||||
variant="contained"
|
||||
href="https://tailchat.msgbyte.com/"
|
||||
startIcon={<HomeIcon />}
|
||||
target="__blank"
|
||||
>
|
||||
访问官网
|
||||
</Button>
|
||||
<Button
|
||||
variant="contained"
|
||||
href="https://github.com/msgbyte/tailchat"
|
||||
startIcon={<CodeIcon />}
|
||||
target="__blank"
|
||||
>
|
||||
浏览源码
|
||||
</Button>
|
||||
</CardActions>
|
||||
</Box>
|
||||
<Box
|
||||
display={{ xs: 'none', sm: 'none', md: 'block' }}
|
||||
sx={{
|
||||
marginLeft: 'auto',
|
||||
backgroundImage: `url(${logoSvg})`,
|
||||
backgroundSize: 'contain',
|
||||
backgroundRepeat: 'no-repeat',
|
||||
}}
|
||||
width="9em"
|
||||
height="9em"
|
||||
overflow="hidden"
|
||||
/>
|
||||
</Box>
|
||||
</Card>
|
||||
);
|
||||
});
|
||||
Welcome.displayName = 'Welcome';
|
Binary file not shown.
After Width: | Height: | Size: 1.1 KiB |
Binary file not shown.
After Width: | Height: | Size: 1.1 KiB |
@ -0,0 +1,78 @@
|
||||
import React from 'react';
|
||||
import CardWithIcon from './CardWithIcon';
|
||||
import { Welcome } from './Welcome';
|
||||
import PersonIcon from '@mui/icons-material/Person';
|
||||
import MessageIcon from '@mui/icons-material/Message';
|
||||
import GroupIcon from '@mui/icons-material/Group';
|
||||
import AttachFileIcon from '@mui/icons-material/AttachFile';
|
||||
import { useGetList } from 'react-admin';
|
||||
import { Grid } from '@mui/material';
|
||||
|
||||
export const Dashboard: React.FC = React.memo(() => {
|
||||
const { total: usersNum } = useGetList('users', {
|
||||
pagination: { page: 1, perPage: 1 },
|
||||
});
|
||||
const { total: tempUsersNum } = useGetList('users', {
|
||||
filter: { temporary: true },
|
||||
pagination: { page: 1, perPage: 1 },
|
||||
});
|
||||
const { total: messageNum } = useGetList('messages', {
|
||||
pagination: { page: 1, perPage: 1 },
|
||||
});
|
||||
const { total: groupNum } = useGetList('groups', {
|
||||
pagination: { page: 1, perPage: 1 },
|
||||
});
|
||||
const { total: fileNum } = useGetList('file', {
|
||||
pagination: { page: 1, perPage: 1 },
|
||||
});
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Welcome />
|
||||
|
||||
<Grid container spacing={2}>
|
||||
<Grid item xs={4}>
|
||||
<CardWithIcon
|
||||
to="/admin/users"
|
||||
icon={PersonIcon}
|
||||
title={'用户数'}
|
||||
subtitle={usersNum}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={4}>
|
||||
<CardWithIcon
|
||||
to="/admin/users"
|
||||
icon={PersonIcon}
|
||||
title={'临时用户数'}
|
||||
subtitle={tempUsersNum}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={4}>
|
||||
<CardWithIcon
|
||||
to="/admin/messages"
|
||||
icon={MessageIcon}
|
||||
title={'总消息数'}
|
||||
subtitle={messageNum}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={4}>
|
||||
<CardWithIcon
|
||||
to="/admin/groups"
|
||||
icon={GroupIcon}
|
||||
title={'总群组数'}
|
||||
subtitle={groupNum}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={4}>
|
||||
<CardWithIcon
|
||||
to="/admin/file"
|
||||
icon={AttachFileIcon}
|
||||
title={'总文件数'}
|
||||
subtitle={fileNum}
|
||||
/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</div>
|
||||
);
|
||||
});
|
||||
Dashboard.displayName = 'Dashboard';
|
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 16 KiB |
Loading…
Reference in New Issue