aboutsummaryrefslogtreecommitdiffstats
path: root/src/components
diff options
context:
space:
mode:
authorLibravatar Stefan Malzner <stefan@adlk.io>2018-12-02 15:08:07 +0100
committerLibravatar Stefan Malzner <stefan@adlk.io>2018-12-02 15:08:07 +0100
commita5aa5e1380a0847eb33be3315d164fb9e0e23255 (patch)
treea1ea4b0f635cabb54d9cf028809d2f079727b9a1 /src/components
parentAdd instruction to install Franz with homebrew (#1134) (diff)
parentMerge branch 'develop' into release/5.0.0-beta.19 (diff)
downloadferdium-app-a5aa5e1380a0847eb33be3315d164fb9e0e23255.tar.gz
ferdium-app-a5aa5e1380a0847eb33be3315d164fb9e0e23255.tar.zst
ferdium-app-a5aa5e1380a0847eb33be3315d164fb9e0e23255.zip
Merge branch 'release/5.0.0-beta.19'
Diffstat (limited to 'src/components')
-rw-r--r--src/components/auth/AuthLayout.js97
-rw-r--r--src/components/auth/Import.js3
-rw-r--r--src/components/auth/Invite.js3
-rw-r--r--src/components/auth/Login.js3
-rw-r--r--src/components/auth/Password.js3
-rw-r--r--src/components/auth/Pricing.js3
-rw-r--r--src/components/auth/Signup.js7
-rw-r--r--src/components/auth/Welcome.js3
-rw-r--r--src/components/layout/AppLayout.js11
-rw-r--r--src/components/layout/Sidebar.js3
-rw-r--r--src/components/services/content/ServiceDisabled.js3
-rw-r--r--src/components/services/content/ServiceWebview.js3
-rw-r--r--src/components/services/content/Services.js3
-rw-r--r--src/components/services/content/WebviewCrashHandler.js3
-rw-r--r--src/components/services/tabs/TabItem.js6
-rw-r--r--src/components/services/tabs/Tabbar.js3
-rw-r--r--src/components/settings/SettingsLayout.js3
-rw-r--r--src/components/settings/account/AccountDashboard.js81
-rw-r--r--src/components/settings/navigation/SettingsNavigation.js4
-rw-r--r--src/components/settings/recipes/RecipeItem.js3
-rw-r--r--src/components/settings/recipes/RecipesDashboard.js3
-rw-r--r--src/components/settings/services/EditServiceForm.js50
-rw-r--r--src/components/settings/services/ServiceError.js3
-rw-r--r--src/components/settings/services/ServiceItem.js3
-rw-r--r--src/components/settings/services/ServicesDashboard.js3
-rw-r--r--src/components/settings/settings/EditSettingsForm.js21
-rw-r--r--src/components/settings/user/EditUserForm.js11
-rw-r--r--src/components/subscription/SubscriptionForm.js38
-rw-r--r--src/components/subscription/SubscriptionPopup.js3
-rw-r--r--src/components/ui/Button.js3
-rw-r--r--src/components/ui/ImageUpload.js4
-rw-r--r--src/components/ui/InfoBar.js3
-rw-r--r--src/components/ui/Infobox.js3
-rw-r--r--src/components/ui/Input.js4
-rw-r--r--src/components/ui/Link.js4
-rw-r--r--src/components/ui/PremiumFeatureContainer/index.js76
-rw-r--r--src/components/ui/PremiumFeatureContainer/styles.js31
-rw-r--r--src/components/ui/Radio.js3
-rw-r--r--src/components/ui/SearchInput.js3
-rw-r--r--src/components/ui/Select.js3
-rw-r--r--src/components/ui/StatusBarTargetUrl.js3
-rw-r--r--src/components/ui/Tabs/Tabs.js3
-rw-r--r--src/components/ui/Toggle.js9
43 files changed, 358 insertions, 177 deletions
diff --git a/src/components/auth/AuthLayout.js b/src/components/auth/AuthLayout.js
index 2741b8a15..4fb0e6a59 100644
--- a/src/components/auth/AuthLayout.js
+++ b/src/components/auth/AuthLayout.js
@@ -3,6 +3,7 @@ import PropTypes from 'prop-types';
3import { observer } from 'mobx-react'; 3import { observer } from 'mobx-react';
4import { RouteTransition } from 'react-router-transition'; 4import { RouteTransition } from 'react-router-transition';
5import { intlShape } from 'react-intl'; 5import { intlShape } from 'react-intl';
6import { TitleBar } from 'electron-react-titlebar';
6 7
7import Link from '../ui/Link'; 8import Link from '../ui/Link';
8import InfoBar from '../ui/InfoBar'; 9import InfoBar from '../ui/InfoBar';
@@ -10,8 +11,9 @@ import InfoBar from '../ui/InfoBar';
10import { oneOrManyChildElements, globalError as globalErrorPropType } from '../../prop-types'; 11import { oneOrManyChildElements, globalError as globalErrorPropType } from '../../prop-types';
11import globalMessages from '../../i18n/globalMessages'; 12import globalMessages from '../../i18n/globalMessages';
12 13
13@observer 14import { isWindows } from '../../environment';
14export default class AuthLayout extends Component { 15
16export default @observer class AuthLayout extends Component {
15 static propTypes = { 17 static propTypes = {
16 children: oneOrManyChildElements.isRequired, 18 children: oneOrManyChildElements.isRequired,
17 pathname: PropTypes.string.isRequired, 19 pathname: PropTypes.string.isRequired,
@@ -20,6 +22,8 @@ export default class AuthLayout extends Component {
20 isAPIHealthy: PropTypes.bool.isRequired, 22 isAPIHealthy: PropTypes.bool.isRequired,
21 retryHealthCheck: PropTypes.func.isRequired, 23 retryHealthCheck: PropTypes.func.isRequired,
22 isHealthCheckLoading: PropTypes.bool.isRequired, 24 isHealthCheckLoading: PropTypes.bool.isRequired,
25 isFullScreen: PropTypes.bool.isRequired,
26 darkMode: PropTypes.bool.isRequired,
23 }; 27 };
24 28
25 static contextTypes = { 29 static contextTypes = {
@@ -35,53 +39,58 @@ export default class AuthLayout extends Component {
35 isAPIHealthy, 39 isAPIHealthy,
36 retryHealthCheck, 40 retryHealthCheck,
37 isHealthCheckLoading, 41 isHealthCheckLoading,
42 isFullScreen,
43 darkMode,
38 } = this.props; 44 } = this.props;
39 const { intl } = this.context; 45 const { intl } = this.context;
40 46
41 return ( 47 return (
42 <div className="auth"> 48 <div className={darkMode ? 'theme__dark' : ''}>
43 {!isOnline && ( 49 {isWindows && !isFullScreen && <TitleBar menu={window.franz.menu.template} icon={'assets/images/logo.svg'} />}
44 <InfoBar 50 <div className={'auth'}>
45 type="warning" 51 {!isOnline && (
46 > 52 <InfoBar
47 <span className="mdi mdi-flash" /> 53 type="warning"
48 {intl.formatMessage(globalMessages.notConnectedToTheInternet)} 54 >
49 </InfoBar> 55 <span className="mdi mdi-flash" />
50 )} 56 {intl.formatMessage(globalMessages.notConnectedToTheInternet)}
51 {isOnline && !isAPIHealthy && ( 57 </InfoBar>
52 <InfoBar 58 )}
53 type="danger" 59 {isOnline && !isAPIHealthy && (
54 ctaLabel="Try again" 60 <InfoBar
55 ctaLoading={isHealthCheckLoading} 61 type="danger"
56 sticky 62 ctaLabel="Try again"
57 onClick={retryHealthCheck} 63 ctaLoading={isHealthCheckLoading}
58 > 64 sticky
59 <span className="mdi mdi-flash" /> 65 onClick={retryHealthCheck}
60 {intl.formatMessage(globalMessages.APIUnhealthy)} 66 >
61 </InfoBar> 67 <span className="mdi mdi-flash" />
62 )} 68 {intl.formatMessage(globalMessages.APIUnhealthy)}
63 <div className="auth__layout"> 69 </InfoBar>
64 <RouteTransition 70 )}
65 pathname={pathname} 71 <div className="auth__layout">
66 atEnter={{ opacity: 0 }} 72 <RouteTransition
67 atLeave={{ opacity: 0 }} 73 pathname={pathname}
68 atActive={{ opacity: 1 }} 74 atEnter={{ opacity: 0 }}
69 mapStyles={styles => ({ 75 atLeave={{ opacity: 0 }}
70 transform: `translateX(${styles.translateX}%)`, 76 atActive={{ opacity: 1 }}
71 opacity: styles.opacity, 77 mapStyles={styles => ({
72 })} 78 transform: `translateX(${styles.translateX}%)`,
73 component="span" 79 opacity: styles.opacity,
74 > 80 })}
75 {/* Inject globalError into children */} 81 component="span"
76 {React.cloneElement(children, { 82 >
77 error, 83 {/* Inject globalError into children */}
78 })} 84 {React.cloneElement(children, {
79 </RouteTransition> 85 error,
86 })}
87 </RouteTransition>
88 </div>
89 {/* </div> */}
90 <Link to="https://adlk.io" className="auth__adlk" target="_blank">
91 <img src="./assets/images/adlk.svg" alt="" />
92 </Link>
80 </div> 93 </div>
81 {/* </div> */}
82 <Link to="https://adlk.io" className="auth__adlk" target="_blank">
83 <img src="./assets/images/adlk.svg" alt="" />
84 </Link>
85 </div> 94 </div>
86 ); 95 );
87 } 96 }
diff --git a/src/components/auth/Import.js b/src/components/auth/Import.js
index 9ba14e768..0d5feb274 100644
--- a/src/components/auth/Import.js
+++ b/src/components/auth/Import.js
@@ -28,8 +28,7 @@ const messages = defineMessages({
28 }, 28 },
29}); 29});
30 30
31@observer 31export default @observer class Import extends Component {
32export default class Import extends Component {
33 static propTypes = { 32 static propTypes = {
34 services: MobxPropTypes.arrayOrObservableArray.isRequired, 33 services: MobxPropTypes.arrayOrObservableArray.isRequired,
35 onSubmit: PropTypes.func.isRequired, 34 onSubmit: PropTypes.func.isRequired,
diff --git a/src/components/auth/Invite.js b/src/components/auth/Invite.js
index f1c16986b..96821a61a 100644
--- a/src/components/auth/Invite.js
+++ b/src/components/auth/Invite.js
@@ -43,8 +43,7 @@ const messages = defineMessages({
43 }, 43 },
44}); 44});
45 45
46@observer 46export default @observer class Invite extends Component {
47export default class Invite extends Component {
48 static propTypes = { 47 static propTypes = {
49 onSubmit: PropTypes.func.isRequired, 48 onSubmit: PropTypes.func.isRequired,
50 embed: PropTypes.bool, 49 embed: PropTypes.bool,
diff --git a/src/components/auth/Login.js b/src/components/auth/Login.js
index 4a3cd6776..f465b35a5 100644
--- a/src/components/auth/Login.js
+++ b/src/components/auth/Login.js
@@ -55,8 +55,7 @@ const messages = defineMessages({
55 }, 55 },
56}); 56});
57 57
58@observer 58export default @observer class Login extends Component {
59export default class Login extends Component {
60 static propTypes = { 59 static propTypes = {
61 onSubmit: PropTypes.func.isRequired, 60 onSubmit: PropTypes.func.isRequired,
62 isSubmitting: PropTypes.bool.isRequired, 61 isSubmitting: PropTypes.bool.isRequired,
diff --git a/src/components/auth/Password.js b/src/components/auth/Password.js
index 5bcc80b6e..ad34e39af 100644
--- a/src/components/auth/Password.js
+++ b/src/components/auth/Password.js
@@ -41,8 +41,7 @@ const messages = defineMessages({
41 }, 41 },
42}); 42});
43 43
44@observer 44export default @observer class Password extends Component {
45export default class Password extends Component {
46 static propTypes = { 45 static propTypes = {
47 onSubmit: PropTypes.func.isRequired, 46 onSubmit: PropTypes.func.isRequired,
48 isSubmitting: PropTypes.bool.isRequired, 47 isSubmitting: PropTypes.bool.isRequired,
diff --git a/src/components/auth/Pricing.js b/src/components/auth/Pricing.js
index 3cc8d5f6b..f08129568 100644
--- a/src/components/auth/Pricing.js
+++ b/src/components/auth/Pricing.js
@@ -28,8 +28,7 @@ const messages = defineMessages({
28 }, 28 },
29}); 29});
30 30
31@observer 31export default @observer class Signup extends Component {
32export default class Signup extends Component {
33 static propTypes = { 32 static propTypes = {
34 donor: MobxPropTypes.objectOrObservableObject.isRequired, 33 donor: MobxPropTypes.objectOrObservableObject.isRequired,
35 isLoading: PropTypes.bool.isRequired, 34 isLoading: PropTypes.bool.isRequired,
diff --git a/src/components/auth/Signup.js b/src/components/auth/Signup.js
index 219948274..bbcad8b67 100644
--- a/src/components/auth/Signup.js
+++ b/src/components/auth/Signup.js
@@ -65,8 +65,7 @@ const messages = defineMessages({
65 }, 65 },
66}); 66});
67 67
68@observer 68export default @observer class Signup extends Component {
69export default class Signup extends Component {
70 static propTypes = { 69 static propTypes = {
71 onSubmit: PropTypes.func.isRequired, 70 onSubmit: PropTypes.func.isRequired,
72 isSubmitting: PropTypes.bool.isRequired, 71 isSubmitting: PropTypes.bool.isRequired,
@@ -187,7 +186,7 @@ export default class Signup extends Component {
187 {intl.formatMessage(messages.legalInfo)} 186 {intl.formatMessage(messages.legalInfo)}
188 <br /> 187 <br />
189 <Link 188 <Link
190 to="http://meetfranz.com/terms" 189 to="https://meetfranz.com/terms"
191 target="_blank" 190 target="_blank"
192 className="link" 191 className="link"
193 > 192 >
@@ -195,7 +194,7 @@ export default class Signup extends Component {
195 </Link> 194 </Link>
196 &nbsp;&amp;&nbsp; 195 &nbsp;&amp;&nbsp;
197 <Link 196 <Link
198 to="http://meetfranz.com/privacy" 197 to="https://meetfranz.com/privacy"
199 target="_blank" 198 target="_blank"
200 className="link" 199 className="link"
201 > 200 >
diff --git a/src/components/auth/Welcome.js b/src/components/auth/Welcome.js
index 9e1c762a5..f6d77f70f 100644
--- a/src/components/auth/Welcome.js
+++ b/src/components/auth/Welcome.js
@@ -16,8 +16,7 @@ const messages = defineMessages({
16 }, 16 },
17}); 17});
18 18
19@observer 19export default @observer class Login extends Component {
20export default class Login extends Component {
21 static propTypes = { 20 static propTypes = {
22 loginRoute: PropTypes.string.isRequired, 21 loginRoute: PropTypes.string.isRequired,
23 signupRoute: PropTypes.string.isRequired, 22 signupRoute: PropTypes.string.isRequired,
diff --git a/src/components/layout/AppLayout.js b/src/components/layout/AppLayout.js
index 746775a7f..3ababe54a 100644
--- a/src/components/layout/AppLayout.js
+++ b/src/components/layout/AppLayout.js
@@ -5,6 +5,7 @@ import { defineMessages, intlShape } from 'react-intl';
5import { TitleBar } from 'electron-react-titlebar'; 5import { TitleBar } from 'electron-react-titlebar';
6 6
7import InfoBar from '../ui/InfoBar'; 7import InfoBar from '../ui/InfoBar';
8import { Component as DelayApp } from '../../features/delayApp';
8import globalMessages from '../../i18n/globalMessages'; 9import globalMessages from '../../i18n/globalMessages';
9 10
10import { isWindows } from '../../environment'; 11import { isWindows } from '../../environment';
@@ -40,8 +41,7 @@ const messages = defineMessages({
40 }, 41 },
41}); 42});
42 43
43@observer 44export default @observer class AppLayout extends Component {
44export default class AppLayout extends Component {
45 static propTypes = { 45 static propTypes = {
46 isFullScreen: PropTypes.bool.isRequired, 46 isFullScreen: PropTypes.bool.isRequired,
47 sidebar: PropTypes.element.isRequired, 47 sidebar: PropTypes.element.isRequired,
@@ -58,6 +58,8 @@ export default class AppLayout extends Component {
58 areRequiredRequestsSuccessful: PropTypes.bool.isRequired, 58 areRequiredRequestsSuccessful: PropTypes.bool.isRequired,
59 retryRequiredRequests: PropTypes.func.isRequired, 59 retryRequiredRequests: PropTypes.func.isRequired,
60 areRequiredRequestsLoading: PropTypes.bool.isRequired, 60 areRequiredRequestsLoading: PropTypes.bool.isRequired,
61 darkMode: PropTypes.bool.isRequired,
62 isDelayAppScreenVisible: PropTypes.bool.isRequired,
61 }; 63 };
62 64
63 static defaultProps = { 65 static defaultProps = {
@@ -85,12 +87,14 @@ export default class AppLayout extends Component {
85 areRequiredRequestsSuccessful, 87 areRequiredRequestsSuccessful,
86 retryRequiredRequests, 88 retryRequiredRequests,
87 areRequiredRequestsLoading, 89 areRequiredRequestsLoading,
90 darkMode,
91 isDelayAppScreenVisible,
88 } = this.props; 92 } = this.props;
89 93
90 const { intl } = this.context; 94 const { intl } = this.context;
91 95
92 return ( 96 return (
93 <div> 97 <div className={(darkMode ? 'theme__dark' : '')}>
94 <div className="app"> 98 <div className="app">
95 {isWindows && !isFullScreen && <TitleBar menu={window.franz.menu.template} icon={'assets/images/logo.svg'} />} 99 {isWindows && !isFullScreen && <TitleBar menu={window.franz.menu.template} icon={'assets/images/logo.svg'} />}
96 <div className="app__content"> 100 <div className="app__content">
@@ -151,6 +155,7 @@ export default class AppLayout extends Component {
151 </a> 155 </a>
152 </InfoBar> 156 </InfoBar>
153 )} 157 )}
158 {isDelayAppScreenVisible && (<DelayApp />)}
154 {services} 159 {services}
155 </div> 160 </div>
156 </div> 161 </div>
diff --git a/src/components/layout/Sidebar.js b/src/components/layout/Sidebar.js
index fa269f216..6ea95bf88 100644
--- a/src/components/layout/Sidebar.js
+++ b/src/components/layout/Sidebar.js
@@ -26,8 +26,7 @@ const messages = defineMessages({
26 }, 26 },
27}); 27});
28 28
29@observer 29export default @observer class Sidebar extends Component {
30export default class Sidebar extends Component {
31 static propTypes = { 30 static propTypes = {
32 openSettings: PropTypes.func.isRequired, 31 openSettings: PropTypes.func.isRequired,
33 toggleMuteApp: PropTypes.func.isRequired, 32 toggleMuteApp: PropTypes.func.isRequired,
diff --git a/src/components/services/content/ServiceDisabled.js b/src/components/services/content/ServiceDisabled.js
index b5af3743d..58fb38d8c 100644
--- a/src/components/services/content/ServiceDisabled.js
+++ b/src/components/services/content/ServiceDisabled.js
@@ -16,8 +16,7 @@ const messages = defineMessages({
16 }, 16 },
17}); 17});
18 18
19@observer 19export default @observer class ServiceDisabled extends Component {
20export default class ServiceDisabled extends Component {
21 static propTypes = { 20 static propTypes = {
22 name: PropTypes.string.isRequired, 21 name: PropTypes.string.isRequired,
23 enable: PropTypes.func.isRequired, 22 enable: PropTypes.func.isRequired,
diff --git a/src/components/services/content/ServiceWebview.js b/src/components/services/content/ServiceWebview.js
index c146abf4e..7163209ee 100644
--- a/src/components/services/content/ServiceWebview.js
+++ b/src/components/services/content/ServiceWebview.js
@@ -10,8 +10,7 @@ import StatusBarTargetUrl from '../../ui/StatusBarTargetUrl';
10import WebviewCrashHandler from './WebviewCrashHandler'; 10import WebviewCrashHandler from './WebviewCrashHandler';
11import ServiceDisabled from './ServiceDisabled'; 11import ServiceDisabled from './ServiceDisabled';
12 12
13@observer 13export default @observer class ServiceWebview extends Component {
14export default class ServiceWebview extends Component {
15 static propTypes = { 14 static propTypes = {
16 service: PropTypes.instanceOf(ServiceModel).isRequired, 15 service: PropTypes.instanceOf(ServiceModel).isRequired,
17 setWebviewReference: PropTypes.func.isRequired, 16 setWebviewReference: PropTypes.func.isRequired,
diff --git a/src/components/services/content/Services.js b/src/components/services/content/Services.js
index b1322afc2..4cbd51043 100644
--- a/src/components/services/content/Services.js
+++ b/src/components/services/content/Services.js
@@ -18,8 +18,7 @@ const messages = defineMessages({
18 }, 18 },
19}); 19});
20 20
21@observer 21export default @observer class Services extends Component {
22export default class Services extends Component {
23 static propTypes = { 22 static propTypes = {
24 services: MobxPropTypes.arrayOrObservableArray.isRequired, 23 services: MobxPropTypes.arrayOrObservableArray.isRequired,
25 setWebviewReference: PropTypes.func.isRequired, 24 setWebviewReference: PropTypes.func.isRequired,
diff --git a/src/components/services/content/WebviewCrashHandler.js b/src/components/services/content/WebviewCrashHandler.js
index d3e6951f3..3be1fccf4 100644
--- a/src/components/services/content/WebviewCrashHandler.js
+++ b/src/components/services/content/WebviewCrashHandler.js
@@ -24,8 +24,7 @@ const messages = defineMessages({
24 }, 24 },
25}); 25});
26 26
27@observer 27export default @observer class WebviewCrashHandler extends Component {
28export default class WebviewCrashHandler extends Component {
29 static propTypes = { 28 static propTypes = {
30 name: PropTypes.string.isRequired, 29 name: PropTypes.string.isRequired,
31 reload: PropTypes.func.isRequired, 30 reload: PropTypes.func.isRequired,
diff --git a/src/components/services/tabs/TabItem.js b/src/components/services/tabs/TabItem.js
index 638262f7f..8de7dc438 100644
--- a/src/components/services/tabs/TabItem.js
+++ b/src/components/services/tabs/TabItem.js
@@ -141,10 +141,10 @@ class TabItem extends Component {
141 {service.unreadIndirectMessageCount > 0 141 {service.unreadIndirectMessageCount > 0
142 && service.unreadDirectMessageCount === 0 142 && service.unreadDirectMessageCount === 0
143 && service.isIndirectMessageBadgeEnabled && ( 143 && service.isIndirectMessageBadgeEnabled && (
144 <span className="tab-item__message-count is-indirect"> 144 <span className="tab-item__message-count is-indirect">
145 • 145 •
146 </span> 146 </span>
147 )} 147 )}
148 </span> 148 </span>
149 ); 149 );
150 } 150 }
diff --git a/src/components/services/tabs/Tabbar.js b/src/components/services/tabs/Tabbar.js
index ceb88c51c..dd5c2140f 100644
--- a/src/components/services/tabs/Tabbar.js
+++ b/src/components/services/tabs/Tabbar.js
@@ -4,8 +4,7 @@ import { observer, PropTypes as MobxPropTypes } from 'mobx-react';
4 4
5import TabBarSortableList from './TabBarSortableList'; 5import TabBarSortableList from './TabBarSortableList';
6 6
7@observer 7export default @observer class TabBar extends Component {
8export default class TabBar extends Component {
9 static propTypes = { 8 static propTypes = {
10 services: MobxPropTypes.arrayOrObservableArray.isRequired, 9 services: MobxPropTypes.arrayOrObservableArray.isRequired,
11 setActive: PropTypes.func.isRequired, 10 setActive: PropTypes.func.isRequired,
diff --git a/src/components/settings/SettingsLayout.js b/src/components/settings/SettingsLayout.js
index d5392ddba..3cb08feb1 100644
--- a/src/components/settings/SettingsLayout.js
+++ b/src/components/settings/SettingsLayout.js
@@ -5,8 +5,7 @@ import { observer } from 'mobx-react';
5import { oneOrManyChildElements } from '../../prop-types'; 5import { oneOrManyChildElements } from '../../prop-types';
6import Appear from '../ui/effects/Appear'; 6import Appear from '../ui/effects/Appear';
7 7
8@observer 8export default @observer class SettingsLayout extends Component {
9export default class SettingsLayout extends Component {
10 static propTypes = { 9 static propTypes = {
11 navigation: PropTypes.element.isRequired, 10 navigation: PropTypes.element.isRequired,
12 children: oneOrManyChildElements.isRequired, 11 children: oneOrManyChildElements.isRequired,
diff --git a/src/components/settings/account/AccountDashboard.js b/src/components/settings/account/AccountDashboard.js
index 4992f0913..06c7074dd 100644
--- a/src/components/settings/account/AccountDashboard.js
+++ b/src/components/settings/account/AccountDashboard.js
@@ -44,6 +44,10 @@ const messages = defineMessages({
44 id: 'settings.account.accountType.premium', 44 id: 'settings.account.accountType.premium',
45 defaultMessage: '!!!Premium Supporter Account', 45 defaultMessage: '!!!Premium Supporter Account',
46 }, 46 },
47 accountTypeEnterprise: {
48 id: 'settings.account.accountType.enterprise',
49 defaultMessage: '!!!Enterprise Account',
50 },
47 accountEditButton: { 51 accountEditButton: {
48 id: 'settings.account.account.editButton', 52 id: 'settings.account.account.editButton',
49 defaultMessage: '!!!Edit Account', 53 defaultMessage: '!!!Edit Account',
@@ -74,8 +78,7 @@ const messages = defineMessages({
74 }, 78 },
75}); 79});
76 80
77@observer 81export default @observer class AccountDashboard extends Component {
78export default class AccountDashboard extends Component {
79 static propTypes = { 82 static propTypes = {
80 user: MobxPropTypes.observableObject.isRequired, 83 user: MobxPropTypes.observableObject.isRequired,
81 orders: MobxPropTypes.arrayOrObservableArray.isRequired, 84 orders: MobxPropTypes.arrayOrObservableArray.isRequired,
@@ -167,17 +170,19 @@ export default class AccountDashboard extends Component {
167 </h2> 170 </h2>
168 {user.organization && `${user.organization}, `} 171 {user.organization && `${user.organization}, `}
169 {user.email}<br /> 172 {user.email}<br />
170 {!user.isPremium && ( 173 {!user.isEnterprise && !user.isPremium && (
171 <span className="badge badge">{intl.formatMessage(messages.accountTypeBasic)}</span> 174 <span className="badge badge">{intl.formatMessage(messages.accountTypeBasic)}</span>
172 )} 175 )}
173 {user.isPremium && ( 176 {user.isPremium && (
174 <span className="badge badge--premium">{intl.formatMessage(messages.accountTypePremium)}</span> 177 <span className="badge badge--premium">{intl.formatMessage(messages.accountTypePremium)}</span>
175 )} 178 )}
179 {user.isEnterprise && (
180 <span className="badge badge--success">{intl.formatMessage(messages.accountTypeEnterprise)}</span>
181 )}
176 </div> 182 </div>
177 <Link to="/settings/user/edit" className="button"> 183 <Link to="/settings/user/edit" className="button">
178 {intl.formatMessage(messages.accountEditButton)} 184 {intl.formatMessage(messages.accountEditButton)}
179 </Link> 185 </Link>
180
181 {user.emailValidated} 186 {user.emailValidated}
182 </div> 187 </div>
183 </div> 188 </div>
@@ -230,6 +235,33 @@ export default class AccountDashboard extends Component {
230 ) 235 )
231 )} 236 )}
232 237
238 {user.isEnterprise && (
239 <div className="account">
240 <div className="account__box">
241 <h2>{user.company.name}</h2>
242 <p>
243 Technical contact:&nbsp;
244 <Link
245 className="link"
246 target="_blank"
247 to={`mailto:${user.company.contact.technical}?subject=Franz`}
248 >
249 {user.company.contact.technical}
250 </Link>
251 <br />
252 General contact:&nbsp;
253 <Link
254 className="link"
255 target="_blank"
256 to={`mailto:${user.company.contact.default}?subject=Franz`}
257 >
258 {user.company.contact.default}
259 </Link>
260 </p>
261 </div>
262 </div>
263 )}
264
233 {user.isMiner && ( 265 {user.isMiner && (
234 <div className="account franz-form"> 266 <div className="account franz-form">
235 <div className="account__box account__box"> 267 <div className="account__box account__box">
@@ -244,7 +276,7 @@ export default class AccountDashboard extends Component {
244 </div> 276 </div>
245 )} 277 )}
246 278
247 {!user.isPremium && ( 279 {!user.isEnterprise && !user.isPremium && (
248 isLoadingPlans ? ( 280 isLoadingPlans ? (
249 <Loader /> 281 <Loader />
250 ) : ( 282 ) : (
@@ -259,28 +291,29 @@ export default class AccountDashboard extends Component {
259 ) 291 )
260 )} 292 )}
261 293
262 <div className="account franz-form"> 294 {!user.isEnterprise && (
263 <div className="account__box"> 295 <div className="account franz-form">
264 <h2>{intl.formatMessage(messages.headlineDangerZone)}</h2> 296 <div className="account__box">
265 {!isDeleteAccountSuccessful && ( 297 <h2>{intl.formatMessage(messages.headlineDangerZone)}</h2>
266 <div className="account__subscription"> 298 {!isDeleteAccountSuccessful && (
267 <p>{intl.formatMessage(messages.deleteInfo)}</p> 299 <div className="account__subscription">
268 <Button 300 <p>{intl.formatMessage(messages.deleteInfo)}</p>
269 label={intl.formatMessage(messages.deleteAccount)} 301 <Button
270 buttonType="danger" 302 label={intl.formatMessage(messages.deleteAccount)}
271 onClick={() => deleteAccount()} 303 buttonType="danger"
272 loaded={!isLoadingDeleteAccount} 304 onClick={() => deleteAccount()}
273 /> 305 loaded={!isLoadingDeleteAccount}
274 </div> 306 />
275 )} 307 </div>
276 {isDeleteAccountSuccessful && ( 308 )}
277 <p>{intl.formatMessage(messages.deleteEmailSent)}</p> 309 {isDeleteAccountSuccessful && (
278 )} 310 <p>{intl.formatMessage(messages.deleteEmailSent)}</p>
311 )}
312 </div>
279 </div> 313 </div>
280 </div> 314 )}
281 </div> 315 </div>
282 )} 316 )}
283
284 </div> 317 </div>
285 <ReactTooltip place="right" type="dark" effect="solid" /> 318 <ReactTooltip place="right" type="dark" effect="solid" />
286 </div> 319 </div>
diff --git a/src/components/settings/navigation/SettingsNavigation.js b/src/components/settings/navigation/SettingsNavigation.js
index 66539f324..b86d94ac7 100644
--- a/src/components/settings/navigation/SettingsNavigation.js
+++ b/src/components/settings/navigation/SettingsNavigation.js
@@ -1,6 +1,7 @@
1import React, { Component } from 'react'; 1import React, { Component } from 'react';
2import PropTypes from 'prop-types'; 2import PropTypes from 'prop-types';
3import { defineMessages, intlShape } from 'react-intl'; 3import { defineMessages, intlShape } from 'react-intl';
4import { inject, observer } from 'mobx-react';
4 5
5import Link from '../../ui/Link'; 6import Link from '../../ui/Link';
6 7
@@ -31,7 +32,7 @@ const messages = defineMessages({
31 }, 32 },
32}); 33});
33 34
34export default class SettingsNavigation extends Component { 35export default @inject('stores') @observer class SettingsNavigation extends Component {
35 static propTypes = { 36 static propTypes = {
36 serviceCount: PropTypes.number.isRequired, 37 serviceCount: PropTypes.number.isRequired,
37 }; 38 };
@@ -92,3 +93,4 @@ export default class SettingsNavigation extends Component {
92 ); 93 );
93 } 94 }
94} 95}
96
diff --git a/src/components/settings/recipes/RecipeItem.js b/src/components/settings/recipes/RecipeItem.js
index 7b2f64d26..dae8891b3 100644
--- a/src/components/settings/recipes/RecipeItem.js
+++ b/src/components/settings/recipes/RecipeItem.js
@@ -4,8 +4,7 @@ import { observer } from 'mobx-react';
4 4
5import RecipePreviewModel from '../../../models/RecipePreview'; 5import RecipePreviewModel from '../../../models/RecipePreview';
6 6
7@observer 7export default @observer class RecipeItem extends Component {
8export default class RecipeItem extends Component {
9 static propTypes = { 8 static propTypes = {
10 recipe: PropTypes.instanceOf(RecipePreviewModel).isRequired, 9 recipe: PropTypes.instanceOf(RecipePreviewModel).isRequired,
11 onClick: PropTypes.func.isRequired, 10 onClick: PropTypes.func.isRequired,
diff --git a/src/components/settings/recipes/RecipesDashboard.js b/src/components/settings/recipes/RecipesDashboard.js
index 4610c69a5..cd783200f 100644
--- a/src/components/settings/recipes/RecipesDashboard.js
+++ b/src/components/settings/recipes/RecipesDashboard.js
@@ -46,8 +46,7 @@ const messages = defineMessages({
46 }, 46 },
47}); 47});
48 48
49@observer 49export default @observer class RecipesDashboard extends Component {
50export default class RecipesDashboard extends Component {
51 static propTypes = { 50 static propTypes = {
52 recipes: MobxPropTypes.arrayOrObservableArray.isRequired, 51 recipes: MobxPropTypes.arrayOrObservableArray.isRequired,
53 isLoading: PropTypes.bool.isRequired, 52 isLoading: PropTypes.bool.isRequired,
diff --git a/src/components/settings/services/EditServiceForm.js b/src/components/settings/services/EditServiceForm.js
index f6f2df2f3..d16ec35b8 100644
--- a/src/components/settings/services/EditServiceForm.js
+++ b/src/components/settings/services/EditServiceForm.js
@@ -15,6 +15,8 @@ import Toggle from '../../ui/Toggle';
15import Button from '../../ui/Button'; 15import Button from '../../ui/Button';
16import ImageUpload from '../../ui/ImageUpload'; 16import ImageUpload from '../../ui/ImageUpload';
17 17
18import PremiumFeatureContainer from '../../ui/PremiumFeatureContainer';
19
18const messages = defineMessages({ 20const messages = defineMessages({
19 saveService: { 21 saveService: {
20 id: 'settings.service.form.saveButton', 22 id: 'settings.service.form.saveButton',
@@ -92,10 +94,17 @@ const messages = defineMessages({
92 id: 'settings.service.form.iconUpload', 94 id: 'settings.service.form.iconUpload',
93 defaultMessage: '!!!Drop your image, or click here', 95 defaultMessage: '!!!Drop your image, or click here',
94 }, 96 },
97 headlineProxy: {
98 id: 'settings.service.form.proxy.headline',
99 defaultMessage: '!!!Proxy Settings',
100 },
101 proxyInfo: {
102 id: 'settings.service.form.proxy.info',
103 defaultMessage: '!!!Proxy settings will not be synchronized with the Franz servers.',
104 },
95}); 105});
96 106
97@observer 107export default @observer class EditServiceForm extends Component {
98export default class EditServiceForm extends Component {
99 static propTypes = { 108 static propTypes = {
100 recipe: PropTypes.instanceOf(Recipe).isRequired, 109 recipe: PropTypes.instanceOf(Recipe).isRequired,
101 service(props, propName) { 110 service(props, propName) {
@@ -113,6 +122,8 @@ export default class EditServiceForm extends Component {
113 onDelete: PropTypes.func.isRequired, 122 onDelete: PropTypes.func.isRequired,
114 isSaving: PropTypes.bool.isRequired, 123 isSaving: PropTypes.bool.isRequired,
115 isDeleting: PropTypes.bool.isRequired, 124 isDeleting: PropTypes.bool.isRequired,
125 isProxyFeatureEnabled: PropTypes.bool.isRequired,
126 isProxyFeaturePremiumFeature: PropTypes.bool.isRequired,
116 }; 127 };
117 128
118 static defaultProps = { 129 static defaultProps = {
@@ -173,6 +184,8 @@ export default class EditServiceForm extends Component {
173 isSaving, 184 isSaving,
174 isDeleting, 185 isDeleting,
175 onDelete, 186 onDelete,
187 isProxyFeatureEnabled,
188 isProxyFeaturePremiumFeature,
176 } = this.props; 189 } = this.props;
177 const { intl } = this.context; 190 const { intl } = this.context;
178 191
@@ -202,6 +215,8 @@ export default class EditServiceForm extends Component {
202 activeTabIndex = 2; 215 activeTabIndex = 2;
203 } 216 }
204 217
218 const requiresUserInput = !recipe.hasHostedOption && (recipe.hasTeamId || recipe.hasCustomUrl);
219
205 return ( 220 return (
206 <div className="settings__main"> 221 <div className="settings__main">
207 <div className="settings__header"> 222 <div className="settings__header">
@@ -303,6 +318,9 @@ export default class EditServiceForm extends Component {
303 318
304 <div className="settings__settings-group"> 319 <div className="settings__settings-group">
305 <h3>{intl.formatMessage(messages.headlineGeneral)}</h3> 320 <h3>{intl.formatMessage(messages.headlineGeneral)}</h3>
321 {recipe.hasDarkMode && (
322 <Toggle field={form.$('isDarkModeEnabled')} />
323 )}
306 <Toggle field={form.$('isEnabled')} /> 324 <Toggle field={form.$('isEnabled')} />
307 </div> 325 </div>
308 </div> 326 </div>
@@ -314,6 +332,33 @@ export default class EditServiceForm extends Component {
314 /> 332 />
315 </div> 333 </div>
316 </div> 334 </div>
335
336 {isProxyFeatureEnabled && (
337 <PremiumFeatureContainer condition={isProxyFeaturePremiumFeature}>
338 <div className="settings__settings-group">
339 <h3>
340 {intl.formatMessage(messages.headlineProxy)}
341 <span className="badge badge--success">beta</span>
342 </h3>
343 <Toggle field={form.$('proxy.isEnabled')} />
344 {form.$('proxy.isEnabled').value && (
345 <div>
346 <Input field={form.$('proxy.host')} />
347 <Input field={form.$('proxy.user')} />
348 <Input
349 field={form.$('proxy.password')}
350 showPasswordToggle
351 />
352 <p>
353 <span className="mdi mdi-information" />
354 {intl.formatMessage(messages.proxyInfo)}
355 </p>
356 </div>
357 )}
358 </div>
359 </PremiumFeatureContainer>
360 )}
361
317 {recipe.message && ( 362 {recipe.message && (
318 <p className="settings__message"> 363 <p className="settings__message">
319 <span className="mdi mdi-information" /> 364 <span className="mdi mdi-information" />
@@ -340,6 +385,7 @@ export default class EditServiceForm extends Component {
340 type="submit" 385 type="submit"
341 label={intl.formatMessage(messages.saveService)} 386 label={intl.formatMessage(messages.saveService)}
342 htmlForm="form" 387 htmlForm="form"
388 disabled={action !== 'edit' && form.isPristine && requiresUserInput}
343 /> 389 />
344 )} 390 )}
345 </div> 391 </div>
diff --git a/src/components/settings/services/ServiceError.js b/src/components/settings/services/ServiceError.js
index 1f1512927..3cfc080d6 100644
--- a/src/components/settings/services/ServiceError.js
+++ b/src/components/settings/services/ServiceError.js
@@ -25,8 +25,7 @@ const messages = defineMessages({
25 }, 25 },
26}); 26});
27 27
28@observer 28export default @observer class ServiceError extends Component {
29export default class ServiceError extends Component {
30 static contextTypes = { 29 static contextTypes = {
31 intl: intlShape, 30 intl: intlShape,
32 }; 31 };
diff --git a/src/components/settings/services/ServiceItem.js b/src/components/settings/services/ServiceItem.js
index 9743315b0..84080519b 100644
--- a/src/components/settings/services/ServiceItem.js
+++ b/src/components/settings/services/ServiceItem.js
@@ -22,8 +22,7 @@ const messages = defineMessages({
22 }, 22 },
23}); 23});
24 24
25@observer 25export default @observer class ServiceItem extends Component {
26export default class ServiceItem extends Component {
27 static propTypes = { 26 static propTypes = {
28 service: PropTypes.instanceOf(ServiceModel).isRequired, 27 service: PropTypes.instanceOf(ServiceModel).isRequired,
29 goToServiceForm: PropTypes.func.isRequired, 28 goToServiceForm: PropTypes.func.isRequired,
diff --git a/src/components/settings/services/ServicesDashboard.js b/src/components/settings/services/ServicesDashboard.js
index 20e451f01..e7dfaf106 100644
--- a/src/components/settings/services/ServicesDashboard.js
+++ b/src/components/settings/services/ServicesDashboard.js
@@ -49,8 +49,7 @@ const messages = defineMessages({
49 }, 49 },
50}); 50});
51 51
52@observer 52export default @observer class ServicesDashboard extends Component {
53export default class ServicesDashboard extends Component {
54 static propTypes = { 53 static propTypes = {
55 services: MobxPropTypes.arrayOrObservableArray.isRequired, 54 services: MobxPropTypes.arrayOrObservableArray.isRequired,
56 isLoading: PropTypes.bool.isRequired, 55 isLoading: PropTypes.bool.isRequired,
diff --git a/src/components/settings/settings/EditSettingsForm.js b/src/components/settings/settings/EditSettingsForm.js
index 97f535594..1ec2ab614 100644
--- a/src/components/settings/settings/EditSettingsForm.js
+++ b/src/components/settings/settings/EditSettingsForm.js
@@ -8,6 +8,7 @@ import Form from '../../../lib/Form';
8import Button from '../../ui/Button'; 8import Button from '../../ui/Button';
9import Toggle from '../../ui/Toggle'; 9import Toggle from '../../ui/Toggle';
10import Select from '../../ui/Select'; 10import Select from '../../ui/Select';
11import PremiumFeatureContainer from '../../ui/PremiumFeatureContainer';
11 12
12import { FRANZ_TRANSLATION } from '../../../config'; 13import { FRANZ_TRANSLATION } from '../../../config';
13 14
@@ -82,8 +83,7 @@ const messages = defineMessages({
82 }, 83 },
83}); 84});
84 85
85@observer 86export default @observer class EditSettingsForm extends Component {
86export default class EditSettingsForm extends Component {
87 static propTypes = { 87 static propTypes = {
88 checkForUpdates: PropTypes.func.isRequired, 88 checkForUpdates: PropTypes.func.isRequired,
89 installUpdate: PropTypes.func.isRequired, 89 installUpdate: PropTypes.func.isRequired,
@@ -96,6 +96,7 @@ export default class EditSettingsForm extends Component {
96 isClearingAllCache: PropTypes.bool.isRequired, 96 isClearingAllCache: PropTypes.bool.isRequired,
97 onClearAllCache: PropTypes.func.isRequired, 97 onClearAllCache: PropTypes.func.isRequired,
98 cacheSize: PropTypes.string.isRequired, 98 cacheSize: PropTypes.string.isRequired,
99 isSpellcheckerPremiumFeature: PropTypes.bool.isRequired,
99 }; 100 };
100 101
101 static contextTypes = { 102 static contextTypes = {
@@ -125,6 +126,7 @@ export default class EditSettingsForm extends Component {
125 isClearingAllCache, 126 isClearingAllCache,
126 onClearAllCache, 127 onClearAllCache,
127 cacheSize, 128 cacheSize,
129 isSpellcheckerPremiumFeature,
128 } = this.props; 130 } = this.props;
129 const { intl } = this.context; 131 const { intl } = this.context;
130 132
@@ -161,10 +163,23 @@ export default class EditSettingsForm extends Component {
161 <h2 id="apperance">{intl.formatMessage(messages.headlineAppearance)}</h2> 163 <h2 id="apperance">{intl.formatMessage(messages.headlineAppearance)}</h2>
162 <Toggle field={form.$('showDisabledServices')} /> 164 <Toggle field={form.$('showDisabledServices')} />
163 <Toggle field={form.$('showMessageBadgeWhenMuted')} /> 165 <Toggle field={form.$('showMessageBadgeWhenMuted')} />
166 <Toggle field={form.$('darkMode')} />
164 167
165 {/* Language */} 168 {/* Language */}
166 <h2 id="language">{intl.formatMessage(messages.headlineLanguage)}</h2> 169 <h2 id="language">{intl.formatMessage(messages.headlineLanguage)}</h2>
167 <Select field={form.$('locale')} showLabel={false} /> 170 <Select field={form.$('locale')} showLabel={false} />
171 <PremiumFeatureContainer
172 condition={isSpellcheckerPremiumFeature}
173 >
174 <div>
175 <Toggle
176 field={form.$('enableSpellchecking')}
177 />
178 {form.$('enableSpellchecking').value && (
179 <Select field={form.$('spellcheckerLanguage')} />
180 )}
181 </div>
182 </PremiumFeatureContainer>
168 <a 183 <a
169 href={FRANZ_TRANSLATION} 184 href={FRANZ_TRANSLATION}
170 target="_blank" 185 target="_blank"
@@ -175,10 +190,8 @@ export default class EditSettingsForm extends Component {
175 190
176 {/* Advanced */} 191 {/* Advanced */}
177 <h2 id="advanced">{intl.formatMessage(messages.headlineAdvanced)}</h2> 192 <h2 id="advanced">{intl.formatMessage(messages.headlineAdvanced)}</h2>
178 <Toggle field={form.$('enableSpellchecking')} />
179 <Toggle field={form.$('enableGPUAcceleration')} /> 193 <Toggle field={form.$('enableGPUAcceleration')} />
180 <p className="settings__help">{intl.formatMessage(messages.enableGPUAccelerationInfo)}</p> 194 <p className="settings__help">{intl.formatMessage(messages.enableGPUAccelerationInfo)}</p>
181 {/* <Select field={form.$('spellcheckingLanguage')} /> */}
182 <div className="settings__settings-group"> 195 <div className="settings__settings-group">
183 <h3> 196 <h3>
184 {intl.formatMessage(messages.subheadlineCache)} 197 {intl.formatMessage(messages.subheadlineCache)}
diff --git a/src/components/settings/user/EditUserForm.js b/src/components/settings/user/EditUserForm.js
index f36887fc2..b825f844a 100644
--- a/src/components/settings/user/EditUserForm.js
+++ b/src/components/settings/user/EditUserForm.js
@@ -39,13 +39,13 @@ const messages = defineMessages({
39 }, 39 },
40}); 40});
41 41
42@observer 42export default @observer class EditServiceForm extends Component {
43export default class EditServiceForm extends Component {
44 static propTypes = { 43 static propTypes = {
45 status: MobxPropTypes.observableArray.isRequired, 44 status: MobxPropTypes.observableArray.isRequired,
46 form: PropTypes.instanceOf(Form).isRequired, 45 form: PropTypes.instanceOf(Form).isRequired,
47 onSubmit: PropTypes.func.isRequired, 46 onSubmit: PropTypes.func.isRequired,
48 isSaving: PropTypes.bool.isRequired, 47 isSaving: PropTypes.bool.isRequired,
48 isEnterprise: PropTypes.bool.isRequired,
49 }; 49 };
50 50
51 static defaultProps = { 51 static defaultProps = {
@@ -72,6 +72,7 @@ export default class EditServiceForm extends Component {
72 // user, 72 // user,
73 status, 73 status,
74 form, 74 form,
75 isEnterprise,
75 isSaving, 76 isSaving,
76 } = this.props; 77 } = this.props;
77 const { intl } = this.context; 78 const { intl } = this.context;
@@ -105,8 +106,10 @@ export default class EditServiceForm extends Component {
105 <Input field={form.$('lastname')} /> 106 <Input field={form.$('lastname')} />
106 </div> 107 </div>
107 <Input field={form.$('email')} /> 108 <Input field={form.$('email')} />
108 <Radio field={form.$('accountType')} /> 109 {!isEnterprise && (
109 {form.$('accountType').value === 'company' && ( 110 <Radio field={form.$('accountType')} />
111 )}
112 {!isEnterprise && form.$('accountType').value === 'company' && (
110 <Input field={form.$('organization')} /> 113 <Input field={form.$('organization')} />
111 )} 114 )}
112 <h2>{intl.formatMessage(messages.headlinePassword)}</h2> 115 <h2>{intl.formatMessage(messages.headlinePassword)}</h2>
diff --git a/src/components/subscription/SubscriptionForm.js b/src/components/subscription/SubscriptionForm.js
index dd350479d..12e8471ff 100644
--- a/src/components/subscription/SubscriptionForm.js
+++ b/src/components/subscription/SubscriptionForm.js
@@ -36,25 +36,21 @@ const messages = defineMessages({
36 defaultMessage: '!!!The Franz Premium Supporter Account includes', 36 defaultMessage: '!!!The Franz Premium Supporter Account includes',
37 }, 37 },
38 features: { 38 features: {
39 unlimitedServices: {
40 id: 'subscription.features.unlimitedServices',
41 defaultMessage: '!!!Add unlimited services',
42 },
43 onpremise: { 39 onpremise: {
44 id: 'subscription.features.onpremise', 40 id: 'subscription.features.onpremise.mattermost',
45 defaultMessage: '!!!Add on-premise/hosted services like HipChat', 41 defaultMessage: '!!!Add on-premise/hosted services like Mattermost',
46 }, 42 },
47 customServices: { 43 noInterruptions: {
48 id: 'subscription.features.customServices', 44 id: 'subscription.features.noInterruptions',
49 defaultMessage: '!!!Add your custom services', 45 defaultMessage: '!!!No app delays & nagging to upgrade license',
50 }, 46 },
51 encryptedSync: { 47 proxy: {
52 id: 'subscription.features.encryptedSync', 48 id: 'subscription.features.proxy',
53 defaultMessage: '!!!Encrypted session synchronization', 49 defaultMessage: '!!!Proxy support for services',
54 }, 50 },
55 vpn: { 51 spellchecker: {
56 id: 'subscription.features.vpn', 52 id: 'subscription.features.spellchecker',
57 defaultMessage: '!!!Proxy & VPN support', 53 defaultMessage: '!!!Support for Spellchecker',
58 }, 54 },
59 ads: { 55 ads: {
60 id: 'subscription.features.ads', 56 id: 'subscription.features.ads',
@@ -71,8 +67,7 @@ const messages = defineMessages({
71 }, 67 },
72}); 68});
73 69
74@observer 70export default @observer class SubscriptionForm extends Component {
75export default class SubscriptionForm extends Component {
76 static propTypes = { 71 static propTypes = {
77 plan: MobxPropTypes.objectOrObservableObject.isRequired, 72 plan: MobxPropTypes.objectOrObservableObject.isRequired,
78 isLoading: PropTypes.bool.isRequired, 73 isLoading: PropTypes.bool.isRequired,
@@ -171,16 +166,13 @@ export default class SubscriptionForm extends Component {
171 <ul className="subscription__premium-features"> 166 <ul className="subscription__premium-features">
172 <li>{intl.formatMessage(messages.features.onpremise)}</li> 167 <li>{intl.formatMessage(messages.features.onpremise)}</li>
173 <li> 168 <li>
174 {intl.formatMessage(messages.features.encryptedSync)} 169 {intl.formatMessage(messages.features.noInterruptions)}
175 <span className="badge">{intl.formatMessage(messages.features.comingSoon)}</span>
176 </li> 170 </li>
177 <li> 171 <li>
178 {intl.formatMessage(messages.features.customServices)} 172 {intl.formatMessage(messages.features.spellchecker)}
179 <span className="badge">{intl.formatMessage(messages.features.comingSoon)}</span>
180 </li> 173 </li>
181 <li> 174 <li>
182 {intl.formatMessage(messages.features.vpn)} 175 {intl.formatMessage(messages.features.proxy)}
183 <span className="badge">{intl.formatMessage(messages.features.comingSoon)}</span>
184 </li> 176 </li>
185 <li> 177 <li>
186 {intl.formatMessage(messages.features.ads)} 178 {intl.formatMessage(messages.features.ads)}
diff --git a/src/components/subscription/SubscriptionPopup.js b/src/components/subscription/SubscriptionPopup.js
index 528d02907..f3c63e7ee 100644
--- a/src/components/subscription/SubscriptionPopup.js
+++ b/src/components/subscription/SubscriptionPopup.js
@@ -17,8 +17,7 @@ const messages = defineMessages({
17 }, 17 },
18}); 18});
19 19
20@observer 20export default @observer class SubscriptionPopup extends Component {
21export default class SubscriptionPopup extends Component {
22 static propTypes = { 21 static propTypes = {
23 url: PropTypes.string.isRequired, 22 url: PropTypes.string.isRequired,
24 closeWindow: PropTypes.func.isRequired, 23 closeWindow: PropTypes.func.isRequired,
diff --git a/src/components/ui/Button.js b/src/components/ui/Button.js
index 554206cb7..309e05bb4 100644
--- a/src/components/ui/Button.js
+++ b/src/components/ui/Button.js
@@ -4,8 +4,7 @@ import { observer } from 'mobx-react';
4import Loader from 'react-loader'; 4import Loader from 'react-loader';
5import classnames from 'classnames'; 5import classnames from 'classnames';
6 6
7@observer 7export default @observer class Button extends Component {
8export default class Button extends Component {
9 static propTypes = { 8 static propTypes = {
10 className: PropTypes.string, 9 className: PropTypes.string,
11 label: PropTypes.string.isRequired, 10 label: PropTypes.string.isRequired,
diff --git a/src/components/ui/ImageUpload.js b/src/components/ui/ImageUpload.js
index 81c3b8da6..76f77d631 100644
--- a/src/components/ui/ImageUpload.js
+++ b/src/components/ui/ImageUpload.js
@@ -2,12 +2,10 @@ import React, { Component } from 'react';
2import PropTypes from 'prop-types'; 2import PropTypes from 'prop-types';
3import { observer } from 'mobx-react'; 3import { observer } from 'mobx-react';
4import { Field } from 'mobx-react-form'; 4import { Field } from 'mobx-react-form';
5// import Loader from 'react-loader';
6import classnames from 'classnames'; 5import classnames from 'classnames';
7import Dropzone from 'react-dropzone'; 6import Dropzone from 'react-dropzone';
8 7
9@observer 8export default @observer class ImageUpload extends Component {
10export default class ImageUpload extends Component {
11 static propTypes = { 9 static propTypes = {
12 field: PropTypes.instanceOf(Field).isRequired, 10 field: PropTypes.instanceOf(Field).isRequired,
13 className: PropTypes.string, 11 className: PropTypes.string,
diff --git a/src/components/ui/InfoBar.js b/src/components/ui/InfoBar.js
index 84a5f1446..94a1ddf76 100644
--- a/src/components/ui/InfoBar.js
+++ b/src/components/ui/InfoBar.js
@@ -7,8 +7,7 @@ import Loader from 'react-loader';
7// import { oneOrManyChildElements } from '../../prop-types'; 7// import { oneOrManyChildElements } from '../../prop-types';
8import Appear from '../ui/effects/Appear'; 8import Appear from '../ui/effects/Appear';
9 9
10@observer 10export default @observer class InfoBar extends Component {
11export default class InfoBar extends Component {
12 static propTypes = { 11 static propTypes = {
13 // eslint-disable-next-line 12 // eslint-disable-next-line
14 children: PropTypes.any.isRequired, 13 children: PropTypes.any.isRequired,
diff --git a/src/components/ui/Infobox.js b/src/components/ui/Infobox.js
index 2d063c7ef..77051f567 100644
--- a/src/components/ui/Infobox.js
+++ b/src/components/ui/Infobox.js
@@ -4,8 +4,7 @@ import { observer } from 'mobx-react';
4import classnames from 'classnames'; 4import classnames from 'classnames';
5import Loader from 'react-loader'; 5import Loader from 'react-loader';
6 6
7@observer 7export default @observer class Infobox extends Component {
8export default class Infobox extends Component {
9 static propTypes = { 8 static propTypes = {
10 children: PropTypes.any.isRequired, // eslint-disable-line 9 children: PropTypes.any.isRequired, // eslint-disable-line
11 icon: PropTypes.string, 10 icon: PropTypes.string,
diff --git a/src/components/ui/Input.js b/src/components/ui/Input.js
index 0bb9f23bf..7bf6e1b00 100644
--- a/src/components/ui/Input.js
+++ b/src/components/ui/Input.js
@@ -6,8 +6,7 @@ import classnames from 'classnames';
6 6
7import { scorePassword as scorePasswordFunc } from '../../helpers/password-helpers'; 7import { scorePassword as scorePasswordFunc } from '../../helpers/password-helpers';
8 8
9@observer 9export default @observer class Input extends Component {
10export default class Input extends Component {
11 static propTypes = { 10 static propTypes = {
12 field: PropTypes.instanceOf(Field).isRequired, 11 field: PropTypes.instanceOf(Field).isRequired,
13 className: PropTypes.string, 12 className: PropTypes.string,
@@ -97,6 +96,7 @@ export default class Input extends Component {
97 onBlur={field.onBlur} 96 onBlur={field.onBlur}
98 onFocus={field.onFocus} 97 onFocus={field.onFocus}
99 ref={(element) => { this.inputElement = element; }} 98 ref={(element) => { this.inputElement = element; }}
99 disabled={field.disabled}
100 /> 100 />
101 {suffix && ( 101 {suffix && (
102 <span className="franz-form__input-suffix">{suffix}</span> 102 <span className="franz-form__input-suffix">{suffix}</span>
diff --git a/src/components/ui/Link.js b/src/components/ui/Link.js
index f5da921fa..0602290f1 100644
--- a/src/components/ui/Link.js
+++ b/src/components/ui/Link.js
@@ -9,9 +9,7 @@ import { oneOrManyChildElements } from '../../prop-types';
9import { matchRoute } from '../../helpers/routing-helpers'; 9import { matchRoute } from '../../helpers/routing-helpers';
10 10
11// TODO: create container component for this component 11// TODO: create container component for this component
12 12export default @inject('stores') @observer class Link extends Component {
13@inject('stores') @observer
14export default class Link extends Component {
15 onClick(e) { 13 onClick(e) {
16 if (this.props.target === '_blank') { 14 if (this.props.target === '_blank') {
17 e.preventDefault(); 15 e.preventDefault();
diff --git a/src/components/ui/PremiumFeatureContainer/index.js b/src/components/ui/PremiumFeatureContainer/index.js
new file mode 100644
index 000000000..73984be94
--- /dev/null
+++ b/src/components/ui/PremiumFeatureContainer/index.js
@@ -0,0 +1,76 @@
1import React, { Component } from 'react';
2import { inject, observer } from 'mobx-react';
3import PropTypes from 'prop-types';
4import { defineMessages, intlShape } from 'react-intl';
5import injectSheet from 'react-jss';
6
7import { oneOrManyChildElements } from '../../../prop-types';
8
9import UserStore from '../../../stores/UserStore';
10
11import styles from './styles';
12
13const messages = defineMessages({
14 action: {
15 id: 'premiumFeature.button.upgradeAccount',
16 defaultMessage: '!!!Upgrade account',
17 },
18});
19
20export default @inject('stores', 'actions') @injectSheet(styles) @observer class PremiumFeatureContainer extends Component {
21 static propTypes = {
22 classes: PropTypes.object.isRequired,
23 condition: PropTypes.bool,
24 };
25
26 static defaultProps = {
27 condition: true,
28 };
29
30 static contextTypes = {
31 intl: intlShape,
32 };
33
34 render() {
35 const {
36 classes,
37 children,
38 actions,
39 condition,
40 stores,
41 } = this.props;
42
43 const { intl } = this.context;
44
45 return !stores.user.data.isPremium && !!condition ? (
46 <div className={classes.container}>
47 <div className={classes.titleContainer}>
48 <p className={classes.title}>Premium Feature</p>
49 <button
50 className={classes.actionButton}
51 type="button"
52 onClick={() => actions.ui.openSettings({ path: 'user' })}
53 >
54 {intl.formatMessage(messages.action)}
55 </button>
56 </div>
57 <div className={classes.content}>
58 {children}
59 </div>
60 </div>
61 ) : children;
62 }
63}
64
65PremiumFeatureContainer.wrappedComponent.propTypes = {
66 children: oneOrManyChildElements.isRequired,
67 stores: PropTypes.shape({
68 user: PropTypes.instanceOf(UserStore).isRequired,
69 }).isRequired,
70 actions: PropTypes.shape({
71 ui: PropTypes.shape({
72 openSettings: PropTypes.func.isRequired,
73 }).isRequired,
74 }).isRequired,
75};
76
diff --git a/src/components/ui/PremiumFeatureContainer/styles.js b/src/components/ui/PremiumFeatureContainer/styles.js
new file mode 100644
index 000000000..16c40d0ec
--- /dev/null
+++ b/src/components/ui/PremiumFeatureContainer/styles.js
@@ -0,0 +1,31 @@
1export default theme => ({
2 container: {
3 background: theme.colorSubscriptionContainerBackground,
4 border: theme.colorSubscriptionContainerBorder,
5 margin: [0, 0, 20, -20],
6 padding: 20,
7 'border-radius': theme.borderRadius,
8 },
9 titleContainer: {
10 display: 'flex',
11 },
12 title: {
13 'font-weight': 'bold',
14 color: theme.colorSubscriptionContainerTitle,
15 },
16 actionButton: {
17 background: theme.colorSubscriptionContainerActionButtonBackground,
18 color: theme.colorSubscriptionContainerActionButtonColor,
19 'margin-left': 'auto',
20 'border-radius': theme.borderRadiusSmall,
21 padding: [2, 4],
22 'font-size': 12,
23 },
24 content: {
25 opacity: 0.5,
26 'margin-top': 20,
27 '& :last-child': {
28 'margin-bottom': 0,
29 },
30 },
31});
diff --git a/src/components/ui/Radio.js b/src/components/ui/Radio.js
index b54cfc820..63ca6f9b8 100644
--- a/src/components/ui/Radio.js
+++ b/src/components/ui/Radio.js
@@ -4,8 +4,7 @@ import { observer } from 'mobx-react';
4import { Field } from 'mobx-react-form'; 4import { Field } from 'mobx-react-form';
5import classnames from 'classnames'; 5import classnames from 'classnames';
6 6
7@observer 7export default @observer class Radio extends Component {
8export default class Radio extends Component {
9 static propTypes = { 8 static propTypes = {
10 field: PropTypes.instanceOf(Field).isRequired, 9 field: PropTypes.instanceOf(Field).isRequired,
11 className: PropTypes.string, 10 className: PropTypes.string,
diff --git a/src/components/ui/SearchInput.js b/src/components/ui/SearchInput.js
index a94cde201..5a9571d27 100644
--- a/src/components/ui/SearchInput.js
+++ b/src/components/ui/SearchInput.js
@@ -5,8 +5,7 @@ import classnames from 'classnames';
5import uuidv1 from 'uuid/v1'; 5import uuidv1 from 'uuid/v1';
6import { debounce } from 'lodash'; 6import { debounce } from 'lodash';
7 7
8@observer 8export default @observer class SearchInput extends Component {
9export default class SearchInput extends Component {
10 static propTypes = { 9 static propTypes = {
11 value: PropTypes.string, 10 value: PropTypes.string,
12 placeholder: PropTypes.string, 11 placeholder: PropTypes.string,
diff --git a/src/components/ui/Select.js b/src/components/ui/Select.js
index 2a877af3e..abcad417e 100644
--- a/src/components/ui/Select.js
+++ b/src/components/ui/Select.js
@@ -4,8 +4,7 @@ import { observer } from 'mobx-react';
4import { Field } from 'mobx-react-form'; 4import { Field } from 'mobx-react-form';
5import classnames from 'classnames'; 5import classnames from 'classnames';
6 6
7@observer 7export default @observer class Select extends Component {
8export default class Select extends Component {
9 static propTypes = { 8 static propTypes = {
10 field: PropTypes.instanceOf(Field).isRequired, 9 field: PropTypes.instanceOf(Field).isRequired,
11 className: PropTypes.string, 10 className: PropTypes.string,
diff --git a/src/components/ui/StatusBarTargetUrl.js b/src/components/ui/StatusBarTargetUrl.js
index b7b198f42..4285a343c 100644
--- a/src/components/ui/StatusBarTargetUrl.js
+++ b/src/components/ui/StatusBarTargetUrl.js
@@ -5,8 +5,7 @@ import classnames from 'classnames';
5 5
6import Appear from '../ui/effects/Appear'; 6import Appear from '../ui/effects/Appear';
7 7
8@observer 8export default @observer class StatusBarTargetUrl extends Component {
9export default class StatusBarTargetUrl extends Component {
10 static propTypes = { 9 static propTypes = {
11 className: PropTypes.string, 10 className: PropTypes.string,
12 text: PropTypes.string, 11 text: PropTypes.string,
diff --git a/src/components/ui/Tabs/Tabs.js b/src/components/ui/Tabs/Tabs.js
index 50397f9bb..12f650ffd 100644
--- a/src/components/ui/Tabs/Tabs.js
+++ b/src/components/ui/Tabs/Tabs.js
@@ -5,8 +5,7 @@ import classnames from 'classnames';
5 5
6import { oneOrManyChildElements } from '../../../prop-types'; 6import { oneOrManyChildElements } from '../../../prop-types';
7 7
8@observer 8export default @observer class Tab extends Component {
9export default class Tab extends Component {
10 static propTypes = { 9 static propTypes = {
11 children: oneOrManyChildElements.isRequired, 10 children: oneOrManyChildElements.isRequired,
12 active: PropTypes.number, 11 active: PropTypes.number,
diff --git a/src/components/ui/Toggle.js b/src/components/ui/Toggle.js
index 62d46393e..78fb77cbe 100644
--- a/src/components/ui/Toggle.js
+++ b/src/components/ui/Toggle.js
@@ -4,17 +4,18 @@ import { observer } from 'mobx-react';
4import classnames from 'classnames'; 4import classnames from 'classnames';
5import { Field } from 'mobx-react-form'; 5import { Field } from 'mobx-react-form';
6 6
7@observer 7export default @observer class Toggle extends Component {
8export default class Toggle extends Component {
9 static propTypes = { 8 static propTypes = {
10 field: PropTypes.instanceOf(Field).isRequired, 9 field: PropTypes.instanceOf(Field).isRequired,
11 className: PropTypes.string, 10 className: PropTypes.string,
12 showLabel: PropTypes.bool, 11 showLabel: PropTypes.bool,
12 disabled: PropTypes.bool,
13 }; 13 };
14 14
15 static defaultProps = { 15 static defaultProps = {
16 className: '', 16 className: '',
17 showLabel: true, 17 showLabel: true,
18 disabled: false,
18 }; 19 };
19 20
20 onChange(e) { 21 onChange(e) {
@@ -28,6 +29,7 @@ export default class Toggle extends Component {
28 field, 29 field,
29 className, 30 className,
30 showLabel, 31 showLabel,
32 disabled,
31 } = this.props; 33 } = this.props;
32 34
33 if (field.value === '' && field.default !== '') { 35 if (field.value === '' && field.default !== '') {
@@ -39,6 +41,7 @@ export default class Toggle extends Component {
39 className={classnames([ 41 className={classnames([
40 'franz-form__field', 42 'franz-form__field',
41 'franz-form__toggle-wrapper', 43 'franz-form__toggle-wrapper',
44 'franz-form__toggle-disabled',
42 className, 45 className,
43 ])} 46 ])}
44 > 47 >
@@ -56,7 +59,7 @@ export default class Toggle extends Component {
56 name={field.name} 59 name={field.name}
57 value={field.name} 60 value={field.name}
58 checked={field.value} 61 checked={field.value}
59 onChange={e => this.onChange(e)} 62 onChange={e => (!disabled ? this.onChange(e) : null)}
60 /> 63 />
61 </label> 64 </label>
62 {field.error && <div className={field.error}>{field.error}</div>} 65 {field.error && <div className={field.error}>{field.error}</div>}