fix(admin): wire up default timezone setting in admin settings page
The admin settings timezone dropdown was incomplete: it had no pre-selection of the current value, was missing consistent styling, and the form submission did not persist timezone changes. Changes: - frontend.go: load default_timezone from system_settings into the systemConfig map passed to the template - admin_settings.templ: match card styling used by the Base URL section; pre-select current timezone with selected?= attribute - sidecar.go: handle default_timezone in UpdateSystemConfiguration by writing to system_settings table instead of system_config; update HTMX response to include timezone section with current value - Add selectedAttr() helper for HTMX HTML string response
This commit is contained in:
@@ -388,6 +388,23 @@ func (h *SidecarHandler) UpdateSystemConfiguration(c *echo.Context) error {
|
|||||||
|
|
||||||
// Update each config value
|
// Update each config value
|
||||||
for key, value := range req {
|
for key, value := range req {
|
||||||
|
if key == "default_timezone" {
|
||||||
|
if _, err := time.LoadLocation(value); err != nil {
|
||||||
|
return c.JSON(http.StatusBadRequest, map[string]string{
|
||||||
|
"error": "invalid timezone",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
err := h.db.UpdateSystemSetting(ctx, database.UpdateSystemSettingParams{
|
||||||
|
SettingKey: "default_timezone",
|
||||||
|
SettingValue: value,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return c.JSON(http.StatusInternalServerError, map[string]string{
|
||||||
|
"error": "failed to update default timezone",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
_, err := h.db.SetSystemConfig(ctx, database.SetSystemConfigParams{
|
_, err := h.db.SetSystemConfig(ctx, database.SetSystemConfigParams{
|
||||||
Key: key,
|
Key: key,
|
||||||
Value: value,
|
Value: value,
|
||||||
@@ -408,6 +425,12 @@ func (h *SidecarHandler) UpdateSystemConfiguration(c *echo.Context) error {
|
|||||||
return c.HTML(http.StatusInternalServerError, `<div class="text-red-500">Failed to fetch updated configuration</div>`)
|
return c.HTML(http.StatusInternalServerError, `<div class="text-red-500">Failed to fetch updated configuration</div>`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
defaultTimezone := "UTC"
|
||||||
|
tz, err := h.db.GetSystemTimezone(ctx)
|
||||||
|
if err == nil && tz != "" {
|
||||||
|
defaultTimezone = tz
|
||||||
|
}
|
||||||
|
|
||||||
// Render success message with updated form
|
// Render success message with updated form
|
||||||
return c.HTML(http.StatusOK, fmt.Sprintf(`
|
return c.HTML(http.StatusOK, fmt.Sprintf(`
|
||||||
<div class="mb-4 p-4 rounded-lg" style="background-color: var(--bg-secondary); border: 1px solid var(--accent);">
|
<div class="mb-4 p-4 rounded-lg" style="background-color: var(--bg-secondary); border: 1px solid var(--accent);">
|
||||||
@@ -437,6 +460,28 @@ func (h *SidecarHandler) UpdateSystemConfiguration(c *echo.Context) error {
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="mt-8 card p-6 rounded-lg border" style="background-color: var(--bg-secondary); border-color: var(--border);">
|
||||||
|
<h3 class="text-xl font-semibold mb-6" style="color: var(--text-primary)">System Defaults</h3>
|
||||||
|
<div>
|
||||||
|
<label class="block text-sm font-medium mb-2" style="color: var(--text-primary)">Default Timezone</label>
|
||||||
|
<select name="default_timezone" id="default_timezone" class="w-full px-4 py-2 rounded-lg border" style="background-color: var(--bg-primary); color: var(--text-primary); border-color: var(--border);">
|
||||||
|
<option value="UTC"%s>UTC (Coordinated Universal Time)</option>
|
||||||
|
<option value="America/New_York"%s>Eastern Time</option>
|
||||||
|
<option value="America/Chicago"%s>Central Time</option>
|
||||||
|
<option value="America/Denver"%s>Mountain Time</option>
|
||||||
|
<option value="America/Los_Angeles"%s>Pacific Time</option>
|
||||||
|
<option value="America/Phoenix"%s>Mountain Time (no DST)</option>
|
||||||
|
<option value="America/Anchorage"%s>Alaska Time</option>
|
||||||
|
<option value="Pacific/Honolulu"%s>Hawaii Time</option>
|
||||||
|
</select>
|
||||||
|
<p class="text-sm mt-1" style="color: var(--text-secondary)">Default timezone for users who haven't set their own.</p>
|
||||||
|
</div>
|
||||||
|
<div class="mt-6 flex justify-end">
|
||||||
|
<button type="submit" class="btn-primary px-6 py-2 rounded-lg font-medium">
|
||||||
|
Save Settings
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<div class="mt-8 card p-6 rounded-lg border" style="background-color: var(--bg-secondary); border-color: var(--border);">
|
<div class="mt-8 card p-6 rounded-lg border" style="background-color: var(--bg-secondary); border-color: var(--border);">
|
||||||
@@ -447,7 +492,16 @@ func (h *SidecarHandler) UpdateSystemConfiguration(c *echo.Context) error {
|
|||||||
<p><strong>Device Sync:</strong> %s/api/sync</p>
|
<p><strong>Device Sync:</strong> %s/api/sync</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
`, baseURL.Value, baseURL.Value, baseURL.Value, baseURL.Value))
|
`, 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"),
|
||||||
|
baseURL.Value, baseURL.Value, baseURL.Value))
|
||||||
}
|
}
|
||||||
|
|
||||||
return c.JSON(http.StatusOK, map[string]string{
|
return c.JSON(http.StatusOK, map[string]string{
|
||||||
@@ -477,3 +531,10 @@ func sanitizeAll(s string, old string, new string) string {
|
|||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func selectedAttr(current, value string) string {
|
||||||
|
if current == value {
|
||||||
|
return " selected"
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|||||||
@@ -932,7 +932,13 @@ func registerFrontendRoutes(cfg *Config) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
systemConfig := map[string]string{
|
systemConfig := map[string]string{
|
||||||
"base_url": baseURL,
|
"base_url": baseURL,
|
||||||
|
"default_timezone": "UTC",
|
||||||
|
}
|
||||||
|
|
||||||
|
defaultTimezone, err := cfg.Queries.GetSystemTimezone(c.Request().Context())
|
||||||
|
if err == nil && defaultTimezone != "" {
|
||||||
|
systemConfig["default_timezone"] = defaultTimezone
|
||||||
}
|
}
|
||||||
|
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
|
|||||||
@@ -51,19 +51,27 @@ templ AdminSettings(user User, systemConfig map[string]string, errorMessage stri
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="setting-group">
|
<div class="mt-8 card p-6 rounded-lg border" style="background-color: var(--bg-secondary); border-color: var(--border);">
|
||||||
<h3>System Defaults</h3>
|
<h3 class="text-xl font-semibold mb-6" style="color: var(--text-primary)">System Defaults</h3>
|
||||||
<label for="default_timezone">Default Timezone</label>
|
<div>
|
||||||
<select name="default_timezone" id="default_timezone">
|
<label class="block text-sm font-medium mb-2" style="color: var(--text-primary)">Default Timezone</label>
|
||||||
<option value="UTC">UTC (Coordinated Universal Time)</option>
|
<select
|
||||||
<option value="America/New_York">Eastern Time</option>
|
name="default_timezone"
|
||||||
<option value="America/Chicago">Central Time</option>
|
id="default_timezone"
|
||||||
<option value="America/Denver">Mountain Time</option>
|
class="w-full px-4 py-2 rounded-lg border"
|
||||||
<option value="America/Los_Angeles">Pacific Time</option>
|
style="background-color: var(--bg-primary); color: var(--text-primary); border-color: var(--border);"
|
||||||
<option value="America/Phoenix">Mountain Time (no DST)</option>
|
>
|
||||||
<option value="America/Anchorage">Alaska Time</option>
|
<option value="UTC" selected?={ systemConfig["default_timezone"] == "UTC" }>UTC (Coordinated Universal Time)</option>
|
||||||
<option value="Pacific/Honolulu">Hawaii Time</option>
|
<option value="America/New_York" selected?={ systemConfig["default_timezone"] == "America/New_York" }>Eastern Time</option>
|
||||||
</select>
|
<option value="America/Chicago" selected?={ systemConfig["default_timezone"] == "America/Chicago" }>Central Time</option>
|
||||||
|
<option value="America/Denver" selected?={ systemConfig["default_timezone"] == "America/Denver" }>Mountain Time</option>
|
||||||
|
<option value="America/Los_Angeles" selected?={ systemConfig["default_timezone"] == "America/Los_Angeles" }>Pacific Time</option>
|
||||||
|
<option value="America/Phoenix" selected?={ systemConfig["default_timezone"] == "America/Phoenix" }>Mountain Time (no DST)</option>
|
||||||
|
<option value="America/Anchorage" selected?={ systemConfig["default_timezone"] == "America/Anchorage" }>Alaska Time</option>
|
||||||
|
<option value="Pacific/Honolulu" selected?={ systemConfig["default_timezone"] == "Pacific/Honolulu" }>Hawaii Time</option>
|
||||||
|
</select>
|
||||||
|
<p class="text-sm mt-1" style="color: var(--text-secondary)">Default timezone for users who haven't set their own.</p>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
<div class="mt-8 card p-6 rounded-lg border" style="background-color: var(--bg-secondary); border-color: var(--border);">
|
<div class="mt-8 card p-6 rounded-lg border" style="background-color: var(--bg-secondary); border-color: var(--border);">
|
||||||
|
|||||||
Reference in New Issue
Block a user