normalize urls, fix website creation

This commit is contained in:
yequari 2025-06-27 13:24:03 -07:00
parent a15bbcee3d
commit 133d8bcfe9
14 changed files with 401 additions and 383 deletions

View File

@ -5,7 +5,6 @@ import (
"errors" "errors"
"fmt" "fmt"
"net/http" "net/http"
"net/url"
"strconv" "strconv"
"time" "time"
@ -258,11 +257,10 @@ func (app *application) postGuestbookCommentCreateRemote(w http.ResponseWriter,
return return
} }
if normalizeUrl(r.Header.Get("Origin")) != normalizeUrl(website.SiteUrl) { if !matchOrigin(r.Header.Get("Origin"), website.Url) {
app.clientError(w, http.StatusForbidden) app.clientError(w, http.StatusForbidden)
return return
} }
if !website.Guestbook.CanComment() { if !website.Guestbook.CanComment() {
app.clientError(w, http.StatusForbidden) app.clientError(w, http.StatusForbidden)
return return
@ -285,12 +283,10 @@ func (app *application) postGuestbookCommentCreateRemote(w http.ResponseWriter,
// otherwise redirect to the guestbook by default // otherwise redirect to the guestbook by default
redirectUrl := fmt.Sprintf("/websites/%s/guestbook", shortIdToSlug(website.ShortId)) redirectUrl := fmt.Sprintf("/websites/%s/guestbook", shortIdToSlug(website.ShortId))
if form.Redirect != "" { if form.Redirect != "" {
u := url.URL{ u, err := website.Url.Parse(form.Redirect)
Scheme: "http", if err == nil {
Host: website.SiteUrl, redirectUrl = u.String()
Path: form.Redirect,
} }
redirectUrl = u.String()
} }
if !form.Valid() { if !form.Valid() {

View File

@ -144,3 +144,88 @@ func TestPostGuestbookCommentCreate(t *testing.T) {
}) })
} }
} }
func TestPostGuestbookCommentCreateRemote(t *testing.T) {
app := newTestApplication(t)
ts := newTestServer(t, app.routes())
defer ts.Close()
_, _, body := ts.get(t, fmt.Sprintf("/websites/%s/guestbook", shortIdToSlug(1)))
validCSRFToken := extractCSRFToken(t, body)
const (
validAuthorName = "John Test"
validAuthorEmail = "test@example.com"
validAuthorSite = "example.com"
validContent = "This is a comment"
)
tests := []struct {
name string
authorName string
authorEmail string
authorSite string
content string
csrfToken string
wantCode int
}{
{
name: "Valid input",
authorName: validAuthorName,
authorEmail: validAuthorEmail,
authorSite: validAuthorSite,
content: validContent,
csrfToken: validCSRFToken,
wantCode: http.StatusSeeOther,
},
{
name: "Blank name",
authorName: "",
authorEmail: validAuthorEmail,
authorSite: validAuthorSite,
content: validContent,
csrfToken: validCSRFToken,
wantCode: http.StatusUnprocessableEntity,
},
{
name: "Blank email",
authorName: validAuthorName,
authorEmail: "",
authorSite: validAuthorSite,
content: validContent,
csrfToken: validCSRFToken,
wantCode: http.StatusSeeOther,
},
{
name: "Blank site",
authorName: validAuthorName,
authorEmail: validAuthorEmail,
authorSite: "",
content: validContent,
csrfToken: validCSRFToken,
wantCode: http.StatusSeeOther,
},
{
name: "Blank content",
authorName: validAuthorName,
authorEmail: validAuthorEmail,
authorSite: validAuthorSite,
content: "",
csrfToken: validCSRFToken,
wantCode: http.StatusUnprocessableEntity,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
form := url.Values{}
form.Add("authorname", tt.authorName)
form.Add("authoremail", tt.authorEmail)
form.Add("authorsite", tt.authorSite)
form.Add("content", tt.content)
form.Add("csrf_token", tt.csrfToken)
code, _, body := ts.postForm(t, fmt.Sprintf("/websites/%s/guestbook/comments/create/remote", shortIdToSlug(1)), form)
assert.Equal(t, code, tt.wantCode)
assert.Equal(t, body, body)
})
}
}

View File

@ -33,16 +33,20 @@ func (app *application) postWebsiteCreate(w http.ResponseWriter, r *http.Request
form.CheckField(validator.MaxChars(form.Name, 256), "sitename", "This field cannot exceed 256 characters") form.CheckField(validator.MaxChars(form.Name, 256), "sitename", "This field cannot exceed 256 characters")
form.CheckField(validator.NotBlank(form.SiteUrl), "siteurl", "This field cannot be blank") form.CheckField(validator.NotBlank(form.SiteUrl), "siteurl", "This field cannot be blank")
form.CheckField(validator.MaxChars(form.SiteUrl, 512), "siteurl", "This field cannot exceed 512 characters") form.CheckField(validator.MaxChars(form.SiteUrl, 512), "siteurl", "This field cannot exceed 512 characters")
form.CheckField(validator.Matches(form.SiteUrl, validator.WebRX), "siteurl", "This field must be a valid URL (including http:// or https://)")
u, err := url.Parse(form.SiteUrl) u, err := url.Parse(form.SiteUrl)
if err != nil {
if !form.Valid() || err != nil { form.CheckField(false, "siteurl", "This field must be a valid URL")
}
if !form.Valid() {
data := app.newCommonData(r) data := app.newCommonData(r)
w.WriteHeader(http.StatusUnprocessableEntity) w.WriteHeader(http.StatusUnprocessableEntity)
views.WebsiteCreate("Add a Website", data, form).Render(r.Context(), w) views.WebsiteCreate("Add a Website", data, form).Render(r.Context(), w)
return
} }
websiteShortID := app.createShortId() websiteShortID := app.createShortId()
_, err = app.websites.Insert(websiteShortID, userId, form.Name, u.Host, form.AuthorName) _, err = app.websites.Insert(websiteShortID, userId, form.Name, u.String(), form.AuthorName)
if err != nil { if err != nil {
app.serverError(w, r, err) app.serverError(w, r, err)
return return
@ -78,10 +82,6 @@ func (app *application) getWebsiteList(w http.ResponseWriter, r *http.Request) {
app.serverError(w, r, err) app.serverError(w, r, err)
return return
} }
if r.Header.Get("HX-Request") == "true" {
views.HxWebsiteList(websites)
return
}
data := app.newCommonData(r) data := app.newCommonData(r)
views.WebsiteList("My Websites", data, websites).Render(r.Context(), w) views.WebsiteList("My Websites", data, websites).Render(r.Context(), w)
} }

View File

@ -5,9 +5,9 @@ import (
"fmt" "fmt"
"math" "math"
"net/http" "net/http"
"net/url"
"runtime/debug" "runtime/debug"
"strconv" "strconv"
"strings"
"time" "time"
"git.32bit.cafe/32bitcafe/guestbook/internal/models" "git.32bit.cafe/32bitcafe/guestbook/internal/models"
@ -130,11 +130,13 @@ func (app *application) durationToTime(duration string) (time.Time, error) {
return result, nil return result, nil
} }
func normalizeUrl(url string) string { func matchOrigin(origin string, u *url.URL) bool {
r, f := strings.CutPrefix(url, "http://") o, err := url.Parse(origin)
if f { if err != nil {
return r return false
} }
r, _ = strings.CutPrefix(url, "https://") if o.Host != u.Host {
return r return false
}
return true
} }

View File

@ -18,6 +18,12 @@ var mockGuestbookComment = models.GuestbookComment{
IsPublished: true, IsPublished: true,
} }
var mockSerializedGuestbookComment = models.GuestbookCommentSerialized{
AuthorName: "John Test",
CommentText: "Hello, world",
Created: time.Now().Format(time.RFC3339),
}
type GuestbookCommentModel struct{} type GuestbookCommentModel struct{}
func (m *GuestbookCommentModel) Insert(shortId uint64, guestbookId, parentId int64, authorName, func (m *GuestbookCommentModel) Insert(shortId uint64, guestbookId, parentId int64, authorName,
@ -45,6 +51,17 @@ func (m *GuestbookCommentModel) GetAll(guestbookId int64) ([]models.GuestbookCom
} }
} }
func (m *GuestbookCommentModel) GetAllSerialized(guestbookId int64) ([]models.GuestbookCommentSerialized, error) {
switch guestbookId {
case 1:
return []models.GuestbookCommentSerialized{mockSerializedGuestbookComment}, nil
case 2:
return []models.GuestbookCommentSerialized{}, nil
default:
return []models.GuestbookCommentSerialized{}, models.ErrNoRecord
}
}
func (m *GuestbookCommentModel) GetDeleted(guestbookId int64) ([]models.GuestbookComment, error) { func (m *GuestbookCommentModel) GetDeleted(guestbookId int64) ([]models.GuestbookComment, error) {
switch guestbookId { switch guestbookId {
default: default:

View File

@ -1,6 +1,7 @@
package mocks package mocks
import ( import (
"net/url"
"time" "time"
"git.32bit.cafe/32bitcafe/guestbook/internal/models" "git.32bit.cafe/32bitcafe/guestbook/internal/models"
@ -22,10 +23,14 @@ var mockGuestbook = models.Guestbook{
} }
var mockWebsite = models.Website{ var mockWebsite = models.Website{
ID: 1, ID: 1,
ShortId: 1, ShortId: 1,
Name: "Example", Name: "Example",
SiteUrl: "example.com", // SiteUrl: "example.com",
Url: &url.URL{
Scheme: "http",
Host: "example.com",
},
AuthorName: "John Test", AuthorName: "John Test",
UserId: 1, UserId: 1,
Created: time.Now(), Created: time.Now(),

View File

@ -3,15 +3,17 @@ package models
import ( import (
"database/sql" "database/sql"
"errors" "errors"
"net/url"
"strconv" "strconv"
"time" "time"
) )
type Website struct { type Website struct {
ID int64 ID int64
ShortId uint64 ShortId uint64
Name string Name string
SiteUrl string // SiteUrl string
Url *url.URL
AuthorName string AuthorName string
UserId int64 UserId int64
Created time.Time Created time.Time
@ -179,7 +181,8 @@ func (m *WebsiteModel) Get(shortId uint64) (Website, error) {
} }
row := tx.QueryRow(stmt, shortId) row := tx.QueryRow(stmt, shortId)
var w Website var w Website
err = row.Scan(&w.ID, &w.ShortId, &w.Name, &w.SiteUrl, &w.AuthorName, &w.UserId, &w.Created) var u string
err = row.Scan(&w.ID, &w.ShortId, &w.Name, &u, &w.AuthorName, &w.UserId, &w.Created)
if err != nil { if err != nil {
if errors.Is(err, sql.ErrNoRows) { if errors.Is(err, sql.ErrNoRows) {
err = ErrNoRecord err = ErrNoRecord
@ -189,6 +192,10 @@ func (m *WebsiteModel) Get(shortId uint64) (Website, error) {
} }
return Website{}, err return Website{}, err
} }
w.Url, err = url.Parse(u)
if err != nil {
return Website{}, err
}
stmt = `SELECT Id, ShortId, UserId, WebsiteId, Created, IsActive FROM guestbooks stmt = `SELECT Id, ShortId, UserId, WebsiteId, Created, IsActive FROM guestbooks
WHERE WebsiteId = ? AND Deleted IS NULL` WHERE WebsiteId = ? AND Deleted IS NULL`
@ -244,11 +251,16 @@ func (m *WebsiteModel) GetAllUser(userId int64) ([]Website, error) {
var websites []Website var websites []Website
for rows.Next() { for rows.Next() {
var w Website var w Website
err := rows.Scan(&w.ID, &w.ShortId, &w.Name, &w.SiteUrl, &w.AuthorName, &w.UserId, &w.Created, var u string
err := rows.Scan(&w.ID, &w.ShortId, &w.Name, &u, &w.AuthorName, &w.UserId, &w.Created,
&w.Guestbook.ID, &w.Guestbook.ShortId, &w.Guestbook.Created, &w.Guestbook.IsActive) &w.Guestbook.ID, &w.Guestbook.ShortId, &w.Guestbook.Created, &w.Guestbook.IsActive)
if err != nil { if err != nil {
return nil, err return nil, err
} }
w.Url, err = url.Parse(u)
if err != nil {
return nil, err
}
websites = append(websites, w) websites = append(websites, w)
} }
if err = rows.Err(); err != nil { if err = rows.Err(); err != nil {
@ -268,11 +280,16 @@ func (m *WebsiteModel) GetAll() ([]Website, error) {
var websites []Website var websites []Website
for rows.Next() { for rows.Next() {
var w Website var w Website
err := rows.Scan(&w.ID, &w.ShortId, &w.Name, &w.SiteUrl, &w.AuthorName, &w.UserId, &w.Created, var u string
err := rows.Scan(&w.ID, &w.ShortId, &w.Name, &u, &w.AuthorName, &w.UserId, &w.Created,
&w.Guestbook.ID, &w.Guestbook.ShortId, &w.Guestbook.Created, &w.Guestbook.IsActive) &w.Guestbook.ID, &w.Guestbook.ShortId, &w.Guestbook.Created, &w.Guestbook.IsActive)
if err != nil { if err != nil {
return nil, err return nil, err
} }
w.Url, err = url.Parse(u)
if err != nil {
return nil, err
}
websites = append(websites, w) websites = append(websites, w)
} }
if err = rows.Err(); err != nil { if err = rows.Err(); err != nil {

View File

@ -8,51 +8,52 @@ import (
) )
var EmailRX = regexp.MustCompile("^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$") var EmailRX = regexp.MustCompile("^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$")
var WebRX = regexp.MustCompile("^https?:\\/\\/")
type Validator struct { type Validator struct {
NonFieldErrors []string NonFieldErrors []string
FieldErrors map[string]string FieldErrors map[string]string
} }
func (v *Validator) Valid() bool { func (v *Validator) Valid() bool {
return len(v.FieldErrors) == 0 && len(v.NonFieldErrors) == 0 return len(v.FieldErrors) == 0 && len(v.NonFieldErrors) == 0
} }
func (v *Validator) AddFieldError(key, message string) { func (v *Validator) AddFieldError(key, message string) {
if v.FieldErrors == nil { if v.FieldErrors == nil {
v.FieldErrors = make(map[string]string) v.FieldErrors = make(map[string]string)
} }
if _, exists := v.FieldErrors[key]; !exists { if _, exists := v.FieldErrors[key]; !exists {
v.FieldErrors[key] = message v.FieldErrors[key] = message
} }
} }
func (v *Validator) AddNonFieldError(message string) { func (v *Validator) AddNonFieldError(message string) {
v.NonFieldErrors = append(v.NonFieldErrors, message) v.NonFieldErrors = append(v.NonFieldErrors, message)
} }
func (v *Validator) CheckField(ok bool, key, message string) { func (v *Validator) CheckField(ok bool, key, message string) {
if !ok { if !ok {
v.AddFieldError(key, message) v.AddFieldError(key, message)
} }
} }
func NotBlank(value string) bool { func NotBlank(value string) bool {
return strings.TrimSpace(value) != "" return strings.TrimSpace(value) != ""
} }
func MaxChars(value string, n int) bool { func MaxChars(value string, n int) bool {
return utf8.RuneCountInString(value) <= n return utf8.RuneCountInString(value) <= n
} }
func PermittedValue[T comparable](value T, permittedValues ...T) bool { func PermittedValue[T comparable](value T, permittedValues ...T) bool {
return slices.Contains(permittedValues, value) return slices.Contains(permittedValues, value)
} }
func MinChars(value string, n int) bool { func MinChars(value string, n int) bool {
return utf8.RuneCountInString(value) >= n return utf8.RuneCountInString(value) >= n
} }
func Matches(value string, rx *regexp.Regexp) bool { func Matches(value string, rx *regexp.Regexp) bool {
return rx.MatchString(value) return rx.MatchString(value)
} }

View File

@ -0,0 +1 @@
UPDATE websites SET SiteUrl = substr(SiteUrl, 8) WHERE substr(SiteUrl, 1, 4) = 'http';

View File

@ -0,0 +1 @@
UPDATE websites SET SiteUrl = 'http://' || SiteUrl WHERE substr(SiteUrl, 1, 4) <> 'http';

View File

@ -10,7 +10,7 @@ templ GuestbookDashboardCommentsView(title string, data CommonData, website mode
<div id="dashboard"> <div id="dashboard">
@wSidebar(website) @wSidebar(website)
<div> <div>
<h1>Comments on { website.SiteUrl }</h1> <h1>Comments on { website.Name }</h1>
<hr/> <hr/>
if len(comments) == 0 { if len(comments) == 0 {
<p>No comments yet!</p> <p>No comments yet!</p>

View File

@ -59,9 +59,9 @@ func GuestbookDashboardCommentsView(title string, data CommonData, website model
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
var templ_7745c5c3_Var3 string var templ_7745c5c3_Var3 string
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(website.SiteUrl) templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(website.Name)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/guestbooks.templ`, Line: 13, Col: 37} return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/guestbooks.templ`, Line: 13, Col: 34}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3)) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {

View File

@ -16,7 +16,7 @@ templ wSidebar(website models.Website) {
<h2>{ website.Name }</h2> <h2>{ website.Name }</h2>
<ul> <ul>
<li><a href={ templ.URL(dashUrl) }>Dashboard</a></li> <li><a href={ templ.URL(dashUrl) }>Dashboard</a></li>
<li><a href={ templ.URL(externalUrl(website.SiteUrl)) } target="_blank">View Website</a></li> <li><a href={ templ.URL(externalUrl(website.Url.String())) } target="_blank">View Website</a></li>
</ul> </ul>
<h3>Guestbook</h3> <h3>Guestbook</h3>
<ul> <ul>
@ -70,7 +70,7 @@ templ websiteCreateForm(csrfToken string, form forms.WebsiteCreateForm) {
if exists { if exists {
<label class="error">{ err }</label> <label class="error">{ err }</label>
} }
<input type="text" name="sitename" id="sitename" required/> <input type="text" name="sitename" id="sitename" value={ form.Name } required/>
</div> </div>
<div> <div>
{{ err, exists = form.FieldErrors["siteurl"] }} {{ err, exists = form.FieldErrors["siteurl"] }}
@ -78,7 +78,7 @@ templ websiteCreateForm(csrfToken string, form forms.WebsiteCreateForm) {
if exists { if exists {
<label class="error">{ err }</label> <label class="error">{ err }</label>
} }
<input type="text" name="siteurl" id="siteurl" required/> <input type="text" name="siteurl" id="siteurl" value={ form.SiteUrl } required/>
</div> </div>
<div> <div>
{{ err, exists = form.FieldErrors["authorname"] }} {{ err, exists = form.FieldErrors["authorname"] }}
@ -86,22 +86,18 @@ templ websiteCreateForm(csrfToken string, form forms.WebsiteCreateForm) {
if exists { if exists {
<label class="error">{ err }</label> <label class="error">{ err }</label>
} }
<input type="text" name="authorname" id="authorname" required/> <input type="text" name="authorname" id="authorname" value={ form.AuthorName } required/>
</div> </div>
<div> <div>
<button type="submit">Submit</button> <button type="submit">Submit</button>
</div> </div>
} }
templ WebsiteCreateButton() {
<button hx-get="/websites/create" hx-target="closest div">Add Website</button>
}
templ WebsiteList(title string, data CommonData, websites []models.Website) { templ WebsiteList(title string, data CommonData, websites []models.Website) {
@base(title, data) { @base(title, data) {
<h1>My Websites</h1> <h1>My Websites</h1>
<div> <div>
@WebsiteCreateButton() <a href="/websites/create">Add Website</a>
</div> </div>
<div> <div>
@displayWebsites(websites) @displayWebsites(websites)
@ -171,42 +167,9 @@ templ WebsiteDashboardComingSoon(title string, data CommonData, website models.W
} }
templ WebsiteCreate(title string, data CommonData, form forms.WebsiteCreateForm) { templ WebsiteCreate(title string, data CommonData, form forms.WebsiteCreateForm) {
<form hx-post="/websites/create" hx-target="closest div"> @base(title, data) {
@websiteCreateForm(data.CSRFToken, form) <form action="/websites/create" method="post">
</form> @websiteCreateForm(data.CSRFToken, form)
} </form>
}
templ embeddableForm(root string, website models.Website) {
{{ postUrl := fmt.Sprintf("https://%s/websites/%s/guestbook/comments/create/remote", root, shortIdToSlug(website.ShortId)) }}
{{formStr :=
`<form action="%s" method="post">
<div>
<label for="authorname">Name</label>
<input type="text" name="authorname" id="authorname"/>
</div>
<div>
<label for="authoremail">Email (Optional) </label>
<input type="text" name="authoremail" id="authoremail"/>
</div>
<div>
<label for="authorsite">Site Url (Optional) </label>
<input type="text" name="authorsite" id="authorsite"/>
</div>
<div>
<label for="content">Comment</label>
<textarea name="content" id="content"></textarea>
</div>
<div>
<input type="submit" value="Submit"/>
</div>
</form>`
}}
<pre>
<code>
{ fmt.Sprintf(formStr, postUrl) }
</code>
</pre>
}
templ embedJavaScriptSnippet(root string, website models.Website) {
} }

View File

@ -65,7 +65,7 @@ func wSidebar(website models.Website) templ.Component {
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
var templ_7745c5c3_Var4 templ.SafeURL = templ.URL(externalUrl(website.SiteUrl)) var templ_7745c5c3_Var4 templ.SafeURL = templ.URL(externalUrl(website.Url.String()))
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var4))) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var4)))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
@ -271,92 +271,102 @@ func websiteCreateForm(csrfToken string, form forms.WebsiteCreateForm) templ.Com
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
} }
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 23, "<input type=\"text\" name=\"sitename\" id=\"sitename\" required></div><div>") templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 23, "<input type=\"text\" name=\"sitename\" id=\"sitename\" value=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var18 string
templ_7745c5c3_Var18, templ_7745c5c3_Err = templ.JoinStringErrs(form.Name)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/websites.templ`, Line: 73, Col: 68}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var18))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 24, "\" required></div><div>")
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
err, exists = form.FieldErrors["siteurl"] err, exists = form.FieldErrors["siteurl"]
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 24, "<label for=\"siteurl\">Site URL: </label> ") templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 25, "<label for=\"siteurl\">Site URL: </label> ")
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
if exists { if exists {
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 25, "<label class=\"error\">") templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 26, "<label class=\"error\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var18 string
templ_7745c5c3_Var18, templ_7745c5c3_Err = templ.JoinStringErrs(err)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/websites.templ`, Line: 79, Col: 29}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var18))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 26, "</label> ")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 27, "<input type=\"text\" name=\"siteurl\" id=\"siteurl\" required></div><div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
err, exists = form.FieldErrors["authorname"]
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 28, "<label for=\"authorname\">Site Author: </label> ")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
if exists {
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 29, "<label class=\"error\">")
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
var templ_7745c5c3_Var19 string var templ_7745c5c3_Var19 string
templ_7745c5c3_Var19, templ_7745c5c3_Err = templ.JoinStringErrs(err) templ_7745c5c3_Var19, templ_7745c5c3_Err = templ.JoinStringErrs(err)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/websites.templ`, Line: 87, Col: 29} return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/websites.templ`, Line: 79, Col: 29}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var19)) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var19))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 30, "</label> ") templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 27, "</label> ")
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
} }
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 31, "<input type=\"text\" name=\"authorname\" id=\"authorname\" required></div><div><button type=\"submit\">Submit</button></div>") templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 28, "<input type=\"text\" name=\"siteurl\" id=\"siteurl\" value=\"")
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
return nil var templ_7745c5c3_Var20 string
}) templ_7745c5c3_Var20, templ_7745c5c3_Err = templ.JoinStringErrs(form.SiteUrl)
} if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/websites.templ`, Line: 81, Col: 69}
func WebsiteCreateButton() templ.Component {
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
return templ_7745c5c3_CtxErr
} }
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var20))
if !templ_7745c5c3_IsBuffer { if templ_7745c5c3_Err != nil {
defer func() { return templ_7745c5c3_Err
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
if templ_7745c5c3_Err == nil {
templ_7745c5c3_Err = templ_7745c5c3_BufErr
}
}()
} }
ctx = templ.InitializeContext(ctx) templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 29, "\" required></div><div>")
templ_7745c5c3_Var20 := templ.GetChildren(ctx) if templ_7745c5c3_Err != nil {
if templ_7745c5c3_Var20 == nil { return templ_7745c5c3_Err
templ_7745c5c3_Var20 = templ.NopComponent
} }
ctx = templ.ClearChildren(ctx) err, exists = form.FieldErrors["authorname"]
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 32, "<button hx-get=\"/websites/create\" hx-target=\"closest div\">Add Website</button>") templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 30, "<label for=\"authorname\">Site Author: </label> ")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
if exists {
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 31, "<label class=\"error\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var21 string
templ_7745c5c3_Var21, templ_7745c5c3_Err = templ.JoinStringErrs(err)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/websites.templ`, Line: 87, Col: 29}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var21))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 32, "</label> ")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 33, "<input type=\"text\" name=\"authorname\" id=\"authorname\" value=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var22 string
templ_7745c5c3_Var22, templ_7745c5c3_Err = templ.JoinStringErrs(form.AuthorName)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/websites.templ`, Line: 89, Col: 78}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var22))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 34, "\" required></div><div><button type=\"submit\">Submit</button></div>")
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
@ -365,69 +375,6 @@ func WebsiteCreateButton() templ.Component {
} }
func WebsiteList(title string, data CommonData, websites []models.Website) templ.Component { func WebsiteList(title string, data CommonData, websites []models.Website) templ.Component {
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
return templ_7745c5c3_CtxErr
}
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
if !templ_7745c5c3_IsBuffer {
defer func() {
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
if templ_7745c5c3_Err == nil {
templ_7745c5c3_Err = templ_7745c5c3_BufErr
}
}()
}
ctx = templ.InitializeContext(ctx)
templ_7745c5c3_Var21 := templ.GetChildren(ctx)
if templ_7745c5c3_Var21 == nil {
templ_7745c5c3_Var21 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
templ_7745c5c3_Var22 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
if !templ_7745c5c3_IsBuffer {
defer func() {
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
if templ_7745c5c3_Err == nil {
templ_7745c5c3_Err = templ_7745c5c3_BufErr
}
}()
}
ctx = templ.InitializeContext(ctx)
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 33, "<h1>My Websites</h1><div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = WebsiteCreateButton().Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 34, "</div><div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = displayWebsites(websites).Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 35, "</div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
return nil
})
templ_7745c5c3_Err = base(title, data).Render(templ.WithChildren(ctx, templ_7745c5c3_Var22), templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
return nil
})
}
func WebsiteDashboard(title string, data CommonData, website models.Website) templ.Component {
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
@ -460,7 +407,62 @@ func WebsiteDashboard(title string, data CommonData, website models.Website) tem
}() }()
} }
ctx = templ.InitializeContext(ctx) ctx = templ.InitializeContext(ctx)
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 36, "<div id=\"dashboard\">") templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 35, "<h1>My Websites</h1><div><a href=\"/websites/create\">Add Website</a></div><div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = displayWebsites(websites).Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 36, "</div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
return nil
})
templ_7745c5c3_Err = base(title, data).Render(templ.WithChildren(ctx, templ_7745c5c3_Var24), templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
return nil
})
}
func WebsiteDashboard(title string, data CommonData, website models.Website) templ.Component {
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
return templ_7745c5c3_CtxErr
}
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
if !templ_7745c5c3_IsBuffer {
defer func() {
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
if templ_7745c5c3_Err == nil {
templ_7745c5c3_Err = templ_7745c5c3_BufErr
}
}()
}
ctx = templ.InitializeContext(ctx)
templ_7745c5c3_Var25 := templ.GetChildren(ctx)
if templ_7745c5c3_Var25 == nil {
templ_7745c5c3_Var25 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
templ_7745c5c3_Var26 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
if !templ_7745c5c3_IsBuffer {
defer func() {
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
if templ_7745c5c3_Err == nil {
templ_7745c5c3_Err = templ_7745c5c3_BufErr
}
}()
}
ctx = templ.InitializeContext(ctx)
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 37, "<div id=\"dashboard\">")
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
@ -468,87 +470,87 @@ func WebsiteDashboard(title string, data CommonData, website models.Website) tem
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 37, "<div><h1>") templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 38, "<div><h1>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var25 string
templ_7745c5c3_Var25, templ_7745c5c3_Err = templ.JoinStringErrs(website.Name)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/websites.templ`, Line: 117, Col: 22}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var25))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 38, "</h1><h2>Embed your Guestbook</h2><p>Upload <a href=\"/static/js/guestbook.js\" download>this JavaScript WebComponent</a> to your site and include it in your <code>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var26 string
templ_7745c5c3_Var26, templ_7745c5c3_Err = templ.JoinStringErrs(`<head>`)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/websites.templ`, Line: 120, Col: 140}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var26))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 39, "</code> tag.</p><div><pre><code id=\"guestbookSnippet\">")
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
var templ_7745c5c3_Var27 string var templ_7745c5c3_Var27 string
templ_7745c5c3_Var27, templ_7745c5c3_Err = templ.JoinStringErrs( templ_7745c5c3_Var27, templ_7745c5c3_Err = templ.JoinStringErrs(website.Name)
`<head>
<script type="module" src="js/guestbook.js"></script>
</head>`)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/websites.templ`, Line: 129, Col: 8} return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/websites.templ`, Line: 113, Col: 22}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var27)) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var27))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 40, "</code></pre><p>Then add the custom elements where you want your form and comments to show up</p>") templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 39, "</h1><h2>Embed your Guestbook</h2><p>Upload <a href=\"/static/js/guestbook.js\" download>this JavaScript WebComponent</a> to your site and include it in your <code>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
gbUrl := fmt.Sprintf("https://%s/websites/%s/guestbook", data.RootUrl, shortIdToSlug(website.ShortId))
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 41, "<pre><code>")
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
var templ_7745c5c3_Var28 string var templ_7745c5c3_Var28 string
templ_7745c5c3_Var28, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf(`<guestbook-form guestbook="%s"></guestbook-form> templ_7745c5c3_Var28, templ_7745c5c3_Err = templ.JoinStringErrs(`<head>`)
<guestbook-comments guestbook="%s"></guestbook-comments>`, gbUrl, gbUrl))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/websites.templ`, Line: 140, Col: 72} return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/websites.templ`, Line: 116, Col: 140}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var28)) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var28))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 42, "</code></pre></div><p>If your web host does not allow CORS requests, use an iframe instead</p><div><pre><code>") templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 40, "</code> tag.</p><div><pre><code id=\"guestbookSnippet\">")
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
var templ_7745c5c3_Var29 string var templ_7745c5c3_Var29 string
templ_7745c5c3_Var29, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf(`<iframe src="%s" title="Guestbook"></iframe>`, gbUrl)) templ_7745c5c3_Var29, templ_7745c5c3_Err = templ.JoinStringErrs(
`<head>
<script type="module" src="js/guestbook.js"></script>
</head>`)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/websites.templ`, Line: 150, Col: 75} return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/websites.templ`, Line: 125, Col: 8}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var29)) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var29))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 43, "</code></pre></div></div></div>") templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 41, "</code></pre><p>Then add the custom elements where you want your form and comments to show up</p>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
gbUrl := fmt.Sprintf("https://%s/websites/%s/guestbook", data.RootUrl, shortIdToSlug(website.ShortId))
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 42, "<pre><code>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var30 string
templ_7745c5c3_Var30, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf(`<guestbook-form guestbook="%s"></guestbook-form>
<guestbook-comments guestbook="%s"></guestbook-comments>`, gbUrl, gbUrl))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/websites.templ`, Line: 136, Col: 72}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var30))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 43, "</code></pre></div><p>If your web host does not allow CORS requests, use an iframe instead</p><div><pre><code>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var31 string
templ_7745c5c3_Var31, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf(`<iframe src="%s" title="Guestbook"></iframe>`, gbUrl))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/websites.templ`, Line: 146, Col: 75}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var31))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 44, "</code></pre></div></div></div>")
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
return nil return nil
}) })
templ_7745c5c3_Err = base(title, data).Render(templ.WithChildren(ctx, templ_7745c5c3_Var24), templ_7745c5c3_Buffer) templ_7745c5c3_Err = base(title, data).Render(templ.WithChildren(ctx, templ_7745c5c3_Var26), templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
@ -572,12 +574,12 @@ func WebsiteDashboardComingSoon(title string, data CommonData, website models.We
}() }()
} }
ctx = templ.InitializeContext(ctx) ctx = templ.InitializeContext(ctx)
templ_7745c5c3_Var30 := templ.GetChildren(ctx) templ_7745c5c3_Var32 := templ.GetChildren(ctx)
if templ_7745c5c3_Var30 == nil { if templ_7745c5c3_Var32 == nil {
templ_7745c5c3_Var30 = templ.NopComponent templ_7745c5c3_Var32 = templ.NopComponent
} }
ctx = templ.ClearChildren(ctx) ctx = templ.ClearChildren(ctx)
templ_7745c5c3_Var31 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { templ_7745c5c3_Var33 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
if !templ_7745c5c3_IsBuffer { if !templ_7745c5c3_IsBuffer {
@ -589,7 +591,7 @@ func WebsiteDashboardComingSoon(title string, data CommonData, website models.We
}() }()
} }
ctx = templ.InitializeContext(ctx) ctx = templ.InitializeContext(ctx)
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 44, "<div id=\"dashboard\">") templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 45, "<div id=\"dashboard\">")
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
@ -597,26 +599,26 @@ func WebsiteDashboardComingSoon(title string, data CommonData, website models.We
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 45, "<div><h1>") templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 46, "<div><h1>")
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
var templ_7745c5c3_Var32 string var templ_7745c5c3_Var34 string
templ_7745c5c3_Var32, templ_7745c5c3_Err = templ.JoinStringErrs(website.Name) templ_7745c5c3_Var34, templ_7745c5c3_Err = templ.JoinStringErrs(website.Name)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/websites.templ`, Line: 164, Col: 22} return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/websites.templ`, Line: 160, Col: 22}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var32)) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var34))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 46, "</h1><p>Coming Soon</p></div></div>") templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 47, "</h1><p>Coming Soon</p></div></div>")
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
return nil return nil
}) })
templ_7745c5c3_Err = base(title, data).Render(templ.WithChildren(ctx, templ_7745c5c3_Var31), templ_7745c5c3_Buffer) templ_7745c5c3_Err = base(title, data).Render(templ.WithChildren(ctx, templ_7745c5c3_Var33), templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
@ -640,113 +642,41 @@ func WebsiteCreate(title string, data CommonData, form forms.WebsiteCreateForm)
}() }()
} }
ctx = templ.InitializeContext(ctx) ctx = templ.InitializeContext(ctx)
templ_7745c5c3_Var33 := templ.GetChildren(ctx) templ_7745c5c3_Var35 := templ.GetChildren(ctx)
if templ_7745c5c3_Var33 == nil { if templ_7745c5c3_Var35 == nil {
templ_7745c5c3_Var33 = templ.NopComponent templ_7745c5c3_Var35 = templ.NopComponent
} }
ctx = templ.ClearChildren(ctx) ctx = templ.ClearChildren(ctx)
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 47, "<form hx-post=\"/websites/create\" hx-target=\"closest div\">") templ_7745c5c3_Var36 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
if !templ_7745c5c3_IsBuffer {
defer func() {
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
if templ_7745c5c3_Err == nil {
templ_7745c5c3_Err = templ_7745c5c3_BufErr
}
}()
}
ctx = templ.InitializeContext(ctx)
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 48, "<form action=\"/websites/create\" method=\"post\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = websiteCreateForm(data.CSRFToken, form).Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 49, "</form>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
return nil
})
templ_7745c5c3_Err = base(title, data).Render(templ.WithChildren(ctx, templ_7745c5c3_Var36), templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
templ_7745c5c3_Err = websiteCreateForm(data.CSRFToken, form).Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 48, "</form>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
return nil
})
}
func embeddableForm(root string, website models.Website) templ.Component {
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
return templ_7745c5c3_CtxErr
}
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
if !templ_7745c5c3_IsBuffer {
defer func() {
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
if templ_7745c5c3_Err == nil {
templ_7745c5c3_Err = templ_7745c5c3_BufErr
}
}()
}
ctx = templ.InitializeContext(ctx)
templ_7745c5c3_Var34 := templ.GetChildren(ctx)
if templ_7745c5c3_Var34 == nil {
templ_7745c5c3_Var34 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
postUrl := fmt.Sprintf("https://%s/websites/%s/guestbook/comments/create/remote", root, shortIdToSlug(website.ShortId))
formStr :=
`<form action="%s" method="post">
<div>
<label for="authorname">Name</label>
<input type="text" name="authorname" id="authorname"/>
</div>
<div>
<label for="authoremail">Email (Optional) </label>
<input type="text" name="authoremail" id="authoremail"/>
</div>
<div>
<label for="authorsite">Site Url (Optional) </label>
<input type="text" name="authorsite" id="authorsite"/>
</div>
<div>
<label for="content">Comment</label>
<textarea name="content" id="content"></textarea>
</div>
<div>
<input type="submit" value="Submit"/>
</div>
</form>`
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 49, "<pre><code>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var35 string
templ_7745c5c3_Var35, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf(formStr, postUrl))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/websites.templ`, Line: 206, Col: 34}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var35))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 50, "</code></pre>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
return nil
})
}
func embedJavaScriptSnippet(root string, website models.Website) templ.Component {
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
return templ_7745c5c3_CtxErr
}
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
if !templ_7745c5c3_IsBuffer {
defer func() {
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
if templ_7745c5c3_Err == nil {
templ_7745c5c3_Err = templ_7745c5c3_BufErr
}
}()
}
ctx = templ.InitializeContext(ctx)
templ_7745c5c3_Var36 := templ.GetChildren(ctx)
if templ_7745c5c3_Var36 == nil {
templ_7745c5c3_Var36 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
return nil return nil
}) })
} }