0
Fork 0
mirror of https://github.com/logto-io/logto.git synced 2025-03-10 22:22:45 -05:00

refactor(console): add user title display rule (#3701)

This commit is contained in:
Xiao Yijun 2023-04-17 17:55:04 +08:00 committed by GitHub
parent 5ef2d7fb48
commit 8565ab3dba
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 35 additions and 19 deletions

View file

@ -7,7 +7,7 @@
cursor: pointer;
user-select: none;
.name {
.title {
flex: 1 1 0;
font: var(--font-body-2);
@include _.text-ellipsis;

View file

@ -5,6 +5,7 @@ import Checkbox from '@/components/Checkbox';
import UserAvatar from '@/components/UserAvatar';
import SuspendedTag from '@/pages/Users/components/SuspendedTag';
import { onKeyDownHandler } from '@/utils/a11y';
import { getUserTitle } from '@/utils/user';
import * as styles from './index.module.scss';
@ -36,7 +37,7 @@ function SourceUserItem({ user, isSelected, onSelect }: Props) {
}}
/>
<UserAvatar user={user} size="micro" />
<div className={styles.name}>{user.name ?? t('users.unnamed')}</div>
<div className={styles.title}>{getUserTitle(user) ?? t('users.unnamed')}</div>
{user.isSuspended && <SuspendedTag className={styles.suspended} />}
</div>
);

View file

@ -12,7 +12,7 @@
align-items: center;
overflow: hidden;
.name {
.title {
flex: 1 1 0;
font: var(--font-body-2);
@include _.text-ellipsis;

View file

@ -5,6 +5,7 @@ import Close from '@/assets/images/close.svg';
import IconButton from '@/components/IconButton';
import UserAvatar from '@/components/UserAvatar';
import SuspendedTag from '@/pages/Users/components/SuspendedTag';
import { getUserTitle } from '@/utils/user';
import * as styles from './index.module.scss';
@ -20,7 +21,7 @@ function TargetUserItem({ user, onDelete }: Props) {
<div className={styles.item}>
<div className={styles.meta}>
<UserAvatar user={user} size="micro" />
<div className={styles.name}>{user.name ?? t('users.unnamed')}</div>
<div className={styles.title}>{getUserTitle(user) ?? t('users.unnamed')}</div>
{user.isSuspended && <SuspendedTag className={styles.suspended} />}
</div>
<IconButton

View file

@ -25,6 +25,7 @@ import useApi from '@/hooks/use-api';
import useSearchParametersWatcher from '@/hooks/use-search-parameters-watcher';
import SuspendedTag from '@/pages/Users/components/SuspendedTag';
import { buildUrl, formatSearchKeyword } from '@/utils/url';
import { getUserTitle, getUserSubtitle } from '@/utils/user';
import type { RoleDetailsOutletContext } from '../types';
@ -93,15 +94,14 @@ function RoleUsers() {
dataIndex: 'name',
colSpan: 5,
render: (user) => {
const { id, name, isSuspended } = user;
const { id, isSuspended } = user;
return (
<ItemPreview
title={name ?? t('users.unnamed')}
subtitle={id}
icon={<UserAvatar user={user} />}
title={getUserTitle(user) ?? t('users.unnamed')}
subtitle={getUserSubtitle(user)}
icon={<UserAvatar size="large" user={user} />}
to={`/users/${id}`}
size="compact"
suffix={conditional(isSuspended && <SuspendedTag />)}
/>
);

View file

@ -26,7 +26,7 @@
}
}
.name {
.title {
font: var(--font-title-1);
color: var(--color-text);
}
@ -39,7 +39,7 @@
border-radius: 10px;
}
.username {
.subtitle {
color: var(--color-text-secondary);
font: var(--font-label-2);
}

View file

@ -26,6 +26,7 @@ import { UserDetailsTabs } from '@/consts/page-tabs';
import type { RequestError } from '@/hooks/use-api';
import useApi from '@/hooks/use-api';
import * as modalStyles from '@/scss/modal.module.scss';
import { getUserTitle, getUserSubtitle } from '@/utils/user';
import UserAccountInformation from '../../components/UserAccountInformation';
import SuspendedTag from '../Users/components/SuspendedTag';
@ -53,6 +54,8 @@ function UserDetails() {
const api = useApi();
const navigate = useNavigate();
const userSubtitle = data && getUserSubtitle(data);
useEffect(() => {
setIsDeleteFormOpen(false);
setIsResetPasswordFormOpen(false);
@ -111,12 +114,12 @@ function UserDetails() {
<Card className={styles.header}>
<UserAvatar user={data} size="xlarge" />
<div className={styles.metadata}>
<div className={styles.name}>{data.name ?? '-'}</div>
<div className={styles.title}>{getUserTitle(data) ?? t('users.unnamed')}</div>
<div>
{isSuspendedUser && <SuspendedTag />}
{data.username && (
{userSubtitle && (
<>
<div className={styles.username}>{data.username}</div>
<div className={styles.subtitle}>{userSubtitle}</div>
<div className={styles.verticalBar} />
</>
)}

View file

@ -24,6 +24,7 @@ import type { RequestError } from '@/hooks/use-api';
import useSearchParametersWatcher from '@/hooks/use-search-parameters-watcher';
import * as resourcesStyles from '@/scss/resources.module.scss';
import { buildUrl, formatSearchKeyword } from '@/utils/url';
import { getUserTitle, getUserSubtitle } from '@/utils/user';
import CreateForm from './components/CreateForm';
import SuspendedTag from './components/SuspendedTag';
@ -98,15 +99,14 @@ function Users() {
dataIndex: 'name',
colSpan: 6,
render: (user) => {
const { id, name, isSuspended } = user;
const { id, isSuspended } = user;
return (
<ItemPreview
title={name ?? t('users.unnamed')}
subtitle={id}
icon={<UserAvatar user={user} />}
title={getUserTitle(user) ?? t('users.unnamed')}
subtitle={getUserSubtitle(user)}
icon={<UserAvatar size="large" user={user} />}
to={buildDetailsPathname(id)}
size="compact"
suffix={conditional(isSuspended && <SuspendedTag />)}
/>
);

View file

@ -0,0 +1,11 @@
import { type User } from '@logto/schemas';
import { conditional } from '@silverhand/essentials';
const getUserIdentity = (user: User) => {
const { primaryEmail, primaryPhone, username } = user;
return primaryEmail ?? primaryPhone ?? username;
};
export const getUserTitle = (user: User) => user.name ?? getUserIdentity(user);
export const getUserSubtitle = (user: User) => conditional(user.name && getUserIdentity(user));