menu added
All checks were successful
Deploy to NAS / deploy (push) Successful in 1m47s

This commit is contained in:
Christoph K.
2026-04-09 22:28:02 +02:00
parent b73d91ccaa
commit 8eef933573
6 changed files with 37 additions and 22 deletions

View File

@@ -44,7 +44,7 @@ func (h *JournalHandler) HandleGetEditEntry(w http.ResponseWriter, r *http.Reque
http.Error(w, "Eintrag nicht gefunden", http.StatusNotFound)
return
}
render(w, "edit_entry.html", map[string]any{"Entry": entry})
render(w, r, "edit_entry.html", map[string]any{"Entry": entry})
}
// HandleUpdateEntry handles POST /entries/{id} (multipart/form-data).

View File

@@ -13,6 +13,13 @@
--pico-primary-underline: rgba(0,0,0,.5);
}
/* Site nav */
.site-nav { display: flex; gap: 1.5rem; align-items: baseline; padding: .7rem 0; margin-bottom: 1.5rem; border-bottom: 1px solid var(--pico-muted-border-color); }
.site-nav a { font-size: .85rem; text-decoration: none; }
.site-nav a:hover { text-decoration: underline; }
.nav-btn { background: none; border: none; color: var(--pico-primary); padding: 0; cursor: pointer; font-family: inherit; font-size: .85rem; margin: 0; }
.site-nav form { margin: 0; padding: 0; }
h1 { font-size: 1.4rem; font-weight: normal; letter-spacing: .05em; }
h2 { font-size: 1rem; font-weight: normal; letter-spacing: .05em; }

View File

@@ -8,6 +8,16 @@
<link rel="stylesheet" href="/static/style.css">
</head>
<body>
<nav class="site-nav container">
<a href="/">Journal</a>
{{if .LoggedIn}}
<a href="/days">Tage</a>
{{if .IsAdmin}}<a href="/admin">Admin</a>{{end}}
<form method="post" action="/logout"><button type="submit" class="nav-btn">Ausloggen</button></form>
{{else}}
<a href="/login">Anmelden</a>
{{end}}
</nav>
{{block "content" .}}{{end}}
{{block "scripts" .}}{{end}}
</body>

View File

@@ -2,13 +2,6 @@
{{define "content"}}
<main class="container">
<div class="page-header">
<h1>REISEJOURNAL</h1>
<span>
{{if .IsAdmin}}<a href="/admin">[ Admin ]</a> · {{end}}
<a href="/logout">[ Ausloggen ]</a>
</span>
</div>
<form method="get" action="/days/redirect" class="gps-row">
<input type="date" name="date" id="nav-date" required>
<button type="submit">Tag öffnen</button>

View File

@@ -2,10 +2,6 @@
{{define "content"}}
<main class="container">
<div class="page-header">
<span>Journal</span>
<a href="/login">Anmelden</a>
</div>
<div id="feed">
{{template "feed_items" .}}
</div>

View File

@@ -56,7 +56,16 @@ func NewWebUI(a *auth.Store, tp *db.TrackpointStore, st *db.StopStore, j *db.Jou
return &WebUI{authStore: a, tpStore: tp, stopStore: st, journalStore: j, userStore: u}
}
func render(w http.ResponseWriter, page string, data any) {
func injectNav(r *http.Request, data map[string]any) {
user := userFromContext(r.Context())
if user.UserID != "" {
data["LoggedIn"] = true
data["IsAdmin"] = user.IsAdmin
}
}
func render(w http.ResponseWriter, r *http.Request, page string, data map[string]any) {
injectNav(r, data)
t, err := tmpls.Clone()
if err == nil {
_, err = t.ParseFS(assets, "templates/"+page)
@@ -120,7 +129,7 @@ func renderAdmin(w http.ResponseWriter, page string, data any) {
// --- Auth ---
func (ui *WebUI) HandleGetLogin(w http.ResponseWriter, r *http.Request) {
render(w, "login.html", map[string]any{"Error": "", "Username": ""})
render(w, r, "login.html", map[string]any{"Error": "", "Username": ""})
}
func (ui *WebUI) HandlePostLogin(w http.ResponseWriter, r *http.Request) {
@@ -137,7 +146,7 @@ func (ui *WebUI) HandlePostLogin(w http.ResponseWriter, r *http.Request) {
if errors.Is(err, auth.ErrInvalidCredentials) {
msg = "Ungültige Zugangsdaten."
}
render(w, "login.html", map[string]any{"Error": msg, "Username": username})
render(w, r, "login.html", map[string]any{"Error": msg, "Username": username})
return
}
@@ -171,7 +180,7 @@ func (ui *WebUI) HandleLogout(w http.ResponseWriter, r *http.Request) {
// --- Register ---
func (ui *WebUI) HandleGetRegister(w http.ResponseWriter, r *http.Request) {
render(w, "register.html", map[string]any{"Error": "", "Username": ""})
render(w, r, "register.html", map[string]any{"Error": "", "Username": ""})
}
func (ui *WebUI) HandlePostRegister(w http.ResponseWriter, r *http.Request) {
@@ -184,11 +193,11 @@ func (ui *WebUI) HandlePostRegister(w http.ResponseWriter, r *http.Request) {
confirm := r.FormValue("confirm")
if username == "" || password == "" {
render(w, "register.html", map[string]any{"Error": "Benutzername und Passwort sind Pflichtfelder.", "Username": username})
render(w, r, "register.html", map[string]any{"Error": "Benutzername und Passwort sind Pflichtfelder.", "Username": username})
return
}
if password != confirm {
render(w, "register.html", map[string]any{"Error": "Passwörter stimmen nicht überein.", "Username": username})
render(w, r, "register.html", map[string]any{"Error": "Passwörter stimmen nicht überein.", "Username": username})
return
}
@@ -197,7 +206,7 @@ func (ui *WebUI) HandlePostRegister(w http.ResponseWriter, r *http.Request) {
if errors.Is(err, auth.ErrUsernameTaken) {
msg = "Benutzername bereits vergeben."
}
render(w, "register.html", map[string]any{"Error": msg, "Username": username})
render(w, r, "register.html", map[string]any{"Error": msg, "Username": username})
return
}
http.Redirect(w, r, "/login", http.StatusSeeOther)
@@ -211,7 +220,7 @@ func (ui *WebUI) HandleFeed(w http.ResponseWriter, r *http.Request) {
http.Error(w, "Fehler beim Laden", http.StatusInternalServerError)
return
}
render(w, "public.html", map[string]any{
render(w, r, "public.html", map[string]any{
"Entries": entries,
"Offset": 20,
"HasMore": len(entries) == 20,
@@ -260,7 +269,7 @@ func (ui *WebUI) HandleDaysList(w http.ResponseWriter, r *http.Request) {
http.Error(w, "Fehler beim Laden", http.StatusInternalServerError)
return
}
render(w, "days.html", map[string]any{"Days": days, "IsAdmin": user.IsAdmin})
render(w, r, "days.html", map[string]any{"Days": days})
}
func (ui *WebUI) HandleDayDetail(w http.ResponseWriter, r *http.Request) {
@@ -288,7 +297,7 @@ func (ui *WebUI) HandleDayDetail(w http.ResponseWriter, r *http.Request) {
return
}
render(w, "day.html", map[string]any{
render(w, r, "day.html", map[string]any{
"Date": date,
"Points": points,
"Stops": stops,