The POC viewer was loading the storefront in an iframe, which hit the
StorefrontAccessMiddleware subscription check (POC sites don't have
subscriptions yet). Fixed by rendering CMS sections directly in the
preview template:
- Load ContentPages and StoreTheme from DB
- Render hero, features, testimonials, CTA sections inline
- Apply template colors/fonts via Tailwind CSS config
- HostWizard preview banner with nav links
- Footer with contact info
- No iframe, no subscription check needed
Also fixed Jinja2 dict.items collision (dict.items is the method,
not the 'items' key — use dict.get('items') instead).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
103 lines
3.0 KiB
Python
103 lines
3.0 KiB
Python
# app/modules/hosting/routes/pages/public.py
|
|
"""
|
|
Hosting Public Page Routes.
|
|
|
|
Public-facing routes for POC site viewing:
|
|
- POC Viewer - Shows the Store's storefront with a HostWizard preview banner
|
|
"""
|
|
|
|
from fastapi import APIRouter, Depends, Path, Request
|
|
from fastapi.responses import HTMLResponse
|
|
from sqlalchemy.orm import Session
|
|
|
|
from app.core.database import get_db
|
|
from app.templates_config import templates
|
|
|
|
router = APIRouter()
|
|
|
|
|
|
@router.get(
|
|
"/hosting/sites/{site_id}/preview",
|
|
response_class=HTMLResponse,
|
|
include_in_schema=False,
|
|
)
|
|
async def poc_site_viewer(
|
|
request: Request,
|
|
site_id: int = Path(..., description="Hosted Site ID"),
|
|
db: Session = Depends(get_db),
|
|
):
|
|
"""Render POC site viewer with HostWizard preview banner.
|
|
|
|
Renders CMS content directly (not via iframe to storefront) to
|
|
bypass the subscription access gate for pre-launch POC sites.
|
|
"""
|
|
from app.modules.cms.models.content_page import ContentPage
|
|
from app.modules.cms.models.store_theme import StoreTheme
|
|
from app.modules.hosting.models import HostedSite, HostedSiteStatus
|
|
from app.modules.tenancy.models import StorePlatform
|
|
|
|
site = db.query(HostedSite).filter(HostedSite.id == site_id).first()
|
|
|
|
# Only allow viewing for poc_ready or proposal_sent sites
|
|
if not site or site.status not in (
|
|
HostedSiteStatus.POC_READY,
|
|
HostedSiteStatus.PROPOSAL_SENT,
|
|
HostedSiteStatus.ACCEPTED,
|
|
):
|
|
return HTMLResponse(content="<h1>Site not available for preview</h1>", status_code=404)
|
|
|
|
store = site.store
|
|
|
|
# Get platform_id for CMS query
|
|
store_platform = (
|
|
db.query(StorePlatform)
|
|
.filter(StorePlatform.store_id == store.id)
|
|
.first()
|
|
) if store else None
|
|
platform_id = store_platform.platform_id if store_platform else None
|
|
|
|
# Load homepage (slug='homepage' from POC builder)
|
|
page = None
|
|
if platform_id:
|
|
page = (
|
|
db.query(ContentPage)
|
|
.filter(
|
|
ContentPage.platform_id == platform_id,
|
|
ContentPage.store_id == store.id,
|
|
ContentPage.slug == "homepage",
|
|
ContentPage.is_published.is_(True),
|
|
)
|
|
.first()
|
|
)
|
|
|
|
# Load all nav pages for this store
|
|
nav_pages = []
|
|
if platform_id:
|
|
nav_pages = (
|
|
db.query(ContentPage)
|
|
.filter(
|
|
ContentPage.platform_id == platform_id,
|
|
ContentPage.store_id == store.id,
|
|
ContentPage.is_published.is_(True),
|
|
ContentPage.show_in_header.is_(True),
|
|
)
|
|
.order_by(ContentPage.display_order)
|
|
.all()
|
|
)
|
|
|
|
# Load theme
|
|
theme = db.query(StoreTheme).filter(StoreTheme.store_id == store.id).first() if store else None
|
|
|
|
context = {
|
|
"request": request,
|
|
"site": site,
|
|
"store": store,
|
|
"page": page,
|
|
"nav_pages": nav_pages,
|
|
"theme": theme,
|
|
}
|
|
return templates.TemplateResponse(
|
|
"hosting/public/poc-viewer.html",
|
|
context,
|
|
)
|