This commit is contained in:
@@ -44,7 +44,7 @@ func (h *JournalHandler) HandleGetEditEntry(w http.ResponseWriter, r *http.Reque
|
|||||||
http.Error(w, "Eintrag nicht gefunden", http.StatusNotFound)
|
http.Error(w, "Eintrag nicht gefunden", http.StatusNotFound)
|
||||||
return
|
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).
|
// HandleUpdateEntry handles POST /entries/{id} (multipart/form-data).
|
||||||
|
|||||||
@@ -13,6 +13,13 @@
|
|||||||
--pico-primary-underline: rgba(0,0,0,.5);
|
--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; }
|
h1 { font-size: 1.4rem; font-weight: normal; letter-spacing: .05em; }
|
||||||
h2 { font-size: 1rem; font-weight: normal; letter-spacing: .05em; }
|
h2 { font-size: 1rem; font-weight: normal; letter-spacing: .05em; }
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,16 @@
|
|||||||
<link rel="stylesheet" href="/static/style.css">
|
<link rel="stylesheet" href="/static/style.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<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 "content" .}}{{end}}
|
||||||
{{block "scripts" .}}{{end}}
|
{{block "scripts" .}}{{end}}
|
||||||
</body>
|
</body>
|
||||||
|
|||||||
@@ -2,13 +2,6 @@
|
|||||||
|
|
||||||
{{define "content"}}
|
{{define "content"}}
|
||||||
<main class="container">
|
<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">
|
<form method="get" action="/days/redirect" class="gps-row">
|
||||||
<input type="date" name="date" id="nav-date" required>
|
<input type="date" name="date" id="nav-date" required>
|
||||||
<button type="submit">Tag öffnen</button>
|
<button type="submit">Tag öffnen</button>
|
||||||
|
|||||||
@@ -2,10 +2,6 @@
|
|||||||
|
|
||||||
{{define "content"}}
|
{{define "content"}}
|
||||||
<main class="container">
|
<main class="container">
|
||||||
<div class="page-header">
|
|
||||||
<span>Journal</span>
|
|
||||||
<a href="/login">Anmelden</a>
|
|
||||||
</div>
|
|
||||||
<div id="feed">
|
<div id="feed">
|
||||||
{{template "feed_items" .}}
|
{{template "feed_items" .}}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -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}
|
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()
|
t, err := tmpls.Clone()
|
||||||
if err == nil {
|
if err == nil {
|
||||||
_, err = t.ParseFS(assets, "templates/"+page)
|
_, err = t.ParseFS(assets, "templates/"+page)
|
||||||
@@ -120,7 +129,7 @@ func renderAdmin(w http.ResponseWriter, page string, data any) {
|
|||||||
// --- Auth ---
|
// --- Auth ---
|
||||||
|
|
||||||
func (ui *WebUI) HandleGetLogin(w http.ResponseWriter, r *http.Request) {
|
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) {
|
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) {
|
if errors.Is(err, auth.ErrInvalidCredentials) {
|
||||||
msg = "Ungültige Zugangsdaten."
|
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
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -171,7 +180,7 @@ func (ui *WebUI) HandleLogout(w http.ResponseWriter, r *http.Request) {
|
|||||||
// --- Register ---
|
// --- Register ---
|
||||||
|
|
||||||
func (ui *WebUI) HandleGetRegister(w http.ResponseWriter, r *http.Request) {
|
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) {
|
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")
|
confirm := r.FormValue("confirm")
|
||||||
|
|
||||||
if username == "" || password == "" {
|
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
|
return
|
||||||
}
|
}
|
||||||
if password != confirm {
|
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
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -197,7 +206,7 @@ func (ui *WebUI) HandlePostRegister(w http.ResponseWriter, r *http.Request) {
|
|||||||
if errors.Is(err, auth.ErrUsernameTaken) {
|
if errors.Is(err, auth.ErrUsernameTaken) {
|
||||||
msg = "Benutzername bereits vergeben."
|
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
|
return
|
||||||
}
|
}
|
||||||
http.Redirect(w, r, "/login", http.StatusSeeOther)
|
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)
|
http.Error(w, "Fehler beim Laden", http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
render(w, "public.html", map[string]any{
|
render(w, r, "public.html", map[string]any{
|
||||||
"Entries": entries,
|
"Entries": entries,
|
||||||
"Offset": 20,
|
"Offset": 20,
|
||||||
"HasMore": len(entries) == 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)
|
http.Error(w, "Fehler beim Laden", http.StatusInternalServerError)
|
||||||
return
|
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) {
|
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
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
render(w, "day.html", map[string]any{
|
render(w, r, "day.html", map[string]any{
|
||||||
"Date": date,
|
"Date": date,
|
||||||
"Points": points,
|
"Points": points,
|
||||||
"Stops": stops,
|
"Stops": stops,
|
||||||
|
|||||||
Reference in New Issue
Block a user