From 589ac73b2500aaca0f7f61bd3664863a3aecd7a8 Mon Sep 17 00:00:00 2001 From: ramforth Date: Mon, 17 Nov 2025 14:14:45 +0100 Subject: [PATCH] Starting implementation of user made custom CSS templates --- main.py | 66 ++++++++++++++++++--- static/css/main.css | 48 ++++++++++++++++ static/css/overlay-base.css | 12 ++++ templates/dashboard.html | 104 +++++++++++++++++++++++++++++++--- templates/overlay-custom.html | 15 +++++ 5 files changed, 228 insertions(+), 17 deletions(-) create mode 100644 static/css/overlay-base.css create mode 100644 templates/overlay-custom.html diff --git a/main.py b/main.py index 23bdda3..c34d720 100644 --- a/main.py +++ b/main.py @@ -1,7 +1,7 @@ import os from fastapi import FastAPI, Request, Depends, HTTPException from starlette.middleware.sessions import SessionMiddleware -from starlette.staticfiles import StaticFiles +from starlette.staticfiles import StaticFiles from starlette.responses import FileResponse, RedirectResponse from fastapi.templating import Jinja2Templates from contextlib import asynccontextmanager @@ -63,7 +63,14 @@ async def read_dashboard(request: Request, db: Session = Depends(auth.get_db)): user.settings = models.Setting() db.commit() - return templates.TemplateResponse("dashboard.html", {"request": request, "user": user, "overlay_url": overlay_url, "current_theme": user.settings.overlay_theme, "settings": settings}) + return templates.TemplateResponse("dashboard.html", { + "request": request, + "user": user, + "overlay_url": overlay_url, + "current_theme": user.settings.overlay_theme, + "settings": settings, + "custom_themes": user.custom_themes + }) @app.get("/logout") async def logout(request: Request): @@ -78,13 +85,20 @@ async def read_overlay(request: Request, user_id: int, theme_override: str = Non if not user: raise HTTPException(status_code=404, detail="User not found") - # The theme can be forced by a query parameter for previewing + theme_name = "dark-purple" # Default theme if theme_override: - theme = theme_override - else: - theme = "dark-purple" # Default theme - if user.settings and user.settings.overlay_theme: - theme = user.settings.overlay_theme + theme_name = theme_override + elif user.settings and user.settings.overlay_theme: + theme_name = user.settings.overlay_theme + + # Check if it's a custom theme + if theme_name.startswith("custom-"): + theme_id = int(theme_name.split("-")[1]) + theme = db.query(models.CustomTheme).filter(models.CustomTheme.id == theme_id, models.CustomTheme.owner_id == user.id).first() + if not theme: + raise HTTPException(status_code=404, detail="Custom theme not found") + # Use a generic overlay template that will link to the dynamic CSS + return templates.TemplateResponse("overlay-custom.html", {"request": request, "theme_id": theme.id}) return templates.TemplateResponse(f"overlay-{theme}.html", {"request": request}) @@ -101,4 +115,38 @@ async def update_settings(settings_data: schemas.SettingsUpdate, request: Reques user.settings.overlay_theme = settings_data.overlay_theme db.commit() - return {"message": "Settings updated successfully"} \ No newline at end of file + return {"message": "Settings updated successfully"} + +@app.post("/api/themes", response_model=schemas.CustomTheme) +async def create_theme(theme_data: schemas.CustomThemeCreate, request: Request, db: Session = Depends(auth.get_db)): + user_id = request.session.get('user_id') + if not user_id: + raise HTTPException(status_code=401, detail="Not authenticated") + + new_theme = models.CustomTheme(**theme_data.dict(), owner_id=user_id) + db.add(new_theme) + db.commit() + db.refresh(new_theme) + return new_theme + +@app.delete("/api/themes/{theme_id}") +async def delete_theme(theme_id: int, request: Request, db: Session = Depends(auth.get_db)): + user_id = request.session.get('user_id') + if not user_id: + raise HTTPException(status_code=401, detail="Not authenticated") + + theme = db.query(models.CustomTheme).filter(models.CustomTheme.id == theme_id, models.CustomTheme.owner_id == user_id).first() + if not theme: + raise HTTPException(status_code=404, detail="Theme not found") + + db.delete(theme) + db.commit() + return {"message": "Theme deleted successfully"} + +@app.get("/css/custom/{theme_id}") +async def get_custom_css(theme_id: int, db: Session = Depends(auth.get_db)): + theme = db.query(models.CustomTheme).filter(models.CustomTheme.id == theme_id).first() + if not theme: + raise HTTPException(status_code=404, detail="Custom theme not found") + + return Response(content=theme.css_content, media_type="text/css") \ No newline at end of file diff --git a/static/css/main.css b/static/css/main.css index fd3d09d..03d83c9 100644 --- a/static/css/main.css +++ b/static/css/main.css @@ -228,4 +228,52 @@ picture { .card p { margin-top: 0; color: var(--text-muted-color); +} + +/* Custom Theme Form Styles */ +.theme-form { + margin-top: 2rem; + padding-top: 1.5rem; + border-top: 1px solid var(--border-color); +} + +.form-group { + margin-bottom: 1rem; +} + +.form-group label { + display: block; + margin-bottom: 0.5rem; + font-weight: 500; +} + +.form-group input[type="text"], +.form-group textarea { + width: 100%; + padding: 0.75rem; + border: 1px solid var(--border-color); + background-color: var(--background-color); + color: var(--text-color); + border-radius: 6px; + font-family: inherit; + font-size: 1rem; +} + +.custom-theme-item { + display: flex; + justify-content: space-between; + align-items: center; + padding: 0.75rem; + border-radius: 6px; + margin-bottom: 0.5rem; + background-color: var(--background-color); +} + +.delete-theme-btn { + background-color: #e43f5a; + color: white; + border: none; + padding: 0.3rem 0.8rem; + border-radius: 4px; + cursor: pointer; } \ No newline at end of file diff --git a/static/css/overlay-base.css b/static/css/overlay-base.css new file mode 100644 index 0000000..02d345e --- /dev/null +++ b/static/css/overlay-base.css @@ -0,0 +1,12 @@ +body { + background-color: transparent; + font-family: 'Inter', sans-serif; + font-size: 16px; + margin: 0; + overflow: hidden; +} + +.chat-container { + padding: 10px; + height: 100vh; +} \ No newline at end of file diff --git a/templates/dashboard.html b/templates/dashboard.html index 8937db5..6973777 100644 --- a/templates/dashboard.html +++ b/templates/dashboard.html @@ -28,6 +28,13 @@ + {% if custom_themes %} + + {% for theme in custom_themes %} + + {% endfor %} + + {% endif %}
@@ -37,7 +44,32 @@
-Logout +
+

Custom Themes

+

Create your own themes with CSS. These are private to your account.

+ +
+ {% for theme in custom_themes %} +
+ {{ theme.name }} + +
+ {% endfor %} +
+ +
+

Create New Theme

+
+ + +
+
+ + +
+ +
+