aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLibravatar André Oliveira <37463445+SpecialAro@users.noreply.github.com>2022-07-12 17:59:43 +0100
committerLibravatar GitHub <noreply@github.com>2022-07-12 16:59:43 +0000
commit6415f2746e38ebe5cb328c2af94413a4d4e5da07 (patch)
tree58cdabbcc7fe9c8ceec58780b73d2528210fdaff /src
parent6.0.0-nightly.98 [skip ci] (diff)
downloadferdium-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')
-rw-r--r--src/components/auth/AuthLayout.jsx (renamed from src/components/auth/AuthLayout.js)14
-rw-r--r--src/components/auth/ChangeServer.jsx (renamed from src/components/auth/ChangeServer.js)68
-rw-r--r--src/components/auth/Login.jsx (renamed from src/components/auth/Login.js)50
-rw-r--r--src/components/auth/SetupAssistant.jsx (renamed from src/components/auth/SetupAssistant.js)35
-rw-r--r--src/components/auth/Signup.jsx (renamed from src/components/auth/Signup.js)67
-rw-r--r--src/i18n/locales/en-US.json4
-rw-r--r--src/styles/auth.scss15
7 files changed, 149 insertions, 104 deletions
diff --git a/src/components/auth/AuthLayout.js b/src/components/auth/AuthLayout.jsx
index 41bda2f67..8a88cedb1 100644
--- a/src/components/auth/AuthLayout.js
+++ b/src/components/auth/AuthLayout.jsx
@@ -36,9 +36,13 @@ class AuthLayout extends Component {
36 appUpdateIsDownloaded: PropTypes.bool.isRequired, 36 appUpdateIsDownloaded: PropTypes.bool.isRequired,
37 }; 37 };
38 38
39 state = { 39 constructor() {
40 shouldShowAppUpdateInfoBar: true, 40 super();
41 }; 41
42 this.state = {
43 shouldShowAppUpdateInfoBar: true,
44 };
45 }
42 46
43 render() { 47 render() {
44 const { 48 const {
@@ -91,7 +95,9 @@ class AuthLayout extends Component {
91 onClick={retryHealthCheck} 95 onClick={retryHealthCheck}
92 > 96 >
93 <Icon icon={mdiFlash} /> 97 <Icon icon={mdiFlash} />
94 {intl.formatMessage(globalMessages.APIUnhealthy, { serverNameParse })} 98 {intl.formatMessage(globalMessages.APIUnhealthy, {
99 serverNameParse,
100 })}
95 </InfoBar> 101 </InfoBar>
96 )} 102 )}
97 <div className="auth__layout"> 103 <div className="auth__layout">
diff --git a/src/components/auth/ChangeServer.js b/src/components/auth/ChangeServer.jsx
index 8d0960843..8f4b85fbb 100644
--- a/src/components/auth/ChangeServer.js
+++ b/src/components/auth/ChangeServer.jsx
@@ -2,6 +2,7 @@ import { Component } from 'react';
2import PropTypes from 'prop-types'; 2import PropTypes from 'prop-types';
3import { observer } from 'mobx-react'; 3import { observer } from 'mobx-react';
4import { defineMessages, injectIntl } from 'react-intl'; 4import { defineMessages, injectIntl } from 'react-intl';
5import { mdiArrowLeftCircle } from '@mdi/js';
5import Form from '../../lib/Form'; 6import Form from '../../lib/Form';
6import Input from '../ui/Input'; 7import Input from '../ui/Input';
7import Select from '../ui/Select'; 8import Select from '../ui/Select';
@@ -12,6 +13,7 @@ import { url, required } from '../../helpers/validation-helpers';
12import { LIVE_FERDIUM_API, LIVE_FRANZ_API } from '../../config'; 13import { LIVE_FERDIUM_API, LIVE_FRANZ_API } from '../../config';
13import globalMessages from '../../i18n/globalMessages'; 14import globalMessages from '../../i18n/globalMessages';
14import { H1 } from '../ui/headline'; 15import { H1 } from '../ui/headline';
16import Icon from '../ui/icon';
15 17
16const messages = defineMessages({ 18const messages = defineMessages({
17 headline: { 19 headline: {
@@ -46,35 +48,36 @@ class ChangeServer extends Component {
46 48
47 franzServer = LIVE_FRANZ_API; 49 franzServer = LIVE_FRANZ_API;
48 50
49 defaultServers = [ this.ferdiumServer, this.franzServer ]; 51 defaultServers = [this.ferdiumServer, this.franzServer];
50 52
51 form = (() => { 53 form = (() => {
52 const { intl } = this.props; 54 const { intl } = this.props;
53 return new Form({ 55 return new Form(
54 fields: { 56 {
55 server: { 57 fields: {
56 label: intl.formatMessage(messages.label), 58 server: {
57 value: this.props.server, 59 label: intl.formatMessage(messages.label),
58 options: [ 60 value: this.props.server,
59 { value: this.ferdiumServer, label: 'Ferdium (Default)' }, 61 options: [
60 { value: this.franzServer, label: 'Franz' }, 62 { value: this.ferdiumServer, label: 'Ferdium (Default)' },
61 { 63 { value: this.franzServer, label: 'Franz' },
62 value: this.defaultServers.includes(this.props.server) 64 {
63 ? '' 65 value: this.defaultServers.includes(this.props.server)
64 : this.props.server, 66 ? ''
65 label: 'Custom', 67 : this.props.server,
66 }, 68 label: 'Custom',
67 ], 69 },
68 }, 70 ],
69 customServer: { 71 },
70 label: intl.formatMessage(messages.customServerLabel), 72 customServer: {
71 value: '', 73 label: intl.formatMessage(messages.customServerLabel),
72 validators: [url, required], 74 value: '',
75 validators: [url, required],
76 },
73 }, 77 },
74 }, 78 },
75 }, 79 intl,
76 intl, 80 );
77 );
78 })(); 81 })();
79 82
80 componentDidMount() { 83 componentDidMount() {
@@ -109,9 +112,11 @@ class ChangeServer extends Component {
109 return ( 112 return (
110 <div className="auth__container"> 113 <div className="auth__container">
111 <form className="franz-form auth__form" onSubmit={e => this.submit(e)}> 114 <form className="franz-form auth__form" onSubmit={e => this.submit(e)}>
112 <Link to='/auth/welcome'><img src="./assets/images/logo.svg" className="auth__logo" alt="" /></Link> 115 <Link to="/auth/welcome">
116 <img src="./assets/images/logo.svg" className="auth__logo" alt="" />
117 </Link>
113 <H1>{intl.formatMessage(messages.headline)}</H1> 118 <H1>{intl.formatMessage(messages.headline)}</H1>
114 {(form.$('server').value === this.franzServer) && ( 119 {form.$('server').value === this.franzServer && (
115 <Infobox type="warning"> 120 <Infobox type="warning">
116 {intl.formatMessage(messages.warning)} 121 {intl.formatMessage(messages.warning)}
117 </Infobox> 122 </Infobox>
@@ -121,8 +126,10 @@ class ChangeServer extends Component {
121 <Input 126 <Input
122 placeholder="Custom Server" 127 placeholder="Custom Server"
123 onChange={e => { 128 onChange={e => {
124 this.form.$('customServer').value = this.form.$('customServer').value.replace(/\/$/, ""); 129 this.form.$('customServer').value = this.form
125 this.submit(e) 130 .$('customServer')
131 .value.replace(/\/$/, '');
132 this.submit(e);
126 }} 133 }}
127 field={form.$('customServer')} 134 field={form.$('customServer')}
128 /> 135 />
@@ -133,6 +140,11 @@ class ChangeServer extends Component {
133 label={intl.formatMessage(globalMessages.submit)} 140 label={intl.formatMessage(globalMessages.submit)}
134 /> 141 />
135 </form> 142 </form>
143 <div className="auth__help">
144 <Link to="/auth/welcome">
145 <Icon icon={mdiArrowLeftCircle} size={1.5} />
146 </Link>
147 </div>
136 </div> 148 </div>
137 ); 149 );
138 } 150 }
diff --git a/src/components/auth/Login.js b/src/components/auth/Login.jsx
index a5893e181..33b4d3e0d 100644
--- a/src/components/auth/Login.js
+++ b/src/components/auth/Login.jsx
@@ -4,6 +4,8 @@ import PropTypes from 'prop-types';
4import { observer, inject } from 'mobx-react'; 4import { observer, inject } from 'mobx-react';
5import { defineMessages, injectIntl } from 'react-intl'; 5import { defineMessages, injectIntl } from 'react-intl';
6 6
7import { mdiArrowLeftCircle } from '@mdi/js';
8import Icon from '../ui/icon';
7import { LIVE_FRANZ_API } from '../../config'; 9import { LIVE_FRANZ_API } from '../../config';
8import { API_VERSION } from '../../environment-remote'; 10import { API_VERSION } from '../../environment-remote';
9import { serverBase } from '../../api/apiBase'; // TODO: Remove this line after fixing password recovery in-app 11import { serverBase } from '../../api/apiBase'; // TODO: Remove this line after fixing password recovery in-app
@@ -61,10 +63,6 @@ const messages = defineMessages({
61 id: 'login.link.password', 63 id: 'login.link.password',
62 defaultMessage: 'Reset password', 64 defaultMessage: 'Reset password',
63 }, 65 },
64 backToWelcome: {
65 id: 'login.backToWelcome',
66 defaultMessage: 'Click the Ferdium icon to go back to the Welcome screen',
67 },
68}); 66});
69 67
70class Login extends Component { 68class Login extends Component {
@@ -80,23 +78,25 @@ class Login extends Component {
80 78
81 form = (() => { 79 form = (() => {
82 const { intl } = this.props; 80 const { intl } = this.props;
83 return new Form({ 81 return new Form(
84 fields: { 82 {
85 email: { 83 fields: {
86 label: intl.formatMessage(messages.emailLabel), 84 email: {
87 value: '', 85 label: intl.formatMessage(messages.emailLabel),
88 validators: [required, email], 86 value: '',
89 }, 87 validators: [required, email],
90 password: { 88 },
91 label: intl.formatMessage(messages.passwordLabel), 89 password: {
92 value: '', 90 label: intl.formatMessage(messages.passwordLabel),
93 validators: [required], 91 value: '',
94 type: 'password', 92 validators: [required],
93 type: 'password',
94 },
95 }, 95 },
96 }, 96 },
97 }, 97 intl,
98 intl, 98 );
99 )})(); 99 })();
100 100
101 submit(e) { 101 submit(e) {
102 e.preventDefault(); 102 e.preventDefault();
@@ -123,7 +123,9 @@ class Login extends Component {
123 return ( 123 return (
124 <div className="auth__container"> 124 <div className="auth__container">
125 <form className="franz-form auth__form" onSubmit={e => this.submit(e)}> 125 <form className="franz-form auth__form" onSubmit={e => this.submit(e)}>
126 <Link to='/auth/welcome'><img src="./assets/images/logo.svg" className="auth__logo" alt="" /></Link> 126 <Link to="/auth/welcome">
127 <img src="./assets/images/logo.svg" className="auth__logo" alt="" />
128 </Link>
127 <H1>{intl.formatMessage(messages.headline)}</H1> 129 <H1>{intl.formatMessage(messages.headline)}</H1>
128 {isTokenExpired && ( 130 {isTokenExpired && (
129 <p className="error-message center"> 131 <p className="error-message center">
@@ -185,15 +187,15 @@ class Login extends Component {
185 <Link 187 <Link
186 // to={passwordRoute} // TODO: Uncomment this line after fixing password recovery in-app 188 // to={passwordRoute} // TODO: Uncomment this line after fixing password recovery in-app
187 to={`${serverBase()}/user/forgot`} // TODO: Remove this line after fixing password recovery in-app 189 to={`${serverBase()}/user/forgot`} // TODO: Remove this line after fixing password recovery in-app
188 target='_blank' // TODO: Remove this line after fixing password recovery in-app 190 target="_blank" // TODO: Remove this line after fixing password recovery in-app
189 > 191 >
190 {intl.formatMessage(messages.passwordLink)} 192 {intl.formatMessage(messages.passwordLink)}
191 </Link> 193 </Link>
192 </div> 194 </div>
193 <div className="auth__help"> 195 <div className="auth__help">
194 <span> 196 <Link to="/auth/welcome">
195 {intl.formatMessage(messages.backToWelcome)} 197 <Icon icon={mdiArrowLeftCircle} size={1.5} />
196 </span> 198 </Link>
197 </div> 199 </div>
198 </div> 200 </div>
199 ); 201 );
diff --git a/src/components/auth/SetupAssistant.js b/src/components/auth/SetupAssistant.jsx
index e3d2d88d1..8d15e36d1 100644
--- a/src/components/auth/SetupAssistant.js
+++ b/src/components/auth/SetupAssistant.jsx
@@ -32,6 +32,10 @@ const messages = defineMessages({
32 id: 'setupAssistant.submit.label', 32 id: 'setupAssistant.submit.label',
33 defaultMessage: "Let's go", 33 defaultMessage: "Let's go",
34 }, 34 },
35 skipButtonLabel: {
36 id: 'setupAssistant.skip.label',
37 defaultMessage: 'Skip',
38 },
35 inviteSuccessInfo: { 39 inviteSuccessInfo: {
36 id: 'invite.successInfo', 40 id: 'invite.successInfo',
37 defaultMessage: 'Invitations sent successfully', 41 defaultMessage: 'Invitations sent successfully',
@@ -145,21 +149,15 @@ class SetupAssistant extends Component {
145 isInviteSuccessful: false, 149 isInviteSuccessful: false,
146 }; 150 };
147 151
148 state = { 152 constructor() {
149 services: [ 153 super();
150 { 154
151 id: 'whatsapp', 155 this.state = {
152 }, 156 services: [],
153 { 157 isSlackModalOpen: false,
154 id: 'messenger', 158 slackWorkspace: '',
155 }, 159 };
156 { 160 }
157 id: 'gmail',
158 },
159 ],
160 isSlackModalOpen: false,
161 slackWorkspace: '',
162 };
163 161
164 slackWorkspaceHandler() { 162 slackWorkspaceHandler() {
165 const { slackWorkspace = '', services } = this.state; 163 const { slackWorkspace = '', services } = this.state;
@@ -321,6 +319,13 @@ class SetupAssistant extends Component {
321 busy={isSettingUpServices} 319 busy={isSettingUpServices}
322 disabled={isSettingUpServices || addedServices.length === 0} 320 disabled={isSettingUpServices || addedServices.length === 0}
323 /> 321 />
322 <Button
323 type="button"
324 className="auth__button auth__button--skip"
325 label={intl.formatMessage(messages.skipButtonLabel)}
326 onClick={() => onSubmit([])}
327 buttonType="secondary"
328 />
324 </div> 329 </div>
325 ); 330 );
326 } 331 }
diff --git a/src/components/auth/Signup.js b/src/components/auth/Signup.jsx
index eaa68f918..e0337656c 100644
--- a/src/components/auth/Signup.js
+++ b/src/components/auth/Signup.jsx
@@ -4,11 +4,13 @@ import PropTypes from 'prop-types';
4import { observer, inject } from 'mobx-react'; 4import { observer, inject } from 'mobx-react';
5import { defineMessages, injectIntl } from 'react-intl'; 5import { defineMessages, injectIntl } from 'react-intl';
6 6
7import { mdiArrowLeftCircle } from '@mdi/js';
7import Form from '../../lib/Form'; 8import Form from '../../lib/Form';
8import { required, email, minLength } from '../../helpers/validation-helpers'; 9import { required, email, minLength } from '../../helpers/validation-helpers';
9import Input from '../ui/Input'; 10import Input from '../ui/Input';
10import Button from '../ui/button'; 11import Button from '../ui/button';
11import Link from '../ui/Link'; 12import Link from '../ui/Link';
13import Icon from '../ui/icon';
12 14
13import { globalError as globalErrorPropType } from '../../prop-types'; 15import { globalError as globalErrorPropType } from '../../prop-types';
14import { serverBase } from '../../api/apiBase'; 16import { serverBase } from '../../api/apiBase';
@@ -75,33 +77,35 @@ class Signup extends Component {
75 77
76 form = (() => { 78 form = (() => {
77 const { intl } = this.props; 79 const { intl } = this.props;
78 return new Form({ 80 return new Form(
79 fields: { 81 {
80 firstname: { 82 fields: {
81 label: intl.formatMessage(messages.firstnameLabel), 83 firstname: {
82 value: '', 84 label: intl.formatMessage(messages.firstnameLabel),
83 validators: [required], 85 value: '',
84 }, 86 validators: [required],
85 lastname: { 87 },
86 label: intl.formatMessage(messages.lastnameLabel), 88 lastname: {
87 value: '', 89 label: intl.formatMessage(messages.lastnameLabel),
88 validators: [required], 90 value: '',
89 }, 91 validators: [required],
90 email: { 92 },
91 label: intl.formatMessage(messages.emailLabel), 93 email: {
92 value: '', 94 label: intl.formatMessage(messages.emailLabel),
93 validators: [required, email], 95 value: '',
94 }, 96 validators: [required, email],
95 password: { 97 },
96 label: intl.formatMessage(messages.passwordLabel), 98 password: {
97 value: '', 99 label: intl.formatMessage(messages.passwordLabel),
98 validators: [required, minLength(6)], 100 value: '',
99 type: 'password', 101 validators: [required, minLength(6)],
102 type: 'password',
103 },
100 }, 104 },
101 }, 105 },
102 }, 106 intl,
103 intl, 107 );
104 )})(); 108 })();
105 109
106 submit(e) { 110 submit(e) {
107 e.preventDefault(); 111 e.preventDefault();
@@ -125,7 +129,13 @@ class Signup extends Component {
125 className="franz-form auth__form" 129 className="franz-form auth__form"
126 onSubmit={e => this.submit(e)} 130 onSubmit={e => this.submit(e)}
127 > 131 >
128 <Link to='/auth/welcome'><img src="./assets/images/logo.svg" className="auth__logo" alt="" /></Link> 132 <Link to="/auth/welcome">
133 <img
134 src="./assets/images/logo.svg"
135 className="auth__logo"
136 alt=""
137 />
138 </Link>
129 <H1>{intl.formatMessage(messages.headline)}</H1> 139 <H1>{intl.formatMessage(messages.headline)}</H1>
130 <div className="grid__row"> 140 <div className="grid__row">
131 <Input field={form.$('firstname')} focus /> 141 <Input field={form.$('firstname')} focus />
@@ -182,6 +192,11 @@ class Signup extends Component {
182 {intl.formatMessage(messages.loginLink)} 192 {intl.formatMessage(messages.loginLink)}
183 </Link> 193 </Link>
184 </div> 194 </div>
195 <div className="auth__help">
196 <Link to="/auth/welcome">
197 <Icon icon={mdiArrowLeftCircle} size={1.5} />
198 </Link>
199 </div>
185 </div> 200 </div>
186 </div> 201 </div>
187 ); 202 );
diff --git a/src/i18n/locales/en-US.json b/src/i18n/locales/en-US.json
index f25d59098..d66a52b0b 100644
--- a/src/i18n/locales/en-US.json
+++ b/src/i18n/locales/en-US.json
@@ -64,7 +64,6 @@
64 "locked.touchId": "Unlock with Touch ID", 64 "locked.touchId": "Unlock with Touch ID",
65 "locked.touchIdPrompt": "unlock via Touch ID", 65 "locked.touchIdPrompt": "unlock via Touch ID",
66 "locked.unlockWithPassword": "Unlock with Password", 66 "locked.unlockWithPassword": "Unlock with Password",
67 "login.backToWelcome": "Click the Ferdium icon to go back to the Welcome screen",
68 "login.changeServer": "Change here!", 67 "login.changeServer": "Change here!",
69 "login.changeServerMessage": "You are using {serverNameParse} Server, do you want to switch?", 68 "login.changeServerMessage": "You are using {serverNameParse} Server, do you want to switch?",
70 "login.customServerQuestion": "Using a custom Ferdium server?", 69 "login.customServerQuestion": "Using a custom Ferdium server?",
@@ -427,6 +426,7 @@
427 "setupAssistant.headline": "Let's get started", 426 "setupAssistant.headline": "Let's get started",
428 "setupAssistant.subheadline": "Choose from our most used services and get back on top of your messaging now.", 427 "setupAssistant.subheadline": "Choose from our most used services and get back on top of your messaging now.",
429 "setupAssistant.submit.label": "Let's go", 428 "setupAssistant.submit.label": "Let's go",
429 "setupAssistant.skip.label": "Skip",
430 "sidebar.addNewService": "Add new service", 430 "sidebar.addNewService": "Add new service",
431 "sidebar.closeTodosDrawer": "Close Ferdium Todos", 431 "sidebar.closeTodosDrawer": "Close Ferdium Todos",
432 "sidebar.closeWorkspaceDrawer": "Close workspace drawer", 432 "sidebar.closeWorkspaceDrawer": "Close workspace drawer",
@@ -480,4 +480,4 @@
480 "workspaceDrawer.workspaceFeatureInfo": "<p>Ferdium Workspaces let you focus on what’s important right now. Set up different sets of services and easily switch between them at any time.</p><p>You decide which services you need when and where, so we can help you stay on top of your game - or easily switch off from work whenever you want.</p>", 480 "workspaceDrawer.workspaceFeatureInfo": "<p>Ferdium Workspaces let you focus on what’s important right now. Set up different sets of services and easily switch between them at any time.</p><p>You decide which services you need when and where, so we can help you stay on top of your game - or easily switch off from work whenever you want.</p>",
481 "workspaceDrawer.workspacesSettingsTooltip": "Edit workspaces settings", 481 "workspaceDrawer.workspacesSettingsTooltip": "Edit workspaces settings",
482 "workspaces.switchingIndicator.switchingTo": "Switching to" 482 "workspaces.switchingIndicator.switchingTo": "Switching to"
483} \ No newline at end of file 483}
diff --git a/src/styles/auth.scss b/src/styles/auth.scss
index 33e3a4a78..e60c4971c 100644
--- a/src/styles/auth.scss
+++ b/src/styles/auth.scss
@@ -49,6 +49,7 @@
49 display: flex; 49 display: flex;
50 align-items: center; 50 align-items: center;
51 justify-content: center; 51 justify-content: center;
52 overflow: auto;
52 } 53 }
53 54
54 .auth__container { 55 .auth__container {
@@ -85,7 +86,10 @@
85 .auth__button { 86 .auth__button {
86 width: 100%; 87 width: 100%;
87 88
88 &.auth__button--skip { margin: 10px auto 0; } 89 &.auth__button--skip {
90 margin: 10px auto 0;
91 width: 20%;
92 }
89 } 93 }
90 94
91 .touchid__button { 95 .touchid__button {
@@ -127,7 +131,10 @@
127 } 131 }
128 132
129 .auth__help { 133 .auth__help {
130 padding: 5% 2%; 134 display: flex;
135 padding-top: 2%;
136 padding-bottom: 2%;
137 justify-content: center;
131 } 138 }
132 139
133 .auth__adlk { 140 .auth__adlk {
@@ -143,10 +150,8 @@
143 .info-bar { position: absolute; } 150 .info-bar { position: absolute; }
144 151
145 &__scroll-container { 152 &__scroll-container {
146 max-height: 100vh;
147 padding: 80px 0;
148 overflow: auto;
149 width: 100%; 153 width: 100%;
154 height: fit-content;
150 } 155 }
151 156
152 .available-services { margin-bottom: 15px; } 157 .available-services { margin-bottom: 15px; }