diff options
author | Joffrey BION <joffrey.bion@gmail.com> | 2019-05-16 23:48:38 +0200 |
---|---|---|
committer | Joffrey BION <joffrey.bion@gmail.com> | 2019-05-16 23:48:38 +0200 |
commit | 2382a452456e4bdef4584e1046925e372624cb79 (patch) | |
tree | 0e49b2e5d81facb55fb8b08228abeb218a27d466 /frontend/src | |
parent | Remove GRADLE_METADATA feature to avoid breaking frontend build (diff) | |
download | seven-wonders-2382a452456e4bdef4584e1046925e372624cb79.tar.gz seven-wonders-2382a452456e4bdef4584e1046925e372624cb79.tar.bz2 seven-wonders-2382a452456e4bdef4584e1046925e372624cb79.zip |
Rationalize module names
Diffstat (limited to 'frontend/src')
56 files changed, 0 insertions, 2046 deletions
diff --git a/frontend/src/@types/reflexbox.d.ts b/frontend/src/@types/reflexbox.d.ts deleted file mode 100644 index 802bc5f3..00000000 --- a/frontend/src/@types/reflexbox.d.ts +++ /dev/null @@ -1,37 +0,0 @@ -declare module 'reflexbox' { - - import { HTMLAttributes } from 'react'; - import * as React from 'react' - - export interface BoxProps { - w?: number | string, - h?: number | string, - - flex?: boolean, - wrap?: boolean, - column?: boolean, - auto?: boolean, - order?: number, - align?: "flex-start" | "flex-end" | "center" | "stretch" | "baseline", - justify?: "flex-start" | "flex-end" | "center" | "space-between" | "space-around" | "space-evenly", - - m?: number | string, - mx?: number | string, - my?: number | string, - mt?: number | string, - mb?: number | string, - ml?: number | string, - mr?: number | string, - - p?: number | string, - px?: number | string, - py?: number | string, - pt?: number | string, - pb?: number | string, - pl?: number | string, - pr?: number | string, - } - - export class Flex extends React.Component<HTMLAttributes & BoxProps> { } - export class Box extends React.Component<HTMLAttributes & BoxProps> { } -} diff --git a/frontend/src/api/model.ts b/frontend/src/api/model.ts deleted file mode 100644 index 2796a6d3..00000000 --- a/frontend/src/api/model.ts +++ /dev/null @@ -1,187 +0,0 @@ -export type ApiErrorDetail = { - message: string -}; - -export type ApiError = { - message: string, - details: ApiErrorDetail[] -}; - -export type ApiPlayer = { - username: string, - displayName: string, - index: number, - gameOwner: boolean, - user: boolean, -}; - -export type ApiWonderSidePickMethod = "EACH_RANDOM" | "ALL_A" | "ALL_B" | "SAME_RANDOM_FOR_ALL"; - -export type ApiSettings = { - randomSeedForTests: number, - timeLimitInSeconds: number, - wonderSidePickMethod: ApiWonderSidePickMethod, - initialGold: number, - discardedCardGold: number, - defaultTradingCost: number, - pointsPer3Gold: number, - lostPointsPerDefeat: number, - wonPointsPerVictoryPerAge: Map<number, number> -}; - -export type ApiGameState = "LOBBY" | "PLAYING"; - -export type ApiLobby = { - id: number, - name: string, - owner: string, - players: ApiPlayer[], - settings: ApiSettings, - state: ApiGameState -}; - -export type ApiScience = { - jokers: number, - nbWheels: number, - nbCompasses: number, - nbTablets: number, -} - -export type ApiMilitary = { - nbShields: number, - totalPoints: number, - nbDefeatTokens: number, -} - -export type ApiResourceType = "WOOD" | "STONE" | "ORE" | "CLAY" | "GLASS" | "PAPYRUS" | "LOOM"; - -export type ApiResources = { - quantities: Map<ApiResourceType, number>, -}; - -export type ApiRequirements = { - gold: number, - resources: ApiResources -} - -export type ApiCardBack = { - image: string, -}; - -export type ApiWonderStage = { - cardBack: ApiCardBack | null, - isBuilt: boolean, - requirements: ApiRequirements, - builtDuringLastMove: boolean, -} - -export type ApiWonderBuildability = { - buildable: boolean -} - -export type ApiWonder = { - name: string, - initialResource: ApiResourceType, - stages: ApiWonderStage[], - image: string, - nbBuiltStages: number, - buildability: ApiWonderBuildability, -} - -export type Color = 'BLUE' | 'GREEN' | 'RED' | 'BROWN' | 'GREY' | 'PURPLE' | 'YELLOW'; - -export type ApiProvider = "LEFT_NEIGHBOUR" | "RIGHT_NEIGHBOUR"; - -export type ApiCountedResource = { - type: ApiResourceType, - count: number, -} - -export type ApiProduction = { - fixedResources: ApiCountedResource[], - alternativeResources: ApiResourceType[][], -} - -export type ApiBoughtResources = { - provider: ApiProvider, - resources: ApiResources, -}; - -export type ApiCard = { - name: string, - color: Color, - requirements: ApiRequirements, - chainParent: String | null, - chainChildren: String[], - image: string, - back: ApiCardBack -}; - -export type ApiTableCard = ApiCard & { - playedDuringLastMove: boolean, -}; - -export type ApiBoard = { - playerIndex: number, - wonder: ApiWonder, - production: ApiProduction, - publicProduction: ApiProduction, - science: ApiScience, - military: ApiMilitary, - playedCards: ApiTableCard[][], - gold: number, -}; - -export type HandRotationDirection = 'LEFT' | 'RIGHT'; - -export type ApiMoveType = "PLAY" | "PLAY_FREE" | "UPGRADE_WONDER" | "DISCARD" | "COPY_GUILD"; - -export type ApiPlayedMove = { - playerIndex: number, - type: ApiMoveType, - card: ApiTableCard, - boughtResources: ApiBoughtResources[], -}; - -export type ApiTable = { - boards: ApiBoard[], - currentAge: number, - handRotationDirection: HandRotationDirection, - lastPlayedMoves: ApiPlayedMove[], - nbPlayers: number, -}; - -export type ApiAction = 'PLAY' | 'PLAY_2' | 'PLAY_LAST' | 'PICK_NEIGHBOR_GUILD' | 'WAIT'; - -export type ApiPlayability = { - playable: boolean, - chainable: boolean, - minPrice: number, -}; - -export type ApiHandCard = ApiCard & { - playability: ApiPlayability, -}; - -export type ApiPreparedCard = { - player: ApiPlayer, - cardBack: ApiCardBack, -}; - -export type ApiPlayerTurnInfo = { - playerIndex: number, - table: ApiTable, - currentAge: number, - action: ApiAction, - hand: ApiHandCard[], - playedMove: ApiPlayedMove | null, - neighbourGuildCards: ApiTableCard[], - message: string, - wonderBuildability: ApiWonderBuildability, -}; - -export type ApiPlayerMove = { - type: ApiMoveType, - cardName: string, - boughtResources: ApiBoughtResources[], -}; diff --git a/frontend/src/api/sevenWondersApi.ts b/frontend/src/api/sevenWondersApi.ts deleted file mode 100644 index 4f76a677..00000000 --- a/frontend/src/api/sevenWondersApi.ts +++ /dev/null @@ -1,104 +0,0 @@ -import { - ApiError, - ApiLobby, - ApiPlayer, - ApiPlayerMove, - ApiPlayerTurnInfo, - ApiPreparedCard, - ApiSettings, - ApiTable, -} from './model'; -import { JsonStompClient, SubscribeFn } from './websocket'; -import { createJsonStompClient } from './websocket'; - -const WS_URL = '/seven-wonders-websocket'; - -export class SevenWondersSession { - client: JsonStompClient; - - constructor(client: JsonStompClient) { - this.client = client; - } - - watchErrors(): SubscribeFn<ApiError> { - return this.client.subscriber('/user/queue/errors'); - } - - watchNameChoice(): SubscribeFn<ApiPlayer> { - return this.client.subscriber('/user/queue/nameChoice'); - } - - chooseName(displayName: string): void { - this.client.send('/app/chooseName', { playerName: displayName }); - } - - watchGames(): SubscribeFn<ApiLobby[]> { - return this.client.subscriber('/topic/games'); - } - - watchLobbyJoined(): SubscribeFn<Object> { - return this.client.subscriber('/user/queue/lobby/joined'); - } - - createGame(gameName: string): void { - this.client.send('/app/lobby/create', { gameName }); - } - - joinGame(gameId: number): void { - this.client.send('/app/lobby/join', { gameId }); - } - - watchLobbyUpdated(currentGameId: number): SubscribeFn<Object> { - return this.client.subscriber(`/topic/lobby/${currentGameId}/updated`); - } - - watchGameStarted(currentGameId: number): SubscribeFn<Object> { - return this.client.subscriber(`/topic/lobby/${currentGameId}/started`); - } - - leave(): void { - this.client.send('/app/lobby/leave'); - } - - reorderPlayers(orderedPlayers: Array<string>): void { - this.client.send('/app/lobby/reorderPlayers', { orderedPlayers }); - } - - updateSettings(settings: ApiSettings): void { - this.client.send('/app/lobby/updateSettings', { settings }); - } - - startGame(): void { - this.client.send('/app/lobby/startGame'); - } - - watchPlayerReady(currentGameId: number): SubscribeFn<string> { - return this.client.subscriber(`/topic/game/${currentGameId}/playerReady`); - } - - watchTableUpdates(currentGameId: number): SubscribeFn<ApiTable> { - return this.client.subscriber(`/topic/game/${currentGameId}/tableUpdates`); - } - - watchPreparedCards(currentGameId: number): SubscribeFn<ApiPreparedCard> { - return this.client.subscriber(`/topic/game/${currentGameId}/prepared`); - } - - watchTurnInfo(): SubscribeFn<ApiPlayerTurnInfo> { - return this.client.subscriber('/user/queue/game/turn'); - } - - sayReady(): void { - this.client.send('/app/game/sayReady'); - } - - prepareMove(move: ApiPlayerMove): void { - this.client.send('/app/game/prepareMove', { move }); - } -} - -export async function connectToGame(): Promise<SevenWondersSession> { - const jsonStompClient: JsonStompClient = createJsonStompClient(WS_URL); - await jsonStompClient.connect(); - return new SevenWondersSession(jsonStompClient); -} diff --git a/frontend/src/api/websocket.ts b/frontend/src/api/websocket.ts deleted file mode 100644 index e9393836..00000000 --- a/frontend/src/api/websocket.ts +++ /dev/null @@ -1,60 +0,0 @@ -import SockJS from 'sockjs-client'; -import { Client, Frame, Message, Options, Subscription } from 'webstomp-client'; -import * as Stomp from 'webstomp-client'; - -const DEFAULT_DEBUG_OPTIONS = { - debug: process.env.NODE_ENV !== 'production', -}; - -export type Callback<T> = (value: T) => void; -export type UnsubscribeFn = () => void; -export type SubscribeFn<T> = (callback: Callback<T>) => UnsubscribeFn; - -export class JsonStompClient { - client: Client; - - constructor(client: Client) { - this.client = client; - } - - connect(headers: Stomp.ConnectionHeaders = {}): Promise<Frame | void> { - return new Promise((resolve, reject) => { - this.client.connect(headers, resolve, reject); - }); - } - - subscribe<T>(path: string, callback: Callback<T>): UnsubscribeFn { - const socketSubscription: Subscription = this.client.subscribe(path, (message: Message) => { - // not all frames have a JSON body - const value: T | void = message && JsonStompClient.parseBody(message); - callback(value || {} as T); - }); - return () => socketSubscription.unsubscribe(); - } - - static parseBody<T>(message: Message): T | void { - try { - return message.body ? JSON.parse(message.body) : undefined; - } catch (jsonParseError) { - throw new Error('Cannot parse websocket message as JSON: ' + jsonParseError.message); - } - } - - subscriber<T>(path: string): SubscribeFn<T> { - return (callback: Callback<T>) => this.subscribe(path, callback); - } - - send(url: string, body?: Object) { - const strBody = body ? JSON.stringify(body) : ''; - this.client.send(url, strBody); - } -} - -function createStompClient(url: string, options: Options = {}): Client { - const optionsWithDebug = Object.assign({}, DEFAULT_DEBUG_OPTIONS, options); - return Stomp.over(new SockJS(url), optionsWithDebug); -} - -export function createJsonStompClient(url: string, options: Options = {}): JsonStompClient { - return new JsonStompClient(createStompClient(url, options)); -} diff --git a/frontend/src/components/Application.tsx b/frontend/src/components/Application.tsx deleted file mode 100644 index e0ec604d..00000000 --- a/frontend/src/components/Application.tsx +++ /dev/null @@ -1,16 +0,0 @@ -import React from 'react'; -import { Redirect, Route, Switch } from 'react-router-dom'; -import { GameBrowser } from './game-browser/GameBrowser'; -import { GameScene } from './game/GameScene'; -import { Lobby } from './lobby/Lobby'; -import { Home } from './home/Home'; - -export const Application = () => ( - <Switch> - <Route path="/game" component={GameScene} /> - <Route path="/games" component={GameBrowser} /> - <Route path="/lobby" component={Lobby} /> - <Route path="/" component={Home} /> - <Redirect to="/" /> - </Switch> -); diff --git a/frontend/src/components/game-browser/GameBrowser.tsx b/frontend/src/components/game-browser/GameBrowser.tsx deleted file mode 100644 index a6367d5e..00000000 --- a/frontend/src/components/game-browser/GameBrowser.tsx +++ /dev/null @@ -1,56 +0,0 @@ -import { Button, Classes, InputGroup, Intent } from '@blueprintjs/core'; -import React, { ChangeEvent, Component, SyntheticEvent } from 'react'; -import { connect } from 'react-redux'; -import { Flex } from 'reflexbox'; -import { actions } from '../../redux/actions/lobby'; -import { GameList } from './GameList'; -import { PlayerInfo } from './PlayerInfo'; - -type GameBrowserProps = { - createGame: (gameName: string) => void, -} - -class GameBrowserPresenter extends Component<GameBrowserProps> { - - _gameName: string | void = undefined; - - createGame = (e: SyntheticEvent<any>): void => { - e.preventDefault(); - if (this._gameName !== undefined) { - this.props.createGame(this._gameName); - } - }; - - render() { - return ( - <div> - <Flex align="center" justify='space-between' p={1}> - <form onSubmit={this.createGame}> - <InputGroup - placeholder="Game name" - name="game_name" - onChange={(e: ChangeEvent<HTMLInputElement>) => (this._gameName = e.target.value)} - rightElement={<CreateGameButton createGame={this.createGame}/>} - /> - </form> - <PlayerInfo /> - </Flex> - <GameList /> - </div> - ); - } -} - -type CreateGameButtonProps = { - createGame: (e: SyntheticEvent<any>) => void -} - -const CreateGameButton = ({createGame}: CreateGameButtonProps) => ( - <Button className={Classes.MINIMAL} intent={Intent.PRIMARY} icon='add' onClick={createGame} /> -); - -const mapDispatchToProps = { - createGame: actions.requestCreateGame, -}; - -export const GameBrowser = connect(null, mapDispatchToProps)(GameBrowserPresenter); diff --git a/frontend/src/components/game-browser/GameList.css b/frontend/src/components/game-browser/GameList.css deleted file mode 100644 index a04e126c..00000000 --- a/frontend/src/components/game-browser/GameList.css +++ /dev/null @@ -1,3 +0,0 @@ -tr.gameListRow td { - vertical-align: middle; -} diff --git a/frontend/src/components/game-browser/GameList.tsx b/frontend/src/components/game-browser/GameList.tsx deleted file mode 100644 index 1b136940..00000000 --- a/frontend/src/components/game-browser/GameList.tsx +++ /dev/null @@ -1,85 +0,0 @@ -import { Button, Classes } from '@blueprintjs/core' -import { List } from 'immutable'; -import React from 'react'; -import { connect } from 'react-redux'; -import { ApiLobby } from '../../api/model'; -import { GlobalState } from '../../reducers'; -import { actions } from '../../redux/actions/lobby'; -import { getAllGames } from '../../redux/games'; -import './GameList.css'; -import { GameStatus } from './GameStatus'; -import { PlayerCount } from './PlayerCount'; - -type GameListStateProps = { - games: List<ApiLobby>, -}; - -type GameListDispatchProps = { - joinGame: (gameId: number) => void, -}; - -type GameListProps = GameListStateProps & GameListDispatchProps - -const GameListPresenter = ({ games, joinGame }: GameListProps) => ( - <table className={Classes.HTML_TABLE}> - <thead> - <GameListHeaderRow /> - </thead> - <tbody> - {games.map((game: ApiLobby) => <GameListItemRow key={game.id} game={game} joinGame={joinGame}/>)} - </tbody> - </table> -); - -const GameListHeaderRow = () => ( - <tr> - <th>Name</th> - <th>Status</th> - <th>Nb Players</th> - <th>Join</th> - </tr> -); - -type GameListItemRowProps = { - game: ApiLobby, - joinGame: (gameId: number) => void, -}; - -const GameListItemRow = ({game, joinGame}: GameListItemRowProps) => ( - <tr className="gameListRow"> - <td>{game.name}</td> - <td> - <GameStatus state={game.state} /> - </td> - <td> - <PlayerCount nbPlayers={game.players.length} /> - </td> - <td> - <JoinButton game={game} joinGame={joinGame}/> - </td> - </tr> -); - -type JoinButtonProps = { - game: ApiLobby, - joinGame: (gameId: number) => void, -}; - -const JoinButton = ({game, joinGame}: JoinButtonProps) => { - const disabled = game.state !== 'LOBBY'; - const onClick = () => joinGame(game.id); - return <Button minimal disabled={disabled} icon='arrow-right' title='Join Game' onClick={onClick}/>; -}; - -function mapStateToProps(state: GlobalState): GameListStateProps { - return { - games: getAllGames(state), - }; -} - -const mapDispatchToProps: GameListDispatchProps = { - joinGame: actions.requestJoinGame, -}; - -export const GameList = connect(mapStateToProps, mapDispatchToProps)(GameListPresenter); - diff --git a/frontend/src/components/game-browser/GameStatus.tsx b/frontend/src/components/game-browser/GameStatus.tsx deleted file mode 100644 index 5f237258..00000000 --- a/frontend/src/components/game-browser/GameStatus.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import { Tag } from '@blueprintjs/core'; -import { Intent } from '@blueprintjs/core'; -import * as React from 'react'; -import { ApiGameState } from '../../api/model'; - -type GameStatusProps = { - state: ApiGameState, -} - -export const GameStatus = ({state}: GameStatusProps) => ( - <Tag minimal intent={statusIntents[state]}>{state}</Tag> -); - -const statusIntents = { - 'LOBBY': Intent.SUCCESS, - 'PLAYING': Intent.WARNING, -}; diff --git a/frontend/src/components/game-browser/PlayerCount.css b/frontend/src/components/game-browser/PlayerCount.css deleted file mode 100644 index d2f18e50..00000000 --- a/frontend/src/components/game-browser/PlayerCount.css +++ /dev/null @@ -1,3 +0,0 @@ -.playerCountIcon, .playerCount { - vertical-align: middle; -} diff --git a/frontend/src/components/game-browser/PlayerCount.tsx b/frontend/src/components/game-browser/PlayerCount.tsx deleted file mode 100644 index 64028f68..00000000 --- a/frontend/src/components/game-browser/PlayerCount.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import { Icon } from '@blueprintjs/core'; -import * as React from 'react'; -import './PlayerCount.css'; - -type PlayerCountProps = { - nbPlayers: number, -} - -export const PlayerCount = ({nbPlayers}: PlayerCountProps) => <div title='Number of players'> - <Icon className="playerCountIcon" icon="people" title={false} /> - <span className="playerCount"> {nbPlayers}</span> -</div>; diff --git a/frontend/src/components/game-browser/PlayerInfo.tsx b/frontend/src/components/game-browser/PlayerInfo.tsx deleted file mode 100644 index 4afed671..00000000 --- a/frontend/src/components/game-browser/PlayerInfo.tsx +++ /dev/null @@ -1,27 +0,0 @@ -import { Text } from '@blueprintjs/core'; -import React from 'react'; -import { connect } from 'react-redux'; -import { GlobalState } from '../../reducers'; -import { User } from '../../redux/user'; -import { getCurrentUser } from '../../redux/user'; - -type PlayerInfoProps = { - user: User | null, -} - -const PlayerInfoPresenter = ({user}: PlayerInfoProps) => ( - <Text> - <b>Username:</b> - {' '} - {user && user.displayName} - </Text> -); - -const mapStateToProps = (state: GlobalState): PlayerInfoProps => ({ - user: getCurrentUser(state), -}); - -const mapDispatchToProps = { -}; - -export const PlayerInfo = connect(mapStateToProps, mapDispatchToProps)(PlayerInfoPresenter); diff --git a/frontend/src/components/game/Board.css b/frontend/src/components/game/Board.css deleted file mode 100644 index 0600bd14..00000000 --- a/frontend/src/components/game/Board.css +++ /dev/null @@ -1,38 +0,0 @@ -.board { - width: 100vw -} - -.cards { - display: flex; - height: 40vh; - width: 100vw; -} - -.card-column { - height: 40vh; - margin: auto; - position: relative; - width: 15vw; -} - -.card { - position: absolute; - /* dynamic positioning in JS */ -} - -.table-card-img { - max-width: 10vw; - max-height: 25vh; -} - -.wonder { - width: 100vw; - text-align: center; -} - -.wonder-img { - border-radius: 0.5%/1.5%; - box-shadow: 0.2rem 0.2rem 0.5rem black; - max-height: 30vh; - max-width: 95vw; -} diff --git a/frontend/src/components/game/Board.tsx b/frontend/src/components/game/Board.tsx deleted file mode 100644 index 98298a1f..00000000 --- a/frontend/src/components/game/Board.tsx +++ /dev/null @@ -1,67 +0,0 @@ -import React from 'react'; -import { ApiBoard, ApiTableCard, ApiWonder } from '../../api/model'; -import './Board.css' -import { CardImage } from './CardImage'; - -// card offsets in % of their size when displayed in columns -const xOffset = 20; -const yOffset = 21; - -type BoardProps = { - board: ApiBoard, -} - -export const Board = ({board}: BoardProps) => { - return <div className='board'> - <TableCards cardColumns={board.playedCards}/> - <Wonder wonder={board.wonder}/> - </div>; -}; - -type TableCardsProps = { - cardColumns: ApiTableCard[][], -} - -const TableCards = ({cardColumns}: TableCardsProps) => { - return <div className="cards"> - {cardColumns.map(column => <TableCardColumn key={column[0].color} cards={column}/>)} - </div> -}; - -type TableCardColumnProps = { - cards: ApiTableCard[] -} - -const TableCardColumn = ({cards}: TableCardColumnProps) => { - return <div className="card-column"> - {cards.map((c, i) => <TableCard key={c.name} card={c} indexInColumn={i}/>)} - </div> -}; - -type TableCardProps = { - card: ApiTableCard, - indexInColumn: number, -} - -const TableCard = ({card, indexInColumn}: TableCardProps) => { - let style = { - transform: `translate(${indexInColumn * xOffset}%, ${indexInColumn * yOffset}%)`, - zIndex: indexInColumn, - }; - return <div className="card" style={style}> - <CardImage card={card} otherClasses="table-card-img"/> - </div> -}; - -type WonderProps = { - wonder: ApiWonder, -} - -const Wonder = ({wonder}: WonderProps) => { - return <div className="wonder"> - <img src={`/images/wonders/${wonder.image}`} - title={wonder.name} - alt={`Wonder ${wonder.name}`} - className="wonder-img"/> - </div> -}; diff --git a/frontend/src/components/game/CardImage.css b/frontend/src/components/game/CardImage.css deleted file mode 100644 index 795c1503..00000000 --- a/frontend/src/components/game/CardImage.css +++ /dev/null @@ -1,4 +0,0 @@ -.card-img { - border-radius: 5%; - box-shadow: 2px 2px 5px black; -} diff --git a/frontend/src/components/game/CardImage.tsx b/frontend/src/components/game/CardImage.tsx deleted file mode 100644 index a37595ad..00000000 --- a/frontend/src/components/game/CardImage.tsx +++ /dev/null @@ -1,26 +0,0 @@ -import React from 'react'; -import { ApiCard } from '../../api/model'; -import './CardImage.css' - -type CardImageProps = { - card: ApiCard, - otherClasses: string, - highlightColor?: string -} - -export const CardImage = ({card, otherClasses, highlightColor}: CardImageProps) => { - const style = highlightStyle(highlightColor); - return <img src={`/images/cards/${card.image}`} - title={card.name} - alt={'Card ' + card.name} - className={`card-img ${otherClasses}`} - style={style}/> -}; - -function highlightStyle(highlightColor?: string) { - if (highlightColor) { - return { boxShadow: `0 0 1rem 0.1rem ${highlightColor}` }; - } else { - return {}; - } -} diff --git a/frontend/src/components/game/GameScene.css b/frontend/src/components/game/GameScene.css deleted file mode 100644 index 3417459b..00000000 --- a/frontend/src/components/game/GameScene.css +++ /dev/null @@ -1,13 +0,0 @@ -.gameSceneRoot { - background: url('background-papyrus.jpg') center no-repeat; - background-size: cover; -} - -.fullscreen { - position: fixed; - top: 0; - left: 0; - bottom: 0; - right: 0; - overflow: hidden; -} diff --git a/frontend/src/components/game/GameScene.tsx b/frontend/src/components/game/GameScene.tsx deleted file mode 100644 index 465d0840..00000000 --- a/frontend/src/components/game/GameScene.tsx +++ /dev/null @@ -1,77 +0,0 @@ -import { Button, Classes, Intent, NonIdealState } from '@blueprintjs/core'; -import { List } from 'immutable'; -import React, { Component } from 'react'; -import { connect } from 'react-redux'; -import { ApiPlayer, ApiPlayerMove, ApiPlayerTurnInfo } from '../../api/model'; -import { GlobalState } from '../../reducers'; -import { actions } from '../../redux/actions/game'; -import { getCurrentTurnInfo } from '../../redux/currentGame'; -import { getCurrentGame } from '../../redux/games'; -import { Board } from './Board'; -import './GameScene.css' -import { Hand } from './Hand'; -import { ProductionBar } from './ProductionBar'; - -type GameSceneStateProps = { - players: List<ApiPlayer>, - turnInfo: ApiPlayerTurnInfo | null, -} - -type GameSceneDispatchProps = { - sayReady: () => void, - prepareMove: (move: ApiPlayerMove) => void, -} - -type GameSceneProps = GameSceneStateProps & GameSceneDispatchProps - -class GameScenePresenter extends Component<GameSceneProps> { - - render() { - return ( - <div className='gameSceneRoot fullscreen'> - {!this.props.turnInfo && <GamePreStart onReadyClicked={this.props.sayReady}/>} - {this.props.turnInfo && this.turnInfoScene(this.props.turnInfo)} - </div> - ); - } - - turnInfoScene(turnInfo: ApiPlayerTurnInfo) { - let board = turnInfo.table.boards[turnInfo.playerIndex]; - return <div> - <p>{turnInfo.message}</p> - <Board board={board}/> - <Hand cards={turnInfo.hand} - wonderUpgradable={turnInfo.wonderBuildability.buildable} - prepareMove={this.props.prepareMove}/> - <ProductionBar gold={board.gold} production={board.production}/> - </div> - } -} - -type GamePreStartProps = { - onReadyClicked: () => void -} -const GamePreStart = ({onReadyClicked}: GamePreStartProps) => <NonIdealState - description={<p>Click "ready" when you are</p>} - action={<Button text="READY" className={Classes.LARGE} intent={Intent.PRIMARY} icon='play' - onClick={() => onReadyClicked()}/>} -/>; - -function mapStateToProps(state: GlobalState): GameSceneStateProps { - const game = getCurrentGame(state); - console.info(game); - - return { - players: game ? List(game.players) : List(), - turnInfo: getCurrentTurnInfo(state), - }; -} - -function mapDispatchToProps(): GameSceneDispatchProps { - return { - sayReady: actions.sayReady, - prepareMove: actions.prepareMove, - } -} - -export const GameScene = connect(mapStateToProps, mapDispatchToProps)(GameScenePresenter); diff --git a/frontend/src/components/game/Hand.css b/frontend/src/components/game/Hand.css deleted file mode 100644 index 8e7d93c5..00000000 --- a/frontend/src/components/game/Hand.css +++ /dev/null @@ -1,50 +0,0 @@ -.hand { - align-items: center; - bottom: 0; - display: flex; - height: 345px; /* can hold enhanced cards */ - left: 50%; - max-height: 25vw; - position: absolute; - transform: translate(-50%, 55%); - transition: 0.5s; - z-index: 30; -} -.hand:hover { - bottom: 4rem; - transform: translate(-50%, 0%); -} - -.hand-card { - align-items: flex-end; - display: grid; - margin: 0.2rem; -} - -.hand-card .hand-card-img { - grid-row: 1; - grid-column: 1; - max-width: 13vw; - max-height: 60vh; - transition: 0.1s; - width: 11rem; -} -.hand-card.unplayable .hand-card-img { - filter: grayscale(50%) contrast(50%); -} -.hand-card:hover .hand-card-img { - box-shadow: 0 10px 40px black; - width: 14rem; - max-width: 15vw; - max-height: 90vh; -} - -.hand-card .action-buttons { - align-items: flex-end; - display: none; - grid-row: 1; - grid-column: 1; -} -.hand-card:hover .action-buttons { - display: flex; -} diff --git a/frontend/src/components/game/Hand.tsx b/frontend/src/components/game/Hand.tsx deleted file mode 100644 index 744c45cc..00000000 --- a/frontend/src/components/game/Hand.tsx +++ /dev/null @@ -1,44 +0,0 @@ -import { Button, ButtonGroup, Classes, Intent } from '@blueprintjs/core'; -import React from 'react'; -import { ApiHandCard, ApiPlayerMove } from '../../api/model'; -import './Hand.css' -import { CardImage } from './CardImage'; - -type HandProps = { - cards: ApiHandCard[], - wonderUpgradable: boolean, - prepareMove: (move: ApiPlayerMove) => void -} - -export const Hand = ({cards, wonderUpgradable, prepareMove}: HandProps) => { - return <div className='hand'>{cards.map((c, i) => <HandCard key={i} card={c} - wonderUpgradable={wonderUpgradable} - prepareMove={prepareMove}/>)}</div>; -}; - -type HandCardProps = { - card: ApiHandCard, - wonderUpgradable: boolean, - prepareMove: (move: ApiPlayerMove) => void -} - -const HandCard = ({card, wonderUpgradable, prepareMove}: HandCardProps) => { - let playableClass = card.playability.playable ? '' : 'unplayable'; - return <div className={`hand-card ${playableClass}`}> - <CardImage card={card} otherClasses="hand-card-img"/> - <ActionButtons card={card} wonderUpgradable={wonderUpgradable} prepareMove={prepareMove} /> - </div> -}; - -type ActionButtonsProps = HandCardProps - -const ActionButtons = ({card, wonderUpgradable, prepareMove}: ActionButtonsProps) => <ButtonGroup className="action-buttons"> - <Button title="PLAY" className={Classes.LARGE} intent={Intent.SUCCESS} icon='play' - disabled={!card.playability.playable} - onClick={() => prepareMove({type: 'PLAY', cardName: card.name, boughtResources: []})}/> - <Button title="BUILD WONDER" className={Classes.LARGE} intent={Intent.PRIMARY} icon='key-shift' - disabled={!wonderUpgradable} - onClick={() => prepareMove({type: 'UPGRADE_WONDER', cardName: card.name, boughtResources: []})}/> - <Button title="DISCARD" className={Classes.LARGE} intent={Intent.DANGER} icon='cross' - onClick={() => prepareMove({type: 'DISCARD', cardName: card.name, boughtResources: []})}/> -</ButtonGroup>; diff --git a/frontend/src/components/game/ProductionBar.css b/frontend/src/components/game/ProductionBar.css deleted file mode 100644 index 77a3b8fc..00000000 --- a/frontend/src/components/game/ProductionBar.css +++ /dev/null @@ -1,50 +0,0 @@ -.production-bar { - align-items: center; - background: lightgray; - bottom: 0; - border-top: 1px #8b8b8b solid; - background: linear-gradient(#eaeaea, #888 7%); - box-shadow: 0 0 15px 0 #747474; - display: flex; - height: 3.5rem; - position: fixed; - width: 100vw; - z-index: 99; -} - -.fixed-resources { - margin: auto; - display: flex; -} -.alternative-resources { - margin: auto; - display: flex; -} - -.resource-with-count { - margin-left: 1rem -} -.resource-choice { - margin-left: 1.5rem; -} - -.choice-separator { - font-size: 2rem; - vertical-align: middle; - margin: 5px; - color: #c29929; - text-shadow: 0 0 1px black; -} - -.token-img { - height: 3rem; - vertical-align: middle; - width: 3rem; -} - -.token-count { - font-family: fantasy; - font-size: 1.5rem; - margin-left: 0.2rem; - vertical-align: middle; -} diff --git a/frontend/src/components/game/ProductionBar.tsx b/frontend/src/components/game/ProductionBar.tsx deleted file mode 100644 index 3e5c6d34..00000000 --- a/frontend/src/components/game/ProductionBar.tsx +++ /dev/null @@ -1,87 +0,0 @@ -import React from 'react'; -import { ApiCountedResource, ApiProduction, ApiResourceType } from '../../api/model'; -import './ProductionBar.css' - -type ProductionBarProps = { - gold: number, - production: ApiProduction, -} - -export const ProductionBar = ({gold, production}: ProductionBarProps) => { - return <div className='production-bar'> - <GoldIndicator amount={gold}/> - <FixedResources resources={production.fixedResources}/> - <AlternativeResources resources={production.alternativeResources}/> - </div>; -}; - -type GoldIndicatorProps = { - amount: number, -} -const GoldIndicator = ({amount}: GoldIndicatorProps) => { - return <TokenWithCount tokenName="coin" count={amount} otherClasses="gold-indicator"/> -}; - -type FixedResourcesProps = { - resources: ApiCountedResource[], -} -const FixedResources = ({resources}: FixedResourcesProps) => { - return <div className="fixed-resources"> - {resources.map(r => <TokenWithCount key={r.type} - tokenName={getTokenName(r.type)} - count={r.count} - otherClasses="resource-with-count"/>)} - </div> -}; - -type AlternativeResourcesProps = { - resources: ApiResourceType[][], -} -const AlternativeResources = ({resources}: AlternativeResourcesProps) => { - return <div className="alternative-resources"> - {resources.map((types, i) => <ResourceChoice key={i} types={types}/>)} - </div> -}; - -type ResourceChoiceProps = { - types: ApiResourceType[], -} -const ResourceChoice = ({types}: ResourceChoiceProps) => { - let typeImages = types.map(type => <TokenImage key={type} tokenName={getTokenName(type)}/>); - let separator = <span className="choice-separator">∕</span>; - return <div className="resource-choice"> - {intersperce(typeImages, separator)} - </div> -}; - -function intersperce<T>(array: T[], separator: T): T[] { - let result = array.reduce((acc: T[], elt: T) => acc.concat(elt, separator), []); - return result.slice(0, -1); // remove extra separator at the end -} - -type TokenWithCountProps = { - tokenName: string, - count: number, - otherClasses?: string, -} -const TokenWithCount = ({tokenName, count, otherClasses = ""}: TokenWithCountProps) => { - return <div className={`token-with-count ${otherClasses}`}> - <TokenImage tokenName={tokenName}/> - <span className="token-count">× {count}</span> - </div> -}; - -type TokenImageProps = { - tokenName: string, -} -const TokenImage = ({tokenName}: TokenImageProps) => { - return <img src={getTokenImagePath(tokenName)} title={tokenName} alt={tokenName} className="token-img"/> -}; - -function getTokenImagePath(tokenName: string): string { - return `/images/tokens/${tokenName}.png`; -} - -function getTokenName(resourceType: ApiResourceType): string { - return `resources/${resourceType.toLowerCase()}`; -} diff --git a/frontend/src/components/game/background-papyrus.jpg b/frontend/src/components/game/background-papyrus.jpg Binary files differdeleted file mode 100644 index 57bdffcf..00000000 --- a/frontend/src/components/game/background-papyrus.jpg +++ /dev/null diff --git a/frontend/src/components/home/ChooseNameForm.tsx b/frontend/src/components/home/ChooseNameForm.tsx deleted file mode 100644 index 8292150b..00000000 --- a/frontend/src/components/home/ChooseNameForm.tsx +++ /dev/null @@ -1,42 +0,0 @@ -import { Button, Classes, InputGroup, Intent } from '@blueprintjs/core'; -import React, { ChangeEvent, Component, SyntheticEvent } from 'react'; -import { connect } from 'react-redux'; -import { actions } from '../../redux/actions/user'; - -type ChooseNameFormPresenterProps = { - chooseUsername: (username: string) => void, -} - -class ChooseNameFormPresenter extends Component<ChooseNameFormPresenterProps> { - _username = ''; - - play = (e: SyntheticEvent<any>) => { - e.preventDefault(); - if (this._username !== undefined) { - this.props.chooseUsername(this._username); - } - }; - - render() { - return ( - <form onSubmit={this.play}> - <InputGroup - className={Classes.LARGE} - placeholder="Username" - onChange={(e: ChangeEvent<HTMLInputElement>) => (this._username = e.target.value)} - rightElement={this.renderSubmit()} - /> - </form> - ); - } - - renderSubmit = () => ( - <Button className={Classes.MINIMAL} onClick={this.play} intent={Intent.PRIMARY} icon="arrow-right" /> - ); -} - -const mapDispatchToProps = { - chooseUsername: actions.chooseUsername, -}; - -export const ChooseNameForm = connect(null, mapDispatchToProps)(ChooseNameFormPresenter); diff --git a/frontend/src/components/home/Home.css b/frontend/src/components/home/Home.css deleted file mode 100644 index 7d9a96de..00000000 --- a/frontend/src/components/home/Home.css +++ /dev/null @@ -1,13 +0,0 @@ -.homeRoot { - background: url('background-zeus-temple.jpg') center no-repeat; - background-size: cover; -} - -.fullscreen { - position: fixed; - top: 0; - left: 0; - bottom: 0; - right: 0; - overflow: hidden; -} diff --git a/frontend/src/components/home/Home.tsx b/frontend/src/components/home/Home.tsx deleted file mode 100644 index 094db658..00000000 --- a/frontend/src/components/home/Home.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import * as React from 'react'; -import { Flex } from 'reflexbox'; -import { ChooseNameForm } from './ChooseNameForm'; -import './Home.css' -import logo from './logo-7-wonders.png'; - -export const Home = () => ( - <Flex className='homeRoot fullscreen' column align='center' justify='center'> - <img src={logo} alt="Seven Wonders"/> - <ChooseNameForm/> - </Flex> -); diff --git a/frontend/src/components/home/background-zeus-temple.jpg b/frontend/src/components/home/background-zeus-temple.jpg Binary files differdeleted file mode 100644 index 5a28e933..00000000 --- a/frontend/src/components/home/background-zeus-temple.jpg +++ /dev/null diff --git a/frontend/src/components/home/logo-7-wonders.png b/frontend/src/components/home/logo-7-wonders.png Binary files differdeleted file mode 100644 index 96974d3e..00000000 --- a/frontend/src/components/home/logo-7-wonders.png +++ /dev/null diff --git a/frontend/src/components/lobby/Lobby.tsx b/frontend/src/components/lobby/Lobby.tsx deleted file mode 100644 index 3594af65..00000000 --- a/frontend/src/components/lobby/Lobby.tsx +++ /dev/null @@ -1,56 +0,0 @@ -import { Button, Classes, Intent } from '@blueprintjs/core'; -import { List } from 'immutable'; -import React, { Component } from 'react'; -import { connect } from 'react-redux'; -import { ApiLobby, ApiPlayer } from '../../api/model'; -import { GlobalState } from '../../reducers'; -import { actions } from '../../redux/actions/lobby'; -import { getCurrentGame } from '../../redux/games'; -import { getCurrentPlayer } from '../../redux/user'; -import { RadialPlayerList } from './RadialPlayerList'; - -export type LobbyStateProps = { - currentGame: ApiLobby | null, - currentPlayer: ApiPlayer | null, - players: List<ApiPlayer>, -} - -export type LobbyDispatchProps = { - startGame: () => void, -} - -export type LobbyProps = LobbyStateProps & LobbyDispatchProps - -class LobbyPresenter extends Component<LobbyProps> { - - render() { - const {currentGame, currentPlayer, players, startGame} = this.props; - if (!currentGame || !currentPlayer) { - return <div>Error: no current game.</div> - } - return ( - <div> - <h2>{currentGame.name + ' — Lobby'}</h2> - <RadialPlayerList players={players}/> - {currentPlayer.gameOwner && <Button text="START" className={Classes.LARGE} intent={Intent.PRIMARY} icon='play' - onClick={startGame} disabled={players.size < 3}/>} - </div> - ); - } -} - -function mapStateToProps(state: GlobalState): LobbyStateProps { - const game = getCurrentGame(state); - console.info(game); - return { - currentGame: game, - currentPlayer: getCurrentPlayer(state), - players: game ? List(game.players) : List(), - }; -} - -const mapDispatchToProps = { - startGame: actions.requestStartGame, -}; - -export const Lobby = connect(mapStateToProps, mapDispatchToProps)(LobbyPresenter); diff --git a/frontend/src/components/lobby/PlayerList.tsx b/frontend/src/components/lobby/PlayerList.tsx deleted file mode 100644 index bfc3a56c..00000000 --- a/frontend/src/components/lobby/PlayerList.tsx +++ /dev/null @@ -1,41 +0,0 @@ -import { Classes, Icon } from '@blueprintjs/core' -import { List } from 'immutable'; -import * as React from 'react'; -import { Flex } from 'reflexbox'; -import { ApiPlayer } from '../../api/model'; - -type PlayerListItemProps = { - player: ApiPlayer, - isOwner: boolean, - isUser: boolean, -}; - -const PlayerListItem = ({player, isOwner, isUser}: PlayerListItemProps) => ( - <tr> - <td> - <Flex align='center'> - {isOwner && <Icon icon='badge' title='Game owner'/>} - {isUser && <Icon icon='user' title='This is you'/>} - </Flex> - </td> - <td>{player.displayName}</td> - <td>{player.username}</td> - </tr> -); - -type PlayerListProps = { - players: List<ApiPlayer>, - owner: string, - currentPlayer: ApiPlayer, -}; - -export const PlayerList = ({players, owner, currentPlayer}: PlayerListProps) => ( - <table className={Classes.HTML_TABLE}> - <tbody> - {players.map((player: ApiPlayer) => <PlayerListItem key={player.username} - player={player} - isOwner={player.username === owner} - isUser={player.username === currentPlayer.username}/>)} - </tbody> - </table> -); diff --git a/frontend/src/components/lobby/RadialPlayerList.tsx b/frontend/src/components/lobby/RadialPlayerList.tsx deleted file mode 100644 index 88db55fc..00000000 --- a/frontend/src/components/lobby/RadialPlayerList.tsx +++ /dev/null @@ -1,69 +0,0 @@ -import { Icon, IconName, Intent } from '@blueprintjs/core'; -import { List } from 'immutable'; -import * as React from 'react'; -import { ReactNode } from 'react'; -import { Flex } from 'reflexbox'; -import { ApiPlayer } from '../../api/model'; -import { RadialList } from './radial-list/RadialList'; -import roundTable from './round-table.png'; - -type PlayerItemProps = { - player: ApiPlayer -}; - -const PlayerItem = ({player}: PlayerItemProps) => ( - <Flex column align='center'> - <UserIcon isOwner={player.gameOwner} isUser={player.user} title={player.gameOwner ? 'Game owner' : null}/> - <h5 style={{margin: 0}}>{player.displayName}</h5> - </Flex> -); - -const PlayerPlaceholder = () => ( - <Flex column align='center' style={{opacity: 0.3}}> - <UserIcon isOwner={false} isUser={false} title='Waiting for player...'/> - <h5 style={{margin: 0}}>?</h5> - </Flex> -); - -type UserIconProps = { - isUser: boolean, - isOwner: boolean, - title: string | null, -}; - -const UserIcon = ({isUser, isOwner, title}: UserIconProps) => { - const icon: IconName = isOwner ? 'badge' : 'user'; - const intent: Intent = isUser ? Intent.WARNING : Intent.NONE; - return <Icon icon={icon} iconSize={50} intent={intent} title={title}/>; -}; - -type RadialPlayerListProps = { - players: List<ApiPlayer> -}; - -export const RadialPlayerList = ({players}: RadialPlayerListProps) => { - const orderedPlayers = placeUserFirst(players.toArray()); - const playerItems = orderedPlayers.map(player => <PlayerItem key={player.username} player={player}/>); - const tableImg = <img src={roundTable} alt='Round table' style={{width: 200, height: 200}}/>; - return <RadialList items={completeWithPlaceholders(playerItems)} - centerElement={tableImg} - radius={175} - offsetDegrees={180} - itemWidth={120} - itemHeight={100}/>; -}; - -function placeUserFirst(players: ApiPlayer[]): ApiPlayer[] { - while (!players[0].user) { - players.push(players.shift()!); - } - return players; -} - -function completeWithPlaceholders(playerItems: Array<ReactNode>): Array<ReactNode> { - while (playerItems.length < 3) { - playerItems.push(<PlayerPlaceholder/>); - } - return playerItems; -} - diff --git a/frontend/src/components/lobby/radial-list/RadialList.css b/frontend/src/components/lobby/radial-list/RadialList.css deleted file mode 100644 index 3b0f3a79..00000000 --- a/frontend/src/components/lobby/radial-list/RadialList.css +++ /dev/null @@ -1,23 +0,0 @@ -.radial-list-container { - margin: 0; - padding: 0; - position: relative; -} - -.radial-list { - margin: 0; - padding: 0; - transition: all 500ms ease-in-out; - z-index: 1; -} - -.radial-list-center { - z-index: 0; -} - -.absolute-center { - position: absolute; - left: 50%; - top: 50%; - transform: translate(-50%, -50%); -} diff --git a/frontend/src/components/lobby/radial-list/RadialList.tsx b/frontend/src/components/lobby/radial-list/RadialList.tsx deleted file mode 100644 index 806cdd08..00000000 --- a/frontend/src/components/lobby/radial-list/RadialList.tsx +++ /dev/null @@ -1,64 +0,0 @@ -import React, { ReactNode } from 'react'; -import { CartesianCoords, RadialConfig } from './radial-math'; -import { offsetsFromCenter, CLOCKWISE, COUNTERCLOCKWISE } from './radial-math'; -import './RadialList.css'; -import { RadialListItem } from './RadialListItem'; - -type RadialListProps = { - items: Array<ReactNode>, - centerElement?: ReactNode, - radius?: number, // 120px by default - offsetDegrees?: number, // defaults to 0 = 12 o'clock - arc?: number, // defaults to 360 (full circle) - clockwise?: boolean, // defaults to true - itemWidth?: number, - itemHeight?: number, -}; - -export const RadialList = ({items, centerElement, radius = 120, offsetDegrees = 0, arc = 360, clockwise = true, itemWidth = 20, itemHeight = 20}: RadialListProps) => { - const diameter = radius * 2; - const containerStyle = { - width: diameter + itemWidth, - height: diameter + itemHeight, - }; - const direction = clockwise ? CLOCKWISE : COUNTERCLOCKWISE; - const radialConfig: RadialConfig = {radius, arc, offsetDegrees, direction}; - - return <div className='radial-list-container' style={containerStyle}> - <RadialListItems items={items} radialConfig={radialConfig}/> - <RadialListCenter centerElement={centerElement}/> - </div>; -}; - -type RadialListItemsProps = { - items: Array<React.ReactNode>, - radialConfig: RadialConfig, -}; - -const RadialListItems = ({items, radialConfig}: RadialListItemsProps) => { - const diameter = radialConfig.radius * 2; - const ulStyle = { - width: diameter, - height: diameter, - }; - const itemOffsets: Array<CartesianCoords> = offsetsFromCenter(items.length, radialConfig); - - return <ul className='radial-list absolute-center' style={ulStyle}> - {items.map((item, i) => (<RadialListItem - key={i} - item={item} - offsets={itemOffsets[i]} - />))} - </ul>; -}; - -type RadialListCenterProps = { - centerElement?: ReactNode, -}; - -const RadialListCenter = ({centerElement}: RadialListCenterProps) => { - if (!centerElement) { - return null; - } - return <div className='radial-list-center absolute-center'>{centerElement}</div>; -}; diff --git a/frontend/src/components/lobby/radial-list/RadialListItem.css b/frontend/src/components/lobby/radial-list/RadialListItem.css deleted file mode 100644 index 65bb9661..00000000 --- a/frontend/src/components/lobby/radial-list/RadialListItem.css +++ /dev/null @@ -1,11 +0,0 @@ -.radial-list-item { - display: block; - position: absolute; - top: 50%; - left: 50%; - margin: 0; - padding: 0; - list-style: unset; - transition: all 500ms ease-in-out; - z-index: 1; -} diff --git a/frontend/src/components/lobby/radial-list/RadialListItem.tsx b/frontend/src/components/lobby/radial-list/RadialListItem.tsx deleted file mode 100644 index 19a27638..00000000 --- a/frontend/src/components/lobby/radial-list/RadialListItem.tsx +++ /dev/null @@ -1,18 +0,0 @@ -import * as React from 'react'; -import { ReactNode } from 'react'; -import { CartesianCoords } from './radial-math'; -import './RadialListItem.css'; - -type RadialListItemProps = { - item: ReactNode, - offsets: CartesianCoords, -}; - -export const RadialListItem = ({item, offsets}: RadialListItemProps) => { - // Y-axis points down, hence the minus sign - const liStyle = { - transform: `translate(${offsets.x}px, ${-offsets.y}px) translate(-50%, -50%)`, - }; - - return <li className='radial-list-item' style={liStyle}>{item}</li>; -}; diff --git a/frontend/src/components/lobby/radial-list/radial-math.ts b/frontend/src/components/lobby/radial-list/radial-math.ts deleted file mode 100644 index f0f411f5..00000000 --- a/frontend/src/components/lobby/radial-list/radial-math.ts +++ /dev/null @@ -1,48 +0,0 @@ -export type CartesianCoords = { - x: number, - y: number, -} -type PolarCoords = { - radius: number, - angleDeg: number, -} - -const toRad = (deg: number) => deg * (Math.PI / 180); -const roundedProjection = (radius: number, thetaRad: number, trigFn: (angle: number) => number) => Math.round(radius * trigFn(thetaRad)); -const xProjection = (radius: number, thetaRad: number) => roundedProjection(radius, thetaRad, Math.cos); -const yProjection = (radius: number, thetaRad: number) => roundedProjection(radius, thetaRad, Math.sin); - -const toCartesian = ({radius, angleDeg}: PolarCoords): CartesianCoords => ({ - x: xProjection(radius, toRad(angleDeg)), - y: yProjection(radius, toRad(angleDeg)), -}); - -export type Direction = -1 | 1; -export const CLOCKWISE: Direction = -1; -export const COUNTERCLOCKWISE: Direction = 1; - -export type RadialConfig = { - radius: number, - arc: number, - offsetDegrees: number, - direction: Direction, -} -const DEFAULT_CONFIG: RadialConfig = { - radius: 120, - arc: 360, - offsetDegrees: 0, - direction: CLOCKWISE, -}; - -const DEFAULT_START = 90; // Up - -export function offsetsFromCenter(nbItems: number, radialConfig: RadialConfig = DEFAULT_CONFIG): Array<CartesianCoords> { - return Array.from({length: nbItems}, (v, i) => itemCartesianOffsets(i, nbItems, radialConfig)); -} - -function itemCartesianOffsets(index: number, nbItems: number, {radius, arc, direction, offsetDegrees}: RadialConfig): CartesianCoords { - const startAngle = DEFAULT_START + direction * offsetDegrees; - const angleStep = arc / nbItems; - const itemAngle = startAngle + direction * angleStep * index; - return toCartesian({radius, angleDeg: itemAngle}); -} diff --git a/frontend/src/components/lobby/round-table.png b/frontend/src/components/lobby/round-table.png Binary files differdeleted file mode 100644 index f277376d..00000000 --- a/frontend/src/components/lobby/round-table.png +++ /dev/null diff --git a/frontend/src/global-styles.css b/frontend/src/global-styles.css deleted file mode 100644 index e69de29b..00000000 --- a/frontend/src/global-styles.css +++ /dev/null diff --git a/frontend/src/index.tsx b/frontend/src/index.tsx deleted file mode 100644 index fce90915..00000000 --- a/frontend/src/index.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import '@blueprintjs/core/lib/css/blueprint.css'; -import React from 'react'; -import ReactDOM from 'react-dom'; -import { Provider } from 'react-redux'; -import { ConnectedRouter } from 'react-router-redux'; -import { Application } from './components/Application'; -import { INITIAL_STATE } from './reducers'; -import { configureStore } from './store'; - -const { store, history } = configureStore(INITIAL_STATE); - -const rootElement = document.getElementById('root'); -if (rootElement) { - ReactDOM.render(<Provider store={store}> - <ConnectedRouter history={history}> - <Application/> - </ConnectedRouter> - </Provider>, rootElement); -} else { - console.error('Element with ID "root" was not found, cannot bootstrap react app'); -} diff --git a/frontend/src/react-app-env.d.ts b/frontend/src/react-app-env.d.ts deleted file mode 100644 index 6431bc5f..00000000 --- a/frontend/src/react-app-env.d.ts +++ /dev/null @@ -1 +0,0 @@ -/// <reference types="react-scripts" /> diff --git a/frontend/src/reducers.ts b/frontend/src/reducers.ts deleted file mode 100644 index f885f642..00000000 --- a/frontend/src/reducers.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { routerReducer } from 'react-router-redux'; -import { combineReducers } from 'redux'; -import { ApiPlayer } from './api/model'; -import { CurrentGameState, EMPTY_CURRENT_GAME } from './redux/currentGame'; -import { createCurrentGameReducer } from './redux/currentGame'; -import { EMPTY_GAMES, GamesState } from './redux/games'; -import { createGamesReducer } from './redux/games'; -import { currentUserReducer } from './redux/user'; - -export type GlobalState = { - currentGame: CurrentGameState; - currentUser: ApiPlayer | null; - games: GamesState; - routing: any; -} - -export const INITIAL_STATE: GlobalState = { - currentGame: EMPTY_CURRENT_GAME, - currentUser: null, - games: EMPTY_GAMES, - routing: null, -}; - -export function createReducer() { - return combineReducers({ - currentGame: createCurrentGameReducer(), - currentUser: currentUserReducer, - games: createGamesReducer(), - routing: routerReducer, - }); -} diff --git a/frontend/src/redux/actions/all.ts b/frontend/src/redux/actions/all.ts deleted file mode 100644 index 57d2a443..00000000 --- a/frontend/src/redux/actions/all.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { GameAction } from './game'; -import { LobbyAction } from './lobby'; -import { PlayerAction } from './user'; - -export type Action = PlayerAction | LobbyAction | GameAction diff --git a/frontend/src/redux/actions/game.ts b/frontend/src/redux/actions/game.ts deleted file mode 100644 index b67ea1dc..00000000 --- a/frontend/src/redux/actions/game.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { ApiPlayerMove, ApiPlayerTurnInfo, ApiPreparedCard, ApiTable } from '../../api/model'; - -export const REQUEST_SAY_READY = 'GAME/REQUEST_SAY_READY'; -export const REQUEST_PREPARE_MOVE = 'GAME/REQUEST_PREPARE_MOVE'; -export const PLAYER_READY_RECEIVED = 'GAME/PLAYER_READY_RECEIVED'; -export const TABLE_UPDATE_RECEIVED = 'GAME/TABLE_UPDATE_RECEIVED'; -export const PREPARED_CARD_RECEIVED = 'GAME/PREPARED_CARD_RECEIVED'; -export const TURN_INFO_RECEIVED = 'GAME/TURN_INFO_RECEIVED'; - -export type SayReadyAction = { type: typeof REQUEST_SAY_READY }; -export type PrepareMoveAction = { type: typeof REQUEST_PREPARE_MOVE, move: ApiPlayerMove }; -export type PlayerReadyEvent = { type: typeof PLAYER_READY_RECEIVED, username: string }; -export type TableUpdateEvent = { type: typeof TABLE_UPDATE_RECEIVED, table: ApiTable }; -export type PreparedCardEvent = { type: typeof PREPARED_CARD_RECEIVED, card: ApiPreparedCard }; -export type TurnInfoEvent = { type: typeof TURN_INFO_RECEIVED, turnInfo: ApiPlayerTurnInfo }; - -export type GameAction = - SayReadyAction - | PrepareMoveAction - | PlayerReadyEvent - | TableUpdateEvent - | PreparedCardEvent - | TurnInfoEvent; - -export const actions = { - sayReady: () => ({ type: REQUEST_SAY_READY }), - prepareMove: (move: ApiPlayerMove) => ({ type: REQUEST_PREPARE_MOVE, move }), - receivePlayerReady: (username: string) => ({ type: PLAYER_READY_RECEIVED, username }), - receiveTableUpdate: (table: ApiTable) => ({ type: TABLE_UPDATE_RECEIVED, table }), - receivePreparedCard: (card: ApiPreparedCard) => ({ type: PREPARED_CARD_RECEIVED, card }), - receiveTurnInfo: (turnInfo: ApiPlayerTurnInfo) => ({ type: TURN_INFO_RECEIVED, turnInfo }), -}; diff --git a/frontend/src/redux/actions/lobby.ts b/frontend/src/redux/actions/lobby.ts deleted file mode 100644 index c121b022..00000000 --- a/frontend/src/redux/actions/lobby.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { ApiLobby } from '../../api/model'; - -export const UPDATE_GAMES = 'GAMES/UPDATE_GAMES'; -export const REQUEST_CREATE_GAME = 'GAMES/REQUEST_CREATE_GAME'; -export const REQUEST_JOIN_GAME = 'GAMES/REQUEST_JOIN_GAME'; -export const REQUEST_START_GAME = 'GAMES/REQUEST_START_GAME'; -export const ENTER_LOBBY = 'GAMES/ENTER_LOBBY'; -export const ENTER_GAME = 'GAMES/ENTER_GAME'; - -export type UpdateGamesAction = { type: typeof UPDATE_GAMES, games: ApiLobby[]}; -export type RequestCreateGameAction = { type: typeof REQUEST_CREATE_GAME, gameName: string }; -export type RequestJoinGameAction = { type: typeof REQUEST_JOIN_GAME, gameId: number }; -export type RequestStartGameAction = { type: typeof REQUEST_START_GAME }; -export type EnterLobbyAction = { type: typeof ENTER_LOBBY, gameId: number }; -export type EnterGameAction = { type: typeof ENTER_GAME, gameId: number }; - -export type LobbyAction = - | UpdateGamesAction - | RequestCreateGameAction - | RequestJoinGameAction - | RequestStartGameAction - | EnterLobbyAction - | EnterGameAction; - -export const actions = { - updateGames: (games: ApiLobby[]): UpdateGamesAction => ({ type: UPDATE_GAMES, games }), - requestJoinGame: (gameId: number): RequestJoinGameAction => ({ type: REQUEST_JOIN_GAME, gameId }), - requestCreateGame: (gameName: string): RequestCreateGameAction => ({ type: REQUEST_CREATE_GAME, gameName }), - requestStartGame: (): RequestStartGameAction => ({ type: REQUEST_START_GAME }), - enterLobby: (gameId: number): EnterLobbyAction => ({ type: ENTER_LOBBY, gameId }), - enterGame: (gameId: number): EnterGameAction => ({ type: ENTER_GAME, gameId }), -}; diff --git a/frontend/src/redux/actions/user.ts b/frontend/src/redux/actions/user.ts deleted file mode 100644 index 29c85707..00000000 --- a/frontend/src/redux/actions/user.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { Map } from 'immutable'; -import { ApiPlayer } from '../../api/model'; - -export const REQUEST_CHOOSE_USERNAME = 'USER/REQUEST_CHOOSE_USERNAME'; -export const SET_CURRENT_PLAYER = 'USER/SET_CURRENT_PLAYER'; -export const UPDATE_PLAYERS = 'USER/UPDATE_PLAYERS'; - -export type RequestChooseUsernameAction = { type: typeof REQUEST_CHOOSE_USERNAME, username: string }; -export type SetCurrentPlayerAction = { type: typeof SET_CURRENT_PLAYER, player: ApiPlayer }; -export type UpdatePlayersAction = { type: typeof UPDATE_PLAYERS, players: Map<string, ApiPlayer> }; - -export type PlayerAction = RequestChooseUsernameAction | SetCurrentPlayerAction | UpdatePlayersAction; - -export const actions = { - chooseUsername: (username: string): RequestChooseUsernameAction => ({ type: REQUEST_CHOOSE_USERNAME, username }), - setCurrentPlayer: (player: ApiPlayer): SetCurrentPlayerAction => ({ type: SET_CURRENT_PLAYER, player }), -}; diff --git a/frontend/src/redux/currentGame.ts b/frontend/src/redux/currentGame.ts deleted file mode 100644 index 5e015d60..00000000 --- a/frontend/src/redux/currentGame.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { combineReducers } from 'redux'; -import { ApiPlayerTurnInfo, ApiTable } from '../api/model'; -import { GlobalState } from '../reducers'; -import { Action } from './actions/all'; -import { TABLE_UPDATE_RECEIVED, TURN_INFO_RECEIVED } from './actions/game'; - -export type CurrentGameState = { - turnInfo: ApiPlayerTurnInfo | null; - table: ApiTable | null; -} - -export const EMPTY_CURRENT_GAME: CurrentGameState = { - turnInfo: null, - table: null, -}; - -export function createCurrentGameReducer() { - return combineReducers({ - turnInfo: turnInfoReducer, - table: tableUpdatesReducer, - }); -} - -const turnInfoReducer = (state: ApiPlayerTurnInfo | null = null, action: Action) => { - switch (action.type) { - case TURN_INFO_RECEIVED: - return action.turnInfo; - case TABLE_UPDATE_RECEIVED: - return null; - default: - return state; - } -}; - -const tableUpdatesReducer = (state: ApiTable | null = null, action: Action) => { - switch (action.type) { - case TURN_INFO_RECEIVED: - return action.turnInfo.table; - case TABLE_UPDATE_RECEIVED: - return action.table; - default: - return state; - } -}; - -export const getCurrentTurnInfo = (state: GlobalState): ApiPlayerTurnInfo | null => state.currentGame.turnInfo; diff --git a/frontend/src/redux/games.ts b/frontend/src/redux/games.ts deleted file mode 100644 index 4df2f1da..00000000 --- a/frontend/src/redux/games.ts +++ /dev/null @@ -1,56 +0,0 @@ -import { List, Map } from 'immutable'; -import { combineReducers } from 'redux'; -import { ApiLobby } from '../api/model'; -import { GlobalState } from '../reducers'; -import { Action } from './actions/all'; -import { ENTER_LOBBY, UPDATE_GAMES } from './actions/lobby'; - -export type GamesState = { - all: Map<string, ApiLobby>, - current: string | null -}; - -export const EMPTY_GAMES: GamesState = { - all: Map(), - current: null, -}; - -export const createGamesReducer = () => { - return combineReducers({ - all: allGamesReducer, - current: currentGameIdReducer - }) -}; - -export const allGamesReducer = (state: Map<string, ApiLobby> = Map(), action: Action) => { - switch (action.type) { - case UPDATE_GAMES: - const newGames = mapify(action.games); - return state.merge(newGames); - default: - return state; - } -}; - -function mapify(games: ApiLobby[]): Map<string, ApiLobby> { - let newGames: {[id:string]:ApiLobby} = {}; - games.forEach(g => newGames[`${g.id}`] = g); - return Map(newGames); -} - -export const currentGameIdReducer = (state: string | null = null, action: Action) => { - switch (action.type) { - case ENTER_LOBBY: - return `${action.gameId}`; - default: - return state; - } -}; - -export const getAllGames = (state: GlobalState): List<ApiLobby> => state.games.all.toList(); -export const getCurrentGame = (state: GlobalState): ApiLobby | null => { - if (state.games.current == null) { - return null; - } - return state.games.all.get(state.games.current) || null; -}; diff --git a/frontend/src/redux/user.ts b/frontend/src/redux/user.ts deleted file mode 100644 index 2cc25cc0..00000000 --- a/frontend/src/redux/user.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { ApiPlayer } from '../api/model'; -import { GlobalState } from '../reducers'; -import { Action } from './actions/all'; -import { SET_CURRENT_PLAYER } from './actions/user'; -import { getCurrentGame } from './games'; - -export type User = { - username: string, - displayName: string, -} - -export const currentUserReducer = (state: User | null = null, action: Action) => { - switch (action.type) { - case SET_CURRENT_PLAYER: - return { - username: action.player.username, - displayName: action.player.displayName - }; - default: - return state; - } -}; - -export function getCurrentUser(state: GlobalState): User | null { - return state.currentUser -} - -export function getCurrentPlayer(state: GlobalState): ApiPlayer | null { - if (state.currentUser == null) { - return null; - } - let game = getCurrentGame(state); - if (game == null) { - return null; - } - for (let i = 0; i < game.players.length; i++) { - let player = game.players[i]; - if (player.username === state.currentUser.username) { - return player; - } - } - return null; -} diff --git a/frontend/src/sagas.ts b/frontend/src/sagas.ts deleted file mode 100644 index 03c71b63..00000000 --- a/frontend/src/sagas.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { SagaIterator } from 'redux-saga'; -import { call, fork } from 'redux-saga/effects'; -import { connectToGame, SevenWondersSession } from './api/sevenWondersApi'; -import { errorHandlingSaga } from './sagas/errors'; -import { gameSaga } from './sagas/game'; -import { gameBrowserSaga } from './sagas/gameBrowser'; -import { homeSaga } from './sagas/home'; -import { lobbySaga } from './sagas/lobby'; - -export function* rootSaga(): SagaIterator { - let sevenWondersSession: SevenWondersSession; - try { - sevenWondersSession = yield call(connectToGame); - } catch (error) { - console.error('Could not connect to socket', error); - return; - } - yield fork(errorHandlingSaga, sevenWondersSession); - yield fork(homeSaga, sevenWondersSession); - yield fork(gameBrowserSaga, sevenWondersSession); - yield fork(lobbySaga, sevenWondersSession); - yield fork(gameSaga, sevenWondersSession); -} diff --git a/frontend/src/sagas/errors.ts b/frontend/src/sagas/errors.ts deleted file mode 100644 index b27dfa95..00000000 --- a/frontend/src/sagas/errors.ts +++ /dev/null @@ -1,36 +0,0 @@ -import {Toaster} from '@blueprintjs/core'; -import {Channel, eventChannel} from 'redux-saga'; -import {apply, cancelled, take} from 'redux-saga/effects'; -import {ApiError} from '../api/model'; -import {SevenWondersSession} from '../api/sevenWondersApi'; - -const ErrorToaster = Toaster.create(); - -export function* errorHandlingSaga(session: SevenWondersSession): any { - const errorChannel: Channel<ApiError> = yield eventChannel(session.watchErrors()); - try { - while (true) { - const error: ApiError = yield take(errorChannel); - yield* handleOneError(error); - } - } finally { - if (yield cancelled()) { - console.log('Error management saga cancelled'); - yield apply(errorChannel, errorChannel.close); - } - } -} - -function* handleOneError(err: ApiError): any { - console.error('Error received on web socket channel', err); - const msg = buildMsg(err); - yield apply(ErrorToaster, ErrorToaster.show, [{ intent: 'danger', icon: 'error', message: msg }]); -} - -function buildMsg(err: ApiError): string { - if (err.details.length > 0) { - return err.details.map(d => d.message).join('\n'); - } else { - return err.message; - } -} diff --git a/frontend/src/sagas/game.ts b/frontend/src/sagas/game.ts deleted file mode 100644 index a60ab2d3..00000000 --- a/frontend/src/sagas/game.ts +++ /dev/null @@ -1,81 +0,0 @@ -import { eventChannel, SagaIterator } from 'redux-saga'; -import { apply, call, put, take } from 'redux-saga/effects'; -import { ApiPlayerTurnInfo, ApiPreparedCard, ApiTable } from '../api/model'; -import { SevenWondersSession } from '../api/sevenWondersApi'; -import { actions, REQUEST_PREPARE_MOVE, REQUEST_SAY_READY } from '../redux/actions/game'; -import { ENTER_GAME } from '../redux/actions/lobby'; - -function* watchPlayerReady(session: SevenWondersSession, gameId: number) { - const channel = yield eventChannel(session.watchPlayerReady(gameId)); - try { - while (true) { - const username = yield take(channel); - yield put(actions.receivePlayerReady(username)); - } - } finally { - yield apply(channel, channel.close); - } -} - -function* watchTableUpdates(session: SevenWondersSession, gameId: number) { - const channel = yield eventChannel(session.watchTableUpdates(gameId)); - try { - while (true) { - const table: ApiTable = yield take(channel); - yield put(actions.receiveTableUpdate(table)); - } - } finally { - yield apply(channel, channel.close); - } -} - -function* watchPreparedCards(session: SevenWondersSession, gameId: number) { - const channel = yield eventChannel(session.watchPreparedCards(gameId)); - try { - while (true) { - const preparedCard: ApiPreparedCard = yield take(channel); - yield put(actions.receivePreparedCard(preparedCard)); - } - } finally { - yield apply(channel, channel.close); - } -} - -function* sayReady(session: SevenWondersSession): SagaIterator { - while (true) { - yield take(REQUEST_SAY_READY); - yield apply(session, session.sayReady); - } -} - -function* prepareMove(session: SevenWondersSession): SagaIterator { - while (true) { - let action = yield take(REQUEST_PREPARE_MOVE); - yield apply(session, session.prepareMove, [action.move]); - } -} - -function* watchTurnInfo(session: SevenWondersSession) { - const channel = yield eventChannel(session.watchTurnInfo()); - try { - while (true) { - const turnInfo: ApiPlayerTurnInfo = yield take(channel); - yield put(actions.receiveTurnInfo(turnInfo)); - } - } finally { - yield apply(channel, channel.close); - } -} - -export function* gameSaga(session: SevenWondersSession): SagaIterator { - const { gameId } = yield take(ENTER_GAME); - console.log('Entered game!', gameId); - yield [ - call(watchPlayerReady, session, gameId), - call(watchTableUpdates, session, gameId), - call(watchPreparedCards, session, gameId), - call(sayReady, session), - call(prepareMove, session), - call(watchTurnInfo, session) - ]; -} diff --git a/frontend/src/sagas/gameBrowser.ts b/frontend/src/sagas/gameBrowser.ts deleted file mode 100644 index 868ec471..00000000 --- a/frontend/src/sagas/gameBrowser.ts +++ /dev/null @@ -1,55 +0,0 @@ -import { push } from 'react-router-redux'; -import { eventChannel, SagaIterator } from 'redux-saga'; -import { all, apply, call, put, take } from 'redux-saga/effects'; -import { ApiLobby } from '../api/model'; -import { SevenWondersSession } from '../api/sevenWondersApi'; -import { actions as gameActions, REQUEST_CREATE_GAME, REQUEST_JOIN_GAME } from '../redux/actions/lobby'; - -function* watchGames(session: SevenWondersSession): any { - const gamesChannel = yield eventChannel(session.watchGames()); - try { - while (true) { - const gameList = yield take(gamesChannel); - yield put(gameActions.updateGames(gameList)); - } - } finally { - yield apply(gamesChannel, gamesChannel.close); - } -} - -function* watchLobbyJoined(session: SevenWondersSession): any { - const joinedLobbyChannel = yield eventChannel(session.watchLobbyJoined()); - try { - const joinedLobby: ApiLobby = yield take(joinedLobbyChannel); - yield put(gameActions.updateGames([joinedLobby])); - yield put(gameActions.enterLobby(joinedLobby.id)); - yield put(push(`/lobby/${joinedLobby.id}`)); - } finally { - yield apply(joinedLobbyChannel, joinedLobbyChannel.close); - } -} - -function* createGame(session: SevenWondersSession): SagaIterator { - while (true) { - const { gameName } = yield take(REQUEST_CREATE_GAME); - // $FlowFixMe - yield apply(session, session.createGame, [gameName]); - } -} - -function* joinGame(session: SevenWondersSession): SagaIterator { - while (true) { - const { gameId } = yield take(REQUEST_JOIN_GAME); - // $FlowFixMe - yield apply(session, session.joinGame, [gameId]); - } -} - -export function* gameBrowserSaga(session: SevenWondersSession): SagaIterator { - yield all([ - call(watchGames, session), - call(watchLobbyJoined, session), - call(createGame, session), - call(joinGame, session), - ]); -} diff --git a/frontend/src/sagas/home.ts b/frontend/src/sagas/home.ts deleted file mode 100644 index 585c536e..00000000 --- a/frontend/src/sagas/home.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { push } from 'react-router-redux'; -import { eventChannel, SagaIterator } from 'redux-saga'; -import { all, apply, call, put, take } from 'redux-saga/effects'; -import { ApiPlayer } from '../api/model'; -import { SevenWondersSession } from '../api/sevenWondersApi'; -import { actions, REQUEST_CHOOSE_USERNAME } from '../redux/actions/user'; - -function* sendUsername(session: SevenWondersSession): SagaIterator { - while (true) { - const { username } = yield take(REQUEST_CHOOSE_USERNAME); - // $FlowFixMe - yield apply(session, session.chooseName, [username]); - } -} - -function* validateUsername(session: SevenWondersSession): any { - const usernameChannel = yield eventChannel(session.watchNameChoice()); - while (true) { - const user: ApiPlayer = yield take(usernameChannel); - yield put(actions.setCurrentPlayer(user)); - yield apply(usernameChannel, usernameChannel.close); - yield put(push('/games')); - } -} - -export function* homeSaga(session: SevenWondersSession): SagaIterator { - yield all([call(sendUsername, session), call(validateUsername, session)]); -} diff --git a/frontend/src/sagas/lobby.ts b/frontend/src/sagas/lobby.ts deleted file mode 100644 index 09360b02..00000000 --- a/frontend/src/sagas/lobby.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { push } from 'react-router-redux'; -import { Channel, eventChannel, SagaIterator } from 'redux-saga'; -import { all, apply, call, put, take } from 'redux-saga/effects'; -import { SevenWondersSession } from '../api/sevenWondersApi'; -import { actions as gameActions, ENTER_LOBBY, REQUEST_START_GAME } from '../redux/actions/lobby'; - -function* watchLobbyUpdates(session: SevenWondersSession, lobbyId: number): any { - const lobbyUpdatesChannel: Channel<Object> = yield eventChannel(session.watchLobbyUpdated(lobbyId)); - try { - while (true) { - const lobby = yield take(lobbyUpdatesChannel); - yield put(gameActions.updateGames([lobby])); - } - } finally { - yield apply(lobbyUpdatesChannel, lobbyUpdatesChannel.close); - } -} - -function* watchGameStart(session: SevenWondersSession, lobbyId: number): any { - const gameStartedChannel = yield eventChannel(session.watchGameStarted(lobbyId)); - try { - yield take(gameStartedChannel); - yield put(gameActions.enterGame(lobbyId)); - yield put(push(`/game/${lobbyId}`)); - } finally { - yield apply(gameStartedChannel, gameStartedChannel.close); - } -} - -function* startGame(session: SevenWondersSession): SagaIterator { - while (true) { - yield take(REQUEST_START_GAME); - yield apply(session, session.startGame); - } -} - -export function* lobbySaga(session: SevenWondersSession): SagaIterator { - const { gameId } = yield take(ENTER_LOBBY); - yield all([ - call(watchLobbyUpdates, session, gameId), - call(watchGameStart, session, gameId), - call(startGame, session) - ]); -} diff --git a/frontend/src/setupProxy.js b/frontend/src/setupProxy.js deleted file mode 100644 index 88831e6e..00000000 --- a/frontend/src/setupProxy.js +++ /dev/null @@ -1,8 +0,0 @@ -const proxy = require('http-proxy-middleware'); - -module.exports = function(app) { - app.use(proxy('/seven-wonders-websocket', { - "target": "http://localhost:8080", - "ws": true - })); -}; diff --git a/frontend/src/store.ts b/frontend/src/store.ts deleted file mode 100644 index 54a65509..00000000 --- a/frontend/src/store.ts +++ /dev/null @@ -1,27 +0,0 @@ -import createHistory from 'history/createBrowserHistory'; -import { routerMiddleware } from 'react-router-redux'; -import { applyMiddleware, createStore } from 'redux'; -import { composeWithDevTools } from 'redux-devtools-extension'; -import createSagaMiddleware from 'redux-saga'; -import { GlobalState } from './reducers'; -import { createReducer } from './reducers'; -import { rootSaga } from './sagas'; - -export function configureStore(initialState: GlobalState) { - const sagaMiddleware = createSagaMiddleware(); - - const history = createHistory(); - - const middlewares = [sagaMiddleware, routerMiddleware(history)]; - - const enhancers = [applyMiddleware(...middlewares)]; - - const store = createStore(createReducer(), initialState, composeWithDevTools(...enhancers)); - - sagaMiddleware.run(rootSaga); - - return { - store, - history, - }; -} |