Webatrice: update package.json (#4590)

* update package.json

* cleanup

Co-authored-by: Jeremy Letto <jeremy.letto@datasite.com>
This commit is contained in:
Jeremy Letto 2022-03-07 12:43:01 -06:00 committed by GitHub
parent 533045445a
commit 0d0337f091
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
17 changed files with 4618 additions and 10629 deletions

14180
webclient/package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -7,33 +7,33 @@
"@material-ui/icons": "^4.11.2", "@material-ui/icons": "^4.11.2",
"@material-ui/lab": "^4.0.0-alpha.60", "@material-ui/lab": "^4.0.0-alpha.60",
"@material-ui/styles": "^4.11.4", "@material-ui/styles": "^4.11.4",
"@testing-library/jest-dom": "^5.16.1", "@testing-library/jest-dom": "^5.16.2",
"@testing-library/react": "^12.1.2", "@testing-library/react": "^12.1.3",
"crypto-js": "^4.1.1", "crypto-js": "^4.1.1",
"dexie": "^3.0.3", "dexie": "^3.2.1",
"final-form": "^4.20.4", "final-form": "^4.20.6",
"final-form-set-field-touched": "^1.0.1", "final-form-set-field-touched": "^1.0.1",
"i18next": "^21.6.10", "i18next": "^21.6.13",
"i18next-browser-languagedetector": "^6.1.3", "i18next-browser-languagedetector": "^6.1.3",
"jquery": "^3.6.0", "jquery": "^3.6.0",
"lodash": "^4.17.21", "lodash": "^4.17.21",
"prop-types": "^15.7.2", "prop-types": "^15.8.1",
"protobufjs": "^6.11.2", "protobufjs": "^6.11.2",
"react": "^17.0.2", "react": "^17.0.2",
"react-dom": "^17.0.2", "react-dom": "^17.0.2",
"react-final-form": "^6.5.7", "react-final-form": "^6.5.8",
"react-final-form-listeners": "^1.0.3", "react-final-form-listeners": "^1.0.3",
"react-i18next": "^11.15.3", "react-i18next": "^11.15.3",
"react-redux": "^7.2.6", "react-redux": "^7.2.6",
"react-router-dom": "^5.3.0", "react-router-dom": "^6.2.2",
"react-scripts": "4.0.3", "react-scripts": "5.0.0",
"react-virtualized-auto-sizer": "^1.0.6", "react-virtualized-auto-sizer": "^1.0.6",
"react-window": "^1.8.6", "react-window": "^1.8.6",
"redux": "^4.1.2", "redux": "^4.1.2",
"redux-form": "^8.3.7", "redux-form": "^8.3.7",
"redux-thunk": "^2.4.0", "redux-thunk": "^2.4.1",
"rxjs": "^7.4.0", "rxjs": "^7.5.4",
"typescript": "^4.4.4" "typescript": "^4.6.2"
}, },
"scripts": { "scripts": {
"prebuild": "node prebuild.js", "prebuild": "node prebuild.js",
@ -68,24 +68,23 @@
} }
}, },
"devDependencies": { "devDependencies": {
"@types/jest": "27.0.2", "@babel/core": "^7.17.5",
"@types/jquery": "^3.5.8", "@types/jest": "27.4.1",
"@types/lodash": "^4.14.176", "@types/jquery": "^3.5.14",
"@types/lodash": "^4.14.179",
"@types/material-ui": "^0.21.12", "@types/material-ui": "^0.21.12",
"@types/node": "16.11.7", "@types/node": "17.0.21",
"@types/prop-types": "^15.7.4", "@types/prop-types": "^15.7.4",
"@types/protobufjs": "^6.0.0", "@types/react": "17.0.39",
"@types/react": "17.0.34", "@types/react-dom": "17.0.13",
"@types/react-dom": "17.0.11", "@types/react-redux": "^7.1.23",
"@types/react-redux": "^7.1.20",
"@types/react-router-dom": "^5.3.2", "@types/react-router-dom": "^5.3.2",
"@types/react-virtualized-auto-sizer": "^1.0.1", "@types/react-virtualized-auto-sizer": "^1.0.1",
"@types/react-window": "^1.8.5", "@types/react-window": "^1.8.5",
"@types/redux-form": "^8.3.3", "@types/redux-form": "^8.3.3",
"@typescript-eslint/eslint-plugin": "^5.3.1", "@typescript-eslint/eslint-plugin": "^5.13.0",
"@typescript-eslint/parser": "^5.3.1", "@typescript-eslint/parser": "^5.13.0",
"eslint": "^7.32.0", "fs-extra": "^10.0.1",
"fs-extra": "^10.0.0",
"i18next-icu": "^2.0.3", "i18next-icu": "^2.0.3",
"identity-obj-proxy": "^3.0.0", "identity-obj-proxy": "^3.0.0",
"intl-messageformat": "^9.11.4" "intl-messageformat": "^9.11.4"

View file

@ -1,6 +1,6 @@
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 { Navigate } from 'react-router-dom';
import { ServerSelectors } from 'store'; import { ServerSelectors } from 'store';
import { RouteEnum } from 'types'; import { RouteEnum } from 'types';
@ -9,7 +9,7 @@ import { AuthenticationService } from 'api';
const AuthGuard = ({ state }: AuthGuardProps) => { const AuthGuard = ({ state }: AuthGuardProps) => {
return !AuthenticationService.isConnected(state) return !AuthenticationService.isConnected(state)
? <Redirect from="*" to={RouteEnum.LOGIN} /> ? <Navigate to={RouteEnum.LOGIN} />
: <div></div>; : <div></div>;
}; };

View file

@ -1,6 +1,6 @@
import React, { Component } from 'react'; import React, { Component } from 'react';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { Redirect } from 'react-router-dom'; import { Navigate } from 'react-router-dom';
import { ServerSelectors } from 'store'; import { ServerSelectors } from 'store';
import { User } from 'types'; import { User } from 'types';
@ -11,7 +11,7 @@ import { RouteEnum } from 'types';
class ModGuard extends Component<ModGuardProps> { class ModGuard extends Component<ModGuardProps> {
render() { render() {
return !AuthenticationService.isModerator(this.props.user) return !AuthenticationService.isModerator(this.props.user)
? <Redirect from="*" to={RouteEnum.SERVER} /> ? <Navigate to={RouteEnum.SERVER} />
: ''; : '';
} }
}; };

View file

@ -1,6 +1,6 @@
import React, { Component } from 'react'; import React, { useState, useEffect } from 'react';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { NavLink, withRouter, generatePath } from 'react-router-dom'; import { NavLink, useNavigate, generatePath } from 'react-router-dom';
import AppBar from '@material-ui/core/AppBar'; import AppBar from '@material-ui/core/AppBar';
import IconButton from '@material-ui/core/IconButton'; import IconButton from '@material-ui/core/IconButton';
import Menu from '@material-ui/core/Menu'; import Menu from '@material-ui/core/Menu';
@ -20,71 +20,19 @@ import { Room, RouteEnum, User } from 'types';
import './Header.css'; import './Header.css';
class Header extends Component<HeaderProps> { const Header = ({ joinedRooms, serverState, user }: HeaderProps) => {
state: HeaderState; const navigate = useNavigate();
options: string[] = [ const [state, setState] = useState<HeaderState>({
'Account', anchorEl: null,
'Replays', showCardImportDialog: false,
]; options: [],
});
constructor(props) { useEffect(() => {
super(props); let options: string[] = [
'Account',
this.state = { 'Replays',
anchorEl: null, ];
showCardImportDialog: false,
};
this.handleMenuOpen = this.handleMenuOpen.bind(this);
this.handleMenuItemClick = this.handleMenuItemClick.bind(this);
this.handleMenuClose = this.handleMenuClose.bind(this);
this.leaveRoom = this.leaveRoom.bind(this);
this.openImportCardWizard = this.openImportCardWizard.bind(this);
this.closeImportCardWizard = this.closeImportCardWizard.bind(this);
}
componentDidUpdate(prevProps) {
const currentRooms = this.props.joinedRooms;
const previousRooms = prevProps.joinedRooms;
if (currentRooms > previousRooms) {
const { roomId } = _.difference(currentRooms, previousRooms)[0];
this.props.history.push(generatePath(RouteEnum.ROOM, { roomId }));
}
}
handleMenuOpen(event) {
this.setState({ anchorEl: event.target });
}
handleMenuItemClick(option: string) {
const route = RouteEnum[option.toUpperCase()];
this.props.history.push(generatePath(route));
}
handleMenuClose() {
this.setState({ anchorEl: null });
}
leaveRoom(event, roomId) {
event.preventDefault();
RoomsService.leaveRoom(roomId);
};
openImportCardWizard() {
this.setState({ showCardImportDialog: true });
this.handleMenuClose();
}
closeImportCardWizard() {
this.setState({ showCardImportDialog: false });
}
render() {
const { joinedRooms, state, user } = this.props;
const { anchorEl, showCardImportDialog } = this.state;
let options = [...this.options];
if (user && AuthenticationService.isModerator(user)) { if (user && AuthenticationService.isModerator(user)) {
options = [ options = [
@ -94,122 +42,155 @@ class Header extends Component<HeaderProps> {
]; ];
} }
return ( setState(s => ({ ...s, options }));
<AppBar className="Header" position="static"> }, [user]);
<Toolbar variant="dense">
<div className="Header__logo">
<NavLink to={RouteEnum.SERVER}>
<img src={Images.Logo} alt="logo" />
</NavLink>
{ AuthenticationService.isConnected(state) && (
<span className="Header-server__indicator"></span>
) }
</div>
{ AuthenticationService.isConnected(state) && (
<div className="Header-content">
<nav className="Header-nav">
<nav className="Header-nav__links">
<div className="Header-nav__link">
<NavLink
className="Header-nav__link-btn"
to={ joinedRooms.length ? generatePath(RouteEnum.ROOM, { roomId: joinedRooms[0].roomId }) : RouteEnum.SERVER }
>
Rooms
<ArrowDropDownIcon className="Header-nav__link-btn__icon" fontSize="small" />
</NavLink>
<div className="Header-nav__link-menu">
{joinedRooms.map(({ name, roomId }) => (
<MenuItem className="Header-nav__link-menu__item" key={roomId}>
<NavLink className="Header-nav__link-menu__btn" to={ generatePath(RouteEnum.ROOM, { roomId: roomId }) }>
{name}
<IconButton size="small" edge="end" onClick={event => this.leaveRoom(event, roomId)}> const handleMenuOpen = (event) => {
<CloseIcon style={{ fontSize: 10, color: 'white' }} /> setState(s => ({ ...s, anchorEl: event.target }));
</IconButton> }
</NavLink>
</MenuItem>
))}
</div>
</div>
<div className="Header-nav__link">
<NavLink className="Header-nav__link-btn" to={ RouteEnum.GAME }>
Games
<ArrowDropDownIcon className="Header-nav__link-btn__icon" fontSize="small" />
</NavLink>
</div>
<div className="Header-nav__link">
<NavLink className="Header-nav__link-btn" to={ RouteEnum.DECKS }>
Decks
<ArrowDropDownIcon className="Header-nav__link-btn__icon" fontSize="small" />
</NavLink>
</div>
</nav>
<div className="Header-nav__actions">
<div className="Header-nav__action">
<IconButton>
<MailOutlineRoundedIcon style={{ color: 'inherit' }} />
</IconButton>
</div>
<div className="Header-nav__action">
<IconButton onClick={this.handleMenuOpen}>
<MenuRoundedIcon style={{ color: 'inherit' }} />
</IconButton>
<Menu
anchorEl={anchorEl}
keepMounted
open={!!anchorEl}
onClose={() => this.handleMenuClose()}
PaperProps={{
style: {
marginTop: '32px',
width: '20ch',
},
}}
>
{options.map((option) => (
<MenuItem key={option} onClick={(event) => this.handleMenuItemClick(option)}>
{option}
</MenuItem>
))}
<MenuItem key='Import Cards' onClick={(event) => this.openImportCardWizard()}> const handleMenuItemClick = (option: string) => {
Import Cards const route = RouteEnum[option.toUpperCase()];
navigate(generatePath(route));
}
const handleMenuClose = () => {
setState(s => ({ ...s, anchorEl: null }));
}
const leaveRoom = (event, roomId) => {
event.preventDefault();
RoomsService.leaveRoom(roomId);
};
const openImportCardWizard = () => {
setState(s => ({ ...s, showCardImportDialog: true }));
handleMenuClose();
}
const closeImportCardWizard = () => {
setState(s => ({ ...s, showCardImportDialog: false }));
}
return (
<AppBar className="Header" position="static">
<Toolbar variant="dense">
<div className="Header__logo">
<NavLink to={RouteEnum.SERVER}>
<img src={Images.Logo} alt="logo" />
</NavLink>
{ AuthenticationService.isConnected(serverState) && (
<span className="Header-server__indicator"></span>
) }
</div>
{ AuthenticationService.isConnected(serverState) && (
<div className="Header-content">
<nav className="Header-nav">
<nav className="Header-nav__links">
<div className="Header-nav__link">
<NavLink
className="Header-nav__link-btn"
to={
joinedRooms.length
? generatePath(RouteEnum.ROOM, { roomId: joinedRooms[0].roomId.toString() })
: RouteEnum.SERVER
}
>
Rooms
<ArrowDropDownIcon className="Header-nav__link-btn__icon" fontSize="small" />
</NavLink>
<div className="Header-nav__link-menu">
{joinedRooms.map(({ name, roomId }) => (
<MenuItem className="Header-nav__link-menu__item" key={roomId}>
<NavLink className="Header-nav__link-menu__btn" to={ generatePath(RouteEnum.ROOM, { roomId: roomId.toString() }) }>
{name}
<IconButton size="small" edge="end" onClick={event => leaveRoom(event, roomId)}>
<CloseIcon style={{ fontSize: 10, color: 'white' }} />
</IconButton>
</NavLink>
</MenuItem> </MenuItem>
</Menu> ))}
</div> </div>
</div> </div>
<div className="Header-nav__link">
<NavLink className="Header-nav__link-btn" to={ RouteEnum.GAME }>
Games
<ArrowDropDownIcon className="Header-nav__link-btn__icon" fontSize="small" />
</NavLink>
</div>
<div className="Header-nav__link">
<NavLink className="Header-nav__link-btn" to={ RouteEnum.DECKS }>
Decks
<ArrowDropDownIcon className="Header-nav__link-btn__icon" fontSize="small" />
</NavLink>
</div>
</nav> </nav>
</div> <div className="Header-nav__actions">
) } <div className="Header-nav__action">
</Toolbar> <IconButton>
<MailOutlineRoundedIcon style={{ color: 'inherit' }} />
</IconButton>
</div>
<div className="Header-nav__action">
<IconButton onClick={handleMenuOpen}>
<MenuRoundedIcon style={{ color: 'inherit' }} />
</IconButton>
<Menu
anchorEl={state.anchorEl}
keepMounted
open={!!state.anchorEl}
onClose={() => handleMenuClose()}
PaperProps={{
style: {
marginTop: '32px',
width: '20ch',
},
}}
>
{state.options.map((option) => (
<MenuItem key={option} onClick={(event) => handleMenuItemClick(option)}>
{option}
</MenuItem>
))}
<CardImportDialog <MenuItem key='Import Cards' onClick={(event) => openImportCardWizard()}>
isOpen={showCardImportDialog} Import Cards
handleClose={this.closeImportCardWizard} </MenuItem>
></CardImportDialog> </Menu>
</AppBar> </div>
) </div>
} </nav>
</div>
) }
</Toolbar>
<CardImportDialog
isOpen={state.showCardImportDialog}
handleClose={closeImportCardWizard}
></CardImportDialog>
</AppBar>
)
} }
interface HeaderProps { interface HeaderProps {
state: number; serverState: number;
server: string; server: string;
user: User; user: User;
joinedRooms: Room[]; joinedRooms: Room[];
history: any;
} }
interface HeaderState { interface HeaderState {
anchorEl: Element; anchorEl: Element;
showCardImportDialog: boolean; showCardImportDialog: boolean;
options: string[];
} }
const mapStateToProps = state => ({ const mapStateToProps = state => ({
state: ServerSelectors.getState(state), serverState: ServerSelectors.getState(state),
server: ServerSelectors.getName(state), server: ServerSelectors.getName(state),
user: ServerSelectors.getUser(state), user: ServerSelectors.getUser(state),
joinedRooms: RoomsSelectors.getJoinedRooms(state), joinedRooms: RoomsSelectors.getJoinedRooms(state),
}); });
export default withRouter(connect(mapStateToProps)(Header)); export default connect(mapStateToProps)(Header);

View file

@ -21,7 +21,7 @@ const InputAction = ({ action, label, name, validate, disabled }) => (
InputAction.defaultProps = { InputAction.defaultProps = {
disabled: false, disabled: false,
validate: () => true, validate: () => false,
} }
export default InputAction; export default InputAction;

View file

@ -1,5 +1,5 @@
import React from 'react'; import React from 'react';
import { Redirect, Route, Switch } from 'react-router-dom'; import { Navigate, Route, Routes } from 'react-router-dom';
import { RouteEnum } from 'types'; import { RouteEnum } from 'types';
import { import {
@ -15,23 +15,22 @@ import {
Unsupported Unsupported
} from 'containers'; } from 'containers';
const Routes = () => ( const AppShellRoutes = () => (
<div className="AppShell-routes overflow-scroll"> <div className="AppShell-routes overflow-scroll">
<Switch> <Routes>
<Route path={RouteEnum.ACCOUNT} render={() => <Account />} /> <Route path='*' element={<Initialize />} />
<Route path={RouteEnum.DECKS} render={() => <Decks />} />
<Route path={RouteEnum.GAME} render={() => <Game />} />
<Route path={RouteEnum.LOGS} render={() => <Logs />} />
<Route path={RouteEnum.PLAYER} render={() => <Player />} />
{<Route path={RouteEnum.ROOM} render={() => <Room />} />}
<Route path={RouteEnum.SERVER} render={() => <Server />} />
<Route path={RouteEnum.LOGIN} render={() => <Login />} />
<Route path={RouteEnum.INITIALIZE} render={() => <Initialize />} />
<Route path={RouteEnum.UNSUPPORTED} render={() => <Unsupported />} />
<Redirect from="*" to={RouteEnum.INITIALIZE} /> <Route path={RouteEnum.ACCOUNT} element={<Account />} />
</Switch> <Route path={RouteEnum.DECKS} element={<Decks />} />
<Route path={RouteEnum.GAME} element={<Game />} />
<Route path={RouteEnum.LOGS} element={<Logs />} />
<Route path={RouteEnum.PLAYER} element={<Player />} />
{<Route path={RouteEnum.ROOM} element={<Room />} />}
<Route path={RouteEnum.SERVER} element={<Server />} />
<Route path={RouteEnum.LOGIN} element={<Login />} />
<Route path={RouteEnum.UNSUPPORTED} element={<Unsupported />} />
</Routes>
</div> </div>
); );
export default Routes; export default AppShellRoutes;

View file

@ -1,5 +1,5 @@
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import { Redirect } from 'react-router-dom'; import { Navigate } from 'react-router-dom';
import { dexieService } from 'services'; import { dexieService } from 'services';
import { RouteEnum } from 'types'; import { RouteEnum } from 'types';
@ -15,7 +15,7 @@ const FeatureDetection = () => {
}, []); }, []);
return unsupported return unsupported
? <Redirect from="*" to={RouteEnum.UNSUPPORTED} /> ? <Navigate to={RouteEnum.UNSUPPORTED} />
: <></>; : <></>;
function detectIndexedDB() { function detectIndexedDB() {

View file

@ -1,7 +1,7 @@
import { useState } from 'react'; import { useState } from 'react';
import { useTranslation, Trans } from 'react-i18next'; import { useTranslation, Trans } from 'react-i18next';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { Redirect, withRouter } from 'react-router-dom'; import { Navigate } from 'react-router-dom';
import { makeStyles } from '@material-ui/core/styles'; import { makeStyles } from '@material-ui/core/styles';
import Typography from '@material-ui/core/Typography'; import Typography from '@material-ui/core/Typography';
@ -28,7 +28,7 @@ const Initialize = ({ initialized }: InitializeProps) => {
const { t } = useTranslation(); const { t } = useTranslation();
return initialized return initialized
? <Redirect from="*" to={RouteEnum.LOGIN} /> ? <Navigate to={RouteEnum.LOGIN} />
: ( : (
<div className={'Initialize ' + classes.root}> <div className={'Initialize ' + classes.root}>
<div className='Initialize-content'> <div className='Initialize-content'>
@ -60,4 +60,4 @@ const mapStateToProps = state => ({
initialized: ServerSelectors.getInitialized(state), initialized: ServerSelectors.getInitialized(state),
}); });
export default withRouter(connect(mapStateToProps)(Initialize)); export default connect(mapStateToProps)(Initialize);

View file

@ -1,7 +1,7 @@
import { useState, useCallback } from 'react'; import { useState, useCallback } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { Redirect } from 'react-router-dom'; import { Navigate } from 'react-router-dom';
import { makeStyles } 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';
@ -221,7 +221,7 @@ const Login = ({ state, description, connectOptions }: LoginProps) => {
return ( return (
<div className={'login overflow-scroll ' + classes.root}> <div className={'login overflow-scroll ' + classes.root}>
{ isConnected && <Redirect from="*" to={RouteEnum.SERVER} />} { isConnected && <Navigate to={RouteEnum.SERVER} />}
<div className="login__wrapper"> <div className="login__wrapper">
<Paper className="login-content"> <Paper className="login-content">

View file

@ -1,6 +1,6 @@
import React from 'react'; import React, { useEffect } from 'react';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { withRouter, generatePath } from 'react-router-dom'; import { useNavigate, useParams, generatePath } from 'react-router-dom';
import ListItem from '@material-ui/core/ListItem'; import ListItem from '@material-ui/core/ListItem';
import Paper from '@material-ui/core/Paper'; import Paper from '@material-ui/core/Paper';
@ -17,26 +17,28 @@ import SayMessage from './SayMessage';
import './Room.css'; import './Room.css';
// @TODO (3) // @TODO (3)
function Room(props) { const Room = (props) => {
const { joined, rooms, messages } = props;
const navigate = useNavigate();
const params = useParams();
const { joined, match, history, rooms, messages } = props; const roomId = parseInt(params.roomId, 0);
const roomId = parseInt(match.params.roomId, 0); const room = rooms[roomId];
const roomMessages = messages[roomId];
const users = room.userList;
if (!joined.find(({ roomId: id }) => id === roomId)) { useEffect(() => {
history.push(generatePath(RouteEnum.SERVER)); if (!joined.find(({ roomId: id }) => id === roomId)) {
} navigate(generatePath(RouteEnum.SERVER));
}
}, [joined]);
function handleRoomSay({ message }) { const handleRoomSay = ({ message }) => {
if (message) { if (message) {
RoomsService.roomSay(roomId, message); RoomsService.roomSay(roomId, message);
} }
} }
const room = rooms[roomId];
const roomMessages = messages[roomId];
const users = room.userList;
return ( return (
<div className="room-view"> <div className="room-view">
<AuthGuard /> <AuthGuard />
@ -98,4 +100,4 @@ const mapStateToProps = state => ({
joined: RoomsSelectors.getJoinedRooms(state), joined: RoomsSelectors.getJoinedRooms(state),
}); });
export default withRouter(connect(mapStateToProps)(Room)); export default connect(mapStateToProps)(Room);

View file

@ -3,22 +3,17 @@ import { Form } from 'react-final-form'
import { InputAction } from 'components'; import { InputAction } from 'components';
const required = (value) => (value ? undefined : 'Required'); const SayMessage = ({ onSubmit }) => (
<Form onSubmit={onSubmit}>
const SayMessage = (props) => { {({ handleSubmit, form }) => (
const { onSubmit } = props <form onSubmit={e => {
return ( handleSubmit(e)
<Form onSubmit={values => onSubmit(values)}> form.restart()
{({ handleSubmit, form }) => ( }}>
<form onSubmit={e => { <InputAction action="Send" label="Chat" name="message" />
handleSubmit(e) </form>
form.restart() )}
}}> </Form>
<InputAction action="Send" label="Chat" name="message" validate={required}/> );
</form>
)}
</Form>
);
}
export default SayMessage; export default SayMessage;

View file

@ -1,6 +1,6 @@
// eslint-disable-next-line // eslint-disable-next-line
import React from "react"; import React from "react";
import { generatePath } from 'react-router-dom'; import { generatePath, useNavigate } from 'react-router-dom';
import * as _ from 'lodash'; import * as _ from 'lodash';
import Button from '@material-ui/core/Button'; import Button from '@material-ui/core/Button';
@ -16,10 +16,12 @@ import { RouteEnum } from 'types';
import './Rooms.css'; import './Rooms.css';
const Rooms = ({ rooms, joinedRooms, history }) => { const Rooms = ({ rooms, joinedRooms }) => {
const navigate = useNavigate();
function onClick(roomId) { function onClick(roomId) {
if (_.find(joinedRooms, room => room.roomId === roomId)) { if (_.find(joinedRooms, room => room.roomId === roomId)) {
history.push(generatePath(RouteEnum.ROOM, { roomId })); navigate(generatePath(RouteEnum.ROOM, { roomId }));
} else { } else {
RoomsService.joinRoom(roomId); RoomsService.joinRoom(roomId);
} }

View file

@ -1,59 +1,62 @@
// eslint-disable-next-line // eslint-disable-next-line
import React, { Component } from "react"; import React, { Component } from "react";
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { withRouter } from 'react-router-dom'; import { generatePath, useNavigate } from 'react-router-dom';
import ListItem from '@material-ui/core/ListItem'; import ListItem from '@material-ui/core/ListItem';
import Paper from '@material-ui/core/Paper'; import Paper from '@material-ui/core/Paper';
import { RoomsSelectors, ServerSelectors } from 'store';
import { AuthGuard, ThreePaneLayout, UserDisplay, VirtualList } from 'components'; import { AuthGuard, ThreePaneLayout, UserDisplay, VirtualList } from 'components';
import { Room, User } from 'types'; import { useReduxEffect } from 'hooks';
import { RoomsSelectors, RoomsTypes, ServerSelectors } from 'store';
import { Room, RouteEnum, User } from 'types';
import Rooms from './Rooms'; import Rooms from './Rooms';
import './Server.css'; import './Server.css';
class Server extends Component<ServerProps, ServerState> { const Server = ({ message, rooms, joinedRooms, users }: ServerProps) => {
render() { const navigate = useNavigate();
const { message, rooms, joinedRooms, history, users } = this.props;
return ( useReduxEffect((action: any) => {
<div className="server-rooms"> const roomId = action.roomInfo.roomId.toString();
<AuthGuard /> navigate(generatePath(RouteEnum.ROOM, { roomId }));
}, RoomsTypes.JOIN_ROOM, []);
<ThreePaneLayout return (
top={( <div className="server-rooms">
<Paper className="serverRoomWrapper overflow-scroll"> <AuthGuard />
<Rooms rooms={rooms} joinedRooms={joinedRooms} history={history} />
</Paper>
)}
bottom={( <ThreePaneLayout
<Paper className="serverMessage overflow-scroll"> top={(
<div className="serverMessage__content" dangerouslySetInnerHTML={{ __html: message }} /> <Paper className="serverRoomWrapper overflow-scroll">
</Paper> <Rooms rooms={rooms} joinedRooms={joinedRooms} />
)} </Paper>
)}
side={( bottom={(
<Paper className="server-rooms__side overflow-scroll"> <Paper className="serverMessage overflow-scroll">
<div className="server-rooms__side-label"> <div className="serverMessage__content" dangerouslySetInnerHTML={{ __html: message }} />
Users connected to server: {users.length} </Paper>
</div> )}
<VirtualList
itemKey={(index) => users[index].name } side={(
items={ users.map(user => ( <Paper className="server-rooms__side overflow-scroll">
<ListItem button dense> <div className="server-rooms__side-label">
<UserDisplay user={user} /> Users connected to server: {users.length}
</ListItem> </div>
)) } <VirtualList
/> itemKey={(index) => users[index].name }
</Paper> items={ users.map(user => (
)} <ListItem button dense>
/> <UserDisplay user={user} />
</div> </ListItem>
); )) }
} />
</Paper>
)}
/>
</div>
);
} }
interface ServerProps { interface ServerProps {
@ -61,11 +64,6 @@ interface ServerProps {
rooms: Room[]; rooms: Room[];
joinedRooms: Room[]; joinedRooms: Room[];
users: User[]; users: User[];
history: any;
}
interface ServerState {
} }
const mapStateToProps = state => ({ const mapStateToProps = state => ({
@ -75,4 +73,4 @@ const mapStateToProps = state => ({
users: ServerSelectors.getUsers(state) users: ServerSelectors.getUsers(state)
}); });
export default withRouter(connect(mapStateToProps)(Server)); export default connect(mapStateToProps)(Server);

View file

@ -1,6 +1,5 @@
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { withRouter } from 'react-router-dom';
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';
@ -27,4 +26,4 @@ const mapStateToProps = state => ({
}); });
export default withRouter(connect(mapStateToProps)(Unsupported)); export default connect(mapStateToProps)(Unsupported);

View file

@ -1,253 +1,255 @@
import ad from './ad.svg'; // Remove !file-loader! once the following is no longer an issue
import ae from './ae.svg'; // https://github.com/facebook/create-react-app/issues/11770
import af from './af.svg'; import ad from '!file-loader!./ad.svg';
import ag from './ag.svg'; import ae from '!file-loader!./ae.svg';
import ai from './ai.svg'; import af from '!file-loader!./af.svg';
import al from './al.svg'; import ag from '!file-loader!./ag.svg';
import am from './am.svg'; import ai from '!file-loader!./ai.svg';
import ao from './ao.svg'; import al from '!file-loader!./al.svg';
import aq from './aq.svg'; import am from '!file-loader!./am.svg';
import ar from './ar.svg'; import ao from '!file-loader!./ao.svg';
import as from './as.svg'; import aq from '!file-loader!./aq.svg';
import at from './at.svg'; import ar from '!file-loader!./ar.svg';
import au from './au.svg'; import as from '!file-loader!./as.svg';
import aw from './aw.svg'; import at from '!file-loader!./at.svg';
import ax from './ax.svg'; import au from '!file-loader!./au.svg';
import az from './az.svg'; import aw from '!file-loader!./aw.svg';
import ba from './ba.svg'; import ax from '!file-loader!./ax.svg';
import bb from './bb.svg'; import az from '!file-loader!./az.svg';
import bd from './bd.svg'; import ba from '!file-loader!./ba.svg';
import be from './be.svg'; import bb from '!file-loader!./bb.svg';
import bf from './bf.svg'; import bd from '!file-loader!./bd.svg';
import bg from './bg.svg'; import be from '!file-loader!./be.svg';
import bh from './bh.svg'; import bf from '!file-loader!./bf.svg';
import bi from './bi.svg'; import bg from '!file-loader!./bg.svg';
import bj from './bj.svg'; import bh from '!file-loader!./bh.svg';
import bl from './bl.svg'; import bi from '!file-loader!./bi.svg';
import bm from './bm.svg'; import bj from '!file-loader!./bj.svg';
import bn from './bn.svg'; import bl from '!file-loader!./bl.svg';
import bo from './bo.svg'; import bm from '!file-loader!./bm.svg';
import bq from './bq.svg'; import bn from '!file-loader!./bn.svg';
import br from './br.svg'; import bo from '!file-loader!./bo.svg';
import bs from './bs.svg'; import bq from '!file-loader!./bq.svg';
import bt from './bt.svg'; import br from '!file-loader!./br.svg';
import bv from './bv.svg'; import bs from '!file-loader!./bs.svg';
import bw from './bw.svg'; import bt from '!file-loader!./bt.svg';
import by from './by.svg'; import bv from '!file-loader!./bv.svg';
import bz from './bz.svg'; import bw from '!file-loader!./bw.svg';
import ca from './ca.svg'; import by from '!file-loader!./by.svg';
import cc from './cc.svg'; import bz from '!file-loader!./bz.svg';
import cd from './cd.svg'; import ca from '!file-loader!./ca.svg';
import cf from './cf.svg'; import cc from '!file-loader!./cc.svg';
import cg from './cg.svg'; import cd from '!file-loader!./cd.svg';
import ch from './ch.svg'; import cf from '!file-loader!./cf.svg';
import ci from './ci.svg'; import cg from '!file-loader!./cg.svg';
import ck from './ck.svg'; import ch from '!file-loader!./ch.svg';
import cl from './cl.svg'; import ci from '!file-loader!./ci.svg';
import cm from './cm.svg'; import ck from '!file-loader!./ck.svg';
import cn from './cn.svg'; import cl from '!file-loader!./cl.svg';
import co from './co.svg'; import cm from '!file-loader!./cm.svg';
import cr from './cr.svg'; import cn from '!file-loader!./cn.svg';
import cu from './cu.svg'; import co from '!file-loader!./co.svg';
import cv from './cv.svg'; import cr from '!file-loader!./cr.svg';
import cw from './cw.svg'; import cu from '!file-loader!./cu.svg';
import cx from './cx.svg'; import cv from '!file-loader!./cv.svg';
import cy from './cy.svg'; import cw from '!file-loader!./cw.svg';
import cz from './cz.svg'; import cx from '!file-loader!./cx.svg';
import de from './de.svg'; import cy from '!file-loader!./cy.svg';
import dj from './dj.svg'; import cz from '!file-loader!./cz.svg';
import dk from './dk.svg'; import de from '!file-loader!./de.svg';
import dm from './dm.svg'; import dj from '!file-loader!./dj.svg';
import _do from './do.svg'; import dk from '!file-loader!./dk.svg';
import dz from './dz.svg'; import dm from '!file-loader!./dm.svg';
import ec from './ec.svg'; import _do from '!file-loader!./do.svg';
import ee from './ee.svg'; import dz from '!file-loader!./dz.svg';
import eg from './eg.svg'; import ec from '!file-loader!./ec.svg';
import eh from './eh.svg'; import ee from '!file-loader!./ee.svg';
import er from './er.svg'; import eg from '!file-loader!./eg.svg';
import es from './es.svg'; import eh from '!file-loader!./eh.svg';
import et from './et.svg'; import er from '!file-loader!./er.svg';
import eu from './eu.svg'; import es from '!file-loader!./es.svg';
import fi from './fi.svg'; import et from '!file-loader!./et.svg';
import fj from './fj.svg'; import eu from '!file-loader!./eu.svg';
import fk from './fk.svg'; import fi from '!file-loader!./fi.svg';
import fm from './fm.svg'; import fj from '!file-loader!./fj.svg';
import fo from './fo.svg'; import fk from '!file-loader!./fk.svg';
import fr from './fr.svg'; import fm from '!file-loader!./fm.svg';
import ga from './ga.svg'; import fo from '!file-loader!./fo.svg';
import gb from './gb.svg'; import fr from '!file-loader!./fr.svg';
import gd from './gd.svg'; import ga from '!file-loader!./ga.svg';
import ge from './ge.svg'; import gb from '!file-loader!./gb.svg';
import gf from './gf.svg'; import gd from '!file-loader!./gd.svg';
import gg from './gg.svg'; import ge from '!file-loader!./ge.svg';
import gh from './gh.svg'; import gf from '!file-loader!./gf.svg';
import gi from './gi.svg'; import gg from '!file-loader!./gg.svg';
import gl from './gl.svg'; import gh from '!file-loader!./gh.svg';
import gm from './gm.svg'; import gi from '!file-loader!./gi.svg';
import gn from './gn.svg'; import gl from '!file-loader!./gl.svg';
import gp from './gp.svg'; import gm from '!file-loader!./gm.svg';
import gq from './gq.svg'; import gn from '!file-loader!./gn.svg';
import gr from './gr.svg'; import gp from '!file-loader!./gp.svg';
import gs from './gs.svg'; import gq from '!file-loader!./gq.svg';
import gt from './gt.svg'; import gr from '!file-loader!./gr.svg';
import gu from './gu.svg'; import gs from '!file-loader!./gs.svg';
import gw from './gw.svg'; import gt from '!file-loader!./gt.svg';
import gy from './gy.svg'; import gu from '!file-loader!./gu.svg';
import hk from './hk.svg'; import gw from '!file-loader!./gw.svg';
import hm from './hm.svg'; import gy from '!file-loader!./gy.svg';
import hn from './hn.svg'; import hk from '!file-loader!./hk.svg';
import hr from './hr.svg'; import hm from '!file-loader!./hm.svg';
import ht from './ht.svg'; import hn from '!file-loader!./hn.svg';
import hu from './hu.svg'; import hr from '!file-loader!./hr.svg';
import id from './id.svg'; import ht from '!file-loader!./ht.svg';
import ie from './ie.svg'; import hu from '!file-loader!./hu.svg';
import il from './il.svg'; import id from '!file-loader!./id.svg';
import im from './im.svg'; import ie from '!file-loader!./ie.svg';
import _in from './in.svg'; import il from '!file-loader!./il.svg';
import io from './io.svg'; import im from '!file-loader!./im.svg';
import iq from './iq.svg'; import _in from '!file-loader!./in.svg';
import ir from './ir.svg'; import io from '!file-loader!./io.svg';
import is from './is.svg'; import iq from '!file-loader!./iq.svg';
import it from './it.svg'; import ir from '!file-loader!./ir.svg';
import je from './je.svg'; import is from '!file-loader!./is.svg';
import jm from './jm.svg'; import it from '!file-loader!./it.svg';
import jo from './jo.svg'; import je from '!file-loader!./je.svg';
import jp from './jp.svg'; import jm from '!file-loader!./jm.svg';
import ke from './ke.svg'; import jo from '!file-loader!./jo.svg';
import kg from './kg.svg'; import jp from '!file-loader!./jp.svg';
import kh from './kh.svg'; import ke from '!file-loader!./ke.svg';
import ki from './ki.svg'; import kg from '!file-loader!./kg.svg';
import km from './km.svg'; import kh from '!file-loader!./kh.svg';
import kn from './kn.svg'; import ki from '!file-loader!./ki.svg';
import kp from './kp.svg'; import km from '!file-loader!./km.svg';
import kr from './kr.svg'; import kn from '!file-loader!./kn.svg';
import kw from './kw.svg'; import kp from '!file-loader!./kp.svg';
import ky from './ky.svg'; import kr from '!file-loader!./kr.svg';
import kz from './kz.svg'; import kw from '!file-loader!./kw.svg';
import la from './la.svg'; import ky from '!file-loader!./ky.svg';
import lb from './lb.svg'; import kz from '!file-loader!./kz.svg';
import lc from './lc.svg'; import la from '!file-loader!./la.svg';
import li from './li.svg'; import lb from '!file-loader!./lb.svg';
import lk from './lk.svg'; import lc from '!file-loader!./lc.svg';
import lr from './lr.svg'; import li from '!file-loader!./li.svg';
import ls from './ls.svg'; import lk from '!file-loader!./lk.svg';
import lt from './lt.svg'; import lr from '!file-loader!./lr.svg';
import lu from './lu.svg'; import ls from '!file-loader!./ls.svg';
import lv from './lv.svg'; import lt from '!file-loader!./lt.svg';
import ly from './ly.svg'; import lu from '!file-loader!./lu.svg';
import ma from './ma.svg'; import lv from '!file-loader!./lv.svg';
import mc from './mc.svg'; import ly from '!file-loader!./ly.svg';
import md from './md.svg'; import ma from '!file-loader!./ma.svg';
import me from './me.svg'; import mc from '!file-loader!./mc.svg';
import mf from './mf.svg'; import md from '!file-loader!./md.svg';
import mg from './mg.svg'; import me from '!file-loader!./me.svg';
import mh from './mh.svg'; import mf from '!file-loader!./mf.svg';
import mk from './mk.svg'; import mg from '!file-loader!./mg.svg';
import ml from './ml.svg'; import mh from '!file-loader!./mh.svg';
import mm from './mm.svg'; import mk from '!file-loader!./mk.svg';
import mn from './mn.svg'; import ml from '!file-loader!./ml.svg';
import mo from './mo.svg'; import mm from '!file-loader!./mm.svg';
import mp from './mp.svg'; import mn from '!file-loader!./mn.svg';
import mq from './mq.svg'; import mo from '!file-loader!./mo.svg';
import mr from './mr.svg'; import mp from '!file-loader!./mp.svg';
import ms from './ms.svg'; import mq from '!file-loader!./mq.svg';
import mt from './mt.svg'; import mr from '!file-loader!./mr.svg';
import mu from './mu.svg'; import ms from '!file-loader!./ms.svg';
import mv from './mv.svg'; import mt from '!file-loader!./mt.svg';
import mw from './mw.svg'; import mu from '!file-loader!./mu.svg';
import mx from './mx.svg'; import mv from '!file-loader!./mv.svg';
import my from './my.svg'; import mw from '!file-loader!./mw.svg';
import mz from './mz.svg'; import mx from '!file-loader!./mx.svg';
import na from './na.svg'; import my from '!file-loader!./my.svg';
import nc from './nc.svg'; import mz from '!file-loader!./mz.svg';
import ne from './ne.svg'; import na from '!file-loader!./na.svg';
import nf from './nf.svg'; import nc from '!file-loader!./nc.svg';
import ng from './ng.svg'; import ne from '!file-loader!./ne.svg';
import ni from './ni.svg'; import nf from '!file-loader!./nf.svg';
import nl from './nl.svg'; import ng from '!file-loader!./ng.svg';
import no from './no.svg'; import ni from '!file-loader!./ni.svg';
import np from './np.svg'; import nl from '!file-loader!./nl.svg';
import nr from './nr.svg'; import no from '!file-loader!./no.svg';
import nu from './nu.svg'; import np from '!file-loader!./np.svg';
import nz from './nz.svg'; import nr from '!file-loader!./nr.svg';
import om from './om.svg'; import nu from '!file-loader!./nu.svg';
import pa from './pa.svg'; import nz from '!file-loader!./nz.svg';
import pe from './pe.svg'; import om from '!file-loader!./om.svg';
import pf from './pf.svg'; import pa from '!file-loader!./pa.svg';
import pg from './pg.svg'; import pe from '!file-loader!./pe.svg';
import ph from './ph.svg'; import pf from '!file-loader!./pf.svg';
import pk from './pk.svg'; import pg from '!file-loader!./pg.svg';
import pl from './pl.svg'; import ph from '!file-loader!./ph.svg';
import pm from './pm.svg'; import pk from '!file-loader!./pk.svg';
import pn from './pn.svg'; import pl from '!file-loader!./pl.svg';
import pr from './pr.svg'; import pm from '!file-loader!./pm.svg';
import ps from './ps.svg'; import pn from '!file-loader!./pn.svg';
import pt from './pt.svg'; import pr from '!file-loader!./pr.svg';
import pw from './pw.svg'; import ps from '!file-loader!./ps.svg';
import py from './py.svg'; import pt from '!file-loader!./pt.svg';
import qa from './qa.svg'; import pw from '!file-loader!./pw.svg';
import re from './re.svg'; import py from '!file-loader!./py.svg';
import ro from './ro.svg'; import qa from '!file-loader!./qa.svg';
import rs from './rs.svg'; import re from '!file-loader!./re.svg';
import ru from './ru.svg'; import ro from '!file-loader!./ro.svg';
import rw from './rw.svg'; import rs from '!file-loader!./rs.svg';
import sa from './sa.svg'; import ru from '!file-loader!./ru.svg';
import sb from './sb.svg'; import rw from '!file-loader!./rw.svg';
import sc from './sc.svg'; import sa from '!file-loader!./sa.svg';
import sd from './sd.svg'; import sb from '!file-loader!./sb.svg';
import se from './se.svg'; import sc from '!file-loader!./sc.svg';
import sg from './sg.svg'; import sd from '!file-loader!./sd.svg';
import sh from './sh.svg'; import se from '!file-loader!./se.svg';
import si from './si.svg'; import sg from '!file-loader!./sg.svg';
import sj from './sj.svg'; import sh from '!file-loader!./sh.svg';
import sk from './sk.svg'; import si from '!file-loader!./si.svg';
import sl from './sl.svg'; import sj from '!file-loader!./sj.svg';
import sm from './sm.svg'; import sk from '!file-loader!./sk.svg';
import sn from './sn.svg'; import sl from '!file-loader!./sl.svg';
import so from './so.svg'; import sm from '!file-loader!./sm.svg';
import sr from './sr.svg'; import sn from '!file-loader!./sn.svg';
import ss from './ss.svg'; import so from '!file-loader!./so.svg';
import st from './st.svg'; import sr from '!file-loader!./sr.svg';
import sv from './sv.svg'; import ss from '!file-loader!./ss.svg';
import sx from './sx.svg'; import st from '!file-loader!./st.svg';
import sy from './sy.svg'; import sv from '!file-loader!./sv.svg';
import sz from './sz.svg'; import sx from '!file-loader!./sx.svg';
import tc from './tc.svg'; import sy from '!file-loader!./sy.svg';
import td from './td.svg'; import sz from '!file-loader!./sz.svg';
import tf from './tf.svg'; import tc from '!file-loader!./tc.svg';
import tg from './tg.svg'; import td from '!file-loader!./td.svg';
import th from './th.svg'; import tf from '!file-loader!./tf.svg';
import tj from './tj.svg'; import tg from '!file-loader!./tg.svg';
import tk from './tk.svg'; import th from '!file-loader!./th.svg';
import tl from './tl.svg'; import tj from '!file-loader!./tj.svg';
import tm from './tm.svg'; import tk from '!file-loader!./tk.svg';
import tn from './tn.svg'; import tl from '!file-loader!./tl.svg';
import to from './to.svg'; import tm from '!file-loader!./tm.svg';
import tr from './tr.svg'; import tn from '!file-loader!./tn.svg';
import tt from './tt.svg'; import to from '!file-loader!./to.svg';
import tv from './tv.svg'; import tr from '!file-loader!./tr.svg';
import tw from './tw.svg'; import tt from '!file-loader!./tt.svg';
import tz from './tz.svg'; import tv from '!file-loader!./tv.svg';
import ua from './ua.svg'; import tw from '!file-loader!./tw.svg';
import ug from './ug.svg'; import tz from '!file-loader!./tz.svg';
import um from './um.svg'; import ua from '!file-loader!./ua.svg';
import us from './us.svg'; import ug from '!file-loader!./ug.svg';
import uy from './uy.svg'; import um from '!file-loader!./um.svg';
import uz from './uz.svg'; import us from '!file-loader!./us.svg';
import va from './va.svg'; import uy from '!file-loader!./uy.svg';
import vc from './vc.svg'; import uz from '!file-loader!./uz.svg';
import ve from './ve.svg'; import va from '!file-loader!./va.svg';
import vg from './vg.svg'; import vc from '!file-loader!./vc.svg';
import vi from './vi.svg'; import ve from '!file-loader!./ve.svg';
import vn from './vn.svg'; import vg from '!file-loader!./vg.svg';
import vu from './vu.svg'; import vi from '!file-loader!./vi.svg';
import wf from './wf.svg'; import vn from '!file-loader!./vn.svg';
import ws from './ws.svg'; import vu from '!file-loader!./vu.svg';
import ye from './ye.svg'; import wf from '!file-loader!./wf.svg';
import yt from './yt.svg'; import ws from '!file-loader!./ws.svg';
import za from './za.svg'; import ye from '!file-loader!./ye.svg';
import zm from './zm.svg'; import yt from '!file-loader!./yt.svg';
import zw from './zw.svg'; import za from '!file-loader!./za.svg';
import zm from '!file-loader!./zm.svg';
import zw from '!file-loader!./zw.svg';
export const Countries = { export const Countries = {
ad, ad,

View file

@ -2,8 +2,6 @@ import { reset } from 'redux-form';
import { Actions } from './rooms.actions'; import { Actions } from './rooms.actions';
import { store } from 'store'; import { store } from 'store';
// const history = useHistory();
export const Dispatch = { export const Dispatch = {
clearStore: () => { clearStore: () => {
store.dispatch(Actions.clearStore()); store.dispatch(Actions.clearStore());