mirror of
https://github.com/iritmaximus/timetrials.git
synced 2026-10-13 03:23:47 +03:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0aef3a64b7 | ||
|
|
4e2415e8c1 | ||
|
|
21140d3477 | ||
|
|
774bb5f453 | ||
|
|
7cbd4d6835 | ||
|
|
34d027b161 | ||
|
|
b58ffef8f2 | ||
|
|
9bb7b27e99 | ||
|
|
1d4a1febeb | ||
|
|
333abd90e5 | ||
|
|
4f8938bab2 | ||
|
|
17e9878dfa | ||
|
|
f9b1683816 | ||
|
|
fbd97abb19 | ||
|
|
4df72b9288 | ||
|
|
32f07af85c | ||
|
|
b6a66b5be5 | ||
|
|
f835b6b197 | ||
|
|
8ccaaa1438 | ||
|
|
a88ac13dd3 | ||
|
|
9c8ce39d04 | ||
|
|
45c84cc0d9 | ||
|
|
8ed709a5e7 | ||
|
|
97cd806b88 |
@@ -0,0 +1,41 @@
|
||||
name: Build and deploy containers
|
||||
|
||||
on:
|
||||
release:
|
||||
types: [published]
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
|
||||
env:
|
||||
IMAGE_NAME: ${{ github.event_name == 'release' && 'timetrials' || 'timetrials-staging' }}
|
||||
|
||||
jobs:
|
||||
build_timetrials:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Extract Docker image metadata
|
||||
id: meta
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: "${{ vars.DOCKER_USERNAME }}/${{ env.IMAGE_NAME }}"
|
||||
# images: "${{ vars.DOCKER_USERNAME }}/${IMAGE_NAME}"
|
||||
|
||||
- name: Log in to Docker Hub
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ vars.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Build and push Docker image
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: "{{defaultContext}}"
|
||||
push: ${{ github.event_name != 'pull_request' }}
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
annotations: ${{ steps.meta.outputs.annotations }}
|
||||
@@ -1,40 +0,0 @@
|
||||
name: Deploy to fly.io and create version
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
|
||||
env:
|
||||
FLY_API_TOKEN: ${{ secrets.FLY_API_TOKEN }}
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
WITH_V: true
|
||||
DEFAULT_BUMP: patch
|
||||
MAJOR_STRING_TOKEN: "release:"
|
||||
MINOR_STRING_TOKEN: "feat:"
|
||||
PATCH_STRING_TOKEN: "fix:"
|
||||
NONE_STRING_TOKEN: "none:"
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
jobs:
|
||||
bump-version:
|
||||
runs-on: ubuntu-latest
|
||||
needs: [deploy]
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: '0'
|
||||
|
||||
- name: Bump version and push tag
|
||||
uses: anothrNick/github-tag-action@1.61.0
|
||||
|
||||
|
||||
deploy:
|
||||
name: Deploy app
|
||||
runs-on: ubuntu-latest
|
||||
environment: production
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: superfly/flyctl-actions/setup-flyctl@master
|
||||
- run: flyctl deploy --remote-only
|
||||
+21
-6
@@ -1,11 +1,26 @@
|
||||
# syntax=docker/dockerfile:1
|
||||
FROM python:alpine
|
||||
WORKDIR /app
|
||||
FROM python:3.10-alpine
|
||||
RUN pip install --upgrade pip
|
||||
|
||||
COPY requirements.txt requirements.txt
|
||||
RUN pip3 install -r requirements.txt
|
||||
RUN adduser -D nonroot
|
||||
RUN mkdir /home/app/ && chown -R nonroot:nonroot /home/app
|
||||
WORKDIR /home/app
|
||||
USER nonroot
|
||||
|
||||
COPY . .
|
||||
COPY --chown=nonroot:nonroot requirements.txt requirements.txt
|
||||
|
||||
CMD [ "gunicorn", "-w", "4", "flaskr:app", "-b", "0.0.0.0:5000", "--access-logfile", "-", "--error-logfile", "-"]
|
||||
# venv
|
||||
ENV VIRTUAL_ENV=/home/app/venv
|
||||
|
||||
# python setup
|
||||
RUN python -m venv $VIRTUAL_ENV
|
||||
ENV PATH="$VIRTUAL_ENV/bin:$PATH"
|
||||
RUN export FLASK_APP=__init__.py
|
||||
RUN pip install -r requirements.txt
|
||||
|
||||
COPY --chown=nonroot:nonroot flaskr flaskr
|
||||
|
||||
ENTRYPOINT ["gunicorn"]
|
||||
CMD [ "-w", "4", "flaskr:app", "-b", "0.0.0.0:5000", "--access-logfile", "-", "--error-logfile", "-"]
|
||||
# CMD ["python", "run.py"]
|
||||
# CMD [ "gunicorn", "-w", "4", "flaskr:app", "-b", "0.0.0.0:5000"]
|
||||
|
||||
@@ -16,13 +16,14 @@ The database will be PostgreSQL-based database hosted on fly.io.
|
||||
* games
|
||||
* cups
|
||||
* courses
|
||||
* standards
|
||||
* times
|
||||
|
||||
### Fancier db things
|
||||
* authenticated user can add times and edit old ones TODO
|
||||
* other boring user/account things, can login
|
||||
* can sort times by game, track, time and other things TODO
|
||||
* user can log in and create new times.
|
||||
* can see times by game, cup and course.
|
||||
* the site tells how many times there are for each category.
|
||||
* can click on individual courses, cups or games to see all the times in the selected category
|
||||
|
||||
|
||||
### Välipalautus 3
|
||||
Most of the fancier db things are todo. This is sort of the MVP (minimun viable product).
|
||||
@@ -30,16 +31,13 @@ Most of the fancier db things are todo. This is sort of the MVP (minimun viable
|
||||
|
||||
## Deployment
|
||||
|
||||
The site is being deployed at https://tsoha-flask.fly.dev/
|
||||
~~The site is being deployed at https://tsoha-flask.fly.dev/~~
|
||||
|
||||
## Routes
|
||||
|
||||
### GET https://tsoha-flask.fly.dev/
|
||||
Works as the main page, can navigate to other sites.
|
||||
|
||||
### GET [db](https://tsoha-flask.fly.dev/db)
|
||||
Just to test if the db works (at the moment)
|
||||
|
||||
### GET [games](https://tsoha-flask.fly.dev/games)
|
||||
List of games.
|
||||
|
||||
@@ -47,7 +45,7 @@ List of games.
|
||||
List of cups
|
||||
|
||||
### GET [courses](https://tsoha-flask.fly.dev/courses)
|
||||
TODO list of all courses.
|
||||
List of all courses.
|
||||
|
||||
### GET [login](https://tsoha-flask.fly.dev/login)
|
||||
Login page to the site. You will be redirected here, if you try to access other pages without a session (login in).
|
||||
@@ -58,8 +56,51 @@ List of all times submitted by the players. There is also a button to add new ti
|
||||
### GET [create/time](https://tsoha-flask.fly.dev/create/time)
|
||||
A page where you can submit new times, you have to be logged in for the submission to go through.
|
||||
|
||||
|
||||
### GET [api/(game/cup/course)/id](https://tsoha-flask.fly.dev/api/)
|
||||
You will be redirected to some of these from clicking any of the corresponding fields in the times.
|
||||
|
||||
## Note
|
||||
If you get an error ´sqlalchemy.exc.NoSuchModuleError: Can't load plugin: sqlalchemy.dialects:postgres´,
|
||||
change your url from ´postgres://´ to ´postgresql://´.
|
||||
If you get an error `sqlalchemy.exc.NoSuchModuleError: Can't load plugin: sqlalchemy.dialects:postgres`,
|
||||
change your url from `postgres://` to `postgresql://`.
|
||||
|
||||
## Local dev
|
||||
### Requirements
|
||||
If you want to run this locally, you need
|
||||
* Virtual environment
|
||||
* Proper .env file
|
||||
* Docker and docker-compose installed (optional)
|
||||
|
||||
### Setting up
|
||||
* Venv (virtual environment) can be achieved through running `python -m venv .venv` in the `timetrials` directory.
|
||||
This will create the venv file to `timetrials/.venv` (a hidden file).
|
||||
* `.env` needs to contain `POSTGRES_URL` and `SECRET_KEY`
|
||||
- The `POSTGRES_URL` needs to be the full url to your postgres database, containing user, password and database
|
||||
- `SECRET_KEY` is some random string that you need to create. One simple way is to launch the python interactive prompt with
|
||||
```bash
|
||||
python
|
||||
```
|
||||
and then run the commands
|
||||
```python
|
||||
>>> import secrets
|
||||
>>> secrets.token_hex(16)
|
||||
```
|
||||
and copy the result to the `SECRET_KEY` variable.
|
||||
|
||||
After that you can either build the app by running
|
||||
```bash
|
||||
docker-compose up -d
|
||||
```
|
||||
|
||||
If you don't have or don't want to use docker, you can activate the venv by calling
|
||||
```bash
|
||||
source .venv/bin/activate
|
||||
```
|
||||
(google the proper way to do it if you are on Windows).
|
||||
Then install the requirements with pip
|
||||
```bash
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
and then you can just run the command
|
||||
```bash
|
||||
python run.py
|
||||
```
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
services:
|
||||
flask:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
# command: sh -c "gunicorn -w 4 flaskr:app -b 0.0.0.0:5000 --access-logfile '-' --error-logfile '-'"
|
||||
# command: sh -c "ls"
|
||||
ports:
|
||||
- "5000:5000"
|
||||
volumes:
|
||||
- .:/app
|
||||
env_file: .env
|
||||
environment:
|
||||
- POSTGRES_DB
|
||||
- POSTGRES_PORT
|
||||
- POSTGRES_HOST
|
||||
- POSTGRES_USER
|
||||
- POSTGRES_PASSWORD
|
||||
# extra_hosts:
|
||||
# - "host.docker.internal:host-gateway"
|
||||
depends_on:
|
||||
- db
|
||||
|
||||
db:
|
||||
image: postgres:16-alpine
|
||||
volumes:
|
||||
- ./data/:/var/lib/postgresql/data
|
||||
environment:
|
||||
- POSTGRES_DB=timetrials-db
|
||||
- POSTGRES_PORT=5432
|
||||
- POSTGRES_HOST=db
|
||||
- POSTGRES_USER=postgres
|
||||
- POSTGRES_PASSWORD=postgres
|
||||
healthcheck:
|
||||
test: pg_isready -U postgres -d timetrials-db
|
||||
interval: 10s
|
||||
timeout: 3s
|
||||
retries: 3
|
||||
@@ -1,12 +0,0 @@
|
||||
services:
|
||||
flask:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
ports:
|
||||
- "5000:5000"
|
||||
volumes:
|
||||
- .:/app
|
||||
env_file: .env
|
||||
environment:
|
||||
- POSTGRES_URL
|
||||
@@ -7,6 +7,23 @@ load_dotenv()
|
||||
app = Flask(__name__)
|
||||
app.config["SECRET_KEY"] = getenv("SECRET_KEY")
|
||||
|
||||
if getenv("POSTGRES_URL") and getenv("POSTGRES_URL").startswith("postgresql://"):
|
||||
app.config["SQLALCHEMY_DATABASE_URI"] = getenv("POSTGRES_URL")
|
||||
else:
|
||||
postgres_host = getenv("POSTGRES_HOST")
|
||||
postgres_db = getenv("POSTGRES_DB")
|
||||
postgres_port = getenv("POSTGRES_PORT")
|
||||
postgres_user = getenv("POSTGRES_USER")
|
||||
postgres_password = getenv("POSTGRES_PASSWORD")
|
||||
postgres_variables = [postgres_host, postgres_db, postgres_port, postgres_user, postgres_password]
|
||||
|
||||
for var in postgres_variables:
|
||||
if not var:
|
||||
raise ValueError("All environment variables not set")
|
||||
|
||||
database_url = f"postgresql://{postgres_user}:{postgres_password}@{postgres_host}:{postgres_port}/{postgres_db}"
|
||||
app.config["SQLALCHEMY_DATABASE_URI"] = database_url
|
||||
|
||||
|
||||
# import flaskr.views
|
||||
import flaskr.views.home
|
||||
|
||||
+3
-2
@@ -4,10 +4,8 @@ from flask_sqlalchemy import SQLAlchemy
|
||||
from random import randint
|
||||
|
||||
|
||||
app.config["SQLALCHEMY_DATABASE_URI"] = getenv("POSTGRES_URL")
|
||||
db = SQLAlchemy(app)
|
||||
|
||||
|
||||
def create_db():
|
||||
print("Initializing the db...")
|
||||
db.session.execute(open("sql/schema.sql", "r").read())
|
||||
@@ -15,6 +13,7 @@ def create_db():
|
||||
db.session.execute(open("sql/cups.sql", "r").read())
|
||||
db.session.execute(open("sql/courses.sql", "r").read())
|
||||
db.session.commit()
|
||||
db.session.close()
|
||||
print("Db initialization completed.")
|
||||
|
||||
return "Success"
|
||||
@@ -29,6 +28,7 @@ def reset_db():
|
||||
db.session.execute(open("sql/cups.sql", "r").read())
|
||||
db.session.execute(open("sql/courses.sql", "r").read())
|
||||
db.session.commit()
|
||||
db.session.close()
|
||||
|
||||
|
||||
def test_db():
|
||||
@@ -49,6 +49,7 @@ def test_db():
|
||||
db.session.commit()
|
||||
|
||||
result = db.session.execute("SELECT * FROM test;").fetchall()
|
||||
db.session.close()
|
||||
print(result)
|
||||
|
||||
return "Working lol"
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
<h1>Add time</h1>
|
||||
|
||||
<form action="/create/time" method="POST">
|
||||
<form name="addNewTime" action="/create/time" method="POST">
|
||||
<label for="game">Game:</label>
|
||||
<input type="text" name="game" required>
|
||||
<label for="course">Course:</label>
|
||||
<input type="text" name="course" required>
|
||||
<label for="time">Time (mm:ss:mss):</label>
|
||||
<input type="text" name="time" required>
|
||||
<input type="text" name="time" required pattern="/\d{0,2}:[0-5]\d:\d\d\/">
|
||||
<input type="submit" name="time">
|
||||
</form>
|
||||
|
||||
@@ -18,8 +18,8 @@ table, tr, td {
|
||||
</tr>
|
||||
{% for time in times %}
|
||||
<tr>
|
||||
<td>{{time[0]}}</td>
|
||||
<td>{{time[1]}}</td>
|
||||
<td><a href="/api/game/{{time[0].replace(' ', '%20')}}">{{time[0]}}</a></td>
|
||||
<td><a href="/api/cup/{{time[1].replace(' ', '%20')}}">{{time[1]}}</a></td>
|
||||
<td>{{time[2]}}</td>
|
||||
<td>{{time[3]}}</td>
|
||||
</tr>
|
||||
|
||||
@@ -8,22 +8,23 @@ table, tr, td {
|
||||
}
|
||||
</style>
|
||||
|
||||
<p>There is {{count}} times in {{cup_name}}</p>
|
||||
|
||||
<h2>Times</h2>
|
||||
<table>
|
||||
<tr>
|
||||
<td>Time</td>
|
||||
<td>Course</td>
|
||||
<td>Cup</td>
|
||||
<td>Game</td>
|
||||
<td>Time</td>
|
||||
<td>User</td>
|
||||
</tr>
|
||||
{% if times_exist %}
|
||||
{% for time in times %}
|
||||
<tr>
|
||||
<td>{{time[0]}}</td>
|
||||
<td><a href="/api/course/{{item[1].replace(' ', '%20')}}">{{time[1]}}</a></td>
|
||||
<td><a href="/api/cup/{{item[2].replace(' ', '%20')}}">{{time[2]}}</a></td>
|
||||
<td><a href="/api/game/{{item[3].replace(' ', '%20')}}">{{time[3]}}</a></td>
|
||||
<td><a href="/api/course/{{time[0].replace(' ', '%20')}}">{{time[0]}}</a></td>
|
||||
<td><a href="/api/game/{{time[1].replace(' ', '%20')}}">{{time[1]}}</a></td>
|
||||
<td>{{time[2]}}</td>
|
||||
<td>{{time[3]}}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
@@ -8,6 +8,8 @@ table, tr, td {
|
||||
}
|
||||
</style>
|
||||
|
||||
<p>There is {{count}} cups</p>
|
||||
|
||||
<table>
|
||||
{% if cups_exist %}
|
||||
<tr>
|
||||
|
||||
@@ -8,6 +8,8 @@ table, tr, td {
|
||||
}
|
||||
</style>
|
||||
|
||||
<p>There is {{count}} times in {{game_name}}</p>
|
||||
|
||||
<h2>Times</h2>
|
||||
<table>
|
||||
<tr>
|
||||
@@ -19,8 +21,8 @@ table, tr, td {
|
||||
{% if times_exist %}
|
||||
{% for time in times %}
|
||||
<tr>
|
||||
<td>{{time[0]}}</td>
|
||||
<td>{{time[1]}}</td>
|
||||
<td><a href="/api/course/{{time[0].replace(' ', '%20')}}">{{time[0]}}</a></td>
|
||||
<td><a href="/api/cup/{{time[1].replace(' ', '%20')}}">{{time[1]}}</a></td>
|
||||
<td>{{time[2]}}</td>
|
||||
<td>{{time[3]}}</td>
|
||||
</tr>
|
||||
|
||||
@@ -8,6 +8,8 @@ table, tr, td {
|
||||
}
|
||||
</style>
|
||||
|
||||
<p>There is {{count}} games.</p>
|
||||
|
||||
<table>
|
||||
{% if games_exist %}
|
||||
<tr>
|
||||
|
||||
@@ -14,17 +14,17 @@ table, tr, td {
|
||||
<table style="border:1px solid black">
|
||||
{% if times_exist %}
|
||||
<tr>
|
||||
<td>Course</td>
|
||||
<td>Game</td>
|
||||
<td>Course</td>
|
||||
<td>Time</td>
|
||||
<td>User</td>
|
||||
</tr>
|
||||
{% for item in times %}
|
||||
<tr>
|
||||
<td>{{item[0]}}</td>
|
||||
<td>{{item[1]}}</td>
|
||||
<td><a href="/api/game/{{item[0].replace(' ', '%20')}}">{{item[0]}}</a></td>
|
||||
<td><a href="/api/course/{{item[1].replace(' ', '%20')}}">{{item[1]}}</a></td>
|
||||
<td>{{item[2]}}</td>
|
||||
<td>{{item[3]}}</td>
|
||||
<td>{{item[3]}}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
@@ -10,6 +10,7 @@ def query_courses():
|
||||
result = db.session.execute(sql).fetchall()
|
||||
sql = "SELECT count(courses.id) FROM courses"
|
||||
count = db.session.execute(sql).fetchone()
|
||||
db.session.close()
|
||||
return result, count[0]
|
||||
|
||||
|
||||
@@ -23,4 +24,5 @@ def query_course_by_name(course_name: str):
|
||||
WHERE times.course_id in (SELECT id FROM courses WHERE name=:course_name)
|
||||
"""
|
||||
result = db.session.execute(sql, {"course_name": course_name}).fetchall()
|
||||
db.session.close()
|
||||
return result
|
||||
|
||||
+11
-4
@@ -4,7 +4,10 @@ from flaskr.database import db
|
||||
def query_cups():
|
||||
sql = "SELECT name, id FROM cups"
|
||||
result = db.session.execute(sql).fetchall()
|
||||
return result
|
||||
sql = "SELECT count(cups.id) FROM cups"
|
||||
count = db.session.execute(sql).fetchone()
|
||||
db.session.close()
|
||||
return result, count[0]
|
||||
|
||||
|
||||
def query_cup_by_name(cup_name: str):
|
||||
@@ -12,6 +15,7 @@ def query_cup_by_name(cup_name: str):
|
||||
SELECT cups.id FROM cups WHERE cups.name=:cup_name
|
||||
"""
|
||||
result = db.session.execute(sql, {"cup_name": cup_name}).fetchone()
|
||||
db.session.close()
|
||||
if result:
|
||||
return result[0]
|
||||
else:
|
||||
@@ -30,13 +34,14 @@ def get_cup_name(id: int):
|
||||
def get_cup_id(course_id: int):
|
||||
sql = "SELECT cups_id FROM courses WHERE id=:course_id"
|
||||
result = db.session.execute(sql, {"course_id": course_id}).fetchall()
|
||||
db.session.close()
|
||||
if result:
|
||||
return result[0]
|
||||
else:
|
||||
raise ValueError("No cup found for current course")
|
||||
|
||||
|
||||
def get_all_times_in_cup(id: int) -> list[str]:
|
||||
def get_all_times_in_cup(id: int):
|
||||
"""Queries the database for all times made in the wanted cup"""
|
||||
|
||||
sql = """
|
||||
@@ -47,6 +52,8 @@ def get_all_times_in_cup(id: int) -> list[str]:
|
||||
JOIN users ON times.user_id=users.id
|
||||
WHERE times.cup_id=:id
|
||||
"""
|
||||
|
||||
result = db.session.execute(sql, {"id": id}).fetchall()
|
||||
return result
|
||||
sql = "SELECT count(times.id) FROM times WHERE times.cup_id=:id"
|
||||
count = db.session.execute(sql, {"id": id}).fetchone()
|
||||
db.session.close()
|
||||
return result, count[0]
|
||||
|
||||
+10
-2
@@ -4,12 +4,16 @@ from flaskr.database import db
|
||||
def query_games():
|
||||
sql = "SELECT name, id FROM games"
|
||||
result = db.session.execute(sql).fetchall()
|
||||
return result
|
||||
sql = "SELECT count(games.id) FROM games"
|
||||
count = db.session.execute(sql).fetchone()
|
||||
db.session.close()
|
||||
return result, count[0]
|
||||
|
||||
|
||||
def query_game_by_name(game_name: str):
|
||||
sql = "SELECT id FROM games WHERE games.name=:game_name"
|
||||
result = db.session.execute(sql, {"game_name": game_name}).fetchone()
|
||||
db.session.close()
|
||||
if result:
|
||||
return result[0]
|
||||
else:
|
||||
@@ -19,6 +23,7 @@ def query_game_by_name(game_name: str):
|
||||
def get_game_name(id: int):
|
||||
sql = f"SELECT name FROM games WHERE id=:id"
|
||||
result = db.session.execute(sql, {"id": id}).fetchone()
|
||||
db.session.close()
|
||||
if result:
|
||||
return result[0]
|
||||
else:
|
||||
@@ -35,4 +40,7 @@ def get_all_times_in_game(id: int):
|
||||
WHERE times.game_id=:id
|
||||
"""
|
||||
results = db.session.execute(sql, {"id": id}).fetchall()
|
||||
return results
|
||||
sql = "SELECT count(times.id) FROM times WHERE times.game_id=:id"
|
||||
count = db.session.execute(sql, {"id": id}).fetchone()
|
||||
db.session.close()
|
||||
return results, count[0]
|
||||
|
||||
@@ -4,6 +4,7 @@ from flaskr.database import db
|
||||
def query_times():
|
||||
sql = "SELECT games.name, courses.name, times.timems, users.username FROM times JOIN games ON games.id=times.game_id JOIN courses ON courses.id=times.course_id JOIN users ON users.id=times.user_id"
|
||||
result = db.session.execute(sql).fetchall()
|
||||
db.session.close()
|
||||
print(result)
|
||||
return result
|
||||
|
||||
@@ -49,3 +50,4 @@ def add_time(game, course, time, user):
|
||||
},
|
||||
)
|
||||
db.session.commit()
|
||||
db.session.close()
|
||||
|
||||
@@ -25,6 +25,7 @@ def user_login(name: str, password: str) -> bool:
|
||||
print("checking if username exists")
|
||||
sql = "SELECT password FROM users as u where u.username=:username"
|
||||
result = db.session.execute(sql, {"username": name}).fetchone()
|
||||
db.session.close()
|
||||
print("password:", result)
|
||||
if result is None:
|
||||
return False
|
||||
@@ -40,6 +41,7 @@ def user_login(name: str, password: str) -> bool:
|
||||
def check_username_exists(username: str) -> bool:
|
||||
sql = "SELECT COUNT(*) FROM users as u WHERE u.username=:username"
|
||||
result = db.session.execute(sql, {"username": username}).fetchone()
|
||||
db.session.close()
|
||||
print("result:", result)
|
||||
if result is not None:
|
||||
if result[0] == 0:
|
||||
@@ -61,6 +63,7 @@ def create_new_user(name: str, text_password: str):
|
||||
sql = "INSERT INTO users (username, password) VALUES (:username, :password)"
|
||||
db.session.execute(sql, {"username": username, "password": password})
|
||||
db.session.commit()
|
||||
db.session.close()
|
||||
print("success")
|
||||
|
||||
|
||||
|
||||
@@ -10,10 +10,10 @@ from flaskr.utils.cups import (
|
||||
|
||||
@app.route("/cups")
|
||||
def get_cups():
|
||||
cups = query_cups()
|
||||
cups, count = query_cups()
|
||||
if cups is None:
|
||||
return render_template("cups.html", cups_exist=False)
|
||||
return render_template("cups.html", cups=cups, cups_exist=True)
|
||||
return render_template("cups.html", cups_exist=False, count=count)
|
||||
return render_template("cups.html", cups=cups, cups_exist=True, count=count)
|
||||
|
||||
|
||||
@app.route("/cups/<int:cup_id>")
|
||||
@@ -24,14 +24,15 @@ def get_cup_by_id(cup_id):
|
||||
cup_name = get_cup_name(cup_id)
|
||||
except ValueError as e:
|
||||
return render_template("error.html", message=f"Incorrect id, {e}")
|
||||
times = get_all_times_in_cup(cup_id)
|
||||
print(times)
|
||||
times, count = get_all_times_in_cup(cup_id)
|
||||
if times:
|
||||
return render_template(
|
||||
"cup_id.html", cup_name=cup_name, times=times, times_exist=True
|
||||
"cup_id.html", cup_name=cup_name, times=times, times_exist=True, count=count
|
||||
)
|
||||
else:
|
||||
return render_template("cup_id.html", times_exist=False)
|
||||
return render_template(
|
||||
"cup_id.html", times_exist=False, count=count, cup_name=cup_name
|
||||
)
|
||||
|
||||
|
||||
@app.route("/api/cup/<string:cup_name>")
|
||||
|
||||
@@ -10,10 +10,10 @@ from flaskr.utils.games import (
|
||||
|
||||
@app.route("/games")
|
||||
def get_games():
|
||||
games = query_games()
|
||||
games, count = query_games()
|
||||
if games is None:
|
||||
return render_template("games.html", games_exist=False)
|
||||
return render_template("games.html", games=games, games_exist=True)
|
||||
return render_template("games.html", games_exist=False, count=count)
|
||||
return render_template("games.html", games=games, games_exist=True, count=count)
|
||||
|
||||
|
||||
@app.route("/games/<int:game_id>")
|
||||
@@ -25,9 +25,9 @@ def get_game_by_id(game_id):
|
||||
return render_template(
|
||||
"error.html", message="Incorrect id, id not found or incorrect value"
|
||||
)
|
||||
times = get_all_times_in_game(game_id)
|
||||
times, count = get_all_times_in_game(game_id)
|
||||
return render_template(
|
||||
"game_id.html", times_exist=True, game_name=game_name, times=times
|
||||
"game_id.html", times_exist=True, game_name=game_name, times=times, count=count
|
||||
)
|
||||
|
||||
|
||||
|
||||
+3
-16
@@ -1,7 +1,6 @@
|
||||
from flask import render_template, redirect, url_for
|
||||
|
||||
from flaskr import app
|
||||
from flaskr.database import test_db, create_db, reset_db
|
||||
from flaskr.utils.user import check_session
|
||||
|
||||
|
||||
@@ -12,18 +11,6 @@ def navigate():
|
||||
return render_template("home.html")
|
||||
|
||||
|
||||
# TODO remove these when ready
|
||||
@app.route("/db/init")
|
||||
def initialize_db():
|
||||
return create_db()
|
||||
|
||||
|
||||
@app.route("/db/reset")
|
||||
def reset_database():
|
||||
reset_db()
|
||||
return "Initialization successful"
|
||||
|
||||
|
||||
@app.route("/db")
|
||||
def test_db_route():
|
||||
return test_db()
|
||||
@app.route("/api")
|
||||
def api_help():
|
||||
return "This is the api route. You will end up here from clicking a course, game or cup part of any time."
|
||||
|
||||
Reference in New Issue
Block a user