Improve list pages' backend
This commit is contained in:
parent
40c56822e5
commit
ab4cccee18
4 changed files with 53 additions and 56 deletions
7
TODO.md
7
TODO.md
|
@ -2,9 +2,10 @@
|
||||||
List of things to add to this project
|
List of things to add to this project
|
||||||
|
|
||||||
* Improve config and use reflection when loading it
|
* Improve config and use reflection when loading it
|
||||||
|
* Do to other methods what was done to GetDays/GetNotes?
|
||||||
|
* API revamp
|
||||||
* Check export function for improvements
|
* Check export function for improvements
|
||||||
* Add notes to frontend?
|
* Add note creation and deletion to frontend
|
||||||
* More slog.Debug and a debug flag?
|
* More slog.Debug and a debug flag?
|
||||||
* Think about timezones
|
* Consider less clunky auth method
|
||||||
* Consider more secure auth methods
|
|
||||||
* *Go* dependency-less? <-- this is a terrible idea
|
* *Go* dependency-less? <-- this is a terrible idea
|
|
@ -1,5 +1,6 @@
|
||||||
{{define "main"}}
|
{{define "main"}}
|
||||||
<h2>{{.Title}}</h2>
|
<h2 class="list-title">{{.Title}}</h2>
|
||||||
|
<p class="list-desc">{{.Description}}</p>
|
||||||
<ul>
|
<ul>
|
||||||
{{range .Entries}}
|
{{range .Entries}}
|
||||||
<li><a href="/{{.Link}}">{{.Title}}</a></li>
|
<li><a href="/{{.Link}}">{{.Title}}</a></li>
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
body {
|
body {
|
||||||
color: #454545;
|
color: #454545;
|
||||||
background-color: #f5f0e1;
|
background-color: #f5f0e1;
|
||||||
font-size: 16px;
|
|
||||||
margin: 2em auto;
|
margin: 2em auto;
|
||||||
max-width: 640px;
|
max-width: 640px;
|
||||||
padding: 1em;
|
padding: 1em;
|
||||||
|
@ -12,10 +11,13 @@ body {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
h2 { margin-bottom:12px; }
|
|
||||||
a, a:visited { color: #f85552; }
|
a, a:visited { color: #f85552; }
|
||||||
a:hover, a:visited:hover { color: #e66868; }
|
a:hover, a:visited:hover { color: #e66868; }
|
||||||
|
|
||||||
|
h2 { margin-bottom:12px; }
|
||||||
|
.list-title { margin-bottom: 0}
|
||||||
|
.list-desc { margin-top: 0 }
|
||||||
|
|
||||||
textarea, input {
|
textarea, input {
|
||||||
background: #f5f2ee;
|
background: #f5f2ee;
|
||||||
max-width: 640px;
|
max-width: 640px;
|
||||||
|
|
89
routes.go
89
routes.go
|
@ -13,6 +13,7 @@ import (
|
||||||
|
|
||||||
type EntryList struct {
|
type EntryList struct {
|
||||||
Title string
|
Title string
|
||||||
|
Description string
|
||||||
Entries []Entry
|
Entries []Entry
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,6 +23,8 @@ type Entry struct {
|
||||||
Link string
|
Link string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type formatEntries func([]string) []Entry
|
||||||
|
|
||||||
// NotFound returns a user-friendly 404 error page
|
// NotFound returns a user-friendly 404 error page
|
||||||
func NotFound(w http.ResponseWriter, r *http.Request) {
|
func NotFound(w http.ResponseWriter, r *http.Request) {
|
||||||
w.WriteHeader(404)
|
w.WriteHeader(404)
|
||||||
|
@ -70,27 +73,15 @@ func PostToday(w http.ResponseWriter, r *http.Request) {
|
||||||
http.Redirect(w, r, r.Header.Get("Referer"), 302)
|
http.Redirect(w, r, r.Header.Get("Referer"), 302)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetDays renders HTML list of previous days' entries
|
// GetEntries is a generic HTML renderer for a list
|
||||||
func GetDays(w http.ResponseWriter, r *http.Request) {
|
func GetEntries(w http.ResponseWriter, r *http.Request, title string, description string, dir string, format formatEntries) {
|
||||||
day, err := ListFiles("day")
|
filesList, err := ListFiles(dir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
slog.Error("error reading file list", "directory", "day", "error", err)
|
slog.Error("error reading file list", "directory", dir, "error", err)
|
||||||
InternalError(w, r)
|
InternalError(w, r)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
var daysFormatted []Entry
|
var filesFormatted = format(filesList)
|
||||||
for i := range day {
|
|
||||||
v := day[len(day)-1-i] // This is suboptimal, but reverse order is better here
|
|
||||||
dayString := v
|
|
||||||
t, err := time.Parse(time.DateOnly, v)
|
|
||||||
if err == nil {
|
|
||||||
dayString = t.Format("02 Jan 2006")
|
|
||||||
}
|
|
||||||
if v == time.Now().Format(time.DateOnly) {
|
|
||||||
dayString = "Today"
|
|
||||||
}
|
|
||||||
daysFormatted = append(daysFormatted, Entry{Title: dayString, Link: "day/" + v})
|
|
||||||
}
|
|
||||||
|
|
||||||
files := []string{"./pages/base.html", "./pages/list.html"}
|
files := []string{"./pages/base.html", "./pages/list.html"}
|
||||||
ts, err := template.ParseFiles(files...)
|
ts, err := template.ParseFiles(files...)
|
||||||
|
@ -100,7 +91,7 @@ func GetDays(w http.ResponseWriter, r *http.Request) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
err = ts.ExecuteTemplate(w, "base", EntryList{Title: "Previous days", Entries: daysFormatted})
|
err = ts.ExecuteTemplate(w, "base", EntryList{Title: title, Description: description, Entries: filesFormatted})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
slog.Error("error executing template", "error", err)
|
slog.Error("error executing template", "error", err)
|
||||||
InternalError(w, r)
|
InternalError(w, r)
|
||||||
|
@ -108,6 +99,38 @@ func GetDays(w http.ResponseWriter, r *http.Request) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetDays renders HTML list of previous days' entries
|
||||||
|
func GetDays(w http.ResponseWriter, r *http.Request) {
|
||||||
|
GetEntries(w, r, "Previous days", "", "day", func(files []string) []Entry {
|
||||||
|
var filesFormatted []Entry
|
||||||
|
for i := range files {
|
||||||
|
v := files[len(files)-1-i] // This is suboptimal, but reverse order is better here
|
||||||
|
dayString := v
|
||||||
|
t, err := time.Parse(time.DateOnly, v)
|
||||||
|
if err == nil {
|
||||||
|
dayString = t.Format("02 Jan 2006")
|
||||||
|
}
|
||||||
|
if v == time.Now().Format(time.DateOnly) {
|
||||||
|
dayString = "Today"
|
||||||
|
}
|
||||||
|
filesFormatted = append(filesFormatted, Entry{Title: dayString, Link: "day/" + v})
|
||||||
|
}
|
||||||
|
return filesFormatted
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetNotes renders HTML list of all notes
|
||||||
|
func GetNotes(w http.ResponseWriter, r *http.Request) {
|
||||||
|
GetEntries(w, r, "Notes", "/notes/<name> for a new note", "notes", func(files []string) []Entry {
|
||||||
|
var filesFormatted []Entry
|
||||||
|
for _, v := range files {
|
||||||
|
titleString := strings.Replace(v, "-", " ", -1) // FIXME: what if I need a hyphen?
|
||||||
|
filesFormatted = append(filesFormatted, Entry{Title: titleString, Link: "notes/" + v})
|
||||||
|
}
|
||||||
|
return filesFormatted
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// GetDay renders HTML page for a specific day entry
|
// GetDay renders HTML page for a specific day entry
|
||||||
func GetDay(w http.ResponseWriter, r *http.Request) {
|
func GetDay(w http.ResponseWriter, r *http.Request) {
|
||||||
dayString := chi.URLParam(r, "day")
|
dayString := chi.URLParam(r, "day")
|
||||||
|
@ -146,36 +169,6 @@ func GetDay(w http.ResponseWriter, r *http.Request) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetNotes renders HTML list of all notes
|
|
||||||
func GetNotes(w http.ResponseWriter, r *http.Request) {
|
|
||||||
notes, err := ListFiles("notes")
|
|
||||||
if err != nil {
|
|
||||||
slog.Error("error reading file list", "directory", "notes", "error", err)
|
|
||||||
InternalError(w, r)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
var notesFormatted []Entry
|
|
||||||
for _, v := range notes {
|
|
||||||
titleString := strings.Replace(v, "-", " ", -1) // FIXME: what if I need a hyphen?
|
|
||||||
notesFormatted = append(notesFormatted, Entry{Title: titleString, Link: "notes/" + v})
|
|
||||||
}
|
|
||||||
|
|
||||||
files := []string{"./pages/base.html", "./pages/list.html"}
|
|
||||||
ts, err := template.ParseFiles(files...)
|
|
||||||
if err != nil {
|
|
||||||
slog.Error("error parsing template files", "error", err)
|
|
||||||
InternalError(w, r)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
err = ts.ExecuteTemplate(w, "base", EntryList{Title: "Notes", Entries: notesFormatted})
|
|
||||||
if err != nil {
|
|
||||||
slog.Error("error executing template", "error", err)
|
|
||||||
InternalError(w, r)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetNote renders HTML page for a note
|
// GetNote renders HTML page for a note
|
||||||
func GetNote(w http.ResponseWriter, r *http.Request) {
|
func GetNote(w http.ResponseWriter, r *http.Request) {
|
||||||
noteString := chi.URLParam(r, "note")
|
noteString := chi.URLParam(r, "note")
|
||||||
|
|
Loading…
Reference in a new issue