fix: re-create missing EN default template, provider type as IconGridSelect

- Template seed now re-creates missing system templates on every startup
  (not just first boot), using raw SQL to handle legacy NOT NULL columns
- Tracking configs: add provider type selector (was missing)
- All config forms: provider type uses IconGridSelect during creation,
  read-only text during editing (immutable after creation)
- Pages: tracking-configs, command-configs, command-template-configs,
  template-configs
This commit is contained in:
2026-03-22 00:36:15 +03:00
parent 9d3abd9fa0
commit db7aac5fe8
@@ -93,6 +93,7 @@ async def _seed_default_templates():
Uses TemplateSlot child rows for template content. Uses TemplateSlot child rows for template content.
""" """
from sqlalchemy import text
from sqlmodel import func, select from sqlmodel import func, select
from sqlmodel.ext.asyncio.session import AsyncSession from sqlmodel.ext.asyncio.session import AsyncSession
from .database.engine import get_engine from .database.engine import get_engine
@@ -101,43 +102,70 @@ async def _seed_default_templates():
engine = get_engine() engine = get_engine()
async with AsyncSession(engine) as session: async with AsyncSession(engine) as session:
result = await session.exec(select(func.count()).select_from(TemplateConfig)) # Find existing system-owned templates
count = result.one() result = await session.exec(
select(TemplateConfig).where(TemplateConfig.user_id == 0)
)
system_configs = result.all()
existing_locales = {
"ru" if "(RU)" in c.name else "en": c for c in system_configs
}
if count == 0: for locale in ("en", "ru"):
# First startup — seed all defaults slots = load_default_templates(locale)
for locale in ("en", "ru"): if not slots:
slots = load_default_templates(locale) continue
if not slots:
continue if locale not in existing_locales:
# Create missing system template via raw SQL
# (legacy NOT NULL columns may still exist in the DB)
name = f"Default ({locale.upper()})" name = f"Default ({locale.upper()})"
config = TemplateConfig( desc = f"Default Immich templates ({locale.upper()})"
user_id=0, # Get column names to build INSERT with defaults for legacy cols
provider_type="immich", col_info = (await session.execute(
name=name, text("PRAGMA table_info(template_config)")
description=f"Default Immich templates ({locale.upper()})", )).fetchall()
col_names = [c[1] for c in col_info if c[1] != "id"]
values = {}
from datetime import datetime, timezone
now = datetime.now(timezone.utc).isoformat()
for col in col_names:
if col == "user_id":
values[col] = 0
elif col == "provider_type":
values[col] = "immich"
elif col == "name":
values[col] = name
elif col == "description":
values[col] = desc
elif col == "created_at":
values[col] = now
elif col == "date_format":
values[col] = "%d.%m.%Y, %H:%M UTC"
elif col == "date_only_format":
values[col] = "%d.%m.%Y"
else:
values[col] = "" # empty string for legacy columns
cols_str = ", ".join(values.keys())
placeholders = ", ".join(f":{k}" for k in values.keys())
await session.execute(
text(f"INSERT INTO template_config ({cols_str}) VALUES ({placeholders})"),
values,
) )
session.add(config) # Get the inserted ID
await session.flush() # get config.id row = (await session.execute(text("SELECT last_insert_rowid()"))).scalar()
config_id = row
for slot_name, template_text in slots.items(): for slot_name, template_text in slots.items():
session.add(TemplateSlot( session.add(TemplateSlot(
config_id=config.id, config_id=config_id,
slot_name=slot_name, slot_name=slot_name,
template=template_text, template=template_text,
)) ))
else: else:
# Update existing system-owned templates from files # Update existing system template slots
result = await session.exec( config = existing_locales[locale]
select(TemplateConfig).where(TemplateConfig.user_id == 0)
)
system_configs = result.all()
for config in system_configs:
locale = "ru" if "(RU)" in config.name else "en"
slots = load_default_templates(locale)
if not slots:
continue
for slot_name, template_text in slots.items(): for slot_name, template_text in slots.items():
# Upsert: find existing slot or create new
slot_result = await session.exec( slot_result = await session.exec(
select(TemplateSlot).where( select(TemplateSlot).where(
TemplateSlot.config_id == config.id, TemplateSlot.config_id == config.id,