Afegir cartells a les jams (i esquelet per a slow jams i notes)
This commit is contained in:
@@ -1,10 +1,12 @@
|
|||||||
from folkugat_web.api.router import get_router
|
from folkugat_web.api.router import get_router
|
||||||
|
|
||||||
from . import index, live, set_page
|
from . import cartell, index, live, playlist, set_page
|
||||||
|
|
||||||
router = get_router()
|
router = get_router()
|
||||||
|
router.include_router(cartell.router)
|
||||||
router.include_router(index.router)
|
router.include_router(index.router)
|
||||||
router.include_router(live.router)
|
router.include_router(live.router)
|
||||||
router.include_router(set_page.router)
|
router.include_router(set_page.router)
|
||||||
|
router.include_router(playlist.router)
|
||||||
|
|
||||||
__all__ = ["router"]
|
__all__ = ["router"]
|
||||||
|
|||||||
71
folkugat_web/api/routes/sessio/cartell.py
Normal file
71
folkugat_web/api/routes/sessio/cartell.py
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
import dataclasses
|
||||||
|
from typing import Annotated
|
||||||
|
|
||||||
|
from fastapi import HTTPException, Request, UploadFile
|
||||||
|
from fastapi.params import File
|
||||||
|
from folkugat_web.api.router import get_router
|
||||||
|
from folkugat_web.fragments.sessio import cartell
|
||||||
|
from folkugat_web.services import auth
|
||||||
|
from folkugat_web.services import files as files_service
|
||||||
|
from folkugat_web.services import sessions as sessions_service
|
||||||
|
|
||||||
|
router = get_router()
|
||||||
|
|
||||||
|
|
||||||
|
@router.get("/api/sessio/{session_id}/cartell")
|
||||||
|
def get_cartell(
|
||||||
|
request: Request,
|
||||||
|
logged_in: auth.LoggedIn,
|
||||||
|
session_id: int,
|
||||||
|
):
|
||||||
|
return cartell.cartell(request, session_id, logged_in)
|
||||||
|
|
||||||
|
|
||||||
|
@router.get("/api/sessio/{session_id}/cartell/editor")
|
||||||
|
def get_cartell_editor(
|
||||||
|
request: Request,
|
||||||
|
_: auth.RequireLogin,
|
||||||
|
session_id: int,
|
||||||
|
):
|
||||||
|
return cartell.cartell_editor(request, session_id)
|
||||||
|
|
||||||
|
|
||||||
|
@router.put("/api/sessio/{session_id}/cartell")
|
||||||
|
async def set_cartell(
|
||||||
|
request: Request,
|
||||||
|
logged_in: auth.RequireLogin,
|
||||||
|
session_id: int,
|
||||||
|
upload_file: Annotated[UploadFile, File()],
|
||||||
|
):
|
||||||
|
session = sessions_service.get_session(session_id=session_id)
|
||||||
|
if not session:
|
||||||
|
raise HTTPException(status_code=404, detail="Could not find session")
|
||||||
|
url = await files_service.store_session_cartell(
|
||||||
|
session_id=session_id,
|
||||||
|
upload_file=upload_file,
|
||||||
|
)
|
||||||
|
new_session = dataclasses.replace(
|
||||||
|
session,
|
||||||
|
cartell_url=url,
|
||||||
|
)
|
||||||
|
sessions_service.set_session(new_session)
|
||||||
|
return cartell.cartell(request, session_id, logged_in)
|
||||||
|
|
||||||
|
|
||||||
|
@router.delete("/api/sessio/{session_id}/cartell")
|
||||||
|
async def delete_cartell(
|
||||||
|
request: Request,
|
||||||
|
logged_in: auth.RequireLogin,
|
||||||
|
session_id: int,
|
||||||
|
):
|
||||||
|
session = sessions_service.get_session(session_id=session_id)
|
||||||
|
if not session:
|
||||||
|
raise HTTPException(status_code=404, detail="Could not find session")
|
||||||
|
if session.cartell_url:
|
||||||
|
new_session = dataclasses.replace(
|
||||||
|
session,
|
||||||
|
cartell_url=None,
|
||||||
|
)
|
||||||
|
sessions_service.set_session(new_session)
|
||||||
|
files_service.clean_orphan_files()
|
||||||
|
return cartell.cartell(request, session_id, logged_in)
|
||||||
@@ -2,7 +2,8 @@ from typing import Annotated
|
|||||||
|
|
||||||
from fastapi import Form, Request
|
from fastapi import Form, Request
|
||||||
from folkugat_web.api.router import get_router
|
from folkugat_web.api.router import get_router
|
||||||
from folkugat_web.fragments import live, sessio
|
from folkugat_web.fragments import live
|
||||||
|
from folkugat_web.fragments.sessio import page as sessio
|
||||||
from folkugat_web.services import auth
|
from folkugat_web.services import auth
|
||||||
from folkugat_web.services.temes import write as temes_service
|
from folkugat_web.services.temes import write as temes_service
|
||||||
from folkugat_web.templates import templates
|
from folkugat_web.templates import templates
|
||||||
@@ -52,150 +53,3 @@ def stop_live(
|
|||||||
session_id: int,
|
session_id: int,
|
||||||
):
|
):
|
||||||
return live.stop_live_session(request=request, session_id=session_id)
|
return live.stop_live_session(request=request, session_id=session_id)
|
||||||
|
|
||||||
|
|
||||||
@router.post("/api/sessio/{session_id}/set")
|
|
||||||
def add_set(
|
|
||||||
request: Request,
|
|
||||||
logged_in: auth.RequireLogin,
|
|
||||||
session_id: int,
|
|
||||||
):
|
|
||||||
return sessio.add_set(request=request, session_id=session_id, logged_in=logged_in)
|
|
||||||
|
|
||||||
|
|
||||||
@router.get("/api/sessio/{session_id}/set/{set_id}")
|
|
||||||
def get_set(
|
|
||||||
request: Request,
|
|
||||||
logged_in: auth.LoggedIn,
|
|
||||||
session_id: int,
|
|
||||||
set_id: int,
|
|
||||||
):
|
|
||||||
return sessio.get_set(request=request, session_id=session_id, set_id=set_id, logged_in=logged_in)
|
|
||||||
|
|
||||||
|
|
||||||
@router.delete("/api/sessio/{session_id}/set/{set_id}")
|
|
||||||
def delete_set(
|
|
||||||
_: auth.RequireLogin,
|
|
||||||
session_id: int,
|
|
||||||
set_id: int,
|
|
||||||
):
|
|
||||||
return sessio.delete_set(session_id=session_id, set_id=set_id)
|
|
||||||
|
|
||||||
|
|
||||||
@router.post("/api/sessio/{session_id}/set/{set_id}")
|
|
||||||
def add_tema(
|
|
||||||
request: Request,
|
|
||||||
logged_in: auth.RequireLogin,
|
|
||||||
session_id: int,
|
|
||||||
set_id: int,
|
|
||||||
):
|
|
||||||
return sessio.add_tema(request=request, session_id=session_id, set_id=set_id, logged_in=logged_in)
|
|
||||||
|
|
||||||
|
|
||||||
@router.get("/api/sessio/{session_id}/set/{set_id}/tema/{entry_id}")
|
|
||||||
def get_tema(
|
|
||||||
request: Request,
|
|
||||||
logged_in: auth.RequireLogin,
|
|
||||||
session_id: int,
|
|
||||||
set_id: int,
|
|
||||||
entry_id: int,
|
|
||||||
):
|
|
||||||
return sessio.get_tema(
|
|
||||||
request=request, session_id=session_id, set_id=set_id, entry_id=entry_id, logged_in=logged_in)
|
|
||||||
|
|
||||||
|
|
||||||
@router.get("/api/sessio/{session_id}/set/{set_id}/tema/{entry_id}/editor")
|
|
||||||
def get_tema_editor(
|
|
||||||
request: Request,
|
|
||||||
logged_in: auth.RequireLogin,
|
|
||||||
session_id: int,
|
|
||||||
set_id: int,
|
|
||||||
entry_id: int,
|
|
||||||
):
|
|
||||||
return sessio.get_tema_editor(
|
|
||||||
request=request, session_id=session_id, set_id=set_id, entry_id=entry_id, logged_in=logged_in)
|
|
||||||
|
|
||||||
|
|
||||||
@router.delete("/api/sessio/{session_id}/set/{set_id}/tema/{entry_id}")
|
|
||||||
def delete_tema(
|
|
||||||
_: auth.RequireLogin,
|
|
||||||
session_id: int,
|
|
||||||
set_id: int,
|
|
||||||
entry_id: int,
|
|
||||||
):
|
|
||||||
return sessio.delete_tema(session_id=session_id, set_id=set_id, entry_id=entry_id)
|
|
||||||
|
|
||||||
|
|
||||||
@router.get("/api/sessio/{session_id}/set/{set_id}/tema/{entry_id}/busca")
|
|
||||||
def busca_tema(
|
|
||||||
request: Request,
|
|
||||||
_: auth.RequireLogin,
|
|
||||||
session_id: int,
|
|
||||||
set_id: int,
|
|
||||||
entry_id: int,
|
|
||||||
query: str,
|
|
||||||
):
|
|
||||||
return sessio.busca_tema(
|
|
||||||
request=request,
|
|
||||||
session_id=session_id,
|
|
||||||
set_id=set_id,
|
|
||||||
entry_id=entry_id,
|
|
||||||
query=query,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@router.put("/api/sessio/{session_id}/set/{set_id}/tema/{entry_id}")
|
|
||||||
def set_tema(
|
|
||||||
request: Request,
|
|
||||||
logged_in: auth.RequireLogin,
|
|
||||||
session_id: int,
|
|
||||||
set_id: int,
|
|
||||||
entry_id: int,
|
|
||||||
tema_id: Annotated[int, Form()],
|
|
||||||
):
|
|
||||||
return sessio.set_tema(
|
|
||||||
request=request,
|
|
||||||
logged_in=logged_in,
|
|
||||||
session_id=session_id,
|
|
||||||
set_id=set_id,
|
|
||||||
entry_id=entry_id,
|
|
||||||
tema_id=tema_id,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@router.put("/api/sessio/{session_id}/set/{set_id}/tema/{entry_id}/unknown")
|
|
||||||
def set_tema_unknown(
|
|
||||||
request: Request,
|
|
||||||
logged_in: auth.RequireLogin,
|
|
||||||
session_id: int,
|
|
||||||
set_id: int,
|
|
||||||
entry_id: int,
|
|
||||||
):
|
|
||||||
return sessio.set_tema(
|
|
||||||
request=request,
|
|
||||||
logged_in=logged_in,
|
|
||||||
session_id=session_id,
|
|
||||||
set_id=set_id,
|
|
||||||
entry_id=entry_id,
|
|
||||||
tema_id=None,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@router.post("/api/sessio/{session_id}/set/{set_id}/tema/{entry_id}")
|
|
||||||
def set_tema_new(
|
|
||||||
request: Request,
|
|
||||||
logged_in: auth.RequireLogin,
|
|
||||||
session_id: int,
|
|
||||||
set_id: int,
|
|
||||||
entry_id: int,
|
|
||||||
title: Annotated[str, Form()],
|
|
||||||
):
|
|
||||||
new_tema = temes_service.create_tema(title=title)
|
|
||||||
return sessio.set_tema(
|
|
||||||
request=request,
|
|
||||||
logged_in=logged_in,
|
|
||||||
session_id=session_id,
|
|
||||||
set_id=set_id,
|
|
||||||
entry_id=entry_id,
|
|
||||||
tema_id=new_tema.id,
|
|
||||||
)
|
|
||||||
|
|||||||
189
folkugat_web/api/routes/sessio/playlist.py
Normal file
189
folkugat_web/api/routes/sessio/playlist.py
Normal file
@@ -0,0 +1,189 @@
|
|||||||
|
from typing import Annotated
|
||||||
|
|
||||||
|
from fastapi import Form, Request
|
||||||
|
from folkugat_web.api.router import get_router
|
||||||
|
from folkugat_web.fragments import live
|
||||||
|
from folkugat_web.fragments.sessio import playlist
|
||||||
|
from folkugat_web.services import auth
|
||||||
|
from folkugat_web.services.temes import write as temes_service
|
||||||
|
from folkugat_web.templates import templates
|
||||||
|
|
||||||
|
router = get_router()
|
||||||
|
|
||||||
|
|
||||||
|
@router.post("/api/sessio/{session_id}/playlist/set")
|
||||||
|
def add_set(
|
||||||
|
request: Request,
|
||||||
|
logged_in: auth.RequireLogin,
|
||||||
|
session_id: int,
|
||||||
|
):
|
||||||
|
return playlist.add_set(
|
||||||
|
request=request,
|
||||||
|
session_id=session_id,
|
||||||
|
logged_in=logged_in,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@router.get("/api/sessio/{session_id}/playlist/set/{set_id}")
|
||||||
|
def get_set(
|
||||||
|
request: Request,
|
||||||
|
logged_in: auth.LoggedIn,
|
||||||
|
session_id: int,
|
||||||
|
set_id: int,
|
||||||
|
):
|
||||||
|
return playlist.get_set(
|
||||||
|
request=request,
|
||||||
|
session_id=session_id,
|
||||||
|
set_id=set_id,
|
||||||
|
logged_in=logged_in,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@router.delete("/api/sessio/{session_id}/playlist/set/{set_id}")
|
||||||
|
def delete_set(
|
||||||
|
_: auth.RequireLogin,
|
||||||
|
session_id: int,
|
||||||
|
set_id: int,
|
||||||
|
):
|
||||||
|
return playlist.delete_set(
|
||||||
|
session_id=session_id,
|
||||||
|
set_id=set_id,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@router.post("/api/sessio/{session_id}/playlist/set/{set_id}")
|
||||||
|
def add_tema(
|
||||||
|
request: Request,
|
||||||
|
logged_in: auth.RequireLogin,
|
||||||
|
session_id: int,
|
||||||
|
set_id: int,
|
||||||
|
):
|
||||||
|
return playlist.add_tema(
|
||||||
|
request=request,
|
||||||
|
session_id=session_id,
|
||||||
|
set_id=set_id,
|
||||||
|
logged_in=logged_in,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@router.get("/api/sessio/{session_id}/playlist/set/{set_id}/tema/{entry_id}")
|
||||||
|
def get_tema(
|
||||||
|
request: Request,
|
||||||
|
logged_in: auth.RequireLogin,
|
||||||
|
session_id: int,
|
||||||
|
set_id: int,
|
||||||
|
entry_id: int,
|
||||||
|
):
|
||||||
|
return playlist.get_tema(
|
||||||
|
request=request,
|
||||||
|
session_id=session_id,
|
||||||
|
set_id=set_id,
|
||||||
|
entry_id=entry_id,
|
||||||
|
logged_in=logged_in,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@router.get("/api/sessio/{session_id}/playlist/set/{set_id}/tema/{entry_id}/editor")
|
||||||
|
def get_tema_editor(
|
||||||
|
request: Request,
|
||||||
|
logged_in: auth.RequireLogin,
|
||||||
|
session_id: int,
|
||||||
|
set_id: int,
|
||||||
|
entry_id: int,
|
||||||
|
):
|
||||||
|
return playlist.get_tema_editor(
|
||||||
|
request=request,
|
||||||
|
session_id=session_id,
|
||||||
|
set_id=set_id,
|
||||||
|
entry_id=entry_id,
|
||||||
|
logged_in=logged_in,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@router.delete("/api/sessio/{session_id}/playlist/set/{set_id}/tema/{entry_id}")
|
||||||
|
def delete_tema(
|
||||||
|
_: auth.RequireLogin,
|
||||||
|
session_id: int,
|
||||||
|
set_id: int,
|
||||||
|
entry_id: int,
|
||||||
|
):
|
||||||
|
return playlist.delete_tema(
|
||||||
|
session_id=session_id,
|
||||||
|
set_id=set_id,
|
||||||
|
entry_id=entry_id,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@router.get("/api/sessio/{session_id}/playlist/set/{set_id}/tema/{entry_id}/busca")
|
||||||
|
def busca_tema(
|
||||||
|
request: Request,
|
||||||
|
_: auth.RequireLogin,
|
||||||
|
session_id: int,
|
||||||
|
set_id: int,
|
||||||
|
entry_id: int,
|
||||||
|
query: str,
|
||||||
|
):
|
||||||
|
return playlist.busca_tema(
|
||||||
|
request=request,
|
||||||
|
session_id=session_id,
|
||||||
|
set_id=set_id,
|
||||||
|
entry_id=entry_id,
|
||||||
|
query=query,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@router.put("/api/sessio/{session_id}/playlist/set/{set_id}/tema/{entry_id}")
|
||||||
|
def set_tema(
|
||||||
|
request: Request,
|
||||||
|
logged_in: auth.RequireLogin,
|
||||||
|
session_id: int,
|
||||||
|
set_id: int,
|
||||||
|
entry_id: int,
|
||||||
|
tema_id: Annotated[int, Form()],
|
||||||
|
):
|
||||||
|
return playlist.set_tema(
|
||||||
|
request=request,
|
||||||
|
logged_in=logged_in,
|
||||||
|
session_id=session_id,
|
||||||
|
set_id=set_id,
|
||||||
|
entry_id=entry_id,
|
||||||
|
tema_id=tema_id,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@router.put("/api/sessio/{session_id}/playlist/set/{set_id}/tema/{entry_id}/unknown")
|
||||||
|
def set_tema_unknown(
|
||||||
|
request: Request,
|
||||||
|
logged_in: auth.RequireLogin,
|
||||||
|
session_id: int,
|
||||||
|
set_id: int,
|
||||||
|
entry_id: int,
|
||||||
|
):
|
||||||
|
return playlist.set_tema(
|
||||||
|
request=request,
|
||||||
|
logged_in=logged_in,
|
||||||
|
session_id=session_id,
|
||||||
|
set_id=set_id,
|
||||||
|
entry_id=entry_id,
|
||||||
|
tema_id=None,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@router.post("/api/sessio/{session_id}/playlist/set/{set_id}/tema/{entry_id}")
|
||||||
|
def set_tema_new(
|
||||||
|
request: Request,
|
||||||
|
logged_in: auth.RequireLogin,
|
||||||
|
session_id: int,
|
||||||
|
set_id: int,
|
||||||
|
entry_id: int,
|
||||||
|
title: Annotated[str, Form()],
|
||||||
|
):
|
||||||
|
new_tema = temes_service.create_tema(title=title)
|
||||||
|
return playlist.set_tema(
|
||||||
|
request=request,
|
||||||
|
logged_in=logged_in,
|
||||||
|
session_id=session_id,
|
||||||
|
set_id=set_id,
|
||||||
|
entry_id=entry_id,
|
||||||
|
tema_id=new_tema.id,
|
||||||
|
)
|
||||||
@@ -34,7 +34,7 @@ async def set_link(
|
|||||||
upload_file: Annotated[UploadFile | None, File()] = None,
|
upload_file: Annotated[UploadFile | None, File()] = None,
|
||||||
):
|
):
|
||||||
if upload_file:
|
if upload_file:
|
||||||
url = await files_service.store_file(tema_id=tema_id, upload_file=upload_file)
|
url = await files_service.store_tema_file(tema_id=tema_id, upload_file=upload_file)
|
||||||
|
|
||||||
link_type = links_service.guess_link_type(url or '')
|
link_type = links_service.guess_link_type(url or '')
|
||||||
new_link = model.Link(
|
new_link = model.Link(
|
||||||
@@ -65,7 +65,7 @@ def create_link(
|
|||||||
|
|
||||||
@router.delete("/api/tema/{tema_id}/link/{link_id}")
|
@router.delete("/api/tema/{tema_id}/link/{link_id}")
|
||||||
def delete_link(
|
def delete_link(
|
||||||
_logged_in: auth.RequireLogin,
|
_: auth.RequireLogin,
|
||||||
tema_id: int,
|
tema_id: int,
|
||||||
link_id: int,
|
link_id: int,
|
||||||
):
|
):
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
36
folkugat_web/assets/templates/fragments/sessio/cartell.html
Normal file
36
folkugat_web/assets/templates/fragments/sessio/cartell.html
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
<div id="cartell"
|
||||||
|
class="flex flex-col items-center">
|
||||||
|
{% if session.cartell_url %}
|
||||||
|
<div class="max-w-[655px] w-full
|
||||||
|
flex flex-col items-center">
|
||||||
|
{% if logged_in %}
|
||||||
|
<div class="my-2 w-full text-beige text-right">
|
||||||
|
<button title="Modifica el cartell"
|
||||||
|
class="mx-1"
|
||||||
|
hx-get="/api/sessio/{{ session_id }}/cartell/editor"
|
||||||
|
hx-target="#cartell"
|
||||||
|
hx-swap="outerHTML">
|
||||||
|
<i class="fa fa-pencil" aria-hidden="true"></i>
|
||||||
|
</button>
|
||||||
|
<button title="Esborra el cartell"
|
||||||
|
class="mx-1"
|
||||||
|
hx-delete="/api/sessio/{{ session_id }}/cartell"
|
||||||
|
hx-target="#cartell"
|
||||||
|
hx-swap="outerHTML">
|
||||||
|
<i class="fa fa-times" aria-hidden="true"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
<img class="w-full h-auto"
|
||||||
|
src="{{ session.cartell_url }}"/>
|
||||||
|
</div>
|
||||||
|
{% elif logged_in %}
|
||||||
|
<button class="text-beige mt-2"
|
||||||
|
hx-get="/api/sessio/{{ session_id }}/cartell/editor"
|
||||||
|
hx-target="#cartell"
|
||||||
|
hx-swap="outerHTML">
|
||||||
|
<i class="fa fa-plus" aria-hidden="true"></i>
|
||||||
|
Afegeix cartell
|
||||||
|
</button>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
<form id="cartell-editor"
|
||||||
|
class="flex flex-row gap-2"
|
||||||
|
hx-encoding="multipart/form-data">
|
||||||
|
<input type='file'
|
||||||
|
class="border border-beige focus:outline-none
|
||||||
|
rounded grow
|
||||||
|
bg-brown p-1 my-1"
|
||||||
|
name='upload_file'/>
|
||||||
|
<button title="Desa els canvis"
|
||||||
|
class="mx-1 text-beige"
|
||||||
|
hx-put="/api/sessio/{{ session_id }}/cartell"
|
||||||
|
hx-target="#cartell-editor"
|
||||||
|
hx-swap="outerHTML">
|
||||||
|
<i class="fa fa-check" aria-hidden="true"></i>
|
||||||
|
</button>
|
||||||
|
<button title="Descarta els canvis"
|
||||||
|
class="mx-1 text-beige"
|
||||||
|
hx-get="/api/sessio/{{ session_id }}/cartell"
|
||||||
|
hx-target="#cartell-editor"
|
||||||
|
hx-swap="outerHTML">
|
||||||
|
<i class="fa fa-times" aria-hidden="true"></i>
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
@@ -12,6 +12,7 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</h3>
|
</h3>
|
||||||
|
{% include "fragments/sessio/cartell.html" %}
|
||||||
<div class="text-left">
|
<div class="text-left">
|
||||||
<h4 class="pt-4 text-xl text-beige">Horari i lloc</h4>
|
<h4 class="pt-4 text-xl text-beige">Horari i lloc</h4>
|
||||||
De {{ session.start_time.strftime("%H:%M") }}
|
De {{ session.start_time.strftime("%H:%M") }}
|
||||||
@@ -29,6 +30,17 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
{% if logged_in or session.notes %}
|
||||||
|
<div class="text-left">
|
||||||
|
<h4 class="py-4 text-xl text-beige">Notes</h4>
|
||||||
|
{% if session.notes %}{{ session.notes }}{% endif %}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
{% if logged_in or False %}
|
||||||
|
<div class="text-left">
|
||||||
|
<h4 class="py-4 text-xl text-beige">Slow Jam</h4>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
{% if logged_in or playlist.sets %}
|
{% if logged_in or playlist.sets %}
|
||||||
<div class="text-left">
|
<div class="text-left">
|
||||||
<h4 class="py-4 text-xl text-beige mt-2">Temes tocats</h4>
|
<h4 class="py-4 text-xl text-beige mt-2">Temes tocats</h4>
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
{% if logged_in %}
|
{% if logged_in %}
|
||||||
<div class="flex flex-col items-center">
|
<div class="flex flex-col items-center">
|
||||||
<button class="text-beige mt-2"
|
<button class="text-beige mt-2"
|
||||||
hx-post="/api/sessio/{{ session.id }}/set"
|
hx-post="/api/sessio/{{ session.id }}/playlist/set"
|
||||||
hx-target="#playlist-{{ session.id }}"
|
hx-target="#playlist-{{ session.id }}"
|
||||||
hx-swap="beforeend transition:true">
|
hx-swap="beforeend transition:true">
|
||||||
<i class="fa fa-plus" aria-hidden="true"></i>
|
<i class="fa fa-plus" aria-hidden="true"></i>
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
m-4 rounded-lg bg-white
|
m-4 rounded-lg bg-white
|
||||||
px-2 py-1 my-1"
|
px-2 py-1 my-1"
|
||||||
id="set-entry-{{ set_id }}"
|
id="set-entry-{{ set_id }}"
|
||||||
hx-get="/api/sessio/{{ session_id }}/set/{{ set_id }}"
|
hx-get="/api/sessio/{{ session_id }}/playlist/set/{{ set_id }}"
|
||||||
hx-target="#set-entry-{{ set_id }}"
|
hx-target="#set-entry-{{ set_id }}"
|
||||||
hx-swap="outerHTML"
|
hx-swap="outerHTML"
|
||||||
hx-trigger="reload-set-{{ set_id }}">
|
hx-trigger="reload-set-{{ set_id }}">
|
||||||
@@ -25,7 +25,7 @@
|
|||||||
w-full max-w-[655px]">
|
w-full max-w-[655px]">
|
||||||
{% if logged_in %}
|
{% if logged_in %}
|
||||||
<button class="text-beige w-full"
|
<button class="text-beige w-full"
|
||||||
hx-delete="/api/sessio/{{ session_id }}/set/{{ set_id }}"
|
hx-delete="/api/sessio/{{ session_id }}/playlist/set/{{ set_id }}"
|
||||||
hx-target="#set-entry-{{ set_id }}"
|
hx-target="#set-entry-{{ set_id }}"
|
||||||
hx-swap="outerHTML">
|
hx-swap="outerHTML">
|
||||||
<i class="fa fa-times" aria-hidden="true"></i>
|
<i class="fa fa-times" aria-hidden="true"></i>
|
||||||
@@ -44,7 +44,7 @@
|
|||||||
</ol>
|
</ol>
|
||||||
{% if logged_in %}
|
{% if logged_in %}
|
||||||
<button class="text-beige mt-2 w-full"
|
<button class="text-beige mt-2 w-full"
|
||||||
hx-post="/api/sessio/{{ session_id }}/set/{{ set_id }}"
|
hx-post="/api/sessio/{{ session_id }}/playlist/set/{{ set_id }}"
|
||||||
hx-target="#set-entry-{{ set_id }}-list"
|
hx-target="#set-entry-{{ set_id }}-list"
|
||||||
hx-swap="beforeend transition:true">
|
hx-swap="beforeend transition:true">
|
||||||
<i class="fa fa-plus" aria-hidden="true"></i>
|
<i class="fa fa-plus" aria-hidden="true"></i>
|
||||||
|
|||||||
@@ -12,13 +12,13 @@
|
|||||||
class="border border-beige focus:outline-none
|
class="border border-beige focus:outline-none
|
||||||
rounded text-center text-black
|
rounded text-center text-black
|
||||||
p-1 m-1"
|
p-1 m-1"
|
||||||
hx-get="/api/sessio/{{ session_id }}/set/{{ set_id }}/tema/{{ tema_entry.id }}/busca"
|
hx-get="/api/sessio/{{ session_id }}/playlist/set/{{ set_id }}/tema/{{ tema_entry.id }}/busca"
|
||||||
hx-trigger="revealed, keyup delay:500ms changed"
|
hx-trigger="revealed, keyup delay:500ms changed"
|
||||||
hx-target="#tune-entry-{{ tema_entry.id }}-search-results"
|
hx-target="#tune-entry-{{ tema_entry.id }}-search-results"
|
||||||
hx-swap="outerHTML"/>
|
hx-swap="outerHTML"/>
|
||||||
<button title="Descarta els canvis"
|
<button title="Descarta els canvis"
|
||||||
class="text-beige mx-1"
|
class="text-beige mx-1"
|
||||||
hx-get="/api/sessio/{{ session_id }}/set/{{ set_id }}/tema/{{ tema_entry.id }}"
|
hx-get="/api/sessio/{{ session_id }}/playlist/set/{{ set_id }}/tema/{{ tema_entry.id }}"
|
||||||
hx-target="#tune-entry-{{ tema_entry.id }}"
|
hx-target="#tune-entry-{{ tema_entry.id }}"
|
||||||
hx-swap="outerHTML">
|
hx-swap="outerHTML">
|
||||||
<i class="fa fa-times" aria-hidden="true"></i>
|
<i class="fa fa-times" aria-hidden="true"></i>
|
||||||
|
|||||||
@@ -15,14 +15,14 @@
|
|||||||
<div class="flex-none flex flex-row shrink-0">
|
<div class="flex-none flex flex-row shrink-0">
|
||||||
<button title="Edita el tema"
|
<button title="Edita el tema"
|
||||||
class="text-beige mx-1"
|
class="text-beige mx-1"
|
||||||
hx-get="/api/sessio/{{ session_id }}/set/{{ set_id }}/tema/{{ tema_entry.id }}/editor"
|
hx-get="/api/sessio/{{ session_id }}/playlist/set/{{ set_id }}/tema/{{ tema_entry.id }}/editor"
|
||||||
hx-target="#tune-entry-{{ tema_entry.id }}"
|
hx-target="#tune-entry-{{ tema_entry.id }}"
|
||||||
hx-swap="outerHTML">
|
hx-swap="outerHTML">
|
||||||
<i class="fa fa-pencil" aria-hidden="true"></i>
|
<i class="fa fa-pencil" aria-hidden="true"></i>
|
||||||
</button>
|
</button>
|
||||||
<button title="Esborra el tema"
|
<button title="Esborra el tema"
|
||||||
class="text-beige mx-1"
|
class="text-beige mx-1"
|
||||||
hx-delete="/api/sessio/{{ session_id }}/set/{{ set_id }}/tema/{{ tema_entry.id }}"
|
hx-delete="/api/sessio/{{ session_id }}/playlist/set/{{ set_id }}/tema/{{ tema_entry.id }}"
|
||||||
hx-target="#tune-entry-{{ tema_entry.id }}"
|
hx-target="#tune-entry-{{ tema_entry.id }}"
|
||||||
hx-swap="outerHTML">
|
hx-swap="outerHTML">
|
||||||
<i class="fa fa-times" aria-hidden="true"></i>
|
<i class="fa fa-times" aria-hidden="true"></i>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<li>
|
<li>
|
||||||
<button class="bg-beige text-brown rounded
|
<button class="bg-beige text-brown rounded
|
||||||
m-1 px-2"
|
m-1 px-2"
|
||||||
hx-put="/api/sessio/{{ session_id }}/set/{{ set_id }}/tema/{{ entry_id }}"
|
hx-put="/api/sessio/{{ session_id }}/playlist/set/{{ set_id }}/tema/{{ entry_id }}"
|
||||||
hx-vals='{"tema_id": "{{ tema.id }}"}'
|
hx-vals='{"tema_id": "{{ tema.id }}"}'
|
||||||
hx-target="#tune-entry-{{ entry_id }}"
|
hx-target="#tune-entry-{{ entry_id }}"
|
||||||
hx-swap="outerHTML">
|
hx-swap="outerHTML">
|
||||||
@@ -15,7 +15,7 @@
|
|||||||
<li>
|
<li>
|
||||||
<button class="border border-beige text-beige rounded
|
<button class="border border-beige text-beige rounded
|
||||||
m-1 px-2"
|
m-1 px-2"
|
||||||
hx-put="/api/sessio/{{ session_id }}/set/{{ set_id }}/tema/{{ entry_id }}/unknown"
|
hx-put="/api/sessio/{{ session_id }}/playlist/set/{{ set_id }}/tema/{{ entry_id }}/unknown"
|
||||||
hx-target="#tune-entry-{{ entry_id }}"
|
hx-target="#tune-entry-{{ entry_id }}"
|
||||||
hx-swap="outerHTML">
|
hx-swap="outerHTML">
|
||||||
<i class="fa fa-question" aria-hidden="true"></i>
|
<i class="fa fa-question" aria-hidden="true"></i>
|
||||||
@@ -25,7 +25,7 @@
|
|||||||
<li>
|
<li>
|
||||||
<button class="border border-beige text-beige rounded
|
<button class="border border-beige text-beige rounded
|
||||||
m-1 px-2"
|
m-1 px-2"
|
||||||
hx-post="/api/sessio/{{ session_id }}/set/{{ set_id }}/tema/{{ entry_id }}"
|
hx-post="/api/sessio/{{ session_id }}/playlist/set/{{ set_id }}/tema/{{ entry_id }}"
|
||||||
hx-vals='{"title": "{{ query }}"}'
|
hx-vals='{"title": "{{ query }}"}'
|
||||||
hx-target="#tune-entry-{{ entry_id }}"
|
hx-target="#tune-entry-{{ entry_id }}"
|
||||||
hx-swap="outerHTML">
|
hx-swap="outerHTML">
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
class="border border-beige focus:outline-none
|
class="border border-beige focus:outline-none
|
||||||
rounded grow
|
rounded grow
|
||||||
bg-brown p-1 my-1"
|
bg-brown p-1 my-1"
|
||||||
name='upload_file'>
|
name='upload_file'/>
|
||||||
<button title="Afegeix un enllaç"
|
<button title="Afegeix un enllaç"
|
||||||
class="border border-beige rounded px-2 py-1 my-1"
|
class="border border-beige rounded px-2 py-1 my-1"
|
||||||
hx-get="/api/tema/{{ link.tema_id }}/editor/link/{{ link.id }}/url"
|
hx-get="/api/tema/{{ link.tema_id }}/editor/link/{{ link.id }}/url"
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ logger.info(f"Using DB_DIR: {DB_DIR}")
|
|||||||
|
|
||||||
DB_FILES_DIR = DB_DIR / "fitxer"
|
DB_FILES_DIR = DB_DIR / "fitxer"
|
||||||
DB_FILES_TEMA_DIR = DB_FILES_DIR / "tema"
|
DB_FILES_TEMA_DIR = DB_FILES_DIR / "tema"
|
||||||
|
DB_FILES_SESSION_DIR = DB_FILES_DIR / "sessio"
|
||||||
DB_FILES_SET_DIR = DB_FILES_DIR / "set"
|
DB_FILES_SET_DIR = DB_FILES_DIR / "set"
|
||||||
DB_FILES_TMP_DIR = DB_FILES_DIR / "tmp"
|
DB_FILES_TMP_DIR = DB_FILES_DIR / "tmp"
|
||||||
|
|
||||||
|
|||||||
@@ -59,13 +59,15 @@ def get_playlist_entries(
|
|||||||
return map(conversion.row_to_playlist_entry, cur.fetchall())
|
return map(conversion.row_to_playlist_entry, cur.fetchall())
|
||||||
|
|
||||||
|
|
||||||
GetTuneSessionsRow = tuple[int, int, str, str, str, str | None, str | None, bool]
|
GetTuneSessionsRow = tuple[int, int, str, str, str, str | None, str | None, str | None, str | None, bool]
|
||||||
|
|
||||||
|
|
||||||
def get_tune_sessions(tema_ids: list[int], con: Connection | None = None) -> dict[int, list[Session]]:
|
def get_tune_sessions(tema_ids: list[int], con: Connection | None = None) -> dict[int, list[Session]]:
|
||||||
placeholders = ", ".join(["?" for _ in tema_ids])
|
placeholders = ", ".join(["?" for _ in tema_ids])
|
||||||
query = f"""
|
query = f"""
|
||||||
SELECT p.tema_id, s.id, s.date, s.start_time, s.end_time, s.venue_name, s.venue_url, s.is_live
|
SELECT
|
||||||
|
p.tema_id, s.id, s.date, s.start_time, s.end_time, s.venue_name,
|
||||||
|
s.venue_url, s.notes, s.cartell_url, s.is_live
|
||||||
FROM playlists p JOIN sessions s ON p.session_id = s.id
|
FROM playlists p JOIN sessions s ON p.session_id = s.id
|
||||||
WHERE p.tema_id IN ({placeholders})
|
WHERE p.tema_id IN ({placeholders})
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -3,7 +3,17 @@ from typing import TypedDict
|
|||||||
|
|
||||||
from folkugat_web.model import sessions as model
|
from folkugat_web.model import sessions as model
|
||||||
|
|
||||||
SessionRowTuple = tuple[int, str, str, str, str | None, str | None, bool]
|
SessionRowTuple = tuple[
|
||||||
|
int, # id
|
||||||
|
str, # date
|
||||||
|
str, # start_time
|
||||||
|
str, # end_time
|
||||||
|
str | None, # venue_name
|
||||||
|
str | None, # venue_url
|
||||||
|
str | None, # notes
|
||||||
|
str | None, # cartell_url
|
||||||
|
bool, # is_live
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
class SessionRowDict(TypedDict):
|
class SessionRowDict(TypedDict):
|
||||||
@@ -13,6 +23,8 @@ class SessionRowDict(TypedDict):
|
|||||||
end_time: str
|
end_time: str
|
||||||
venue_name: str | None
|
venue_name: str | None
|
||||||
venue_url: str | None
|
venue_url: str | None
|
||||||
|
notes: str | None
|
||||||
|
cartell_url: str | None
|
||||||
is_live: bool
|
is_live: bool
|
||||||
|
|
||||||
|
|
||||||
@@ -24,6 +36,8 @@ def session_to_row(sessio: model.Session) -> SessionRowDict:
|
|||||||
'end_time': sessio.end_time.isoformat(),
|
'end_time': sessio.end_time.isoformat(),
|
||||||
'venue_name': sessio.venue.name,
|
'venue_name': sessio.venue.name,
|
||||||
'venue_url': sessio.venue.url,
|
'venue_url': sessio.venue.url,
|
||||||
|
'notes': sessio.notes,
|
||||||
|
'cartell_url': sessio.cartell_url,
|
||||||
'is_live': sessio.is_live,
|
'is_live': sessio.is_live,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -38,5 +52,7 @@ def row_to_session(row: SessionRowTuple) -> model.Session:
|
|||||||
name=row[4],
|
name=row[4],
|
||||||
url=row[5],
|
url=row[5],
|
||||||
),
|
),
|
||||||
is_live=row[6],
|
notes=row[6],
|
||||||
|
cartell_url=row[7],
|
||||||
|
is_live=row[8],
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -15,6 +15,8 @@ def create_sessions_table(con: Connection):
|
|||||||
end_time TEXT NOT NULL,
|
end_time TEXT NOT NULL,
|
||||||
venue_name TEXT,
|
venue_name TEXT,
|
||||||
venue_url TEXT,
|
venue_url TEXT,
|
||||||
|
notes TEXT,
|
||||||
|
cartell_url TEXT,
|
||||||
is_live BOOLEAN DEFAULT false
|
is_live BOOLEAN DEFAULT false
|
||||||
)
|
)
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ def get_sessions(session_id: int | None = None,
|
|||||||
|
|
||||||
clauses_str = " ".join(clauses)
|
clauses_str = " ".join(clauses)
|
||||||
query = f"""
|
query = f"""
|
||||||
SELECT id, date, start_time, end_time, venue_name, venue_url, is_live
|
SELECT id, date, start_time, end_time, venue_name, venue_url, notes, cartell_url, is_live
|
||||||
FROM sessions
|
FROM sessions
|
||||||
{clauses_str}
|
{clauses_str}
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -7,9 +7,9 @@ from . import conversion
|
|||||||
def insert_session(session: model.Session, con: Connection | None = None):
|
def insert_session(session: model.Session, con: Connection | None = None):
|
||||||
query = """
|
query = """
|
||||||
INSERT INTO sessions
|
INSERT INTO sessions
|
||||||
(id, date, start_time, end_time, venue_name, venue_url, is_live)
|
(id, date, start_time, end_time, venue_name, venue_url, notes, cartell_url, is_live)
|
||||||
VALUES
|
VALUES
|
||||||
(:id, :date, :start_time, :end_time, :venue_name, :venue_url, :is_live)
|
(:id, :date, :start_time, :end_time, :venue_name, :venue_url, :notes, :cartell_url, :is_live)
|
||||||
RETURNING *
|
RETURNING *
|
||||||
"""
|
"""
|
||||||
data = conversion.session_to_row(session)
|
data = conversion.session_to_row(session)
|
||||||
@@ -24,7 +24,8 @@ def update_session(session: model.Session, con: Connection | None = None):
|
|||||||
query = """
|
query = """
|
||||||
UPDATE sessions SET
|
UPDATE sessions SET
|
||||||
date = :date, start_time = :start_time, end_time = :end_time,
|
date = :date, start_time = :start_time, end_time = :end_time,
|
||||||
venue_name = :venue_name, venue_url = :venue_url, is_live = :is_live
|
venue_name = :venue_name, venue_url = :venue_url,
|
||||||
|
notes = :notes, cartell_url = :cartell_url, is_live = :is_live
|
||||||
WHERE id = :id
|
WHERE id = :id
|
||||||
"""
|
"""
|
||||||
data = conversion.session_to_row(session)
|
data = conversion.session_to_row(session)
|
||||||
|
|||||||
0
folkugat_web/fragments/sessio/__init__.py
Normal file
0
folkugat_web/fragments/sessio/__init__.py
Normal file
31
folkugat_web/fragments/sessio/cartell.py
Normal file
31
folkugat_web/fragments/sessio/cartell.py
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
from fastapi import Request
|
||||||
|
from fastapi.responses import HTMLResponse
|
||||||
|
from folkugat_web.model.pagines import Pages
|
||||||
|
from folkugat_web.services import playlists as playlists_service
|
||||||
|
from folkugat_web.services import sessions as sessions_service
|
||||||
|
from folkugat_web.services.temes import query as query_service
|
||||||
|
from folkugat_web.services.temes import search as search_service
|
||||||
|
from folkugat_web.templates import templates
|
||||||
|
|
||||||
|
|
||||||
|
def cartell(request: Request, session_id: int, logged_in: bool):
|
||||||
|
session = sessions_service.get_session(session_id=session_id)
|
||||||
|
return templates.TemplateResponse(
|
||||||
|
"fragments/sessio/cartell.html",
|
||||||
|
{
|
||||||
|
"request": request,
|
||||||
|
"logged_in": logged_in,
|
||||||
|
"session_id": session_id,
|
||||||
|
"session": session,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def cartell_editor(request: Request, session_id: int):
|
||||||
|
return templates.TemplateResponse(
|
||||||
|
"fragments/sessio/cartell_editor.html",
|
||||||
|
{
|
||||||
|
"request": request,
|
||||||
|
"session_id": session_id,
|
||||||
|
}
|
||||||
|
)
|
||||||
25
folkugat_web/fragments/sessio/page.py
Normal file
25
folkugat_web/fragments/sessio/page.py
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
from fastapi import HTTPException, Request
|
||||||
|
from folkugat_web.model.pagines import Pages
|
||||||
|
from folkugat_web.services import playlists as playlists_service
|
||||||
|
from folkugat_web.services import sessions as sessions_service
|
||||||
|
from folkugat_web.templates import templates
|
||||||
|
|
||||||
|
|
||||||
|
def pagina(request: Request, session_id: int, logged_in: bool):
|
||||||
|
session = sessions_service.get_session(session_id=session_id)
|
||||||
|
if not session:
|
||||||
|
raise HTTPException(status_code=404, detail="Could not find session")
|
||||||
|
playlist = playlists_service.get_playlist(session_id=session_id)
|
||||||
|
playlist = playlists_service.add_temes_to_playlist(playlist)
|
||||||
|
return templates.TemplateResponse(
|
||||||
|
"fragments/sessio/pagina.html",
|
||||||
|
{
|
||||||
|
"request": request,
|
||||||
|
"logged_in": logged_in,
|
||||||
|
"Pages": Pages,
|
||||||
|
"session_id": session_id,
|
||||||
|
"session": session,
|
||||||
|
"playlist": playlist,
|
||||||
|
"date_names": sessions_service.get_date_names,
|
||||||
|
}
|
||||||
|
)
|
||||||
@@ -8,24 +8,6 @@ from folkugat_web.services.temes import search as search_service
|
|||||||
from folkugat_web.templates import templates
|
from folkugat_web.templates import templates
|
||||||
|
|
||||||
|
|
||||||
def pagina(request: Request, session_id: int, logged_in: bool):
|
|
||||||
session = sessions_service.get_session(session_id=session_id)
|
|
||||||
playlist = playlists_service.get_playlist(session_id=session_id)
|
|
||||||
playlist = playlists_service.add_temes_to_playlist(playlist)
|
|
||||||
return templates.TemplateResponse(
|
|
||||||
"fragments/sessio/pagina.html",
|
|
||||||
{
|
|
||||||
"request": request,
|
|
||||||
"logged_in": logged_in,
|
|
||||||
"Pages": Pages,
|
|
||||||
"session_id": session_id,
|
|
||||||
"session": session,
|
|
||||||
"playlist": playlist,
|
|
||||||
"date_names": sessions_service.get_date_names,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def add_set(request: Request, session_id: int, logged_in: bool):
|
def add_set(request: Request, session_id: int, logged_in: bool):
|
||||||
new_set = playlists_service.add_set(session_id=session_id)
|
new_set = playlists_service.add_set(session_id=session_id)
|
||||||
return templates.TemplateResponse(
|
return templates.TemplateResponse(
|
||||||
@@ -19,6 +19,8 @@ class Session:
|
|||||||
start_time: datetime.time = DEFAULT_START_TIME
|
start_time: datetime.time = DEFAULT_START_TIME
|
||||||
end_time: datetime.time = DEFAULT_END_TIME
|
end_time: datetime.time = DEFAULT_END_TIME
|
||||||
venue: SessionVenue = dataclasses.field(default_factory=SessionVenue)
|
venue: SessionVenue = dataclasses.field(default_factory=SessionVenue)
|
||||||
|
notes: str | None = None
|
||||||
|
cartell_url: str | None = None
|
||||||
is_live: bool = False
|
is_live: bool = False
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import mimetypes
|
|||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import uuid
|
import uuid
|
||||||
from collections.abc import Iterator
|
from collections.abc import Iterable, Iterator
|
||||||
from contextlib import asynccontextmanager
|
from contextlib import asynccontextmanager
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
@@ -11,6 +11,7 @@ import aiofiles
|
|||||||
import magic
|
import magic
|
||||||
from fastapi import HTTPException, UploadFile
|
from fastapi import HTTPException, UploadFile
|
||||||
from folkugat_web.config import db
|
from folkugat_web.config import db
|
||||||
|
from folkugat_web.dal.sql.sessions import query as sessions_dal
|
||||||
from folkugat_web.dal.sql.temes import links as links_dal
|
from folkugat_web.dal.sql.temes import links as links_dal
|
||||||
from folkugat_web.dal.sql.temes import scores as scores_dal
|
from folkugat_web.dal.sql.temes import scores as scores_dal
|
||||||
from folkugat_web.log import logger
|
from folkugat_web.log import logger
|
||||||
@@ -22,22 +23,16 @@ async def get_mimetype(upload_file: UploadFile) -> str:
|
|||||||
return info.mime_type
|
return info.mime_type
|
||||||
|
|
||||||
|
|
||||||
ACCEPTED_MIMETYPES = [
|
IMAGE_MIMETYPE = re.compile(r"image/.+")
|
||||||
re.compile(r"image/.+"),
|
PDF_MIMETYPE = re.compile(r".+/pdf")
|
||||||
re.compile(r".+/pdf"),
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
def check_mimetype(mimetype: str) -> None:
|
def check_mimetype(mimetype: str, accepted_mimetypes: Iterable[re.Pattern[str]]) -> None:
|
||||||
if not any(regex.match(mimetype) for regex in ACCEPTED_MIMETYPES):
|
if not any(regex.match(mimetype) for regex in accepted_mimetypes):
|
||||||
raise HTTPException(status_code=400, detail=f"Unsupported file type: {mimetype}")
|
raise HTTPException(status_code=400, detail=f"Unsupported file type: {mimetype}")
|
||||||
|
|
||||||
|
|
||||||
def get_db_file_path(filepath: Path) -> str:
|
def check_upload_file_size(upload_file: UploadFile) -> None:
|
||||||
return f"{db.DB_FILES_URL}/{filepath.relative_to(db.DB_FILES_DIR)}"
|
|
||||||
|
|
||||||
|
|
||||||
async def store_file(tema_id: int, upload_file: UploadFile) -> str:
|
|
||||||
if not upload_file.size:
|
if not upload_file.size:
|
||||||
raise HTTPException(status_code=400, detail="Couldn't find out the size of the file")
|
raise HTTPException(status_code=400, detail="Couldn't find out the size of the file")
|
||||||
if upload_file.size > db.FILE_MAX_SIZE:
|
if upload_file.size > db.FILE_MAX_SIZE:
|
||||||
@@ -46,8 +41,15 @@ async def store_file(tema_id: int, upload_file: UploadFile) -> str:
|
|||||||
detail=f"The uploaded file is too big (max size = {db.FILE_MAX_SIZE} bytes)",
|
detail=f"The uploaded file is too big (max size = {db.FILE_MAX_SIZE} bytes)",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def get_db_file_path(filepath: Path) -> str:
|
||||||
|
return f"{db.DB_FILES_URL}/{filepath.relative_to(db.DB_FILES_DIR)}"
|
||||||
|
|
||||||
|
|
||||||
|
async def store_tema_file(tema_id: int, upload_file: UploadFile) -> str:
|
||||||
|
check_upload_file_size(upload_file)
|
||||||
mimetype = await get_mimetype(upload_file)
|
mimetype = await get_mimetype(upload_file)
|
||||||
check_mimetype(mimetype)
|
check_mimetype(mimetype, [IMAGE_MIMETYPE, PDF_MIMETYPE])
|
||||||
|
|
||||||
extension = mimetypes.guess_extension(mimetype) or ""
|
extension = mimetypes.guess_extension(mimetype) or ""
|
||||||
filepath = create_tema_filename(tema_id=tema_id, extension=extension)
|
filepath = create_tema_filename(tema_id=tema_id, extension=extension)
|
||||||
@@ -58,6 +60,20 @@ async def store_file(tema_id: int, upload_file: UploadFile) -> str:
|
|||||||
return get_db_file_path(filepath)
|
return get_db_file_path(filepath)
|
||||||
|
|
||||||
|
|
||||||
|
async def store_session_cartell(session_id: int, upload_file: UploadFile) -> str:
|
||||||
|
check_upload_file_size(upload_file)
|
||||||
|
mimetype = await get_mimetype(upload_file)
|
||||||
|
check_mimetype(mimetype, [IMAGE_MIMETYPE])
|
||||||
|
|
||||||
|
extension = mimetypes.guess_extension(mimetype) or ""
|
||||||
|
filepath = create_cartell_filename(session_id=session_id, extension=extension)
|
||||||
|
|
||||||
|
with open(filepath, "wb") as f:
|
||||||
|
_ = f.write(await upload_file.read())
|
||||||
|
|
||||||
|
return get_db_file_path(filepath)
|
||||||
|
|
||||||
|
|
||||||
def create_tema_filename(tema_id: int, extension: str = "") -> Path:
|
def create_tema_filename(tema_id: int, extension: str = "") -> Path:
|
||||||
filename = str(uuid.uuid4().hex) + extension
|
filename = str(uuid.uuid4().hex) + extension
|
||||||
filedir = db.DB_FILES_TEMA_DIR / str(tema_id)
|
filedir = db.DB_FILES_TEMA_DIR / str(tema_id)
|
||||||
@@ -66,6 +82,14 @@ def create_tema_filename(tema_id: int, extension: str = "") -> Path:
|
|||||||
return filepath
|
return filepath
|
||||||
|
|
||||||
|
|
||||||
|
def create_cartell_filename(session_id: int, extension: str = "") -> Path:
|
||||||
|
filename = str(uuid.uuid4().hex) + extension
|
||||||
|
filedir = db.DB_FILES_SESSION_DIR / str(session_id) / "cartell"
|
||||||
|
filedir.mkdir(parents=True, exist_ok=True)
|
||||||
|
filepath = filedir / filename
|
||||||
|
return filepath
|
||||||
|
|
||||||
|
|
||||||
def create_tmp_filename(extension: str = "") -> Path:
|
def create_tmp_filename(extension: str = "") -> Path:
|
||||||
filename = str(uuid.uuid4().hex) + extension
|
filename = str(uuid.uuid4().hex) + extension
|
||||||
filepath = db.DB_FILES_TMP_DIR / filename
|
filepath = db.DB_FILES_TMP_DIR / filename
|
||||||
@@ -94,11 +118,13 @@ def list_files(tema_id: str) -> list[str]:
|
|||||||
|
|
||||||
|
|
||||||
def get_orphan_files() -> Iterator[Path]:
|
def get_orphan_files() -> Iterator[Path]:
|
||||||
link_urls = {link.url for link in links_dal.get_links()}
|
alive_urls = (
|
||||||
score_pdf_urls = {score.pdf_url for score in scores_dal.get_scores() if score.pdf_url is not None}
|
{link.url for link in links_dal.get_links()}
|
||||||
score_img_urls = {score.img_url for score in scores_dal.get_scores() if score.img_url is not None}
|
| {score.pdf_url for score in scores_dal.get_scores() if score.pdf_url is not None}
|
||||||
score_preview_urls = {score.preview_url for score in scores_dal.get_scores() if score.preview_url is not None}
|
| {score.img_url for score in scores_dal.get_scores() if score.img_url is not None}
|
||||||
alive_urls = link_urls | score_pdf_urls | score_img_urls | score_preview_urls
|
| {score.preview_url for score in scores_dal.get_scores() if score.preview_url is not None}
|
||||||
|
| {session.cartell_url for session in sessions_dal.get_sessions() if session.cartell_url}
|
||||||
|
)
|
||||||
return filter(
|
return filter(
|
||||||
lambda p: p.is_file() and get_db_file_path(p) not in alive_urls,
|
lambda p: p.is_file() and get_db_file_path(p) not in alive_urls,
|
||||||
itertools.chain(
|
itertools.chain(
|
||||||
|
|||||||
10
scripts/04_add_session_notes_i_cartell.py
Normal file
10
scripts/04_add_session_notes_i_cartell.py
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
from folkugat_web.dal.sql import get_connection
|
||||||
|
|
||||||
|
with get_connection() as con:
|
||||||
|
cur = con.cursor()
|
||||||
|
alter_query_1 = """ ALTER TABLE sessions ADD COLUMN notes TEXT """
|
||||||
|
alter_query_2 = """ ALTER TABLE sessions ADD COLUMN cartell_url TEXT """
|
||||||
|
_ = cur.execute(alter_query_1)
|
||||||
|
_ = cur.execute(alter_query_2)
|
||||||
|
|
||||||
|
print("DONE!")
|
||||||
Reference in New Issue
Block a user