aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLibravatar Stefan Malzner <stefan@adlk.io>2019-09-05 09:49:25 +0200
committerLibravatar Stefan Malzner <stefan@adlk.io>2019-09-05 09:49:25 +0200
commit24d0223fee38c36ec19d9c662579dba7d787f8b4 (patch)
tree17a50e725cef1266506fc9ac6352c15a120cba78 /src
parentdon't warn on react/destructuring-assignment (diff)
downloadferdium-app-24d0223fee38c36ec19d9c662579dba7d787f8b4.tar.gz
ferdium-app-24d0223fee38c36ec19d9c662579dba7d787f8b4.tar.zst
ferdium-app-24d0223fee38c36ec19d9c662579dba7d787f8b4.zip
polishing
Diffstat (limited to 'src')
-rw-r--r--src/assets/images/workspaces/teaser_dark.pngbin179047 -> 0 bytes
-rw-r--r--src/assets/images/workspaces/teaser_light.pngbin182321 -> 0 bytes
-rw-r--r--src/components/settings/team/TeamDashboard.js62
-rw-r--r--src/components/ui/UpgradeButton/index.js90
-rw-r--r--src/config.js2
-rw-r--r--src/containers/settings/TeamScreen.js1
-rw-r--r--src/containers/subscription/SubscriptionFormScreen.js2
-rw-r--r--src/environment.js6
-rw-r--r--src/features/todos/components/TodosWebview.js8
-rw-r--r--src/features/todos/store.js18
-rw-r--r--src/features/workspaces/components/WorkspacesDashboard.js167
-rw-r--r--src/features/workspaces/containers/WorkspacesScreen.js13
-rw-r--r--src/i18n/globalMessages.js4
-rw-r--r--src/i18n/locales/defaultMessages.json67
-rw-r--r--src/i18n/locales/en-US.json4
-rw-r--r--src/i18n/messages/src/components/settings/team/TeamDashboard.json24
-rw-r--r--src/i18n/messages/src/components/ui/UpgradeButton/index.json15
-rw-r--r--src/i18n/messages/src/i18n/globalMessages.json13
-rw-r--r--src/stores/UIStore.js1
-rw-r--r--src/stores/UserStore.js4
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';
5import ReactTooltip from 'react-tooltip'; 5import ReactTooltip from 'react-tooltip';
6import injectSheet from 'react-jss'; 6import injectSheet from 'react-jss';
7 7
8import { Badge } from '@meetfranz/ui';
8import Loader from '../../ui/Loader'; 9import Loader from '../../ui/Loader';
9import Button from '../../ui/Button'; 10import Button from '../../ui/Button';
10import Infobox from '../../ui/Infobox'; 11import Infobox from '../../ui/Infobox';
11import PremiumFeatureContainer from '../../ui/PremiumFeatureContainer'; 12import PremiumFeatureContainer from '../../ui/PremiumFeatureContainer';
13import globalMessages from '../../../i18n/globalMessages';
14import ActivateTrialButton from '../../ui/ActivateTrialButton';
15import UpgradeButton from '../../ui/UpgradeButton';
12 16
13const messages = defineMessages({ 17const messages = defineMessages({
14 headline: { 18 headline: {
@@ -40,6 +44,7 @@ const messages = defineMessages({
40const styles = { 44const 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 @@
1import React, { Component } from 'react';
2import PropTypes from 'prop-types';
3import { inject, observer } from 'mobx-react';
4import { defineMessages, intlShape } from 'react-intl';
5import classnames from 'classnames';
6
7import { Button } from '@meetfranz/forms';
8import { gaEvent } from '../../../lib/analytics';
9
10import UserStore from '../../../stores/UserStore';
11import ActivateTrialButton from '../ActivateTrialButton';
12
13const messages = defineMessages({
14 upgradeToPro: {
15 id: 'global.upgradeButton.upgradeToPro',
16 defaultMessage: '!!!Upgrade to Franz Professional',
17 },
18});
19
20@inject('stores', 'actions') @observer
21class 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
79export default UpgradeButton;
80
81UpgradeButton.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
21export const LOCAL_API_WEBSITE = 'http://localhost:3333'; 21export 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
23export const DEV_API_WEBSITE = 'http://hash-3ac3ccd2472269cf585c58a4f6973d86f3c9e7bd.franzstaging.com/'; // TODO: revert me 23export const DEV_API_WEBSITE = 'http://hash-58883791519ef6288c952316bdce7fb462283893.franzstaging.com/'; // TODO: revert me
24export const LIVE_API_WEBSITE = 'https://meetfranz.com'; 24export const LIVE_API_WEBSITE = 'https://meetfranz.com';
25 25
26export const STATS_API = 'https://stats.franzinfra.com'; 26export 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;
36let web; 36let web;
37let todos; 37let todos;
38if (!isDevMode || (isDevMode && useLiveAPI)) { 38if (!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';
9import { mdiChevronRight, mdiCheckAll } from '@mdi/js'; 9import { mdiChevronRight, mdiCheckAll } from '@mdi/js';
10import * as environment from '../../../environment'; 10import * as environment from '../../../environment';
11import Appear from '../../../components/ui/effects/Appear'; 11import Appear from '../../../components/ui/effects/Appear';
12import ActivateTrialButton from '../../../components/ui/ActivateTrialButton'; 12import UpgradeButton from '../../../components/ui/UpgradeButton';
13 13
14const OPEN_TODOS_BUTTON_SIZE = 45; 14const OPEN_TODOS_BUTTON_SIZE = 45;
15const CLOSE_TODOS_BUTTON_SIZE = 35; 15const 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';
3import { observer, PropTypes as MobxPropTypes, inject } from 'mobx-react'; 3import { observer, PropTypes as MobxPropTypes, inject } from 'mobx-react';
4import { defineMessages, intlShape } from 'react-intl'; 4import { defineMessages, intlShape } from 'react-intl';
5import injectSheet from 'react-jss'; 5import injectSheet from 'react-jss';
6import { Infobox } from '@meetfranz/ui'; 6import { Infobox, Badge } from '@meetfranz/ui';
7 7
8import Loader from '../../../components/ui/Loader'; 8import Loader from '../../../components/ui/Loader';
9import WorkspaceItem from './WorkspaceItem'; 9import WorkspaceItem from './WorkspaceItem';
@@ -11,9 +11,9 @@ import CreateWorkspaceForm from './CreateWorkspaceForm';
11import Request from '../../../stores/lib/Request'; 11import Request from '../../../stores/lib/Request';
12import Appear from '../../../components/ui/effects/Appear'; 12import Appear from '../../../components/ui/effects/Appear';
13import { workspaceStore } from '../index'; 13import { workspaceStore } from '../index';
14import PremiumFeatureContainer from '../../../components/ui/PremiumFeatureContainer';
15import UIStore from '../../../stores/UIStore'; 14import UIStore from '../../../stores/UIStore';
16import ActivateTrialButton from '../../../components/ui/ActivateTrialButton'; 15import globalMessages from '../../../i18n/globalMessages';
16import UpgradeButton from '../../../components/ui/UpgradeButton';
17 17
18const messages = defineMessages({ 18const 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';
13import UserStore from '../../../stores/UserStore';
13 14
14@inject('actions') @observer 15@inject('stores', 'actions') @observer
15class WorkspacesScreen extends Component { 16class 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;