From 616aa3a934951260d5daa81ab3d0f93fbc94ebee Mon Sep 17 00:00:00 2001 From: grm Date: Thu, 17 Sep 2026 18:54:33 +0300 Subject: Keep a chosen image older than the picker's list, and the layout on a rejected save MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The image picker's select lists the newest recentImages library images and was meant to add the chosen one when it is older than those, but the fallback option was gated on the filename being unknown, which designData makes known: the option never rendered, the browser selected "None", and every save of the design form cleared a logo or favicon older than the 48 newest images (the post form's featured image the same way). The partial now checks whether the choice is listed and otherwise emits it, named. handleDesign ran the uploads before parsing the module and menu rows and gave up at the first problem, so a rejected upload rendered the form without any rows — and, since a missing row means delete, the next save would have wiped the layout and menu. Everything is read before the first problem is reported. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01Sd8UPWrvyYCLj97JexNw3A --- internal/web/web_test.go | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) (limited to 'internal/web/web_test.go') diff --git a/internal/web/web_test.go b/internal/web/web_test.go index b707339..fcd1e41 100644 --- a/internal/web/web_test.go +++ b/internal/web/web_test.go @@ -691,3 +691,39 @@ func TestPostSummary(t *testing.T) { t.Error("summary: expected a cut") } } + +// A chosen image older than the recent ones the picker lists must still be +// the select's selected option, else saving the form clears it (the logo of +// a blog with more than recentImages images vanished on every save). +func TestImagePickKeepsOlderChoice(t *testing.T) { + tpl, err := newTemplates(false).get("en", "dashboard/design.html") + if err != nil { + t.Fatal(err) + } + recent := uuid.New() + old := uuid.New() + for _, tc := range []struct { + name string + names map[string]string + want string + }{ + {"known name", map[string]string{recent.String(): "new.png", old.String(): "logo.png"}, ``}, + {"unknown name", map[string]string{recent.String(): "new.png"}, ``}, + } { + var b strings.Builder + err := tpl.ExecuteTemplate(&b, "imagepick", map[string]any{ + "name": "logo", "current": old.String(), "sub": "x", "label": "Logo", + "images": []store.File{{ID: recent, Filename: "new.png"}}, "names": tc.names, + }) + if err != nil { + t.Fatal(err) + } + out := b.String() + if !strings.Contains(out, tc.want) { + t.Errorf("%s: the chosen image is not the selected option:\n%s", tc.name, out) + } + if strings.Contains(out, `