diff options
author | André Oliveira <37463445+SpecialAro@users.noreply.github.com> | 2022-07-12 17:59:43 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-07-12 16:59:43 +0000 |
commit | 6415f2746e38ebe5cb328c2af94413a4d4e5da07 (patch) | |
tree | 58cdabbcc7fe9c8ceec58780b73d2528210fdaff /src/components/auth/Login.jsx | |
parent | 6.0.0-nightly.98 [skip ci] (diff) | |
download | ferdium-app-6415f2746e38ebe5cb328c2af94413a4d4e5da07.tar.gz ferdium-app-6415f2746e38ebe5cb328c2af94413a4d4e5da07.tar.zst ferdium-app-6415f2746e38ebe5cb328c2af94413a4d4e5da07.zip |
Refactor the 'Welcome' screen and the 'SetupAssistant' for better UX (#472)
* Change auth styling and add back button
* Add Skip button on 'SetupAssistant'
Diffstat (limited to 'src/components/auth/Login.jsx')
-rw-r--r-- | src/components/auth/Login.jsx | 205 |
1 files changed, 205 insertions, 0 deletions
diff --git a/src/components/auth/Login.jsx b/src/components/auth/Login.jsx new file mode 100644 index 000000000..33b4d3e0d --- /dev/null +++ b/src/components/auth/Login.jsx | |||
@@ -0,0 +1,205 @@ | |||
1 | /* eslint jsx-a11y/anchor-is-valid: 0 */ | ||
2 | import { Component } from 'react'; | ||
3 | import PropTypes from 'prop-types'; | ||
4 | import { observer, inject } from 'mobx-react'; | ||
5 | import { defineMessages, injectIntl } from 'react-intl'; | ||
6 | |||
7 | import { mdiArrowLeftCircle } from '@mdi/js'; | ||
8 | import Icon from '../ui/icon'; | ||
9 | import { LIVE_FRANZ_API } from '../../config'; | ||
10 | import { API_VERSION } from '../../environment-remote'; | ||
11 | import { serverBase } from '../../api/apiBase'; // TODO: Remove this line after fixing password recovery in-app | ||
12 | import Form from '../../lib/Form'; | ||
13 | import { required, email } from '../../helpers/validation-helpers'; | ||
14 | import Input from '../ui/Input'; | ||
15 | import Button from '../ui/button'; | ||
16 | import Link from '../ui/Link'; | ||
17 | |||
18 | import { globalError as globalErrorPropType } from '../../prop-types'; | ||
19 | import { H1 } from '../ui/headline'; | ||
20 | |||
21 | const 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 | |||
68 | class Login extends Component { | ||
69 | static propTypes = { | ||
70 | onSubmit: PropTypes.func.isRequired, | ||
71 | isSubmitting: PropTypes.bool.isRequired, | ||
72 | isTokenExpired: PropTypes.bool.isRequired, | ||
73 | isServerLogout: PropTypes.bool.isRequired, | ||
74 | signupRoute: PropTypes.string.isRequired, | ||
75 | // passwordRoute: PropTypes.string.isRequired, // TODO: Uncomment this line after fixing password recovery in-app | ||
76 | error: globalErrorPropType.isRequired, | ||
77 | }; | ||
78 | |||
79 | form = (() => { | ||
80 | const { intl } = this.props; | ||
81 | return new Form( | ||
82 | { | ||
83 | fields: { | ||
84 | email: { | ||
85 | label: intl.formatMessage(messages.emailLabel), | ||
86 | value: '', | ||
87 | validators: [required, email], | ||
88 | }, | ||
89 | password: { | ||
90 | label: intl.formatMessage(messages.passwordLabel), | ||
91 | value: '', | ||
92 | validators: [required], | ||
93 | type: 'password', | ||
94 | }, | ||
95 | }, | ||
96 | }, | ||
97 | intl, | ||
98 | ); | ||
99 | })(); | ||
100 | |||
101 | submit(e) { | ||
102 | e.preventDefault(); | ||
103 | this.form.submit({ | ||
104 | onSuccess: form => { | ||
105 | this.props.onSubmit(form.values()); | ||
106 | }, | ||
107 | onError: () => {}, | ||
108 | }); | ||
109 | } | ||
110 | |||
111 | render() { | ||
112 | const { form } = this; | ||
113 | const { intl } = this.props; | ||
114 | const { | ||
115 | isSubmitting, | ||
116 | isTokenExpired, | ||
117 | isServerLogout, | ||
118 | signupRoute, | ||
119 | // passwordRoute, // TODO: Uncomment this line after fixing password recovery in-app | ||
120 | error, | ||
121 | } = this.props; | ||
122 | |||
123 | return ( | ||
124 | <div className="auth__container"> | ||
125 | <form className="franz-form auth__form" onSubmit={e => this.submit(e)}> | ||
126 | <Link to="/auth/welcome"> | ||
127 | <img src="./assets/images/logo.svg" className="auth__logo" alt="" /> | ||
128 | </Link> | ||
129 | <H1>{intl.formatMessage(messages.headline)}</H1> | ||
130 | {isTokenExpired && ( | ||
131 | <p className="error-message center"> | ||
132 | {intl.formatMessage(messages.tokenExpired)} | ||
133 | </p> | ||
134 | )} | ||
135 | {isServerLogout && ( | ||
136 | <p className="error-message center"> | ||
137 | {intl.formatMessage(messages.serverLogout)} | ||
138 | </p> | ||
139 | )} | ||
140 | <Input field={form.$('email')} focus /> | ||
141 | <Input field={form.$('password')} showPasswordToggle /> | ||
142 | {error.code === 'invalid-credentials' && ( | ||
143 | <> | ||
144 | <p className="error-message center"> | ||
145 | {intl.formatMessage(messages.invalidCredentials)} | ||
146 | </p> | ||
147 | {window['ferdium'].stores.settings.all.app.server !== | ||
148 | LIVE_FRANZ_API && ( | ||
149 | <p className="error-message center"> | ||
150 | {intl.formatMessage(messages.customServerQuestion)}{' '} | ||
151 | <Link | ||
152 | to={`${window[ | ||
153 | 'ferdium' | ||
154 | ].stores.settings.all.app.server.replace( | ||
155 | API_VERSION, | ||
156 | '', | ||
157 | )}/import`} | ||
158 | target="_blank" | ||
159 | style={{ cursor: 'pointer', textDecoration: 'underline' }} | ||
160 | > | ||
161 | {intl.formatMessage(messages.customServerSuggestion)} | ||
162 | </Link> | ||
163 | </p> | ||
164 | )} | ||
165 | </> | ||
166 | )} | ||
167 | {isSubmitting ? ( | ||
168 | <Button | ||
169 | className="auth__button is-loading" | ||
170 | buttonType="secondary" | ||
171 | label={`${intl.formatMessage(messages.submitButtonLabel)} ...`} | ||
172 | loaded={false} | ||
173 | disabled | ||
174 | /> | ||
175 | ) : ( | ||
176 | <Button | ||
177 | type="submit" | ||
178 | className="auth__button" | ||
179 | label={intl.formatMessage(messages.submitButtonLabel)} | ||
180 | /> | ||
181 | )} | ||
182 | </form> | ||
183 | <div className="auth__links"> | ||
184 | <Link to={signupRoute}> | ||
185 | {intl.formatMessage(messages.signupLink)} | ||
186 | </Link> | ||
187 | <Link | ||
188 | // to={passwordRoute} // TODO: Uncomment this line after fixing password recovery in-app | ||
189 | to={`${serverBase()}/user/forgot`} // TODO: Remove this line after fixing password recovery in-app | ||
190 | target="_blank" // TODO: Remove this line after fixing password recovery in-app | ||
191 | > | ||
192 | {intl.formatMessage(messages.passwordLink)} | ||
193 | </Link> | ||
194 | </div> | ||
195 | <div className="auth__help"> | ||
196 | <Link to="/auth/welcome"> | ||
197 | <Icon icon={mdiArrowLeftCircle} size={1.5} /> | ||
198 | </Link> | ||
199 | </div> | ||
200 | </div> | ||
201 | ); | ||
202 | } | ||
203 | } | ||
204 | |||
205 | export default injectIntl(inject('actions')(observer(Login))); | ||