feat(webui): move channel list into navbar dropdown with checkmark; remove sidebar and footer; show short commit centered in navbar
This commit is contained in:
parent
b70cf17713
commit
6e64969bb6
5 changed files with 22 additions and 10 deletions
|
|
@ -1,10 +1,13 @@
|
||||||
html, body { height: 100%; }
|
html, body { height: 100%; }
|
||||||
body { padding: 0; min-height: 100vh; }
|
body { padding: 0; min-height: 100vh; }
|
||||||
header.nav { position: fixed; top: 0; left: 0; right: 0; z-index: 1000; padding: .6rem 1rem; border-bottom: 1px solid var(--muted-border-color); display: flex; justify-content: space-between; align-items: center; background-color: var(--pico-background-color, #fff); }
|
header.nav { position: fixed; top: 0; left: 0; right: 0; z-index: 1000; padding: .6rem 1rem; border-bottom: 1px solid var(--muted-border-color); display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; background-color: var(--pico-background-color, #fff); }
|
||||||
|
header.nav .brand { justify-self: start; }
|
||||||
|
header.nav .commit { justify-self: center; font-size: .75rem; opacity: .75; }
|
||||||
|
header.nav nav { justify-self: end; }
|
||||||
main, article, .dash { margin-top: var(--headerH, 56px); margin-bottom: var(--footerH, 44px); }
|
main, article, .dash { margin-top: var(--headerH, 56px); margin-bottom: var(--footerH, 44px); }
|
||||||
header.nav a.brand { text-decoration: none; font-weight: 600; }
|
header.nav a.brand { text-decoration: none; font-weight: 600; }
|
||||||
/* Dashboard-only grid layout */
|
/* Dashboard-only grid layout */
|
||||||
.dash { display: grid; grid-template-columns: 220px 1fr; gap: 0; }
|
.dash { display: grid; grid-template-columns: 1fr; gap: 0; }
|
||||||
.dash aside.sidebar { border-right: 1px solid var(--muted-border-color); padding: .75rem; overflow-y: auto; }
|
.dash aside.sidebar { border-right: 1px solid var(--muted-border-color); padding: .75rem; overflow-y: auto; }
|
||||||
.dash aside.sidebar a { display:block; padding:.25rem .5rem; border-radius:.25rem; text-decoration:none; }
|
.dash aside.sidebar a { display:block; padding:.25rem .5rem; border-radius:.25rem; text-decoration:none; }
|
||||||
.dash aside.sidebar a.active { background: var(--muted-color); color: var(--contrast); }
|
.dash aside.sidebar a.active { background: var(--muted-color); color: var(--contrast); }
|
||||||
|
|
|
||||||
|
|
@ -63,7 +63,7 @@ function processLinks(scope){ const links = scope.querySelectorAll('a[href]:not(
|
||||||
}); }
|
}); }
|
||||||
|
|
||||||
async function loadChannels(){ try{ const data = await api('/api/channels'); st.channels = data; renderChannels(); if(data.length>0){ selectChannel(data[0]); } } catch(e){} }
|
async function loadChannels(){ try{ const data = await api('/api/channels'); st.channels = data; renderChannels(); if(data.length>0){ selectChannel(data[0]); } } catch(e){} }
|
||||||
function renderChannels(){ const list=document.getElementById('chanlist'); if(!list) return; list.innerHTML=''; st.channels.forEach(c=>{ const a=document.createElement('a'); a.href='#'; a.textContent=c; a.onclick=(ev)=>{ev.preventDefault(); selectChannel(c)}; if(c===st.current) a.className='active'; list.appendChild(a); }); }
|
function renderChannels(){ const list=document.getElementById('nav-chans'); if(!list) return; list.innerHTML=''; st.channels.forEach(c=>{ const li=document.createElement('li'); const a=document.createElement('a'); a.href='#'; a.textContent=c + (c===st.current? ' ✓':''); a.onclick=(ev)=>{ev.preventDefault(); selectChannel(c);}; li.appendChild(a); list.appendChild(li); }); }
|
||||||
|
|
||||||
async function selectChannel(ch){ if(st.sse){ st.sse.close(); st.sse=null; } st.current=ch; renderChannels(); const el=document.getElementById('tail'); if(!el) return; el.textContent=''; const data = await api('/api/tail',{query:{channel:ch,limit:50}}); appendBatch(data); requestAnimationFrame(()=>{ snapBottom(); st.atBottom=true; }); st.earliest = data.length? data[0].time : null; startStream(); initScrollHandlers(); }
|
async function selectChannel(ch){ if(st.sse){ st.sse.close(); st.sse=null; } st.current=ch; renderChannels(); const el=document.getElementById('tail'); if(!el) return; el.textContent=''; const data = await api('/api/tail',{query:{channel:ch,limit:50}}); appendBatch(data); requestAnimationFrame(()=>{ snapBottom(); st.atBottom=true; }); st.earliest = data.length? data[0].time : null; startStream(); initScrollHandlers(); }
|
||||||
function initScrollHandlers(){ const el=document.getElementById('tail'); if(!el) return; const onScroll = async ()=>{ const nearBottom = (window.innerHeight + window.pageYOffset + 16) >= document.documentElement.scrollHeight; st.atBottom = nearBottom; const nearTop = window.pageYOffset <= 4; if(nearTop && st.earliest){ try{ const older = await api('/api/history',{query:{channel:st.current,before:st.earliest,limit:50}}); if(older.length){ prependBatch(older); st.earliest = older[0].time; } } catch(e){} } }; window.removeEventListener('scroll', st._scrollHandler || (()=>{})); st._scrollHandler = onScroll; window.addEventListener('scroll', onScroll, {passive:true}); }
|
function initScrollHandlers(){ const el=document.getElementById('tail'); if(!el) return; const onScroll = async ()=>{ const nearBottom = (window.innerHeight + window.pageYOffset + 16) >= document.documentElement.scrollHeight; st.atBottom = nearBottom; const nearTop = window.pageYOffset <= 4; if(nearTop && st.earliest){ try{ const older = await api('/api/history',{query:{channel:st.current,before:st.earliest,limit:50}}); if(older.length){ prependBatch(older); st.earliest = older[0].time; } } catch(e){} } }; window.removeEventListener('scroll', st._scrollHandler || (()=>{})); st._scrollHandler = onScroll; window.addEventListener('scroll', onScroll, {passive:true}); }
|
||||||
|
|
@ -75,7 +75,7 @@ async function summarize(){ const ch=document.getElementById('channel'); const w
|
||||||
window.addEventListener('DOMContentLoaded', ()=>{
|
window.addEventListener('DOMContentLoaded', ()=>{
|
||||||
if('scrollRestoration' in history){ history.scrollRestoration = 'manual'; }
|
if('scrollRestoration' in history){ history.scrollRestoration = 'manual'; }
|
||||||
measureBars();
|
measureBars();
|
||||||
if(document.getElementById('chanlist')){ loadChannels(); }
|
loadChannels();
|
||||||
if(document.getElementById('channel')){
|
if(document.getElementById('channel')){
|
||||||
fetch('/api/channels').then(r=>r.json()).then(arr=>{ const sel=document.getElementById('channel'); arr.forEach(c=>{ const o=document.createElement('option'); o.value=c; o.textContent=c; sel.appendChild(o); }); }).catch(()=>{});
|
fetch('/api/channels').then(r=>r.json()).then(arr=>{ const sel=document.getElementById('channel'); arr.forEach(c=>{ const o=document.createElement('option'); o.value=c; o.textContent=c; sel.appendChild(o); }); }).catch(()=>{});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,11 @@ func (s *Server) render(w http.ResponseWriter, name string, data map[string]any)
|
||||||
}
|
}
|
||||||
data["Version"] = s.Version
|
data["Version"] = s.Version
|
||||||
data["Commit"] = s.Commit
|
data["Commit"] = s.Commit
|
||||||
|
if s.Commit != "" {
|
||||||
|
c := s.Commit
|
||||||
|
if len(c) > 12 { c = c[:12] }
|
||||||
|
data["CommitShort"] = c
|
||||||
|
}
|
||||||
base := strings.TrimSuffix(path.Base(name), path.Ext(name))
|
base := strings.TrimSuffix(path.Base(name), path.Ext(name))
|
||||||
if base == "dashboard" {
|
if base == "dashboard" {
|
||||||
data["Title"] = "sojuboy"
|
data["Title"] = "sojuboy"
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,6 @@
|
||||||
{{ define "dashboard" }}
|
{{ define "dashboard" }}
|
||||||
<main class="dash">
|
<main class="dash single">
|
||||||
<aside class="sidebar">
|
<section class="chat" style="grid-column: 1 / -1">
|
||||||
<nav id="chanlist"></nav>
|
|
||||||
</aside>
|
|
||||||
<section class="chat">
|
|
||||||
<div id="tail"></div>
|
<div id="tail"></div>
|
||||||
</section>
|
</section>
|
||||||
</main>
|
</main>
|
||||||
|
|
|
||||||
|
|
@ -12,8 +12,15 @@
|
||||||
<body>
|
<body>
|
||||||
<header class="nav">
|
<header class="nav">
|
||||||
<div><a class="brand" href="/">sojuboy</a></div>
|
<div><a class="brand" href="/">sojuboy</a></div>
|
||||||
|
<div class="commit">{{ .CommitShort }}</div>
|
||||||
<nav>
|
<nav>
|
||||||
<ul>
|
<ul>
|
||||||
|
<li class="chan">
|
||||||
|
<details role="list">
|
||||||
|
<summary aria-haspopup="listbox">Channel</summary>
|
||||||
|
<ul id="nav-chans" role="listbox"></ul>
|
||||||
|
</details>
|
||||||
|
</li>
|
||||||
<li><a href="/summarizer">Summarizer</a></li>
|
<li><a href="/summarizer">Summarizer</a></li>
|
||||||
<li><a href="/logout">Logout</a></li>
|
<li><a href="/logout">Logout</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
@ -24,7 +31,7 @@
|
||||||
{{ else if eq .Content "summarizer" }}
|
{{ else if eq .Content "summarizer" }}
|
||||||
{{ template "summarizer" . }}
|
{{ template "summarizer" . }}
|
||||||
{{ end }}
|
{{ end }}
|
||||||
<footer><small>{{ .Version }} ({{ .Commit }})</small></footer>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
{{ end }}
|
{{ end }}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue