From 4a6f987bf7f9d73e9dd33d225fd2d73e9bf69a88 Mon Sep 17 00:00:00 2001 From: grm Date: Wed, 16 Sep 2026 19:10:13 +0300 Subject: Merge the Layout and Design tabs into one form with a single Save The look and the layout of a blog were split over two tabs that cross-linked each other, and the Layout tab saved every toggle, move and add straight away through a dozen tiny forms. Now one Design tab holds it all, organised by part of the blog (colours & fonts, header, menu, content, side columns, footer, logo & icon) behind a sticky side index, and one Save stores the theme, every module and the menu atomically (BlogStore.SaveDesign). Module settings are edited inline; Discard changes throws the edits away; a validation error shows the form again exactly as it was sent. The image pickers no longer render the whole library four times over: a select of the newest images, and a script-driven panel that fetches the library page by page (GET /files as JSON) with lazy thumbnails. New options: posts per page, site title size, footer alignment. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01Sd8UPWrvyYCLj97JexNw3A --- internal/web/handlers_files.go | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'internal/web/handlers_files.go') diff --git a/internal/web/handlers_files.go b/internal/web/handlers_files.go index 2b68871..576f2ca 100644 --- a/internal/web/handlers_files.go +++ b/internal/web/handlers_files.go @@ -129,6 +129,14 @@ func (s *Server) handleFiles(w http.ResponseWriter, r *http.Request) { s.serverError(w, err) return } + if wantsJSON(r) { // the design page's library panel: one page of files at a time + files := []map[string]string{} + for _, f := range d["files"].([]store.File) { + files = append(files, map[string]string{"id": f.ID.String(), "filename": f.Filename}) + } + writeJSON(w, http.StatusOK, map[string]any{"files": files, "page": d["pageNum"], "last": d["lastPage"]}) + return + } s.render(w, r, "dashboard/files.html", d) } -- cgit v1.2.3