+
{{ end }}
@@ -267,11 +273,6 @@
@@ -340,6 +341,7 @@
let ownerList = document.querySelector("#owner_list");
let ownerTemplate = makeTemplateCloner("owner_row");
let ownerPreviewTemplate = makeTemplateCloner("owner_preview");
+ let ownersPreviewContainer = document.querySelector("#owners_preview");
addOwnerInput.addEventListener("keypress", function(ev) {
if (ev.which == 13) {
@@ -385,7 +387,7 @@
let result = xhr.response;
if (result) {
if (result.found) {
- addOwner(result.canonical);
+ addOwner(result.username, result.name, result.avatarUrl);
addOwnerInput.value = "";
} else {
ownersError.textContent = "Username not found";
@@ -417,21 +419,41 @@
updateAddOwnerStyles();
}
- function addOwner(username) {
+ function addOwner(username, bestName, avatarUrl) {
let ownerEl = ownerTemplate();
ownerEl.input.value = username;
- ownerEl.name.textContent = username;
+ ownerEl.name.textContent = bestName;
+ ownerEl.title = username;
+ ownerEl.avatar.src = avatarUrl;
ownerList.appendChild(ownerEl.root);
updateAddOwnerStyles();
+ updateOwnersPreview();
}
ownerList.addEventListener("click", function(ev) {
- if (ev.target.classList.contains("remove_owner")) {
- ev.target.parentElement.remove();
+ if (ev.target.closest(".remove_owner")) {
+ ev.target.closest(".owner_row").remove();
}
updateAddOwnerStyles();
+ updateOwnersPreview();
});
+ function updateOwnersPreview() {
+ let ownerEls = ownerList.querySelectorAll(".owner_row");
+ ownersPreviewContainer.innerHTML = "";
+ for (let i = 0; i < ownerEls.length; ++i) {
+ let avatarUrl = ownerEls[i].querySelector("img").src;
+ let name = ownerEls[i].querySelector("span").textContent;
+ let previewEl = ownerPreviewTemplate();
+ previewEl.avatar.src = avatarUrl;
+ previewEl.name.textContent = name;
+ ownersPreviewContainer.appendChild(previewEl.root);
+ }
+
+ }
+
+ updateOwnersPreview();
+
//////////////////////////////
// Logo / header management //
//////////////////////////////
diff --git a/src/website/api.go b/src/website/api.go
index 80645159..09bd3af9 100644
--- a/src/website/api.go
+++ b/src/website/api.go
@@ -8,50 +8,34 @@ import (
"strings"
"git.handmade.network/hmn/hmn/src/db"
+ "git.handmade.network/hmn/hmn/src/hmndata"
"git.handmade.network/hmn/hmn/src/models"
"git.handmade.network/hmn/hmn/src/oops"
+ "git.handmade.network/hmn/hmn/src/templates"
"git.handmade.network/hmn/hmn/src/utils"
)
func APICheckUsername(c *RequestContext) ResponseData {
c.Req.ParseForm()
usernameArgs, hasUsername := c.Req.Form["username"]
- found := false
- canonicalUsername := ""
+ var user *models.User
+ var err error
if hasUsername {
requestedUsername := usernameArgs[0]
- found = true
- c.Perf.StartBlock("SQL", "Fetch user")
- user, err := db.QueryOne[models.User](c, c.Conn,
- `
- SELECT $columns
- FROM
- hmn_user
- WHERE
- LOWER(hmn_user.username) = LOWER($1)
- AND status = ANY ($2)
- `,
- requestedUsername,
- []models.UserStatus{models.UserStatusConfirmed, models.UserStatusApproved},
- )
- c.Perf.EndBlock()
- if err != nil {
- if errors.Is(err, db.NotFound) {
- found = false
- } else {
- return c.ErrorResponse(http.StatusInternalServerError, oops.New(err, "failed to fetch user: %s", requestedUsername))
- }
- } else {
- canonicalUsername = user.Username
+ user, err = hmndata.FetchUserByUsername(c, c.Conn, c.CurrentUser, requestedUsername, hmndata.UsersQuery{})
+ if err != nil && !errors.Is(err, db.NotFound) {
+ return c.ErrorResponse(http.StatusInternalServerError, oops.New(err, "failed to fetch user: %s", requestedUsername))
}
}
var res ResponseData
addCORSHeaders(c, &res)
- if found {
+ if user != nil {
res.WriteJson(map[string]any{
"found": true,
- "canonical": canonicalUsername,
+ "username": user.Username,
+ "name": user.BestName(),
+ "avatarUrl": templates.UserAvatarUrl(user),
}, nil)
} else {
res.WriteJson(map[string]any{