From 040a3a894e0816596532d7f7430baa4a5524f67b Mon Sep 17 00:00:00 2001 From: Karan Jayachandra Date: Fri, 25 Jul 2025 14:17:07 +0200 Subject: Added the grid layout using custom css --- app/static/custom.css | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) (limited to 'app/static') diff --git a/app/static/custom.css b/app/static/custom.css index fafc51a..18462d3 100644 --- a/app/static/custom.css +++ b/app/static/custom.css @@ -1,5 +1,6 @@ button, input, .select, .select select { width: 100%; + height: 100%; } table { font-size: 17.5px; @@ -7,13 +8,17 @@ table { td { width: 20%; } -img { - position: absolute; - top: 50%; - left: 50%; - transform: translate(-50%,-50%); -} .center { margin: auto; width: 50%; -} \ No newline at end of file +} +.parent { + display: grid; + grid-column-gap: 20px; + grid-row-gap: 20px; +} +@media (min-width: 800px) { + .parent { + grid-template-columns: repeat(4, 1fr); + } +} -- cgit v1.3.1 From 08e4a27c0db7fc2867cce3eb6f80799148c03ba6 Mon Sep 17 00:00:00 2001 From: Karan Jayachandra Date: Fri, 25 Jul 2025 15:30:07 +0200 Subject: Moved to a mobile friendly CSS framework --- app/__init__.py | 27 +++++++-------- app/static/custom.css | 13 ++++---- app/static/custom.js | 2 +- app/templates/controls.j2 | 83 +++++++++++++++++++++++------------------------ app/templates/games.j2 | 6 ++-- app/templates/index.j2 | 11 ++++--- app/templates/login.html | 8 ++--- app/templates/macros.j2 | 54 ++++++++---------------------- app/templates/players.j2 | 59 ++++++++++++++++----------------- 9 files changed, 121 insertions(+), 142 deletions(-) (limited to 'app/static') diff --git a/app/__init__.py b/app/__init__.py index 3d3b498..639f030 100644 --- a/app/__init__.py +++ b/app/__init__.py @@ -54,19 +54,29 @@ def get_list_of_courts(): return render_template("courts.j2", courts=g.courts.all()) +def login_required(f): + @wraps(f) + def decorated_function(*args, **kwargs): + if not is_logged_in(): + response = Response("User isn't logged in!") + response.headers["HX-Redirect"] = url_for("simplelogin.login") + return response + return f(*args, **kwargs) + + return decorated_function + + @app.route("/propose", methods=["POST"]) +@login_required def get_random_games(): - if not is_logged_in(): - return redirect(url_for("login")) g.levels = int(request.form["levels"].split()[0]) g.teams = request.form["team"] == "Teams" return render_template("games.j2", games=g.propose(), title="Proposal") @app.route("/confirm", methods=["POST"]) +@login_required def confirm_games(): - if not is_logged_in(): - return redirect(url_for("simplelogin.login")) return render_template("games.j2", games=g.confirm(), title=f"Round: {g.round()}") @@ -76,15 +86,6 @@ def clear_games(): "games.j2", games=g.current_round(), title=f"Round: {g.round()}" ) -def login_required(f): - @wraps(f) - def decorated_function(*args, **kwargs): - if not is_logged_in(): - response = Response("User isn't logged in!") - response.headers["HX-Redirect"] = url_for("simplelogin.login") - return response - return f(*args, **kwargs) - return decorated_function @app.route("/reset", methods=["POST"]) @login_required diff --git a/app/static/custom.css b/app/static/custom.css index 18462d3..9992ee5 100644 --- a/app/static/custom.css +++ b/app/static/custom.css @@ -1,21 +1,20 @@ -button, input, .select, .select select { +button, input, select { width: 100%; height: 100%; } -table { - font-size: 17.5px; -} td { width: 20%; } -.center { - margin: auto; - width: 50%; +.grid { + margin-top: 20px; + margin-bottom: 20px; } .parent { display: grid; grid-column-gap: 20px; grid-row-gap: 20px; + margin-top: 20px; + margin-bottom: 20px; } @media (min-width: 800px) { .parent { diff --git a/app/static/custom.js b/app/static/custom.js index 1d36493..2c47448 100644 --- a/app/static/custom.js +++ b/app/static/custom.js @@ -3,7 +3,7 @@ let timerRunningFlag = Number(sessionStorage.getItem("timerRunningFlag")) || 0; let deadline = Number(sessionStorage.getItem("deadline")) || new Date().getTime(); let clock = 0; -function setTimer(m, s) { +window.onload += function setTimer(m, s) { let timer = document.getElementById("timer-display"); m = m < 10 ? ("0" + m) : m; s = s < 10 ? ("0" + s) : s; diff --git a/app/templates/controls.j2 b/app/templates/controls.j2 index f67f745..a8cba89 100644 --- a/app/templates/controls.j2 +++ b/app/templates/controls.j2 @@ -1,47 +1,46 @@ {% from "macros.j2" import court_button %} -
-
- {% for court in courts %} - {{ court_button(court) }} - {% endfor %} -
+

Courts

+
+{% for court in courts %} + {{ court_button(court) }} +{% endfor %}
-
-
-
- -
-
-
-
- -
-
-
- +

Generation

+
+
+
-
-
- -
-
- +
+
+
+
+ + + +
+

Timer

+
+ + + + +
\ No newline at end of file diff --git a/app/templates/games.j2 b/app/templates/games.j2 index dff1e0f..ce2a412 100644 --- a/app/templates/games.j2 +++ b/app/templates/games.j2 @@ -1,4 +1,5 @@ - +
+
@@ -18,4 +19,5 @@ {% endfor %} -
{{ title }}
\ No newline at end of file + +
\ No newline at end of file diff --git a/app/templates/index.j2 b/app/templates/index.j2 index ce0d531..8a13fa0 100644 --- a/app/templates/index.j2 +++ b/app/templates/index.j2 @@ -3,11 +3,14 @@ {{ header(url_for) }} -
- {{ navbar(url_for) }} +
{{ navbar(url_for) }}
+
+

Games

+

Controls

- {{ footer() }} -
+ +
{{ footer() }}
+ diff --git a/app/templates/login.html b/app/templates/login.html index a42f2c5..e3109b6 100644 --- a/app/templates/login.html +++ b/app/templates/login.html @@ -3,8 +3,8 @@ {{ header(url_for) }} -
- {{ navbar(url_for) }} +
{{ navbar(url_for) }}
+
{{ form.csrf_token }} @@ -16,8 +16,8 @@ - {{ footer() }} -
+ +
{{ footer() }}
\ No newline at end of file diff --git a/app/templates/macros.j2 b/app/templates/macros.j2 index 4fe35f0..17a2940 100644 --- a/app/templates/macros.j2 +++ b/app/templates/macros.j2 @@ -1,11 +1,11 @@ {% macro court_button(court) -%} - {%- endmacro %} {% macro player_button(player) -%} - {%- endmacro %} @@ -16,56 +16,30 @@ Match Up! - + - {%- endmacro %} {% macro footer() -%} -
Made by Karan using Flask, HTMX, Notyf and Bulma
+
Made by Karan with
{%- endmacro %} + {% macro navbar(url_for) -%} -

Timer

-
- - - - - +
+
+ + + +
+
+
+ +
\ No newline at end of file diff --git a/app/templates/players.j2 b/app/templates/players.j2 index f10b0a9..4b9660e 100644 --- a/app/templates/players.j2 +++ b/app/templates/players.j2 @@ -18,30 +18,33 @@ {% endfor %}

Controls

-
-
- -
-
-
-
- - -
-
-
-
{{ footer() }}
-
+
+ +
+

Player Update

+
+
+
+ + +
+
+
+
{{ footer() }}
+ \ No newline at end of file -- cgit v1.3.1 From 63e1b52e1b76e136e6534949980d85ffe413f0c9 Mon Sep 17 00:00:00 2001 From: Karan Jayachandra Date: Fri, 25 Jul 2025 16:06:20 +0200 Subject: Working mobile and desktop version --- app/__init__.py | 3 +- app/static/custom.js | 91 ----------------------------------------------- app/static/file.js | 11 ++++++ app/static/timer.js | 91 +++++++++++++++++++++++++++++++++++++++++++++++ app/templates/controls.j2 | 12 +++---- app/templates/games.j2 | 2 +- app/templates/index.j2 | 4 +-- app/templates/macros.j2 | 4 +-- app/templates/players.j2 | 14 ++------ 9 files changed, 117 insertions(+), 115 deletions(-) delete mode 100644 app/static/custom.js create mode 100644 app/static/file.js create mode 100644 app/static/timer.js (limited to 'app/static') diff --git a/app/__init__.py b/app/__init__.py index 639f030..0e0ea09 100644 --- a/app/__init__.py +++ b/app/__init__.py @@ -31,7 +31,7 @@ g = Session() @app.route("/", methods=["GET"]) def home(): - return render_template("index.j2", url_for=url_for) + return render_template("index.j2", url_for=url_for, login_status=is_logged_in()) @app.route("/control", methods=["GET"]) @@ -46,6 +46,7 @@ def get_list_of_players(): regulars=g.players.regulars(), guests=g.players.guests(), url_for=url_for, + login_status=is_logged_in(), ) diff --git a/app/static/custom.js b/app/static/custom.js deleted file mode 100644 index 3daeb17..0000000 --- a/app/static/custom.js +++ /dev/null @@ -1,91 +0,0 @@ -let minsPerRound = Number(sessionStorage.getItem("minsPerRound")) || 12; -let timerRunningFlag = Number(sessionStorage.getItem("timerRunningFlag")) || 0; -let deadline = Number(sessionStorage.getItem("deadline")) || new Date().getTime(); -let clock = 0; - -function setTimer(m, s) { - let timer = document.getElementById("timer-display"); - m = m < 10 ? ("0" + m) : m; - s = s < 10 ? ("0" + s) : s; - timer.value = `${m}:${s}`; -} - -function setSessionData() { - sessionStorage.setItem("deadline", deadline); - sessionStorage.setItem("minsPerRound", minsPerRound); - sessionStorage.setItem("timerRunningFlag", timerRunningFlag); -} - -function resetTimer() { - clearInterval(clock); - setTimer(minsPerRound, 0); - timerRunningFlag = 0; - setSessionData(); -} - -function updateTimer(milliseconds) { - const m = Math.floor((milliseconds % (1000 * 60 * 60)) / (1000 * 60)); - const s = Math.floor((milliseconds % (1000 * 60)) / 1000); - setTimer(m, s); -} - -function refreshTimer() { - const now = new Date().getTime(); - const millisecondsToDeadline = deadline - now; - if (millisecondsToDeadline > 0) { - updateTimer(millisecondsToDeadline); - return; - } - resetTimer(); - const notification = new Notyf({ - duration: 30 * 1000, - position: {x: 'center', y: 'top'}, - types: [{ - type: 'success', - background: 'indianred', - duration: 1000 * 1000, - dismissible: true - }] - }); - notification.success("Round completed"); -} - -function startTimer(fresh) { - if (fresh) { - now = new Date().getTime(); - const millisecondsToDeadline = minsPerRound * 60 * 1000; - deadline = now + millisecondsToDeadline; - } - timerRunningFlag = 1; - setSessionData(); - clock = setInterval(refreshTimer, 1000); -} - -window.onload = function () { - if (timerRunningFlag) - startTimer(0); - else resetTimer(); - - document.getElementById("timer-start").addEventListener('click', ()=> { - if (timerRunningFlag != 0) return; - startTimer(1); - }); - - document.getElementById("timer-stop").addEventListener('click', ()=>{ - resetTimer(); - }); - - document.getElementById("timer-inc").addEventListener('click', ()=> { - if (timerRunningFlag == 0) { - minsPerRound += 1; - resetTimer(); - } - }); - - document.getElementById("timer-dec").addEventListener('click', ()=> { - if (timerRunningFlag == 0 && minsPerRound != 0) { - minsPerRound -= 1; - resetTimer(); - } - }); -} \ No newline at end of file diff --git a/app/static/file.js b/app/static/file.js new file mode 100644 index 0000000..403ddf6 --- /dev/null +++ b/app/static/file.js @@ -0,0 +1,11 @@ +window.onload = function() { + const fileInput = document.querySelector("#file-js input[type=file]"); + if (fileInput !== null) { + fileInput.onchange = () => { + if (fileInput.files.length > 0) { + const fileName = document.querySelector("#file-js .file-name"); + fileName.textContent = fileInput.files[0].name; + } + } + }; +} \ No newline at end of file diff --git a/app/static/timer.js b/app/static/timer.js new file mode 100644 index 0000000..e8e7854 --- /dev/null +++ b/app/static/timer.js @@ -0,0 +1,91 @@ +let minsPerRound = Number(sessionStorage.getItem("minsPerRound")) || 12; +let timerRunningFlag = Number(sessionStorage.getItem("timerRunningFlag")) || 0; +let deadline = Number(sessionStorage.getItem("deadline")) || new Date().getTime(); +let clock = 0; + +function setTimer(m, s) { + let timer = document.getElementById("timer-display"); + m = m < 10 ? ("0" + m) : m; + s = s < 10 ? ("0" + s) : s; + timer.value = `${m}:${s}`; +} + +function setSessionData() { + sessionStorage.setItem("deadline", deadline); + sessionStorage.setItem("minsPerRound", minsPerRound); + sessionStorage.setItem("timerRunningFlag", timerRunningFlag); +} + +function resetTimer() { + clearInterval(clock); + setTimer(minsPerRound, 0); + timerRunningFlag = 0; + setSessionData(); +} + +function updateTimer(milliseconds) { + const m = Math.floor((milliseconds % (1000 * 60 * 60)) / (1000 * 60)); + const s = Math.floor((milliseconds % (1000 * 60)) / 1000); + setTimer(m, s); +} + +function refreshTimer() { + const now = new Date().getTime(); + const millisecondsToDeadline = deadline - now; + if (millisecondsToDeadline > 0) { + updateTimer(millisecondsToDeadline); + return; + } + resetTimer(); + const notification = new Notyf({ + duration: 30 * 1000, + position: {x: 'center', y: 'top'}, + types: [{ + type: 'success', + background: 'indianred', + duration: 1000 * 1000, + dismissible: true + }] + }); + notification.success("Round completed"); +} + +function startTimer(fresh) { + if (fresh) { + now = new Date().getTime(); + const millisecondsToDeadline = minsPerRound * 60 * 1000; + deadline = now + millisecondsToDeadline; + } + timerRunningFlag = 1; + setSessionData(); + clock = setInterval(refreshTimer, 1000); +} + +window.onload = function () { + if (timerRunningFlag) + startTimer(0); + else resetTimer(); + + document.getElementById("timer-start").addEventListener('click', ()=> { + if (timerRunningFlag != 0) return; + startTimer(1); + }); + + document.getElementById("timer-stop").addEventListener('click', ()=>{ + resetTimer(); + }); + + document.getElementById("timer-inc").addEventListener('click', ()=> { + if (timerRunningFlag == 0) { + minsPerRound += 1; + resetTimer(); + } + }); + + document.getElementById("timer-dec").addEventListener('click', ()=> { + if (timerRunningFlag == 0 && minsPerRound != 0) { + minsPerRound -= 1; + resetTimer(); + } + }); +} \ No newline at end of file diff --git a/app/templates/controls.j2 b/app/templates/controls.j2 index 14e7520..8e7440e 100644 --- a/app/templates/controls.j2 +++ b/app/templates/controls.j2 @@ -1,10 +1,4 @@ {% from "macros.j2" import court_button %} -

Courts

-
-{% for court in courts %} - {{ court_button(court) }} -{% endfor %} -

Generation

@@ -47,4 +41,10 @@
+
+

Courts

+
+{% for court in courts %} + {{ court_button(court) }} +{% endfor %}
\ No newline at end of file diff --git a/app/templates/games.j2 b/app/templates/games.j2 index ce2a412..5041ce1 100644 --- a/app/templates/games.j2 +++ b/app/templates/games.j2 @@ -10,7 +10,7 @@ {% for game in games %} - + {{ game.court.id }} {{ game.team_1[0].first_name }}{{ " " + game.team_1[0].last_name }} {{ game.team_1[1].first_name }}{{ " " + game.team_1[1].last_name }} diff --git a/app/templates/index.j2 b/app/templates/index.j2 index 8a13fa0..af6ca4c 100644 --- a/app/templates/index.j2 +++ b/app/templates/index.j2 @@ -3,7 +3,7 @@ {{ header(url_for) }} -
{{ navbar(url_for) }}
+
{{ navbar(url_for, login_status) }}

Games

@@ -11,6 +11,6 @@
{{ footer() }}
- + diff --git a/app/templates/macros.j2 b/app/templates/macros.j2 index 17a2940..e82b910 100644 --- a/app/templates/macros.j2 +++ b/app/templates/macros.j2 @@ -31,7 +31,7 @@ {%- endmacro %} -{% macro navbar(url_for) -%} +{% macro navbar(url_for, login_status) -%} {%- endmacro %} \ No newline at end of file diff --git a/app/templates/players.j2 b/app/templates/players.j2 index 4b9660e..bacb215 100644 --- a/app/templates/players.j2 +++ b/app/templates/players.j2 @@ -3,7 +3,7 @@ {{ header(url_for) }} -
{{ navbar(url_for) }}
+
{{ navbar(url_for, login_status) }}

Members

@@ -34,17 +34,7 @@
{{ footer() }}
- +
\ No newline at end of file -- cgit v1.3.1 From 38f099ae6ec7e7ae7338402a03654ee6378e4274 Mon Sep 17 00:00:00 2001 From: Karan Jayachandra Date: Fri, 25 Jul 2025 16:35:33 +0200 Subject: Finally happy with the work --- app/static/custom.css | 12 ++++++++++-- app/templates/controls.j2 | 46 ++++++++++++++++++++++------------------------ app/templates/games.j2 | 42 ++++++++++++++++++++---------------------- 3 files changed, 52 insertions(+), 48 deletions(-) (limited to 'app/static') diff --git a/app/static/custom.css b/app/static/custom.css index 8aa5b57..a5ca36f 100644 --- a/app/static/custom.css +++ b/app/static/custom.css @@ -12,15 +12,23 @@ td { footer { text-align: center; } -.parent { +.parent, .timer { display: grid; grid-column-gap: 20px; grid-row-gap: 20px; margin-top: 20px; margin-bottom: 20px; + grid-auto-columns: 1fr; + grid-auto-rows: 1fr; } -@media (min-width: 800px) { +@media (min-width: 900px) { + table { + font-size: xx-large; + } .parent { grid-template-columns: repeat(4, 1fr); } + .timer { + grid-template-columns: 4fr repeat(2, 1fr); + } } diff --git a/app/templates/controls.j2 b/app/templates/controls.j2 index 8e7440e..97351bf 100644 --- a/app/templates/controls.j2 +++ b/app/templates/controls.j2 @@ -1,5 +1,27 @@ {% from "macros.j2" import court_button %} +

Timer

+
+
+ + + +
+ + +

Generation

+
+ + + +
-
- - - -
-

Timer

-
-
- - - -
-
-
- - -

Courts

{% for court in courts %} diff --git a/app/templates/games.j2 b/app/templates/games.j2 index 5041ce1..00ffb71 100644 --- a/app/templates/games.j2 +++ b/app/templates/games.j2 @@ -1,23 +1,21 @@ -
- - - - - - - - - - -{% for game in games %} - - - -{% endfor %} - -
{{ title }}
Court Team 1 Team 2
{{ game.court.id }}{{ game.team_1[0].first_name }}{{ " " + game.team_1[0].last_name }} - {{ game.team_1[1].first_name }}{{ " " + game.team_1[1].last_name }} - {{ game.team_2[0].first_name }}{{ " " + game.team_2[0].last_name }} - {{ game.team_2[1].first_name }}{{ " " + game.team_2[1].last_name }} -
+
+

{{ title }}

+ + + + + + + + {% for game in games %} + + + {% endfor %} + +
Court Team 1 Team 2
{{ game.court.id }} + {{ game.team_1[0].first_name }}{{ " " + game.team_1[0].last_name }} + {{ game.team_1[1].first_name }}{{ " " + game.team_1[1].last_name }} + {{ game.team_2[0].first_name }}{{ " " + game.team_2[0].last_name }} + {{ game.team_2[1].first_name }}{{ " " + game.team_2[1].last_name }} +
\ No newline at end of file -- cgit v1.3.1