Session editor and live sessions!
This commit is contained in:
@@ -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 *
|
||||
|
||||
1
folkugat_web/api/sessio/__init__.py
Normal file
1
folkugat_web/api/sessio/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
from . import index, live, set_page
|
||||
199
folkugat_web/api/sessio/index.py
Normal file
199
folkugat_web/api/sessio/index.py
Normal file
@@ -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,
|
||||
)
|
||||
37
folkugat_web/api/sessio/live.py
Normal file
37
folkugat_web/api/sessio/live.py
Normal file
@@ -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)
|
||||
33
folkugat_web/api/sessio/set_page.py
Normal file
33
folkugat_web/api/sessio/set_page.py
Normal file
@@ -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)
|
||||
@@ -1 +1 @@
|
||||
from . import editor, index, sessio
|
||||
from . import editor, index
|
||||
|
||||
@@ -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)
|
||||
@@ -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}'
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
<div class="h-4/5 min-h-[400px] flex flex-col items-center justify-center">
|
||||
<img src = "{{ url_for('static', path='img/folkugat.svg') }}" class="{% if animate %} opacity-0 animate-fade-in-one {% endif %} m-3" width="100" alt="Folkugat"/>
|
||||
<img src="{{ url_for('static', path='img/folkugat.svg') }}"
|
||||
class="{% if animate %} opacity-0 animate-fade-in-one {% endif %} m-3"
|
||||
width="100"
|
||||
alt="Folkugat"/>
|
||||
<h1 class="text-3xl sm:text-8xl text-beige m-3 {% if animate %} opacity-0 animate-fade-in-one {% endif %}">{{ page_title }}</h1>
|
||||
<h2 class="text-center sm:text-3xl m-6 {% if animate %} opacity-0 animate-fade-in-two {% endif %}">Sessions de folk a Sant Cugat</h2>
|
||||
</div>
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
{% if session %}
|
||||
<div class="bg-beige text-white mt-2 py-2 text-xl overflow-hidden">
|
||||
{% if current_set is not none %}
|
||||
<a href="/live">
|
||||
{% else %}
|
||||
<a href="/sessio/{{ session.id }}">
|
||||
{% endif %}
|
||||
<div class="animate-marquee whitespace-nowrap">
|
||||
{% for _ in (1, 2, 3) %}
|
||||
<span class="inline-block mx-4">
|
||||
@@ -9,14 +12,25 @@
|
||||
<span class="inline-block mx-4">
|
||||
♫
|
||||
</span>
|
||||
<span class="inline-block mx-4">
|
||||
Està sonant <i>Pasdoble de Muntanya</i>
|
||||
</span>
|
||||
<span class="inline-block mx-4">
|
||||
♫
|
||||
</span>
|
||||
{% if current_set is not none %}
|
||||
<span class="inline-block mx-4">
|
||||
Estem tocant
|
||||
{% for tema_in_set in current_set.temes %}
|
||||
{% if loop.index != 1 %}
|
||||
+
|
||||
{% endif %}
|
||||
{% if tema_in_set.tema is not none %}
|
||||
<i>{{ tema_in_set.tema.title }}</i>
|
||||
{% else %}
|
||||
<i> ??? </i>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</span>
|
||||
<span class="inline-block mx-4">
|
||||
♫
|
||||
</span>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
{% include "fragments/menu.html" %}
|
||||
{% include "fragments/sessio/live/set_page.html" %}
|
||||
@@ -0,0 +1,5 @@
|
||||
<div hx-get="/api/content/live/set"
|
||||
hx-trigger="every 20s"
|
||||
hx-swap="outerHTML">
|
||||
{% include "fragments/sessio/set/set_page.html" %}
|
||||
</div>"
|
||||
@@ -1,5 +1,5 @@
|
||||
<button title="Inicia una sessió"
|
||||
class="text-beige mx-1"
|
||||
class="text-beige m-2"
|
||||
hx-put="/api/sessio/{{ session.id }}/live"
|
||||
hx-swap="outerHTML">
|
||||
<i class="fa fa-play" aria-hidden="true"></i>
|
||||
@@ -1,5 +1,5 @@
|
||||
<button title="Atura una sessió"
|
||||
class="text-beige mx-1"
|
||||
class="text-beige m-2"
|
||||
hx-delete="/api/sessio/{{ session.id }}/live"
|
||||
hx-swap="outerHTML">
|
||||
<i class="fa fa-stop" aria-hidden="true"></i>
|
||||
@@ -1,19 +1,19 @@
|
||||
{% include "fragments/menu.html" %}
|
||||
<div class="flex justify-center">
|
||||
<div class="m-12 grow max-w-4xl text-center">
|
||||
<h3 class="text-3xl p-4">
|
||||
<div class="m-12 grow max-w-4xl">
|
||||
<h3 class="text-center text-3xl p-4">
|
||||
{% set dn = date_names(session.date) %}
|
||||
{{ dn.day_name }} {{ dn.day }} {{ dn.month_name }} de {{ dn.year }}
|
||||
{% if logged_in %}
|
||||
{% if session.is_live %}
|
||||
{% include "fragments/sessio/live/stop.html" %}
|
||||
{% else %}
|
||||
{% include "fragments/sessio/live/start.html" %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</h3>
|
||||
{% if logged_in %}
|
||||
{% if session.is_live %}
|
||||
{% include "fragments/sessions/live/stop.html" %}
|
||||
{% else %}
|
||||
{% include "fragments/sessions/live/start.html" %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
<div class="text-left">
|
||||
<h4 class="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") }}
|
||||
a {{ session.end_time.strftime("%H:%M") }}
|
||||
{% if session.venue.name %}
|
||||
@@ -29,5 +29,11 @@
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</div>
|
||||
{% if logged_in or playlist.sets %}
|
||||
<div class="text-left">
|
||||
<h4 class="pt-4 text-xl text-beige mt-2">Temes tocats</h4>
|
||||
{% include "fragments/sessio/playlist.html" %}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
17
folkugat_web/assets/templates/fragments/sessio/playlist.html
Normal file
17
folkugat_web/assets/templates/fragments/sessio/playlist.html
Normal file
@@ -0,0 +1,17 @@
|
||||
<ul id="playlist-{{ session.id }}" class="">
|
||||
{% for set_entry in playlist.sets %}
|
||||
{% set set_id = set_entry.id %}
|
||||
{% include "fragments/sessio/set_entry.html" %}
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% if logged_in %}
|
||||
<div class="flex flex-col items-center">
|
||||
<button class="text-beige mt-2"
|
||||
hx-post="/api/sessio/{{ session.id }}/set"
|
||||
hx-target="#playlist-{{ session.id }}"
|
||||
hx-swap="beforeend transition:true">
|
||||
<i class="fa fa-plus" aria-hidden="true"></i>
|
||||
Afegeix set
|
||||
</button>
|
||||
</div>
|
||||
{% endif %}
|
||||
@@ -0,0 +1,2 @@
|
||||
{% include "fragments/menu.html" %}
|
||||
{% include "fragments/sessio/set/set_page.html" %}
|
||||
@@ -0,0 +1,30 @@
|
||||
{% if session is not none %}
|
||||
<div class="text-beige m-3">
|
||||
{% set dn = date_names(session.date) %}
|
||||
<a href="/sessio/{{ session.id }}">
|
||||
<i class="fa fa-chevron-left px-2" aria-hidden="true"></i>
|
||||
<i>
|
||||
Tocat el {{ dn.day_name }} {{ dn.day }} {{ dn.month_name }} de {{ dn.year }}
|
||||
</i>
|
||||
</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% for tema_in_set in set.temes %}
|
||||
{% if loop.index != 1 %}
|
||||
<div class="mx-12">
|
||||
<hr class="h-px mt-1 mb-3 bg-beige border-0">
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if tema_in_set.tema is not none %}
|
||||
{% set tema = tema_in_set.tema %}
|
||||
{% include "fragments/sessio/set/tema.html"%}
|
||||
{% else %}
|
||||
<h3 class="text-center text-3xl p-4">
|
||||
<i>Desconegut</i>
|
||||
</h3>
|
||||
<div class="text-center">
|
||||
<i>No sabem quin tema és aquest</i>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="m-8"> </div>
|
||||
{% endfor %}
|
||||
25
folkugat_web/assets/templates/fragments/sessio/set/tema.html
Normal file
25
folkugat_web/assets/templates/fragments/sessio/set/tema.html
Normal file
@@ -0,0 +1,25 @@
|
||||
<h3 class="text-center text-3xl p-4">
|
||||
{{ tema.title }}
|
||||
<a class="text-beige"
|
||||
º href="/tema/{{ tema.id }}">
|
||||
<i class="fa fa-chevron-right px-2" aria-hidden="true"></i>
|
||||
</a>
|
||||
</h3>
|
||||
<div class="mx-12 text-left">
|
||||
|
||||
{% if tema.score() is not none %}
|
||||
{% include "fragments/tema/score.html" %}
|
||||
{% endif %}
|
||||
|
||||
{% if tema.lyrics %}
|
||||
{% set lyric = tema.lyrics[0] %}
|
||||
<div>
|
||||
<h4 class="mt-4 text-xl text-beige">Lletra</h4>
|
||||
<hr class="h-px mt-1 mb-3 bg-beige border-0">
|
||||
<div class="text-center">
|
||||
{{ lyric.content.replace('\n', '<br>') | safe }}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
</div>
|
||||
@@ -0,0 +1,46 @@
|
||||
<li class="flex flex-row grow items-center
|
||||
border border-beige rounded
|
||||
px-2 py-1 my-1"
|
||||
id="set-entry-{{ set_id }}"
|
||||
hx-get="/api/sessio/{{ session_id }}/set/{{ set_id }}"
|
||||
hx-target="#set-entry-{{ set_id }}"
|
||||
hx-swap="outerHTML"
|
||||
hx-trigger="reload-set-{{ set_id }}">
|
||||
<div class="flex-1 flex flex-col items-center">
|
||||
{% if logged_in %}
|
||||
<button class="text-beige mt-2"
|
||||
hx-delete="/api/sessio/{{ session_id }}/set/{{ set_id }}"
|
||||
hx-target="#set-entry-{{ set_id }}"
|
||||
hx-swap="outerHTML">
|
||||
<i class="fa fa-times" aria-hidden="true"></i>
|
||||
Esborra el set
|
||||
</button>
|
||||
{% endif %}
|
||||
<ol id="set-entry-{{ set_id }}-list"
|
||||
class="flex flex-col items-center">
|
||||
{% 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 %}
|
||||
</ol>
|
||||
{% if logged_in %}
|
||||
<button class="text-beige mt-2"
|
||||
hx-post="/api/sessio/{{ session_id }}/set/{{ set_id }}"
|
||||
hx-target="#set-entry-{{ set_id }}-list"
|
||||
hx-swap="beforeend transition:true">
|
||||
<i class="fa fa-plus" aria-hidden="true"></i>
|
||||
Afegeix un tema
|
||||
</button>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="ml-auto">
|
||||
<a title="Mostra els temes"
|
||||
class="text-beige"
|
||||
href="/sessio/{{ session_id }}/set/{{ set_id }}">
|
||||
<i class="fa fa-chevron-right" aria-hidden="true"></i>
|
||||
</a>
|
||||
</div>
|
||||
</li>
|
||||
@@ -0,0 +1,30 @@
|
||||
<li id="tune-entry-{{ tema_entry.id }}"
|
||||
class="flex flex-col items-center my-1">
|
||||
<div class="flex flex-row">
|
||||
<input
|
||||
name="query"
|
||||
{% if tema_entry.tema %}
|
||||
value="{{ tema_entry.tema.title }}"
|
||||
{% else %}
|
||||
value=""
|
||||
{% endif %}
|
||||
placeholder="Busca un tema..."
|
||||
class="border border-beige focus:outline-none
|
||||
rounded text-center
|
||||
bg-brown p-1 m-1"
|
||||
hx-get="/api/sessio/{{ session_id }}/set/{{ set_id }}/tema/{{ tema_entry.id }}/busca"
|
||||
hx-trigger="revealed, keyup delay:500ms changed"
|
||||
hx-target="#tune-entry-{{ tema_entry.id }}-search-results"
|
||||
hx-swap="outerHTML"/>
|
||||
<button title="Descarta els canvis"
|
||||
class="text-beige mx-1"
|
||||
hx-get="/api/sessio/{{ session_id }}/set/{{ set_id }}/tema/{{ tema_entry.id }}"
|
||||
hx-target="#tune-entry-{{ tema_entry.id }}"
|
||||
hx-swap="outerHTML">
|
||||
<i class="fa fa-times" aria-hidden="true"></i>
|
||||
</button>
|
||||
</div>
|
||||
<ul id="tune-entry-{{ tema_entry.id }}-search-results"
|
||||
class="flex flex-wrap">
|
||||
</ul>
|
||||
</li>
|
||||
@@ -0,0 +1,29 @@
|
||||
<li id="tune-entry-{{ tema_entry.id }}"
|
||||
class="flex flex-row my-1">
|
||||
<div class="mx-1 text-center">
|
||||
{% if tema_entry.tema is none %}
|
||||
<i class="fa fa-question" aria-hidden="true"></i>
|
||||
<i>(Desconegut)</i>
|
||||
{% else %}
|
||||
<a href="/sessio/{{ session_id }}/set/{{ set_id }}">
|
||||
{{ tema_entry.tema.title }}
|
||||
</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% if logged_in %}
|
||||
<button title="Edita el tema"
|
||||
class="text-beige mx-1"
|
||||
hx-get="/api/sessio/{{ session_id }}/set/{{ set_id }}/tema/{{ tema_entry.id }}/editor"
|
||||
hx-target="#tune-entry-{{ tema_entry.id }}"
|
||||
hx-swap="outerHTML">
|
||||
<i class="fa fa-pencil" aria-hidden="true"></i>
|
||||
</button>
|
||||
<button title="Esborra el tema"
|
||||
class="text-beige mx-1"
|
||||
hx-delete="/api/sessio/{{ session_id }}/set/{{ set_id }}/tema/{{ tema_entry.id }}"
|
||||
hx-target="#tune-entry-{{ tema_entry.id }}"
|
||||
hx-swap="outerHTML">
|
||||
<i class="fa fa-times" aria-hidden="true"></i>
|
||||
</button>
|
||||
{% endif %}
|
||||
</li>
|
||||
@@ -0,0 +1,36 @@
|
||||
<ul id="tune-entry-{{ entry_id }}-search-results"
|
||||
class="flex flex-wrap items-center justify-center">
|
||||
{% for tema in results %}
|
||||
<li>
|
||||
<button class="bg-beige text-brown rounded
|
||||
m-1 px-2"
|
||||
hx-put="/api/sessio/{{ session_id }}/set/{{ set_id }}/tema/{{ entry_id }}"
|
||||
hx-vals='{"tema_id": "{{ tema.id }}"}'
|
||||
hx-target="#tune-entry-{{ entry_id }}"
|
||||
hx-swap="outerHTML">
|
||||
{{ tema.title }}
|
||||
</button>
|
||||
</li>
|
||||
{% endfor %}
|
||||
<li>
|
||||
<button class="border border-beige text-beige rounded
|
||||
m-1 px-2"
|
||||
hx-put="/api/sessio/{{ session_id }}/set/{{ set_id }}/tema/{{ entry_id }}/unknown"
|
||||
hx-target="#tune-entry-{{ entry_id }}"
|
||||
hx-swap="outerHTML">
|
||||
<i class="fa fa-question" aria-hidden="true"></i>
|
||||
<i>(Desconegut)</i>
|
||||
</button>
|
||||
</li>
|
||||
<li>
|
||||
<button class="border border-beige text-beige rounded
|
||||
m-1 px-2"
|
||||
hx-post="/api/sessio/{{ session_id }}/set/{{ set_id }}/tema/{{ entry_id }}"
|
||||
hx-vals='{"title": "{{ query }}"}'
|
||||
hx-target="#tune-entry-{{ entry_id }}"
|
||||
hx-swap="outerHTML">
|
||||
<i class="fa fa-plus" aria-hidden="true"></i>
|
||||
<i>{{ query }}</i>
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
@@ -1,24 +1,11 @@
|
||||
<p>
|
||||
{% if session == None %}
|
||||
<a> L'últim Dimecres de cada mes </a>
|
||||
{% else %}
|
||||
<a>
|
||||
{% set dn = date_names(session.date) %}
|
||||
{{ dn.day_name }} {{ dn.day }} {{ dn.month_name }}
|
||||
</a>
|
||||
de {{ session.start_time.strftime("%H:%M") }}
|
||||
a {{ session.end_time.strftime("%H:%M") }}
|
||||
{% if session.venue.name %}
|
||||
a {{ session.venue.name }}
|
||||
<!-- {% if session.venue.url %} -->
|
||||
<!-- <a href="{{ session.venue.url }}" -->
|
||||
<!-- class="text-beige" -->
|
||||
<!-- target="_blank"> -->
|
||||
<!-- {{ session.venue.name }} -->
|
||||
<!-- </a> -->
|
||||
<!-- {% else %} -->
|
||||
<!-- {{ session.venue.name }} -->
|
||||
<!-- {% endif %} -->
|
||||
{% 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 %}
|
||||
</p>
|
||||
{% endif %}
|
||||
|
||||
@@ -4,15 +4,17 @@
|
||||
relative"
|
||||
id="session-row-{{session.id}}">
|
||||
<a href="/session/{{session.id}}">
|
||||
<div class="flex flex-row grow justify-center pl-10">
|
||||
<div class="flex flex-row grow items-center">
|
||||
<div class="flex-1">
|
||||
<a href="/sessio/{{session.id}}/">
|
||||
{% include "fragments/sessions/session_date.html" %}
|
||||
</a>
|
||||
</div>
|
||||
<div class="ml-auto">
|
||||
<a title="Més informació"
|
||||
class="text-beige mx-1"
|
||||
href="/sessio/{{session.id}}/">
|
||||
<i class="fa fa-info-circle" aria-hidden="true"></i>
|
||||
<i class="fa fa-chevron-right" aria-hidden="true"></i>
|
||||
</a>
|
||||
{% if logged_in %}
|
||||
<button title="Edita la sessió"
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
{% include "icons/pdf.svg" %}
|
||||
{% elif link.content_type == ContentType.AUDIO %}
|
||||
{% include "icons/notes.svg" %}
|
||||
{% elif link.content_type == ContentType.PARTITURA %}
|
||||
{% include "icons/notes.svg" %}
|
||||
{% else %}
|
||||
{% include "icons/link.svg" %}
|
||||
{% endif %}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{% if logged_in or tema.links %}
|
||||
<h4 class="text-xl text-beige">Enllaços</h4>
|
||||
<h4 class="pt-4 text-xl text-beige">Enllaços</h4>
|
||||
<hr class="h-px mt-1 mb-3 bg-beige border-0">
|
||||
<ul class="flex flex-col justify-center"
|
||||
id="new-link-target">
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{% if logged_in or tema.lyrics %}
|
||||
<h4 class="text-xl text-beige">Lletra</h4>
|
||||
<h4 class="pt-4 text-xl text-beige">Lletra</h4>
|
||||
{% endif %}
|
||||
|
||||
{% if tema.lyrics %}
|
||||
|
||||
@@ -1,20 +1,17 @@
|
||||
{% include "fragments/menu.html" %}
|
||||
<div class="flex justify-center">
|
||||
<div class="m-12 grow max-w-4xl text-center">
|
||||
<div class="flex flex-col justify-center">
|
||||
<div class="mt-8">
|
||||
{% include "fragments/tema/title.html" %}
|
||||
<div class="text-left">
|
||||
|
||||
</div>
|
||||
<div class="p-12 text-left">
|
||||
<div id="tema-{{ tema.id }}-score"
|
||||
hx-get="/api/tema/{{ tema.id }}/score"
|
||||
hx-trigger="load, reload-tema-{{ tema.id }}-score from:body"
|
||||
hx-swap="innerHTML"
|
||||
>
|
||||
hx-get="/api/tema/{{ tema.id }}/score"
|
||||
hx-trigger="load, reload-tema-{{ tema.id }}-score from:body"
|
||||
hx-swap="innerHTML"
|
||||
>
|
||||
</div>
|
||||
|
||||
{% include "fragments/tema/lyrics.html" %}
|
||||
{% include "fragments/tema/links.html" %}
|
||||
{% include "fragments/tema/properties.html" %}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{% if logged_in or tema.properties %}
|
||||
<h4 class="text-xl mt-3 text-beige">Informació</h4>
|
||||
<h4 class="pt-4 text-xl mt-3 text-beige">Informació</h4>
|
||||
<hr class="h-px mt-1 mb-3 bg-beige border-0">
|
||||
|
||||
<ul class="flex flex-col"
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
{% set score = tema.score() %}
|
||||
{% if score %}
|
||||
<h4 class="text-xl text-beige">Partitura</h4>
|
||||
<h4 class="mp-4 text-xl text-beige">Partitura</h4>
|
||||
<hr class="h-px mt-1 mb-3 bg-beige border-0">
|
||||
{% if score.link_type == LinkType.PDF %}
|
||||
{% set pdf_url = score.url %}
|
||||
{% include "fragments/pdf_viewer.html" %}
|
||||
{% elif score.link_type == LinkType.IMAGE %}
|
||||
<div class="flex justify-center">
|
||||
<img class="m-2"
|
||||
src="{{ score.url }}"
|
||||
/>
|
||||
<a href="{{ score.url }}" target="_blank">
|
||||
<img class="m-2" src="{{ score.url }}" />
|
||||
</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<div class="flex flex-row flex-wrap justify-center"
|
||||
id="tema-title">
|
||||
<h3 class="text-3xl p-4">{{ tema.title }}</h3>
|
||||
<h3 class="text-3xl text-center p-4">{{ tema.title }}</h3>
|
||||
{% if logged_in %}
|
||||
<button title="Canvia el títol"
|
||||
class="text-beige text-2xl mx-2"
|
||||
|
||||
@@ -10,7 +10,8 @@
|
||||
p-2 m-2"
|
||||
hx-get="/api/temes/busca"
|
||||
hx-trigger="revealed, keyup delay:500ms changed"
|
||||
hx-target="#search-results">
|
||||
hx-target="#search-results"
|
||||
hx-swap="outerHTML">
|
||||
{% if logged_in %}
|
||||
<button title="Afegeix un tema"
|
||||
class="text-beige m-2"
|
||||
|
||||
@@ -4,19 +4,9 @@
|
||||
<li class="px-2 text-beige">
|
||||
<a href="{{ link.url }}" target="_blank">
|
||||
{% if link.content_type == ContentType.AUDIO %}
|
||||
{% if link.link_type == LinkType.SPOTIFY %}
|
||||
<i class="fa fa-music" aria-hidden="true"></i>
|
||||
{% elif link.link_type == LinkType.YOUTUBE %}
|
||||
<i class="fa fa-play" aria-hidden="true"></i>
|
||||
{% else %}
|
||||
<i class="fa fa-music" aria-hidden="true"></i>
|
||||
{% endif %}
|
||||
<i class="fa fa-volume-up" aria-hidden="true"></i>
|
||||
{% elif link.content_type == ContentType.PARTITURA %}
|
||||
{% if link.link_type == LinkType.PDF %}
|
||||
<i class="fa fa-file" aria-hidden="true"></i>
|
||||
{% else %}
|
||||
<i class="fa fa-link" aria-hidden="true"></i>
|
||||
{% endif %}
|
||||
<i class="fa fa-music" aria-hidden="true"></i>
|
||||
{% else %}
|
||||
<i class="fa fa-link" aria-hidden="true"></i>
|
||||
{% endif %}
|
||||
|
||||
@@ -1,19 +1,41 @@
|
||||
<table id="search-results"
|
||||
class="text-left min-w-full w-full">
|
||||
<tr class="border-b border-beige">
|
||||
<td class="font-bold py-2 px-4">Nom</td>
|
||||
<td class="font-bold py-2 px-4">Enllaços</td>
|
||||
</tr>
|
||||
{% for tema in temes %}
|
||||
<tr class="border-b border-beige">
|
||||
<td class="py-2 px-4">
|
||||
<a href="/tema/{{ tema.id }}">
|
||||
{{ tema.title }}
|
||||
</a>
|
||||
</td>
|
||||
<td class="py-2 px-4">
|
||||
{% include "fragments/temes/result_links.html" %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
<div id="search-results"
|
||||
class="min-w-full w-full">
|
||||
<table class="text-left min-w-full w-full">
|
||||
<tr class="border-b border-beige">
|
||||
<td class="font-bold py-2 px-4">Nom</td>
|
||||
<td class="font-bold py-2 px-4">Enllaços</td>
|
||||
</tr>
|
||||
{% for tema in temes %}
|
||||
<tr class="border-b border-beige">
|
||||
<td class="py-2 px-4">
|
||||
<a href="/tema/{{ tema.id }}">
|
||||
{{ tema.title }}
|
||||
</a>
|
||||
</td>
|
||||
<td class="py-2 px-4">
|
||||
{% include "fragments/temes/result_links.html" %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
{% if prev_offset is not none or next_offset is not none %}
|
||||
<div class="py-2">
|
||||
{% if prev_offset is not none %}
|
||||
<button class="text-beige mx-2"
|
||||
hx-get="/api/temes/busca?query={{ query }}&offset={{ prev_offset }}"
|
||||
hx-target="#search-results"
|
||||
hx-swap="outerHTML">
|
||||
<i class="fa fa-chevron-left" aria-hidden="true"></i>
|
||||
</button>
|
||||
{% endif %}
|
||||
{% if next_offset is not none %}
|
||||
<button class="text-beige mx-2"
|
||||
hx-get="/api/temes/busca?query={{ query }}&offset={{ next_offset }}"
|
||||
hx-target="#search-results"
|
||||
hx-swap="outerHTML">
|
||||
<i class="fa fa-chevron-right" aria-hidden="true"></i>
|
||||
</button>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
@@ -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)
|
||||
|
||||
0
folkugat_web/dal/sql/playlists/__init__.py
Normal file
0
folkugat_web/dal/sql/playlists/__init__.py
Normal file
19
folkugat_web/dal/sql/playlists/_conversion.py
Normal file
19
folkugat_web/dal/sql/playlists/_conversion.py
Normal file
@@ -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],
|
||||
)
|
||||
27
folkugat_web/dal/sql/playlists/ddl.py
Normal file
27
folkugat_web/dal/sql/playlists/ddl.py
Normal file
@@ -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)
|
||||
47
folkugat_web/dal/sql/playlists/query.py
Normal file
47
folkugat_web/dal/sql/playlists/query.py
Normal file
@@ -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())
|
||||
61
folkugat_web/dal/sql/playlists/write.py
Normal file
61
folkugat_web/dal/sql/playlists/write.py
Normal file
@@ -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
|
||||
@@ -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,
|
||||
)
|
||||
|
||||
@@ -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,
|
||||
|
||||
163
folkugat_web/fragments/sessio.py
Normal file
163
folkugat_web/fragments/sessio.py
Normal file
@@ -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,
|
||||
}
|
||||
)
|
||||
@@ -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:
|
||||
|
||||
72
folkugat_web/fragments/set_page.py
Normal file
72
folkugat_web/fragments/set_page.py
Normal file
@@ -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,
|
||||
}
|
||||
)
|
||||
@@ -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,
|
||||
}
|
||||
|
||||
77
folkugat_web/model/playlists.py
Normal file
77
folkugat_web/model/playlists.py
Normal file
@@ -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)
|
||||
],
|
||||
)
|
||||
@@ -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)
|
||||
|
||||
78
folkugat_web/services/playlists.py
Normal file
78
folkugat_web/services/playlists.py
Normal file
@@ -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)
|
||||
@@ -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(
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user