Simplified user info update APIs, DB and frontend to remove separate update functions for each property. Automatically choose preferred username for users as they register, based on display name.

This commit is contained in:
Leo Vasanko
2026-02-17 18:16:32 +00:00
parent 8128d40202
commit 7a09dbc040
10 changed files with 197 additions and 222 deletions
+1 -1
View File
@@ -808,7 +808,7 @@ async function submitDialog() {
// Close dialog immediately, then perform async operation
closeDialog()
apiJson(`/auth/api/admin/users/${user.uuid}/display-name`, { method: 'PATCH', body: { display_name: name } })
apiJson(`/auth/api/admin/users/${user.uuid}/info`, { method: 'PATCH', body: { display_name: name } })
.then(() => {
authStore.showMessage(`User renamed to "${name}".`, 'success', 2500)
onUserNameSaved()
+1 -1
View File
@@ -189,7 +189,7 @@ defineExpose({ focusFirstElement })
:loading="loading"
:org-display-name="userDetail.org.display_name"
:role-name="userDetail.role"
:update-endpoint="`/auth/api/admin/users/${selectedUser.uuid}/display-name`"
:update-endpoint="`/auth/api/admin/users/${selectedUser.uuid}/info`"
@saved="$emit('onUserNameSaved')"
@edit="handleEditName"
>
+1 -1
View File
@@ -817,7 +817,7 @@ th {
display: grid;
border-radius: var(--radius-md);
background: var(--color-surface);
padding: 1.1rem 1.25rem;
padding: 1rem;
}
.user-details {
+8 -12
View File
@@ -25,7 +25,7 @@
:loading="authStore.isLoading"
:org-display-name="authStore.userInfo.ctx.org.display_name"
:role-name="authStore.userInfo.ctx.role.display_name"
update-endpoint="/auth/api/user/display-name"
update-endpoint="/auth/api/user/info"
@saved="authStore.loadUserInfo()"
@edit="openEditDialog"
@keydown="handleUserInfoKeydown"
@@ -397,17 +397,13 @@ const saveProfile = async () => {
try {
editError.value = ''
saving.value = true
const tasks = []
if (name !== user.display_name)
tasks.push(apiJson('/auth/api/user/display-name', { method: 'PATCH', body: { display_name: name } }))
if (emailVal !== (user.email || null))
tasks.push(apiJson('/auth/api/user/email', { method: 'PATCH', body: { email: emailVal } }))
if (usernameVal !== (user.preferred_username || null))
tasks.push(apiJson('/auth/api/user/preferred-username', { method: 'PATCH', body: { preferred_username: usernameVal } }))
if (telephoneVal !== (user.telephone || null))
tasks.push(apiJson('/auth/api/user/telephone', { method: 'PATCH', body: { telephone: telephoneVal } }))
if (tasks.length) {
await Promise.all(tasks)
const body = {}
if (name !== user.display_name) body.display_name = name
if (emailVal !== (user.email || null)) body.email = emailVal
if (usernameVal !== (user.preferred_username || null)) body.preferred_username = usernameVal
if (telephoneVal !== (user.telephone || null)) body.telephone = telephoneVal
if (Object.keys(body).length) {
await apiJson('/auth/api/user/info', { method: 'PATCH', body })
await authStore.loadUserInfo()
authStore.showMessage('Profile updated!', 'success', 3000)
}
+1 -1
View File
@@ -109,7 +109,7 @@ const userLoaded = computed(() => !!props.name)
.info-fields-block { grid-area: fields; display: flex; flex-direction: column; gap: 0.25rem; min-width: 0; }
.contact-item { display: block; color: var(--color-text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.contact-link { color: var(--color-text); text-decoration: none; display: block; transition: transform 0.1s ease; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.contact-link:hover { transform: scale(1.05); }
.contact-link:hover { transform: scale(1.01); }
.info-line { grid-area: info; line-height: 1.4; font-size: 0.9em; }
.info-date { color: var(--color-text) !important; }
.info-label { color: var(--color-text) !important; }