aboutsummaryrefslogtreecommitdiff
path: root/main.go
diff options
context:
space:
mode:
authorRaymaekers Luca <raymaekers.luca@gmail.com>2024-09-28 03:19:04 +0200
committerRaymaekers Luca <raymaekers.luca@gmail.com>2024-09-28 03:27:54 +0200
commit39a847ce13295290e43ef92784fa7fc27a842aa2 (patch)
treedbc190c809664c9759743eb6d80560c759624e8d /main.go
parent5b2097cd2ed016f78ae2c2bcc068dfe3f42e44bd (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.go131
1 files changed, 108 insertions, 23 deletions
diff --git a/main.go b/main.go
index 8d07d58..1077ea9 100644
--- a/main.go
+++ b/main.go
@@ -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")