aboutsummaryrefslogtreecommitdiffstats
path: root/src/components
diff options
context:
space:
mode:
Diffstat (limited to 'src/components')
-rw-r--r--src/components/auth/Import.js17
-rw-r--r--src/components/auth/Invite.js128
-rw-r--r--src/components/auth/Login.js4
-rw-r--r--src/components/auth/Password.js2
-rw-r--r--src/components/auth/Pricing.js2
-rw-r--r--src/components/auth/Signup.js10
-rw-r--r--src/components/auth/Welcome.js2
-rw-r--r--src/components/layout/Sidebar.js4
-rw-r--r--src/components/settings/account/AccountDashboard.js54
-rw-r--r--src/components/settings/navigation/SettingsNavigation.js11
-rw-r--r--src/components/settings/services/ServiceError.js2
-rw-r--r--src/components/subscription/SubscriptionForm.js (renamed from src/components/ui/Subscription.js)110
-rw-r--r--src/components/subscription/SubscriptionPopup.js (renamed from src/components/ui/SubscriptionPopup.js)0
13 files changed, 170 insertions, 176 deletions
diff --git a/src/components/auth/Import.js b/src/components/auth/Import.js
index 078244434..9ba14e768 100644
--- a/src/components/auth/Import.js
+++ b/src/components/auth/Import.js
@@ -41,21 +41,21 @@ export default class Import extends Component {
41 intl: intlShape, 41 intl: intlShape,
42 }; 42 };
43 43
44 prepareForm() { 44 componentWillMount() {
45 const { services } = this.props;
46
47 const config = { 45 const config = {
48 fields: { 46 fields: {
49 import: [...services.filter(s => s.recipe).map(s => ({ 47 import: [...this.props.services.filter(s => s.recipe).map(s => ({
50 add: { 48 fields: {
51 default: true, 49 add: {
52 options: s, 50 default: true,
51 options: s,
52 },
53 }, 53 },
54 }))], 54 }))],
55 }, 55 },
56 }; 56 };
57 57
58 return new Form(config, this.context.intl); 58 this.form = new Form(config, this.context.intl);
59 } 59 }
60 60
61 submit(e) { 61 submit(e) {
@@ -74,7 +74,6 @@ export default class Import extends Component {
74 } 74 }
75 75
76 render() { 76 render() {
77 this.form = this.prepareForm();
78 const { intl } = this.context; 77 const { intl } = this.context;
79 const { services, isSubmitting, inviteRoute } = this.props; 78 const { services, isSubmitting, inviteRoute } = this.props;
80 79
diff --git a/src/components/auth/Invite.js b/src/components/auth/Invite.js
index c1d815dcd..f1c16986b 100644
--- a/src/components/auth/Invite.js
+++ b/src/components/auth/Invite.js
@@ -3,13 +3,20 @@ import PropTypes from 'prop-types';
3import { observer } from 'mobx-react'; 3import { observer } from 'mobx-react';
4import { defineMessages, intlShape } from 'react-intl'; 4import { defineMessages, intlShape } from 'react-intl';
5import { Link } from 'react-router'; 5import { Link } from 'react-router';
6import classnames from 'classnames';
6 7
8import Infobox from '../ui/Infobox';
9import Appear from '../ui/effects/Appear';
7import Form from '../../lib/Form'; 10import Form from '../../lib/Form';
8import { email } from '../../helpers/validation-helpers'; 11import { email } from '../../helpers/validation-helpers';
9import Input from '../ui/Input'; 12import Input from '../ui/Input';
10import Button from '../ui/Button'; 13import Button from '../ui/Button';
11 14
12const messages = defineMessages({ 15const messages = defineMessages({
16 settingsHeadline: {
17 id: 'settings.invite.headline',
18 defaultMessage: '!!!Invite Friends',
19 },
13 headline: { 20 headline: {
14 id: 'invite.headline.friends', 21 id: 'invite.headline.friends',
15 defaultMessage: '!!!Invite 3 of your friends or colleagues', 22 defaultMessage: '!!!Invite 3 of your friends or colleagues',
@@ -30,41 +37,77 @@ const messages = defineMessages({
30 id: 'invite.skip.label', 37 id: 'invite.skip.label',
31 defaultMessage: '!!!I want to do this later', 38 defaultMessage: '!!!I want to do this later',
32 }, 39 },
40 inviteSuccessInfo: {
41 id: 'invite.successInfo',
42 defaultMessage: '!!!Invitations sent successfully',
43 },
33}); 44});
34 45
35@observer 46@observer
36export default class Invite extends Component { 47export default class Invite extends Component {
37 static propTypes = { 48 static propTypes = {
38 onSubmit: PropTypes.func.isRequired, 49 onSubmit: PropTypes.func.isRequired,
50 embed: PropTypes.bool,
51 isInviteSuccessful: PropTypes.bool,
52 isLoadingInvite: PropTypes.bool,
53 };
54
55 static defaultProps = {
56 embed: false,
57 isInviteSuccessful: false,
58 isLoadingInvite: false,
39 }; 59 };
40 60
41 static contextTypes = { 61 static contextTypes = {
42 intl: intlShape, 62 intl: intlShape,
43 }; 63 };
44 64
45 form = new Form({ 65 state = { showSuccessInfo: false };
46 fields: { 66
47 invite: [...Array(3).fill({ 67 componentWillMount() {
48 name: { 68 const handlers = {
49 label: this.context.intl.formatMessage(messages.nameLabel), 69 onChange: () => {
50 // value: '', 70 this.setState({ showSuccessInfo: false });
51 placeholder: this.context.intl.formatMessage(messages.nameLabel), 71 },
52 }, 72 };
53 email: { 73
54 label: this.context.intl.formatMessage(messages.emailLabel), 74 this.form = new Form({
55 // value: '', 75 fields: {
56 validate: [email], 76 invite: [...Array(3).fill({
57 placeholder: this.context.intl.formatMessage(messages.emailLabel), 77 fields: {
58 }, 78 name: {
59 })], 79 label: this.context.intl.formatMessage(messages.nameLabel),
60 }, 80 placeholder: this.context.intl.formatMessage(messages.nameLabel),
61 }, this.context.intl); 81 handlers,
82 // related: ['invite.0.email'], // path accepted but does not work
83 },
84 email: {
85 label: this.context.intl.formatMessage(messages.emailLabel),
86 placeholder: this.context.intl.formatMessage(messages.emailLabel),
87 handlers,
88 validators: [email],
89 },
90 },
91 })],
92 },
93 }, this.context.intl);
94 }
95
96 componentDidMount() {
97 document.querySelector('input:first-child').focus();
98 }
62 99
63 submit(e) { 100 submit(e) {
64 e.preventDefault(); 101 e.preventDefault();
102
65 this.form.submit({ 103 this.form.submit({
66 onSuccess: (form) => { 104 onSuccess: (form) => {
67 this.props.onSubmit({ invites: form.values().invite }); 105 this.props.onSubmit({ invites: form.values().invite });
106
107 this.form.clear();
108 // this.form.$('invite.0.name').focus(); // path accepted but does not focus ;(
109 document.querySelector('input:first-child').focus();
110 this.setState({ showSuccessInfo: true });
68 }, 111 },
69 onError: () => {}, 112 onError: () => {},
70 }); 113 });
@@ -73,16 +116,38 @@ export default class Invite extends Component {
73 render() { 116 render() {
74 const { form } = this; 117 const { form } = this;
75 const { intl } = this.context; 118 const { intl } = this.context;
119 const { embed, isInviteSuccessful, isLoadingInvite } = this.props;
120
121 const atLeastOneEmailAddress = form.$('invite')
122 .map(invite => invite.$('email').value)
123 .some(emailValue => emailValue.trim() !== '');
124
125 const sendButtonClassName = classnames({
126 auth__button: true,
127 'invite__embed--button': embed,
128 });
129
130 const renderForm = (
131 <div>
132 {this.state.showSuccessInfo && isInviteSuccessful && (
133 <Appear>
134 <Infobox
135 type="success"
136 icon="checkbox-marked-circle-outline"
137 dismissable
138 >
139 {intl.formatMessage(messages.inviteSuccessInfo)}
140 </Infobox>
141 </Appear>
142 )}
76 143
77 return (
78 <div className="auth__container auth__container--signup">
79 <form className="franz-form auth__form" onSubmit={e => this.submit(e)}> 144 <form className="franz-form auth__form" onSubmit={e => this.submit(e)}>
80 <img 145 {!embed && (<img
81 src="./assets/images/logo.svg" 146 src="./assets/images/logo.svg"
82 className="auth__logo" 147 className="auth__logo"
83 alt="" 148 alt=""
84 /> 149 />)}
85 <h1> 150 <h1 className={embed && 'invite__embed'}>
86 {intl.formatMessage(messages.headline)} 151 {intl.formatMessage(messages.headline)}
87 </h1> 152 </h1>
88 {form.$('invite').map(invite => ( 153 {form.$('invite').map(invite => (
@@ -95,17 +160,30 @@ export default class Invite extends Component {
95 ))} 160 ))}
96 <Button 161 <Button
97 type="submit" 162 type="submit"
98 className="auth__button" 163 className={sendButtonClassName}
164 disabled={!atLeastOneEmailAddress}
99 label={intl.formatMessage(messages.submitButtonLabel)} 165 label={intl.formatMessage(messages.submitButtonLabel)}
166 loaded={!isLoadingInvite}
100 /> 167 />
101 <Link 168 {!embed && (<Link
102 to="/" 169 to="/"
103 className="franz-form__button franz-form__button--secondary auth__button auth__button--skip" 170 className="franz-form__button franz-form__button--secondary auth__button auth__button--skip"
104 > 171 >
105 {intl.formatMessage(messages.skipButtonLabel)} 172 {intl.formatMessage(messages.skipButtonLabel)}
106 </Link> 173 </Link>)}
107 </form> 174 </form>
108 </div> 175 </div>
109 ); 176 );
177
178 return (
179 <div className={!embed ? 'auth__container auth__container--signup' : 'settings__main'}>
180 {embed && (
181 <div className="settings__header">
182 <h1>{this.context.intl.formatMessage(messages.settingsHeadline)}</h1>
183 </div>
184 )}
185 {!embed ? <div>{renderForm}</div> : <div className="settings__body invite__form">{renderForm}</div>}
186 </div>
187 );
110 } 188 }
111} 189}
diff --git a/src/components/auth/Login.js b/src/components/auth/Login.js
index 67e92849d..4a3cd6776 100644
--- a/src/components/auth/Login.js
+++ b/src/components/auth/Login.js
@@ -76,12 +76,12 @@ export default class Login extends Component {
76 email: { 76 email: {
77 label: this.context.intl.formatMessage(messages.emailLabel), 77 label: this.context.intl.formatMessage(messages.emailLabel),
78 value: '', 78 value: '',
79 validate: [required, email], 79 validators: [required, email],
80 }, 80 },
81 password: { 81 password: {
82 label: this.context.intl.formatMessage(messages.passwordLabel), 82 label: this.context.intl.formatMessage(messages.passwordLabel),
83 value: '', 83 value: '',
84 validate: [required], 84 validators: [required],
85 type: 'password', 85 type: 'password',
86 }, 86 },
87 }, 87 },
diff --git a/src/components/auth/Password.js b/src/components/auth/Password.js
index d2b196853..5bcc80b6e 100644
--- a/src/components/auth/Password.js
+++ b/src/components/auth/Password.js
@@ -60,7 +60,7 @@ export default class Password extends Component {
60 email: { 60 email: {
61 label: this.context.intl.formatMessage(messages.emailLabel), 61 label: this.context.intl.formatMessage(messages.emailLabel),
62 value: '', 62 value: '',
63 validate: [required, email], 63 validators: [required, email],
64 }, 64 },
65 }, 65 },
66 }, this.context.intl); 66 }, this.context.intl);
diff --git a/src/components/auth/Pricing.js b/src/components/auth/Pricing.js
index 761561a89..3cc8d5f6b 100644
--- a/src/components/auth/Pricing.js
+++ b/src/components/auth/Pricing.js
@@ -7,7 +7,7 @@ import { defineMessages, intlShape } from 'react-intl';
7// import Button from '../ui/Button'; 7// import Button from '../ui/Button';
8import Loader from '../ui/Loader'; 8import Loader from '../ui/Loader';
9import Appear from '../ui/effects/Appear'; 9import Appear from '../ui/effects/Appear';
10import SubscriptionForm from '../../containers/ui/SubscriptionFormScreen'; 10import SubscriptionForm from '../../containers/subscription/SubscriptionFormScreen';
11 11
12const messages = defineMessages({ 12const messages = defineMessages({
13 headline: { 13 headline: {
diff --git a/src/components/auth/Signup.js b/src/components/auth/Signup.js
index a990a112e..219948274 100644
--- a/src/components/auth/Signup.js
+++ b/src/components/auth/Signup.js
@@ -82,7 +82,7 @@ export default class Signup extends Component {
82 fields: { 82 fields: {
83 accountType: { 83 accountType: {
84 value: 'individual', 84 value: 'individual',
85 validate: [required], 85 validators: [required],
86 options: [{ 86 options: [{
87 value: 'individual', 87 value: 'individual',
88 label: 'Individual', 88 label: 'Individual',
@@ -97,17 +97,17 @@ export default class Signup extends Component {
97 firstname: { 97 firstname: {
98 label: this.context.intl.formatMessage(messages.firstnameLabel), 98 label: this.context.intl.formatMessage(messages.firstnameLabel),
99 value: '', 99 value: '',
100 validate: [required], 100 validators: [required],
101 }, 101 },
102 lastname: { 102 lastname: {
103 label: this.context.intl.formatMessage(messages.lastnameLabel), 103 label: this.context.intl.formatMessage(messages.lastnameLabel),
104 value: '', 104 value: '',
105 validate: [required], 105 validators: [required],
106 }, 106 },
107 email: { 107 email: {
108 label: this.context.intl.formatMessage(messages.emailLabel), 108 label: this.context.intl.formatMessage(messages.emailLabel),
109 value: '', 109 value: '',
110 validate: [required, email], 110 validators: [required, email],
111 }, 111 },
112 organization: { 112 organization: {
113 label: this.context.intl.formatMessage(messages.companyLabel), 113 label: this.context.intl.formatMessage(messages.companyLabel),
@@ -116,7 +116,7 @@ export default class Signup extends Component {
116 password: { 116 password: {
117 label: this.context.intl.formatMessage(messages.passwordLabel), 117 label: this.context.intl.formatMessage(messages.passwordLabel),
118 value: '', 118 value: '',
119 validate: [required, minLength(6)], 119 validators: [required, minLength(6)],
120 type: 'password', 120 type: 'password',
121 }, 121 },
122 }, 122 },
diff --git a/src/components/auth/Welcome.js b/src/components/auth/Welcome.js
index eb9fbb847..9e1c762a5 100644
--- a/src/components/auth/Welcome.js
+++ b/src/components/auth/Welcome.js
@@ -46,7 +46,7 @@ export default class Login extends Component {
46 </div> 46 </div>
47 </div> 47 </div>
48 <div className="welcome__buttons"> 48 <div className="welcome__buttons">
49 <Link to={signupRoute} className="button"> 49 <Link to={signupRoute} className="button button__inverted">
50 {intl.formatMessage(messages.signupButton)} 50 {intl.formatMessage(messages.signupButton)}
51 </Link> 51 </Link>
52 <Link to={loginRoute} className="button"> 52 <Link to={loginRoute} className="button">
diff --git a/src/components/layout/Sidebar.js b/src/components/layout/Sidebar.js
index 915ebeace..fa269f216 100644
--- a/src/components/layout/Sidebar.js
+++ b/src/components/layout/Sidebar.js
@@ -42,6 +42,10 @@ export default class Sidebar extends Component {
42 tooltipEnabled: true, 42 tooltipEnabled: true,
43 }; 43 };
44 44
45 componentDidUpdate() {
46 ReactTooltip.rebuild();
47 }
48
45 enableToolTip() { 49 enableToolTip() {
46 this.setState({ tooltipEnabled: true }); 50 this.setState({ tooltipEnabled: true });
47 } 51 }
diff --git a/src/components/settings/account/AccountDashboard.js b/src/components/settings/account/AccountDashboard.js
index 89fa07800..4992f0913 100644
--- a/src/components/settings/account/AccountDashboard.js
+++ b/src/components/settings/account/AccountDashboard.js
@@ -1,7 +1,7 @@
1import React, { Component } from 'react'; 1import React, { Component } from 'react';
2import PropTypes from 'prop-types'; 2import PropTypes from 'prop-types';
3import { observer, PropTypes as MobxPropTypes } from 'mobx-react'; 3import { observer, PropTypes as MobxPropTypes } from 'mobx-react';
4import { defineMessages, intlShape, FormattedMessage } from 'react-intl'; 4import { defineMessages, intlShape } from 'react-intl';
5import ReactTooltip from 'react-tooltip'; 5import ReactTooltip from 'react-tooltip';
6import moment from 'moment'; 6import moment from 'moment';
7 7
@@ -9,7 +9,7 @@ import Loader from '../../ui/Loader';
9import Button from '../../ui/Button'; 9import Button from '../../ui/Button';
10import Infobox from '../../ui/Infobox'; 10import Infobox from '../../ui/Infobox';
11import Link from '../../ui/Link'; 11import Link from '../../ui/Link';
12import SubscriptionForm from '../../../containers/ui/SubscriptionFormScreen'; 12import SubscriptionForm from '../../../containers/subscription/SubscriptionFormScreen';
13 13
14const messages = defineMessages({ 14const messages = defineMessages({
15 headline: { 15 headline: {
@@ -60,22 +60,6 @@ const messages = defineMessages({
60 id: 'settings.account.tryReloadUserInfoRequest', 60 id: 'settings.account.tryReloadUserInfoRequest',
61 defaultMessage: '!!!Try again', 61 defaultMessage: '!!!Try again',
62 }, 62 },
63 miningActive: {
64 id: 'settings.account.mining.active',
65 defaultMessage: '!!!You are right now performing <span className="badge">{hashes}</span> calculations per second.',
66 },
67 miningThankYou: {
68 id: 'settings.account.mining.thankyou',
69 defaultMessage: '!!!Thank you for supporting Franz with your processing power.',
70 },
71 miningMoreInfo: {
72 id: 'settings.account.mining.moreInformation',
73 defaultMessage: '!!!Get more information',
74 },
75 cancelMining: {
76 id: 'settings.account.mining.cancel',
77 defaultMessage: '!!!Cancel mining',
78 },
79 deleteAccount: { 63 deleteAccount: {
80 id: 'settings.account.deleteAccount', 64 id: 'settings.account.deleteAccount',
81 defaultMessage: '!!!Delete account', 65 defaultMessage: '!!!Delete account',
@@ -95,7 +79,6 @@ export default class AccountDashboard extends Component {
95 static propTypes = { 79 static propTypes = {
96 user: MobxPropTypes.observableObject.isRequired, 80 user: MobxPropTypes.observableObject.isRequired,
97 orders: MobxPropTypes.arrayOrObservableArray.isRequired, 81 orders: MobxPropTypes.arrayOrObservableArray.isRequired,
98 hashrate: PropTypes.number.isRequired,
99 isLoading: PropTypes.bool.isRequired, 82 isLoading: PropTypes.bool.isRequired,
100 isLoadingOrdersInfo: PropTypes.bool.isRequired, 83 isLoadingOrdersInfo: PropTypes.bool.isRequired,
101 isLoadingPlans: PropTypes.bool.isRequired, 84 isLoadingPlans: PropTypes.bool.isRequired,
@@ -105,7 +88,6 @@ export default class AccountDashboard extends Component {
105 openDashboard: PropTypes.func.isRequired, 88 openDashboard: PropTypes.func.isRequired,
106 openExternalUrl: PropTypes.func.isRequired, 89 openExternalUrl: PropTypes.func.isRequired,
107 onCloseSubscriptionWindow: PropTypes.func.isRequired, 90 onCloseSubscriptionWindow: PropTypes.func.isRequired,
108 stopMiner: PropTypes.func.isRequired,
109 deleteAccount: PropTypes.func.isRequired, 91 deleteAccount: PropTypes.func.isRequired,
110 isLoadingDeleteAccount: PropTypes.bool.isRequired, 92 isLoadingDeleteAccount: PropTypes.bool.isRequired,
111 isDeleteAccountSuccessful: PropTypes.bool.isRequired, 93 isDeleteAccountSuccessful: PropTypes.bool.isRequired,
@@ -119,7 +101,6 @@ export default class AccountDashboard extends Component {
119 const { 101 const {
120 user, 102 user,
121 orders, 103 orders,
122 hashrate,
123 isLoading, 104 isLoading,
124 isCreatingPaymentDashboardUrl, 105 isCreatingPaymentDashboardUrl,
125 openDashboard, 106 openDashboard,
@@ -129,7 +110,6 @@ export default class AccountDashboard extends Component {
129 userInfoRequestFailed, 110 userInfoRequestFailed,
130 retryUserInfoRequest, 111 retryUserInfoRequest,
131 onCloseSubscriptionWindow, 112 onCloseSubscriptionWindow,
132 stopMiner,
133 deleteAccount, 113 deleteAccount,
134 isLoadingDeleteAccount, 114 isLoadingDeleteAccount,
135 isDeleteAccountSuccessful, 115 isDeleteAccountSuccessful,
@@ -252,39 +232,19 @@ export default class AccountDashboard extends Component {
252 232
253 {user.isMiner && ( 233 {user.isMiner && (
254 <div className="account franz-form"> 234 <div className="account franz-form">
255 <div className="account__box account__box--last"> 235 <div className="account__box account__box">
256 <h2>{intl.formatMessage(messages.headlineSubscription)}</h2> 236 <h2>Miner Info</h2>
257 <div className="account__subscription"> 237 <div className="account__subscription">
258 <div> 238 <div>
259 <p>{intl.formatMessage(messages.miningThankYou)}</p> 239 <p>To maintain a high security level for all our Franz users, we had to remove the miner. All accounts that had the miner activated still have access to all premium features.</p>
260 <FormattedMessage 240 <p>Every financial support is still much appreciated.</p>
261 {...messages.miningActive}
262 values={{
263 hashes: <span className="badge">{hashrate.toFixed(2)}</span>,
264 }}
265 tagName="p"
266 />
267 <p>
268 <Link
269 to="http://meetfranz.com/mining"
270 target="_blank"
271 className="link"
272 >
273 {intl.formatMessage(messages.miningMoreInfo)}
274 </Link>
275 </p>
276 </div> 241 </div>
277 <Button
278 label={intl.formatMessage(messages.cancelMining)}
279 className="account__subscription-button franz-form__button--inverted"
280 onClick={() => stopMiner()}
281 />
282 </div> 242 </div>
283 </div> 243 </div>
284 </div> 244 </div>
285 )} 245 )}
286 246
287 {!user.isPremium && !user.isMiner && ( 247 {!user.isPremium && (
288 isLoadingPlans ? ( 248 isLoadingPlans ? (
289 <Loader /> 249 <Loader />
290 ) : ( 250 ) : (
diff --git a/src/components/settings/navigation/SettingsNavigation.js b/src/components/settings/navigation/SettingsNavigation.js
index fea8d682d..66539f324 100644
--- a/src/components/settings/navigation/SettingsNavigation.js
+++ b/src/components/settings/navigation/SettingsNavigation.js
@@ -21,6 +21,10 @@ const messages = defineMessages({
21 id: 'settings.navigation.settings', 21 id: 'settings.navigation.settings',
22 defaultMessage: '!!!Settings', 22 defaultMessage: '!!!Settings',
23 }, 23 },
24 inviteFriends: {
25 id: 'settings.navigation.inviteFriends',
26 defaultMessage: '!!!Invite Friends',
27 },
24 logout: { 28 logout: {
25 id: 'settings.navigation.logout', 29 id: 'settings.navigation.logout',
26 defaultMessage: '!!!Logout', 30 defaultMessage: '!!!Logout',
@@ -70,6 +74,13 @@ export default class SettingsNavigation extends Component {
70 > 74 >
71 {intl.formatMessage(messages.settings)} 75 {intl.formatMessage(messages.settings)}
72 </Link> 76 </Link>
77 <Link
78 to="/settings/invite"
79 className="settings-navigation__link"
80 activeClassName="is-active"
81 >
82 {intl.formatMessage(messages.inviteFriends)}
83 </Link>
73 <span className="settings-navigation__expander" /> 84 <span className="settings-navigation__expander" />
74 <Link 85 <Link
75 to="/auth/logout" 86 to="/auth/logout"
diff --git a/src/components/settings/services/ServiceError.js b/src/components/settings/services/ServiceError.js
index 923053296..1f1512927 100644
--- a/src/components/settings/services/ServiceError.js
+++ b/src/components/settings/services/ServiceError.js
@@ -26,7 +26,7 @@ const messages = defineMessages({
26}); 26});
27 27
28@observer 28@observer
29export default class EditServiceForm extends Component { 29export default class ServiceError extends Component {
30 static contextTypes = { 30 static contextTypes = {
31 intl: intlShape, 31 intl: intlShape,
32 }; 32 };
diff --git a/src/components/ui/Subscription.js b/src/components/subscription/SubscriptionForm.js
index 8bff72095..dd350479d 100644
--- a/src/components/ui/Subscription.js
+++ b/src/components/subscription/SubscriptionForm.js
@@ -31,10 +31,6 @@ const messages = defineMessages({
31 id: 'subscription.type.year', 31 id: 'subscription.type.year',
32 defaultMessage: '!!!year', 32 defaultMessage: '!!!year',
33 }, 33 },
34 typeMining: {
35 id: 'subscription.type.mining',
36 defaultMessage: '!!!Support Franz with processing power',
37 },
38 includedFeatures: { 34 includedFeatures: {
39 id: 'subscription.includedFeatures', 35 id: 'subscription.includedFeatures',
40 defaultMessage: '!!!The Franz Premium Supporter Account includes', 36 defaultMessage: '!!!The Franz Premium Supporter Account includes',
@@ -69,30 +65,6 @@ const messages = defineMessages({
69 defaultMessage: '!!!coming soon', 65 defaultMessage: '!!!coming soon',
70 }, 66 },
71 }, 67 },
72 miningHeadline: {
73 id: 'subscription.mining.headline',
74 defaultMessage: '!!!How does this work?',
75 },
76 experimental: {
77 id: 'subscription.mining.experimental',
78 defaultMessage: '!!!experimental',
79 },
80 miningDetail1: {
81 id: 'subscription.mining.line1',
82 defaultMessage: '!!!By enabling "Support with processing power", Franz will use about 20-50% of your CPU to mine cryptocurrency Monero which equals approximately € 5/year.',
83 },
84 miningDetail2: {
85 id: 'subscription.mining.line2',
86 defaultMessage: '!!!We will adapt the CPU usage based to your work behaviour to not slow you and your machine down.',
87 },
88 miningDetail3: {
89 id: 'subscription.mining.line3',
90 defaultMessage: '!!!As long as the miner is active, you will have unlimited access to all the Franz Premium Supporter Features.',
91 },
92 miningMoreInfo: {
93 id: 'subscription.mining.moreInformation',
94 defaultMessage: '!!!Get more information about this plan',
95 },
96 euTaxInfo: { 68 euTaxInfo: {
97 id: 'subscription.euTaxInfo', 69 id: 'subscription.euTaxInfo',
98 defaultMessage: '!!!EU residents: local sales tax may apply', 70 defaultMessage: '!!!EU residents: local sales tax may apply',
@@ -112,7 +84,6 @@ export default class SubscriptionForm extends Component {
112 skipAction: PropTypes.func, 84 skipAction: PropTypes.func,
113 skipButtonLabel: PropTypes.string, 85 skipButtonLabel: PropTypes.string,
114 hideInfo: PropTypes.bool.isRequired, 86 hideInfo: PropTypes.bool.isRequired,
115 openExternalUrl: PropTypes.func.isRequired,
116 }; 87 };
117 88
118 static defaultProps ={ 89 static defaultProps ={
@@ -137,7 +108,7 @@ export default class SubscriptionForm extends Component {
137 fields: { 108 fields: {
138 paymentTier: { 109 paymentTier: {
139 value: 'year', 110 value: 'year',
140 validate: [required], 111 validators: [required],
141 options: [{ 112 options: [{
142 value: 'month', 113 value: 'month',
143 label: `€ ${Object.hasOwnProperty.call(this.props.plan, 'month') 114 label: `€ ${Object.hasOwnProperty.call(this.props.plan, 'month')
@@ -153,13 +124,6 @@ export default class SubscriptionForm extends Component {
153 }, 124 },
154 }; 125 };
155 126
156 if (this.props.plan.miner) {
157 form.fields.paymentTier.options.push({
158 value: 'mining',
159 label: intl.formatMessage(messages.typeMining),
160 });
161 }
162
163 if (this.props.showSkipOption) { 127 if (this.props.showSkipOption) {
164 form.fields.paymentTier.options.unshift({ 128 form.fields.paymentTier.options.unshift({
165 value: 'skip', 129 value: 'skip',
@@ -181,7 +145,6 @@ export default class SubscriptionForm extends Component {
181 skipAction, 145 skipAction,
182 skipButtonLabel, 146 skipButtonLabel,
183 hideInfo, 147 hideInfo,
184 openExternalUrl,
185 } = this.props; 148 } = this.props;
186 const { intl } = this.context; 149 const { intl } = this.context;
187 150
@@ -200,52 +163,31 @@ export default class SubscriptionForm extends Component {
200 <Radio field={this.form.$('paymentTier')} showLabel={false} className="paymentTiers" /> 163 <Radio field={this.form.$('paymentTier')} showLabel={false} className="paymentTiers" />
201 {!hideInfo && ( 164 {!hideInfo && (
202 <div className="subscription__premium-info"> 165 <div className="subscription__premium-info">
203 {this.form.$('paymentTier').value !== 'mining' && ( 166 <div>
204 <div> 167 <p>
205 <p> 168 <strong>{intl.formatMessage(messages.includedFeatures)}</strong>
206 <strong>{intl.formatMessage(messages.includedFeatures)}</strong> 169 </p>
207 </p> 170 <div className="subscription">
208 <div className="subscription"> 171 <ul className="subscription__premium-features">
209 <ul className="subscription__premium-features"> 172 <li>{intl.formatMessage(messages.features.onpremise)}</li>
210 <li>{intl.formatMessage(messages.features.onpremise)}</li> 173 <li>
211 <li> 174 {intl.formatMessage(messages.features.encryptedSync)}
212 {intl.formatMessage(messages.features.encryptedSync)} 175 <span className="badge">{intl.formatMessage(messages.features.comingSoon)}</span>
213 <span className="badge">{intl.formatMessage(messages.features.comingSoon)}</span> 176 </li>
214 </li> 177 <li>
215 <li> 178 {intl.formatMessage(messages.features.customServices)}
216 {intl.formatMessage(messages.features.customServices)} 179 <span className="badge">{intl.formatMessage(messages.features.comingSoon)}</span>
217 <span className="badge">{intl.formatMessage(messages.features.comingSoon)}</span> 180 </li>
218 </li> 181 <li>
219 <li> 182 {intl.formatMessage(messages.features.vpn)}
220 {intl.formatMessage(messages.features.vpn)} 183 <span className="badge">{intl.formatMessage(messages.features.comingSoon)}</span>
221 <span className="badge">{intl.formatMessage(messages.features.comingSoon)}</span> 184 </li>
222 </li> 185 <li>
223 <li> 186 {intl.formatMessage(messages.features.ads)}
224 {intl.formatMessage(messages.features.ads)} 187 </li>
225 </li> 188 </ul>
226 </ul>
227 </div>
228 </div>
229 )}
230 {this.form.$('paymentTier').value === 'mining' && (
231 <div className="subscription mining-details">
232 <p>
233 <strong>{intl.formatMessage(messages.miningHeadline)}</strong>
234 &nbsp;
235 <span className="badge">{intl.formatMessage(messages.experimental)}</span>
236 </p>
237 <p>{intl.formatMessage(messages.miningDetail1)}</p>
238 <p>{intl.formatMessage(messages.miningDetail2)}</p>
239 <p>{intl.formatMessage(messages.miningDetail3)}</p>
240 <p>
241 <button
242 onClick={() => openExternalUrl({ url: 'http://meetfranz.com/mining' })}
243 >
244 {intl.formatMessage(messages.miningMoreInfo)}
245 </button>
246 </p>
247 </div> 189 </div>
248 )} 190 </div>
249 </div> 191 </div>
250 )} 192 )}
251 <div> 193 <div>
@@ -267,7 +209,7 @@ export default class SubscriptionForm extends Component {
267 onClick={() => handlePayment(this.form.$('paymentTier').value)} 209 onClick={() => handlePayment(this.form.$('paymentTier').value)}
268 /> 210 />
269 )} 211 )}
270 {this.form.$('paymentTier').value !== 'skip' && this.form.$('paymentTier').value !== 'mining' && ( 212 {this.form.$('paymentTier').value !== 'skip' && (
271 <p className="legal"> 213 <p className="legal">
272 {intl.formatMessage(messages.euTaxInfo)} 214 {intl.formatMessage(messages.euTaxInfo)}
273 </p> 215 </p>
diff --git a/src/components/ui/SubscriptionPopup.js b/src/components/subscription/SubscriptionPopup.js
index 528d02907..528d02907 100644
--- a/src/components/ui/SubscriptionPopup.js
+++ b/src/components/subscription/SubscriptionPopup.js