-
Notifications
You must be signed in to change notification settings - Fork 8.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Redesigned user profile page (#127624)
* Add user profile UI * add code doc * More * Fix nav control for anonymous users * Move presentational logic outside form row * Fix disabled state and update profile api * remove presentational logic from form row * wip * Fix initials * . * empty user avatar * simplify reserved user screen * . * unit tests * type fixes * . * . * . * . * . * . * . * . * . * . * . * . * . * . * . * . * . * [CI] Auto-commit changed files from 'node scripts/eslint --no-cache --fix' * . * . * . * . * . * . * Review#1: handle UI inconsistencies, update avatar in the navigation bar when profile data is updated, etc. * Fix type errors. * Use different validation model for the first and subsequent submits. * Review#2: move change password form to a modal, support users authenticated via authentication proxies. * Use proper test subject for the password change Cancel button. * Review#3: retry profile activation requests. * Review#4: align text color of the non-editable profile fields with the designs. * Review#4: improve warning message for the change password form when changing password for Kibana system users. Co-authored-by: kibanamachine <[email protected]> Co-authored-by: Aleh Zasypkin <[email protected]>
- Loading branch information
1 parent
169d503
commit 1775421
Showing
74 changed files
with
3,693 additions
and
1,320 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License | ||
* 2.0; you may not use this file except in compliance with the Elastic License | ||
* 2.0. | ||
*/ | ||
|
||
import { mockAuthenticatedUser } from './authenticated_user.mock'; | ||
import type { AuthenticatedUserProfile } from './user_profile'; | ||
|
||
export const userProfileMock = { | ||
create: (userProfile: Partial<AuthenticatedUserProfile> = {}): AuthenticatedUserProfile => { | ||
const user = mockAuthenticatedUser({ | ||
username: 'some-username', | ||
roles: [], | ||
enabled: true, | ||
}); | ||
return { | ||
uid: 'some-profile-uid', | ||
enabled: true, | ||
user: { | ||
...user, | ||
active: true, | ||
}, | ||
data: {}, | ||
...userProfile, | ||
}; | ||
}, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License | ||
* 2.0; you may not use this file except in compliance with the Elastic License | ||
* 2.0. | ||
*/ | ||
|
||
import { VISUALIZATION_COLORS } from '@elastic/eui'; | ||
|
||
import type { User } from '..'; | ||
import type { AuthenticatedUser } from './authenticated_user'; | ||
import { getUserDisplayName } from './user'; | ||
|
||
/** | ||
* User information returned in user profile. | ||
*/ | ||
export interface UserInfo extends User { | ||
active: boolean; | ||
} | ||
|
||
/** | ||
* Avatar stored in user profile. | ||
*/ | ||
export interface UserAvatar { | ||
initials?: string; | ||
color?: string; | ||
imageUrl?: string; | ||
} | ||
|
||
/** | ||
* Placeholder for data stored in user profile. | ||
*/ | ||
export type UserData = Record<string, unknown>; | ||
|
||
/** | ||
* Describes properties stored in user profile. | ||
*/ | ||
export interface UserProfile<T extends UserData = UserData> { | ||
/** | ||
* Unique ID for of the user profile. | ||
*/ | ||
uid: string; | ||
|
||
/** | ||
* Indicates whether user profile is enabled or not. | ||
*/ | ||
enabled: boolean; | ||
|
||
/** | ||
* Information about the user that owns profile. | ||
*/ | ||
user: UserInfo; | ||
|
||
/** | ||
* User specific data associated with the profile. | ||
*/ | ||
data: T; | ||
} | ||
|
||
/** | ||
* User profile enriched with session information. | ||
*/ | ||
export interface AuthenticatedUserProfile<T extends UserData = UserData> extends UserProfile<T> { | ||
/** | ||
* Information about the currently authenticated user that owns the profile. | ||
*/ | ||
user: UserProfile['user'] & Pick<AuthenticatedUser, 'authentication_provider'>; | ||
} | ||
|
||
export const USER_AVATAR_FALLBACK_CODE_POINT = 97; // code point for lowercase "a" | ||
export const USER_AVATAR_MAX_INITIALS = 2; | ||
|
||
/** | ||
* Determines the color for the provided user profile. | ||
* If a color is present on the user profile itself, then that is used. | ||
* Otherwise, a color is provided from EUI's Visualization Colors based on the display name. | ||
* | ||
* @param {UserInfo} user User info | ||
* @param {UserAvatar} avatar User avatar | ||
*/ | ||
export function getUserAvatarColor( | ||
user: Pick<UserInfo, 'username' | 'full_name'>, | ||
avatar?: UserAvatar | ||
) { | ||
if (avatar && avatar.color) { | ||
return avatar.color; | ||
} | ||
|
||
const firstCodePoint = getUserDisplayName(user).codePointAt(0) || USER_AVATAR_FALLBACK_CODE_POINT; | ||
|
||
return VISUALIZATION_COLORS[firstCodePoint % VISUALIZATION_COLORS.length]; | ||
} | ||
|
||
/** | ||
* Determines the initials for the provided user profile. | ||
* If initials are present on the user profile itself, then that is used. | ||
* Otherwise, the initials are calculated based off the words in the display name, with a max length of 2 characters. | ||
* | ||
* @param {UserInfo} user User info | ||
* @param {UserAvatar} avatar User avatar | ||
*/ | ||
export function getUserAvatarInitials( | ||
user: Pick<UserInfo, 'username' | 'full_name'>, | ||
avatar?: UserAvatar | ||
) { | ||
if (avatar && avatar.initials) { | ||
return avatar.initials; | ||
} | ||
|
||
const words = getUserDisplayName(user).split(' '); | ||
const numInitials = Math.min(USER_AVATAR_MAX_INITIALS, words.length); | ||
|
||
words.splice(numInitials, words.length); | ||
|
||
return words.map((word) => word.substring(0, 1)).join(''); | ||
} |
Oops, something went wrong.