ui: single footer with version+hash; summarizer gets navbar and channel dropdown; cookie auth redirect on /summarizer

This commit is contained in:
Thomas Cravey 2025-08-16 20:23:12 -05:00
parent c140b36363
commit 6783f2954d
2 changed files with 5 additions and 37 deletions

2
go.mod
View file

@ -10,6 +10,7 @@ require (
github.com/robfig/cron/v3 v3.0.1 github.com/robfig/cron/v3 v3.0.1
github.com/sashabaranov/go-openai v1.41.1 github.com/sashabaranov/go-openai v1.41.1
github.com/sorcix/irc v1.1.4 github.com/sorcix/irc v1.1.4
golang.org/x/net v0.35.0
modernc.org/sqlite v1.38.2 modernc.org/sqlite v1.38.2
) )
@ -24,7 +25,6 @@ require (
github.com/ncruces/go-strftime v0.1.9 // indirect github.com/ncruces/go-strftime v0.1.9 // indirect
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b // indirect golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b // indirect
golang.org/x/net v0.35.0 // indirect
golang.org/x/sys v0.34.0 // indirect golang.org/x/sys v0.34.0 // indirect
golang.org/x/text v0.22.0 // indirect golang.org/x/text v0.22.0 // indirect
modernc.org/libc v1.66.3 // indirect modernc.org/libc v1.66.3 // indirect

View file

@ -388,54 +388,22 @@ func (s *Server) handleUI(w http.ResponseWriter, r *http.Request) {
</section> </section>
</main> </main>
<footer> <footer>
<small>` + s.Version + `</small> <small>` + s.Version + ` (` + s.Commit + `)</small>
</footer> </footer>
</body> </body>
<footer><small>` + s.Version + ` (` + s.Commit + `)</small></footer>
</html>` </html>`
_, _ = w.Write([]byte(page)) _, _ = w.Write([]byte(page))
} }
func (s *Server) handleSummarizerUI(w http.ResponseWriter, r *http.Request) { func (s *Server) handleSummarizerUI(w http.ResponseWriter, r *http.Request) {
if s.AuthToken != "" { if s.AuthToken != "" {
if !checkAuth(r, s.AuthToken) { if c, err := r.Cookie("auth_token"); err != nil || c.Value != s.AuthToken {
w.WriteHeader(http.StatusUnauthorized) http.Redirect(w, r, "/login", http.StatusFound)
_, _ = w.Write([]byte("unauthorized"))
return return
} }
} }
w.Header().Set("Content-Type", "text/html; charset=utf-8") w.Header().Set("Content-Type", "text/html; charset=utf-8")
page := `<!doctype html> page := `<!doctype html><html><head><meta charset="utf-8"/><meta name="viewport" content="width=device-width, initial-scale=1"/><title>Summarizer · sojuboy</title><link rel="stylesheet" href="https://unpkg.com/@picocss/pico@2/css/pico.min.css"><style>body{padding:0} header.nav{position:sticky;top:0;z-index:10;padding:.6rem 1rem;border-bottom:1px solid var(--muted-border-color);display:flex;justify-content:space-between;align-items:center} header.nav a.brand{text-decoration:none;font-weight:600} main{max-width:900px;margin:0 auto;padding:1rem} footer{text-align:center;font-size:.85rem;padding:.5rem 0;opacity:.7}</style><script>async function api(path,params){const url=new URL(path,window.location.origin);if(params&&params.query){Object.entries(params.query).forEach(([k,v])=>url.searchParams.set(k,v));}const res=await fetch(url);if(!res.ok) throw new Error('HTTP '+res.status);return res.text();}async function summarize(){const ch=document.getElementById('channel').value;const win=document.getElementById('window').value||'6h';const push=document.getElementById('push').checked?'1':'0';const btn=document.getElementById('btn');const out=document.getElementById('out');btn.disabled=true;out.textContent='';try{const txt=await api('/trigger',{query:{channel:ch,window:win}});out.textContent=txt;}catch(e){out.textContent='error: '+e;}btn.disabled=false;}</script></head><body><header class="nav"><div><a class="brand" href="/">sojuboy</a></div><nav><ul><li><a href="/summarizer" aria-current="page">Summarizer</a></li><li><a href="/logout">Logout</a></li></ul></nav></header><main><article><h3>On-demand summarization</h3><label>Channel<select id="channel"></select></label><label>Window<input id="window" value="6h"></label><label><input type="checkbox" id="push"> Send via Pushover</label><button id="btn" onclick="summarize()">Summarize</button><pre id="out"></pre></article></main><footer><small>` + s.Version + ` (` + s.Commit + `)</small></footer><script>(async()=>{try{const res=await fetch('/api/channels');const arr=await res.json();const sel=document.getElementById('channel');arr.forEach(c=>{const o=document.createElement('option');o.value=c;o.textContent=c;sel.appendChild(o);});}catch(e){}})();</script></body></html>`
<html>
<head>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>Summarizer · sojuboy</title>
<link rel="stylesheet" href="https://unpkg.com/@picocss/pico@2/css/pico.min.css">
<style>body{padding:1rem;} main{max-width:480px;margin:auto;margin-top:15vh}</style>
</head>
<body>
<main class="container">
<article>
<h2>Summarizer</h2>
<form id="f" method="post" action="/api/summarize">
<label>Channel
<input type="text" name="channel" id="channel" required placeholder="irc.example.com"/>
</label>
<label>Window
<input type="text" name="window" id="window" value="6h" placeholder="1h, 12h, 24h"/>
</label>
<label>Push to Notifier
<input type="checkbox" name="push" id="push" checked/>
</label>
<button type="submit" id="summBtn">Summarize</button>
</form>
<div id="summary" style="margin-top: 1rem; padding: 1rem; border: 1px solid var(--muted-border-color); border-radius: 0.5rem; background-color: var(--muted-color);"></div>
<progress id="summProg" style="display: none;"></progress>
</article>
</main>
</body>
</html>`
_, _ = w.Write([]byte(page)) _, _ = w.Write([]byte(page))
} }