fix(web): field-mapping + fragile-hx-vals sweep across profile and library surfaces
Field-by-field audit of the profile surface (set → save → reopen → read back, driven through the emulator browser via CDP): - getTemplateUserWithTheme (every SSR page + the /profile self-edit form) never mapped FirstName/LastName/CreatedAt — stored names rendered as empty inputs. Now mapped (timezone was already mapped). - Admin profile-modal Timezone mapping fixed earlier this round held: all seven fields verified set → 200 + HX-Refresh → reopen → correct values, DB cross-checked. - Role promote/demote via the card select verified against the DB (the PUT answers HX-Refresh, so the page reload shows the new role). - Admin password reset verified end-to-end: new password logs in, old one 401s, original restored. - admin_library folder-remove hx-vals was string-concatenated JSON — a folder path containing a quote or backslash made it invalid and the remove button silently died under htmx 2 (the same class as the profile-save bug). Now built with json.Marshal behind the js: prefix. Verified the generated attribute on the live page. - Other hx-vals/hx-headers sites audited: constants and uuids only (safe charset), left alone.
This commit is contained in:
1 parent
dc353b0f3f
commit
320f31086d
4 files changed
+24
-10
No files matched your search
@@ -52,13 +52,16 @@ func getTemplateUserWithTheme(c *echo.Context, cfg *Config) (templates.User, err
|
|||||||
}
|
}
|
||||||
|
|
||||||
return templates.User{
|
return templates.User{
|
||||||
ID: userID,
|
ID: userID,
|
||||||
Email: userEmail,
|
Email: userEmail,
|
||||||
Username: userUsername,
|
Username: userUsername,
|
||||||
Role: userRole,
|
Role: userRole,
|
||||||
Theme: userTheme,
|
Theme: userTheme,
|
||||||
Token: token,
|
Token: token,
|
||||||
Timezone: userTimezone,
|
Timezone: userTimezone,
|
||||||
|
FirstName: getText(userDB.FirstName),
|
||||||
|
LastName: getText(userDB.LastName),
|
||||||
|
CreatedAt: userDB.CreatedAt.Time,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -307,7 +307,7 @@ templ LibraryPanel(user User, libraryID string, library LibraryData, folders []F
|
|||||||
<button
|
<button
|
||||||
class="icon-btn h-7 w-7 shrink-0"
|
class="icon-btn h-7 w-7 shrink-0"
|
||||||
hx-delete={ "/admin/library/" + libraryID + "/folders" }
|
hx-delete={ "/admin/library/" + libraryID + "/folders" }
|
||||||
hx-vals={ `{"folder_path": "` + folder.FolderPath + `"}` }
|
hx-vals={ hxValsFolderDelete(folder.FolderPath) }
|
||||||
hx-target={ "#library-panel-" + libraryID }
|
hx-target={ "#library-panel-" + libraryID }
|
||||||
hx-swap="innerHTML"
|
hx-swap="innerHTML"
|
||||||
hx-confirm="Remove this folder from the library?"
|
hx-confirm="Remove this folder from the library?"
|
||||||
|
|||||||
@@ -432,9 +432,9 @@ func LibraryPanel(user User, libraryID string, library LibraryData, folders []Fo
|
|||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
var templ_7745c5c3_Var14 string
|
var templ_7745c5c3_Var14 string
|
||||||
templ_7745c5c3_Var14, templ_7745c5c3_Err = templ.ResolveAttributeValue(`{"folder_path": "` + folder.FolderPath + `"}`)
|
templ_7745c5c3_Var14, templ_7745c5c3_Err = templ.ResolveAttributeValue(hxValsFolderDelete(folder.FolderPath))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `admin_library.templ`, Line: 310, Col: 64}
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `admin_library.templ`, Line: 310, Col: 55}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var14)
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var14)
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
|
|||||||
@@ -339,3 +339,14 @@ func GroupTunableSettings(entries []SettingEntry) (live, restart []SettingGroup)
|
|||||||
}
|
}
|
||||||
return liveGroups, restartGroups
|
return liveGroups, restartGroups
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// hxValsFolderDelete builds the hx-vals attribute for removing a library
|
||||||
|
// folder: htmx 2 requires valid JSON (or a js: expression) — string
|
||||||
|
// concatenation broke on paths containing quotes or backslashes.
|
||||||
|
func hxValsFolderDelete(folderPath string) string {
|
||||||
|
b, err := json.Marshal(map[string]string{"folder_path": folderPath})
|
||||||
|
if err != nil {
|
||||||
|
return `js:{"folder_path": ""}`
|
||||||
|
}
|
||||||
|
return "js:" + string(b)
|
||||||
|
}
|
||||||
Reference in new issue
Block a user