reorganize server dashboard into categories
This commit is contained in:
parent
180f722ed3
commit
b077943e41
4 changed files with 233 additions and 123 deletions
|
@ -5,7 +5,7 @@ import '@revoltchat/ui/src/styles/dark.css';
|
|||
import '@revoltchat/ui/src/styles/common.css';
|
||||
import RequireAuth from './components/RequireAuth';
|
||||
import DashboardHome from './pages/DashboardHome';
|
||||
import ServerDashboard from './pages/ServerDashboard';
|
||||
import ServerDashboard from './pages/ServerDashboard/ServerDashboard';
|
||||
|
||||
const API_URL = import.meta.env.VITE_API_URL?.toString()
|
||||
|| 'http://localhost:9000';
|
||||
|
|
20
web/src/components/CategorySelector.tsx
Normal file
20
web/src/components/CategorySelector.tsx
Normal file
|
@ -0,0 +1,20 @@
|
|||
import { FunctionComponent, useState } from "react";
|
||||
import './styles/CategorySelector.css';
|
||||
|
||||
const CategorySelector: FunctionComponent<{ keys: { id: string, name: string }[], selected: string, onChange: (key: string) => void }> = (props) => {
|
||||
return (
|
||||
<div className="category-selector-outer">
|
||||
{props.keys.map((k) => (
|
||||
<div
|
||||
className={`category-selector-inner ${props.selected == k.id ? 'selected' : ''}`}
|
||||
key={k.id}
|
||||
onClick={() => props.onChange(k.id)}
|
||||
>
|
||||
<span>{k.name}</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default CategorySelector;
|
40
web/src/components/styles/CategorySelector.css
Normal file
40
web/src/components/styles/CategorySelector.css
Normal file
|
@ -0,0 +1,40 @@
|
|||
.category-selector-outer {
|
||||
width: calc(100% - 20px);
|
||||
margin: 8px 10px;
|
||||
height: 32px;
|
||||
background-color: var(--secondary-background);
|
||||
display: flex;
|
||||
border-radius: 6px;
|
||||
justify-content: space-evenly;
|
||||
}
|
||||
|
||||
.category-selector-inner {
|
||||
background-color: var(--tertiary-background);
|
||||
height: 24px;
|
||||
margin: 4px;
|
||||
width: 100vw;
|
||||
user-select: none;
|
||||
text-align: center;
|
||||
overflow: hidden;
|
||||
border-radius: 4px;
|
||||
transition: filter .2s, background-color .3s;
|
||||
}
|
||||
|
||||
.category-selector-inner:hover {
|
||||
filter: brightness(1.1);
|
||||
}
|
||||
|
||||
.category-selector-inner:active {
|
||||
filter: brightness(1.2);
|
||||
}
|
||||
|
||||
.category-selector-inner.selected {
|
||||
background-color: var(--accent);
|
||||
}
|
||||
|
||||
.category-selector-inner span {
|
||||
color: var(--secondary-foreground);
|
||||
}
|
||||
.category-selector-inner.selected span {
|
||||
color: var(--foreground);
|
||||
}
|
|
@ -10,10 +10,11 @@ import { H3 } from '@revoltchat/ui/lib/components/atoms/heading/H3';
|
|||
import { H4 } from '@revoltchat/ui/lib/components/atoms/heading/H4';
|
||||
import { Icon } from '@mdi/react';
|
||||
import { mdiChevronLeft, mdiCloseBox } from '@mdi/js';
|
||||
import { API_URL } from "../App";
|
||||
import { getAuthHeaders } from "../utils";
|
||||
import { API_URL } from "../../App";
|
||||
import { getAuthHeaders } from "../../utils";
|
||||
import { Link, useParams } from "react-router-dom";
|
||||
import defaultChannelIcon from '../assets/channel-default-icon.svg';
|
||||
import defaultChannelIcon from '../../assets/channel-default-icon.svg';
|
||||
import CategorySelector from '../../components/CategorySelector';
|
||||
|
||||
type User = { id: string, username?: string, avatarURL?: string }
|
||||
type Channel = { id: string, name: string, icon?: string, type: 'VOICE'|'TEXT', nsfw: boolean }
|
||||
|
@ -40,6 +41,8 @@ type AntispamRule = {
|
|||
}
|
||||
|
||||
const ServerDashboard: FunctionComponent = () => {
|
||||
const [category, setCategory] = useState('home');
|
||||
|
||||
const [serverInfo, setServerInfo] = useState({} as Server);
|
||||
const [status, setStatus] = useState('');
|
||||
|
||||
|
@ -108,18 +111,59 @@ const ServerDashboard: FunctionComponent = () => {
|
|||
|
||||
return (
|
||||
<>
|
||||
<Link to='/dashboard'>
|
||||
<div style={{ display: 'flex', marginTop: '4px' }}>
|
||||
<Icon path={mdiChevronLeft} style={{ height: '24px' }} />
|
||||
{status.length ? <a>{status}</a> : <></>}
|
||||
<div
|
||||
style={{
|
||||
marginTop: '8px',
|
||||
marginLeft: '8px',
|
||||
textOverflow: 'ellipsis',
|
||||
whiteSpace: 'nowrap',
|
||||
overflow: 'hidden',
|
||||
color: 'var(--secondary-foreground)',
|
||||
maxWidth: 'calc(100% - 20px)',
|
||||
}}
|
||||
>
|
||||
<Link to='/dashboard' style={{ float: 'left' }}>
|
||||
<div style={{ display: 'flex' }}>
|
||||
<Icon path={mdiChevronLeft} style={{ height: '25px' }} />
|
||||
<span>Back</span>
|
||||
</div>
|
||||
</Link>
|
||||
<H1 style={{ marginTop: '8px' }}>{serverInfo?.name ?? 'Loading...'}</H1>
|
||||
{status.length ? <a>{status}</a> : <br/>}
|
||||
<span
|
||||
style={{
|
||||
color: 'var(--foreground)',
|
||||
marginLeft: '8px',
|
||||
}}
|
||||
>
|
||||
{serverInfo?.name ?? 'Loading...'}
|
||||
</span>
|
||||
<span style={{ color: 'var(--secondary-foreground)', marginLeft: '6px' }}>
|
||||
•
|
||||
</span>
|
||||
<span
|
||||
style={{
|
||||
color: 'var(--secondary-foreground)',
|
||||
marginLeft: '6px',
|
||||
}}
|
||||
>
|
||||
{serverInfo.description || <i>No server description set</i>}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<CategorySelector
|
||||
keys={[
|
||||
{ id: 'home', name: 'Home' },
|
||||
{ id: 'automod', name: 'Moderation Rules' },
|
||||
]}
|
||||
selected={category}
|
||||
onChange={setCategory}
|
||||
/>
|
||||
|
||||
<div hidden={Object.keys(serverInfo).length == 0}>
|
||||
<H4>{serverInfo.description ?? <i>No server description set</i>}</H4>
|
||||
<br/>
|
||||
<div style={{ paddingLeft: '10px', paddingRight: '10px' }}>
|
||||
|
||||
{category == 'home' && (
|
||||
<>
|
||||
<>
|
||||
<H3>Prefix</H3>
|
||||
<InputBox
|
||||
|
@ -182,16 +226,22 @@ const ServerDashboard: FunctionComponent = () => {
|
|||
</UserListContainer>
|
||||
</UserListTypeContainer>
|
||||
</>
|
||||
</>
|
||||
)}
|
||||
|
||||
<LineDivider />
|
||||
|
||||
{category == 'automod' && (
|
||||
<>
|
||||
<H3>Antispam Rules</H3>
|
||||
{serverInfo.perms != null && automodSettings && (
|
||||
serverInfo.perms > 0
|
||||
? (
|
||||
<>
|
||||
{automodSettings.antispam.map(r => <AntispamRule rule={r} key={r.id} />)}
|
||||
{automodSettings.antispam.map((r, i) => (
|
||||
<>
|
||||
<AntispamRule rule={r} key={r.id} />
|
||||
{i < automodSettings.antispam.length - 1 && <LineDivider/>}
|
||||
</>
|
||||
))}
|
||||
<Button style={{
|
||||
marginTop: '12px',
|
||||
marginBottom: '8px',
|
||||
|
@ -233,6 +283,7 @@ const ServerDashboard: FunctionComponent = () => {
|
|||
)
|
||||
}
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
|
@ -613,7 +664,6 @@ const ServerDashboard: FunctionComponent = () => {
|
|||
{props.rule.id}
|
||||
</code>
|
||||
<div style={{ clear: 'both' }} />
|
||||
<div style={{ maxWidth: 'max(40%, 600px)' }}><LineDivider/></div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
Loading…
Reference in a new issue