mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
[User Profile] Update edit profile header layout (#202902)
## Summary This PR updates layout of `User Profile` header according to [this design](https://github.com/elastic/kibana/issues/200059#issuecomment-2512452474). Since those changes break the layout pattern suggested by EUI, I had to move the content to be `children` of the header [as the EUI docs suggest.](https://eui.elastic.co/#/layout/page-header#customizing-the-page-header) Closes: #200059 --------- Co-authored-by: Ryan Keairns <contactryank@gmail.com>
This commit is contained in:
parent
55b5baae64
commit
780316832b
3 changed files with 98 additions and 62 deletions
|
@ -414,14 +414,14 @@ describe('useUserProfileForm', () => {
|
|||
expect(testWrapper.exists('EuiBadgeGroup[data-test-subj="remainingRoles"]')).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should display a popover for users with more than one role', () => {
|
||||
it('should display a popover for users with more than three roles', () => {
|
||||
const data: UserProfileData = {};
|
||||
|
||||
const nonCloudUser = mockAuthenticatedUser({ elastic_cloud_user: false });
|
||||
coreStart.settings.client.get.mockReturnValue(false);
|
||||
coreStart.settings.client.isOverridden.mockReturnValue(true);
|
||||
|
||||
nonCloudUser.roles = [...nonCloudUser.roles, 'user-role-1', 'user-role-2'];
|
||||
nonCloudUser.roles = [...nonCloudUser.roles, 'user-role-1', 'user-role-2', 'user-role-3'];
|
||||
const testWrapper = mount(
|
||||
<Providers
|
||||
services={coreStart}
|
||||
|
@ -436,7 +436,7 @@ describe('useUserProfileForm', () => {
|
|||
</Providers>
|
||||
);
|
||||
|
||||
const extraRoles = nonCloudUser.roles.splice(1);
|
||||
const extraRoles = nonCloudUser.roles.splice(3);
|
||||
|
||||
const userRolesExpandButton = testWrapper.find(
|
||||
'EuiButtonEmpty[data-test-subj="userRolesExpand"]'
|
||||
|
|
|
@ -22,9 +22,12 @@ import {
|
|||
EuiIconTip,
|
||||
EuiKeyPadMenu,
|
||||
EuiKeyPadMenuItem,
|
||||
EuiPageHeaderSection,
|
||||
EuiPopover,
|
||||
EuiSpacer,
|
||||
EuiText,
|
||||
EuiTextTruncate,
|
||||
EuiTitle,
|
||||
EuiToolTip,
|
||||
useEuiTheme,
|
||||
useGeneratedHtmlId,
|
||||
|
@ -72,6 +75,28 @@ const formRowCSS = css`
|
|||
}
|
||||
`;
|
||||
|
||||
const pageHeaderCSS = css`
|
||||
max-width: 1248px;
|
||||
margin: auto;
|
||||
border-bottom: none;
|
||||
`;
|
||||
|
||||
const pageTitleCSS = css`
|
||||
min-width: 120px;
|
||||
`;
|
||||
|
||||
const rightSideItemsCSS = css`
|
||||
justify-content: flex-start;
|
||||
|
||||
@include euiBreakpoint('m') {
|
||||
justify-content: flex-end;
|
||||
}
|
||||
`;
|
||||
|
||||
const rightSideItemCSS = css`
|
||||
min-width: 160px;
|
||||
`;
|
||||
|
||||
export interface UserProfileProps {
|
||||
user: AuthenticatedUser;
|
||||
data?: UserProfileData;
|
||||
|
@ -607,14 +632,13 @@ function UserPasswordEditor({
|
|||
}
|
||||
|
||||
const UserRoles: FunctionComponent<UserRoleProps> = ({ user }) => {
|
||||
const { euiTheme } = useEuiTheme();
|
||||
const [isPopoverOpen, setIsPopoverOpen] = useState(false);
|
||||
|
||||
const onButtonClick = () => setIsPopoverOpen((isOpen) => !isOpen);
|
||||
const closePopover = () => setIsPopoverOpen(false);
|
||||
|
||||
const [firstRole] = user.roles;
|
||||
const remainingRoles = user.roles.slice(1);
|
||||
const firstThreeRoles = user.roles.slice(0, 3);
|
||||
const remainingRoles = user.roles.slice(3);
|
||||
|
||||
const renderMoreRoles = () => {
|
||||
const button = (
|
||||
|
@ -653,16 +677,13 @@ const UserRoles: FunctionComponent<UserRoleProps> = ({ user }) => {
|
|||
|
||||
return (
|
||||
<>
|
||||
<div
|
||||
style={{
|
||||
maxWidth: euiTheme.breakpoint.m / 6,
|
||||
display: 'inline-block',
|
||||
}}
|
||||
>
|
||||
<EuiBadge key={firstRole} color="hollow" data-test-subj={`role${firstRole}`}>
|
||||
{firstRole}
|
||||
</EuiBadge>
|
||||
</div>
|
||||
<EuiBadgeGroup gutterSize="xs" data-test-subj="displayedRoles">
|
||||
{firstThreeRoles.map((role) => (
|
||||
<EuiBadge key={role} color="hollow" data-test-subj={`role${role}`}>
|
||||
{role}
|
||||
</EuiBadge>
|
||||
))}
|
||||
</EuiBadgeGroup>
|
||||
{remainingRoles.length ? renderMoreRoles() : null}
|
||||
</>
|
||||
);
|
||||
|
@ -693,7 +714,9 @@ export const UserProfile: FunctionComponent<UserProfileProps> = ({ user, data })
|
|||
defaultMessage="Username"
|
||||
/>
|
||||
),
|
||||
description: user.username as string | undefined | JSX.Element,
|
||||
description:
|
||||
user.username &&
|
||||
((<EuiTextTruncate text={user.username} />) as string | undefined | JSX.Element),
|
||||
helpText: (
|
||||
<FormattedMessage
|
||||
id="xpack.security.accountManagement.userProfile.usernameHelpText"
|
||||
|
@ -712,7 +735,7 @@ export const UserProfile: FunctionComponent<UserProfileProps> = ({ user, data })
|
|||
defaultMessage="Full name"
|
||||
/>
|
||||
),
|
||||
description: user.full_name,
|
||||
description: user.full_name && <EuiTextTruncate text={user.full_name} />,
|
||||
helpText: (
|
||||
<FormattedMessage
|
||||
id="xpack.security.accountManagement.userProfile.fullNameHelpText"
|
||||
|
@ -729,7 +752,7 @@ export const UserProfile: FunctionComponent<UserProfileProps> = ({ user, data })
|
|||
defaultMessage="Email address"
|
||||
/>
|
||||
),
|
||||
description: user.email,
|
||||
description: user.email && <EuiTextTruncate text={user.email} />,
|
||||
helpText: (
|
||||
<FormattedMessage
|
||||
id="xpack.security.accountManagement.userProfile.emailHelpText"
|
||||
|
@ -778,48 +801,61 @@ export const UserProfile: FunctionComponent<UserProfileProps> = ({ user, data })
|
|||
/>
|
||||
) : null}
|
||||
|
||||
<KibanaPageTemplate className="eui-fullHeight" restrictWidth={1000}>
|
||||
<KibanaPageTemplate.Header
|
||||
pageTitle={
|
||||
<FormattedMessage
|
||||
id="xpack.security.accountManagement.userProfile.title"
|
||||
defaultMessage="Profile"
|
||||
/>
|
||||
}
|
||||
id={titleId}
|
||||
rightSideItems={rightSideItems.reverse().map((item) => (
|
||||
<EuiDescriptionList
|
||||
textStyle="reverse"
|
||||
listItems={[
|
||||
{
|
||||
title: (
|
||||
<EuiText color={euiTheme.colors.darkestShade} size="s">
|
||||
<EuiFlexGroup responsive={false} alignItems="center" gutterSize="none">
|
||||
<EuiFlexItem grow={false}>{item.title}</EuiFlexItem>
|
||||
<EuiFlexItem grow={false} style={{ marginLeft: '0.33em' }}>
|
||||
<EuiIconTip type="questionInCircle" content={item.helpText} />
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
</EuiText>
|
||||
),
|
||||
description: (
|
||||
<span data-test-subj={item.testSubj}>
|
||||
{item.description || (
|
||||
<EuiText color={euiTheme.colors.textDisabled} size="s">
|
||||
<FormattedMessage
|
||||
id="xpack.security.accountManagement.userProfile.noneProvided"
|
||||
defaultMessage="None provided"
|
||||
/>
|
||||
<KibanaPageTemplate className="eui-fullHeight" restrictWidth={true}>
|
||||
<KibanaPageTemplate.Header id={titleId} css={pageHeaderCSS}>
|
||||
<EuiPageHeaderSection>
|
||||
<EuiTitle size="l" css={pageTitleCSS}>
|
||||
<h1>
|
||||
<FormattedMessage
|
||||
id="xpack.security.accountManagement.userProfile.title"
|
||||
defaultMessage="Profile"
|
||||
/>
|
||||
</h1>
|
||||
</EuiTitle>
|
||||
</EuiPageHeaderSection>
|
||||
<EuiPageHeaderSection>
|
||||
<EuiFlexGroup alignItems="flexStart" css={rightSideItemsCSS}>
|
||||
{rightSideItems.map((item) => (
|
||||
<EuiDescriptionList
|
||||
key={item.testSubj}
|
||||
textStyle="reverse"
|
||||
css={rightSideItemCSS}
|
||||
listItems={[
|
||||
{
|
||||
title: (
|
||||
<EuiText color={euiTheme.colors.darkestShade} size="s">
|
||||
<EuiFlexGroup
|
||||
responsive={false}
|
||||
alignItems="center"
|
||||
gutterSize="none"
|
||||
>
|
||||
<EuiFlexItem grow={false}>{item.title}</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiIconTip type="questionInCircle" content={item.helpText} />
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
</EuiText>
|
||||
)}
|
||||
</span>
|
||||
),
|
||||
},
|
||||
]}
|
||||
compressed
|
||||
/>
|
||||
))}
|
||||
/>
|
||||
),
|
||||
description: (
|
||||
<span data-test-subj={item.testSubj}>
|
||||
{item.description || (
|
||||
<EuiText color={euiTheme.colors.textDisabled} size="s">
|
||||
<FormattedMessage
|
||||
id="xpack.security.accountManagement.userProfile.noneProvided"
|
||||
defaultMessage="None provided"
|
||||
/>
|
||||
</EuiText>
|
||||
)}
|
||||
</span>
|
||||
),
|
||||
},
|
||||
]}
|
||||
compressed
|
||||
/>
|
||||
))}
|
||||
</EuiFlexGroup>
|
||||
</EuiPageHeaderSection>
|
||||
</KibanaPageTemplate.Header>
|
||||
<KibanaPageTemplate.Section>
|
||||
<Form aria-labelledby={titleId}>
|
||||
<UserDetailsEditor user={user} />
|
||||
|
|
|
@ -29,8 +29,8 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
|
|||
const actualFullname = await pageObjects.userProfiles.getProfileFullname();
|
||||
const actualEmail = await pageObjects.userProfiles.getProfileEmail();
|
||||
|
||||
expect(actualFullname).to.be(userData.full_name);
|
||||
expect(actualEmail).to.be(userData.email);
|
||||
expect(actualFullname).to.contain(userData.full_name);
|
||||
expect(actualEmail).to.contain(userData.email);
|
||||
});
|
||||
|
||||
it('should not have edit actions', async () => {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue