diff --git a/bp/blog/routes.py b/bp/blog/routes.py index 2368b09..e6a6336 100644 --- a/bp/blog/routes.py +++ b/bp/blog/routes.py @@ -85,7 +85,7 @@ def register(url_prefix, title): from shared.config import config as get_config from shared.infrastructure.cart_identity import current_cart_identity from shared.services.registry import services as svc - from shared.services.widget_registry import widgets + from shared.infrastructure.fragments import fetch_fragment, fetch_fragments p_data = await _post_data("home", g.s, include_drafts=False) if not p_data: @@ -98,23 +98,27 @@ def register(url_prefix, title): db_post_id = p_data["post"]["id"] post_slug = p_data["post"]["slug"] - container_nav_loaded = [] - for w in widgets.container_nav: - try: - wctx = await w.context_fn( - g.s, container_type="page", container_id=db_post_id, - post_slug=post_slug, - ) - has_data = any(v for v in wctx.values() if isinstance(v, list) and v) - if has_data: - container_nav_loaded.append({"widget": w, "ctx": wctx}) - except Exception: - pass + # Fetch container nav fragments from events + market + paginate_url = url_for( + 'blog.post.widget_paginate', + slug=post_slug, widget_domain='calendar', + ) + nav_params = { + "container_type": "page", + "container_id": str(db_post_id), + "post_slug": post_slug, + "paginate_url": paginate_url, + } + events_nav_html, market_nav_html = await fetch_fragments([ + ("events", "container-nav", nav_params), + ("market", "container-nav", nav_params), + ]) + container_nav_html = events_nav_html + market_nav_html ctx = { **p_data, "base_title": f"{get_config()['title']} {p_data['post']['title']}", - "container_nav_widgets": container_nav_loaded, + "container_nav_html": container_nav_html, } # Page cart badge diff --git a/bp/blog/services/posts_data.py b/bp/blog/services/posts_data.py index 7a08296..3203aae 100644 --- a/bp/blog/services/posts_data.py +++ b/bp/blog/services/posts_data.py @@ -1,7 +1,9 @@ +import re + from ..ghost_db import DBClient # adjust import path from sqlalchemy import select from models.ghost_content import PostLike -from shared.services.widget_registry import widgets +from shared.infrastructure.fragments import fetch_fragment from quart import g async def posts_data( @@ -85,11 +87,16 @@ async def posts_data( for post in posts: post["is_liked"] = False - # Widget-driven card decoration - for w in widgets.container_cards: - batch_data = await w.batch_fn(session, post_ids) - for post in posts: - post[w.context_key] = batch_data.get(post["id"], []) + # Fetch card decoration fragments from events + card_widgets_html = {} + if post_ids: + post_slugs = [p.get("slug", "") for p in posts] + cards_html = await fetch_fragment("events", "container-cards", params={ + "post_ids": ",".join(str(pid) for pid in post_ids), + "post_slugs": ",".join(post_slugs), + }) + if cards_html: + card_widgets_html = _parse_card_fragments(cards_html) tags=await client.list_tags( limit=50000 @@ -113,4 +120,23 @@ async def posts_data( "draft_count": draft_count, "tag_groups": tag_groups, "selected_groups": selected_groups, + "card_widgets_html": card_widgets_html, } + + +# Regex to extract per-post blocks delimited by comment markers +_CARD_MARKER_RE = re.compile( + r'(.*?)', + re.DOTALL, +) + + +def _parse_card_fragments(html: str) -> dict[str, str]: + """Parse the container-cards fragment into {post_id_str: html} dict.""" + result = {} + for m in _CARD_MARKER_RE.finditer(html): + post_id_str = m.group(1) + inner = m.group(2).strip() + if inner: + result[post_id_str] = inner + return result diff --git a/bp/post/routes.py b/bp/post/routes.py index c16687f..7aa3fb4 100644 --- a/bp/post/routes.py +++ b/bp/post/routes.py @@ -13,7 +13,7 @@ from quart import ( from .services.post_data import post_data from .services.post_operations import toggle_post_like from shared.services.registry import services -from shared.services.widget_registry import widgets +from shared.infrastructure.fragments import fetch_fragment, fetch_fragments from shared.browser.app.redis_cacher import cache_page, clear_cache @@ -69,24 +69,27 @@ def register(): db_post_id = (g.post_data.get("post") or {}).get("id") post_slug = (g.post_data.get("post") or {}).get("slug", "") - # Widget-driven container nav - container_nav_loaded = [] - for w in widgets.container_nav: - try: - wctx = await w.context_fn( - g.s, container_type="page", container_id=db_post_id, - post_slug=post_slug, - ) - has_data = any(v for v in wctx.values() if isinstance(v, list) and v) - if has_data: - container_nav_loaded.append({"widget": w, "ctx": wctx}) - except Exception: - pass + # Fetch container nav fragments from events + market + paginate_url = url_for( + 'blog.post.widget_paginate', + slug=post_slug, widget_domain='calendar', + ) + nav_params = { + "container_type": "page", + "container_id": str(db_post_id), + "post_slug": post_slug, + "paginate_url": paginate_url, + } + events_nav_html, market_nav_html = await fetch_fragments([ + ("events", "container-nav", nav_params), + ("market", "container-nav", nav_params), + ]) + container_nav_html = events_nav_html + market_nav_html ctx = { **p_data, "base_title": f"{config()['title']} {p_data['post']['title']}", - "container_nav_widgets": container_nav_loaded, + "container_nav_html": container_nav_html, } # Page cart badge via service @@ -154,20 +157,22 @@ def register(): @bp.get("/w//") async def widget_paginate(slug: str, widget_domain: str): - """Generic paginated widget endpoint for infinite scroll.""" + """Proxies paginated widget requests to the appropriate fragment provider.""" page = int(request.args.get("page", 1)) post_id = g.post_data["post"]["id"] - for w in widgets.container_nav: - if w.domain == widget_domain: - ctx = await w.context_fn( - g.s, container_type="page", container_id=post_id, - post_slug=slug, page=page, - ) - html = await render_template( - w.template, ctx=ctx, post=g.post_data["post"], - ) - return await make_response(html) + if widget_domain == "calendar": + html = await fetch_fragment("events", "container-nav", params={ + "container_type": "page", + "container_id": str(post_id), + "post_slug": slug, + "page": str(page), + "paginate_url": url_for( + 'blog.post.widget_paginate', + slug=slug, widget_domain='calendar', + ), + }) + return await make_response(html or "") abort(404) return bp diff --git a/shared b/shared index ab674ad..d2e07e0 160000 --- a/shared +++ b/shared @@ -1 +1 @@ -Subproject commit ab674ada31f09edb1a4333e520d482e13e0c90da +Subproject commit d2e07e047eb161dc7cffbc215b728d5556dae82b