change(ui): auth with api error messages and antd components

This commit is contained in:
Shekar Siri 2025-02-11 13:45:12 +01:00
parent 0d9c265452
commit ba55b359fb
5 changed files with 70 additions and 87 deletions

View file

@ -1,8 +1,9 @@
import React from 'react';
import { Form, Input, Loader, Button, Icon } from 'UI';
import { Loader, Icon } from 'UI';
import ReCAPTCHA from 'react-google-recaptcha';
import { observer } from 'mobx-react-lite';
import { useStore } from 'App/mstore';
import {Form, Input, Button } from 'antd'
function ResetPasswordRequest() {
const { userStore } = useStore();
@ -20,8 +21,8 @@ function ResetPasswordRequest() {
if (name === 'email') setEmail(value);
};
const onSubmit = (e: any) => {
e.preventDefault();
const onSubmit = () => {
// e.preventDefault();
if (CAPTCHA_ENABLED && recaptchaRef.current) {
recaptchaRef.current.execute();
} else if (!CAPTCHA_ENABLED) {
@ -30,19 +31,21 @@ function ResetPasswordRequest() {
};
const handleSubmit = (token?: any) => {
if (CAPTCHA_ENABLED && recaptchaRef.current && (token === null || token === undefined)) return;
if (CAPTCHA_ENABLED && recaptchaRef.current && (token === null || token === undefined)) return;
setError(null);
requestResetPassword({ email: email.trim(), 'g-recaptcha-response': token })
.then((response: any) => {
setRequested(true);
if (response && response.errors && response.errors.length > 0) {
setError(response.errors[0]);
}
});
// if (response && response.errors && response.errors.length > 0) {
// setError(response.errors[0]);
// }
}).catch((err: any) => {
setRequested(false);
});
};
return (
<Form onSubmit={onSubmit} style={{ minWidth: '50%' }} className="flex flex-col">
<Form onFinish={onSubmit} style={{ minWidth: '50%' }} className="flex flex-col">
<Loader loading={false}>
{CAPTCHA_ENABLED && (
<div className="flex justify-center">
@ -57,7 +60,7 @@ function ResetPasswordRequest() {
)}
{!requested && (
<>
<Form.Field>
<Form.Item>
<label>{'Email Address'}</label>
<Input
autoFocus={true}
@ -67,11 +70,11 @@ function ResetPasswordRequest() {
name="email"
onChange={write}
className="w-full"
icon="envelope"
prefix={<Icon name="envelope" size={16} />}
required
/>
</Form.Field>
<Button type="submit" variant="primary" className="mt-4 rounded-lg" loading={loading} disabled={loading}>
</Form.Item>
<Button type="primary" htmlType="submit" loading={loading} disabled={loading}>
Email Password Reset Link
</Button>
</>
@ -89,14 +92,14 @@ function ResetPasswordRequest() {
</div>
)}
{error && (
<div className="flex items-center flex-col text-center">
<div className="w-16 h-16 rounded-full bg-red-lightest flex items-center justify-center mb-2">
<Icon name="envelope-x" size="30" color="red" />
</div>
{error}
</div>
)}
{/*{error && (*/}
{/* <div className="flex items-center flex-col text-center">*/}
{/* <div className="w-16 h-16 rounded-full bg-red-lightest flex items-center justify-center mb-2">*/}
{/* <Icon name="envelope-x" size="30" color="red" />*/}
{/* </div>*/}
{/* {error}*/}
{/* </div>*/}
{/*)}*/}
</Loader>
</Form>
);

View file

@ -10,7 +10,8 @@ import { toast } from 'react-toastify';
import { ENTERPRISE_REQUEIRED } from 'App/constants';
import { useStore } from 'App/mstore';
import { forgotPassword, signup } from 'App/routes';
import { Button, Form, Icon, Input, Link, Loader, Tooltip } from 'UI';
import { Icon, Link, Loader, Tooltip } from 'UI';
import { Button, Form, Input } from 'antd';
import Copyright from 'Shared/Copyright';
@ -24,12 +25,12 @@ interface LoginProps {
}
const Login = ({
location,
}: LoginProps) => {
location
}: LoginProps) => {
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const CAPTCHA_ENABLED = React.useMemo(() => {
return window.env.CAPTCHA_ENABLED === 'true'
return window.env.CAPTCHA_ENABLED === 'true';
}, []);
const recaptchaRef = useRef<ReCAPTCHA>(null);
const { loginStore, userStore } = useStore();
@ -41,9 +42,9 @@ const Login = ({
const params = new URLSearchParams(location.search);
useEffect(() => {
if (authDetails && !authDetails.tenants) {
history.push(SIGNUP_ROUTE);
}
if (authDetails && !authDetails.tenants) {
history.push(SIGNUP_ROUTE);
}
}, [authDetails]);
useEffect(() => {
@ -83,7 +84,7 @@ const Login = ({
window.postMessage(
{
type: 'orspot:token',
token: jwt,
token: jwt
},
'*'
);
@ -104,7 +105,7 @@ const Login = ({
.generateJWT()
.then((resp) => {
if (resp) {
userStore.syntheticLogin(resp)
userStore.syntheticLogin(resp);
setJwt({ jwt: resp.jwt, spotJwt: resp.spotJwt ?? null });
handleSpotLogin(resp.spotJwt);
}
@ -114,8 +115,7 @@ const Login = ({
});
};
const onSubmit = (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
const onSubmit = () => {
if (CAPTCHA_ENABLED && recaptchaRef.current) {
recaptchaRef.current.execute();
} else if (!CAPTCHA_ENABLED) {
@ -140,7 +140,7 @@ const Login = ({
</h2>
<div className={cn(authDetails?.enforceSSO ? '!hidden' : '')}>
<Form
onSubmit={onSubmit}
onFinish={onSubmit}
className={cn('flex items-center justify-center flex-col')}
style={{ width: '350px' }}
>
@ -154,7 +154,7 @@ const Login = ({
/>
)}
<div style={{ width: '350px' }} className="px-8">
<Form.Field>
<Form.Item>
<label>Email Address</label>
<Input
data-test-id={'login'}
@ -165,10 +165,10 @@ const Login = ({
name="email"
onChange={(e) => setEmail(e.target.value)}
required
icon="envelope"
prefix={<Icon name="envelope" size={16} />}
/>
</Form.Field>
<Form.Field>
</Form.Item>
<Form.Item>
<label className="mb-2">Password</label>
<Input
data-test-id={'password'}
@ -178,9 +178,9 @@ const Login = ({
name="password"
onChange={(e) => setPassword(e.target.value)}
required
icon="key"
prefix={<Icon name="key" size={16} />}
/>
</Form.Field>
</Form.Item>
</div>
</Loader>
{errors && errors.length ? (
@ -201,8 +201,8 @@ const Login = ({
<Button
data-test-id={'log-button'}
className="mt-2 w-full text-center rounded-lg"
type="submit"
variant="primary"
type="primary"
htmlType="submit"
>
{'Login'}
</Button>
@ -221,7 +221,7 @@ const Login = ({
<div className={cn(stl.sso, 'py-2 flex flex-col items-center')}>
{authDetails.sso ? (
<a href={ssoLink} rel="noopener noreferrer">
<Button variant="text-primary" type="submit">
<Button type="text" htmlType="submit">
{`Login with SSO ${
authDetails.ssoProvider
? `(${authDetails.ssoProvider})`
@ -247,8 +247,8 @@ const Login = ({
placement="top"
>
<Button
variant="text-primary"
type="submit"
type="text"
htmlType="submit"
className="pointer-events-none opacity-30"
>
{`Login with SSO ${
@ -263,11 +263,11 @@ const Login = ({
</div>
<div
className={cn('flex items-center w-96 justify-center my-8', {
'!hidden': !authDetails?.enforceSSO,
'!hidden': !authDetails?.enforceSSO
})}
>
<a href={ssoLink} rel="noopener noreferrer">
<Button variant="primary">{`Login with SSO ${
<Button type="primary">{`Login with SSO ${
authDetails.ssoProvider ? `(${authDetails.ssoProvider})` : ''
}`}</Button>
</a>

View file

@ -399,21 +399,18 @@ class UserStore {
};
requestResetPassword = async (params: any) => {
runInAction(() => {
this.loading = true;
});
this.loading = true;
try {
const response = await userService.requestResetPassword(params);
if (response.errors) {
toast.error(response.errors[0] || 'Error resetting your password, please try again');
return response;
}
await userService.requestResetPassword(params);
// if (response.errors) {
// toast.error(response.errors[0] || 'Error resetting your password, please try again');
// return response;
// }
} catch (error) {
toast.error('Unexpected error resetting your password; please try again');
toast.error(error.message || 'Unexpected error resetting your password; please try again');
throw error;
} finally {
runInAction(() => {
this.loading = false;
});
}
};

View file

@ -156,17 +156,9 @@ export default class UserService {
}
async requestResetPassword(data: any) {
try {
const response = await this.client.post('/password/reset-link', data);
const responseData = await response.json();
return responseData.data || {};
} catch (error: any) {
if (error.response) {
const errorData = await error.response.json();
return { errors: errorData.errors };
}
return { errors: ['An unexpected error occurred.'] };
}
const response = await this.client.post('/password/reset-link', data);
const responseData = await response.json();
return responseData.data || {};
}
updatePassword = async (data: any) => {

View file

@ -6,27 +6,18 @@ export default class LoginService extends BaseService {
password: string,
captchaResponse?: string
}) {
try {
const response = await this.client.post('/login', {
email: email.trim(),
password,
'g-recaptcha-response': captchaResponse
});
const response = await this.client.post('/login', {
email: email.trim(),
password,
'g-recaptcha-response': captchaResponse
});
const responseData = await response.json();
const responseData = await response.json();
if (responseData.errors) {
throw new Error(responseData.errors[0] || 'An unexpected error occurred.');
}
// if (responseData.errors) {
// throw new Error(responseData.errors[0] || 'An unexpected error occurred.');
// }
return responseData || {};
} catch (error: any) {
if (error.response) {
const errorData = await error.response.json();
const errorMessage = errorData.errors ? errorData.errors[0] : 'An unexpected error occurred.';
throw new Error(errorMessage);
}
throw new Error('An unexpected error occurred.');
}
return responseData || {};
}
}