diff --git a/cmd/web/handlers_user.go b/cmd/web/handlers_user.go index 772c8d4..18e04bb 100644 --- a/cmd/web/handlers_user.go +++ b/cmd/web/handlers_user.go @@ -39,7 +39,8 @@ func (app *application) postUserRegister(w http.ResponseWriter, r *http.Request) return } shortId := app.createShortId() - err = app.users.Insert(shortId, form.Name, form.Email, form.Password) + settings := DefaultUserSettings() + err = app.users.Insert(shortId, form.Name, form.Email, form.Password, settings) if err != nil { if errors.Is(err, models.ErrDuplicateEmail) { form.AddFieldError("email", "Email address is already in use") @@ -129,3 +130,34 @@ func (app *application) getUser(w http.ResponseWriter, r *http.Request) { data := app.newCommonData(r) views.UserProfile(user.Username, data, user).Render(r.Context(), w) } + +func (app *application) getUserSettings(w http.ResponseWriter, r *http.Request) { + data := app.newCommonData(r) + views.UserSettingsView(data, app.timezones).Render(r.Context(), w) +} + +func (app *application) putUserSettings(w http.ResponseWriter, r *http.Request) { + userId := app.getCurrentUser(r).ID + var form forms.UserSettingsForm + err := app.decodePostForm(r, &form) + if err != nil { + app.clientError(w, http.StatusBadRequest) + app.serverError(w, r, err) + return + } + form.CheckField(validator.PermittedValue(form.LocalTimezone, app.timezones...), "timezone", "Invalid value") + if !form.Valid() { + // rerender template with errors + app.clientError(w, http.StatusUnprocessableEntity) + } + err = app.users.SetLocalTimezone(userId, form.LocalTimezone) + 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.UserSettingsView(data, app.timezones).Render(r.Context(), w) + +} diff --git a/cmd/web/helpers.go b/cmd/web/helpers.go index ca0dfdd..43a6cc5 100644 --- a/cmd/web/helpers.go +++ b/cmd/web/helpers.go @@ -112,3 +112,9 @@ func (app *application) newCommonData(r *http.Request) views.CommonData { IsHtmx: r.Header.Get("Hx-Request") == "true", } } + +func DefaultUserSettings() models.UserSettings { + return models.UserSettings{ + LocalTimezone: time.Now().UTC().Location(), + } +} diff --git a/cmd/web/main.go b/cmd/web/main.go index e1a2bec..3d7fb96 100644 --- a/cmd/web/main.go +++ b/cmd/web/main.go @@ -7,7 +7,9 @@ import ( "log/slog" "net/http" "os" + "strings" "time" + "unicode" "git.32bit.cafe/32bitcafe/guestbook/internal/models" "github.com/alexedwards/scs/sqlite3store" @@ -26,6 +28,7 @@ type application struct { sessionManager *scs.SessionManager formDecoder *schema.Decoder debug bool + timezones []string } func main() { @@ -60,6 +63,7 @@ func main() { guestbookComments: &models.GuestbookCommentModel{DB: db}, formDecoder: formDecoder, debug: *debug, + timezones: getAvailableTimezones(), } tlsConfig := &tls.Config{ @@ -97,3 +101,50 @@ func openDB(dsn string) (*sql.DB, error) { } return db, nil } + +func getAvailableTimezones() []string { + var zones []string + var zoneDirs = []string{ + "/usr/share/zoneinfo/", + "/usr/share/lib/zoneinfo/", + "/usr/lib/locale/TZ/", + } + for _, zd := range zoneDirs { + zones = walkTzDir(zd, zones) + for idx, zone := range zones { + zones[idx] = strings.ReplaceAll(zone, zd+"/", "") + } + } + return zones +} + +func walkTzDir(path string, zones []string) []string { + fileInfos, err := os.ReadDir(path) + if err != nil { + return zones + } + isAlpha := func(s string) bool { + for _, r := range s { + if !unicode.IsLetter(r) { + return false + } + } + return true + } + for _, info := range fileInfos { + if info.Name() != strings.ToUpper(info.Name()[:1])+info.Name()[1:] { + continue + } + if !isAlpha(info.Name()[:1]) { + continue + } + newPath := path + "/" + info.Name() + if info.IsDir() { + zones = walkTzDir(newPath, zones) + } else { + zones = append(zones, newPath) + } + } + return zones + +} diff --git a/cmd/web/routes.go b/cmd/web/routes.go index cc5b6b5..9690c7c 100644 --- a/cmd/web/routes.go +++ b/cmd/web/routes.go @@ -28,7 +28,8 @@ func (app *application) routes() http.Handler { // mux.Handle("GET /users", protected.ThenFunc(app.getUsersList)) mux.Handle("GET /users/{id}", protected.ThenFunc(app.getUser)) mux.Handle("POST /users/logout", protected.ThenFunc(app.postUserLogout)) - mux.Handle("GET /users/settings", protected.ThenFunc(app.notImplemented)) + mux.Handle("GET /users/settings", protected.ThenFunc(app.getUserSettings)) + mux.Handle("PUT /users/settings", protected.ThenFunc(app.putUserSettings)) mux.Handle("GET /users/privacy", protected.ThenFunc(app.notImplemented)) mux.Handle("GET /guestbooks", protected.ThenFunc(app.getAllGuestbooks)) diff --git a/db/create-settings-tables.sql b/db/create-settings-tables.sql new file mode 100644 index 0000000..07e19f1 --- /dev/null +++ b/db/create-settings-tables.sql @@ -0,0 +1,76 @@ +CREATE TABLE setting_groups ( + Id integer primary key autoincrement, + Description varchar(256) NOT NULL +); + +CREATE TABLE setting_data_types ( + Id integer primary key autoincrement, + Description varchar(64) NOT NULL +); + +CREATE TABLE settings ( + Id integer primary key autoincrement, + Description varchar(256) NOT NULL, + Constrained boolean NOT NULL, + DataType integer NOT NULL, + SettingGroup int NOT NULL, + MinValue varchar(6), + MaxValue varchar(6), + FOREIGN KEY (DataType) REFERENCES setting_data_types(Id) + ON DELETE RESTRICT + ON UPDATE RESTRICT, + FOREIGN KEY (SettingGroup) REFERENCES setting_groups(Id) + ON DELETE RESTRICT + ON UPDATE RESTRICT +); + +CREATE TABLE allowed_setting_values ( + Id integer primary key autoincrement, + SettingId integer NOT NULL, + ItemValue varchar(256), + Caption varchar(256), + FOREIGN KEY (SettingId) REFERENCES settings(Id) + ON DELETE RESTRICT + ON UPDATE RESTRICT +); + +CREATE TABLE user_settings ( + Id integer primary key autoincrement, + UserId integer NOT NULL, + SettingId integer NOT NULL, + AllowedSettingValueId integer NOT NULL, + UnconstrainedValue varchar(256), + FOREIGN KEY (UserId) REFERENCES users(Id) + ON DELETE RESTRICT + ON UPDATE RESTRICT, + FOREIGN KEY (SettingId) REFERENCES settings(Id) + ON DELETE RESTRICT + ON UPDATE RESTRICT, + FOREIGN KEY (AllowedSettingValueId) REFERENCES allowed_setting_values(Id) + ON DELETE RESTRICT + ON UPDATE RESTRICT +); + +CREATE TABLE guestbook_settings ( + Id integer primary key autoincrement, + GuestbookId integer NOT NULL, + SettingId integer NOT NULL, + AllowedSettingValueId integer NOT NULL, + UnconstrainedValue varchar(256), + FOREIGN KEY (GuestbookId) REFERENCES guestbooks(Id) + ON DELETE RESTRICT + ON UPDATE RESTRICT, + FOREIGN KEY (SettingId) REFERENCES settings(Id) + ON DELETE RESTRICT + ON UPDATE RESTRICT, + FOREIGN KEY (AllowedSettingValueId) REFERENCES allowed_setting_values(Id) + ON DELETE RESTRICT + ON UPDATE RESTRICT +); + +INSERT INTO setting_groups (Description) VALUES ('guestbook'); +INSERT INTO setting_groups (Description) VALUES ('user'); + +INSERT INTO setting_data_types (Description) VALUES ('alphanumeric'); +INSERT INTO setting_data_types (Description) VALUES ('integer'); +INSERT INTO setting_data_types (Description) VALUES ('datetime'); diff --git a/db/create-settings.sql b/db/create-settings.sql new file mode 100644 index 0000000..87ee494 --- /dev/null +++ b/db/create-settings.sql @@ -0,0 +1,9 @@ +INSERT INTO setting_groups (Description) VALUES ("guestbook"); +INSERT INTO setting_groups (Description) VALUES ("user"); + +INSERT INTO setting_data_types (Description) VALUES ("alphanumeric") +INSERT INTO setting_data_types (Description) VALUES ("integer") +INSERT INTO setting_data_types (Description) VALUES ("datetime") + +INSERT INTO settings (Description, Constrained, DataType, SettingGroup) +VALUES ("Local Timezone", 0, 1, 1); diff --git a/internal/forms/forms.go b/internal/forms/forms.go index 8d5664f..8891f2b 100644 --- a/internal/forms/forms.go +++ b/internal/forms/forms.go @@ -29,3 +29,8 @@ type WebsiteCreateForm struct { AuthorName string `schema:"authorname"` validator.Validator `schema:"-"` } + +type UserSettingsForm struct { + LocalTimezone string `schema:"timezones"` + validator.Validator `schema:"-"` +} diff --git a/internal/models/user.go b/internal/models/user.go index e4dfbe2..35ce1fd 100644 --- a/internal/models/user.go +++ b/internal/models/user.go @@ -10,6 +10,14 @@ import ( "golang.org/x/crypto/bcrypt" ) +const ( + u_timezone = 1 +) + +type UserSettings struct { + LocalTimezone *time.Location +} + type User struct { ID int64 ShortId uint64 @@ -19,20 +27,21 @@ type User struct { IsBanned bool HashedPassword []byte Created time.Time + Settings UserSettings } type UserModel struct { DB *sql.DB } -func (m *UserModel) Insert(shortId uint64, username string, email string, password string) error { +func (m *UserModel) Insert(shortId uint64, username string, email string, password string, settings UserSettings) error { hashedPassword, err := bcrypt.GenerateFromPassword([]byte(password), 12) if err != nil { return err } stmt := `INSERT INTO users (ShortId, Username, Email, IsBanned, HashedPassword, Created) VALUES (?, ?, ?, FALSE, ?, ?)` - _, err = m.DB.Exec(stmt, shortId, username, email, hashedPassword, time.Now().UTC()) + result, err := m.DB.Exec(stmt, shortId, username, email, hashedPassword, time.Now().UTC()) if err != nil { if sqliteError, ok := err.(sqlite3.Error); ok { if sqliteError.ExtendedCode == 2067 && strings.Contains(sqliteError.Error(), "Email") { @@ -41,6 +50,17 @@ func (m *UserModel) Insert(shortId uint64, username string, email string, passwo } return err } + id, err := result.LastInsertId() + if err != nil { + return err + } + settingsStmt := `INSERT INTO user_settings + (UserId, SettingId, AllowedSettingValueId, UnconstrainedValue) + VALUES (?, ?, ?, ?)` + _, err = m.DB.Exec(settingsStmt, id, u_timezone, nil, settings.LocalTimezone.String()) + if err != nil { + return err + } return nil } @@ -55,6 +75,11 @@ func (m *UserModel) Get(id uint64) (User, error) { } return User{}, err } + settings, err := m.GetSettings(u.ID) + if err != nil { + return u, err + } + u.Settings = settings return u, nil } @@ -69,6 +94,11 @@ func (m *UserModel) GetById(id int64) (User, error) { } return User{}, err } + settings, err := m.GetSettings(u.ID) + if err != nil { + return u, err + } + u.Settings = settings return u, nil } @@ -125,3 +155,40 @@ func (m *UserModel) Exists(id int64) (bool, error) { err := m.DB.QueryRow(stmt, id).Scan(&exists) return exists, err } + +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 + WHERE UserId = ?` + var settings UserSettings + rows, err := m.DB.Query(stmt, userId) + 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 u_timezone: + settings.LocalTimezone, err = time.LoadLocation(unconstrainedValue.String) + if err != nil { + panic(err) + } + } + } + return settings, err +} + +func (m *UserModel) SetLocalTimezone(userId int64, timezone string) error { + stmt := `UPDATE user_settings SET UnconstrainedValue = ? WHERE UserId = ?` + _, err := m.DB.Exec(stmt, timezone, userId) + if err != nil { + return err + } + return nil +} diff --git a/ui/views/common_templ.go b/ui/views/common_templ.go index f707c81..895a1cd 100644 --- a/ui/views/common_templ.go +++ b/ui/views/common_templ.go @@ -1,6 +1,6 @@ // Code generated by templ - DO NOT EDIT. -// templ: version: v0.3.833 +// templ: version: v0.3.857 package views //lint:file-ignore SA4006 This context is only used if a nested component is present. diff --git a/ui/views/guestbooks.templ b/ui/views/guestbooks.templ index a8d56b7..92545f5 100644 --- a/ui/views/guestbooks.templ +++ b/ui/views/guestbooks.templ @@ -48,7 +48,7 @@ templ GuestbookDashboardCommentView(data CommonData, w models.Website, c models. | { c.AuthorSite } }

- { c.Created.Format("01-02-2006 03:04PM") } + { c.Created.In(data.CurrentUser.Settings.LocalTimezone).Format("01-02-2006 03:04PM") }

@@ -167,4 +167,4 @@ templ AllGuestbooksView(data CommonData, websites []models.Website) { } -} \ No newline at end of file +} diff --git a/ui/views/guestbooks_templ.go b/ui/views/guestbooks_templ.go index aab14aa..21732fa 100644 --- a/ui/views/guestbooks_templ.go +++ b/ui/views/guestbooks_templ.go @@ -1,6 +1,6 @@ // Code generated by templ - DO NOT EDIT. -// templ: version: v0.3.833 +// templ: version: v0.3.857 package views //lint:file-ignore SA4006 This context is only used if a nested component is present. @@ -275,9 +275,9 @@ func GuestbookDashboardCommentView(data CommonData, w models.Website, c models.G return templ_7745c5c3_Err } var templ_7745c5c3_Var14 string - templ_7745c5c3_Var14, templ_7745c5c3_Err = templ.JoinStringErrs(c.Created.Format("01-02-2006 03:04PM")) + 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: 56} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/guestbooks.templ`, Line: 51, Col: 100} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var14)) if templ_7745c5c3_Err != nil { diff --git a/ui/views/home_templ.go b/ui/views/home_templ.go index 23a3c6d..4829e83 100644 --- a/ui/views/home_templ.go +++ b/ui/views/home_templ.go @@ -1,6 +1,6 @@ // Code generated by templ - DO NOT EDIT. -// templ: version: v0.3.833 +// templ: version: v0.3.857 package views //lint:file-ignore SA4006 This context is only used if a nested component is present. diff --git a/ui/views/users.templ b/ui/views/users.templ index 46467c8..20c5b26 100644 --- a/ui/views/users.templ +++ b/ui/views/users.templ @@ -79,5 +79,11 @@ templ UserProfile (title string, data CommonData, user models.User) { } } -templ UserSettings () { +templ UserSettings (title string, data CommonData, user models.User) { + @base(title, data) { +

+ + +
+ } } diff --git a/ui/views/users_settings.templ b/ui/views/users_settings.templ new file mode 100644 index 0000000..7f46ff8 --- /dev/null +++ b/ui/views/users_settings.templ @@ -0,0 +1,24 @@ +package views + +templ UserSettingsView(data CommonData, timezones []string) { + {{ user := data.CurrentUser }} + @base("User Settings", data) { +
+

User Settings

+
+ +

Timezone

+ + +
+
+ } +} diff --git a/ui/views/users_settings_templ.go b/ui/views/users_settings_templ.go new file mode 100644 index 0000000..5660866 --- /dev/null +++ b/ui/views/users_settings_templ.go @@ -0,0 +1,141 @@ +// Code generated by templ - DO NOT EDIT. + +// templ: version: v0.3.857 +package views + +//lint:file-ignore SA4006 This context is only used if a nested component is present. + +import "github.com/a-h/templ" +import templruntime "github.com/a-h/templ/runtime" + +func UserSettingsView(data CommonData, timezones []string) templ.Component { + return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { + templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context + if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { + return templ_7745c5c3_CtxErr + } + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) + if !templ_7745c5c3_IsBuffer { + defer func() { + templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) + if templ_7745c5c3_Err == nil { + templ_7745c5c3_Err = templ_7745c5c3_BufErr + } + }() + } + ctx = templ.InitializeContext(ctx) + templ_7745c5c3_Var1 := templ.GetChildren(ctx) + if templ_7745c5c3_Var1 == nil { + templ_7745c5c3_Var1 = templ.NopComponent + } + ctx = templ.ClearChildren(ctx) + user := data.CurrentUser + templ_7745c5c3_Var2 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { + templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) + if !templ_7745c5c3_IsBuffer { + defer func() { + templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) + if templ_7745c5c3_Err == nil { + templ_7745c5c3_Err = templ_7745c5c3_BufErr + } + }() + } + ctx = templ.InitializeContext(ctx) + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "

User Settings

Timezone

") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + return nil + }) + templ_7745c5c3_Err = base("User Settings", data).Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + return nil + }) +} + +var _ = templruntime.GeneratedTemplate diff --git a/ui/views/users_templ.go b/ui/views/users_templ.go index 661a6f5..81e1a2d 100644 --- a/ui/views/users_templ.go +++ b/ui/views/users_templ.go @@ -1,6 +1,6 @@ // Code generated by templ - DO NOT EDIT. -// templ: version: v0.3.833 +// templ: version: v0.3.857 package views //lint:file-ignore SA4006 This context is only used if a nested component is present. @@ -400,7 +400,7 @@ func UserProfile(title string, data CommonData, user models.User) templ.Componen }) } -func UserSettings() templ.Component { +func UserSettings(title string, data CommonData, user models.User) templ.Component { return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { @@ -421,6 +421,28 @@ func UserSettings() templ.Component { templ_7745c5c3_Var20 = templ.NopComponent } ctx = templ.ClearChildren(ctx) + templ_7745c5c3_Var21 := 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, 32, "
") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + return nil + }) + templ_7745c5c3_Err = base(title, data).Render(templ.WithChildren(ctx, templ_7745c5c3_Var21), templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } return nil }) } diff --git a/ui/views/websites.templ b/ui/views/websites.templ index 5dbf533..cead964 100644 --- a/ui/views/websites.templ +++ b/ui/views/websites.templ @@ -4,151 +4,151 @@ import "fmt" import "git.32bit.cafe/32bitcafe/guestbook/internal/models" import "git.32bit.cafe/32bitcafe/guestbook/internal/forms" -func wUrl (w models.Website) string { - return fmt.Sprintf("/websites/%s", shortIdToSlug(w.ShortId)) +func wUrl(w models.Website) string { + return fmt.Sprintf("/websites/%s", shortIdToSlug(w.ShortId)) } templ wSidebar(website models.Website) { - {{ dashUrl := wUrl(website) + "/dashboard" }} - {{ gbUrl := wUrl(website) + "/guestbook" }} - + {{ dashUrl := wUrl(website) + "/dashboard" }} + {{ gbUrl := wUrl(website) + "/guestbook" }} + } -templ displayWebsites (websites []models.Website) { - if len(websites) == 0 { -

No Websites yet. Register a website.

- } else { - - } +templ displayWebsites(websites []models.Website) { + if len(websites) == 0 { +

No Websites yet. Register a website.

+ } else { + + } } templ websiteCreateForm(csrfToken string, form forms.WebsiteCreateForm) { - -
- {{ err, exists := form.FieldErrors["sitename"]}} - - if exists { - - } - -
-
- {{ err, exists = form.FieldErrors["siteurl"] }} - - if exists { - - } - -
-
- {{ err, exists = form.FieldErrors["authorname"] }} - - if exists { - - } - -
-
- -
+ +
+ {{ err, exists := form.FieldErrors["sitename"] }} + + if exists { + + } + +
+
+ {{ err, exists = form.FieldErrors["siteurl"] }} + + if exists { + + } + +
+
+ {{ err, exists = form.FieldErrors["authorname"] }} + + if exists { + + } + +
+
+ +
} templ WebsiteCreateButton() { - + } templ WebsiteList(title string, data CommonData, websites []models.Website) { - if data.IsHtmx { - @displayWebsites(websites) - } else { - @base(title, data) { -

My Websites

-
- @WebsiteCreateButton() -
-
- @displayWebsites(websites) -
- } - } + if data.IsHtmx { + @displayWebsites(websites) + } else { + @base(title, data) { +

My Websites

+

+ @WebsiteCreateButton() +

+
+ @displayWebsites(websites) +
+ } + } } templ WebsiteDashboard(title string, data CommonData, website models.Website) { - @base(title, data) { -
- @wSidebar(website) -
-

{ website.Name }

-

- Stats and stuff will go here. -

-
-
- } + @base(title, data) { +
+ @wSidebar(website) +
+

{ website.Name }

+

+ Stats and stuff will go here. +

+
+
+ } } templ WebsiteDashboardComingSoon(title string, data CommonData, website models.Website) { - @base(title, data) { -
- @wSidebar(website) -
-

{ website.Name }

-

- Coming Soon -

-
-
- } + @base(title, data) { +
+ @wSidebar(website) +
+

{ website.Name }

+

+ Coming Soon +

+
+
+ } } templ WebsiteCreate(title string, data CommonData, form forms.WebsiteCreateForm) { - if data.IsHtmx { -
- @websiteCreateForm(data.CSRFToken, form) -
- } else { -
- @websiteCreateForm(data.CSRFToken, form) -
- } -} \ No newline at end of file + if data.IsHtmx { +
+ @websiteCreateForm(data.CSRFToken, form) +
+ } else { +
+ @websiteCreateForm(data.CSRFToken, form) +
+ } +} diff --git a/ui/views/websites_templ.go b/ui/views/websites_templ.go index fbe1f45..c29b127 100644 --- a/ui/views/websites_templ.go +++ b/ui/views/websites_templ.go @@ -1,6 +1,6 @@ // Code generated by templ - DO NOT EDIT. -// templ: version: v0.3.833 +// templ: version: v0.3.857 package views //lint:file-ignore SA4006 This context is only used if a nested component is present. @@ -46,7 +46,7 @@ func wSidebar(website models.Website) templ.Component { var templ_7745c5c3_Var2 string templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(website.Name) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/websites.templ`, Line: 16, Col: 30} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/websites.templ`, Line: 16, Col: 21} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2)) if templ_7745c5c3_Err != nil { @@ -189,7 +189,7 @@ func displayWebsites(websites []models.Website) templ.Component { var templ_7745c5c3_Var14 string templ_7745c5c3_Var14, templ_7745c5c3_Err = templ.JoinStringErrs(w.Name) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/websites.templ`, Line: 58, Col: 73} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/websites.templ`, Line: 58, Col: 59} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var14)) if templ_7745c5c3_Err != nil { @@ -237,7 +237,7 @@ func websiteCreateForm(csrfToken string, form forms.WebsiteCreateForm) templ.Com var templ_7745c5c3_Var16 string templ_7745c5c3_Var16, templ_7745c5c3_Err = templ.JoinStringErrs(csrfToken) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/websites.templ`, Line: 66, Col: 59} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/websites.templ`, Line: 66, Col: 57} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var16)) if templ_7745c5c3_Err != nil { @@ -260,7 +260,7 @@ func websiteCreateForm(csrfToken string, form forms.WebsiteCreateForm) templ.Com var templ_7745c5c3_Var17 string templ_7745c5c3_Var17, templ_7745c5c3_Err = templ.JoinStringErrs(err) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/websites.templ`, Line: 71, Col: 38} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/websites.templ`, Line: 71, Col: 29} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var17)) if templ_7745c5c3_Err != nil { @@ -288,7 +288,7 @@ func websiteCreateForm(csrfToken string, form forms.WebsiteCreateForm) templ.Com var templ_7745c5c3_Var18 string templ_7745c5c3_Var18, templ_7745c5c3_Err = templ.JoinStringErrs(err) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/websites.templ`, Line: 79, Col: 38} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/websites.templ`, Line: 79, Col: 29} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var18)) if templ_7745c5c3_Err != nil { @@ -316,7 +316,7 @@ func websiteCreateForm(csrfToken string, form forms.WebsiteCreateForm) templ.Com var templ_7745c5c3_Var19 string templ_7745c5c3_Var19, templ_7745c5c3_Err = templ.JoinStringErrs(err) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/websites.templ`, Line: 87, Col: 38} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/websites.templ`, Line: 87, Col: 29} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var19)) if templ_7745c5c3_Err != nil { @@ -403,7 +403,7 @@ func WebsiteList(title string, data CommonData, websites []models.Website) templ }() } ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 33, "

My Websites

") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 33, "

My Websites

") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -411,7 +411,7 @@ func WebsiteList(title string, data CommonData, websites []models.Website) templ if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 34, "

") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 34, "

") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -482,7 +482,7 @@ func WebsiteDashboard(title string, data CommonData, website models.Website) tem var templ_7745c5c3_Var25 string templ_7745c5c3_Var25, templ_7745c5c3_Err = templ.JoinStringErrs(website.Name) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/websites.templ`, Line: 121, Col: 34} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/websites.templ`, Line: 121, Col: 22} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var25)) if templ_7745c5c3_Err != nil { @@ -550,7 +550,7 @@ func WebsiteDashboardComingSoon(title string, data CommonData, website models.We var templ_7745c5c3_Var28 string templ_7745c5c3_Var28, templ_7745c5c3_Err = templ.JoinStringErrs(website.Name) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/websites.templ`, Line: 135, Col: 34} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `ui/views/websites.templ`, Line: 135, Col: 22} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var28)) if templ_7745c5c3_Err != nil {