feat(storefront): section-based homepages, header action partials, fixes
Phase 1 — Section-based store homepages:
- Store defaults use template="full" with per-platform sections JSON
- OMS: shop hero + features + CTA; Loyalty: rewards hero + features + CTA
- Hosting: services hero + features + CTA
- Deep placeholder resolution for {{store_name}} inside sections JSON
- landing-full.html uses resolved page_sections from context
Phase 2 — Module-contributed header actions:
- header_template field on MenuItemDefinition + DiscoveredMenuItem
- Catalog provides header-search.html partial
- Cart provides header-cart.html partial with badge
- Base template iterates storefront_nav.actions with {% include %}
- Generic icon fallback for actions without a template
Fixes:
- Store theme API: get_store_by_code → get_store_by_code_or_subdomain
Docs:
- CMS redesign proposal: menu restructure, page types, translations UI
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -24,6 +24,7 @@ Lookup Strategy for Store Storefronts:
|
||||
|
||||
import logging
|
||||
from datetime import UTC, datetime
|
||||
from typing import Any
|
||||
|
||||
from sqlalchemy import and_
|
||||
from sqlalchemy.orm import Session
|
||||
@@ -991,6 +992,28 @@ class ContentPageService:
|
||||
content = content.replace(placeholder, value)
|
||||
return content
|
||||
|
||||
@staticmethod
|
||||
def resolve_placeholders_deep(data, store) -> Any:
|
||||
"""
|
||||
Recursively resolve {{store_name}} etc. in a nested data structure
|
||||
(dicts, lists, strings). Used for sections JSON in store default pages.
|
||||
"""
|
||||
if not data or not store:
|
||||
return data
|
||||
if isinstance(data, str):
|
||||
return ContentPageService.resolve_placeholders(data, store)
|
||||
if isinstance(data, dict):
|
||||
return {
|
||||
k: ContentPageService.resolve_placeholders_deep(v, store)
|
||||
for k, v in data.items()
|
||||
}
|
||||
if isinstance(data, list):
|
||||
return [
|
||||
ContentPageService.resolve_placeholders_deep(item, store)
|
||||
for item in data
|
||||
]
|
||||
return data
|
||||
|
||||
# =========================================================================
|
||||
# Homepage Sections Management
|
||||
# =========================================================================
|
||||
|
||||
@@ -70,7 +70,7 @@ class StoreThemeService:
|
||||
"""
|
||||
from app.modules.tenancy.services.store_service import store_service
|
||||
|
||||
store = store_service.get_store_by_code(db, store_code)
|
||||
store = store_service.get_store_by_code_or_subdomain(db, store_code)
|
||||
|
||||
if not store:
|
||||
self.logger.warning(f"Store not found: {store_code}")
|
||||
|
||||
Reference in New Issue
Block a user