Simplify templates to pure Jinja2 + CodeMirror editor + variable reference
Some checks failed
Validate / Hassfest (push) Has been cancelled
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:
@@ -108,7 +108,11 @@ class TrackingConfig(SQLModel, table=True):
|
||||
|
||||
|
||||
class TemplateConfig(SQLModel, table=True):
|
||||
"""Message template configuration: all template slots from the blueprint."""
|
||||
"""Message template configuration with full Jinja2 templates.
|
||||
|
||||
Each slot is a complete Jinja2 template with access to loops, conditionals,
|
||||
and filters. No sub-templates needed -- use {% for %}, {% if %} inline.
|
||||
"""
|
||||
|
||||
__tablename__ = "template_config"
|
||||
|
||||
@@ -117,49 +121,19 @@ class TemplateConfig(SQLModel, table=True):
|
||||
name: str # e.g. "Default EN", "Default RU"
|
||||
icon: str = Field(default="")
|
||||
|
||||
# Event messages
|
||||
message_assets_added: str = Field(
|
||||
default='📷 {added_count} new photo(s) added to album "{album_name}"{common_date}{common_location}.{people}{assets}{video_warning}'
|
||||
)
|
||||
message_assets_removed: str = Field(
|
||||
default='🗑️ {removed_count} photo(s) removed from album "{album_name}".'
|
||||
)
|
||||
message_album_renamed: str = Field(
|
||||
default='✏️ Album "{old_name}" renamed to "{new_name}".'
|
||||
)
|
||||
message_album_deleted: str = Field(
|
||||
default='🗑️ Album "{album_name}" was deleted.'
|
||||
)
|
||||
# Event-driven notification templates (full Jinja2)
|
||||
message_assets_added: str = Field(default="")
|
||||
message_assets_removed: str = Field(default="")
|
||||
message_album_renamed: str = Field(default="")
|
||||
message_album_deleted: str = Field(default="")
|
||||
|
||||
# Asset item formatting
|
||||
message_asset_image: str = Field(default="\n • 🖼️ {filename}")
|
||||
message_asset_video: str = Field(default="\n • 🎬 {filename}")
|
||||
message_assets_format: str = Field(default="\nAssets:{assets}")
|
||||
message_assets_more: str = Field(default="\n • ...and {more_count} more")
|
||||
message_people_format: str = Field(default=" People: {people}.")
|
||||
# Scheduled notification templates (full Jinja2)
|
||||
periodic_summary_message: str = Field(default="")
|
||||
scheduled_assets_message: str = Field(default="")
|
||||
memory_mode_message: str = Field(default="")
|
||||
|
||||
# Date/location formatting
|
||||
# Settings
|
||||
date_format: str = Field(default="%d.%m.%Y, %H:%M UTC")
|
||||
common_date_template: str = Field(default=" from {date}")
|
||||
date_if_unique_template: str = Field(default=" ({date})")
|
||||
location_format: str = Field(default="{city}, {country}")
|
||||
common_location_template: str = Field(default=" in {location}")
|
||||
location_if_unique_template: str = Field(default=" 📍 {location}")
|
||||
favorite_indicator: str = Field(default="❤️")
|
||||
|
||||
# Scheduled notification templates
|
||||
periodic_summary_message: str = Field(
|
||||
default="📋 Tracked Albums Summary ({album_count} albums):{albums}"
|
||||
)
|
||||
periodic_album_template: str = Field(
|
||||
default="\n • {album_name}: {album_url}"
|
||||
)
|
||||
scheduled_assets_message: str = Field(
|
||||
default='📸 Here are some photos from album "{album_name}":{assets}'
|
||||
)
|
||||
memory_mode_message: str = Field(default="📅 On this day:{assets}")
|
||||
|
||||
# Telegram-specific
|
||||
video_warning: str = Field(
|
||||
default="\n\n⚠️ Note: Videos may not be sent due to Telegram's 50 MB file size limit."
|
||||
)
|
||||
@@ -167,6 +141,81 @@ class TemplateConfig(SQLModel, table=True):
|
||||
created_at: datetime = Field(default_factory=_utcnow)
|
||||
|
||||
|
||||
# --- Default template content (EN) ---
|
||||
|
||||
DEFAULT_TEMPLATE_EN = {
|
||||
"message_assets_added": """📷 {{ added_count }} new photo(s) added to album "{{ album_name }}".\
|
||||
{% if people %}
|
||||
👤 {{ people | join(", ") }}{% endif %}\
|
||||
{% if added_assets %}
|
||||
{% for asset in added_assets %}\
|
||||
• {% if asset.type == "VIDEO" %}🎬{% else %}🖼️{% endif %} {{ asset.filename }}\
|
||||
{% if asset.city %} 📍 {{ asset.city }}{% if asset.country %}, {{ asset.country }}{% endif %}{% endif %}\
|
||||
{% if asset.is_favorite %} ❤️{% endif %}
|
||||
{% endfor %}\
|
||||
{% endif %}\
|
||||
{{ video_warning }}""",
|
||||
|
||||
"message_assets_removed": '🗑️ {{ removed_count }} photo(s) removed from album "{{ album_name }}".',
|
||||
|
||||
"message_album_renamed": '✏️ Album "{{ old_name }}" renamed to "{{ new_name }}".',
|
||||
|
||||
"message_album_deleted": '🗑️ Album "{{ album_name }}" was deleted.',
|
||||
|
||||
"periodic_summary_message": """📋 Tracked Albums Summary ({{ albums | length }} albums):\
|
||||
{% for album in albums %}
|
||||
• {{ album.name }}: {{ album.asset_count }} assets{% if album.url %} — {{ album.url }}{% endif %}\
|
||||
{% endfor %}""",
|
||||
|
||||
"scheduled_assets_message": """📸 Photos from "{{ album_name }}":\
|
||||
{% for asset in assets %}
|
||||
• {% if asset.type == "VIDEO" %}🎬{% else %}🖼️{% endif %} {{ asset.filename }}\
|
||||
{% endfor %}""",
|
||||
|
||||
"memory_mode_message": """📅 On this day:\
|
||||
{% for asset in assets %}
|
||||
• {% if asset.type == "VIDEO" %}🎬{% else %}🖼️{% endif %} {{ asset.filename }} ({{ asset.created_at[:4] }})\
|
||||
{% endfor %}""",
|
||||
}
|
||||
|
||||
# --- Default template content (RU) ---
|
||||
|
||||
DEFAULT_TEMPLATE_RU = {
|
||||
"message_assets_added": """📷 {{ added_count }} новых фото добавлено в альбом "{{ album_name }}".\
|
||||
{% if people %}
|
||||
👤 {{ people | join(", ") }}{% endif %}\
|
||||
{% if added_assets %}
|
||||
{% for asset in added_assets %}\
|
||||
• {% if asset.type == "VIDEO" %}🎬{% else %}🖼️{% endif %} {{ asset.filename }}\
|
||||
{% if asset.city %} 📍 {{ asset.city }}{% if asset.country %}, {{ asset.country }}{% endif %}{% endif %}\
|
||||
{% if asset.is_favorite %} ❤️{% endif %}
|
||||
{% endfor %}\
|
||||
{% endif %}\
|
||||
{{ video_warning }}""",
|
||||
|
||||
"message_assets_removed": '🗑️ {{ removed_count }} фото удалено из альбома "{{ album_name }}".',
|
||||
|
||||
"message_album_renamed": '✏️ Альбом "{{ old_name }}" переименован в "{{ new_name }}".',
|
||||
|
||||
"message_album_deleted": '🗑️ Альбом "{{ album_name }}" был удалён.',
|
||||
|
||||
"periodic_summary_message": """📋 Сводка альбомов ({{ albums | length }}):\
|
||||
{% for album in albums %}
|
||||
• {{ album.name }}: {{ album.asset_count }} файлов{% if album.url %} — {{ album.url }}{% endif %}\
|
||||
{% endfor %}""",
|
||||
|
||||
"scheduled_assets_message": """📸 Фото из "{{ album_name }}":\
|
||||
{% for asset in assets %}
|
||||
• {% if asset.type == "VIDEO" %}🎬{% else %}🖼️{% endif %} {{ asset.filename }}\
|
||||
{% endfor %}""",
|
||||
|
||||
"memory_mode_message": """📅 В этот день:\
|
||||
{% for asset in assets %}
|
||||
• {% if asset.type == "VIDEO" %}🎬{% else %}🖼️{% endif %} {{ asset.filename }} ({{ asset.created_at[:4] }})\
|
||||
{% endfor %}""",
|
||||
}
|
||||
|
||||
|
||||
class NotificationTarget(SQLModel, table=True):
|
||||
"""Notification destination with tracking and template config references."""
|
||||
|
||||
|
||||
Reference in New Issue
Block a user