Webatrice updates (#4366)
This commit is contained in:
parent
8db9475804
commit
0d05f9097d
14 changed files with 5517 additions and 20090 deletions
25269
webclient/package-lock.json
generated
25269
webclient/package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
@ -3,11 +3,12 @@
|
|||
"version": "1.0.0",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@material-ui/core": "^4.6.1",
|
||||
"@material-ui/core": "^4.11.4",
|
||||
"@material-ui/icons": "^4.11.2",
|
||||
"@types/jest": "24.0.20",
|
||||
"@types/jquery": "^3.3.31",
|
||||
"@types/lodash": "^4.14.145",
|
||||
"@types/material-ui": "^0.21.7",
|
||||
"@types/material-ui": "^0.21.8",
|
||||
"@types/node": "12.11.7",
|
||||
"@types/prop-types": "^15.7.3",
|
||||
"@types/protobufjs": "^6.0.0",
|
||||
|
|
|
@ -14,7 +14,9 @@ export default class AuthenticationService {
|
|||
}
|
||||
|
||||
static isModerator(user) {
|
||||
return user.userLevel >= webClient.pb.ServerInfo_User.UserLevelFlag.IsModerator;
|
||||
const moderatorLevel = webClient.pb.ServerInfo_User.UserLevelFlag.IsModerator;
|
||||
// @TODO tell cockatrice not to do this so shittily
|
||||
return (user.userLevel & moderatorLevel) === moderatorLevel;
|
||||
}
|
||||
|
||||
static isAdmin() {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import React, { Component } from "react";
|
||||
import React from "react";
|
||||
import { connect } from "react-redux";
|
||||
import { Redirect } from "react-router-dom";
|
||||
|
||||
|
@ -7,12 +7,10 @@ import { RouteEnum } from "types";
|
|||
|
||||
import { AuthenticationService } from "api";
|
||||
|
||||
class AuthGuard extends Component<AuthGuardProps> {
|
||||
render() {
|
||||
return !AuthenticationService.isConnected(this.props.state)
|
||||
const AuthGuard = ({ state }: AuthGuardProps) => {
|
||||
return !AuthenticationService.isConnected(state)
|
||||
? <Redirect from="*" to={RouteEnum.SERVER} />
|
||||
: "";
|
||||
}
|
||||
: <div></div>;
|
||||
};
|
||||
|
||||
interface AuthGuardProps {
|
||||
|
|
|
@ -25,13 +25,13 @@
|
|||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.Header-nav__items {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.Header-nav__item {
|
||||
|
@ -39,6 +39,10 @@
|
|||
margin: 0 10px;
|
||||
}
|
||||
|
||||
.Header-nav__menu {
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.Header-account {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
|
|
@ -3,7 +3,11 @@ import { connect } from "react-redux";
|
|||
import { NavLink, withRouter, generatePath } from "react-router-dom";
|
||||
import AppBar from "@material-ui/core/AppBar";
|
||||
import Chip from "@material-ui/core/Chip";
|
||||
import IconButton from "@material-ui/core/IconButton";
|
||||
import Menu from "@material-ui/core/Menu";
|
||||
import MenuItem from "@material-ui/core/MenuItem";
|
||||
import Toolbar from "@material-ui/core/Toolbar";
|
||||
import MenuRoundedIcon from '@material-ui/icons/MenuRounded';
|
||||
import * as _ from "lodash";
|
||||
|
||||
import { AuthenticationService, RoomsService } from "api";
|
||||
|
@ -14,6 +18,24 @@ import "./Header.css";
|
|||
import logo from "./logo.png";
|
||||
|
||||
class Header extends Component<HeaderProps> {
|
||||
state: HeaderState;
|
||||
options: string[] = [
|
||||
'Decks',
|
||||
'Replays',
|
||||
];
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
anchorEl: null,
|
||||
};
|
||||
|
||||
this.handleMenuClick = this.handleMenuClick.bind(this);
|
||||
this.handleMenuItemClick = this.handleMenuItemClick.bind(this);
|
||||
this.handleMenuClose = this.handleMenuClose.bind(this);
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps) {
|
||||
const currentRooms = this.props.joinedRooms;
|
||||
const previousRooms = prevProps.joinedRooms;
|
||||
|
@ -24,8 +46,30 @@ class Header extends Component<HeaderProps> {
|
|||
}
|
||||
}
|
||||
|
||||
handleMenuClick({ target }) {
|
||||
this.setState({ anchorEl: target });
|
||||
}
|
||||
|
||||
handleMenuItemClick(option: string) {
|
||||
const route = RouteEnum[option.toUpperCase()];
|
||||
this.props.history.push(generatePath(route));
|
||||
|
||||
this.handleMenuClose();
|
||||
}
|
||||
|
||||
handleMenuClose() {
|
||||
this.setState({ anchorEl: null });
|
||||
}
|
||||
|
||||
render() {
|
||||
const { joinedRooms, server, state, user } = this.props;
|
||||
const anchorEl = this.state.anchorEl;
|
||||
const options = [ ...this.options ];
|
||||
|
||||
if (user && AuthenticationService.isModerator(user)) {
|
||||
options.push('Administration');
|
||||
options.push('Logs');
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
|
@ -39,20 +83,6 @@ class Header extends Component<HeaderProps> {
|
|||
<div className="Header-content">
|
||||
<nav className="Header-nav">
|
||||
<ul className="Header-nav__items">
|
||||
{
|
||||
AuthenticationService.isModerator(user) && (
|
||||
<li className="Header-nav__item">
|
||||
<NavLink to={RouteEnum.LOGS}>
|
||||
<button>Logs</button>
|
||||
</NavLink>
|
||||
</li>
|
||||
)
|
||||
}
|
||||
<li className="Header-nav__item">
|
||||
<NavLink to={RouteEnum.SERVER} className="plain-link">
|
||||
Server ({server})
|
||||
</NavLink>
|
||||
</li>
|
||||
<NavLink to={RouteEnum.ACCOUNT} className="plain-link">
|
||||
<div className="Header-account">
|
||||
<span className="Header-account__name">
|
||||
|
@ -61,6 +91,35 @@ class Header extends Component<HeaderProps> {
|
|||
<span className="Header-account__indicator"></span>
|
||||
</div>
|
||||
</NavLink>
|
||||
<div className="Header-nav__menu">
|
||||
<IconButton
|
||||
aria-label="more"
|
||||
aria-controls="long-menu"
|
||||
aria-haspopup="true"
|
||||
onClick={this.handleMenuClick}
|
||||
>
|
||||
<MenuRoundedIcon fontSize="large" />
|
||||
</IconButton>
|
||||
<Menu
|
||||
id="long-menu"
|
||||
anchorEl={anchorEl}
|
||||
keepMounted
|
||||
open={!!anchorEl}
|
||||
onClose={this.handleMenuClose}
|
||||
PaperProps={{
|
||||
style: {
|
||||
marginTop: '53px',
|
||||
width: '20ch',
|
||||
},
|
||||
}}
|
||||
>
|
||||
{options.map((option) => (
|
||||
<MenuItem key={option} onClick={() => this.handleMenuItemClick(option)}>
|
||||
{option}
|
||||
</MenuItem>
|
||||
))}
|
||||
</Menu>
|
||||
</div>
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
|
@ -113,11 +172,15 @@ interface HeaderProps {
|
|||
history: any;
|
||||
}
|
||||
|
||||
interface HeaderState {
|
||||
anchorEl: Element;
|
||||
}
|
||||
|
||||
const mapStateToProps = state => ({
|
||||
state: ServerSelectors.getState(state),
|
||||
server: ServerSelectors.getName(state),
|
||||
user: ServerSelectors.getUser(state),
|
||||
joinedRooms: RoomsSelectors.getJoinedRooms(state)
|
||||
joinedRooms: RoomsSelectors.getJoinedRooms(state),
|
||||
});
|
||||
|
||||
export default withRouter(connect(mapStateToProps)(Header));
|
||||
|
|
|
@ -4,6 +4,7 @@ import { connect } from "react-redux";
|
|||
import { Form, reduxForm } from "redux-form"
|
||||
|
||||
import { InputAction } from 'components';
|
||||
import { FormKey } from 'types';
|
||||
|
||||
const AddToBuddies = ({ handleSubmit }) => (
|
||||
<Form onSubmit={handleSubmit}>
|
||||
|
@ -12,7 +13,7 @@ const AddToBuddies = ({ handleSubmit }) => (
|
|||
);
|
||||
|
||||
const propsMap = {
|
||||
form: "addToBuddies"
|
||||
form: FormKey.ADD_TO_BUDDIES
|
||||
};
|
||||
|
||||
export default connect()(reduxForm(propsMap)(AddToBuddies));
|
||||
|
|
|
@ -4,6 +4,7 @@ import { connect } from "react-redux";
|
|||
import { Form, reduxForm } from "redux-form"
|
||||
|
||||
import { InputAction } from 'components';
|
||||
import { FormKey } from 'types';
|
||||
|
||||
const AddToIgnore = ({ handleSubmit }) => (
|
||||
<Form onSubmit={handleSubmit}>
|
||||
|
@ -12,7 +13,7 @@ const AddToIgnore = ({ handleSubmit }) => (
|
|||
);
|
||||
|
||||
const propsMap = {
|
||||
form: "addToIgnore"
|
||||
form: FormKey.ADD_TO_IGNORE,
|
||||
};
|
||||
|
||||
export default connect()(reduxForm(propsMap)(AddToIgnore));
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
// eslint-disable-next-line
|
||||
import React, { Component } from "react";
|
||||
import { connect } from "react-redux";
|
||||
import { Form, Field, InjectedFormProps, reduxForm } from "redux-form"
|
||||
import { Form, Field, reduxForm } from "redux-form"
|
||||
|
||||
import Button from "@material-ui/core/Button";
|
||||
import { InputField } from "../../components";
|
||||
|
||||
import { InputField } from "components";
|
||||
import { FormKey } from 'types';
|
||||
|
||||
import "./ConnectForm.css";
|
||||
|
||||
class ConnectForm extends Component<InjectedFormProps> {
|
||||
render() {
|
||||
return (
|
||||
<Form className="connectForm" onSubmit={this.props.handleSubmit}>
|
||||
const ConnectForm = ({ handleSubmit }) => (
|
||||
<Form className="connectForm" onSubmit={handleSubmit}>
|
||||
<div className="connectForm-item">
|
||||
<Field label="Host" name="host" component={InputField} />
|
||||
</div>
|
||||
|
@ -28,12 +28,10 @@ class ConnectForm extends Component<InjectedFormProps> {
|
|||
Connect
|
||||
</Button>
|
||||
</Form>
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
const propsMap = {
|
||||
form: "connect"
|
||||
form: FormKey.CONNECT
|
||||
};
|
||||
|
||||
const mapStateToProps = () => ({
|
||||
|
|
|
@ -1,18 +1,17 @@
|
|||
// eslint-disable-next-line
|
||||
import React, { Component } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { Form, Field, InjectedFormProps, reduxForm } from 'redux-form'
|
||||
import { Form, Field, reduxForm } from 'redux-form'
|
||||
|
||||
import Button from '@material-ui/core/Button';
|
||||
|
||||
import { InputField } from '../../components';
|
||||
import { InputField } from 'components';
|
||||
import { FormKey } from 'types';
|
||||
|
||||
import './RegisterForm.css';
|
||||
|
||||
class RegisterForm extends Component<InjectedFormProps> {
|
||||
render() {
|
||||
return (
|
||||
<Form className="registerForm" onSubmit={this.props.handleSubmit} autoComplete="off">
|
||||
const RegisterForm = ({ handleSubmit }) => (
|
||||
<Form className="registerForm" onSubmit={handleSubmit} autoComplete="off">
|
||||
<div className="registerForm-item">
|
||||
<Field label="Host" name="host" component={InputField} />
|
||||
</div>
|
||||
|
@ -41,12 +40,10 @@ class RegisterForm extends Component<InjectedFormProps> {
|
|||
Register
|
||||
</Button>
|
||||
</Form>
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
const propsMap = {
|
||||
form: 'register'
|
||||
form: FormKey.REGISTER,
|
||||
};
|
||||
|
||||
const mapStateToProps = () => ({
|
||||
|
|
|
@ -1,21 +1,20 @@
|
|||
// eslint-disable-next-line
|
||||
import React, { Component } from "react";
|
||||
import { connect } from "react-redux";
|
||||
import { Form, Field, InjectedFormProps, reduxForm } from "redux-form"
|
||||
import { Form, Field, reduxForm } from "redux-form"
|
||||
|
||||
import Button from "@material-ui/core/Button";
|
||||
import Divider from "@material-ui/core/Divider";
|
||||
import Paper from "@material-ui/core/Paper";
|
||||
|
||||
import { InputField, CheckboxField } from "../../components";
|
||||
import { InputField, CheckboxField } from "components";
|
||||
import { FormKey } from "types";
|
||||
|
||||
import "./SearchForm.css";
|
||||
|
||||
class SearchForm extends Component<InjectedFormProps> {
|
||||
render() {
|
||||
return (
|
||||
const SearchForm = ({ handleSubmit }) => (
|
||||
<Paper className="log-search">
|
||||
<Form className="log-search__form" onSubmit={this.props.handleSubmit}>
|
||||
<Form className="log-search__form" onSubmit={handleSubmit}>
|
||||
<div className="log-search__form-item">
|
||||
<Field label="Username" name="userName" component={InputField} />
|
||||
</div>
|
||||
|
@ -51,12 +50,10 @@ class SearchForm extends Component<InjectedFormProps> {
|
|||
</Button>
|
||||
</Form>
|
||||
</Paper>
|
||||
)
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
const propsMap = {
|
||||
form: "logs"
|
||||
form: FormKey.SEARCH_LOGS,
|
||||
};
|
||||
|
||||
const mapStateToProps = () => ({
|
||||
|
@ -64,4 +61,3 @@ const mapStateToProps = () => ({
|
|||
});
|
||||
|
||||
export default connect(mapStateToProps)(reduxForm(propsMap)(SearchForm));
|
||||
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
export { default as ConnectForm } from './ConnectForm/ConnectForm';
|
||||
export { default as RegisterForm } from './RegisterForm/RegisterForm';
|
||||
export { default as SearchForm } from './SearchForm/SearchForm';
|
||||
|
|
7
webclient/src/types/forms.ts
Normal file
7
webclient/src/types/forms.ts
Normal file
|
@ -0,0 +1,7 @@
|
|||
export enum FormKey {
|
||||
ADD_TO_BUDDIES = "ADD_TO_BUDDIES",
|
||||
ADD_TO_IGNORE = "ADD_TO_IGNORE",
|
||||
CONNECT = "CONNECT",
|
||||
REGISTER = "REGISTER",
|
||||
SEARCH_LOGS = "SEARCH_LOGS",
|
||||
}
|
|
@ -5,3 +5,4 @@ export * from "./sort";
|
|||
export * from "./user";
|
||||
export * from "./routes";
|
||||
export * from "./sort";
|
||||
export * from "./forms";
|
||||
|
|
Loading…
Reference in a new issue