Phase 6: Replace render_template() with s-expression rendering in all GET routes
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 1m15s
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 1m15s
Migrate ~52 GET route handlers across all 7 services from Jinja render_template() to s-expression component rendering. Each service gets a sexp_components.py with page/oob/cards render functions. - Add per-service sexp_components.py (account, blog, cart, events, federation, market, orders) with full page, OOB, and pagination card rendering - Add shared/sexp/helpers.py with call_url, root_header_html, full_page, oob_page utilities - Update all GET routes to use get_template_context() + render fns - Fix get_template_context() to inject Jinja globals (URL helpers) - Add qs_filter to base_context for sexp filter URL building - Mount sexp_components.py in docker-compose.dev.yml for all services - Import sexp_components in app.py for Hypercorn --reload watching - Fix route_prefix import (shared.utils not shared.infrastructure.urls) - Fix federation choose-username missing actor in context - Fix market page_markets missing post in context Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -100,7 +100,10 @@ def register(url_prefix="/auth"):
|
||||
# If there's a pending redirect (e.g. OAuth authorize), follow it
|
||||
redirect_url = pop_login_redirect_target()
|
||||
return redirect(redirect_url)
|
||||
return await render_template("auth/login.html")
|
||||
from shared.sexp.page import get_template_context
|
||||
from sexp_components import render_login_page
|
||||
ctx = await get_template_context()
|
||||
return await render_login_page(ctx)
|
||||
|
||||
@auth_bp.post("/start/")
|
||||
async def start_login():
|
||||
|
||||
@@ -39,7 +39,11 @@ def register(url_prefix="/identity"):
|
||||
if actor:
|
||||
return redirect(url_for("activitypub.actor_profile", username=actor.preferred_username))
|
||||
|
||||
return await render_template("federation/choose_username.html")
|
||||
from shared.sexp.page import get_template_context
|
||||
from sexp_components import render_choose_username_page
|
||||
ctx = await get_template_context()
|
||||
ctx["actor"] = actor
|
||||
return await render_choose_username_page(ctx)
|
||||
|
||||
@bp.post("/choose-username")
|
||||
async def choose_username():
|
||||
|
||||
@@ -39,12 +39,10 @@ def register(url_prefix="/social"):
|
||||
return redirect(url_for("auth.login_form"))
|
||||
actor = _require_actor()
|
||||
items = await services.federation.get_home_timeline(g.s, actor.id)
|
||||
return await render_template(
|
||||
"federation/timeline.html",
|
||||
items=items,
|
||||
timeline_type="home",
|
||||
actor=actor,
|
||||
)
|
||||
from shared.sexp.page import get_template_context
|
||||
from sexp_components import render_timeline_page
|
||||
ctx = await get_template_context()
|
||||
return await render_timeline_page(ctx, items, "home", actor)
|
||||
|
||||
@bp.get("/timeline")
|
||||
async def home_timeline_page():
|
||||
@@ -59,23 +57,17 @@ def register(url_prefix="/social"):
|
||||
items = await services.federation.get_home_timeline(
|
||||
g.s, actor.id, before=before,
|
||||
)
|
||||
return await render_template(
|
||||
"federation/_timeline_items.html",
|
||||
items=items,
|
||||
timeline_type="home",
|
||||
actor=actor,
|
||||
)
|
||||
from sexp_components import render_timeline_items
|
||||
return await render_timeline_items(items, "home", actor)
|
||||
|
||||
@bp.get("/public")
|
||||
async def public_timeline():
|
||||
items = await services.federation.get_public_timeline(g.s)
|
||||
actor = getattr(g, "_social_actor", None)
|
||||
return await render_template(
|
||||
"federation/timeline.html",
|
||||
items=items,
|
||||
timeline_type="public",
|
||||
actor=actor,
|
||||
)
|
||||
from shared.sexp.page import get_template_context
|
||||
from sexp_components import render_timeline_page
|
||||
ctx = await get_template_context()
|
||||
return await render_timeline_page(ctx, items, "public", actor)
|
||||
|
||||
@bp.get("/public/timeline")
|
||||
async def public_timeline_page():
|
||||
@@ -88,12 +80,8 @@ def register(url_prefix="/social"):
|
||||
pass
|
||||
items = await services.federation.get_public_timeline(g.s, before=before)
|
||||
actor = getattr(g, "_social_actor", None)
|
||||
return await render_template(
|
||||
"federation/_timeline_items.html",
|
||||
items=items,
|
||||
timeline_type="public",
|
||||
actor=actor,
|
||||
)
|
||||
from sexp_components import render_timeline_items
|
||||
return await render_timeline_items(items, "public", actor)
|
||||
|
||||
# -- Compose --------------------------------------------------------------
|
||||
|
||||
@@ -101,11 +89,10 @@ def register(url_prefix="/social"):
|
||||
async def compose_form():
|
||||
actor = _require_actor()
|
||||
reply_to = request.args.get("reply_to")
|
||||
return await render_template(
|
||||
"federation/compose.html",
|
||||
actor=actor,
|
||||
reply_to=reply_to,
|
||||
)
|
||||
from shared.sexp.page import get_template_context
|
||||
from sexp_components import render_compose_page
|
||||
ctx = await get_template_context()
|
||||
return await render_compose_page(ctx, actor, reply_to)
|
||||
|
||||
@bp.post("/compose")
|
||||
async def compose_submit():
|
||||
@@ -148,15 +135,10 @@ def register(url_prefix="/social"):
|
||||
g.s, actor.preferred_username, page=1, per_page=1000,
|
||||
)
|
||||
followed_urls = {a.actor_url for a in following}
|
||||
return await render_template(
|
||||
"federation/search.html",
|
||||
query=query,
|
||||
actors=actors,
|
||||
total=total,
|
||||
page=1,
|
||||
followed_urls=followed_urls,
|
||||
actor=actor,
|
||||
)
|
||||
from shared.sexp.page import get_template_context
|
||||
from sexp_components import render_search_page
|
||||
ctx = await get_template_context()
|
||||
return await render_search_page(ctx, query, actors, total, 1, followed_urls, actor)
|
||||
|
||||
@bp.get("/search/page")
|
||||
async def search_page():
|
||||
@@ -175,15 +157,8 @@ def register(url_prefix="/social"):
|
||||
g.s, actor.preferred_username, page=1, per_page=1000,
|
||||
)
|
||||
followed_urls = {a.actor_url for a in following}
|
||||
return await render_template(
|
||||
"federation/_search_results.html",
|
||||
actors=actors,
|
||||
total=total,
|
||||
page=page,
|
||||
query=query,
|
||||
followed_urls=followed_urls,
|
||||
actor=actor,
|
||||
)
|
||||
from sexp_components import render_search_results
|
||||
return await render_search_results(actors, query, page, followed_urls, actor)
|
||||
|
||||
@bp.post("/follow")
|
||||
async def follow():
|
||||
@@ -340,13 +315,10 @@ def register(url_prefix="/social"):
|
||||
actors, total = await services.federation.get_following(
|
||||
g.s, actor.preferred_username,
|
||||
)
|
||||
return await render_template(
|
||||
"federation/following.html",
|
||||
actors=actors,
|
||||
total=total,
|
||||
page=1,
|
||||
actor=actor,
|
||||
)
|
||||
from shared.sexp.page import get_template_context
|
||||
from sexp_components import render_following_page
|
||||
ctx = await get_template_context()
|
||||
return await render_following_page(ctx, actors, total, actor)
|
||||
|
||||
@bp.get("/following/page")
|
||||
async def following_list_page():
|
||||
@@ -355,15 +327,8 @@ def register(url_prefix="/social"):
|
||||
actors, total = await services.federation.get_following(
|
||||
g.s, actor.preferred_username, page=page,
|
||||
)
|
||||
return await render_template(
|
||||
"federation/_actor_list_items.html",
|
||||
actors=actors,
|
||||
total=total,
|
||||
page=page,
|
||||
list_type="following",
|
||||
followed_urls=set(),
|
||||
actor=actor,
|
||||
)
|
||||
from sexp_components import render_following_items
|
||||
return await render_following_items(actors, page, actor)
|
||||
|
||||
@bp.get("/followers")
|
||||
async def followers_list():
|
||||
@@ -376,14 +341,10 @@ def register(url_prefix="/social"):
|
||||
g.s, actor.preferred_username, page=1, per_page=1000,
|
||||
)
|
||||
followed_urls = {a.actor_url for a in following}
|
||||
return await render_template(
|
||||
"federation/followers.html",
|
||||
actors=actors,
|
||||
total=total,
|
||||
page=1,
|
||||
followed_urls=followed_urls,
|
||||
actor=actor,
|
||||
)
|
||||
from shared.sexp.page import get_template_context
|
||||
from sexp_components import render_followers_page
|
||||
ctx = await get_template_context()
|
||||
return await render_followers_page(ctx, actors, total, followed_urls, actor)
|
||||
|
||||
@bp.get("/followers/page")
|
||||
async def followers_list_page():
|
||||
@@ -396,15 +357,8 @@ def register(url_prefix="/social"):
|
||||
g.s, actor.preferred_username, page=1, per_page=1000,
|
||||
)
|
||||
followed_urls = {a.actor_url for a in following}
|
||||
return await render_template(
|
||||
"federation/_actor_list_items.html",
|
||||
actors=actors,
|
||||
total=total,
|
||||
page=page,
|
||||
list_type="followers",
|
||||
followed_urls=followed_urls,
|
||||
actor=actor,
|
||||
)
|
||||
from sexp_components import render_followers_items
|
||||
return await render_followers_items(actors, page, followed_urls, actor)
|
||||
|
||||
@bp.get("/actor/<int:id>")
|
||||
async def actor_timeline(id: int):
|
||||
@@ -435,13 +389,10 @@ def register(url_prefix="/social"):
|
||||
)
|
||||
).scalar_one_or_none()
|
||||
is_following = existing is not None
|
||||
return await render_template(
|
||||
"federation/actor_timeline.html",
|
||||
remote_actor=remote_dto,
|
||||
items=items,
|
||||
is_following=is_following,
|
||||
actor=actor,
|
||||
)
|
||||
from shared.sexp.page import get_template_context
|
||||
from sexp_components import render_actor_timeline_page
|
||||
ctx = await get_template_context()
|
||||
return await render_actor_timeline_page(ctx, remote_dto, items, is_following, actor)
|
||||
|
||||
@bp.get("/actor/<int:id>/timeline")
|
||||
async def actor_timeline_page(id: int):
|
||||
@@ -456,13 +407,8 @@ def register(url_prefix="/social"):
|
||||
items = await services.federation.get_actor_timeline(
|
||||
g.s, id, before=before,
|
||||
)
|
||||
return await render_template(
|
||||
"federation/_timeline_items.html",
|
||||
items=items,
|
||||
timeline_type="actor",
|
||||
actor_id=id,
|
||||
actor=actor,
|
||||
)
|
||||
from sexp_components import render_actor_timeline_items
|
||||
return await render_actor_timeline_items(items, id, actor)
|
||||
|
||||
# -- Notifications --------------------------------------------------------
|
||||
|
||||
@@ -471,11 +417,10 @@ def register(url_prefix="/social"):
|
||||
actor = _require_actor()
|
||||
items = await services.federation.get_notifications(g.s, actor.id)
|
||||
await services.federation.mark_notifications_read(g.s, actor.id)
|
||||
return await render_template(
|
||||
"federation/notifications.html",
|
||||
notifications=items,
|
||||
actor=actor,
|
||||
)
|
||||
from shared.sexp.page import get_template_context
|
||||
from sexp_components import render_notifications_page
|
||||
ctx = await get_template_context()
|
||||
return await render_notifications_page(ctx, items, actor)
|
||||
|
||||
@bp.get("/notifications/count")
|
||||
async def notification_count():
|
||||
|
||||
Reference in New Issue
Block a user