diff options
Diffstat (limited to 'src/containers')
-rw-r--r-- | src/containers/auth/AuthLayoutContainer.js | 10 | ||||
-rw-r--r-- | src/containers/auth/PricingScreen.js | 40 | ||||
-rw-r--r-- | src/containers/layout/AppLayoutContainer.js | 7 | ||||
-rw-r--r-- | src/containers/settings/AccountScreen.js | 3 | ||||
-rw-r--r-- | src/containers/settings/EditServiceScreen.js | 4 | ||||
-rw-r--r-- | src/containers/settings/EditSettingsScreen.js | 6 | ||||
-rw-r--r-- | src/containers/settings/RecipesScreen.js | 40 | ||||
-rw-r--r-- | src/containers/settings/SettingsWindow.js | 35 | ||||
-rw-r--r-- | src/containers/settings/TeamScreen.js | 1 | ||||
-rw-r--r-- | src/containers/subscription/SubscriptionFormScreen.js | 99 | ||||
-rw-r--r-- | src/containers/subscription/SubscriptionPopupScreen.js | 3 |
11 files changed, 134 insertions, 114 deletions
diff --git a/src/containers/auth/AuthLayoutContainer.js b/src/containers/auth/AuthLayoutContainer.js index 1f9c1ea61..427054d3d 100644 --- a/src/containers/auth/AuthLayoutContainer.js +++ b/src/containers/auth/AuthLayoutContainer.js | |||
@@ -2,7 +2,6 @@ import React, { Component } from 'react'; | |||
2 | import PropTypes from 'prop-types'; | 2 | import PropTypes from 'prop-types'; |
3 | import { inject, observer } from 'mobx-react'; | 3 | import { inject, observer } from 'mobx-react'; |
4 | import { ThemeProvider } from 'react-jss'; | 4 | import { ThemeProvider } from 'react-jss'; |
5 | import { theme } from '@meetfranz/theme'; | ||
6 | 5 | ||
7 | import AuthLayout from '../../components/auth/AuthLayout'; | 6 | import AuthLayout from '../../components/auth/AuthLayout'; |
8 | import AppStore from '../../stores/AppStore'; | 7 | import AppStore from '../../stores/AppStore'; |
@@ -24,24 +23,22 @@ export default @inject('stores', 'actions') @observer class AuthLayoutContainer | |||
24 | stores, actions, children, location, | 23 | stores, actions, children, location, |
25 | } = this.props; | 24 | } = this.props; |
26 | const { | 25 | const { |
27 | app, features, globalError, settings, | 26 | app, features, globalError, |
28 | } = stores; | 27 | } = stores; |
29 | 28 | ||
30 | const isLoadingBaseFeatures = features.defaultFeaturesRequest.isExecuting | 29 | const isLoadingBaseFeatures = features.defaultFeaturesRequest.isExecuting |
31 | && !features.defaultFeaturesRequest.wasExecuted; | 30 | && !features.defaultFeaturesRequest.wasExecuted; |
32 | 31 | ||
33 | const themeType = theme(settings.app.darkMode ? 'dark' : 'default'); | ||
34 | |||
35 | if (isLoadingBaseFeatures) { | 32 | if (isLoadingBaseFeatures) { |
36 | return ( | 33 | return ( |
37 | <ThemeProvider theme={theme(themeType)}> | 34 | <ThemeProvider theme={stores.ui.theme}> |
38 | <AppLoader /> | 35 | <AppLoader /> |
39 | </ThemeProvider> | 36 | </ThemeProvider> |
40 | ); | 37 | ); |
41 | } | 38 | } |
42 | 39 | ||
43 | return ( | 40 | return ( |
44 | <ThemeProvider theme={theme(themeType)}> | 41 | <ThemeProvider theme={stores.ui.theme}> |
45 | <AuthLayout | 42 | <AuthLayout |
46 | error={globalError.response} | 43 | error={globalError.response} |
47 | pathname={location.pathname} | 44 | pathname={location.pathname} |
@@ -50,7 +47,6 @@ export default @inject('stores', 'actions') @observer class AuthLayoutContainer | |||
50 | retryHealthCheck={actions.app.healthCheck} | 47 | retryHealthCheck={actions.app.healthCheck} |
51 | isHealthCheckLoading={app.healthCheckRequest.isExecuting} | 48 | isHealthCheckLoading={app.healthCheckRequest.isExecuting} |
52 | isFullScreen={app.isFullScreen} | 49 | isFullScreen={app.isFullScreen} |
53 | darkMode={app.isSystemDarkModeEnabled} | ||
54 | installAppUpdate={actions.app.installUpdate} | 50 | installAppUpdate={actions.app.installUpdate} |
55 | nextAppReleaseVersion={app.nextAppReleaseVersion} | 51 | nextAppReleaseVersion={app.nextAppReleaseVersion} |
56 | appUpdateIsDownloaded={app.updateStatus === app.updateStatusTypes.DOWNLOADED} | 52 | appUpdateIsDownloaded={app.updateStatus === app.updateStatusTypes.DOWNLOADED} |
diff --git a/src/containers/auth/PricingScreen.js b/src/containers/auth/PricingScreen.js index 8d179a170..af1651931 100644 --- a/src/containers/auth/PricingScreen.js +++ b/src/containers/auth/PricingScreen.js | |||
@@ -5,7 +5,6 @@ import { RouterStore } from 'mobx-react-router'; | |||
5 | 5 | ||
6 | import Pricing from '../../components/auth/Pricing'; | 6 | import Pricing from '../../components/auth/Pricing'; |
7 | import UserStore from '../../stores/UserStore'; | 7 | import UserStore from '../../stores/UserStore'; |
8 | import PaymentStore from '../../stores/PaymentStore'; | ||
9 | 8 | ||
10 | import { globalError as globalErrorPropType } from '../../prop-types'; | 9 | import { globalError as globalErrorPropType } from '../../prop-types'; |
11 | 10 | ||
@@ -14,20 +13,40 @@ export default @inject('stores', 'actions') @observer class PricingScreen extend | |||
14 | error: globalErrorPropType.isRequired, | 13 | error: globalErrorPropType.isRequired, |
15 | }; | 14 | }; |
16 | 15 | ||
16 | async submit() { | ||
17 | const { | ||
18 | actions, | ||
19 | stores, | ||
20 | } = this.props; | ||
21 | |||
22 | const { activateTrialRequest } = stores.user; | ||
23 | const { defaultTrialPlan } = stores.features.features; | ||
24 | |||
25 | actions.user.activateTrial({ planId: defaultTrialPlan }); | ||
26 | await activateTrialRequest._promise; | ||
27 | |||
28 | if (!activateTrialRequest.isError) { | ||
29 | stores.router.push('/'); | ||
30 | stores.user.hasCompletedSignup = true; | ||
31 | } | ||
32 | } | ||
33 | |||
17 | render() { | 34 | render() { |
18 | const { actions, stores, error } = this.props; | 35 | const { |
36 | error, | ||
37 | stores, | ||
38 | } = this.props; | ||
19 | 39 | ||
20 | const nextStepRoute = stores.user.legacyServices.length ? stores.user.importRoute : stores.user.inviteRoute; | 40 | const { getUserInfoRequest, activateTrialRequest } = stores.user; |
41 | const { featuresRequest } = stores.features; | ||
21 | 42 | ||
22 | return ( | 43 | return ( |
23 | <Pricing | 44 | <Pricing |
24 | donor={stores.user.data.donor || {}} | 45 | onSubmit={this.submit.bind(this)} |
25 | onSubmit={actions.user.signup} | 46 | isLoadingRequiredData={(getUserInfoRequest.isExecuting || !getUserInfoRequest.wasExecuted) || (featuresRequest.isExecuting || !featuresRequest.wasExecuted)} |
26 | onCloseSubscriptionWindow={() => this.props.stores.router.push(nextStepRoute)} | 47 | isActivatingTrial={activateTrialRequest.isExecuting} |
27 | isLoading={stores.payment.plansRequest.isExecuting} | 48 | trialActivationError={activateTrialRequest.isError} |
28 | isLoadingUser={stores.user.getUserInfoRequest.isExecuting} | ||
29 | error={error} | 49 | error={error} |
30 | skipAction={() => this.props.stores.router.push(nextStepRoute)} | ||
31 | /> | 50 | /> |
32 | ); | 51 | ); |
33 | } | 52 | } |
@@ -36,12 +55,11 @@ export default @inject('stores', 'actions') @observer class PricingScreen extend | |||
36 | PricingScreen.wrappedComponent.propTypes = { | 55 | PricingScreen.wrappedComponent.propTypes = { |
37 | actions: PropTypes.shape({ | 56 | actions: PropTypes.shape({ |
38 | user: PropTypes.shape({ | 57 | user: PropTypes.shape({ |
39 | signup: PropTypes.func.isRequired, | 58 | activateTrial: PropTypes.func.isRequired, |
40 | }).isRequired, | 59 | }).isRequired, |
41 | }).isRequired, | 60 | }).isRequired, |
42 | stores: PropTypes.shape({ | 61 | stores: PropTypes.shape({ |
43 | user: PropTypes.instanceOf(UserStore).isRequired, | 62 | user: PropTypes.instanceOf(UserStore).isRequired, |
44 | payment: PropTypes.instanceOf(PaymentStore).isRequired, | ||
45 | router: PropTypes.instanceOf(RouterStore).isRequired, | 63 | router: PropTypes.instanceOf(RouterStore).isRequired, |
46 | }).isRequired, | 64 | }).isRequired, |
47 | }; | 65 | }; |
diff --git a/src/containers/layout/AppLayoutContainer.js b/src/containers/layout/AppLayoutContainer.js index d290a6094..a14a98554 100644 --- a/src/containers/layout/AppLayoutContainer.js +++ b/src/containers/layout/AppLayoutContainer.js | |||
@@ -10,6 +10,7 @@ import FeaturesStore from '../../stores/FeaturesStore'; | |||
10 | import UIStore from '../../stores/UIStore'; | 10 | import UIStore from '../../stores/UIStore'; |
11 | import NewsStore from '../../stores/NewsStore'; | 11 | import NewsStore from '../../stores/NewsStore'; |
12 | import SettingsStore from '../../stores/SettingsStore'; | 12 | import SettingsStore from '../../stores/SettingsStore'; |
13 | import UserStore from '../../stores/UserStore'; | ||
13 | import RequestStore from '../../stores/RequestStore'; | 14 | import RequestStore from '../../stores/RequestStore'; |
14 | import GlobalErrorStore from '../../stores/GlobalErrorStore'; | 15 | import GlobalErrorStore from '../../stores/GlobalErrorStore'; |
15 | 16 | ||
@@ -39,6 +40,7 @@ export default @inject('stores', 'actions') @observer class AppLayoutContainer e | |||
39 | settings, | 40 | settings, |
40 | globalError, | 41 | globalError, |
41 | requests, | 42 | requests, |
43 | user, | ||
42 | } = this.props.stores; | 44 | } = this.props.stores; |
43 | 45 | ||
44 | const { | 46 | const { |
@@ -125,6 +127,8 @@ export default @inject('stores', 'actions') @observer class AppLayoutContainer e | |||
125 | reload={reload} | 127 | reload={reload} |
126 | openSettings={openSettings} | 128 | openSettings={openSettings} |
127 | update={updateService} | 129 | update={updateService} |
130 | userHasCompletedSignup={user.hasCompletedSignup} | ||
131 | hasActivatedTrial={user.hasActivatedTrial} | ||
128 | /> | 132 | /> |
129 | ); | 133 | ); |
130 | 134 | ||
@@ -148,8 +152,8 @@ export default @inject('stores', 'actions') @observer class AppLayoutContainer e | |||
148 | areRequiredRequestsSuccessful={requests.areRequiredRequestsSuccessful} | 152 | areRequiredRequestsSuccessful={requests.areRequiredRequestsSuccessful} |
149 | retryRequiredRequests={retryRequiredRequests} | 153 | retryRequiredRequests={retryRequiredRequests} |
150 | areRequiredRequestsLoading={requests.areRequiredRequestsLoading} | 154 | areRequiredRequestsLoading={requests.areRequiredRequestsLoading} |
151 | darkMode={settings.all.app.darkMode} | ||
152 | isDelayAppScreenVisible={delayAppState.isDelayAppScreenVisible} | 155 | isDelayAppScreenVisible={delayAppState.isDelayAppScreenVisible} |
156 | hasActivatedTrial={user.hasActivatedTrial} | ||
153 | > | 157 | > |
154 | {React.Children.count(children) > 0 ? children : null} | 158 | {React.Children.count(children) > 0 ? children : null} |
155 | </AppLayout> | 159 | </AppLayout> |
@@ -167,6 +171,7 @@ AppLayoutContainer.wrappedComponent.propTypes = { | |||
167 | ui: PropTypes.instanceOf(UIStore).isRequired, | 171 | ui: PropTypes.instanceOf(UIStore).isRequired, |
168 | news: PropTypes.instanceOf(NewsStore).isRequired, | 172 | news: PropTypes.instanceOf(NewsStore).isRequired, |
169 | settings: PropTypes.instanceOf(SettingsStore).isRequired, | 173 | settings: PropTypes.instanceOf(SettingsStore).isRequired, |
174 | user: PropTypes.instanceOf(UserStore).isRequired, | ||
170 | requests: PropTypes.instanceOf(RequestStore).isRequired, | 175 | requests: PropTypes.instanceOf(RequestStore).isRequired, |
171 | globalError: PropTypes.instanceOf(GlobalErrorStore).isRequired, | 176 | globalError: PropTypes.instanceOf(GlobalErrorStore).isRequired, |
172 | }).isRequired, | 177 | }).isRequired, |
diff --git a/src/containers/settings/AccountScreen.js b/src/containers/settings/AccountScreen.js index 66076504f..f9eae4957 100644 --- a/src/containers/settings/AccountScreen.js +++ b/src/containers/settings/AccountScreen.js | |||
@@ -26,7 +26,7 @@ export default @inject('stores', 'actions') @observer class AccountScreen extend | |||
26 | handleWebsiteLink(route) { | 26 | handleWebsiteLink(route) { |
27 | const { actions, stores } = this.props; | 27 | const { actions, stores } = this.props; |
28 | 28 | ||
29 | const url = `${WEBSITE}${route}?authToken=${stores.user.authToken}&utm_source=app&utm_medium=account_dashboard`; | 29 | const url = stores.user.getAuthURL(`${WEBSITE}${route}?utm_source=app&utm_medium=account_dashboard`); |
30 | 30 | ||
31 | actions.app.openExternalUrl({ url }); | 31 | actions.app.openExternalUrl({ url }); |
32 | } | 32 | } |
@@ -51,6 +51,7 @@ export default @inject('stores', 'actions') @observer class AccountScreen extend | |||
51 | isLoadingDeleteAccount={user.deleteAccountRequest.isExecuting} | 51 | isLoadingDeleteAccount={user.deleteAccountRequest.isExecuting} |
52 | isDeleteAccountSuccessful={user.deleteAccountRequest.wasExecuted && !user.deleteAccountRequest.isError} | 52 | isDeleteAccountSuccessful={user.deleteAccountRequest.wasExecuted && !user.deleteAccountRequest.isError} |
53 | openEditAccount={() => this.handleWebsiteLink('/user/profile')} | 53 | openEditAccount={() => this.handleWebsiteLink('/user/profile')} |
54 | upgradeToPro={() => this.handleWebsiteLink('/inapp/user/licenses')} | ||
54 | openBilling={() => this.handleWebsiteLink('/user/billing')} | 55 | openBilling={() => this.handleWebsiteLink('/user/billing')} |
55 | openInvoices={() => this.handleWebsiteLink('/user/invoices')} | 56 | openInvoices={() => this.handleWebsiteLink('/user/invoices')} |
56 | /> | 57 | /> |
diff --git a/src/containers/settings/EditServiceScreen.js b/src/containers/settings/EditServiceScreen.js index 870ca4ecd..e4ff03bb3 100644 --- a/src/containers/settings/EditServiceScreen.js +++ b/src/containers/settings/EditServiceScreen.js | |||
@@ -330,8 +330,8 @@ export default @inject('stores', 'actions') @observer class EditServiceScreen ex | |||
330 | onSubmit={d => this.onSubmit(d)} | 330 | onSubmit={d => this.onSubmit(d)} |
331 | onDelete={() => this.deleteService()} | 331 | onDelete={() => this.deleteService()} |
332 | isProxyFeatureEnabled={proxyFeature.isEnabled} | 332 | isProxyFeatureEnabled={proxyFeature.isEnabled} |
333 | isProxyPremiumFeature={proxyFeature.isPremium} | 333 | isServiceProxyIncludedInCurrentPlan={proxyFeature.isIncludedInCurrentPlan} |
334 | isSpellcheckerPremiumFeature={spellcheckerFeature.isPremium} | 334 | isSpellcheckerIncludedInCurrentPlan={spellcheckerFeature.isIncludedInCurrentPlan} |
335 | /> | 335 | /> |
336 | </ErrorBoundary> | 336 | </ErrorBoundary> |
337 | ); | 337 | ); |
diff --git a/src/containers/settings/EditSettingsScreen.js b/src/containers/settings/EditSettingsScreen.js index 97c1fa3b1..67d52f102 100644 --- a/src/containers/settings/EditSettingsScreen.js +++ b/src/containers/settings/EditSettingsScreen.js | |||
@@ -159,8 +159,8 @@ export default @inject('stores', 'actions') @observer class EditSettingsScreen e | |||
159 | }, | 159 | }, |
160 | enableSpellchecking: { | 160 | enableSpellchecking: { |
161 | label: intl.formatMessage(messages.enableSpellchecking), | 161 | label: intl.formatMessage(messages.enableSpellchecking), |
162 | value: !this.props.stores.user.data.isPremium && spellcheckerConfig.isPremium ? false : settings.all.app.enableSpellchecking, | 162 | value: !this.props.stores.user.data.isPremium && !spellcheckerConfig.isIncludedInCurrentPlan ? false : settings.all.app.enableSpellchecking, |
163 | default: !this.props.stores.user.data.isPremium && spellcheckerConfig.isPremium ? false : DEFAULT_APP_SETTINGS.enableSpellchecking, | 163 | default: !this.props.stores.user.data.isPremium && !spellcheckerConfig.isIncludedInCurrentPlan ? false : DEFAULT_APP_SETTINGS.enableSpellchecking, |
164 | }, | 164 | }, |
165 | spellcheckerLanguage: { | 165 | spellcheckerLanguage: { |
166 | label: intl.formatMessage(globalMessages.spellcheckerLanguage), | 166 | label: intl.formatMessage(globalMessages.spellcheckerLanguage), |
@@ -223,7 +223,7 @@ export default @inject('stores', 'actions') @observer class EditSettingsScreen e | |||
223 | cacheSize={cacheSize} | 223 | cacheSize={cacheSize} |
224 | isClearingAllCache={isClearingAllCache} | 224 | isClearingAllCache={isClearingAllCache} |
225 | onClearAllCache={clearAllCache} | 225 | onClearAllCache={clearAllCache} |
226 | isSpellcheckerPremiumFeature={spellcheckerConfig.isPremium} | 226 | isSpellcheckerIncludedInCurrentPlan={spellcheckerConfig.isIncludedInCurrentPlan} |
227 | /> | 227 | /> |
228 | </ErrorBoundary> | 228 | </ErrorBoundary> |
229 | ); | 229 | ); |
diff --git a/src/containers/settings/RecipesScreen.js b/src/containers/settings/RecipesScreen.js index eda5ae54c..132820b6f 100644 --- a/src/containers/settings/RecipesScreen.js +++ b/src/containers/settings/RecipesScreen.js | |||
@@ -1,7 +1,9 @@ | |||
1 | import { remote, shell } from 'electron'; | ||
1 | import React, { Component } from 'react'; | 2 | import React, { Component } from 'react'; |
2 | import PropTypes from 'prop-types'; | 3 | import PropTypes from 'prop-types'; |
3 | import { autorun } from 'mobx'; | 4 | import { autorun } from 'mobx'; |
4 | import { inject, observer } from 'mobx-react'; | 5 | import { inject, observer } from 'mobx-react'; |
6 | import path from 'path'; | ||
5 | 7 | ||
6 | import RecipePreviewsStore from '../../stores/RecipePreviewsStore'; | 8 | import RecipePreviewsStore from '../../stores/RecipePreviewsStore'; |
7 | import RecipeStore from '../../stores/RecipesStore'; | 9 | import RecipeStore from '../../stores/RecipesStore'; |
@@ -10,6 +12,11 @@ import UserStore from '../../stores/UserStore'; | |||
10 | 12 | ||
11 | import RecipesDashboard from '../../components/settings/recipes/RecipesDashboard'; | 13 | import RecipesDashboard from '../../components/settings/recipes/RecipesDashboard'; |
12 | import ErrorBoundary from '../../components/util/ErrorBoundary'; | 14 | import ErrorBoundary from '../../components/util/ErrorBoundary'; |
15 | import { FRANZ_DEV_DOCS } from '../../config'; | ||
16 | import { gaEvent } from '../../lib/analytics'; | ||
17 | import { communityRecipesStore } from '../../features/communityRecipes'; | ||
18 | |||
19 | const { app } = remote; | ||
13 | 20 | ||
14 | export default @inject('stores', 'actions') @observer class RecipesScreen extends Component { | 21 | export default @inject('stores', 'actions') @observer class RecipesScreen extends Component { |
15 | static propTypes = { | 22 | static propTypes = { |
@@ -67,9 +74,16 @@ export default @inject('stores', 'actions') @observer class RecipesScreen extend | |||
67 | 74 | ||
68 | render() { | 75 | render() { |
69 | const { | 76 | const { |
70 | recipePreviews, recipes, services, user, | 77 | recipePreviews, |
78 | recipes, | ||
79 | services, | ||
80 | user, | ||
71 | } = this.props.stores; | 81 | } = this.props.stores; |
72 | const { showAddServiceInterface } = this.props.actions.service; | 82 | |
83 | const { | ||
84 | app: appActions, | ||
85 | service: serviceActions, | ||
86 | } = this.props.actions; | ||
73 | 87 | ||
74 | const { filter } = this.props.params; | 88 | const { filter } = this.props.params; |
75 | let recipeFilter; | 89 | let recipeFilter; |
@@ -77,7 +91,7 @@ export default @inject('stores', 'actions') @observer class RecipesScreen extend | |||
77 | if (filter === 'all') { | 91 | if (filter === 'all') { |
78 | recipeFilter = recipePreviews.all; | 92 | recipeFilter = recipePreviews.all; |
79 | } else if (filter === 'dev') { | 93 | } else if (filter === 'dev') { |
80 | recipeFilter = recipePreviews.dev; | 94 | recipeFilter = communityRecipesStore.communityRecipes; |
81 | } else { | 95 | } else { |
82 | recipeFilter = recipePreviews.featured; | 96 | recipeFilter = recipePreviews.featured; |
83 | } | 97 | } |
@@ -89,6 +103,8 @@ export default @inject('stores', 'actions') @observer class RecipesScreen extend | |||
89 | || recipes.installRecipeRequest.isExecuting | 103 | || recipes.installRecipeRequest.isExecuting |
90 | || recipePreviews.searchRecipePreviewsRequest.isExecuting; | 104 | || recipePreviews.searchRecipePreviewsRequest.isExecuting; |
91 | 105 | ||
106 | const recipeDirectory = path.join(app.getPath('userData'), 'recipes', 'dev'); | ||
107 | |||
92 | return ( | 108 | return ( |
93 | <ErrorBoundary> | 109 | <ErrorBoundary> |
94 | <RecipesDashboard | 110 | <RecipesDashboard |
@@ -97,12 +113,23 @@ export default @inject('stores', 'actions') @observer class RecipesScreen extend | |||
97 | addedServiceCount={services.all.length} | 113 | addedServiceCount={services.all.length} |
98 | isPremium={user.data.isPremium} | 114 | isPremium={user.data.isPremium} |
99 | hasLoadedRecipes={recipePreviews.featuredRecipePreviewsRequest.wasExecuted} | 115 | hasLoadedRecipes={recipePreviews.featuredRecipePreviewsRequest.wasExecuted} |
100 | showAddServiceInterface={showAddServiceInterface} | 116 | showAddServiceInterface={serviceActions.showAddServiceInterface} |
101 | searchRecipes={e => this.searchRecipes(e)} | 117 | searchRecipes={e => this.searchRecipes(e)} |
102 | resetSearch={() => this.resetSearch()} | 118 | resetSearch={() => this.resetSearch()} |
103 | searchNeedle={this.state.needle} | 119 | searchNeedle={this.state.needle} |
104 | serviceStatus={services.actionStatus} | 120 | serviceStatus={services.actionStatus} |
105 | devRecipesCount={recipePreviews.dev.length} | 121 | recipeFilter={filter} |
122 | recipeDirectory={recipeDirectory} | ||
123 | openRecipeDirectory={() => { | ||
124 | shell.openItem(recipeDirectory); | ||
125 | gaEvent('Recipe', 'open-recipe-folder', 'Open Folder'); | ||
126 | }} | ||
127 | openDevDocs={() => { | ||
128 | appActions.openExternalUrl({ url: FRANZ_DEV_DOCS }); | ||
129 | gaEvent('Recipe', 'open-dev-docs', 'Developer Documentation'); | ||
130 | }} | ||
131 | isCommunityRecipesIncludedInCurrentPlan={communityRecipesStore.isCommunityRecipesIncludedInCurrentPlan} | ||
132 | isUserPremiumUser={user.isPremium} | ||
106 | /> | 133 | /> |
107 | </ErrorBoundary> | 134 | </ErrorBoundary> |
108 | ); | 135 | ); |
@@ -117,6 +144,9 @@ RecipesScreen.wrappedComponent.propTypes = { | |||
117 | user: PropTypes.instanceOf(UserStore).isRequired, | 144 | user: PropTypes.instanceOf(UserStore).isRequired, |
118 | }).isRequired, | 145 | }).isRequired, |
119 | actions: PropTypes.shape({ | 146 | actions: PropTypes.shape({ |
147 | app: PropTypes.shape({ | ||
148 | openExternalUrl: PropTypes.func.isRequired, | ||
149 | }).isRequired, | ||
120 | service: PropTypes.shape({ | 150 | service: PropTypes.shape({ |
121 | showAddServiceInterface: PropTypes.func.isRequired, | 151 | showAddServiceInterface: PropTypes.func.isRequired, |
122 | }).isRequired, | 152 | }).isRequired, |
diff --git a/src/containers/settings/SettingsWindow.js b/src/containers/settings/SettingsWindow.js index 663b9e2e4..440d32a46 100644 --- a/src/containers/settings/SettingsWindow.js +++ b/src/containers/settings/SettingsWindow.js | |||
@@ -1,4 +1,5 @@ | |||
1 | import React, { Component } from 'react'; | 1 | import React, { Component } from 'react'; |
2 | import ReactDOM from 'react-dom'; | ||
2 | import PropTypes from 'prop-types'; | 3 | import PropTypes from 'prop-types'; |
3 | import { observer, inject } from 'mobx-react'; | 4 | import { observer, inject } from 'mobx-react'; |
4 | 5 | ||
@@ -10,10 +11,23 @@ import ErrorBoundary from '../../components/util/ErrorBoundary'; | |||
10 | import { workspaceStore } from '../../features/workspaces'; | 11 | import { workspaceStore } from '../../features/workspaces'; |
11 | 12 | ||
12 | export default @inject('stores', 'actions') @observer class SettingsContainer extends Component { | 13 | export default @inject('stores', 'actions') @observer class SettingsContainer extends Component { |
14 | portalRoot = document.querySelector('#portalContainer'); | ||
15 | |||
16 | el = document.createElement('div'); | ||
17 | |||
18 | componentDidMount() { | ||
19 | this.portalRoot.appendChild(this.el); | ||
20 | } | ||
21 | |||
22 | componentWillUnmount() { | ||
23 | this.portalRoot.removeChild(this.el); | ||
24 | } | ||
25 | |||
13 | render() { | 26 | render() { |
14 | const { children, stores } = this.props; | 27 | const { children, stores } = this.props; |
15 | const { closeSettings } = this.props.actions.ui; | 28 | const { closeSettings } = this.props.actions.ui; |
16 | 29 | ||
30 | |||
17 | const navigation = ( | 31 | const navigation = ( |
18 | <Navigation | 32 | <Navigation |
19 | serviceCount={stores.services.all.length} | 33 | serviceCount={stores.services.all.length} |
@@ -21,15 +35,18 @@ export default @inject('stores', 'actions') @observer class SettingsContainer ex | |||
21 | /> | 35 | /> |
22 | ); | 36 | ); |
23 | 37 | ||
24 | return ( | 38 | return ReactDOM.createPortal( |
25 | <ErrorBoundary> | 39 | ( |
26 | <Layout | 40 | <ErrorBoundary> |
27 | navigation={navigation} | 41 | <Layout |
28 | closeSettings={closeSettings} | 42 | navigation={navigation} |
29 | > | 43 | closeSettings={closeSettings} |
30 | {children} | 44 | > |
31 | </Layout> | 45 | {children} |
32 | </ErrorBoundary> | 46 | </Layout> |
47 | </ErrorBoundary> | ||
48 | ), | ||
49 | this.el, | ||
33 | ); | 50 | ); |
34 | } | 51 | } |
35 | } | 52 | } |
diff --git a/src/containers/settings/TeamScreen.js b/src/containers/settings/TeamScreen.js index c69d5ad08..b7b1b78cb 100644 --- a/src/containers/settings/TeamScreen.js +++ b/src/containers/settings/TeamScreen.js | |||
@@ -14,7 +14,6 @@ export default @inject('stores', 'actions') @observer class TeamScreen extends C | |||
14 | const { actions, stores } = this.props; | 14 | const { actions, stores } = this.props; |
15 | 15 | ||
16 | const url = `${WEBSITE}${route}?authToken=${stores.user.authToken}&utm_source=app&utm_medium=account_dashboard`; | 16 | const url = `${WEBSITE}${route}?authToken=${stores.user.authToken}&utm_source=app&utm_medium=account_dashboard`; |
17 | console.log(url); | ||
18 | 17 | ||
19 | actions.app.openExternalUrl({ url }); | 18 | actions.app.openExternalUrl({ url }); |
20 | } | 19 | } |
diff --git a/src/containers/subscription/SubscriptionFormScreen.js b/src/containers/subscription/SubscriptionFormScreen.js index aa1166f5e..e9e457084 100644 --- a/src/containers/subscription/SubscriptionFormScreen.js +++ b/src/containers/subscription/SubscriptionFormScreen.js | |||
@@ -1,4 +1,3 @@ | |||
1 | import { remote } from 'electron'; | ||
2 | import React, { Component } from 'react'; | 1 | import React, { Component } from 'react'; |
3 | import PropTypes from 'prop-types'; | 2 | import PropTypes from 'prop-types'; |
4 | import { inject, observer } from 'mobx-react'; | 3 | import { inject, observer } from 'mobx-react'; |
@@ -6,96 +5,50 @@ import { inject, observer } from 'mobx-react'; | |||
6 | import PaymentStore from '../../stores/PaymentStore'; | 5 | import PaymentStore from '../../stores/PaymentStore'; |
7 | 6 | ||
8 | import SubscriptionForm from '../../components/subscription/SubscriptionForm'; | 7 | import SubscriptionForm from '../../components/subscription/SubscriptionForm'; |
9 | 8 | import TrialForm from '../../components/subscription/TrialForm'; | |
10 | const { BrowserWindow } = remote; | ||
11 | 9 | ||
12 | export default @inject('stores', 'actions') @observer class SubscriptionFormScreen extends Component { | 10 | export default @inject('stores', 'actions') @observer class SubscriptionFormScreen extends Component { |
13 | static propTypes = { | 11 | async openBrowser() { |
14 | onCloseWindow: PropTypes.func, | ||
15 | content: PropTypes.node, | ||
16 | showSkipOption: PropTypes.bool, | ||
17 | skipAction: PropTypes.func, | ||
18 | skipButtonLabel: PropTypes.string, | ||
19 | hideInfo: PropTypes.bool, | ||
20 | } | ||
21 | |||
22 | static defaultProps = { | ||
23 | onCloseWindow: () => null, | ||
24 | content: '', | ||
25 | showSkipOption: false, | ||
26 | skipAction: () => null, | ||
27 | skipButtonLabel: '', | ||
28 | hideInfo: false, | ||
29 | } | ||
30 | |||
31 | async handlePayment(plan) { | ||
32 | const { | 12 | const { |
33 | actions, | 13 | actions, |
34 | stores, | 14 | stores, |
35 | onCloseWindow, | ||
36 | } = this.props; | 15 | } = this.props; |
37 | 16 | ||
38 | const interval = plan; | 17 | const { |
39 | 18 | user, | |
40 | const { id } = stores.payment.plan[interval]; | 19 | features, |
41 | actions.payment.createHostedPage({ | 20 | } = stores; |
42 | planId: id, | ||
43 | }); | ||
44 | |||
45 | const hostedPage = await stores.payment.createHostedPageRequest; | ||
46 | 21 | ||
47 | if (hostedPage.url) { | 22 | let hostedPageURL = !user.data.hadSubscription ? features.features.planSelectionURL : features.features.subscribeURL; |
48 | if (hostedPage.legacyCheckoutFlow) { | 23 | hostedPageURL = user.getAuthURL(hostedPageURL); |
49 | const paymentWindow = new BrowserWindow({ | ||
50 | parent: remote.getCurrentWindow(), | ||
51 | modal: true, | ||
52 | title: '🔒 Franz Supporter License', | ||
53 | width: 600, | ||
54 | height: window.innerHeight - 100, | ||
55 | maxWidth: 600, | ||
56 | minWidth: 600, | ||
57 | webPreferences: { | ||
58 | nodeIntegration: true, | ||
59 | webviewTag: true, | ||
60 | }, | ||
61 | }); | ||
62 | paymentWindow.loadURL(`file://${__dirname}/../../index.html#/payment/${encodeURIComponent(hostedPage.url)}`); | ||
63 | 24 | ||
64 | paymentWindow.on('closed', () => { | 25 | actions.app.openExternalUrl({ url: hostedPageURL }); |
65 | onCloseWindow(); | ||
66 | }); | ||
67 | } else { | ||
68 | actions.app.openExternalUrl({ | ||
69 | url: hostedPage.url, | ||
70 | }); | ||
71 | } | ||
72 | } | ||
73 | } | 26 | } |
74 | 27 | ||
75 | render() { | 28 | render() { |
76 | const { | 29 | const { |
77 | content, | ||
78 | actions, | 30 | actions, |
79 | stores, | 31 | stores, |
80 | showSkipOption, | ||
81 | skipAction, | ||
82 | skipButtonLabel, | ||
83 | hideInfo, | ||
84 | } = this.props; | 32 | } = this.props; |
33 | |||
34 | const { data: user } = stores.user; | ||
35 | |||
36 | if (user.hadSubscription) { | ||
37 | return ( | ||
38 | <SubscriptionForm | ||
39 | plan={stores.payment.plan} | ||
40 | selectPlan={() => this.openBrowser()} | ||
41 | isActivatingTrial={stores.user.activateTrialRequest.isExecuting || stores.user.getUserInfoRequest.isExecuting} | ||
42 | /> | ||
43 | ); | ||
44 | } | ||
45 | |||
85 | return ( | 46 | return ( |
86 | <SubscriptionForm | 47 | <TrialForm |
87 | plan={stores.payment.plan} | 48 | plan={stores.payment.plan} |
88 | isLoading={stores.payment.plansRequest.isExecuting} | 49 | activateTrial={() => actions.user.activateTrial({ planId: stores.features.features.defaultTrialPlan })} |
89 | retryPlanRequest={() => stores.payment.plansRequest.reload()} | 50 | showAllOptions={() => this.openBrowser()} |
90 | isCreatingHostedPage={stores.payment.createHostedPageRequest.isExecuting} | 51 | isActivatingTrial={stores.user.activateTrialRequest.isExecuting || stores.user.getUserInfoRequest.isExecuting} |
91 | handlePayment={price => this.handlePayment(price)} | ||
92 | content={content} | ||
93 | error={stores.payment.plansRequest.isError} | ||
94 | showSkipOption={showSkipOption} | ||
95 | skipAction={skipAction} | ||
96 | skipButtonLabel={skipButtonLabel} | ||
97 | hideInfo={hideInfo} | ||
98 | openExternalUrl={actions.app.openExternalUrl} | ||
99 | /> | 52 | /> |
100 | ); | 53 | ); |
101 | } | 54 | } |
diff --git a/src/containers/subscription/SubscriptionPopupScreen.js b/src/containers/subscription/SubscriptionPopupScreen.js index f76d6c5a6..0de5a87c4 100644 --- a/src/containers/subscription/SubscriptionPopupScreen.js +++ b/src/containers/subscription/SubscriptionPopupScreen.js | |||
@@ -3,6 +3,7 @@ import PropTypes from 'prop-types'; | |||
3 | import { inject, observer } from 'mobx-react'; | 3 | import { inject, observer } from 'mobx-react'; |
4 | 4 | ||
5 | import SubscriptionPopup from '../../components/subscription/SubscriptionPopup'; | 5 | import SubscriptionPopup from '../../components/subscription/SubscriptionPopup'; |
6 | import { isDevMode } from '../../environment'; | ||
6 | 7 | ||
7 | 8 | ||
8 | export default @inject('stores', 'actions') @observer class SubscriptionPopupScreen extends Component { | 9 | export default @inject('stores', 'actions') @observer class SubscriptionPopupScreen extends Component { |
@@ -13,7 +14,7 @@ export default @inject('stores', 'actions') @observer class SubscriptionPopupScr | |||
13 | completeCheck(event) { | 14 | completeCheck(event) { |
14 | const { url } = event; | 15 | const { url } = event; |
15 | 16 | ||
16 | if ((url.includes('recurly') && url.includes('confirmation')) || (url.includes('meetfranz') && url.includes('success'))) { | 17 | if ((url.includes('recurly') && url.includes('confirmation')) || ((url.includes('meetfranz') || isDevMode) && url.includes('success'))) { |
17 | this.setState({ | 18 | this.setState({ |
18 | complete: true, | 19 | complete: true, |
19 | }); | 20 | }); |