Rewrote guestbook

This commit is contained in:
DutchEllie 2022-03-15 16:42:26 +01:00
parent 73442b212c
commit cd07bef29e
Signed by: DutchEllie
SSH Key Fingerprint: SHA256:dKq6ZSgN5E3Viqrw/+xAdf2VdR6hdRGNyrYqXXwfjTY
9 changed files with 383 additions and 87 deletions

239
src/guestbook.go Normal file
View File

@ -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")
}

View File

@ -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 {
),
)
}
*/

View File

@ -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")
}
*/

View File

@ -11,6 +11,6 @@ func (h *header) Render() app.UI {
Class("header").
Body(
app.Text("Internetica Galactica"),
&updater{},
//&updater{},
)
}

View File

@ -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(),*/
)
}

View File

@ -55,6 +55,7 @@ func main() {
"/web/static/adreena.css",
"/web/static/anisha.css",
"/web/static/havakana.css",
"/web/static/form.css",
},
CacheableResources: []string{},
}

View File

@ -5,48 +5,39 @@
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="../web/static/style.css">
<link rel="stylesheet" href="../web/static/form.css">
<link rel="stylesheet" href="static/anisha.css?family=anisha">
<link rel="stylesheet" href="static/adreena.css?family=adreena">
<link rel="stylesheet" href="static/havakana.css?family=havakana">
<title>Index</title>
</head>
<body>
<div class="header">
Internetica Galactica
<div class="update-box">
<img src="/web/static/images/hot1.gif" alt="" height="50px" style="" class="pulsing">
<p class="update-message">
An update is available! Click here to reload!
</p>
</div>
</div>
<div class="main">
<div class="navbar">
<ul>
<li><a href="base.html">Home</a></li>
</ul>
</div>
<div class="content">
Dit is eigenlijk 1 van die dingen die steeds kan veranderen
Deze doet dat
</div>
<p class="content-text">
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
<a href="https://dutchellie.nl/DutchEllie/proper-website-2>here</a> so if you like that sort
of stuff, be my guest it's cool!</p>
<div class="content">
<p class="p-h1">My friends!</p>
<p>These are some of the websites of my friends!</p>
</div>
<div class="block right content">
<form action="" class="guestbook-form">
<div class="input-groups">
<div class="fr">
<div class="input-group input-group-name">
<label for="name">Name:</label>
<input type="text" name="name" class="input">
</div>
<div class="input-group input-group-email">
<label for="email">Email:</label>
<input type="text" name="email" class="input">
</div>
</div>
<div class="input-group input-group-website">
<label for="website">Website:</label>
<input type="text" name="website" class="input">
</div>
<div class="input-group input-group-message">
<label for="message">Message:</label>
<textarea name="message" cols="30" rows="5" class="input"></textarea>
</div>
</div>
<div class="submit-field">
<input type="submit" value="Send!">
</div>
</form>
</div>
</body>
</html>

45
web/static/form.css Normal file
View File

@ -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;
}

View File

@ -126,10 +126,11 @@ body {
margin-bottom: 5px;
}*/
.gbp {
.guestbook-form-div {
margin: 0px 0px 10px 0px;
}
.comment {
border: 2px solid;
border-radius: 6px;