Simplify templates to pure Jinja2 + CodeMirror editor + variable reference
Some checks failed
Validate / Hassfest (push) Has been cancelled

Major template system overhaul:
- TemplateConfig simplified from 21 fields to 9: removed all sub-templates
  (asset_image, asset_video, assets_format, people_format, etc.)
  Users write full Jinja2 with {% for %}, {% if %} inline.
- Default EN/RU templates seeded on first startup (user_id=0, system-owned)
  with proper Jinja2 loops over added_assets, people, albums.
- build_full_context() simplified: passes raw data directly to Jinja2
  instead of pre-rendering sub-templates.
- CodeMirror editor for template slots (HTML syntax highlighting,
  line wrapping, dark theme support via oneDark).
- Variable reference API: GET /api/template-configs/variables returns
  per-slot variable descriptions + asset_fields for loop contexts.
- Variable reference modal in UI: click "{{ }} Variables" next to any
  slot to see available variables with Jinja2 syntax examples.
- Route ordering fix: /variables registered before /{config_id}.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-19 18:57:51 +03:00
parent bc8fda5984
commit 0bb4d8a949
9 changed files with 791 additions and 181 deletions

View File

@@ -33,6 +33,33 @@ logging.basicConfig(
_LOGGER = logging.getLogger(__name__)
async def _seed_default_templates():
"""Create default EN/RU template configs if none exist."""
from sqlmodel import func, select
from sqlmodel.ext.asyncio.session import AsyncSession
from .database.engine import get_engine
from .database.models import (
TemplateConfig,
DEFAULT_TEMPLATE_EN,
DEFAULT_TEMPLATE_RU,
)
engine = get_engine()
async with AsyncSession(engine) as session:
result = await session.exec(select(func.count()).select_from(TemplateConfig))
count = result.one()
if count > 0:
return
# user_id=0 means system-owned (available to all users)
en = TemplateConfig(user_id=0, name="Default EN", icon="mdiTranslate", **DEFAULT_TEMPLATE_EN)
ru = TemplateConfig(user_id=0, name="По умолчанию RU", icon="mdiTranslate", **DEFAULT_TEMPLATE_RU)
session.add(en)
session.add(ru)
await session.commit()
_LOGGER.info("Seeded default EN and RU template configs")
@asynccontextmanager
async def lifespan(app: FastAPI):
"""Application lifespan: startup and shutdown."""
@@ -41,6 +68,9 @@ async def lifespan(app: FastAPI):
await init_db()
_LOGGER.info("Database initialized at %s", settings.effective_database_url)
# Seed default templates if none exist
await _seed_default_templates()
await start_scheduler()
yield