from typing import Annotated, Optional from fastapi import Request, UploadFile from fastapi.params import File, Form, Param from fastapi.responses import HTMLResponse from folkugat_web.api import router from folkugat_web.config import db from folkugat_web.fragments import tema, temes from folkugat_web.model import temes as model from folkugat_web.services import auth, files from folkugat_web.services.temes import write as temes_w from folkugat_web.services.temes.links import guess_link_type from folkugat_web.templates import templates @router.get("/tema/{tema_id}") def page(request: Request, logged_in: auth.LoggedIn, tema_id: int): return templates.TemplateResponse( "index.html", { "request": request, "page_title": "Folkugat", "content": f"/api/tema/{tema_id}", "logged_in": logged_in, } ) @router.get("/api/tema/{tema_id}") def contingut(request: Request, logged_in: auth.LoggedIn, tema_id: int): return temes.tema(request, tema_id, logged_in) @router.delete("/api/tema/{tema_id}") def delete_tema(request: Request, _: auth.RequireLogin, tema_id: int): temes_w.delete_tema(tema_id=tema_id) return HTMLResponse(headers={ 'HX-Redirect': '/temes' }) @router.post("/api/tema") def create_tema(request: Request, _: 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.get("/api/tema/{tema_id}/lyric/{lyric_id}") def lyric(request: Request, logged_in: auth.LoggedIn, tema_id: int, lyric_id: int): return tema.lyric(request=request, logged_in=logged_in, tema_id=tema_id, lyric_id=lyric_id) @router.put("/api/tema/{tema_id}/lyric/{lyric_id}") def set_lyric( request: Request, logged_in: auth.RequireLogin, tema_id: int, lyric_id: int, title: Annotated[str, Form()], lyric: Annotated[str, Form()], ): new_lyric = model.Lyrics(id=lyric_id, title=title, content=lyric.strip()) temes_w.update_lyric(tema_id=tema_id, lyric_id=lyric_id, lyric=new_lyric) return tema.lyric(request=request, logged_in=logged_in, tema_id=tema_id, lyric_id=lyric_id) @router.post("/api/tema/{tema_id}/lyric") def add_lyric( request: Request, logged_in: auth.RequireLogin, tema_id: int, ): new_tema = temes_w.add_lyric(tema_id=tema_id) lyric_id = new_tema.lyrics[-1].id if lyric_id is None: raise RuntimeError("Invalid lyric_id on newly created lyric!") return tema.lyric_editor( request=request, logged_in=logged_in, tema_id=tema_id, lyric_id=lyric_id, ) @router.delete("/api/tema/{tema_id}/lyric/{lyric_id}") def delete_lyric( tema_id: int, lyric_id: int, ): temes_w.delete_lyric(tema_id=tema_id, lyric_id=lyric_id) return HTMLResponse() @router.get("/api/tema/{tema_id}/link/{link_id}") def link(request: Request, logged_in: auth.LoggedIn, tema_id: int, link_id: int): return tema.link(request=request, logged_in=logged_in, tema_id=tema_id, link_id=link_id) @router.put("/api/tema/{tema_id}/link/{link_id}") async def set_link( request: Request, logged_in: auth.RequireLogin, tema_id: int, link_id: int, content_type: Annotated[model.ContentType, Form()], title: Annotated[Optional[str], Form()] = None, url: Annotated[Optional[str], Form()] = None, upload_file: Annotated[Optional[UploadFile], File()] = None, ): if upload_file: url = await files.store_file(tema_id=tema_id, upload_file=upload_file) link_type = guess_link_type(url or '') new_link = model.Link( id=link_id, content_type=content_type, link_type=link_type, url=url or '', title=title or '', ) new_tema = temes_w.update_link(tema_id=tema_id, link_id=link_id, link=new_link) return tema.link(request=request, logged_in=logged_in, tema_id=tema_id, link_id=link_id) @router.post("/api/tema/{tema_id}/link") def add_link( request: Request, logged_in: auth.RequireLogin, tema_id: int, ): new_tema = temes_w.add_link(tema_id=tema_id) link_id = new_tema.links[-1].id if link_id is None: raise RuntimeError("Invalid link_id on newly created link!") return tema.link_editor( request=request, logged_in=logged_in, tema_id=tema_id, link_id=link_id, ) @router.delete("/api/tema/{tema_id}/link/{link_id}") def delete_link( _: auth.RequireLogin, tema_id: int, link_id: int, ): temes_w.delete_link(tema_id=tema_id, link_id=link_id) return HTMLResponse( headers={ "HX-Trigger": f"reload-tema-{tema_id}-score" } ) @router.get("/api/tema/{tema_id}/link/{link_id}/icon") def link_icon( request: Request, logged_in: auth.LoggedIn, tema_id: int, link_id: int, content_type: Annotated[model.ContentType, Param()], url: Annotated[str, Param()], ): return tema.link_icon( request=request, logged_in=logged_in, tema_id=tema_id, link_id=link_id, url=url, content_type=content_type, ) @router.get("/api/tema/{tema_id}/score") def get_score( request: Request, logged_in: auth.LoggedIn, tema_id: int, ): return tema.score( request=request, logged_in=logged_in, tema_id=tema_id, ) @router.get("/api/tema/{tema_id}/property/{property_id}") def property_(request: Request, logged_in: auth.LoggedIn, tema_id: int, property_id: int): return tema.property_(request=request, logged_in=logged_in, tema_id=tema_id, property_id=property_id) @router.put("/api/tema/{tema_id}/property/{property_id}") def set_property( request: Request, logged_in: auth.RequireLogin, tema_id: int, property_id: int, field: Annotated[model.PropertyField, Form()], value: Annotated[str, Form()], ): new_property = model.Property(id=property_id, field=field, value=value.strip()) temes_w.update_property(tema_id=tema_id, property_id=property_id, prop=new_property) return tema.property_(request=request, logged_in=logged_in, tema_id=tema_id, property_id=property_id) @router.post("/api/tema/{tema_id}/property") def add_property( request: Request, logged_in: auth.RequireLogin, tema_id: int, ): new_tema = temes_w.add_property(tema_id=tema_id) property_id = new_tema.properties[-1].id if property_id is None: raise RuntimeError("Invalid property_id on newly created property!") return tema.property_editor( request=request, logged_in=logged_in, tema_id=tema_id, property_id=property_id, ) @router.delete("/api/tema/{tema_id}/property/{property_id}") def delete_property(_: auth.RequireLogin, tema_id: int, property_id: int): temes_w.delete_property(tema_id=tema_id, property_id=property_id) return HTMLResponse() @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, )