aboutsummaryrefslogtreecommitdiffstats
path: root/src/containers
diff options
context:
space:
mode:
Diffstat (limited to 'src/containers')
-rw-r--r--src/containers/auth/PricingScreen.js32
-rw-r--r--src/containers/auth/SignupScreen.js22
-rw-r--r--src/containers/layout/AppLayoutContainer.js5
-rw-r--r--src/containers/settings/AccountScreen.js17
-rw-r--r--src/containers/subscription/SubscriptionFormScreen.js32
5 files changed, 92 insertions, 16 deletions
diff --git a/src/containers/auth/PricingScreen.js b/src/containers/auth/PricingScreen.js
index af1651931..21c859c12 100644
--- a/src/containers/auth/PricingScreen.js
+++ b/src/containers/auth/PricingScreen.js
@@ -20,14 +20,19 @@ export default @inject('stores', 'actions') @observer class PricingScreen extend
20 } = this.props; 20 } = this.props;
21 21
22 const { activateTrialRequest } = stores.user; 22 const { activateTrialRequest } = stores.user;
23 const { defaultTrialPlan } = stores.features.features; 23 const { defaultTrialPlan, canSkipTrial } = stores.features.anonymousFeatures;
24 24
25 actions.user.activateTrial({ planId: defaultTrialPlan }); 25 if (!canSkipTrial) {
26 await activateTrialRequest._promise;
27
28 if (!activateTrialRequest.isError) {
29 stores.router.push('/'); 26 stores.router.push('/');
30 stores.user.hasCompletedSignup = true; 27 stores.user.hasCompletedSignup = true;
28 } else {
29 actions.user.activateTrial({ planId: defaultTrialPlan });
30 await activateTrialRequest._promise;
31
32 if (!activateTrialRequest.isError) {
33 stores.router.push('/');
34 stores.user.hasCompletedSignup = true;
35 }
31 } 36 }
32 } 37 }
33 38
@@ -37,8 +42,17 @@ export default @inject('stores', 'actions') @observer class PricingScreen extend
37 stores, 42 stores,
38 } = this.props; 43 } = this.props;
39 44
40 const { getUserInfoRequest, activateTrialRequest } = stores.user; 45 const { getUserInfoRequest, activateTrialRequest, data } = stores.user;
41 const { featuresRequest } = stores.features; 46 const { featuresRequest, features } = stores.features;
47
48 const { pricingConfig } = features;
49
50 let currency = '$';
51 let price = 5.99;
52 if (pricingConfig) {
53 ({ currency } = pricingConfig);
54 ({ price } = pricingConfig.plans.pro.yearly);
55 }
42 56
43 return ( 57 return (
44 <Pricing 58 <Pricing
@@ -46,7 +60,11 @@ export default @inject('stores', 'actions') @observer class PricingScreen extend
46 isLoadingRequiredData={(getUserInfoRequest.isExecuting || !getUserInfoRequest.wasExecuted) || (featuresRequest.isExecuting || !featuresRequest.wasExecuted)} 60 isLoadingRequiredData={(getUserInfoRequest.isExecuting || !getUserInfoRequest.wasExecuted) || (featuresRequest.isExecuting || !featuresRequest.wasExecuted)}
47 isActivatingTrial={activateTrialRequest.isExecuting} 61 isActivatingTrial={activateTrialRequest.isExecuting}
48 trialActivationError={activateTrialRequest.isError} 62 trialActivationError={activateTrialRequest.isError}
63 canSkipTrial={features.canSkipTrial}
49 error={error} 64 error={error}
65 currency={currency}
66 price={price}
67 name={data.firstname}
50 /> 68 />
51 ); 69 );
52 } 70 }
diff --git a/src/containers/auth/SignupScreen.js b/src/containers/auth/SignupScreen.js
index efc7ea4c1..f93498be2 100644
--- a/src/containers/auth/SignupScreen.js
+++ b/src/containers/auth/SignupScreen.js
@@ -4,6 +4,7 @@ import { inject, observer } from 'mobx-react';
4 4
5import Signup from '../../components/auth/Signup'; 5import Signup from '../../components/auth/Signup';
6import UserStore from '../../stores/UserStore'; 6import UserStore from '../../stores/UserStore';
7import FeaturesStore from '../../stores/FeaturesStore';
7 8
8import { globalError as globalErrorPropType } from '../../prop-types'; 9import { globalError as globalErrorPropType } from '../../prop-types';
9 10
@@ -12,11 +13,27 @@ export default @inject('stores', 'actions') @observer class SignupScreen extends
12 error: globalErrorPropType.isRequired, 13 error: globalErrorPropType.isRequired,
13 }; 14 };
14 15
16 onSignup(values) {
17 const { actions, stores } = this.props;
18
19 const { canSkipTrial, defaultTrialPlan, pricingConfig } = stores.features.anonymousFeatures;
20
21 if (!canSkipTrial) {
22 Object.assign(values, {
23 plan: defaultTrialPlan,
24 currency: pricingConfig.currencyID,
25 });
26 }
27
28 actions.user.signup(values);
29 }
30
15 render() { 31 render() {
16 const { actions, stores, error } = this.props; 32 const { stores, error } = this.props;
33
17 return ( 34 return (
18 <Signup 35 <Signup
19 onSubmit={actions.user.signup} 36 onSubmit={values => this.onSignup(values)}
20 isSubmitting={stores.user.signupRequest.isExecuting} 37 isSubmitting={stores.user.signupRequest.isExecuting}
21 loginRoute={stores.user.loginRoute} 38 loginRoute={stores.user.loginRoute}
22 error={error} 39 error={error}
@@ -33,5 +50,6 @@ SignupScreen.wrappedComponent.propTypes = {
33 }).isRequired, 50 }).isRequired,
34 stores: PropTypes.shape({ 51 stores: PropTypes.shape({
35 user: PropTypes.instanceOf(UserStore).isRequired, 52 user: PropTypes.instanceOf(UserStore).isRequired,
53 features: PropTypes.instanceOf(FeaturesStore).isRequired,
36 }).isRequired, 54 }).isRequired,
37}; 55};
diff --git a/src/containers/layout/AppLayoutContainer.js b/src/containers/layout/AppLayoutContainer.js
index 95fbd109f..a4312d9de 100644
--- a/src/containers/layout/AppLayoutContainer.js
+++ b/src/containers/layout/AppLayoutContainer.js
@@ -24,6 +24,7 @@ import { state as delayAppState } from '../../features/delayApp';
24import { workspaceActions } from '../../features/workspaces/actions'; 24import { workspaceActions } from '../../features/workspaces/actions';
25import WorkspaceDrawer from '../../features/workspaces/components/WorkspaceDrawer'; 25import WorkspaceDrawer from '../../features/workspaces/components/WorkspaceDrawer';
26import { workspaceStore } from '../../features/workspaces'; 26import { workspaceStore } from '../../features/workspaces';
27import WorkspacesStore from '../../features/workspaces/store';
27 28
28export default @inject('stores', 'actions') @observer class AppLayoutContainer extends Component { 29export default @inject('stores', 'actions') @observer class AppLayoutContainer extends Component {
29 static defaultProps = { 30 static defaultProps = {
@@ -41,6 +42,7 @@ export default @inject('stores', 'actions') @observer class AppLayoutContainer e
41 globalError, 42 globalError,
42 requests, 43 requests,
43 user, 44 user,
45 workspaces,
44 } = this.props.stores; 46 } = this.props.stores;
45 47
46 const { 48 const {
@@ -79,7 +81,7 @@ export default @inject('stores', 'actions') @observer class AppLayoutContainer e
79 const isLoadingServices = services.allServicesRequest.isExecuting 81 const isLoadingServices = services.allServicesRequest.isExecuting
80 && services.allServicesRequest.isExecutingFirstTime; 82 && services.allServicesRequest.isExecutingFirstTime;
81 83
82 if (isLoadingFeatures || isLoadingServices) { 84 if (isLoadingFeatures || isLoadingServices || workspaces.isLoadingWorkspaces) {
83 return ( 85 return (
84 <ThemeProvider theme={ui.theme}> 86 <ThemeProvider theme={ui.theme}>
85 <AppLoader /> 87 <AppLoader />
@@ -175,6 +177,7 @@ AppLayoutContainer.wrappedComponent.propTypes = {
175 user: PropTypes.instanceOf(UserStore).isRequired, 177 user: PropTypes.instanceOf(UserStore).isRequired,
176 requests: PropTypes.instanceOf(RequestStore).isRequired, 178 requests: PropTypes.instanceOf(RequestStore).isRequired,
177 globalError: PropTypes.instanceOf(GlobalErrorStore).isRequired, 179 globalError: PropTypes.instanceOf(GlobalErrorStore).isRequired,
180 workspaces: PropTypes.instanceOf(WorkspacesStore).isRequired,
178 }).isRequired, 181 }).isRequired,
179 actions: PropTypes.shape({ 182 actions: PropTypes.shape({
180 service: PropTypes.shape({ 183 service: PropTypes.shape({
diff --git a/src/containers/settings/AccountScreen.js b/src/containers/settings/AccountScreen.js
index 41cdeb79a..93ab44690 100644
--- a/src/containers/settings/AccountScreen.js
+++ b/src/containers/settings/AccountScreen.js
@@ -5,6 +5,7 @@ import { inject, observer } from 'mobx-react';
5import PaymentStore from '../../stores/PaymentStore'; 5import PaymentStore from '../../stores/PaymentStore';
6import UserStore from '../../stores/UserStore'; 6import UserStore from '../../stores/UserStore';
7import AppStore from '../../stores/AppStore'; 7import AppStore from '../../stores/AppStore';
8import FeaturesStore from '../../stores/FeaturesStore';
8 9
9import AccountDashboard from '../../components/settings/account/AccountDashboard'; 10import AccountDashboard from '../../components/settings/account/AccountDashboard';
10import ErrorBoundary from '../../components/util/ErrorBoundary'; 11import ErrorBoundary from '../../components/util/ErrorBoundary';
@@ -12,8 +13,9 @@ import { WEBSITE } from '../../environment';
12 13
13export default @inject('stores', 'actions') @observer class AccountScreen extends Component { 14export default @inject('stores', 'actions') @observer class AccountScreen extends Component {
14 onCloseWindow() { 15 onCloseWindow() {
15 const { user } = this.props.stores; 16 const { user, features } = this.props.stores;
16 user.getUserInfoRequest.invalidate({ immediately: true }); 17 user.getUserInfoRequest.invalidate({ immediately: true });
18 features.featuresRequest.invalidate({ immediately: true });
17 } 19 }
18 20
19 reloadData() { 21 reloadData() {
@@ -39,12 +41,17 @@ export default @inject('stores', 'actions') @observer class AccountScreen extend
39 } 41 }
40 42
41 render() { 43 render() {
42 const { user, payment } = this.props.stores; 44 const { user, payment, features } = this.props.stores;
43 const { user: userActions } = this.props.actions; 45 const {
46 user: userActions,
47 payment: paymentActions,
48 } = this.props.actions;
44 49
45 const isLoadingUserInfo = user.getUserInfoRequest.isExecuting; 50 const isLoadingUserInfo = user.getUserInfoRequest.isExecuting;
46 const isLoadingPlans = payment.plansRequest.isExecuting; 51 const isLoadingPlans = payment.plansRequest.isExecuting;
47 52
53 const { upgradeAccount } = paymentActions;
54
48 return ( 55 return (
49 <ErrorBoundary> 56 <ErrorBoundary>
50 <AccountDashboard 57 <AccountDashboard
@@ -60,7 +67,7 @@ export default @inject('stores', 'actions') @observer class AccountScreen extend
60 isLoadingDeleteAccount={user.deleteAccountRequest.isExecuting} 67 isLoadingDeleteAccount={user.deleteAccountRequest.isExecuting}
61 isDeleteAccountSuccessful={user.deleteAccountRequest.wasExecuted && !user.deleteAccountRequest.isError} 68 isDeleteAccountSuccessful={user.deleteAccountRequest.wasExecuted && !user.deleteAccountRequest.isError}
62 openEditAccount={() => this.handleWebsiteLink('/user/profile')} 69 openEditAccount={() => this.handleWebsiteLink('/user/profile')}
63 upgradeToPro={() => this.handleWebsiteLink('/inapp/user/licenses')} 70 upgradeToPro={() => upgradeAccount({ planId: features.features.pricingConfig.plans.pro.yearly.id })}
64 openBilling={() => this.handleWebsiteLink('/user/billing')} 71 openBilling={() => this.handleWebsiteLink('/user/billing')}
65 openInvoices={() => this.handleWebsiteLink('/user/invoices')} 72 openInvoices={() => this.handleWebsiteLink('/user/invoices')}
66 /> 73 />
@@ -72,12 +79,14 @@ export default @inject('stores', 'actions') @observer class AccountScreen extend
72AccountScreen.wrappedComponent.propTypes = { 79AccountScreen.wrappedComponent.propTypes = {
73 stores: PropTypes.shape({ 80 stores: PropTypes.shape({
74 user: PropTypes.instanceOf(UserStore).isRequired, 81 user: PropTypes.instanceOf(UserStore).isRequired,
82 features: PropTypes.instanceOf(FeaturesStore).isRequired,
75 payment: PropTypes.instanceOf(PaymentStore).isRequired, 83 payment: PropTypes.instanceOf(PaymentStore).isRequired,
76 app: PropTypes.instanceOf(AppStore).isRequired, 84 app: PropTypes.instanceOf(AppStore).isRequired,
77 }).isRequired, 85 }).isRequired,
78 actions: PropTypes.shape({ 86 actions: PropTypes.shape({
79 payment: PropTypes.shape({ 87 payment: PropTypes.shape({
80 createDashboardUrl: PropTypes.func.isRequired, 88 createDashboardUrl: PropTypes.func.isRequired,
89 upgradeAccount: PropTypes.func.isRequired,
81 }).isRequired, 90 }).isRequired,
82 app: PropTypes.shape({ 91 app: PropTypes.shape({
83 openExternalUrl: PropTypes.func.isRequired, 92 openExternalUrl: PropTypes.func.isRequired,
diff --git a/src/containers/subscription/SubscriptionFormScreen.js b/src/containers/subscription/SubscriptionFormScreen.js
index 726b10628..38e46a7ba 100644
--- a/src/containers/subscription/SubscriptionFormScreen.js
+++ b/src/containers/subscription/SubscriptionFormScreen.js
@@ -1,4 +1,5 @@
1import React, { Component } from 'react'; 1import React, { Component } from 'react';
2import { remote } from 'electron';
2import PropTypes from 'prop-types'; 3import PropTypes from 'prop-types';
3import { inject, observer } from 'mobx-react'; 4import { inject, observer } from 'mobx-react';
4 5
@@ -7,11 +8,21 @@ import PaymentStore from '../../stores/PaymentStore';
7import SubscriptionForm from '../../components/subscription/SubscriptionForm'; 8import SubscriptionForm from '../../components/subscription/SubscriptionForm';
8import TrialForm from '../../components/subscription/TrialForm'; 9import TrialForm from '../../components/subscription/TrialForm';
9 10
11const { BrowserWindow } = remote;
12
10export default @inject('stores', 'actions') @observer class SubscriptionFormScreen extends Component { 13export default @inject('stores', 'actions') @observer class SubscriptionFormScreen extends Component {
14 static propTypes = {
15 onCloseWindow: PropTypes.func,
16 }
17
18 static defaultProps = {
19 onCloseWindow: () => null,
20 }
21
11 async openBrowser() { 22 async openBrowser() {
12 const { 23 const {
13 actions,
14 stores, 24 stores,
25 onCloseWindow,
15 } = this.props; 26 } = this.props;
16 27
17 const { 28 const {
@@ -22,7 +33,24 @@ export default @inject('stores', 'actions') @observer class SubscriptionFormScre
22 let hostedPageURL = features.features.planSelectionURL; 33 let hostedPageURL = features.features.planSelectionURL;
23 hostedPageURL = user.getAuthURL(hostedPageURL); 34 hostedPageURL = user.getAuthURL(hostedPageURL);
24 35
25 actions.app.openExternalUrl({ url: hostedPageURL }); 36 const paymentWindow = new BrowserWindow({
37 parent: remote.getCurrentWindow(),
38 modal: true,
39 title: '🔒 Franz Supporter License',
40 width: 800,
41 height: window.innerHeight - 100,
42 maxWidth: 800,
43 minWidth: 600,
44 webPreferences: {
45 nodeIntegration: true,
46 webviewTag: true,
47 },
48 });
49 paymentWindow.loadURL(`file://${__dirname}/../../index.html#/payment/${encodeURIComponent(hostedPageURL)}`);
50
51 paymentWindow.on('closed', () => {
52 onCloseWindow();
53 });
26 } 54 }
27 55
28 render() { 56 render() {