Unify post admin nav across all services
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 1m56s
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 1m56s
Move post admin header into shared/sexp/helpers.py so blog, cart, events, and market all render the same admin row with identical nav: calendars | markets | payments | entries | data | edit | settings. All links are external (cross-service). The selected item shows highlighted on the right and as white text next to "admin" on the left. - blog: delegates to shared helper, removes blog-specific nav builder - cart: delegates to shared helper for payments admin - events: adds shared admin row (selected=calendars) to calendar admin - market: adds /<slug>/admin/ route + page_admin blueprint, delegates to shared helper (selected=markets). Fixes 404 on page-level admin. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -11,7 +11,7 @@ from sqlalchemy import select
|
||||
from shared.infrastructure.factory import create_base_app
|
||||
from shared.config import config
|
||||
|
||||
from bp import register_market_bp, register_all_markets, register_page_markets, register_fragments, register_actions, register_data
|
||||
from bp import register_market_bp, register_all_markets, register_page_markets, register_page_admin, register_fragments, register_actions, register_data
|
||||
|
||||
|
||||
async def market_context() -> dict:
|
||||
@@ -111,6 +111,12 @@ def create_app() -> "Quart":
|
||||
url_prefix="/<slug>",
|
||||
)
|
||||
|
||||
# Page admin: /<slug>/admin/ — post-level admin for markets
|
||||
app.register_blueprint(
|
||||
register_page_admin(),
|
||||
url_prefix="/<slug>/admin",
|
||||
)
|
||||
|
||||
# Market blueprint nested under post slug: /<page_slug>/<market_slug>/
|
||||
app.register_blueprint(
|
||||
register_market_bp(
|
||||
|
||||
@@ -2,6 +2,7 @@ from .market.routes import register as register_market_bp
|
||||
from .product.routes import register as register_product
|
||||
from .all_markets.routes import register as register_all_markets
|
||||
from .page_markets.routes import register as register_page_markets
|
||||
from .page_admin.routes import register as register_page_admin
|
||||
from .fragments import register_fragments
|
||||
from .actions import register_actions
|
||||
from .data import register_data
|
||||
|
||||
0
market/bp/page_admin/__init__.py
Normal file
0
market/bp/page_admin/__init__.py
Normal file
25
market/bp/page_admin/routes.py
Normal file
25
market/bp/page_admin/routes.py
Normal file
@@ -0,0 +1,25 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from quart import make_response, Blueprint
|
||||
|
||||
from shared.browser.app.authz import require_admin
|
||||
from shared.browser.app.utils.htmx import is_htmx_request
|
||||
|
||||
|
||||
def register():
|
||||
bp = Blueprint("page_admin", __name__)
|
||||
|
||||
@bp.get("/")
|
||||
@require_admin
|
||||
async def admin(**kwargs):
|
||||
from shared.sexp.page import get_template_context
|
||||
from sexp.sexp_components import render_page_admin_page, render_page_admin_oob
|
||||
|
||||
tctx = await get_template_context()
|
||||
if not is_htmx_request():
|
||||
html = await render_page_admin_page(tctx)
|
||||
else:
|
||||
html = await render_page_admin_oob(tctx)
|
||||
return await make_response(html)
|
||||
|
||||
return bp
|
||||
@@ -15,6 +15,7 @@ from shared.sexp.jinja_bridge import render, load_service_components
|
||||
from shared.sexp.helpers import (
|
||||
call_url, get_asset_url, root_header_html,
|
||||
post_header_html as _post_header_html,
|
||||
post_admin_header_html,
|
||||
oob_header_html as _oob_header_html,
|
||||
search_mobile_html, search_desktop_html,
|
||||
full_page, oob_page,
|
||||
@@ -1420,7 +1421,7 @@ async def render_market_admin_page(ctx: dict) -> str:
|
||||
content = "market admin"
|
||||
|
||||
hdr = root_header_html(ctx)
|
||||
child = _post_header_html(ctx) + _market_header_html(ctx) + _market_admin_header_html(ctx)
|
||||
child = _post_header_html(ctx) + _market_header_html(ctx) + _market_admin_header_html(ctx, selected="markets")
|
||||
hdr += render("header-child", inner_html=child)
|
||||
return full_page(ctx, header_rows_html=hdr, content_html=content)
|
||||
|
||||
@@ -1431,21 +1432,37 @@ async def render_market_admin_oob(ctx: dict) -> str:
|
||||
|
||||
oobs = _market_header_html(ctx, oob=True)
|
||||
oobs += _oob_header_html("market-header-child", "market-admin-header-child",
|
||||
_market_admin_header_html(ctx))
|
||||
_market_admin_header_html(ctx, selected="markets"))
|
||||
return oob_page(ctx, oobs_html=oobs, content_html=content)
|
||||
|
||||
|
||||
def _market_admin_header_html(ctx: dict, *, oob: bool = False) -> str:
|
||||
"""Build market admin header row."""
|
||||
from quart import url_for
|
||||
def _market_admin_header_html(ctx: dict, *, oob: bool = False, selected: str = "") -> str:
|
||||
"""Build market admin header row — delegates to shared helper."""
|
||||
slug = (ctx.get("post") or {}).get("slug", "")
|
||||
return post_admin_header_html(ctx, slug, oob=oob, selected=selected)
|
||||
|
||||
link_href = url_for("market.admin.admin")
|
||||
return render(
|
||||
"menu-row",
|
||||
id="market-admin-row", level=3,
|
||||
link_href=link_href, link_label="admin", icon="fa fa-cog",
|
||||
child_id="market-admin-header-child", oob=oob,
|
||||
)
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Page admin (/<slug>/admin/) — post-level admin for markets
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
async def render_page_admin_page(ctx: dict) -> str:
|
||||
"""Full page: page-level market admin."""
|
||||
slug = (ctx.get("post") or {}).get("slug", "")
|
||||
admin_hdr = post_admin_header_html(ctx, slug, selected="markets")
|
||||
hdr = root_header_html(ctx)
|
||||
child = _post_header_html(ctx) + admin_hdr
|
||||
hdr += render("header-child", inner_html=child)
|
||||
content = '<div id="main-panel"><div class="p-4 text-stone-500">Market admin</div></div>'
|
||||
return full_page(ctx, header_rows_html=hdr, content_html=content)
|
||||
|
||||
|
||||
async def render_page_admin_oob(ctx: dict) -> str:
|
||||
"""OOB response: page-level market admin."""
|
||||
slug = (ctx.get("post") or {}).get("slug", "")
|
||||
oobs = post_admin_header_html(ctx, slug, oob=True, selected="markets")
|
||||
content = '<div id="main-panel"><div class="p-4 text-stone-500">Market admin</div></div>'
|
||||
return oob_page(ctx, oobs_html=oobs, content_html=content)
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user