From ac54453b7f226cf9b3fd5e348458f9b5bace6c3c Mon Sep 17 00:00:00 2001 From: marc Date: Fri, 21 Mar 2025 19:42:43 +0100 Subject: [PATCH] Session editor and live sessions! --- folkugat_web/api/__init__.py | 1 + folkugat_web/api/sessio/__init__.py | 1 + folkugat_web/api/sessio/index.py | 199 ++++++++++++++++++ folkugat_web/api/sessio/live.py | 37 ++++ folkugat_web/api/sessio/set_page.py | 33 +++ folkugat_web/api/sessions/__init__.py | 2 +- folkugat_web/api/sessions/sessio.py | 41 ---- folkugat_web/api/tema/index.py | 4 +- folkugat_web/api/temes/index.py | 4 +- folkugat_web/assets/static/css/main.css | 30 ++- .../assets/templates/fragments/header.html | 5 +- .../assets/templates/fragments/marquee.html | 30 ++- .../fragments/sessio/live/pagina.html | 2 + .../fragments/sessio/live/set_page.html | 5 + .../{sessions => sessio}/live/start.html | 2 +- .../{sessions => sessio}/live/stop.html | 2 +- .../sessio.html => sessio/pagina.html} | 26 ++- .../templates/fragments/sessio/playlist.html | 17 ++ .../fragments/sessio/set/pagina.html | 2 + .../fragments/sessio/set/set_page.html | 30 +++ .../templates/fragments/sessio/set/tema.html | 25 +++ .../templates/fragments/sessio/set_entry.html | 46 ++++ .../fragments/sessio/tema_editor.html | 30 +++ .../fragments/sessio/tema_entry.html | 29 +++ .../fragments/sessio/tema_results.html | 36 ++++ .../fragments/sessions/session_date.html | 33 +-- .../fragments/sessions/session_row.html | 6 +- .../templates/fragments/tema/link_icon.html | 2 + .../templates/fragments/tema/links.html | 2 +- .../templates/fragments/tema/lyrics.html | 2 +- .../templates/fragments/tema/pagina.html | 19 +- .../templates/fragments/tema/properties.html | 2 +- .../templates/fragments/tema/score.html | 8 +- .../templates/fragments/tema/title.html | 2 +- .../templates/fragments/temes/pagina.html | 3 +- .../fragments/temes/result_links.html | 14 +- .../templates/fragments/temes/results.html | 60 ++++-- folkugat_web/dal/sql/ddl.py | 2 + folkugat_web/dal/sql/playlists/__init__.py | 0 folkugat_web/dal/sql/playlists/_conversion.py | 19 ++ folkugat_web/dal/sql/playlists/ddl.py | 27 +++ folkugat_web/dal/sql/playlists/query.py | 47 +++++ folkugat_web/dal/sql/playlists/write.py | 61 ++++++ folkugat_web/data.py | 18 +- folkugat_web/fragments/live.py | 17 +- folkugat_web/fragments/sessio.py | 163 ++++++++++++++ folkugat_web/fragments/sessions.py | 14 -- folkugat_web/fragments/set_page.py | 72 +++++++ folkugat_web/fragments/temes.py | 20 +- folkugat_web/model/playlists.py | 77 +++++++ folkugat_web/model/temes.py | 2 +- folkugat_web/services/playlists.py | 78 +++++++ folkugat_web/services/temes/search.py | 2 +- folkugat_web/services/temes/write.py | 9 +- 54 files changed, 1247 insertions(+), 173 deletions(-) create mode 100644 folkugat_web/api/sessio/__init__.py create mode 100644 folkugat_web/api/sessio/index.py create mode 100644 folkugat_web/api/sessio/live.py create mode 100644 folkugat_web/api/sessio/set_page.py delete mode 100644 folkugat_web/api/sessions/sessio.py create mode 100644 folkugat_web/assets/templates/fragments/sessio/live/pagina.html create mode 100644 folkugat_web/assets/templates/fragments/sessio/live/set_page.html rename folkugat_web/assets/templates/fragments/{sessions => sessio}/live/start.html (84%) rename folkugat_web/assets/templates/fragments/{sessions => sessio}/live/stop.html (84%) rename folkugat_web/assets/templates/fragments/{sessions/sessio.html => sessio/pagina.html} (55%) create mode 100644 folkugat_web/assets/templates/fragments/sessio/playlist.html create mode 100644 folkugat_web/assets/templates/fragments/sessio/set/pagina.html create mode 100644 folkugat_web/assets/templates/fragments/sessio/set/set_page.html create mode 100644 folkugat_web/assets/templates/fragments/sessio/set/tema.html create mode 100644 folkugat_web/assets/templates/fragments/sessio/set_entry.html create mode 100644 folkugat_web/assets/templates/fragments/sessio/tema_editor.html create mode 100644 folkugat_web/assets/templates/fragments/sessio/tema_entry.html create mode 100644 folkugat_web/assets/templates/fragments/sessio/tema_results.html create mode 100644 folkugat_web/dal/sql/playlists/__init__.py create mode 100644 folkugat_web/dal/sql/playlists/_conversion.py create mode 100644 folkugat_web/dal/sql/playlists/ddl.py create mode 100644 folkugat_web/dal/sql/playlists/query.py create mode 100644 folkugat_web/dal/sql/playlists/write.py create mode 100644 folkugat_web/fragments/sessio.py create mode 100644 folkugat_web/fragments/set_page.py create mode 100644 folkugat_web/model/playlists.py create mode 100644 folkugat_web/services/playlists.py diff --git a/folkugat_web/api/__init__.py b/folkugat_web/api/__init__.py index 0b302bc..12f6d40 100644 --- a/folkugat_web/api/__init__.py +++ b/folkugat_web/api/__init__.py @@ -1,6 +1,7 @@ from ._router import router from .auth import * from .index import * +from .sessio import * from .sessions import * from .tema import * from .temes import * diff --git a/folkugat_web/api/sessio/__init__.py b/folkugat_web/api/sessio/__init__.py new file mode 100644 index 0000000..b56b5e1 --- /dev/null +++ b/folkugat_web/api/sessio/__init__.py @@ -0,0 +1 @@ +from . import index, live, set_page diff --git a/folkugat_web/api/sessio/index.py b/folkugat_web/api/sessio/index.py new file mode 100644 index 0000000..17249f6 --- /dev/null +++ b/folkugat_web/api/sessio/index.py @@ -0,0 +1,199 @@ +from typing import Annotated + +from fastapi import Form, Request +from folkugat_web.api import router +from folkugat_web.fragments import live, sessio +from folkugat_web.services import auth +from folkugat_web.services.temes import write as temes_service +from folkugat_web.templates import templates + + +@router.get("/sessio/{session_id}") +def page( + request: Request, + logged_in: auth.LoggedIn, + session_id: int, +): + return templates.TemplateResponse( + "index.html", + { + "request": request, + "page_title": "Folkugat", + "content": f"/api/content/sessio/{session_id}", + "logged_in": logged_in, + } + ) + + +@router.get("/api/content/sessio/{session_id}") +def contingut( + request: Request, + logged_in: auth.LoggedIn, + session_id: int, +): + return sessio.pagina(request, session_id, logged_in) + + +@router.put("/api/sessio/{session_id}/live") +def set_live( + request: Request, + _: auth.RequireLogin, + session_id: int, +): + return live.start_live_session(request=request, session_id=session_id) + + +@router.delete("/api/sessio/{session_id}/live") +def stop_live( + request: Request, + _: auth.RequireLogin, + session_id: int, +): + 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, + ) diff --git a/folkugat_web/api/sessio/live.py b/folkugat_web/api/sessio/live.py new file mode 100644 index 0000000..70e09dc --- /dev/null +++ b/folkugat_web/api/sessio/live.py @@ -0,0 +1,37 @@ +from fastapi import Request +from folkugat_web.api import router +from folkugat_web.fragments import set_page +from folkugat_web.services import auth +from folkugat_web.templates import templates + + +@router.get("/live") +def page( + request: Request, + logged_in: auth.LoggedIn, +): + return templates.TemplateResponse( + "index.html", + { + "request": request, + "page_title": "Folkugat", + "content": f"/api/content/live", + "logged_in": logged_in, + } + ) + + +@router.get("/api/content/live") +def contingut( + request: Request, + logged_in: auth.LoggedIn, +): + return set_page.live(request, logged_in) + + +@router.get("/api/content/live/set") +def get_set_page( + request: Request, + logged_in: auth.LoggedIn, +): + return set_page.live_set(request, logged_in) diff --git a/folkugat_web/api/sessio/set_page.py b/folkugat_web/api/sessio/set_page.py new file mode 100644 index 0000000..7502321 --- /dev/null +++ b/folkugat_web/api/sessio/set_page.py @@ -0,0 +1,33 @@ +from fastapi import Request +from folkugat_web.api import router +from folkugat_web.fragments import set_page +from folkugat_web.services import auth +from folkugat_web.templates import templates + + +@router.get("/sessio/{session_id}/set/{set_id}") +def page( + request: Request, + logged_in: auth.LoggedIn, + session_id: int, + set_id: int, +): + return templates.TemplateResponse( + "index.html", + { + "request": request, + "page_title": "Folkugat", + "content": f"/api/content/sessio/{session_id}/set/{set_id}", + "logged_in": logged_in, + } + ) + + +@router.get("/api/content/sessio/{session_id}/set/{set_id}") +def contingut( + request: Request, + logged_in: auth.LoggedIn, + session_id: int, + set_id: int, +): + return set_page.pagina(request, session_id, set_id, logged_in) diff --git a/folkugat_web/api/sessions/__init__.py b/folkugat_web/api/sessions/__init__.py index 66b414f..aba1bbe 100644 --- a/folkugat_web/api/sessions/__init__.py +++ b/folkugat_web/api/sessions/__init__.py @@ -1 +1 @@ -from . import editor, index, sessio +from . import editor, index diff --git a/folkugat_web/api/sessions/sessio.py b/folkugat_web/api/sessions/sessio.py deleted file mode 100644 index 9c26b01..0000000 --- a/folkugat_web/api/sessions/sessio.py +++ /dev/null @@ -1,41 +0,0 @@ -from fastapi import Request -from folkugat_web.api import router -from folkugat_web.fragments import live, sessions -from folkugat_web.services import auth -from folkugat_web.templates import templates - - -@router.get("/sessio/{session_id}") -def page( - request: Request, - session_id: int, - logged_in: auth.LoggedIn, -): - return templates.TemplateResponse( - "index.html", - { - "request": request, - "page_title": "Folkugat", - "content": f"/api/content/sessio/{session_id}", - "logged_in": logged_in, - } - ) - - -@router.get("/api/content/sessio/{session_id}") -def contingut( - request: Request, - session_id: int, - logged_in: auth.LoggedIn, -): - return sessions.sessio(request, session_id, logged_in) - - -@router.put("/api/sessio/{session_id}/live") -def set_live(request: Request, session_id: int, _: auth.RequireLogin): - return live.start_live_session(request=request, session_id=session_id) - - -@router.delete("/api/sessio/{session_id}/live") -def stop_live(request: Request, session_id: int, _: auth.RequireLogin): - return live.stop_live_session(request=request, session_id=session_id) diff --git a/folkugat_web/api/tema/index.py b/folkugat_web/api/tema/index.py index 74f5f15..a79ec30 100644 --- a/folkugat_web/api/tema/index.py +++ b/folkugat_web/api/tema/index.py @@ -32,7 +32,7 @@ def contingut(request: Request, logged_in: auth.LoggedIn, tema_id: int): @router.delete("/api/tema/{tema_id}") -def delete_tema(request: Request, _: auth.RequireLogin, tema_id: int): +def delete_tema(_: auth.RequireLogin, tema_id: int): temes_w.delete_tema(tema_id=tema_id) return HTMLResponse(headers={ 'HX-Redirect': '/temes' @@ -40,7 +40,7 @@ def delete_tema(request: Request, _: auth.RequireLogin, tema_id: int): @router.post("/api/tema") -def create_tema(request: Request, _: auth.RequireLogin, title: Annotated[str, Form()] = ""): +def create_tema(_: auth.RequireLogin, title: Annotated[str, Form()] = ""): new_tema = temes_w.create_tema(title=title) return HTMLResponse(headers={ 'HX-Redirect': f'/tema/{new_tema.id}' diff --git a/folkugat_web/api/temes/index.py b/folkugat_web/api/temes/index.py index ceb63d8..cd5183e 100644 --- a/folkugat_web/api/temes/index.py +++ b/folkugat_web/api/temes/index.py @@ -36,5 +36,5 @@ def content( @router.get("/api/temes/busca") -def busca(request: Request, query: str, logged_in: auth.LoggedIn): - return temes.temes_busca(request, query, logged_in) +def busca(request: Request, query: str, logged_in: auth.LoggedIn, limit: int = 10, offset: int = 0): + return temes.temes_busca(request, query=query, limit=limit, offset=offset, logged_in=logged_in) diff --git a/folkugat_web/assets/static/css/main.css b/folkugat_web/assets/static/css/main.css index 462f760..4ed7a43 100644 --- a/folkugat_web/assets/static/css/main.css +++ b/folkugat_web/assets/static/css/main.css @@ -606,11 +606,20 @@ video { margin: 1.5rem; } +.m-8 { + margin: 2rem; +} + .mx-1 { margin-left: 0.25rem; margin-right: 0.25rem; } +.mx-12 { + margin-left: 3rem; + margin-right: 3rem; +} + .mx-2 { margin-left: 0.5rem; margin-right: 0.5rem; @@ -661,6 +670,14 @@ video { margin-top: 0.75rem; } +.mt-4 { + margin-top: 1rem; +} + +.mt-8 { + margin-top: 2rem; +} + .inline-block { display: inline-block; } @@ -936,14 +953,14 @@ video { padding-bottom: 0.5rem; } -.pl-10 { - padding-left: 2.5rem; -} - .pl-5 { padding-left: 1.25rem; } +.pt-4 { + padding-top: 1rem; +} + .text-left { text-align: left; } @@ -994,6 +1011,11 @@ video { color: rgb(178 124 9 / var(--tw-text-opacity, 1)); } +.text-brown { + --tw-text-opacity: 1; + color: rgb(62 56 52 / var(--tw-text-opacity, 1)); +} + .text-white { --tw-text-opacity: 1; color: rgb(255 255 255 / var(--tw-text-opacity, 1)); diff --git a/folkugat_web/assets/templates/fragments/header.html b/folkugat_web/assets/templates/fragments/header.html index 0d2b7ea..68bb5b9 100644 --- a/folkugat_web/assets/templates/fragments/header.html +++ b/folkugat_web/assets/templates/fragments/header.html @@ -1,5 +1,8 @@
- Folkugat + Folkugat

{{ page_title }}

Sessions de folk a Sant Cugat

diff --git a/folkugat_web/assets/templates/fragments/marquee.html b/folkugat_web/assets/templates/fragments/marquee.html index 50f953b..d0886d9 100644 --- a/folkugat_web/assets/templates/fragments/marquee.html +++ b/folkugat_web/assets/templates/fragments/marquee.html @@ -1,6 +1,9 @@ -{% if session %}
+ {% if current_set is not none %} + + {% else %} + {% endif %}
{% for _ in (1, 2, 3) %} @@ -9,14 +12,25 @@ - - Està sonant Pasdoble de Muntanya - - - ♫ - + {% if current_set is not none %} + + Estem tocant + {% for tema_in_set in current_set.temes %} + {% if loop.index != 1 %} + + + {% endif %} + {% if tema_in_set.tema is not none %} + {{ tema_in_set.tema.title }} + {% else %} + ??? + {% endif %} + {% endfor %} + + + ♫ + + {% endif %} {% endfor %}
-{% endif %} diff --git a/folkugat_web/assets/templates/fragments/sessio/live/pagina.html b/folkugat_web/assets/templates/fragments/sessio/live/pagina.html new file mode 100644 index 0000000..474b6b1 --- /dev/null +++ b/folkugat_web/assets/templates/fragments/sessio/live/pagina.html @@ -0,0 +1,2 @@ +{% include "fragments/menu.html" %} +{% include "fragments/sessio/live/set_page.html" %} diff --git a/folkugat_web/assets/templates/fragments/sessio/live/set_page.html b/folkugat_web/assets/templates/fragments/sessio/live/set_page.html new file mode 100644 index 0000000..a8d7db5 --- /dev/null +++ b/folkugat_web/assets/templates/fragments/sessio/live/set_page.html @@ -0,0 +1,5 @@ +
+ {% include "fragments/sessio/set/set_page.html" %} +
" diff --git a/folkugat_web/assets/templates/fragments/sessions/live/start.html b/folkugat_web/assets/templates/fragments/sessio/live/start.html similarity index 84% rename from folkugat_web/assets/templates/fragments/sessions/live/start.html rename to folkugat_web/assets/templates/fragments/sessio/live/start.html index 7fdb560..bebee97 100644 --- a/folkugat_web/assets/templates/fragments/sessions/live/start.html +++ b/folkugat_web/assets/templates/fragments/sessio/live/start.html @@ -1,5 +1,5 @@ + +{% endif %} diff --git a/folkugat_web/assets/templates/fragments/sessio/set/pagina.html b/folkugat_web/assets/templates/fragments/sessio/set/pagina.html new file mode 100644 index 0000000..e062eba --- /dev/null +++ b/folkugat_web/assets/templates/fragments/sessio/set/pagina.html @@ -0,0 +1,2 @@ +{% include "fragments/menu.html" %} +{% include "fragments/sessio/set/set_page.html" %} diff --git a/folkugat_web/assets/templates/fragments/sessio/set/set_page.html b/folkugat_web/assets/templates/fragments/sessio/set/set_page.html new file mode 100644 index 0000000..1732cb8 --- /dev/null +++ b/folkugat_web/assets/templates/fragments/sessio/set/set_page.html @@ -0,0 +1,30 @@ +{% if session is not none %} +
+ {% set dn = date_names(session.date) %} + + + + Tocat el {{ dn.day_name }} {{ dn.day }} {{ dn.month_name }} de {{ dn.year }} + + +
+{% endif %} +{% for tema_in_set in set.temes %} + {% if loop.index != 1 %} +
+
+
+ {% endif %} + {% if tema_in_set.tema is not none %} + {% set tema = tema_in_set.tema %} + {% include "fragments/sessio/set/tema.html"%} + {% else %} +

+ Desconegut +

+
+ No sabem quin tema és aquest +
+ {% endif %} +
+{% endfor %} diff --git a/folkugat_web/assets/templates/fragments/sessio/set/tema.html b/folkugat_web/assets/templates/fragments/sessio/set/tema.html new file mode 100644 index 0000000..83c1c8a --- /dev/null +++ b/folkugat_web/assets/templates/fragments/sessio/set/tema.html @@ -0,0 +1,25 @@ +

+ {{ tema.title }} + + + +

+
+ + {% if tema.score() is not none %} + {% include "fragments/tema/score.html" %} + {% endif %} + + {% if tema.lyrics %} + {% set lyric = tema.lyrics[0] %} +
+

Lletra

+
+
+ {{ lyric.content.replace('\n', '
') | safe }} +
+
+ {% endif %} + +
diff --git a/folkugat_web/assets/templates/fragments/sessio/set_entry.html b/folkugat_web/assets/templates/fragments/sessio/set_entry.html new file mode 100644 index 0000000..6d84681 --- /dev/null +++ b/folkugat_web/assets/templates/fragments/sessio/set_entry.html @@ -0,0 +1,46 @@ +
  • +
    + {% if logged_in %} + + {% endif %} +
      + {% for tema_entry in set_entry.temes %} + {% if new_entry %} + {% include "fragments/sessio/tema_editor.html" %} + {% else %} + {% include "fragments/sessio/tema_entry.html" %} + {% endif %} + {% endfor %} +
    + {% if logged_in %} + + {% endif %} +
    +
    + + + +
    +
  • diff --git a/folkugat_web/assets/templates/fragments/sessio/tema_editor.html b/folkugat_web/assets/templates/fragments/sessio/tema_editor.html new file mode 100644 index 0000000..01ec5e9 --- /dev/null +++ b/folkugat_web/assets/templates/fragments/sessio/tema_editor.html @@ -0,0 +1,30 @@ +
  • +
    + + +
    + +
  • diff --git a/folkugat_web/assets/templates/fragments/sessio/tema_entry.html b/folkugat_web/assets/templates/fragments/sessio/tema_entry.html new file mode 100644 index 0000000..d2b8e07 --- /dev/null +++ b/folkugat_web/assets/templates/fragments/sessio/tema_entry.html @@ -0,0 +1,29 @@ +
  • +
    + {% if tema_entry.tema is none %} + + (Desconegut) + {% else %} + + {{ tema_entry.tema.title }} + + {% endif %} +
    + {% if logged_in %} + + + {% endif %} +
  • diff --git a/folkugat_web/assets/templates/fragments/sessio/tema_results.html b/folkugat_web/assets/templates/fragments/sessio/tema_results.html new file mode 100644 index 0000000..f8e1c66 --- /dev/null +++ b/folkugat_web/assets/templates/fragments/sessio/tema_results.html @@ -0,0 +1,36 @@ + diff --git a/folkugat_web/assets/templates/fragments/sessions/session_date.html b/folkugat_web/assets/templates/fragments/sessions/session_date.html index df7eafb..3442de3 100644 --- a/folkugat_web/assets/templates/fragments/sessions/session_date.html +++ b/folkugat_web/assets/templates/fragments/sessions/session_date.html @@ -1,24 +1,11 @@ -

    - {% if session == None %} - L'últim Dimecres de cada mes - {% else %} - - {% set dn = date_names(session.date) %} - {{ dn.day_name }} {{ dn.day }} {{ dn.month_name }} - - de {{ session.start_time.strftime("%H:%M") }} - a {{ session.end_time.strftime("%H:%M") }} - {% if session.venue.name %} - a {{ session.venue.name }} - - - - - - - - - - {% endif %} +{% if session == None %} + L'últim Dimecres de cada mes +{% else %} + {% set dn = date_names(session.date) %} + {{ dn.day_name }} {{ dn.day }} {{ dn.month_name }} + de {{ session.start_time.strftime("%H:%M") }} + a {{ session.end_time.strftime("%H:%M") }} + {% if session.venue.name %} + a {{ session.venue.name }} {% endif %} -

    +{% endif %} diff --git a/folkugat_web/assets/templates/fragments/sessions/session_row.html b/folkugat_web/assets/templates/fragments/sessions/session_row.html index 341abda..aa055cf 100644 --- a/folkugat_web/assets/templates/fragments/sessions/session_row.html +++ b/folkugat_web/assets/templates/fragments/sessions/session_row.html @@ -4,15 +4,17 @@ relative" id="session-row-{{session.id}}"> -
    +
    - + {% if logged_in %} + {% endif %} + {% if next_offset is not none %} + + {% endif %} +
    + {% endif %} +
    diff --git a/folkugat_web/dal/sql/ddl.py b/folkugat_web/dal/sql/ddl.py index e84a6f6..e68475c 100644 --- a/folkugat_web/dal/sql/ddl.py +++ b/folkugat_web/dal/sql/ddl.py @@ -1,4 +1,5 @@ from folkugat_web.dal.sql import get_connection, sessions +from folkugat_web.dal.sql.playlists import ddl as playlists_ddl from folkugat_web.dal.sql.temes import ddl as temes_ddl @@ -6,3 +7,4 @@ def create_db(): with get_connection() as con: sessions.create_db(con) temes_ddl.create_db(con) + playlists_ddl.create_db(con) diff --git a/folkugat_web/dal/sql/playlists/__init__.py b/folkugat_web/dal/sql/playlists/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/folkugat_web/dal/sql/playlists/_conversion.py b/folkugat_web/dal/sql/playlists/_conversion.py new file mode 100644 index 0000000..787d4d3 --- /dev/null +++ b/folkugat_web/dal/sql/playlists/_conversion.py @@ -0,0 +1,19 @@ +from folkugat_web.model import playlists as model + + +def playlist_entry_to_row(tema_in_set: model.PlaylistEntry) -> dict: + return { + 'id': tema_in_set.id, + 'session_id': tema_in_set.session_id, + 'set_id': tema_in_set.set_id, + 'tema_id': tema_in_set.tema_id, + } + + +def row_to_playlist_entry(row: tuple) -> model.PlaylistEntry: + return model.PlaylistEntry( + id=row[0], + session_id=row[1], + set_id=row[2], + tema_id=row[3], + ) diff --git a/folkugat_web/dal/sql/playlists/ddl.py b/folkugat_web/dal/sql/playlists/ddl.py new file mode 100644 index 0000000..3c5efeb --- /dev/null +++ b/folkugat_web/dal/sql/playlists/ddl.py @@ -0,0 +1,27 @@ +from typing import Optional + +from folkugat_web.dal.sql import Connection, get_connection + + +def create_db(con: Optional[Connection] = None): + with get_connection(con) as con: + create_playlists_table(con) + + +def drop_playlists_table(con: Connection): + query = "DROP TABLE IF EXISTS playlists" + cur = con.cursor() + cur.execute(query) + + +def create_playlists_table(con: Connection): + query = """ + CREATE TABLE IF NOT EXISTS playlists ( + id INTEGER PRIMARY KEY, + session_id INTEGER NOT NULL, + set_id INTEGER NOT NULL, + tema_id INTEGER + ) + """ + cur = con.cursor() + cur.execute(query) diff --git a/folkugat_web/dal/sql/playlists/query.py b/folkugat_web/dal/sql/playlists/query.py new file mode 100644 index 0000000..0c8bbdd --- /dev/null +++ b/folkugat_web/dal/sql/playlists/query.py @@ -0,0 +1,47 @@ +from collections.abc import Iterator +from typing import Optional + +from folkugat_web.dal.sql import Connection, get_connection +from folkugat_web.model import playlists as model + +from ._conversion import row_to_playlist_entry + + +def _filter_clause( + entry_id: Optional[int] = None, + set_id: Optional[int] = None, + session_id: Optional[int] = None, +) -> tuple[str, dict]: + filter_clauses = [] + query_data = {} + + if entry_id is not None: + filter_clauses.append("id = :id") + query_data["id"] = entry_id + if set_id is not None: + filter_clauses.append("set_id = :set_id") + query_data["set_id"] = set_id + if session_id is not None: + filter_clauses.append("session_id = :session_id") + query_data["session_id"] = session_id + + return " AND ".join(filter_clauses), query_data + + +def get_playlist_entries( + entry_id: Optional[int] = None, + set_id: Optional[int] = None, + session_id: Optional[int] = None, + con: Optional[Connection] = None, +) -> Iterator[model.PlaylistEntry]: + filter_clause, data = _filter_clause(entry_id=entry_id, set_id=set_id, session_id=session_id) + query = f""" + SELECT + id, session_id, set_id, tema_id + FROM playlists + WHERE {filter_clause} + """ + with get_connection(con) as con: + cur = con.cursor() + cur.execute(query, data) + return map(row_to_playlist_entry, cur.fetchall()) diff --git a/folkugat_web/dal/sql/playlists/write.py b/folkugat_web/dal/sql/playlists/write.py new file mode 100644 index 0000000..84fcc47 --- /dev/null +++ b/folkugat_web/dal/sql/playlists/write.py @@ -0,0 +1,61 @@ +from typing import Optional + +from folkugat_web.dal.sql import Connection, get_connection +from folkugat_web.model import playlists as model + +from ._conversion import playlist_entry_to_row, row_to_playlist_entry + + +def insert_playlist_entry(pl_entry: model.PlaylistEntry, con: Optional[Connection] = None) -> model.PlaylistEntry: + query = """ + INSERT INTO playlists + (id, session_id, set_id, tema_id) + VALUES + (:id, :session_id, :set_id, :tema_id) + RETURNING * + """ + data = playlist_entry_to_row(pl_entry) + with get_connection(con) as con: + cur = con.cursor() + cur.execute(query, data) + row = cur.fetchone() + return row_to_playlist_entry(row) + + +def update_playlist_entry(entry: model.PlaylistEntry, con: Optional[Connection] = None): + query = """ + UPDATE playlists + SET + id = :id, session_id = :session_id, set_id = :set_id, tema_id = :tema_id + WHERE + id = :id + """ + data = playlist_entry_to_row(entry) + with get_connection(con) as con: + cur = con.cursor() + cur.execute(query, data) + return + + +def delete_playlist_entry(entry_id: int, con: Optional[Connection] = None): + query = """ + DELETE FROM playlists + WHERE id = :id + """ + data = dict(id=entry_id) + with get_connection(con) as con: + cur = con.cursor() + cur.execute(query, data) + return + + +def delete_playlist_set(session_id: int, set_id: int, con: Optional[Connection] = None): + query = """ + DELETE FROM playlists + WHERE session_id = :session_id AND set_id = :set_id + """ + data = dict(session_id=session_id, set_id=set_id) + with get_connection(con) as con: + cur = con.cursor() + cur.execute(query, data) + return diff --git a/folkugat_web/data.py b/folkugat_web/data.py index 2154280..40aee94 100644 --- a/folkugat_web/data.py +++ b/folkugat_web/data.py @@ -1,4 +1,4 @@ -from folkugat_web.model import IndexedList +from folkugat_web.model import IndexedList, playlists from folkugat_web.model import temes as model TEMES = [ @@ -110,3 +110,19 @@ el meu País Valencià. hidden=False, ).with_ngrams(), ] + +PLAYLIST_ENTRIES = [ + playlists.PlaylistEntry(0, 2, 0, 1), + playlists.PlaylistEntry(1, 2, 0, 2), + playlists.PlaylistEntry(2, 2, 1, 3), + playlists.PlaylistEntry(3, 2, 2, 4), + playlists.PlaylistEntry(4, 2, 2, 5), + playlists.PlaylistEntry(5, 2, 2, 6), + playlists.PlaylistEntry(6, 2, 3, 7), + playlists.PlaylistEntry(7, 2, 4, 8), +] + +PLAYLIST = playlists.Playlist.from_playlist_entries( + session_id=2, + entries=PLAYLIST_ENTRIES, +) diff --git a/folkugat_web/fragments/live.py b/folkugat_web/fragments/live.py index c114989..9c9f95c 100644 --- a/folkugat_web/fragments/live.py +++ b/folkugat_web/fragments/live.py @@ -1,16 +1,29 @@ from fastapi import Request +from fastapi.responses import HTMLResponse from folkugat_web.model import sessions as model +from folkugat_web.services import playlists as playlists_service from folkugat_web.services import sessions as service from folkugat_web.templates import templates def sessio_en_directe(request: Request): session = service.get_live_session() + if not session: + return HTMLResponse() + if not session.id: + raise RuntimeError("Got a session without id!") + + current_set = None + if playlist := playlists_service.get_playlist(session_id=session.id): + if playlist.sets: + current_set = playlists_service.add_temes_to_set(playlist.sets[-1]) + return templates.TemplateResponse( "fragments/marquee.html", { "request": request, "session": session, + "current_set": current_set, } ) @@ -19,7 +32,7 @@ def start_live_session(request: Request, session_id: int): service.set_live_session(session_id=session_id) session = model.Session(id=session_id) return templates.TemplateResponse( - "fragments/sessions/live/stop.html", + "fragments/sessio/live/stop.html", { "request": request, "session": session, @@ -34,7 +47,7 @@ def stop_live_session(request: Request, session_id: int): service.stop_live_sessions() session = model.Session(id=session_id) return templates.TemplateResponse( - "fragments/sessions/live/start.html", + "fragments/sessio/live/start.html", { "request": request, "session": session, diff --git a/folkugat_web/fragments/sessio.py b/folkugat_web/fragments/sessio.py new file mode 100644 index 0000000..06efcdf --- /dev/null +++ b/folkugat_web/fragments/sessio.py @@ -0,0 +1,163 @@ +from typing import Optional + +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 search as search_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) + 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): + new_set = playlists_service.add_set(session_id=session_id) + return templates.TemplateResponse( + "fragments/sessio/set_entry.html", + { + "request": request, + "logged_in": logged_in, + "new_entry": True, + "session_id": session_id, + "set_id": new_set.id, + "set_entry": new_set, + } + ) + + +def get_set(request: Request, session_id: int, set_id: int, logged_in: bool): + set_entry = playlists_service.get_set(session_id=session_id, set_id=set_id) + if set_entry: + return templates.TemplateResponse( + "fragments/sessio/set_entry.html", + { + "request": request, + "logged_in": logged_in, + "new_entry": True, + "session_id": session_id, + "set_id": set_id, + "set_entry": set_entry, + } + ) + else: + return HTMLResponse() + + +def delete_set(session_id: int, set_id: int): + playlists_service.delete_set(session_id=session_id, set_id=set_id) + return HTMLResponse() + + +def add_tema(request: Request, session_id: int, set_id: int, logged_in: bool): + new_tema = playlists_service.add_tema(session_id=session_id, set_id=set_id) + playlists_service.add_tema_to_tema_in_set(new_tema) + return templates.TemplateResponse( + "fragments/sessio/tema_editor.html", + { + "request": request, + "logged_in": logged_in, + "session_id": session_id, + "set_id": set_id, + "tema_entry": new_tema, + } + ) + + +def get_tema(request: Request, session_id: int, set_id: int, entry_id: int, logged_in: bool): + tema_entry = playlists_service.get_tema(entry_id=entry_id) + playlists_service.add_tema_to_tema_in_set(tema_entry) + return templates.TemplateResponse( + "fragments/sessio/tema_entry.html", + { + "request": request, + "logged_in": logged_in, + "session_id": session_id, + "set_id": set_id, + "tema_entry": tema_entry, + } + ) + + +def get_tema_editor(request: Request, session_id: int, set_id: int, entry_id: int, logged_in: bool): + tema_entry = playlists_service.get_tema(entry_id=entry_id) + playlists_service.add_tema_to_tema_in_set(tema_entry) + return templates.TemplateResponse( + "fragments/sessio/tema_editor.html", + { + "request": request, + "logged_in": logged_in, + "session_id": session_id, + "set_id": set_id, + "tema_entry": tema_entry, + } + ) + + +def delete_tema(session_id: int, set_id: int, entry_id: int): + playlists_service.delete_tema(entry_id=entry_id) + if not playlists_service.get_set(session_id=session_id, set_id=set_id): + headers = { + "HX-Trigger": f"reload-set-{set_id}" + } + else: + headers = {} + return HTMLResponse(headers=headers) + + +def busca_tema( + request: Request, + session_id: int, + set_id: int, + entry_id: int, + query: str, +): + results = search_service.busca_temes( + query=query, + hidden=True, + limit=4, + offset=0, + ) + return templates.TemplateResponse( + "fragments/sessio/tema_results.html", + { + "request": request, + "session_id": session_id, + "set_id": set_id, + "entry_id": entry_id, + "results": results, + "query": query, + } + ) + + +def set_tema(request: Request, logged_in: bool, session_id: int, set_id: int, entry_id: int, tema_id: Optional[int]): + playlists_service.set_tema(session_id=session_id, set_id=set_id, entry_id=entry_id, tema_id=tema_id) + tema_entry = playlists_service.get_tema(entry_id=entry_id) + playlists_service.add_tema_to_tema_in_set(tema_entry) + return templates.TemplateResponse( + "fragments/sessio/tema_entry.html", + { + "request": request, + "logged_in": logged_in, + "session_id": session_id, + "set_id": set_id, + "tema_entry": tema_entry, + } + ) diff --git a/folkugat_web/fragments/sessions.py b/folkugat_web/fragments/sessions.py index caa3842..1f349cf 100644 --- a/folkugat_web/fragments/sessions.py +++ b/folkugat_web/fragments/sessions.py @@ -87,20 +87,6 @@ def _sessions_list(request: Request, sessions: list[model.Session], has_more_ses ) -def sessio(request: Request, session_id: int, logged_in: bool): - session = service.get_session(session_id=session_id) - return templates.TemplateResponse( - "fragments/sessions/sessio.html", - { - "request": request, - "logged_in": logged_in, - "Pages": Pages, - "session": session, - "date_names": service.get_date_names, - } - ) - - def sessions_editor_row(request: Request, session_date: Optional[model.Session] = None, session_id: Optional[int] = None): if session_date is None: if session_id is None: diff --git a/folkugat_web/fragments/set_page.py b/folkugat_web/fragments/set_page.py new file mode 100644 index 0000000..0fb6bc5 --- /dev/null +++ b/folkugat_web/fragments/set_page.py @@ -0,0 +1,72 @@ +from fastapi import HTTPException, Request +from folkugat_web.model.pagines import Pages +from folkugat_web.model.temes import ContentType, LinkType +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, set_id: int, logged_in: bool): + session = sessions_service.get_session(session_id=session_id) + set_ = playlists_service.get_set(session_id=session_id, set_id=set_id) + if not set_: + raise HTTPException(status_code=404, detail="Set not found") + set_ = playlists_service.add_temes_to_set(set_) + return templates.TemplateResponse( + "fragments/sessio/set/pagina.html", + { + "request": request, + "logged_in": logged_in, + "Pages": Pages, + "session_id": session_id, + "session": session, + "set": set_, + "date_names": sessions_service.get_date_names, + "LinkType": LinkType, + "ContentType": ContentType, + } + ) + + +def live(request: Request, logged_in: bool): + session = sessions_service.get_live_session() + set_ = None + if session and session.id: + playlist = playlists_service.get_playlist(session_id=session.id) + if playlist.sets: + set_ = playlists_service.add_temes_to_set(playlist.sets[-1]) + return templates.TemplateResponse( + "fragments/sessio/set/pagina.html", + { + "request": request, + "logged_in": logged_in, + "Pages": Pages, + "session": session, + "set": set_, + "date_names": sessions_service.get_date_names, + "LinkType": LinkType, + "ContentType": ContentType, + } + ) + + +def live_set(request: Request, logged_in: bool): + session = sessions_service.get_live_session() + set_ = None + if session and session.id: + playlist = playlists_service.get_playlist(session_id=session.id) + if playlist.sets: + set_ = playlists_service.add_temes_to_set(playlist.sets[-1]) + return templates.TemplateResponse( + "fragments/sessio/set/set_page.html", + { + "request": request, + "logged_in": logged_in, + "Pages": Pages, + "session": session, + "set": set_, + "date_names": sessions_service.get_date_names, + "LinkType": LinkType, + "ContentType": ContentType, + } + ) diff --git a/folkugat_web/fragments/temes.py b/folkugat_web/fragments/temes.py index 594dfb5..59591f5 100644 --- a/folkugat_web/fragments/temes.py +++ b/folkugat_web/fragments/temes.py @@ -19,14 +19,30 @@ def temes_pagina(request: Request, logged_in: bool, query: str): ) -def temes_busca(request: Request, query: str, logged_in: bool): - temes = temes_s.busca_temes(query=query, hidden=logged_in) +def temes_busca(request: Request, logged_in: bool, query: str, offset: int = 0, limit: int = 10): + temes = temes_s.busca_temes( + query=query, + hidden=logged_in, + limit=limit + 1, + offset=offset, + ) + + next_offset, prev_offset = None, None + if len(temes) > limit: + next_offset = offset + limit + temes = temes[:limit] + if offset > 0: + prev_offset = max(offset - limit, 0) + return templates.TemplateResponse( "fragments/temes/results.html", { "request": request, "logged_in": logged_in, "temes": temes, + "query": query, + "prev_offset": prev_offset, + "next_offset": next_offset, "LinkType": model.LinkType, "ContentType": model.ContentType, } diff --git a/folkugat_web/model/playlists.py b/folkugat_web/model/playlists.py new file mode 100644 index 0000000..0857c75 --- /dev/null +++ b/folkugat_web/model/playlists.py @@ -0,0 +1,77 @@ +import dataclasses +from collections.abc import Iterator +from typing import Optional, Self + +from folkugat_web.model.temes import Tema +from folkugat_web.utils import groupby + + +@dataclasses.dataclass +class PlaylistEntry: + id: Optional[int] + session_id: int + set_id: int + tema_id: Optional[int] + + +@dataclasses.dataclass +class TemaInSet: + id: Optional[int] + tema_id: Optional[int] + tema: Optional[Tema] + + def to_playlist_entry(self, session_id: int, set_id: int) -> PlaylistEntry: + return PlaylistEntry( + id=self.id, + session_id=session_id, + set_id=set_id, + tema_id=self.tema_id, + ) + + @classmethod + def from_playlist_entry(cls, entry: PlaylistEntry) -> Self: + return cls(id=entry.id, tema_id=entry.tema_id, tema=None) + + +@dataclasses.dataclass +class Set: + id: int + temes: list[TemaInSet] + + def to_playlist_entries(self, session_id) -> Iterator[PlaylistEntry]: + for tema_in_set in self.temes: + yield tema_in_set.to_playlist_entry( + session_id=session_id, + set_id=self.id, + ) + + @classmethod + def from_playlist_entries(cls, set_id: int, entries: list[PlaylistEntry]) -> Self: + if any(entry.set_id != set_id for entry in entries): + raise ValueError("All PlaylistEntries must have the same session_id") + return cls( + id=set_id, + temes=[TemaInSet.from_playlist_entry(entry) for entry in entries], + ) + + +@dataclasses.dataclass +class Playlist: + session_id: int + sets: list[Set] + + def to_playlist_entries(self) -> Iterator[PlaylistEntry]: + for set_entry in self.sets: + yield from set_entry.to_playlist_entries(session_id=self.session_id) + + @classmethod + def from_playlist_entries(cls, session_id: int, entries: list[PlaylistEntry]) -> Self: + if any(entry.session_id != session_id for entry in entries): + raise ValueError("All PlaylistEntries must have the same session_id") + return cls( + session_id=session_id, + sets=[ + Set.from_playlist_entries(set_id, set_entries) + for set_id, set_entries in groupby(entries, key_fn=lambda e: e.set_id, group_fn=list) + ], + ) diff --git a/folkugat_web/model/temes.py b/folkugat_web/model/temes.py index 88fb020..64c9ee7 100644 --- a/folkugat_web/model/temes.py +++ b/folkugat_web/model/temes.py @@ -125,4 +125,4 @@ class Tema: return self def score(self) -> Optional[Link]: - return next(filter(lambda l: l.content_type is ContentType.PARTITURA, self.links), None) + return next(filter(lambda l: l.content_type is ContentType.PARTITURA and l.url.startswith('/'), self.links), None) diff --git a/folkugat_web/services/playlists.py b/folkugat_web/services/playlists.py new file mode 100644 index 0000000..94ed929 --- /dev/null +++ b/folkugat_web/services/playlists.py @@ -0,0 +1,78 @@ +from typing import Optional + +from folkugat_web.dal.sql import Connection +from folkugat_web.dal.sql._connection import get_connection +from folkugat_web.dal.sql.playlists import query, write +from folkugat_web.model import playlists +from folkugat_web.services.temes import query as temes_query + + +def add_temes_to_playlist(playlist: playlists.Playlist) -> playlists.Playlist: + for set_ in playlist.sets: + add_temes_to_set(set_) + return playlist + + +def add_temes_to_set(set_: playlists.Set) -> playlists.Set: + for tema_in_set in set_.temes: + add_tema_to_tema_in_set(tema_in_set) + return set_ + + +def add_tema_to_tema_in_set(tema_in_set: playlists.TemaInSet) -> playlists.TemaInSet: + if tema_in_set.tema_id is not None: + tema_in_set.tema = temes_query.get_tema_by_id(tema_in_set.tema_id) + return tema_in_set + + +def get_playlist(session_id: int, con: Optional[Connection] = None) -> playlists.Playlist: + return playlists.Playlist.from_playlist_entries( + session_id=session_id, + entries=list(query.get_playlist_entries(session_id=session_id, con=con)) + ) + + +def add_set(session_id: int, con: Optional[Connection] = None) -> playlists.Set: + with get_connection(con) as con: + curr_playlist = get_playlist(session_id=session_id, con=con) + new_set_id = max([set_entry.id for set_entry in curr_playlist.sets], default=0) + 1 + new_entry = playlists.PlaylistEntry(id=None, session_id=session_id, set_id=new_set_id, tema_id=None) + inserted_entry = write.insert_playlist_entry(new_entry) + return playlists.Set.from_playlist_entries(set_id=inserted_entry.set_id, entries=[inserted_entry]) + + +def get_set(session_id: int, set_id: int, con: Optional[Connection] = None) -> Optional[playlists.Set]: + entries = list(query.get_playlist_entries(session_id=session_id, set_id=set_id, con=con)) + if entries: + return playlists.Set.from_playlist_entries(set_id=set_id, entries=entries) + else: + return None + + +def delete_set(session_id: int, set_id: int, con: Optional[Connection] = None): + write.delete_playlist_set(session_id=session_id, set_id=set_id, con=con) + + +def add_tema(session_id: int, set_id: int, con: Optional[Connection] = None) -> playlists.TemaInSet: + with get_connection(con) as con: + new_entry = playlists.PlaylistEntry(id=None, session_id=session_id, set_id=set_id, tema_id=None) + inserted_entry = write.insert_playlist_entry(new_entry) + return playlists.TemaInSet.from_playlist_entry(inserted_entry) + + +def get_tema(entry_id: int, con: Optional[Connection] = None) -> playlists.TemaInSet: + with get_connection(con) as con: + entry = next(query.get_playlist_entries(entry_id=entry_id)) + return playlists.TemaInSet.from_playlist_entry(entry) + + +def delete_tema(entry_id: int, con: Optional[Connection] = None): + with get_connection(con) as con: + write.delete_playlist_entry(entry_id=entry_id, con=con) + + +def set_tema(session_id: int, set_id: int, entry_id: int, tema_id: Optional[int], + con: Optional[Connection] = None): + with get_connection(con) as con: + new_entry = playlists.PlaylistEntry(id=entry_id, session_id=session_id, set_id=set_id, tema_id=tema_id) + write.update_playlist_entry(entry=new_entry, con=con) diff --git a/folkugat_web/services/temes/search.py b/folkugat_web/services/temes/search.py index 19ce957..7d2654c 100644 --- a/folkugat_web/services/temes/search.py +++ b/folkugat_web/services/temes/search.py @@ -55,7 +55,7 @@ def _thread(it: Iterable[T], *funcs: Callable[[Iterable], Iterable]) -> Iterable return functools.reduce(lambda i, fn: fn(i), funcs, it) -def busca_temes(query: str, hidden: bool = False, limit: int = 20, offset: int = 0) -> list[model.Tema]: +def busca_temes(query: str, hidden: bool = False, limit: int = 10, offset: int = 0) -> list[model.Tema]: t0 = time.time() with get_connection() as con: result = _thread( diff --git a/folkugat_web/services/temes/write.py b/folkugat_web/services/temes/write.py index 9503784..6044b54 100644 --- a/folkugat_web/services/temes/write.py +++ b/folkugat_web/services/temes/write.py @@ -7,11 +7,12 @@ from folkugat_web.model import temes as model def create_tema(title: str = "") -> model.Tema: - return temes_w.insert_tema(tema=model.Tema(title=title)) + new_tema = model.Tema(title=title, hidden=False).with_ngrams() + return temes_w.insert_tema(tema=new_tema) def delete_tema(tema_id: int) -> None: - tema = temes_w.delete_tema(tema_id=tema_id) + temes_w.delete_tema(tema_id=tema_id) def update_title(tema_id: int, title: str) -> model.Tema: @@ -20,9 +21,7 @@ def update_title(tema_id: int, title: str) -> model.Tema: if tema is None: raise ValueError(f"No tune found with tema_id = {tema_id}!") - new_tema = dataclasses.replace(tema, title=title) - new_tema.compute_ngrams() - + new_tema = dataclasses.replace(tema, title=title).with_ngrams() temes_w.update_tema(tema=new_tema, con=con) return new_tema