"""Market page helpers — data-only. All helpers return data values (dicts, lists) — no sx_call(). Markup composition lives entirely in .sx defpage and .sx defcomp files. """ from __future__ import annotations from .cards import _market_card_data # --------------------------------------------------------------------------- # Registration # --------------------------------------------------------------------------- def _register_market_helpers() -> None: from shared.sx.pages import register_page_helpers register_page_helpers("market", { "all-markets-data": _h_all_markets_data, "page-markets-data": _h_page_markets_data, "page-admin-data": _h_page_admin_data, "market-home-data": _h_market_home_data, }) # --------------------------------------------------------------------------- # All markets (global view) # --------------------------------------------------------------------------- async def _h_all_markets_data(**kw) -> dict: from quart import g, url_for, request from shared.utils import route_prefix from shared.services.registry import services from shared.infrastructure.data_client import fetch_data from shared.contracts.dtos import PostDTO, dto_from_dict page = int(request.args.get("page", 1)) markets, has_more = await services.market.list_marketplaces( g.s, page=page, per_page=20, ) page_info = {} if markets: post_ids = list({m.container_id for m in markets if m.container_type == "page"}) if post_ids: raw_posts = await fetch_data("blog", "posts-by-ids", params={"ids": ",".join(str(i) for i in post_ids)}, required=False) or [] for raw_p in raw_posts: p = dto_from_dict(PostDTO, raw_p) page_info[p.id] = {"title": p.title, "slug": p.slug} if not markets: return {"no-markets": True} prefix = route_prefix() next_url = prefix + url_for("all_markets.markets_fragment", page=page + 1) market_data = [_market_card_data(m, page_info) for m in markets] return { "no-markets": False, "market-data": market_data, "market-page": page, "has-more": has_more, "next-url": next_url, } # --------------------------------------------------------------------------- # Page markets (markets for a single page) # --------------------------------------------------------------------------- async def _h_page_markets_data(slug=None, **kw) -> dict: from quart import g, url_for, request from shared.utils import route_prefix from shared.services.registry import services post = g.post_data["post"] page = int(request.args.get("page", 1)) markets, has_more = await services.market.list_marketplaces( g.s, "page", post["id"], page=page, per_page=20, ) post_slug = post.get("slug", "") if not markets: return {"no-markets": True} prefix = route_prefix() next_url = prefix + url_for("page_markets.markets_fragment", page=page + 1) market_data = [_market_card_data(m, {}, show_page_badge=False, post_slug=post_slug) for m in markets] return { "no-markets": False, "market-data": market_data, "market-page": page, "has-more": has_more, "next-url": next_url, } # --------------------------------------------------------------------------- # Page admin (CRUD panel for markets under a page) # --------------------------------------------------------------------------- async def _h_page_admin_data(slug=None, **kw) -> dict: from quart import g, url_for from shared.sx.page import get_template_context from shared.services.registry import services from shared.browser.app.csrf import generate_csrf_token from shared.utils import route_prefix ctx = await get_template_context() rights = ctx.get("rights") or {} is_admin = getattr(rights, "admin", False) if hasattr(rights, "admin") else rights.get("admin", False) has_access = ctx.get("has_access") can_create = has_access("page_admin.create_market") if callable(has_access) else is_admin csrf = generate_csrf_token() post = ctx.get("post") or {} post_id = post.get("id") post_slug = post.get("slug", "") markets_raw = await services.market.marketplaces_for_container(g.s, "page", post_id) if post_id else [] prefix = route_prefix() markets = [] for m in markets_raw: m_slug = getattr(m, "slug", "") or (m.get("slug", "") if isinstance(m, dict) else "") m_name = getattr(m, "name", "") or (m.get("name", "") if isinstance(m, dict) else "") href = prefix + f"/{post_slug}/{m_slug}/" del_url = url_for("page_admin.delete_market", market_slug=m_slug) csrf_hdr = {"X-CSRFToken": csrf} markets.append({ "href": href, "name": m_name, "slug": m_slug, "del-url": del_url, "csrf-hdr": csrf_hdr, }) return { "can-create": can_create, "create-url": url_for("page_admin.create_market") if can_create else None, "csrf": csrf, "admin-markets": markets, } # --------------------------------------------------------------------------- # Market landing page # --------------------------------------------------------------------------- def _h_market_home_data(page_slug=None, market_slug=None, **kw) -> dict: from quart import g post_data = getattr(g, "post_data", {}) post = post_data.get("post", {}) return { "excerpt": post.get("custom_excerpt") or None, "feature-image": post.get("feature_image") or None, "html": post.get("html") or None, }