mirror of
https://github.com/mgerb/go-discord-bot
synced 2026-01-09 16:42:48 +00:00
feat: add user admin page - various dependency updates
This commit is contained in:
@@ -2,7 +2,18 @@ import { Provider } from 'mobx-react';
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import { BrowserRouter, Route, Switch } from 'react-router-dom';
|
||||
import { Admin, Clips, Downloader, NotFound, Oauth, Soundboard, Stats, UploadHistory, VideoArchive } from './pages';
|
||||
import {
|
||||
Clips,
|
||||
Downloader,
|
||||
NotFound,
|
||||
Oauth,
|
||||
Soundboard,
|
||||
Stats,
|
||||
UploadHistory,
|
||||
UserEventLog,
|
||||
VideoArchive,
|
||||
} from './pages';
|
||||
import { Users } from './pages/users';
|
||||
import './scss/index.scss';
|
||||
import { rootStoreInstance } from './stores';
|
||||
import { Wrapper } from './wrapper';
|
||||
@@ -20,7 +31,8 @@ const App: any = (): any => {
|
||||
<Route path="/oauth" component={Oauth} />
|
||||
<Route path="/stats" component={Stats} />
|
||||
<Route path="/video-archive" component={VideoArchive} />
|
||||
<Route path="/admin" component={Admin} />
|
||||
<Route path="/user-event-log" component={UserEventLog} />
|
||||
<Route path="/users" component={Users} />
|
||||
<Route component={NotFound} />
|
||||
</Switch>
|
||||
</Wrapper>
|
||||
@@ -29,4 +41,4 @@ const App: any = (): any => {
|
||||
);
|
||||
};
|
||||
|
||||
ReactDOM.render(<App /> as any, document.getElementById('app'));
|
||||
ReactDOM.render((<App />) as any, document.getElementById('app'));
|
||||
|
||||
@@ -67,8 +67,23 @@ export class Navbar extends React.Component<Props, State> {
|
||||
);
|
||||
};
|
||||
|
||||
renderAuthLinks = () => {
|
||||
const { hasAdminPermissions } = this.props.appStore;
|
||||
|
||||
if (hasAdminPermissions()) {
|
||||
return (
|
||||
<>
|
||||
{this.renderNavLink('User Event Log', '/user-event-log')}
|
||||
{this.renderNavLink('Users', '/users')}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
render() {
|
||||
const { claims, navbarOpen, hasModPermissions, hasAdminPermissions } = this.props.appStore;
|
||||
const { claims, navbarOpen, hasModPermissions } = this.props.appStore;
|
||||
const openClass = navbarOpen ? 'navbar--open' : '';
|
||||
return (
|
||||
<div className={'navbar ' + openClass}>
|
||||
@@ -78,7 +93,7 @@ export class Navbar extends React.Component<Props, State> {
|
||||
{this.renderNavLink('Youtube Downloader', '/downloader')}
|
||||
{this.renderNavLink('Clips', '/clips')}
|
||||
{this.renderNavLink('Stats', '/stats')}
|
||||
{hasAdminPermissions() && this.renderNavLink('Admin', '/admin')}
|
||||
{this.renderAuthLinks()}
|
||||
{this.renderLoginButton()}
|
||||
|
||||
{claims && claims.email && <div className="navbar__email">{claims.email}</div>}
|
||||
|
||||
@@ -13,5 +13,6 @@ export interface IUser {
|
||||
token: string;
|
||||
updated_at: string;
|
||||
username: string;
|
||||
voice_join_sound: string;
|
||||
verified: boolean;
|
||||
}
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
export * from './admin';
|
||||
@@ -1,4 +1,3 @@
|
||||
export * from './admin';
|
||||
export * from './clips/clips';
|
||||
export * from './downloader/downloader';
|
||||
export * from './not-found/not-found';
|
||||
@@ -6,4 +5,5 @@ export * from './oauth/oauth';
|
||||
export * from './soundboard/soundboard';
|
||||
export * from './stats/stats';
|
||||
export * from './upload-history/upload-history';
|
||||
export * from './user-event-log';
|
||||
export * from './video-archive/video-archive';
|
||||
|
||||
1
client/app/pages/user-event-log/index.ts
Normal file
1
client/app/pages/user-event-log/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export * from './user-event-log';
|
||||
@@ -8,15 +8,16 @@ interface IState {
|
||||
userEventLogs: IUserEventLog[];
|
||||
}
|
||||
|
||||
export class Admin extends React.Component<IProps, IState> {
|
||||
export class UserEventLog extends React.Component<IProps, IState> {
|
||||
constructor(props: IProps) {
|
||||
super(props);
|
||||
this.state = {
|
||||
userEventLogs: [],
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
UserEventLogService.getUserEventLogs().then(userEventLogs => {
|
||||
UserEventLogService.getUserEventLogs().then((userEventLogs) => {
|
||||
this.setState({
|
||||
userEventLogs,
|
||||
});
|
||||
1
client/app/pages/users/index.tsx
Normal file
1
client/app/pages/users/index.tsx
Normal file
@@ -0,0 +1 @@
|
||||
export * from './users';
|
||||
103
client/app/pages/users/users.tsx
Normal file
103
client/app/pages/users/users.tsx
Normal file
@@ -0,0 +1,103 @@
|
||||
import React from 'react';
|
||||
import { IUser } from '../../model';
|
||||
import { UserService } from '../../services/user.service';
|
||||
|
||||
interface IState {
|
||||
users: IUser[];
|
||||
showSavedMessage: boolean;
|
||||
}
|
||||
|
||||
export class Users extends React.Component<any, IState> {
|
||||
constructor(props: any) {
|
||||
super(props);
|
||||
this.state = {
|
||||
users: [],
|
||||
showSavedMessage: false,
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
UserService.getUsers().then((users) => {
|
||||
this.setState({ users });
|
||||
});
|
||||
}
|
||||
|
||||
onUserChange = (type: 'permissions' | 'voice_join_sound', event: any, index: number) => {
|
||||
this.setState({ showSavedMessage: false });
|
||||
|
||||
let users = [...this.state.users];
|
||||
const val = type === 'permissions' ? parseInt(event.target.value) : event.target.value;
|
||||
users[index] = {
|
||||
...users[index],
|
||||
[type]: val,
|
||||
};
|
||||
|
||||
this.setState({ users });
|
||||
};
|
||||
|
||||
renderUsers = () => {
|
||||
return this.state.users.map((u: IUser, i: number) => {
|
||||
return (
|
||||
<tr key={i}>
|
||||
<td>{u.username}</td>
|
||||
<td>{u.email}</td>
|
||||
<td>
|
||||
<input
|
||||
className="input"
|
||||
type="number"
|
||||
min={1}
|
||||
max={3}
|
||||
value={u.permissions}
|
||||
onChange={(e) => this.onUserChange('permissions', e, i)}
|
||||
/>
|
||||
</td>
|
||||
<td>
|
||||
<input
|
||||
className="input"
|
||||
type="text"
|
||||
value={u.voice_join_sound || ''}
|
||||
onChange={(e) => this.onUserChange('voice_join_sound', e, i)}
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
save = (event: any) => {
|
||||
this.setState({ showSavedMessage: false });
|
||||
event.preventDefault();
|
||||
UserService.putUsers(this.state.users).then((users: IUser[]) => {
|
||||
this.setState({ users, showSavedMessage: true });
|
||||
});
|
||||
};
|
||||
|
||||
render() {
|
||||
return (
|
||||
<form className="content" onSubmit={this.save}>
|
||||
<div className="card card--wide">
|
||||
<div className="card__header">Users</div>
|
||||
<div className="overflow-x-auto">
|
||||
<table className="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Username</th>
|
||||
<th>Email</th>
|
||||
<th>Permissions</th>
|
||||
<th>Join Sound</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>{this.renderUsers()}</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<br />
|
||||
<button className="button button--primary" type="submit">
|
||||
Save
|
||||
</button>
|
||||
{this.state.showSavedMessage && <span style={{ marginLeft: 5 }}>Users updated</span>}
|
||||
</div>
|
||||
</form>
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,10 @@
|
||||
border: 1px solid $gray3;
|
||||
}
|
||||
|
||||
.card--wide {
|
||||
max-width: 1200px;
|
||||
}
|
||||
|
||||
.card__header {
|
||||
margin: -10px -10px 10px -10px;
|
||||
display: flex;
|
||||
|
||||
@@ -92,3 +92,7 @@ body {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.overflow-x-auto {
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
14
client/app/services/user.service.ts
Normal file
14
client/app/services/user.service.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
import { IUser } from '../model';
|
||||
import { axios } from './axios.service';
|
||||
|
||||
export class UserService {
|
||||
public static async getUsers(): Promise<IUser[]> {
|
||||
const resp = await axios.get('/api/user');
|
||||
return resp.data.data;
|
||||
}
|
||||
|
||||
public static async putUsers(users: IUser[]): Promise<IUser[]> {
|
||||
const resp = await axios.put('/api/user', { users });
|
||||
return resp.data.data;
|
||||
}
|
||||
}
|
||||
16217
client/package-lock.json
generated
16217
client/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -44,7 +44,7 @@
|
||||
"mini-css-extract-plugin": "^0.4.2",
|
||||
"mobx": "^5.15.4",
|
||||
"mobx-react": "^5.2.5",
|
||||
"node-sass": "^4.14.1",
|
||||
"node-sass": "^7.0.1",
|
||||
"normalize.css": "^8.0.1",
|
||||
"nprogress": "^0.2.0",
|
||||
"postcss-loader": "^2.1.5",
|
||||
|
||||
Reference in New Issue
Block a user