Integrate notes into front end

This commit is contained in:
Andrew-71 2024-03-30 14:22:03 +03:00
parent 02e1c80c24
commit cbdb94a260
5 changed files with 97 additions and 15 deletions

8
api.go
View file

@ -86,8 +86,8 @@ func PostTodayApi(w http.ResponseWriter, r *http.Request) {
PostFile("day/"+time.Now().Format(time.DateOnly), w, r) PostFile("day/"+time.Now().Format(time.DateOnly), w, r)
} }
// GetNote returns contents of a note specified in URL // GetNoteApi returns contents of a note specified in URL
func GetNote(w http.ResponseWriter, r *http.Request) { func GetNoteApi(w http.ResponseWriter, r *http.Request) {
noteString := chi.URLParam(r, "note") noteString := chi.URLParam(r, "note")
if noteString == "" { if noteString == "" {
w.WriteHeader(http.StatusBadRequest) w.WriteHeader(http.StatusBadRequest)
@ -97,8 +97,8 @@ func GetNote(w http.ResponseWriter, r *http.Request) {
GetFile("notes/"+noteString, w) GetFile("notes/"+noteString, w)
} }
// PostNote writes request's body contents to a note specified in URL // PostNoteApi writes request's body contents to a note specified in URL
func PostNote(w http.ResponseWriter, r *http.Request) { func PostNoteApi(w http.ResponseWriter, r *http.Request) {
noteString := chi.URLParam(r, "note") noteString := chi.URLParam(r, "note")
if noteString == "" { if noteString == "" {
w.WriteHeader(http.StatusBadRequest) w.WriteHeader(http.StatusBadRequest)

View file

@ -29,6 +29,6 @@
{{define "footer"}} {{define "footer"}}
<footer> <footer>
<p><a href="/">today</a> | <a href="/day">previous days</a></p> <p><a href="/">today</a> | <a href="/day">previous days</a> | <a href="/notes">notes</a></p>
</footer> </footer>
{{end}} {{end}}

View file

@ -1,4 +1,4 @@
{{define "main"}} {{define "main"}}
<h2><label for="text">{{ .Title }}</label> | <a href="/day">Go back</a></h2> <h2><label for="text">{{ .Title }}</label></h2>
<textarea id="text" cols="40" rows="15" readonly>{{ .Content }}</textarea> <textarea id="text" cols="40" rows="15" readonly>{{ .Content }}</textarea>
{{end}} {{end}}

View file

@ -7,6 +7,7 @@ import (
"log/slog" "log/slog"
"net/http" "net/http"
"os" "os"
"strings"
"time" "time"
) )
@ -33,7 +34,7 @@ func InternalError(w http.ResponseWriter, r *http.Request) {
http.ServeFile(w, r, "./pages/error/500.html") http.ServeFile(w, r, "./pages/error/500.html")
} }
// GetToday renders HTML page for today's view // GetToday renders HTML page for today's entry
func GetToday(w http.ResponseWriter, r *http.Request) { func GetToday(w http.ResponseWriter, r *http.Request) {
day, err := ReadToday() day, err := ReadToday()
if err != nil { if err != nil {
@ -69,16 +70,16 @@ 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 page for list of previous days // GetDays renders HTML list of previous days' entries
func GetDays(w http.ResponseWriter, r *http.Request) { func GetDays(w http.ResponseWriter, r *http.Request) {
day, err := ListFiles("day") day, err := ListFiles("day")
if err != nil { if err != nil {
slog.Error("error reading today's file", "error", err) slog.Error("error reading file list", "directory", "day", "error", err)
InternalError(w, r) InternalError(w, r)
return return
} }
var daysFormatted []Entry var daysFormatted []Entry
for i, _ := range day { for i := range day {
v := day[len(day)-1-i] // This is suboptimal, but reverse order is better here v := day[len(day)-1-i] // This is suboptimal, but reverse order is better here
dayString := v dayString := v
t, err := time.Parse(time.DateOnly, v) t, err := time.Parse(time.DateOnly, v)
@ -94,20 +95,20 @@ func GetDays(w http.ResponseWriter, r *http.Request) {
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...)
if err != nil { if err != nil {
slog.Error("Error parsing template files", "error", err) slog.Error("error parsing template files", "error", err)
InternalError(w, r) InternalError(w, r)
return return
} }
err = ts.ExecuteTemplate(w, "base", EntryList{Title: "Previous days", Entries: daysFormatted}) err = ts.ExecuteTemplate(w, "base", EntryList{Title: "Previous days", Entries: daysFormatted})
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)
return return
} }
} }
// GetDay renders HTML page for a specific day // 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")
if dayString == "" { if dayString == "" {
@ -144,3 +145,81 @@ func GetDay(w http.ResponseWriter, r *http.Request) {
return return
} }
} }
// 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
func GetNote(w http.ResponseWriter, r *http.Request) {
noteString := chi.URLParam(r, "note")
if noteString == "" {
w.WriteHeader(http.StatusBadRequest)
HandleWrite(w.Write([]byte("note not specified")))
return
}
note, err := ReadFile("notes/" + noteString)
if err != nil {
if errors.Is(err, os.ErrNotExist) {
note = []byte("")
} else {
slog.Error("error reading note's file", "error", err)
InternalError(w, r)
return
}
}
files := []string{"./pages/base.html", "./pages/edit.html"}
ts, err := template.ParseFiles(files...)
if err != nil {
InternalError(w, r)
return
}
err = ts.ExecuteTemplate(w, "base", Entry{Title: noteString, Content: string(note)})
if err != nil {
InternalError(w, r)
return
}
}
// PostNote saves a note form and redirects back to GET
func PostNote(w http.ResponseWriter, r *http.Request) {
noteString := chi.URLParam(r, "note")
if noteString == "" {
w.WriteHeader(http.StatusBadRequest)
HandleWrite(w.Write([]byte("note not specified")))
return
}
err := SaveFile("notes/"+noteString, []byte(r.FormValue("text")))
if err != nil {
slog.Error("error saving a note", "note", noteString, "error", err)
}
http.Redirect(w, r, r.Header.Get("Referer"), 302)
}

View file

@ -21,6 +21,9 @@ func Serve() {
r.Post("/", PostToday) r.Post("/", PostToday)
r.Get("/day", GetDays) r.Get("/day", GetDays)
r.Get("/day/{day}", GetDay) r.Get("/day/{day}", GetDay)
r.Get("/notes", GetNotes)
r.Get("/notes/{note}", GetNote)
r.Post("/notes/{note}", PostNote)
// API ============= // API =============
apiRouter := chi.NewRouter() apiRouter := chi.NewRouter()
@ -29,8 +32,8 @@ func Serve() {
apiRouter.Get("/day", func(w http.ResponseWriter, r *http.Request) { GetFileList("day", w) }) apiRouter.Get("/day", func(w http.ResponseWriter, r *http.Request) { GetFileList("day", w) })
apiRouter.Get("/day/{day}", GetDayApi) apiRouter.Get("/day/{day}", GetDayApi)
apiRouter.Get("/notes", func(w http.ResponseWriter, r *http.Request) { GetFileList("notes", w) }) apiRouter.Get("/notes", func(w http.ResponseWriter, r *http.Request) { GetFileList("notes", w) })
apiRouter.Get("/notes/{note}", GetNote) apiRouter.Get("/notes/{note}", GetNoteApi)
apiRouter.Post("/notes/{note}", PostNote) apiRouter.Post("/notes/{note}", PostNoteApi)
apiRouter.Get("/today", GetTodayApi) apiRouter.Get("/today", GetTodayApi)
apiRouter.Post("/today", PostTodayApi) apiRouter.Post("/today", PostTodayApi)
apiRouter.Get("/export", GetExport) apiRouter.Get("/export", GetExport)