work on team search

This commit is contained in:
Elijah Steres 2021-01-10 23:47:49 -05:00
parent 72edbf5022
commit c3a35c07a4
6 changed files with 293 additions and 121 deletions

View File

@ -1,6 +1,7 @@
import asyncio, time, datetime, games, json, threading, jinja2, leagues, os
from flask import Flask, url_for, Response, render_template, request, jsonify, send_from_directory
from flask import Flask, url_for, Response, render_template, request, jsonify, send_from_directory, abort
from flask_socketio import SocketIO, emit
import database as db
app = Flask("the-prestige", static_folder='simmadome/build')
app.config['SECRET KEY'] = 'dev'
@ -16,6 +17,27 @@ def serve(path):
else:
return send_from_directory(app.static_folder, 'index.html')
### API
@app.route('/api/teams/search')
def searchteams():
query = request.args.get('query')
page_len = int(request.args.get('page_len'))
page_num = int(request.args.get('page_num'))
if query is None:
abort(400, "A query term is required")
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_num is None:
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]
return jsonify([json.loads(x[0])['name'] for x in result]) #currently all we need is the name but that can change
### SOCKETS
thread2 = threading.Thread(target=socketio.run,args=(app,'0.0.0.0'))
thread2.start()

View File

@ -1974,6 +1974,7 @@
"version": "7.29.1",
"resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-7.29.1.tgz",
"integrity": "sha512-6BU7vAjKuMspCy9QQEtbWgmkuXi/yOSZo3ANdvZmNQW8N/WQGjO9cvlcA5EFJaPtp2hL1RAaPGpCXxumijUxCg==",
"dev": true,
"requires": {
"@babel/code-frame": "^7.10.4",
"@babel/runtime": "^7.12.5",
@ -1989,6 +1990,7 @@
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
"dev": true,
"requires": {
"color-convert": "^2.0.1"
}
@ -1997,6 +1999,7 @@
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz",
"integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==",
"dev": true,
"requires": {
"ansi-styles": "^4.1.0",
"supports-color": "^7.1.0"
@ -2006,6 +2009,7 @@
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"dev": true,
"requires": {
"color-name": "~1.1.4"
}
@ -2013,17 +2017,20 @@
"color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true
},
"has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
"dev": true
},
"supports-color": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
"dev": true,
"requires": {
"has-flag": "^4.0.0"
}
@ -2034,6 +2041,7 @@
"version": "5.11.8",
"resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-5.11.8.tgz",
"integrity": "sha512-ScyKrWQM5xNcr79PkSewnA79CLaoxVskE+f7knTOhDD9ftZSA1Jw8mj+pneqhEu3x37ncNfW84NUr7lqK+mXjA==",
"dev": true,
"requires": {
"@babel/runtime": "^7.9.2",
"@types/testing-library__jest-dom": "^5.9.1",
@ -2049,6 +2057,7 @@
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
"dev": true,
"requires": {
"color-convert": "^2.0.1"
}
@ -2057,6 +2066,7 @@
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz",
"integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==",
"dev": true,
"requires": {
"ansi-styles": "^4.1.0",
"supports-color": "^7.1.0"
@ -2066,6 +2076,7 @@
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"dev": true,
"requires": {
"color-name": "~1.1.4"
}
@ -2073,12 +2084,14 @@
"color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true
},
"css": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/css/-/css-3.0.0.tgz",
"integrity": "sha512-DG9pFfwOrzc+hawpmqX/dHYHJG+Bsdb0klhyi1sDneOgGOXy9wQIC8hzyVp1e4NRYDBdxcylvywPkkXCHAzTyQ==",
"dev": true,
"requires": {
"inherits": "^2.0.4",
"source-map": "^0.6.1",
@ -2088,17 +2101,20 @@
"has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
"dev": true
},
"source-map": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
"dev": true
},
"source-map-resolve": {
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.6.0.tgz",
"integrity": "sha512-KXBr9d/fO/bWo97NXsPIAW1bFSBOuCnjbNTBMO7N59hsv5i9yzRDfcYwwt0l04+VqnKC+EwzvJZIP/qkuMgR/w==",
"dev": true,
"requires": {
"atob": "^2.1.2",
"decode-uri-component": "^0.2.0"
@ -2108,6 +2124,7 @@
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
"dev": true,
"requires": {
"has-flag": "^4.0.0"
}
@ -2118,6 +2135,7 @@
"version": "11.2.2",
"resolved": "https://registry.npmjs.org/@testing-library/react/-/react-11.2.2.tgz",
"integrity": "sha512-jaxm0hwUjv+hzC+UFEywic7buDC9JQ1q3cDsrWVSDAPmLotfA6E6kUHlYm/zOeGCac6g48DR36tFHxl7Zb+N5A==",
"dev": true,
"requires": {
"@babel/runtime": "^7.12.5",
"@testing-library/dom": "^7.28.1"
@ -2127,6 +2145,7 @@
"version": "12.6.0",
"resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-12.6.0.tgz",
"integrity": "sha512-FNEH/HLmOk5GO70I52tKjs7WvGYckeE/SrnLX/ip7z2IGbffyd5zOUM1tZ10vsTphqm+VbDFI0oaXu0wcfQsAQ==",
"dev": true,
"requires": {
"@babel/runtime": "^7.12.5"
}
@ -2139,7 +2158,8 @@
"@types/aria-query": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-4.2.0.tgz",
"integrity": "sha512-iIgQNzCm0v7QMhhe4Jjn9uRh+I6GoPmt03CbEtwx3ao8/EfoQcmgtqH4vQ5Db/lxiIGaWDv6nwvunuh0RyX0+A=="
"integrity": "sha512-iIgQNzCm0v7QMhhe4Jjn9uRh+I6GoPmt03CbEtwx3ao8/EfoQcmgtqH4vQ5Db/lxiIGaWDv6nwvunuh0RyX0+A==",
"dev": true
},
"@types/babel__core": {
"version": "7.1.12",
@ -2217,7 +2237,8 @@
"@types/history": {
"version": "4.7.8",
"resolved": "https://registry.npmjs.org/@types/history/-/history-4.7.8.tgz",
"integrity": "sha512-S78QIYirQcUoo6UJZx9CSP0O2ix9IaeAXwQi26Rhr/+mg7qqPy8TzaxHSUut7eGjL8WmLccT7/MXf304WjqHcA=="
"integrity": "sha512-S78QIYirQcUoo6UJZx9CSP0O2ix9IaeAXwQi26Rhr/+mg7qqPy8TzaxHSUut7eGjL8WmLccT7/MXf304WjqHcA==",
"dev": true
},
"@types/html-minifier-terser": {
"version": "5.1.1",
@ -2249,11 +2270,21 @@
"version": "26.0.19",
"resolved": "https://registry.npmjs.org/@types/jest/-/jest-26.0.19.tgz",
"integrity": "sha512-jqHoirTG61fee6v6rwbnEuKhpSKih0tuhqeFbCmMmErhtu3BYlOZaXWjffgOstMM4S/3iQD31lI5bGLTrs97yQ==",
"dev": true,
"requires": {
"jest-diff": "^26.0.0",
"pretty-format": "^26.0.0"
}
},
"@types/jquery": {
"version": "3.5.5",
"resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.5.5.tgz",
"integrity": "sha512-6RXU9Xzpc6vxNrS6FPPapN1SxSHgQ336WC6Jj/N8q30OiaBZ00l1GBgeP7usjVZPivSkGUfL1z/WW6TX989M+w==",
"dev": true,
"requires": {
"@types/sizzle": "*"
}
},
"@types/json-schema": {
"version": "7.0.6",
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.6.tgz",
@ -2292,7 +2323,8 @@
"@types/prop-types": {
"version": "15.7.3",
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.3.tgz",
"integrity": "sha512-KfRL3PuHmqQLOG+2tGpRO26Ctg+Cq1E01D2DMriKEATHgWLfeNDmq9e29Q9WIky0dQ3NPkd1mzYH8Lm936Z9qw=="
"integrity": "sha512-KfRL3PuHmqQLOG+2tGpRO26Ctg+Cq1E01D2DMriKEATHgWLfeNDmq9e29Q9WIky0dQ3NPkd1mzYH8Lm936Z9qw==",
"dev": true
},
"@types/q": {
"version": "1.5.4",
@ -2303,6 +2335,7 @@
"version": "16.14.2",
"resolved": "https://registry.npmjs.org/@types/react/-/react-16.14.2.tgz",
"integrity": "sha512-BzzcAlyDxXl2nANlabtT4thtvbbnhee8hMmH/CcJrISDBVcJS1iOsP1f0OAgSdGE0MsY9tqcrb9YoZcOFv9dbQ==",
"dev": true,
"requires": {
"@types/prop-types": "*",
"csstype": "^3.0.2"
@ -2312,6 +2345,7 @@
"version": "16.9.10",
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-16.9.10.tgz",
"integrity": "sha512-ItatOrnXDMAYpv6G8UCk2VhbYVTjZT9aorLtA/OzDN9XJ2GKcfam68jutoAcILdRjsRUO8qb7AmyObF77Q8QFw==",
"dev": true,
"requires": {
"@types/react": "^16"
}
@ -2320,6 +2354,7 @@
"version": "5.1.10",
"resolved": "https://registry.npmjs.org/@types/react-router/-/react-router-5.1.10.tgz",
"integrity": "sha512-yu11Hu16CfGvvBWc7wluRlxbwfuSlY0snEntbbOTvfgMvyO6uLaEpAbnVOntr+9TNIpR++OOlPkmDcJPxOXRaQ==",
"dev": true,
"requires": {
"@types/history": "*",
"@types/react": "*"
@ -2329,6 +2364,7 @@
"version": "5.1.7",
"resolved": "https://registry.npmjs.org/@types/react-router-dom/-/react-router-dom-5.1.7.tgz",
"integrity": "sha512-D5mHD6TbdV/DNHYsnwBTv+y73ei+mMjrkGrla86HthE4/PVvL1J94Bu3qABU+COXzpL23T1EZapVVpwHuBXiUg==",
"dev": true,
"requires": {
"@types/history": "*",
"@types/react": "*",
@ -2343,10 +2379,17 @@
"@types/node": "*"
}
},
"@types/sizzle": {
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.2.tgz",
"integrity": "sha512-7EJYyKTL7tFR8+gDbB6Wwz/arpGa0Mywk1TJbNzKzHtzbwVmY4HR9WqS5VV7dsBUKQmPNr192jHr/VpBluj/hg==",
"dev": true
},
"@types/socket.io-client": {
"version": "1.4.34",
"resolved": "https://registry.npmjs.org/@types/socket.io-client/-/socket.io-client-1.4.34.tgz",
"integrity": "sha512-Lzia5OTQFJZJ5R4HsEEldywiiqT9+W2rDbyHJiiTGqOcju89sCsQ8aUXDljY6Ls33wKZZGC0bfMhr/VpOyjtXg=="
"integrity": "sha512-Lzia5OTQFJZJ5R4HsEEldywiiqT9+W2rDbyHJiiTGqOcju89sCsQ8aUXDljY6Ls33wKZZGC0bfMhr/VpOyjtXg==",
"dev": true
},
"@types/source-list-map": {
"version": "0.1.2",
@ -2367,6 +2410,7 @@
"version": "5.9.5",
"resolved": "https://registry.npmjs.org/@types/testing-library__jest-dom/-/testing-library__jest-dom-5.9.5.tgz",
"integrity": "sha512-ggn3ws+yRbOHog9GxnXiEZ/35Mow6YtPZpd7Z5mKDeZS/o7zx3yAle0ov/wjhVB5QT4N2Dt+GNoGCdqkBGCajQ==",
"dev": true,
"requires": {
"@types/jest": "*"
}
@ -2374,7 +2418,8 @@
"@types/twemoji": {
"version": "12.1.1",
"resolved": "https://registry.npmjs.org/@types/twemoji/-/twemoji-12.1.1.tgz",
"integrity": "sha512-dW1B1WHTfrWmEzXb/tp8xsZqQHAyMB9JwLwbBqkIQVzmNUI02R7lJqxUpKFM114ygNZHKA1r74oPugCAiYHt1A=="
"integrity": "sha512-dW1B1WHTfrWmEzXb/tp8xsZqQHAyMB9JwLwbBqkIQVzmNUI02R7lJqxUpKFM114ygNZHKA1r74oPugCAiYHt1A==",
"dev": true
},
"@types/uglify-js": {
"version": "3.11.1",
@ -4598,7 +4643,8 @@
"css.escape": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/css.escape/-/css.escape-1.5.1.tgz",
"integrity": "sha1-QuJ9T6BK4y+TGktNQZH6nN3ul8s="
"integrity": "sha1-QuJ9T6BK4y+TGktNQZH6nN3ul8s=",
"dev": true
},
"cssdb": {
"version": "4.4.0",
@ -4769,7 +4815,8 @@
"csstype": {
"version": "3.0.5",
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.5.tgz",
"integrity": "sha512-uVDi8LpBUKQj6sdxNaTetL6FpeCqTjOvAQuQUa/qAqq8oOd4ivkbhgnqayl0dnPal8Tb/yB1tF+gOvCBiicaiQ=="
"integrity": "sha512-uVDi8LpBUKQj6sdxNaTetL6FpeCqTjOvAQuQUa/qAqq8oOd4ivkbhgnqayl0dnPal8Tb/yB1tF+gOvCBiicaiQ==",
"dev": true
},
"cyclist": {
"version": "1.0.1",
@ -5090,7 +5137,8 @@
"dom-accessibility-api": {
"version": "0.5.4",
"resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.4.tgz",
"integrity": "sha512-TvrjBckDy2c6v6RLxPv5QXOnU+SmF9nBII5621Ve5fu6Z/BDrENurBEvlC1f44lKEUVqOpK4w9E5Idc5/EgkLQ=="
"integrity": "sha512-TvrjBckDy2c6v6RLxPv5QXOnU+SmF9nBII5621Ve5fu6Z/BDrENurBEvlC1f44lKEUVqOpK4w9E5Idc5/EgkLQ==",
"dev": true
},
"dom-converter": {
"version": "0.2.0",
@ -9496,6 +9544,11 @@
}
}
},
"jquery": {
"version": "3.5.1",
"resolved": "https://registry.npmjs.org/jquery/-/jquery-3.5.1.tgz",
"integrity": "sha512-XwIBPqcMn57FxfT+Go5pzySnm4KWkT1Tv7gjrpT1srtf8Weynl6R273VJ5GjkRb51IzMp5nbaPjJXMWeju2MKg=="
},
"js-tokens": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
@ -9818,7 +9871,8 @@
"lz-string": {
"version": "1.4.4",
"resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.4.4.tgz",
"integrity": "sha1-wNjq82BZ9wV5bh40SBHPTEmNOiY="
"integrity": "sha1-wNjq82BZ9wV5bh40SBHPTEmNOiY=",
"dev": true
},
"magic-string": {
"version": "0.25.7",
@ -9994,7 +10048,8 @@
"min-indent": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz",
"integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg=="
"integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==",
"dev": true
},
"mini-create-react-context": {
"version": "0.4.1",
@ -12670,6 +12725,7 @@
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz",
"integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==",
"dev": true,
"requires": {
"indent-string": "^4.0.0",
"strip-indent": "^3.0.0"
@ -14279,6 +14335,7 @@
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz",
"integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==",
"dev": true,
"requires": {
"min-indent": "^1.0.0"
}

View File

@ -4,6 +4,7 @@
"private": true,
"proxy": "http://localhost:5000",
"dependencies": {
"jquery": "^3.5.1",
"react": "^17.0.1",
"react-dom": "^17.0.1",
"react-router": "^5.2.0",
@ -14,11 +15,12 @@
"typescript": "^4.1.3",
"web-vitals": "^0.2.4"
},
"devDependencies" : {
"devDependencies": {
"@testing-library/jest-dom": "^5.11.8",
"@testing-library/react": "^11.2.2",
"@testing-library/user-event": "^12.6.0",
"@types/jest": "^26.0.19",
"@types/jquery": "^3.5.5",
"@types/node": "^12.19.12",
"@types/react": "^16.14.2",
"@types/react-dom": "^16.9.10",

View File

@ -1,22 +1,17 @@
th, td {
border: none;
padding: 0;
height: 100%;
}
table {
border-collapse: collapse;
height: min-content;
}
th .cl_subleague_bg {
.cl_table_header > .cl_subleague_bg {
border-top-left-radius: 0.5rem;
border-top-right-radius: 0.5rem;
padding-top: 1rem;
}
tbody tr:last-child .cl_subleague_bg {
.cl_league_structure_table .cl_table_row:last-child .cl_subleague_bg {
border-bottom-left-radius: 0.5rem;
border-bottom-right-radius: 0.5rem;
padding-bottom: 1rem;
}
.cl_league_structure_table .cl_table_row:last-child .cl_division_delete {
margin-bottom: 0.5rem;
}
input {
@ -28,6 +23,10 @@ input {
font-size: 14pt;
}
input:focus {
outline: none;
}
.cl_league_main {
display: flex;
flex-direction: column;
@ -57,9 +56,23 @@ input {
}
.cl_league_structure_table {
margin: 1rem;
margin-left: 0rem;
margin-top: 0rem;
display: table;
margin-right: 1rem;
table-layout: fixed;
}
.cl_headers, .cl_table_row {
display: table-row;
height: min-content;
}
.cl_table_header, .cl_delete_filler, .cl_delete_box, .cl_division_cell {
display: table-cell;
height:100%;
}
.cl_delete_box {
vertical-align: middle;
}
.cl_league_structure_scrollbox {
@ -92,14 +105,14 @@ input {
.cl_subleague_bg {
background: var(--background-main);
padding:1rem;
padding-bottom: 0rem;
padding: 0.5rem 1rem;
margin: 0rem 0.5rem;
height: 100%;
width: 20rem;
width: 22rem;
height:100%;
box-sizing: border-box;
}
.cl_subleague_name, .cl_newteam_name {
.cl_subleague_name {
flex-grow: 1;
margin-right: 0.5rem;
}
@ -109,6 +122,10 @@ input {
width: 95%;
}
.cl_newteam_name {
width: 95%;
}
.cl_division {
display: flex;
flex-direction: column;
@ -124,7 +141,7 @@ input {
align-items: center;
justify-content: space-between;
width: 100%;
margin: 0.25rem 0rem;
margin: 0.4rem 0rem;
}
.cl_team_name {
@ -134,13 +151,38 @@ input {
text-overflow: ellipsis;
}
.cl_team_add {
display: flex;
flex-direction: column;
margin-bottom: 0rem;
}
.cl_search_list {
width: 95%;
margin-top: 0.6rem;
padding: 0.5rem;
background: var(--background-tertiary);
border-radius: 0.5rem;
}
.cl_search_result {
padding: 0.2rem 0.4rem;
border-radius: 0.5rem;
}
.cl_search_result:hover {
background: var(--background-main);
}
/* button styles */
button > .emoji {
margin: 0;
width: 1rem;
height: 1rem;
}
.cl_subleague_delete, .cl_team_delete, .cl_division_delete, .cl_subleague_add, .cl_division_add, .cl_newteam_add {
.cl_subleague_delete, .cl_team_delete, .cl_division_delete, .cl_subleague_add, .cl_division_add {
padding: 0;
width: 2rem;
height: 2rem;
@ -155,21 +197,18 @@ button > .emoji {
background: var(--accent-red);
}
.cl_subleague_add, .cl_division_add, .cl_newteam_add {
.cl_subleague_add, .cl_division_add {
background: var(--accent-green);
}
.cl_subleague_add {
margin-top: 3rem;
position: relative;
top: 1.6rem;
}
.cl_division_add {
margin: 1.25rem;
}
.cl_division_delete {
margin-right: 1rem;
margin-top: 1rem;
margin-top: 1.25rem;
margin-bottom: 1.25rem;
}
.cl_delete_filler {

View File

@ -1,6 +1,7 @@
import React, {useState, useRef, useLayoutEffect, useReducer} from 'react';
import './CreateLeague.css';
import twemoji from 'twemoji';
import $, {getJSON} from 'jquery';
interface LeagueStructureState {
subleagues: SubleagueState[]
@ -8,26 +9,19 @@ interface LeagueStructureState {
interface SubleagueState {
name: string
id: string|number
divisions: DivisionState[]
}
interface DivisionState {
name: string
id: string|number
teams: TeamState[]
}
interface TeamState {
name: string
}
let initLeagueStructure = {
subleagues: [0, 1].map((val) => ({
name: "",
divisions: [0, 1].map((val) => ({
name: "",
teams: []
}))
}))
id: string|number
}
type LeagueReducerActions =
@ -42,6 +36,11 @@ type LeagueReducerActions =
type DistributiveOmit<T, K extends keyof any> = T extends any ? Omit<T, K> : never;
let getUID = function() { // does NOT generate UUIDs. Meant to create list keys ONLY
let id = 0;
return function() { return id++}
}()
function leagueStructureReducer(state: LeagueStructureState, action: LeagueReducerActions): LeagueStructureState {
switch (action.type) {
case 'remove_subleague':
@ -49,40 +48,55 @@ function leagueStructureReducer(state: LeagueStructureState, action: LeagueReduc
case 'add_subleague':
return {subleagues: state.subleagues.concat([{
name: "",
id: getUID(),
divisions: arrayOf(state.subleagues[0].divisions.length, i => ({
name: "",
id: getUID(),
teams: []
}))
}])};
case 'rename_subleague':
return replaceSubleague(state, action.subleague_index, subleague => ({
name: action.name,
id: subleague.id,
divisions: subleague.divisions
}));
case 'remove_divisions':
return {subleagues: state.subleagues.map(subleague => ({
name: subleague.name,
id: subleague.id,
divisions: removeIndex(subleague.divisions, action.division_index)
}))};
case 'add_divisions':
return {subleagues: state.subleagues.map(subleague => ({
name: subleague.name,
divisions: subleague.divisions.concat([{name: "", teams: []}])
id: subleague.id,
divisions: subleague.divisions.concat([{
name: "",
id: getUID(),
teams: []
}])
}))};
case 'rename_division':
return replaceDivision(state, action.subleague_index, action.division_index, division => ({
name: action.name,
id: division.id,
teams: division.teams
}));
case 'remove_team':
return replaceDivision(state, action.subleague_index, action.division_index, division => ({
name: division.name,
id: division.id,
teams: removeIndex(division.teams, division.teams.findIndex(val => val.name === action.name))
}));
case 'add_team':
return replaceDivision(state, action.subleague_index, action.division_index, division => ({
name: division.name,
teams: division.teams.concat([{name: action.name}])
id: division.id,
teams: division.teams.concat([{
name: action.name,
id: getUID()
}])
}));
}
}
@ -94,6 +108,7 @@ function replaceSubleague(state: LeagueStructureState, si: number, func: (val: S
function replaceDivision(state: LeagueStructureState, si: number, di: number, func:(val: DivisionState) => DivisionState) {
return replaceSubleague(state, si, subleague => ({
name: subleague.name,
id: subleague.id,
divisions: replaceIndex(subleague.divisions, di, func(subleague.divisions[di]))
}))
}
@ -118,6 +133,18 @@ function arrayOf<T>(length: number, func: (i: number) => T): T[] {
return out;
}
let initLeagueStructure = {
subleagues: [0, 1].map((val) => ({
name: "",
id: getUID(),
divisions: [0, 1].map((val) => ({
name: "",
id: getUID(),
teams: []
}))
}))
}
function CreateLeague() {
let [name, setName] = useState("");
let [structure, dispatch] = useReducer(leagueStructureReducer, initLeagueStructure);
@ -144,10 +171,10 @@ function LeagueStructre(props: {state: LeagueStructureState, dispatch: React.Dis
<div className="cl_league_structure">
<div className="cl_league_structure_scrollbox">
<div className="cl_subleague_add_align">
<table className="cl_league_structure_table">
<div className="cl_league_structure_table">
<SubleagueHeaders subleagues={props.state.subleagues} dispatch={props.dispatch} />
<Divisions subleagues={props.state.subleagues} dispatch={props.dispatch} />
</table>
</div>
<button className="cl_subleague_add" onClick={e => props.dispatch({type: 'add_subleague'})}></button>
</div>
</div>
@ -158,20 +185,18 @@ function LeagueStructre(props: {state: LeagueStructureState, dispatch: React.Dis
function SubleagueHeaders(props: {subleagues: SubleagueState[], dispatch: React.Dispatch<LeagueReducerActions>}) {
return (
<thead>
<tr className="cl_headers">
<th key="filler" className="cl_delete_filler"/>
{props.subleagues.map((subleague, i) => (
<th key={i}>
<div className="cl_subleague_bg">
<SubleageHeader state={subleague} canDelete={props.subleagues.length > 1} dispatch={action =>
props.dispatch(Object.assign({subleague_index: i}, action))
}/>
</div>
</th>
))}
</tr>
</thead>
<div className="cl_headers">
<div key="filler" className="cl_delete_filler"/>
{props.subleagues.map((subleague, i) => (
<div key={subleague.id} className="cl_table_header">
<div className="cl_subleague_bg">
<SubleageHeader state={subleague} canDelete={props.subleagues.length > 1} dispatch={action =>
props.dispatch(Object.assign({subleague_index: i}, action))
}/>
</div>
</div>
))}
</div>
);
}
@ -187,33 +212,40 @@ function SubleageHeader(props: {state: SubleagueState, canDelete: boolean, dispa
}
function Divisions(props: {subleagues: SubleagueState[], dispatch: React.Dispatch<LeagueReducerActions>}) {
return (
<tbody>
{props.subleagues[0].divisions.map((val, di) => (
<tr key={di}>
<td key="delete" className="cl_delete_box">
{props.subleagues[0].divisions.length > 1 ?
<button className="cl_division_delete" onClick={e => props.dispatch({type: 'remove_divisions', division_index: di})}></button> :
null
}
</td>
{props.subleagues.map((subleague, si) => (
<td key={si}>
<div className="cl_subleague_bg">
<Division state={subleague.divisions[di]} dispatch={action =>
props.dispatch(Object.assign({subleague_index: si, division_index: di}, action))
}/>
</div>
</td>
))}
</tr>
))}
</tbody>
);
return (<>
{props.subleagues[0].divisions.map((val, di) => (
<div key={val.id} className="cl_table_row">
<div key="delete" className="cl_delete_box">
{props.subleagues[0].divisions.length > 1 ?
<button className="cl_division_delete" onClick={e => props.dispatch({type: 'remove_divisions', division_index: di})}></button> :
null
}
</div>
{props.subleagues.map((subleague, si) => (
<div key={subleague.id} className="cl_division_cell">
<div className="cl_subleague_bg">
<Division state={subleague.divisions[di]} dispatch={action =>
props.dispatch(Object.assign({subleague_index: si, division_index: di}, action))
}/>
</div>
</div>
))}
</div>
))}
</>);
}
function Division(props: {state: DivisionState, dispatch:(action: DistributiveOmit<LeagueReducerActions, 'subleague_index'|'division_index'>) => void}) {
let [newName, setNewName] = useState("");
let [searchResults, setSearchResults] = useState<string[]>([]);
let newNameInput = useRef<HTMLInputElement>(null);
let resultList = useRef<HTMLDivElement>(null);
useLayoutEffect(() => {
if (resultList.current) {
twemoji.parse(resultList.current)
}
})
return (
<div className="cl_division">
@ -221,18 +253,36 @@ function Division(props: {state: DivisionState, dispatch:(action: DistributiveOm
props.dispatch({type: 'rename_division', name: e.target.value})
}/>
{props.state.teams.map((team, i) => (
<div className="cl_team" key={i}>
<div className="cl_team" key={team.id}>
<div className="cl_team_name">{team.name}</div>
<button className="cl_team_delete" onClick={e => props.dispatch({type:'remove_team', name: team.name})}></button>
</div>
))}
<div className="cl_team_add">
<input type="text" className="cl_newteam_name" placeholder="Add team..." value={newName} onChange={e => setNewName(e.target.value)}/>
<button className="cl_newteam_add" onClick={e => {if (newName.length > 0) {
props.dispatch({type: 'add_team', name: newName});
setNewName("");
}}}></button>
<input type="text" className="cl_newteam_name" placeholder="Add team..." value={newName} ref={newNameInput}
onChange={e => {
let params = new URLSearchParams({query: e.target.value, page_len: '5', page_num: '0'});
$.getJSON("/api/teams/search?" + params.toString(), data => {
console.log(data);
setSearchResults(data);
})
setNewName(e.target.value);
}}/>
</div>
{searchResults.length > 0 && newName.length > 0 ?
(<div className="cl_search_list" ref={resultList}>
{searchResults.map(result =>
<div className="cl_search_result" key={result} onClick={e => {
props.dispatch({type:'add_team', name: result});
setNewName("");
if (newNameInput.current) {
newNameInput.current.focus();
}
}}>{result}</div>
)}
</div>):
<div/>
}
</div>
);
}
@ -240,9 +290,7 @@ function Division(props: {state: DivisionState, dispatch:(action: DistributiveOm
function LeagueOptions() {
return (
<div className="cl_league_options">
<form>
</form>
</div>
);
}

View File

@ -7,20 +7,24 @@ import GamePage from './GamePage';
import CreateLeague from './CreateLeague';
import discordlogo from "./img/discord.png";
import reportWebVitals from './reportWebVitals';
import $ from 'jquery'
$(document).ready(function() {
ReactDOM.render(
<React.StrictMode>
<Router>
<Header />
<Switch>
<Route path="/game/:id" component={GamePage}/>
<Route path="/create_league" component={CreateLeague} />
<Route path="/" component={GamesPage}/>
</Switch>
</Router>
</React.StrictMode>,
document.getElementById('root')
);
});
ReactDOM.render(
<React.StrictMode>
<Router>
<Header />
<Switch>
<Route path="/game/:id" component={GamePage}/>
<Route path="/create_league" component={CreateLeague} />
<Route path="/" component={GamesPage}/>
</Switch>
</Router>
</React.StrictMode>,
document.getElementById('root')
);
function Header() {
return (