[MM-57369] Remote users no longer labeled as 'remote' after updates to the System Console Users UI (#26612)

* new mixin created for text ellipsis
* shared user indicator api modified
* use shared icon indicator instead of tag
This commit is contained in:
M-ZubairAhmed 2024-03-28 13:49:42 +00:00 committed by GitHub
parent 22c978e223
commit f34fac7731
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 60 additions and 31 deletions

View File

@ -1,8 +1,4 @@
@mixin textElipsis { @import "sass/utils/_mixins";
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
table.systemUsersTable { table.systemUsersTable {
thead { thead {
@ -44,19 +40,25 @@ table.systemUsersTable {
} }
.displayName { .displayName {
display: flex;
align-items: center;
align-self: start; align-self: start;
color: var(--sys-denim-button-bg); color: var(--sys-denim-button-bg);
font-weight: 600; font-weight: 600;
grid-area: displayName; grid-area: displayName;
@include textElipsis; @include textEllipsis;
.icon {
color: rgba(var(--sys-denim-center-channel-text-rgb), 0.8);
}
} }
.userName { .userName {
align-self: start; align-self: start;
grid-area: userName; grid-area: userName;
@include textElipsis; @include textEllipsis;
} }
.error { .error {
@ -64,9 +66,9 @@ table.systemUsersTable {
align-self: start; align-self: start;
grid-area: error; grid-area: error;
@include textElipsis; @include textEllipsis;
// this need to be here, after textElipsis because // this need to be here, after textEllipsis because
// we need to override white-space property coming from the mixing // we need to override white-space property coming from the mixing
white-space: normal; white-space: normal;
} }

View File

@ -17,6 +17,7 @@ import Preferences from 'mattermost-redux/constants/preferences';
import {AdminConsoleListTable, ElapsedDurationCell, PAGE_SIZES, LoadingStates} from 'components/admin_console/list_table'; import {AdminConsoleListTable, ElapsedDurationCell, PAGE_SIZES, LoadingStates} from 'components/admin_console/list_table';
import type {TableMeta} from 'components/admin_console/list_table'; import type {TableMeta} from 'components/admin_console/list_table';
import AlertBanner from 'components/alert_banner'; import AlertBanner from 'components/alert_banner';
import SharedUserIndicator from 'components/shared_user_indicator';
import AdminHeader from 'components/widgets/admin_console/admin_header'; import AdminHeader from 'components/widgets/admin_console/admin_header';
import {getDisplayName, imageURLForUser} from 'utils/utils'; import {getDisplayName, imageURLForUser} from 'utils/utils';
@ -258,6 +259,7 @@ function SystemUsers(props: Props) {
defaultMessage: 'User details', defaultMessage: 'User details',
}), }),
cell: (info: CellContext<UserReportWithError, null>) => { cell: (info: CellContext<UserReportWithError, null>) => {
const isRemoteUser = Boolean(info.row.original?.remote_id?.length);
return ( return (
<div> <div>
<div className='profilePictureContainer'> <div className='profilePictureContainer'>
@ -272,6 +274,17 @@ function SystemUsers(props: Props) {
title={getDisplayName(info.row.original)} title={getDisplayName(info.row.original)}
> >
{getDisplayName(info.row.original) || ''} {getDisplayName(info.row.original) || ''}
{isRemoteUser && (
<SharedUserIndicator
id={`sharedUserIndicator-${info.row.original.id}`}
title={formatMessage({id: 'admin.system_users.list.userIsRemote', defaultMessage: 'Remote user'})}
ariaLabel={formatMessage({id: 'admin.system_users.list.userIsRemoteAriaLabel', defaultMessage: 'This is a remote user'})}
role='img'
className='icon-12'
withTooltip={true}
placement='top'
/>
)}
</div> </div>
<div <div
className='userName' className='userName'

View File

@ -23,6 +23,7 @@ const FullName = ({
if (remoteId) { if (remoteId) {
sharedIcon = ( sharedIcon = (
<SharedUserIndicator <SharedUserIndicator
id={`sharedUserIndicator-${username}`}
className='shared-user-icon' className='shared-user-icon'
withTooltip={true} withTooltip={true}
/> />

View File

@ -1,26 +1,36 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information. // See LICENSE.txt for license information.
import classNames from 'classnames';
import type {AriaRole, AriaAttributes} from 'react';
import React from 'react'; import React from 'react';
import {FormattedMessage, useIntl} from 'react-intl'; import {useIntl} from 'react-intl';
import OverlayTrigger from 'components/overlay_trigger'; import WithTooltip from 'components/with_tooltip';
import Tooltip from 'components/tooltip';
import {Constants} from 'utils/constants';
type Props = { type Props = {
id: string;
/**
* If not provided, the default title 'From trusted organizations' will be used for the tooltip.
*/
title?: string;
ariaLabel?: AriaAttributes['aria-label'];
role?: AriaRole;
className?: string; className?: string;
withTooltip?: boolean; withTooltip?: boolean;
placement?: string;
}; };
const SharedUserIndicator: React.FC<Props> = (props: Props): JSX.Element => { const SharedUserIndicator = (props: Props) => {
const intl = useIntl(); const intl = useIntl();
const sharedIcon = ( const sharedIcon = (
<i <i
className={`${props.className || ''} icon-circle-multiple-outline`} className={classNames('icon icon-circle-multiple-outline', props.className)}
aria-label={intl.formatMessage({id: 'shared_user_indicator.aria_label', defaultMessage: 'shared user indicator'})} aria-label={props.ariaLabel || intl.formatMessage({id: 'shared_user_indicator.aria_label', defaultMessage: 'shared user indicator'})}
role={props?.role}
/> />
); );
@ -28,23 +38,14 @@ const SharedUserIndicator: React.FC<Props> = (props: Props): JSX.Element => {
return sharedIcon; return sharedIcon;
} }
const sharedTooltip = (
<Tooltip id='sharedTooltip'>
<FormattedMessage
id='shared_user_indicator.tooltip'
defaultMessage='From trusted organizations'
/>
</Tooltip>
);
return ( return (
<OverlayTrigger <WithTooltip
delayShow={Constants.OVERLAY_TIME_DELAY} id={props.id}
placement='bottom' title={props.title || intl.formatMessage({id: 'shared_user_indicator.tooltip', defaultMessage: 'From trusted organizations'})}
overlay={sharedTooltip} placement={props.placement || 'bottom'}
> >
{sharedIcon} {sharedIcon}
</OverlayTrigger> </WithTooltip>
); );
}; };

View File

@ -149,6 +149,7 @@ const AtMentionSuggestion = React.forwardRef<HTMLDivElement, SuggestionProps<Ite
const sharedIcon = item.remote_id ? ( const sharedIcon = item.remote_id ? (
<SharedUserIndicator <SharedUserIndicator
id={`sharedUserIndicator-${item.id}`}
className='shared-user-icon' className='shared-user-icon'
withTooltip={true} withTooltip={true}
/> />

View File

@ -35,6 +35,7 @@ const SearchUserSuggestion = React.forwardRef<HTMLDivElement, SuggestionProps<Us
if (item.remote_id) { if (item.remote_id) {
sharedIcon = ( sharedIcon = (
<SharedUserIndicator <SharedUserIndicator
id={`sharedUserIndicator-${item.id}`}
className='mention__shared-user-icon' className='mention__shared-user-icon'
withTooltip={true} withTooltip={true}
/> />

View File

@ -103,6 +103,7 @@ exports[`components/UserProfile should match snapshot, when user is shared 1`] =
</OverlayTrigger> </OverlayTrigger>
<SharedUserIndicator <SharedUserIndicator
className="shared-user-icon" className="shared-user-icon"
id="sharedUserIndicator-user_id"
withTooltip={true} withTooltip={true}
/> />
</Fragment> </Fragment>

View File

@ -118,6 +118,7 @@ export default class UserProfile extends PureComponent<Props> {
if (isShared) { if (isShared) {
sharedIcon = ( sharedIcon = (
<SharedUserIndicator <SharedUserIndicator
id={`sharedUserIndicator-${userId}`}
className='shared-user-icon' className='shared-user-icon'
withTooltip={true} withTooltip={true}
/> />

View File

@ -2557,6 +2557,8 @@
"admin.system_users.list.memberSince.yesterday": "Yesterday", "admin.system_users.list.memberSince.yesterday": "Yesterday",
"admin.system_users.list.totalPosts": "Messages posted", "admin.system_users.list.totalPosts": "Messages posted",
"admin.system_users.list.userDetails": "User details", "admin.system_users.list.userDetails": "User details",
"admin.system_users.list.userIsRemote": "Remote user",
"admin.system_users.list.userIsRemoteAriaLabel": "This is a remote user",
"admin.system_users.mysql_stats.desc": "Use of MySQL may limit the availability of some statistics features. We recommend transitioning from MySQL to PostgreSQL to fully leverage improved performance and comprehensive analytics. While youre still using MySQL, please use the export functionality to view all user statistics.", "admin.system_users.mysql_stats.desc": "Use of MySQL may limit the availability of some statistics features. We recommend transitioning from MySQL to PostgreSQL to fully leverage improved performance and comprehensive analytics. While youre still using MySQL, please use the export functionality to view all user statistics.",
"admin.system_users.mysql_stats.dismiss": "Dismiss", "admin.system_users.mysql_stats.dismiss": "Dismiss",
"admin.system_users.mysql_stats.learn_more": "Learn more", "admin.system_users.mysql_stats.learn_more": "Learn more",

View File

@ -414,3 +414,9 @@
transform: translate3d(4px, 0, 0); transform: translate3d(4px, 0, 0);
} }
} }
@mixin textEllipsis {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}