Eliminate Python page helpers from account, federation, and cart
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 2m8s
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 2m8s
All three services now fetch page data via (service ...) IO primitives in .sx defpages instead of Python middleman functions. - Account: newsletters-data → AccountPageService.newsletters_data - Federation: 8 page helpers → FederationPageService methods (timeline, compose, search, following, followers, notifications) - Cart: 4 page helpers → CartPageService methods (overview, page-cart, admin, payments) - Serializers moved to service modules, thin delegates kept for routes - ~520 lines of Python page helpers removed Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -3,9 +3,7 @@ from __future__ import annotations
|
||||
|
||||
|
||||
def register_domain_services() -> None:
|
||||
"""Register services for the account app.
|
||||
|
||||
Account is a consumer-only dashboard app. It has no own domain.
|
||||
All cross-app data comes via fragments and HTTP data endpoints.
|
||||
"""
|
||||
pass
|
||||
"""Register services for the account app."""
|
||||
from shared.services.registry import services
|
||||
from .account_page import AccountPageService
|
||||
services.register("account_page", AccountPageService())
|
||||
|
||||
40
account/services/account_page.py
Normal file
40
account/services/account_page.py
Normal file
@@ -0,0 +1,40 @@
|
||||
"""Account page data service — provides serialized dicts for .sx defpages."""
|
||||
from __future__ import annotations
|
||||
|
||||
|
||||
class AccountPageService:
|
||||
"""Service for account page data, callable via (service "account-page" ...)."""
|
||||
|
||||
async def newsletters_data(self, session, **kw):
|
||||
"""Return newsletter list with user subscription status."""
|
||||
from quart import g
|
||||
from sqlalchemy import select
|
||||
from shared.models import UserNewsletter
|
||||
from shared.models.ghost_membership_entities import GhostNewsletter
|
||||
|
||||
result = await session.execute(
|
||||
select(GhostNewsletter).order_by(GhostNewsletter.name)
|
||||
)
|
||||
all_newsletters = result.scalars().all()
|
||||
|
||||
sub_result = await session.execute(
|
||||
select(UserNewsletter).where(
|
||||
UserNewsletter.user_id == g.user.id,
|
||||
)
|
||||
)
|
||||
user_subs = {un.newsletter_id: un for un in sub_result.scalars().all()}
|
||||
|
||||
newsletter_list = []
|
||||
for nl in all_newsletters:
|
||||
un = user_subs.get(nl.id)
|
||||
newsletter_list.append({
|
||||
"newsletter": {"id": nl.id, "name": nl.name, "description": nl.description},
|
||||
"un": {"newsletter_id": un.newsletter_id, "subscribed": un.subscribed} if un else None,
|
||||
"subscribed": un.subscribed if un else False,
|
||||
})
|
||||
|
||||
from shared.infrastructure.urls import account_url
|
||||
return {
|
||||
"newsletter_list": newsletter_list,
|
||||
"account_url": account_url(""),
|
||||
}
|
||||
@@ -1,13 +1,12 @@
|
||||
"""Account defpage setup — registers layouts, page helpers, and loads .sx pages."""
|
||||
"""Account defpage setup — registers layouts and loads .sx pages."""
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
|
||||
|
||||
def setup_account_pages() -> None:
|
||||
"""Register account-specific layouts, page helpers, and load page definitions."""
|
||||
"""Register account-specific layouts and load page definitions."""
|
||||
_register_account_layouts()
|
||||
_register_account_helpers()
|
||||
_load_account_page_files()
|
||||
|
||||
|
||||
@@ -90,50 +89,3 @@ def _as_sx_nav(ctx: dict) -> Any:
|
||||
return _as_sx(ctx.get("account_nav"))
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Page helpers
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
def _register_account_helpers() -> None:
|
||||
from shared.sx.pages import register_page_helpers
|
||||
|
||||
register_page_helpers("account", {
|
||||
"newsletters-data": _h_newsletters_data,
|
||||
})
|
||||
|
||||
|
||||
async def _h_newsletters_data(**kw):
|
||||
"""Fetch newsletter data — returns dict merged into defpage env."""
|
||||
from quart import g
|
||||
from sqlalchemy import select
|
||||
from shared.models import UserNewsletter
|
||||
from shared.models.ghost_membership_entities import GhostNewsletter
|
||||
|
||||
result = await g.s.execute(
|
||||
select(GhostNewsletter).order_by(GhostNewsletter.name)
|
||||
)
|
||||
all_newsletters = result.scalars().all()
|
||||
|
||||
sub_result = await g.s.execute(
|
||||
select(UserNewsletter).where(
|
||||
UserNewsletter.user_id == g.user.id,
|
||||
)
|
||||
)
|
||||
user_subs = {un.newsletter_id: un for un in sub_result.scalars().all()}
|
||||
|
||||
newsletter_list = []
|
||||
for nl in all_newsletters:
|
||||
un = user_subs.get(nl.id)
|
||||
newsletter_list.append({
|
||||
"newsletter": {"id": nl.id, "name": nl.name, "description": nl.description},
|
||||
"un": {"newsletter_id": un.newsletter_id, "subscribed": un.subscribed} if un else None,
|
||||
"subscribed": un.subscribed if un else False,
|
||||
})
|
||||
|
||||
account_url = getattr(g, "_account_url", None)
|
||||
if account_url is None:
|
||||
from shared.infrastructure.urls import account_url as _account_url
|
||||
account_url = _account_url
|
||||
account_url_str = account_url("") if callable(account_url) else str(account_url or "")
|
||||
|
||||
return {"newsletter-list": newsletter_list, "account-url": account_url_str}
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
:path "/newsletters/"
|
||||
:auth :login
|
||||
:layout :account
|
||||
:data (newsletters-data)
|
||||
:data (service "account-page" "newsletters-data")
|
||||
:content (~account-newsletters-content
|
||||
:newsletter-list newsletter-list
|
||||
:account-url account-url))
|
||||
|
||||
Reference in New Issue
Block a user