From 18d6c563a5b6babdc3b4f837c3245ecedc6ee76c Mon Sep 17 00:00:00 2001 From: Tine Date: Mon, 12 Feb 2024 14:20:38 +0100 Subject: [PATCH] feat: settings navigation and mocked healthchecks in index --- cmd/server/main.go | 3 +- internal/handlers/handlers.go | 4 +- internal/handlers/index.go | 45 ++++++- internal/handlers/settings.go | 47 +++++++- web/static/css/main.css | 8 ++ web/static/css/tailwind.css | 80 +++++-------- web/templates/components/settings.tmpl | 28 +++++ web/templates/pages/index.tmpl | 111 +++--------------- web/templates/pages/settings.tmpl | 24 ---- .../pages/settings_healthchecks.tmpl | 5 + web/templates/pages/settings_overview.tmpl | 3 + 11 files changed, 175 insertions(+), 183 deletions(-) create mode 100644 web/templates/components/settings.tmpl delete mode 100644 web/templates/pages/settings.tmpl create mode 100644 web/templates/pages/settings_healthchecks.tmpl create mode 100644 web/templates/pages/settings_overview.tmpl diff --git a/cmd/server/main.go b/cmd/server/main.go index d0b8716..490de2e 100644 --- a/cmd/server/main.go +++ b/cmd/server/main.go @@ -46,7 +46,8 @@ func main() { r.HandleFunc("/", h.Index).Methods("GET") // Authenticated routes - r.HandleFunc("/settings", h.Authenticated(h.Settings)).Methods("GET") + r.HandleFunc("/settings", h.Authenticated(h.SettingsOverviewGET)).Methods("GET") + r.HandleFunc("/settings/healthchecks", h.Authenticated(h.SettingsHealthchecksGET)).Methods("GET") // OAuth2 r.HandleFunc("/oauth2/login", h.OAuth2LoginGET).Methods("GET") diff --git a/internal/handlers/handlers.go b/internal/handlers/handlers.go index c673ecf..67cb443 100644 --- a/internal/handlers/handlers.go +++ b/internal/handlers/handlers.go @@ -14,8 +14,8 @@ var Pages = []*components.Page{ {Path: "/settings", Title: "Settings"}, } -func GetPageByTitle(title string) *components.Page { - for _, p := range Pages { +func GetPageByTitle(pages []*components.Page, title string) *components.Page { + for _, p := range pages { if p.Title == title { return p } diff --git a/internal/handlers/index.go b/internal/handlers/index.go index 0dd8312..cdb316b 100644 --- a/internal/handlers/index.go +++ b/internal/handlers/index.go @@ -1,6 +1,7 @@ package handlers import ( + "math/rand" "net/http" "text/template" @@ -8,6 +9,36 @@ import ( "code.tjo.space/mentos1386/zdravko/web/templates/components" ) +type IndexData struct { + *components.Base + HealthChecks []*HealthCheck +} + +type HealthCheck struct { + Domain string + Healthy bool + Uptime string + History []bool +} + +func newMockHealthCheck(domain string) *HealthCheck { + randBool := func() bool { + return rand.Intn(2) == 1 + } + + var history []bool + for i := 0; i < 90; i++ { + history = append(history, randBool()) + } + + return &HealthCheck{ + Domain: domain, + Healthy: randBool(), + Uptime: "100", + History: history, + } +} + func (h *BaseHandler) Index(w http.ResponseWriter, r *http.Request) { ts, err := template.ParseFS(templates.Templates, "components/base.tmpl", @@ -18,9 +49,17 @@ func (h *BaseHandler) Index(w http.ResponseWriter, r *http.Request) { return } - err = ts.ExecuteTemplate(w, "base", &components.Base{ - Page: GetPageByTitle("Status"), - Pages: Pages, + err = ts.ExecuteTemplate(w, "base", &IndexData{ + Base: &components.Base{ + Page: GetPageByTitle(Pages, "Status"), + Pages: Pages, + }, + HealthChecks: []*HealthCheck{ + newMockHealthCheck("example.com"), + newMockHealthCheck("example.org"), + newMockHealthCheck("example.net"), + newMockHealthCheck("foo.example.net"), + }, }) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) diff --git a/internal/handlers/settings.go b/internal/handlers/settings.go index 5eb9c7d..52a8626 100644 --- a/internal/handlers/settings.go +++ b/internal/handlers/settings.go @@ -10,13 +10,23 @@ import ( type Settings struct { *components.Base - User *AuthenticatedUser + SettingsPage *components.Page + SettingsPages []*components.Page + User *AuthenticatedUser } -func (h *BaseHandler) Settings(w http.ResponseWriter, r *http.Request, user *AuthenticatedUser) { +var SettingsPages = []*components.Page{ + {Path: "/settings", Title: "Overview"}, + {Path: "/settings/healthchecks", Title: "Healthchecks"}, + {Path: "/settings/workers", Title: "Workers"}, + {Path: "/oauth2/logout", Title: "Logout"}, +} + +func (h *BaseHandler) SettingsOverviewGET(w http.ResponseWriter, r *http.Request, user *AuthenticatedUser) { ts, err := template.ParseFS(templates.Templates, "components/base.tmpl", - "pages/settings.tmpl", + "components/settings.tmpl", + "pages/settings_overview.tmpl", ) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) @@ -25,10 +35,37 @@ func (h *BaseHandler) Settings(w http.ResponseWriter, r *http.Request, user *Aut err = ts.ExecuteTemplate(w, "base", &Settings{ Base: &components.Base{ - Page: GetPageByTitle("Settings"), + Page: GetPageByTitle(Pages, "Settings"), Pages: Pages, }, - User: user, + SettingsPage: GetPageByTitle(SettingsPages, "Overview"), + SettingsPages: SettingsPages, + User: user, + }) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + } +} + +func (h *BaseHandler) SettingsHealthchecksGET(w http.ResponseWriter, r *http.Request, user *AuthenticatedUser) { + ts, err := template.ParseFS(templates.Templates, + "components/base.tmpl", + "components/settings.tmpl", + "pages/settings_healthchecks.tmpl", + ) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + + err = ts.ExecuteTemplate(w, "base", &Settings{ + Base: &components.Base{ + Page: GetPageByTitle(Pages, "Settings"), + Pages: Pages, + }, + SettingsPage: GetPageByTitle(SettingsPages, "Healthchecks"), + SettingsPages: SettingsPages, + User: user, }) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) diff --git a/web/static/css/main.css b/web/static/css/main.css index 9c0cae0..992ef74 100644 --- a/web/static/css/main.css +++ b/web/static/css/main.css @@ -44,3 +44,11 @@ .sidebar a.active { @apply bg-blue-700 text-white; } + +.healthchecks { + @apply grid justify-items-stretch justify-stretch items-center mt-20 bg-gray-200 shadow-inner p-5 rounded-lg; +} + +.healthchecks > div:not(:last-child) { + @apply mb-3; +} diff --git a/web/static/css/tailwind.css b/web/static/css/tailwind.css index 9f7ee66..7934c9d 100644 --- a/web/static/css/tailwind.css +++ b/web/static/css/tailwind.css @@ -603,8 +603,8 @@ video { margin-bottom: 1rem; } -.mr-1 { - margin-right: 0.25rem; +.me-2 { + margin-inline-end: 0.5rem; } .mt-10 { @@ -631,8 +631,8 @@ video { height: 5rem; } -.h-5 { - height: 1.25rem; +.h-3 { + height: 0.75rem; } .h-8 { @@ -643,8 +643,8 @@ video { width: 5rem; } -.w-5 { - width: 1.25rem; +.w-3 { + width: 0.75rem; } .max-w-screen-md { @@ -663,8 +663,8 @@ video { grid-template-columns: repeat(2, minmax(0, 1fr)); } -.grid-cols-\[1fr_auto\] { - grid-template-columns: 1fr auto; +.grid-cols-\[1fr_100\%\] { + grid-template-columns: 1fr 100%; } .flex-col { @@ -679,14 +679,6 @@ video { justify-content: center; } -.justify-stretch { - justify-content: stretch; -} - -.justify-items-stretch { - justify-items: stretch; -} - .gap-2 { gap: 0.5rem; } @@ -729,30 +721,16 @@ video { border-radius: 9999px; } -.rounded-lg { - border-radius: 0.5rem; -} - .bg-gray-100 { --tw-bg-opacity: 1; background-color: rgb(243 244 246 / var(--tw-bg-opacity)); } -.bg-gray-200 { - --tw-bg-opacity: 1; - background-color: rgb(229 231 235 / var(--tw-bg-opacity)); -} - .bg-green-300 { --tw-bg-opacity: 1; background-color: rgb(134 239 172 / var(--tw-bg-opacity)); } -.bg-green-400 { - --tw-bg-opacity: 1; - background-color: rgb(74 222 128 / var(--tw-bg-opacity)); -} - .bg-green-500 { --tw-bg-opacity: 1; background-color: rgb(34 197 94 / var(--tw-bg-opacity)); @@ -768,22 +746,10 @@ video { background-color: rgb(239 68 68 / var(--tw-bg-opacity)); } -.stroke-\[3\] { - stroke-width: 3; -} - -.p-1 { - padding: 0.25rem; -} - .p-4 { padding: 1rem; } -.p-5 { - padding: 1.25rem; -} - .text-center { text-align: center; } @@ -798,11 +764,6 @@ video { line-height: 1.25rem; } -.text-xl { - font-size: 1.25rem; - line-height: 1.75rem; -} - .text-xs { font-size: 0.75rem; line-height: 1rem; @@ -836,12 +797,6 @@ video { text-decoration-line: underline; } -.shadow-inner { - --tw-shadow: inset 0 2px 4px 0 rgb(0 0 0 / 0.05); - --tw-shadow-colored: inset 0 2px 4px 0 var(--tw-shadow-color); - box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); -} - .btn { border-radius: 0.25rem; padding-top: 0.5rem; @@ -940,6 +895,25 @@ video { color: rgb(255 255 255 / var(--tw-text-opacity)); } +.healthchecks { + margin-top: 5rem; + display: grid; + align-items: center; + justify-content: stretch; + justify-items: stretch; + border-radius: 0.5rem; + --tw-bg-opacity: 1; + background-color: rgb(229 231 235 / var(--tw-bg-opacity)); + padding: 1.25rem; + --tw-shadow: inset 0 2px 4px 0 rgb(0 0 0 / 0.05); + --tw-shadow-colored: inset 0 2px 4px 0 var(--tw-shadow-color); + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); +} + +.healthchecks > div:not(:last-child) { + margin-bottom: 0.75rem; +} + .hover\:bg-green-700:hover { --tw-bg-opacity: 1; background-color: rgb(21 128 61 / var(--tw-bg-opacity)); diff --git a/web/templates/components/settings.tmpl b/web/templates/components/settings.tmpl new file mode 100644 index 0000000..09e9ff0 --- /dev/null +++ b/web/templates/components/settings.tmpl @@ -0,0 +1,28 @@ +{{define "main"}} +{{ $title := "" }} +{{ $path := "" }} +{{ if ne nil .SettingsPage }} + {{ $title = .SettingsPage.Title }} + {{ $path = .SettingsPage.Path }} +{{ end }} + +
+ + +
+ {{template "settings" .}} +
+
+{{end}} diff --git a/web/templates/pages/index.tmpl b/web/templates/pages/index.tmpl index 9b2cd68..e395316 100644 --- a/web/templates/pages/index.tmpl +++ b/web/templates/pages/index.tmpl @@ -1,5 +1,3 @@ -{{define "title"}}Status{{end}} - {{define "main"}}
@@ -11,107 +9,30 @@

Degraded performance

Last updated on Feb 10 at 10:55am UTC

-
+
+ {{ range .HealthChecks }}
- -

foo.bar

+ {{ if .Healthy }} + + {{ else }} + + {{ end }} +

{{ .Domain }}

-
69.420% uptime
+
{{ .Uptime }}% uptime
+ {{ range .History }} + {{ if . }}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ {{ else }}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ {{ end }} + {{ end }} +
90 days ago
Today
+ {{ end }}
{{end}} diff --git a/web/templates/pages/settings.tmpl b/web/templates/pages/settings.tmpl deleted file mode 100644 index 9cc302f..0000000 --- a/web/templates/pages/settings.tmpl +++ /dev/null @@ -1,24 +0,0 @@ -{{define "main"}} -
- - -
-

Hi {{.User.Email}}!

-

Your id is {{.User.ID}}.

-

Your access expieres at {{.User.OAuth2Expiry}}.

-
-
-{{end}} diff --git a/web/templates/pages/settings_healthchecks.tmpl b/web/templates/pages/settings_healthchecks.tmpl new file mode 100644 index 0000000..76fba81 --- /dev/null +++ b/web/templates/pages/settings_healthchecks.tmpl @@ -0,0 +1,5 @@ +{{define "settings"}} +

Hello, {{.User.Email}}

+ +

Imagine you see a list of healthchecks and how to configure them.

+{{end}} diff --git a/web/templates/pages/settings_overview.tmpl b/web/templates/pages/settings_overview.tmpl new file mode 100644 index 0000000..de3129d --- /dev/null +++ b/web/templates/pages/settings_overview.tmpl @@ -0,0 +1,3 @@ +{{define "settings"}} +

Hello, {{.User.Email}}

+{{end}}