import dataclasses from typing import Annotated from fastapi import HTTPException, Request from fastapi.params import Form from fastapi.responses import HTMLResponse from folkugat_web.api.router import get_router from folkugat_web.fragments import tema, temes from folkugat_web.model.temes import Tema from folkugat_web.services import auth from folkugat_web.services import files as files_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 properties as properties_service 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 write as temes_w from folkugat_web.templates import templates from folkugat_web.utils import FnChain router = get_router() def _build_page_description(tema: Tema) -> str: info_lines = [] if composer := tema.composer(): info_lines.append(f"Autor: {composer}") if origin := tema.origin(): info_lines.append(f"OrĂ­gen: {origin}") return "\n".join(info_lines) @router.get("/tema/{tema_id}") def page(request: Request, logged_in: auth.LoggedIn, tema_id: int): tema = temes_q.get_tema_by_id(tema_id) if not tema: raise HTTPException(status_code=404, detail="Could not find tune") tema = ( FnChain.transform(tema) | scores_service.add_scores_to_tema | properties_service.add_properties_to_tema ).result() return templates.TemplateResponse( "index.html", { "request": request, "page_title": f"Folkugat - {tema.title}", "page_description": _build_page_description(tema), "page_card": "", "content": f"/api/tema/{tema_id}", "logged_in": logged_in, } ) def augment_played_with(tema: Tema) -> Tema: if tema.played_with: tema.played_with = [ dataclasses.replace( co_tema, tema=( FnChain.transform(co_tema.tema) | scores_service.add_scores_to_tema | properties_service.add_properties_to_tema ).result() ) for co_tema in tema.played_with ] return tema @router.get("/api/tema/{tema_id}") def contingut(request: Request, logged_in: auth.LoggedIn, tema_id: int): tema = temes_q.get_tema_by_id(tema_id) if not tema: raise HTTPException(status_code=404, detail="Could not find tune") tema = ( FnChain.transform(tema) | temes_q.tema_compute_stats | temes_q.tema_compute_played_with | augment_played_with | links_service.add_links_to_tema | lyrics_service.add_lyrics_to_tema | scores_service.add_scores_to_tema | properties_service.add_properties_to_tema ).result() return temes.tema(request, logged_in, tema) @router.delete("/api/tema/{tema_id}") def delete_tema(_: auth.RequireLogin, tema_id: int): tema = temes_q.get_tema_by_id(tema_id) if not tema: raise HTTPException(status_code=404, detail="Could not find tune") tema = temes_q.tema_compute_stats(tema=tema) if tema.stats: raise HTTPException(status_code=400, detail="Can't delete a tune that has been played in a set!") temes_w.delete_tema(tema_id=tema_id) files_service.clean_orphan_files() return HTMLResponse(headers={ 'HX-Redirect': '/temes' }) @router.post("/api/tema") 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}' }) @router.get("/api/tema/{tema_id}/title") def title(request: Request, logged_in: auth.LoggedIn, tema_id: int): return tema.title(request=request, tema_id=tema_id, logged_in=logged_in) @router.put("/api/tema/{tema_id}/title") def set_title( request: Request, logged_in: auth.RequireLogin, tema_id: int, title: Annotated[str, Form()], ): new_tema = temes_w.update_title(tema_id=tema_id, title=title) return tema.title(request=request, tema=new_tema, logged_in=logged_in) @router.put("/api/tema/{tema_id}/visible") def set_visible(request: Request, logged_in: auth.RequireLogin, tema_id: int): new_tema = temes_w.set_visibility(tema_id=tema_id, hidden=False) return tema.visibility( request=request, logged_in=logged_in, tema=new_tema, ) @router.put("/api/tema/{tema_id}/invisible") def set_invisible(request: Request, logged_in: auth.RequireLogin, tema_id: int): new_tema = temes_w.set_visibility(tema_id=tema_id, hidden=True) return tema.visibility( request=request, logged_in=logged_in, tema=new_tema, )