diff options
Diffstat (limited to 'src/components')
-rw-r--r-- | src/components/auth/Import.js | 17 | ||||
-rw-r--r-- | src/components/auth/Invite.js | 128 | ||||
-rw-r--r-- | src/components/auth/Login.js | 4 | ||||
-rw-r--r-- | src/components/auth/Password.js | 2 | ||||
-rw-r--r-- | src/components/auth/Pricing.js | 2 | ||||
-rw-r--r-- | src/components/auth/Signup.js | 10 | ||||
-rw-r--r-- | src/components/auth/Welcome.js | 2 | ||||
-rw-r--r-- | src/components/layout/Sidebar.js | 4 | ||||
-rw-r--r-- | src/components/settings/account/AccountDashboard.js | 54 | ||||
-rw-r--r-- | src/components/settings/navigation/SettingsNavigation.js | 11 | ||||
-rw-r--r-- | src/components/settings/services/ServiceError.js | 2 | ||||
-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'; | |||
3 | import { observer } from 'mobx-react'; | 3 | import { observer } from 'mobx-react'; |
4 | import { defineMessages, intlShape } from 'react-intl'; | 4 | import { defineMessages, intlShape } from 'react-intl'; |
5 | import { Link } from 'react-router'; | 5 | import { Link } from 'react-router'; |
6 | import classnames from 'classnames'; | ||
6 | 7 | ||
8 | import Infobox from '../ui/Infobox'; | ||
9 | import Appear from '../ui/effects/Appear'; | ||
7 | import Form from '../../lib/Form'; | 10 | import Form from '../../lib/Form'; |
8 | import { email } from '../../helpers/validation-helpers'; | 11 | import { email } from '../../helpers/validation-helpers'; |
9 | import Input from '../ui/Input'; | 12 | import Input from '../ui/Input'; |
10 | import Button from '../ui/Button'; | 13 | import Button from '../ui/Button'; |
11 | 14 | ||
12 | const messages = defineMessages({ | 15 | const 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 |
36 | export default class Invite extends Component { | 47 | export 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'; |
8 | import Loader from '../ui/Loader'; | 8 | import Loader from '../ui/Loader'; |
9 | import Appear from '../ui/effects/Appear'; | 9 | import Appear from '../ui/effects/Appear'; |
10 | import SubscriptionForm from '../../containers/ui/SubscriptionFormScreen'; | 10 | import SubscriptionForm from '../../containers/subscription/SubscriptionFormScreen'; |
11 | 11 | ||
12 | const messages = defineMessages({ | 12 | const 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 @@ | |||
1 | import React, { Component } from 'react'; | 1 | import React, { Component } from 'react'; |
2 | import PropTypes from 'prop-types'; | 2 | import PropTypes from 'prop-types'; |
3 | import { observer, PropTypes as MobxPropTypes } from 'mobx-react'; | 3 | import { observer, PropTypes as MobxPropTypes } from 'mobx-react'; |
4 | import { defineMessages, intlShape, FormattedMessage } from 'react-intl'; | 4 | import { defineMessages, intlShape } from 'react-intl'; |
5 | import ReactTooltip from 'react-tooltip'; | 5 | import ReactTooltip from 'react-tooltip'; |
6 | import moment from 'moment'; | 6 | import moment from 'moment'; |
7 | 7 | ||
@@ -9,7 +9,7 @@ import Loader from '../../ui/Loader'; | |||
9 | import Button from '../../ui/Button'; | 9 | import Button from '../../ui/Button'; |
10 | import Infobox from '../../ui/Infobox'; | 10 | import Infobox from '../../ui/Infobox'; |
11 | import Link from '../../ui/Link'; | 11 | import Link from '../../ui/Link'; |
12 | import SubscriptionForm from '../../../containers/ui/SubscriptionFormScreen'; | 12 | import SubscriptionForm from '../../../containers/subscription/SubscriptionFormScreen'; |
13 | 13 | ||
14 | const messages = defineMessages({ | 14 | const 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 |
29 | export default class EditServiceForm extends Component { | 29 | export 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 | | ||
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 | |||