Adds website theme serialization system
This commit is contained in:
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -305,6 +305,25 @@ async def _upload_files_to_worker(
|
||||
raise RuntimeError(f"Failed to upload file {row.original_name}: {out}")
|
||||
|
||||
|
||||
async def _upload_theme_to_worker(
|
||||
session: AsyncSession,
|
||||
request: MobileBuildRequest,
|
||||
host: str,
|
||||
) -> None:
|
||||
"""SCP theme.json to the build worker (no-op if file doesn't exist)."""
|
||||
theme_path = Path(settings.THEME_JSON_PATH)
|
||||
if not theme_path.exists():
|
||||
await _append_log(session, request, "[theme] theme.json not found — skipping upload")
|
||||
return
|
||||
|
||||
scp_prefix = _build_scp_prefix(host)
|
||||
remote_target = f"{settings.MOBILE_BUILD_SSH_USER}@{host}:{settings.MOBILE_BUILD_REMOTE_APP_DIR}/theme.json"
|
||||
code, out = await _run_command(scp_prefix + [str(theme_path), remote_target])
|
||||
if code != 0:
|
||||
raise RuntimeError(f"Failed to upload theme.json: {out}")
|
||||
await _append_log(session, request, "[theme] theme.json uploaded to worker")
|
||||
|
||||
|
||||
async def _run_platform_build(
|
||||
session: AsyncSession,
|
||||
request: MobileBuildRequest,
|
||||
@@ -317,6 +336,9 @@ async def _run_platform_build(
|
||||
await _append_log(session, request, f"[{platform}] Uploading {len(platform_files)} file(s) to worker")
|
||||
await _upload_files_to_worker(platform_files, host)
|
||||
|
||||
# Upload theme.json to worker
|
||||
await _upload_theme_to_worker(session, request, host)
|
||||
|
||||
ssh_prefix = _build_ssh_prefix(host)
|
||||
cmd = ssh_prefix + [
|
||||
(
|
||||
|
||||
@@ -1,15 +1,20 @@
|
||||
"""Station config router: read/update the singleton station branding config."""
|
||||
|
||||
import logging
|
||||
|
||||
from fastapi import APIRouter, Depends, HTTPException, status
|
||||
|
||||
from app.auth import get_current_admin_user
|
||||
from app.database import get_session
|
||||
from app.models import StationConfig
|
||||
from app.schemas import StationConfigResponse, StationConfigUpdate
|
||||
from app.theme_export import write_theme_json
|
||||
from app.user_models import User
|
||||
from sqlalchemy import select
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
|
||||
@@ -47,4 +52,11 @@ async def update_station_config(
|
||||
|
||||
await session.commit()
|
||||
await session.refresh(config)
|
||||
|
||||
# Regenerate theme.json on disk (best-effort)
|
||||
try:
|
||||
await write_theme_json()
|
||||
except Exception:
|
||||
logger.warning("Failed to regenerate theme.json after config update", exc_info=True)
|
||||
|
||||
return config
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
"""Theme export: public JSON endpoint, status check, and admin regeneration trigger."""
|
||||
|
||||
from typing import Any, Dict
|
||||
|
||||
from fastapi import APIRouter, Depends, HTTPException, status
|
||||
|
||||
from app.auth import get_current_admin_user
|
||||
from app.theme_export import get_theme_status, write_theme_json
|
||||
from app.user_models import User
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
|
||||
@router.get("/status")
|
||||
async def theme_status() -> Dict[str, Any]:
|
||||
"""Return theme.json file status. Public endpoint."""
|
||||
return get_theme_status()
|
||||
|
||||
|
||||
@router.get("")
|
||||
async def get_theme() -> Dict[str, Any]:
|
||||
"""Return the current theme as a JSON dict. Public endpoint.
|
||||
|
||||
Also regenerates the theme.json file on disk as a side effect,
|
||||
ensuring the file is always up-to-date.
|
||||
"""
|
||||
try:
|
||||
theme = await write_theme_json()
|
||||
except Exception as e:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||
detail=f"Failed to generate theme: {e}",
|
||||
)
|
||||
return theme
|
||||
|
||||
|
||||
@router.post("/regenerate", status_code=200)
|
||||
async def regenerate_theme(
|
||||
_: User = Depends(get_current_admin_user),
|
||||
) -> Dict[str, Any]:
|
||||
"""Force regenerate the theme.json file. Admin only.
|
||||
|
||||
Returns the newly generated theme dict.
|
||||
"""
|
||||
try:
|
||||
theme = await write_theme_json()
|
||||
except Exception as e:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||
detail=f"Failed to regenerate theme: {e}",
|
||||
)
|
||||
return theme
|
||||
Reference in New Issue
Block a user