feat(cabana): add backend user avatars to My account and the top bar
- cabana.BackendUser is an attach.Owner (MorphName Backend\Models\User,
cabana.BackendUserMorphType) with one public attachOne avatar
(cabana.BackendUserAvatarField), as WinterCMS stores it
- POST /account/avatar stores one file_data image (jpg, jpeg, png, gif or
webp, image guard, at most cabana.AvatarMaxBytes = 2 MiB, under a
server-generated name) and replaces the previous avatar: old rows are
deleted in the transaction, their blobs after the commit
- DELETE /account/avatar removes the avatar and is idempotent
- GET /auth/me and the account routes return avatar {url, thumb_url}
(250x250 crop); cabana.BackendUserAvatar lets plugins read it
- swag annotations, regenerated admin.json and schema.d.ts; route
inventories, CSRF walk (29) and OpenAPI conformance learn both routes
- SPA: avatar upload and remove on My account, avatar image in the user
menu trigger and header; backend::lang.myaccount avatar strings
- rebuilt boardwalk dist; cabana README, users-and-permissions and
admin-spa docs
This commit is contained in:
@@ -54,6 +54,21 @@ export async function me(): Promise<AdminProfile | null> {
|
||||
return user.value
|
||||
}
|
||||
|
||||
/** First and last name initials, else the login's first two letters. */
|
||||
export function profileInitials(user: Pick<AdminProfile, 'first_name' | 'last_name' | 'login'> | null): string {
|
||||
if (!user) {
|
||||
return ''
|
||||
}
|
||||
const parts = [user.first_name, user.last_name].map((part) => part.trim()).filter(Boolean)
|
||||
if (parts.length > 0) {
|
||||
return parts
|
||||
.slice(0, 2)
|
||||
.map((part) => part.charAt(0).toUpperCase())
|
||||
.join('')
|
||||
}
|
||||
return user.login.slice(0, 2).toUpperCase()
|
||||
}
|
||||
|
||||
/** Replaces the signed-in profile, e.g. with the one PUT /account returned. */
|
||||
export function setCurrentUser(profile: AdminProfile): void {
|
||||
user.value = profile
|
||||
|
||||
Reference in New Issue
Block a user