front: gamestate polling + gameproposal tab
- gamestate controller - css for gameproposal tab
This commit is contained in:
		
							parent
							
								
									6c885bfa68
								
							
						
					
					
						commit
						72daeddb9d
					
				@ -0,0 +1,37 @@
 | 
				
			|||||||
 | 
					package djmil.cordacheckers.api;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import java.util.List;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import org.springframework.beans.factory.annotation.Autowired;
 | 
				
			||||||
 | 
					import org.springframework.http.ResponseEntity;
 | 
				
			||||||
 | 
					import org.springframework.security.core.annotation.AuthenticationPrincipal;
 | 
				
			||||||
 | 
					import org.springframework.web.bind.annotation.GetMapping;
 | 
				
			||||||
 | 
					import org.springframework.web.bind.annotation.RequestMapping;
 | 
				
			||||||
 | 
					import org.springframework.web.bind.annotation.RestController;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import djmil.cordacheckers.cordaclient.CordaClient;
 | 
				
			||||||
 | 
					import djmil.cordacheckers.cordaclient.dao.GameState;
 | 
				
			||||||
 | 
					import djmil.cordacheckers.user.HoldingIdentityResolver;
 | 
				
			||||||
 | 
					import djmil.cordacheckers.user.User;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@RestController
 | 
				
			||||||
 | 
					@RequestMapping("api/gamestate")
 | 
				
			||||||
 | 
					public class GameStateController {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Autowired
 | 
				
			||||||
 | 
					    CordaClient cordaClient;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Autowired
 | 
				
			||||||
 | 
					    HoldingIdentityResolver holdingIdentityResolver;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @GetMapping
 | 
				
			||||||
 | 
					    public ResponseEntity<List<GameState>> gameStateList(
 | 
				
			||||||
 | 
					        @AuthenticationPrincipal User player
 | 
				
			||||||
 | 
					    ) {
 | 
				
			||||||
 | 
					        final List<GameState> gsList = cordaClient.gameStateList(player.getHoldingIdentity());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return ResponseEntity.ok(gsList);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -1,23 +1,51 @@
 | 
				
			|||||||
import './App.css';
 | 
					import './App.css';
 | 
				
			||||||
import Leaderboard from "./Leaderboard";
 | 
					import React, { useState, useEffect, useCallback } from 'react';
 | 
				
			||||||
import React from 'react';
 | 
					 | 
				
			||||||
import {
 | 
					import {
 | 
				
			||||||
  BrowserRouter,
 | 
					  BrowserRouter,
 | 
				
			||||||
  Routes, //replaces "Switch" used till v5
 | 
					  Routes, //replaces "Switch" used till v5
 | 
				
			||||||
  Route,
 | 
					  Route,
 | 
				
			||||||
} from "react-router-dom";
 | 
					} from "react-router-dom";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import Header from "./Header"
 | 
					import Header from "./Header"
 | 
				
			||||||
 | 
					import Leaderboard from "./Leaderboard";
 | 
				
			||||||
 | 
					import GameProposal from "./GameProposal";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function App() { 
 | 
					function App() { 
 | 
				
			||||||
 | 
					  const [games, setGames] = useState(null);
 | 
				
			||||||
 | 
					  const [polling, setPolling] = useState(false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const pollGames = useCallback(() => { 
 | 
				
			||||||
 | 
					    console.log('start polling..');
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    if (polling) {
 | 
				
			||||||
 | 
					      console.log(' ..already in progress');
 | 
				
			||||||
 | 
					      return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    setPolling(true);
 | 
				
			||||||
 | 
					    fetch('/api/gamestate')
 | 
				
			||||||
 | 
					      .then(response => response.json())
 | 
				
			||||||
 | 
					      .then(data => {
 | 
				
			||||||
 | 
					        console.log('poooled');
 | 
				
			||||||
 | 
					        setGames(data);
 | 
				
			||||||
 | 
					        setPolling(false);
 | 
				
			||||||
 | 
					      })
 | 
				
			||||||
 | 
					      .catch(err => console.log(err.message));
 | 
				
			||||||
 | 
					  }, [polling]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  useEffect(() => {
 | 
				
			||||||
 | 
					    const timer = setInterval(pollGames(), 35 * 1000);
 | 
				
			||||||
 | 
					    return clearInterval(timer);
 | 
				
			||||||
 | 
					  }, [pollGames])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return (
 | 
					  return (
 | 
				
			||||||
    <div className="App">
 | 
					    <div className="App">
 | 
				
			||||||
      <BrowserRouter>
 | 
					      <BrowserRouter>
 | 
				
			||||||
        <Header/>
 | 
					        <Header/>
 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        <div className="Container">
 | 
					        <div className="Container">
 | 
				
			||||||
          <Routes>
 | 
					          <Routes>
 | 
				
			||||||
            <Route path="/leaderboard" element={<Leaderboard/>} />
 | 
					            <Route path="/leaderboard" element={<Leaderboard/>} />
 | 
				
			||||||
 | 
					            <Route path="/gameproposal" element={<GameProposal games={games}/>} />
 | 
				
			||||||
          </Routes>
 | 
					          </Routes>
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										26
									
								
								webapp/src/GameProposal.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								webapp/src/GameProposal.css
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,26 @@
 | 
				
			|||||||
 | 
					.GameProposal {
 | 
				
			||||||
 | 
					    display: flex;
 | 
				
			||||||
 | 
					    flex-direction: column;
 | 
				
			||||||
 | 
					    justify-content: center; 
 | 
				
			||||||
 | 
					    align-items: center;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.GameProposal .li {
 | 
				
			||||||
 | 
					    width: 50%;
 | 
				
			||||||
 | 
					    border: 1px solid black;
 | 
				
			||||||
 | 
					    margin-bottom: 5px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.GameProposal .li p {
 | 
				
			||||||
 | 
					    margin: 5px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.separator {
 | 
				
			||||||
 | 
					    width: 20%; 
 | 
				
			||||||
 | 
					    /* height: 20px;  */
 | 
				
			||||||
 | 
					    border-bottom: 1px dotted black; 
 | 
				
			||||||
 | 
					    text-align: center;
 | 
				
			||||||
 | 
					    font-size: 8px;
 | 
				
			||||||
 | 
					    padding-left: 50%;
 | 
				
			||||||
 | 
					    margin-bottom: 7px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										52
									
								
								webapp/src/GameProposal.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								webapp/src/GameProposal.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,52 @@
 | 
				
			|||||||
 | 
					import React from 'react';
 | 
				
			||||||
 | 
					import './GameProposal.css';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const State = {
 | 
				
			||||||
 | 
						WaitForOpponent: "GAME_PROPOSAL_WAIT_FOR_OPPONENT",
 | 
				
			||||||
 | 
						WaitForYou:      "GAME_PROPOSAL_WAIT_FOR_YOU",
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const GameProposal = ({games}) => {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (games == null)
 | 
				
			||||||
 | 
					    return <p>Loading..</p>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // for (const [key, value] of Object.entries(games))
 | 
				
			||||||
 | 
					  //   console.log(key, value);
 | 
				
			||||||
 | 
					   
 | 
				
			||||||
 | 
					  const waitForYou = games
 | 
				
			||||||
 | 
					    .filter(game => game.status === State.WaitForYou)
 | 
				
			||||||
 | 
					    .map(game => { return (
 | 
				
			||||||
 | 
					      <div class="li" key={game.uuid}>
 | 
				
			||||||
 | 
					        <p>
 | 
				
			||||||
 | 
					          from {game.opponentName}, opponentColor {game.opponentColor}<br/>
 | 
				
			||||||
 | 
					          <q color="grey">{game.message}</q>
 | 
				
			||||||
 | 
					        </p>
 | 
				
			||||||
 | 
					      </div>
 | 
				
			||||||
 | 
					    )});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const WaitForOpponent = games
 | 
				
			||||||
 | 
					    .filter(game => game.status === State.WaitForOpponent)
 | 
				
			||||||
 | 
					    .map(game => { return (
 | 
				
			||||||
 | 
					      <div class="li" key={game.uuid}>
 | 
				
			||||||
 | 
					        <p> 
 | 
				
			||||||
 | 
					          to {game.opponentName}, opponentColor ⛀ ⛂{game.opponentColor}<br/>
 | 
				
			||||||
 | 
					          <q color="grey">{game.message}</q>
 | 
				
			||||||
 | 
					        </p>
 | 
				
			||||||
 | 
					      </div>
 | 
				
			||||||
 | 
					    )});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return (
 | 
				
			||||||
 | 
					    <p className="GameProposal">
 | 
				
			||||||
 | 
					      {waitForYou}
 | 
				
			||||||
 | 
					      {WaitForOpponent.length > 0 && 
 | 
				
			||||||
 | 
					        <div class="separator">
 | 
				
			||||||
 | 
					          waiting for opponent ({WaitForOpponent.length})
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      {WaitForOpponent}
 | 
				
			||||||
 | 
					    </p>
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default GameProposal;
 | 
				
			||||||
							
								
								
									
										3
									
								
								webapp/src/Header.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								webapp/src/Header.css
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,3 @@
 | 
				
			|||||||
 | 
					p {
 | 
				
			||||||
 | 
					    margin-bottom: 30px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -1,15 +1,17 @@
 | 
				
			|||||||
import { Link } from "react-router-dom";
 | 
					import { Link } from "react-router-dom";
 | 
				
			||||||
 | 
					import './Header.css';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default function Header() {
 | 
					export default function Header() {
 | 
				
			||||||
    return (
 | 
					    return (
 | 
				
			||||||
      <div>
 | 
					      <p>
 | 
				
			||||||
        <h1>CordaCheckers</h1>
 | 
					        <h1>CordaCheckers</h1>
 | 
				
			||||||
        <nav>
 | 
					        <nav>
 | 
				
			||||||
          <Link to="/leaderboard">Leaderboard</Link> {"| "}
 | 
					          <Link to="/leaderboard">Leaderboard</Link> {"| "}
 | 
				
			||||||
          <Link to="/gameproposal">Game Proposal</Link> {"| "}
 | 
					          <Link to="/gameproposal">Game Proposal</Link> {"| "}
 | 
				
			||||||
          <Link to="/game">Games</Link> {"| "}
 | 
					          <Link to="/game">Active Games</Link> {"| "}
 | 
				
			||||||
 | 
					          <Link to="/archive">Archive</Link> {"| "}
 | 
				
			||||||
          <Link to="about">About</Link>
 | 
					          <Link to="about">About</Link>
 | 
				
			||||||
        </nav>
 | 
					        </nav>
 | 
				
			||||||
      </div>
 | 
					      </p>
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@ -2,5 +2,4 @@
 | 
				
			|||||||
  display: flex;
 | 
					  display: flex;
 | 
				
			||||||
  justify-content: center;
 | 
					  justify-content: center;
 | 
				
			||||||
  align-items: center;
 | 
					  align-items: center;
 | 
				
			||||||
  margin-top: 25px
 | 
					}
 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
				
			|||||||
@ -1,16 +1,5 @@
 | 
				
			|||||||
import React, { useState, useEffect } from 'react';
 | 
					import React, { useState, useEffect } from 'react';
 | 
				
			||||||
import './Leaderboard.css';
 | 
					import './Leaderboard.css';
 | 
				
			||||||
//const Leaderboard = ({hashmap}) => {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// var listItems = Object.keys(hashmap).map(playerName => {
 | 
					 | 
				
			||||||
//   var rank = hashmap[playerName];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
//   return <li key={playerName}>
 | 
					 | 
				
			||||||
//     {playerName}: played {rank.gamesPlayed}, won {rank.gamesWon}, draw {rank.gamesDraw}
 | 
					 | 
				
			||||||
//   </li>
 | 
					 | 
				
			||||||
// });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// return <ul>{listItems}</ul>;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
const Leaderboard = () => {
 | 
					const Leaderboard = () => {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -28,7 +17,16 @@ const Leaderboard = () => {
 | 
				
			|||||||
  }, []);
 | 
					  }, []);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (data == null) 
 | 
					  if (data == null) 
 | 
				
			||||||
    return <span>Loading...</span>
 | 
					    return <p>Loading...</p>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//  var listItems = Object.keys(data).map(playerName => {
 | 
				
			||||||
 | 
					//    var rank = data[playerName];
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//    return <li key={playerName}>
 | 
				
			||||||
 | 
					//      {playerName}: played {rank.gamesPlayed}, won {rank.gamesWon}, draw {rank.gamesDraw}
 | 
				
			||||||
 | 
					//    </li>
 | 
				
			||||||
 | 
					//  });
 | 
				
			||||||
 | 
					//  return <ul>{listItems}</ul>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const tableRows = Object.keys(data).map(playerName => {
 | 
					  const tableRows = Object.keys(data).map(playerName => {
 | 
				
			||||||
    var rank = data[playerName];
 | 
					    var rank = data[playerName];
 | 
				
			||||||
@ -48,7 +46,7 @@ const Leaderboard = () => {
 | 
				
			|||||||
      <table>
 | 
					      <table>
 | 
				
			||||||
        <thead>
 | 
					        <thead>
 | 
				
			||||||
          <tr>
 | 
					          <tr>
 | 
				
			||||||
            <th>Name</th>
 | 
					            <th></th>
 | 
				
			||||||
            <th>Played</th>
 | 
					            <th>Played</th>
 | 
				
			||||||
            <th>Won</th>
 | 
					            <th>Won</th>
 | 
				
			||||||
            <th>Draw</th>
 | 
					            <th>Draw</th>
 | 
				
			||||||
@ -62,5 +60,4 @@ const Leaderboard = () => {
 | 
				
			|||||||
  );
 | 
					  );
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
export default Leaderboard;
 | 
					export default Leaderboard;
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user