From 03d151f75a06badfd9f710aa14f10a70914a2aa0 Mon Sep 17 00:00:00 2001 From: James Tombleson Date: Sun, 14 Apr 2024 18:33:17 -0700 Subject: [PATCH 01/12] Moved the cookie consts to a domain package --- domain/consts.go | 9 +++++++++ handlers/handler.go | 15 +++++---------- 2 files changed, 14 insertions(+), 10 deletions(-) create mode 100644 domain/consts.go diff --git a/domain/consts.go b/domain/consts.go new file mode 100644 index 0000000..9e67900 --- /dev/null +++ b/domain/consts.go @@ -0,0 +1,9 @@ +package domain + +const ( + CookieToken = "token" + CookieRefreshToken = "refresh" + CookieUser = "user" + + CookieSettingsDarkMode = "darkmode" +) diff --git a/handlers/handler.go b/handlers/handler.go index 4cbfa70..d3c9f0f 100644 --- a/handlers/handler.go +++ b/handlers/handler.go @@ -3,6 +3,7 @@ package handlers import ( "errors" "templ-test/client" + "templ-test/domain" "templ-test/models" "templ-test/services" "time" @@ -13,12 +14,6 @@ import ( "github.com/labstack/echo/v4" ) -const ( - CookieToken = "token" - CookieRefreshToken = "refresh" - CookieUser = "user" -) - type Handlers struct { api client.ApiClient cfg services.EnvConfig @@ -76,7 +71,7 @@ func ValidateJwt(ctx echo.Context, sharedSecret, issuer string) (jwtToken, error if !token.Valid { return jwtToken{}, errors.New("invalid jwt token") } - + claims := token.Claims.(*jwtToken) if !claims.Exp.After(time.Now()) { return jwtToken{}, errors.New("the jwt token has expired") @@ -91,17 +86,17 @@ func ValidateJwt(ctx echo.Context, sharedSecret, issuer string) (jwtToken, error func GetCookieValues(ctx echo.Context) models.AllCookies { m := models.AllCookies{} - token, err := ctx.Cookie(CookieToken) + token, err := ctx.Cookie(domain.CookieToken) if err == nil { m.Token = token.Value } - user, err := ctx.Cookie(CookieUser) + user, err := ctx.Cookie(domain.CookieUser) if err == nil { m.Username = user.Value } - refresh, err := ctx.Cookie(CookieRefreshToken) + refresh, err := ctx.Cookie(domain.CookieRefreshToken) if err == nil { m.RefreshToken = refresh.Value } From 9d88d649d1eb33be347c06d771cf71cda933fe13 Mon Sep 17 00:00:00 2001 From: James Tombleson Date: Sun, 14 Apr 2024 18:36:04 -0700 Subject: [PATCH 02/12] cleaned up the current bootstrap components --- .../bootstrap/{bs_card.templ => alert.templ} | 4 ---- views/components/bootstrap/button.templ | 10 ++++++++++ views/components/bootstrap/label.templ | 5 +++++ views/components/bootstrap/switch.templ | 13 +++++++++++++ 4 files changed, 28 insertions(+), 4 deletions(-) rename views/components/bootstrap/{bs_card.templ => alert.templ} (75%) create mode 100644 views/components/bootstrap/button.templ create mode 100644 views/components/bootstrap/label.templ create mode 100644 views/components/bootstrap/switch.templ diff --git a/views/components/bootstrap/bs_card.templ b/views/components/bootstrap/alert.templ similarity index 75% rename from views/components/bootstrap/bs_card.templ rename to views/components/bootstrap/alert.templ index 6f4073b..c2be6c8 100644 --- a/views/components/bootstrap/bs_card.templ +++ b/views/components/bootstrap/alert.templ @@ -17,7 +17,3 @@ templ BootstrapAlert(message, variant string) { { message } } - -templ BootstrapButton(message, variant string) { - -} diff --git a/views/components/bootstrap/button.templ b/views/components/bootstrap/button.templ new file mode 100644 index 0000000..fc85b61 --- /dev/null +++ b/views/components/bootstrap/button.templ @@ -0,0 +1,10 @@ +package bootstrap + +const ( + ButtonTypeSubmit = "submit" + ButtonTypeDefault = "button" +) + +templ BootstrapButton(message, variant, buttonType string) { + +} diff --git a/views/components/bootstrap/label.templ b/views/components/bootstrap/label.templ new file mode 100644 index 0000000..9786fe9 --- /dev/null +++ b/views/components/bootstrap/label.templ @@ -0,0 +1,5 @@ +package bootstrap + +templ Label(cssClass, name, cssForId, message string) { + +} \ No newline at end of file diff --git a/views/components/bootstrap/switch.templ b/views/components/bootstrap/switch.templ new file mode 100644 index 0000000..e0635f3 --- /dev/null +++ b/views/components/bootstrap/switch.templ @@ -0,0 +1,13 @@ +package bootstrap + +const ( + SwitchTypeCheckbox = "checkbox" +) + +templ Switch(name, switchType, cssId string, enabled bool) { + if enabled == true { + + } else { + + } +} From 68c44812d85b0ee781c91eaef900acaf86c87ff8 Mon Sep 17 00:00:00 2001 From: James Tombleson Date: Sun, 14 Apr 2024 18:37:12 -0700 Subject: [PATCH 03/12] vscode config --- .vscode/launch.json | 15 +++++++++++++++ .vscode/settings.json | 7 +++++++ 2 files changed, 22 insertions(+) create mode 100644 .vscode/launch.json diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..b1258dc --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,15 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "Launch file", + "type": "go", + "request": "launch", + "mode": "debug", + "program": "cmd/main.go" + } + ] +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json index 1d914e3..276f6bf 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,6 +1,13 @@ { + "editor.formatOnSave": true, + "[templ]": { + "editor.defaultFormatter": "a-h.templ" + }, "files.exclude": { "**/*_templ.go": true, "**/*_templ.txt": true + }, + "emmet.includeLanguages": { + "templ": "html" } } \ No newline at end of file From a4d5b7ade38227f8519803644fba1f62808269d4 Mon Sep 17 00:00:00 2001 From: James Tombleson Date: Sun, 14 Apr 2024 18:38:09 -0700 Subject: [PATCH 04/12] moving things to use WithLayout and push the darkmode theme to a cookie that is pulled on layout render --- views/auth/cookie.templ | 2 +- views/auth/login.templ | 2 +- views/home/error.templ | 2 +- views/home/home.templ | 6 +++--- views/layout/body.templ | 2 +- views/layout/util.go | 8 +++++++- 6 files changed, 14 insertions(+), 8 deletions(-) diff --git a/views/auth/cookie.templ b/views/auth/cookie.templ index a9e8ada..907609b 100644 --- a/views/auth/cookie.templ +++ b/views/auth/cookie.templ @@ -4,7 +4,7 @@ import "templ-test/models" import "templ-test/views/layout" templ ShowCookie(m models.AllCookies) { - @layout.Testing("Cookie Explorer") { + @layout.WithLayout("Cookie Explorer") {

These are stored as cookies

Username: { m.Username }

JWT Token: { m.Token }

diff --git a/views/auth/login.templ b/views/auth/login.templ index 6dc0886..b617169 100644 --- a/views/auth/login.templ +++ b/views/auth/login.templ @@ -3,7 +3,7 @@ package auth import "templ-test/views/layout" templ AuthLogin() { - @layout.WithLayout("Login", true) { + @layout.WithLayout("Login") {
diff --git a/views/home/error.templ b/views/home/error.templ index 7ca9230..f92a3b9 100644 --- a/views/home/error.templ +++ b/views/home/error.templ @@ -3,7 +3,7 @@ package home import "templ-test/views/layout" templ Error(message error) { - @layout.Testing("Error") { + @layout.WithLayout("Error") {

Oops... :(

{ message.Error() }

} diff --git a/views/home/home.templ b/views/home/home.templ index 0a1add7..e6e9f74 100644 --- a/views/home/home.templ +++ b/views/home/home.templ @@ -4,14 +4,14 @@ import "templ-test/views/components/bootstrap" import "templ-test/views/layout" templ Home() { - @layout.WithLayout("Home", true) { + @layout.WithLayout("Home") {

this should be above the alert

@bootstrap.BootstrapAlert("Testing!", bootstrap.VariantDark)

you should now see this under the Alert

- @bootstrap.BootstrapButton("I am in danger", bootstrap.VariantDanger) - @bootstrap.BootstrapButton("I am the darkness", bootstrap.VariantDark) + @bootstrap.BootstrapButton("I am in danger", bootstrap.VariantDanger, bootstrap.ButtonTypeDefault) + @bootstrap.BootstrapButton("I am the darkness", bootstrap.VariantDark, bootstrap.ButtonTypeDefault) } } diff --git a/views/layout/body.templ b/views/layout/body.templ index a626b65..f4eb6e0 100644 --- a/views/layout/body.templ +++ b/views/layout/body.templ @@ -1,6 +1,6 @@ package layout -templ WithLayout(pageName string, useDarkMode bool) { +templ WithLayout(pageName string) { @getHtmlHead() diff --git a/views/layout/util.go b/views/layout/util.go index ea4ec80..78351cd 100644 --- a/views/layout/util.go +++ b/views/layout/util.go @@ -2,8 +2,14 @@ package layout import ( "context" + "templ-test/domain" ) func useLightOrDarkTheme(ctx context.Context) string { - return "dark" + cookie := ctx.Value(domain.CookieSettingsDarkMode) + if cookie == "on" { + return "dark" + } else { + return "light" + } } From 22940d952c6aa28036bb33e578ee89546c6a8705 Mon Sep 17 00:00:00 2001 From: James Tombleson Date: Sun, 14 Apr 2024 18:38:28 -0700 Subject: [PATCH 05/12] added a custom viewmodel for SettingsView --- models/home.go | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 models/home.go diff --git a/models/home.go b/models/home.go new file mode 100644 index 0000000..ac1d1d3 --- /dev/null +++ b/models/home.go @@ -0,0 +1,5 @@ +package models + +type SettingsViewModel struct { + DarkMode string +} From f9c7032e92ca4b596361e7416da5b3dc3069bd57 Mon Sep 17 00:00:00 2001 From: James Tombleson Date: Sun, 14 Apr 2024 18:38:44 -0700 Subject: [PATCH 06/12] domain updates --- handlers/auth.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/handlers/auth.go b/handlers/auth.go index 5b152a2..a9edb38 100644 --- a/handlers/auth.go +++ b/handlers/auth.go @@ -3,6 +3,7 @@ package handlers import ( "log" "net/http" + "templ-test/domain" "templ-test/views/auth" "templ-test/views/home" @@ -25,17 +26,17 @@ func (h *Handlers) AuthLoginPost(c echo.Context) error { } cookie := new(http.Cookie) - cookie.Name = CookieToken + cookie.Name = domain.CookieToken cookie.Value = resp.Token c.SetCookie(cookie) cookie = new(http.Cookie) - cookie.Name = CookieRefreshToken + cookie.Name = domain.CookieRefreshToken cookie.Value = resp.RefreshToken c.SetCookie(cookie) cookie = new(http.Cookie) - cookie.Name = CookieUser + cookie.Name = domain.CookieUser cookie.Value = user c.SetCookie(cookie) From 6cfc53901eb920a819e45e31697d671b359e5630 Mon Sep 17 00:00:00 2001 From: James Tombleson Date: Sun, 14 Apr 2024 18:39:04 -0700 Subject: [PATCH 07/12] working on getting the clientside settings in place --- handlers/home.go | 20 ++++++++++++++++++-- views/home/settings.templ | 30 +++++++++++++++++++++++++++--- views/home/settingsUpdated.templ | 9 +++++++++ 3 files changed, 54 insertions(+), 5 deletions(-) create mode 100644 views/home/settingsUpdated.templ diff --git a/handlers/home.go b/handlers/home.go index d35c8df..2c216ed 100644 --- a/handlers/home.go +++ b/handlers/home.go @@ -2,6 +2,8 @@ package handlers import ( "net/http" + "templ-test/domain" + "templ-test/models" "templ-test/views/home" "github.com/labstack/echo/v4" @@ -12,13 +14,27 @@ func (h *Handlers) HomeHandler(c echo.Context) error { } func (h *Handlers) Settings(c echo.Context) error { - return Render(c, http.StatusOK, home.UserSettings()) + m := models.SettingsViewModel{} + darkMode, err := c.Cookie(domain.CookieSettingsDarkMode) + if err == nil { + m.DarkMode = darkMode.Value + } + + return Render(c, http.StatusOK, home.UserSettings(m)) } func (h *Handlers) SettingsPost(c echo.Context) error { // take in the updated values from he user and write the cookies... tbd + useDarkMode := c.FormValue(domain.CookieSettingsDarkMode) + if useDarkMode != "" { + darkModeCookie := new(http.Cookie) + darkModeCookie.Name = domain.CookieSettingsDarkMode + darkModeCookie.Value = useDarkMode - return Render(c, http.StatusOK, home.UserSettings()) + c.SetCookie(darkModeCookie) + } + + return Render(c, http.StatusOK, home.SettingsUpdated()) } //func (h *Handlers) ListHandler(c echo.Context) error { diff --git a/views/home/settings.templ b/views/home/settings.templ index 30da693..2c50972 100644 --- a/views/home/settings.templ +++ b/views/home/settings.templ @@ -1,9 +1,33 @@ package home import "templ-test/views/layout" +import "templ-test/views/components/bootstrap" +import "templ-test/models" +import "templ-test/domain" -templ UserSettings() { - @layout.Testing("Settings") { -

This is not ready yet

+const ( + test = "t" +) + +templ UserSettings(model models.SettingsViewModel) { + @layout.WithLayout("Settings") { + +
+ if useDarkMode(model.DarkMode) { + @bootstrap.Switch("darkmode", bootstrap.SwitchTypeCheckbox, test, true) + } else { + @bootstrap.Switch("darkmode", bootstrap.SwitchTypeCheckbox, "flexSwitchCheckDefault", true) + } + @bootstrap.Label("form-check-label", domain.CookieSettingsDarkMode, "flexSwitchCheckDefault", "Use Dark Mode") +
+ @bootstrap.BootstrapButton("Submit", bootstrap.VariantInfo, bootstrap.ButtonTypeSubmit) + } } + +func useDarkMode(value string) bool { + if value == "on" { + return true + } + return false +} \ No newline at end of file diff --git a/views/home/settingsUpdated.templ b/views/home/settingsUpdated.templ new file mode 100644 index 0000000..33440c1 --- /dev/null +++ b/views/home/settingsUpdated.templ @@ -0,0 +1,9 @@ +package home + +import "templ-test/views/layout" + +templ SettingsUpdated() { + @layout.WithLayout("Settings Updated") { +

You are now free to move about the cabin. Thank you for saving with us!

+ } +} \ No newline at end of file From cda43e8ae271f2063c465fcf1f2b97b6cc9f9df7 Mon Sep 17 00:00:00 2001 From: James Tombleson Date: Sun, 14 Apr 2024 19:36:30 -0700 Subject: [PATCH 08/12] updated the cookie view to show darkmode settings --- views/auth/cookie.templ | 3 +++ 1 file changed, 3 insertions(+) diff --git a/views/auth/cookie.templ b/views/auth/cookie.templ index 907609b..64e92dc 100644 --- a/views/auth/cookie.templ +++ b/views/auth/cookie.templ @@ -6,8 +6,11 @@ import "templ-test/views/layout" templ ShowCookie(m models.AllCookies) { @layout.WithLayout("Cookie Explorer") {

These are stored as cookies

+

JWT Values

Username: { m.Username }

JWT Token: { m.Token }

RefreshToken: { m.RefreshToken }

+

User Settings

+

DarkMode: { m.DarkMode }

} } From 2086ff3547cf3749d47af9f034f649e3d73ed23b Mon Sep 17 00:00:00 2001 From: James Tombleson Date: Sun, 14 Apr 2024 19:36:45 -0700 Subject: [PATCH 09/12] simple loginPost to avoid double layouts --- views/auth/loginPost.templ | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 views/auth/loginPost.templ diff --git a/views/auth/loginPost.templ b/views/auth/loginPost.templ new file mode 100644 index 0000000..d1c7556 --- /dev/null +++ b/views/auth/loginPost.templ @@ -0,0 +1,7 @@ +package auth + +import "templ-test/views/components/bootstrap" + +templ LoginPost() { + @bootstrap.BootstrapAlert("Login successful!", bootstrap.VariantSuccess) +} From 9dbd8e0e003eb7c917f1e81e37cda91a9b3ea2ad Mon Sep 17 00:00:00 2001 From: James Tombleson Date: Sun, 14 Apr 2024 19:37:06 -0700 Subject: [PATCH 10/12] Same thing here, once they post a new value just return something basic for now --- views/home/settingsUpdated.templ | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/views/home/settingsUpdated.templ b/views/home/settingsUpdated.templ index 33440c1..69b1eb3 100644 --- a/views/home/settingsUpdated.templ +++ b/views/home/settingsUpdated.templ @@ -1,9 +1,5 @@ package home -import "templ-test/views/layout" - templ SettingsUpdated() { - @layout.WithLayout("Settings Updated") { -

You are now free to move about the cabin. Thank you for saving with us!

- } -} \ No newline at end of file +

You are now free to move about the cabin. Thank you for saving with us!

+} From a110f2de73b3a5066a4564cc84eddd75ecffbbce Mon Sep 17 00:00:00 2001 From: James Tombleson Date: Sun, 14 Apr 2024 19:38:15 -0700 Subject: [PATCH 11/12] the base layout now pulls the cookie for darkmode and loads it into the context --- handlers/handler.go | 17 ++++++++++++++++- views/layout/body.templ | 16 ++-------------- views/layout/navbar.templ | 2 +- views/layout/util.go | 4 ++-- 4 files changed, 21 insertions(+), 18 deletions(-) diff --git a/handlers/handler.go b/handlers/handler.go index d3c9f0f..315852b 100644 --- a/handlers/handler.go +++ b/handlers/handler.go @@ -1,6 +1,7 @@ package handlers import ( + "context" "errors" "templ-test/client" "templ-test/domain" @@ -43,7 +44,16 @@ func (h *Handlers) Register(group echo.Group) { func Render(ctx echo.Context, statusCode int, t templ.Component) error { ctx.Response().Writer.WriteHeader(statusCode) ctx.Response().Header().Set(echo.HeaderContentType, echo.MIMETextHTML) - return t.Render(ctx.Request().Context(), ctx.Response().Writer) + + // take the request context and make it a var + request := ctx.Request().Context() + //Check to see if we the echo context has the cookie we are looking for, if so, create a new context based on what we had and add the value + darkMode, err := ctx.Cookie(domain.CookieSettingsDarkMode) + if err == nil { + request = context.WithValue(request, domain.CookieSettingsDarkMode, darkMode.Value) + } + + return t.Render(request, ctx.Response().Writer) } type jwtToken struct { @@ -101,5 +111,10 @@ func GetCookieValues(ctx echo.Context) models.AllCookies { m.RefreshToken = refresh.Value } + darkMode, err := ctx.Cookie(domain.CookieSettingsDarkMode) + if err == nil { + m.DarkMode = darkMode.Value + } + return m } diff --git a/views/layout/body.templ b/views/layout/body.templ index f4eb6e0..e1af390 100644 --- a/views/layout/body.templ +++ b/views/layout/body.templ @@ -1,20 +1,8 @@ package layout templ WithLayout(pageName string) { - - @getHtmlHead() - - @bootstrapNavBar() - @getBodyHeader(pageName) -
- { children... } -
- - -} - -templ Testing(pageName string) { - + + @getHtmlHead() @bootstrapNavBar() diff --git a/views/layout/navbar.templ b/views/layout/navbar.templ index 9101e8b..131d6ca 100644 --- a/views/layout/navbar.templ +++ b/views/layout/navbar.templ @@ -1,7 +1,7 @@ package layout templ bootstrapNavBar() { -