diff options
author | Joffrey Bion <joffrey.bion@gmail.com> | 2017-05-28 21:32:36 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-05-28 21:32:36 +0200 |
commit | ba9cd259ed1ca2370565265eab9fe2628ad6502c (patch) | |
tree | 0c24821770274a414f80b3092d5be54902c042d9 /frontend/src | |
parent | Fix proxy not working since CRA upgrade (diff) | |
parent | Move to immutable with Records (diff) | |
download | seven-wonders-ba9cd259ed1ca2370565265eab9fe2628ad6502c.tar.gz seven-wonders-ba9cd259ed1ca2370565265eab9fe2628ad6502c.tar.bz2 seven-wonders-ba9cd259ed1ca2370565265eab9fe2628ad6502c.zip |
Merge pull request #14 from luxons/immutable
Move to immutable with Records
Diffstat (limited to 'frontend/src')
-rw-r--r-- | frontend/src/components/gameList.js | 9 | ||||
-rw-r--r-- | frontend/src/components/playerList.js | 5 | ||||
-rw-r--r-- | frontend/src/containers/gameBrowser.js | 4 | ||||
-rw-r--r-- | frontend/src/containers/lobby.js | 7 | ||||
-rw-r--r-- | frontend/src/models/errors.js | 34 | ||||
-rw-r--r-- | frontend/src/models/games.js | 41 | ||||
-rw-r--r-- | frontend/src/models/players.js | 26 | ||||
-rw-r--r-- | frontend/src/reducers.js | 3 | ||||
-rw-r--r-- | frontend/src/redux/app.js | 2 | ||||
-rw-r--r-- | frontend/src/redux/errors.js | 22 | ||||
-rw-r--r-- | frontend/src/redux/games.js | 29 | ||||
-rw-r--r-- | frontend/src/redux/players.js | 21 | ||||
-rw-r--r-- | frontend/src/store.js | 4 |
13 files changed, 138 insertions, 69 deletions
diff --git a/frontend/src/components/gameList.js b/frontend/src/components/gameList.js index f3a0d381..17dad16f 100644 --- a/frontend/src/components/gameList.js +++ b/frontend/src/components/gameList.js @@ -1,18 +1,15 @@ import React from 'react'; import { Flex } from 'reflexbox'; import { Text, Space, Button } from 'rebass'; -import Immutable from 'seamless-immutable'; -const GameList = props => ( +const GameList = ({ games, joinGame }) => ( <div> - {Immutable.asMutable(props.games).map((game, index) => { - const joinGame = () => props.joinGame(game.id); - + {games.map((game, index) => { return ( <Flex key={index}> <Text>{game.name}</Text> <Space auto /> - <Button onClick={joinGame}>Join</Button> + <Button onClick={() => joinGame(game.id)}>Join</Button> </Flex> ); })} diff --git a/frontend/src/components/playerList.js b/frontend/src/components/playerList.js index 1a68b067..bc2c768e 100644 --- a/frontend/src/components/playerList.js +++ b/frontend/src/components/playerList.js @@ -1,11 +1,10 @@ import React from 'react'; import { Flex } from 'reflexbox'; import { Text } from 'rebass'; -import Immutable from 'seamless-immutable'; -const PlayerList = props => ( +const PlayerList = ({ players }) => ( <div> - {Immutable.asMutable(props.players).map(player => { + {players.map(player => { return ( <Flex key={player.index}> <Text>{player.displayName}</Text> diff --git a/frontend/src/containers/gameBrowser.js b/frontend/src/containers/gameBrowser.js index 643dbebc..ac3f1504 100644 --- a/frontend/src/containers/gameBrowser.js +++ b/frontend/src/containers/gameBrowser.js @@ -41,8 +41,8 @@ class GameBrowser extends Component { } const mapStateToProps = state => ({ - currentPlayer: getCurrentPlayer(state) || { displayName: '[ERROR]' }, - games: getAllGames(state), + currentPlayer: getCurrentPlayer(state.get('players')), + games: getAllGames(state.get('games')), }); const mapDispatchToProps = { diff --git a/frontend/src/containers/lobby.js b/frontend/src/containers/lobby.js index 90714aec..fc762056 100644 --- a/frontend/src/containers/lobby.js +++ b/frontend/src/containers/lobby.js @@ -1,6 +1,6 @@ import React, { Component } from 'react'; +import { List } from 'immutable'; import { connect } from 'react-redux'; -import Immutable from 'seamless-immutable'; import { Button } from 'rebass'; import PlayerList from '../components/playerList'; @@ -28,10 +28,11 @@ class Lobby extends Component { } const mapStateToProps = state => { - const game = getCurrentGame(state); + const game = getCurrentGame(state.get('games')); + console.info(game); return { currentGame: game, - players: game ? getPlayers(state, game.players) : Immutable([]), + players: game ? getPlayers(state.get('players'), game.players) : new List(), }; }; diff --git a/frontend/src/models/errors.js b/frontend/src/models/errors.js new file mode 100644 index 00000000..c00954cd --- /dev/null +++ b/frontend/src/models/errors.js @@ -0,0 +1,34 @@ +import { Record, List } from 'immutable'; + +const ErrorsRecord = Record({ + nextId: 0, + history: new List(), +}); + +export default class ErrorsState extends ErrorsRecord { + addError(error) { + const errorObject = new Error({ id: this.nextId, error: new ErrorBag(error) }); + return this.set('history', this.history.push(errorObject)).set('nextId', this.nextId + 1); + } +} + +const ErrorRecord = Record({ + id: -1, + timestamp: new Date(), + error: new ErrorsRecord(), +}); + +export class Error extends ErrorRecord {} + +const ErrorBagRecord = Record({ + type: '', + position: 'bottom-left', + options: { + icon: 'error', + removeOnHover: true, + showCloseButton: true, + }, + title: 'Unknown Error', +}); + +export class ErrorBag extends ErrorBagRecord {} diff --git a/frontend/src/models/games.js b/frontend/src/models/games.js new file mode 100644 index 00000000..95bf8015 --- /dev/null +++ b/frontend/src/models/games.js @@ -0,0 +1,41 @@ +import { Record, Map, List } from 'immutable'; + +const SettingsRecord = Record({ + initialGold: 3, + lostPointsPerDefeat: 1, + timeLimitInSeconds: 45, + randomSeedForTests: -1, + discardedCardGold: 3, + defaultTradingCost: 2, + wonPointsPerVictoryPerAge: { + '1': 1, + '2': 3, + '3': 5, + }, + wonderSidePickMethod: 'EACH_RANDOM', + pointsPer3Gold: 1, +}); +export class Settings extends SettingsRecord {} + +const GameRecord = Record({ + id: -1, + name: null, + players: new List(), + settings: new Settings(), + state: 'LOBBY', +}); +export class Game extends GameRecord {} + +const GamesRecord = Record({ + all: new Map(), + current: '', +}); +export default class GamesState extends GamesRecord { + addGame(g) { + const game = new Game(g); + return this.mergeDeepIn(['all', game.id], game); + } + addGames(games) { + return this.mergeIn(['all'], games.map(game => new Game(game))); + } +} diff --git a/frontend/src/models/players.js b/frontend/src/models/players.js new file mode 100644 index 00000000..3df32c57 --- /dev/null +++ b/frontend/src/models/players.js @@ -0,0 +1,26 @@ +import { Record, Map } from 'immutable'; + +const PlayerRecord = Record({ + username: null, + displayName: null, + index: 0, + ready: false, +}); +export class Player extends PlayerRecord {} + +const PlayersRecord = Record({ + all: new Map(), + current: '', +}); +export default class PlayerState extends PlayersRecord { + addPlayer(p) { + const player = new Player(p); + const playerMap = new Map({ [player.username]: player }); + return this.addPlayers(playerMap).set('current', player.username); + } + + addPlayers(p) { + const players = new Map(p); + return this.mergeIn(['all'], players.map(player => new Player(player))); + } +} diff --git a/frontend/src/reducers.js b/frontend/src/reducers.js index a7bba09a..4b98a9ca 100644 --- a/frontend/src/reducers.js +++ b/frontend/src/reducers.js @@ -1,4 +1,5 @@ -import { combineReducers, routerReducer } from 'redux-seamless-immutable'; +import { combineReducers } from 'redux-immutable'; +import { routerReducer } from 'react-router-redux'; import { reducer as toastrReducer } from 'react-redux-toastr'; import errorsReducer from './redux/errors'; diff --git a/frontend/src/redux/app.js b/frontend/src/redux/app.js index d24fbbfd..614e7d93 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.get('routing'); }; }; diff --git a/frontend/src/redux/errors.js b/frontend/src/redux/errors.js index ec1e30b6..ad1e2795 100644 --- a/frontend/src/redux/errors.js +++ b/frontend/src/redux/errors.js @@ -1,4 +1,4 @@ -import Immutable from 'seamless-immutable'; +import ErrorsState from '../models/errors'; export const types = { ERROR_RECEIVED_ON_WS: 'ERROR/RECEIVED_ON_WS', @@ -11,27 +11,11 @@ export const actions = { }), }; -const initialState = Immutable.from({ - nextId: 0, - history: [], -}); - -export default (state = initialState, action) => { +export default (state = new ErrorsState(), 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; + return state.addError(action.error); default: return state; } }; - -function addErrorToHistory(state, error) { - return addToArray(state, 'history', error); -} - -function addToArray(state, arrayKey, element) { - return state.set(arrayKey, state[arrayKey].concat([element])); -} diff --git a/frontend/src/redux/games.js b/frontend/src/redux/games.js index 9ef0e7cd..d5953db1 100644 --- a/frontend/src/redux/games.js +++ b/frontend/src/redux/games.js @@ -1,4 +1,5 @@ -import Immutable from 'seamless-immutable'; +import { fromJS } from 'immutable'; +import GamesState from '../models/games'; export const types = { UPDATE_GAMES: 'GAME/UPDATE_GAMES', @@ -10,37 +11,29 @@ export const types = { }; export const actions = { - updateGames: games => ({ type: types.UPDATE_GAMES, games: Immutable(games) }), + updateGames: games => ({ type: types.UPDATE_GAMES, games: fromJS(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) }), + enterLobby: lobby => ({ type: types.ENTER_LOBBY, lobby: fromJS(lobby) }), enterGame: () => ({ type: types.ENTER_GAME }), }; -const initialState = Immutable.from({ - all: {}, - current: '', -}); - -export default (state = initialState, action) => { +export default (state = new GamesState(), action) => { switch (action.type) { case types.UPDATE_GAMES: - return Immutable.merge(state, { all: action.games }, { deep: true }); + return state.addGames(action.games); case types.ENTER_LOBBY: - return state.set('current', action.lobby.id); + return state.set('current', action.lobby.get('id')); default: return state; } }; -export const getAllGamesById = state => state.games.all; -export const getAllGames = 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 getAllGamesById = games => games.all; +export const getAllGames = games => getAllGamesById(games).toList(); +export const getGame = (games, id) => getAllGamesById(games).get(`${id}`); +export const getCurrentGame = games => getGame(games, games.current); diff --git a/frontend/src/redux/players.js b/frontend/src/redux/players.js index b11e920f..85b579f3 100644 --- a/frontend/src/redux/players.js +++ b/frontend/src/redux/players.js @@ -1,4 +1,4 @@ -import Immutable from 'seamless-immutable'; +import PlayerState, { Player } from '../models/players'; export const types = { REQUEST_CHOOSE_USERNAME: 'USER/REQUEST_CHOOSE_USERNAME', @@ -21,24 +21,17 @@ export const actions = { }), }; -const initialState = Immutable.from({ - all: {}, - current: '', -}); - -export default (state = initialState, action) => { +export default (state = new PlayerState(), 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); + return state.addPlayer(action.player); case types.UPDATE_PLAYERS: - return Immutable.merge(state, { all: action.players }, { deep: true }); + return state.addPlayers(action.players); default: 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 = players => players.all.get(players.current, new Player({ displayName: '[ERROR]' })); +export const getPlayer = (players, username) => players.all.get(username); +export const getPlayers = (players, usernames) => usernames.map(u => getPlayer(players, u)); diff --git a/frontend/src/store.js b/frontend/src/store.js index 4bd22184..57f43a4f 100644 --- a/frontend/src/store.js +++ b/frontend/src/store.js @@ -1,7 +1,7 @@ import { createStore, applyMiddleware, compose } from 'redux'; import { browserHistory } from 'react-router'; import { syncHistoryWithStore, routerMiddleware } from 'react-router-redux'; -import Immutable from 'seamless-immutable'; +import { fromJS } from 'immutable'; import createReducer from './reducers'; import createSagaMiddleware from 'redux-saga'; @@ -21,7 +21,7 @@ export default function configureStore(initialState = {}) { ? window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ : compose; - const store = createStore(createReducer(), Immutable.from(initialState), composeEnhancers(...enhancers)); + const store = createStore(createReducer(), fromJS(initialState), composeEnhancers(...enhancers)); sagaMiddleware.run(rootSaga, browserHistory); |