diff options
author | Raymaekers Luca <raymaekers.luca@gmail.com> | 2024-09-28 03:19:04 +0200 |
---|---|---|
committer | Raymaekers Luca <raymaekers.luca@gmail.com> | 2024-09-28 03:27:54 +0200 |
commit | 39a847ce13295290e43ef92784fa7fc27a842aa2 (patch) | |
tree | dbc190c809664c9759743eb6d80560c759624e8d /main.go | |
parent | 5b2097cd2ed016f78ae2c2bcc068dfe3f42e44bd (diff) |
Added Idea CRD
- Also added sending back errors to the template for displaying what
went wrong.
- Renamed Description to Text
- Added Delete operation for an idea
- Removed Store type because it had no real value
Diffstat (limited to 'main.go')
-rw-r--r-- | main.go | 131 |
1 files changed, 108 insertions, 23 deletions
@@ -10,6 +10,7 @@ import ( "os" "os/signal" "runtime/debug" + "time" ) // File for persistent storage @@ -21,12 +22,12 @@ var Version string // layout for how the date should be output in html var DateLayout string = "02/01/2006 on 15:04" -// template for listing out the ideas, should be bundled inside the executable +// template for /ideas // //go:embed ideas.html var ideas_html string -var data Store +var Ideas []Idea // ToDo's // - [ ] Add a post @@ -41,17 +42,24 @@ var data Store // out of 5 rating of the idea // formatted time string with DateLayout type Idea struct { - Title string - Description string - Author string - CreatedAt string + Title string + Text string + Author string + CreatedAt string + Comment []Comment } -// Data needed through the programm, this data is written to DataFilename for persistent storage -// Is also the format for the Data file -type Store struct { - Version string - Ideas []Idea +// Represents a comment on an idea +type Comment struct { + Text string + Author string + CreatedAt string +} + +// Data passed to the ideas_html template +type PageData struct { + Ideas []Idea + Error string } func GetVersion() string { @@ -65,7 +73,7 @@ func GetVersion() string { func main() { Version = GetVersion() - // Create a .data file in the cache directory and decode eventual ideas from it + // If the .data file does not exist, create it in the cache directory { p := os.Getenv("XDG_CACHE_HOME") // TODO: remove for testing @@ -80,25 +88,33 @@ func main() { log.Fatalln("Error while opening data file:", err) } + // Decode the data and import it into Ideas + dec := gob.NewDecoder(f) - if err := dec.Decode(&data); err != io.EOF && err != nil { - log.Fatalln("Error while decoding ideas:", err) + var v string + if err := dec.Decode(&v); err != io.EOF && err != nil { + log.Fatalln("Error while decoding version:", err) } - log.Println(data) - if data.Version != Version { - log.Fatalf("Version mismatch for datafile@%s != package@%s\n", data.Version, Version) + if v != Version { + log.Fatalf("Version mismatch for datafile@%s != package@%s\n", v, Version) } - log.Printf("Imported @%s: %d ideas\n", data.Version, len(data.Ideas)) + err = dec.Decode(&Ideas) + if err != nil && err != io.EOF { + log.Fatalln("Error while decoding ideas:", err) + } + + log.Printf("Imported @%s: %d ideas\n", v, len(Ideas)) if err := f.Close(); err != nil { log.Fatalln("Error while closing file:", err) } } // Handle SIGINT - // On program exit it should write all its data to the datafile - // TODO: Instead of recreating the file the new ideas should be appended, a way to achieve this would be that every time a new idea is added it is appended to the file, this way there is no need to ensure this. + // Save all Ideas into the data file + // NOTE (Luca): This system might seem dumb, but it only adds overhead at startup + // and exit of the program which is fine. go func() { c := make(chan os.Signal, 1) signal.Notify(c, os.Interrupt) @@ -111,20 +127,89 @@ func main() { defer f.Close() enc := gob.NewEncoder(f) - if err := enc.Encode(data); err != nil { + if err := enc.Encode(Version); err != nil { log.Fatalln(err) } + + if err := enc.Encode(Ideas); err != nil { + log.Fatalln("Error while saving ideas:", err) + } + log.Println("data saved.") os.Exit(0) }() + // Handling http + tmpl, err := template.New("ideas_html").Parse(ideas_html) if err != nil { log.Fatalln(err) } - http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { - tmpl.Execute(w, data) + // TODO (Luca): Make the app more interactive by using websockets instead, + // such that adding, editing or commenting on an idea does not require to + // refresh the page. + // Another approach would be to use htmx? + + http.HandleFunc("/ideas/", func(w http.ResponseWriter, r *http.Request) { + tmpl.Execute(w, PageData{Ideas, ""}) + }) + + http.HandleFunc("/create/", func(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodPost { + http.Redirect(w, r, "/ideas/", http.StatusMovedPermanently) + return + } + i := Idea{ + Title: r.FormValue("title"), + Author: r.FormValue("author"), + CreatedAt: time.Now().Format(DateLayout), + Text: r.FormValue("text"), + } + + for _, v := range Ideas { + if i.Title == v.Title { + tmpl.Execute(w, PageData{Ideas, "An idea with title '" + v.Title + "' already exists!"}) + return + } + } + + Ideas = append(Ideas, i) + log.Println("Added new idea:", i.Title) + http.Redirect(w, r, "/ideas/", http.StatusMovedPermanently) + }) + + http.HandleFunc("/edit/", func(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodPost { + http.Redirect(w, r, "/ideas/", http.StatusMovedPermanently) + return + } + http.Redirect(w, r, "/ideas/", http.StatusMovedPermanently) + }) + + http.HandleFunc("/delete/", func(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodPost { + http.Redirect(w, r, "/ideas/", http.StatusMovedPermanently) + return + } + t := r.FormValue("title") + for i, v := range Ideas { + if t == v.Title { + log.Println("Deleted:", v.Title) + Ideas = append(Ideas[:i], Ideas[i+1:]...) + http.Redirect(w, r, "/ideas/", http.StatusMovedPermanently) + return + } + } + tmpl.Execute(w, PageData{Ideas, "No idea with name '" + t + "'."}) + }) + + http.HandleFunc("/comment/", func(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodPost { + http.Redirect(w, r, "/ideas/", http.StatusMovedPermanently) + return + } + http.Redirect(w, r, "/ideas/", http.StatusMovedPermanently) }) log.Println("Listening on http://localhost:8080") |