connect league create page to backend

This commit is contained in:
Elijah Steres 2021-01-14 01:30:31 -05:00
parent 8f610eaa2e
commit c837a826c0
5 changed files with 92 additions and 22 deletions

View File

@ -64,6 +64,7 @@ def init_league_db(league):
c.execute(teams_table_check_string) c.execute(teams_table_check_string)
for team in league.teams_in_league(): for team in league.teams_in_league():
print(team)
c.execute("INSERT INTO teams (name) VALUES (?)", (team.name,)) c.execute("INSERT INTO teams (name) VALUES (?)", (team.name,))
player_string = "INSERT INTO stats (name, team_name) VALUES (?,?)" player_string = "INSERT INTO stats (name, team_name) VALUES (?,?)"

View File

@ -14,7 +14,7 @@ class league_structure(object):
self.owner = None self.owner = None
def setup(self, league_dic, division_games = 1, inter_division_games = 1, inter_league_games = 1, games_per_hour = 2): def setup(self, league_dic, division_games = 1, inter_division_games = 1, inter_league_games = 1, games_per_hour = 2):
self.league = league_dic #key: subleague, value: {division : team_name} self.league = league_dic # { subleague name : { division name : [team object] } }
self.constraints = { self.constraints = {
"division_games" : division_games, "division_games" : division_games,
"inter_div_games" : inter_division_games, "inter_div_games" : inter_division_games,

View File

@ -1,4 +1,6 @@
import asyncio, time, datetime, games, json, threading, jinja2, leagues, os import asyncio, time, datetime, games, json, threading, jinja2, leagues, os, leagues
from leagues import league_structure
from league_storage import league_exists
from flask import Flask, url_for, Response, render_template, request, jsonify, send_from_directory, abort from flask import Flask, url_for, Response, render_template, request, jsonify, send_from_directory, abort
from flask_socketio import SocketIO, emit from flask_socketio import SocketIO, emit
import database as db import database as db
@ -20,7 +22,7 @@ def serve(path):
### API ### API
@app.route('/api/teams/search') @app.route('/api/teams/search')
def searchteams(): def search_teams():
query = request.args.get('query') query = request.args.get('query')
page_len = int(request.args.get('page_len')) page_len = int(request.args.get('page_len'))
page_num = int(request.args.get('page_num')) page_num = int(request.args.get('page_num'))
@ -29,7 +31,7 @@ def searchteams():
abort(400, "A query term is required") abort(400, "A query term is required")
result = db.search_teams(query) result = db.search_teams(query)
if page_len is not None: #pagination should probably be doen in the sqlite query but this will do for now if page_len is not None: #pagination should probably be done in the sqlite query but this will do for now
if page_num is None: if page_num is None:
abort(400, "A page_len argument must be accompanied by a page_num argument") abort(400, "A page_len argument must be accompanied by a page_num argument")
result = result[page_num*page_len : (page_num + 1)*page_len] result = result[page_num*page_len : (page_num + 1)*page_len]
@ -37,6 +39,36 @@ def searchteams():
return jsonify([json.loads(x[0])['name'] for x in result]) #currently all we need is the name but that can change return jsonify([json.loads(x[0])['name'] for x in result]) #currently all we need is the name but that can change
@app.route('/api/leagues', methods=['POST'])
def create_league():
config = json.loads(request.data)
if (league_exists(config['name'])):
abort(400, "A league by that name already exists")
print(config)
league_dic = {
subleague['name'] : {
division['name'] : [games.get_team(team_name) for team_name in division['teams']]
for division in subleague['divisions']
}
for subleague in config['structure']['subleagues']
}
new_league = league_structure(config['name'])
new_league.setup(
league_dic,
division_games=config['division_series'],
inter_division_games=config['inter_division_series'],
inter_league_games=config['inter_league_series'],
)
new_league.generate_schedule()
leagues.save_league(new_league)
return "League created successfully"
### SOCKETS ### SOCKETS
thread2 = threading.Thread(target=socketio.run,args=(app,'0.0.0.0')) thread2 = threading.Thread(target=socketio.run,args=(app,'0.0.0.0'))

View File

@ -49,7 +49,7 @@ input[type=number]::-webkit-outer-spin-button {
margin-top: 1rem; margin-top: 1rem;
} }
.cl_league_options, .cl_league_structure { .cl_league_options, .cl_league_structure, .cl_confirm_box {
display: flex; display: flex;
background: var(--background-tertiary); background: var(--background-tertiary);
flex-direction: column; flex-direction: column;
@ -58,6 +58,15 @@ input[type=number]::-webkit-outer-spin-button {
padding-top: 1.5rem; padding-top: 1.5rem;
} }
.cl_confirm_box {
min-width: 55rem;
padding: 2.5rem;
display: flex;
align-items: center;
justify-content: center;
font-size: 20pt;
}
.cl_league_options { .cl_league_options {
align-items: center; align-items: center;
} }

View File

@ -210,6 +210,8 @@ let initLeagueStructure = {
function CreateLeague() { function CreateLeague() {
let [name, setName] = useState(""); let [name, setName] = useState("");
let [showError, setShowError] = useState(false); let [showError, setShowError] = useState(false);
let [nameExists, setNameExists] = useState(false);
let [createSuccess, setCreateSuccess] = useState(false);
let [structure, structureDispatch] = useReducer(leagueStructureReducer, initLeagueStructure); let [structure, structureDispatch] = useReducer(leagueStructureReducer, initLeagueStructure);
let [options, optionsDispatch] = useReducer(LeagueOptionsReducer, new LeagueOptionsState()); let [options, optionsDispatch] = useReducer(LeagueOptionsReducer, new LeagueOptionsState());
@ -221,18 +223,52 @@ function CreateLeague() {
} }
}) })
if (createSuccess) {
return(
<div className="cl_league_main" ref={self}>
<div className="cl_confirm_box">
League created succesfully!
</div>
</div>
);
}
return ( return (
<div className="cl_league_main" ref={self}> <div className="cl_league_main" ref={self}>
<input type="text" className="cl_league_name" placeholder="League Name" value={name} onChange={(e) => setName(e.target.value)}/> <input type="text" className="cl_league_name" placeholder="League Name" value={name} onChange={(e) => {
<div className="cl_structure_err">{name === "" && showError ? "A name is required." : ""}</div> setName(e.target.value);
setNameExists(false);
}}/>
<div className="cl_structure_err">{
name === "" && showError ? "A name is required." :
nameExists && showError ? "A league by that name already exists" :
""
}</div>
<LeagueStructre state={structure} dispatch={structureDispatch} showError={showError}/> <LeagueStructre state={structure} dispatch={structureDispatch} showError={showError}/>
<div className="cl_league_options"> <div className="cl_league_options">
<LeagueOptions state={options} dispatch={optionsDispatch} showError={showError}/> <LeagueOptions state={options} dispatch={optionsDispatch} showError={showError}/>
<div className="cl_option_submit_box"> <div className="cl_option_submit_box">
<button className="cl_option_submit" onClick={e => { <button className="cl_option_submit" onClick={e => {
//make network call, once leagues are merged
if (!validRequest(name, structure, options)) { if (!validRequest(name, structure, options)) {
setShowError(true); setShowError(true);
} else {
let req = new XMLHttpRequest();
let data = makeRequest(name, structure, options);
req.open("POST", "/api/leagues", true);
req.setRequestHeader("Content-type", "application/json");
req.onreadystatechange = () => {
if(req.readyState === 4) {
if (req.status === 200) {
setCreateSuccess(true);
}
if (req.status === 400) {
setNameExists(true);
setShowError(true);
}
}
}
req.send(data);
} }
}}>Submit</button> }}>Submit</button>
<div className="cl_option_err">{ <div className="cl_option_err">{
@ -246,19 +282,14 @@ function CreateLeague() {
} }
function makeRequest(name:string, structure: LeagueStructureState, options:LeagueOptionsState) { function makeRequest(name:string, structure: LeagueStructureState, options:LeagueOptionsState) {
return JSON.stringify({
if (!validRequest(name, structure, options)) {
return null
}
return ({
structure: {
name: name, name: name,
structure: {
subleagues: structure.subleagues.map(subleague => ({ subleagues: structure.subleagues.map(subleague => ({
name: subleague.name, name: subleague.name,
divisions: subleague.divisions.map(division => ({ divisions: subleague.divisions.map(division => ({
name: division.name, name: division.name,
teams: division.teams teams: division.teams.map(team => team.name)
})) }))
})) }))
}, },
@ -272,7 +303,6 @@ function makeRequest(name:string, structure: LeagueStructureState, options:Leagu
} }
function validRequest(name:string, structure: LeagueStructureState, options:LeagueOptionsState) { function validRequest(name:string, structure: LeagueStructureState, options:LeagueOptionsState) {
return ( return (
name !== "" && name !== "" &&
validNumber(options.games_series) && validNumber(options.games_series) &&
@ -280,7 +310,7 @@ function validRequest(name:string, structure: LeagueStructureState, options:Leag
validNumber(options.inter_division_series) && validNumber(options.inter_division_series) &&
validNumber(options.inter_league_series) && validNumber(options.inter_league_series) &&
validNumber(options.top_postseason) && validNumber(options.top_postseason) &&
validNumber(options.wildcards) && validNumber(options.wildcards, 0) &&
structure.subleagues.length % 2 === 0 && structure.subleagues.length % 2 === 0 &&
structure.subleagues.every(subleague => structure.subleagues.every(subleague =>
subleague.name !== "" && subleague.name !== "" &&
@ -292,8 +322,8 @@ function validRequest(name:string, structure: LeagueStructureState, options:Leag
) )
} }
function validNumber(value: string) { function validNumber(value: string, min = 1) {
return Number(value) !== NaN && Number(value) > 0 return Number(value) !== NaN && Number(value) >= min
} }
// LEAGUE STRUCUTRE // LEAGUE STRUCUTRE
@ -426,8 +456,6 @@ function Division(props: {state: DivisionState, dispatch:(action: DistributiveOm
// LEAGUE OPTIONS // LEAGUE OPTIONS
type StateBundle<T> = [T, React.Dispatch<React.SetStateAction<T>>]
function LeagueOptions(props: {state: LeagueOptionsState, dispatch: React.Dispatch<OptionsReducerActions>, showError: boolean}) { function LeagueOptions(props: {state: LeagueOptionsState, dispatch: React.Dispatch<OptionsReducerActions>, showError: boolean}) {
return ( return (
<div className="cl_option_main"> <div className="cl_option_main">