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 gbModalOpen bool
OnSubmit func( OnSubmit func(
ctx app.Context,
name string, name string,
message string, message string,
) // Handler to implement which calls the api ) // Handler to implement which calls the api
@ -52,7 +53,7 @@ func (g *guestbookForm) Render() app.UI {
g.gbModalOpen = true g.gbModalOpen = true
return return
} }
g.OnSubmit(g.name, g.message) g.OnSubmit(ctx, g.name, g.message)
g.clear() g.clear()
}), }),
app.If( app.If(
@ -72,6 +73,7 @@ func (g *guestbookForm) clear() {
g.message = "" g.message = ""
} }
/*
type guestbookAlertModal struct { type guestbookAlertModal struct {
app.Compo app.Compo
@ -100,3 +102,4 @@ func (g *guestbookAlertModal) Render() app.UI {
), ),
) )
} }
*/

View File

@ -4,7 +4,6 @@ import (
"encoding/json" "encoding/json"
"io" "io"
"net/http" "net/http"
"time"
"dutchellie.nl/DutchEllie/proper-website-2/entity" "dutchellie.nl/DutchEllie/proper-website-2/entity"
"github.com/maxence-charriere/go-app/v9/pkg/app" "github.com/maxence-charriere/go-app/v9/pkg/app"
@ -28,24 +27,35 @@ type guestbookPanel struct {
comments []entity.Comment comments []entity.Comment
} }
func newGuestbookPanel() *guestbookPanel { func (g *guestbookPanel) OnMount(ctx app.Context) {
g := &guestbookPanel{} g.LoadComments(ctx)
g.LoadComments() }
return g
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 { func (g *guestbookPanel) Render() app.UI {
return app.Range(g.comments).Slice(func(i int) app.UI { return app.Div().Body(
app.Range(g.comments).Slice(func(i int) app.UI {
return &guestbookComment{ return &guestbookComment{
Comment: g.comments[i], 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? // TODO: maybe you can put this in a localbrowser storage?
url := ApiURL url := ApiURL
ctx.Async(func() {
res, err := http.Get(url) res, err := http.Get(url)
if err != nil { if err != nil {
app.Log(err) app.Log(err)
@ -58,14 +68,17 @@ func (g *guestbookPanel) LoadComments() {
return return
} }
ctx.Dispatch(func(ctx app.Context) {
err = json.Unmarshal(jsondata, &g.comments) err = json.Unmarshal(jsondata, &g.comments)
if err != nil { if err != nil {
app.Log(err) app.Log(err)
return return
} }
})
})
} }
type guestbookComment struct { /*type guestbookComment struct {
app.Compo app.Compo
Comment entity.Comment Comment entity.Comment
@ -84,3 +97,4 @@ func (c *guestbookComment) Render() app.UI {
), ),
).Class("comment") ).Class("comment")
} }
*/

View File

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

View File

@ -23,7 +23,6 @@ func NewHomepage() *Homepage {
} }
func (p *Homepage) Render() app.UI { func (p *Homepage) Render() app.UI {
gbp := newGuestbookPanel()
return newPage(). return newPage().
Title("Homepage"). Title("Homepage").
LeftBar( LeftBar(
@ -41,10 +40,12 @@ func (p *Homepage) Render() app.UI {
Class("right"). Class("right").
Class("contentblock"). Class("contentblock").
UI( UI(
&guestbookForm{ &guestbook{
OnSubmit: func(name, message string) { OnSubmit: func(ctx app.Context, name, email, website, message string) {
var comment entity.Comment var comment entity.Comment
comment.Name = name comment.Name = name
comment.Email = email
comment.Website = website
comment.Message = message comment.Message = message
jsondata, err := json.Marshal(comment) jsondata, err := json.Marshal(comment)
@ -54,6 +55,7 @@ func (p *Homepage) Render() app.UI {
} }
url := ApiURL url := ApiURL
ctx.Async(func() {
req, err := http.Post(url, "application/json", bytes.NewBuffer(jsondata)) req, err := http.Post(url, "application/json", bytes.NewBuffer(jsondata))
if err != nil { if err != nil {
fmt.Printf("err: %v\n", err) fmt.Printf("err: %v\n", err)
@ -63,14 +65,14 @@ func (p *Homepage) Render() app.UI {
p.Update() p.Update()
} }
defer req.Body.Close() defer req.Body.Close()
})
}, },
}, },
), ),
/*
newUIBlock(). newUIBlock().
Class("right"). Class("right").
Class("contentblock"). Class("contentblock").
UI( UI(),*/
gbp.Render(),
),
) )
} }

View File

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

View File

@ -5,48 +5,39 @@
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <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/style.css">
<link rel="stylesheet" href="../web/static/form.css">
<link rel="stylesheet" href="static/anisha.css?family=anisha"> <link rel="stylesheet" href="static/anisha.css?family=anisha">
<link rel="stylesheet" href="static/adreena.css?family=adreena"> <link rel="stylesheet" href="static/adreena.css?family=adreena">
<link rel="stylesheet" href="static/havakana.css?family=havakana"> <link rel="stylesheet" href="static/havakana.css?family=havakana">
<title>Index</title> <title>Index</title>
</head> </head>
<body> <body>
<div class="header"> <div class="block right content">
Internetica Galactica <form action="" class="guestbook-form">
<div class="update-box"> <div class="input-groups">
<img src="/web/static/images/hot1.gif" alt="" height="50px" style="" class="pulsing"> <div class="fr">
<p class="update-message"> <div class="input-group input-group-name">
An update is available! Click here to reload! <label for="name">Name:</label>
</p> <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> </div>
<div class="main"> <div class="input-group input-group-website">
<div class="navbar"> <label for="website">Website:</label>
<ul> <input type="text" name="website" class="input">
<li><a href="base.html">Home</a></li>
</ul>
</div> </div>
<div class="content"> <div class="input-group input-group-message">
Dit is eigenlijk 1 van die dingen die steeds kan veranderen <label for="message">Message:</label>
Deze doet dat <textarea name="message" cols="30" rows="5" class="input"></textarea>
</div> </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>
<div class="submit-field">
<input type="submit" value="Send!">
</div>
</form>
</div> </div>
</body> </body>
</html> </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; margin-bottom: 5px;
}*/ }*/
.gbp { .guestbook-form-div {
margin: 0px 0px 10px 0px;
} }
.comment { .comment {
border: 2px solid; border: 2px solid;
border-radius: 6px; border-radius: 6px;