feat(web): admin area with instance default theme, custom logo/favicon; .theme.json export
- Admin settings tab (admin-only) now holds user management plus a server-wide default theme editor (live preview + discard) and logo/favicon branding. - New singleton InstanceSettings model + /api/instance router (public GET for the login screen; admin-gated theme PUT and logo/favicon upload/delete, reusing the avatar PIL/validation pattern). - Instance default theme is the base users inherit and the target a per-colour "Reset" returns to (baseColor: instance default -> built-in). - Custom favicon overrides the primary-colour tinting; custom logo replaces the top-left glyph+text, hard-capped so it only scales down and never breaks layout. Branding + defaults load before login (public endpoint). - Theme export now uses the recognised .theme.json extension (old .theme still imports); import stays partial/unknown-key aware. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -139,6 +139,20 @@ class UserSettings(Base):
|
||||
user = relationship("User", back_populates="settings")
|
||||
|
||||
|
||||
class InstanceSettings(Base):
|
||||
"""Server-wide (singleton, id=1) branding + default theme set by an admin.
|
||||
Applies to everyone; a user's own settings still override the default theme."""
|
||||
__tablename__ = "instance_settings"
|
||||
|
||||
id = Column(Integer, primary_key=True) # always 1
|
||||
# JSON {colorKey: "#RRGGBB"} — the instance default theme. Empty/NULL = use the
|
||||
# client's built-in defaults. A user's own colour wins over this.
|
||||
default_theme = Column(Text, nullable=True)
|
||||
# Uploaded branding files (stored under DATA_DIR/branding). NULL = use bundled.
|
||||
logo_filename = Column(String(255), nullable=True)
|
||||
favicon_filename = Column(String(255), nullable=True)
|
||||
|
||||
|
||||
class AppPassword(Base):
|
||||
"""Per-device app-specific password for CalDAV (Basic Auth).
|
||||
|
||||
|
||||
Reference in New Issue
Block a user