From e92d0f2c265b7c0050eff4f493f475c7528ca886 Mon Sep 17 00:00:00 2001
From: DutchEllie
Date: Wed, 2 Mar 2022 13:38:28 +0100
Subject: [PATCH] So many things
---
comments.go | 73 +++++++++++++++++++++++++
components/aboutpage.go | 22 +++++++-
components/guestbookform.go | 58 ++++++++++++++++++++
components/guestbookpanel.go | 93 ++++++++++++++++++++++++++++++++
components/homepage.go | 43 +++++++++++++--
components/homepanel.go | 8 ++-
components/updater.go | 27 ++++++++++
entity/comment.go | 12 +++++
go.mod | 19 ++++++-
go.sum | 49 +++++++++++++++++
main.go | 38 +++++++++++++
web/static/images/rin-1.gif | Bin 0 -> 482670 bytes
web/static/pages/aboutpage.html | 14 +++++
web/static/style.css | 7 +++
14 files changed, 453 insertions(+), 10 deletions(-)
create mode 100644 comments.go
create mode 100644 components/guestbookform.go
create mode 100644 components/guestbookpanel.go
create mode 100644 components/updater.go
create mode 100644 entity/comment.go
create mode 100644 web/static/images/rin-1.gif
create mode 100644 web/static/pages/aboutpage.html
diff --git a/comments.go b/comments.go
new file mode 100644
index 0000000..4f128ab
--- /dev/null
+++ b/comments.go
@@ -0,0 +1,73 @@
+package main
+
+import (
+ "context"
+ "encoding/json"
+ "io"
+ "net/http"
+ "time"
+
+ "git.home.dutchellie.nl/DutchEllie/proper-website-2/entity"
+ "go.mongodb.org/mongo-driver/bson"
+ "go.mongodb.org/mongo-driver/mongo/options"
+)
+
+func (a *application) Comment(w http.ResponseWriter, r *http.Request) {
+ switch r.Method {
+ case "POST":
+ var comment entity.Comment
+ body, err := io.ReadAll(r.Body)
+ if err != nil {
+ a.WriteError(w, http.StatusInternalServerError, err.Error())
+ return
+ }
+ err = json.Unmarshal(body, &comment)
+ if err != nil {
+ a.WriteError(w, http.StatusInternalServerError, err.Error())
+ return
+ }
+ comment.PostDate = time.Now()
+
+ if comment.Name == "" || comment.Message == "" {
+ a.WriteError(w, http.StatusBadRequest, "one or more fields empty")
+ return
+ }
+
+ _, err = a.collection.InsertOne(context.Background(), comment)
+ if err != nil {
+ a.WriteError(w, http.StatusInternalServerError, err.Error())
+ return
+ }
+ w.WriteHeader(200)
+ return
+ case "GET":
+ comments := make([]entity.Comment, 0)
+ filter := bson.D{}
+ sort := options.Find()
+ sort.SetSort(bson.D{{"time", -1}})
+ cur, err := a.collection.Find(context.Background(), filter, sort)
+ if err != nil {
+ a.WriteError(w, http.StatusInternalServerError, err.Error())
+ return
+ }
+ err = cur.All(context.Background(), &comments)
+ if err != nil {
+ a.WriteError(w, http.StatusInternalServerError, err.Error())
+ return
+ }
+ jsondata, err := json.Marshal(comments)
+ if err != nil {
+ a.WriteError(w, http.StatusInternalServerError, err.Error())
+ return
+ }
+
+ w.WriteHeader(200)
+ w.Write(jsondata)
+ return
+ }
+}
+
+func (a *application) WriteError(w http.ResponseWriter, code int, err string) {
+ w.WriteHeader(code)
+ w.Write([]byte(err))
+}
diff --git a/components/aboutpage.go b/components/aboutpage.go
index 7c5fc8e..d5cb344 100644
--- a/components/aboutpage.go
+++ b/components/aboutpage.go
@@ -1,6 +1,8 @@
package components
-import "github.com/maxence-charriere/go-app/v9/pkg/app"
+import (
+ "github.com/maxence-charriere/go-app/v9/pkg/app"
+)
type AboutPage struct {
app.Compo
@@ -22,10 +24,26 @@ func (a *AboutPage) Render() app.UI {
type aboutPanel struct {
app.Compo
+
+ aboutText string
}
func (a *aboutPanel) Render() app.UI {
return app.Div().Body(
- app.Raw(`I am a 21 year old computer science student, living and studying in The Netherlands.
`),
+ app.Img().Src("/web/static/images/rin-1.gif").Styles(map[string]string{"width": "100px", "position": "absolute", "top": "10px", "right": "10px"}),
+ app.Raw(`I am a 21 year old computer science student, living and studying in The Netherlands. I like Docker, Kubernetes and Golang!
+
+I made this website because I was inspired again by the amazing Neocities pages that I discovered because of my friends.
+They also have their own pages (you can find them on the friends tab, do check them out!) and I just had to get a good website of my own!
+
+I am not that great at web development, especially design, but I love trying it regardless!
+
+To say a bit more about me personally, I love all things computers. From servers to embedded devices! I love the cloud and all that it brings
+(except for big megacorps, but alright) and it's my goal to work for a big cloud company!
+
+Aside from career path ambitions, ボーカロイドはすきです! I love vocaloid and other Japanese music and culture!!
+I also like Vtubers, especially from Hololive and it's my goal to one day finally understand them in their native language!
+
+There is a lot more to say in words, but who cares about those! Have a look around my creative digital oasis and see what crazy stuff you can find!
`),
).Class("content")
}
diff --git a/components/guestbookform.go b/components/guestbookform.go
new file mode 100644
index 0000000..105a578
--- /dev/null
+++ b/components/guestbookform.go
@@ -0,0 +1,58 @@
+package components
+
+import (
+ "fmt"
+
+ "github.com/maxence-charriere/go-app/v9/pkg/app"
+)
+
+type guestbookForm struct {
+ app.Compo
+
+ name string
+ message string
+
+ OnSubmit func(
+ name string,
+ message string,
+ ) // Handler to implement which calls the api
+}
+
+func (g *guestbookForm) Render() app.UI {
+ return app.Div().Body(
+ app.Form().Body(
+ app.Input().
+ Type("text").
+ Name("name").
+ Placeholder("Name").
+ Required(true).
+ OnInput(g.ValueTo(&g.name)).
+ Value(g.name),
+ app.Input().
+ Type("text").
+ Name("message").
+ Placeholder("Message").
+ Required(true).
+ OnInput(g.ValueTo(&g.message)).
+ Value(g.message),
+ app.Input().
+ Type("submit").
+ Name("submit"),
+ ).ID("form").
+ OnSubmit(func(ctx app.Context, e app.Event) {
+ // This was to prevent the page from reloading
+ e.PreventDefault()
+ if g.name == "" || g.message == "" {
+ fmt.Printf("Error: one or more field(s) are empty. For now unhandled\n")
+ }
+ g.OnSubmit(g.name, g.message)
+ g.clear()
+ g.Update()
+ }),
+ ).Class("content")
+}
+
+func (g *guestbookForm) clear() {
+ g.name = ""
+ g.message = ""
+}
diff --git a/components/guestbookpanel.go b/components/guestbookpanel.go
new file mode 100644
index 0000000..3861e59
--- /dev/null
+++ b/components/guestbookpanel.go
@@ -0,0 +1,93 @@
+package components
+
+import (
+ "encoding/json"
+ "io"
+ "net/http"
+
+ "git.home.dutchellie.nl/DutchEllie/proper-website-2/entity"
+ "github.com/maxence-charriere/go-app/v9/pkg/app"
+)
+
+/*
+What is this supposed to do:
+- It should call on the API to give it a certain number of comments, in the range x to y (this has to be implemented in the api)
+- When it has called that, it should display those
+- Dynamic links are there to navigate the user along the pages
+- Comments are shown dynamically
+- This panel can be shown or hidden (maybe)
+
+AND VERY IMPORTANT!
+- If a user submits a new comment, automatically put it on the page, no reloading
+
+*/
+type guestbookPanel struct {
+ app.Compo
+
+ comments []entity.Comment
+ CommentUpdate bool
+}
+
+func newGuestbookPanel() *guestbookPanel {
+ return &guestbookPanel{}
+}
+
+func (g *guestbookPanel) Render() app.UI {
+ g.LoadComments()
+ return app.Div().Body(
+ app.Range(g.comments).Slice(func(i int) app.UI {
+ return &guestbookComment{
+ Comment: g.comments[i],
+ }
+ }),
+ ).Class("content")
+}
+
+func (g *guestbookPanel) LoadComments() {
+ // TODO: maybe you can put this in a localbrowser storage?
+ url := "/api/comment"
+ res, err := http.Get(url)
+ if err != nil {
+ app.Log(err)
+ return
+ }
+ defer res.Body.Close()
+ jsondata, err := io.ReadAll(res.Body)
+ if err != nil {
+ app.Log(err)
+ return
+ }
+
+ err = json.Unmarshal(jsondata, &g.comments)
+ if err != nil {
+ app.Log(err)
+ return
+ }
+}
+
+func (g *guestbookPanel) OnMount(ctx app.Context) {
+ //g.LoadComments()
+}
+
+func (g *guestbookPanel) OnUpdate(ctx app.Context) {
+ if g.CommentUpdate {
+ g.LoadComments()
+ g.Update()
+ g.CommentUpdate = false
+ }
+}
+
+type guestbookComment struct {
+ app.Compo
+
+ Comment entity.Comment
+}
+
+func (c *guestbookComment) Render() app.UI {
+ return app.Div().Body(
+ app.Span().Text("Name:").Style("font-weight", "800"),
+ app.P().Text(c.Comment.Name),
+ app.Span().Text("Comment:").Style("font-weight", "800"),
+ app.P().Text(c.Comment.Message),
+ ).Class("comment")
+}
diff --git a/components/homepage.go b/components/homepage.go
index 25b0c8d..70e8c43 100644
--- a/components/homepage.go
+++ b/components/homepage.go
@@ -1,27 +1,60 @@
package components
import (
+ "bytes"
+ "encoding/json"
+ "fmt"
+ "net/http"
+
+ "git.home.dutchellie.nl/DutchEllie/proper-website-2/entity"
"github.com/maxence-charriere/go-app/v9/pkg/app"
)
type Homepage struct {
app.Compo
- content *contentView
+ showGuestbook bool
+ guestbookUpdated bool
}
func NewHomepage() *Homepage {
- p1 := newHomePanel()
- c := newContentView(p1)
- return &Homepage{content: c}
+ return &Homepage{showGuestbook: true, guestbookUpdated: false}
}
func (p *Homepage) Render() app.UI {
+ gbp := newGuestbookPanel()
return app.Div().Body(
&header{},
app.Div().Body(
newNavbar(),
- newHomePanel(),
+ &homePanel{
+ onShowClick: func() {
+ p.showGuestbook = !p.showGuestbook
+ },
+ },
+ &guestbookForm{
+ OnSubmit: func(name, message string) {
+ var comment entity.Comment
+ comment.Name = name
+ comment.Message = message
+
+ jsondata, err := json.Marshal(comment)
+ if err != nil {
+ fmt.Printf("err: %v\n", err)
+ return
+ }
+ url := "/api/comment"
+ req, err := http.Post(url, "application/json", bytes.NewBuffer(jsondata))
+ if err != nil {
+ fmt.Printf("err: %v\n", err)
+ return
+ }
+ if req.StatusCode == 200 {
+ }
+ defer req.Body.Close()
+ },
+ },
+ app.If(p.showGuestbook, gbp),
).Class("main"),
)
}
diff --git a/components/homepanel.go b/components/homepanel.go
index e3f0489..73edb4c 100644
--- a/components/homepanel.go
+++ b/components/homepanel.go
@@ -4,6 +4,8 @@ import "github.com/maxence-charriere/go-app/v9/pkg/app"
type homePanel struct {
app.Compo
+
+ onShowClick func()
}
func newHomePanel() *homePanel {
@@ -20,6 +22,10 @@ Please enjoy yourself and do sign the guestbook!!
`),
app.Div().Body(
app.P().Text("Please sign my guestbook!").Style("font-size", "0.8em"),
app.Img().Src("/web/static/images/email3.gif").Style("width", "40px").Style("position", "absolute").Style("bottom", "0px").Style("right", "0px"),
- ).Style("position", "absolute").Style("bottom", "5px").Style("right", "5px"),
+ ).Style("position", "absolute").Style("bottom", "5px").Style("right", "5px").
+ OnClick(func(ctx app.Context, e app.Event) {
+ e.PreventDefault()
+ p.onShowClick()
+ }),
).Class("content")
}
diff --git a/components/updater.go b/components/updater.go
new file mode 100644
index 0000000..d5f32b9
--- /dev/null
+++ b/components/updater.go
@@ -0,0 +1,27 @@
+package components
+
+import "github.com/maxence-charriere/go-app/v9/pkg/app"
+
+type updater struct {
+ app.Compo
+
+ updateAvailable bool
+}
+
+func (u *updater) onAppUpdate(ctx app.Context) {
+ u.updateAvailable = ctx.AppUpdateAvailable()
+}
+
+func (u *updater) Render() app.UI {
+ return app.Div().Body(
+ app.If(u.updateAvailable,
+ app.Div().Body(
+ app.P().Text("An update for this website is available! Please click here to reload!"),
+ ).Styles(map[string]string{"position": "absolute", "width": "100px", "bottom": "10px", "right": "10px"}).OnClick(u.onUpdateClick),
+ ),
+ )
+}
+
+func (u *updater) onUpdateClick(ctx app.Context, e app.Event) {
+ ctx.Reload()
+}
diff --git a/entity/comment.go b/entity/comment.go
new file mode 100644
index 0000000..8157afb
--- /dev/null
+++ b/entity/comment.go
@@ -0,0 +1,12 @@
+package entity
+
+import "time"
+
+type Comment struct {
+ ID string `json:"id,omitempty" bson:"_id,omitempty"`
+ Name string `json:"name" bson:"name"`
+ Website string `json:"website,omitempty" bson:"website,omitempty"`
+ Email string `json:"email,omitempty" bson:"email,omitempty"`
+ Message string `json:"message" bson:"message"`
+ PostDate time.Time `json:"time" bson:"time"`
+}
diff --git a/go.mod b/go.mod
index 949b38e..854c9fc 100644
--- a/go.mod
+++ b/go.mod
@@ -3,6 +3,21 @@ module git.home.dutchellie.nl/DutchEllie/proper-website-2
go 1.17
require (
- github.com/google/uuid v1.3.0 // indirect
- github.com/maxence-charriere/go-app/v9 v9.3.0 // indirect
+ github.com/maxence-charriere/go-app/v9 v9.3.0
+ go.mongodb.org/mongo-driver v1.8.3
+)
+
+require (
+ github.com/go-stack/stack v1.8.0 // indirect
+ github.com/golang/snappy v0.0.1 // indirect
+ github.com/google/uuid v1.3.0 // indirect
+ github.com/klauspost/compress v1.13.6 // indirect
+ github.com/pkg/errors v0.9.1 // indirect
+ github.com/xdg-go/pbkdf2 v1.0.0 // indirect
+ github.com/xdg-go/scram v1.0.2 // indirect
+ github.com/xdg-go/stringprep v1.0.2 // indirect
+ github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d // indirect
+ golang.org/x/crypto v0.0.0-20201216223049-8b5274cf687f // indirect
+ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e // indirect
+ golang.org/x/text v0.3.6 // indirect
)
diff --git a/go.sum b/go.sum
index 99eac09..ce62fcf 100644
--- a/go.sum
+++ b/go.sum
@@ -1,19 +1,68 @@
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
+github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk=
+github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
+github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4=
+github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/gomarkdown/markdown v0.0.0-20210408062403-ad838ccf8cdd/go.mod h1:aii0r/K0ZnHv7G0KF7xy1v0A7s2Ljrb5byB7MO5p6TU=
+github.com/google/go-cmp v0.5.2 h1:X2ev0eStA3AbceY54o37/0PQ/UWqKEiiO2dKL5OPaFM=
+github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/klauspost/compress v1.13.6 h1:P76CopJELS0TiO2mebmnzgWaajssP/EszplttgQxcgc=
+github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
+github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
+github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
+github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/maxence-charriere/go-app/v9 v9.3.0 h1:PWNZWcme5hnMR9/cSdSRv+9WvPowETj0qhfy+3HCQRM=
github.com/maxence-charriere/go-app/v9 v9.3.0/go.mod h1:zo0n1kh4OMKn7P+MrTUUi7QwUMU2HOfHsZ293TITtxI=
+github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc=
+github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
+github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4=
+github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
+github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c=
+github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
+github.com/xdg-go/scram v1.0.2 h1:akYIkZ28e6A96dkWNJQu3nmCzH3YfwMPQExUYDaRv7w=
+github.com/xdg-go/scram v1.0.2/go.mod h1:1WAq6h33pAW+iRreB34OORO2Nf7qel3VV3fjBj+hCSs=
+github.com/xdg-go/stringprep v1.0.2 h1:6iq84/ryjjeRmMJwxutI51F2GIPlP5BfTvXHeYjyhBc=
+github.com/xdg-go/stringprep v1.0.2/go.mod h1:8F9zXuvzgwmyT5DUm4GUfZGDdT3W+LCvS6+da4O5kxM=
+github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d h1:splanxYIlg+5LfHAM6xpdFEAYOk8iySO56hMFq6uLyA=
+github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA=
+go.mongodb.org/mongo-driver v1.8.3 h1:TDKlTkGDKm9kkJVUOAXDK5/fkqKHJVwYQSpoRfB43R4=
+go.mongodb.org/mongo-driver v1.8.3/go.mod h1:0sQWfOeY63QTntERDJJ/0SuKK0T1uVSgKCuAROlKEPY=
golang.org/dl v0.0.0-20190829154251-82a15e2f2ead/go.mod h1:IUMfjQLJQd4UTqG1Z90tenwKoCX93Gn3MAQJMOSBsDQ=
+golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/crypto v0.0.0-20201216223049-8b5274cf687f h1:aZp0e2vLN4MToVqnjNEYEtrEA8RH8U8FN1CU7JgqsPU=
+golang.org/x/crypto v0.0.0-20201216223049-8b5274cf687f/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
+golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20210415231046-e915ea6b2b7d/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8=
+golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e h1:vcxGaoTs7kV8m5Np9uUNQin4BrLOthgV7252N8V+FwY=
+golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
+golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20190531172133-b3315ee88b7d/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
+golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
+golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
diff --git a/main.go b/main.go
index e4c428c..2fd1d63 100644
--- a/main.go
+++ b/main.go
@@ -1,13 +1,24 @@
package main
import (
+ "context"
+ "fmt"
"log"
"net/http"
"git.home.dutchellie.nl/DutchEllie/proper-website-2/components"
"github.com/maxence-charriere/go-app/v9/pkg/app"
+ "go.mongodb.org/mongo-driver/mongo"
+ "go.mongodb.org/mongo-driver/mongo/options"
+ "go.mongodb.org/mongo-driver/mongo/readpref"
)
+type application struct {
+ client *mongo.Client
+ database *mongo.Database
+ collection *mongo.Collection
+}
+
func main() {
homepage := components.NewHomepage()
aboutpage := components.NewAboutPage()
@@ -19,6 +30,32 @@ func main() {
// It exits immediately on the server side
app.RunWhenOnBrowser()
+ uri := "mongodb+srv://guestbook-database:5WUDzpvBKBBiiMCy@cluster0.wtt64.mongodb.net/myFirstDatabase?retryWrites=true&w=majority"
+
+ client, err := mongo.Connect(context.TODO(), options.Client().ApplyURI(uri))
+ if err != nil {
+ fmt.Println(err)
+ return
+ }
+ defer func() {
+ if err = client.Disconnect(context.TODO()); err != nil {
+ panic(err)
+ }
+ }()
+
+ // Ping the primary
+ if err := client.Ping(context.TODO(), readpref.Primary()); err != nil {
+ panic(err)
+ }
+ db := client.Database("guestbook")
+ coll := db.Collection("comments")
+
+ apiapp := &application{
+ client: client,
+ database: db,
+ collection: coll,
+ }
+
http.Handle("/", &app.Handler{
Name: "Internetica Galactica",
Description: "A 1990's style PWA!",
@@ -30,6 +67,7 @@ func main() {
},
CacheableResources: []string{},
})
+ http.HandleFunc("/api/comment", apiapp.Comment)
if err := http.ListenAndServe(":8000", nil); err != nil {
log.Fatal(err)
diff --git a/web/static/images/rin-1.gif b/web/static/images/rin-1.gif
new file mode 100644
index 0000000000000000000000000000000000000000..c196128eb089ab1dd140e1c159b8336bc8cf3576
GIT binary patch
literal 482670
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