small improvements (#4452)

Co-authored-by: Jeremy Letto <jeremy.letto@datasite.com>
This commit is contained in:
Jeremy Letto 2021-10-31 21:21:24 -05:00 committed by GitHub
parent a87c66885c
commit 4cb7240f9a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
21 changed files with 197 additions and 74 deletions

View file

@ -13,11 +13,11 @@ import MenuRoundedIcon from '@material-ui/icons/MenuRounded';
import * as _ from "lodash"; import * as _ from "lodash";
import { AuthenticationService, RoomsService } from "api"; import { AuthenticationService, RoomsService } from "api";
import { Images } from 'images';
import { RoomsSelectors, ServerSelectors } from "store"; import { RoomsSelectors, ServerSelectors } from "store";
import { Room, RouteEnum, User } from "types"; import { Room, RouteEnum, User } from "types";
import "./Header.css"; import "./Header.css";
import logo from "./logo.png";
import CardImportDialog from '../CardImportDialog/CardImportDialog'; import CardImportDialog from '../CardImportDialog/CardImportDialog';
@ -100,7 +100,7 @@ class Header extends Component<HeaderProps> {
<Toolbar variant="dense"> <Toolbar variant="dense">
<div className="Header__logo"> <div className="Header__logo">
<NavLink to={RouteEnum.SERVER}> <NavLink to={RouteEnum.SERVER}>
<img src={logo} alt="logo" /> <img src={Images.Logo} alt="logo" />
</NavLink> </NavLink>
{ AuthenticationService.isConnected(state) && ( { AuthenticationService.isConnected(state) && (
<span className="Header-server__indicator"></span> <span className="Header-server__indicator"></span>

View file

@ -1,3 +1,20 @@
.KnownHosts { .KnownHosts {
width: 100%; width: 100%;
} }
.KnownHosts-item__label {
position: relative;
}
.KnownHosts-item__label svg {
display: none;
position: absolute;
left: -.1em;
top: 50%;
transform: translate(-100%, -50%);
font-size: .9em;
}
.Mui-selected .KnownHosts-item__label svg {
display: block;
}

View file

@ -5,6 +5,7 @@ import Button from '@material-ui/core/Button';
import FormControl from '@material-ui/core/FormControl'; import FormControl from '@material-ui/core/FormControl';
import IconButton from '@material-ui/core/IconButton'; import IconButton from '@material-ui/core/IconButton';
import InputLabel from '@material-ui/core/InputLabel'; import InputLabel from '@material-ui/core/InputLabel';
import Check from '@material-ui/icons/Check';
import EditRoundedIcon from '@material-ui/icons/Edit'; import EditRoundedIcon from '@material-ui/icons/Edit';
import { HostDTO } from 'services'; import { HostDTO } from 'services';
@ -64,10 +65,16 @@ const KnownHosts = ({ onChange }) => {
{ {
state.hosts.map((host, index) => ( state.hosts.map((host, index) => (
<MenuItem className='KnownHosts-item' value={index} key={index}> <MenuItem className='KnownHosts-item' value={index} key={index}>
<span>{host.name} ({ getHostPort(state.hosts[index]).host }:{getHostPort(state.hosts[index]).port})</span> <div className='KnownHosts-item__label'>
<IconButton size='small' color='primary' disabled={!host.editable} onClick={() => editKnownHost(index)}> <Check />
<EditRoundedIcon fontSize='small' /> <span>{host.name} ({ getHostPort(state.hosts[index]).host }:{getHostPort(state.hosts[index]).port})</span>
</IconButton> </div>
{ host.editable && (
<IconButton size='small' color='primary' onClick={() => editKnownHost(index)}>
<EditRoundedIcon fontSize='small' />
</IconButton>
) }
</MenuItem> </MenuItem>
)) ))
} }

View file

@ -6,6 +6,8 @@ import Hidden from "@material-ui/core/Hidden";
import "./ThreePaneLayout.css"; import "./ThreePaneLayout.css";
// @DEPRECATED
// This component sucks balls, dont use it. It will be removed sooner than later.
class ThreePaneLayout extends Component<ThreePaneLayoutProps> { class ThreePaneLayout extends Component<ThreePaneLayoutProps> {
render() { render() {
return ( return (

View file

@ -24,7 +24,8 @@ const Routes = () => (
{<Route path={RouteEnum.ROOM} render={() => <Room />} />} {<Route path={RouteEnum.ROOM} render={() => <Room />} />}
<Route path={RouteEnum.SERVER} render={() => <Server />} /> <Route path={RouteEnum.SERVER} render={() => <Server />} />
<Route path={RouteEnum.LOGIN} render={() => <Login />} /> <Route path={RouteEnum.LOGIN} render={() => <Login />} />
<Redirect from="/" to={RouteEnum.LOGIN} />
<Redirect from="*" to={RouteEnum.LOGIN} />
</Switch> </Switch>
</div> </div>
); );

View file

@ -11,32 +11,28 @@
.login-content { .login-content {
width: 100%; width: 100%;
max-width: 1000px; max-width: 500px;
display: flex; display: flex;
border-radius: 8px; border-radius: 8px;
overflow: hidden; overflow: hidden;
} }
.login-content__header { .login-content__header {
font-family: Teko, sans-serif; font-family: 'Teko', sans-serif;
font-size: 34px; font-size: 34px;
font-weight: bold; font-weight: bold;
display: flex; display: flex;
align-items: center; align-items: center;
margin-bottom: 20px;
} }
.login-content__header img { .login-content__header img {
height: 60px; height: 60px;
margin-right: 15px; margin-right: 15px;
margin-bottom: 20px;
}
.login-content__form,
.login-content__description {
width: 50%;
} }
.login-content__form { .login-content__form {
width: 100%;
padding: 50px 50px 33px; padding: 50px 50px 33px;
} }
@ -49,8 +45,8 @@
} }
.login-content__description { .login-content__description {
display: none;
position: relative; position: relative;
display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
text-align: center; text-align: center;
@ -67,14 +63,54 @@
align-items: center; align-items: center;
} }
.login-content__description-image { .login-content__description-cards {
width: 100%;
}
.login-content__description-placeholder {
width: 100%; width: 100%;
height: 207px; position: relative;
border: 1px solid; display: flex;
justify-content: space-between;
} }
.login-content__description-cards__card {
position: relative;
width: 34%;
padding-bottom: 46%;
border-radius: 8px;
box-shadow: 0 5px 10px 2px rgba(0,0,0,0.20);
font-weight: bold;
font-size: 16px;
}
.login-content__description-cards__card-wrapper {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
.login-content__description-cards__card img {
width: 70%;
border-radius: 50%;
margin: 21% 0 9%;
}
.login-content__description-cards__card.leftCard {
transform: rotate(-12deg);
}
.login-content__description-cards__card.rightCard {
transform: rotate(12deg);
}
.login-content__description-cards__card.topCard {
width: 44%;
padding-bottom: 59%;
position: absolute;
top: 45%;
left: 50%;
transform: translate(-50%, -50%);
}
.login-content__description-subtitle1 { .login-content__description-subtitle1 {
margin: 40px 0 20px; margin: 40px 0 20px;
font-size: 28px; font-size: 28px;
@ -91,8 +127,7 @@
} }
.login-content__description-bar { .login-content__description-bar {
position: absolute; position: absolute;
opacity: .2; opacity: .1;
background-color: #401C7F;
border-radius: 8px; border-radius: 8px;
} }
@ -159,4 +194,5 @@
text-align: center; text-align: center;
margin: 20px 0; margin: 20px 0;
padding: 20px; padding: 20px;
font-weight: bold;
} }

View file

@ -2,21 +2,58 @@
import React from "react"; import React from "react";
import { connect } from "react-redux"; import { connect } from "react-redux";
import { Redirect } from "react-router-dom"; import { Redirect } from "react-router-dom";
import { styled } from '@material-ui/core/styles'; import { makeStyles } from '@material-ui/core/styles';
import Button from '@material-ui/core/Button'; import Button from '@material-ui/core/Button';
import Paper from '@material-ui/core/Paper'; import Paper from '@material-ui/core/Paper';
import Typography from '@material-ui/core/Typography'; import Typography from '@material-ui/core/Typography';
import { AuthenticationService } from "api"; import { AuthenticationService } from "api";
import { LoginForm } from "forms"; import { LoginForm } from "forms";
import { Images } from "images";
import { RouteEnum } from "types"; import { RouteEnum } from "types";
import { /* ServerDispatch, */ ServerSelectors } from "store"; import { /* ServerDispatch, */ ServerSelectors } from "store";
import "./Login.css"; import "./Login.css";
import logo from "images/logo.png";
/*import loginGraphic from "images/login-graphic.png"*/ const useStyles = makeStyles(theme => ({
root: {
'& .login-content__header': {
color: theme.palette.success.light
},
'& .login-content__description': {
backgroundColor: theme.palette.primary.main,
color: theme.palette.primary.contrastText,
},
'& .login-content__description-bar': {
backgroundColor: theme.palette.primary.dark,
},
'& .login-content__description-cards__card': {
backgroundColor: theme.palette.background.paper,
color: theme.palette.primary.main,
},
[theme.breakpoints.up('lg')]: {
'& .login-content': {
maxWidth: '1000px',
},
'& .login-content__form': {
width: '50%',
},
'& .login-content__description': {
width: '50%',
display: 'flex',
},
},
},
}));
const Login = ({ state, description }: LoginProps) => { const Login = ({ state, description }: LoginProps) => {
const classes = useStyles();
const isConnected = AuthenticationService.isConnected(state); const isConnected = AuthenticationService.isConnected(state);
const showDescription = () => { const showDescription = () => {
@ -28,16 +65,16 @@ const Login = ({ state, description }: LoginProps) => {
}; };
return ( return (
<div className="login overflow-scroll"> <div className={'login overflow-scroll ' + classes.root}>
{ isConnected && <Redirect from="*" to={RouteEnum.SERVER} />} { isConnected && <Redirect from="*" to={RouteEnum.SERVER} />}
<div className="login__wrapper"> <div className="login__wrapper">
<ThemedLoginContent className="login-content"> <Paper className="login-content">
<div className="login-content__form"> <div className="login-content__form">
<ThemedLoginHeader className="login-content__header"> <div className="login-content__header">
<img src={logo} alt="logo" /> <img src={Images.Logo} alt="logo" />
<span>COCKATRICE</span> <span>COCKATRICE</span>
</ThemedLoginHeader> </div>
<Typography variant="h1">Login</Typography> <Typography variant="h1">Login</Typography>
<Typography variant="subtitle1">A cross-platform virtual tabletop for multiplayer card games.</Typography> <Typography variant="subtitle1">A cross-platform virtual tabletop for multiplayer card games.</Typography>
<div className="login-form"> <div className="login-form">
@ -58,11 +95,11 @@ const Login = ({ state, description }: LoginProps) => {
<Button color="primary" onClick={createAccount}>Create an account</Button> <Button color="primary" onClick={createAccount}>Create an account</Button>
</div> </div>
<Typography variant="subtitle2" className="login-footer__copyright"> <Typography variant="subtitle2" className="login-footer__copyright">
Cockatrice is an open source project @{ new Date().getUTCFullYear() } Cockatrice is an open source project. { new Date().getUTCFullYear() }
</Typography> </Typography>
</div> </div>
</div> </div>
<ThemedLoginDescription className="login-content__description"> <div className="login-content__description">
<div className="login-content__description-graphics"> <div className="login-content__description-graphics">
<div className="topLeft login-content__description-square" /> <div className="topLeft login-content__description-square" />
<div className="topRight login-content__description-square" /> <div className="topRight login-content__description-square" />
@ -72,31 +109,37 @@ const Login = ({ state, description }: LoginProps) => {
<div className="bottomBar login-content__description-bar" /> <div className="bottomBar login-content__description-bar" />
</div> </div>
<div className="login-content__description-wrapper"> <div className="login-content__description-wrapper">
<div className="login-content__description-cards">
<div className="login-content__description-cards__card leftCard">
<div className="login-content__description-cards__card-wrapper">
<img src={Images.Faces.face1} alt='Stock Player' />
<span>1mrlee</span>
</div>
</div>
<div className="login-content__description-cards__card rightCard">
<div className="login-content__description-cards__card-wrapper">
<img src={Images.Faces.face2} alt='Stock Player' />
<span>CyberX</span>
</div>
</div>
<div className="login-content__description-cards__card topCard">
<div className="login-content__description-cards__card-wrapper">
<img src={Images.Faces.face3} alt='Stock Player' />
<span>Gamer69</span>
</div>
</div>
</div>
{ /*<img src={loginGraphic} className="login-content__description-image"/>*/} { /*<img src={loginGraphic} className="login-content__description-image"/>*/}
<div className="login-content__description-placeholder"/>
<p className="login-content__description-subtitle1">Play multiplayer card games online.</p> <p className="login-content__description-subtitle1">Play multiplayer card games online.</p>
<p className="login-content__description-subtitle2">Cross-platform virtual tabletop for multiplayer card games. Forever free.</p> <p className="login-content__description-subtitle2">Cross-platform virtual tabletop for multiplayer card games. Forever free.</p>
</div> </div>
</ThemedLoginDescription> </div>
</ThemedLoginContent> </Paper>
</div> </div>
</div> </div>
); );
} }
const ThemedLoginContent = styled('div')(({ theme }) => ({
backgroundColor: theme.palette.background.paper
}));
const ThemedLoginDescription = styled('div')(({ theme }) => ({
backgroundColor: theme.palette.primary.main,
color: theme.palette.primary.contrastText,
}));
const ThemedLoginHeader = styled('div')(({ theme }) => ({
color: theme.palette.success.light
}));
interface LoginProps { interface LoginProps {
state: number; state: number;
description: string; description: string;

View file

@ -8,7 +8,7 @@ import Paper from "@material-ui/core/Paper";
import { RoomsSelectors, ServerSelectors } from "store"; import { RoomsSelectors, ServerSelectors } from "store";
import { ThreePaneLayout, UserDisplay, VirtualList } from "components"; import { AuthGuard, ThreePaneLayout, UserDisplay, VirtualList } from "components";
import { Room, User } from "types"; import { Room, User } from "types";
import Rooms from './Rooms'; import Rooms from './Rooms';
@ -20,6 +20,8 @@ class Server extends Component<ServerProps, ServerState> {
return ( return (
<div className="server-rooms"> <div className="server-rooms">
<AuthGuard />
<ThreePaneLayout <ThreePaneLayout
top={( top={(
<Paper className="serverRoomWrapper overflow-scroll"> <Paper className="serverRoomWrapper overflow-scroll">

View file

@ -27,13 +27,13 @@ const LoginForm = (props) => {
<Form className="loginForm" onSubmit={handleSubmit}> <Form className="loginForm" onSubmit={handleSubmit}>
<div className="loginForm-items"> <div className="loginForm-items">
<div className="loginForm-item"> <div className="loginForm-item">
<Field label="User" name="user" component={InputField} autoComplete="username" /> <Field label="Username" name="user" component={InputField} autoComplete="username" />
</div> </div>
<div className="loginForm-item"> <div className="loginForm-item">
<Field label="Pass" name="pass" type="password" component={InputField} autoComplete="current-password" /> <Field label="Password" name="pass" type="password" component={InputField} autoComplete="current-password" />
</div> </div>
<div className="loginForm-actions"> <div className="loginForm-actions">
<span>Auto Connect</span> <span>Remember Me</span>
<Button color="primary" onClick={forgotPassword}>Forgot Password</Button> <Button color="primary" onClick={forgotPassword}>Forgot Password</Button>
</div> </div>
<div className="loginForm-item"> <div className="loginForm-item">

View file

@ -0,0 +1,9 @@
import { Countries } from "./countries/_Countries";
import { Faces } from "./faces/_Faces";
import Logo from './logo.png';
export class Images {
static Countries = Countries;
static Faces = Faces;
static Logo = Logo;
}

View file

@ -1,7 +0,0 @@
import Countries from "./countries/_Countries";
export class Images {
static Countries = {
...Countries
};
}

View file

@ -3,4 +3,4 @@
# Except gitignore # Except gitignore
!.gitignore !.gitignore
!_Countries.tsx !_Countries.ts

View file

@ -247,7 +247,7 @@ import za from "./za.svg";
import zm from "./zm.svg"; import zm from "./zm.svg";
import zw from "./zw.svg"; import zw from "./zw.svg";
const Countries = { export const Countries = {
ad, ad,
ae, ae,
af, af,
@ -497,5 +497,3 @@ const Countries = {
zm, zm,
zw, zw,
}; };
export default Countries;

View file

@ -0,0 +1,9 @@
import face1 from './face1.jpg';
import face2 from './face2.jpg';
import face3 from './face3.jpg';
export const Faces = {
face1,
face2,
face3,
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.7 KiB

View file

@ -0,0 +1 @@
export * from './Images';

View file

@ -1,4 +1,5 @@
@import url('https://fonts.googleapis.com/css2?family=Teko&display=swap'); @import url('https://fonts.googleapis.com/css2?family=Teko&display=swap');
@import url('https://fonts.googleapis.com/css2?family=Open+Sans:ital,wght@0,300;0,400;0,500;0,600;0,700;0,800;1,300;1,400;1,500;1,600;1,700;1,800&display=swap');
:root { :root {
@ -19,6 +20,7 @@ body {
font-family: font-family:
-apple-system, -apple-system,
BlinkMacSystemFont, BlinkMacSystemFont,
"Open Sans",
"Segoe UI", "Segoe UI",
"Roboto", "Roboto",
"Oxygen", "Oxygen",

View file

@ -2,7 +2,7 @@ import { createMuiTheme } from '@material-ui/core';
const palette = { const palette = {
background: { background: {
default: 'dimgrey', default: 'rgb(35, 35, 35)',
paper: '#FFFFFF', paper: '#FFFFFF',
}, },
primary: { primary: {
@ -86,15 +86,15 @@ export const materialTheme = createMuiTheme({
justifyContent: 'space-between', justifyContent: 'space-between',
}, },
'& .MuiButtonBase-root.Mui-selected, & .MuiButtonBase-root.Mui-selected:hover, & .MuiButtonBase-root:hover': { '& .MuiButtonBase-root.Mui-selected': {
background: palette.primary.light background: 'none',
fontWeight: 'bold',
}, },
[[ [
'& .MuiButtonBase-root.Mui-selected', '& .MuiButtonBase-root:hover,' +
'& .MuiButtonBase-root.Mui-selected:hover', '& .MuiButtonBase-root.Mui-selected:hover'
'& .MuiButtonBase-root:hover' ]: {
].join(', ')]: {
background: palette.primary.light background: palette.primary.light
}, },
}, },
@ -132,6 +132,7 @@ export const materialTheme = createMuiTheme({
typography: { typography: {
fontSize: 12, fontSize: 12,
fontFamily: 'Open Sans, sans-serif',
h1: { h1: {
fontSize: 28, fontSize: 28,

View file

@ -2,10 +2,12 @@ export enum RouteEnum {
PLAYER = '/player/:name', PLAYER = '/player/:name',
SERVER = '/server', SERVER = '/server',
ROOM = '/room/:roomId', ROOM = '/room/:roomId',
LOGIN = '/', LOGIN = '/login',
LOGS = '/logs', LOGS = '/logs',
GAME = '/game', GAME = '/game',
DECKS = '/decks', DECKS = '/decks',
DECK = '/deck', DECK = '/deck',
ACCOUNT = '/account', ACCOUNT = '/account',
ADMINISTRATION = '/administration',
REPLAYS = '/replays',
} }