diff options
Diffstat (limited to 'frontend/src')
-rw-r--r-- | frontend/src/components/gameList.js | 28 | ||||
-rw-r--r-- | frontend/src/components/modals/username.js | 14 | ||||
-rw-r--r-- | frontend/src/components/playerList.js | 24 | ||||
-rw-r--r-- | frontend/src/containers/home.js | 33 | ||||
-rw-r--r-- | frontend/src/layouts/HomeLayout.js | 19 | ||||
-rw-r--r-- | frontend/src/layouts/LobbyLayout.js | 19 | ||||
-rw-r--r-- | frontend/src/layouts/index.js | 4 | ||||
-rw-r--r-- | frontend/src/reducers.js | 12 | ||||
-rw-r--r-- | frontend/src/redux/app.js | 8 | ||||
-rw-r--r-- | frontend/src/redux/errors.js | 33 | ||||
-rw-r--r-- | frontend/src/redux/games.js | 53 | ||||
-rw-r--r-- | frontend/src/redux/players.js | 44 | ||||
-rw-r--r-- | frontend/src/sagas.js | 24 | ||||
-rw-r--r-- | frontend/src/sagas/errors.js | 38 | ||||
-rw-r--r-- | frontend/src/sagas/home.js | 41 | ||||
-rw-r--r-- | frontend/src/sagas/lobby.js | 68 | ||||
-rw-r--r-- | frontend/src/schemas/games.js | 20 | ||||
-rw-r--r-- | frontend/src/store.js | 43 | ||||
-rw-r--r-- | frontend/src/utils/websocket.js | 35 |
19 files changed, 296 insertions, 264 deletions
diff --git a/frontend/src/components/gameList.js b/frontend/src/components/gameList.js index b4167927..e1d011e1 100644 --- a/frontend/src/components/gameList.js +++ b/frontend/src/components/gameList.js @@ -1,20 +1,22 @@ -import React from 'react' -import { Flex } from 'reflexbox' -import { Text, Space, Button } from 'rebass' -import Immutable from 'seamless-immutable' +import React from "react"; +import { Flex } from "reflexbox"; +import { Text, Space, Button } from "rebass"; +import Immutable from "seamless-immutable"; -const GameList = (props) => ( +const GameList = props => ( <div> {Immutable.asMutable(props.games).map((game, index) => { - const joinGame = () => props.joinGame(game.id) + const joinGame = () => props.joinGame(game.id); - return (<Flex key={index}> - <Text>{game.name}</Text> - <Space auto /> - <Button onClick={joinGame}>Join</Button> - </Flex>) + return ( + <Flex key={index}> + <Text>{game.name}</Text> + <Space auto /> + <Button onClick={joinGame}>Join</Button> + </Flex> + ); })} </div> -) +); -export default GameList +export default GameList; diff --git a/frontend/src/components/modals/username.js b/frontend/src/components/modals/username.js index 61b52114..826bce85 100644 --- a/frontend/src/components/modals/username.js +++ b/frontend/src/components/modals/username.js @@ -1,4 +1,4 @@ -import React from 'react' +import React from "react"; import { Overlay, Panel, @@ -8,15 +8,15 @@ import { Input, Close, Space -} from 'rebass' +} from "rebass"; const Modal = ({ modalOpen, toggleModal }) => ( - <Overlay open={modalOpen} onDismiss={toggleModal('usernameModal')}> + <Overlay open={modalOpen} onDismiss={toggleModal("usernameModal")}> <Panel theme="info"> <PanelHeader> What's your username ? <Space auto /> - <Close onClick={toggleModal('usernameModal')} /> + <Close onClick={toggleModal("usernameModal")} /> </PanelHeader> <Input label="Username" @@ -29,12 +29,12 @@ const Modal = ({ modalOpen, toggleModal }) => ( <Space auto /> <Button theme="success" - onClick={toggleModal('usernameModal')} + onClick={toggleModal("usernameModal")} children="Ok" /> </PanelFooter> </Panel> </Overlay> -) +); -export default Modal +export default Modal; diff --git a/frontend/src/components/playerList.js b/frontend/src/components/playerList.js index 70e8b1f6..b7f6e7c3 100644 --- a/frontend/src/components/playerList.js +++ b/frontend/src/components/playerList.js @@ -1,17 +1,19 @@ -import React from 'react' -import { Flex } from 'reflexbox' -import { Text } from 'rebass' -import Immutable from 'seamless-immutable' +import React from "react"; +import { Flex } from "reflexbox"; +import { Text } from "rebass"; +import Immutable from "seamless-immutable"; -const PlayerList = (props) => ( +const PlayerList = props => ( <div> {Immutable.asMutable(props.players).map(player => { - return (<Flex key={player.index}> - <Text>{player.displayName}</Text> - <Text>({player.username})</Text> - </Flex>) + return ( + <Flex key={player.index}> + <Text>{player.displayName}</Text> + <Text>({player.username})</Text> + </Flex> + ); })} </div> -) +); -export default PlayerList +export default PlayerList; diff --git a/frontend/src/containers/home.js b/frontend/src/containers/home.js index 78ff5e6e..40c2efb3 100644 --- a/frontend/src/containers/home.js +++ b/frontend/src/containers/home.js @@ -1,16 +1,15 @@ -import React, { Component } from 'react' -import { connect } from 'react-redux' -import { Button, Container, Input } from 'rebass' -import { actions } from '../redux/players' +import React, { Component } from "react"; +import { connect } from "react-redux"; +import { Button, Container, Input } from "rebass"; +import { actions } from "../redux/players"; class HomePage extends Component { - - play = (e) => { - e.preventDefault() + play = e => { + e.preventDefault(); if (this._username !== undefined) { - this.props.chooseUsername(this._username) + this.props.chooseUsername(this._username); } - } + }; render() { return ( @@ -20,24 +19,20 @@ class HomePage extends Component { label="Username" placeholder="Username" hideLabel - onChange={(e) => this._username = e.target.value} + onChange={e => (this._username = e.target.value)} /> - <Button - backgroundColor="primary" - color="white" - big - onClick={this.play}> + <Button backgroundColor="primary" color="white" big onClick={this.play}> PLAY NOW! </Button> </Container> - ) + ); } } -const mapStateToProps = (state) => ({}) +const mapStateToProps = state => ({}); const mapDispatchToProps = { chooseUsername: actions.chooseUsername -} +}; -export default connect(mapStateToProps, mapDispatchToProps)(HomePage) +export default connect(mapStateToProps, mapDispatchToProps)(HomePage); diff --git a/frontend/src/layouts/HomeLayout.js b/frontend/src/layouts/HomeLayout.js index 76236383..77231c77 100644 --- a/frontend/src/layouts/HomeLayout.js +++ b/frontend/src/layouts/HomeLayout.js @@ -1,19 +1,20 @@ -import React from 'react' -import { Banner } from 'rebass' -import logo from './logo-7-wonders.png' -import background from './background-zeus-temple.jpg' -import ReduxToastr from 'react-redux-toastr' +import React from "react"; +import { Banner } from "rebass"; +import logo from "./logo-7-wonders.png"; +import background from "./background-zeus-temple.jpg"; +import ReduxToastr from "react-redux-toastr"; -export default (props) => ( +export default props => ( <div> <Banner align="center" backgroundImage={background}> - <img src={logo} alt="Seven Wonders"/> + <img src={logo} alt="Seven Wonders" /> {props.children} </Banner> <ReduxToastr timeOut={4000} preventDuplicates position="bottom-left" - progressBar/> + progressBar + /> </div> -) +); diff --git a/frontend/src/layouts/LobbyLayout.js b/frontend/src/layouts/LobbyLayout.js index dba3d589..84d3998f 100644 --- a/frontend/src/layouts/LobbyLayout.js +++ b/frontend/src/layouts/LobbyLayout.js @@ -1,22 +1,23 @@ -import React from 'react' -import { Banner } from 'rebass' -import logo from './logo-7-wonders.png' -import ReduxToastr from 'react-redux-toastr' +import React from "react"; +import { Banner } from "rebass"; +import logo from "./logo-7-wonders.png"; +import ReduxToastr from "react-redux-toastr"; -export default (props) => ( +export default props => ( <div> <Banner align="center" - style={{minHeight: '30vh', marginBottom: 0}} + style={{ minHeight: "30vh", marginBottom: 0 }} backgroundImage="https://images.unsplash.com/photo-1431207446535-a9296cf995b1?dpr=1&auto=format&fit=crop&w=1199&h=799&q=80&cs=tinysrgb&crop=" > - <img src={logo} alt="Seven Wonders Logo"/> + <img src={logo} alt="Seven Wonders Logo" /> </Banner> {props.children} <ReduxToastr timeOut={4000} preventDuplicates position="bottom-left" - progressBar/> + progressBar + /> </div> -) +); diff --git a/frontend/src/layouts/index.js b/frontend/src/layouts/index.js index 0413b647..f09b2a20 100644 --- a/frontend/src/layouts/index.js +++ b/frontend/src/layouts/index.js @@ -1,2 +1,2 @@ -export { default as HomeLayout } from './HomeLayout' -export { default as LobbyLayout } from './LobbyLayout' +export { default as HomeLayout } from "./HomeLayout"; +export { default as LobbyLayout } from "./LobbyLayout"; diff --git a/frontend/src/reducers.js b/frontend/src/reducers.js index f5063ac1..a5d4a9fd 100644 --- a/frontend/src/reducers.js +++ b/frontend/src/reducers.js @@ -1,9 +1,9 @@ -import { combineReducers, routerReducer } from 'redux-seamless-immutable' -import { reducer as toastrReducer } from 'react-redux-toastr' +import { combineReducers, routerReducer } from "redux-seamless-immutable"; +import { reducer as toastrReducer } from "react-redux-toastr"; -import errorsReducer from './redux/errors' -import gamesReducer from './redux/games' -import playersReducer from './redux/players' +import errorsReducer from "./redux/errors"; +import gamesReducer from "./redux/games"; +import playersReducer from "./redux/players"; export default function createReducer() { return combineReducers({ @@ -12,5 +12,5 @@ export default function createReducer() { players: playersReducer, routing: routerReducer, toastr: toastrReducer - }) + }); } diff --git a/frontend/src/redux/app.js b/frontend/src/redux/app.js index 251b12a2..d24fbbfd 100644 --- a/frontend/src/redux/app.js +++ b/frontend/src/redux/app.js @@ -1,5 +1,5 @@ export const makeSelectLocationState = () => { - return (state) => { - return state.routing - } -} + return state => { + return state.routing; + }; +}; diff --git a/frontend/src/redux/errors.js b/frontend/src/redux/errors.js index 7d113db1..eb807fdc 100644 --- a/frontend/src/redux/errors.js +++ b/frontend/src/redux/errors.js @@ -1,37 +1,40 @@ -import Immutable from 'seamless-immutable' +import Immutable from "seamless-immutable"; export const types = { - ERROR_RECEIVED_ON_WS: 'ERROR/RECEIVED_ON_WS', -} + ERROR_RECEIVED_ON_WS: "ERROR/RECEIVED_ON_WS" +}; export const actions = { - errorReceived: (error) => ({ + errorReceived: error => ({ type: types.ERROR_RECEIVED_ON_WS, error - }), -} + }) +}; const initialState = Immutable.from({ nextId: 0, history: [] -}) +}); export default (state = initialState, action) => { switch (action.type) { case types.ERROR_RECEIVED_ON_WS: - let error = Object.assign({id: state.nextId, timestamp: new Date()}, action.error); - let newState = state.set('nextId', state.nextId + 1) - newState = addErrorToHistory(newState, error) - return newState + let error = Object.assign( + { id: state.nextId, timestamp: new Date() }, + action.error + ); + let newState = state.set("nextId", state.nextId + 1); + newState = addErrorToHistory(newState, error); + return newState; default: - return state + return state; } -} +}; function addErrorToHistory(state, error) { - return addToArray(state, 'history', error); + return addToArray(state, "history", error); } function addToArray(state, arrayKey, element) { - return state.set(arrayKey, state[arrayKey].concat([ element ])); + return state.set(arrayKey, state[arrayKey].concat([element])); } diff --git a/frontend/src/redux/games.js b/frontend/src/redux/games.js index 2986de07..a7115dcc 100644 --- a/frontend/src/redux/games.js +++ b/frontend/src/redux/games.js @@ -1,43 +1,46 @@ -import Immutable from 'seamless-immutable' +import Immutable from "seamless-immutable"; export const types = { - UPDATE_GAMES: 'GAME/UPDATE_GAMES', - REQUEST_CREATE_GAME: 'GAME/REQUEST_CREATE_GAME', - REQUEST_JOIN_GAME: 'GAME/REQUEST_JOIN_GAME', - REQUEST_START_GAME: 'GAME/REQUEST_JOIN_GAME', - ENTER_LOBBY: 'GAME/ENTER_LOBBY', - ENTER_GAME: 'GAME/ENTER_GAME', -} + UPDATE_GAMES: "GAME/UPDATE_GAMES", + REQUEST_CREATE_GAME: "GAME/REQUEST_CREATE_GAME", + REQUEST_JOIN_GAME: "GAME/REQUEST_JOIN_GAME", + REQUEST_START_GAME: "GAME/REQUEST_JOIN_GAME", + ENTER_LOBBY: "GAME/ENTER_LOBBY", + ENTER_GAME: "GAME/ENTER_GAME" +}; export const actions = { - updateGames: (games) => ({ type: types.UPDATE_GAMES, games: Immutable(games) }), - requestJoinGame: (gameId) => ({ type: types.REQUEST_JOIN_GAME, gameId }), - requestCreateGame: (gameName) => ({ type: types.REQUEST_CREATE_GAME, gameName }), + updateGames: games => ({ type: types.UPDATE_GAMES, games: Immutable(games) }), + requestJoinGame: gameId => ({ type: types.REQUEST_JOIN_GAME, gameId }), + requestCreateGame: gameName => ({ + type: types.REQUEST_CREATE_GAME, + gameName + }), requestStartGame: () => ({ type: types.REQUEST_START_GAME }), - enterLobby: (lobby) => ({ type: types.ENTER_LOBBY, lobby: Immutable(lobby) }), - enterGame: () => ({ type: types.ENTER_GAME }), -} + enterLobby: lobby => ({ type: types.ENTER_LOBBY, lobby: Immutable(lobby) }), + enterGame: () => ({ type: types.ENTER_GAME }) +}; const initialState = Immutable.from({ all: {}, - current: '' -}) + current: "" +}); export default (state = initialState, action) => { switch (action.type) { case types.UPDATE_GAMES: - return Immutable.merge(state, {all: action.games}, {deep: true}) + return Immutable.merge(state, { all: action.games }, { deep: true }); case types.ENTER_LOBBY: - return state.set('current', action.lobby.id) + return state.set("current", action.lobby.id); default: - return state + return state; } -} +}; -export const getAllGamesById = state => state.games.all +export const getAllGamesById = state => state.games.all; export const getAllGames = state => { - let gamesById = getAllGamesById(state) + let gamesById = getAllGamesById(state); return Object.keys(gamesById).map(k => gamesById[k]); -} -export const getGame = (state, id) => getAllGamesById(state)[id] -export const getCurrentGame = state => getGame(state, state.games.current) +}; +export const getGame = (state, id) => getAllGamesById(state)[id]; +export const getCurrentGame = state => getGame(state, state.games.current); diff --git a/frontend/src/redux/players.js b/frontend/src/redux/players.js index 2b530ca1..4016076f 100644 --- a/frontend/src/redux/players.js +++ b/frontend/src/redux/players.js @@ -1,44 +1,46 @@ -import Immutable from 'seamless-immutable' +import Immutable from "seamless-immutable"; export const types = { - REQUEST_CHOOSE_USERNAME: 'USER/REQUEST_CHOOSE_USERNAME', - SET_CURRENT_PLAYER: 'USER/SET_CURRENT_PLAYER', - UPDATE_PLAYERS: 'USER/UPDATE_PLAYERS' -} + REQUEST_CHOOSE_USERNAME: "USER/REQUEST_CHOOSE_USERNAME", + SET_CURRENT_PLAYER: "USER/SET_CURRENT_PLAYER", + UPDATE_PLAYERS: "USER/UPDATE_PLAYERS" +}; export const actions = { - chooseUsername: (username) => ({ + chooseUsername: username => ({ type: types.REQUEST_CHOOSE_USERNAME, username }), - setCurrentPlayer: (player) => ({ + setCurrentPlayer: player => ({ type: types.SET_CURRENT_PLAYER, player }), - updatePlayers: (players) => ({ + updatePlayers: players => ({ type: types.UPDATE_PLAYERS, players - }), -} + }) +}; const initialState = Immutable.from({ all: {}, - current: '' -}) + current: "" +}); export default (state = initialState, action) => { switch (action.type) { case types.SET_CURRENT_PLAYER: - const player = action.player - const withNewPlayer = state.setIn(['all', player.username], player) - return Immutable.set(withNewPlayer, 'current', player.username) + const player = action.player; + const withNewPlayer = state.setIn(["all", player.username], player); + return Immutable.set(withNewPlayer, "current", player.username); case types.UPDATE_PLAYERS: - return Immutable.merge(state, {all: action.players}, {deep: true}) + return Immutable.merge(state, { all: action.players }, { deep: true }); default: - return state + return state; } -} +}; -export const getCurrentPlayer = state => state.players.all && state.players.all[state.players.current] -export const getPlayer = (state, username) => state.players.all[username] -export const getPlayers = (state, usernames) => usernames.map(u => getPlayer(state, u)) +export const getCurrentPlayer = state => + state.players.all && state.players.all[state.players.current]; +export const getPlayer = (state, username) => state.players.all[username]; +export const getPlayers = (state, usernames) => + usernames.map(u => getPlayer(state, u)); diff --git a/frontend/src/sagas.js b/frontend/src/sagas.js index c5166cd5..ff66453e 100644 --- a/frontend/src/sagas.js +++ b/frontend/src/sagas.js @@ -1,18 +1,18 @@ -import { router } from 'redux-saga-router' -import { call, fork } from 'redux-saga/effects' +import { router } from "redux-saga-router"; +import { call, fork } from "redux-saga/effects"; -import { makeSagaRoutes } from './routes' -import { createWsConnection } from './utils/websocket' -import errorHandlingSaga from './sagas/errors' +import { makeSagaRoutes } from "./routes"; +import { createWsConnection } from "./utils/websocket"; +import errorHandlingSaga from "./sagas/errors"; -export default function *rootSaga(history) { - let wsConnection +export default function* rootSaga(history) { + let wsConnection; try { - wsConnection = yield call(createWsConnection) + wsConnection = yield call(createWsConnection); } catch (error) { - console.error('Could not connect to socket') - return + console.error("Could not connect to socket"); + return; } - yield fork(errorHandlingSaga, wsConnection) - yield* router(history, makeSagaRoutes(wsConnection)) + yield fork(errorHandlingSaga, wsConnection); + yield* router(history, makeSagaRoutes(wsConnection)); } diff --git a/frontend/src/sagas/errors.js b/frontend/src/sagas/errors.js index ba1ae40d..42994610 100644 --- a/frontend/src/sagas/errors.js +++ b/frontend/src/sagas/errors.js @@ -1,36 +1,40 @@ -import { apply, call, cancelled, put, take } from 'redux-saga/effects' +import { apply, call, cancelled, put, take } from "redux-saga/effects"; -import { createSubscriptionChannel } from '../utils/websocket' -import { actions } from '../redux/errors' +import { createSubscriptionChannel } from "../utils/websocket"; +import { actions } from "../redux/errors"; -import {toastr} from 'react-redux-toastr' +import { toastr } from "react-redux-toastr"; -export default function *errorHandlingSaga({ socket }) { - const errorChannel = yield call(createSubscriptionChannel, socket, '/user/queue/errors') +export default function* errorHandlingSaga({ socket }) { + const errorChannel = yield call( + createSubscriptionChannel, + socket, + "/user/queue/errors" + ); try { while (true) { - const error = yield take(errorChannel) - yield* handleOneError(error) + const error = yield take(errorChannel); + yield* handleOneError(error); } } finally { if (yield cancelled()) { - console.log('Error management saga cancelled') - yield apply(errorChannel, errorChannel.close) + console.log("Error management saga cancelled"); + yield apply(errorChannel, errorChannel.close); } } } -function *handleOneError(err) { - console.error("Error received on web socket channel", err) - const msg = buildMsg(err) - yield apply(toastr, toastr.error, [msg, {icon: 'error'}]) - yield put(actions.errorReceived(err)) +function* handleOneError(err) { + console.error("Error received on web socket channel", err); + const msg = buildMsg(err); + yield apply(toastr, toastr.error, [msg, { icon: "error" }]); + yield put(actions.errorReceived(err)); } function buildMsg(err) { if (err.details.length > 0) { - return err.details.map(d => d.message).join('\n') + return err.details.map(d => d.message).join("\n"); } else { - return err.message + return err.message; } } diff --git a/frontend/src/sagas/home.js b/frontend/src/sagas/home.js index 151fcb57..15f95162 100644 --- a/frontend/src/sagas/home.js +++ b/frontend/src/sagas/home.js @@ -1,32 +1,39 @@ -import { apply, call, put, take } from 'redux-saga/effects' -import { createSubscriptionChannel } from '../utils/websocket' -import { push } from 'react-router-redux' +import { apply, call, put, take } from "redux-saga/effects"; +import { createSubscriptionChannel } from "../utils/websocket"; +import { push } from "react-router-redux"; -import { actions, types } from '../redux/players' +import { actions, types } from "../redux/players"; -function *sendUsername({ socket }) { +function* sendUsername({ socket }) { while (true) { - const {username} = yield take(types.REQUEST_CHOOSE_USERNAME) - yield apply(socket, socket.send, ['/app/chooseName', JSON.stringify({playerName: username})]) + const { username } = yield take(types.REQUEST_CHOOSE_USERNAME); + yield apply(socket, socket.send, [ + "/app/chooseName", + JSON.stringify({ playerName: username }) + ]); } } -function *validateUsername({ socket }) { - const usernameChannel = yield call(createSubscriptionChannel, socket, '/user/queue/nameChoice') +function* validateUsername({ socket }) { + const usernameChannel = yield call( + createSubscriptionChannel, + socket, + "/user/queue/nameChoice" + ); while (true) { - const user = yield take(usernameChannel) - yield put(actions.setCurrentPlayer(user)) - yield apply(usernameChannel, usernameChannel.close) - yield put(push('/games')) + const user = yield take(usernameChannel); + yield put(actions.setCurrentPlayer(user)); + yield apply(usernameChannel, usernameChannel.close); + yield put(push("/games")); } } -function *usernameChoiceSaga(wsConnection) { +function* usernameChoiceSaga(wsConnection) { // TODO: Run sendUsername in loop when we have the ability to cancel saga on route change yield [ call(sendUsername, wsConnection), - call(validateUsername, wsConnection), - ] + call(validateUsername, wsConnection) + ]; } -export default usernameChoiceSaga +export default usernameChoiceSaga; diff --git a/frontend/src/sagas/lobby.js b/frontend/src/sagas/lobby.js index f002c897..f092fdb7 100644 --- a/frontend/src/sagas/lobby.js +++ b/frontend/src/sagas/lobby.js @@ -1,58 +1,66 @@ -import { call, put, take, apply } from 'redux-saga/effects' -import { createSubscriptionChannel } from '../utils/websocket' -import { push } from 'react-router-redux' +import { call, put, take, apply } from "redux-saga/effects"; +import { createSubscriptionChannel } from "../utils/websocket"; +import { push } from "react-router-redux"; -import { normalize } from 'normalizr' -import { game as gameSchema } from '../schemas/games' +import { normalize } from "normalizr"; +import { game as gameSchema } from "../schemas/games"; -import { actions as gameActions, types } from '../redux/games' -import { actions as playerActions } from '../redux/players' +import { actions as gameActions, types } from "../redux/games"; +import { actions as playerActions } from "../redux/players"; function getCurrentGameId() { - const path = window.location.pathname - return path.split('lobby/')[1] + const path = window.location.pathname; + return path.split("lobby/")[1]; } -function *watchLobbyUpdates({ socket }) { - const currentGameId = getCurrentGameId() - const lobbyUpdatesChannel = yield call(createSubscriptionChannel, socket, `/topic/lobby/${currentGameId}/updated`) +function* watchLobbyUpdates({ socket }) { + const currentGameId = getCurrentGameId(); + const lobbyUpdatesChannel = yield call( + createSubscriptionChannel, + socket, + `/topic/lobby/${currentGameId}/updated` + ); try { while (true) { - const lobby = yield take(lobbyUpdatesChannel) - const normalized = normalize(lobby, gameSchema) - yield put(gameActions.updateGames(normalized.entities.games)) - yield put(playerActions.updatePlayers(normalized.entities.players)) + const lobby = yield take(lobbyUpdatesChannel); + const normalized = normalize(lobby, gameSchema); + yield put(gameActions.updateGames(normalized.entities.games)); + yield put(playerActions.updatePlayers(normalized.entities.players)); } } finally { - yield apply(lobbyUpdatesChannel, lobbyUpdatesChannel.close) + yield apply(lobbyUpdatesChannel, lobbyUpdatesChannel.close); } } -function *watchGameStart({ socket }) { - const currentGameId = getCurrentGameId() - const gameStartedChannel = yield call(createSubscriptionChannel, socket, `/topic/lobby/${currentGameId}/started`) +function* watchGameStart({ socket }) { + const currentGameId = getCurrentGameId(); + const gameStartedChannel = yield call( + createSubscriptionChannel, + socket, + `/topic/lobby/${currentGameId}/started` + ); try { - yield take(gameStartedChannel) - yield put(gameActions.enterGame()) - yield put(push('/game')) + yield take(gameStartedChannel); + yield put(gameActions.enterGame()); + yield put(push("/game")); } finally { - yield apply(gameStartedChannel, gameStartedChannel.close) + yield apply(gameStartedChannel, gameStartedChannel.close); } } -function *startGame({ socket }) { +function* startGame({ socket }) { while (true) { - yield take(types.REQUEST_START_GAME) - yield apply(socket, socket.send, ['/app/lobby/startGame', {}]) + yield take(types.REQUEST_START_GAME); + yield apply(socket, socket.send, ["/app/lobby/startGame", {}]); } } -function *lobbySaga(socketConnection) { +function* lobbySaga(socketConnection) { yield [ call(watchLobbyUpdates, socketConnection), call(watchGameStart, socketConnection), call(startGame, socketConnection) - ] + ]; } -export default lobbySaga +export default lobbySaga; diff --git a/frontend/src/schemas/games.js b/frontend/src/schemas/games.js index f7a9ffb8..9c9681da 100644 --- a/frontend/src/schemas/games.js +++ b/frontend/src/schemas/games.js @@ -1,11 +1,15 @@ -import { schema } from 'normalizr' +import { schema } from "normalizr"; -const player = new schema.Entity('players', {}, { - idAttribute: 'username' -}) +const player = new schema.Entity( + "players", + {}, + { + idAttribute: "username" + } +); -export const game = new schema.Entity('games', { - players: [ player ] -}) +export const game = new schema.Entity("games", { + players: [player] +}); -export const gameList = [ game ] +export const gameList = [game]; diff --git a/frontend/src/store.js b/frontend/src/store.js index bd05e2c5..ef9038eb 100644 --- a/frontend/src/store.js +++ b/frontend/src/store.js @@ -1,43 +1,38 @@ -import { createStore, applyMiddleware, compose } from 'redux' -import { browserHistory } from 'react-router' -import { syncHistoryWithStore, routerMiddleware } from 'react-router-redux' -import Immutable from 'seamless-immutable' +import { createStore, applyMiddleware, compose } from "redux"; +import { browserHistory } from "react-router"; +import { syncHistoryWithStore, routerMiddleware } from "react-router-redux"; +import Immutable from "seamless-immutable"; -import createReducer from './reducers' -import createSagaMiddleware from 'redux-saga' -import rootSaga from './sagas' -import { makeSelectLocationState } from './redux/app' +import createReducer from "./reducers"; +import createSagaMiddleware from "redux-saga"; +import rootSaga from "./sagas"; +import { makeSelectLocationState } from "./redux/app"; export default function configureStore(initialState = {}) { - const sagaMiddleware = createSagaMiddleware() + const sagaMiddleware = createSagaMiddleware(); - const middlewares = [ - sagaMiddleware, - routerMiddleware(browserHistory) - ] + const middlewares = [sagaMiddleware, routerMiddleware(browserHistory)]; - const enhancers = [ - applyMiddleware(...middlewares) - ] + const enhancers = [applyMiddleware(...middlewares)]; - const composeEnhancers = - process.env.NODE_ENV !== 'production' && - typeof window === 'object' && - window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ ? - window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ : compose; + const composeEnhancers = process.env.NODE_ENV !== "production" && + typeof window === "object" && + window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ + ? window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ + : compose; const store = createStore( createReducer(), Immutable.from(initialState), composeEnhancers(...enhancers) - ) + ); - sagaMiddleware.run(rootSaga, browserHistory) + sagaMiddleware.run(rootSaga, browserHistory); return { store, history: syncHistoryWithStore(browserHistory, store, { selectLocationState: makeSelectLocationState() }) - } + }; } diff --git a/frontend/src/utils/websocket.js b/frontend/src/utils/websocket.js index 1dde5397..6db91899 100644 --- a/frontend/src/utils/websocket.js +++ b/frontend/src/utils/websocket.js @@ -1,23 +1,28 @@ -import SockJS from 'sockjs-client' -import Stomp from 'webstomp-client' -import { eventChannel } from 'redux-saga' +import SockJS from "sockjs-client"; +import Stomp from "webstomp-client"; +import { eventChannel } from "redux-saga"; -const wsURL = '/seven-wonders-websocket' +const wsURL = "/seven-wonders-websocket"; -export const createWsConnection = (headers = {}) => new Promise((resolve, reject) => { +export const createWsConnection = (headers = {}) => + new Promise((resolve, reject) => { let socket = Stomp.over(new SockJS(wsURL), { debug: process.env.NODE_ENV !== "production" - }) - socket.connect(headers, (frame) => { - return resolve({ frame, socket }) - }, reject) -}) + }); + socket.connect( + headers, + frame => { + return resolve({ frame, socket }); + }, + reject + ); + }); export const createSubscriptionChannel = (socket, path) => { return eventChannel(emitter => { const receiveUsernameHandler = socket.subscribe(path, event => { - emitter(JSON.parse(event.body)) - }) - return () => receiveUsernameHandler.unsubscribe() - }) -} + emitter(JSON.parse(event.body)); + }); + return () => receiveUsernameHandler.unsubscribe(); + }); +}; |