From 19a85a3390b8df31a0a8f6517fd699020e5c3571 Mon Sep 17 00:00:00 2001 From: John O'Keefe Date: Wed, 29 Apr 2026 20:47:11 -0400 Subject: [PATCH] feat(ui): expand timezone dropdowns to cover all populated UTC offsets Replaced the 8 US-centric timezone options with 24 entries covering every populated UTC offset worldwide (UTC-10 through UTC+12). Each option is labeled by regional name with UTC offset in parentheses, e.g. 'Central European (UTC+1/+2)'. DST-shifting zones show both standard and daylight offsets. Covers: Hawaii, Alaska, Pacific, Mountain, Mountain-no DST, Central, Eastern, Brasilia, British, Central European, Eastern European, Moscow, Iran, Gulf, Pakistan, India, Bangladesh, Indochina, China, Japan/Korea, Australian Central, Australian Eastern, New Zealand. Backend already validates all IANA zones via time.LoadLocation(), so users with uncommon zones can still set them via the API. Updated in three locations: - templates/profile_form.templ (user profile dropdown) - templates/admin_settings.templ (admin settings dropdown) - internal/handlers/sidecar.go (HTMX save response HTML) --- internal/handlers/sidecar.go | 60 +++++++-- templates/admin_settings.templ | 32 +++-- templates/admin_settings_templ.go | 200 +++++++++++++++++++++++++--- templates/profile_form.templ | 32 +++-- templates/profile_form_templ.go | 214 ++++++++++++++++++++++++++---- 5 files changed, 461 insertions(+), 77 deletions(-) diff --git a/internal/handlers/sidecar.go b/internal/handlers/sidecar.go index 9ba5cf9..9e469ce 100644 --- a/internal/handlers/sidecar.go +++ b/internal/handlers/sidecar.go @@ -465,14 +465,30 @@ func (h *SidecarHandler) UpdateSystemConfiguration(c *echo.Context) error {

Default timezone for users who haven't set their own.

@@ -494,13 +510,29 @@ func (h *SidecarHandler) UpdateSystemConfiguration(c *echo.Context) error { `, baseURL.Value, selectedAttr(defaultTimezone, "UTC"), - selectedAttr(defaultTimezone, "America/New_York"), - selectedAttr(defaultTimezone, "America/Chicago"), - selectedAttr(defaultTimezone, "America/Denver"), - selectedAttr(defaultTimezone, "America/Los_Angeles"), - selectedAttr(defaultTimezone, "America/Phoenix"), - selectedAttr(defaultTimezone, "America/Anchorage"), selectedAttr(defaultTimezone, "Pacific/Honolulu"), + selectedAttr(defaultTimezone, "America/Anchorage"), + selectedAttr(defaultTimezone, "America/Los_Angeles"), + selectedAttr(defaultTimezone, "America/Denver"), + selectedAttr(defaultTimezone, "America/Phoenix"), + selectedAttr(defaultTimezone, "America/Chicago"), + selectedAttr(defaultTimezone, "America/New_York"), + selectedAttr(defaultTimezone, "America/Sao_Paulo"), + selectedAttr(defaultTimezone, "Europe/London"), + selectedAttr(defaultTimezone, "Europe/Paris"), + selectedAttr(defaultTimezone, "Europe/Helsinki"), + selectedAttr(defaultTimezone, "Europe/Moscow"), + selectedAttr(defaultTimezone, "Asia/Tehran"), + selectedAttr(defaultTimezone, "Asia/Dubai"), + selectedAttr(defaultTimezone, "Asia/Karachi"), + selectedAttr(defaultTimezone, "Asia/Kolkata"), + selectedAttr(defaultTimezone, "Asia/Dhaka"), + selectedAttr(defaultTimezone, "Asia/Bangkok"), + selectedAttr(defaultTimezone, "Asia/Shanghai"), + selectedAttr(defaultTimezone, "Asia/Tokyo"), + selectedAttr(defaultTimezone, "Australia/Darwin"), + selectedAttr(defaultTimezone, "Australia/Sydney"), + selectedAttr(defaultTimezone, "Pacific/Auckland"), baseURL.Value, baseURL.Value, baseURL.Value)) } diff --git a/templates/admin_settings.templ b/templates/admin_settings.templ index f9d254c..feacf7d 100644 --- a/templates/admin_settings.templ +++ b/templates/admin_settings.templ @@ -61,14 +61,30 @@ templ AdminSettings(user User, systemConfig map[string]string, errorMessage stri class="w-full px-4 py-2 rounded-lg border" style="background-color: var(--bg-primary); color: var(--text-primary); border-color: var(--border);" > - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + +

Default timezone for users who haven't set their own.

diff --git a/templates/admin_settings_templ.go b/templates/admin_settings_templ.go index 6afc9e6..a41d2b4 100644 --- a/templates/admin_settings_templ.go +++ b/templates/admin_settings_templ.go @@ -91,47 +91,47 @@ func AdminSettings(user User, systemConfig map[string]string, errorMessage strin return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, ">UTC (Coordinated Universal Time)

Default timezone for users who haven't set their own.

URL Paths

OPDS: ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 23, ">Eastern (UTC-5/-4)

Default timezone for users who haven't set their own.

URL Paths

OPDS: ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var4 string templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(systemConfig["base_url"]) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/admin_settings.templ`, Line: 80, Col: 60} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/admin_settings.templ`, Line: 96, Col: 60} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 24, "/opds

API: ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 56, "/opds

API: ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var5 string templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(systemConfig["base_url"]) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/admin_settings.templ`, Line: 81, Col: 59} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/admin_settings.templ`, Line: 97, Col: 59} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 25, "/api

Device Sync: ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 57, "/api

Device Sync: ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var6 string templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(systemConfig["base_url"]) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/admin_settings.templ`, Line: 82, Col: 67} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/admin_settings.templ`, Line: 98, Col: 67} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 26, "/api/sync

") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 58, "/api/sync

") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } diff --git a/templates/profile_form.templ b/templates/profile_form.templ index b9a8eb9..fe00f1e 100644 --- a/templates/profile_form.templ +++ b/templates/profile_form.templ @@ -77,14 +77,30 @@ templ ProfileForm(user User, actionURL string, requireCurrentPassword bool, show class="w-full px-3 py-2 border rounded" style="background-color: var(--bg-primary); color: var(--text-primary); border-color: var(--border);" > - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + if showRoleField { diff --git a/templates/profile_form_templ.go b/templates/profile_form_templ.go index 65a6d66..f6aae65 100644 --- a/templates/profile_form_templ.go +++ b/templates/profile_form_templ.go @@ -174,47 +174,47 @@ func ProfileForm(user User, actionURL string, requireCurrentPassword bool, showR return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 22, ">UTC (Coordinated Universal Time) ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 36, ">Eastern (UTC-5/-4) ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } if showRoleField { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 37, "
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 73, ">Admin") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 42, "

Change Password

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

Change Password

") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } if requireCurrentPassword { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 43, "
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 75, "
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } else { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 44, "

As an admin, you can change this user's password without knowing their current password.

") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 77, "\" hx-headers='{\"Authorization\": \"Bearer \" + localStorage.getItem(\"token\")}' hx-target=\"#password-result\" hx-swap=\"innerHTML\" hx-include=\"closest form\" class=\"px-4 py-2 rounded\" style=\"background-color: var(--accent); color: white;\">Reset Password
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 46, "
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 78, "
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } if showCancelButton { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 47, " ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 79, " ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 48, "
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 80, "
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err }