aboutsummaryrefslogtreecommitdiffstats
path: root/src/components/auth/Login.tsx
diff options
context:
space:
mode:
authorLibravatar muhamedsalih-tw <104364298+muhamedsalih-tw@users.noreply.github.com>2022-10-31 05:20:17 +0530
committerLibravatar GitHub <noreply@github.com>2022-10-30 23:50:17 +0000
commit011e73f24f8ae15091d41781c93c313d0167d887 (patch)
tree3e012f97a9c3ecf98e348690f82dae0d58ec0155 /src/components/auth/Login.tsx
parent6.2.1-nightly.33 [skip ci] (diff)
downloadferdium-app-011e73f24f8ae15091d41781c93c313d0167d887.tar.gz
ferdium-app-011e73f24f8ae15091d41781c93c313d0167d887.tar.zst
ferdium-app-011e73f24f8ae15091d41781c93c313d0167d887.zip
Convert LoginScreen component tree to typescript (#721)
Diffstat (limited to 'src/components/auth/Login.tsx')
-rw-r--r--src/components/auth/Login.tsx210
1 files changed, 210 insertions, 0 deletions
diff --git a/src/components/auth/Login.tsx b/src/components/auth/Login.tsx
new file mode 100644
index 000000000..65381fe04
--- /dev/null
+++ b/src/components/auth/Login.tsx
@@ -0,0 +1,210 @@
1import { Component, FormEvent, ReactElement } from 'react';
2import { observer, inject } from 'mobx-react';
3import { defineMessages, injectIntl, WrappedComponentProps } from 'react-intl';
4import { mdiArrowLeftCircle } from '@mdi/js';
5import { noop } from 'lodash';
6import Icon from '../ui/icon';
7import { LIVE_FRANZ_API } from '../../config';
8import { API_VERSION } from '../../environment-remote';
9import { serverBase } from '../../api/apiBase'; // TODO: Remove this line after fixing password recovery in-app
10import Form from '../../lib/Form';
11import { required, email } from '../../helpers/validation-helpers';
12import Input from '../ui/Input';
13import Button from '../ui/button';
14import Link from '../ui/Link';
15import { H1 } from '../ui/headline';
16import {
17 GlobalError,
18 StoresProps,
19} from '../../@types/ferdium-components.types';
20
21const messages = defineMessages({
22 headline: {
23 id: 'login.headline',
24 defaultMessage: 'Sign in',
25 },
26 emailLabel: {
27 id: 'login.email.label',
28 defaultMessage: 'Email address',
29 },
30 passwordLabel: {
31 id: 'login.password.label',
32 defaultMessage: 'Password',
33 },
34 submitButtonLabel: {
35 id: 'login.submit.label',
36 defaultMessage: 'Sign in',
37 },
38 invalidCredentials: {
39 id: 'login.invalidCredentials',
40 defaultMessage: 'Email or password not valid',
41 },
42 customServerQuestion: {
43 id: 'login.customServerQuestion',
44 defaultMessage: 'Using a custom Ferdium server?',
45 },
46 customServerSuggestion: {
47 id: 'login.customServerSuggestion',
48 defaultMessage: 'Try importing your Franz account',
49 },
50 tokenExpired: {
51 id: 'login.tokenExpired',
52 defaultMessage: 'Your session expired, please login again.',
53 },
54 serverLogout: {
55 id: 'login.serverLogout',
56 defaultMessage: 'Your session expired, please login again.',
57 },
58 signupLink: {
59 id: 'login.link.signup',
60 defaultMessage: 'Create a free account',
61 },
62 passwordLink: {
63 id: 'login.link.password',
64 defaultMessage: 'Reset password',
65 },
66});
67
68interface IProps extends Partial<StoresProps>, WrappedComponentProps {
69 onSubmit: (...args: any[]) => void;
70 isSubmitting: boolean;
71 isTokenExpired: boolean;
72 isServerLogout: boolean;
73 signupRoute: string;
74 // eslint-disable-next-line react/no-unused-prop-types
75 passwordRoute: string; // TODO: Uncomment this line after fixing password recovery in-app
76 error: GlobalError;
77}
78
79@inject('actions')
80@observer
81class Login extends Component<IProps> {
82 form: Form;
83
84 constructor(props: IProps) {
85 super(props);
86
87 this.form = new Form({
88 fields: {
89 email: {
90 label: this.props.intl.formatMessage(messages.emailLabel),
91 value: '',
92 validators: [required, email],
93 },
94 password: {
95 label: this.props.intl.formatMessage(messages.passwordLabel),
96 value: '',
97 validators: [required],
98 type: 'password',
99 },
100 },
101 });
102 }
103
104 submit(e: FormEvent<HTMLFormElement>): void {
105 e.preventDefault();
106 this.form.submit({
107 onSuccess: form => {
108 this.props.onSubmit(form.values());
109 },
110 onError: () => {},
111 });
112 }
113
114 render(): ReactElement {
115 const { form } = this;
116 const {
117 isSubmitting,
118 isTokenExpired,
119 isServerLogout,
120 signupRoute,
121 error,
122 intl,
123 // passwordRoute, // TODO: Uncomment this line after fixing password recovery in-app
124 } = this.props;
125
126 return (
127 <div className="auth__container">
128 <form className="franz-form auth__form" onSubmit={e => this.submit(e)}>
129 <Link to="/auth/welcome">
130 <img src="./assets/images/logo.svg" className="auth__logo" alt="" />
131 </Link>
132 <H1>{intl.formatMessage(messages.headline)}</H1>
133 {isTokenExpired && (
134 <p className="error-message center">
135 {intl.formatMessage(messages.tokenExpired)}
136 </p>
137 )}
138 {isServerLogout && (
139 <p className="error-message center">
140 {intl.formatMessage(messages.serverLogout)}
141 </p>
142 )}
143 <Input field={form.$('email')} focus />
144 <Input field={form.$('password')} showPasswordToggle />
145 {error.code === 'invalid-credentials' && (
146 <>
147 <p className="error-message center">
148 {intl.formatMessage(messages.invalidCredentials)}
149 </p>
150 {window['ferdium'].stores.settings.all.app.server !==
151 LIVE_FRANZ_API && (
152 <p className="error-message center">
153 {intl.formatMessage(messages.customServerQuestion)}{' '}
154 <Link
155 to={`${window[
156 'ferdium'
157 ].stores.settings.all.app.server.replace(
158 API_VERSION,
159 '',
160 )}/import`}
161 target="_blank"
162 style={{ cursor: 'pointer', textDecoration: 'underline' }}
163 >
164 {intl.formatMessage(messages.customServerSuggestion)}
165 </Link>
166 </p>
167 )}
168 </>
169 )}
170 {isSubmitting ? (
171 <Button
172 className="auth__button is-loading"
173 buttonType="secondary"
174 label={`${intl.formatMessage(messages.submitButtonLabel)} ...`}
175 loaded={false}
176 disabled
177 onClick={noop}
178 />
179 ) : (
180 <Button
181 type="submit"
182 className="auth__button"
183 label={intl.formatMessage(messages.submitButtonLabel)}
184 onClick={noop}
185 />
186 )}
187 </form>
188 <div className="auth__links">
189 <Link to={signupRoute}>
190 {intl.formatMessage(messages.signupLink)}
191 </Link>
192 <Link
193 // to={passwordRoute} // TODO: Uncomment this line after fixing password recovery in-app
194 to={`${serverBase()}/user/forgot`} // TODO: Remove this line after fixing password recovery in-app
195 target="_blank" // TODO: Remove this line after fixing password recovery in-app
196 >
197 {intl.formatMessage(messages.passwordLink)}
198 </Link>
199 </div>
200 <div className="auth__help">
201 <Link to="/auth/welcome">
202 <Icon icon={mdiArrowLeftCircle} size={1.5} />
203 </Link>
204 </div>
205 </div>
206 );
207 }
208}
209
210export default injectIntl(Login);