merge guestbookmodel with websitemodel and fix minor ui bugs
This commit is contained in:
		
							parent
							
								
									a08a6b3f41
								
							
						
					
					
						commit
						d009bd98ac
					
				@ -24,15 +24,6 @@ func (app *application) getGuestbook(w http.ResponseWriter, r *http.Request) {
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
		return
 | 
							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 {
 | 
						if !website.Guestbook.Settings.IsVisible {
 | 
				
			||||||
		u := app.getCurrentUser(r)
 | 
							u := app.getCurrentUser(r)
 | 
				
			||||||
		if u == nil {
 | 
							if u == nil {
 | 
				
			||||||
@ -63,14 +54,6 @@ func (app *application) getGuestbookSettings(w http.ResponseWriter, r *http.Requ
 | 
				
			|||||||
			app.serverError(w, r, err)
 | 
								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)
 | 
						data := app.newCommonData(r)
 | 
				
			||||||
	views.GuestbookSettingsView(data, website).Render(r.Context(), w)
 | 
						views.GuestbookSettingsView(data, website).Render(r.Context(), w)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -121,7 +104,7 @@ func (app *application) putGuestbookSettings(w http.ResponseWriter, r *http.Requ
 | 
				
			|||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		app.serverError(w, r, err)
 | 
							app.serverError(w, r, err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	err = app.guestbooks.UpdateGuestbookSettings(website.Guestbook.ID, website.Guestbook.Settings)
 | 
						err = app.websites.UpdateGuestbookSettings(website.Guestbook.ID, website.Guestbook.Settings)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		app.serverError(w, r, err)
 | 
							app.serverError(w, r, err)
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
@ -144,14 +127,6 @@ func (app *application) getGuestbookComments(w http.ResponseWriter, r *http.Requ
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
		return
 | 
							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)
 | 
						comments, err := app.guestbookComments.GetAll(website.Guestbook.ID)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		app.serverError(w, r, err)
 | 
							app.serverError(w, r, err)
 | 
				
			||||||
@ -173,15 +148,6 @@ func (app *application) getGuestbookCommentCreate(w http.ResponseWriter, r *http
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
		return
 | 
							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)
 | 
						data := app.newCommonData(r)
 | 
				
			||||||
	form := forms.CommentCreateForm{}
 | 
						form := forms.CommentCreateForm{}
 | 
				
			||||||
	views.CreateGuestbookComment("New Comment", data, website, website.Guestbook, form).Render(r.Context(), w)
 | 
						views.CreateGuestbookComment("New Comment", data, website, website.Guestbook, form).Render(r.Context(), w)
 | 
				
			||||||
@ -198,14 +164,6 @@ func (app *application) postGuestbookCommentCreate(w http.ResponseWriter, r *htt
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
		return
 | 
							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() {
 | 
						if !website.Guestbook.CanComment() {
 | 
				
			||||||
		app.clientError(w, http.StatusForbidden)
 | 
							app.clientError(w, http.StatusForbidden)
 | 
				
			||||||
@ -228,6 +186,7 @@ func (app *application) postGuestbookCommentCreate(w http.ResponseWriter, r *htt
 | 
				
			|||||||
	form.CheckField(validator.NotBlank(form.Content), "content", "This field cannot be blank")
 | 
						form.CheckField(validator.NotBlank(form.Content), "content", "This field cannot be blank")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if !form.Valid() {
 | 
						if !form.Valid() {
 | 
				
			||||||
 | 
							// TODO: use htmx to avoid getting comments again
 | 
				
			||||||
		comments, err := app.guestbookComments.GetAll(website.Guestbook.ID)
 | 
							comments, err := app.guestbookComments.GetAll(website.Guestbook.ID)
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			app.serverError(w, r, err)
 | 
								app.serverError(w, r, err)
 | 
				
			||||||
@ -259,14 +218,6 @@ func (app *application) getCommentQueue(w http.ResponseWriter, r *http.Request)
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
		return
 | 
							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)
 | 
						comments, err := app.guestbookComments.GetUnpublished(website.Guestbook.ID)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
@ -293,14 +244,6 @@ func (app *application) getCommentTrash(w http.ResponseWriter, r *http.Request)
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
		return
 | 
							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)
 | 
						comments, err := app.guestbookComments.GetDeleted(website.Guestbook.ID)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
@ -332,14 +275,6 @@ func (app *application) putHideGuestbookComment(w http.ResponseWriter, r *http.R
 | 
				
			|||||||
	if user.ID != website.UserId {
 | 
						if user.ID != website.UserId {
 | 
				
			||||||
		app.clientError(w, http.StatusUnauthorized)
 | 
							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")
 | 
						cSlug := r.PathValue("commentId")
 | 
				
			||||||
	comment, err := app.guestbookComments.Get(slugToShortId(cSlug))
 | 
						comment, err := app.guestbookComments.Get(slugToShortId(cSlug))
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
@ -374,14 +309,6 @@ func (app *application) deleteGuestbookComment(w http.ResponseWriter, r *http.Re
 | 
				
			|||||||
	if user.ID != website.UserId {
 | 
						if user.ID != website.UserId {
 | 
				
			||||||
		app.clientError(w, http.StatusUnauthorized)
 | 
							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")
 | 
						cSlug := r.PathValue("commentId")
 | 
				
			||||||
	comment, err := app.guestbookComments.Get(slugToShortId(cSlug))
 | 
						comment, err := app.guestbookComments.Get(slugToShortId(cSlug))
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
 | 
				
			|||||||
@ -39,28 +39,13 @@ func (app *application) postWebsiteCreate(w http.ResponseWriter, r *http.Request
 | 
				
			|||||||
		views.WebsiteCreate("Add a Website", data, form).Render(r.Context(), w)
 | 
							views.WebsiteCreate("Add a Website", data, form).Render(r.Context(), w)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	websiteShortID := app.createShortId()
 | 
						websiteShortID := app.createShortId()
 | 
				
			||||||
	websiteId, err := app.websites.Insert(websiteShortID, userId, form.Name, form.SiteUrl, form.AuthorName)
 | 
						_, err = app.websites.Insert(websiteShortID, userId, form.Name, form.SiteUrl, form.AuthorName)
 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		app.serverError(w, r, err)
 | 
					 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	// TODO: how to handle website creation success but guestbook creation failure?
 | 
					 | 
				
			||||||
	guestbookShortID := app.createShortId()
 | 
					 | 
				
			||||||
	guestbookSettings := models.GuestbookSettings{
 | 
					 | 
				
			||||||
		IsCommentingEnabled: true,
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	_, err = app.guestbooks.Insert(guestbookShortID, userId, websiteId, guestbookSettings)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		app.serverError(w, r, err)
 | 
							app.serverError(w, r, err)
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	app.sessionManager.Put(r.Context(), "flash", "Website successfully registered!")
 | 
						app.sessionManager.Put(r.Context(), "flash", "Website successfully registered!")
 | 
				
			||||||
	if r.Header.Get("HX-Request") == "true" {
 | 
						http.Redirect(w, r, fmt.Sprintf("/websites/%s/dashboard", shortIdToSlug(websiteShortID)), http.StatusSeeOther)
 | 
				
			||||||
		w.Header().Add("HX-Trigger", "newWebsite")
 | 
					 | 
				
			||||||
		views.WebsiteCreateButton().Render(r.Context(), w)
 | 
					 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	http.Redirect(w, r, fmt.Sprintf("/websites/%s", shortIdToSlug(websiteShortID)), http.StatusSeeOther)
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (app *application) getWebsiteDashboard(w http.ResponseWriter, r *http.Request) {
 | 
					func (app *application) getWebsiteDashboard(w http.ResponseWriter, r *http.Request) {
 | 
				
			||||||
@ -91,7 +76,8 @@ func (app *application) getWebsiteList(w http.ResponseWriter, r *http.Request) {
 | 
				
			|||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if r.Header.Get("HX-Request") == "true" {
 | 
						if r.Header.Get("HX-Request") == "true" {
 | 
				
			||||||
		w.Header().Add("HX-Trigger", "newWebsite")
 | 
							views.HxWebsiteList(websites)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	data := app.newCommonData(r)
 | 
						data := app.newCommonData(r)
 | 
				
			||||||
	views.WebsiteList("My Websites", data, websites).Render(r.Context(), w)
 | 
						views.WebsiteList("My Websites", data, websites).Render(r.Context(), w)
 | 
				
			||||||
 | 
				
			|||||||
@ -23,8 +23,7 @@ func (app *application) serverError(w http.ResponseWriter, r *http.Request, err
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	app.logger.Error(err.Error(), "method", method, "uri", uri)
 | 
						app.logger.Error(err.Error(), "method", method, "uri", uri)
 | 
				
			||||||
	if app.debug {
 | 
						if app.debug {
 | 
				
			||||||
		http.Error(w, string(debug.Stack()), http.StatusInternalServerError)
 | 
							http.Error(w, err.Error()+"\n"+string(debug.Stack()), http.StatusInternalServerError)
 | 
				
			||||||
		app.logger.Error(err.Error(), "method", method, "uri", uri, "stack", string(debug.Stack()))
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
 | 
						http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -22,7 +22,6 @@ type application struct {
 | 
				
			|||||||
	sequence          uint16
 | 
						sequence          uint16
 | 
				
			||||||
	logger            *slog.Logger
 | 
						logger            *slog.Logger
 | 
				
			||||||
	websites          *models.WebsiteModel
 | 
						websites          *models.WebsiteModel
 | 
				
			||||||
	guestbooks        *models.GuestbookModel
 | 
					 | 
				
			||||||
	users             *models.UserModel
 | 
						users             *models.UserModel
 | 
				
			||||||
	guestbookComments *models.GuestbookCommentModel
 | 
						guestbookComments *models.GuestbookCommentModel
 | 
				
			||||||
	sessionManager    *scs.SessionManager
 | 
						sessionManager    *scs.SessionManager
 | 
				
			||||||
@ -58,7 +57,6 @@ func main() {
 | 
				
			|||||||
		logger:            logger,
 | 
							logger:            logger,
 | 
				
			||||||
		sessionManager:    sessionManager,
 | 
							sessionManager:    sessionManager,
 | 
				
			||||||
		websites:          &models.WebsiteModel{DB: db},
 | 
							websites:          &models.WebsiteModel{DB: db},
 | 
				
			||||||
		guestbooks:        &models.GuestbookModel{DB: db},
 | 
					 | 
				
			||||||
		users:             &models.UserModel{DB: db, Settings: make(map[string]models.Setting)},
 | 
							users:             &models.UserModel{DB: db, Settings: make(map[string]models.Setting)},
 | 
				
			||||||
		guestbookComments: &models.GuestbookCommentModel{DB: db},
 | 
							guestbookComments: &models.GuestbookCommentModel{DB: db},
 | 
				
			||||||
		formDecoder:       formDecoder,
 | 
							formDecoder:       formDecoder,
 | 
				
			||||||
@ -71,7 +69,7 @@ func main() {
 | 
				
			|||||||
		logger.Error(err.Error())
 | 
							logger.Error(err.Error())
 | 
				
			||||||
		os.Exit(1)
 | 
							os.Exit(1)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	err = app.guestbooks.InitializeSettingsMap()
 | 
						err = app.websites.InitializeSettingsMap()
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		logger.Error(err.Error())
 | 
							logger.Error(err.Error())
 | 
				
			||||||
		os.Exit(1)
 | 
							os.Exit(1)
 | 
				
			||||||
 | 
				
			|||||||
@ -1,284 +0,0 @@
 | 
				
			|||||||
package models
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"database/sql"
 | 
					 | 
				
			||||||
	"errors"
 | 
					 | 
				
			||||||
	"strconv"
 | 
					 | 
				
			||||||
	"time"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type GuestbookSettings struct {
 | 
					 | 
				
			||||||
	IsCommentingEnabled   bool
 | 
					 | 
				
			||||||
	ReenableCommenting    time.Time
 | 
					 | 
				
			||||||
	IsVisible             bool
 | 
					 | 
				
			||||||
	FilteredWords         []string
 | 
					 | 
				
			||||||
	AllowRemoteHostAccess bool
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var ValidDisableDurations = []string{"true", "false", "1h", "4h", "8h", "24h", "72h", "168h"}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const (
 | 
					 | 
				
			||||||
	SettingGbCommentingEnabled = "commenting_enabled"
 | 
					 | 
				
			||||||
	SettingGbReenableComments  = "reenable_comments"
 | 
					 | 
				
			||||||
	SettingGbVisible           = "is_visible"
 | 
					 | 
				
			||||||
	SettingGbFilteredWords     = "filtered_words"
 | 
					 | 
				
			||||||
	SettingGbAllowRemote       = "remote_enabled"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type Guestbook struct {
 | 
					 | 
				
			||||||
	ID        int64
 | 
					 | 
				
			||||||
	ShortId   uint64
 | 
					 | 
				
			||||||
	UserId    int64
 | 
					 | 
				
			||||||
	WebsiteId int64
 | 
					 | 
				
			||||||
	Created   time.Time
 | 
					 | 
				
			||||||
	Deleted   time.Time
 | 
					 | 
				
			||||||
	IsActive  bool
 | 
					 | 
				
			||||||
	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
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (m *GuestbookModel) InitializeSettingsMap() error {
 | 
					 | 
				
			||||||
	if m.Settings == nil {
 | 
					 | 
				
			||||||
		m.Settings = make(map[string]Setting)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	stmt := `SELECT settings.Id, settings.Description, Constrained, d.Id, d.Description, g.Id, g.Description, MinValue, MaxValue
 | 
					 | 
				
			||||||
        FROM settings
 | 
					 | 
				
			||||||
        LEFT JOIN setting_data_types d ON settings.DataType = d.Id
 | 
					 | 
				
			||||||
        LEFT JOIN setting_groups g ON settings.SettingGroup = g.Id
 | 
					 | 
				
			||||||
        WHERE SettingGroup = (SELECT Id FROM setting_groups WHERE Description = 'guestbook' LIMIT 1)`
 | 
					 | 
				
			||||||
	result, err := m.DB.Query(stmt)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	for result.Next() {
 | 
					 | 
				
			||||||
		var s Setting
 | 
					 | 
				
			||||||
		var mn sql.NullString
 | 
					 | 
				
			||||||
		var mx sql.NullString
 | 
					 | 
				
			||||||
		err := result.Scan(&s.id, &s.description, &s.constrained, &s.dataType.id, &s.dataType.description, &s.settingGroup.id, &s.settingGroup.description, &mn, &mx)
 | 
					 | 
				
			||||||
		if mn.Valid {
 | 
					 | 
				
			||||||
			s.minValue = mn.String
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if mx.Valid {
 | 
					 | 
				
			||||||
			s.maxValue = mx.String
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			return err
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		m.Settings[s.description] = s
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (m *GuestbookModel) Insert(shortId uint64, userId int64, websiteId int64, settings GuestbookSettings) (int64, error) {
 | 
					 | 
				
			||||||
	stmt := `INSERT INTO guestbooks (ShortId, UserId, WebsiteId, Created, IsActive)
 | 
					 | 
				
			||||||
    VALUES(?, ?, ?, ?, TRUE)`
 | 
					 | 
				
			||||||
	result, err := m.DB.Exec(stmt, shortId, userId, websiteId, time.Now().UTC())
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return -1, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	id, err := result.LastInsertId()
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return -1, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	err = m.initializeGuestbookSettings(id, settings)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return id, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return id, nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (m *GuestbookModel) Get(shortId uint64) (Guestbook, error) {
 | 
					 | 
				
			||||||
	stmt := `SELECT Id, ShortId, UserId, WebsiteId, Created, Deleted, IsActive FROM guestbooks
 | 
					 | 
				
			||||||
    WHERE ShortId = ?`
 | 
					 | 
				
			||||||
	row := m.DB.QueryRow(stmt, shortId)
 | 
					 | 
				
			||||||
	var g Guestbook
 | 
					 | 
				
			||||||
	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
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (m *GuestbookModel) GetAll(userId int64) ([]Guestbook, error) {
 | 
					 | 
				
			||||||
	stmt := `SELECT Id, ShortId, UserId, WebsiteId, Created, IsActive FROM guestbooks
 | 
					 | 
				
			||||||
    WHERE UserId = ? AND DELETED IS NULL`
 | 
					 | 
				
			||||||
	rows, err := m.DB.Query(stmt, userId)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	var guestbooks []Guestbook
 | 
					 | 
				
			||||||
	for rows.Next() {
 | 
					 | 
				
			||||||
		var g Guestbook
 | 
					 | 
				
			||||||
		err = rows.Scan(&g.ID, &g.ShortId, &g.UserId, &g.WebsiteId, &g.Created, &g.IsActive)
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			return nil, err
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		guestbooks = append(guestbooks, g)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if err = rows.Err(); err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	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 
 | 
					 | 
				
			||||||
	(?, ?, ?, ?),
 | 
					 | 
				
			||||||
	(?, ?, ?, ?),
 | 
					 | 
				
			||||||
	(?, ?, ?, ?),
 | 
					 | 
				
			||||||
	(?, ?, ?, ?),
 | 
					 | 
				
			||||||
	(?, ?, ?, ?)`
 | 
					 | 
				
			||||||
	_, err := m.DB.Exec(stmt,
 | 
					 | 
				
			||||||
		guestbookId, m.Settings[SettingGbCommentingEnabled].id, settings.IsCommentingEnabled, nil,
 | 
					 | 
				
			||||||
		guestbookId, m.Settings[SettingGbReenableComments].id, nil, settings.ReenableCommenting.String(),
 | 
					 | 
				
			||||||
		guestbookId, m.Settings[SettingGbVisible].id, settings.IsVisible, nil,
 | 
					 | 
				
			||||||
		guestbookId, m.Settings[SettingGbAllowRemote].id, settings.AllowRemoteHostAccess, nil)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (m *GuestbookModel) UpdateGuestbookSettings(guestbookId int64, settings GuestbookSettings) error {
 | 
					 | 
				
			||||||
	err := m.UpdateSetting(guestbookId, m.Settings[SettingGbVisible], strconv.FormatBool(settings.IsVisible))
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	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
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (m *GuestbookModel) UpdateSetting(guestbookId int64, setting Setting, value string) error {
 | 
					 | 
				
			||||||
	stmt := `UPDATE guestbook_settings SET
 | 
					 | 
				
			||||||
				AllowedSettingValueId=IFNULL(
 | 
					 | 
				
			||||||
					(SELECT Id FROM allowed_setting_values WHERE SettingId = guestbook_settings.SettingId AND ItemValue = ?), AllowedSettingValueId
 | 
					 | 
				
			||||||
				), 
 | 
					 | 
				
			||||||
				UnconstrainedValue=(SELECT ? FROM settings WHERE settings.Id = guestbook_settings.SettingId AND settings.Constrained=0)
 | 
					 | 
				
			||||||
			WHERE GuestbookId = ?
 | 
					 | 
				
			||||||
			AND SettingId = (SELECT Id from Settings WHERE Description=?);`
 | 
					 | 
				
			||||||
	result, err := m.DB.Exec(stmt, value, value, guestbookId, setting.description)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	rows, err := result.RowsAffected()
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if rows != 1 {
 | 
					 | 
				
			||||||
		return ErrInvalidSettingValue
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (m *GuestbookModel) AddFilteredWord(guestbookId int64, word string) error {
 | 
					 | 
				
			||||||
	return nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (m *GuestbookModel) RemoveFilteredWord(guestbookId int64, word string) error {
 | 
					 | 
				
			||||||
	return nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@ -2,6 +2,8 @@ package models
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"database/sql"
 | 
						"database/sql"
 | 
				
			||||||
 | 
						"errors"
 | 
				
			||||||
 | 
						"strconv"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -17,51 +19,206 @@ type Website struct {
 | 
				
			|||||||
	Guestbook  Guestbook
 | 
						Guestbook  Guestbook
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type GuestbookSettings struct {
 | 
				
			||||||
 | 
						IsCommentingEnabled   bool
 | 
				
			||||||
 | 
						ReenableCommenting    time.Time
 | 
				
			||||||
 | 
						IsVisible             bool
 | 
				
			||||||
 | 
						FilteredWords         []string
 | 
				
			||||||
 | 
						AllowRemoteHostAccess bool
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var ValidDisableDurations = []string{"true", "false", "1h", "4h", "8h", "24h", "72h", "168h"}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						SettingGbCommentingEnabled = "commenting_enabled"
 | 
				
			||||||
 | 
						SettingGbReenableComments  = "reenable_comments"
 | 
				
			||||||
 | 
						SettingGbVisible           = "is_visible"
 | 
				
			||||||
 | 
						SettingGbFilteredWords     = "filtered_words"
 | 
				
			||||||
 | 
						SettingGbAllowRemote       = "remote_enabled"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Guestbook struct {
 | 
				
			||||||
 | 
						ID        int64
 | 
				
			||||||
 | 
						ShortId   uint64
 | 
				
			||||||
 | 
						UserId    int64
 | 
				
			||||||
 | 
						WebsiteId int64
 | 
				
			||||||
 | 
						Created   time.Time
 | 
				
			||||||
 | 
						Deleted   time.Time
 | 
				
			||||||
 | 
						IsActive  bool
 | 
				
			||||||
 | 
						Settings  GuestbookSettings
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (g Guestbook) CanComment() bool {
 | 
				
			||||||
 | 
						now := time.Now().UTC()
 | 
				
			||||||
 | 
						return g.Settings.IsCommentingEnabled && g.Settings.ReenableCommenting.Before(now)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type WebsiteModel struct {
 | 
					type WebsiteModel struct {
 | 
				
			||||||
	DB *sql.DB
 | 
						DB       *sql.DB
 | 
				
			||||||
 | 
						Settings map[string]Setting
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (m *WebsiteModel) InitializeSettingsMap() error {
 | 
				
			||||||
 | 
						if m.Settings == nil {
 | 
				
			||||||
 | 
							m.Settings = make(map[string]Setting)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						stmt := `SELECT settings.Id, settings.Description, Constrained, d.Id, d.Description, g.Id, g.Description, MinValue, MaxValue
 | 
				
			||||||
 | 
					        FROM settings
 | 
				
			||||||
 | 
					        LEFT JOIN setting_data_types d ON settings.DataType = d.Id
 | 
				
			||||||
 | 
					        LEFT JOIN setting_groups g ON settings.SettingGroup = g.Id
 | 
				
			||||||
 | 
					        WHERE SettingGroup = (SELECT Id FROM setting_groups WHERE Description = 'guestbook' LIMIT 1)`
 | 
				
			||||||
 | 
						result, err := m.DB.Query(stmt)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						for result.Next() {
 | 
				
			||||||
 | 
							var s Setting
 | 
				
			||||||
 | 
							var mn sql.NullString
 | 
				
			||||||
 | 
							var mx sql.NullString
 | 
				
			||||||
 | 
							err := result.Scan(&s.id, &s.description, &s.constrained, &s.dataType.id, &s.dataType.description, &s.settingGroup.id, &s.settingGroup.description, &mn, &mx)
 | 
				
			||||||
 | 
							if mn.Valid {
 | 
				
			||||||
 | 
								s.minValue = mn.String
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if mx.Valid {
 | 
				
			||||||
 | 
								s.maxValue = mx.String
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							m.Settings[s.description] = s
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (m *WebsiteModel) Insert(shortId uint64, userId int64, siteName, siteUrl, authorName string) (int64, error) {
 | 
					func (m *WebsiteModel) Insert(shortId uint64, userId int64, siteName, siteUrl, authorName string) (int64, error) {
 | 
				
			||||||
	stmt := `INSERT INTO websites (ShortId, Name, SiteUrl, AuthorName, UserId, Created)
 | 
						stmt := `INSERT INTO websites (ShortId, Name, SiteUrl, AuthorName, UserId, Created)
 | 
				
			||||||
			VALUES (?, ?, ?, ?, ?, ?)`
 | 
								VALUES (?, ?, ?, ?, ?, ?)`
 | 
				
			||||||
	result, err := m.DB.Exec(stmt, shortId, siteName, siteUrl, authorName, userId, time.Now().UTC())
 | 
						tx, err := m.DB.Begin()
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return -1, err
 | 
							return -1, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	id, err := result.LastInsertId()
 | 
					
 | 
				
			||||||
 | 
						result, err := tx.Exec(stmt, shortId, siteName, siteUrl, authorName, userId, time.Now().UTC())
 | 
				
			||||||
 | 
						// result, err := m.DB.Exec(stmt, shortId, siteName, siteUrl, authorName, userId, time.Now().UTC())
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
 | 
							if rollbackError := tx.Rollback(); rollbackError != nil {
 | 
				
			||||||
 | 
								return -1, err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		return -1, err
 | 
							return -1, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return id, nil
 | 
						websiteId, err := result.LastInsertId()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							if rollbackError := tx.Rollback(); rollbackError != nil {
 | 
				
			||||||
 | 
								return -1, err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return -1, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						stmt = `INSERT INTO guestbooks (ShortId, UserId, WebsiteId, Created, IsActive)
 | 
				
			||||||
 | 
					    VALUES(?, ?, ?, ?, TRUE)`
 | 
				
			||||||
 | 
						result, err = tx.Exec(stmt, shortId, userId, websiteId, time.Now().UTC())
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							if rollbackError := tx.Rollback(); rollbackError != nil {
 | 
				
			||||||
 | 
								return -1, err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return -1, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						guestbookId, err := result.LastInsertId()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							if rollbackError := tx.Rollback(); rollbackError != nil {
 | 
				
			||||||
 | 
								return -1, err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return -1, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						settings := GuestbookSettings{
 | 
				
			||||||
 | 
							IsCommentingEnabled:   true,
 | 
				
			||||||
 | 
							IsVisible:             true,
 | 
				
			||||||
 | 
							AllowRemoteHostAccess: true,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						stmt = `INSERT INTO guestbook_settings (GuestbookId, SettingId, AllowedSettingValueId, UnconstrainedValue) VALUES 
 | 
				
			||||||
 | 
						(?, ?, ?, ?),
 | 
				
			||||||
 | 
						(?, ?, ?, ?),
 | 
				
			||||||
 | 
						(?, ?, ?, ?),
 | 
				
			||||||
 | 
						(?, ?, ?, ?)`
 | 
				
			||||||
 | 
						_, err = tx.Exec(stmt,
 | 
				
			||||||
 | 
							guestbookId, m.Settings[SettingGbCommentingEnabled].id, settings.IsCommentingEnabled, nil,
 | 
				
			||||||
 | 
							guestbookId, m.Settings[SettingGbReenableComments].id, nil, settings.ReenableCommenting.Format(time.RFC3339),
 | 
				
			||||||
 | 
							guestbookId, m.Settings[SettingGbVisible].id, settings.IsVisible, nil,
 | 
				
			||||||
 | 
							guestbookId, m.Settings[SettingGbAllowRemote].id, settings.AllowRemoteHostAccess, nil)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							if rollbackError := tx.Rollback(); rollbackError != nil {
 | 
				
			||||||
 | 
								return -1, err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return -1, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if err := tx.Commit(); err != nil {
 | 
				
			||||||
 | 
							return -1, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return websiteId, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (m *WebsiteModel) Get(shortId uint64) (Website, error) {
 | 
					func (m *WebsiteModel) Get(shortId uint64) (Website, error) {
 | 
				
			||||||
	stmt := `SELECT w.Id, w.ShortId, w.Name, w.SiteUrl, w.AuthorName, w.UserId, w.Created,
 | 
						stmt := `SELECT w.Id, w.ShortId, w.Name, w.SiteUrl, w.AuthorName, w.UserId, w.Created
 | 
				
			||||||
	g.Id, g.ShortId
 | 
						FROM websites AS w
 | 
				
			||||||
	FROM websites AS w INNER JOIN guestbooks AS g ON w.Id = g.WebsiteId
 | 
					 | 
				
			||||||
	WHERE w.ShortId = ? AND w.DELETED IS NULL`
 | 
						WHERE w.ShortId = ? AND w.DELETED IS NULL`
 | 
				
			||||||
	row := m.DB.QueryRow(stmt, shortId)
 | 
						tx, err := m.DB.Begin()
 | 
				
			||||||
	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)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return Website{}, nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						row := tx.QueryRow(stmt, shortId)
 | 
				
			||||||
 | 
						var w Website
 | 
				
			||||||
 | 
						err = row.Scan(&w.ID, &w.ShortId, &w.Name, &w.SiteUrl, &w.AuthorName, &w.UserId, &w.Created)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							if errors.Is(err, sql.ErrNoRows) {
 | 
				
			||||||
 | 
								err = ErrNoRecord
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if rollbackErr := tx.Rollback(); rollbackErr != nil {
 | 
				
			||||||
 | 
								return Website{}, err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		return Website{}, err
 | 
							return Website{}, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return w, nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (m *WebsiteModel) GetById(id int64) (Website, error) {
 | 
						stmt = `SELECT Id, ShortId, UserId, WebsiteId, Created, IsActive FROM guestbooks
 | 
				
			||||||
	stmt := `SELECT w.Id, w.ShortId, w.Name, w.SiteUrl, w.AuthorName, w.UserId, w.Created,
 | 
					    WHERE WebsiteId = ? AND Deleted IS NULL`
 | 
				
			||||||
	g.Id, g.ShortId, g.Created, g.IsActive
 | 
						row = tx.QueryRow(stmt, w.ID)
 | 
				
			||||||
	FROM websites AS w INNER JOIN guestbooks AS g ON w.Id = g.WebsiteId
 | 
						var g Guestbook
 | 
				
			||||||
	WHERE w.Id = ? AND w.DELETED IS NULL`
 | 
						err = row.Scan(&g.ID, &g.ShortId, &g.UserId, &g.WebsiteId, &g.Created, &g.IsActive)
 | 
				
			||||||
	row := m.DB.QueryRow(stmt, id)
 | 
					 | 
				
			||||||
	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)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
 | 
							if errors.Is(err, sql.ErrNoRows) {
 | 
				
			||||||
 | 
								err = ErrNoRecord
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if rollbackErr := tx.Rollback(); rollbackErr != nil {
 | 
				
			||||||
 | 
								return Website{}, err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		return Website{}, err
 | 
							return Website{}, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						gbSettings, err := m.getGuestbookSettings(tx, g.ID)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							if errors.Is(err, sql.ErrNoRows) {
 | 
				
			||||||
 | 
								err = ErrNoRecord
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if rollbackErr := tx.Rollback(); rollbackErr != nil {
 | 
				
			||||||
 | 
								return Website{}, err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return Website{}, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						err = tx.Commit()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return Website{}, nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// if comment disable setting has expired, enable commenting
 | 
				
			||||||
 | 
						commentingReenabled := time.Now().UTC().After(gbSettings.ReenableCommenting)
 | 
				
			||||||
 | 
						if commentingReenabled {
 | 
				
			||||||
 | 
							gbSettings.IsCommentingEnabled = true
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						g.Settings = gbSettings
 | 
				
			||||||
 | 
						w.Guestbook = g
 | 
				
			||||||
	return w, nil
 | 
						return w, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -113,3 +270,92 @@ func (m *WebsiteModel) GetAll() ([]Website, error) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	return websites, nil
 | 
						return websites, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (m *WebsiteModel) getGuestbookSettings(tx *sql.Tx, 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 := tx.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
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return settings, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (m *WebsiteModel) UpdateGuestbookSettings(guestbookId int64, settings GuestbookSettings) error {
 | 
				
			||||||
 | 
						err := m.UpdateSetting(guestbookId, m.Settings[SettingGbVisible], strconv.FormatBool(settings.IsVisible))
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						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 *WebsiteModel) UpdateSetting(guestbookId int64, setting Setting, value string) error {
 | 
				
			||||||
 | 
						stmt := `UPDATE guestbook_settings SET
 | 
				
			||||||
 | 
									AllowedSettingValueId=IFNULL(
 | 
				
			||||||
 | 
										(SELECT Id FROM allowed_setting_values WHERE SettingId = guestbook_settings.SettingId AND ItemValue = ?), AllowedSettingValueId
 | 
				
			||||||
 | 
									), 
 | 
				
			||||||
 | 
									UnconstrainedValue=(SELECT ? FROM settings WHERE settings.Id = guestbook_settings.SettingId AND settings.Constrained=0)
 | 
				
			||||||
 | 
								WHERE GuestbookId = ?
 | 
				
			||||||
 | 
								AND SettingId = (SELECT Id from Settings WHERE Description=?);`
 | 
				
			||||||
 | 
						result, err := m.DB.Exec(stmt, value, value, guestbookId, setting.description)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						rows, err := result.RowsAffected()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if rows != 1 {
 | 
				
			||||||
 | 
							return ErrInvalidSettingValue
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -98,18 +98,14 @@ templ WebsiteCreateButton() {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
templ WebsiteList(title string, data CommonData, websites []models.Website) {
 | 
					templ WebsiteList(title string, data CommonData, websites []models.Website) {
 | 
				
			||||||
	if data.IsHtmx {
 | 
						@base(title, data) {
 | 
				
			||||||
		@displayWebsites(websites)
 | 
							<h1>My Websites</h1>
 | 
				
			||||||
	} else {
 | 
							<div>
 | 
				
			||||||
		@base(title, data) {
 | 
								@WebsiteCreateButton()
 | 
				
			||||||
			<h1>My Websites</h1>
 | 
							</div>
 | 
				
			||||||
			<p>
 | 
							<div>
 | 
				
			||||||
				@WebsiteCreateButton()
 | 
								@displayWebsites(websites)
 | 
				
			||||||
			</p>
 | 
							</div>
 | 
				
			||||||
			<div>
 | 
					 | 
				
			||||||
				@displayWebsites(websites)
 | 
					 | 
				
			||||||
			</div>
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -142,13 +138,7 @@ templ WebsiteDashboardComingSoon(title string, data CommonData, website models.W
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
templ WebsiteCreate(title string, data CommonData, form forms.WebsiteCreateForm) {
 | 
					templ WebsiteCreate(title string, data CommonData, form forms.WebsiteCreateForm) {
 | 
				
			||||||
	if data.IsHtmx {
 | 
						<form hx-post="/websites/create" hx-target="closest div">
 | 
				
			||||||
		<form hx-post="/websites/create" hx-target="closest div">
 | 
							@websiteCreateForm(data.CSRFToken, form)
 | 
				
			||||||
			@websiteCreateForm(data.CSRFToken, form)
 | 
						</form>
 | 
				
			||||||
		</form>
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		<form action="/websites/create" method="post">
 | 
					 | 
				
			||||||
			@websiteCreateForm(data.CSRFToken, form)
 | 
					 | 
				
			||||||
		</form>
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										7
									
								
								ui/views/websites_hx.templ
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								ui/views/websites_hx.templ
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,7 @@
 | 
				
			|||||||
 | 
					package views
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "git.32bit.cafe/32bitcafe/guestbook/internal/models"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					templ HxWebsiteList(websites []models.Website) {
 | 
				
			||||||
 | 
						@displayWebsites(websites)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										42
									
								
								ui/views/websites_hx_templ.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								ui/views/websites_hx_templ.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,42 @@
 | 
				
			|||||||
 | 
					// 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"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func HxWebsiteList(websites []models.Website) templ.Component {
 | 
				
			||||||
 | 
						return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
 | 
				
			||||||
 | 
							templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
 | 
				
			||||||
 | 
							if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
 | 
				
			||||||
 | 
								return templ_7745c5c3_CtxErr
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
 | 
				
			||||||
 | 
							if !templ_7745c5c3_IsBuffer {
 | 
				
			||||||
 | 
								defer func() {
 | 
				
			||||||
 | 
									templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
 | 
				
			||||||
 | 
									if templ_7745c5c3_Err == nil {
 | 
				
			||||||
 | 
										templ_7745c5c3_Err = templ_7745c5c3_BufErr
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}()
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							ctx = templ.InitializeContext(ctx)
 | 
				
			||||||
 | 
							templ_7745c5c3_Var1 := templ.GetChildren(ctx)
 | 
				
			||||||
 | 
							if templ_7745c5c3_Var1 == nil {
 | 
				
			||||||
 | 
								templ_7745c5c3_Var1 = templ.NopComponent
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							ctx = templ.ClearChildren(ctx)
 | 
				
			||||||
 | 
							templ_7745c5c3_Err = displayWebsites(websites).Render(ctx, templ_7745c5c3_Buffer)
 | 
				
			||||||
 | 
							if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
								return templ_7745c5c3_Err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var _ = templruntime.GeneratedTemplate
 | 
				
			||||||
@ -385,50 +385,43 @@ func WebsiteList(title string, data CommonData, websites []models.Website) templ
 | 
				
			|||||||
			templ_7745c5c3_Var21 = templ.NopComponent
 | 
								templ_7745c5c3_Var21 = templ.NopComponent
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		ctx = templ.ClearChildren(ctx)
 | 
							ctx = templ.ClearChildren(ctx)
 | 
				
			||||||
		if data.IsHtmx {
 | 
							templ_7745c5c3_Var22 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
 | 
				
			||||||
 | 
								templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
 | 
				
			||||||
 | 
								templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
 | 
				
			||||||
 | 
								if !templ_7745c5c3_IsBuffer {
 | 
				
			||||||
 | 
									defer func() {
 | 
				
			||||||
 | 
										templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
 | 
				
			||||||
 | 
										if templ_7745c5c3_Err == nil {
 | 
				
			||||||
 | 
											templ_7745c5c3_Err = templ_7745c5c3_BufErr
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									}()
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								ctx = templ.InitializeContext(ctx)
 | 
				
			||||||
 | 
								templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 33, "<h1>My Websites</h1><div>")
 | 
				
			||||||
 | 
								if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
									return templ_7745c5c3_Err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								templ_7745c5c3_Err = WebsiteCreateButton().Render(ctx, templ_7745c5c3_Buffer)
 | 
				
			||||||
 | 
								if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
									return templ_7745c5c3_Err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 34, "</div><div>")
 | 
				
			||||||
 | 
								if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
									return templ_7745c5c3_Err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
			templ_7745c5c3_Err = displayWebsites(websites).Render(ctx, templ_7745c5c3_Buffer)
 | 
								templ_7745c5c3_Err = displayWebsites(websites).Render(ctx, templ_7745c5c3_Buffer)
 | 
				
			||||||
			if templ_7745c5c3_Err != nil {
 | 
								if templ_7745c5c3_Err != nil {
 | 
				
			||||||
				return templ_7745c5c3_Err
 | 
									return templ_7745c5c3_Err
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		} else {
 | 
								templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 35, "</div>")
 | 
				
			||||||
			templ_7745c5c3_Var22 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
 | 
					 | 
				
			||||||
				templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
 | 
					 | 
				
			||||||
				templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
 | 
					 | 
				
			||||||
				if !templ_7745c5c3_IsBuffer {
 | 
					 | 
				
			||||||
					defer func() {
 | 
					 | 
				
			||||||
						templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
 | 
					 | 
				
			||||||
						if templ_7745c5c3_Err == nil {
 | 
					 | 
				
			||||||
							templ_7745c5c3_Err = templ_7745c5c3_BufErr
 | 
					 | 
				
			||||||
						}
 | 
					 | 
				
			||||||
					}()
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				ctx = templ.InitializeContext(ctx)
 | 
					 | 
				
			||||||
				templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 33, "<h1>My Websites</h1><p>")
 | 
					 | 
				
			||||||
				if templ_7745c5c3_Err != nil {
 | 
					 | 
				
			||||||
					return templ_7745c5c3_Err
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				templ_7745c5c3_Err = WebsiteCreateButton().Render(ctx, templ_7745c5c3_Buffer)
 | 
					 | 
				
			||||||
				if templ_7745c5c3_Err != nil {
 | 
					 | 
				
			||||||
					return templ_7745c5c3_Err
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 34, "</p><div>")
 | 
					 | 
				
			||||||
				if templ_7745c5c3_Err != nil {
 | 
					 | 
				
			||||||
					return templ_7745c5c3_Err
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				templ_7745c5c3_Err = displayWebsites(websites).Render(ctx, templ_7745c5c3_Buffer)
 | 
					 | 
				
			||||||
				if templ_7745c5c3_Err != nil {
 | 
					 | 
				
			||||||
					return templ_7745c5c3_Err
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 35, "</div>")
 | 
					 | 
				
			||||||
				if templ_7745c5c3_Err != nil {
 | 
					 | 
				
			||||||
					return templ_7745c5c3_Err
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				return nil
 | 
					 | 
				
			||||||
			})
 | 
					 | 
				
			||||||
			templ_7745c5c3_Err = base(title, data).Render(templ.WithChildren(ctx, templ_7745c5c3_Var22), templ_7745c5c3_Buffer)
 | 
					 | 
				
			||||||
			if templ_7745c5c3_Err != nil {
 | 
								if templ_7745c5c3_Err != nil {
 | 
				
			||||||
				return templ_7745c5c3_Err
 | 
									return templ_7745c5c3_Err
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
								return nil
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
							templ_7745c5c3_Err = base(title, data).Render(templ.WithChildren(ctx, templ_7745c5c3_Var22), templ_7745c5c3_Buffer)
 | 
				
			||||||
 | 
							if templ_7745c5c3_Err != nil {
 | 
				
			||||||
 | 
								return templ_7745c5c3_Err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		return nil
 | 
							return nil
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
@ -482,7 +475,7 @@ func WebsiteDashboard(title string, data CommonData, website models.Website) tem
 | 
				
			|||||||
			var templ_7745c5c3_Var25 string
 | 
								var templ_7745c5c3_Var25 string
 | 
				
			||||||
			templ_7745c5c3_Var25, templ_7745c5c3_Err = templ.JoinStringErrs(website.Name)
 | 
								templ_7745c5c3_Var25, templ_7745c5c3_Err = templ.JoinStringErrs(website.Name)
 | 
				
			||||||
			if templ_7745c5c3_Err != nil {
 | 
								if templ_7745c5c3_Err != nil {
 | 
				
			||||||
				return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/websites.templ`, Line: 121, Col: 22}
 | 
									return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/websites.templ`, Line: 117, Col: 22}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var25))
 | 
								_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var25))
 | 
				
			||||||
			if templ_7745c5c3_Err != nil {
 | 
								if templ_7745c5c3_Err != nil {
 | 
				
			||||||
@ -550,7 +543,7 @@ func WebsiteDashboardComingSoon(title string, data CommonData, website models.We
 | 
				
			|||||||
			var templ_7745c5c3_Var28 string
 | 
								var templ_7745c5c3_Var28 string
 | 
				
			||||||
			templ_7745c5c3_Var28, templ_7745c5c3_Err = templ.JoinStringErrs(website.Name)
 | 
								templ_7745c5c3_Var28, templ_7745c5c3_Err = templ.JoinStringErrs(website.Name)
 | 
				
			||||||
			if templ_7745c5c3_Err != nil {
 | 
								if templ_7745c5c3_Err != nil {
 | 
				
			||||||
				return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/websites.templ`, Line: 135, Col: 22}
 | 
									return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/websites.templ`, Line: 131, Col: 22}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var28))
 | 
								_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var28))
 | 
				
			||||||
			if templ_7745c5c3_Err != nil {
 | 
								if templ_7745c5c3_Err != nil {
 | 
				
			||||||
@ -591,32 +584,17 @@ func WebsiteCreate(title string, data CommonData, form forms.WebsiteCreateForm)
 | 
				
			|||||||
			templ_7745c5c3_Var29 = templ.NopComponent
 | 
								templ_7745c5c3_Var29 = templ.NopComponent
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		ctx = templ.ClearChildren(ctx)
 | 
							ctx = templ.ClearChildren(ctx)
 | 
				
			||||||
		if data.IsHtmx {
 | 
							templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 42, "<form hx-post=\"/websites/create\" hx-target=\"closest div\">")
 | 
				
			||||||
			templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 42, "<form hx-post=\"/websites/create\" hx-target=\"closest div\">")
 | 
							if templ_7745c5c3_Err != nil {
 | 
				
			||||||
			if templ_7745c5c3_Err != nil {
 | 
								return templ_7745c5c3_Err
 | 
				
			||||||
				return templ_7745c5c3_Err
 | 
							}
 | 
				
			||||||
			}
 | 
							templ_7745c5c3_Err = websiteCreateForm(data.CSRFToken, form).Render(ctx, templ_7745c5c3_Buffer)
 | 
				
			||||||
			templ_7745c5c3_Err = websiteCreateForm(data.CSRFToken, form).Render(ctx, templ_7745c5c3_Buffer)
 | 
							if templ_7745c5c3_Err != nil {
 | 
				
			||||||
			if templ_7745c5c3_Err != nil {
 | 
								return templ_7745c5c3_Err
 | 
				
			||||||
				return templ_7745c5c3_Err
 | 
							}
 | 
				
			||||||
			}
 | 
							templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 43, "</form>")
 | 
				
			||||||
			templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 43, "</form>")
 | 
							if templ_7745c5c3_Err != nil {
 | 
				
			||||||
			if templ_7745c5c3_Err != nil {
 | 
								return templ_7745c5c3_Err
 | 
				
			||||||
				return templ_7745c5c3_Err
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 44, "<form action=\"/websites/create\" method=\"post\">")
 | 
					 | 
				
			||||||
			if templ_7745c5c3_Err != nil {
 | 
					 | 
				
			||||||
				return templ_7745c5c3_Err
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			templ_7745c5c3_Err = websiteCreateForm(data.CSRFToken, form).Render(ctx, templ_7745c5c3_Buffer)
 | 
					 | 
				
			||||||
			if templ_7745c5c3_Err != nil {
 | 
					 | 
				
			||||||
				return templ_7745c5c3_Err
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 45, "</form>")
 | 
					 | 
				
			||||||
			if templ_7745c5c3_Err != nil {
 | 
					 | 
				
			||||||
				return templ_7745c5c3_Err
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		return nil
 | 
							return nil
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user