Various fixes

This commit is contained in:
marc
2025-04-04 22:18:49 +02:00
parent 26aa4579b1
commit d5eb40e300
14 changed files with 1135 additions and 101 deletions

View File

@@ -6,7 +6,9 @@
** TODO Usuaris i permisos granulars ** TODO Usuaris i permisos granulars
** TODO Lilypond support (o similar) ** TODO Lilypond support (o similar)
*** TODO Fer cançoners "en directe" *** TODO Fer cançoners "en directe"
** TODO Arreglar estadístiques de temes (dos temes tocats a la mateixa sessió compten un cop) *** TODO Suport de caràcters especials (al títol i més llocs?)
*** TODO Mostrar partitura als enllaços (resultats de cerca)
** DONE Arreglar estadístiques de temes (dos temes tocats a la mateixa sessió compten un cop)
** TODO Arreglar visualitzador de pdf, suportar més d'un visualitzador per pàgina ** TODO Arreglar visualitzador de pdf, suportar més d'un visualitzador per pàgina
* Idees * Idees
** Jams ** Jams

File diff suppressed because one or more lines are too long

View File

@@ -47,13 +47,18 @@
{% endif %} {% endif %}
</h5> </h5>
<hr class="h-px mt-1 mb-3 bg-beige border-0"> <hr class="h-px mt-1 mb-3 bg-beige border-0">
<div> <div class="flex flex-col items-center">
{% if score.img_url is not none %} {% if score.img_url is not none %}
<div class="flex justify-center"> <div class="flex justify-center">
<a href="{{ score.pdf_url or score.img_url }}" target="_blank"> <a href="{{ score.pdf_url or score.img_url }}" target="_blank">
<img class="m-2" src="{{ score.img_url }}" /> <img class="m-2" src="{{ score.img_url }}" />
</a> </a>
</div> </div>
{% if score.pdf_url is not none %}
<div class="text-beige border rounded border-beige m-2 p-1">
<a href="{{ score.pdf_url }}" target="_blank">Obre el PDF</a>
</div>
{% endif %}
{% elif score.pdf_url is not none %} {% elif score.pdf_url is not none %}
{% set pdf_url = score.pdf_url %} {% set pdf_url = score.pdf_url %}
{% include "fragments/pdf_viewer.html" %} {% include "fragments/pdf_viewer.html" %}

View File

@@ -1,17 +1,19 @@
<ul class="flex flex-row items-center"> <ul class="flex flex-row items-center">
{% if tema.links %}
{% for link in tema.links %}
<li class="px-2 text-beige"> <li class="px-2 text-beige">
<a href="{{ link.url }}" target="_blank"> {% if tema.has_score %}
{% if link.content_type == ContentType.AUDIO %} <a href="/tema/{{ tema.id }}" target="_blank">
<i class="fa fa-volume-up" aria-hidden="true"></i> <i class="fa fa-music px-1" aria-hidden="true"></i>
{% elif link.content_type == ContentType.PARTITURA %}
<i class="fa fa-music" aria-hidden="true"></i>
{% else %}
<i class="fa fa-link" aria-hidden="true"></i>
{% endif %}
</a> </a>
</li>
{% endfor %}
{% endif %} {% endif %}
{% if tema.has_lyrics %}
<a href="/tema/{{ tema.id }}" target="_blank">
<i class="fa fa-font px-1" aria-hidden="true"></i>
</a>
{% endif %}
{% if tema.has_audio %}
<a href="/tema/{{ tema.id }}" target="_blank">
<i class="fa fa-volume-up px-1" aria-hidden="true"></i>
</a>
{% endif %}
</li>
</ul> </ul>

View File

@@ -1,75 +0,0 @@
\new ChordNames {
\chords {
\set chordChanges = ##t
\set noChordSymbol = ""
\partial 2
r2
% A
\repeat volta 2 {
d1 g a:5 r4 a2.:aug | d1 g a
\alternative {
\volta 1 { a4 a2.:aug }
\volta 2 { d4 d2.:7 }
}
}
% B
g1 d/fs g2 a b:m c/a
g1 d/fs g2 a d a/cs
% C
b1:m d/fs a g2 a
b1:m d/fs a2 g d a/cs
b1:m d/fs a g2 a
b1:m g a2 a:aug a1:aug
}
}
\new Staff {
\relative {
\numericTimeSignature
\time 4/4
\set Timing.beamExceptions = #'()
\set Timing.baseMoment = #(ly:make-moment 1/4)
\set Timing.beatStructure = 2,2
\key d \major
\partial 2
a8 b d e
% A
\mark \default
\repeat volta 2 {
fs4. fs8 e fs e d | g, r r4 e'8 fs e d |
a16 b8( b8.) c16 b a8 b d e | e d( d) a( a) b d e |
fs4. fs8 e fs e d | g, r r4 e'8 fs e d |
a b d e e d( d) e |
\alternative {
\volta 1 { d4 a( a8) b d e }
\volta 2 { d4 fs( fs) e8 d }
}
}
% B
\mark \default
b2 e8 fs e d | a2 e'8 fs e d | b4. b8 a b d e | e d( d) fs( fs) a e d |
b2 e8 fs e d | a2 e'8 fs e d | a b d e e d( d) e | d4 d16 d d8 d fs a cs |
\bar "||" \break
% C
\mark \default
d4. d8 cs d cs a | fs4 e8 d a' b a fs | e2 e8 fs e d | a b d e d fs a cs |
d4. d8 cs d cs b | fs4 e8 d a' b a fs | e2 d4. e8 | d4 d16 d d8 d fs a cs |
d2 cs4 b8 a | fs4 e8 d a b a fs | e'2 e8 fs e d | a b d e d fs a cs |
d2 d8 cs a fs | b2 b8 a fs d | e-> r r fs-> d-> r r4 | r8 c' c c c b a g |
\bar "|."
}
}

View File

@@ -36,7 +36,7 @@
\numericTimeSignature \numericTimeSignature
\time 4/4 \time 4/4
\set Timing.beamExceptions = #'() \set Timing.beamExceptions = #'()
\set Timing.baseMoment = #(ly:make-moment 1/4) \set Timing.baseMoment = #(ly:make-moment 1/8)
\set Timing.beatStructure = 2,2 \set Timing.beatStructure = 2,2
% ----------------------------------------------------- % -----------------------------------------------------

View File

@@ -5,7 +5,7 @@
} }
\header { \header {
title = \markup { "{{ tema.title }}" } title = \markup { "{{ tema.title | safe }}" }
{% if tema.composer() %} {% if tema.composer() %}
composer = "{{ tema.composer() }}" composer = "{{ tema.composer() }}"
{% elif tema.origin() %} {% elif tema.origin() %}

View File

@@ -3,8 +3,7 @@ import random
import string import string
from datetime import timedelta from datetime import timedelta
SESSION_DURATION = timedelta(minutes=120)
SESSION_DURATION = timedelta(minutes=30)
COOKIE_NAME = "nota_folkugat" COOKIE_NAME = "nota_folkugat"
COOKIE_MAX_AGE = int(SESSION_DURATION.total_seconds()) COOKIE_MAX_AGE = int(SESSION_DURATION.total_seconds())
ADMIN_PASSWORD = os.getenv("ADMIN_PASSWORD", "hola") ADMIN_PASSWORD = os.getenv("ADMIN_PASSWORD", "hola")

View File

@@ -4,7 +4,9 @@ from folkugat_web.model.lilypond import RenderError
from folkugat_web.model.pagines import Pages from folkugat_web.model.pagines import Pages
from folkugat_web.services import sessions as sessions_service from folkugat_web.services import sessions as sessions_service
from folkugat_web.services.temes import links as links_service from folkugat_web.services.temes import links as links_service
from folkugat_web.services.temes import lyrics as lyrics_service
from folkugat_web.services.temes import query as temes_q from folkugat_web.services.temes import query as temes_q
from folkugat_web.services.temes import scores as scores_service
from folkugat_web.services.temes import search as temes_s from folkugat_web.services.temes import search as temes_s
from folkugat_web.templates import templates from folkugat_web.templates import templates
from folkugat_web.utils import FnChain from folkugat_web.utils import FnChain
@@ -42,6 +44,8 @@ def temes_busca(request: Request, logged_in: bool, query: str, offset: int = 0,
FnChain.transform(temes) | FnChain.transform(temes) |
temes_q.temes_compute_stats | temes_q.temes_compute_stats |
links_service.add_links_to_temes | links_service.add_links_to_temes |
lyrics_service.add_lyrics_to_temes |
scores_service.add_scores_to_temes |
list list
).result() ).result()

View File

@@ -6,13 +6,13 @@ DEFAULT_START_TIME = datetime.time(20, 30)
DEFAULT_END_TIME = datetime.time(22, 30) DEFAULT_END_TIME = datetime.time(22, 30)
@dataclasses.dataclass @dataclasses.dataclass(frozen=True)
class SessionVenue: class SessionVenue:
name: str | None = None name: str | None = None
url: str | None = None url: str | None = None
@dataclasses.dataclass @dataclasses.dataclass(frozen=True)
class Session: class Session:
id: int | None = None id: int | None = None
date: datetime.date = dataclasses.field(default_factory=datetime.date.today) date: datetime.date = dataclasses.field(default_factory=datetime.date.today)

View File

@@ -133,6 +133,19 @@ class Tema:
result = next(filter(lambda prop: prop.field is PropertyField.ORIGEN, self.properties), None) result = next(filter(lambda prop: prop.field is PropertyField.ORIGEN, self.properties), None)
return result.value if result else None return result.value if result else None
@property
def has_score(self) -> bool:
return bool(self.main_score())
@property
def has_audio(self) -> bool:
audio_links = filter(lambda l: l.content_type is ContentType.AUDIO, self.links)
return any(audio_links)
@property
def has_lyrics(self) -> bool:
return bool(self.lyrics)
class TemaCols(enum.Enum): class TemaCols(enum.Enum):
NOM = "nom" NOM = "nom"

View File

@@ -1,5 +1,5 @@
import datetime import datetime
from typing import Annotated, Optional from typing import Annotated
import jwt import jwt
from fastapi import Cookie, Depends, HTTPException from fastapi import Cookie, Depends, HTTPException

View File

@@ -4,6 +4,7 @@ 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.services.temes import links as links_service from folkugat_web.services.temes import links as links_service
from folkugat_web.services.temes import lyrics as lyrics_service
from folkugat_web.services.temes import query as temes_query from folkugat_web.services.temes import query as temes_query
from folkugat_web.services.temes import scores as scores_service from folkugat_web.services.temes import scores as scores_service
@@ -27,6 +28,7 @@ def add_tema_to_tema_in_set(tema_in_set: playlists.TemaInSet) -> playlists.TemaI
logger.error("fCould not load tune in set: {tema_in_set}") logger.error("fCould not load tune in set: {tema_in_set}")
else: else:
_ = links_service.add_links_to_tema(tema_in_set.tema) _ = links_service.add_links_to_tema(tema_in_set.tema)
_ = lyrics_service.add_lyrics_to_tema(tema_in_set.tema)
_ = scores_service.add_scores_to_tema(tema_in_set.tema) _ = scores_service.add_scores_to_tema(tema_in_set.tema)
return tema_in_set return tema_in_set

View File

@@ -16,9 +16,10 @@ def tema_compute_stats(
if tune_sessions_dict is None: if tune_sessions_dict is None:
tune_sessions_dict = playlists_q.get_tune_sessions(tema_ids=[tema.id]) tune_sessions_dict = playlists_q.get_tune_sessions(tema_ids=[tema.id])
if tema.id and (tune_sessions := tune_sessions_dict.get(tema.id)): if tema.id and (tune_sessions := tune_sessions_dict.get(tema.id)):
unique_tune_sessions = set(tune_sessions)
tema.stats = model.Stats( tema.stats = model.Stats(
times_played=len(tune_sessions), times_played=len(unique_tune_sessions),
sessions_played=list(reversed(sorted(tune_sessions, key=lambda s: s.date))), sessions_played=list(reversed(sorted(unique_tune_sessions, key=lambda s: s.date))),
) )
return tema return tema