style: login form style
This commit is contained in:
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="#1f1f1f"><path d="M140-180v-88.92q0-29.39 15.96-54.43 15.96-25.03 42.66-38.49 59.3-29.08 119.65-43.62Q378.62-420 440-420q21.06 0 42.12 1.89 21.05 1.88 42.11 5.65-1.69 51.46 20.81 96.81Q567.54-270.31 609-240v60H140ZM753.85-72.31l-53.35-53.14v-164.73q-39.11-11.51-63.85-43.97-24.73-32.46-24.73-74.7 0-51.46 36.38-87.84t87.85-36.38q51.46 0 87.66 36.39Q860-460.28 860-408.79q0 39.94-22.42 70.71-22.43 30.77-57.2 44.23l44.23 44.23-53.07 53.2 53.07 53.19-70.76 70.92ZM440-484.62q-57.75 0-98.87-41.12Q300-566.86 300-624.61q0-57.75 41.13-98.88 41.12-41.12 98.87-41.12 57.75 0 98.87 41.12Q580-682.36 580-624.61q0 57.75-41.13 98.87-41.12 41.12-98.87 41.12Zm296.15 93.47q14.7 0 25.04-10.54 10.35-10.54 10.35-25.23 0-14.69-10.35-25.04-10.34-10.35-25.04-10.35-14.69 0-25.23 10.35-10.54 10.35-10.54 25.04t10.54 25.23q10.54 10.54 25.23 10.54Z"/></svg>
|
||||||
|
After Width: | Height: | Size: 934 B |
@@ -6,9 +6,6 @@ export default {
|
|||||||
'common.button.shortcut': 'Keyboard Shortcut',
|
'common.button.shortcut': 'Keyboard Shortcut',
|
||||||
'common.button.add': 'Add',
|
'common.button.add': 'Add',
|
||||||
'common.button.login': 'Log in',
|
'common.button.login': 'Log in',
|
||||||
'common.button.login.local': 'Log in with local user',
|
|
||||||
'common.button.oidclogin': 'Log in with OIDC',
|
|
||||||
'common.button.samllogin': 'Log in with SAML',
|
|
||||||
'common.button.select': 'Select',
|
'common.button.select': 'Select',
|
||||||
'common.button.selected': 'Selected',
|
'common.button.selected': 'Selected',
|
||||||
'common.button.continue': 'Continue',
|
'common.button.continue': 'Continue',
|
||||||
@@ -257,5 +254,6 @@ export default {
|
|||||||
'common.select.count': '{count} selected',
|
'common.select.count': '{count} selected',
|
||||||
'common.login.auth': 'Authenticating...',
|
'common.login.auth': 'Authenticating...',
|
||||||
'common.login.auth.failed': 'Authentication failed',
|
'common.login.auth.failed': 'Authentication failed',
|
||||||
'common.login.thirdparty': 'or login with'
|
'common.login.password': 'Log in with Password',
|
||||||
|
'common.external.login': 'Log in with {type}'
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -6,9 +6,6 @@ export default {
|
|||||||
'common.button.shortcut': 'キーボードショートカット',
|
'common.button.shortcut': 'キーボードショートカット',
|
||||||
'common.button.add': '追加',
|
'common.button.add': '追加',
|
||||||
'common.button.login': 'ログイン',
|
'common.button.login': 'ログイン',
|
||||||
'common.button.login.local': 'ローカルユーザーでログイン',
|
|
||||||
'common.button.oidclogin': 'OIDC でログイン',
|
|
||||||
'common.button.samllogin': 'SAML でログイン',
|
|
||||||
'common.button.select': '選択',
|
'common.button.select': '選択',
|
||||||
'common.button.selected': '選択済み',
|
'common.button.selected': '選択済み',
|
||||||
'common.button.continue': '続行',
|
'common.button.continue': '続行',
|
||||||
@@ -257,7 +254,8 @@ export default {
|
|||||||
'common.select.count': '{count} selected',
|
'common.select.count': '{count} selected',
|
||||||
'common.login.auth': 'Authenticating...',
|
'common.login.auth': 'Authenticating...',
|
||||||
'common.login.auth.failed': 'Authentication failed',
|
'common.login.auth.failed': 'Authentication failed',
|
||||||
'common.login.thirdparty': 'or login with'
|
'common.login.password': 'Log in with Password',
|
||||||
|
'common.external.login': 'Log in with {type}'
|
||||||
};
|
};
|
||||||
|
|
||||||
// ========== To-Do: Translate Keys (Remove After Translation) ==========
|
// ========== To-Do: Translate Keys (Remove After Translation) ==========
|
||||||
@@ -277,6 +275,7 @@ export default {
|
|||||||
// 14. 'common.button.clearSelection': 'Clear Selection',
|
// 14. 'common.button.clearSelection': 'Clear Selection',
|
||||||
// 15. 'common.select.count': '{count} selected',
|
// 15. 'common.select.count': '{count} selected',
|
||||||
// 16. 'common.login.auth': 'Authenticating...',
|
// 16. 'common.login.auth': 'Authenticating...',
|
||||||
// 17. 'common.login.auth.failed': 'Authentication failed'
|
// 17. 'common.login.auth.failed': 'Authentication failed',
|
||||||
// 18. 'common.login.thirdparty': 'or login with'
|
// 18. 'common.external.login': 'Log in with {type}'
|
||||||
|
// 19. 'common.login.password': 'Log in with Password',
|
||||||
// ========== End of To-Do List ==========
|
// ========== End of To-Do List ==========
|
||||||
|
|||||||
@@ -6,9 +6,6 @@ export default {
|
|||||||
'common.button.shortcut': 'Сочетания клавиш',
|
'common.button.shortcut': 'Сочетания клавиш',
|
||||||
'common.button.add': 'Добавить',
|
'common.button.add': 'Добавить',
|
||||||
'common.button.login': 'Войти',
|
'common.button.login': 'Войти',
|
||||||
'common.button.login.local': 'Войти с локальным пользователем',
|
|
||||||
'common.button.oidclogin': 'Войти с OIDC',
|
|
||||||
'common.button.samllogin': 'Войти с SAML',
|
|
||||||
'common.button.select': 'Выбрать',
|
'common.button.select': 'Выбрать',
|
||||||
'common.button.selected': 'Выбрано',
|
'common.button.selected': 'Выбрано',
|
||||||
'common.button.continue': 'Продолжить',
|
'common.button.continue': 'Продолжить',
|
||||||
@@ -256,9 +253,11 @@ export default {
|
|||||||
'common.select.count': '{count} Выбрано',
|
'common.select.count': '{count} Выбрано',
|
||||||
'common.login.auth': 'Аутентификация...',
|
'common.login.auth': 'Аутентификация...',
|
||||||
'common.login.auth.failed': 'Ошибка аутентификации',
|
'common.login.auth.failed': 'Ошибка аутентификации',
|
||||||
'common.login.thirdparty': 'or login with'
|
'common.login.password': 'Log in with Password',
|
||||||
|
'common.external.login': 'Log in with {type}'
|
||||||
};
|
};
|
||||||
|
|
||||||
// ========== To-Do: Translate Keys (Remove After Translation) ==========
|
// ========== To-Do: Translate Keys (Remove After Translation) ==========
|
||||||
// 1. 'common.login.thirdparty': 'or login with'
|
// 1. 'common.external.login': 'Log in with {type}'
|
||||||
|
// 2. 'common.login.password': 'Log in with Password'
|
||||||
// ========== End of To-Do List ==========
|
// ========== End of To-Do List ==========
|
||||||
|
|||||||
@@ -6,9 +6,6 @@ export default {
|
|||||||
'common.button.shortcut': '快捷键',
|
'common.button.shortcut': '快捷键',
|
||||||
'common.button.add': '添加',
|
'common.button.add': '添加',
|
||||||
'common.button.login': '登录',
|
'common.button.login': '登录',
|
||||||
'common.button.login.local': '本地用户登录',
|
|
||||||
'common.button.oidclogin': '使用 OIDC 登录',
|
|
||||||
'common.button.samllogin': '使用 SAML 登录',
|
|
||||||
'common.button.select': '选择',
|
'common.button.select': '选择',
|
||||||
'common.button.selected': '已选择',
|
'common.button.selected': '已选择',
|
||||||
'common.button.continue': '继续',
|
'common.button.continue': '继续',
|
||||||
@@ -250,5 +247,6 @@ export default {
|
|||||||
'common.select.count': '已选 {count} 项',
|
'common.select.count': '已选 {count} 项',
|
||||||
'common.login.auth': '认证中...',
|
'common.login.auth': '认证中...',
|
||||||
'common.login.auth.failed': '认证失败',
|
'common.login.auth.failed': '认证失败',
|
||||||
'common.login.thirdparty': '或使用以下方式登录'
|
'common.login.password': '使用密码登录',
|
||||||
|
'common.external.login': '使用 {type} 登录'
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -0,0 +1,96 @@
|
|||||||
|
import SealInput from '@/components/seal-form/seal-input';
|
||||||
|
import externalLinks from '@/constants/external-links';
|
||||||
|
import { LockOutlined, UserOutlined } from '@ant-design/icons';
|
||||||
|
import { useIntl } from '@umijs/max';
|
||||||
|
import { Button, Checkbox, Form, FormInstance } from 'antd';
|
||||||
|
|
||||||
|
interface LocalUserFormProps {
|
||||||
|
handleLogin: (values: any) => void;
|
||||||
|
form: FormInstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
const LocalUserForm: React.FC<LocalUserFormProps> = (props) => {
|
||||||
|
const { handleLogin, form } = props;
|
||||||
|
const intl = useIntl();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Form
|
||||||
|
form={form}
|
||||||
|
style={{ width: '360px', margin: '0 auto' }}
|
||||||
|
onFinish={handleLogin}
|
||||||
|
>
|
||||||
|
<Form.Item
|
||||||
|
name="username"
|
||||||
|
rules={[
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: intl.formatMessage(
|
||||||
|
{ id: 'common.form.rule.input' },
|
||||||
|
{
|
||||||
|
name: intl.formatMessage({ id: 'common.form.username' })
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
<SealInput.Input
|
||||||
|
label={intl.formatMessage({ id: 'common.form.username' })}
|
||||||
|
prefix={<UserOutlined />}
|
||||||
|
/>
|
||||||
|
</Form.Item>
|
||||||
|
|
||||||
|
<Form.Item
|
||||||
|
name="password"
|
||||||
|
rules={[
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: intl.formatMessage(
|
||||||
|
{ id: 'common.form.rule.input' },
|
||||||
|
{
|
||||||
|
name: intl.formatMessage({ id: 'common.form.password' })
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
<SealInput.Password
|
||||||
|
prefix={<LockOutlined />}
|
||||||
|
label={intl.formatMessage({ id: 'common.form.password' })}
|
||||||
|
/>
|
||||||
|
</Form.Item>
|
||||||
|
<div
|
||||||
|
className="flex-center flex-between"
|
||||||
|
style={{
|
||||||
|
marginBottom: 24
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Form.Item noStyle name="autoLogin" valuePropName="checked">
|
||||||
|
<Checkbox style={{ marginLeft: 5 }}>
|
||||||
|
<span style={{ color: 'var(--ant-color-text-secondary)' }}>
|
||||||
|
{intl.formatMessage({ id: 'common.login.rember' })}
|
||||||
|
</span>
|
||||||
|
</Checkbox>
|
||||||
|
</Form.Item>
|
||||||
|
<Button
|
||||||
|
type="link"
|
||||||
|
size="small"
|
||||||
|
href={externalLinks.resetPassword}
|
||||||
|
target="_blank"
|
||||||
|
style={{ padding: 0 }}
|
||||||
|
>
|
||||||
|
{intl.formatMessage({ id: 'common.button.forgotpassword' })}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
<Button
|
||||||
|
htmlType="submit"
|
||||||
|
type="primary"
|
||||||
|
block
|
||||||
|
style={{ height: '48px', fontSize: '14px' }}
|
||||||
|
>
|
||||||
|
{intl.formatMessage({ id: 'common.button.login' })}
|
||||||
|
</Button>
|
||||||
|
</Form>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default LocalUserForm;
|
||||||
@@ -3,12 +3,9 @@ import OIDCIcon from '@/assets/images/oidc.svg';
|
|||||||
import SAMLIcon from '@/assets/images/saml.svg';
|
import SAMLIcon from '@/assets/images/saml.svg';
|
||||||
import { userAtom } from '@/atoms/user';
|
import { userAtom } from '@/atoms/user';
|
||||||
import LangSelect from '@/components/lang-select';
|
import LangSelect from '@/components/lang-select';
|
||||||
import SealInput from '@/components/seal-form/seal-input';
|
|
||||||
import ThemeDropActions from '@/components/theme-toggle/theme-drop-actions';
|
import ThemeDropActions from '@/components/theme-toggle/theme-drop-actions';
|
||||||
import externalLinks from '@/constants/external-links';
|
|
||||||
import { LockOutlined, UserOutlined } from '@ant-design/icons';
|
|
||||||
import { useIntl, useModel } from '@umijs/max';
|
import { useIntl, useModel } from '@umijs/max';
|
||||||
import { Button, Checkbox, Divider, Form, Spin, Tooltip, message } from 'antd';
|
import { Button, Divider, Form, Spin, message } from 'antd';
|
||||||
import { createStyles } from 'antd-style';
|
import { createStyles } from 'antd-style';
|
||||||
import { useAtom } from 'jotai';
|
import { useAtom } from 'jotai';
|
||||||
import { useMemo, useState } from 'react';
|
import { useMemo, useState } from 'react';
|
||||||
@@ -17,22 +14,34 @@ import styled from 'styled-components';
|
|||||||
import { useLocalAuth } from '../hooks/use-local-auth';
|
import { useLocalAuth } from '../hooks/use-local-auth';
|
||||||
import { useSSOAuth } from '../hooks/use-sso-auth';
|
import { useSSOAuth } from '../hooks/use-sso-auth';
|
||||||
import { checkDefaultPage } from '../utils';
|
import { checkDefaultPage } from '../utils';
|
||||||
|
import LocalUserForm from './local-user-form';
|
||||||
|
|
||||||
const Buttons = styled.div`
|
const Buttons = styled.div`
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
flex-direction: column;
|
||||||
align-items: center;
|
justify-content: flex-start;
|
||||||
gap: 32px;
|
align-items: flex-start;
|
||||||
|
gap: 24px;
|
||||||
|
width: 360px;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const BackButton = styled(Button).attrs({
|
||||||
|
type: 'link',
|
||||||
|
size: 'small',
|
||||||
|
block: true
|
||||||
|
})`
|
||||||
|
margin-top: 20px;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const ButtonWrapper = styled(Button).attrs({
|
const ButtonWrapper = styled(Button).attrs({
|
||||||
shape: 'circle',
|
shape: 'round',
|
||||||
size: 'large',
|
block: true
|
||||||
color: 'default',
|
})``;
|
||||||
variant: 'filled'
|
|
||||||
})`
|
const ButtonText = styled.span`
|
||||||
height: 42px;
|
display: flex;
|
||||||
width: 42px;
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const DividerWrapper = styled(Divider)`
|
const DividerWrapper = styled(Divider)`
|
||||||
@@ -68,6 +77,16 @@ const useStyles = createStyles(({ token, css }) => ({
|
|||||||
.title {
|
.title {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
`,
|
||||||
|
welcome: css`
|
||||||
|
display: flex;
|
||||||
|
margin-bottom: 32px;
|
||||||
|
font-size: 20px;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
.text {
|
||||||
|
color: ${token.colorText};
|
||||||
|
}
|
||||||
`
|
`
|
||||||
}));
|
}));
|
||||||
|
|
||||||
@@ -79,20 +98,15 @@ const LoginForm = () => {
|
|||||||
const [authError, setAuthError] = useState<Error | null>(null);
|
const [authError, setAuthError] = useState<Error | null>(null);
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
const [form] = Form.useForm();
|
const [form] = Form.useForm();
|
||||||
|
const [isPassword, setIsPassword] = useState(false);
|
||||||
|
|
||||||
const renderWelCome = useMemo(() => {
|
const renderWelCome = () => {
|
||||||
return (
|
return (
|
||||||
<div
|
<div className={styles.welcome}>
|
||||||
style={{
|
|
||||||
display: 'flex',
|
|
||||||
marginBottom: 32,
|
|
||||||
fontSize: 20,
|
|
||||||
justifyContent: 'center',
|
|
||||||
alignItems: 'center'
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<div className="flex-center">
|
<div className="flex-center">
|
||||||
<span>{intl?.formatMessage({ id: 'users.login.title' })}</span>
|
<span className="text">
|
||||||
|
{intl?.formatMessage({ id: 'users.login.title' })}
|
||||||
|
</span>
|
||||||
<img
|
<img
|
||||||
src={LogoIcon}
|
src={LogoIcon}
|
||||||
alt="logo"
|
alt="logo"
|
||||||
@@ -101,7 +115,7 @@ const LoginForm = () => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}, [intl]);
|
};
|
||||||
|
|
||||||
const gotoDefaultPage = async (userInfo: any) => {
|
const gotoDefaultPage = async (userInfo: any) => {
|
||||||
checkDefaultPage(userInfo, true);
|
checkDefaultPage(userInfo, true);
|
||||||
@@ -162,34 +176,56 @@ const LoginForm = () => {
|
|||||||
onError: handleOnError
|
onError: handleOnError
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const handleLoginWithPassword = () => {
|
||||||
|
setIsPassword(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleLoginWithThirdParty = () => {
|
||||||
|
if (SSOAuth.options.oidc) {
|
||||||
|
SSOAuth.loginWithOIDC();
|
||||||
|
} else if (SSOAuth.options.saml) {
|
||||||
|
SSOAuth.loginWithSAML();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const hasThirdPartyLogin = useMemo(() => {
|
const hasThirdPartyLogin = useMemo(() => {
|
||||||
return SSOAuth.options.oidc || SSOAuth.options.saml;
|
return SSOAuth.options.oidc || SSOAuth.options.saml;
|
||||||
}, [SSOAuth.options]);
|
}, [SSOAuth.options]);
|
||||||
|
|
||||||
const renderThirdPartyLoginButtons = () => {
|
const renderLoginButtons = () => {
|
||||||
if (!hasThirdPartyLogin) return null;
|
// do not render login buttons if using password login or no third-party login
|
||||||
|
if (!hasThirdPartyLogin || isPassword) return null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<Buttons>
|
||||||
<DividerWrapper plain>
|
{SSOAuth.options.oidc && (
|
||||||
{intl.formatMessage({ id: 'common.login.thirdparty' })}
|
<ButtonWrapper onClick={SSOAuth.loginWithOIDC}>
|
||||||
</DividerWrapper>
|
<ButtonText>
|
||||||
<Buttons>
|
<img src={OIDCIcon} alt="" height={24} width={24} />
|
||||||
{SSOAuth.options.oidc && (
|
{intl.formatMessage(
|
||||||
<Tooltip title="OIDC">
|
{ id: 'common.external.login' },
|
||||||
<ButtonWrapper onClick={SSOAuth.loginWithOIDC}>
|
{ type: 'OIDC' }
|
||||||
<img src={OIDCIcon} alt="" height={32} width={32} />
|
)}
|
||||||
</ButtonWrapper>
|
</ButtonText>
|
||||||
</Tooltip>
|
</ButtonWrapper>
|
||||||
)}
|
)}
|
||||||
{SSOAuth.options.saml && (
|
{SSOAuth.options.saml && (
|
||||||
<Tooltip title="SAML">
|
<ButtonWrapper onClick={SSOAuth.loginWithSAML}>
|
||||||
<ButtonWrapper onClick={SSOAuth.loginWithSAML}>
|
<ButtonText>
|
||||||
<img src={SAMLIcon} alt="" height={32} width={32} />
|
<img src={SAMLIcon} alt="" height={24} width={24} />
|
||||||
</ButtonWrapper>
|
{intl.formatMessage(
|
||||||
</Tooltip>
|
{ id: 'common.external.login' },
|
||||||
)}
|
{ type: 'SAML' }
|
||||||
</Buttons>
|
)}
|
||||||
</>
|
</ButtonText>
|
||||||
|
</ButtonWrapper>
|
||||||
|
)}
|
||||||
|
<Button type="link" block onClick={handleLoginWithPassword}>
|
||||||
|
<ButtonText>
|
||||||
|
{intl.formatMessage({ id: 'common.login.password' })}
|
||||||
|
</ButtonText>
|
||||||
|
</Button>
|
||||||
|
</Buttons>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -212,84 +248,21 @@ const LoginForm = () => {
|
|||||||
</span>
|
</span>
|
||||||
</Spin>
|
</Spin>
|
||||||
) : (
|
) : (
|
||||||
<Form
|
<>
|
||||||
form={form}
|
{renderWelCome()}
|
||||||
style={{ width: '360px', margin: '0 auto' }}
|
{renderLoginButtons()}
|
||||||
onFinish={handleLogin}
|
{(!hasThirdPartyLogin || isPassword) && (
|
||||||
>
|
<LocalUserForm handleLogin={handleLogin} form={form} />
|
||||||
{renderWelCome}
|
)}
|
||||||
<Form.Item
|
{hasThirdPartyLogin && isPassword && (
|
||||||
name="username"
|
<BackButton onClick={handleLoginWithThirdParty}>
|
||||||
rules={[
|
{intl.formatMessage(
|
||||||
{
|
{ id: 'common.external.login' },
|
||||||
required: true,
|
{ type: SSOAuth.options.oidc ? 'OIDC' : 'SAML' }
|
||||||
message: intl.formatMessage(
|
)}
|
||||||
{ id: 'common.form.rule.input' },
|
</BackButton>
|
||||||
{
|
)}
|
||||||
name: intl.formatMessage({ id: 'common.form.username' })
|
</>
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
]}
|
|
||||||
>
|
|
||||||
<SealInput.Input
|
|
||||||
label={intl.formatMessage({ id: 'common.form.username' })}
|
|
||||||
prefix={<UserOutlined />}
|
|
||||||
/>
|
|
||||||
</Form.Item>
|
|
||||||
|
|
||||||
<Form.Item
|
|
||||||
name="password"
|
|
||||||
rules={[
|
|
||||||
{
|
|
||||||
required: true,
|
|
||||||
message: intl.formatMessage(
|
|
||||||
{ id: 'common.form.rule.input' },
|
|
||||||
{
|
|
||||||
name: intl.formatMessage({ id: 'common.form.password' })
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
]}
|
|
||||||
>
|
|
||||||
<SealInput.Password
|
|
||||||
prefix={<LockOutlined />}
|
|
||||||
label={intl.formatMessage({ id: 'common.form.password' })}
|
|
||||||
/>
|
|
||||||
</Form.Item>
|
|
||||||
<div
|
|
||||||
className="flex-center flex-between"
|
|
||||||
style={{
|
|
||||||
marginBottom: 24
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Form.Item noStyle name="autoLogin" valuePropName="checked">
|
|
||||||
<Checkbox style={{ marginLeft: 5 }}>
|
|
||||||
<span style={{ color: 'var(--ant-color-text-secondary)' }}>
|
|
||||||
{intl.formatMessage({ id: 'common.login.rember' })}
|
|
||||||
</span>
|
|
||||||
</Checkbox>
|
|
||||||
</Form.Item>
|
|
||||||
<Button
|
|
||||||
type="link"
|
|
||||||
size="small"
|
|
||||||
href={externalLinks.resetPassword}
|
|
||||||
target="_blank"
|
|
||||||
style={{ padding: 0 }}
|
|
||||||
>
|
|
||||||
{intl.formatMessage({ id: 'common.button.forgotpassword' })}
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
<Button
|
|
||||||
htmlType="submit"
|
|
||||||
type="primary"
|
|
||||||
block
|
|
||||||
style={{ height: '48px', fontSize: '14px' }}
|
|
||||||
>
|
|
||||||
{intl.formatMessage({ id: 'common.button.login' })}
|
|
||||||
</Button>
|
|
||||||
{renderThirdPartyLoginButtons()}
|
|
||||||
</Form>
|
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ export const useLocalAuth = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
onSuccess?.(userInfo);
|
onSuccess?.(userInfo);
|
||||||
} catch (error) {
|
} catch (error: any) {
|
||||||
onError?.(error);
|
onError?.(error);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -45,27 +45,27 @@ export function useSSOAuth({
|
|||||||
window.location.href = '/auth/saml/login';
|
window.location.href = '/auth/saml/login';
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
const init = async () => {
|
||||||
fetchAuthConfig('/auth_config')
|
try {
|
||||||
.then((authConfig) => {
|
const authConfig = await fetchAuthConfig('/auth_config');
|
||||||
setLoginOption({
|
setLoginOption({
|
||||||
oidc: !!authConfig.is_oidc,
|
oidc: !!authConfig.is_oidc,
|
||||||
saml: !!authConfig.is_saml
|
saml: !!authConfig.is_saml
|
||||||
});
|
|
||||||
})
|
|
||||||
.catch(() => {
|
|
||||||
setLoginOption({ oidc: false, saml: false });
|
|
||||||
});
|
});
|
||||||
|
if (sso) {
|
||||||
if (sso) {
|
if (authConfig.is_oidc) {
|
||||||
fetchUserInfo()
|
oidcLogin();
|
||||||
.then((userInfo) => {
|
} else if (authConfig.is_saml) {
|
||||||
onSuccess?.(userInfo);
|
samlLogin();
|
||||||
})
|
}
|
||||||
.catch((error) => {
|
}
|
||||||
onError?.(error);
|
} catch {
|
||||||
});
|
setLoginOption({ oidc: false, saml: false });
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
init();
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
+27
-13
@@ -1,8 +1,10 @@
|
|||||||
|
import { userAtom } from '@/atoms/user';
|
||||||
import useTabActive from '@/hooks/use-tab-active';
|
import useTabActive from '@/hooks/use-tab-active';
|
||||||
import { PageContainer } from '@ant-design/pro-components';
|
import { PageContainer } from '@ant-design/pro-components';
|
||||||
import { useIntl } from '@umijs/max';
|
import { useIntl } from '@umijs/max';
|
||||||
import { TabsProps } from 'antd';
|
import { TabsProps } from 'antd';
|
||||||
import React, { useCallback, useState } from 'react';
|
import { useAtom } from 'jotai';
|
||||||
|
import React, { useCallback, useMemo, useState } from 'react';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
import Appearance from './components/appearance';
|
import Appearance from './components/appearance';
|
||||||
import ModifyPasswordn from './components/modify-password';
|
import ModifyPasswordn from './components/modify-password';
|
||||||
@@ -15,23 +17,35 @@ const Wrapper = styled.div`
|
|||||||
|
|
||||||
const Profile: React.FC = () => {
|
const Profile: React.FC = () => {
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
|
const [userInfo, setUserInfo] = useAtom(userAtom);
|
||||||
const { setTabActive, getTabActive, tabsMap } = useTabActive();
|
const { setTabActive, getTabActive, tabsMap } = useTabActive();
|
||||||
const [activeKey, setActiveKey] = useState(
|
const [activeKey, setActiveKey] = useState(
|
||||||
getTabActive(tabsMap.userSettings) || 'modify-password'
|
userInfo?.source === 'Local' ? 'modify-password' : 'appearance'
|
||||||
);
|
);
|
||||||
|
|
||||||
const items: TabsProps['items'] = [
|
const items: TabsProps['items'] = useMemo(() => {
|
||||||
{
|
if (userInfo?.source !== 'Local') {
|
||||||
key: 'modify-password',
|
return [
|
||||||
label: intl.formatMessage({ id: 'users.form.updatepassword' }),
|
{
|
||||||
children: <ModifyPasswordn />
|
key: 'appearance',
|
||||||
},
|
label: intl.formatMessage({ id: 'common.appearance' }),
|
||||||
{
|
children: <Appearance />
|
||||||
key: 'appearance',
|
}
|
||||||
label: intl.formatMessage({ id: 'common.appearance' }),
|
];
|
||||||
children: <Appearance />
|
|
||||||
}
|
}
|
||||||
];
|
return [
|
||||||
|
{
|
||||||
|
key: 'modify-password',
|
||||||
|
label: intl.formatMessage({ id: 'users.form.updatepassword' }),
|
||||||
|
children: <ModifyPasswordn />
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'appearance',
|
||||||
|
label: intl.formatMessage({ id: 'common.appearance' }),
|
||||||
|
children: <Appearance />
|
||||||
|
}
|
||||||
|
];
|
||||||
|
}, [userInfo?.source]);
|
||||||
|
|
||||||
const handleChangeTab = useCallback((key: string) => {
|
const handleChangeTab = useCallback((key: string) => {
|
||||||
setActiveKey(key);
|
setActiveKey(key);
|
||||||
|
|||||||
Reference in New Issue
Block a user