Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions apps/meteor/client/components/UserInfo/UserInfo.spec.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { composeStories } from '@storybook/react';
import { render } from '@testing-library/react';
import { axe } from 'jest-axe';

import * as stories from './UserInfo.stories';

const testCases = Object.values(composeStories(stories)).map((Story) => [Story.storyName || 'Story', Story]);
test.each(testCases)(`renders %s without crashing`, async (_storyname, Story) => {
const { baseElement } = render(<Story />);
expect(baseElement).toMatchSnapshot();
});

test.each(testCases)('%s should have no a11y violations', async (_storyname, Story) => {
const { container } = render(<Story />);

const results = await axe(container);
expect(results).toHaveNoViolations();
});
41 changes: 21 additions & 20 deletions apps/meteor/client/components/UserInfo/UserInfo.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,41 +1,42 @@
import type { Meta, StoryFn } from '@storybook/react';

import { Contextualbar } from '../Contextualbar';
import { ContextualbarDialog } from '../Contextualbar';
import * as Status from '../UserStatus';
import UserInfo from './UserInfo';
import { UserCardRole } from '../UserCard';

export default {
component: UserInfo,
parameters: {
layout: 'fullscreen',
actions: { argTypesRegex: '^on.*' },
},
decorators: [(fn) => <Contextualbar height='100vh'>{fn()}</Contextualbar>],
decorators: [
(fn) => (
<ContextualbarDialog aria-label='User Info' height='100vh'>
{fn()}
</ContextualbarDialog>
),
],
} satisfies Meta<typeof UserInfo>;

const Template: StoryFn<typeof UserInfo> = (args) => <UserInfo {...args} />;

export const Default = Template.bind({});
Default.args = {
const defaultArgs = {
name: 'Guilherme Gazzo',
username: 'guilherme.gazzo',
nickname: 'gazzo',
statusText: '🛴 currently working on User Card',
bio: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla tempus, eros convallis vulputate cursus, nisi neque eleifend libero, eget lacinia justo purus nec est. In at sodales ipsum. Sed lacinia quis purus eget pulvinar. Aenean eu pretium nunc, at aliquam magna. Praesent dignissim, tortor sed volutpat mattis, mauris diam pulvinar leo, porta commodo risus est non purus. Mauris in justo vel lorem ullamcorper hendrerit. Nam est metus, viverra a pellentesque vitae, ornare eget odio. Morbi tempor feugiat mattis. Morbi non felis tempor, aliquam justo sed, sagittis nibh. Mauris consequat ex metus. Praesent sodales sit amet nibh a vulputate. Integer commodo, mi vel bibendum sollicitudin, urna lectus accumsan ante, eget faucibus augue ex id neque. Aenean consectetur, orci a pellentesque mattis, tortor tellus fringilla elit, non ullamcorper risus nunc feugiat risus. Fusce sit amet nisi dapibus turpis commodo placerat. In tortor ante, vehicula sit amet augue et, imperdiet porta sem.',
// actions: [<UserCard.Action icon='message'/>, <UserCard.Action icon='phone'/>],
utcOffset: -3,
bio: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla tempus, eros convallis vulputate cursus, nisi neque eleifend libero, eget lacinia justo purus nec est. In at sodales ipsum. Sed lacinia quis purus eget pulvinar. Aenean eu pretium nunc, at aliquam magna. Praesent dignissim, tortor sed volutpat mattis, mauris diam pulvinar leo, porta commodo risus est non purus.',
email: '[email protected]',
status: <Status.Offline />,
roles: [<UserCardRole key='admin'>admin</UserCardRole>, <UserCardRole key='user'>user</UserCardRole>],
};

export const WithNickname = Template.bind({});
WithNickname.args = {
name: 'Guilherme Gazzo',
username: 'guilherme.gazzo',
statusText: '🛴 currently working on User Card',
bio: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla tempus, eros convallis vulputate cursus, nisi neque eleifend libero, eget lacinia justo purus nec est. In at sodales ipsum. Sed lacinia quis purus eget pulvinar. Aenean eu pretium nunc, at aliquam magna. Praesent dignissim, tortor sed volutpat mattis, mauris diam pulvinar leo, porta commodo risus est non purus. Mauris in justo vel lorem ullamcorper hendrerit. Nam est metus, viverra a pellentesque vitae, ornare eget odio. Morbi tempor feugiat mattis. Morbi non felis tempor, aliquam justo sed, sagittis nibh. Mauris consequat ex metus. Praesent sodales sit amet nibh a vulputate. Integer commodo, mi vel bibendum sollicitudin, urna lectus accumsan ante, eget faucibus augue ex id neque. Aenean consectetur, orci a pellentesque mattis, tortor tellus fringilla elit, non ullamcorper risus nunc feugiat risus. Fusce sit amet nisi dapibus turpis commodo placerat. In tortor ante, vehicula sit amet augue et, imperdiet porta sem.',
// actions: [<UserCard.Action icon='message'/>, <UserCard.Action icon='phone'/>],
utcOffset: -3,
email: '[email protected]',
status: <Status.Offline />,
nickname: 'Nickname',
const Template: StoryFn<typeof UserInfo> = (args) => <UserInfo {...defaultArgs} {...args} />;

export const Default = Template.bind({});

export const WithABACAttributes = Template.bind({});
WithABACAttributes.args = {
// @ts-expect-error - abacAttributes is not yet implemented in Users properties
abacAttributes: ['Classified', 'Top Secret', 'Confidential'],
};
17 changes: 14 additions & 3 deletions apps/meteor/client/components/UserInfo/UserInfo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import {
import MarkdownText from '../MarkdownText';
import UTCClock from '../UTCClock';
import { UserCardRoles } from '../UserCard';
import UserInfoABACAttributes from './UserInfoABACAttributes';
import UserInfoAvatar from './UserInfoAvatar';

type UserInfoDataProps = Serialized<
Expand Down Expand Up @@ -70,6 +71,8 @@ const UserInfo = ({
canViewAllInfo,
actions,
reason,
// @ts-expect-error - abacAttributes is not yet implemented in Users properties
abacAttributes = null,
...props
}: UserInfoProps): ReactElement => {
const { t } = useTranslation();
Expand Down Expand Up @@ -113,7 +116,7 @@ const UserInfo = ({
</InfoPanelField>
)}

{roles.length !== 0 && (
{roles?.length !== 0 && (
<InfoPanelField>
<InfoPanelLabel>{t('Roles')}</InfoPanelLabel>
<UserCardRoles>{roles}</UserCardRoles>
Expand All @@ -127,10 +130,12 @@ const UserInfo = ({
</InfoPanelField>
)}

{Number.isInteger(utcOffset) && (
{utcOffset && Number.isInteger(utcOffset) && (
<InfoPanelField>
<InfoPanelLabel>{t('Local_Time')}</InfoPanelLabel>
<InfoPanelText>{utcOffset && <UTCClock utcOffset={utcOffset} />}</InfoPanelText>
<InfoPanelText>
<UTCClock utcOffset={utcOffset} />
</InfoPanelText>
</InfoPanelField>
)}

Expand Down Expand Up @@ -175,6 +180,12 @@ const UserInfo = ({
</InfoPanelField>
)}

{abacAttributes?.length > 0 && (
<InfoPanelField>
<InfoPanelLabel title={t('ABAC_Attributes_description')}>{t('ABAC_Attributes')}</InfoPanelLabel>
<UserInfoABACAttributes abacAttributes={abacAttributes} />
</InfoPanelField>
)}
{userCustomFields?.map(
(customField) =>
customField?.value && (
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { Tag } from '@rocket.chat/fuselage';

type UserInfoABACAttributeProps = {
attribute: string;
};

const UserInfoABACAttribute = ({ attribute }: UserInfoABACAttributeProps) => {
return <Tag variant='secondary-warning' children={attribute} />;
};

export default UserInfoABACAttribute;
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { Box, Margins } from '@rocket.chat/fuselage';

import UserInfoABACAttribute from './UserInfoABACAttribute';

type UserInfoABACAttributesProps = {
abacAttributes: string[];
};

const UserInfoABACAttributes = ({ abacAttributes }: UserInfoABACAttributesProps) => {
return (
<Box m='neg-x2'>
<Box flexWrap='wrap' display='flex' flexShrink={0} mb={8}>
{abacAttributes.map((attribute, index) => (
<Margins inline={2} blockEnd={4} key={`${attribute}-${index}`}>
<UserInfoABACAttribute attribute={attribute} />
</Margins>
))}
</Box>
</Box>
);
};

export default UserInfoABACAttributes;
Loading
Loading