diff --git a/internal/admin/dashboard/dashboard.go b/internal/admin/dashboard/dashboard.go index 8178f66e..5e3c83d4 100644 --- a/internal/admin/dashboard/dashboard.go +++ b/internal/admin/dashboard/dashboard.go @@ -13,6 +13,7 @@ import ( "strings" "gomodel/config" + "gomodel/internal/version" "github.com/labstack/echo/v5" ) @@ -66,12 +67,13 @@ func NewWithBasePath(basePath string) (*Handler, error) { type templateData struct { BasePath string + Version string } // Index serves GET /admin/dashboard — the main dashboard page. func (h *Handler) Index(c *echo.Context) error { var buf bytes.Buffer - if err := h.indexTmpl.ExecuteTemplate(&buf, "layout", templateData{BasePath: h.basePath}); err != nil { + if err := h.indexTmpl.ExecuteTemplate(&buf, "layout", templateData{BasePath: h.basePath, Version: version.Info()}); err != nil { slog.Error("failed to render admin dashboard", "path", c.Request().URL.Path, "error", err) return err } @@ -113,8 +115,8 @@ func assetURL(basePath, assetPath string, versions map[string]string) string { return config.JoinBasePath(basePath, "/admin/static/") } urlPath := config.JoinBasePath(basePath, "/admin/static/"+normalizedPath) - if version := versions[normalizedPath]; version != "" { - return urlPath + "?v=" + version + if v := versions[normalizedPath]; v != "" { + return urlPath + "?v=" + v } return urlPath } diff --git a/internal/admin/dashboard/dashboard_test.go b/internal/admin/dashboard/dashboard_test.go index 8eaa43ba..2d427fb7 100644 --- a/internal/admin/dashboard/dashboard_test.go +++ b/internal/admin/dashboard/dashboard_test.go @@ -63,6 +63,12 @@ func TestIndex_ReturnsHTML(t *testing.T) { if !regexp.MustCompile(`/admin/static/css/dashboard\.css\?v=[0-9a-f]+`).MatchString(rec.Body.String()) { t.Errorf("expected versioned dashboard CSS link in page HTML") } + if !strings.Contains(body, "settings-version-footer") { + t.Errorf("expected settings-version-footer element in page HTML") + } + if !strings.Contains(body, "gomodel ") { + t.Errorf("expected gomodel version string in page HTML") + } } func TestIndex_UsesBasePathForGeneratedURLs(t *testing.T) { diff --git a/internal/admin/dashboard/static/css/dashboard.css b/internal/admin/dashboard/static/css/dashboard.css index e12f302b..0005e8a2 100644 --- a/internal/admin/dashboard/static/css/dashboard.css +++ b/internal/admin/dashboard/static/css/dashboard.css @@ -3414,6 +3414,13 @@ body.conversation-drawer-open { border-top: 1px solid var(--border); } +.settings-version-footer { + margin-top: 24px; + color: var(--text-muted); + font-size: 12px; + text-align: right; +} + .settings-refresh-section h3 { font-size: 18px; } diff --git a/internal/admin/dashboard/templates/page-settings.html b/internal/admin/dashboard/templates/page-settings.html index 84932dea..efc71c1c 100644 --- a/internal/admin/dashboard/templates/page-settings.html +++ b/internal/admin/dashboard/templates/page-settings.html @@ -245,6 +245,8 @@