Canvia estil de la playlist i suggerir temes coocurrents

This commit is contained in:
marc
2025-10-25 00:21:05 +02:00
parent 1909af9107
commit 98c009ba53
7 changed files with 96 additions and 1175 deletions

File diff suppressed because one or more lines are too long

View File

@@ -31,7 +31,7 @@
</div> </div>
{% if logged_in or playlist.sets %} {% if logged_in or playlist.sets %}
<div class="text-left"> <div class="text-left">
<h4 class="pt-4 text-xl text-beige mt-2">Temes tocats</h4> <h4 class="py-4 text-xl text-beige mt-2">Temes tocats</h4>
{% include "fragments/sessio/playlist.html" %} {% include "fragments/sessio/playlist.html" %}
</div> </div>
{% endif %} {% endif %}

View File

@@ -1,14 +1,18 @@
<li class="flex flex-row grow items-center <li class="flex flex-row grow items-center
border border-beige rounded m-4 rounded-lg bg-white
px-2 py-1 my-1" px-2 py-1 my-1"
id="set-entry-{{ set_id }}" id="set-entry-{{ set_id }}"
hx-get="/api/sessio/{{ session_id }}/set/{{ set_id }}" hx-get="/api/sessio/{{ session_id }}/set/{{ set_id }}"
hx-target="#set-entry-{{ set_id }}" hx-target="#set-entry-{{ set_id }}"
hx-swap="outerHTML" hx-swap="outerHTML"
hx-trigger="reload-set-{{ set_id }}"> hx-trigger="reload-set-{{ set_id }}">
<div class="flex-1 flex flex-col items-center"> <div class="flex-1"></div>
<div class="flex flex-col
items-start
py-2 mx-2
w-full max-w-[655px]">
{% if logged_in %} {% if logged_in %}
<button class="text-beige mt-2" <button class="text-beige w-full"
hx-delete="/api/sessio/{{ session_id }}/set/{{ set_id }}" hx-delete="/api/sessio/{{ session_id }}/set/{{ set_id }}"
hx-target="#set-entry-{{ set_id }}" hx-target="#set-entry-{{ set_id }}"
hx-swap="outerHTML"> hx-swap="outerHTML">
@@ -17,7 +21,7 @@
</button> </button>
{% endif %} {% endif %}
<ol id="set-entry-{{ set_id }}-list" <ol id="set-entry-{{ set_id }}-list"
class="flex flex-col items-center"> class="flex flex-col items-start w-full">
{% for tema_entry in set_entry.temes %} {% for tema_entry in set_entry.temes %}
{% if new_entry %} {% if new_entry %}
{% include "fragments/sessio/tema_editor.html" %} {% include "fragments/sessio/tema_editor.html" %}
@@ -27,7 +31,7 @@
{% endfor %} {% endfor %}
</ol> </ol>
{% if logged_in %} {% if logged_in %}
<button class="text-beige mt-2" <button class="text-beige mt-2 w-full"
hx-post="/api/sessio/{{ session_id }}/set/{{ set_id }}" hx-post="/api/sessio/{{ session_id }}/set/{{ set_id }}"
hx-target="#set-entry-{{ set_id }}-list" hx-target="#set-entry-{{ set_id }}-list"
hx-swap="beforeend transition:true"> hx-swap="beforeend transition:true">
@@ -36,10 +40,15 @@
</button> </button>
{% endif %} {% endif %}
</div> </div>
<div class="ml-auto"> <div class="flex-1">
<a title="Mostra els temes" <a title="Mostra els temes"
class="text-beige" class="text-beige"
href="/sessio/{{ session_id }}/set/{{ set_id }}"> {% if set_entry.temes | length > 1 or not set_entry.temes[0] %}
href="/sessio/{{ session_id }}/set/{{ set_id }}"
{% else %}
href="/tema/{{ set_entry.temes[0].tema_id }}"
{% endif %}
>
<i class="fa fa-chevron-right" aria-hidden="true"></i> <i class="fa fa-chevron-right" aria-hidden="true"></i>
</a> </a>
</div> </div>

View File

@@ -1,5 +1,5 @@
<li id="tune-entry-{{ tema_entry.id }}" <li id="tune-entry-{{ tema_entry.id }}"
class="flex flex-col items-center my-1"> class="flex flex-col items-center my-1 w-full">
<div class="flex flex-row"> <div class="flex flex-row">
<input <input
name="query" name="query"
@@ -10,8 +10,8 @@
{% endif %} {% endif %}
placeholder="Busca un tema..." placeholder="Busca un tema..."
class="border border-beige focus:outline-none class="border border-beige focus:outline-none
rounded text-center rounded text-center text-black
bg-brown p-1 m-1" p-1 m-1"
hx-get="/api/sessio/{{ session_id }}/set/{{ set_id }}/tema/{{ tema_entry.id }}/busca" hx-get="/api/sessio/{{ session_id }}/set/{{ set_id }}/tema/{{ tema_entry.id }}/busca"
hx-trigger="revealed, keyup delay:500ms changed" hx-trigger="revealed, keyup delay:500ms changed"
hx-target="#tune-entry-{{ tema_entry.id }}-search-results" hx-target="#tune-entry-{{ tema_entry.id }}-search-results"

View File

@@ -1,16 +1,19 @@
<li id="tune-entry-{{ tema_entry.id }}" <li id="tune-entry-{{ tema_entry.id }}"
class="flex flex-row my-1"> class="flex flex-col w-full">
<div class="mx-1 text-center"> <div class="flex flex-row my-1 w-full">
{% if tema_entry.tema is none %} <div class="flex-1 min-w-0 text-black font-bold">
<i class="fa fa-question" aria-hidden="true"></i> {% if tema_entry.tema %}
<i>(Desconegut)</i> <a href="/tema/{{ tema_entry.tema_id }}"
{% else %} class="break-words block">
<a href="/sessio/{{ session_id }}/set/{{ set_id }}">
{{ tema_entry.tema.title }} {{ tema_entry.tema.title }}
</a> </a>
{% else %}
<i class="fa fa-question" aria-hidden="true"></i>
<i>(Desconegut)</i>
{% endif %} {% endif %}
</div> </div>
{% if logged_in %} {% if logged_in %}
<div class="flex-none flex flex-row shrink-0">
<button title="Edita el tema" <button title="Edita el tema"
class="text-beige mx-1" class="text-beige mx-1"
hx-get="/api/sessio/{{ session_id }}/set/{{ set_id }}/tema/{{ tema_entry.id }}/editor" hx-get="/api/sessio/{{ session_id }}/set/{{ set_id }}/tema/{{ tema_entry.id }}/editor"
@@ -25,5 +28,15 @@
hx-swap="outerHTML"> hx-swap="outerHTML">
<i class="fa fa-times" aria-hidden="true"></i> <i class="fa fa-times" aria-hidden="true"></i>
</button> </button>
</div>
{% endif %} {% endif %}
</div>
<div class="my-1 w-full">
{% if tema_entry.tema and tema_entry.tema.main_score() and tema_entry.tema.main_score().preview_url %}
<a href="/tema/{{ tema_entry.tema.id }}">
<img class="px-4 pb-2"
src="{{ tema_entry.tema.main_score().preview_url }}" />
</a>
{% endif %}
</div>
</li> </li>

View File

@@ -3,6 +3,7 @@ from fastapi.responses import HTMLResponse
from folkugat_web.model.pagines import Pages from folkugat_web.model.pagines import Pages
from folkugat_web.services import playlists as playlists_service from folkugat_web.services import playlists as playlists_service
from folkugat_web.services import sessions as sessions_service from folkugat_web.services import sessions as sessions_service
from folkugat_web.services.temes import query as query_service
from folkugat_web.services.temes import search as search_service from folkugat_web.services.temes import search as search_service
from folkugat_web.templates import templates from folkugat_web.templates import templates
@@ -126,11 +127,35 @@ def busca_tema(
entry_id: int, entry_id: int,
query: str, query: str,
): ):
results = search_service.busca_temes( n_results = 4
suggestions = []
if not query:
# If there is no query, suggest tunes commonly played together
set_entry = playlists_service.get_set(
session_id=session_id,
set_id=set_id,
)
if set_entry:
tema_ids = {tema_in_set.tema_id
for tema_in_set in set_entry.temes
if tema_in_set and tema_in_set.tema_id is not None}
commonly_played_tema_ids = {
cpt.tema.id
for tema_id in tema_ids
for cpt in playlists_service.get_commonly_played_temes(tema_id)
if cpt.tema.id is not None
} - tema_ids
suggestions = query_service.get_temes_by_ids(
tema_ids=list(commonly_played_tema_ids)
)
if len(suggestions) >= n_results:
suggestions = suggestions[:n_results]
elif not suggestions:
suggestions = search_service.busca_temes(
query=query, query=query,
properties=[], properties=[],
hidden=True, hidden=True,
limit=4, limit=n_results,
offset=0, offset=0,
) )
return templates.TemplateResponse( return templates.TemplateResponse(
@@ -140,7 +165,7 @@ def busca_tema(
"session_id": session_id, "session_id": session_id,
"set_id": set_id, "set_id": set_id,
"entry_id": entry_id, "entry_id": entry_id,
"results": results, "results": suggestions,
"query": query, "query": query,
} }
) )

View File

@@ -5,6 +5,7 @@ from folkugat_web.dal.sql._connection import get_connection
from folkugat_web.dal.sql.playlists import query, write from folkugat_web.dal.sql.playlists import query, write
from folkugat_web.log import logger from folkugat_web.log import logger
from folkugat_web.model import playlists from folkugat_web.model import playlists
from folkugat_web.model import temes as temes_model
from folkugat_web.model.lilypond import score as lilypond_model from folkugat_web.model.lilypond import score as lilypond_model
from folkugat_web.services import files as files_service from folkugat_web.services import files as files_service
from folkugat_web.services.lilypond import build as lilypond_build from folkugat_web.services.lilypond import build as lilypond_build
@@ -162,3 +163,9 @@ async def add_set_score_to_set(tune_set: playlists.Set) -> playlists.Set:
) )
else: else:
return tune_set return tune_set
def get_commonly_played_temes(
tema_id: int,
) -> list[temes_model.CommonlyPlayedTema]:
return query.get_commonly_played_tunes(tema_id=tema_id)