mirror of
https://github.com/logto-io/logto.git
synced 2025-01-06 20:40:08 -05:00
fix(console): fix linked social account not shown bug (#3550)
This commit is contained in:
parent
4d1fd8624b
commit
6e2a84ef61
11 changed files with 20 additions and 14 deletions
|
@ -1,6 +1,7 @@
|
|||
import type { IdTokenClaims } from '@logto/react';
|
||||
import type { User } from '@logto/schemas';
|
||||
import classNames from 'classnames';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import UserAvatar from '../UserAvatar';
|
||||
import * as styles from './index.module.scss';
|
||||
|
@ -15,6 +16,8 @@ type Props = {
|
|||
};
|
||||
|
||||
const UserInfoCard = ({ className, user, avatarSize = 'medium' }: Props) => {
|
||||
const { t } = useTranslation(undefined, { keyPrefix: 'admin_console' });
|
||||
|
||||
const { name, username, avatar, picture, primaryEmail, email } = user ?? {};
|
||||
const avatarToDisplay = avatar ?? picture;
|
||||
const nameToDisplay = name ?? username;
|
||||
|
@ -29,6 +32,9 @@ const UserInfoCard = ({ className, user, avatarSize = 'medium' }: Props) => {
|
|||
<div className={styles.nameWrapper}>
|
||||
<div className={styles.name}>{nameToDisplay}</div>
|
||||
{emailToDisplay && <div className={styles.email}>{emailToDisplay}</div>}
|
||||
{!nameToDisplay && !emailToDisplay && (
|
||||
<div className={styles.email}>({t('profile.link_account.anonymous')})</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
import type { SocialUserInfo } from '@logto/connector-kit';
|
||||
import { socialUserInfoGuard } from '@logto/connector-kit';
|
||||
import { buildIdGenerator } from '@logto/core-kit';
|
||||
import type { ConnectorResponse, UserInfo } from '@logto/schemas';
|
||||
import { Theme } from '@logto/schemas';
|
||||
|
@ -6,7 +8,6 @@ import { appendPath, conditional } from '@silverhand/essentials';
|
|||
import { useCallback, useMemo } from 'react';
|
||||
import { Trans, useTranslation } from 'react-i18next';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { is } from 'superstruct';
|
||||
|
||||
import MailIcon from '@/assets/images/mail.svg';
|
||||
import FormCard from '@/components/FormCard';
|
||||
|
@ -17,8 +18,6 @@ import { adminTenantEndpoint, getBasename, meApi, profileSocialLinkingKeyPrefix
|
|||
import { useStaticApi } from '@/hooks/use-api';
|
||||
import { useConfirmModal } from '@/hooks/use-confirm-modal';
|
||||
import useTheme from '@/hooks/use-theme';
|
||||
import type { SocialUserInfo } from '@/types/profile';
|
||||
import { socialUserInfoGuard } from '@/types/profile';
|
||||
|
||||
import { popupWindow } from '../../utils';
|
||||
import type { Row } from '../CardContent';
|
||||
|
@ -63,13 +62,15 @@ const LinkAccountSection = ({ user, connectors, onUpdate }: Props) => {
|
|||
return connectors.map(({ id, name, logo, logoDark, target }) => {
|
||||
const logoSrc = theme === Theme.Dark && logoDark ? logoDark : logo;
|
||||
const relatedUserDetails = user.identities?.[target]?.details;
|
||||
const hasLinked = is(relatedUserDetails, socialUserInfoGuard);
|
||||
|
||||
const socialUserInfo = socialUserInfoGuard.safeParse(relatedUserDetails);
|
||||
const hasLinked = socialUserInfo.success;
|
||||
|
||||
return {
|
||||
key: target,
|
||||
icon: <ImageWithErrorFallback src={logoSrc} />,
|
||||
label: <UnnamedTrans resource={name} />,
|
||||
value: conditional(hasLinked && relatedUserDetails),
|
||||
value: conditional(hasLinked && socialUserInfo.data),
|
||||
renderer: (user) => (user ? <UserInfoCard user={user} /> : <NotSet />),
|
||||
action: hasLinked
|
||||
? {
|
||||
|
|
|
@ -6,12 +6,3 @@ export const locationStateGuard = s.object({
|
|||
});
|
||||
|
||||
export type LocationState = s.Infer<typeof locationStateGuard>;
|
||||
|
||||
export const socialUserInfoGuard = s.object({
|
||||
id: s.string(),
|
||||
name: s.string(),
|
||||
email: s.string(),
|
||||
avatar: s.string(),
|
||||
});
|
||||
|
||||
export type SocialUserInfo = s.Infer<typeof socialUserInfoGuard>;
|
||||
|
|
|
@ -19,6 +19,7 @@ const profile = {
|
|||
email_required: 'Email is required', // UNTRANSLATED
|
||||
invalid_email: 'Invalid email address', // UNTRANSLATED
|
||||
identical_email_address: 'The input email address is identical to the current one', // UNTRANSLATED
|
||||
anonymous: 'Anonymous', // UNTRANSLATED
|
||||
},
|
||||
password: {
|
||||
title: 'PASSWORD & SECURITY', // UNTRANSLATED
|
||||
|
|
|
@ -19,6 +19,7 @@ const profile = {
|
|||
email_required: 'Email is required',
|
||||
invalid_email: 'Invalid email address',
|
||||
identical_email_address: 'The input email address is identical to the current one',
|
||||
anonymous: 'Anonymous',
|
||||
},
|
||||
password: {
|
||||
title: 'PASSWORD & SECURITY',
|
||||
|
|
|
@ -19,6 +19,7 @@ const profile = {
|
|||
email_required: 'Email is required', // UNTRANSLATED
|
||||
invalid_email: 'Invalid email address', // UNTRANSLATED
|
||||
identical_email_address: 'The input email address is identical to the current one', // UNTRANSLATED
|
||||
anonymous: 'Anonymous', // UNTRANSLATED
|
||||
},
|
||||
password: {
|
||||
title: 'PASSWORD & SECURITY', // UNTRANSLATED
|
||||
|
|
|
@ -19,6 +19,7 @@ const profile = {
|
|||
email_required: 'Email is required', // UNTRANSLATED
|
||||
invalid_email: 'Invalid email address', // UNTRANSLATED
|
||||
identical_email_address: 'The input email address is identical to the current one', // UNTRANSLATED
|
||||
anonymous: 'Anonymous', // UNTRANSLATED
|
||||
},
|
||||
password: {
|
||||
title: 'PASSWORD & SECURITY', // UNTRANSLATED
|
||||
|
|
|
@ -19,6 +19,7 @@ const profile = {
|
|||
email_required: 'Email is required', // UNTRANSLATED
|
||||
invalid_email: 'Invalid email address', // UNTRANSLATED
|
||||
identical_email_address: 'The input email address is identical to the current one', // UNTRANSLATED
|
||||
anonymous: 'Anonymous', // UNTRANSLATED
|
||||
},
|
||||
password: {
|
||||
title: 'PASSWORD & SECURITY', // UNTRANSLATED
|
||||
|
|
|
@ -19,6 +19,7 @@ const profile = {
|
|||
email_required: 'Email is required', // UNTRANSLATED
|
||||
invalid_email: 'Invalid email address', // UNTRANSLATED
|
||||
identical_email_address: 'The input email address is identical to the current one', // UNTRANSLATED
|
||||
anonymous: 'Anonymous', // UNTRANSLATED
|
||||
},
|
||||
password: {
|
||||
title: 'PASSWORD & SECURITY', // UNTRANSLATED
|
||||
|
|
|
@ -19,6 +19,7 @@ const profile = {
|
|||
email_required: 'Email is required', // UNTRANSLATED
|
||||
invalid_email: 'Invalid email address', // UNTRANSLATED
|
||||
identical_email_address: 'The input email address is identical to the current one', // UNTRANSLATED
|
||||
anonymous: 'Anonymous', // UNTRANSLATED
|
||||
},
|
||||
password: {
|
||||
title: 'PASSWORD & SECURITY', // UNTRANSLATED
|
||||
|
|
|
@ -18,6 +18,7 @@ const profile = {
|
|||
email_required: '邮箱不能为空',
|
||||
invalid_email: '无效的邮箱地址',
|
||||
identical_email_address: '输入的邮箱地址与当前邮箱地址相同',
|
||||
anonymous: '匿名',
|
||||
},
|
||||
password: {
|
||||
title: '密码与安全',
|
||||
|
|
Loading…
Reference in a new issue