diff --git a/cmd/web/handlers_guestbook.go b/cmd/web/handlers_guestbook.go index 30f97cd..00217b1 100644 --- a/cmd/web/handlers_guestbook.go +++ b/cmd/web/handlers_guestbook.go @@ -4,6 +4,7 @@ import ( "errors" "fmt" "net/http" + "strconv" "time" "git.32bit.cafe/32bitcafe/guestbook/internal/forms" @@ -23,6 +24,26 @@ func (app *application) getGuestbook(w http.ResponseWriter, r *http.Request) { } return } + website.Guestbook, err = app.guestbooks.Get(website.Guestbook.ShortId) + if err != nil { + if errors.Is(err, models.ErrNoRecord) { + http.NotFound(w, r) + } else { + app.serverError(w, r, err) + } + return + } + if !website.Guestbook.Settings.IsVisible { + u := app.getCurrentUser(r) + if u == nil { + app.clientError(w, http.StatusForbidden) + return + } + if u.ID != website.UserId { + app.clientError(w, http.StatusForbidden) + return + } + } comments, err := app.guestbookComments.GetAll(website.Guestbook.ID) if err != nil { app.serverError(w, r, err) @@ -42,10 +63,76 @@ func (app *application) getGuestbookSettings(w http.ResponseWriter, r *http.Requ app.serverError(w, r, err) } } + website.Guestbook, err = app.guestbooks.Get(website.Guestbook.ShortId) + if err != nil { + if errors.Is(err, models.ErrNoRecord) { + http.NotFound(w, r) + } else { + app.serverError(w, r, err) + } + } data := app.newCommonData(r) views.GuestbookSettingsView(data, website).Render(r.Context(), w) } +func (app *application) putGuestbookSettings(w http.ResponseWriter, r *http.Request) { + slug := r.PathValue("id") + website, err := app.websites.Get(slugToShortId(slug)) + if err != nil { + if errors.Is(err, models.ErrNoRecord) { + http.NotFound(w, r) + } else { + app.serverError(w, r, err) + } + } + + var form forms.GuestbookSettingsForm + err = app.decodePostForm(r, &form) + if err != nil { + app.clientError(w, http.StatusBadRequest) + app.serverError(w, r, err) + return + } + form.CheckField(validator.PermittedValue(form.Visibility, "true", "false"), "gb_visible", "Invalid value") + form.CheckField(validator.PermittedValue(form.CommentingEnabled, models.ValidDisableDurations...), "gb_visible", "Invalid value") + form.CheckField(validator.PermittedValue(form.WidgetsEnabled, "true", "false"), "gb_remote", "Invalid value") + if !form.Valid() { + // TODO: rerender template with errors + app.clientError(w, http.StatusUnprocessableEntity) + } + + c, err := strconv.ParseBool(form.CommentingEnabled) + if err != nil { + website.Guestbook.Settings.IsCommentingEnabled = false + website.Guestbook.Settings.ReenableCommenting, err = app.durationToTime(form.CommentingEnabled) + if err != nil { + app.serverError(w, r, err) + } + } else { + website.Guestbook.Settings.IsCommentingEnabled = c + } + + // can skip error checking for these two since we verify valid values above + website.Guestbook.Settings.IsVisible, err = strconv.ParseBool(form.Visibility) + if err != nil { + app.serverError(w, r, err) + } + website.Guestbook.Settings.AllowRemoteHostAccess, err = strconv.ParseBool(form.WidgetsEnabled) + if err != nil { + app.serverError(w, r, err) + } + err = app.guestbooks.UpdateGuestbookSettings(website.Guestbook.ID, website.Guestbook.Settings) + if err != nil { + app.serverError(w, r, err) + return + } + app.sessionManager.Put(r.Context(), "flash", "Settings changed successfully") + data := app.newCommonData(r) + w.Header().Add("HX-Refresh", "true") + views.GuestbookSettingsView(data, website).Render(r.Context(), w) + +} + func (app *application) getGuestbookComments(w http.ResponseWriter, r *http.Request) { slug := r.PathValue("id") website, err := app.websites.Get(slugToShortId(slug)) @@ -57,6 +144,14 @@ func (app *application) getGuestbookComments(w http.ResponseWriter, r *http.Requ } return } + website.Guestbook, err = app.guestbooks.Get(website.Guestbook.ShortId) + if err != nil { + if errors.Is(err, models.ErrNoRecord) { + http.NotFound(w, r) + } else { + app.serverError(w, r, err) + } + } comments, err := app.guestbookComments.GetAll(website.Guestbook.ID) if err != nil { app.serverError(w, r, err) @@ -78,6 +173,14 @@ func (app *application) getGuestbookCommentCreate(w http.ResponseWriter, r *http } return } + website.Guestbook, err = app.guestbooks.Get(website.Guestbook.ShortId) + if err != nil { + if errors.Is(err, models.ErrNoRecord) { + http.NotFound(w, r) + } else { + app.serverError(w, r, err) + } + } data := app.newCommonData(r) form := forms.CommentCreateForm{} @@ -95,6 +198,19 @@ func (app *application) postGuestbookCommentCreate(w http.ResponseWriter, r *htt } return } + website.Guestbook, err = app.guestbooks.Get(website.Guestbook.ShortId) + if err != nil { + if errors.Is(err, models.ErrNoRecord) { + http.NotFound(w, r) + } else { + app.serverError(w, r, err) + } + } + + if !website.Guestbook.CanComment() { + app.clientError(w, http.StatusForbidden) + return + } var form forms.CommentCreateForm err = app.decodePostForm(r, &form) @@ -143,6 +259,14 @@ func (app *application) getCommentQueue(w http.ResponseWriter, r *http.Request) } return } + website.Guestbook, err = app.guestbooks.Get(website.Guestbook.ShortId) + if err != nil { + if errors.Is(err, models.ErrNoRecord) { + http.NotFound(w, r) + } else { + app.serverError(w, r, err) + } + } comments, err := app.guestbookComments.GetUnpublished(website.Guestbook.ID) if err != nil { @@ -169,6 +293,14 @@ func (app *application) getCommentTrash(w http.ResponseWriter, r *http.Request) } return } + website.Guestbook, err = app.guestbooks.Get(website.Guestbook.ShortId) + if err != nil { + if errors.Is(err, models.ErrNoRecord) { + http.NotFound(w, r) + } else { + app.serverError(w, r, err) + } + } comments, err := app.guestbookComments.GetDeleted(website.Guestbook.ID) if err != nil { @@ -200,6 +332,14 @@ func (app *application) putHideGuestbookComment(w http.ResponseWriter, r *http.R if user.ID != website.UserId { app.clientError(w, http.StatusUnauthorized) } + website.Guestbook, err = app.guestbooks.Get(website.Guestbook.ShortId) + if err != nil { + if errors.Is(err, models.ErrNoRecord) { + http.NotFound(w, r) + } else { + app.serverError(w, r, err) + } + } cSlug := r.PathValue("commentId") comment, err := app.guestbookComments.Get(slugToShortId(cSlug)) if err != nil { @@ -234,6 +374,14 @@ func (app *application) deleteGuestbookComment(w http.ResponseWriter, r *http.Re if user.ID != website.UserId { app.clientError(w, http.StatusUnauthorized) } + website.Guestbook, err = app.guestbooks.Get(website.Guestbook.ShortId) + if err != nil { + if errors.Is(err, models.ErrNoRecord) { + http.NotFound(w, r) + } else { + app.serverError(w, r, err) + } + } cSlug := r.PathValue("commentId") comment, err := app.guestbookComments.Get(slugToShortId(cSlug)) if err != nil { diff --git a/cmd/web/helpers.go b/cmd/web/helpers.go index 43a6cc5..85959d6 100644 --- a/cmd/web/helpers.go +++ b/cmd/web/helpers.go @@ -118,3 +118,13 @@ func DefaultUserSettings() models.UserSettings { LocalTimezone: time.Now().UTC().Location(), } } + +func (app *application) durationToTime(duration string) (time.Time, error) { + var result time.Time + offset, err := time.ParseDuration(duration) + if err != nil { + return result, nil + } + result = time.Now().UTC().Add(offset) + return result, nil +} diff --git a/cmd/web/main.go b/cmd/web/main.go index 7b678b6..89e2ff1 100644 --- a/cmd/web/main.go +++ b/cmd/web/main.go @@ -71,6 +71,11 @@ func main() { logger.Error(err.Error()) os.Exit(1) } + err = app.guestbooks.InitializeSettingsMap() + if err != nil { + logger.Error(err.Error()) + os.Exit(1) + } tlsConfig := &tls.Config{ CurvePreferences: []tls.CurveID{tls.X25519, tls.CurveP256}, diff --git a/cmd/web/routes.go b/cmd/web/routes.go index 2a26790..c2fe48a 100644 --- a/cmd/web/routes.go +++ b/cmd/web/routes.go @@ -42,6 +42,7 @@ func (app *application) routes() http.Handler { mux.Handle("DELETE /websites/{id}/dashboard/guestbook/comments/{commentId}", protected.ThenFunc(app.deleteGuestbookComment)) mux.Handle("PUT /websites/{id}/dashboard/guestbook/comments/{commentId}", protected.ThenFunc(app.putHideGuestbookComment)) mux.Handle("GET /websites/{id}/dashboard/guestbook/settings", protected.ThenFunc(app.getGuestbookSettings)) + mux.Handle("PUT /websites/{id}/dashboard/guestbook/settings", protected.ThenFunc(app.putGuestbookSettings)) mux.Handle("GET /websites/{id}/dashboard/guestbook/comments/trash", protected.ThenFunc(app.getCommentTrash)) mux.Handle("GET /websites/{id}/dashboard/guestbook/themes", protected.ThenFunc(app.getComingSoon)) mux.Handle("GET /websites/{id}/dashboard/guestbook/customize", protected.ThenFunc(app.getComingSoon)) diff --git a/internal/forms/forms.go b/internal/forms/forms.go index 8891f2b..2014c84 100644 --- a/internal/forms/forms.go +++ b/internal/forms/forms.go @@ -34,3 +34,10 @@ type UserSettingsForm struct { LocalTimezone string `schema:"timezones"` validator.Validator `schema:"-"` } + +type GuestbookSettingsForm struct { + Visibility string `schema:"gb_visible"` + CommentingEnabled string `schema:"gb_commenting"` + WidgetsEnabled string `schema:"gb_remote"` + validator.Validator `schema:"-"` +} diff --git a/internal/models/guestbook.go b/internal/models/guestbook.go index a9e762a..42a8a9b 100644 --- a/internal/models/guestbook.go +++ b/internal/models/guestbook.go @@ -2,6 +2,7 @@ package models import ( "database/sql" + "errors" "strconv" "time" ) @@ -14,6 +15,8 @@ type GuestbookSettings struct { AllowRemoteHostAccess bool } +var ValidDisableDurations = []string{"true", "false", "1h", "4h", "8h", "24h", "72h", "168h"} + const ( SettingGbCommentingEnabled = "commenting_enabled" SettingGbReenableComments = "reenable_comments" @@ -33,6 +36,11 @@ type Guestbook struct { Settings GuestbookSettings } +func (g Guestbook) CanComment() bool { + now := time.Now().UTC() + return g.Settings.IsCommentingEnabled && g.Settings.ReenableCommenting.Before(now) +} + type GuestbookModel struct { DB *sql.DB Settings map[string]Setting @@ -96,11 +104,19 @@ func (m *GuestbookModel) Get(shortId uint64) (Guestbook, error) { var t sql.NullTime err := row.Scan(&g.ID, &g.ShortId, &g.UserId, &g.WebsiteId, &g.Created, &t, &g.IsActive) if err != nil { + if errors.Is(err, sql.ErrNoRows) { + return Guestbook{}, ErrNoRecord + } return Guestbook{}, err } if t.Valid { g.Deleted = t.Time } + settings, err := m.GetSettings(g.ID) + if err != nil { + return g, err + } + g.Settings = settings return g, nil } @@ -126,6 +142,58 @@ func (m *GuestbookModel) GetAll(userId int64) ([]Guestbook, error) { return guestbooks, nil } +func (m *GuestbookModel) GetSettings(guestbookId int64) (GuestbookSettings, error) { + stmt := `SELECT g.SettingId, a.ItemValue, g.UnconstrainedValue FROM guestbook_settings AS g + LEFT JOIN allowed_setting_values AS a ON g.AllowedSettingValueId = a.Id + WHERE GuestbookId = ?` + var settings GuestbookSettings + rows, err := m.DB.Query(stmt, guestbookId) + if err != nil { + return settings, err + } + for rows.Next() { + var id int + var itemValue sql.NullString + var unconstrainedValue sql.NullString + err = rows.Scan(&id, &itemValue, &unconstrainedValue) + if err != nil { + return settings, err + } + switch id { + case m.Settings[SettingGbCommentingEnabled].id: + settings.IsCommentingEnabled, err = strconv.ParseBool(itemValue.String) + if err != nil { + return settings, err + } + break + case m.Settings[SettingGbReenableComments].id: + settings.ReenableCommenting, err = time.Parse(time.RFC3339, unconstrainedValue.String) + if err != nil { + return settings, err + } + break + case m.Settings[SettingGbVisible].id: + settings.IsVisible, err = strconv.ParseBool(itemValue.String) + if err != nil { + return settings, err + } + break + case m.Settings[SettingGbAllowRemote].id: + settings.AllowRemoteHostAccess, err = strconv.ParseBool(itemValue.String) + if err != nil { + return settings, err + } + break + } + } + // if comment disable setting has expired, enable commenting + if time.Now().UTC().After(settings.ReenableCommenting) { + settings.IsCommentingEnabled = true + m.UpdateSetting(guestbookId, m.Settings[SettingGbCommentingEnabled], "true") + } + return settings, nil +} + func (m *GuestbookModel) initializeGuestbookSettings(guestbookId int64, settings GuestbookSettings) error { stmt := `INSERT INTO guestbook_settings (GuestbookId, SettingId, AllowedSettingValueId, UnconstrainedValue) VALUES (?, ?, ?, ?), @@ -145,11 +213,40 @@ func (m *GuestbookModel) initializeGuestbookSettings(guestbookId int64, settings } func (m *GuestbookModel) UpdateGuestbookSettings(guestbookId int64, settings GuestbookSettings) error { - err := m.UpdateSetting(guestbookId, m.Settings[SettingGbCommentingEnabled], strconv.FormatBool(settings.IsCommentingEnabled)) + err := m.UpdateSetting(guestbookId, m.Settings[SettingGbVisible], strconv.FormatBool(settings.IsVisible)) if err != nil { return err } - err = m.UpdateSetting(guestbookId, m.Settings[SettingGbReenableComments], settings.ReenableCommenting.String()) + err = m.UpdateSetting(guestbookId, m.Settings[SettingGbAllowRemote], strconv.FormatBool(settings.AllowRemoteHostAccess)) + if err != nil { + return err + } + err = m.UpdateSetting(guestbookId, m.Settings[SettingGbCommentingEnabled], strconv.FormatBool(settings.IsCommentingEnabled)) + if err != nil { + return err + } + err = m.UpdateSetting(guestbookId, m.Settings[SettingGbReenableComments], settings.ReenableCommenting.Format(time.RFC3339)) + if err != nil { + return err + } + return nil +} + +func (m *GuestbookModel) InsertSetting(guestbookId int64, setting Setting, value string) error { + stmt := ` +INSERT INTO guestbook_settings (GuestbookId, SettingId, AllowedSettingValueId, UnconstrainedValue) +SELECT ?, + settings.Id, + (SELECT Id FROM allowed_setting_values WHERE SettingId = settings.id AND ItemValue = ?), + CASE WHEN NOT EXISTS (SELECT 1 FROM settings AS s where s.Id = settings.Id AND s.Constrained = 1) THEN ? ELSE NULL END +FROM settings +WHERE settings.id = ? + ` + result, err := m.DB.Exec(stmt, guestbookId, value, value, setting.id) + if err != nil { + return err + } + _, err = result.LastInsertId() if err != nil { return err } diff --git a/internal/models/settings.go b/internal/models/settings.go index 3dfadc9..9ae8259 100644 --- a/internal/models/settings.go +++ b/internal/models/settings.go @@ -121,7 +121,7 @@ func (s *Setting) validateInt(value string) bool { } func (s *Setting) validateDatetime(value string) bool { - v, err := time.Parse(time.DateTime, value) + v, err := time.Parse(time.RFC3339, value) if err != nil { return false } @@ -129,7 +129,7 @@ func (s *Setting) validateDatetime(value string) bool { var max time.Time if len(s.minValue) > 0 { - min, err = time.Parse(time.DateTime, s.minValue) + min, err = time.Parse(time.RFC3339, s.minValue) if err != nil { return false } @@ -138,7 +138,7 @@ func (s *Setting) validateDatetime(value string) bool { } } if len(s.maxValue) > 0 { - max, err = time.Parse(time.DateTime, s.maxValue) + max, err = time.Parse(time.RFC3339, s.maxValue) if err != nil { return false } diff --git a/internal/models/user.go b/internal/models/user.go index 85f5b65..318202d 100644 --- a/internal/models/user.go +++ b/internal/models/user.go @@ -188,7 +188,7 @@ func (m *UserModel) Exists(id int64) (bool, error) { func (m *UserModel) GetSettings(userId int64) (UserSettings, error) { stmt := `SELECT u.SettingId, a.ItemValue, u.UnconstrainedValue FROM user_settings AS u - LEFT JOIN allowed_setting_values AS a ON u.SettingId = a.SettingId + LEFT JOIN allowed_setting_values AS a ON u.AllowedSettingValueId = a.Id WHERE UserId = ?` var settings UserSettings rows, err := m.DB.Query(stmt, userId) diff --git a/internal/models/website.go b/internal/models/website.go index 4142697..b753613 100644 --- a/internal/models/website.go +++ b/internal/models/website.go @@ -37,13 +37,13 @@ func (m *WebsiteModel) Insert(shortId uint64, userId int64, siteName, siteUrl, a func (m *WebsiteModel) Get(shortId uint64) (Website, error) { stmt := `SELECT w.Id, w.ShortId, w.Name, w.SiteUrl, w.AuthorName, w.UserId, w.Created, - g.Id, g.ShortId, g.Created, g.IsActive + g.Id, g.ShortId FROM websites AS w INNER JOIN guestbooks AS g ON w.Id = g.WebsiteId WHERE w.ShortId = ? AND w.DELETED IS NULL` row := m.DB.QueryRow(stmt, shortId) var w Website err := row.Scan(&w.ID, &w.ShortId, &w.Name, &w.SiteUrl, &w.AuthorName, &w.UserId, &w.Created, - &w.Guestbook.ID, &w.Guestbook.ShortId, &w.Guestbook.Created, &w.Guestbook.IsActive) + &w.Guestbook.ID, &w.Guestbook.ShortId) if err != nil { return Website{}, err } diff --git a/ui/views/guestbooks.templ b/ui/views/guestbooks.templ index 99f9ea6..5ad5583 100644 --- a/ui/views/guestbooks.templ +++ b/ui/views/guestbooks.templ @@ -3,6 +3,7 @@ package views import "fmt" import "git.32bit.cafe/32bitcafe/guestbook/internal/models" import "git.32bit.cafe/32bitcafe/guestbook/internal/forms" +import "time" templ GuestbookDashboardCommentsView(title string, data CommonData, website models.Website, guestbook models.Guestbook, comments []models.GuestbookComment) { @base(title, data) { @@ -150,8 +151,13 @@ templ CreateGuestbookComment(title string, data CommonData, website models.Websi } } +templ settingRadio(selected bool, name, id, value string) { + +} + templ GuestbookSettingsView(data CommonData, website models.Website) { {{ putUrl := fmt.Sprintf("/websites/%s/dashboard/guestbook/settings", shortIdToSlug(website.ShortId)) }} + {{ gb := website.Guestbook }} @base("Guestbook Settings", data) {
@wSidebar(website) @@ -162,36 +168,39 @@ templ GuestbookSettingsView(data CommonData, website models.Website) {
- + if !website.Guestbook.CanComment() { + {{ localtime := gb.Settings.ReenableCommenting.In(data.CurrentUser.Settings.LocalTimezone) }} + + }
-
diff --git a/ui/views/guestbooks_templ.go b/ui/views/guestbooks_templ.go index 65416be..5a9bf27 100644 --- a/ui/views/guestbooks_templ.go +++ b/ui/views/guestbooks_templ.go @@ -11,6 +11,7 @@ import templruntime "github.com/a-h/templ/runtime" import "fmt" import "git.32bit.cafe/32bitcafe/guestbook/internal/models" import "git.32bit.cafe/32bitcafe/guestbook/internal/forms" +import "time" func GuestbookDashboardCommentsView(title string, data CommonData, website models.Website, guestbook models.Guestbook, comments []models.GuestbookComment) templ.Component { return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { @@ -60,7 +61,7 @@ func GuestbookDashboardCommentsView(title string, data CommonData, website model var templ_7745c5c3_Var3 string templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(website.SiteUrl) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/guestbooks.templ`, Line: 12, Col: 37} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/guestbooks.templ`, Line: 13, Col: 37} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3)) if templ_7745c5c3_Err != nil { @@ -131,7 +132,7 @@ func GuestbookDashboardCommentView(data CommonData, w models.Website, c models.G var templ_7745c5c3_Var5 string templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(commentUrl) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/guestbooks.templ`, Line: 31, Col: 49} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/guestbooks.templ`, Line: 32, Col: 49} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5)) if templ_7745c5c3_Err != nil { @@ -144,7 +145,7 @@ func GuestbookDashboardCommentView(data CommonData, w models.Website, c models.G var templ_7745c5c3_Var6 string templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(hxHeaders) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/guestbooks.templ`, Line: 31, Col: 106} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/guestbooks.templ`, Line: 32, Col: 106} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6)) if templ_7745c5c3_Err != nil { @@ -157,7 +158,7 @@ func GuestbookDashboardCommentView(data CommonData, w models.Website, c models.G var templ_7745c5c3_Var7 string templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(commentUrl) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/guestbooks.templ`, Line: 32, Col: 47} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/guestbooks.templ`, Line: 33, Col: 47} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7)) if templ_7745c5c3_Err != nil { @@ -170,7 +171,7 @@ func GuestbookDashboardCommentView(data CommonData, w models.Website, c models.G var templ_7745c5c3_Var8 string templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(hxHeaders) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/guestbooks.templ`, Line: 32, Col: 104} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/guestbooks.templ`, Line: 33, Col: 104} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8)) if templ_7745c5c3_Err != nil { @@ -203,7 +204,7 @@ func GuestbookDashboardCommentView(data CommonData, w models.Website, c models.G var templ_7745c5c3_Var9 string templ_7745c5c3_Var9, 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: 42, Col: 25} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/guestbooks.templ`, Line: 43, Col: 25} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9)) if templ_7745c5c3_Err != nil { @@ -231,7 +232,7 @@ func GuestbookDashboardCommentView(data CommonData, w models.Website, c models.G var templ_7745c5c3_Var11 string templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(c.AuthorEmail) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/guestbooks.templ`, Line: 45, Col: 66} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/guestbooks.templ`, Line: 46, Col: 66} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11)) if templ_7745c5c3_Err != nil { @@ -259,7 +260,7 @@ func GuestbookDashboardCommentView(data CommonData, w models.Website, c models.G var templ_7745c5c3_Var13 string templ_7745c5c3_Var13, templ_7745c5c3_Err = templ.JoinStringErrs(c.AuthorSite) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/guestbooks.templ`, Line: 48, Col: 85} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/guestbooks.templ`, Line: 49, Col: 85} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var13)) if templ_7745c5c3_Err != nil { @@ -277,7 +278,7 @@ func GuestbookDashboardCommentView(data CommonData, w models.Website, c models.G var templ_7745c5c3_Var14 string templ_7745c5c3_Var14, templ_7745c5c3_Err = templ.JoinStringErrs(c.Created.In(data.CurrentUser.Settings.LocalTimezone).Format("01-02-2006 03:04PM")) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/guestbooks.templ`, Line: 51, Col: 88} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/guestbooks.templ`, Line: 52, Col: 88} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var14)) if templ_7745c5c3_Err != nil { @@ -290,7 +291,7 @@ func GuestbookDashboardCommentView(data CommonData, w models.Website, c models.G var templ_7745c5c3_Var15 string templ_7745c5c3_Var15, 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: 55, Col: 18} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/guestbooks.templ`, Line: 56, Col: 18} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var15)) if templ_7745c5c3_Err != nil { @@ -338,7 +339,7 @@ func commentForm(form forms.CommentCreateForm) templ.Component { var templ_7745c5c3_Var17 string templ_7745c5c3_Var17, templ_7745c5c3_Err = templ.JoinStringErrs(error) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/guestbooks.templ`, Line: 66, Col: 31} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/guestbooks.templ`, Line: 67, Col: 31} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var17)) if templ_7745c5c3_Err != nil { @@ -362,7 +363,7 @@ func commentForm(form forms.CommentCreateForm) templ.Component { var templ_7745c5c3_Var18 string templ_7745c5c3_Var18, templ_7745c5c3_Err = templ.JoinStringErrs(error) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/guestbooks.templ`, Line: 74, Col: 31} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/guestbooks.templ`, Line: 75, Col: 31} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var18)) if templ_7745c5c3_Err != nil { @@ -386,7 +387,7 @@ func commentForm(form forms.CommentCreateForm) templ.Component { var templ_7745c5c3_Var19 string templ_7745c5c3_Var19, templ_7745c5c3_Err = templ.JoinStringErrs(error) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/guestbooks.templ`, Line: 82, Col: 31} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/guestbooks.templ`, Line: 83, Col: 31} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var19)) if templ_7745c5c3_Err != nil { @@ -410,7 +411,7 @@ func commentForm(form forms.CommentCreateForm) templ.Component { var templ_7745c5c3_Var20 string templ_7745c5c3_Var20, templ_7745c5c3_Err = templ.JoinStringErrs(error) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/guestbooks.templ`, Line: 90, Col: 31} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/guestbooks.templ`, Line: 91, Col: 31} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var20)) if templ_7745c5c3_Err != nil { @@ -464,7 +465,7 @@ func GuestbookView(title string, data CommonData, website models.Website, guestb var templ_7745c5c3_Var22 string templ_7745c5c3_Var22, templ_7745c5c3_Err = templ.JoinStringErrs(title) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/guestbooks.templ`, Line: 106, Col: 18} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/guestbooks.templ`, Line: 107, Col: 18} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var22)) if templ_7745c5c3_Err != nil { @@ -477,7 +478,7 @@ func GuestbookView(title string, data CommonData, website models.Website, guestb var templ_7745c5c3_Var23 string templ_7745c5c3_Var23, templ_7745c5c3_Err = templ.JoinStringErrs(website.Name) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/guestbooks.templ`, Line: 112, Col: 38} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/guestbooks.templ`, Line: 113, Col: 38} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var23)) if templ_7745c5c3_Err != nil { @@ -499,7 +500,7 @@ func GuestbookView(title string, data CommonData, website models.Website, guestb var templ_7745c5c3_Var25 string templ_7745c5c3_Var25, templ_7745c5c3_Err = templ.JoinStringErrs(data.CSRFToken) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/guestbooks.templ`, Line: 114, Col: 68} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/guestbooks.templ`, Line: 115, Col: 68} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var25)) if templ_7745c5c3_Err != nil { @@ -531,7 +532,7 @@ func GuestbookView(title string, data CommonData, website models.Website, guestb var templ_7745c5c3_Var26 string templ_7745c5c3_Var26, 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: 124, Col: 26} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/guestbooks.templ`, Line: 125, Col: 26} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var26)) if templ_7745c5c3_Err != nil { @@ -544,7 +545,7 @@ func GuestbookView(title string, data CommonData, website models.Website, guestb var templ_7745c5c3_Var27 string templ_7745c5c3_Var27, 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: 125, Col: 48} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/guestbooks.templ`, Line: 126, Col: 48} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var27)) if templ_7745c5c3_Err != nil { @@ -557,7 +558,7 @@ func GuestbookView(title string, data CommonData, website models.Website, guestb var templ_7745c5c3_Var28 string templ_7745c5c3_Var28, 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: 127, Col: 24} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/guestbooks.templ`, Line: 128, Col: 24} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var28)) if templ_7745c5c3_Err != nil { @@ -607,7 +608,7 @@ func CreateGuestbookComment(title string, data CommonData, website models.Websit var templ_7745c5c3_Var30 string templ_7745c5c3_Var30, templ_7745c5c3_Err = templ.JoinStringErrs(postUrl) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/guestbooks.templ`, Line: 141, Col: 25} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/guestbooks.templ`, Line: 142, Col: 25} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var30)) if templ_7745c5c3_Err != nil { @@ -670,7 +671,7 @@ func CreateGuestbookComment(title string, data CommonData, website models.Websit }) } -func GuestbookSettingsView(data CommonData, website models.Website) templ.Component { +func settingRadio(selected bool, name, id, value 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 { @@ -691,8 +692,87 @@ func GuestbookSettingsView(data CommonData, website models.Website) templ.Compon templ_7745c5c3_Var33 = templ.NopComponent } ctx = templ.ClearChildren(ctx) + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 57, "") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + return nil + }) +} + +func GuestbookSettingsView(data CommonData, website models.Website) templ.Component { + return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { + templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context + if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { + return templ_7745c5c3_CtxErr + } + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) + if !templ_7745c5c3_IsBuffer { + defer func() { + templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) + if templ_7745c5c3_Err == nil { + templ_7745c5c3_Err = templ_7745c5c3_BufErr + } + }() + } + ctx = templ.InitializeContext(ctx) + templ_7745c5c3_Var37 := templ.GetChildren(ctx) + if templ_7745c5c3_Var37 == nil { + templ_7745c5c3_Var37 = templ.NopComponent + } + ctx = templ.ClearChildren(ctx) putUrl := fmt.Sprintf("/websites/%s/dashboard/guestbook/settings", shortIdToSlug(website.ShortId)) - templ_7745c5c3_Var34 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { + gb := website.Guestbook + templ_7745c5c3_Var38 := 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 { @@ -704,7 +784,7 @@ func GuestbookSettingsView(data CommonData, website models.Website) templ.Compon }() } ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 57, "
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 63, "
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -712,39 +792,149 @@ func GuestbookSettingsView(data CommonData, website models.Website) templ.Compon if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 58, "

Guestbook Settings

Guestbook Settings

") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 66, "\">
") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + if !website.Guestbook.CanComment() { + localtime := gb.Settings.ReenableCommenting.In(data.CurrentUser.Settings.LocalTimezone) + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 75, "") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + } + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 79, "
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } return nil }) - templ_7745c5c3_Err = base("Guestbook Settings", data).Render(templ.WithChildren(ctx, templ_7745c5c3_Var34), templ_7745c5c3_Buffer) + templ_7745c5c3_Err = base("Guestbook Settings", data).Render(templ.WithChildren(ctx, templ_7745c5c3_Var38), templ_7745c5c3_Buffer) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -768,12 +958,12 @@ func AllGuestbooksView(data CommonData, websites []models.Website) templ.Compone }() } ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var37 := templ.GetChildren(ctx) - if templ_7745c5c3_Var37 == nil { - templ_7745c5c3_Var37 = templ.NopComponent + templ_7745c5c3_Var44 := templ.GetChildren(ctx) + if templ_7745c5c3_Var44 == nil { + templ_7745c5c3_Var44 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Var38 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { + templ_7745c5c3_Var45 := 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 { @@ -785,50 +975,50 @@ func AllGuestbooksView(data CommonData, websites []models.Website) templ.Compone }() } ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 61, "

All Guestbooks

This page exists only for testing the service.

") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } return nil }) - templ_7745c5c3_Err = base("All Guestbooks", data).Render(templ.WithChildren(ctx, templ_7745c5c3_Var38), templ_7745c5c3_Buffer) + templ_7745c5c3_Err = base("All Guestbooks", data).Render(templ.WithChildren(ctx, templ_7745c5c3_Var45), templ_7745c5c3_Buffer) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err }