restructure session management
This commit is contained in:
39
app/crud.py
39
app/crud.py
@@ -1,8 +1,11 @@
|
|||||||
import app.models as models
|
import app.models as models
|
||||||
from sqlalchemy import func
|
from sqlalchemy import func
|
||||||
|
from sqlalchemy.orm.attributes import flag_modified
|
||||||
|
|
||||||
def get_songs_and_vote_for_user(db, user_id) -> list[models.Song]:
|
def get_songs_and_vote_for_session(db, session_name) -> list[models.Song]:
|
||||||
votes = db.query(models.Vote).filter(models.Vote.user_id == user_id).subquery()
|
session_entry = activate_session(db, session_name)
|
||||||
|
|
||||||
|
votes = db.query(models.Vote).filter(models.Vote.session_id == session_entry.id).subquery()
|
||||||
|
|
||||||
songs_and_votes = db.query(
|
songs_and_votes = db.query(
|
||||||
models.Song, votes.c.vote
|
models.Song, votes.c.vote
|
||||||
@@ -58,12 +61,38 @@ def create_song(db,
|
|||||||
db.commit()
|
db.commit()
|
||||||
|
|
||||||
|
|
||||||
def create_or_update_vote(db, song_id, user_id, vote):
|
def create_or_update_vote(db, song_id, session_name, vote):
|
||||||
|
session_entry = activate_session(db, session_name)
|
||||||
|
|
||||||
vote_entry = db.query(models.Vote).filter(
|
vote_entry = db.query(models.Vote).filter(
|
||||||
(models.Vote.user_id == user_id) & (models.Vote.song_id == song_id)).first()
|
(models.Vote.session_id == session_entry.id) & (models.Vote.song_id == song_id)).first()
|
||||||
if vote_entry:
|
if vote_entry:
|
||||||
vote_entry.vote = str(vote) # type: ignore
|
vote_entry.vote = str(vote) # type: ignore
|
||||||
else:
|
else:
|
||||||
vote_entry = models.Vote(song_id=song_id, user_id=user_id, vote=vote)
|
vote_entry = models.Vote(song_id=song_id, session_id=session_entry.id, vote=vote)
|
||||||
db.add(vote_entry)
|
db.add(vote_entry)
|
||||||
db.commit()
|
db.commit()
|
||||||
|
|
||||||
|
|
||||||
|
def activate_session(db, session_name):
|
||||||
|
session_entry = db.query(models.Session).filter(
|
||||||
|
(models.Session.session_name == session_name)).first()
|
||||||
|
if session_entry:
|
||||||
|
session_entry.active = True
|
||||||
|
else:
|
||||||
|
session_entry = models.Session(session_name=session_name, active=True)
|
||||||
|
db.add(session_entry)
|
||||||
|
flag_modified(session_entry, "active")
|
||||||
|
db.commit()
|
||||||
|
|
||||||
|
return session_entry
|
||||||
|
|
||||||
|
def deactivate_session(db, session_name):
|
||||||
|
session_entry = db.query(models.Session).filter(
|
||||||
|
(models.Session.session_name == session_name)).first()
|
||||||
|
if session_entry:
|
||||||
|
session_entry.active = False
|
||||||
|
else:
|
||||||
|
session_entry = models.Session(session_name=session_name, active=False)
|
||||||
|
db.add(session_entry)
|
||||||
|
db.commit()
|
||||||
@@ -1,10 +1,10 @@
|
|||||||
from fastapi import FastAPI, Request, Depends
|
from fastapi import FastAPI, Request, Depends
|
||||||
from app.routers import admin, user, songs
|
from app.routers import admin, user, songs, session
|
||||||
from fastapi.staticfiles import StaticFiles
|
from fastapi.staticfiles import StaticFiles
|
||||||
from fastapi.responses import HTMLResponse
|
from fastapi.responses import HTMLResponse
|
||||||
from fastapi.templating import Jinja2Templates
|
from fastapi.templating import Jinja2Templates
|
||||||
from app.database import engine, Base, get_db
|
from app.database import engine, Base, get_db
|
||||||
from app.crud import get_songs_and_vote_for_user
|
from app.crud import get_songs_and_vote_for_session
|
||||||
from sqlalchemy.orm import Session
|
from sqlalchemy.orm import Session
|
||||||
from typing import Annotated
|
from typing import Annotated
|
||||||
from app.schemas import Song
|
from app.schemas import Song
|
||||||
@@ -16,6 +16,7 @@ app = FastAPI()
|
|||||||
app.include_router(admin.router)
|
app.include_router(admin.router)
|
||||||
app.include_router(user.router)
|
app.include_router(user.router)
|
||||||
app.include_router(songs.router)
|
app.include_router(songs.router)
|
||||||
|
app.include_router(session.router)
|
||||||
|
|
||||||
app.mount("/static", StaticFiles(directory="static"), name="static")
|
app.mount("/static", StaticFiles(directory="static"), name="static")
|
||||||
|
|
||||||
@@ -28,7 +29,7 @@ async def root(request: Request, session_id : str = "", db: Annotated[Session, D
|
|||||||
request=request, name="landing.html"
|
request=request, name="landing.html"
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
songs = [Song(**s.__dict__, vote=v) for s, v in get_songs_and_vote_for_user(db, session_id)]
|
songs = [Song(**s.__dict__, vote=v) for s, v in get_songs_and_vote_for_session(db, session_id)]
|
||||||
|
|
||||||
songs_by_category = {}
|
songs_by_category = {}
|
||||||
all_categories = set()
|
all_categories = set()
|
||||||
|
|||||||
@@ -25,11 +25,20 @@ class Song(Base):
|
|||||||
singable: Mapped[Optional[bool]]
|
singable: Mapped[Optional[bool]]
|
||||||
|
|
||||||
|
|
||||||
|
class Session(Base):
|
||||||
|
__tablename__ = 'sessions'
|
||||||
|
id: Mapped[int] = mapped_column(primary_key=True)
|
||||||
|
session_name: Mapped[int]
|
||||||
|
active: Mapped[bool]
|
||||||
|
time_created: Mapped[datetime] = mapped_column(server_default=func.now())
|
||||||
|
time_updated: Mapped[Optional[datetime]
|
||||||
|
] = mapped_column(onupdate=func.now())
|
||||||
|
|
||||||
class Vote(Base):
|
class Vote(Base):
|
||||||
__tablename__ = 'votes'
|
__tablename__ = 'votes'
|
||||||
id: Mapped[int] = mapped_column(primary_key=True)
|
id: Mapped[int] = mapped_column(primary_key=True)
|
||||||
song_id: Mapped[int] = mapped_column(Integer, ForeignKey("songs.id"))
|
song_id: Mapped[int] = mapped_column(Integer, ForeignKey("songs.id"))
|
||||||
user_id: Mapped[int]
|
session_id: Mapped[int] = mapped_column(Integer, ForeignKey("sessions.id"))
|
||||||
vote: Mapped[Optional[int]]
|
vote: Mapped[Optional[int]]
|
||||||
time_created: Mapped[datetime] = mapped_column(server_default=func.now())
|
time_created: Mapped[datetime] = mapped_column(server_default=func.now())
|
||||||
time_updated: Mapped[Optional[datetime]
|
time_updated: Mapped[Optional[datetime]
|
||||||
|
|||||||
27
app/routers/session.py
Normal file
27
app/routers/session.py
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
from typing import Annotated
|
||||||
|
from fastapi import APIRouter, Depends
|
||||||
|
from sqlalchemy.orm import Session
|
||||||
|
|
||||||
|
import app.models as models
|
||||||
|
from app.database import get_db
|
||||||
|
from app.schemas import Song
|
||||||
|
import app.crud as crud
|
||||||
|
|
||||||
|
router = APIRouter(
|
||||||
|
prefix="/session",
|
||||||
|
# dependencies=[Security(get_current_user, scopes=["public"])],
|
||||||
|
responses={404: {"description": "Not found"}},
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@router.put("/{session_id}")
|
||||||
|
async def activate_session(session_id: str = "", db: Annotated[Session, Depends(get_db)] = None):
|
||||||
|
crud.activate_session(db, session_id)
|
||||||
|
|
||||||
|
@router.delete("/{session_id}")
|
||||||
|
async def deactivate_session(session_id: str = "", db: Annotated[Session, Depends(get_db)] = None):
|
||||||
|
crud.deactivate_session(db, session_id)
|
||||||
|
|
||||||
|
#@router.get("/{session_id}")
|
||||||
|
#async def get_session(session_id: str = "", db: Annotated[Session, Depends(get_db)] = None):
|
||||||
|
# return "get " + session_id
|
||||||
@@ -5,7 +5,7 @@ from sqlalchemy.orm import Session
|
|||||||
import app.models as models
|
import app.models as models
|
||||||
from app.database import get_db
|
from app.database import get_db
|
||||||
from app.schemas import Song
|
from app.schemas import Song
|
||||||
from app.crud import get_songs_and_vote_for_user, create_or_update_vote, get_all_songs_and_votes
|
from app.crud import get_songs_and_vote_for_session, create_or_update_vote, get_all_songs_and_votes
|
||||||
|
|
||||||
router = APIRouter(
|
router = APIRouter(
|
||||||
prefix="/songs",
|
prefix="/songs",
|
||||||
@@ -15,13 +15,13 @@ router = APIRouter(
|
|||||||
|
|
||||||
|
|
||||||
@router.get("/")
|
@router.get("/")
|
||||||
async def get_songs(user_id: str = "", db: Annotated[Session, Depends(get_db)] = None) -> list[Song]:
|
async def get_songs(session_id: str = "", db: Annotated[Session, Depends(get_db)] = None) -> list[Song]:
|
||||||
return [Song(**s.__dict__, vote=v) for s, v in get_songs_and_vote_for_user(db, user_id)]
|
return [Song(**s.__dict__, vote=v) for s, v in get_songs_and_vote_for_session(db, session_id)]
|
||||||
|
|
||||||
|
|
||||||
@router.post("/{song_id}/vote")
|
@router.post("/{song_id}/vote")
|
||||||
async def vote(song_id: str, user_id: str, vote: int, db: Annotated[Session, Depends(get_db)]):
|
async def vote(song_id: str, session_id: str, vote: int, db: Annotated[Session, Depends(get_db)]):
|
||||||
create_or_update_vote(db, song_id, user_id, vote)
|
create_or_update_vote(db, song_id, session_id, vote)
|
||||||
|
|
||||||
|
|
||||||
@router.get("/evaluation")
|
@router.get("/evaluation")
|
||||||
|
|||||||
@@ -12,6 +12,34 @@
|
|||||||
<script src="https://open.spotify.com/embed/iframe-api/v1" async></script>
|
<script src="https://open.spotify.com/embed/iframe-api/v1" async></script>
|
||||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
|
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
|
const session_id = "{{ session_id }}";
|
||||||
|
|
||||||
|
function activate_session() {
|
||||||
|
$.ajax({
|
||||||
|
url: "/session/" + session_id,
|
||||||
|
method: "PUT"
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function deactivate_session() {
|
||||||
|
$.ajax({
|
||||||
|
url: "/session/" + session_id,
|
||||||
|
method: "DELETE"
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
$( window ).on("load", activate_session);
|
||||||
|
|
||||||
|
$( window ).on("beforeunload", deactivate_session);
|
||||||
|
$( window ).on("pagehide", deactivate_session);
|
||||||
|
$(document).on('visibilitychange', function() {
|
||||||
|
if (document.visibilityState == 'hidden') {
|
||||||
|
deactivate_session();
|
||||||
|
} else {
|
||||||
|
activate_session()
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
var spotify_embed_controller;
|
var spotify_embed_controller;
|
||||||
|
|
||||||
window.onSpotifyIframeApiReady = (IFrameAPI) => {
|
window.onSpotifyIframeApiReady = (IFrameAPI) => {
|
||||||
@@ -79,8 +107,6 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function vote(song_id, vote) {
|
function vote(song_id, vote) {
|
||||||
const session_id = "{{ session_id }}";
|
|
||||||
|
|
||||||
no_button = $("#song-" + song_id).find(".button-no")
|
no_button = $("#song-" + song_id).find(".button-no")
|
||||||
yes_button = $("#song-" + song_id).find(".button-yes")
|
yes_button = $("#song-" + song_id).find(".button-yes")
|
||||||
neutral_button = $("#song-" + song_id).find(".button-neutral")
|
neutral_button = $("#song-" + song_id).find(".button-neutral")
|
||||||
@@ -103,7 +129,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
$.ajax({
|
$.ajax({
|
||||||
url: "/songs/" + song_id + "/vote?" + $.param({ user_id: session_id, vote: vote }),
|
url: "/songs/" + song_id + "/vote?" + $.param({ session_id: session_id, vote: vote }),
|
||||||
method: "POST"
|
method: "POST"
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user