import json import urllib.parse from fastapi import Request from folkugat_web.model import temes as model from folkugat_web.model.lilypond.processing import RenderError from folkugat_web.model.pagines import Pages from folkugat_web.model.search import Order, OrderBy, OrderParams from folkugat_web.services import sessions as sessions_service from folkugat_web.services.sessions import get_date_names 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.templates import templates from folkugat_web.utils import FnChain def build_temes_params( query: str, properties: list[str], order_params: OrderParams | None = None, ) -> str: content_params = [ ("query", query), *[("properties", prop) for prop in properties or []] ] if order_params: content_params.append(("order_by", order_params.order_by.value)) content_params.append(("order", order_params.order.value)) return urllib.parse.urlencode(content_params) def build_hx_vars(*vars_dicts: dict[str, str]) -> str: result = ",".join(f"{var}:{value}" for hx_vars in vars_dicts for var, value in hx_vars.items()) return result def build_property_str(properties: list[str]) -> str: return json.dumps(properties).replace("'", "\\'").replace('"', "'") def build_order_params_dict(order_params: OrderParams | None) -> dict[str, str]: if not order_params: return {} return { "order_by": f"'{order_params.order_by.value}'", "order": f"'{order_params.order.value}'", } def temes_pagina( request: Request, logged_in: bool, query: str, properties: list[str], order_params: OrderParams | None, ): properties_str = build_property_str(properties) order_params_dict = build_order_params_dict(order_params) return templates.TemplateResponse( "fragments/temes/pagina.html", { "request": request, "logged_in": logged_in, "query": query, "properties": properties, "properties_str": properties_str, "order_params": order_params, "order_params_dict": order_params_dict, "build_hx_vars": build_hx_vars, "property_results": [], "Order": Order, "OrderBy": OrderBy, "Pages": Pages, "get_date_names": get_date_names, "menu_selected_id": Pages.Temes, } ) def temes_busca( request: Request, logged_in: bool, query: str, properties: list[str], order_params: OrderParams | None = None, offset: int = 0, limit: int = 10, ): temes = temes_s.busca_temes( query=query, properties=properties, order_params=order_params, hidden=logged_in, limit=limit + 1, offset=offset, ) next_offset, prev_offset = None, None if len(temes) > limit: next_offset = offset + limit temes = temes[:limit] if offset > 0: prev_offset = max(offset - limit, 0) temes = ( FnChain.transform(temes) | temes_q.temes_compute_stats | scores_service.add_scores_to_temes | # No properties added because search already does that list ).result() property_results = [ prop for prop in temes_s.busca_properties(query=query, limit=5) if prop not in properties ] temes_params = build_temes_params( query=query, properties=properties, order_params=order_params, ) temes_url = f"/temes?{temes_params}" def _add_property_str(prop: str) -> str: properties_dedup = list(set(properties + [prop])) return build_property_str(properties_dedup) def _remove_property_str(prop: str) -> str: properties_clean = [p for p in properties if p.lower() != prop.lower()] return build_property_str(properties_clean) return templates.TemplateResponse( "fragments/temes/results.html", { "request": request, "logged_in": logged_in, "temes": temes, "query": query, "properties": properties, "properties_str": build_property_str(properties), "order_params": order_params, "order_params_dict": build_order_params_dict(order_params), "property_results": property_results, "prev_offset": prev_offset, "next_offset": next_offset, "LinkType": model.LinkType, "ContentType": model.ContentType, "Order": Order, "OrderBy": OrderBy, "get_date_names": get_date_names, "add_property_str": _add_property_str, "remove_property_str": _remove_property_str, "build_hx_vars": build_hx_vars, }, headers={"HX-Replace-Url": temes_url}, ) def tema(request: Request, logged_in: bool, tema: model.Tema): return templates.TemplateResponse( "fragments/tema/pagina.html", { "request": request, "logged_in": logged_in, "Pages": Pages, "LinkType": model.LinkType, "ContentType": model.ContentType, "tema": tema, "date_names": sessions_service.get_date_names, } ) def score_render( request: Request, score_id: int, score_render_url: str = "", errors: list[RenderError] | None = None, ): return templates.TemplateResponse( "fragments/tema/editor/score_render.html", { "request": request, "score_id": score_id, "score_render_url": score_render_url, "errors": errors, } )