From cd07bef29e910c89fbc27fa9883934d22908676a Mon Sep 17 00:00:00 2001 From: DutchEllie Date: Tue, 15 Mar 2022 16:42:26 +0100 Subject: [PATCH] Rewrote guestbook --- src/guestbook.go | 239 +++++++++++++++++++++++++++++++++++++++++ src/guestbookform.go | 5 +- src/guestbookpanel.go | 72 ++++++++----- src/header.go | 2 +- src/homepage.go | 38 +++---- src/main.go | 1 + test-website/base.html | 63 +++++------ web/static/form.css | 45 ++++++++ web/static/style.css | 5 +- 9 files changed, 383 insertions(+), 87 deletions(-) create mode 100644 src/guestbook.go create mode 100644 web/static/form.css diff --git a/src/guestbook.go b/src/guestbook.go new file mode 100644 index 0000000..34ad5e7 --- /dev/null +++ b/src/guestbook.go @@ -0,0 +1,239 @@ +package main + +import ( + "encoding/json" + "fmt" + "io" + "net/http" + "time" + + "dutchellie.nl/DutchEllie/proper-website-2/entity" + "github.com/maxence-charriere/go-app/v9/pkg/app" +) + +type guestbook struct { + app.Compo + + comments []entity.Comment + + name string + email string + website string + message string + + gbModalOpen bool + OnSubmit func( + ctx app.Context, + name string, + email string, + website string, + message string, + ) // Handler to implement which calls the api +} + +func (g *guestbook) OnMount(ctx app.Context) { + g.LoadComments(ctx) +} + +func (g *guestbook) OnNav(ctx app.Context) { + g.LoadComments(ctx) +} + +func (g *guestbook) OnUpdate(ctx app.Context) { + g.LoadComments(ctx) +} + +func (g guestbook) Render() app.UI { + return app.Div().Body( + app.Form(). + Class("guestbook-form"). + Body( + app.Div(). + Class("input-groups"). + Body( + app.Div(). + Class("fr"). + Body( + app.Div(). + Class("input-group"). + Class("input-group-name"). + Body( + app.Label(). + For("name"). + Text("Name:"), + app.Input(). + Type("text"). + Name("name"). + Class("input"). + Required(true). + OnChange(g.ValueTo(&g.name)), + ), + app.Div(). + Class("input-group"). + Class("input-group-email"). + Body( + app.Label(). + For("email"). + Text("Email: (optional)"), + app.Input(). + Type("text"). + Name("email"). + Class("input"). + Required(false). + OnChange(g.ValueTo(&g.email)), + ), + ), + app.Div(). + Class("input-group"). + Class("input-group-website"). + Body( + app.Label(). + For("website"). + Text("Website: (optional)"), + app.Input(). + Type("text"). + Name("website"). + Class("input"). + Required(false). + OnChange(g.ValueTo(&g.website)), + ), + app.Div(). + Class("input-group"). + Class("input-group-message"). + Body( + app.Label(). + For("message"). + Text("Message:"), + app.Textarea(). + Name("message"). + Class("input"). + Rows(5). + Cols(30). + Required(true). + OnChange(g.ValueTo(&g.message)), + ), + app.Div(). + Class("submit-field"). + Body( + app.Input(). + Type("submit"). + Value("Send!"), + ), + ), + ).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") + return + } + if len(g.name) > 40 || len(g.message) > 360 { + fmt.Printf("Error: Your message is too long fucker\n") + g.gbModalOpen = true + return + } + g.OnSubmit(ctx, g.name, g.email, g.website, g.message) + ctx.Dispatch(func(ctx app.Context) { + g.clear() + }) + g.LoadComments(ctx) + }), + app.If( + g.gbModalOpen, + &guestbookAlertModal{ + OnClose: func() { + g.gbModalOpen = false + g.Update() + }, + }, + ), + app.Div().Body( + app.Range(g.comments).Slice(func(i int) app.UI { + return &guestbookComment{ + Comment: g.comments[i], + } + }, + ), + ), + ) +} + +func (g *guestbook) LoadComments(ctx app.Context) { + // TODO: maybe you can put this in a localbrowser storage? + url := ApiURL + ctx.Async(func() { + 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 + } + + ctx.Dispatch(func(ctx app.Context) { + err = json.Unmarshal(jsondata, &g.comments) + if err != nil { + app.Log(err) + return + } + }) + }) +} + +func (g *guestbook) clear() { + g.name = "" + g.message = "" +} + +type guestbookAlertModal struct { + app.Compo + + PreviousAttempts int + OnClose func() // For when we close the modal +} + +func (g *guestbookAlertModal) Render() app.UI { + return app.Div(). + Class("gb-modal"). + ID("gbModal"). + OnClick(func(ctx app.Context, e app.Event) { + g.OnClose() + }). + Body( + app.Div(). + Class("gb-modal-content"). + Body( + app.Span().Class("close").Text("X"). + OnClick(func(ctx app.Context, e app.Event) { + //modal := app.Window().GetElementByID("gbModal") + //modal.Set("style", "none") + g.OnClose() + }), + app.P().Text("Your name must be <= 40 and your message must be <= 360 characters"), + ), + ) +} + +type guestbookComment struct { + app.Compo + + Comment entity.Comment + time string +} + +func (c *guestbookComment) Render() app.UI { + c.time = c.Comment.PostDate.Format(time.RFC1123) + return app.Div().Body( + app.Div().Class().Body( + app.P().Text(c.Comment.Name).Class("name"), + app.P().Text(c.time).Class("date"), + ).Class("comment-header"), + app.Div().Class("comment-message").Body( + app.P().Text(c.Comment.Message), + ), + ).Class("comment") +} diff --git a/src/guestbookform.go b/src/guestbookform.go index dbf1eda..ab8263a 100644 --- a/src/guestbookform.go +++ b/src/guestbookform.go @@ -14,6 +14,7 @@ type guestbookForm struct { gbModalOpen bool OnSubmit func( + ctx app.Context, name string, message string, ) // Handler to implement which calls the api @@ -52,7 +53,7 @@ func (g *guestbookForm) Render() app.UI { g.gbModalOpen = true return } - g.OnSubmit(g.name, g.message) + g.OnSubmit(ctx, g.name, g.message) g.clear() }), app.If( @@ -72,6 +73,7 @@ func (g *guestbookForm) clear() { g.message = "" } +/* type guestbookAlertModal struct { app.Compo @@ -100,3 +102,4 @@ func (g *guestbookAlertModal) Render() app.UI { ), ) } +*/ diff --git a/src/guestbookpanel.go b/src/guestbookpanel.go index 74a2b12..6cbd7af 100644 --- a/src/guestbookpanel.go +++ b/src/guestbookpanel.go @@ -4,7 +4,6 @@ import ( "encoding/json" "io" "net/http" - "time" "dutchellie.nl/DutchEllie/proper-website-2/entity" "github.com/maxence-charriere/go-app/v9/pkg/app" @@ -28,44 +27,58 @@ type guestbookPanel struct { comments []entity.Comment } -func newGuestbookPanel() *guestbookPanel { - g := &guestbookPanel{} - g.LoadComments() - return g +func (g *guestbookPanel) OnMount(ctx app.Context) { + g.LoadComments(ctx) +} + +func (g *guestbookPanel) OnNav(ctx app.Context) { + g.LoadComments(ctx) +} + +func (g *guestbookPanel) OnUpdate(ctx app.Context) { + g.LoadComments(ctx) } func (g *guestbookPanel) Render() app.UI { - return app.Range(g.comments).Slice(func(i int) app.UI { - return &guestbookComment{ - Comment: g.comments[i], - } - }, - ) + return app.Div().Body( + app.Range(g.comments).Slice(func(i int) app.UI { + return &guestbookComment{ + Comment: g.comments[i], + } + }, + ), + ).OnSubmit(func(ctx app.Context, e app.Event) { + g.LoadComments(ctx) + }) } -func (g *guestbookPanel) LoadComments() { +func (g *guestbookPanel) LoadComments(ctx app.Context) { // TODO: maybe you can put this in a localbrowser storage? url := ApiURL - 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 - } + ctx.Async(func() { + 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 - } + ctx.Dispatch(func(ctx app.Context) { + err = json.Unmarshal(jsondata, &g.comments) + if err != nil { + app.Log(err) + return + } + }) + }) } -type guestbookComment struct { +/*type guestbookComment struct { app.Compo Comment entity.Comment @@ -84,3 +97,4 @@ func (c *guestbookComment) Render() app.UI { ), ).Class("comment") } +*/ diff --git a/src/header.go b/src/header.go index 1a1e590..62e9794 100644 --- a/src/header.go +++ b/src/header.go @@ -11,6 +11,6 @@ func (h *header) Render() app.UI { Class("header"). Body( app.Text("Internetica Galactica"), - &updater{}, + //&updater{}, ) } diff --git a/src/homepage.go b/src/homepage.go index 6c09d5e..0c0ff1f 100644 --- a/src/homepage.go +++ b/src/homepage.go @@ -23,7 +23,6 @@ func NewHomepage() *Homepage { } func (p *Homepage) Render() app.UI { - gbp := newGuestbookPanel() return newPage(). Title("Homepage"). LeftBar( @@ -41,10 +40,12 @@ func (p *Homepage) Render() app.UI { Class("right"). Class("contentblock"). UI( - &guestbookForm{ - OnSubmit: func(name, message string) { + &guestbook{ + OnSubmit: func(ctx app.Context, name, email, website, message string) { var comment entity.Comment comment.Name = name + comment.Email = email + comment.Website = website comment.Message = message jsondata, err := json.Marshal(comment) @@ -54,23 +55,24 @@ func (p *Homepage) Render() app.UI { } url := ApiURL - req, err := http.Post(url, "application/json", bytes.NewBuffer(jsondata)) - if err != nil { - fmt.Printf("err: %v\n", err) - return - } - if req.StatusCode == 200 { - p.Update() - } - defer req.Body.Close() + ctx.Async(func() { + req, err := http.Post(url, "application/json", bytes.NewBuffer(jsondata)) + if err != nil { + fmt.Printf("err: %v\n", err) + return + } + if req.StatusCode == 200 { + p.Update() + } + defer req.Body.Close() + }) }, }, ), - newUIBlock(). - Class("right"). - Class("contentblock"). - UI( - gbp.Render(), - ), + /* + newUIBlock(). + Class("right"). + Class("contentblock"). + UI(),*/ ) } diff --git a/src/main.go b/src/main.go index 5509eec..f9118e8 100644 --- a/src/main.go +++ b/src/main.go @@ -55,6 +55,7 @@ func main() { "/web/static/adreena.css", "/web/static/anisha.css", "/web/static/havakana.css", + "/web/static/form.css", }, CacheableResources: []string{}, } diff --git a/test-website/base.html b/test-website/base.html index db0adac..6ad8251 100644 --- a/test-website/base.html +++ b/test-website/base.html @@ -5,48 +5,39 @@ + Index -
- Internetica Galactica -
- -

- An update is available! Click here to reload! -

-
-
-
- -
- Dit is eigenlijk 1 van die dingen die steeds kan veranderen - Deze doet dat -
- -

- Welcome to my webspace! Whether you stumbled across this page by accident - or were linked here, you're more than welcome! This is my personal project that I like - to work on! I was inspired by a couple friends of mine, please do check their webspaces - out as well under "Galaxies" on the left side there! - If you like this page, there is a lot more, so have a look around! You can also leave a - nice message for me in the guestbook! There is no registration (unlike the rest of the "modern" - internet) so nothing of that sort! - That said, this website is my creative outlet and a way to introduce myself, so be kind please! - Also its code is entirely open-source and can be found - -

My friends!

-

These are some of the websites of my friends!

-
+
+
+
+
+
+ + +
+
+ + +
+
+
+ + +
+
+ + +
+
+
+ +
+
diff --git a/web/static/form.css b/web/static/form.css new file mode 100644 index 0000000..f193bca --- /dev/null +++ b/web/static/form.css @@ -0,0 +1,45 @@ +.input-groups { + display:flex; + flex-wrap:wrap; +} + +.input-group { + padding: 6px; +} + +.input-group-name { + width: 50%; + float:left; +} + +.input-group-email { + width: 50%; + float:right; + padding-right: 16px; +} + +.input-group-website { + width: 100%; + padding-right: 16px; +} + +.input-group-message { + width: 100%; + padding-right: 16px; + +} + +.submit-field { + text-align: right; + padding-right: 10px; + padding-bottom: 5px; +} + +.input { + width: 100%; +} + +.fr { + width: 100%; + display: flex; +} \ No newline at end of file diff --git a/web/static/style.css b/web/static/style.css index fe36168..dcdbc55 100644 --- a/web/static/style.css +++ b/web/static/style.css @@ -126,10 +126,11 @@ body { margin-bottom: 5px; }*/ -.gbp { - +.guestbook-form-div { + margin: 0px 0px 10px 0px; } + .comment { border: 2px solid; border-radius: 6px;