diff --git a/manager/main.py b/manager/main.py index fdecb1d..58d4459 100644 --- a/manager/main.py +++ b/manager/main.py @@ -144,6 +144,20 @@ async def bots_page(request: Request): }) +RELAY_KINDS = {"chat": "Chat relay", "file": "File relay", "message": "Message relay"} + + +@app.get("/relays/{kind}", response_class=HTMLResponse) +async def relay_page(request: Request, kind: str): + if redir := _redirect_if_unauth(request): + return redir + if kind not in RELAY_KINDS: + raise HTTPException(status_code=404, detail="Unknown relay") + return TEMPLATES.TemplateResponse(request, "relay.html", { + "nav_active": "relays", "kind": kind, "title": RELAY_KINDS[kind], + }) + + @app.get("/settings", response_class=HTMLResponse) async def settings_page(request: Request): if redir := _redirect_if_unauth(request): diff --git a/manager/templates/base.html b/manager/templates/base.html index 55c6462..a7a7c80 100644 --- a/manager/templates/base.html +++ b/manager/templates/base.html @@ -129,6 +129,23 @@ .side-nav .ico { width: 20px; text-align: center; font-size: 16px; flex-shrink: 0; } .side-nav a.nav-sep { margin-top: 10px; padding-top: 17px; border-top: 1px solid var(--border); } + /* collapsible nav group (e.g. Relays) */ + .nav-group-toggle { + display: flex; align-items: center; gap: 12px; width: 100%; + padding: 11px 18px; background: none; border: none; border-left: 3px solid transparent; + color: var(--muted); font-family: inherit; font-size: 14px; font-weight: 600; + white-space: nowrap; overflow: hidden; cursor: pointer; text-align: left; + } + .nav-group-toggle:hover { color: var(--text); background: var(--bg); } + .nav-group-toggle .ico { width: 20px; text-align: center; font-size: 16px; flex-shrink: 0; } + .nav-group-toggle .caret { margin-left: auto; font-size: 10px; transition: transform 0.15s; } + .nav-group.open .nav-group-toggle .caret { transform: rotate(90deg); } + .nav-sub { display: none; } + .nav-group.open .nav-sub { display: block; } + .nav-sub a { padding-left: 44px; font-size: 13px; } + html.collapsed .nav-group-toggle .caret { display: none; } + html.collapsed .nav-sub { display: none !important; } + .side-foot { margin-top: auto; padding: 8px 0; border-top: 1px solid var(--border); } .side-status { padding: 10px 18px 12px; font-size: 12px; color: var(--muted); @@ -274,6 +291,16 @@ π€Users πΌBusinesses π€Bots +
πFile upload πNotifications βοΈSettings @@ -324,6 +351,18 @@ if (ico && document.documentElement.classList.contains('collapsed')) ico.textContent = 'βΊ'; })(); + // Collapsible sidebar groups (e.g. Relays) β persist open state + function toggleNavGroup(id) { + const g = document.getElementById('nav-' + id); + if (!g) return; + const open = g.classList.toggle('open'); + localStorage.setItem('navgroup-' + id, open ? '1' : ''); + } + (function(){ + const g = document.getElementById('nav-relays'); + if (g && localStorage.getItem('navgroup-relays')) g.classList.add('open'); + })(); + // Poll for unread notifications and update the sidebar badge async function pollNotifications() { try { diff --git a/manager/templates/home.html b/manager/templates/home.html index 582a145..1a0c01c 100644 --- a/manager/templates/home.html +++ b/manager/templates/home.html @@ -8,7 +8,8 @@ .home-head p { color: var(--muted); font-size: 14px; } .tiles { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 16px; } - .tiles + .tiles { margin-top: 32px; } /* vertical buffer between areas */ + /* faded bar between areas, like the sidebar separators */ + .tiles + .tiles { margin-top: 28px; padding-top: 28px; border-top: 1px solid var(--border); } .tile { display: flex; flex-direction: column; gap: 8px; background: var(--card); border: 1px solid var(--border); border-radius: 12px; @@ -58,6 +59,25 @@ + +This relay isnβt implemented yet.
+