diff options
Diffstat (limited to 'src')
23 files changed, 411 insertions, 106 deletions
diff --git a/src/assets/images/workspaces/teaser_dark.png b/src/assets/images/workspaces/teaser_dark.png new file mode 100644 index 000000000..5b6d7334b --- /dev/null +++ b/src/assets/images/workspaces/teaser_dark.png | |||
Binary files differ | |||
diff --git a/src/assets/images/workspaces/teaser_light.png b/src/assets/images/workspaces/teaser_light.png new file mode 100644 index 000000000..635af43fa --- /dev/null +++ b/src/assets/images/workspaces/teaser_light.png | |||
Binary files differ | |||
diff --git a/src/components/settings/account/AccountDashboard.js b/src/components/settings/account/AccountDashboard.js index 900a83a78..4fd1e8163 100644 --- a/src/components/settings/account/AccountDashboard.js +++ b/src/components/settings/account/AccountDashboard.js | |||
@@ -93,9 +93,11 @@ const messages = defineMessages({ | |||
93 | }, | 93 | }, |
94 | }); | 94 | }); |
95 | 95 | ||
96 | export default @observer class AccountDashboard extends Component { | 96 | @observer |
97 | class AccountDashboard extends Component { | ||
97 | static propTypes = { | 98 | static propTypes = { |
98 | user: MobxPropTypes.observableObject.isRequired, | 99 | user: MobxPropTypes.observableObject.isRequired, |
100 | isProUser: PropTypes.bool.isRequired, | ||
99 | isLoading: PropTypes.bool.isRequired, | 101 | isLoading: PropTypes.bool.isRequired, |
100 | userInfoRequestFailed: PropTypes.bool.isRequired, | 102 | userInfoRequestFailed: PropTypes.bool.isRequired, |
101 | retryUserInfoRequest: PropTypes.func.isRequired, | 103 | retryUserInfoRequest: PropTypes.func.isRequired, |
@@ -115,6 +117,7 @@ export default @observer class AccountDashboard extends Component { | |||
115 | render() { | 117 | render() { |
116 | const { | 118 | const { |
117 | user, | 119 | user, |
120 | isProUser, | ||
118 | isLoading, | 121 | isLoading, |
119 | userInfoRequestFailed, | 122 | userInfoRequestFailed, |
120 | retryUserInfoRequest, | 123 | retryUserInfoRequest, |
@@ -234,11 +237,13 @@ export default @observer class AccountDashboard extends Component { | |||
234 | </> | 237 | </> |
235 | )} | 238 | )} |
236 | <div className="manage-user-links"> | 239 | <div className="manage-user-links"> |
237 | <Button | 240 | {!isProUser && ( |
238 | label={intl.formatMessage(messages.upgradeAccountToPro)} | 241 | <Button |
239 | className="franz-form__button--primary" | 242 | label={intl.formatMessage(messages.upgradeAccountToPro)} |
240 | onClick={upgradeToPro} | 243 | className="franz-form__button--primary" |
241 | /> | 244 | onClick={upgradeToPro} |
245 | /> | ||
246 | )} | ||
242 | <Button | 247 | <Button |
243 | label={intl.formatMessage(messages.manageSubscriptionButtonLabel)} | 248 | label={intl.formatMessage(messages.manageSubscriptionButtonLabel)} |
244 | className="franz-form__button--inverted" | 249 | className="franz-form__button--inverted" |
@@ -290,3 +295,5 @@ export default @observer class AccountDashboard extends Component { | |||
290 | ); | 295 | ); |
291 | } | 296 | } |
292 | } | 297 | } |
298 | |||
299 | export default AccountDashboard; | ||
diff --git a/src/components/settings/recipes/RecipesDashboard.js b/src/components/settings/recipes/RecipesDashboard.js index 75e60b7ec..08988024a 100644 --- a/src/components/settings/recipes/RecipesDashboard.js +++ b/src/components/settings/recipes/RecipesDashboard.js | |||
@@ -218,7 +218,7 @@ export default @injectSheet(styles) @observer class RecipesDashboard extends Com | |||
218 | <> | 218 | <> |
219 | <H2> | 219 | <H2> |
220 | {intl.formatMessage(messages.headlineCustomRecipes)} | 220 | {intl.formatMessage(messages.headlineCustomRecipes)} |
221 | {isCommunityRecipesIncludedInCurrentPlan && ( | 221 | {!isCommunityRecipesIncludedInCurrentPlan && ( |
222 | <ProBadge className={classes.proBadge} /> | 222 | <ProBadge className={classes.proBadge} /> |
223 | )} | 223 | )} |
224 | </H2> | 224 | </H2> |
@@ -247,7 +247,7 @@ export default @injectSheet(styles) @observer class RecipesDashboard extends Com | |||
247 | </> | 247 | </> |
248 | )} | 248 | )} |
249 | <PremiumFeatureContainer | 249 | <PremiumFeatureContainer |
250 | condition={(recipeFilter === 'dev' && communityRecipes.length > 0) && isCommunityRecipesIncludedInCurrentPlan} | 250 | condition={(recipeFilter === 'dev' && communityRecipes.length > 0) && !isCommunityRecipesIncludedInCurrentPlan} |
251 | > | 251 | > |
252 | {recipeFilter === 'dev' && communityRecipes.length > 0 && ( | 252 | {recipeFilter === 'dev' && communityRecipes.length > 0 && ( |
253 | <H3>{intl.formatMessage(messages.headlineCommunityRecipes)}</H3> | 253 | <H3>{intl.formatMessage(messages.headlineCommunityRecipes)}</H3> |
diff --git a/src/components/subscription/TrialForm.js b/src/components/subscription/TrialForm.js index 9fe1c93b7..9ed548f16 100644 --- a/src/components/subscription/TrialForm.js +++ b/src/components/subscription/TrialForm.js | |||
@@ -41,7 +41,7 @@ const messages = defineMessages({ | |||
41 | }, | 41 | }, |
42 | }); | 42 | }); |
43 | 43 | ||
44 | const styles = () => ({ | 44 | const styles = theme => ({ |
45 | activateTrialButton: { | 45 | activateTrialButton: { |
46 | margin: [40, 0, 10], | 46 | margin: [40, 0, 10], |
47 | }, | 47 | }, |
@@ -49,6 +49,7 @@ const styles = () => ({ | |||
49 | margin: [0, 0, 40], | 49 | margin: [0, 0, 40], |
50 | background: 'none', | 50 | background: 'none', |
51 | border: 'none', | 51 | border: 'none', |
52 | color: theme.colorText, | ||
52 | }, | 53 | }, |
53 | keyTerms: { | 54 | keyTerms: { |
54 | marginTop: 20, | 55 | marginTop: 20, |
diff --git a/src/components/ui/ActivateTrialButton/index.js b/src/components/ui/ActivateTrialButton/index.js new file mode 100644 index 000000000..c3e5f4a6f --- /dev/null +++ b/src/components/ui/ActivateTrialButton/index.js | |||
@@ -0,0 +1,115 @@ | |||
1 | import React, { Component } from 'react'; | ||
2 | import PropTypes from 'prop-types'; | ||
3 | import { inject, observer } from 'mobx-react'; | ||
4 | import { defineMessages, intlShape } from 'react-intl'; | ||
5 | import classnames from 'classnames'; | ||
6 | |||
7 | import { Button } from '@meetfranz/forms'; | ||
8 | import { gaEvent } from '../../../lib/analytics'; | ||
9 | |||
10 | import UserStore from '../../../stores/UserStore'; | ||
11 | |||
12 | const messages = defineMessages({ | ||
13 | action: { | ||
14 | id: 'feature.delayApp.upgrade.action', | ||
15 | defaultMessage: '!!!Get a Franz Supporter License', | ||
16 | }, | ||
17 | actionTrial: { | ||
18 | id: 'feature.delayApp.trial.action', | ||
19 | defaultMessage: '!!!Yes, I want the free 14 day trial of Franz Professional', | ||
20 | }, | ||
21 | shortAction: { | ||
22 | id: 'feature.delayApp.upgrade.actionShort', | ||
23 | defaultMessage: '!!!Upgrade account', | ||
24 | }, | ||
25 | shortActionTrial: { | ||
26 | id: 'feature.delayApp.trial.actionShort', | ||
27 | defaultMessage: '!!!Activate the free Franz Professional trial', | ||
28 | }, | ||
29 | }); | ||
30 | |||
31 | @inject('stores', 'actions') @observer | ||
32 | class ActivateTrialButton extends Component { | ||
33 | static propTypes = { | ||
34 | // eslint-disable-next-line | ||
35 | classes: PropTypes.object.isRequired, | ||
36 | className: PropTypes.string, | ||
37 | short: PropTypes.bool, | ||
38 | gaEventInfo: PropTypes.shape({ | ||
39 | category: PropTypes.string.isRequired, | ||
40 | event: PropTypes.string.isRequired, | ||
41 | label: PropTypes.string, | ||
42 | }), | ||
43 | }; | ||
44 | |||
45 | static defaultProps = { | ||
46 | className: '', | ||
47 | short: false, | ||
48 | gaEventInfo: null, | ||
49 | } | ||
50 | |||
51 | static contextTypes = { | ||
52 | intl: intlShape, | ||
53 | }; | ||
54 | |||
55 | handleCTAClick() { | ||
56 | const { actions, stores, gaEventInfo } = this.props; | ||
57 | const { hadSubscription } = stores.user.data; | ||
58 | const { defaultTrialPlan } = stores.features.features; | ||
59 | |||
60 | let label = ''; | ||
61 | if (!hadSubscription) { | ||
62 | actions.user.activateTrial({ planId: defaultTrialPlan }); | ||
63 | |||
64 | label = 'Start Trial'; | ||
65 | } else { | ||
66 | actions.ui.openSettings({ path: 'user' }); | ||
67 | |||
68 | label = 'Upgrade Account'; | ||
69 | } | ||
70 | |||
71 | if (gaEventInfo) { | ||
72 | const { category, event } = gaEventInfo; | ||
73 | gaEvent(category, event, label); | ||
74 | } | ||
75 | } | ||
76 | |||
77 | render() { | ||
78 | const { stores, className, short } = this.props; | ||
79 | const { intl } = this.context; | ||
80 | |||
81 | const { hadSubscription } = stores.user.data; | ||
82 | |||
83 | let label; | ||
84 | if (hadSubscription) { | ||
85 | label = short ? messages.shortAction : messages.action; | ||
86 | } else { | ||
87 | label = short ? messages.shortActionTrial : messages.actionTrial; | ||
88 | } | ||
89 | |||
90 | return ( | ||
91 | <Button | ||
92 | label={intl.formatMessage(label)} | ||
93 | className={classnames({ | ||
94 | [className]: className, | ||
95 | })} | ||
96 | buttonType="inverted" | ||
97 | onClick={this.handleCTAClick.bind(this)} | ||
98 | busy={stores.user.activateTrialRequest.isExecuting} | ||
99 | /> | ||
100 | ); | ||
101 | } | ||
102 | } | ||
103 | |||
104 | export default ActivateTrialButton; | ||
105 | |||
106 | ActivateTrialButton.wrappedComponent.propTypes = { | ||
107 | stores: PropTypes.shape({ | ||
108 | user: PropTypes.instanceOf(UserStore).isRequired, | ||
109 | }).isRequired, | ||
110 | actions: PropTypes.shape({ | ||
111 | ui: PropTypes.shape({ | ||
112 | openSettings: PropTypes.func.isRequired, | ||
113 | }).isRequired, | ||
114 | }).isRequired, | ||
115 | }; | ||
diff --git a/src/components/ui/FeatureItem.js b/src/components/ui/FeatureItem.js index 53616f2eb..7c482c4d4 100644 --- a/src/components/ui/FeatureItem.js +++ b/src/components/ui/FeatureItem.js | |||
@@ -6,7 +6,7 @@ import { mdiCheckCircle } from '@mdi/js'; | |||
6 | 6 | ||
7 | const styles = theme => ({ | 7 | const styles = theme => ({ |
8 | featureItem: { | 8 | featureItem: { |
9 | borderBottom: [1, 'solid', theme.legacyStyles.themeGrayDark], | 9 | borderBottom: [1, 'solid', theme.defaultContentBorder], |
10 | padding: [8, 0], | 10 | padding: [8, 0], |
11 | display: 'flex', | 11 | display: 'flex', |
12 | alignItems: 'center', | 12 | alignItems: 'center', |
diff --git a/src/components/ui/PremiumFeatureContainer/index.js b/src/components/ui/PremiumFeatureContainer/index.js index 3c1e0fac3..8d2746e22 100644 --- a/src/components/ui/PremiumFeatureContainer/index.js +++ b/src/components/ui/PremiumFeatureContainer/index.js | |||
@@ -10,6 +10,7 @@ import UserStore from '../../../stores/UserStore'; | |||
10 | 10 | ||
11 | import styles from './styles'; | 11 | import styles from './styles'; |
12 | import { gaEvent } from '../../../lib/analytics'; | 12 | import { gaEvent } from '../../../lib/analytics'; |
13 | import { FeatureStore } from '../../../features/utils/FeatureStore'; | ||
13 | 14 | ||
14 | const messages = defineMessages({ | 15 | const messages = defineMessages({ |
15 | action: { | 16 | action: { |
@@ -22,7 +23,10 @@ const messages = defineMessages({ | |||
22 | class PremiumFeatureContainer extends Component { | 23 | class PremiumFeatureContainer extends Component { |
23 | static propTypes = { | 24 | static propTypes = { |
24 | classes: PropTypes.object.isRequired, | 25 | classes: PropTypes.object.isRequired, |
25 | condition: PropTypes.bool, | 26 | condition: PropTypes.oneOfType([ |
27 | PropTypes.bool, | ||
28 | PropTypes.func, | ||
29 | ]), | ||
26 | gaEventInfo: PropTypes.shape({ | 30 | gaEventInfo: PropTypes.shape({ |
27 | category: PropTypes.string.isRequired, | 31 | category: PropTypes.string.isRequired, |
28 | event: PropTypes.string.isRequired, | 32 | event: PropTypes.string.isRequired, |
@@ -31,7 +35,7 @@ class PremiumFeatureContainer extends Component { | |||
31 | }; | 35 | }; |
32 | 36 | ||
33 | static defaultProps = { | 37 | static defaultProps = { |
34 | condition: true, | 38 | condition: null, |
35 | gaEventInfo: null, | 39 | gaEventInfo: null, |
36 | }; | 40 | }; |
37 | 41 | ||
@@ -51,7 +55,18 @@ class PremiumFeatureContainer extends Component { | |||
51 | 55 | ||
52 | const { intl } = this.context; | 56 | const { intl } = this.context; |
53 | 57 | ||
54 | return !stores.user.data.isPremium && !!condition ? ( | 58 | let showWrapper = !!condition; |
59 | |||
60 | if (condition === null) { | ||
61 | showWrapper = !stores.user.data.isPremium; | ||
62 | } else if (typeof condition === 'function') { | ||
63 | showWrapper = condition({ | ||
64 | isPremium: stores.user.data.isPremium, | ||
65 | features: stores.features.features, | ||
66 | }); | ||
67 | } | ||
68 | |||
69 | return showWrapper ? ( | ||
55 | <div className={classes.container}> | 70 | <div className={classes.container}> |
56 | <div className={classes.titleContainer}> | 71 | <div className={classes.titleContainer}> |
57 | <p className={classes.title}>Premium Feature</p> | 72 | <p className={classes.title}>Premium Feature</p> |
@@ -81,6 +96,7 @@ PremiumFeatureContainer.wrappedComponent.propTypes = { | |||
81 | children: oneOrManyChildElements.isRequired, | 96 | children: oneOrManyChildElements.isRequired, |
82 | stores: PropTypes.shape({ | 97 | stores: PropTypes.shape({ |
83 | user: PropTypes.instanceOf(UserStore).isRequired, | 98 | user: PropTypes.instanceOf(UserStore).isRequired, |
99 | features: PropTypes.instanceOf(FeatureStore).isRequired, | ||
84 | }).isRequired, | 100 | }).isRequired, |
85 | actions: PropTypes.shape({ | 101 | actions: PropTypes.shape({ |
86 | ui: PropTypes.shape({ | 102 | ui: PropTypes.shape({ |
diff --git a/src/config.js b/src/config.js index 405cc5253..fba739ddd 100644 --- a/src/config.js +++ b/src/config.js | |||
@@ -91,8 +91,8 @@ export const ALLOWED_PROTOCOLS = [ | |||
91 | ]; | 91 | ]; |
92 | 92 | ||
93 | export const PLANS = { | 93 | export const PLANS = { |
94 | PERSONAL: 'PERSONAL_MONTHLY', | 94 | PERSONAL: 'PERSONAL', |
95 | PRO: 'PRO_MONTHLY', | 95 | PRO: 'PRO', |
96 | LEGACY: 'LEGACY', | 96 | LEGACY: 'LEGACY', |
97 | FREE: 'FREE', | 97 | FREE: 'FREE', |
98 | }; | 98 | }; |
diff --git a/src/containers/settings/AccountScreen.js b/src/containers/settings/AccountScreen.js index f9eae4957..2b5eba91c 100644 --- a/src/containers/settings/AccountScreen.js +++ b/src/containers/settings/AccountScreen.js | |||
@@ -42,6 +42,7 @@ export default @inject('stores', 'actions') @observer class AccountScreen extend | |||
42 | <ErrorBoundary> | 42 | <ErrorBoundary> |
43 | <AccountDashboard | 43 | <AccountDashboard |
44 | user={user.data} | 44 | user={user.data} |
45 | isProUser={user.isPro} | ||
45 | isLoading={isLoadingUserInfo} | 46 | isLoading={isLoadingUserInfo} |
46 | isLoadingPlans={isLoadingPlans} | 47 | isLoadingPlans={isLoadingPlans} |
47 | userInfoRequestFailed={user.getUserInfoRequest.wasExecuted && user.getUserInfoRequest.isError} | 48 | userInfoRequestFailed={user.getUserInfoRequest.wasExecuted && user.getUserInfoRequest.isError} |
diff --git a/src/features/todos/components/TodosWebview.js b/src/features/todos/components/TodosWebview.js index d8d96ba85..9cf925444 100644 --- a/src/features/todos/components/TodosWebview.js +++ b/src/features/todos/components/TodosWebview.js | |||
@@ -10,6 +10,7 @@ import { mdiChevronRight, mdiCheckAll } from '@mdi/js'; | |||
10 | import { Button } from '@meetfranz/forms'; | 10 | import { Button } from '@meetfranz/forms'; |
11 | import * as environment from '../../../environment'; | 11 | import * as environment from '../../../environment'; |
12 | import Appear from '../../../components/ui/effects/Appear'; | 12 | import Appear from '../../../components/ui/effects/Appear'; |
13 | import ActivateTrialButton from '../../../components/ui/activateTrialButton'; | ||
13 | 14 | ||
14 | const OPEN_TODOS_BUTTON_SIZE = 45; | 15 | const OPEN_TODOS_BUTTON_SIZE = 45; |
15 | const CLOSE_TODOS_BUTTON_SIZE = 35; | 16 | const CLOSE_TODOS_BUTTON_SIZE = 35; |
@@ -70,7 +71,7 @@ const styles = theme => ({ | |||
70 | height: OPEN_TODOS_BUTTON_SIZE, | 71 | height: OPEN_TODOS_BUTTON_SIZE, |
71 | background: theme.todos.toggleButton.background, | 72 | background: theme.todos.toggleButton.background, |
72 | position: 'absolute', | 73 | position: 'absolute', |
73 | bottom: 80, | 74 | bottom: 120, |
74 | right: props => (props.width + (props.isVisible ? -OPEN_TODOS_BUTTON_SIZE / 2 : 0)), | 75 | right: props => (props.width + (props.isVisible ? -OPEN_TODOS_BUTTON_SIZE / 2 : 0)), |
75 | borderRadius: OPEN_TODOS_BUTTON_SIZE / 2, | 76 | borderRadius: OPEN_TODOS_BUTTON_SIZE / 2, |
76 | opacity: props => (props.isVisible ? 0 : 1), | 77 | opacity: props => (props.isVisible ? 0 : 1), |
@@ -94,7 +95,7 @@ const styles = theme => ({ | |||
94 | height: CLOSE_TODOS_BUTTON_SIZE, | 95 | height: CLOSE_TODOS_BUTTON_SIZE, |
95 | background: theme.todos.toggleButton.background, | 96 | background: theme.todos.toggleButton.background, |
96 | position: 'absolute', | 97 | position: 'absolute', |
97 | bottom: 80, | 98 | bottom: 120, |
98 | right: ({ width }) => (width + -CLOSE_TODOS_BUTTON_SIZE / 2), | 99 | right: ({ width }) => (width + -CLOSE_TODOS_BUTTON_SIZE / 2), |
99 | borderRadius: CLOSE_TODOS_BUTTON_SIZE / 2, | 100 | borderRadius: CLOSE_TODOS_BUTTON_SIZE / 2, |
100 | opacity: ({ isTodosIncludedInCurrentPlan }) => (!isTodosIncludedInCurrentPlan ? 1 : 0), | 101 | opacity: ({ isTodosIncludedInCurrentPlan }) => (!isTodosIncludedInCurrentPlan ? 1 : 0), |
@@ -143,7 +144,6 @@ class TodosWebview extends Component { | |||
143 | width: PropTypes.number.isRequired, | 144 | width: PropTypes.number.isRequired, |
144 | minWidth: PropTypes.number.isRequired, | 145 | minWidth: PropTypes.number.isRequired, |
145 | isTodosIncludedInCurrentPlan: PropTypes.bool.isRequired, | 146 | isTodosIncludedInCurrentPlan: PropTypes.bool.isRequired, |
146 | upgradeAccount: PropTypes.func.isRequired, | ||
147 | }; | 147 | }; |
148 | 148 | ||
149 | state = { | 149 | state = { |
@@ -235,7 +235,6 @@ class TodosWebview extends Component { | |||
235 | isVisible, | 235 | isVisible, |
236 | togglePanel, | 236 | togglePanel, |
237 | isTodosIncludedInCurrentPlan, | 237 | isTodosIncludedInCurrentPlan, |
238 | upgradeAccount, | ||
239 | } = this.props; | 238 | } = this.props; |
240 | 239 | ||
241 | const { | 240 | const { |
@@ -291,11 +290,10 @@ class TodosWebview extends Component { | |||
291 | <Icon icon={mdiCheckAll} className={classes.premiumIcon} size={5} /> | 290 | <Icon icon={mdiCheckAll} className={classes.premiumIcon} size={5} /> |
292 | <p>{intl.formatMessage(messages.premiumInfo)}</p> | 291 | <p>{intl.formatMessage(messages.premiumInfo)}</p> |
293 | <p>{intl.formatMessage(messages.rolloutInfo)}</p> | 292 | <p>{intl.formatMessage(messages.rolloutInfo)}</p> |
294 | <Button | 293 | <ActivateTrialButton |
295 | label={intl.formatMessage(messages.upgradeCTA)} | ||
296 | className={classes.premiumCTA} | 294 | className={classes.premiumCTA} |
297 | onClick={upgradeAccount} | 295 | gaEventInfo={{ category: 'Todos', event: 'upgrade' }} |
298 | buttonType="inverted" | 296 | short |
299 | /> | 297 | /> |
300 | </div> | 298 | </div> |
301 | </Appear> | 299 | </Appear> |
diff --git a/src/features/todos/containers/TodosScreen.js b/src/features/todos/containers/TodosScreen.js index 7f3688828..65afc985b 100644 --- a/src/features/todos/containers/TodosScreen.js +++ b/src/features/todos/containers/TodosScreen.js | |||
@@ -26,7 +26,6 @@ class TodosScreen extends Component { | |||
26 | minWidth={TODOS_MIN_WIDTH} | 26 | minWidth={TODOS_MIN_WIDTH} |
27 | resize={width => todoActions.resize({ width })} | 27 | resize={width => todoActions.resize({ width })} |
28 | isTodosIncludedInCurrentPlan={this.props.stores.features.features.isTodosIncludedInCurrentPlan || false} | 28 | isTodosIncludedInCurrentPlan={this.props.stores.features.features.isTodosIncludedInCurrentPlan || false} |
29 | upgradeAccount={() => this.props.actions.ui.openSettings({ path: 'user' })} | ||
30 | /> | 29 | /> |
31 | </ErrorBoundary> | 30 | </ErrorBoundary> |
32 | ); | 31 | ); |
@@ -39,9 +38,4 @@ TodosScreen.wrappedComponent.propTypes = { | |||
39 | stores: PropTypes.shape({ | 38 | stores: PropTypes.shape({ |
40 | features: PropTypes.instanceOf(FeaturesStore).isRequired, | 39 | features: PropTypes.instanceOf(FeaturesStore).isRequired, |
41 | }).isRequired, | 40 | }).isRequired, |
42 | actions: PropTypes.shape({ | ||
43 | ui: PropTypes.shape({ | ||
44 | openSettings: PropTypes.func.isRequired, | ||
45 | }).isRequired, | ||
46 | }).isRequired, | ||
47 | }; | 41 | }; |
diff --git a/src/features/todos/store.js b/src/features/todos/store.js index 7da3b7f49..56e117c6c 100644 --- a/src/features/todos/store.js +++ b/src/features/todos/store.js | |||
@@ -12,6 +12,7 @@ import { createReactions } from '../../stores/lib/Reaction'; | |||
12 | import { createActionBindings } from '../utils/ActionBinding'; | 12 | import { createActionBindings } from '../utils/ActionBinding'; |
13 | import { DEFAULT_TODOS_WIDTH, TODOS_MIN_WIDTH, DEFAULT_TODOS_VISIBLE } from '.'; | 13 | import { DEFAULT_TODOS_WIDTH, TODOS_MIN_WIDTH, DEFAULT_TODOS_VISIBLE } from '.'; |
14 | import { IPC } from './constants'; | 14 | import { IPC } from './constants'; |
15 | import { state as delayAppState } from '../delayApp'; | ||
15 | 16 | ||
16 | const debug = require('debug')('Franz:feature:todos:store'); | 17 | const debug = require('debug')('Franz:feature:todos:store'); |
17 | 18 | ||
@@ -29,7 +30,7 @@ export default class TodoStore extends FeatureStore { | |||
29 | } | 30 | } |
30 | 31 | ||
31 | @computed get isTodosPanelVisible() { | 32 | @computed get isTodosPanelVisible() { |
32 | if (this.stores.services.all.length === 0) return false; | 33 | if (this.stores.services.all.length === 0 || delayAppState.isDelayAppScreenVisible) return false; |
33 | if (this.settings.isTodosPanelVisible === undefined) return DEFAULT_TODOS_VISIBLE; | 34 | if (this.settings.isTodosPanelVisible === undefined) return DEFAULT_TODOS_VISIBLE; |
34 | 35 | ||
35 | return this.settings.isTodosPanelVisible; | 36 | return this.settings.isTodosPanelVisible; |
diff --git a/src/features/workspaces/components/WorkspacesDashboard.js b/src/features/workspaces/components/WorkspacesDashboard.js index 09c98ab8c..9e06a78e3 100644 --- a/src/features/workspaces/components/WorkspacesDashboard.js +++ b/src/features/workspaces/components/WorkspacesDashboard.js | |||
@@ -1,6 +1,6 @@ | |||
1 | import React, { Component, Fragment } from 'react'; | 1 | import React, { Component, Fragment } 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, inject } from 'mobx-react'; |
4 | import { defineMessages, intlShape } from 'react-intl'; | 4 | import { defineMessages, intlShape } from 'react-intl'; |
5 | import injectSheet from 'react-jss'; | 5 | import injectSheet from 'react-jss'; |
6 | import { Infobox } from '@meetfranz/ui'; | 6 | import { Infobox } from '@meetfranz/ui'; |
@@ -12,6 +12,8 @@ import Request from '../../../stores/lib/Request'; | |||
12 | import Appear from '../../../components/ui/effects/Appear'; | 12 | import Appear from '../../../components/ui/effects/Appear'; |
13 | import { workspaceStore } from '../index'; | 13 | import { workspaceStore } from '../index'; |
14 | import PremiumFeatureContainer from '../../../components/ui/PremiumFeatureContainer'; | 14 | import PremiumFeatureContainer from '../../../components/ui/PremiumFeatureContainer'; |
15 | import UIStore from '../../../stores/UIStore'; | ||
16 | import ActivateTrialButton from '../../../components/ui/activateTrialButton'; | ||
15 | 17 | ||
16 | const messages = defineMessages({ | 18 | const messages = defineMessages({ |
17 | headline: { | 19 | headline: { |
@@ -62,17 +64,27 @@ const styles = theme => ({ | |||
62 | height: 'auto', | 64 | height: 'auto', |
63 | }, | 65 | }, |
64 | premiumAnnouncement: { | 66 | premiumAnnouncement: { |
65 | padding: '20px', | 67 | padding: 20, |
66 | backgroundColor: '#3498db', | 68 | // backgroundColor: '#3498db', |
67 | marginLeft: '-20px', | 69 | marginLeft: -20, |
68 | marginBottom: '20px', | 70 | marginBottom: 40, |
71 | paddingBottom: 40, | ||
69 | height: 'auto', | 72 | height: 'auto', |
70 | color: 'white', | 73 | display: 'flex', |
71 | borderRadius: theme.borderRadius, | 74 | borderBottom: [1, 'solid', theme.inputBackground], |
75 | }, | ||
76 | teaserImage: { | ||
77 | width: 200, | ||
78 | height: '100%', | ||
79 | float: 'left', | ||
80 | margin: [-8, 0, 0, -20], | ||
81 | }, | ||
82 | upgradeCTA: { | ||
83 | marginTop: 20, | ||
72 | }, | 84 | }, |
73 | }); | 85 | }); |
74 | 86 | ||
75 | @injectSheet(styles) @observer | 87 | @inject('stores') @injectSheet(styles) @observer |
76 | class WorkspacesDashboard extends Component { | 88 | class WorkspacesDashboard extends Component { |
77 | static propTypes = { | 89 | static propTypes = { |
78 | classes: PropTypes.object.isRequired, | 90 | classes: PropTypes.object.isRequired, |
@@ -100,7 +112,9 @@ class WorkspacesDashboard extends Component { | |||
100 | onWorkspaceClick, | 112 | onWorkspaceClick, |
101 | workspaces, | 113 | workspaces, |
102 | } = this.props; | 114 | } = this.props; |
115 | |||
103 | const { intl } = this.context; | 116 | const { intl } = this.context; |
117 | |||
104 | return ( | 118 | return ( |
105 | <div className="settings__main"> | 119 | <div className="settings__main"> |
106 | <div className="settings__header"> | 120 | <div className="settings__header"> |
@@ -138,13 +152,21 @@ class WorkspacesDashboard extends Component { | |||
138 | 152 | ||
139 | {workspaceStore.isPremiumUpgradeRequired && ( | 153 | {workspaceStore.isPremiumUpgradeRequired && ( |
140 | <div className={classes.premiumAnnouncement}> | 154 | <div className={classes.premiumAnnouncement}> |
141 | <h2>{intl.formatMessage(messages.workspaceFeatureHeadline)}</h2> | 155 | <img src={`./assets/images/workspaces/teaser_${this.props.stores.ui.isDarkThemeActive ? 'dark' : 'light'}.png`} className={classes.teaserImage} alt="" /> |
142 | <p>{intl.formatMessage(messages.workspaceFeatureInfo)}</p> | 156 | <div> |
157 | <h2>{intl.formatMessage(messages.workspaceFeatureHeadline)}</h2> | ||
158 | <p>{intl.formatMessage(messages.workspaceFeatureInfo)}</p> | ||
159 | <ActivateTrialButton | ||
160 | className={classes.upgradeCTA} | ||
161 | gaEventInfo={{ category: 'Workspaces', event: 'upgrade' }} | ||
162 | short | ||
163 | /> | ||
164 | </div> | ||
143 | </div> | 165 | </div> |
144 | )} | 166 | )} |
145 | 167 | ||
146 | <PremiumFeatureContainer | 168 | <PremiumFeatureContainer |
147 | condition={workspaceStore.isPremiumFeature} | 169 | condition={() => workspaceStore.isPremiumUpgradeRequired} |
148 | gaEventInfo={{ category: 'User', event: 'upgrade', label: 'workspaces' }} | 170 | gaEventInfo={{ category: 'User', event: 'upgrade', label: 'workspaces' }} |
149 | > | 171 | > |
150 | {/* ===== Create workspace form ===== */} | 172 | {/* ===== Create workspace form ===== */} |
@@ -207,3 +229,9 @@ class WorkspacesDashboard extends Component { | |||
207 | } | 229 | } |
208 | 230 | ||
209 | export default WorkspacesDashboard; | 231 | export default WorkspacesDashboard; |
232 | |||
233 | WorkspacesDashboard.wrappedComponent.propTypes = { | ||
234 | stores: PropTypes.shape({ | ||
235 | ui: PropTypes.instanceOf(UIStore).isRequired, | ||
236 | }).isRequired, | ||
237 | }; | ||
diff --git a/src/features/workspaces/store.js b/src/features/workspaces/store.js index e44569be9..4a1f80b4e 100644 --- a/src/features/workspaces/store.js +++ b/src/features/workspaces/store.js | |||
@@ -253,11 +253,10 @@ export default class WorkspacesStore extends FeatureStore { | |||
253 | }; | 253 | }; |
254 | 254 | ||
255 | _setIsPremiumFeatureReaction = () => { | 255 | _setIsPremiumFeatureReaction = () => { |
256 | const { features, user } = this.stores; | 256 | const { features } = this.stores; |
257 | const { isPremium } = user.data; | ||
258 | const { isWorkspaceIncludedInCurrentPlan } = features.features; | 257 | const { isWorkspaceIncludedInCurrentPlan } = features.features; |
259 | this.isPremiumFeature = !isWorkspaceIncludedInCurrentPlan; | 258 | this.isPremiumFeature = !isWorkspaceIncludedInCurrentPlan; |
260 | this.isPremiumUpgradeRequired = !isWorkspaceIncludedInCurrentPlan && !isPremium; | 259 | this.isPremiumUpgradeRequired = !isWorkspaceIncludedInCurrentPlan; |
261 | }; | 260 | }; |
262 | 261 | ||
263 | _setWorkspaceBeingEditedReaction = () => { | 262 | _setWorkspaceBeingEditedReaction = () => { |
diff --git a/src/helpers/plan-helpers.js b/src/helpers/plan-helpers.js index 19392585e..e0f1fd89a 100644 --- a/src/helpers/plan-helpers.js +++ b/src/helpers/plan-helpers.js | |||
@@ -33,3 +33,13 @@ export function i18nPlanName(planId, intl) { | |||
33 | 33 | ||
34 | return intl.formatMessage(messages[plan]); | 34 | return intl.formatMessage(messages[plan]); |
35 | } | 35 | } |
36 | |||
37 | export function getPlan(planId) { | ||
38 | if (!planId) { | ||
39 | throw new Error('planId is required'); | ||
40 | } | ||
41 | |||
42 | const plan = PLANS_MAPPING[planId]; | ||
43 | |||
44 | return plan; | ||
45 | } | ||
diff --git a/src/i18n/locales/defaultMessages.json b/src/i18n/locales/defaultMessages.json index dabe2f11f..367184c01 100644 --- a/src/i18n/locales/defaultMessages.json +++ b/src/i18n/locales/defaultMessages.json | |||
@@ -2895,6 +2895,63 @@ | |||
2895 | { | 2895 | { |
2896 | "descriptors": [ | 2896 | "descriptors": [ |
2897 | { | 2897 | { |
2898 | "defaultMessage": "!!!Get a Franz Supporter License", | ||
2899 | "end": { | ||
2900 | "column": 3, | ||
2901 | "line": 16 | ||
2902 | }, | ||
2903 | "file": "src/components/ui/ActivateTrialButton/index.js", | ||
2904 | "id": "feature.delayApp.upgrade.action", | ||
2905 | "start": { | ||
2906 | "column": 10, | ||
2907 | "line": 13 | ||
2908 | } | ||
2909 | }, | ||
2910 | { | ||
2911 | "defaultMessage": "!!!Yes, I want the free 14 day trial of Franz Professional", | ||
2912 | "end": { | ||
2913 | "column": 3, | ||
2914 | "line": 20 | ||
2915 | }, | ||
2916 | "file": "src/components/ui/ActivateTrialButton/index.js", | ||
2917 | "id": "feature.delayApp.trial.action", | ||
2918 | "start": { | ||
2919 | "column": 15, | ||
2920 | "line": 17 | ||
2921 | } | ||
2922 | }, | ||
2923 | { | ||
2924 | "defaultMessage": "!!!Upgrade account", | ||
2925 | "end": { | ||
2926 | "column": 3, | ||
2927 | "line": 24 | ||
2928 | }, | ||
2929 | "file": "src/components/ui/ActivateTrialButton/index.js", | ||
2930 | "id": "feature.delayApp.upgrade.actionShort", | ||
2931 | "start": { | ||
2932 | "column": 15, | ||
2933 | "line": 21 | ||
2934 | } | ||
2935 | }, | ||
2936 | { | ||
2937 | "defaultMessage": "!!!Activate the free Franz Professional trial", | ||
2938 | "end": { | ||
2939 | "column": 3, | ||
2940 | "line": 28 | ||
2941 | }, | ||
2942 | "file": "src/components/ui/ActivateTrialButton/index.js", | ||
2943 | "id": "feature.delayApp.trial.actionShort", | ||
2944 | "start": { | ||
2945 | "column": 20, | ||
2946 | "line": 25 | ||
2947 | } | ||
2948 | } | ||
2949 | ], | ||
2950 | "path": "src/components/ui/ActivateTrialButton/index.json" | ||
2951 | }, | ||
2952 | { | ||
2953 | "descriptors": [ | ||
2954 | { | ||
2898 | "defaultMessage": "!!!Add unlimited services", | 2955 | "defaultMessage": "!!!Add unlimited services", |
2899 | "end": { | 2956 | "end": { |
2900 | "column": 3, | 2957 | "column": 3, |
@@ -3033,13 +3090,13 @@ | |||
3033 | "defaultMessage": "!!!Upgrade account", | 3090 | "defaultMessage": "!!!Upgrade account", |
3034 | "end": { | 3091 | "end": { |
3035 | "column": 3, | 3092 | "column": 3, |
3036 | "line": 18 | 3093 | "line": 19 |
3037 | }, | 3094 | }, |
3038 | "file": "src/components/ui/PremiumFeatureContainer/index.js", | 3095 | "file": "src/components/ui/PremiumFeatureContainer/index.js", |
3039 | "id": "premiumFeature.button.upgradeAccount", | 3096 | "id": "premiumFeature.button.upgradeAccount", |
3040 | "start": { | 3097 | "start": { |
3041 | "column": 10, | 3098 | "column": 10, |
3042 | "line": 15 | 3099 | "line": 16 |
3043 | } | 3100 | } |
3044 | } | 3101 | } |
3045 | ], | 3102 | ], |
@@ -3720,91 +3777,91 @@ | |||
3720 | "defaultMessage": "!!!Franz is better together!", | 3777 | "defaultMessage": "!!!Franz is better together!", |
3721 | "end": { | 3778 | "end": { |
3722 | "column": 3, | 3779 | "column": 3, |
3723 | "line": 19 | 3780 | "line": 21 |
3724 | }, | 3781 | }, |
3725 | "file": "src/features/shareFranz/Component.js", | 3782 | "file": "src/features/shareFranz/Component.js", |
3726 | "id": "feature.shareFranz.headline", | 3783 | "id": "feature.shareFranz.headline", |
3727 | "start": { | 3784 | "start": { |
3728 | "column": 12, | 3785 | "column": 12, |
3729 | "line": 16 | 3786 | "line": 18 |
3730 | } | 3787 | } |
3731 | }, | 3788 | }, |
3732 | { | 3789 | { |
3733 | "defaultMessage": "!!!Tell your friends and colleagues how awesome Franz is and help us to spread the word.", | 3790 | "defaultMessage": "!!!Tell your friends and colleagues how awesome Franz is and help us to spread the word.", |
3734 | "end": { | 3791 | "end": { |
3735 | "column": 3, | 3792 | "column": 3, |
3736 | "line": 23 | 3793 | "line": 25 |
3737 | }, | 3794 | }, |
3738 | "file": "src/features/shareFranz/Component.js", | 3795 | "file": "src/features/shareFranz/Component.js", |
3739 | "id": "feature.shareFranz.text", | 3796 | "id": "feature.shareFranz.text", |
3740 | "start": { | 3797 | "start": { |
3741 | "column": 8, | 3798 | "column": 8, |
3742 | "line": 20 | 3799 | "line": 22 |
3743 | } | 3800 | } |
3744 | }, | 3801 | }, |
3745 | { | 3802 | { |
3746 | "defaultMessage": "!!!Share as email", | 3803 | "defaultMessage": "!!!Share as email", |
3747 | "end": { | 3804 | "end": { |
3748 | "column": 3, | 3805 | "column": 3, |
3749 | "line": 27 | 3806 | "line": 29 |
3750 | }, | 3807 | }, |
3751 | "file": "src/features/shareFranz/Component.js", | 3808 | "file": "src/features/shareFranz/Component.js", |
3752 | "id": "feature.shareFranz.action.email", | 3809 | "id": "feature.shareFranz.action.email", |
3753 | "start": { | 3810 | "start": { |
3754 | "column": 16, | 3811 | "column": 16, |
3755 | "line": 24 | 3812 | "line": 26 |
3756 | } | 3813 | } |
3757 | }, | 3814 | }, |
3758 | { | 3815 | { |
3759 | "defaultMessage": "!!!Share on Facebook", | 3816 | "defaultMessage": "!!!Share on Facebook", |
3760 | "end": { | 3817 | "end": { |
3761 | "column": 3, | 3818 | "column": 3, |
3762 | "line": 31 | 3819 | "line": 33 |
3763 | }, | 3820 | }, |
3764 | "file": "src/features/shareFranz/Component.js", | 3821 | "file": "src/features/shareFranz/Component.js", |
3765 | "id": "feature.shareFranz.action.facebook", | 3822 | "id": "feature.shareFranz.action.facebook", |
3766 | "start": { | 3823 | "start": { |
3767 | "column": 19, | 3824 | "column": 19, |
3768 | "line": 28 | 3825 | "line": 30 |
3769 | } | 3826 | } |
3770 | }, | 3827 | }, |
3771 | { | 3828 | { |
3772 | "defaultMessage": "!!!Share on Twitter", | 3829 | "defaultMessage": "!!!Share on Twitter", |
3773 | "end": { | 3830 | "end": { |
3774 | "column": 3, | 3831 | "column": 3, |
3775 | "line": 35 | 3832 | "line": 37 |
3776 | }, | 3833 | }, |
3777 | "file": "src/features/shareFranz/Component.js", | 3834 | "file": "src/features/shareFranz/Component.js", |
3778 | "id": "feature.shareFranz.action.twitter", | 3835 | "id": "feature.shareFranz.action.twitter", |
3779 | "start": { | 3836 | "start": { |
3780 | "column": 18, | 3837 | "column": 18, |
3781 | "line": 32 | 3838 | "line": 34 |
3782 | } | 3839 | } |
3783 | }, | 3840 | }, |
3784 | { | 3841 | { |
3785 | "defaultMessage": "!!! I've added {count} services to Franz! Get the free app for WhatsApp, Messenger, Slack, Skype and co at www.meetfranz.com", | 3842 | "defaultMessage": "!!! I've added {count} services to Franz! Get the free app for WhatsApp, Messenger, Slack, Skype and co at www.meetfranz.com", |
3786 | "end": { | 3843 | "end": { |
3787 | "column": 3, | 3844 | "column": 3, |
3788 | "line": 39 | 3845 | "line": 41 |
3789 | }, | 3846 | }, |
3790 | "file": "src/features/shareFranz/Component.js", | 3847 | "file": "src/features/shareFranz/Component.js", |
3791 | "id": "feature.shareFranz.shareText.email", | 3848 | "id": "feature.shareFranz.shareText.email", |
3792 | "start": { | 3849 | "start": { |
3793 | "column": 18, | 3850 | "column": 18, |
3794 | "line": 36 | 3851 | "line": 38 |
3795 | } | 3852 | } |
3796 | }, | 3853 | }, |
3797 | { | 3854 | { |
3798 | "defaultMessage": "!!! I've added {count} services to Franz! Get the free app for WhatsApp, Messenger, Slack, Skype and co at www.meetfranz.com /cc @FranzMessenger", | 3855 | "defaultMessage": "!!! I've added {count} services to Franz! Get the free app for WhatsApp, Messenger, Slack, Skype and co at www.meetfranz.com /cc @FranzMessenger", |
3799 | "end": { | 3856 | "end": { |
3800 | "column": 3, | 3857 | "column": 3, |
3801 | "line": 43 | 3858 | "line": 45 |
3802 | }, | 3859 | }, |
3803 | "file": "src/features/shareFranz/Component.js", | 3860 | "file": "src/features/shareFranz/Component.js", |
3804 | "id": "feature.shareFranz.shareText.twitter", | 3861 | "id": "feature.shareFranz.shareText.twitter", |
3805 | "start": { | 3862 | "start": { |
3806 | "column": 20, | 3863 | "column": 20, |
3807 | "line": 40 | 3864 | "line": 42 |
3808 | } | 3865 | } |
3809 | } | 3866 | } |
3810 | ], | 3867 | ], |
@@ -3816,39 +3873,39 @@ | |||
3816 | "defaultMessage": "!!!The Franz Todos Preview is currently only available for Franz Premium accounts.", | 3873 | "defaultMessage": "!!!The Franz Todos Preview is currently only available for Franz Premium accounts.", |
3817 | "end": { | 3874 | "end": { |
3818 | "column": 3, | 3875 | "column": 3, |
3819 | "line": 21 | 3876 | "line": 22 |
3820 | }, | 3877 | }, |
3821 | "file": "src/features/todos/components/TodosWebview.js", | 3878 | "file": "src/features/todos/components/TodosWebview.js", |
3822 | "id": "feature.todos.premium.info", | 3879 | "id": "feature.todos.premium.info", |
3823 | "start": { | 3880 | "start": { |
3824 | "column": 15, | 3881 | "column": 15, |
3825 | "line": 18 | 3882 | "line": 19 |
3826 | } | 3883 | } |
3827 | }, | 3884 | }, |
3828 | { | 3885 | { |
3829 | "defaultMessage": "!!!Upgrade Account", | 3886 | "defaultMessage": "!!!Upgrade Account", |
3830 | "end": { | 3887 | "end": { |
3831 | "column": 3, | 3888 | "column": 3, |
3832 | "line": 25 | 3889 | "line": 26 |
3833 | }, | 3890 | }, |
3834 | "file": "src/features/todos/components/TodosWebview.js", | 3891 | "file": "src/features/todos/components/TodosWebview.js", |
3835 | "id": "feature.todos.premium.upgrade", | 3892 | "id": "feature.todos.premium.upgrade", |
3836 | "start": { | 3893 | "start": { |
3837 | "column": 14, | 3894 | "column": 14, |
3838 | "line": 22 | 3895 | "line": 23 |
3839 | } | 3896 | } |
3840 | }, | 3897 | }, |
3841 | { | 3898 | { |
3842 | "defaultMessage": "!!!Franz Todos will be available to everyone soon.", | 3899 | "defaultMessage": "!!!Franz Todos will be available to everyone soon.", |
3843 | "end": { | 3900 | "end": { |
3844 | "column": 3, | 3901 | "column": 3, |
3845 | "line": 29 | 3902 | "line": 30 |
3846 | }, | 3903 | }, |
3847 | "file": "src/features/todos/components/TodosWebview.js", | 3904 | "file": "src/features/todos/components/TodosWebview.js", |
3848 | "id": "feature.todos.premium.rollout", | 3905 | "id": "feature.todos.premium.rollout", |
3849 | "start": { | 3906 | "start": { |
3850 | "column": 15, | 3907 | "column": 15, |
3851 | "line": 26 | 3908 | "line": 27 |
3852 | } | 3909 | } |
3853 | } | 3910 | } |
3854 | ], | 3911 | ], |
@@ -4127,104 +4184,104 @@ | |||
4127 | "defaultMessage": "!!!Your workspaces", | 4184 | "defaultMessage": "!!!Your workspaces", |
4128 | "end": { | 4185 | "end": { |
4129 | "column": 3, | 4186 | "column": 3, |
4130 | "line": 20 | 4187 | "line": 22 |
4131 | }, | 4188 | }, |
4132 | "file": "src/features/workspaces/components/WorkspacesDashboard.js", | 4189 | "file": "src/features/workspaces/components/WorkspacesDashboard.js", |
4133 | "id": "settings.workspaces.headline", | 4190 | "id": "settings.workspaces.headline", |
4134 | "start": { | 4191 | "start": { |
4135 | "column": 12, | 4192 | "column": 12, |
4136 | "line": 17 | 4193 | "line": 19 |
4137 | } | 4194 | } |
4138 | }, | 4195 | }, |
4139 | { | 4196 | { |
4140 | "defaultMessage": "!!!You haven't added any workspaces yet.", | 4197 | "defaultMessage": "!!!You haven't added any workspaces yet.", |
4141 | "end": { | 4198 | "end": { |
4142 | "column": 3, | 4199 | "column": 3, |
4143 | "line": 24 | 4200 | "line": 26 |
4144 | }, | 4201 | }, |
4145 | "file": "src/features/workspaces/components/WorkspacesDashboard.js", | 4202 | "file": "src/features/workspaces/components/WorkspacesDashboard.js", |
4146 | "id": "settings.workspaces.noWorkspacesAdded", | 4203 | "id": "settings.workspaces.noWorkspacesAdded", |
4147 | "start": { | 4204 | "start": { |
4148 | "column": 19, | 4205 | "column": 19, |
4149 | "line": 21 | 4206 | "line": 23 |
4150 | } | 4207 | } |
4151 | }, | 4208 | }, |
4152 | { | 4209 | { |
4153 | "defaultMessage": "!!!Could not load your workspaces", | 4210 | "defaultMessage": "!!!Could not load your workspaces", |
4154 | "end": { | 4211 | "end": { |
4155 | "column": 3, | 4212 | "column": 3, |
4156 | "line": 28 | 4213 | "line": 30 |
4157 | }, | 4214 | }, |
4158 | "file": "src/features/workspaces/components/WorkspacesDashboard.js", | 4215 | "file": "src/features/workspaces/components/WorkspacesDashboard.js", |
4159 | "id": "settings.workspaces.workspacesRequestFailed", | 4216 | "id": "settings.workspaces.workspacesRequestFailed", |
4160 | "start": { | 4217 | "start": { |
4161 | "column": 27, | 4218 | "column": 27, |
4162 | "line": 25 | 4219 | "line": 27 |
4163 | } | 4220 | } |
4164 | }, | 4221 | }, |
4165 | { | 4222 | { |
4166 | "defaultMessage": "!!!Try again", | 4223 | "defaultMessage": "!!!Try again", |
4167 | "end": { | 4224 | "end": { |
4168 | "column": 3, | 4225 | "column": 3, |
4169 | "line": 32 | 4226 | "line": 34 |
4170 | }, | 4227 | }, |
4171 | "file": "src/features/workspaces/components/WorkspacesDashboard.js", | 4228 | "file": "src/features/workspaces/components/WorkspacesDashboard.js", |
4172 | "id": "settings.workspaces.tryReloadWorkspaces", | 4229 | "id": "settings.workspaces.tryReloadWorkspaces", |
4173 | "start": { | 4230 | "start": { |
4174 | "column": 23, | 4231 | "column": 23, |
4175 | "line": 29 | 4232 | "line": 31 |
4176 | } | 4233 | } |
4177 | }, | 4234 | }, |
4178 | { | 4235 | { |
4179 | "defaultMessage": "!!!Your changes have been saved", | 4236 | "defaultMessage": "!!!Your changes have been saved", |
4180 | "end": { | 4237 | "end": { |
4181 | "column": 3, | 4238 | "column": 3, |
4182 | "line": 36 | 4239 | "line": 38 |
4183 | }, | 4240 | }, |
4184 | "file": "src/features/workspaces/components/WorkspacesDashboard.js", | 4241 | "file": "src/features/workspaces/components/WorkspacesDashboard.js", |
4185 | "id": "settings.workspaces.updatedInfo", | 4242 | "id": "settings.workspaces.updatedInfo", |
4186 | "start": { | 4243 | "start": { |
4187 | "column": 15, | 4244 | "column": 15, |
4188 | "line": 33 | 4245 | "line": 35 |
4189 | } | 4246 | } |
4190 | }, | 4247 | }, |
4191 | { | 4248 | { |
4192 | "defaultMessage": "!!!Workspace has been deleted", | 4249 | "defaultMessage": "!!!Workspace has been deleted", |
4193 | "end": { | 4250 | "end": { |
4194 | "column": 3, | 4251 | "column": 3, |
4195 | "line": 40 | 4252 | "line": 42 |
4196 | }, | 4253 | }, |
4197 | "file": "src/features/workspaces/components/WorkspacesDashboard.js", | 4254 | "file": "src/features/workspaces/components/WorkspacesDashboard.js", |
4198 | "id": "settings.workspaces.deletedInfo", | 4255 | "id": "settings.workspaces.deletedInfo", |
4199 | "start": { | 4256 | "start": { |
4200 | "column": 15, | 4257 | "column": 15, |
4201 | "line": 37 | 4258 | "line": 39 |
4202 | } | 4259 | } |
4203 | }, | 4260 | }, |
4204 | { | 4261 | { |
4205 | "defaultMessage": "!!!Info about workspace feature", | 4262 | "defaultMessage": "!!!Info about workspace feature", |
4206 | "end": { | 4263 | "end": { |
4207 | "column": 3, | 4264 | "column": 3, |
4208 | "line": 44 | 4265 | "line": 46 |
4209 | }, | 4266 | }, |
4210 | "file": "src/features/workspaces/components/WorkspacesDashboard.js", | 4267 | "file": "src/features/workspaces/components/WorkspacesDashboard.js", |
4211 | "id": "settings.workspaces.workspaceFeatureInfo", | 4268 | "id": "settings.workspaces.workspaceFeatureInfo", |
4212 | "start": { | 4269 | "start": { |
4213 | "column": 24, | 4270 | "column": 24, |
4214 | "line": 41 | 4271 | "line": 43 |
4215 | } | 4272 | } |
4216 | }, | 4273 | }, |
4217 | { | 4274 | { |
4218 | "defaultMessage": "!!!Less is More: Introducing Franz Workspaces", | 4275 | "defaultMessage": "!!!Less is More: Introducing Franz Workspaces", |
4219 | "end": { | 4276 | "end": { |
4220 | "column": 3, | 4277 | "column": 3, |
4221 | "line": 48 | 4278 | "line": 50 |
4222 | }, | 4279 | }, |
4223 | "file": "src/features/workspaces/components/WorkspacesDashboard.js", | 4280 | "file": "src/features/workspaces/components/WorkspacesDashboard.js", |
4224 | "id": "settings.workspaces.workspaceFeatureHeadline", | 4281 | "id": "settings.workspaces.workspaceFeatureHeadline", |
4225 | "start": { | 4282 | "start": { |
4226 | "column": 28, | 4283 | "column": 28, |
4227 | "line": 45 | 4284 | "line": 47 |
4228 | } | 4285 | } |
4229 | } | 4286 | } |
4230 | ], | 4287 | ], |
diff --git a/src/i18n/locales/en-US.json b/src/i18n/locales/en-US.json index 32e9c743a..f11d5ca91 100644 --- a/src/i18n/locales/en-US.json +++ b/src/i18n/locales/en-US.json | |||
@@ -5,8 +5,10 @@ | |||
5 | "feature.delayApp.headline": "Please purchase a Franz Supporter License to skip waiting", | 5 | "feature.delayApp.headline": "Please purchase a Franz Supporter License to skip waiting", |
6 | "feature.delayApp.text": "Franz will continue in {seconds} seconds.", | 6 | "feature.delayApp.text": "Franz will continue in {seconds} seconds.", |
7 | "feature.delayApp.trial.action": "Yes, I want the free 14 day trial of Franz Professional", | 7 | "feature.delayApp.trial.action": "Yes, I want the free 14 day trial of Franz Professional", |
8 | "feature.delayApp.trial.actionShort": "Activate the free Franz Professional trial", | ||
8 | "feature.delayApp.trial.headline": "Get the free Franz Professional 14 day trial and skip the line", | 9 | "feature.delayApp.trial.headline": "Get the free Franz Professional 14 day trial and skip the line", |
9 | "feature.delayApp.upgrade.action": "Get a Franz Supporter License", | 10 | "feature.delayApp.upgrade.action": "Get a Franz Supporter License", |
11 | "feature.delayApp.upgrade.actionShort": "Upgrade account", | ||
10 | "feature.serviceLimit.limitReached": "You have added {amount} out of {limit} services that are included in your plan. Please upgrade your account to add more services.", | 12 | "feature.serviceLimit.limitReached": "You have added {amount} out of {limit} services that are included in your plan. Please upgrade your account to add more services.", |
11 | "feature.shareFranz.action.email": "Send as email", | 13 | "feature.shareFranz.action.email": "Send as email", |
12 | "feature.shareFranz.action.facebook": "Share on Facebook", | 14 | "feature.shareFranz.action.facebook": "Share on Facebook", |
diff --git a/src/i18n/messages/src/components/ui/ActivateTrialButton/index.json b/src/i18n/messages/src/components/ui/ActivateTrialButton/index.json new file mode 100644 index 000000000..08c1a9293 --- /dev/null +++ b/src/i18n/messages/src/components/ui/ActivateTrialButton/index.json | |||
@@ -0,0 +1,54 @@ | |||
1 | [ | ||
2 | { | ||
3 | "id": "feature.delayApp.upgrade.action", | ||
4 | "defaultMessage": "!!!Get a Franz Supporter License", | ||
5 | "file": "src/components/ui/ActivateTrialButton/index.js", | ||
6 | "start": { | ||
7 | "line": 13, | ||
8 | "column": 10 | ||
9 | }, | ||
10 | "end": { | ||
11 | "line": 16, | ||
12 | "column": 3 | ||
13 | } | ||
14 | }, | ||
15 | { | ||
16 | "id": "feature.delayApp.trial.action", | ||
17 | "defaultMessage": "!!!Yes, I want the free 14 day trial of Franz Professional", | ||
18 | "file": "src/components/ui/ActivateTrialButton/index.js", | ||
19 | "start": { | ||
20 | "line": 17, | ||
21 | "column": 15 | ||
22 | }, | ||
23 | "end": { | ||
24 | "line": 20, | ||
25 | "column": 3 | ||
26 | } | ||
27 | }, | ||
28 | { | ||
29 | "id": "feature.delayApp.upgrade.actionShort", | ||
30 | "defaultMessage": "!!!Upgrade account", | ||
31 | "file": "src/components/ui/ActivateTrialButton/index.js", | ||
32 | "start": { | ||
33 | "line": 21, | ||
34 | "column": 15 | ||
35 | }, | ||
36 | "end": { | ||
37 | "line": 24, | ||
38 | "column": 3 | ||
39 | } | ||
40 | }, | ||
41 | { | ||
42 | "id": "feature.delayApp.trial.actionShort", | ||
43 | "defaultMessage": "!!!Activate the free Franz Professional trial", | ||
44 | "file": "src/components/ui/ActivateTrialButton/index.js", | ||
45 | "start": { | ||
46 | "line": 25, | ||
47 | "column": 20 | ||
48 | }, | ||
49 | "end": { | ||
50 | "line": 28, | ||
51 | "column": 3 | ||
52 | } | ||
53 | } | ||
54 | ] \ No newline at end of file | ||
diff --git a/src/i18n/messages/src/components/ui/PremiumFeatureContainer/index.json b/src/i18n/messages/src/components/ui/PremiumFeatureContainer/index.json index 320d3ca3e..0cde4cee5 100644 --- a/src/i18n/messages/src/components/ui/PremiumFeatureContainer/index.json +++ b/src/i18n/messages/src/components/ui/PremiumFeatureContainer/index.json | |||
@@ -4,11 +4,11 @@ | |||
4 | "defaultMessage": "!!!Upgrade account", | 4 | "defaultMessage": "!!!Upgrade account", |
5 | "file": "src/components/ui/PremiumFeatureContainer/index.js", | 5 | "file": "src/components/ui/PremiumFeatureContainer/index.js", |
6 | "start": { | 6 | "start": { |
7 | "line": 15, | 7 | "line": 16, |
8 | "column": 10 | 8 | "column": 10 |
9 | }, | 9 | }, |
10 | "end": { | 10 | "end": { |
11 | "line": 18, | 11 | "line": 19, |
12 | "column": 3 | 12 | "column": 3 |
13 | } | 13 | } |
14 | } | 14 | } |
diff --git a/src/i18n/messages/src/features/todos/components/TodosWebview.json b/src/i18n/messages/src/features/todos/components/TodosWebview.json index 2387112b4..7d26342b7 100644 --- a/src/i18n/messages/src/features/todos/components/TodosWebview.json +++ b/src/i18n/messages/src/features/todos/components/TodosWebview.json | |||
@@ -4,11 +4,11 @@ | |||
4 | "defaultMessage": "!!!The Franz Todos Preview is currently only available for Franz Premium accounts.", | 4 | "defaultMessage": "!!!The Franz Todos Preview is currently only available for Franz Premium accounts.", |
5 | "file": "src/features/todos/components/TodosWebview.js", | 5 | "file": "src/features/todos/components/TodosWebview.js", |
6 | "start": { | 6 | "start": { |
7 | "line": 18, | 7 | "line": 19, |
8 | "column": 15 | 8 | "column": 15 |
9 | }, | 9 | }, |
10 | "end": { | 10 | "end": { |
11 | "line": 21, | 11 | "line": 22, |
12 | "column": 3 | 12 | "column": 3 |
13 | } | 13 | } |
14 | }, | 14 | }, |
@@ -17,11 +17,11 @@ | |||
17 | "defaultMessage": "!!!Upgrade Account", | 17 | "defaultMessage": "!!!Upgrade Account", |
18 | "file": "src/features/todos/components/TodosWebview.js", | 18 | "file": "src/features/todos/components/TodosWebview.js", |
19 | "start": { | 19 | "start": { |
20 | "line": 22, | 20 | "line": 23, |
21 | "column": 14 | 21 | "column": 14 |
22 | }, | 22 | }, |
23 | "end": { | 23 | "end": { |
24 | "line": 25, | 24 | "line": 26, |
25 | "column": 3 | 25 | "column": 3 |
26 | } | 26 | } |
27 | }, | 27 | }, |
@@ -30,11 +30,11 @@ | |||
30 | "defaultMessage": "!!!Franz Todos will be available to everyone soon.", | 30 | "defaultMessage": "!!!Franz Todos will be available to everyone soon.", |
31 | "file": "src/features/todos/components/TodosWebview.js", | 31 | "file": "src/features/todos/components/TodosWebview.js", |
32 | "start": { | 32 | "start": { |
33 | "line": 26, | 33 | "line": 27, |
34 | "column": 15 | 34 | "column": 15 |
35 | }, | 35 | }, |
36 | "end": { | 36 | "end": { |
37 | "line": 29, | 37 | "line": 30, |
38 | "column": 3 | 38 | "column": 3 |
39 | } | 39 | } |
40 | } | 40 | } |
diff --git a/src/i18n/messages/src/features/workspaces/components/WorkspacesDashboard.json b/src/i18n/messages/src/features/workspaces/components/WorkspacesDashboard.json index ef8f1bebc..7eb4fab50 100644 --- a/src/i18n/messages/src/features/workspaces/components/WorkspacesDashboard.json +++ b/src/i18n/messages/src/features/workspaces/components/WorkspacesDashboard.json | |||
@@ -4,11 +4,11 @@ | |||
4 | "defaultMessage": "!!!Your workspaces", | 4 | "defaultMessage": "!!!Your workspaces", |
5 | "file": "src/features/workspaces/components/WorkspacesDashboard.js", | 5 | "file": "src/features/workspaces/components/WorkspacesDashboard.js", |
6 | "start": { | 6 | "start": { |
7 | "line": 17, | 7 | "line": 19, |
8 | "column": 12 | 8 | "column": 12 |
9 | }, | 9 | }, |
10 | "end": { | 10 | "end": { |
11 | "line": 20, | 11 | "line": 22, |
12 | "column": 3 | 12 | "column": 3 |
13 | } | 13 | } |
14 | }, | 14 | }, |
@@ -17,11 +17,11 @@ | |||
17 | "defaultMessage": "!!!You haven't added any workspaces yet.", | 17 | "defaultMessage": "!!!You haven't added any workspaces yet.", |
18 | "file": "src/features/workspaces/components/WorkspacesDashboard.js", | 18 | "file": "src/features/workspaces/components/WorkspacesDashboard.js", |
19 | "start": { | 19 | "start": { |
20 | "line": 21, | 20 | "line": 23, |
21 | "column": 19 | 21 | "column": 19 |
22 | }, | 22 | }, |
23 | "end": { | 23 | "end": { |
24 | "line": 24, | 24 | "line": 26, |
25 | "column": 3 | 25 | "column": 3 |
26 | } | 26 | } |
27 | }, | 27 | }, |
@@ -30,11 +30,11 @@ | |||
30 | "defaultMessage": "!!!Could not load your workspaces", | 30 | "defaultMessage": "!!!Could not load your workspaces", |
31 | "file": "src/features/workspaces/components/WorkspacesDashboard.js", | 31 | "file": "src/features/workspaces/components/WorkspacesDashboard.js", |
32 | "start": { | 32 | "start": { |
33 | "line": 25, | 33 | "line": 27, |
34 | "column": 27 | 34 | "column": 27 |
35 | }, | 35 | }, |
36 | "end": { | 36 | "end": { |
37 | "line": 28, | 37 | "line": 30, |
38 | "column": 3 | 38 | "column": 3 |
39 | } | 39 | } |
40 | }, | 40 | }, |
@@ -43,11 +43,11 @@ | |||
43 | "defaultMessage": "!!!Try again", | 43 | "defaultMessage": "!!!Try again", |
44 | "file": "src/features/workspaces/components/WorkspacesDashboard.js", | 44 | "file": "src/features/workspaces/components/WorkspacesDashboard.js", |
45 | "start": { | 45 | "start": { |
46 | "line": 29, | 46 | "line": 31, |
47 | "column": 23 | 47 | "column": 23 |
48 | }, | 48 | }, |
49 | "end": { | 49 | "end": { |
50 | "line": 32, | 50 | "line": 34, |
51 | "column": 3 | 51 | "column": 3 |
52 | } | 52 | } |
53 | }, | 53 | }, |
@@ -56,11 +56,11 @@ | |||
56 | "defaultMessage": "!!!Your changes have been saved", | 56 | "defaultMessage": "!!!Your changes have been saved", |
57 | "file": "src/features/workspaces/components/WorkspacesDashboard.js", | 57 | "file": "src/features/workspaces/components/WorkspacesDashboard.js", |
58 | "start": { | 58 | "start": { |
59 | "line": 33, | 59 | "line": 35, |
60 | "column": 15 | 60 | "column": 15 |
61 | }, | 61 | }, |
62 | "end": { | 62 | "end": { |
63 | "line": 36, | 63 | "line": 38, |
64 | "column": 3 | 64 | "column": 3 |
65 | } | 65 | } |
66 | }, | 66 | }, |
@@ -69,11 +69,11 @@ | |||
69 | "defaultMessage": "!!!Workspace has been deleted", | 69 | "defaultMessage": "!!!Workspace has been deleted", |
70 | "file": "src/features/workspaces/components/WorkspacesDashboard.js", | 70 | "file": "src/features/workspaces/components/WorkspacesDashboard.js", |
71 | "start": { | 71 | "start": { |
72 | "line": 37, | 72 | "line": 39, |
73 | "column": 15 | 73 | "column": 15 |
74 | }, | 74 | }, |
75 | "end": { | 75 | "end": { |
76 | "line": 40, | 76 | "line": 42, |
77 | "column": 3 | 77 | "column": 3 |
78 | } | 78 | } |
79 | }, | 79 | }, |
@@ -82,11 +82,11 @@ | |||
82 | "defaultMessage": "!!!Info about workspace feature", | 82 | "defaultMessage": "!!!Info about workspace feature", |
83 | "file": "src/features/workspaces/components/WorkspacesDashboard.js", | 83 | "file": "src/features/workspaces/components/WorkspacesDashboard.js", |
84 | "start": { | 84 | "start": { |
85 | "line": 41, | 85 | "line": 43, |
86 | "column": 24 | 86 | "column": 24 |
87 | }, | 87 | }, |
88 | "end": { | 88 | "end": { |
89 | "line": 44, | 89 | "line": 46, |
90 | "column": 3 | 90 | "column": 3 |
91 | } | 91 | } |
92 | }, | 92 | }, |
@@ -95,11 +95,11 @@ | |||
95 | "defaultMessage": "!!!Less is More: Introducing Franz Workspaces", | 95 | "defaultMessage": "!!!Less is More: Introducing Franz Workspaces", |
96 | "file": "src/features/workspaces/components/WorkspacesDashboard.js", | 96 | "file": "src/features/workspaces/components/WorkspacesDashboard.js", |
97 | "start": { | 97 | "start": { |
98 | "line": 45, | 98 | "line": 47, |
99 | "column": 28 | 99 | "column": 28 |
100 | }, | 100 | }, |
101 | "end": { | 101 | "end": { |
102 | "line": 48, | 102 | "line": 50, |
103 | "column": 3 | 103 | "column": 3 |
104 | } | 104 | } |
105 | } | 105 | } |
diff --git a/src/stores/UserStore.js b/src/stores/UserStore.js index f3dfbdbf0..7ac7d2375 100644 --- a/src/stores/UserStore.js +++ b/src/stores/UserStore.js | |||
@@ -10,6 +10,8 @@ import Request from './lib/Request'; | |||
10 | import CachedRequest from './lib/CachedRequest'; | 10 | import CachedRequest from './lib/CachedRequest'; |
11 | import { gaEvent } from '../lib/analytics'; | 11 | import { gaEvent } from '../lib/analytics'; |
12 | import { sleep } from '../helpers/async-helpers'; | 12 | import { sleep } from '../helpers/async-helpers'; |
13 | import { getPlan } from '../helpers/plan-helpers'; | ||
14 | import { PLANS } from '../config'; | ||
13 | 15 | ||
14 | const debug = require('debug')('Franz:UserStore'); | 16 | const debug = require('debug')('Franz:UserStore'); |
15 | 17 | ||
@@ -150,10 +152,30 @@ export default class UserStore extends Store { | |||
150 | return this.getUserInfoRequest.execute().result || {}; | 152 | return this.getUserInfoRequest.execute().result || {}; |
151 | } | 153 | } |
152 | 154 | ||
155 | @computed get team() { | ||
156 | return this.data.team || null; | ||
157 | } | ||
158 | |||
153 | @computed get isPremium() { | 159 | @computed get isPremium() { |
154 | return !!this.data.isPremium; | 160 | return !!this.data.isPremium; |
155 | } | 161 | } |
156 | 162 | ||
163 | @computed get isPersonal() { | ||
164 | if (!this.team.plan) return false; | ||
165 | const plan = getPlan(this.team.plan); | ||
166 | |||
167 | return plan === PLANS.PERSONAL; | ||
168 | } | ||
169 | |||
170 | @computed get isPro() { | ||
171 | if (!this.team.plan && this.isPremium) return true; | ||
172 | |||
173 | if (!this.team.plan) return false; | ||
174 | const plan = getPlan(this.team.plan); | ||
175 | |||
176 | return plan === PLANS.PRO; | ||
177 | } | ||
178 | |||
157 | @computed get legacyServices() { | 179 | @computed get legacyServices() { |
158 | return this.getLegacyServicesRequest.execute() || {}; | 180 | return this.getLegacyServicesRequest.execute() || {}; |
159 | } | 181 | } |