mirror of
https://github.com/logto-io/logto.git
synced 2024-12-16 20:26:19 -05:00
feat(console): display user password information on user details page (#6544)
This commit is contained in:
parent
27d2c91d2e
commit
f150a67d58
24 changed files with 198 additions and 99 deletions
6
.changeset/brave-horses-knock.md
Normal file
6
.changeset/brave-horses-knock.md
Normal file
|
@ -0,0 +1,6 @@
|
|||
---
|
||||
"@logto/console": minor
|
||||
"@logto/phrases": minor
|
||||
---
|
||||
|
||||
display user password information on user details page
|
|
@ -0,0 +1,34 @@
|
|||
@use '@/scss/underscore' as _;
|
||||
|
||||
.password {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
user-select: none;
|
||||
border: 1px solid var(--color-divider);
|
||||
border-radius: 12px;
|
||||
padding: _.unit(3) _.unit(6);
|
||||
justify-content: space-between;
|
||||
font: var(--font-body-2);
|
||||
|
||||
.label {
|
||||
flex: 5;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.icon {
|
||||
margin-right: _.unit(3);
|
||||
color: var(--color-text-secondary);
|
||||
}
|
||||
}
|
||||
|
||||
.text {
|
||||
flex: 8;
|
||||
color: var(--color-text-secondary);
|
||||
}
|
||||
|
||||
.actionButton {
|
||||
flex: 3;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,102 @@
|
|||
import { type UserProfileResponse } from '@logto/schemas';
|
||||
import { useRef, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import ReactModal from 'react-modal';
|
||||
|
||||
import Key from '@/assets/icons/key.svg?react';
|
||||
import UserAccountInformation from '@/components/UserAccountInformation';
|
||||
import Button from '@/ds-components/Button';
|
||||
import DynamicT from '@/ds-components/DynamicT';
|
||||
import modalStyles from '@/scss/modal.module.scss';
|
||||
|
||||
import ResetPasswordForm from '../../components/ResetPasswordForm';
|
||||
|
||||
import styles from './index.module.scss';
|
||||
|
||||
type Props = {
|
||||
readonly user: UserProfileResponse;
|
||||
readonly onResetPassword: () => void;
|
||||
};
|
||||
|
||||
function UserPassword({ user, onResetPassword }: Props) {
|
||||
const { t } = useTranslation(undefined, { keyPrefix: 'admin_console' });
|
||||
const { hasPassword = false } = user;
|
||||
|
||||
const [isResetPasswordFormOpen, setIsResetPasswordFormOpen] = useState(false);
|
||||
const [newPassword, setNewPassword] = useState<string>();
|
||||
|
||||
// Use a ref to store the initial state of hasPassword to determine which title to show when the password has been reset
|
||||
const initialHasPassword = useRef(hasPassword);
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className={styles.password}>
|
||||
<div className={styles.label}>
|
||||
<Key className={styles.icon} />
|
||||
<span>
|
||||
<DynamicT forKey="user_details.field_password" />
|
||||
</span>
|
||||
</div>
|
||||
<div className={styles.text}>
|
||||
<DynamicT
|
||||
forKey={`user_details.${hasPassword ? 'password_already_set' : 'no_password_set'}`}
|
||||
/>
|
||||
</div>
|
||||
<div className={styles.actionButton}>
|
||||
<Button
|
||||
title={`general.${hasPassword ? 'reset' : 'generate'}`}
|
||||
type="text"
|
||||
size="small"
|
||||
onClick={() => {
|
||||
setIsResetPasswordFormOpen(true);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<ReactModal
|
||||
shouldCloseOnEsc
|
||||
isOpen={isResetPasswordFormOpen}
|
||||
className={modalStyles.content}
|
||||
overlayClassName={modalStyles.overlay}
|
||||
onRequestClose={() => {
|
||||
setIsResetPasswordFormOpen(false);
|
||||
}}
|
||||
>
|
||||
<ResetPasswordForm
|
||||
userId={user.id}
|
||||
hasPassword={hasPassword}
|
||||
onClose={(password) => {
|
||||
setIsResetPasswordFormOpen(false);
|
||||
|
||||
if (password) {
|
||||
setNewPassword(password);
|
||||
onResetPassword();
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</ReactModal>
|
||||
{newPassword && (
|
||||
<UserAccountInformation
|
||||
title={`user_details.reset_password.${
|
||||
initialHasPassword.current ? 'reset_complete' : 'generate_complete'
|
||||
}`}
|
||||
user={user}
|
||||
password={newPassword}
|
||||
passwordLabel={t(
|
||||
`user_details.reset_password.${
|
||||
initialHasPassword.current ? 'new_password' : 'password'
|
||||
}`
|
||||
)}
|
||||
onClose={() => {
|
||||
setNewPassword(undefined);
|
||||
// Update the initial state to true once the user has acknowledged the new password
|
||||
// eslint-disable-next-line @silverhand/fp/no-mutation
|
||||
initialHasPassword.current = true;
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export default UserPassword;
|
|
@ -28,6 +28,7 @@ import { userDetailsParser } from '../utils';
|
|||
|
||||
import PersonalAccessTokens from './PersonalAccessTokens';
|
||||
import UserMfaVerifications from './UserMfaVerifications';
|
||||
import UserPassword from './UserPassword';
|
||||
import UserSocialIdentities from './UserSocialIdentities';
|
||||
import UserSsoIdentities from './UserSsoIdentities';
|
||||
|
||||
|
@ -150,6 +151,14 @@ function UserSettings() {
|
|||
placeholder={t('users.placeholder_username')}
|
||||
/>
|
||||
</FormField>
|
||||
<FormField title="user_details.field_password">
|
||||
<UserPassword
|
||||
user={user}
|
||||
onResetPassword={() => {
|
||||
onUserUpdated({ ...user, hasPassword: true });
|
||||
}}
|
||||
/>
|
||||
</FormField>
|
||||
<FormField title="user_details.field_connectors">
|
||||
<UserSocialIdentities
|
||||
userId={user.id}
|
||||
|
|
|
@ -8,10 +8,11 @@ import { generateRandomPassword } from '@/utils/password';
|
|||
|
||||
type Props = {
|
||||
readonly userId: string;
|
||||
readonly hasPassword: boolean;
|
||||
readonly onClose?: (password?: string) => void;
|
||||
};
|
||||
|
||||
function ResetPasswordForm({ onClose, userId }: Props) {
|
||||
function ResetPasswordForm({ onClose, userId, hasPassword }: Props) {
|
||||
const { t } = useTranslation(undefined, {
|
||||
keyPrefix: 'admin_console',
|
||||
});
|
||||
|
@ -29,7 +30,7 @@ function ResetPasswordForm({ onClose, userId }: Props) {
|
|||
return (
|
||||
<ConfirmModal
|
||||
isOpen
|
||||
title="user_details.reset_password.title"
|
||||
title={`user_details.reset_password.${hasPassword ? 'reset_title' : 'generate_title'}`}
|
||||
isLoading={isLoading}
|
||||
onCancel={() => {
|
||||
onClose?.();
|
||||
|
|
|
@ -3,13 +3,11 @@ import classNames from 'classnames';
|
|||
import { useEffect, useState } from 'react';
|
||||
import { toast } from 'react-hot-toast';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import ReactModal from 'react-modal';
|
||||
import { Outlet, useLocation, useParams } from 'react-router-dom';
|
||||
import useSWR from 'swr';
|
||||
|
||||
import Delete from '@/assets/icons/delete.svg?react';
|
||||
import Forbidden from '@/assets/icons/forbidden.svg?react';
|
||||
import Reset from '@/assets/icons/reset.svg?react';
|
||||
import Shield from '@/assets/icons/shield.svg?react';
|
||||
import DetailsPage from '@/components/DetailsPage';
|
||||
import DetailsPageHeader from '@/components/DetailsPage/DetailsPageHeader';
|
||||
|
@ -22,14 +20,11 @@ import TabNav, { TabNavItem } from '@/ds-components/TabNav';
|
|||
import type { RequestError } from '@/hooks/use-api';
|
||||
import useApi from '@/hooks/use-api';
|
||||
import useTenantPathname from '@/hooks/use-tenant-pathname';
|
||||
import modalStyles from '@/scss/modal.module.scss';
|
||||
import { buildUrl } from '@/utils/url';
|
||||
import { getUserTitle, getUserSubtitle } from '@/utils/user';
|
||||
|
||||
import UserAccountInformation from '../../components/UserAccountInformation';
|
||||
import SuspendedTag from '../Users/components/SuspendedTag';
|
||||
|
||||
import ResetPasswordForm from './components/ResetPasswordForm';
|
||||
import styles from './index.module.scss';
|
||||
import { type UserDetailsOutletContext } from './types';
|
||||
|
||||
|
@ -41,10 +36,8 @@ function UserDetails() {
|
|||
const { t } = useTranslation(undefined, { keyPrefix: 'admin_console' });
|
||||
const [isDeleteFormOpen, setIsDeleteFormOpen] = useState(false);
|
||||
const [isDeleting, setIsDeleting] = useState(false);
|
||||
const [isResetPasswordFormOpen, setIsResetPasswordFormOpen] = useState(false);
|
||||
const [isToggleSuspendFormOpen, setIsToggleSuspendFormOpen] = useState(false);
|
||||
const [isUpdatingSuspendState, setIsUpdatingSuspendState] = useState(false);
|
||||
const [resetResult, setResetResult] = useState<string>();
|
||||
|
||||
// Get user info with user's SSO identities in a single API call.
|
||||
const { data, error, mutate } = useSWR<UserProfileResponse, RequestError>(
|
||||
|
@ -59,7 +52,6 @@ function UserDetails() {
|
|||
|
||||
useEffect(() => {
|
||||
setIsDeleteFormOpen(false);
|
||||
setIsResetPasswordFormOpen(false);
|
||||
setIsToggleSuspendFormOpen(false);
|
||||
}, [pathname]);
|
||||
|
||||
|
@ -119,13 +111,6 @@ function UserDetails() {
|
|||
primaryTag={isSuspendedUser && <SuspendedTag />}
|
||||
identifier={{ name: 'User ID', value: data.id }}
|
||||
actionMenuItems={[
|
||||
{
|
||||
title: 'user_details.reset_password.reset_password',
|
||||
icon: <Reset />,
|
||||
onClick: () => {
|
||||
setIsResetPasswordFormOpen(true);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: isSuspendedUser
|
||||
? 'user_details.reactivate_user'
|
||||
|
@ -145,26 +130,6 @@ function UserDetails() {
|
|||
},
|
||||
]}
|
||||
/>
|
||||
<ReactModal
|
||||
shouldCloseOnEsc
|
||||
isOpen={isResetPasswordFormOpen}
|
||||
className={modalStyles.content}
|
||||
overlayClassName={modalStyles.overlay}
|
||||
onRequestClose={() => {
|
||||
setIsResetPasswordFormOpen(false);
|
||||
}}
|
||||
>
|
||||
<ResetPasswordForm
|
||||
userId={data.id}
|
||||
onClose={(password) => {
|
||||
setIsResetPasswordFormOpen(false);
|
||||
|
||||
if (password) {
|
||||
setResetResult(password);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</ReactModal>
|
||||
<DeleteConfirmModal
|
||||
isOpen={isDeleteFormOpen}
|
||||
isLoading={isDeleting}
|
||||
|
@ -217,17 +182,6 @@ function UserDetails() {
|
|||
} satisfies UserDetailsOutletContext
|
||||
}
|
||||
/>
|
||||
{resetResult && (
|
||||
<UserAccountInformation
|
||||
title="user_details.reset_password.congratulations"
|
||||
user={data}
|
||||
password={resetResult}
|
||||
passwordLabel={t('user_details.reset_password.new_password')}
|
||||
onClose={() => {
|
||||
setResetResult(undefined);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</DetailsPage>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import type { User, UserProfileResponse } from '@logto/schemas';
|
||||
import type { UserProfileResponse } from '@logto/schemas';
|
||||
|
||||
export type UserDetailsForm = {
|
||||
primaryEmail: string;
|
||||
|
@ -13,5 +13,5 @@ export type UserDetailsForm = {
|
|||
export type UserDetailsOutletContext = {
|
||||
user: UserProfileResponse;
|
||||
isDeleting: boolean;
|
||||
onUserUpdated: (user?: User) => void;
|
||||
onUserUpdated: (user?: UserProfileResponse) => void;
|
||||
};
|
||||
|
|
|
@ -11,11 +11,10 @@ const user_details = {
|
|||
delete_description: 'لا يمكن التراجع عن هذا الإجراء. سيتم حذف المستخدم نهائيًا.',
|
||||
deleted: 'تم حذف المستخدم بنجاح',
|
||||
reset_password: {
|
||||
reset_password: 'إعادة تعيين كلمة المرور',
|
||||
title: 'هل أنت متأكد أنك تريد إعادة تعيين كلمة المرور؟',
|
||||
reset_title: 'هل أنت متأكد أنك تريد إعادة تعيين كلمة المرور؟',
|
||||
content:
|
||||
'لا يمكن التراجع عن هذا الإجراء. سيتم إعادة تعيين معلومات تسجيل الدخول الخاصة بالمستخدم.',
|
||||
congratulations: 'تم إعادة تعيين هذا المستخدم',
|
||||
reset_complete: 'تم إعادة تعيين هذا المستخدم',
|
||||
new_password: 'كلمة المرور الجديدة:',
|
||||
},
|
||||
tab_settings: 'الإعدادات',
|
||||
|
|
|
@ -12,11 +12,10 @@ const user_details = {
|
|||
'Diese Aktion kann nicht rückgängig gemacht werden. Der Benutzer wird permanent gelöscht.',
|
||||
deleted: 'Der Benutzer wurde erfolgreich gelöscht',
|
||||
reset_password: {
|
||||
reset_password: 'Passwort zurücksetzen',
|
||||
title: 'Willst du das Passwort wirklich zurücksetzen?',
|
||||
reset_title: 'Willst du das Passwort wirklich zurücksetzen?',
|
||||
content:
|
||||
'Diese Aktion kann nicht rückgängig gemacht werden. Das Anmeldeinformationen werden zurückgesetzt.',
|
||||
congratulations: 'Der Benutzer wurde erfolgreich zurückgesetzt',
|
||||
reset_complete: 'Der Benutzer wurde erfolgreich zurückgesetzt',
|
||||
new_password: 'Neues Passwort:',
|
||||
},
|
||||
tab_settings: 'Einstellungen',
|
||||
|
|
|
@ -71,6 +71,8 @@ const general = {
|
|||
delete_field: 'Delete {{field}}',
|
||||
coming_soon: 'Coming soon',
|
||||
or: 'Or',
|
||||
reset: 'Reset',
|
||||
generate: 'Generate',
|
||||
};
|
||||
|
||||
export default Object.freeze(general);
|
||||
|
|
|
@ -11,11 +11,13 @@ const user_details = {
|
|||
delete_description: 'This action cannot be undone. It will permanently delete the user.',
|
||||
deleted: 'The user has been successfully deleted',
|
||||
reset_password: {
|
||||
reset_password: 'Reset password',
|
||||
title: 'Are you sure you want to reset the password?',
|
||||
content: "This action cannot be undone. This will reset the user's log in information.",
|
||||
congratulations: 'This user has been reset',
|
||||
reset_title: 'Are you sure you want to reset the password?',
|
||||
generate_title: 'Are you sure you want to generate a password?',
|
||||
content: "This action cannot be undone. This will update the user's sign-in information.",
|
||||
reset_complete: 'The password has been reset',
|
||||
generate_complete: 'The password has been generated',
|
||||
new_password: 'New password:',
|
||||
password: 'Password:',
|
||||
},
|
||||
tab_settings: 'Settings',
|
||||
tab_roles: 'Roles',
|
||||
|
@ -28,6 +30,7 @@ const user_details = {
|
|||
field_email: 'Email address',
|
||||
field_phone: 'Phone number',
|
||||
field_username: 'Username',
|
||||
field_password: 'Password',
|
||||
field_name: 'Name',
|
||||
field_avatar: 'Avatar image URL',
|
||||
field_avatar_placeholder: 'https://your.cdn.domain/avatar.png',
|
||||
|
@ -41,6 +44,8 @@ const user_details = {
|
|||
field_sso_connectors: 'Enterprise connections',
|
||||
custom_data_invalid: 'Custom data must be a valid JSON object',
|
||||
profile_invalid: 'Profile must be a valid JSON object',
|
||||
password_already_set: 'Password already set',
|
||||
no_password_set: 'No password set',
|
||||
connectors: {
|
||||
connectors: 'Connectors',
|
||||
user_id: 'User ID',
|
||||
|
|
|
@ -12,11 +12,10 @@ const user_details = {
|
|||
delete_description: 'Esta acción no se puede deshacer. Eliminará permanentemente al usuario.',
|
||||
deleted: 'Usuario eliminado con éxito',
|
||||
reset_password: {
|
||||
reset_password: 'Restablecer contraseña',
|
||||
title: '¿Está seguro de que desea restablecer la contraseña?',
|
||||
reset_title: '¿Está seguro de que desea restablecer la contraseña?',
|
||||
content:
|
||||
'Esta acción no se puede deshacer. Esto restablecerá la información de inicio de sesión del usuario.',
|
||||
congratulations: 'Se ha restablecido la información de inicio de sesión del usuario',
|
||||
reset_complete: 'Se ha restablecido la información de inicio de sesión del usuario',
|
||||
new_password: 'Nueva contraseña:',
|
||||
},
|
||||
tab_settings: 'Configuración',
|
||||
|
|
|
@ -12,11 +12,10 @@ const user_details = {
|
|||
"Cette action ne peut être annulée. Elle supprimera définitivement l'utilisateur.",
|
||||
deleted: "L'utilisateur a été supprimé avec succès",
|
||||
reset_password: {
|
||||
reset_password: 'Réinitialiser le mot de passe',
|
||||
title: 'Êtes-vous sûr de vouloir réinitialiser le mot de passe ?',
|
||||
reset_title: 'Êtes-vous sûr de vouloir réinitialiser le mot de passe ?',
|
||||
content:
|
||||
"Cette action ne peut être annulée. Cette action réinitialisera les informations de connexion de l'utilisateur.",
|
||||
congratulations: 'Cet utilisateur a été réinitialisé',
|
||||
reset_complete: 'Cet utilisateur a été réinitialisé',
|
||||
new_password: 'Nouveau mot de passe :',
|
||||
},
|
||||
tab_settings: 'Paramètres',
|
||||
|
|
|
@ -12,11 +12,10 @@ const user_details = {
|
|||
"Questa azione non può essere annullata. Eliminerai l'utente in modo permanente.",
|
||||
deleted: "L'utente è stato eliminato con successo",
|
||||
reset_password: {
|
||||
reset_password: 'Resetta la password',
|
||||
title: 'Sei sicuro di voler reimpostare la password?',
|
||||
reset_title: 'Sei sicuro di voler reimpostare la password?',
|
||||
content:
|
||||
"Questa azione non può essere annullata. Questo reimposterà le informazioni di accesso dell'utente.",
|
||||
congratulations: "L'utente è stato reimpostato",
|
||||
reset_complete: "L'utente è stato reimpostato",
|
||||
new_password: 'Nuova password:',
|
||||
},
|
||||
tab_settings: 'Impostazioni',
|
||||
|
|
|
@ -11,10 +11,9 @@ const user_details = {
|
|||
delete_description: 'この操作は取り消せません。ユーザーが永久に削除されます。',
|
||||
deleted: 'ユーザーは正常に削除されました',
|
||||
reset_password: {
|
||||
reset_password: 'パスワードをリセット',
|
||||
title: '本当にパスワードをリセットしますか?',
|
||||
reset_title: '本当にパスワードをリセットしますか?',
|
||||
content: 'この操作は取り消せません。ユーザーのログイン情報がリセットされます。',
|
||||
congratulations: 'このユーザーはリセットされました',
|
||||
reset_complete: 'このユーザーはリセットされました',
|
||||
new_password: '新しいパスワード:',
|
||||
},
|
||||
tab_settings: '設定',
|
||||
|
|
|
@ -11,10 +11,9 @@ const user_details = {
|
|||
delete_description: '이 사용자를 영원히 삭제할까요? 이 행동은 취소될 수 없어요.',
|
||||
deleted: '해당 사용자가 성공적으로 삭제되었어요.',
|
||||
reset_password: {
|
||||
reset_password: '비밀번호 초기화',
|
||||
title: '정말로 비밀번호를 초기화 할까요?',
|
||||
reset_title: '정말로 비밀번호를 초기화 할까요?',
|
||||
content: '정말로 비밀번호를 초기화 할까요? 이 행동은 취소될 수 없어요.',
|
||||
congratulations: '해당 사용자의 비밀번호가 성공적으로 초기화 되었어요.',
|
||||
reset_complete: '해당 사용자의 비밀번호가 성공적으로 초기화 되었어요.',
|
||||
new_password: '새로운 비밀번호:',
|
||||
},
|
||||
tab_settings: '설정',
|
||||
|
|
|
@ -11,10 +11,9 @@ const user_details = {
|
|||
delete_description: 'Tej akcji nie można cofnąć. Usunie to użytkownika na stałe.',
|
||||
deleted: 'Użytkownik został pomyślnie usunięty',
|
||||
reset_password: {
|
||||
reset_password: 'Zresetuj hasło',
|
||||
title: 'Czy na pewno chcesz zresetować hasło?',
|
||||
reset_title: 'Czy na pewno chcesz zresetować hasło?',
|
||||
content: 'Tej akcji nie można cofnąć. To zresetuje informacje o logowaniu użytkownika.',
|
||||
congratulations: 'Ten użytkownik został zresetowany',
|
||||
reset_complete: 'Ten użytkownik został zresetowany',
|
||||
new_password: 'Nowe hasło:',
|
||||
},
|
||||
tab_settings: 'Ustawienia',
|
||||
|
|
|
@ -11,10 +11,9 @@ const user_details = {
|
|||
delete_description: 'Essa ação não pode ser desfeita. Isso excluirá permanentemente o usuário.',
|
||||
deleted: 'O usuário foi excluído com sucesso',
|
||||
reset_password: {
|
||||
reset_password: 'Redefinir senha',
|
||||
title: 'Tem certeza de que deseja redefinir a senha?',
|
||||
reset_title: 'Tem certeza de que deseja redefinir a senha?',
|
||||
content: 'Essa ação não pode ser desfeita. Isso redefinirá as informações de login do usuário.',
|
||||
congratulations: 'Este usuário foi redefinido',
|
||||
reset_complete: 'Este usuário foi redefinido',
|
||||
new_password: 'Nova senha:',
|
||||
},
|
||||
tab_settings: 'Configurações',
|
||||
|
|
|
@ -12,11 +12,10 @@ const user_details = {
|
|||
'Esta ação não pode ser desfeita. Isso irá eliminar o utilizador permanentemente.',
|
||||
deleted: 'O utilizador foi eliminado com sucesso',
|
||||
reset_password: {
|
||||
reset_password: 'Redefinir palavra-passe',
|
||||
title: 'Tem a certeza de que deseja redefinir a palavra-passe?',
|
||||
reset_title: 'Tem a certeza de que deseja redefinir a palavra-passe?',
|
||||
content:
|
||||
'Esta ação não pode ser desfeita. Isso irá redefinir as informações de login do utilizador.',
|
||||
congratulations: 'Este utilizador foi redefinido',
|
||||
reset_complete: 'Este utilizador foi redefinido',
|
||||
new_password: 'Nova palavra-passe:',
|
||||
},
|
||||
tab_settings: 'Definições',
|
||||
|
|
|
@ -11,10 +11,9 @@ const user_details = {
|
|||
delete_description: 'Это действие нельзя отменить. Оно окончательно удалит пользователя.',
|
||||
deleted: 'Пользователь успешно удален',
|
||||
reset_password: {
|
||||
reset_password: 'Сбросить пароль',
|
||||
title: 'Вы уверены, что хотите сбросить пароль?',
|
||||
reset_title: 'Вы уверены, что хотите сбросить пароль?',
|
||||
content: 'Это действие нельзя отменить. Это сбросит информацию для входа пользователя.',
|
||||
congratulations: 'Пользователь был сброшен',
|
||||
reset_complete: 'Пользователь был сброшен',
|
||||
new_password: 'Новый пароль:',
|
||||
},
|
||||
tab_settings: 'Настройки',
|
||||
|
|
|
@ -11,10 +11,9 @@ const user_details = {
|
|||
delete_description: 'Bu işlem geri alınamaz. Kullanıcıyı kalıcı olarak siler.',
|
||||
deleted: 'Kullanıcı başarıyla silindi.',
|
||||
reset_password: {
|
||||
reset_password: 'Şifreyi sıfırla',
|
||||
title: 'Şifreyi sıfırlamak istediğinizden emin misiniz?',
|
||||
reset_title: 'Şifreyi sıfırlamak istediğinizden emin misiniz?',
|
||||
content: 'Bu işlem geri alınamaz. Bu, kullanıcının oturum açma bilgilerini sıfırlayacaktır.',
|
||||
congratulations: 'Bu kullanıcı sıfırlandı',
|
||||
reset_complete: 'Bu kullanıcı sıfırlandı',
|
||||
new_password: 'Yeni şifre:',
|
||||
},
|
||||
tab_settings: 'Ayarlar',
|
||||
|
|
|
@ -11,10 +11,9 @@ const user_details = {
|
|||
delete_description: '本操作将永久删除该用户,且无法撤销。',
|
||||
deleted: '用户已成功删除。',
|
||||
reset_password: {
|
||||
reset_password: '重置密码',
|
||||
title: '确定要重置密码?',
|
||||
reset_title: '确定要重置密码?',
|
||||
content: '本操作不可撤销,将会重置用户的登录信息。',
|
||||
congratulations: '该用户已被重置',
|
||||
reset_complete: '该用户已被重置',
|
||||
new_password: '新密码:',
|
||||
},
|
||||
tab_settings: '设置',
|
||||
|
|
|
@ -11,10 +11,10 @@ const user_details = {
|
|||
delete_description: '本操作將永久刪除該用戶,且無法撤銷。',
|
||||
deleted: '用戶已成功刪除。',
|
||||
reset_password: {
|
||||
reset_password: '重置密碼',
|
||||
title: '確定要重置密碼?',
|
||||
reset_title: '確定要重置密碼?',
|
||||
generate_title: '確定要生成密碼?',
|
||||
content: '本操作不可撤銷,將會重置用戶的登錄信息。',
|
||||
congratulations: '該用戶已被重置',
|
||||
reset_complete: '該用戶已被重置',
|
||||
new_password: '新密碼:',
|
||||
},
|
||||
tab_settings: '設置',
|
||||
|
|
|
@ -11,10 +11,9 @@ const user_details = {
|
|||
delete_description: '本操作將永久刪除該用戶,且無法撤銷。',
|
||||
deleted: '用戶已成功刪除。',
|
||||
reset_password: {
|
||||
reset_password: '重置密碼',
|
||||
title: '確定要重置密碼?',
|
||||
reset_title: '確定要重置密碼?',
|
||||
content: '本操作不可撤銷,將會重置用戶的登入資訊。',
|
||||
congratulations: '該用戶已被重置',
|
||||
reset_complete: '該用戶已被重置',
|
||||
new_password: '新密碼:',
|
||||
},
|
||||
tab_settings: '設定',
|
||||
|
|
Loading…
Reference in a new issue