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 import router from folkugat_web.fragments import temes from folkugat_web.fragments.tema import scores as scores_fragments from folkugat_web.services import auth, files, lilypond 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.utils import FnChain @router.get("/api/tema/{tema_id}/score/{score_id}") def score(request: Request, logged_in: auth.LoggedIn, tema_id: int, score_id: int): score = scores_service.get_score_by_id(score_id=score_id, tema_id=tema_id) if not score: raise HTTPException(status_code=404, detail="Could not find lyric!") return scores_fragments.score(request=request, logged_in=logged_in, score=score) @router.put("/api/tema/{tema_id}/score/{score_id}") async def set_score( request: Request, logged_in: auth.RequireLogin, tema_id: int, score_id: int, title: Annotated[str, Form()], source: Annotated[str, Form()], ): source = source.strip() score = scores_service.get_score_by_id(score_id=score_id, tema_id=tema_id) if not score: raise HTTPException(status_code=404, detail="Could not find lyric!") full_source = scores_service.build_single_tune_full_source(tema_id=tema_id, source=source) pdf_filename = files.create_tema_filename(tema_id=tema_id) pdf_filename, errors = await lilypond.render(source=full_source, fmt="pdf", output_filename=pdf_filename) if errors: new_score = dataclasses.replace( score, source=source, title=title, errors=errors, ) else: png_filename = files.create_tema_filename(tema_id=tema_id) png_filename, errors = await lilypond.render(source=full_source, fmt="png", output_filename=png_filename) new_score = dataclasses.replace( score, source=source, title=title, pdf_url=files.get_db_file_path(pdf_filename) if pdf_filename else None, img_url=files.get_db_file_path(png_filename) if png_filename else None, errors=errors, ) scores_service.update_score(score=new_score) files.clean_orphan_files() return scores_fragments.score(request=request, logged_in=logged_in, score=new_score) @router.post("/api/tema/{tema_id}/score") def add_score( request: Request, logged_in: auth.RequireLogin, tema_id: int, ): score = scores_service.create_score(tema_id=tema_id) return scores_fragments.score_editor( request=request, logged_in=logged_in, score=score, ) @router.delete("/api/tema/{tema_id}/score/{score_id}") def delete_score(request: Request, logged_in: auth.RequireLogin, tema_id: int, score_id: int): scores_service.delete_score(score_id=score_id, tema_id=tema_id) files.clean_orphan_files() return HTMLResponse() @router.get("/api/tema/{tema_id}/editor/score/{score_id}") def score_editor( request: Request, logged_in: auth.RequireLogin, tema_id: int, score_id: int, ): score = scores_service.get_score_by_id(score_id=score_id, tema_id=tema_id) if not score: raise HTTPException(status_code=404, detail="Could not find lyric!") return scores_fragments.score_editor( request=request, logged_in=logged_in, score=score, ) @router.post("/api/tema/{tema_id}/editor/score/{score_id}/render") async def render( request: Request, _: auth.RequireLogin, tema_id: int, score_id: int, source: Annotated[str, Form()], ): full_source = scores_service.build_single_tune_full_source(tema_id=tema_id, source=source) output_filename, errors = await lilypond.render(source=full_source, fmt="png") if output_filename: score_render_url = files.get_db_file_path(output_filename) return temes.score_render(request=request, score_id=score_id, score_render_url=score_render_url) else: return temes.score_render(request=request, score_id=score_id, errors=errors) @router.put("/api/tema/{tema_id}/score/{score_id}/show") async def show_score( request: Request, logged_in: auth.RequireLogin, tema_id: int, score_id: int, ): score = scores_service.get_score_by_id(score_id=score_id, tema_id=tema_id) if not score: raise HTTPException(status_code=404, detail="Could not find lyric!") new_score = dataclasses.replace(score, hidden=False) scores_service.update_score(score=new_score) return scores_fragments.score(request=request, logged_in=logged_in, score=new_score) @router.put("/api/tema/{tema_id}/score/{score_id}/hide") async def hide_score( request: Request, logged_in: auth.RequireLogin, tema_id: int, score_id: int, ): score = scores_service.get_score_by_id(score_id=score_id, tema_id=tema_id) if not score: raise HTTPException(status_code=404, detail="Could not find lyric!") new_score = dataclasses.replace(score, hidden=True) scores_service.update_score(score=new_score) return scores_fragments.score(request=request, logged_in=logged_in, score=new_score)