From 98c7d6f5785182117b9fe6ebd6b892f860bc2024 Mon Sep 17 00:00:00 2001 From: Julien Dessaux Date: Thu, 30 Jan 2025 00:19:16 +0100 Subject: feat(webui): bootstrap account settings management with light and dark mode --- pkg/webui/html/base.html | 6 ++++- pkg/webui/html/settings.html | 25 +++++++++++++++++++++ pkg/webui/index.go | 9 ++++++++ pkg/webui/login.go | 7 ++++++ pkg/webui/routes.go | 2 ++ pkg/webui/settings.go | 53 ++++++++++++++++++++++++++++++++++++++++++++ pkg/webui/state.go | 6 ++--- pkg/webui/states.go | 4 ++-- pkg/webui/version.go | 8 +++---- 9 files changed, 110 insertions(+), 10 deletions(-) create mode 100644 pkg/webui/html/settings.html create mode 100644 pkg/webui/settings.go (limited to 'pkg/webui') diff --git a/pkg/webui/html/base.html b/pkg/webui/html/base.html index c0138ac..4ec6565 100644 --- a/pkg/webui/html/base.html +++ b/pkg/webui/html/base.html @@ -16,6 +16,10 @@ home_storage States + + settings + Settings + logout Logout @@ -32,7 +36,7 @@ TFSTATED - {{ .Page.Title }} - + diff --git a/pkg/webui/html/settings.html b/pkg/webui/html/settings.html new file mode 100644 index 0000000..4040b9b --- /dev/null +++ b/pkg/webui/html/settings.html @@ -0,0 +1,25 @@ +{{ define "main" }} +
+
+
+
+ +
+ +
+
+
+{{ end }} diff --git a/pkg/webui/index.go b/pkg/webui/index.go index 89e5ad6..1168098 100644 --- a/pkg/webui/index.go +++ b/pkg/webui/index.go @@ -3,14 +3,23 @@ package webui import ( "fmt" "net/http" + + "git.adyxax.org/adyxax/tfstated/pkg/model" ) type Page struct { + LightMode bool Precedent string Section string Title string } +func makePage(r *http.Request, page *Page) *Page { + settings := r.Context().Value(model.SettingsContextKey{}).(*model.Settings) + page.LightMode = settings.LightMode + return page +} + func handleIndexGET() http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.URL.Path == "/" { diff --git a/pkg/webui/login.go b/pkg/webui/login.go index 6f688c1..18864b2 100644 --- a/pkg/webui/login.go +++ b/pkg/webui/login.go @@ -2,8 +2,10 @@ package webui import ( "context" + "encoding/json" "fmt" "html/template" + "log/slog" "net/http" "regexp" @@ -113,6 +115,11 @@ func loginMiddleware(db *database.DB, requireSession func(http.Handler) http.Han return } ctx := context.WithValue(r.Context(), model.AccountContextKey{}, account) + var settings model.Settings + if err := json.Unmarshal(account.Settings, &settings); err != nil { + slog.Error("failed to unmarshal account settings", "err", err, "accountId", account.Id) + } + ctx = context.WithValue(ctx, model.SettingsContextKey{}, &settings) next.ServeHTTP(w, r.WithContext(ctx)) })) } diff --git a/pkg/webui/routes.go b/pkg/webui/routes.go index 84017dd..e84f33a 100644 --- a/pkg/webui/routes.go +++ b/pkg/webui/routes.go @@ -16,6 +16,8 @@ func addRoutes( mux.Handle("GET /login", requireSession(handleLoginGET())) mux.Handle("POST /login", requireSession(handleLoginPOST(db))) mux.Handle("GET /logout", requireLogin(handleLogoutGET(db))) + mux.Handle("GET /settings", requireLogin(handleSettingsGET(db))) + mux.Handle("POST /settings", requireLogin(handleSettingsPOST(db))) mux.Handle("GET /states", requireLogin(handleStatesGET(db))) mux.Handle("GET /state/{id}", requireLogin(handleStateGET(db))) mux.Handle("GET /static/", cache(http.FileServer(http.FS(staticFS)))) diff --git a/pkg/webui/settings.go b/pkg/webui/settings.go new file mode 100644 index 0000000..eb0910f --- /dev/null +++ b/pkg/webui/settings.go @@ -0,0 +1,53 @@ +package webui + +import ( + "html/template" + "net/http" + + "git.adyxax.org/adyxax/tfstated/pkg/database" + "git.adyxax.org/adyxax/tfstated/pkg/model" +) + +type SettingsPage struct { + Page *Page + Settings *model.Settings +} + +var settingsTemplates = template.Must(template.ParseFS(htmlFS, "html/base.html", "html/settings.html")) + +func handleSettingsGET(db *database.DB) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + settings := r.Context().Value(model.SettingsContextKey{}).(*model.Settings) + render(w, settingsTemplates, http.StatusOK, SettingsPage{ + Page: makePage(r, &Page{Title: "Settings", Section: "settings"}), + Settings: settings, + }) + }) +} + +func handleSettingsPOST(db *database.DB) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if err := r.ParseForm(); err != nil { + errorResponse(w, http.StatusBadRequest, err) + return + } + darkMode := r.FormValue("dark-mode") + settings := model.Settings{ + LightMode: darkMode != "1", + } + account := r.Context().Value(model.AccountContextKey{}).(*model.Account) + err := db.SaveAccountSettings(account, &settings) + if err != nil { + errorResponse(w, http.StatusInternalServerError, err) + return + } + render(w, settingsTemplates, http.StatusOK, SettingsPage{ + Page: &Page{ + LightMode: settings.LightMode, + Title: "Settings", + Section: "settings", + }, + Settings: &settings, + }) + }) +} diff --git a/pkg/webui/state.go b/pkg/webui/state.go index c7a6aaf..141d2d8 100644 --- a/pkg/webui/state.go +++ b/pkg/webui/state.go @@ -13,7 +13,7 @@ var stateTemplate = template.Must(template.ParseFS(htmlFS, "html/base.html", "ht func handleStateGET(db *database.DB) http.Handler { type StatesData struct { - Page + Page *Page State *model.State Usernames map[int]string Versions []model.Version @@ -41,11 +41,11 @@ func handleStateGET(db *database.DB) http.Handler { return } render(w, stateTemplate, http.StatusOK, StatesData{ - Page: Page{ + Page: makePage(r, &Page{ Precedent: "/states", Section: "states", Title: state.Path, - }, + }), State: state, Usernames: usernames, Versions: versions, diff --git a/pkg/webui/states.go b/pkg/webui/states.go index d99d310..a0d16ca 100644 --- a/pkg/webui/states.go +++ b/pkg/webui/states.go @@ -12,7 +12,7 @@ var statesTemplates = template.Must(template.ParseFS(htmlFS, "html/base.html", " func handleStatesGET(db *database.DB) http.Handler { type StatesData struct { - Page + Page *Page States []model.State } return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { @@ -22,7 +22,7 @@ func handleStatesGET(db *database.DB) http.Handler { return } render(w, statesTemplates, http.StatusOK, StatesData{ - Page: Page{Title: "States", Section: "states"}, + Page: makePage(r, &Page{Title: "States", Section: "states"}), States: states, }) }) diff --git a/pkg/webui/version.go b/pkg/webui/version.go index 04c3e6d..2aa1422 100644 --- a/pkg/webui/version.go +++ b/pkg/webui/version.go @@ -14,7 +14,7 @@ var versionTemplate = template.Must(template.ParseFS(htmlFS, "html/base.html", " func handleVersionGET(db *database.DB) http.Handler { type VersionsData struct { - Page + Page *Page Account *model.Account State *model.State Version *model.Version @@ -44,11 +44,11 @@ func handleVersionGET(db *database.DB) http.Handler { } versionData := string(version.Data[:]) render(w, versionTemplate, http.StatusOK, VersionsData{ - Page: Page{ + Page: makePage(r, &Page{ Precedent: fmt.Sprintf("/state/%d", state.Id), - Section: "versions", + Section: "states", Title: state.Path, - }, + }), Account: account, State: state, Version: version, -- cgit v1.2.3