convert most frontend to templ, implement design wireframes
This commit is contained in:
		
							parent
							
								
									19364225c9
								
							
						
					
					
						commit
						d899769ba0
					
				@ -5,57 +5,49 @@ import (
 | 
				
			|||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
	"net/http"
 | 
						"net/http"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        "git.32bit.cafe/32bitcafe/guestbook/internal/forms"
 | 
				
			||||||
	"git.32bit.cafe/32bitcafe/guestbook/internal/models"
 | 
						"git.32bit.cafe/32bitcafe/guestbook/internal/models"
 | 
				
			||||||
	"git.32bit.cafe/32bitcafe/guestbook/internal/validator"
 | 
						"git.32bit.cafe/32bitcafe/guestbook/internal/validator"
 | 
				
			||||||
 | 
						"git.32bit.cafe/32bitcafe/guestbook/ui/views"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (app *application) home(w http.ResponseWriter, r *http.Request) {
 | 
					func (app *application) home(w http.ResponseWriter, r *http.Request) {
 | 
				
			||||||
    data := app.newTemplateData(r)
 | 
					    data := app.newCommonData(r)
 | 
				
			||||||
    app.render(w, r, http.StatusOK, "home.tmpl.html", data)
 | 
					    views.Home("Home", data).Render(r.Context(), w)
 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type userRegistrationForm struct {
 | 
					 | 
				
			||||||
    Name        string  `schema:"username"`
 | 
					 | 
				
			||||||
    Email       string  `schema:"email"`
 | 
					 | 
				
			||||||
    Password    string  `schema:"password"`
 | 
					 | 
				
			||||||
    validator.Validator `schema:"-"`
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (app *application) getUserRegister(w http.ResponseWriter, r *http.Request) {
 | 
					func (app *application) getUserRegister(w http.ResponseWriter, r *http.Request) {
 | 
				
			||||||
    data := app.newTemplateData(r)
 | 
					    form := forms.UserRegistrationForm{}
 | 
				
			||||||
    data.Form = userRegistrationForm{}
 | 
					    data := app.newCommonData(r)
 | 
				
			||||||
    app.render(w, r, http.StatusOK, "usercreate.view.tmpl.html", data)
 | 
					    views.UserRegistration("User Registration", data, form).Render(r.Context(), w)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (app *application) postUserRegister(w http.ResponseWriter, r *http.Request) {
 | 
					func (app *application) postUserRegister(w http.ResponseWriter, r *http.Request) {
 | 
				
			||||||
    var form userRegistrationForm
 | 
					    var form forms.UserRegistrationForm
 | 
				
			||||||
    err := app.decodePostForm(r, &form)
 | 
					    err := app.decodePostForm(r, &form)
 | 
				
			||||||
    if err != nil {
 | 
					    if err != nil {
 | 
				
			||||||
        app.clientError(w, http.StatusBadRequest)
 | 
					        app.clientError(w, http.StatusBadRequest)
 | 
				
			||||||
        return
 | 
					        return
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    form.CheckField(validator.NotBlank(form.Name), "name", "This field cannot be blank")
 | 
					    form.CheckField(validator.NotBlank(form.Name), "name", "This field cannot be blank")
 | 
				
			||||||
    form.CheckField(validator.NotBlank(form.Email), "email", "This field cannot be blank")
 | 
					    form.CheckField(validator.NotBlank(form.Email), "email", "This field cannot be blank")
 | 
				
			||||||
    form.CheckField(validator.Matches(form.Email, validator.EmailRX), "email", "This field must be a valid email address")
 | 
					    form.CheckField(validator.Matches(form.Email, validator.EmailRX), "email", "This field must be a valid email address")
 | 
				
			||||||
    form.CheckField(validator.NotBlank(form.Password), "password", "This field cannot be blank")
 | 
					    form.CheckField(validator.NotBlank(form.Password), "password", "This field cannot be blank")
 | 
				
			||||||
    form.CheckField(validator.MinChars(form.Password, 8), "password", "This field must be at least 8 characters long")
 | 
					    form.CheckField(validator.MinChars(form.Password, 8), "password", "This field must be at least 8 characters long")
 | 
				
			||||||
 | 
					 | 
				
			||||||
    if !form.Valid() {
 | 
					    if !form.Valid() {
 | 
				
			||||||
        data := app.newTemplateData(r)
 | 
					        data := app.newCommonData(r)
 | 
				
			||||||
        data.Form = form
 | 
					        w.WriteHeader(http.StatusUnprocessableEntity)
 | 
				
			||||||
        app.render(w, r, http.StatusUnprocessableEntity, "usercreate.view.tmpl.html", data)
 | 
					        views.UserRegistration("User Registration", data, form).Render(r.Context(), w)
 | 
				
			||||||
        return
 | 
					        return
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					 | 
				
			||||||
    shortId := app.createShortId()
 | 
					    shortId := app.createShortId()
 | 
				
			||||||
    err = app.users.Insert(shortId, form.Name, form.Email, form.Password)
 | 
					    err = app.users.Insert(shortId, form.Name, form.Email, form.Password)
 | 
				
			||||||
    if err != nil {
 | 
					    if err != nil {
 | 
				
			||||||
        if errors.Is(err, models.ErrDuplicateEmail) {
 | 
					        if errors.Is(err, models.ErrDuplicateEmail) {
 | 
				
			||||||
            form.AddFieldError("email", "Email address is already in use")
 | 
					            form.AddFieldError("email", "Email address is already in use")
 | 
				
			||||||
            data := app.newTemplateData(r)
 | 
					            data := app.newCommonData(r)
 | 
				
			||||||
            data.Form = form
 | 
					            w.WriteHeader(http.StatusUnprocessableEntity)
 | 
				
			||||||
            app.render(w ,r, http.StatusUnprocessableEntity, "usercreate.view.tmpl.html", data)
 | 
					            views.UserRegistration("User Registration", data, form).Render(r.Context(), w)
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            app.serverError(w, r, err)
 | 
					            app.serverError(w, r, err)
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@ -65,58 +57,42 @@ func (app *application) postUserRegister(w http.ResponseWriter, r *http.Request)
 | 
				
			|||||||
    http.Redirect(w, r, "/users/login", http.StatusSeeOther)
 | 
					    http.Redirect(w, r, "/users/login", http.StatusSeeOther)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type userLoginForm struct {
 | 
					 | 
				
			||||||
    Email       string  `schema:"email"`
 | 
					 | 
				
			||||||
    Password    string  `schema:"password"`
 | 
					 | 
				
			||||||
    validator.Validator `schema:"-"`
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (app *application) getUserLogin(w http.ResponseWriter, r *http.Request) {
 | 
					func (app *application) getUserLogin(w http.ResponseWriter, r *http.Request) {
 | 
				
			||||||
    data := app.newTemplateData(r)
 | 
					    views.UserLogin("Login", app.newCommonData(r), forms.UserLoginForm{}).Render(r.Context(), w)
 | 
				
			||||||
    data.Form = userLoginForm{}
 | 
					 | 
				
			||||||
    app.render(w, r, http.StatusOK, "login.view.tmpl.html", data)
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (app *application) postUserLogin(w http.ResponseWriter, r *http.Request) {
 | 
					func (app *application) postUserLogin(w http.ResponseWriter, r *http.Request) {
 | 
				
			||||||
    var form userLoginForm
 | 
					    var form forms.UserLoginForm
 | 
				
			||||||
 | 
					 | 
				
			||||||
    err := app.decodePostForm(r, &form)
 | 
					    err := app.decodePostForm(r, &form)
 | 
				
			||||||
    if err != nil {
 | 
					    if err != nil {
 | 
				
			||||||
        app.clientError(w, http.StatusBadRequest)
 | 
					        app.clientError(w, http.StatusBadRequest)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					 | 
				
			||||||
    form.CheckField(validator.NotBlank(form.Email), "email", "This field cannot be blank")
 | 
					    form.CheckField(validator.NotBlank(form.Email), "email", "This field cannot be blank")
 | 
				
			||||||
    form.CheckField(validator.Matches(form.Email, validator.EmailRX), "email", "This field must be a valid email address")
 | 
					    form.CheckField(validator.Matches(form.Email, validator.EmailRX), "email", "This field must be a valid email address")
 | 
				
			||||||
    form.CheckField(validator.NotBlank(form.Password), "password", "This field cannot be blank")
 | 
					    form.CheckField(validator.NotBlank(form.Password), "password", "This field cannot be blank")
 | 
				
			||||||
 | 
					 | 
				
			||||||
    if !form.Valid() {
 | 
					    if !form.Valid() {
 | 
				
			||||||
        data := app.newTemplateData(r)
 | 
					        data := app.newCommonData(r)
 | 
				
			||||||
        data.Form = userLoginForm{}
 | 
					        w.WriteHeader(http.StatusUnprocessableEntity)
 | 
				
			||||||
        app.render(w, r, http.StatusUnprocessableEntity, "login.view.tmpl.html", data)
 | 
					        views.UserLogin("Login", data, form).Render(r.Context(), w)
 | 
				
			||||||
        return
 | 
					        return
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					 | 
				
			||||||
    id, err := app.users.Authenticate(form.Email, form.Password)
 | 
					    id, err := app.users.Authenticate(form.Email, form.Password)
 | 
				
			||||||
    if err != nil {
 | 
					    if err != nil {
 | 
				
			||||||
        if errors.Is(err, models.ErrInvalidCredentials) {
 | 
					        if errors.Is(err, models.ErrInvalidCredentials) {
 | 
				
			||||||
            form.AddNonFieldError("Email or password is incorrect")
 | 
					            form.AddNonFieldError("Email or password is incorrect")
 | 
				
			||||||
            data := app.newTemplateData(r)
 | 
					            data := app.newCommonData(r)
 | 
				
			||||||
            data.Form = form
 | 
					            views.UserLogin("Login", data, form).Render(r.Context(), w)
 | 
				
			||||||
            app.render(w, r, http.StatusUnprocessableEntity, "login.view.tmpl.html", data)
 | 
					 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            app.serverError(w, r, err)
 | 
					            app.serverError(w, r, err)
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        return
 | 
					        return
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					 | 
				
			||||||
    err = app.sessionManager.RenewToken(r.Context())
 | 
					    err = app.sessionManager.RenewToken(r.Context())
 | 
				
			||||||
    if err != nil {
 | 
					    if err != nil {
 | 
				
			||||||
        app.serverError(w, r, err)
 | 
					        app.serverError(w, r, err)
 | 
				
			||||||
        return
 | 
					        return
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					 | 
				
			||||||
    app.sessionManager.Put(r.Context(), "authenticatedUserId", id)
 | 
					    app.sessionManager.Put(r.Context(), "authenticatedUserId", id)
 | 
				
			||||||
 | 
					 | 
				
			||||||
    http.Redirect(w, r, "/", http.StatusSeeOther)
 | 
					    http.Redirect(w, r, "/", http.StatusSeeOther)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -126,13 +102,14 @@ func (app *application) postUserLogout(w http.ResponseWriter, r *http.Request) {
 | 
				
			|||||||
        app.serverError(w, r, err)
 | 
					        app.serverError(w, r, err)
 | 
				
			||||||
        return
 | 
					        return
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					 | 
				
			||||||
    app.sessionManager.Remove(r.Context(), "authenticatedUserId")
 | 
					    app.sessionManager.Remove(r.Context(), "authenticatedUserId")
 | 
				
			||||||
    app.sessionManager.Put(r.Context(), "flash", "You've been logged out successfully!")
 | 
					    app.sessionManager.Put(r.Context(), "flash", "You've been logged out successfully!")
 | 
				
			||||||
    http.Redirect(w, r, "/", http.StatusSeeOther)
 | 
					    http.Redirect(w, r, "/", http.StatusSeeOther)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (app *application) getUsersList(w http.ResponseWriter, r *http.Request) {
 | 
					func (app *application) getUsersList(w http.ResponseWriter, r *http.Request) {
 | 
				
			||||||
 | 
					    // skip templ conversion for this view, which will not be available in the final app
 | 
				
			||||||
 | 
					    // something similar will be available in the admin panel
 | 
				
			||||||
    users, err := app.users.GetAll()
 | 
					    users, err := app.users.GetAll()
 | 
				
			||||||
    if err != nil {
 | 
					    if err != nil {
 | 
				
			||||||
        app.serverError(w, r, err)
 | 
					        app.serverError(w, r, err)
 | 
				
			||||||
@ -154,18 +131,13 @@ func (app *application) getUser(w http.ResponseWriter, r *http.Request) {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
        return
 | 
					        return
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    data := app.newTemplateData(r)
 | 
					    data := app.newCommonData(r)
 | 
				
			||||||
    data.User = user
 | 
					    views.UserProfile(user.Username, data, user).Render(r.Context(), w)
 | 
				
			||||||
    app.render(w, r, http.StatusOK, "user.view.tmpl.html", data)
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (app *application) getGuestbookCreate(w http.ResponseWriter, r* http.Request) {
 | 
					func (app *application) getGuestbookCreate(w http.ResponseWriter, r* http.Request) {
 | 
				
			||||||
    data := app.newTemplateData(r)
 | 
					    data := app.newCommonData(r)
 | 
				
			||||||
    if r.Header.Get("HX-Request") == "true" {
 | 
					    views.GuestbookCreate("New Guestbook", data).Render(r.Context(), w)
 | 
				
			||||||
        app.renderHTMX(w, r, http.StatusOK, "guestbookcreate.part.html", data)
 | 
					 | 
				
			||||||
        return
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    app.render(w, r, http.StatusOK, "guestbookcreate.view.tmpl.html", data)
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (app *application) postGuestbookCreate(w http.ResponseWriter, r* http.Request) {
 | 
					func (app *application) postGuestbookCreate(w http.ResponseWriter, r* http.Request) {
 | 
				
			||||||
@ -194,24 +166,13 @@ func (app *application) postGuestbookCreate(w http.ResponseWriter, r* http.Reque
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
func (app *application) getGuestbookList(w http.ResponseWriter, r *http.Request) {
 | 
					func (app *application) getGuestbookList(w http.ResponseWriter, r *http.Request) {
 | 
				
			||||||
    userId := app.sessionManager.GetInt64(r.Context(), "authenticatedUserId")
 | 
					    userId := app.sessionManager.GetInt64(r.Context(), "authenticatedUserId")
 | 
				
			||||||
    user, err := app.users.GetById(userId)
 | 
					 | 
				
			||||||
    if err != nil {
 | 
					 | 
				
			||||||
        app.serverError(w, r, err)
 | 
					 | 
				
			||||||
        return
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    guestbooks, err := app.guestbooks.GetAll(userId)
 | 
					    guestbooks, err := app.guestbooks.GetAll(userId)
 | 
				
			||||||
    if err != nil {
 | 
					    if err != nil {
 | 
				
			||||||
        app.serverError(w, r, err)
 | 
					        app.serverError(w, r, err)
 | 
				
			||||||
        return
 | 
					        return
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    data := app.newTemplateData(r)
 | 
					    data := app.newCommonData(r)
 | 
				
			||||||
    data.Guestbooks = guestbooks
 | 
					    views.GuestbookList("Guestbooks", data, guestbooks).Render(r.Context(), w)
 | 
				
			||||||
    data.User = user
 | 
					 | 
				
			||||||
    if r.Header.Get("HX-Request") == "true" {
 | 
					 | 
				
			||||||
        app.renderHTMX(w, r, http.StatusCreated, "guestbooklist.part.html", data)
 | 
					 | 
				
			||||||
        return
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    app.render(w, r, http.StatusOK, "guestbooklist.view.tmpl.html", data)
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (app *application) getGuestbook(w http.ResponseWriter, r *http.Request) {
 | 
					func (app *application) getGuestbook(w http.ResponseWriter, r *http.Request) {
 | 
				
			||||||
@ -230,10 +191,8 @@ func (app *application) getGuestbook(w http.ResponseWriter, r *http.Request) {
 | 
				
			|||||||
        app.serverError(w, r, err)
 | 
					        app.serverError(w, r, err)
 | 
				
			||||||
        return
 | 
					        return
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    data := app.newTemplateData(r)
 | 
					    data := app.newCommonData(r)
 | 
				
			||||||
    data.Guestbook = guestbook
 | 
					    views.GuestbookView("Guestbook", data, guestbook, comments).Render(r.Context(), w)
 | 
				
			||||||
    data.Comments = comments
 | 
					 | 
				
			||||||
    app.render(w, r, http.StatusOK, "guestbook.view.tmpl.html", data)
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (app *application) getGuestbookComments(w http.ResponseWriter, r *http.Request) {
 | 
					func (app *application) getGuestbookComments(w http.ResponseWriter, r *http.Request) {
 | 
				
			||||||
@ -267,6 +226,7 @@ type commentCreateForm struct {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (app *application) getGuestbookCommentCreate(w http.ResponseWriter, r *http.Request) {
 | 
					func (app *application) getGuestbookCommentCreate(w http.ResponseWriter, r *http.Request) {
 | 
				
			||||||
 | 
					    // TODO: This will be the embeddable form
 | 
				
			||||||
    slug := r.PathValue("id")
 | 
					    slug := r.PathValue("id")
 | 
				
			||||||
    guestbook, err := app.guestbooks.Get(slugToShortId(slug))
 | 
					    guestbook, err := app.guestbooks.Get(slugToShortId(slug))
 | 
				
			||||||
    if err != nil {
 | 
					    if err != nil {
 | 
				
			||||||
@ -324,7 +284,7 @@ func (app *application) postGuestbookCommentCreate(w http.ResponseWriter, r *htt
 | 
				
			|||||||
        app.serverError(w, r, err)
 | 
					        app.serverError(w, r, err)
 | 
				
			||||||
        return
 | 
					        return
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    app.sessionManager.Put(r.Context(), "flash", "Comment successfully posted!")
 | 
					    // app.sessionManager.Put(r.Context(), "flash", "Comment successfully posted!")
 | 
				
			||||||
    http.Redirect(w, r, fmt.Sprintf("/guestbooks/%s", guestbookSlug), http.StatusSeeOther)
 | 
					    http.Redirect(w, r, fmt.Sprintf("/guestbooks/%s", guestbookSlug), http.StatusSeeOther)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -41,6 +41,21 @@ func (app *application) renderHTMX(w http.ResponseWriter, r *http.Request, statu
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (app *application) renderFullPage(w http.ResponseWriter, r *http.Request, status int, page string, data templateData) {
 | 
				
			||||||
 | 
					    ts, ok := app.templateCache[page]
 | 
				
			||||||
 | 
					    if !ok {
 | 
				
			||||||
 | 
					        err := fmt.Errorf("the template %s does not exist", page)
 | 
				
			||||||
 | 
					        app.serverError(w, r, err)
 | 
				
			||||||
 | 
					        return
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    w.WriteHeader(status)
 | 
				
			||||||
 | 
					    err := ts.ExecuteTemplate(w, "base", data)
 | 
				
			||||||
 | 
					    if err != nil {
 | 
				
			||||||
 | 
					        app.serverError(w, r, err)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (app *application) render(w http.ResponseWriter, r *http.Request, status int, page string, data templateData) {
 | 
					func (app *application) render(w http.ResponseWriter, r *http.Request, status int, page string, data templateData) {
 | 
				
			||||||
    ts, ok := app.templateCache[page]
 | 
					    ts, ok := app.templateCache[page]
 | 
				
			||||||
    if !ok {
 | 
					    if !ok {
 | 
				
			||||||
 | 
				
			|||||||
@ -12,9 +12,10 @@ func (app *application) routes() http.Handler {
 | 
				
			|||||||
    mux.Handle("GET /static/", http.StripPrefix("/static", fileServer))
 | 
					    mux.Handle("GET /static/", http.StripPrefix("/static", fileServer))
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    dynamic := alice.New(app.sessionManager.LoadAndSave, noSurf, app.authenticate)
 | 
					    dynamic := alice.New(app.sessionManager.LoadAndSave, noSurf, app.authenticate)
 | 
				
			||||||
 | 
					    standard := alice.New(app.recoverPanic, app.logRequest, commonHeaders)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    mux.Handle("/{$}", dynamic.ThenFunc(app.home))
 | 
					    mux.Handle("/{$}", dynamic.ThenFunc(app.home))
 | 
				
			||||||
    mux.Handle("POST /guestbooks/{id}/comments/create", dynamic.ThenFunc(app.postGuestbookCommentCreate))
 | 
					    mux.Handle("POST /guestbooks/{id}/comments/create", standard.ThenFunc(app.postGuestbookCommentCreate))
 | 
				
			||||||
    mux.Handle("GET /guestbooks/{id}", dynamic.ThenFunc(app.getGuestbook))
 | 
					    mux.Handle("GET /guestbooks/{id}", dynamic.ThenFunc(app.getGuestbook))
 | 
				
			||||||
    mux.Handle("GET /users/register", dynamic.ThenFunc(app.getUserRegister))
 | 
					    mux.Handle("GET /users/register", dynamic.ThenFunc(app.getUserRegister))
 | 
				
			||||||
    mux.Handle("POST /users/register", dynamic.ThenFunc(app.postUserRegister))
 | 
					    mux.Handle("POST /users/register", dynamic.ThenFunc(app.postUserRegister))
 | 
				
			||||||
@ -31,7 +32,6 @@ func (app *application) routes() http.Handler {
 | 
				
			|||||||
    mux.Handle("POST /guestbooks/create", protected.ThenFunc(app.postGuestbookCreate))
 | 
					    mux.Handle("POST /guestbooks/create", protected.ThenFunc(app.postGuestbookCreate))
 | 
				
			||||||
    mux.Handle("GET /guestbooks/{id}/comments/create", protected.ThenFunc(app.getGuestbookCommentCreate))
 | 
					    mux.Handle("GET /guestbooks/{id}/comments/create", protected.ThenFunc(app.getGuestbookCommentCreate))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    standard := alice.New(app.recoverPanic, app.logRequest, commonHeaders)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return standard.Then(mux)
 | 
					    return standard.Then(mux)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -7,6 +7,7 @@ import (
 | 
				
			|||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"git.32bit.cafe/32bitcafe/guestbook/internal/models"
 | 
						"git.32bit.cafe/32bitcafe/guestbook/internal/models"
 | 
				
			||||||
 | 
						"git.32bit.cafe/32bitcafe/guestbook/ui/views"
 | 
				
			||||||
	"github.com/justinas/nosurf"
 | 
						"github.com/justinas/nosurf"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -77,6 +78,17 @@ func newTemplateCache() (map[string]*template.Template, error) {
 | 
				
			|||||||
    return cache, nil
 | 
					    return cache, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (app *application) newCommonData(r *http.Request) views.CommonData {
 | 
				
			||||||
 | 
					    return views.CommonData {
 | 
				
			||||||
 | 
					        CurrentYear: time.Now().Year(),
 | 
				
			||||||
 | 
					        Flash: app.sessionManager.PopString(r.Context(), "flash"),
 | 
				
			||||||
 | 
					        IsAuthenticated: app.isAuthenticated(r),
 | 
				
			||||||
 | 
					        CSRFToken: nosurf.Token(r),
 | 
				
			||||||
 | 
					        CurrentUser: app.getCurrentUser(r),
 | 
				
			||||||
 | 
					        IsHtmx: r.Header.Get("Hx-Request") == "true",
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (app *application) newTemplateData(r *http.Request) templateData {
 | 
					func (app *application) newTemplateData(r *http.Request) templateData {
 | 
				
			||||||
    return templateData {
 | 
					    return templateData {
 | 
				
			||||||
        CurrentYear: time.Now().Year(),
 | 
					        CurrentYear: time.Now().Year(),
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										1
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								go.mod
									
									
									
									
									
								
							@ -10,6 +10,7 @@ require (
 | 
				
			|||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
require (
 | 
					require (
 | 
				
			||||||
 | 
						github.com/a-h/templ v0.3.833 // indirect
 | 
				
			||||||
	github.com/gorilla/schema v1.4.1 // indirect
 | 
						github.com/gorilla/schema v1.4.1 // indirect
 | 
				
			||||||
	github.com/justinas/alice v1.2.0 // indirect
 | 
						github.com/justinas/alice v1.2.0 // indirect
 | 
				
			||||||
	github.com/justinas/nosurf v1.1.1 // indirect
 | 
						github.com/justinas/nosurf v1.1.1 // indirect
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										2
									
								
								go.sum
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								go.sum
									
									
									
									
									
								
							@ -1,3 +1,5 @@
 | 
				
			|||||||
 | 
					github.com/a-h/templ v0.3.833 h1:L/KOk/0VvVTBegtE0fp2RJQiBm7/52Zxv5fqlEHiQUU=
 | 
				
			||||||
 | 
					github.com/a-h/templ v0.3.833/go.mod h1:cAu4AiZhtJfBjMY0HASlyzvkrtjnHWPeEsyGK2YYmfk=
 | 
				
			||||||
github.com/alexedwards/scs/sqlite3store v0.0.0-20240316134038-7e11d57e8885 h1:+DCxWg/ojncqS+TGAuRUoV7OfG/S4doh0pcpAwEcow0=
 | 
					github.com/alexedwards/scs/sqlite3store v0.0.0-20240316134038-7e11d57e8885 h1:+DCxWg/ojncqS+TGAuRUoV7OfG/S4doh0pcpAwEcow0=
 | 
				
			||||||
github.com/alexedwards/scs/sqlite3store v0.0.0-20240316134038-7e11d57e8885/go.mod h1:Iyk7S76cxGaiEX/mSYmTZzYehp4KfyylcLaV3OnToss=
 | 
					github.com/alexedwards/scs/sqlite3store v0.0.0-20240316134038-7e11d57e8885/go.mod h1:Iyk7S76cxGaiEX/mSYmTZzYehp4KfyylcLaV3OnToss=
 | 
				
			||||||
github.com/alexedwards/scs/v2 v2.8.0 h1:h31yUYoycPuL0zt14c0gd+oqxfRwIj6SOjHdKRZxhEw=
 | 
					github.com/alexedwards/scs/v2 v2.8.0 h1:h31yUYoycPuL0zt14c0gd+oqxfRwIj6SOjHdKRZxhEw=
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										17
									
								
								internal/forms/forms.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								internal/forms/forms.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,17 @@
 | 
				
			|||||||
 | 
					package forms
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "git.32bit.cafe/32bitcafe/guestbook/internal/validator"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type UserRegistrationForm struct {
 | 
				
			||||||
 | 
					    Name        string  `schema:"username"`
 | 
				
			||||||
 | 
					    Email       string  `schema:"email"`
 | 
				
			||||||
 | 
					    Password    string  `schema:"password"`
 | 
				
			||||||
 | 
					    validator.Validator `schema:"-"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type UserLoginForm struct {
 | 
				
			||||||
 | 
					    Email       string  `schema:"email"`
 | 
				
			||||||
 | 
					    Password    string  `schema:"password"`
 | 
				
			||||||
 | 
					    validator.Validator `schema:"-"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -2,6 +2,7 @@ package models
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"database/sql"
 | 
						"database/sql"
 | 
				
			||||||
 | 
						"strconv"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -15,6 +16,10 @@ type Guestbook struct {
 | 
				
			|||||||
    IsActive bool
 | 
					    IsActive bool
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (gb Guestbook) Slug() string {
 | 
				
			||||||
 | 
					    return strconv.FormatUint(gb.ShortId, 36)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type GuestbookModel struct {
 | 
					type GuestbookModel struct {
 | 
				
			||||||
    DB *sql.DB
 | 
					    DB *sql.DB
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -1,511 +1,78 @@
 | 
				
			|||||||
/* Set the global variables for everything. Change these to use your own fonts and colours. */
 | 
					 | 
				
			||||||
:root {
 | 
					 | 
				
			||||||
  /* Set sans-serif & mono fonts */
 | 
					 | 
				
			||||||
  --sans-font: -apple-system, BlinkMacSystemFont, "Avenir Next", Avenir,
 | 
					 | 
				
			||||||
    "Nimbus Sans L", Roboto, Noto, "Segoe UI", Arial, Helvetica,
 | 
					 | 
				
			||||||
    "Helvetica Neue", sans-serif;
 | 
					 | 
				
			||||||
  --mono-font: Consolas, Menlo, Monaco, "Andale Mono", "Ubuntu Mono", monospace;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  /* Body font size. By default, effectively 18.4px, based on 16px as 'root em' */
 | 
					 | 
				
			||||||
  --base-fontsize: 1.15rem;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  /* Major third scale progression - see https://type-scale.com/ */
 | 
					 | 
				
			||||||
  --header-scale: 1.25;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  /* Line height is set to the "Golden ratio" for optimal legibility */
 | 
					 | 
				
			||||||
  --line-height: 1.618;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  /* Default (light) theme */
 | 
					 | 
				
			||||||
  --bg: #fff;
 | 
					 | 
				
			||||||
  --accent-bg: #f5f7ff;
 | 
					 | 
				
			||||||
  --text: #212121;
 | 
					 | 
				
			||||||
  --text-light: #585858;
 | 
					 | 
				
			||||||
  --border: #d8dae1;
 | 
					 | 
				
			||||||
  --accent: #0d47a1;
 | 
					 | 
				
			||||||
  --accent-light: #90caf9;
 | 
					 | 
				
			||||||
  --code: #d81b60;
 | 
					 | 
				
			||||||
  --preformatted: #444;
 | 
					 | 
				
			||||||
  --marked: #ffdd33;
 | 
					 | 
				
			||||||
  --disabled: #efefef;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* Dark theme */
 | 
					 | 
				
			||||||
@media (prefers-color-scheme: dark) {
 | 
					 | 
				
			||||||
  :root {
 | 
					 | 
				
			||||||
    --bg: #212121;
 | 
					 | 
				
			||||||
    --accent-bg: #2b2b2b;
 | 
					 | 
				
			||||||
    --text: #dcdcdc;
 | 
					 | 
				
			||||||
    --text-light: #ababab;
 | 
					 | 
				
			||||||
    --border: #666;
 | 
					 | 
				
			||||||
    --accent: #ffb300;
 | 
					 | 
				
			||||||
    --accent-light: #ffecb3;
 | 
					 | 
				
			||||||
    --code: #f06292;
 | 
					 | 
				
			||||||
    --preformatted: #ccc;
 | 
					 | 
				
			||||||
    --disabled: #111;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  img,
 | 
					 | 
				
			||||||
  video {
 | 
					 | 
				
			||||||
    opacity: 0.6;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
html {
 | 
					html {
 | 
				
			||||||
  /* Set the font globally */
 | 
					  background: lightgray;
 | 
				
			||||||
  font-family: var(--sans-font);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Make the body a nice central block */
 | 
					 | 
				
			||||||
body {
 | 
					body {
 | 
				
			||||||
  color: var(--text);
 | 
					  max-width: 1024px;
 | 
				
			||||||
  background: var(--bg);
 | 
					  margin: 1rem auto;
 | 
				
			||||||
  font-size: var(--base-fontsize);
 | 
					  padding: 1rem;
 | 
				
			||||||
  line-height: var(--line-height);
 | 
					  background: white;
 | 
				
			||||||
  display: flex;
 | 
					  font-size: 1.2rem;
 | 
				
			||||||
  min-height: 100vh;
 | 
					  line-height: 1.5;
 | 
				
			||||||
  flex-direction: column;
 | 
					  font-family: Arial, Helvetica, sans-serif;
 | 
				
			||||||
  flex: 1;
 | 
					 | 
				
			||||||
  margin: 0 auto;
 | 
					 | 
				
			||||||
  max-width: 45rem;
 | 
					 | 
				
			||||||
  padding: 0 0.5rem;
 | 
					 | 
				
			||||||
  overflow-x: hidden;
 | 
					 | 
				
			||||||
  word-break: break-word;
 | 
					 | 
				
			||||||
  overflow-wrap: break-word;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Make the header bg full width, but the content inline with body */
 | 
					 | 
				
			||||||
header {
 | 
					header {
 | 
				
			||||||
  background: var(--accent-bg);
 | 
					 | 
				
			||||||
  border-bottom: 1px solid var(--border);
 | 
					 | 
				
			||||||
  text-align: center;
 | 
					  text-align: center;
 | 
				
			||||||
  padding: 2rem 0.5rem;
 | 
					 | 
				
			||||||
  width: 100vw;
 | 
					 | 
				
			||||||
  position: relative;
 | 
					 | 
				
			||||||
  box-sizing: border-box;
 | 
					 | 
				
			||||||
  left: 50%;
 | 
					 | 
				
			||||||
  right: 50%;
 | 
					 | 
				
			||||||
  margin-left: -50vw;
 | 
					 | 
				
			||||||
  margin-right: -50vw;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Remove margins for header text */
 | 
					body > nav {
 | 
				
			||||||
header h1,
 | 
					  display: flex;
 | 
				
			||||||
header p {
 | 
					  justify-content: space-between;
 | 
				
			||||||
  margin: 0;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Add a little padding to ensure spacing is correct between content and nav */
 | 
					body > nav ul {
 | 
				
			||||||
main {
 | 
					  list-style: none;
 | 
				
			||||||
  padding-top: 1.5rem;
 | 
					  margin: 0 1rem;
 | 
				
			||||||
 | 
					  padding: 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Fix line height when title wraps */
 | 
					body > nav li {
 | 
				
			||||||
h1,
 | 
					 | 
				
			||||||
h2,
 | 
					 | 
				
			||||||
h3 {
 | 
					 | 
				
			||||||
  line-height: 1.1;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* Format navigation */
 | 
					 | 
				
			||||||
nav {
 | 
					 | 
				
			||||||
  font-size: 1rem;
 | 
					 | 
				
			||||||
  line-height: 2;
 | 
					 | 
				
			||||||
  padding: 1rem 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
nav a {
 | 
					 | 
				
			||||||
  margin: 1rem 1rem 0 0;
 | 
					 | 
				
			||||||
  border: 1px solid var(--border);
 | 
					 | 
				
			||||||
  border-radius: 5px;
 | 
					 | 
				
			||||||
  color: var(--text) !important;
 | 
					 | 
				
			||||||
  display: inline-block;
 | 
					  display: inline-block;
 | 
				
			||||||
  padding: 0.1rem 1rem;
 | 
					  padding: 0 0.5rem;
 | 
				
			||||||
  text-decoration: none;
 | 
					 | 
				
			||||||
  transition: 0.4s;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
nav a:hover {
 | 
					nav form {
 | 
				
			||||||
  color: var(--accent) !important;
 | 
					  display: inline-block;
 | 
				
			||||||
  border-color: var(--accent);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
nav a.current:hover {
 | 
					nav button {
 | 
				
			||||||
  text-decoration: none;
 | 
					  border: none;
 | 
				
			||||||
 | 
					  background: none;
 | 
				
			||||||
 | 
					  font-family: unset;
 | 
				
			||||||
 | 
					  font-size: unset;
 | 
				
			||||||
 | 
					  color: blue;
 | 
				
			||||||
 | 
					  text-decoration: underline;
 | 
				
			||||||
 | 
					  cursor: pointer;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					main {
 | 
				
			||||||
 | 
					  padding: 1rem;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					div#main {
 | 
				
			||||||
 | 
					  display: flex;
 | 
				
			||||||
 | 
					  flex-flow: row wrap;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					div#main nav {
 | 
				
			||||||
 | 
					  flex: 1 1 25%;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					div#main > div {
 | 
				
			||||||
 | 
					  flex: 10 1 40%;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					main nav ul {
 | 
				
			||||||
 | 
					  list-style: none;
 | 
				
			||||||
 | 
					  margin: 1rem;
 | 
				
			||||||
 | 
					  padding: 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
footer {
 | 
					footer {
 | 
				
			||||||
  margin-top: 4rem;
 | 
					 | 
				
			||||||
  padding: 2rem 1rem 1.5rem 1rem;
 | 
					 | 
				
			||||||
  color: var(--text-light);
 | 
					 | 
				
			||||||
  font-size: 0.9rem;
 | 
					 | 
				
			||||||
  text-align: center;
 | 
					  text-align: center;
 | 
				
			||||||
  border-top: 1px solid var(--border);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Format headers */
 | 
					a {
 | 
				
			||||||
h1 {
 | 
					  color: blue;
 | 
				
			||||||
  font-size: calc(
 | 
					 | 
				
			||||||
    var(--base-fontsize) * var(--header-scale) * var(--header-scale) *
 | 
					 | 
				
			||||||
      var(--header-scale) * var(--header-scale)
 | 
					 | 
				
			||||||
  );
 | 
					 | 
				
			||||||
  margin-top: calc(var(--line-height) * 1.5rem);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
h2 {
 | 
					 | 
				
			||||||
  font-size: calc(
 | 
					 | 
				
			||||||
    var(--base-fontsize) * var(--header-scale) * var(--header-scale) *
 | 
					 | 
				
			||||||
      var(--header-scale)
 | 
					 | 
				
			||||||
  );
 | 
					 | 
				
			||||||
  margin-top: calc(var(--line-height) * 1.5rem);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
h3 {
 | 
					 | 
				
			||||||
  font-size: calc(
 | 
					 | 
				
			||||||
    var(--base-fontsize) * var(--header-scale) * var(--header-scale)
 | 
					 | 
				
			||||||
  );
 | 
					 | 
				
			||||||
  margin-top: calc(var(--line-height) * 1.5rem);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
h4 {
 | 
					 | 
				
			||||||
  font-size: calc(var(--base-fontsize) * var(--header-scale));
 | 
					 | 
				
			||||||
  margin-top: calc(var(--line-height) * 1.5rem);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
h5 {
 | 
					 | 
				
			||||||
  font-size: var(--base-fontsize);
 | 
					 | 
				
			||||||
  margin-top: calc(var(--line-height) * 1.5rem);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
h6 {
 | 
					 | 
				
			||||||
  font-size: calc(var(--base-fontsize) / var(--header-scale));
 | 
					 | 
				
			||||||
  margin-top: calc(var(--line-height) * 1.5rem);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* Format links & buttons */
 | 
					 | 
				
			||||||
a,
 | 
					 | 
				
			||||||
a:visited {
 | 
					 | 
				
			||||||
  color: var(--accent);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
a:hover {
 | 
					 | 
				
			||||||
  text-decoration: none;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
a button,
 | 
					 | 
				
			||||||
button,
 | 
					 | 
				
			||||||
[role="button"],
 | 
					 | 
				
			||||||
input[type="submit"],
 | 
					 | 
				
			||||||
input[type="reset"],
 | 
					 | 
				
			||||||
input[type="button"] {
 | 
					 | 
				
			||||||
  border: none;
 | 
					 | 
				
			||||||
  border-radius: 5px;
 | 
					 | 
				
			||||||
  background: var(--accent);
 | 
					 | 
				
			||||||
  font-size: 1rem;
 | 
					 | 
				
			||||||
  color: var(--bg);
 | 
					 | 
				
			||||||
  padding: 0.7rem 0.9rem;
 | 
					 | 
				
			||||||
  margin: 0.5rem 0;
 | 
					 | 
				
			||||||
  transition: 0.4s;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
a button[disabled],
 | 
					 | 
				
			||||||
button[disabled],
 | 
					 | 
				
			||||||
[role="button"][aria-disabled="true"],
 | 
					 | 
				
			||||||
input[type="submit"][disabled],
 | 
					 | 
				
			||||||
input[type="reset"][disabled],
 | 
					 | 
				
			||||||
input[type="button"][disabled],
 | 
					 | 
				
			||||||
input[type="checkbox"][disabled],
 | 
					 | 
				
			||||||
input[type="radio"][disabled],
 | 
					 | 
				
			||||||
select[disabled] {
 | 
					 | 
				
			||||||
  cursor: default;
 | 
					 | 
				
			||||||
  opacity: 0.5;
 | 
					 | 
				
			||||||
  cursor: not-allowed;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
input:disabled,
 | 
					 | 
				
			||||||
textarea:disabled,
 | 
					 | 
				
			||||||
select:disabled {
 | 
					 | 
				
			||||||
  cursor: not-allowed;
 | 
					 | 
				
			||||||
  background-color: var(--disabled);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
input[type="range"] {
 | 
					 | 
				
			||||||
  padding: 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* Set the cursor to '?' while hovering over an abbreviation */
 | 
					 | 
				
			||||||
abbr {
 | 
					 | 
				
			||||||
  cursor: help;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
button:focus,
 | 
					 | 
				
			||||||
button:enabled:hover,
 | 
					 | 
				
			||||||
[role="button"]:focus,
 | 
					 | 
				
			||||||
[role="button"]:not([aria-disabled="true"]):hover,
 | 
					 | 
				
			||||||
input[type="submit"]:focus,
 | 
					 | 
				
			||||||
input[type="submit"]:enabled:hover,
 | 
					 | 
				
			||||||
input[type="reset"]:focus,
 | 
					 | 
				
			||||||
input[type="reset"]:enabled:hover,
 | 
					 | 
				
			||||||
input[type="button"]:focus,
 | 
					 | 
				
			||||||
input[type="button"]:enabled:hover,
 | 
					 | 
				
			||||||
input[type="checkbox"]:focus,
 | 
					 | 
				
			||||||
input[type="checkbox"]:enabled:hover,
 | 
					 | 
				
			||||||
input[type="radio"]:focus,
 | 
					 | 
				
			||||||
input[type="radio"]:enabled:hover {
 | 
					 | 
				
			||||||
  filter: brightness(1.4);
 | 
					 | 
				
			||||||
  cursor: pointer;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* Format the expanding box */
 | 
					 | 
				
			||||||
details {
 | 
					 | 
				
			||||||
  background: var(--accent-bg);
 | 
					 | 
				
			||||||
  border: 1px solid var(--border);
 | 
					 | 
				
			||||||
  border-radius: 5px;
 | 
					 | 
				
			||||||
  margin-bottom: 1rem;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
summary {
 | 
					 | 
				
			||||||
  cursor: pointer;
 | 
					 | 
				
			||||||
  font-weight: bold;
 | 
					 | 
				
			||||||
  padding: 0.6rem 1rem;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
details[open] {
 | 
					 | 
				
			||||||
  padding: 0.6rem 1rem 0.75rem 1rem;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
details[open] summary {
 | 
					 | 
				
			||||||
  margin-bottom: 0.5rem;
 | 
					 | 
				
			||||||
  padding: 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
details[open] > *:last-child {
 | 
					 | 
				
			||||||
  margin-bottom: 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* Format tables */
 | 
					 | 
				
			||||||
table {
 | 
					 | 
				
			||||||
  border-collapse: collapse;
 | 
					 | 
				
			||||||
  width: 100%;
 | 
					 | 
				
			||||||
  margin: 1.5rem 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
td,
 | 
					 | 
				
			||||||
th {
 | 
					 | 
				
			||||||
  border: 1px solid var(--border);
 | 
					 | 
				
			||||||
  text-align: left;
 | 
					 | 
				
			||||||
  padding: 0.5rem;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
th {
 | 
					 | 
				
			||||||
  background: var(--accent-bg);
 | 
					 | 
				
			||||||
  font-weight: bold;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
tr:nth-child(even) {
 | 
					 | 
				
			||||||
  /* Set every other cell slightly darker. Improves readability. */
 | 
					 | 
				
			||||||
  background: var(--accent-bg);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
table caption {
 | 
					 | 
				
			||||||
  font-weight: bold;
 | 
					 | 
				
			||||||
  margin-bottom: 0.5rem;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* Lists */
 | 
					 | 
				
			||||||
ol,
 | 
					 | 
				
			||||||
ul {
 | 
					 | 
				
			||||||
  padding-left: 3rem;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* Format forms */
 | 
					 | 
				
			||||||
textarea,
 | 
					 | 
				
			||||||
select,
 | 
					 | 
				
			||||||
input {
 | 
					 | 
				
			||||||
  font-size: inherit;
 | 
					 | 
				
			||||||
  font-family: inherit;
 | 
					 | 
				
			||||||
  padding: 0.5rem;
 | 
					 | 
				
			||||||
  margin-bottom: 0.5rem;
 | 
					 | 
				
			||||||
  color: var(--text);
 | 
					 | 
				
			||||||
  background: var(--bg);
 | 
					 | 
				
			||||||
  border: 1px solid var(--border);
 | 
					 | 
				
			||||||
  border-radius: 5px;
 | 
					 | 
				
			||||||
  box-shadow: none;
 | 
					 | 
				
			||||||
  box-sizing: border-box;
 | 
					 | 
				
			||||||
  width: 60%;
 | 
					 | 
				
			||||||
  -moz-appearance: none;
 | 
					 | 
				
			||||||
  -webkit-appearance: none;
 | 
					 | 
				
			||||||
  appearance: none;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* Add arrow to  */
 | 
					 | 
				
			||||||
select {
 | 
					 | 
				
			||||||
  background-image: linear-gradient(45deg, transparent 49%, var(--text) 51%),
 | 
					 | 
				
			||||||
    linear-gradient(135deg, var(--text) 51%, transparent 49%);
 | 
					 | 
				
			||||||
  background-position: calc(100% - 20px), calc(100% - 15px);
 | 
					 | 
				
			||||||
  background-size: 5px 5px, 5px 5px;
 | 
					 | 
				
			||||||
  background-repeat: no-repeat;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
select[multiple] {
 | 
					 | 
				
			||||||
  background-image: none !important;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* checkbox and radio button style */
 | 
					 | 
				
			||||||
input[type="checkbox"],
 | 
					 | 
				
			||||||
input[type="radio"] {
 | 
					 | 
				
			||||||
  vertical-align: bottom;
 | 
					 | 
				
			||||||
  position: relative;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
input[type="radio"] {
 | 
					 | 
				
			||||||
  border-radius: 100%;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
input[type="checkbox"]:checked,
 | 
					 | 
				
			||||||
input[type="radio"]:checked {
 | 
					 | 
				
			||||||
  background: var(--accent);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
input[type="checkbox"]:checked::after {
 | 
					 | 
				
			||||||
  /* Creates a rectangle with colored right and bottom borders which is rotated to look like a check mark */
 | 
					 | 
				
			||||||
  content: " ";
 | 
					 | 
				
			||||||
  width: 0.1em;
 | 
					 | 
				
			||||||
  height: 0.25em;
 | 
					 | 
				
			||||||
  border-radius: 0;
 | 
					 | 
				
			||||||
  position: absolute;
 | 
					 | 
				
			||||||
  top: 0.05em;
 | 
					 | 
				
			||||||
  left: 0.18em;
 | 
					 | 
				
			||||||
  background: transparent;
 | 
					 | 
				
			||||||
  border-right: solid var(--bg) 0.08em;
 | 
					 | 
				
			||||||
  border-bottom: solid var(--bg) 0.08em;
 | 
					 | 
				
			||||||
  font-size: 1.8em;
 | 
					 | 
				
			||||||
  transform: rotate(45deg);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
input[type="radio"]:checked::after {
 | 
					 | 
				
			||||||
  /* creates a colored circle for the checked radio button  */
 | 
					 | 
				
			||||||
  content: " ";
 | 
					 | 
				
			||||||
  width: 0.25em;
 | 
					 | 
				
			||||||
  height: 0.25em;
 | 
					 | 
				
			||||||
  border-radius: 100%;
 | 
					 | 
				
			||||||
  position: absolute;
 | 
					 | 
				
			||||||
  top: 0.125em;
 | 
					 | 
				
			||||||
  background: var(--bg);
 | 
					 | 
				
			||||||
  left: 0.125em;
 | 
					 | 
				
			||||||
  font-size: 32px;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* Make the textarea wider than other inputs */
 | 
					 | 
				
			||||||
textarea {
 | 
					 | 
				
			||||||
  width: 80%;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* Makes input fields wider on smaller screens */
 | 
					 | 
				
			||||||
@media only screen and (max-width: 720px) {
 | 
					 | 
				
			||||||
  textarea,
 | 
					 | 
				
			||||||
  select,
 | 
					 | 
				
			||||||
  input {
 | 
					 | 
				
			||||||
    width: 100%;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* Ensures the checkbox and radio inputs do not have a set width like other input fields */
 | 
					 | 
				
			||||||
input[type="checkbox"],
 | 
					 | 
				
			||||||
input[type="radio"] {
 | 
					 | 
				
			||||||
  width: auto;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* do not show border around file selector button */
 | 
					 | 
				
			||||||
input[type="file"] {
 | 
					 | 
				
			||||||
  border: 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* Without this any HTML using <fieldset> shows ugly borders and has additional padding/margin. (Issue #3) */
 | 
					 | 
				
			||||||
fieldset {
 | 
					 | 
				
			||||||
  border: 0;
 | 
					 | 
				
			||||||
  padding: 0;
 | 
					 | 
				
			||||||
  margin: 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* Misc body elements */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
hr {
 | 
					 | 
				
			||||||
  color: var(--border);
 | 
					 | 
				
			||||||
  border-top: 1px;
 | 
					 | 
				
			||||||
  margin: 1rem auto;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
mark {
 | 
					 | 
				
			||||||
  padding: 2px 5px;
 | 
					 | 
				
			||||||
  border-radius: 4px;
 | 
					 | 
				
			||||||
  background: var(--marked);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
main img,
 | 
					 | 
				
			||||||
main video {
 | 
					 | 
				
			||||||
  max-width: 100%;
 | 
					 | 
				
			||||||
  height: auto;
 | 
					 | 
				
			||||||
  border-radius: 5px;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
figure {
 | 
					 | 
				
			||||||
  margin: 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
figcaption {
 | 
					 | 
				
			||||||
  font-size: 0.9rem;
 | 
					 | 
				
			||||||
  color: var(--text-light);
 | 
					 | 
				
			||||||
  text-align: center;
 | 
					 | 
				
			||||||
  margin-bottom: 1rem;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
blockquote {
 | 
					 | 
				
			||||||
  margin: 2rem 0 2rem 2rem;
 | 
					 | 
				
			||||||
  padding: 0.4rem 0.8rem;
 | 
					 | 
				
			||||||
  border-left: 0.35rem solid var(--accent);
 | 
					 | 
				
			||||||
  opacity: 0.8;
 | 
					 | 
				
			||||||
  font-style: italic;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
cite {
 | 
					 | 
				
			||||||
  font-size: 0.9rem;
 | 
					 | 
				
			||||||
  color: var(--text-light);
 | 
					 | 
				
			||||||
  font-style: normal;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* Use mono font for code like elements */
 | 
					 | 
				
			||||||
code,
 | 
					 | 
				
			||||||
pre,
 | 
					 | 
				
			||||||
pre span,
 | 
					 | 
				
			||||||
kbd,
 | 
					 | 
				
			||||||
samp {
 | 
					 | 
				
			||||||
  font-size: 1.075rem;
 | 
					 | 
				
			||||||
  font-family: var(--mono-font);
 | 
					 | 
				
			||||||
  color: var(--code);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
kbd {
 | 
					 | 
				
			||||||
  color: var(--preformatted);
 | 
					 | 
				
			||||||
  border: 1px solid var(--preformatted);
 | 
					 | 
				
			||||||
  border-bottom: 3px solid var(--preformatted);
 | 
					 | 
				
			||||||
  border-radius: 5px;
 | 
					 | 
				
			||||||
  padding: 0.1rem;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
pre {
 | 
					 | 
				
			||||||
  padding: 1rem 1.4rem;
 | 
					 | 
				
			||||||
  max-width: 100%;
 | 
					 | 
				
			||||||
  overflow: auto;
 | 
					 | 
				
			||||||
  overflow-x: auto;
 | 
					 | 
				
			||||||
  color: var(--preformatted);
 | 
					 | 
				
			||||||
  background: var(--accent-bg);
 | 
					 | 
				
			||||||
  border: 1px solid var(--border);
 | 
					 | 
				
			||||||
  border-radius: 5px;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* Fix embedded code within pre */
 | 
					 | 
				
			||||||
pre code {
 | 
					 | 
				
			||||||
  color: var(--preformatted);
 | 
					 | 
				
			||||||
  background: none;
 | 
					 | 
				
			||||||
  margin: 0;
 | 
					 | 
				
			||||||
  padding: 0;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										81
									
								
								ui/views/common.templ
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										81
									
								
								ui/views/common.templ
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,81 @@
 | 
				
			|||||||
 | 
					package views
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "git.32bit.cafe/32bitcafe/guestbook/internal/models"
 | 
				
			||||||
 | 
					import "strconv"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type CommonData struct {
 | 
				
			||||||
 | 
					    CurrentYear int
 | 
				
			||||||
 | 
					    Flash string
 | 
				
			||||||
 | 
					    IsAuthenticated bool
 | 
				
			||||||
 | 
					    CSRFToken string
 | 
				
			||||||
 | 
					    CurrentUser *models.User
 | 
				
			||||||
 | 
					    IsHtmx bool
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func slugToShortId(slug string) uint64 {
 | 
				
			||||||
 | 
					    id, _ := strconv.ParseUint(slug, 36, 64)
 | 
				
			||||||
 | 
					    return id
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					templ commonHeader() {
 | 
				
			||||||
 | 
					    <header>
 | 
				
			||||||
 | 
					        <h1><a href="/">webweav.ing</a></h1>
 | 
				
			||||||
 | 
					    </header>
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					templ topNav(data CommonData) {
 | 
				
			||||||
 | 
					    <nav>
 | 
				
			||||||
 | 
					        <div>
 | 
				
			||||||
 | 
					            <ul>
 | 
				
			||||||
 | 
					                <li><a href="/guestbooks">Guestbooks</a></li>
 | 
				
			||||||
 | 
					                <li>RSS Feeds</li>
 | 
				
			||||||
 | 
					            </ul>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					        <div>
 | 
				
			||||||
 | 
					            if data.IsAuthenticated {
 | 
				
			||||||
 | 
					                Welcome, { data.CurrentUser.Username }
 | 
				
			||||||
 | 
					                <a href="/users/settings">Settings</a> | 
 | 
				
			||||||
 | 
					                <form action="/users/logout" method="post">
 | 
				
			||||||
 | 
					                    <input type="hidden" name="csrf_token" value={ data.CSRFToken }>
 | 
				
			||||||
 | 
					                    <button>Logout</button>
 | 
				
			||||||
 | 
					                </form>
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                <a href="/users/register">Create an Account</a> | 
 | 
				
			||||||
 | 
					                <a href="/users/login">Login</a>
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					    </nav>
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					templ commonFooter() {
 | 
				
			||||||
 | 
					    <footer>
 | 
				
			||||||
 | 
					        <p>Generated with Templ</p>
 | 
				
			||||||
 | 
					        <p>A <a href="https://32bit.cafe">32-bit cafe</a> Project</p>
 | 
				
			||||||
 | 
					    </footer>
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					templ base(title string, data CommonData) {
 | 
				
			||||||
 | 
					    <!DOCTYPE html>
 | 
				
			||||||
 | 
					    <html lang="en">
 | 
				
			||||||
 | 
					        <head>
 | 
				
			||||||
 | 
					            <title>{ title } - webweav.ing</title>
 | 
				
			||||||
 | 
					            <meta charset="UTF-8">
 | 
				
			||||||
 | 
					            <meta name="viewport" content="width=device-width, initial-scale=1">
 | 
				
			||||||
 | 
					            <link href="/static/css/style.css" rel="stylesheet">
 | 
				
			||||||
 | 
					            <script src="/static/js/htmx.min.js"></script>
 | 
				
			||||||
 | 
					        </head>
 | 
				
			||||||
 | 
					        <body>
 | 
				
			||||||
 | 
					            @commonHeader()
 | 
				
			||||||
 | 
					            @topNav(data)
 | 
				
			||||||
 | 
					            <main>
 | 
				
			||||||
 | 
					                if data.Flash != "" {
 | 
				
			||||||
 | 
					                    <div class="flash">{ data.Flash }</div>
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                { children... }
 | 
				
			||||||
 | 
					            </main>
 | 
				
			||||||
 | 
					            @commonFooter()
 | 
				
			||||||
 | 
					        </body>
 | 
				
			||||||
 | 
					    </html>
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										245
									
								
								ui/views/common_templ.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										245
									
								
								ui/views/common_templ.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,245 @@
 | 
				
			|||||||
 | 
					// Code generated by templ - DO NOT EDIT.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// templ: version: v0.3.833
 | 
				
			||||||
 | 
					package views
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//lint:file-ignore SA4006 This context is only used if a nested component is present.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "github.com/a-h/templ"
 | 
				
			||||||
 | 
					import templruntime "github.com/a-h/templ/runtime"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "git.32bit.cafe/32bitcafe/guestbook/internal/models"
 | 
				
			||||||
 | 
					import "strconv"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type CommonData struct {
 | 
				
			||||||
 | 
						CurrentYear     int
 | 
				
			||||||
 | 
						Flash           string
 | 
				
			||||||
 | 
						IsAuthenticated bool
 | 
				
			||||||
 | 
						CSRFToken       string
 | 
				
			||||||
 | 
						CurrentUser     *models.User
 | 
				
			||||||
 | 
						IsHtmx          bool
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func slugToShortId(slug string) uint64 {
 | 
				
			||||||
 | 
						id, _ := strconv.ParseUint(slug, 36, 64)
 | 
				
			||||||
 | 
						return id
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func commonHeader() 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_Var1 := templ.GetChildren(ctx)
 | 
				
			||||||
 | 
							if templ_7745c5c3_Var1 == nil {
 | 
				
			||||||
 | 
								templ_7745c5c3_Var1 = templ.NopComponent
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							ctx = templ.ClearChildren(ctx)
 | 
				
			||||||
 | 
							templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<header><h1><a href=\"/\">webweav.ing</a></h1></header>")
 | 
				
			||||||
 | 
							if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
								return templ_7745c5c3_Err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func topNav(data CommonData) 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_Var2 := templ.GetChildren(ctx)
 | 
				
			||||||
 | 
							if templ_7745c5c3_Var2 == nil {
 | 
				
			||||||
 | 
								templ_7745c5c3_Var2 = templ.NopComponent
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							ctx = templ.ClearChildren(ctx)
 | 
				
			||||||
 | 
							templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "<nav><div><ul><li><a href=\"/guestbooks\">Guestbooks</a></li><li>RSS Feeds</li></ul></div><div>")
 | 
				
			||||||
 | 
							if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
								return templ_7745c5c3_Err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if data.IsAuthenticated {
 | 
				
			||||||
 | 
								templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "Welcome, ")
 | 
				
			||||||
 | 
								if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
									return templ_7745c5c3_Err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								var templ_7745c5c3_Var3 string
 | 
				
			||||||
 | 
								templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(data.CurrentUser.Username)
 | 
				
			||||||
 | 
								if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
									return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/common.templ`, Line: 36, Col: 52}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
 | 
				
			||||||
 | 
								if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
									return templ_7745c5c3_Err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, " <a href=\"/users/settings\">Settings</a> | <form action=\"/users/logout\" method=\"post\"><input type=\"hidden\" name=\"csrf_token\" value=\"")
 | 
				
			||||||
 | 
								if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
									return templ_7745c5c3_Err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								var templ_7745c5c3_Var4 string
 | 
				
			||||||
 | 
								templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(data.CSRFToken)
 | 
				
			||||||
 | 
								if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
									return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/common.templ`, Line: 39, Col: 81}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
 | 
				
			||||||
 | 
								if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
									return templ_7745c5c3_Err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "\"> <button>Logout</button></form>")
 | 
				
			||||||
 | 
								if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
									return templ_7745c5c3_Err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "<a href=\"/users/register\">Create an Account</a> |  <a href=\"/users/login\">Login</a>")
 | 
				
			||||||
 | 
								if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
									return templ_7745c5c3_Err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "</div></nav>")
 | 
				
			||||||
 | 
							if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
								return templ_7745c5c3_Err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func commonFooter() 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_Var5 := templ.GetChildren(ctx)
 | 
				
			||||||
 | 
							if templ_7745c5c3_Var5 == nil {
 | 
				
			||||||
 | 
								templ_7745c5c3_Var5 = templ.NopComponent
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							ctx = templ.ClearChildren(ctx)
 | 
				
			||||||
 | 
							templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "<footer><p>Generated with Templ</p><p>A <a href=\"https://32bit.cafe\">32-bit cafe</a> Project</p></footer>")
 | 
				
			||||||
 | 
							if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
								return templ_7745c5c3_Err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func base(title string, data CommonData) 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_Var6 := templ.GetChildren(ctx)
 | 
				
			||||||
 | 
							if templ_7745c5c3_Var6 == nil {
 | 
				
			||||||
 | 
								templ_7745c5c3_Var6 = templ.NopComponent
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							ctx = templ.ClearChildren(ctx)
 | 
				
			||||||
 | 
							templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "<!doctype html><html lang=\"en\"><head><title>")
 | 
				
			||||||
 | 
							if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
								return templ_7745c5c3_Err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							var templ_7745c5c3_Var7 string
 | 
				
			||||||
 | 
							templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(title)
 | 
				
			||||||
 | 
							if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
								return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/common.templ`, Line: 62, Col: 26}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7))
 | 
				
			||||||
 | 
							if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
								return templ_7745c5c3_Err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, " - webweav.ing</title><meta charset=\"UTF-8\"><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"><link href=\"/static/css/style.css\" rel=\"stylesheet\"><script src=\"/static/js/htmx.min.js\"></script></head><body>")
 | 
				
			||||||
 | 
							if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
								return templ_7745c5c3_Err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							templ_7745c5c3_Err = commonHeader().Render(ctx, templ_7745c5c3_Buffer)
 | 
				
			||||||
 | 
							if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
								return templ_7745c5c3_Err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							templ_7745c5c3_Err = topNav(data).Render(ctx, templ_7745c5c3_Buffer)
 | 
				
			||||||
 | 
							if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
								return templ_7745c5c3_Err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "<main>")
 | 
				
			||||||
 | 
							if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
								return templ_7745c5c3_Err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if data.Flash != "" {
 | 
				
			||||||
 | 
								templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "<div class=\"flash\">")
 | 
				
			||||||
 | 
								if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
									return templ_7745c5c3_Err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								var templ_7745c5c3_Var8 string
 | 
				
			||||||
 | 
								templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(data.Flash)
 | 
				
			||||||
 | 
								if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
									return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/common.templ`, Line: 73, Col: 51}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8))
 | 
				
			||||||
 | 
								if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
									return templ_7745c5c3_Err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "</div>")
 | 
				
			||||||
 | 
								if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
									return templ_7745c5c3_Err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							templ_7745c5c3_Err = templ_7745c5c3_Var6.Render(ctx, templ_7745c5c3_Buffer)
 | 
				
			||||||
 | 
							if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
								return templ_7745c5c3_Err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "</main>")
 | 
				
			||||||
 | 
							if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
								return templ_7745c5c3_Err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							templ_7745c5c3_Err = commonFooter().Render(ctx, templ_7745c5c3_Buffer)
 | 
				
			||||||
 | 
							if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
								return templ_7745c5c3_Err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "</body></html>")
 | 
				
			||||||
 | 
							if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
								return templ_7745c5c3_Err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var _ = templruntime.GeneratedTemplate
 | 
				
			||||||
							
								
								
									
										15
									
								
								ui/views/common_templ.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								ui/views/common_templ.txt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,15 @@
 | 
				
			|||||||
 | 
					<header><h1><a href=\"/\">webweav.ing</a></h1></header>
 | 
				
			||||||
 | 
					<nav><div><ul><li><a href=\"/guestbooks\">Guestbooks</a></li><li>RSS Feeds</li></ul></div><div>
 | 
				
			||||||
 | 
					Welcome, 
 | 
				
			||||||
 | 
					 <a href=\"/users/settings\">Settings</a> | <form action=\"/users/logout\" method=\"post\"><input type=\"hidden\" name=\"csrf_token\" value=\"
 | 
				
			||||||
 | 
					\"> <button>Logout</button></form>
 | 
				
			||||||
 | 
					<a href=\"/users/register\">Create an Account</a> |  <a href=\"/users/login\">Login</a>
 | 
				
			||||||
 | 
					</div></nav>
 | 
				
			||||||
 | 
					<footer><p>Generated with Templ</p><p>A <a href=\"https://32bit.cafe\">32-bit cafe</a> Project</p></footer>
 | 
				
			||||||
 | 
					<!doctype html><html lang=\"en\"><head><title>
 | 
				
			||||||
 | 
					 - webweav.ing</title><meta charset=\"UTF-8\"><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"><link href=\"/static/css/style.css\" rel=\"stylesheet\"><script src=\"/static/js/htmx.min.js\"></script></head><body>
 | 
				
			||||||
 | 
					<main>
 | 
				
			||||||
 | 
					<div class=\"flash\">
 | 
				
			||||||
 | 
					</div>
 | 
				
			||||||
 | 
					</main>
 | 
				
			||||||
 | 
					</body></html>
 | 
				
			||||||
							
								
								
									
										116
									
								
								ui/views/guestbooks.templ
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										116
									
								
								ui/views/guestbooks.templ
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,116 @@
 | 
				
			|||||||
 | 
					package views
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "fmt"
 | 
				
			||||||
 | 
					import "git.32bit.cafe/32bitcafe/guestbook/internal/models"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					templ gbCreateForm(csrf_token string) {
 | 
				
			||||||
 | 
					    <input type="hidden" name="csrf_token" value={ csrf_token }>
 | 
				
			||||||
 | 
					    <label for="siteurl">Site URL: </label>
 | 
				
			||||||
 | 
					    <input type="text" name="siteurl" id="siteurl" required />
 | 
				
			||||||
 | 
					    <button type="submit">Submit</button>
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					templ gbList(guestbooks []models.Guestbook) {
 | 
				
			||||||
 | 
					    if len(guestbooks) == 0 {
 | 
				
			||||||
 | 
					        <p>No Guestbooks yet</p>
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        <ul id="guestbooks" hx-get="/guestbooks" hx-trigger="newGuestbook from:body" hx-swap="outerHTML">
 | 
				
			||||||
 | 
					            for _, gb := range guestbooks {
 | 
				
			||||||
 | 
					                {{ gbUrl := fmt.Sprintf("/guestbooks/%s", gb.Slug()) }}
 | 
				
			||||||
 | 
					                <li><a href={ templ.URL(gbUrl) }>
 | 
				
			||||||
 | 
					                    if len(gb.SiteUrl) == 0 {
 | 
				
			||||||
 | 
					                        Untitled
 | 
				
			||||||
 | 
					                    } else {
 | 
				
			||||||
 | 
					                        { gb.SiteUrl }
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                </a></li>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        </ul>
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					templ GuestbookList(title string, data CommonData, guestbooks []models.Guestbook) {
 | 
				
			||||||
 | 
					    if data.IsHtmx {
 | 
				
			||||||
 | 
					        @gbList(guestbooks)
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        @base(title, data) {
 | 
				
			||||||
 | 
					            <h1>My Guestbooks</h1>
 | 
				
			||||||
 | 
					            <div>
 | 
				
			||||||
 | 
					                <button hx-get="/guestbooks/create" hx-target="closest div">New Guestbook</button>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					            @gbList(guestbooks)
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					templ GuestbookCreate(title string, data CommonData) {
 | 
				
			||||||
 | 
					    if data.IsHtmx {
 | 
				
			||||||
 | 
					        <form hx-post="/guestbooks/create" hx-target="closest div">
 | 
				
			||||||
 | 
					            @gbCreateForm(data.CSRFToken)
 | 
				
			||||||
 | 
					        </form>
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        @base(title, data) {
 | 
				
			||||||
 | 
					            <form action="/guestbooks/create" method="post">
 | 
				
			||||||
 | 
					                @gbCreateForm(data.CSRFToken)
 | 
				
			||||||
 | 
					            </form>
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					templ sidebar(guestbook models.Guestbook) {
 | 
				
			||||||
 | 
					    {{ gbUrl := fmt.Sprintf("/guestbooks/%s", guestbook.Slug()) }}
 | 
				
			||||||
 | 
					    <nav>
 | 
				
			||||||
 | 
					        <div>
 | 
				
			||||||
 | 
					            <h3>Messages</h3>
 | 
				
			||||||
 | 
					            <ul>
 | 
				
			||||||
 | 
					                <li><a href={ templ.URL(gbUrl + "/comments") }>Manage messages</a></li>
 | 
				
			||||||
 | 
					                <li><a href={ templ.URL(gbUrl + "/comments/queue") }>Review message queue</a></li>
 | 
				
			||||||
 | 
					                <li><a href={ templ.URL(gbUrl + "/blocklist") }>Block users</a></li>
 | 
				
			||||||
 | 
					                <li><a href={ templ.URL(gbUrl + "/comments/trash") }>Trash</a></li>
 | 
				
			||||||
 | 
					            </ul>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					        <div>
 | 
				
			||||||
 | 
					            <h3>Design</h3>
 | 
				
			||||||
 | 
					            <ul>
 | 
				
			||||||
 | 
					                <li><a href={ templ.URL(gbUrl + "/themes") }>Themes</a></li>
 | 
				
			||||||
 | 
					                <li><a href={ templ.URL(gbUrl + "/customize") }>Custom CSS</a></li>
 | 
				
			||||||
 | 
					            </ul>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					        <div>
 | 
				
			||||||
 | 
					            <h3>Account</h3>
 | 
				
			||||||
 | 
					            <ul>
 | 
				
			||||||
 | 
					                <li><a href="/users/settings">Settings</a></li>
 | 
				
			||||||
 | 
					                <li><a href="/users/privacy">Privacy</a></li>
 | 
				
			||||||
 | 
					                <li><a href="/help">Help</a></li>
 | 
				
			||||||
 | 
					            </ul>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					    </nav>
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					templ GuestbookView(title string, data CommonData, guestbook models.Guestbook, comments []models.GuestbookComment) {
 | 
				
			||||||
 | 
					    @base(title, data) {
 | 
				
			||||||
 | 
					        <div id="main">
 | 
				
			||||||
 | 
					            @sidebar(guestbook)
 | 
				
			||||||
 | 
					            <div>
 | 
				
			||||||
 | 
					                <h1>Guestbook for { guestbook.SiteUrl }</h1>
 | 
				
			||||||
 | 
					                {{ commentCreateUrl := fmt.Sprintf("/guestbooks/%s/comments/create", guestbook.Slug()) }}
 | 
				
			||||||
 | 
					                <p>
 | 
				
			||||||
 | 
					                    <a href={ templ.URL(commentCreateUrl) }>New Comment</a>
 | 
				
			||||||
 | 
					                </p>
 | 
				
			||||||
 | 
					                if len(comments) == 0 {
 | 
				
			||||||
 | 
					                    <p>No comments yet!</p>
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                for  _, c := range comments {
 | 
				
			||||||
 | 
					                    <div>
 | 
				
			||||||
 | 
					                        <strong>{ c.AuthorName }</strong>
 | 
				
			||||||
 | 
					                        { c.Created.Format("01-02-2006 03:04PM") }
 | 
				
			||||||
 | 
					                        <p>
 | 
				
			||||||
 | 
					                            { c.CommentText }
 | 
				
			||||||
 | 
					                        </p>
 | 
				
			||||||
 | 
					                    </div>
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										481
									
								
								ui/views/guestbooks_templ.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										481
									
								
								ui/views/guestbooks_templ.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,481 @@
 | 
				
			|||||||
 | 
					// Code generated by templ - DO NOT EDIT.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// templ: version: v0.3.833
 | 
				
			||||||
 | 
					package views
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//lint:file-ignore SA4006 This context is only used if a nested component is present.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "github.com/a-h/templ"
 | 
				
			||||||
 | 
					import templruntime "github.com/a-h/templ/runtime"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "fmt"
 | 
				
			||||||
 | 
					import "git.32bit.cafe/32bitcafe/guestbook/internal/models"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func gbCreateForm(csrf_token string) 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_Var1 := templ.GetChildren(ctx)
 | 
				
			||||||
 | 
							if templ_7745c5c3_Var1 == nil {
 | 
				
			||||||
 | 
								templ_7745c5c3_Var1 = templ.NopComponent
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							ctx = templ.ClearChildren(ctx)
 | 
				
			||||||
 | 
							templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<input type=\"hidden\" name=\"csrf_token\" value=\"")
 | 
				
			||||||
 | 
							if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
								return templ_7745c5c3_Err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							var templ_7745c5c3_Var2 string
 | 
				
			||||||
 | 
							templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(csrf_token)
 | 
				
			||||||
 | 
							if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
								return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/guestbooks.templ`, Line: 7, Col: 61}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2))
 | 
				
			||||||
 | 
							if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
								return templ_7745c5c3_Err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "\"> <label for=\"siteurl\">Site URL: </label> <input type=\"text\" name=\"siteurl\" id=\"siteurl\" required> <button type=\"submit\">Submit</button>")
 | 
				
			||||||
 | 
							if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
								return templ_7745c5c3_Err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func gbList(guestbooks []models.Guestbook) 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_Var3 := templ.GetChildren(ctx)
 | 
				
			||||||
 | 
							if templ_7745c5c3_Var3 == nil {
 | 
				
			||||||
 | 
								templ_7745c5c3_Var3 = templ.NopComponent
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							ctx = templ.ClearChildren(ctx)
 | 
				
			||||||
 | 
							if len(guestbooks) == 0 {
 | 
				
			||||||
 | 
								templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "<p>No Guestbooks yet</p>")
 | 
				
			||||||
 | 
								if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
									return templ_7745c5c3_Err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "<ul id=\"guestbooks\" hx-get=\"/guestbooks\" hx-trigger=\"newGuestbook from:body\" hx-swap=\"outerHTML\">")
 | 
				
			||||||
 | 
								if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
									return templ_7745c5c3_Err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								for _, gb := range guestbooks {
 | 
				
			||||||
 | 
									gbUrl := fmt.Sprintf("/guestbooks/%s", gb.Slug())
 | 
				
			||||||
 | 
									templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "<li><a href=\"")
 | 
				
			||||||
 | 
									if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
										return templ_7745c5c3_Err
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									var templ_7745c5c3_Var4 templ.SafeURL = templ.URL(gbUrl)
 | 
				
			||||||
 | 
									_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var4)))
 | 
				
			||||||
 | 
									if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
										return templ_7745c5c3_Err
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "\">")
 | 
				
			||||||
 | 
									if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
										return templ_7745c5c3_Err
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									if len(gb.SiteUrl) == 0 {
 | 
				
			||||||
 | 
										templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "Untitled")
 | 
				
			||||||
 | 
										if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
											return templ_7745c5c3_Err
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									} else {
 | 
				
			||||||
 | 
										var templ_7745c5c3_Var5 string
 | 
				
			||||||
 | 
										templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(gb.SiteUrl)
 | 
				
			||||||
 | 
										if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
											return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/guestbooks.templ`, Line: 24, Col: 36}
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
										_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
 | 
				
			||||||
 | 
										if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
											return templ_7745c5c3_Err
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "</a></li>")
 | 
				
			||||||
 | 
									if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
										return templ_7745c5c3_Err
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "</ul>")
 | 
				
			||||||
 | 
								if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
									return templ_7745c5c3_Err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func GuestbookList(title string, data CommonData, guestbooks []models.Guestbook) 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_Var6 := templ.GetChildren(ctx)
 | 
				
			||||||
 | 
							if templ_7745c5c3_Var6 == nil {
 | 
				
			||||||
 | 
								templ_7745c5c3_Var6 = templ.NopComponent
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							ctx = templ.ClearChildren(ctx)
 | 
				
			||||||
 | 
							if data.IsHtmx {
 | 
				
			||||||
 | 
								templ_7745c5c3_Err = gbList(guestbooks).Render(ctx, templ_7745c5c3_Buffer)
 | 
				
			||||||
 | 
								if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
									return templ_7745c5c3_Err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								templ_7745c5c3_Var7 := 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, 10, "<h1>My Guestbooks</h1><div><button hx-get=\"/guestbooks/create\" hx-target=\"closest div\">New Guestbook</button></div>")
 | 
				
			||||||
 | 
									if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
										return templ_7745c5c3_Err
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									templ_7745c5c3_Err = gbList(guestbooks).Render(ctx, templ_7745c5c3_Buffer)
 | 
				
			||||||
 | 
									if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
										return templ_7745c5c3_Err
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									return nil
 | 
				
			||||||
 | 
								})
 | 
				
			||||||
 | 
								templ_7745c5c3_Err = base(title, data).Render(templ.WithChildren(ctx, templ_7745c5c3_Var7), templ_7745c5c3_Buffer)
 | 
				
			||||||
 | 
								if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
									return templ_7745c5c3_Err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func GuestbookCreate(title string, data CommonData) 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_Var8 := templ.GetChildren(ctx)
 | 
				
			||||||
 | 
							if templ_7745c5c3_Var8 == nil {
 | 
				
			||||||
 | 
								templ_7745c5c3_Var8 = templ.NopComponent
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							ctx = templ.ClearChildren(ctx)
 | 
				
			||||||
 | 
							if data.IsHtmx {
 | 
				
			||||||
 | 
								templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "<form hx-post=\"/guestbooks/create\" hx-target=\"closest div\">")
 | 
				
			||||||
 | 
								if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
									return templ_7745c5c3_Err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								templ_7745c5c3_Err = gbCreateForm(data.CSRFToken).Render(ctx, templ_7745c5c3_Buffer)
 | 
				
			||||||
 | 
								if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
									return templ_7745c5c3_Err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "</form>")
 | 
				
			||||||
 | 
								if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
									return templ_7745c5c3_Err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								templ_7745c5c3_Var9 := 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, 13, "<form action=\"/guestbooks/create\" method=\"post\">")
 | 
				
			||||||
 | 
									if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
										return templ_7745c5c3_Err
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									templ_7745c5c3_Err = gbCreateForm(data.CSRFToken).Render(ctx, templ_7745c5c3_Buffer)
 | 
				
			||||||
 | 
									if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
										return templ_7745c5c3_Err
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "</form>")
 | 
				
			||||||
 | 
									if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
										return templ_7745c5c3_Err
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									return nil
 | 
				
			||||||
 | 
								})
 | 
				
			||||||
 | 
								templ_7745c5c3_Err = base(title, data).Render(templ.WithChildren(ctx, templ_7745c5c3_Var9), templ_7745c5c3_Buffer)
 | 
				
			||||||
 | 
								if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
									return templ_7745c5c3_Err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func sidebar(guestbook models.Guestbook) 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_Var10 := templ.GetChildren(ctx)
 | 
				
			||||||
 | 
							if templ_7745c5c3_Var10 == nil {
 | 
				
			||||||
 | 
								templ_7745c5c3_Var10 = templ.NopComponent
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							ctx = templ.ClearChildren(ctx)
 | 
				
			||||||
 | 
							gbUrl := fmt.Sprintf("/guestbooks/%s", guestbook.Slug())
 | 
				
			||||||
 | 
							templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "<nav><div><h3>Messages</h3><ul><li><a href=\"")
 | 
				
			||||||
 | 
							if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
								return templ_7745c5c3_Err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							var templ_7745c5c3_Var11 templ.SafeURL = templ.URL(gbUrl + "/comments")
 | 
				
			||||||
 | 
							_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var11)))
 | 
				
			||||||
 | 
							if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
								return templ_7745c5c3_Err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "\">Manage messages</a></li><li><a href=\"")
 | 
				
			||||||
 | 
							if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
								return templ_7745c5c3_Err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							var templ_7745c5c3_Var12 templ.SafeURL = templ.URL(gbUrl + "/comments/queue")
 | 
				
			||||||
 | 
							_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var12)))
 | 
				
			||||||
 | 
							if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
								return templ_7745c5c3_Err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 17, "\">Review message queue</a></li><li><a href=\"")
 | 
				
			||||||
 | 
							if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
								return templ_7745c5c3_Err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							var templ_7745c5c3_Var13 templ.SafeURL = templ.URL(gbUrl + "/blocklist")
 | 
				
			||||||
 | 
							_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var13)))
 | 
				
			||||||
 | 
							if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
								return templ_7745c5c3_Err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 18, "\">Block users</a></li><li><a href=\"")
 | 
				
			||||||
 | 
							if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
								return templ_7745c5c3_Err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							var templ_7745c5c3_Var14 templ.SafeURL = templ.URL(gbUrl + "/comments/trash")
 | 
				
			||||||
 | 
							_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var14)))
 | 
				
			||||||
 | 
							if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
								return templ_7745c5c3_Err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 19, "\">Trash</a></li></ul></div><div><h3>Design</h3><ul><li><a href=\"")
 | 
				
			||||||
 | 
							if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
								return templ_7745c5c3_Err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							var templ_7745c5c3_Var15 templ.SafeURL = templ.URL(gbUrl + "/themes")
 | 
				
			||||||
 | 
							_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var15)))
 | 
				
			||||||
 | 
							if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
								return templ_7745c5c3_Err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 20, "\">Themes</a></li><li><a href=\"")
 | 
				
			||||||
 | 
							if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
								return templ_7745c5c3_Err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							var templ_7745c5c3_Var16 templ.SafeURL = templ.URL(gbUrl + "/customize")
 | 
				
			||||||
 | 
							_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var16)))
 | 
				
			||||||
 | 
							if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
								return templ_7745c5c3_Err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 21, "\">Custom CSS</a></li></ul></div><div><h3>Account</h3><ul><li><a href=\"/users/settings\">Settings</a></li><li><a href=\"/users/privacy\">Privacy</a></li><li><a href=\"/help\">Help</a></li></ul></div></nav>")
 | 
				
			||||||
 | 
							if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
								return templ_7745c5c3_Err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func GuestbookView(title string, data CommonData, guestbook models.Guestbook, comments []models.GuestbookComment) 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_Var17 := templ.GetChildren(ctx)
 | 
				
			||||||
 | 
							if templ_7745c5c3_Var17 == nil {
 | 
				
			||||||
 | 
								templ_7745c5c3_Var17 = templ.NopComponent
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							ctx = templ.ClearChildren(ctx)
 | 
				
			||||||
 | 
							templ_7745c5c3_Var18 := 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, 22, "<div id=\"main\">")
 | 
				
			||||||
 | 
								if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
									return templ_7745c5c3_Err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								templ_7745c5c3_Err = sidebar(guestbook).Render(ctx, templ_7745c5c3_Buffer)
 | 
				
			||||||
 | 
								if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
									return templ_7745c5c3_Err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 23, "<div><h1>Guestbook for ")
 | 
				
			||||||
 | 
								if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
									return templ_7745c5c3_Err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								var templ_7745c5c3_Var19 string
 | 
				
			||||||
 | 
								templ_7745c5c3_Var19, templ_7745c5c3_Err = templ.JoinStringErrs(guestbook.SiteUrl)
 | 
				
			||||||
 | 
								if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
									return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/guestbooks.templ`, Line: 96, Col: 53}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var19))
 | 
				
			||||||
 | 
								if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
									return templ_7745c5c3_Err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 24, "</h1>")
 | 
				
			||||||
 | 
								if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
									return templ_7745c5c3_Err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								commentCreateUrl := fmt.Sprintf("/guestbooks/%s/comments/create", guestbook.Slug())
 | 
				
			||||||
 | 
								templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 25, "<p><a href=\"")
 | 
				
			||||||
 | 
								if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
									return templ_7745c5c3_Err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								var templ_7745c5c3_Var20 templ.SafeURL = templ.URL(commentCreateUrl)
 | 
				
			||||||
 | 
								_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var20)))
 | 
				
			||||||
 | 
								if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
									return templ_7745c5c3_Err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 26, "\">New Comment</a></p>")
 | 
				
			||||||
 | 
								if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
									return templ_7745c5c3_Err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if len(comments) == 0 {
 | 
				
			||||||
 | 
									templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 27, "<p>No comments yet!</p>")
 | 
				
			||||||
 | 
									if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
										return templ_7745c5c3_Err
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								for _, c := range comments {
 | 
				
			||||||
 | 
									templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 28, "<div><strong>")
 | 
				
			||||||
 | 
									if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
										return templ_7745c5c3_Err
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									var templ_7745c5c3_Var21 string
 | 
				
			||||||
 | 
									templ_7745c5c3_Var21, templ_7745c5c3_Err = templ.JoinStringErrs(c.AuthorName)
 | 
				
			||||||
 | 
									if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
										return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/guestbooks.templ`, Line: 106, Col: 46}
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									_, 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, 29, "</strong> ")
 | 
				
			||||||
 | 
									if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
										return templ_7745c5c3_Err
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									var templ_7745c5c3_Var22 string
 | 
				
			||||||
 | 
									templ_7745c5c3_Var22, templ_7745c5c3_Err = templ.JoinStringErrs(c.Created.Format("01-02-2006 03:04PM"))
 | 
				
			||||||
 | 
									if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
										return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/guestbooks.templ`, Line: 107, Col: 64}
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									_, 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, 30, "<p>")
 | 
				
			||||||
 | 
									if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
										return templ_7745c5c3_Err
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									var templ_7745c5c3_Var23 string
 | 
				
			||||||
 | 
									templ_7745c5c3_Var23, templ_7745c5c3_Err = templ.JoinStringErrs(c.CommentText)
 | 
				
			||||||
 | 
									if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
										return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/guestbooks.templ`, Line: 109, Col: 43}
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var23))
 | 
				
			||||||
 | 
									if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
										return templ_7745c5c3_Err
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 31, "</p></div>")
 | 
				
			||||||
 | 
									if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
										return templ_7745c5c3_Err
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 32, "</div></div>")
 | 
				
			||||||
 | 
								if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
									return templ_7745c5c3_Err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								return nil
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
							templ_7745c5c3_Err = base(title, data).Render(templ.WithChildren(ctx, templ_7745c5c3_Var18), templ_7745c5c3_Buffer)
 | 
				
			||||||
 | 
							if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
								return templ_7745c5c3_Err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var _ = templruntime.GeneratedTemplate
 | 
				
			||||||
							
								
								
									
										32
									
								
								ui/views/guestbooks_templ.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								ui/views/guestbooks_templ.txt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,32 @@
 | 
				
			|||||||
 | 
					<input type=\"hidden\" name=\"csrf_token\" value=\"
 | 
				
			||||||
 | 
					\"> <label for=\"siteurl\">Site URL: </label> <input type=\"text\" name=\"siteurl\" id=\"siteurl\" required> <button type=\"submit\">Submit</button>
 | 
				
			||||||
 | 
					<p>No Guestbooks yet</p>
 | 
				
			||||||
 | 
					<ul id=\"guestbooks\" hx-get=\"/guestbooks\" hx-trigger=\"newGuestbook from:body\" hx-swap=\"outerHTML\">
 | 
				
			||||||
 | 
					<li><a href=\"
 | 
				
			||||||
 | 
					\">
 | 
				
			||||||
 | 
					Untitled
 | 
				
			||||||
 | 
					</a></li>
 | 
				
			||||||
 | 
					</ul>
 | 
				
			||||||
 | 
					<h1>My Guestbooks</h1><div><button hx-get=\"/guestbooks/create\" hx-target=\"closest div\">New Guestbook</button></div>
 | 
				
			||||||
 | 
					<form hx-post=\"/guestbooks/create\" hx-target=\"closest div\">
 | 
				
			||||||
 | 
					</form>
 | 
				
			||||||
 | 
					<form action=\"/guestbooks/create\" method=\"post\">
 | 
				
			||||||
 | 
					</form>
 | 
				
			||||||
 | 
					<nav><div><h3>Messages</h3><ul><li><a href=\"
 | 
				
			||||||
 | 
					\">Manage messages</a></li><li><a href=\"
 | 
				
			||||||
 | 
					\">Review message queue</a></li><li><a href=\"
 | 
				
			||||||
 | 
					\">Block users</a></li><li><a href=\"
 | 
				
			||||||
 | 
					\">Trash</a></li></ul></div><div><h3>Design</h3><ul><li><a href=\"
 | 
				
			||||||
 | 
					\">Themes</a></li><li><a href=\"
 | 
				
			||||||
 | 
					\">Custom CSS</a></li></ul></div><div><h3>Account</h3><ul><li><a href=\"/users/settings\">Settings</a></li><li><a href=\"/users/privacy\">Privacy</a></li><li><a href=\"/help\">Help</a></li></ul></div></nav>
 | 
				
			||||||
 | 
					<div id=\"main\">
 | 
				
			||||||
 | 
					<div><h1>Guestbook for 
 | 
				
			||||||
 | 
					</h1>
 | 
				
			||||||
 | 
					<p><a href=\"
 | 
				
			||||||
 | 
					\">New Comment</a></p>
 | 
				
			||||||
 | 
					<p>No comments yet!</p>
 | 
				
			||||||
 | 
					<div><strong>
 | 
				
			||||||
 | 
					</strong> 
 | 
				
			||||||
 | 
					<p>
 | 
				
			||||||
 | 
					</p></div>
 | 
				
			||||||
 | 
					</div></div>
 | 
				
			||||||
							
								
								
									
										25
									
								
								ui/views/home.templ
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								ui/views/home.templ
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,25 @@
 | 
				
			|||||||
 | 
					package views
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					templ loggedInHome() {
 | 
				
			||||||
 | 
					    <h2>Tools</h2>
 | 
				
			||||||
 | 
					    <p>
 | 
				
			||||||
 | 
					        <a href="/guestbooks">Guestbooks</a>
 | 
				
			||||||
 | 
					    </p>
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					templ loggedOutHome() {
 | 
				
			||||||
 | 
					    <h2>Welcome</h2>
 | 
				
			||||||
 | 
					    <p>
 | 
				
			||||||
 | 
					        Welcome to webweav.ing, a collection of webmastery tools created by the <a href="https://32bit.cafe">32-Bit Cafe</a>.
 | 
				
			||||||
 | 
					    </p>
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					templ Home(title string, data CommonData) {
 | 
				
			||||||
 | 
					    @base(title, data) {
 | 
				
			||||||
 | 
					        if data.IsAuthenticated {
 | 
				
			||||||
 | 
					            @loggedInHome()
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            @loggedOutHome()
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										123
									
								
								ui/views/home_templ.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										123
									
								
								ui/views/home_templ.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,123 @@
 | 
				
			|||||||
 | 
					// Code generated by templ - DO NOT EDIT.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// templ: version: v0.3.833
 | 
				
			||||||
 | 
					package views
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//lint:file-ignore SA4006 This context is only used if a nested component is present.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "github.com/a-h/templ"
 | 
				
			||||||
 | 
					import templruntime "github.com/a-h/templ/runtime"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func loggedInHome() 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_Var1 := templ.GetChildren(ctx)
 | 
				
			||||||
 | 
							if templ_7745c5c3_Var1 == nil {
 | 
				
			||||||
 | 
								templ_7745c5c3_Var1 = templ.NopComponent
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							ctx = templ.ClearChildren(ctx)
 | 
				
			||||||
 | 
							templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<h2>Tools</h2><p><a href=\"/guestbooks\">Guestbooks</a></p>")
 | 
				
			||||||
 | 
							if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
								return templ_7745c5c3_Err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func loggedOutHome() 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_Var2 := templ.GetChildren(ctx)
 | 
				
			||||||
 | 
							if templ_7745c5c3_Var2 == nil {
 | 
				
			||||||
 | 
								templ_7745c5c3_Var2 = templ.NopComponent
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							ctx = templ.ClearChildren(ctx)
 | 
				
			||||||
 | 
							templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "<h2>Welcome</h2><p>Welcome to webweav.ing, a collection of webmastery tools created by the <a href=\"https://32bit.cafe\">32-Bit Cafe</a>.</p>")
 | 
				
			||||||
 | 
							if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
								return templ_7745c5c3_Err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func Home(title string, data CommonData) 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_Var3 := templ.GetChildren(ctx)
 | 
				
			||||||
 | 
							if templ_7745c5c3_Var3 == nil {
 | 
				
			||||||
 | 
								templ_7745c5c3_Var3 = templ.NopComponent
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							ctx = templ.ClearChildren(ctx)
 | 
				
			||||||
 | 
							templ_7745c5c3_Var4 := 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)
 | 
				
			||||||
 | 
								if data.IsAuthenticated {
 | 
				
			||||||
 | 
									templ_7745c5c3_Err = loggedInHome().Render(ctx, templ_7745c5c3_Buffer)
 | 
				
			||||||
 | 
									if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
										return templ_7745c5c3_Err
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									templ_7745c5c3_Err = loggedOutHome().Render(ctx, templ_7745c5c3_Buffer)
 | 
				
			||||||
 | 
									if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
										return templ_7745c5c3_Err
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								return nil
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
							templ_7745c5c3_Err = base(title, data).Render(templ.WithChildren(ctx, templ_7745c5c3_Var4), templ_7745c5c3_Buffer)
 | 
				
			||||||
 | 
							if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
								return templ_7745c5c3_Err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var _ = templruntime.GeneratedTemplate
 | 
				
			||||||
							
								
								
									
										2
									
								
								ui/views/home_templ.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								ui/views/home_templ.txt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,2 @@
 | 
				
			|||||||
 | 
					<h2>Tools</h2><p><a href=\"/guestbooks\">Guestbooks</a></p>
 | 
				
			||||||
 | 
					<h2>Welcome</h2><p>Welcome to webweav.ing, a collection of webmastery tools created by the <a href=\"https://32bit.cafe\">32-Bit Cafe</a>.</p>
 | 
				
			||||||
							
								
								
									
										83
									
								
								ui/views/users.templ
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										83
									
								
								ui/views/users.templ
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,83 @@
 | 
				
			|||||||
 | 
					package views
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"git.32bit.cafe/32bitcafe/guestbook/internal/forms"
 | 
				
			||||||
 | 
						"git.32bit.cafe/32bitcafe/guestbook/internal/models"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					templ UserLogin (title string, data CommonData, form forms.UserLoginForm) {
 | 
				
			||||||
 | 
					    @base(title, data) {
 | 
				
			||||||
 | 
					        <h1>Login</h1>
 | 
				
			||||||
 | 
					        <form action="/users/login" method="POST" novalidate>
 | 
				
			||||||
 | 
					            <input type="hidden" name="csrf_token" value={ data.CSRFToken }>
 | 
				
			||||||
 | 
					            for _, error := range form.NonFieldErrors {
 | 
				
			||||||
 | 
					                <div class="error">{ error }</div>
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            <div>
 | 
				
			||||||
 | 
					                <label>Email: </label>
 | 
				
			||||||
 | 
					                {{ error, exists := form.FieldErrors["email"] }}
 | 
				
			||||||
 | 
					                if exists {
 | 
				
			||||||
 | 
					                    <label class="error">{ error }</label>
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                <input type="email" name="email" value={form.Email}>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					            <div>
 | 
				
			||||||
 | 
					                <label>Password: </label>
 | 
				
			||||||
 | 
					                {{ error, exists = form.FieldErrors["password"] }}
 | 
				
			||||||
 | 
					                if exists {
 | 
				
			||||||
 | 
					                    <label class="error">{ error }</label>
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                <input type="password" name="password">
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					            <div>
 | 
				
			||||||
 | 
					                <input type="submit" value="login">
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					        </form>
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					templ UserRegistration (title string, data CommonData, form forms.UserRegistrationForm) {
 | 
				
			||||||
 | 
					    @base(title, data) {
 | 
				
			||||||
 | 
					        <h1>User Registration</h1>
 | 
				
			||||||
 | 
					        <form action="/users/register" method="post">
 | 
				
			||||||
 | 
					            <input type="hidden" name="csrf_token" value={ data.CSRFToken }>
 | 
				
			||||||
 | 
					            <div>
 | 
				
			||||||
 | 
					                {{ error, exists := form.FieldErrors["name"] }}
 | 
				
			||||||
 | 
					                <label for="username">Username: </label>
 | 
				
			||||||
 | 
					                if exists {
 | 
				
			||||||
 | 
					                    <label class="error">{ error }</label>
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                <input type="text" name="username" id="username" value={form.Name} required />
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					            <div>
 | 
				
			||||||
 | 
					                {{ error, exists = form.FieldErrors["email"] }}
 | 
				
			||||||
 | 
					                <label for="email">Email: </label>
 | 
				
			||||||
 | 
					                if exists {
 | 
				
			||||||
 | 
					                    <label class="error">{ error }</label>
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                <input type="text" name="email" id="email" value={form.Email} required />
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					            <div>
 | 
				
			||||||
 | 
					                {{ error, exists = form.FieldErrors["password"] }}
 | 
				
			||||||
 | 
					                <label for="password">Password: </label>
 | 
				
			||||||
 | 
					                if exists {
 | 
				
			||||||
 | 
					                    <label class="error">{ error }</label>
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                <input type="password" name="password" id="password" />
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					            <div>
 | 
				
			||||||
 | 
					                <input type="submit" value="Register" />
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					        </form>
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					templ UserProfile (title string, data CommonData, user models.User) {
 | 
				
			||||||
 | 
					    @base(title, data) {
 | 
				
			||||||
 | 
					        <h1>{ user.Username }</h1>
 | 
				
			||||||
 | 
					        <p>{ user.Email }</p>
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					templ UserSettings () {
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										428
									
								
								ui/views/users_templ.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										428
									
								
								ui/views/users_templ.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,428 @@
 | 
				
			|||||||
 | 
					// Code generated by templ - DO NOT EDIT.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// templ: version: v0.3.833
 | 
				
			||||||
 | 
					package views
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//lint:file-ignore SA4006 This context is only used if a nested component is present.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "github.com/a-h/templ"
 | 
				
			||||||
 | 
					import templruntime "github.com/a-h/templ/runtime"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"git.32bit.cafe/32bitcafe/guestbook/internal/forms"
 | 
				
			||||||
 | 
						"git.32bit.cafe/32bitcafe/guestbook/internal/models"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func UserLogin(title string, data CommonData, form forms.UserLoginForm) 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_Var1 := templ.GetChildren(ctx)
 | 
				
			||||||
 | 
							if templ_7745c5c3_Var1 == nil {
 | 
				
			||||||
 | 
								templ_7745c5c3_Var1 = templ.NopComponent
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							ctx = templ.ClearChildren(ctx)
 | 
				
			||||||
 | 
							templ_7745c5c3_Var2 := 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, 1, "<h1>Login</h1><form action=\"/users/login\" method=\"POST\" novalidate><input type=\"hidden\" name=\"csrf_token\" value=\"")
 | 
				
			||||||
 | 
								if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
									return templ_7745c5c3_Err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								var templ_7745c5c3_Var3 string
 | 
				
			||||||
 | 
								templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(data.CSRFToken)
 | 
				
			||||||
 | 
								if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
									return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/users.templ`, Line: 12, Col: 73}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
 | 
				
			||||||
 | 
								if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
									return templ_7745c5c3_Err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "\"> ")
 | 
				
			||||||
 | 
								if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
									return templ_7745c5c3_Err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								for _, error := range form.NonFieldErrors {
 | 
				
			||||||
 | 
									templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "<div class=\"error\">")
 | 
				
			||||||
 | 
									if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
										return templ_7745c5c3_Err
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									var templ_7745c5c3_Var4 string
 | 
				
			||||||
 | 
									templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(error)
 | 
				
			||||||
 | 
									if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
										return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/users.templ`, Line: 14, Col: 42}
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
 | 
				
			||||||
 | 
									if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
										return templ_7745c5c3_Err
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "</div>")
 | 
				
			||||||
 | 
									if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
										return templ_7745c5c3_Err
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "<div><label>Email: </label>")
 | 
				
			||||||
 | 
								if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
									return templ_7745c5c3_Err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								error, exists := form.FieldErrors["email"]
 | 
				
			||||||
 | 
								if exists {
 | 
				
			||||||
 | 
									templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "<label class=\"error\">")
 | 
				
			||||||
 | 
									if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
										return templ_7745c5c3_Err
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									var templ_7745c5c3_Var5 string
 | 
				
			||||||
 | 
									templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(error)
 | 
				
			||||||
 | 
									if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
										return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/users.templ`, Line: 20, Col: 48}
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
 | 
				
			||||||
 | 
									if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
										return templ_7745c5c3_Err
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "</label> ")
 | 
				
			||||||
 | 
									if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
										return templ_7745c5c3_Err
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "<input type=\"email\" name=\"email\" value=\"")
 | 
				
			||||||
 | 
								if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
									return templ_7745c5c3_Err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								var templ_7745c5c3_Var6 string
 | 
				
			||||||
 | 
								templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(form.Email)
 | 
				
			||||||
 | 
								if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
									return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/users.templ`, Line: 22, Col: 66}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6))
 | 
				
			||||||
 | 
								if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
									return templ_7745c5c3_Err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "\"></div><div><label>Password: </label>")
 | 
				
			||||||
 | 
								if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
									return templ_7745c5c3_Err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								error, exists = form.FieldErrors["password"]
 | 
				
			||||||
 | 
								if exists {
 | 
				
			||||||
 | 
									templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "<label class=\"error\">")
 | 
				
			||||||
 | 
									if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
										return templ_7745c5c3_Err
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									var templ_7745c5c3_Var7 string
 | 
				
			||||||
 | 
									templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(error)
 | 
				
			||||||
 | 
									if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
										return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/users.templ`, Line: 28, Col: 48}
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7))
 | 
				
			||||||
 | 
									if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
										return templ_7745c5c3_Err
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "</label> ")
 | 
				
			||||||
 | 
									if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
										return templ_7745c5c3_Err
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "<input type=\"password\" name=\"password\"></div><div><input type=\"submit\" value=\"login\"></div></form>")
 | 
				
			||||||
 | 
								if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
									return templ_7745c5c3_Err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								return nil
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
							templ_7745c5c3_Err = base(title, data).Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer)
 | 
				
			||||||
 | 
							if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
								return templ_7745c5c3_Err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func UserRegistration(title string, data CommonData, form forms.UserRegistrationForm) 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_Var8 := templ.GetChildren(ctx)
 | 
				
			||||||
 | 
							if templ_7745c5c3_Var8 == nil {
 | 
				
			||||||
 | 
								templ_7745c5c3_Var8 = templ.NopComponent
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							ctx = templ.ClearChildren(ctx)
 | 
				
			||||||
 | 
							templ_7745c5c3_Var9 := 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, 13, "<h1>User Registration</h1><form action=\"/users/register\" method=\"post\"><input type=\"hidden\" name=\"csrf_token\" value=\"")
 | 
				
			||||||
 | 
								if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
									return templ_7745c5c3_Err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								var templ_7745c5c3_Var10 string
 | 
				
			||||||
 | 
								templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs(data.CSRFToken)
 | 
				
			||||||
 | 
								if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
									return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/users.templ`, Line: 43, Col: 73}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10))
 | 
				
			||||||
 | 
								if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
									return templ_7745c5c3_Err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "\"><div>")
 | 
				
			||||||
 | 
								if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
									return templ_7745c5c3_Err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								error, exists := form.FieldErrors["name"]
 | 
				
			||||||
 | 
								templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "<label for=\"username\">Username: </label> ")
 | 
				
			||||||
 | 
								if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
									return templ_7745c5c3_Err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if exists {
 | 
				
			||||||
 | 
									templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "<label class=\"error\">")
 | 
				
			||||||
 | 
									if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
										return templ_7745c5c3_Err
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									var templ_7745c5c3_Var11 string
 | 
				
			||||||
 | 
									templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(error)
 | 
				
			||||||
 | 
									if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
										return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/users.templ`, Line: 48, Col: 48}
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11))
 | 
				
			||||||
 | 
									if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
										return templ_7745c5c3_Err
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 17, "</label> ")
 | 
				
			||||||
 | 
									if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
										return templ_7745c5c3_Err
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 18, "<input type=\"text\" name=\"username\" id=\"username\" value=\"")
 | 
				
			||||||
 | 
								if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
									return templ_7745c5c3_Err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								var templ_7745c5c3_Var12 string
 | 
				
			||||||
 | 
								templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinStringErrs(form.Name)
 | 
				
			||||||
 | 
								if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
									return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/users.templ`, Line: 50, Col: 81}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var12))
 | 
				
			||||||
 | 
								if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
									return templ_7745c5c3_Err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 19, "\" required></div><div>")
 | 
				
			||||||
 | 
								if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
									return templ_7745c5c3_Err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								error, exists = form.FieldErrors["email"]
 | 
				
			||||||
 | 
								templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 20, "<label for=\"email\">Email: </label> ")
 | 
				
			||||||
 | 
								if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
									return templ_7745c5c3_Err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if exists {
 | 
				
			||||||
 | 
									templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 21, "<label class=\"error\">")
 | 
				
			||||||
 | 
									if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
										return templ_7745c5c3_Err
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									var templ_7745c5c3_Var13 string
 | 
				
			||||||
 | 
									templ_7745c5c3_Var13, templ_7745c5c3_Err = templ.JoinStringErrs(error)
 | 
				
			||||||
 | 
									if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
										return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/users.templ`, Line: 56, Col: 48}
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var13))
 | 
				
			||||||
 | 
									if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
										return templ_7745c5c3_Err
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 22, "</label> ")
 | 
				
			||||||
 | 
									if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
										return templ_7745c5c3_Err
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 23, "<input type=\"text\" name=\"email\" id=\"email\" value=\"")
 | 
				
			||||||
 | 
								if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
									return templ_7745c5c3_Err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								var templ_7745c5c3_Var14 string
 | 
				
			||||||
 | 
								templ_7745c5c3_Var14, templ_7745c5c3_Err = templ.JoinStringErrs(form.Email)
 | 
				
			||||||
 | 
								if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
									return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/users.templ`, Line: 58, Col: 76}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var14))
 | 
				
			||||||
 | 
								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 {
 | 
				
			||||||
 | 
									return templ_7745c5c3_Err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								error, exists = form.FieldErrors["password"]
 | 
				
			||||||
 | 
								templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 25, "<label for=\"password\">Password: </label> ")
 | 
				
			||||||
 | 
								if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
									return templ_7745c5c3_Err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if exists {
 | 
				
			||||||
 | 
									templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 26, "<label class=\"error\">")
 | 
				
			||||||
 | 
									if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
										return templ_7745c5c3_Err
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									var templ_7745c5c3_Var15 string
 | 
				
			||||||
 | 
									templ_7745c5c3_Var15, templ_7745c5c3_Err = templ.JoinStringErrs(error)
 | 
				
			||||||
 | 
									if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
										return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/users.templ`, Line: 64, Col: 48}
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var15))
 | 
				
			||||||
 | 
									if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
										return templ_7745c5c3_Err
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 27, "</label> ")
 | 
				
			||||||
 | 
									if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
										return templ_7745c5c3_Err
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 28, "<input type=\"password\" name=\"password\" id=\"password\"></div><div><input type=\"submit\" value=\"Register\"></div></form>")
 | 
				
			||||||
 | 
								if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
									return templ_7745c5c3_Err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								return nil
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
							templ_7745c5c3_Err = base(title, data).Render(templ.WithChildren(ctx, templ_7745c5c3_Var9), templ_7745c5c3_Buffer)
 | 
				
			||||||
 | 
							if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
								return templ_7745c5c3_Err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func UserProfile(title string, data CommonData, user models.User) 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_Var16 := templ.GetChildren(ctx)
 | 
				
			||||||
 | 
							if templ_7745c5c3_Var16 == nil {
 | 
				
			||||||
 | 
								templ_7745c5c3_Var16 = templ.NopComponent
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							ctx = templ.ClearChildren(ctx)
 | 
				
			||||||
 | 
							templ_7745c5c3_Var17 := 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, 29, "<h1>")
 | 
				
			||||||
 | 
								if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
									return templ_7745c5c3_Err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								var templ_7745c5c3_Var18 string
 | 
				
			||||||
 | 
								templ_7745c5c3_Var18, templ_7745c5c3_Err = templ.JoinStringErrs(user.Username)
 | 
				
			||||||
 | 
								if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
									return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/users.templ`, Line: 77, Col: 27}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								_, 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, 30, "</h1><p>")
 | 
				
			||||||
 | 
								if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
									return templ_7745c5c3_Err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								var templ_7745c5c3_Var19 string
 | 
				
			||||||
 | 
								templ_7745c5c3_Var19, templ_7745c5c3_Err = templ.JoinStringErrs(user.Email)
 | 
				
			||||||
 | 
								if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
									return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/users.templ`, Line: 78, Col: 23}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var19))
 | 
				
			||||||
 | 
								if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
									return templ_7745c5c3_Err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 31, "</p>")
 | 
				
			||||||
 | 
								if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
									return templ_7745c5c3_Err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								return nil
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
							templ_7745c5c3_Err = base(title, data).Render(templ.WithChildren(ctx, templ_7745c5c3_Var17), templ_7745c5c3_Buffer)
 | 
				
			||||||
 | 
							if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
								return templ_7745c5c3_Err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func UserSettings() 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_Var20 := templ.GetChildren(ctx)
 | 
				
			||||||
 | 
							if templ_7745c5c3_Var20 == nil {
 | 
				
			||||||
 | 
								templ_7745c5c3_Var20 = templ.NopComponent
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							ctx = templ.ClearChildren(ctx)
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var _ = templruntime.GeneratedTemplate
 | 
				
			||||||
							
								
								
									
										31
									
								
								ui/views/users_templ.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								ui/views/users_templ.txt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,31 @@
 | 
				
			|||||||
 | 
					<h1>Login</h1><form action=\"/users/login\" method=\"POST\" novalidate><input type=\"hidden\" name=\"csrf_token\" value=\"
 | 
				
			||||||
 | 
					\"> 
 | 
				
			||||||
 | 
					<div class=\"error\">
 | 
				
			||||||
 | 
					</div>
 | 
				
			||||||
 | 
					<div><label>Email: </label>
 | 
				
			||||||
 | 
					<label class=\"error\">
 | 
				
			||||||
 | 
					</label> 
 | 
				
			||||||
 | 
					<input type=\"email\" name=\"email\" value=\"
 | 
				
			||||||
 | 
					\"></div><div><label>Password: </label>
 | 
				
			||||||
 | 
					<label class=\"error\">
 | 
				
			||||||
 | 
					</label> 
 | 
				
			||||||
 | 
					<input type=\"password\" name=\"password\"></div><div><input type=\"submit\" value=\"login\"></div></form>
 | 
				
			||||||
 | 
					<h1>User Registration</h1><form action=\"/users/register\" method=\"post\"><input type=\"hidden\" name=\"csrf_token\" value=\"
 | 
				
			||||||
 | 
					\"><div>
 | 
				
			||||||
 | 
					<label for=\"username\">Username: </label> 
 | 
				
			||||||
 | 
					<label class=\"error\">
 | 
				
			||||||
 | 
					</label> 
 | 
				
			||||||
 | 
					<input type=\"text\" name=\"username\" id=\"username\" value=\"
 | 
				
			||||||
 | 
					\" required></div><div>
 | 
				
			||||||
 | 
					<label for=\"email\">Email: </label> 
 | 
				
			||||||
 | 
					<label class=\"error\">
 | 
				
			||||||
 | 
					</label> 
 | 
				
			||||||
 | 
					<input type=\"text\" name=\"email\" id=\"email\" value=\"
 | 
				
			||||||
 | 
					\" required></div><div>
 | 
				
			||||||
 | 
					<label for=\"password\">Password: </label> 
 | 
				
			||||||
 | 
					<label class=\"error\">
 | 
				
			||||||
 | 
					</label> 
 | 
				
			||||||
 | 
					<input type=\"password\" name=\"password\" id=\"password\"></div><div><input type=\"submit\" value=\"Register\"></div></form>
 | 
				
			||||||
 | 
					<h1>
 | 
				
			||||||
 | 
					</h1><p>
 | 
				
			||||||
 | 
					</p>
 | 
				
			||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user