refactor(client): Use subcomponents for `InfoPanel` and `UserInfo` (#32470)

pull/32570/head
Henrique Guimarães Ribeiro 2 years ago committed by GitHub
parent ca3d90b101
commit b553cfcd60
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 99
      apps/meteor/client/components/InfoPanel/InfoPanel.stories.tsx
  2. 29
      apps/meteor/client/components/InfoPanel/index.ts
  3. 125
      apps/meteor/client/components/UserInfo/UserInfo.tsx
  4. 17
      apps/meteor/client/components/UserInfo/index.ts
  5. 6
      apps/meteor/client/omnichannel/additionalForms/MaxChatsPerAgentDisplay.tsx
  6. 56
      apps/meteor/client/views/admin/deviceManagement/DeviceManagementInfo/DeviceManagementInfo.tsx
  7. 4
      apps/meteor/client/views/admin/users/AdminUserInfoActions.tsx
  8. 2
      apps/meteor/client/views/admin/users/AdminUserInfoWithData.tsx
  9. 4
      apps/meteor/client/views/omnichannel/agents/AgentEdit.tsx
  10. 11
      apps/meteor/client/views/omnichannel/agents/AgentInfo.tsx
  11. 10
      apps/meteor/client/views/omnichannel/directory/calls/contextualBar/InfoField.tsx
  12. 26
      apps/meteor/client/views/omnichannel/directory/calls/contextualBar/VoipInfo.tsx
  13. 76
      apps/meteor/client/views/room/contextualBar/Info/RoomInfo/RoomInfo.tsx
  14. 4
      apps/meteor/client/views/room/contextualBar/UserInfo/UserInfoActions.tsx
  15. 2
      apps/meteor/client/views/room/contextualBar/UserInfo/UserInfoWithData.tsx
  16. 86
      apps/meteor/client/views/teams/contextualBar/info/TeamsInfo.tsx

@ -1,7 +1,17 @@
import type { ComponentMeta, ComponentStory } from '@storybook/react';
import React from 'react';
import InfoPanel from '.';
import {
InfoPanel,
InfoPanelAction,
InfoPanelActionGroup,
InfoPanelAvatar,
InfoPanelField,
InfoPanelLabel,
InfoPanelSection,
InfoPanelText,
InfoPanelTitle,
} from '.';
import { createFakeRoom } from '../../../tests/mocks/data';
import RetentionPolicyCallout from './RetentionPolicyCallout';
@ -9,14 +19,14 @@ export default {
title: 'Info Panel/InfoPanel',
component: InfoPanel,
subcomponents: {
'InfoPanel.Action': InfoPanel.Action,
'InfoPanel.ActionGroup': InfoPanel.ActionGroup,
'InfoPanel.Avatar': InfoPanel.Avatar,
'InfoPanel.Field': InfoPanel.Field,
'InfoPanel.Label': InfoPanel.Label,
'InfoPanel.Section': InfoPanel.Section,
'InfoPanel.Text': InfoPanel.Text,
'InfoPanel.Title': InfoPanel.Title,
InfoPanelAction,
InfoPanelActionGroup,
InfoPanelAvatar,
InfoPanelField,
InfoPanelLabel,
InfoPanelSection,
InfoPanelText,
InfoPanelTitle,
RetentionPolicyCallout,
},
} as ComponentMeta<typeof InfoPanel>;
@ -25,62 +35,37 @@ const fakeRoom = createFakeRoom();
export const Default: ComponentStory<typeof InfoPanel> = () => (
<InfoPanel>
<InfoPanel.Avatar />
<InfoPanel.Section>
<InfoPanel.Title title='rocketchat-frontend-team' icon='hashtag' />
</InfoPanel.Section>
<InfoPanelAvatar />
<InfoPanelSection>
<InfoPanelTitle title='rocketchat-frontend-team' icon='hashtag' />
</InfoPanelSection>
<InfoPanel.Section>
<InfoPanel.Field>
<InfoPanel.Label>Description</InfoPanel.Label>
<InfoPanel.Text>
<InfoPanelSection>
<InfoPanelField>
<InfoPanelLabel>Description</InfoPanelLabel>
<InfoPanelText>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam mollis nisi vel arcu bibendum vehicula. Integer vitae suscipit
libero
</InfoPanel.Text>
</InfoPanel.Field>
<InfoPanel.Field>
<InfoPanel.Label>Announcement</InfoPanel.Label>
<InfoPanel.Text>
</InfoPanelText>
</InfoPanelField>
<InfoPanelField>
<InfoPanelLabel>Announcement</InfoPanelLabel>
<InfoPanelText>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam mollis nisi vel arcu bibendum vehicula. Integer vitae suscipit
libero
</InfoPanel.Text>
</InfoPanel.Field>
<InfoPanel.Field>
<InfoPanel.Label>Topic</InfoPanel.Label>
<InfoPanel.Text>
</InfoPanelText>
</InfoPanelField>
<InfoPanelField>
<InfoPanelLabel>Topic</InfoPanelLabel>
<InfoPanelText>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam mollis nisi vel arcu bibendum vehicula. Integer vitae suscipit
libero
</InfoPanel.Text>
</InfoPanel.Field>
</InfoPanel.Section>
<InfoPanel.Section>
</InfoPanelText>
</InfoPanelField>
</InfoPanelSection>
<InfoPanelSection>
<RetentionPolicyCallout room={fakeRoom} />
</InfoPanel.Section>
</InfoPanelSection>
</InfoPanel>
);
Default.storyName = 'InfoPanel';
// export const Archived = () => <Contextualbar height={800}>
// <RoomInfo
// {...room}
// icon='lock'
// onClickHide={alert}
// onClickLeave={alert}
// onClickEdit={alert}
// onClickDelete={alert}
// archived
// />
// </Contextualbar>;
// export const Broadcast = () => <Contextualbar height={800}>
// <RoomInfo
// {...room}
// icon='lock'
// onClickHide={alert}
// onClickLeave={alert}
// onClickEdit={alert}
// onClickDelete={alert}
// broadcast
// />
// </Contextualbar>;

@ -1,20 +1,9 @@
import InfoPanel from './InfoPanel';
import InfoPanelAction from './InfoPanelAction';
import InfoPanelActionGroup from './InfoPanelActionGroup';
import InfoPanelAvatar from './InfoPanelAvatar';
import InfoPanelField from './InfoPanelField';
import InfoPanelLabel from './InfoPanelLabel';
import InfoPanelSection from './InfoPanelSection';
import InfoPanelText from './InfoPanelText';
import InfoPanelTitle from './InfoPanelTitle';
export default Object.assign(InfoPanel, {
Title: InfoPanelTitle,
Label: InfoPanelLabel,
Text: InfoPanelText,
Avatar: InfoPanelAvatar,
Field: InfoPanelField,
Action: InfoPanelAction,
Section: InfoPanelSection,
ActionGroup: InfoPanelActionGroup,
});
export { default as InfoPanel } from './InfoPanel';
export { default as InfoPanelAction } from './InfoPanelAction';
export { default as InfoPanelActionGroup } from './InfoPanelActionGroup';
export { default as InfoPanelAvatar } from './InfoPanelAvatar';
export { default as InfoPanelField } from './InfoPanelField';
export { default as InfoPanelLabel } from './InfoPanelLabel';
export { default as InfoPanelSection } from './InfoPanelSection';
export { default as InfoPanelText } from './InfoPanelText';
export { default as InfoPanelTitle } from './InfoPanelTitle';

@ -9,7 +9,16 @@ import { useTimeAgo } from '../../hooks/useTimeAgo';
import { useUserCustomFields } from '../../hooks/useUserCustomFields';
import { useUserDisplayName } from '../../hooks/useUserDisplayName';
import { ContextualbarScrollableContent } from '../Contextualbar';
import InfoPanel from '../InfoPanel';
import {
InfoPanel,
InfoPanelActionGroup,
InfoPanelAvatar,
InfoPanelField,
InfoPanelLabel,
InfoPanelSection,
InfoPanelText,
InfoPanelTitle,
} from '../InfoPanel';
import MarkdownText from '../MarkdownText';
import UTCClock from '../UTCClock';
import { UserCardRoles } from '../UserCard';
@ -72,119 +81,119 @@ const UserInfo = ({
<ContextualbarScrollableContent p={24} {...props}>
<InfoPanel>
{username && (
<InfoPanel.Avatar>
<InfoPanelAvatar>
<UserInfoAvatar username={username} etag={avatarETag} />
</InfoPanel.Avatar>
</InfoPanelAvatar>
)}
{actions && <InfoPanel.ActionGroup>{actions}</InfoPanel.ActionGroup>}
{actions && <InfoPanelActionGroup>{actions}</InfoPanelActionGroup>}
<InfoPanel.Section>
{userDisplayName && <InfoPanel.Title icon={status} title={userDisplayName} />}
<InfoPanelSection>
{userDisplayName && <InfoPanelTitle icon={status} title={userDisplayName} />}
{statusText && (
<InfoPanel.Text>
<InfoPanelText>
<MarkdownText content={statusText} parseEmoji={true} variant='inline' />
</InfoPanel.Text>
</InfoPanelText>
)}
</InfoPanel.Section>
</InfoPanelSection>
<InfoPanel.Section>
<InfoPanelSection>
{reason && (
<InfoPanel.Field>
<InfoPanel.Label>{t('Reason_for_joining')}</InfoPanel.Label>
<InfoPanel.Text>{reason}</InfoPanel.Text>
</InfoPanel.Field>
<InfoPanelField>
<InfoPanelLabel>{t('Reason_for_joining')}</InfoPanelLabel>
<InfoPanelText>{reason}</InfoPanelText>
</InfoPanelField>
)}
{nickname && (
<InfoPanel.Field>
<InfoPanel.Label>{t('Nickname')}</InfoPanel.Label>
<InfoPanel.Text>{nickname}</InfoPanel.Text>
</InfoPanel.Field>
<InfoPanelField>
<InfoPanelLabel>{t('Nickname')}</InfoPanelLabel>
<InfoPanelText>{nickname}</InfoPanelText>
</InfoPanelField>
)}
{roles.length !== 0 && (
<InfoPanel.Field>
<InfoPanel.Label>{t('Roles')}</InfoPanel.Label>
<InfoPanelField>
<InfoPanelLabel>{t('Roles')}</InfoPanelLabel>
<UserCardRoles>{roles}</UserCardRoles>
</InfoPanel.Field>
</InfoPanelField>
)}
{username && username !== name && (
<InfoPanel.Field>
<InfoPanel.Label>{t('Username')}</InfoPanel.Label>
<InfoPanel.Text data-qa='UserInfoUserName'>{username}</InfoPanel.Text>
</InfoPanel.Field>
<InfoPanelField>
<InfoPanelLabel>{t('Username')}</InfoPanelLabel>
<InfoPanelText data-qa='UserInfoUserName'>{username}</InfoPanelText>
</InfoPanelField>
)}
{Number.isInteger(utcOffset) && (
<InfoPanel.Field>
<InfoPanel.Label>{t('Local_Time')}</InfoPanel.Label>
<InfoPanel.Text>{utcOffset && <UTCClock utcOffset={utcOffset} />}</InfoPanel.Text>
</InfoPanel.Field>
<InfoPanelField>
<InfoPanelLabel>{t('Local_Time')}</InfoPanelLabel>
<InfoPanelText>{utcOffset && <UTCClock utcOffset={utcOffset} />}</InfoPanelText>
</InfoPanelField>
)}
{bio && (
<InfoPanel.Field>
<InfoPanel.Label>{t('Bio')}</InfoPanel.Label>
<InfoPanel.Text withTruncatedText={false}>
<InfoPanelField>
<InfoPanelLabel>{t('Bio')}</InfoPanelLabel>
<InfoPanelText withTruncatedText={false}>
<MarkdownText variant='inline' content={bio} />
</InfoPanel.Text>
</InfoPanel.Field>
</InfoPanelText>
</InfoPanelField>
)}
{Number.isInteger(utcOffset) && canViewAllInfo && (
<InfoPanel.Field>
<InfoPanel.Label>{t('Last_login')}</InfoPanel.Label>
<InfoPanel.Text>{lastLogin ? timeAgo(lastLogin) : t('Never')}</InfoPanel.Text>
</InfoPanel.Field>
<InfoPanelField>
<InfoPanelLabel>{t('Last_login')}</InfoPanelLabel>
<InfoPanelText>{lastLogin ? timeAgo(lastLogin) : t('Never')}</InfoPanelText>
</InfoPanelField>
)}
{phone && (
<InfoPanel.Field>
<InfoPanel.Label>{t('Phone')}</InfoPanel.Label>
<InfoPanel.Text display='flex' flexDirection='row' alignItems='center'>
<InfoPanelField>
<InfoPanelLabel>{t('Phone')}</InfoPanelLabel>
<InfoPanelText display='flex' flexDirection='row' alignItems='center'>
<Box is='a' withTruncatedText href={`tel:${phone}`}>
{phone}
</Box>
</InfoPanel.Text>
</InfoPanel.Field>
</InfoPanelText>
</InfoPanelField>
)}
{email && (
<InfoPanel.Field>
<InfoPanel.Label>{t('Email')}</InfoPanel.Label>
<InfoPanel.Text display='flex' flexDirection='row' alignItems='center'>
<InfoPanelField>
<InfoPanelLabel>{t('Email')}</InfoPanelLabel>
<InfoPanelText display='flex' flexDirection='row' alignItems='center'>
<Box is='a' withTruncatedText href={`mailto:${email}`}>
{email}
</Box>
<Margins inline={4}>
<Tag>{verified ? t('Verified') : t('Not_verified')}</Tag>
</Margins>
</InfoPanel.Text>
</InfoPanel.Field>
</InfoPanelText>
</InfoPanelField>
)}
{userCustomFields?.map(
(customField) =>
customField?.value && (
<InfoPanel.Field key={customField.value}>
<InfoPanel.Label>{t(customField.label as TranslationKey)}</InfoPanel.Label>
<InfoPanel.Text>
<InfoPanelField key={customField.value}>
<InfoPanelLabel>{t(customField.label as TranslationKey)}</InfoPanelLabel>
<InfoPanelText>
<MarkdownText content={customField.value} variant='inline' />
</InfoPanel.Text>
</InfoPanel.Field>
</InfoPanelText>
</InfoPanelField>
),
)}
{createdAt && (
<InfoPanel.Field>
<InfoPanel.Label>{t('Created_at')}</InfoPanel.Label>
<InfoPanel.Text>{timeAgo(createdAt)}</InfoPanel.Text>
</InfoPanel.Field>
<InfoPanelField>
<InfoPanelLabel>{t('Created_at')}</InfoPanelLabel>
<InfoPanelText>{timeAgo(createdAt)}</InfoPanelText>
</InfoPanelField>
)}
</InfoPanel.Section>
</InfoPanelSection>
</InfoPanel>
</ContextualbarScrollableContent>
);

@ -1,13 +1,4 @@
import InfoPanel from '../InfoPanel';
import UserInfo from './UserInfo';
import UserInfoAction from './UserInfoAction';
import UserInfoAvatar from './UserInfoAvatar';
import UserInfoUsername from './UserInfoUsername';
export default Object.assign(UserInfo, {
Action: UserInfoAction,
Avatar: UserInfoAvatar,
Info: InfoPanel.Text,
Label: InfoPanel.Label,
Username: UserInfoUsername,
});
export { default as UserInfo } from './UserInfo';
export { default as UserInfoAction } from './UserInfoAction';
export { default as UserInfoAvatar } from './UserInfoAvatar';
export { default as UserInfoUsername } from './UserInfoUsername';

@ -1,7 +1,7 @@
import { useTranslation } from '@rocket.chat/ui-contexts';
import React from 'react';
import UserInfo from '../../components/UserInfo';
import { InfoPanelLabel, InfoPanelText } from '../../components/InfoPanel';
import { useHasLicenseModule } from '../../hooks/useHasLicenseModule';
const MaxChatsPerAgentDisplay = ({ maxNumberSimultaneousChat = 0 }) => {
@ -14,8 +14,8 @@ const MaxChatsPerAgentDisplay = ({ maxNumberSimultaneousChat = 0 }) => {
return (
<>
<UserInfo.Label>{t('Max_number_of_chats_per_agent')}</UserInfo.Label>
<UserInfo.Info>{maxNumberSimultaneousChat}</UserInfo.Info>
<InfoPanelLabel>{t('Max_number_of_chats_per_agent')}</InfoPanelLabel>
<InfoPanelText>{maxNumberSimultaneousChat}</InfoPanelText>
</>
);
};

@ -13,7 +13,7 @@ import {
ContextualbarFooter,
ContextualbarTitle,
} from '../../../../components/Contextualbar';
import InfoPanel from '../../../../components/InfoPanel';
import { InfoPanel, InfoPanelField, InfoPanelLabel, InfoPanelText } from '../../../../components/InfoPanel';
import { useDeviceLogout } from '../../../../hooks/useDeviceLogout';
import { useFormatDateAndTime } from '../../../../hooks/useFormatDateAndTime';
import { usePresence } from '../../../../hooks/usePresence';
@ -43,24 +43,24 @@ const DeviceManagementInfo = ({ device, sessionId, loginAt, ip, userId, _user, o
</ContextualbarHeader>
<ContextualbarScrollableContent>
<InfoPanel>
<InfoPanel.Field>
<InfoPanel.Label>{t('Client')}</InfoPanel.Label>
<InfoPanel.Text>{clientName}</InfoPanel.Text>
</InfoPanel.Field>
<InfoPanelField>
<InfoPanelLabel>{t('Client')}</InfoPanelLabel>
<InfoPanelText>{clientName}</InfoPanelText>
</InfoPanelField>
<InfoPanel.Field>
<InfoPanel.Label>{t('Version')}</InfoPanel.Label>
<InfoPanel.Text>{rcVersion || '—'}</InfoPanel.Text>
</InfoPanel.Field>
<InfoPanelField>
<InfoPanelLabel>{t('Version')}</InfoPanelLabel>
<InfoPanelText>{rcVersion || '—'}</InfoPanelText>
</InfoPanelField>
<InfoPanel.Field>
<InfoPanel.Label>{t('OS')}</InfoPanel.Label>
<InfoPanel.Text>{`${os?.name || ''} ${os?.version || ''}`}</InfoPanel.Text>
</InfoPanel.Field>
<InfoPanelField>
<InfoPanelLabel>{t('OS')}</InfoPanelLabel>
<InfoPanelText>{`${os?.name || ''} ${os?.version || ''}`}</InfoPanelText>
</InfoPanelField>
{username && (
<InfoPanel.Field>
<InfoPanel.Label>{t('User')}</InfoPanel.Label>
<InfoPanelField>
<InfoPanelLabel>{t('User')}</InfoPanelLabel>
<Box>
<UserAvatar username={username} etag={userPresence?.avatarETag} />
<Box is='span' pi={8}>
@ -71,23 +71,23 @@ const DeviceManagementInfo = ({ device, sessionId, loginAt, ip, userId, _user, o
{`(${username})`}
</Box>
</Box>
</InfoPanel.Field>
</InfoPanelField>
)}
<InfoPanel.Field>
<InfoPanel.Label>{t('Last_login')}</InfoPanel.Label>
<InfoPanel.Text>{formatDateAndTime(loginAt)}</InfoPanel.Text>
</InfoPanel.Field>
<InfoPanelField>
<InfoPanelLabel>{t('Last_login')}</InfoPanelLabel>
<InfoPanelText>{formatDateAndTime(loginAt)}</InfoPanelText>
</InfoPanelField>
<InfoPanel.Field>
<InfoPanel.Label>{t('Device_ID')}</InfoPanel.Label>
<InfoPanel.Text>{sessionId}</InfoPanel.Text>
</InfoPanel.Field>
<InfoPanelField>
<InfoPanelLabel>{t('Device_ID')}</InfoPanelLabel>
<InfoPanelText>{sessionId}</InfoPanelText>
</InfoPanelField>
<InfoPanel.Field>
<InfoPanel.Label>{t('IP_Address')}</InfoPanel.Label>
<InfoPanel.Text>{ip}</InfoPanel.Text>
</InfoPanel.Field>
<InfoPanelField>
<InfoPanelLabel>{t('IP_Address')}</InfoPanelLabel>
<InfoPanelText>{ip}</InfoPanelText>
</InfoPanelField>
</InfoPanel>
</ContextualbarScrollableContent>
<ContextualbarFooter>

@ -4,7 +4,7 @@ import { useRoute, usePermission, useTranslation } from '@rocket.chat/ui-context
import type { ReactElement } from 'react';
import React, { useCallback, useMemo } from 'react';
import UserInfo from '../../../components/UserInfo';
import { UserInfoAction } from '../../../components/UserInfo';
import { useActionSpread } from '../../hooks/useActionSpread';
import { useChangeAdminStatusAction } from './hooks/useChangeAdminStatusAction';
import { useChangeUserStatusAction } from './hooks/useChangeUserStatusAction';
@ -126,7 +126,7 @@ const AdminUserInfoActions = ({
// TODO: sanitize Action type to avoid any
const actions = useMemo(() => {
const mapAction = ([key, { label, icon, action, disabled, title }]: any): ReactElement => (
<UserInfo.Action key={key} title={title} label={label} onClick={action} disabled={disabled} icon={icon} />
<UserInfoAction key={key} title={title} label={label} onClick={action} disabled={disabled} icon={icon} />
);
return [...actionsDefinition.map(mapAction), menu].filter(Boolean);
}, [actionsDefinition, menu]);

@ -10,7 +10,7 @@ import { getUserEmailAddress } from '../../../../lib/getUserEmailAddress';
import { ContextualbarContent } from '../../../components/Contextualbar';
import { FormSkeleton } from '../../../components/Skeleton';
import { UserCardRole } from '../../../components/UserCard';
import UserInfo from '../../../components/UserInfo';
import { UserInfo } from '../../../components/UserInfo';
import { UserStatus } from '../../../components/UserStatus';
import { getUserEmailVerified } from '../../../lib/utils/getUserEmailVerified';
import AdminUserInfoActions from './AdminUserInfoActions';

@ -29,7 +29,7 @@ import {
ContextualbarHeader,
ContextualbarScrollableContent,
} from '../../../components/Contextualbar';
import UserInfo from '../../../components/UserInfo';
import { UserInfoAvatar } from '../../../components/UserInfo';
import { MaxChatsPerAgent } from '../additionalForms';
type AgentEditProps = {
@ -123,7 +123,7 @@ const AgentEdit = ({ agentData, userDepartments, availableDepartments }: AgentEd
<form id={formId} onSubmit={handleSubmit(handleSave)}>
{username && (
<Box display='flex' flexDirection='column' alignItems='center'>
<UserInfo.Avatar data-qa-id='agent-edit-avatar' username={username} />
<UserInfoAvatar data-qa-id='agent-edit-avatar' username={username} />
</Box>
)}
<FieldGroup>

@ -11,7 +11,8 @@ import {
ContextualbarHeader,
ContextualbarScrollableContent,
} from '../../../components/Contextualbar';
import UserInfo from '../../../components/UserInfo';
import { InfoPanelLabel, InfoPanelText } from '../../../components/InfoPanel';
import { UserInfoAvatar, UserInfoUsername } from '../../../components/UserInfo';
import { UserStatus } from '../../../components/UserStatus';
import { MaxChatsPerAgentDisplay } from '../additionalForms';
import AgentInfoAction from './AgentInfoAction';
@ -50,7 +51,7 @@ const AgentInfo = ({ uid }: AgentInfoProps) => {
<ContextualbarScrollableContent>
{username && (
<Box alignSelf='center'>
<UserInfo.Avatar data-qa='AgentUserInfoAvatar' username={username} />
<UserInfoAvatar data-qa='AgentUserInfoAvatar' username={username} />
</Box>
)}
<ButtonGroup align='center'>
@ -65,12 +66,12 @@ const AgentInfo = ({ uid }: AgentInfoProps) => {
</ButtonGroup>
<Margins block={4}>
<Box mb={2}>
<UserInfo.Username data-qa='AgentInfoUserInfoUserName' username={username} status={<UserStatus status={userStatus} />} />
<UserInfoUsername data-qa='AgentInfoUserInfoUserName' username={username} status={<UserStatus status={userStatus} />} />
</Box>
{statusLivechat && (
<>
<UserInfo.Label data-qa='AgentInfoUserInfoLabel'>{t('Livechat_status')}</UserInfo.Label>
<UserInfo.Info>{t(statusLivechat === 'available' ? 'Available' : 'Not_Available')}</UserInfo.Info>
<InfoPanelLabel data-qa='AgentInfoUserInfoLabel'>{t('Livechat_status')}</InfoPanelLabel>
<InfoPanelText>{t(statusLivechat === 'available' ? 'Available' : 'Not_Available')}</InfoPanelText>
</>
)}
{MaxChatsPerAgentDisplay && <MaxChatsPerAgentDisplay maxNumberSimultaneousChat={data.user.livechat?.maxNumberSimultaneousChat} />}

@ -1,7 +1,7 @@
import type { ReactElement } from 'react';
import React from 'react';
import InfoPanel from '../../../../../components/InfoPanel';
import { InfoPanelField, InfoPanelLabel, InfoPanelText } from '../../../../../components/InfoPanel';
type InfoFieldPropsType = {
label: string;
@ -9,8 +9,8 @@ type InfoFieldPropsType = {
};
export const InfoField = ({ label, info }: InfoFieldPropsType): ReactElement => (
<InfoPanel.Field>
<InfoPanel.Label>{label}</InfoPanel.Label>
<InfoPanel.Text>{info}</InfoPanel.Text>
</InfoPanel.Field>
<InfoPanelField>
<InfoPanelLabel>{label}</InfoPanelLabel>
<InfoPanelText>{info}</InfoPanelText>
</InfoPanelField>
);

@ -14,7 +14,7 @@ import {
ContextualbarScrollableContent,
ContextualbarFooter,
} from '../../../../../components/Contextualbar';
import InfoPanel from '../../../../../components/InfoPanel';
import { InfoPanel, InfoPanelField, InfoPanelLabel, InfoPanelText } from '../../../../../components/InfoPanel';
import { UserStatus } from '../../../../../components/UserStatus';
import { useIsCallReady } from '../../../../../contexts/CallContext';
import { parseOutboundPhoneNumber } from '../../../../../lib/voip/parseOutboundPhoneNumber';
@ -52,22 +52,22 @@ export const VoipInfo = ({ room, onClickClose /* , onClickReport */ }: VoipInfo
</ContextualbarHeader>
<ContextualbarScrollableContent>
<InfoPanel>
<InfoPanel.Field>
<InfoPanel.Label>{t('Channel')}</InfoPanel.Label>
<InfoPanelField>
<InfoPanelLabel>{t('Channel')}</InfoPanelLabel>
<Box color='default'>
<Icon size='x24' name='phone' verticalAlign='middle' />
{t('Voice_Call')}
</Box>
</InfoPanel.Field>
</InfoPanelField>
{servedBy && <AgentField isSmall agent={servedBy} />}
{v && _name && (
<InfoPanel.Field>
<InfoPanel.Label>{t('Contact')}</InfoPanel.Label>
<InfoPanelField>
<InfoPanelLabel>{t('Contact')}</InfoPanelLabel>
<Box display='flex'>
<UserAvatar size='x28' username={_name} />
<AgentInfoDetails mis={8} name={parseOutboundPhoneNumber(_name)} status={<UserStatus status={v?.status} />} />
</Box>
</InfoPanel.Field>
</InfoPanelField>
)}
{phoneNumber && <InfoField label={t('Caller_Id')} info={parseOutboundPhoneNumber(phoneNumber)} />}
{queue && <InfoField label={t('Queue')} info={queue} />}
@ -75,11 +75,11 @@ export const VoipInfo = ({ room, onClickClose /* , onClickReport */ }: VoipInfo
<InfoField label={t('Waiting_Time')} info={waiting || t('Not_Available')} />
<InfoField label={t('Talk_Time')} info={duration || t('Not_Available')} />
<InfoField label={t('Hold_Time')} info={hold || t('Not_Available')} />
<InfoPanel.Field>
<InfoPanel.Label>{t('Wrap_Up_Notes')}</InfoPanel.Label>
<InfoPanel.Text withTruncatedText={false}>{shouldShowWrapup ? lastMessage?.msg : t('Not_Available')}</InfoPanel.Text>
<InfoPanelField>
<InfoPanelLabel>{t('Wrap_Up_Notes')}</InfoPanelLabel>
<InfoPanelText withTruncatedText={false}>{shouldShowWrapup ? lastMessage?.msg : t('Not_Available')}</InfoPanelText>
{shouldShowTags && (
<InfoPanel.Text>
<InfoPanelText>
<Box display='flex' flexDirection='row' alignItems='center'>
{tags?.map((tag: string) => (
<Chip mie={4} key={tag} value={tag}>
@ -87,9 +87,9 @@ export const VoipInfo = ({ room, onClickClose /* , onClickReport */ }: VoipInfo
</Chip>
))}
</Box>
</InfoPanel.Text>
</InfoPanelText>
)}
</InfoPanel.Field>
</InfoPanelField>
</InfoPanel>
</ContextualbarScrollableContent>
<ContextualbarFooter>

@ -12,7 +12,17 @@ import {
ContextualbarClose,
ContextualbarTitle,
} from '../../../../../components/Contextualbar';
import InfoPanel from '../../../../../components/InfoPanel';
import {
InfoPanel,
InfoPanelAction,
InfoPanelActionGroup,
InfoPanelAvatar,
InfoPanelField,
InfoPanelLabel,
InfoPanelSection,
InfoPanelText,
InfoPanelTitle,
} from '../../../../../components/InfoPanel';
import RetentionPolicyCallout from '../../../../../components/InfoPanel/RetentionPolicyCallout';
import MarkdownText from '../../../../../components/MarkdownText';
import type { Action } from '../../../../hooks/useActionSpread';
@ -61,7 +71,7 @@ const RoomInfo = ({ room, icon, onClickBack, onClickClose, onClickEnterRoom, onC
const actions = useMemo(() => {
const mapAction = ([key, { label, icon, action }]: [string, Action]) => (
<InfoPanel.Action key={key} label={label} onClick={action} icon={icon} />
<InfoPanelAction key={key} label={label} onClick={action} icon={icon} />
);
return [...actionsDefinition.map(mapAction), menu].filter(Boolean);
@ -77,66 +87,66 @@ const RoomInfo = ({ room, icon, onClickBack, onClickClose, onClickEnterRoom, onC
<ContextualbarScrollableContent p={24}>
<InfoPanel>
<InfoPanel.Section maxWidth='x332' mi='auto'>
<InfoPanel.Avatar>
<InfoPanelSection maxWidth='x332' mi='auto'>
<InfoPanelAvatar>
<RoomAvatar size='x332' room={room} />
</InfoPanel.Avatar>
</InfoPanelAvatar>
<InfoPanel.ActionGroup>{actions}</InfoPanel.ActionGroup>
</InfoPanel.Section>
<InfoPanelActionGroup>{actions}</InfoPanelActionGroup>
</InfoPanelSection>
{archived && (
<InfoPanel.Section>
<InfoPanelSection>
<Box mb={16}>
<Callout type='warning'>{t('Room_archived')}</Callout>
</Box>
</InfoPanel.Section>
</InfoPanelSection>
)}
{roomTitle && (
<InfoPanel.Section>
<InfoPanel.Title title={roomTitle} icon={icon} />
</InfoPanel.Section>
<InfoPanelSection>
<InfoPanelTitle title={roomTitle} icon={icon} />
</InfoPanelSection>
)}
<InfoPanel.Section>
<InfoPanelSection>
{broadcast && (
<InfoPanel.Field>
<InfoPanel.Label>
<InfoPanelField>
<InfoPanelLabel>
<b>{t('Broadcast_channel')}</b> {t('Broadcast_channel_Description')}
</InfoPanel.Label>
</InfoPanel.Field>
</InfoPanelLabel>
</InfoPanelField>
)}
{description && description !== '' && (
<InfoPanel.Field>
<InfoPanel.Label>{t('Description')}</InfoPanel.Label>
<InfoPanel.Text withTruncatedText={false}>
<InfoPanelField>
<InfoPanelLabel>{t('Description')}</InfoPanelLabel>
<InfoPanelText withTruncatedText={false}>
<MarkdownText variant='inline' content={description} />
</InfoPanel.Text>
</InfoPanel.Field>
</InfoPanelText>
</InfoPanelField>
)}
{announcement && announcement !== '' && (
<InfoPanel.Field>
<InfoPanel.Label>{t('Announcement')}</InfoPanel.Label>
<InfoPanel.Text withTruncatedText={false}>
<InfoPanelField>
<InfoPanelLabel>{t('Announcement')}</InfoPanelLabel>
<InfoPanelText withTruncatedText={false}>
<MarkdownText variant='inline' content={announcement} />
</InfoPanel.Text>
</InfoPanel.Field>
</InfoPanelText>
</InfoPanelField>
)}
{topic && topic !== '' && (
<InfoPanel.Field>
<InfoPanel.Label>{t('Topic')}</InfoPanel.Label>
<InfoPanel.Text withTruncatedText={false}>
<InfoPanelField>
<InfoPanelLabel>{t('Topic')}</InfoPanelLabel>
<InfoPanelText withTruncatedText={false}>
<MarkdownText variant='inline' content={topic} />
</InfoPanel.Text>
</InfoPanel.Field>
</InfoPanelText>
</InfoPanelField>
)}
{retentionPolicy?.isActive && <RetentionPolicyCallout room={room} />}
</InfoPanel.Section>
</InfoPanelSection>
</InfoPanel>
</ContextualbarScrollableContent>
</>

@ -6,7 +6,7 @@ import type { ReactElement } from 'react';
import React, { useMemo } from 'react';
import GenericMenu from '../../../../components/GenericMenu/GenericMenu';
import UserInfo from '../../../../components/UserInfo';
import { UserInfoAction } from '../../../../components/UserInfo';
import { useUserInfoActions } from '../../hooks/useUserInfoActions';
type UserInfoActionsProps = {
@ -45,7 +45,7 @@ const UserInfoActions = ({ user, rid, backToList }: UserInfoActionsProps): React
// TODO: sanitize Action type to avoid any
const actions = useMemo(() => {
const mapAction = ([key, { content, icon, onClick }]: any): ReactElement => (
<UserInfo.Action key={key} title={content} label={content} onClick={onClick} icon={icon} />
<UserInfoAction key={key} title={content} label={content} onClick={onClick} icon={icon} />
);
return [...actionsDefinition.map(mapAction), menu].filter(Boolean);

@ -15,7 +15,7 @@ import {
} from '../../../../components/Contextualbar';
import { FormSkeleton } from '../../../../components/Skeleton';
import { UserCardRole } from '../../../../components/UserCard';
import UserInfo from '../../../../components/UserInfo';
import { UserInfo } from '../../../../components/UserInfo';
import { ReactiveUserStatus } from '../../../../components/UserStatus';
import { AsyncStatePhase } from '../../../../hooks/useAsyncState';
import { useEndpointData } from '../../../../hooks/useEndpointData';

@ -12,7 +12,17 @@ import {
ContextualbarClose,
ContextualbarScrollableContent,
} from '../../../../components/Contextualbar';
import InfoPanel from '../../../../components/InfoPanel';
import {
InfoPanel,
InfoPanelAction,
InfoPanelActionGroup,
InfoPanelAvatar,
InfoPanelField,
InfoPanelLabel,
InfoPanelSection,
InfoPanelText,
InfoPanelTitle,
} from '../../../../components/InfoPanel';
import RetentionPolicyCallout from '../../../../components/InfoPanel/RetentionPolicyCallout';
import MarkdownText from '../../../../components/MarkdownText';
import type { Action } from '../../../hooks/useActionSpread';
@ -108,7 +118,7 @@ const TeamsInfo = ({
const actions = useMemo(() => {
const mapAction = ([key, { label, icon, action }]: [string, Action]): ReactElement => (
<InfoPanel.Action key={key} label={label as string} onClick={action} icon={icon} />
<InfoPanelAction key={key} label={label as string} onClick={action} icon={icon} />
);
return [...actionsDefinition.map(mapAction), menu].filter(Boolean);
@ -123,75 +133,75 @@ const TeamsInfo = ({
</ContextualbarHeader>
<ContextualbarScrollableContent p={24}>
<InfoPanel>
<InfoPanel.Section maxWidth='x332' mi='auto'>
<InfoPanel.Avatar>
<InfoPanelSection maxWidth='x332' mi='auto'>
<InfoPanelAvatar>
<RoomAvatar size='x332' room={room} />
</InfoPanel.Avatar>
</InfoPanelAvatar>
<InfoPanel.ActionGroup>{actions}</InfoPanel.ActionGroup>
</InfoPanel.Section>
<InfoPanelActionGroup>{actions}</InfoPanelActionGroup>
</InfoPanelSection>
<InfoPanel.Section>
<InfoPanelSection>
{room.archived && (
<Box mb={16}>
<Callout type='warning'>{t('Room_archived')}</Callout>
</Box>
)}
</InfoPanel.Section>
</InfoPanelSection>
<InfoPanel.Section>
<InfoPanel.Title title={room.fname || room.name || ''} icon='team' />
</InfoPanel.Section>
<InfoPanelSection>
<InfoPanelTitle title={room.fname || room.name || ''} icon='team' />
</InfoPanelSection>
<InfoPanel.Section>
<InfoPanelSection>
{room.broadcast && (
<InfoPanel.Field>
<InfoPanel.Label>
<InfoPanelField>
<InfoPanelLabel>
<b>{t('Broadcast_channel')}</b> {t('Broadcast_channel_Description')}
</InfoPanel.Label>
</InfoPanel.Field>
</InfoPanelLabel>
</InfoPanelField>
)}
{room.description && (
<InfoPanel.Field>
<InfoPanel.Label>{t('Description')}</InfoPanel.Label>
<InfoPanel.Text withTruncatedText={false}>
<InfoPanelField>
<InfoPanelLabel>{t('Description')}</InfoPanelLabel>
<InfoPanelText withTruncatedText={false}>
<MarkdownText variant='inline' content={room.description} />
</InfoPanel.Text>
</InfoPanel.Field>
</InfoPanelText>
</InfoPanelField>
)}
{room.announcement && (
<InfoPanel.Field>
<InfoPanel.Label>{t('Announcement')}</InfoPanel.Label>
<InfoPanel.Text withTruncatedText={false}>
<InfoPanelField>
<InfoPanelLabel>{t('Announcement')}</InfoPanelLabel>
<InfoPanelText withTruncatedText={false}>
<MarkdownText variant='inline' content={room.announcement} />
</InfoPanel.Text>
</InfoPanel.Field>
</InfoPanelText>
</InfoPanelField>
)}
{room.topic && (
<InfoPanel.Field>
<InfoPanel.Label>{t('Topic')}</InfoPanel.Label>
<InfoPanel.Text withTruncatedText={false}>
<InfoPanelField>
<InfoPanelLabel>{t('Topic')}</InfoPanelLabel>
<InfoPanelText withTruncatedText={false}>
<MarkdownText variant='inline' content={room.topic} />
</InfoPanel.Text>
</InfoPanel.Field>
</InfoPanelText>
</InfoPanelField>
)}
{onClickViewChannels && (
<InfoPanel.Field>
<InfoPanel.Label>{t('Teams_channels')}</InfoPanel.Label>
<InfoPanel.Text>
<InfoPanelField>
<InfoPanelLabel>{t('Teams_channels')}</InfoPanelLabel>
<InfoPanelText>
<Button onClick={onClickViewChannels} small>
{t('View_channels')}
</Button>
</InfoPanel.Text>
</InfoPanel.Field>
</InfoPanelText>
</InfoPanelField>
)}
{retentionPolicy?.isActive && <RetentionPolicyCallout room={room} />}
</InfoPanel.Section>
</InfoPanelSection>
</InfoPanel>
</ContextualbarScrollableContent>
</>

Loading…
Cancel
Save