diff options
Diffstat (limited to 'src')
20 files changed, 360 insertions, 141 deletions
diff --git a/src/assets/images/workspaces/teaser_dark.png b/src/assets/images/workspaces/teaser_dark.png deleted file mode 100644 index 5b6d7334b..000000000 --- a/src/assets/images/workspaces/teaser_dark.png +++ /dev/null | |||
Binary files differ | |||
diff --git a/src/assets/images/workspaces/teaser_light.png b/src/assets/images/workspaces/teaser_light.png deleted file mode 100644 index 635af43fa..000000000 --- a/src/assets/images/workspaces/teaser_light.png +++ /dev/null | |||
Binary files differ | |||
diff --git a/src/components/settings/team/TeamDashboard.js b/src/components/settings/team/TeamDashboard.js index 990ee52e7..51a3f375d 100644 --- a/src/components/settings/team/TeamDashboard.js +++ b/src/components/settings/team/TeamDashboard.js | |||
@@ -5,10 +5,14 @@ import { defineMessages, intlShape } from 'react-intl'; | |||
5 | import ReactTooltip from 'react-tooltip'; | 5 | import ReactTooltip from 'react-tooltip'; |
6 | import injectSheet from 'react-jss'; | 6 | import injectSheet from 'react-jss'; |
7 | 7 | ||
8 | import { Badge } from '@meetfranz/ui'; | ||
8 | import Loader from '../../ui/Loader'; | 9 | import Loader from '../../ui/Loader'; |
9 | import Button from '../../ui/Button'; | 10 | import Button from '../../ui/Button'; |
10 | import Infobox from '../../ui/Infobox'; | 11 | import Infobox from '../../ui/Infobox'; |
11 | import PremiumFeatureContainer from '../../ui/PremiumFeatureContainer'; | 12 | import PremiumFeatureContainer from '../../ui/PremiumFeatureContainer'; |
13 | import globalMessages from '../../../i18n/globalMessages'; | ||
14 | import ActivateTrialButton from '../../ui/ActivateTrialButton'; | ||
15 | import UpgradeButton from '../../ui/UpgradeButton'; | ||
12 | 16 | ||
13 | const messages = defineMessages({ | 17 | const messages = defineMessages({ |
14 | headline: { | 18 | headline: { |
@@ -40,6 +44,7 @@ const messages = defineMessages({ | |||
40 | const styles = { | 44 | const styles = { |
41 | cta: { | 45 | cta: { |
42 | margin: [40, 'auto'], | 46 | margin: [40, 'auto'], |
47 | height: 'auto', | ||
43 | }, | 48 | }, |
44 | container: { | 49 | container: { |
45 | display: 'flex', | 50 | display: 'flex', |
@@ -69,6 +74,17 @@ const styles = { | |||
69 | order: 1, | 74 | order: 1, |
70 | }, | 75 | }, |
71 | }, | 76 | }, |
77 | headline: { | ||
78 | marginBottom: 0, | ||
79 | }, | ||
80 | proRequired: { | ||
81 | margin: [10, 0, 40], | ||
82 | height: 'auto', | ||
83 | }, | ||
84 | buttonContainer: { | ||
85 | display: 'flex', | ||
86 | height: 'auto', | ||
87 | }, | ||
72 | }; | 88 | }; |
73 | 89 | ||
74 | 90 | ||
@@ -79,6 +95,7 @@ export default @injectSheet(styles) @observer class TeamDashboard extends Compon | |||
79 | retryUserInfoRequest: PropTypes.func.isRequired, | 95 | retryUserInfoRequest: PropTypes.func.isRequired, |
80 | openTeamManagement: PropTypes.func.isRequired, | 96 | openTeamManagement: PropTypes.func.isRequired, |
81 | classes: PropTypes.object.isRequired, | 97 | classes: PropTypes.object.isRequired, |
98 | isProUser: PropTypes.bool.isRequired, | ||
82 | }; | 99 | }; |
83 | 100 | ||
84 | static contextTypes = { | 101 | static contextTypes = { |
@@ -91,6 +108,7 @@ export default @injectSheet(styles) @observer class TeamDashboard extends Compon | |||
91 | userInfoRequestFailed, | 108 | userInfoRequestFailed, |
92 | retryUserInfoRequest, | 109 | retryUserInfoRequest, |
93 | openTeamManagement, | 110 | openTeamManagement, |
111 | isProUser, | ||
94 | classes, | 112 | classes, |
95 | } = this.props; | 113 | } = this.props; |
96 | const { intl } = this.context; | 114 | const { intl } = this.context; |
@@ -123,23 +141,35 @@ export default @injectSheet(styles) @observer class TeamDashboard extends Compon | |||
123 | <> | 141 | <> |
124 | {!isLoading && ( | 142 | {!isLoading && ( |
125 | <> | 143 | <> |
126 | <PremiumFeatureContainer> | 144 | <> |
127 | <> | 145 | <h1 className={classes.headline}>{intl.formatMessage(messages.contentHeadline)}</h1> |
128 | <h1>{intl.formatMessage(messages.contentHeadline)}</h1> | 146 | {!isProUser && ( |
129 | <div className={classes.container}> | 147 | <Badge className={classes.proRequired}>{intl.formatMessage(globalMessages.proRequired)}</Badge> |
130 | <div className={classes.content}> | 148 | )} |
131 | <p>{intl.formatMessage(messages.intro)}</p> | 149 | <div className={classes.container}> |
132 | <p>{intl.formatMessage(messages.copy)}</p> | 150 | <div className={classes.content}> |
133 | </div> | 151 | <p>{intl.formatMessage(messages.intro)}</p> |
134 | <img className={classes.image} src="https://cdn.franzinfra.com/announcements/assets/teams.png" alt="Franz for Teams" /> | 152 | <p>{intl.formatMessage(messages.copy)}</p> |
135 | </div> | 153 | </div> |
136 | </> | 154 | <img className={classes.image} src="https://cdn.franzinfra.com/announcements/assets/teams.png" alt="Franz for Teams" /> |
137 | </PremiumFeatureContainer> | 155 | </div> |
138 | <Button | 156 | <div className={classes.buttonContainer}> |
139 | label={intl.formatMessage(messages.manageButton)} | 157 | {!isProUser ? ( |
140 | onClick={openTeamManagement} | 158 | <UpgradeButton |
141 | className={classes.cta} | 159 | className={classes.cta} |
142 | /> | 160 | gaEventInfo={{ category: 'Todos', event: 'upgrade' }} |
161 | requiresPro | ||
162 | short | ||
163 | /> | ||
164 | ) : ( | ||
165 | <Button | ||
166 | label={intl.formatMessage(messages.manageButton)} | ||
167 | onClick={openTeamManagement} | ||
168 | className={classes.cta} | ||
169 | /> | ||
170 | )} | ||
171 | </div> | ||
172 | </> | ||
143 | </> | 173 | </> |
144 | )} | 174 | )} |
145 | </> | 175 | </> |
diff --git a/src/components/ui/UpgradeButton/index.js b/src/components/ui/UpgradeButton/index.js new file mode 100644 index 000000000..4aa494e38 --- /dev/null +++ b/src/components/ui/UpgradeButton/index.js | |||
@@ -0,0 +1,90 @@ | |||
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 | import ActivateTrialButton from '../ActivateTrialButton'; | ||
12 | |||
13 | const messages = defineMessages({ | ||
14 | upgradeToPro: { | ||
15 | id: 'global.upgradeButton.upgradeToPro', | ||
16 | defaultMessage: '!!!Upgrade to Franz Professional', | ||
17 | }, | ||
18 | }); | ||
19 | |||
20 | @inject('stores', 'actions') @observer | ||
21 | class UpgradeButton extends Component { | ||
22 | static propTypes = { | ||
23 | // eslint-disable-next-line | ||
24 | classes: PropTypes.object.isRequired, | ||
25 | className: PropTypes.string, | ||
26 | gaEventInfo: PropTypes.shape({ | ||
27 | category: PropTypes.string.isRequired, | ||
28 | event: PropTypes.string.isRequired, | ||
29 | label: PropTypes.string, | ||
30 | }), | ||
31 | requiresPro: PropTypes.bool, | ||
32 | }; | ||
33 | |||
34 | static defaultProps = { | ||
35 | className: '', | ||
36 | gaEventInfo: null, | ||
37 | requiresPro: false, | ||
38 | } | ||
39 | |||
40 | static contextTypes = { | ||
41 | intl: intlShape, | ||
42 | }; | ||
43 | |||
44 | handleCTAClick() { | ||
45 | const { actions, gaEventInfo } = this.props; | ||
46 | |||
47 | actions.ui.openSettings({ path: 'user' }); | ||
48 | if (gaEventInfo) { | ||
49 | const { category, event } = gaEventInfo; | ||
50 | gaEvent(category, event, 'Upgrade Account'); | ||
51 | } | ||
52 | } | ||
53 | |||
54 | render() { | ||
55 | const { stores, requiresPro } = this.props; | ||
56 | const { intl } = this.context; | ||
57 | |||
58 | const { isPremium, isPersonal } = stores.user; | ||
59 | |||
60 | if (isPremium && isPersonal && requiresPro) { | ||
61 | return ( | ||
62 | <Button | ||
63 | label={intl.formatMessage(messages.upgradeToPro)} | ||
64 | onClick={this.handleCTAClick.bind(this)} | ||
65 | className={this.props.className} | ||
66 | buttonType="inverted" | ||
67 | /> | ||
68 | ); | ||
69 | } | ||
70 | |||
71 | if (!isPremium) { | ||
72 | return <ActivateTrialButton {...this.props} />; | ||
73 | } | ||
74 | |||
75 | return null; | ||
76 | } | ||
77 | } | ||
78 | |||
79 | export default UpgradeButton; | ||
80 | |||
81 | UpgradeButton.wrappedComponent.propTypes = { | ||
82 | stores: PropTypes.shape({ | ||
83 | user: PropTypes.instanceOf(UserStore).isRequired, | ||
84 | }).isRequired, | ||
85 | actions: PropTypes.shape({ | ||
86 | ui: PropTypes.shape({ | ||
87 | openSettings: PropTypes.func.isRequired, | ||
88 | }).isRequired, | ||
89 | }).isRequired, | ||
90 | }; | ||
diff --git a/src/config.js b/src/config.js index fba739ddd..78a92d948 100644 --- a/src/config.js +++ b/src/config.js | |||
@@ -20,7 +20,7 @@ export const LIVE_WS_API = 'wss://api.franzinfra.com'; | |||
20 | 20 | ||
21 | export const LOCAL_API_WEBSITE = 'http://localhost:3333'; | 21 | export const LOCAL_API_WEBSITE = 'http://localhost:3333'; |
22 | // export const DEV_API_WEBSITE = 'https://meetfranz.com';t | 22 | // export const DEV_API_WEBSITE = 'https://meetfranz.com';t |
23 | export const DEV_API_WEBSITE = 'http://hash-3ac3ccd2472269cf585c58a4f6973d86f3c9e7bd.franzstaging.com/'; // TODO: revert me | 23 | export const DEV_API_WEBSITE = 'http://hash-58883791519ef6288c952316bdce7fb462283893.franzstaging.com/'; // TODO: revert me |
24 | export const LIVE_API_WEBSITE = 'https://meetfranz.com'; | 24 | export const LIVE_API_WEBSITE = 'https://meetfranz.com'; |
25 | 25 | ||
26 | export const STATS_API = 'https://stats.franzinfra.com'; | 26 | export const STATS_API = 'https://stats.franzinfra.com'; |
diff --git a/src/containers/settings/TeamScreen.js b/src/containers/settings/TeamScreen.js index b7b1b78cb..f600c9947 100644 --- a/src/containers/settings/TeamScreen.js +++ b/src/containers/settings/TeamScreen.js | |||
@@ -30,6 +30,7 @@ export default @inject('stores', 'actions') @observer class TeamScreen extends C | |||
30 | userInfoRequestFailed={user.getUserInfoRequest.wasExecuted && user.getUserInfoRequest.isError} | 30 | userInfoRequestFailed={user.getUserInfoRequest.wasExecuted && user.getUserInfoRequest.isError} |
31 | retryUserInfoRequest={() => this.reloadData()} | 31 | retryUserInfoRequest={() => this.reloadData()} |
32 | openTeamManagement={() => this.handleWebsiteLink('/user/team')} | 32 | openTeamManagement={() => this.handleWebsiteLink('/user/team')} |
33 | isProUser={user.isPro} | ||
33 | /> | 34 | /> |
34 | </ErrorBoundary> | 35 | </ErrorBoundary> |
35 | ); | 36 | ); |
diff --git a/src/containers/subscription/SubscriptionFormScreen.js b/src/containers/subscription/SubscriptionFormScreen.js index e9e457084..726b10628 100644 --- a/src/containers/subscription/SubscriptionFormScreen.js +++ b/src/containers/subscription/SubscriptionFormScreen.js | |||
@@ -19,7 +19,7 @@ export default @inject('stores', 'actions') @observer class SubscriptionFormScre | |||
19 | features, | 19 | features, |
20 | } = stores; | 20 | } = stores; |
21 | 21 | ||
22 | let hostedPageURL = !user.data.hadSubscription ? features.features.planSelectionURL : features.features.subscribeURL; | 22 | let hostedPageURL = features.features.planSelectionURL; |
23 | hostedPageURL = user.getAuthURL(hostedPageURL); | 23 | hostedPageURL = user.getAuthURL(hostedPageURL); |
24 | 24 | ||
25 | actions.app.openExternalUrl({ url: hostedPageURL }); | 25 | actions.app.openExternalUrl({ url: hostedPageURL }); |
diff --git a/src/environment.js b/src/environment.js index 707449e09..2c247618f 100644 --- a/src/environment.js +++ b/src/environment.js | |||
@@ -36,9 +36,11 @@ let wsApi; | |||
36 | let web; | 36 | let web; |
37 | let todos; | 37 | let todos; |
38 | if (!isDevMode || (isDevMode && useLiveAPI)) { | 38 | if (!isDevMode || (isDevMode && useLiveAPI)) { |
39 | api = LIVE_API; | 39 | // api = LIVE_API; |
40 | api = DEV_API; | ||
40 | wsApi = LIVE_WS_API; | 41 | wsApi = LIVE_WS_API; |
41 | web = LIVE_API_WEBSITE; | 42 | // web = LIVE_API_WEBSITE; |
43 | web = DEV_API_WEBSITE; | ||
42 | todos = PRODUCTION_TODOS_FRONTEND_URL; | 44 | todos = PRODUCTION_TODOS_FRONTEND_URL; |
43 | } else if (isDevMode && useLocalAPI) { | 45 | } else if (isDevMode && useLocalAPI) { |
44 | api = LOCAL_API; | 46 | api = LOCAL_API; |
diff --git a/src/features/todos/components/TodosWebview.js b/src/features/todos/components/TodosWebview.js index 9a50f7e8d..fa530daed 100644 --- a/src/features/todos/components/TodosWebview.js +++ b/src/features/todos/components/TodosWebview.js | |||
@@ -9,7 +9,7 @@ import { defineMessages, intlShape } from 'react-intl'; | |||
9 | import { mdiChevronRight, mdiCheckAll } from '@mdi/js'; | 9 | import { mdiChevronRight, mdiCheckAll } from '@mdi/js'; |
10 | import * as environment from '../../../environment'; | 10 | import * as environment from '../../../environment'; |
11 | import Appear from '../../../components/ui/effects/Appear'; | 11 | import Appear from '../../../components/ui/effects/Appear'; |
12 | import ActivateTrialButton from '../../../components/ui/ActivateTrialButton'; | 12 | import UpgradeButton from '../../../components/ui/UpgradeButton'; |
13 | 13 | ||
14 | const OPEN_TODOS_BUTTON_SIZE = 45; | 14 | const OPEN_TODOS_BUTTON_SIZE = 45; |
15 | const CLOSE_TODOS_BUTTON_SIZE = 35; | 15 | const CLOSE_TODOS_BUTTON_SIZE = 35; |
@@ -116,7 +116,7 @@ const styles = theme => ({ | |||
116 | alignItems: 'center', | 116 | alignItems: 'center', |
117 | width: '80%', | 117 | width: '80%', |
118 | maxWidth: 300, | 118 | maxWidth: 300, |
119 | margin: [-50, 'auto', 0], | 119 | margin: [0, 'auto'], |
120 | textAlign: 'center', | 120 | textAlign: 'center', |
121 | }, | 121 | }, |
122 | premiumIcon: { | 122 | premiumIcon: { |
@@ -286,10 +286,10 @@ class TodosWebview extends Component { | |||
286 | ) : ( | 286 | ) : ( |
287 | <Appear> | 287 | <Appear> |
288 | <div className={classes.premiumContainer}> | 288 | <div className={classes.premiumContainer}> |
289 | <Icon icon={mdiCheckAll} className={classes.premiumIcon} size={5} /> | 289 | <Icon icon={mdiCheckAll} className={classes.premiumIcon} size={4} /> |
290 | <p>{intl.formatMessage(messages.premiumInfo)}</p> | 290 | <p>{intl.formatMessage(messages.premiumInfo)}</p> |
291 | <p>{intl.formatMessage(messages.rolloutInfo)}</p> | 291 | <p>{intl.formatMessage(messages.rolloutInfo)}</p> |
292 | <ActivateTrialButton | 292 | <UpgradeButton |
293 | className={classes.premiumCTA} | 293 | className={classes.premiumCTA} |
294 | gaEventInfo={{ category: 'Todos', event: 'upgrade' }} | 294 | gaEventInfo={{ category: 'Todos', event: 'upgrade' }} |
295 | short | 295 | short |
diff --git a/src/features/todos/store.js b/src/features/todos/store.js index 56e117c6c..5c6abff4c 100644 --- a/src/features/todos/store.js +++ b/src/features/todos/store.js | |||
@@ -30,7 +30,7 @@ export default class TodoStore extends FeatureStore { | |||
30 | } | 30 | } |
31 | 31 | ||
32 | @computed get isTodosPanelVisible() { | 32 | @computed get isTodosPanelVisible() { |
33 | if (this.stores.services.all.length === 0 || delayAppState.isDelayAppScreenVisible) return false; | 33 | if (delayAppState.isDelayAppScreenVisible) return false; |
34 | if (this.settings.isTodosPanelVisible === undefined) return DEFAULT_TODOS_VISIBLE; | 34 | if (this.settings.isTodosPanelVisible === undefined) return DEFAULT_TODOS_VISIBLE; |
35 | 35 | ||
36 | return this.settings.isTodosPanelVisible; | 36 | return this.settings.isTodosPanelVisible; |
@@ -61,6 +61,7 @@ export default class TodoStore extends FeatureStore { | |||
61 | 61 | ||
62 | this._allReactions = createReactions([ | 62 | this._allReactions = createReactions([ |
63 | this._setFeatureEnabledReaction, | 63 | this._setFeatureEnabledReaction, |
64 | this._firstLaunchReaction, | ||
64 | ]); | 65 | ]); |
65 | 66 | ||
66 | this._registerReactions(this._allReactions); | 67 | this._registerReactions(this._allReactions); |
@@ -146,4 +147,19 @@ export default class TodoStore extends FeatureStore { | |||
146 | 147 | ||
147 | this.isFeatureEnabled = isTodosEnabled; | 148 | this.isFeatureEnabled = isTodosEnabled; |
148 | }; | 149 | }; |
150 | |||
151 | _firstLaunchReaction = () => { | ||
152 | const { stats } = this.stores.settings.all; | ||
153 | |||
154 | // Hide todos layer on first app start but show on second | ||
155 | if (stats.appStarts <= 1) { | ||
156 | this._updateSettings({ | ||
157 | isTodosPanelVisible: false, | ||
158 | }); | ||
159 | } else if (stats.appStarts <= 2) { | ||
160 | this._updateSettings({ | ||
161 | isTodosPanelVisible: true, | ||
162 | }); | ||
163 | } | ||
164 | }; | ||
149 | } | 165 | } |
diff --git a/src/features/workspaces/components/WorkspacesDashboard.js b/src/features/workspaces/components/WorkspacesDashboard.js index 059a681de..fc636dd95 100644 --- a/src/features/workspaces/components/WorkspacesDashboard.js +++ b/src/features/workspaces/components/WorkspacesDashboard.js | |||
@@ -3,7 +3,7 @@ import PropTypes from 'prop-types'; | |||
3 | import { observer, PropTypes as MobxPropTypes, inject } 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, Badge } from '@meetfranz/ui'; |
7 | 7 | ||
8 | import Loader from '../../../components/ui/Loader'; | 8 | import Loader from '../../../components/ui/Loader'; |
9 | import WorkspaceItem from './WorkspaceItem'; | 9 | import WorkspaceItem from './WorkspaceItem'; |
@@ -11,9 +11,9 @@ import CreateWorkspaceForm from './CreateWorkspaceForm'; | |||
11 | import Request from '../../../stores/lib/Request'; | 11 | 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'; | ||
15 | import UIStore from '../../../stores/UIStore'; | 14 | import UIStore from '../../../stores/UIStore'; |
16 | import ActivateTrialButton from '../../../components/ui/ActivateTrialButton'; | 15 | import globalMessages from '../../../i18n/globalMessages'; |
16 | import UpgradeButton from '../../../components/ui/UpgradeButton'; | ||
17 | 17 | ||
18 | const messages = defineMessages({ | 18 | const messages = defineMessages({ |
19 | headline: { | 19 | headline: { |
@@ -64,23 +64,24 @@ const styles = theme => ({ | |||
64 | height: 'auto', | 64 | height: 'auto', |
65 | }, | 65 | }, |
66 | premiumAnnouncement: { | 66 | premiumAnnouncement: { |
67 | padding: 20, | ||
68 | // backgroundColor: '#3498db', | ||
69 | marginLeft: -20, | ||
70 | marginBottom: 40, | ||
71 | paddingBottom: 40, | ||
72 | height: 'auto', | 67 | height: 'auto', |
68 | }, | ||
69 | premiumAnnouncementContainer: { | ||
73 | display: 'flex', | 70 | display: 'flex', |
74 | borderBottom: [1, 'solid', theme.inputBackground], | 71 | }, |
72 | announcementHeadline: { | ||
73 | marginBottom: 0, | ||
75 | }, | 74 | }, |
76 | teaserImage: { | 75 | teaserImage: { |
77 | width: 200, | 76 | width: 250, |
78 | height: '100%', | 77 | margin: [-8, 0, 0, 20], |
79 | float: 'left', | 78 | alignSelf: 'center', |
80 | margin: [-8, 0, 0, -20], | ||
81 | }, | 79 | }, |
82 | upgradeCTA: { | 80 | upgradeCTA: { |
83 | marginTop: 20, | 81 | margin: [40, 'auto'], |
82 | }, | ||
83 | proRequired: { | ||
84 | margin: [10, 0, 40], | ||
84 | }, | 85 | }, |
85 | }); | 86 | }); |
86 | 87 | ||
@@ -95,6 +96,8 @@ class WorkspacesDashboard extends Component { | |||
95 | onCreateWorkspaceSubmit: PropTypes.func.isRequired, | 96 | onCreateWorkspaceSubmit: PropTypes.func.isRequired, |
96 | onWorkspaceClick: PropTypes.func.isRequired, | 97 | onWorkspaceClick: PropTypes.func.isRequired, |
97 | workspaces: MobxPropTypes.arrayOrObservableArray.isRequired, | 98 | workspaces: MobxPropTypes.arrayOrObservableArray.isRequired, |
99 | isPersonalUser: PropTypes.bool.isRequired, | ||
100 | onUpgradeAccount: PropTypes.func.isRequired, | ||
98 | }; | 101 | }; |
99 | 102 | ||
100 | static contextTypes = { | 103 | static contextTypes = { |
@@ -152,76 +155,80 @@ class WorkspacesDashboard extends Component { | |||
152 | 155 | ||
153 | {workspaceStore.isPremiumUpgradeRequired && ( | 156 | {workspaceStore.isPremiumUpgradeRequired && ( |
154 | <div className={classes.premiumAnnouncement}> | 157 | <div className={classes.premiumAnnouncement}> |
155 | <img src={`./assets/images/workspaces/teaser_${this.props.stores.ui.isDarkThemeActive ? 'dark' : 'light'}.png`} className={classes.teaserImage} alt="" /> | 158 | |
156 | <div> | 159 | <h1 className={classes.announcementHeadline}>{intl.formatMessage(messages.workspaceFeatureHeadline)}</h1> |
157 | <h2>{intl.formatMessage(messages.workspaceFeatureHeadline)}</h2> | 160 | <Badge className={classes.proRequired}>{intl.formatMessage(globalMessages.proRequired)}</Badge> |
158 | <p>{intl.formatMessage(messages.workspaceFeatureInfo)}</p> | 161 | <div className={classes.premiumAnnouncementContainer}> |
159 | <ActivateTrialButton | 162 | <div className={classes.premiumAnnouncementContent}> |
160 | className={classes.upgradeCTA} | 163 | <p>{intl.formatMessage(messages.workspaceFeatureInfo)}</p> |
161 | gaEventInfo={{ category: 'Workspaces', event: 'upgrade' }} | 164 | <UpgradeButton |
162 | short | 165 | className={classes.upgradeCTA} |
163 | /> | 166 | gaEventInfo={{ category: 'Workspaces', event: 'upgrade' }} |
167 | short | ||
168 | requiresPro | ||
169 | /> | ||
170 | </div> | ||
171 | <img src={`https://cdn.franzinfra.com/announcements/assets/workspaces_${this.props.stores.ui.isDarkThemeActive ? 'dark' : 'light'}.png`} className={classes.teaserImage} alt="" /> | ||
164 | </div> | 172 | </div> |
165 | </div> | 173 | </div> |
166 | )} | 174 | )} |
167 | 175 | ||
168 | <PremiumFeatureContainer | 176 | {!workspaceStore.isPremiumUpgradeRequired && ( |
169 | condition={() => workspaceStore.isPremiumUpgradeRequired} | 177 | <> |
170 | gaEventInfo={{ category: 'User', event: 'upgrade', label: 'workspaces' }} | 178 | {/* ===== Create workspace form ===== */} |
171 | > | 179 | <div className={classes.createForm}> |
172 | {/* ===== Create workspace form ===== */} | 180 | <CreateWorkspaceForm |
173 | <div className={classes.createForm}> | 181 | isSubmitting={createWorkspaceRequest.isExecuting} |
174 | <CreateWorkspaceForm | 182 | onSubmit={onCreateWorkspaceSubmit} |
175 | isSubmitting={createWorkspaceRequest.isExecuting} | 183 | /> |
176 | onSubmit={onCreateWorkspaceSubmit} | 184 | </div> |
177 | /> | 185 | {getUserWorkspacesRequest.isExecuting ? ( |
178 | </div> | 186 | <Loader /> |
179 | {getUserWorkspacesRequest.isExecuting ? ( | 187 | ) : ( |
180 | <Loader /> | 188 | <Fragment> |
181 | ) : ( | 189 | {/* ===== Workspace could not be loaded error ===== */} |
182 | <Fragment> | 190 | {getUserWorkspacesRequest.error ? ( |
183 | {/* ===== Workspace could not be loaded error ===== */} | 191 | <Infobox |
184 | {getUserWorkspacesRequest.error ? ( | 192 | icon="alert" |
185 | <Infobox | 193 | type="danger" |
186 | icon="alert" | 194 | ctaLabel={intl.formatMessage(messages.tryReloadWorkspaces)} |
187 | type="danger" | 195 | ctaLoading={getUserWorkspacesRequest.isExecuting} |
188 | ctaLabel={intl.formatMessage(messages.tryReloadWorkspaces)} | 196 | ctaOnClick={getUserWorkspacesRequest.retry} |
189 | ctaLoading={getUserWorkspacesRequest.isExecuting} | 197 | > |
190 | ctaOnClick={getUserWorkspacesRequest.retry} | 198 | {intl.formatMessage(messages.workspacesRequestFailed)} |
191 | > | 199 | </Infobox> |
192 | {intl.formatMessage(messages.workspacesRequestFailed)} | 200 | ) : ( |
193 | </Infobox> | 201 | <Fragment> |
194 | ) : ( | 202 | {workspaces.length === 0 ? ( |
195 | <Fragment> | 203 | <div className="align-middle settings__empty-state"> |
196 | {workspaces.length === 0 ? ( | 204 | {/* ===== Workspaces empty state ===== */} |
197 | <div className="align-middle settings__empty-state"> | 205 | <p className="settings__empty-text"> |
198 | {/* ===== Workspaces empty state ===== */} | 206 | <span className="emoji"> |
199 | <p className="settings__empty-text"> | 207 | <img src="./assets/images/emoji/sad.png" alt="" /> |
200 | <span className="emoji"> | 208 | </span> |
201 | <img src="./assets/images/emoji/sad.png" alt="" /> | 209 | {intl.formatMessage(messages.noServicesAdded)} |
202 | </span> | 210 | </p> |
203 | {intl.formatMessage(messages.noServicesAdded)} | 211 | </div> |
204 | </p> | 212 | ) : ( |
205 | </div> | 213 | <table className={classes.table}> |
206 | ) : ( | 214 | {/* ===== Workspaces list ===== */} |
207 | <table className={classes.table}> | 215 | <tbody> |
208 | {/* ===== Workspaces list ===== */} | 216 | {workspaces.map(workspace => ( |
209 | <tbody> | 217 | <WorkspaceItem |
210 | {workspaces.map(workspace => ( | 218 | key={workspace.id} |
211 | <WorkspaceItem | 219 | workspace={workspace} |
212 | key={workspace.id} | 220 | onItemClick={w => onWorkspaceClick(w)} |
213 | workspace={workspace} | 221 | /> |
214 | onItemClick={w => onWorkspaceClick(w)} | 222 | ))} |
215 | /> | 223 | </tbody> |
216 | ))} | 224 | </table> |
217 | </tbody> | 225 | )} |
218 | </table> | 226 | </Fragment> |
219 | )} | 227 | )} |
220 | </Fragment> | 228 | </Fragment> |
221 | )} | 229 | )} |
222 | </Fragment> | 230 | </> |
223 | )} | 231 | )} |
224 | </PremiumFeatureContainer> | ||
225 | </div> | 232 | </div> |
226 | </div> | 233 | </div> |
227 | ); | 234 | ); |
diff --git a/src/features/workspaces/containers/WorkspacesScreen.js b/src/features/workspaces/containers/WorkspacesScreen.js index 2ab565fa1..5fbb0c31d 100644 --- a/src/features/workspaces/containers/WorkspacesScreen.js +++ b/src/features/workspaces/containers/WorkspacesScreen.js | |||
@@ -10,29 +10,38 @@ import { | |||
10 | getUserWorkspacesRequest, | 10 | getUserWorkspacesRequest, |
11 | updateWorkspaceRequest, | 11 | updateWorkspaceRequest, |
12 | } from '../api'; | 12 | } from '../api'; |
13 | import UserStore from '../../../stores/UserStore'; | ||
13 | 14 | ||
14 | @inject('actions') @observer | 15 | @inject('stores', 'actions') @observer |
15 | class WorkspacesScreen extends Component { | 16 | class WorkspacesScreen extends Component { |
16 | static propTypes = { | 17 | static propTypes = { |
18 | stores: PropTypes.shape({ | ||
19 | user: PropTypes.instanceOf(UserStore), | ||
20 | }).isRequired, | ||
17 | actions: PropTypes.shape({ | 21 | actions: PropTypes.shape({ |
18 | workspace: PropTypes.shape({ | 22 | workspace: PropTypes.shape({ |
19 | edit: PropTypes.func.isRequired, | 23 | edit: PropTypes.func.isRequired, |
20 | }), | 24 | }), |
25 | ui: PropTypes.shape({ | ||
26 | openSettings: PropTypes.func.isRequired, | ||
27 | }), | ||
21 | }).isRequired, | 28 | }).isRequired, |
22 | }; | 29 | }; |
23 | 30 | ||
24 | render() { | 31 | render() { |
25 | const { actions } = this.props; | 32 | const { stores, actions } = this.props; |
26 | return ( | 33 | return ( |
27 | <ErrorBoundary> | 34 | <ErrorBoundary> |
28 | <WorkspacesDashboard | 35 | <WorkspacesDashboard |
29 | workspaces={workspaceStore.workspaces} | 36 | workspaces={workspaceStore.workspaces} |
37 | isPersonalUser={stores.user.isPersonal} | ||
30 | getUserWorkspacesRequest={getUserWorkspacesRequest} | 38 | getUserWorkspacesRequest={getUserWorkspacesRequest} |
31 | createWorkspaceRequest={createWorkspaceRequest} | 39 | createWorkspaceRequest={createWorkspaceRequest} |
32 | deleteWorkspaceRequest={deleteWorkspaceRequest} | 40 | deleteWorkspaceRequest={deleteWorkspaceRequest} |
33 | updateWorkspaceRequest={updateWorkspaceRequest} | 41 | updateWorkspaceRequest={updateWorkspaceRequest} |
34 | onCreateWorkspaceSubmit={data => actions.workspaces.create(data)} | 42 | onCreateWorkspaceSubmit={data => actions.workspaces.create(data)} |
35 | onWorkspaceClick={w => actions.workspaces.edit({ workspace: w })} | 43 | onWorkspaceClick={w => actions.workspaces.edit({ workspace: w })} |
44 | onUpgradeAccount={() => actions.ui.openSettings({ path: 'user' })} | ||
36 | /> | 45 | /> |
37 | </ErrorBoundary> | 46 | </ErrorBoundary> |
38 | ); | 47 | ); |
diff --git a/src/i18n/globalMessages.js b/src/i18n/globalMessages.js index 1b5ece223..af8479c59 100644 --- a/src/i18n/globalMessages.js +++ b/src/i18n/globalMessages.js | |||
@@ -25,4 +25,8 @@ export default defineMessages({ | |||
25 | id: 'global.spellchecking.autodetect.short', | 25 | id: 'global.spellchecking.autodetect.short', |
26 | defaultMessage: '!!!Automatic', | 26 | defaultMessage: '!!!Automatic', |
27 | }, | 27 | }, |
28 | proRequired: { | ||
29 | id: 'global.franzProRequired', | ||
30 | defaultMessage: '!!!Franz Professional Required', | ||
31 | }, | ||
28 | }); | 32 | }); |
diff --git a/src/i18n/locales/defaultMessages.json b/src/i18n/locales/defaultMessages.json index 367184c01..b03512fe1 100644 --- a/src/i18n/locales/defaultMessages.json +++ b/src/i18n/locales/defaultMessages.json | |||
@@ -2530,78 +2530,78 @@ | |||
2530 | "defaultMessage": "!!!Team", | 2530 | "defaultMessage": "!!!Team", |
2531 | "end": { | 2531 | "end": { |
2532 | "column": 3, | 2532 | "column": 3, |
2533 | "line": 17 | 2533 | "line": 21 |
2534 | }, | 2534 | }, |
2535 | "file": "src/components/settings/team/TeamDashboard.js", | 2535 | "file": "src/components/settings/team/TeamDashboard.js", |
2536 | "id": "settings.team.headline", | 2536 | "id": "settings.team.headline", |
2537 | "start": { | 2537 | "start": { |
2538 | "column": 12, | 2538 | "column": 12, |
2539 | "line": 14 | 2539 | "line": 18 |
2540 | } | 2540 | } |
2541 | }, | 2541 | }, |
2542 | { | 2542 | { |
2543 | "defaultMessage": "!!!Franz for Teams", | 2543 | "defaultMessage": "!!!Franz for Teams", |
2544 | "end": { | 2544 | "end": { |
2545 | "column": 3, | 2545 | "column": 3, |
2546 | "line": 21 | 2546 | "line": 25 |
2547 | }, | 2547 | }, |
2548 | "file": "src/components/settings/team/TeamDashboard.js", | 2548 | "file": "src/components/settings/team/TeamDashboard.js", |
2549 | "id": "settings.team.contentHeadline", | 2549 | "id": "settings.team.contentHeadline", |
2550 | "start": { | 2550 | "start": { |
2551 | "column": 19, | 2551 | "column": 19, |
2552 | "line": 18 | 2552 | "line": 22 |
2553 | } | 2553 | } |
2554 | }, | 2554 | }, |
2555 | { | 2555 | { |
2556 | "defaultMessage": "!!!You and your team use Franz? You can now manage Premium subscriptions for as many colleagues, friends or family members as you want, all from within one account.", | 2556 | "defaultMessage": "!!!You and your team use Franz? You can now manage Premium subscriptions for as many colleagues, friends or family members as you want, all from within one account.", |
2557 | "end": { | 2557 | "end": { |
2558 | "column": 3, | 2558 | "column": 3, |
2559 | "line": 25 | 2559 | "line": 29 |
2560 | }, | 2560 | }, |
2561 | "file": "src/components/settings/team/TeamDashboard.js", | 2561 | "file": "src/components/settings/team/TeamDashboard.js", |
2562 | "id": "settings.team.intro", | 2562 | "id": "settings.team.intro", |
2563 | "start": { | 2563 | "start": { |
2564 | "column": 9, | 2564 | "column": 9, |
2565 | "line": 22 | 2565 | "line": 26 |
2566 | } | 2566 | } |
2567 | }, | 2567 | }, |
2568 | { | 2568 | { |
2569 | "defaultMessage": "!!!Franz for Teams gives you the option to invite co-workers to your team by sending them email invitations and manage their subscriptions in your account’s preferences. Don’t waste time setting up subscriptions for every team member individually, forget about multiple invoices and different billing cycles - one team to rule them all!", | 2569 | "defaultMessage": "!!!Franz for Teams gives you the option to invite co-workers to your team by sending them email invitations and manage their subscriptions in your account’s preferences. Don’t waste time setting up subscriptions for every team member individually, forget about multiple invoices and different billing cycles - one team to rule them all!", |
2570 | "end": { | 2570 | "end": { |
2571 | "column": 3, | 2571 | "column": 3, |
2572 | "line": 29 | 2572 | "line": 33 |
2573 | }, | 2573 | }, |
2574 | "file": "src/components/settings/team/TeamDashboard.js", | 2574 | "file": "src/components/settings/team/TeamDashboard.js", |
2575 | "id": "settings.team.copy", | 2575 | "id": "settings.team.copy", |
2576 | "start": { | 2576 | "start": { |
2577 | "column": 8, | 2577 | "column": 8, |
2578 | "line": 26 | 2578 | "line": 30 |
2579 | } | 2579 | } |
2580 | }, | 2580 | }, |
2581 | { | 2581 | { |
2582 | "defaultMessage": "!!!Manage your Team on meetfranz.com", | 2582 | "defaultMessage": "!!!Manage your Team on meetfranz.com", |
2583 | "end": { | 2583 | "end": { |
2584 | "column": 3, | 2584 | "column": 3, |
2585 | "line": 33 | 2585 | "line": 37 |
2586 | }, | 2586 | }, |
2587 | "file": "src/components/settings/team/TeamDashboard.js", | 2587 | "file": "src/components/settings/team/TeamDashboard.js", |
2588 | "id": "settings.team.manageAction", | 2588 | "id": "settings.team.manageAction", |
2589 | "start": { | 2589 | "start": { |
2590 | "column": 16, | 2590 | "column": 16, |
2591 | "line": 30 | 2591 | "line": 34 |
2592 | } | 2592 | } |
2593 | }, | 2593 | }, |
2594 | { | 2594 | { |
2595 | "defaultMessage": "!!!Upgrade your Account", | 2595 | "defaultMessage": "!!!Upgrade your Account", |
2596 | "end": { | 2596 | "end": { |
2597 | "column": 3, | 2597 | "column": 3, |
2598 | "line": 37 | 2598 | "line": 41 |
2599 | }, | 2599 | }, |
2600 | "file": "src/components/settings/team/TeamDashboard.js", | 2600 | "file": "src/components/settings/team/TeamDashboard.js", |
2601 | "id": "settings.team.upgradeAction", | 2601 | "id": "settings.team.upgradeAction", |
2602 | "start": { | 2602 | "start": { |
2603 | "column": 17, | 2603 | "column": 17, |
2604 | "line": 34 | 2604 | "line": 38 |
2605 | } | 2605 | } |
2606 | } | 2606 | } |
2607 | ], | 2607 | ], |
@@ -3105,6 +3105,24 @@ | |||
3105 | { | 3105 | { |
3106 | "descriptors": [ | 3106 | "descriptors": [ |
3107 | { | 3107 | { |
3108 | "defaultMessage": "!!!Upgrade to Franz Professional", | ||
3109 | "end": { | ||
3110 | "column": 3, | ||
3111 | "line": 17 | ||
3112 | }, | ||
3113 | "file": "src/components/ui/UpgradeButton/index.js", | ||
3114 | "id": "global.upgradeButton.upgradeToPro", | ||
3115 | "start": { | ||
3116 | "column": 16, | ||
3117 | "line": 14 | ||
3118 | } | ||
3119 | } | ||
3120 | ], | ||
3121 | "path": "src/components/ui/UpgradeButton/index.json" | ||
3122 | }, | ||
3123 | { | ||
3124 | "descriptors": [ | ||
3125 | { | ||
3108 | "defaultMessage": "!!!Loading", | 3126 | "defaultMessage": "!!!Loading", |
3109 | "end": { | 3127 | "end": { |
3110 | "column": 3, | 3128 | "column": 3, |
@@ -3873,39 +3891,39 @@ | |||
3873 | "defaultMessage": "!!!The Franz Todos Preview is currently only available for Franz Premium accounts.", | 3891 | "defaultMessage": "!!!The Franz Todos Preview is currently only available for Franz Premium accounts.", |
3874 | "end": { | 3892 | "end": { |
3875 | "column": 3, | 3893 | "column": 3, |
3876 | "line": 22 | 3894 | "line": 21 |
3877 | }, | 3895 | }, |
3878 | "file": "src/features/todos/components/TodosWebview.js", | 3896 | "file": "src/features/todos/components/TodosWebview.js", |
3879 | "id": "feature.todos.premium.info", | 3897 | "id": "feature.todos.premium.info", |
3880 | "start": { | 3898 | "start": { |
3881 | "column": 15, | 3899 | "column": 15, |
3882 | "line": 19 | 3900 | "line": 18 |
3883 | } | 3901 | } |
3884 | }, | 3902 | }, |
3885 | { | 3903 | { |
3886 | "defaultMessage": "!!!Upgrade Account", | 3904 | "defaultMessage": "!!!Upgrade Account", |
3887 | "end": { | 3905 | "end": { |
3888 | "column": 3, | 3906 | "column": 3, |
3889 | "line": 26 | 3907 | "line": 25 |
3890 | }, | 3908 | }, |
3891 | "file": "src/features/todos/components/TodosWebview.js", | 3909 | "file": "src/features/todos/components/TodosWebview.js", |
3892 | "id": "feature.todos.premium.upgrade", | 3910 | "id": "feature.todos.premium.upgrade", |
3893 | "start": { | 3911 | "start": { |
3894 | "column": 14, | 3912 | "column": 14, |
3895 | "line": 23 | 3913 | "line": 22 |
3896 | } | 3914 | } |
3897 | }, | 3915 | }, |
3898 | { | 3916 | { |
3899 | "defaultMessage": "!!!Franz Todos will be available to everyone soon.", | 3917 | "defaultMessage": "!!!Franz Todos will be available to everyone soon.", |
3900 | "end": { | 3918 | "end": { |
3901 | "column": 3, | 3919 | "column": 3, |
3902 | "line": 30 | 3920 | "line": 29 |
3903 | }, | 3921 | }, |
3904 | "file": "src/features/todos/components/TodosWebview.js", | 3922 | "file": "src/features/todos/components/TodosWebview.js", |
3905 | "id": "feature.todos.premium.rollout", | 3923 | "id": "feature.todos.premium.rollout", |
3906 | "start": { | 3924 | "start": { |
3907 | "column": 15, | 3925 | "column": 15, |
3908 | "line": 27 | 3926 | "line": 26 |
3909 | } | 3927 | } |
3910 | } | 3928 | } |
3911 | ], | 3929 | ], |
@@ -4594,6 +4612,19 @@ | |||
4594 | "column": 39, | 4612 | "column": 39, |
4595 | "line": 24 | 4613 | "line": 24 |
4596 | } | 4614 | } |
4615 | }, | ||
4616 | { | ||
4617 | "defaultMessage": "!!!Franz Professional Required", | ||
4618 | "end": { | ||
4619 | "column": 3, | ||
4620 | "line": 31 | ||
4621 | }, | ||
4622 | "file": "src/i18n/globalMessages.js", | ||
4623 | "id": "global.franzProRequired", | ||
4624 | "start": { | ||
4625 | "column": 15, | ||
4626 | "line": 28 | ||
4627 | } | ||
4597 | } | 4628 | } |
4598 | ], | 4629 | ], |
4599 | "path": "src/i18n/globalMessages.json" | 4630 | "path": "src/i18n/globalMessages.json" |
diff --git a/src/i18n/locales/en-US.json b/src/i18n/locales/en-US.json index f11d5ca91..0fe1da81e 100644 --- a/src/i18n/locales/en-US.json +++ b/src/i18n/locales/en-US.json | |||
@@ -21,11 +21,13 @@ | |||
21 | "feature.todos.premium.rollout": "Franz Todos will be available to everyone soon.", | 21 | "feature.todos.premium.rollout": "Franz Todos will be available to everyone soon.", |
22 | "feature.todos.premium.upgrade": "Upgrade Account", | 22 | "feature.todos.premium.upgrade": "Upgrade Account", |
23 | "global.api.unhealthy": "Can't connect to Franz online services", | 23 | "global.api.unhealthy": "Can't connect to Franz online services", |
24 | "global.franzProRequired": "Franz Professional Required", | ||
24 | "global.notConnectedToTheInternet": "You are not connected to the internet.", | 25 | "global.notConnectedToTheInternet": "You are not connected to the internet.", |
25 | "global.spellchecker.useDefault": "Use System Default ({default})", | 26 | "global.spellchecker.useDefault": "Use System Default ({default})", |
26 | "global.spellchecking.autodetect": "Detect language automatically", | 27 | "global.spellchecking.autodetect": "Detect language automatically", |
27 | "global.spellchecking.autodetect.short": "Automatic", | 28 | "global.spellchecking.autodetect.short": "Automatic", |
28 | "global.spellchecking.language": "Spell checking language", | 29 | "global.spellchecking.language": "Spell checking language", |
30 | "global.upgradeButton.upgradeToPro": "Upgrade to Franz Professional", | ||
29 | "import.headline": "Import your Franz 4 services", | 31 | "import.headline": "Import your Franz 4 services", |
30 | "import.notSupportedHeadline": "Services not yet supported in Franz 5", | 32 | "import.notSupportedHeadline": "Services not yet supported in Franz 5", |
31 | "import.skip.label": "I want to add services manually", | 33 | "import.skip.label": "I want to add services manually", |
@@ -376,4 +378,4 @@ | |||
376 | "workspaceDrawer.workspaceFeatureInfo": "<p>Franz Workspaces let you focus on what’s important right now. Set up different sets of services and easily switch between them at any time.</p><p>You decide which services you need when and where, so we can help you stay on top of your game - or easily switch off from work whenever you want.</p>", | 378 | "workspaceDrawer.workspaceFeatureInfo": "<p>Franz Workspaces let you focus on what’s important right now. Set up different sets of services and easily switch between them at any time.</p><p>You decide which services you need when and where, so we can help you stay on top of your game - or easily switch off from work whenever you want.</p>", |
377 | "workspaceDrawer.workspacesSettingsTooltip": "Edit workspaces settings", | 379 | "workspaceDrawer.workspacesSettingsTooltip": "Edit workspaces settings", |
378 | "workspaces.switchingIndicator.switchingTo": "Switching to" | 380 | "workspaces.switchingIndicator.switchingTo": "Switching to" |
379 | } \ No newline at end of file | 381 | } |
diff --git a/src/i18n/messages/src/components/settings/team/TeamDashboard.json b/src/i18n/messages/src/components/settings/team/TeamDashboard.json index 6bccc25ff..6ef3789c4 100644 --- a/src/i18n/messages/src/components/settings/team/TeamDashboard.json +++ b/src/i18n/messages/src/components/settings/team/TeamDashboard.json | |||
@@ -4,11 +4,11 @@ | |||
4 | "defaultMessage": "!!!Team", | 4 | "defaultMessage": "!!!Team", |
5 | "file": "src/components/settings/team/TeamDashboard.js", | 5 | "file": "src/components/settings/team/TeamDashboard.js", |
6 | "start": { | 6 | "start": { |
7 | "line": 14, | 7 | "line": 18, |
8 | "column": 12 | 8 | "column": 12 |
9 | }, | 9 | }, |
10 | "end": { | 10 | "end": { |
11 | "line": 17, | 11 | "line": 21, |
12 | "column": 3 | 12 | "column": 3 |
13 | } | 13 | } |
14 | }, | 14 | }, |
@@ -17,11 +17,11 @@ | |||
17 | "defaultMessage": "!!!Franz for Teams", | 17 | "defaultMessage": "!!!Franz for Teams", |
18 | "file": "src/components/settings/team/TeamDashboard.js", | 18 | "file": "src/components/settings/team/TeamDashboard.js", |
19 | "start": { | 19 | "start": { |
20 | "line": 18, | 20 | "line": 22, |
21 | "column": 19 | 21 | "column": 19 |
22 | }, | 22 | }, |
23 | "end": { | 23 | "end": { |
24 | "line": 21, | 24 | "line": 25, |
25 | "column": 3 | 25 | "column": 3 |
26 | } | 26 | } |
27 | }, | 27 | }, |
@@ -30,11 +30,11 @@ | |||
30 | "defaultMessage": "!!!You and your team use Franz? You can now manage Premium subscriptions for as many colleagues, friends or family members as you want, all from within one account.", | 30 | "defaultMessage": "!!!You and your team use Franz? You can now manage Premium subscriptions for as many colleagues, friends or family members as you want, all from within one account.", |
31 | "file": "src/components/settings/team/TeamDashboard.js", | 31 | "file": "src/components/settings/team/TeamDashboard.js", |
32 | "start": { | 32 | "start": { |
33 | "line": 22, | 33 | "line": 26, |
34 | "column": 9 | 34 | "column": 9 |
35 | }, | 35 | }, |
36 | "end": { | 36 | "end": { |
37 | "line": 25, | 37 | "line": 29, |
38 | "column": 3 | 38 | "column": 3 |
39 | } | 39 | } |
40 | }, | 40 | }, |
@@ -43,11 +43,11 @@ | |||
43 | "defaultMessage": "!!!Franz for Teams gives you the option to invite co-workers to your team by sending them email invitations and manage their subscriptions in your account’s preferences. Don’t waste time setting up subscriptions for every team member individually, forget about multiple invoices and different billing cycles - one team to rule them all!", | 43 | "defaultMessage": "!!!Franz for Teams gives you the option to invite co-workers to your team by sending them email invitations and manage their subscriptions in your account’s preferences. Don’t waste time setting up subscriptions for every team member individually, forget about multiple invoices and different billing cycles - one team to rule them all!", |
44 | "file": "src/components/settings/team/TeamDashboard.js", | 44 | "file": "src/components/settings/team/TeamDashboard.js", |
45 | "start": { | 45 | "start": { |
46 | "line": 26, | 46 | "line": 30, |
47 | "column": 8 | 47 | "column": 8 |
48 | }, | 48 | }, |
49 | "end": { | 49 | "end": { |
50 | "line": 29, | 50 | "line": 33, |
51 | "column": 3 | 51 | "column": 3 |
52 | } | 52 | } |
53 | }, | 53 | }, |
@@ -56,11 +56,11 @@ | |||
56 | "defaultMessage": "!!!Manage your Team on meetfranz.com", | 56 | "defaultMessage": "!!!Manage your Team on meetfranz.com", |
57 | "file": "src/components/settings/team/TeamDashboard.js", | 57 | "file": "src/components/settings/team/TeamDashboard.js", |
58 | "start": { | 58 | "start": { |
59 | "line": 30, | 59 | "line": 34, |
60 | "column": 16 | 60 | "column": 16 |
61 | }, | 61 | }, |
62 | "end": { | 62 | "end": { |
63 | "line": 33, | 63 | "line": 37, |
64 | "column": 3 | 64 | "column": 3 |
65 | } | 65 | } |
66 | }, | 66 | }, |
@@ -69,11 +69,11 @@ | |||
69 | "defaultMessage": "!!!Upgrade your Account", | 69 | "defaultMessage": "!!!Upgrade your Account", |
70 | "file": "src/components/settings/team/TeamDashboard.js", | 70 | "file": "src/components/settings/team/TeamDashboard.js", |
71 | "start": { | 71 | "start": { |
72 | "line": 34, | 72 | "line": 38, |
73 | "column": 17 | 73 | "column": 17 |
74 | }, | 74 | }, |
75 | "end": { | 75 | "end": { |
76 | "line": 37, | 76 | "line": 41, |
77 | "column": 3 | 77 | "column": 3 |
78 | } | 78 | } |
79 | } | 79 | } |
diff --git a/src/i18n/messages/src/components/ui/UpgradeButton/index.json b/src/i18n/messages/src/components/ui/UpgradeButton/index.json new file mode 100644 index 000000000..87e0bc913 --- /dev/null +++ b/src/i18n/messages/src/components/ui/UpgradeButton/index.json | |||
@@ -0,0 +1,15 @@ | |||
1 | [ | ||
2 | { | ||
3 | "id": "global.upgradeButton.upgradeToPro", | ||
4 | "defaultMessage": "!!!Upgrade to Franz Professional", | ||
5 | "file": "src/components/ui/UpgradeButton/index.js", | ||
6 | "start": { | ||
7 | "line": 14, | ||
8 | "column": 16 | ||
9 | }, | ||
10 | "end": { | ||
11 | "line": 17, | ||
12 | "column": 3 | ||
13 | } | ||
14 | } | ||
15 | ] \ No newline at end of file | ||
diff --git a/src/i18n/messages/src/i18n/globalMessages.json b/src/i18n/messages/src/i18n/globalMessages.json index 28001614f..f4fd5b8b0 100644 --- a/src/i18n/messages/src/i18n/globalMessages.json +++ b/src/i18n/messages/src/i18n/globalMessages.json | |||
@@ -76,5 +76,18 @@ | |||
76 | "line": 27, | 76 | "line": 27, |
77 | "column": 3 | 77 | "column": 3 |
78 | } | 78 | } |
79 | }, | ||
80 | { | ||
81 | "id": "global.franzProRequired", | ||
82 | "defaultMessage": "!!!Franz Professional Required", | ||
83 | "file": "src/i18n/globalMessages.js", | ||
84 | "start": { | ||
85 | "line": 28, | ||
86 | "column": 15 | ||
87 | }, | ||
88 | "end": { | ||
89 | "line": 31, | ||
90 | "column": 3 | ||
91 | } | ||
79 | } | 92 | } |
80 | ] \ No newline at end of file | 93 | ] \ No newline at end of file |
diff --git a/src/stores/UIStore.js b/src/stores/UIStore.js index 2c785111f..9680c5bcc 100644 --- a/src/stores/UIStore.js +++ b/src/stores/UIStore.js | |||
@@ -46,7 +46,6 @@ export default class UIStore extends Store { | |||
46 | // Actions | 46 | // Actions |
47 | @action _openSettings({ path = '/settings' }) { | 47 | @action _openSettings({ path = '/settings' }) { |
48 | const settingsPath = path !== '/settings' ? `/settings/${path}` : path; | 48 | const settingsPath = path !== '/settings' ? `/settings/${path}` : path; |
49 | console.log(settingsPath); | ||
50 | this.stores.router.push(settingsPath); | 49 | this.stores.router.push(settingsPath); |
51 | } | 50 | } |
52 | 51 | ||
diff --git a/src/stores/UserStore.js b/src/stores/UserStore.js index 7ac7d2375..d44208923 100644 --- a/src/stores/UserStore.js +++ b/src/stores/UserStore.js | |||
@@ -168,9 +168,9 @@ export default class UserStore extends Store { | |||
168 | } | 168 | } |
169 | 169 | ||
170 | @computed get isPro() { | 170 | @computed get isPro() { |
171 | if (!this.team.plan && this.isPremium) return true; | 171 | if ((!this.team.plan || this.team.state !== 'expired') && this.isPremium) return true; |
172 | 172 | ||
173 | if (!this.team.plan) return false; | 173 | if ((!this.team.plan || this.team.state === 'expired')) return false; |
174 | const plan = getPlan(this.team.plan); | 174 | const plan = getPlan(this.team.plan); |
175 | 175 | ||
176 | return plan === PLANS.PRO; | 176 | return plan === PLANS.PRO; |