aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/components/settings/account/AccountDashboard.js86
-rw-r--r--src/components/settings/navigation/SettingsNavigation.js28
-rw-r--r--src/components/settings/services/EditServiceForm.js4
-rw-r--r--src/components/settings/user/EditUserForm.js8
-rw-r--r--src/components/ui/Input.js1
-rw-r--r--src/containers/layout/AppLayoutContainer.js4
-rw-r--r--src/containers/settings/EditServiceScreen.js12
-rw-r--r--src/containers/settings/EditUserScreen.js1
-rw-r--r--src/models/User.js17
-rw-r--r--src/styles/badge.scss6
10 files changed, 127 insertions, 40 deletions
diff --git a/src/components/settings/account/AccountDashboard.js b/src/components/settings/account/AccountDashboard.js
index 4992f0913..e6ccdaac7 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',
@@ -167,17 +171,21 @@ export default class AccountDashboard extends Component {
167 </h2> 171 </h2>
168 {user.organization && `${user.organization}, `} 172 {user.organization && `${user.organization}, `}
169 {user.email}<br /> 173 {user.email}<br />
170 {!user.isPremium && ( 174 {!user.isEnterprise && !user.isPremium && (
171 <span className="badge badge">{intl.formatMessage(messages.accountTypeBasic)}</span> 175 <span className="badge badge">{intl.formatMessage(messages.accountTypeBasic)}</span>
172 )} 176 )}
173 {user.isPremium && ( 177 {user.isPremium && (
174 <span className="badge badge--premium">{intl.formatMessage(messages.accountTypePremium)}</span> 178 <span className="badge badge--premium">{intl.formatMessage(messages.accountTypePremium)}</span>
175 )} 179 )}
180 {user.isEnterprise && (
181 <span className="badge badge--success">{intl.formatMessage(messages.accountTypeEnterprise)}</span>
182 )}
176 </div> 183 </div>
177 <Link to="/settings/user/edit" className="button"> 184 {!user.isSSO && (
178 {intl.formatMessage(messages.accountEditButton)} 185 <Link to="/settings/user/edit" className="button">
179 </Link> 186 {intl.formatMessage(messages.accountEditButton)}
180 187 </Link>
188 )}
181 {user.emailValidated} 189 {user.emailValidated}
182 </div> 190 </div>
183 </div> 191 </div>
@@ -230,6 +238,33 @@ export default class AccountDashboard extends Component {
230 ) 238 )
231 )} 239 )}
232 240
241 {user.isEnterprise && (
242 <div className="account">
243 <div className="account__box">
244 <h2>{user.company.name}</h2>
245 <p>
246 Technical contact:&nbsp;
247 <Link
248 className="link"
249 target="_blank"
250 to={`mailto:${user.company.contact.technical}?subject=Franz`}
251 >
252 {user.company.contact.technical}
253 </Link>
254 <br />
255 General contact:&nbsp;
256 <Link
257 className="link"
258 target="_blank"
259 to={`mailto:${user.company.contact.default}?subject=Franz`}
260 >
261 {user.company.contact.default}
262 </Link>
263 </p>
264 </div>
265 </div>
266 )}
267
233 {user.isMiner && ( 268 {user.isMiner && (
234 <div className="account franz-form"> 269 <div className="account franz-form">
235 <div className="account__box account__box"> 270 <div className="account__box account__box">
@@ -244,7 +279,7 @@ export default class AccountDashboard extends Component {
244 </div> 279 </div>
245 )} 280 )}
246 281
247 {!user.isPremium && ( 282 {!user.isEnterprise && !user.isPremium && (
248 isLoadingPlans ? ( 283 isLoadingPlans ? (
249 <Loader /> 284 <Loader />
250 ) : ( 285 ) : (
@@ -259,28 +294,29 @@ export default class AccountDashboard extends Component {
259 ) 294 )
260 )} 295 )}
261 296
262 <div className="account franz-form"> 297 {!user.isEnterprise && (
263 <div className="account__box"> 298 <div className="account franz-form">
264 <h2>{intl.formatMessage(messages.headlineDangerZone)}</h2> 299 <div className="account__box">
265 {!isDeleteAccountSuccessful && ( 300 <h2>{intl.formatMessage(messages.headlineDangerZone)}</h2>
266 <div className="account__subscription"> 301 {!isDeleteAccountSuccessful && (
267 <p>{intl.formatMessage(messages.deleteInfo)}</p> 302 <div className="account__subscription">
268 <Button 303 <p>{intl.formatMessage(messages.deleteInfo)}</p>
269 label={intl.formatMessage(messages.deleteAccount)} 304 <Button
270 buttonType="danger" 305 label={intl.formatMessage(messages.deleteAccount)}
271 onClick={() => deleteAccount()} 306 buttonType="danger"
272 loaded={!isLoadingDeleteAccount} 307 onClick={() => deleteAccount()}
273 /> 308 loaded={!isLoadingDeleteAccount}
274 </div> 309 />
275 )} 310 </div>
276 {isDeleteAccountSuccessful && ( 311 )}
277 <p>{intl.formatMessage(messages.deleteEmailSent)}</p> 312 {isDeleteAccountSuccessful && (
278 )} 313 <p>{intl.formatMessage(messages.deleteEmailSent)}</p>
314 )}
315 </div>
279 </div> 316 </div>
280 </div> 317 )}
281 </div> 318 </div>
282 )} 319 )}
283
284 </div> 320 </div>
285 <ReactTooltip place="right" type="dark" effect="solid" /> 321 <ReactTooltip place="right" type="dark" effect="solid" />
286 </div> 322 </div>
diff --git a/src/components/settings/navigation/SettingsNavigation.js b/src/components/settings/navigation/SettingsNavigation.js
index 66539f324..46b2f82fc 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,6 +32,7 @@ const messages = defineMessages({
31 }, 32 },
32}); 33});
33 34
35@inject('stores') @observer
34export default class SettingsNavigation extends Component { 36export default class SettingsNavigation extends Component {
35 static propTypes = { 37 static propTypes = {
36 serviceCount: PropTypes.number.isRequired, 38 serviceCount: PropTypes.number.isRequired,
@@ -42,17 +44,20 @@ export default class SettingsNavigation extends Component {
42 44
43 render() { 45 render() {
44 const { serviceCount } = this.props; 46 const { serviceCount } = this.props;
47 const { features } = this.props.stores.features;
45 const { intl } = this.context; 48 const { intl } = this.context;
46 49
47 return ( 50 return (
48 <div className="settings-navigation"> 51 <div className="settings-navigation">
49 <Link 52 {features.userCanManageServices && (
50 to="/settings/recipes" 53 <Link
51 className="settings-navigation__link" 54 to="/settings/recipes"
52 activeClassName="is-active" 55 className="settings-navigation__link"
53 > 56 activeClassName="is-active"
54 {intl.formatMessage(messages.availableServices)} 57 >
55 </Link> 58 {intl.formatMessage(messages.availableServices)}
59 </Link>
60 )}
56 <Link 61 <Link
57 to="/settings/services" 62 to="/settings/services"
58 className="settings-navigation__link" 63 className="settings-navigation__link"
@@ -92,3 +97,12 @@ export default class SettingsNavigation extends Component {
92 ); 97 );
93 } 98 }
94} 99}
100
101SettingsNavigation.wrappedComponent.propTypes = {
102 stores: PropTypes.shape({
103 features: PropTypes.shape({
104 features: PropTypes.object.isRequired,
105 }).isRequired,
106 }).isRequired,
107};
108
diff --git a/src/components/settings/services/EditServiceForm.js b/src/components/settings/services/EditServiceForm.js
index f6f2df2f3..3ffca99a7 100644
--- a/src/components/settings/services/EditServiceForm.js
+++ b/src/components/settings/services/EditServiceForm.js
@@ -107,6 +107,7 @@ export default class EditServiceForm extends Component {
107 return null; 107 return null;
108 }, 108 },
109 user: PropTypes.instanceOf(User).isRequired, 109 user: PropTypes.instanceOf(User).isRequired,
110 userCanManageServices: PropTypes.bool.isRequired,
110 action: PropTypes.string.isRequired, 111 action: PropTypes.string.isRequired,
111 form: PropTypes.instanceOf(Form).isRequired, 112 form: PropTypes.instanceOf(Form).isRequired,
112 onSubmit: PropTypes.func.isRequired, 113 onSubmit: PropTypes.func.isRequired,
@@ -169,6 +170,7 @@ export default class EditServiceForm extends Component {
169 service, 170 service,
170 action, 171 action,
171 user, 172 user,
173 userCanManageServices,
172 form, 174 form,
173 isSaving, 175 isSaving,
174 isDeleting, 176 isDeleting,
@@ -324,7 +326,7 @@ export default class EditServiceForm extends Component {
324 </div> 326 </div>
325 <div className="settings__controls"> 327 <div className="settings__controls">
326 {/* Delete Button */} 328 {/* Delete Button */}
327 {action === 'edit' && deleteButton} 329 {action === 'edit' && userCanManageServices && deleteButton}
328 330
329 {/* Save Button */} 331 {/* Save Button */}
330 {isSaving || isValidatingCustomUrl ? ( 332 {isSaving || isValidatingCustomUrl ? (
diff --git a/src/components/settings/user/EditUserForm.js b/src/components/settings/user/EditUserForm.js
index f36887fc2..1ac8be80f 100644
--- a/src/components/settings/user/EditUserForm.js
+++ b/src/components/settings/user/EditUserForm.js
@@ -46,6 +46,7 @@ export default class EditServiceForm extends Component {
46 form: PropTypes.instanceOf(Form).isRequired, 46 form: PropTypes.instanceOf(Form).isRequired,
47 onSubmit: PropTypes.func.isRequired, 47 onSubmit: PropTypes.func.isRequired,
48 isSaving: PropTypes.bool.isRequired, 48 isSaving: PropTypes.bool.isRequired,
49 isEnterprise: PropTypes.bool.isRequired,
49 }; 50 };
50 51
51 static defaultProps = { 52 static defaultProps = {
@@ -72,6 +73,7 @@ export default class EditServiceForm extends Component {
72 // user, 73 // user,
73 status, 74 status,
74 form, 75 form,
76 isEnterprise,
75 isSaving, 77 isSaving,
76 } = this.props; 78 } = this.props;
77 const { intl } = this.context; 79 const { intl } = this.context;
@@ -105,8 +107,10 @@ export default class EditServiceForm extends Component {
105 <Input field={form.$('lastname')} /> 107 <Input field={form.$('lastname')} />
106 </div> 108 </div>
107 <Input field={form.$('email')} /> 109 <Input field={form.$('email')} />
108 <Radio field={form.$('accountType')} /> 110 {!isEnterprise && (
109 {form.$('accountType').value === 'company' && ( 111 <Radio field={form.$('accountType')} />
112 )}
113 {!isEnterprise && form.$('accountType').value === 'company' && (
110 <Input field={form.$('organization')} /> 114 <Input field={form.$('organization')} />
111 )} 115 )}
112 <h2>{intl.formatMessage(messages.headlinePassword)}</h2> 116 <h2>{intl.formatMessage(messages.headlinePassword)}</h2>
diff --git a/src/components/ui/Input.js b/src/components/ui/Input.js
index 0bb9f23bf..69c95702b 100644
--- a/src/components/ui/Input.js
+++ b/src/components/ui/Input.js
@@ -97,6 +97,7 @@ export default class Input extends Component {
97 onBlur={field.onBlur} 97 onBlur={field.onBlur}
98 onFocus={field.onFocus} 98 onFocus={field.onFocus}
99 ref={(element) => { this.inputElement = element; }} 99 ref={(element) => { this.inputElement = element; }}
100 disabled={field.disabled}
100 /> 101 />
101 {suffix && ( 102 {suffix && (
102 <span className="franz-form__input-suffix">{suffix}</span> 103 <span className="franz-form__input-suffix">{suffix}</span>
diff --git a/src/containers/layout/AppLayoutContainer.js b/src/containers/layout/AppLayoutContainer.js
index 2db2b7bb7..7a398ed2d 100644
--- a/src/containers/layout/AppLayoutContainer.js
+++ b/src/containers/layout/AppLayoutContainer.js
@@ -5,6 +5,7 @@ import { inject, observer } from 'mobx-react';
5import AppStore from '../../stores/AppStore'; 5import AppStore from '../../stores/AppStore';
6import RecipesStore from '../../stores/RecipesStore'; 6import RecipesStore from '../../stores/RecipesStore';
7import ServicesStore from '../../stores/ServicesStore'; 7import ServicesStore from '../../stores/ServicesStore';
8import FeaturesStore from '../../stores/FeaturesStore';
8import UIStore from '../../stores/UIStore'; 9import UIStore from '../../stores/UIStore';
9import NewsStore from '../../stores/NewsStore'; 10import NewsStore from '../../stores/NewsStore';
10import SettingsStore from '../../stores/SettingsStore'; 11import SettingsStore from '../../stores/SettingsStore';
@@ -66,7 +67,7 @@ export default class AppLayoutContainer extends Component {
66 const { children } = this.props; 67 const { children } = this.props;
67 68
68 const isLoadingFeatures = features.featuresRequest.isExecuting 69 const isLoadingFeatures = features.featuresRequest.isExecuting
69 && features.featuresRequest.isExecutingFirstTime; 70 && !features.featuresRequest.wasExecuted;
70 71
71 const isLoadingServices = services.allServicesRequest.isExecuting 72 const isLoadingServices = services.allServicesRequest.isExecuting
72 && services.allServicesRequest.isExecutingFirstTime; 73 && services.allServicesRequest.isExecutingFirstTime;
@@ -134,6 +135,7 @@ export default class AppLayoutContainer extends Component {
134AppLayoutContainer.wrappedComponent.propTypes = { 135AppLayoutContainer.wrappedComponent.propTypes = {
135 stores: PropTypes.shape({ 136 stores: PropTypes.shape({
136 services: PropTypes.instanceOf(ServicesStore).isRequired, 137 services: PropTypes.instanceOf(ServicesStore).isRequired,
138 features: PropTypes.instanceOf(FeaturesStore).isRequired,
137 recipes: PropTypes.instanceOf(RecipesStore).isRequired, 139 recipes: PropTypes.instanceOf(RecipesStore).isRequired,
138 app: PropTypes.instanceOf(AppStore).isRequired, 140 app: PropTypes.instanceOf(AppStore).isRequired,
139 ui: PropTypes.instanceOf(UIStore).isRequired, 141 ui: PropTypes.instanceOf(UIStore).isRequired,
diff --git a/src/containers/settings/EditServiceScreen.js b/src/containers/settings/EditServiceScreen.js
index 67c2731fc..f2d5550e1 100644
--- a/src/containers/settings/EditServiceScreen.js
+++ b/src/containers/settings/EditServiceScreen.js
@@ -6,6 +6,7 @@ import { defineMessages, intlShape } from 'react-intl';
6import UserStore from '../../stores/UserStore'; 6import UserStore from '../../stores/UserStore';
7import RecipesStore from '../../stores/RecipesStore'; 7import RecipesStore from '../../stores/RecipesStore';
8import ServicesStore from '../../stores/ServicesStore'; 8import ServicesStore from '../../stores/ServicesStore';
9import FeaturesStore from '../../stores/FeaturesStore';
9import Form from '../../lib/Form'; 10import Form from '../../lib/Form';
10import { gaPage } from '../../lib/analytics'; 11import { gaPage } from '../../lib/analytics';
11 12
@@ -77,7 +78,7 @@ export default class EditServiceScreen extends Component {
77 } 78 }
78 } 79 }
79 80
80 prepareForm(recipe, service) { 81 prepareForm(recipe, service, userCanManageServices) {
81 const { intl } = this.context; 82 const { intl } = this.context;
82 const config = { 83 const config = {
83 fields: { 84 fields: {
@@ -118,6 +119,7 @@ export default class EditServiceScreen extends Component {
118 if (recipe.hasTeamId) { 119 if (recipe.hasTeamId) {
119 Object.assign(config.fields, { 120 Object.assign(config.fields, {
120 team: { 121 team: {
122 disabled: !userCanManageServices,
121 label: intl.formatMessage(messages.team), 123 label: intl.formatMessage(messages.team),
122 placeholder: intl.formatMessage(messages.team), 124 placeholder: intl.formatMessage(messages.team),
123 value: service.team, 125 value: service.team,
@@ -129,6 +131,7 @@ export default class EditServiceScreen extends Component {
129 if (recipe.hasCustomUrl) { 131 if (recipe.hasCustomUrl) {
130 Object.assign(config.fields, { 132 Object.assign(config.fields, {
131 customUrl: { 133 customUrl: {
134 disabled: !userCanManageServices,
132 label: intl.formatMessage(messages.customUrl), 135 label: intl.formatMessage(messages.customUrl),
133 placeholder: 'https://', 136 placeholder: 'https://',
134 value: service.customUrl, 137 value: service.customUrl,
@@ -180,7 +183,7 @@ export default class EditServiceScreen extends Component {
180 } 183 }
181 184
182 render() { 185 render() {
183 const { recipes, services, user } = this.props.stores; 186 const { recipes, services, user, features } = this.props.stores;
184 const { action } = this.props.router.params; 187 const { action } = this.props.router.params;
185 188
186 let recipe; 189 let recipe;
@@ -215,7 +218,8 @@ export default class EditServiceScreen extends Component {
215 ); 218 );
216 } 219 }
217 220
218 const form = this.prepareForm(recipe, service); 221 const userCanManageServices = features.features.userCanManageServices;
222 const form = this.prepareForm(recipe, service, userCanManageServices);
219 223
220 return ( 224 return (
221 <EditServiceForm 225 <EditServiceForm
@@ -223,6 +227,7 @@ export default class EditServiceScreen extends Component {
223 recipe={recipe} 227 recipe={recipe}
224 service={service} 228 service={service}
225 user={user.data} 229 user={user.data}
230 userCanManageServices={userCanManageServices}
226 form={form} 231 form={form}
227 status={services.actionStatus} 232 status={services.actionStatus}
228 isSaving={services.updateServiceRequest.isExecuting || services.createServiceRequest.isExecuting} 233 isSaving={services.updateServiceRequest.isExecuting || services.createServiceRequest.isExecuting}
@@ -239,6 +244,7 @@ EditServiceScreen.wrappedComponent.propTypes = {
239 user: PropTypes.instanceOf(UserStore).isRequired, 244 user: PropTypes.instanceOf(UserStore).isRequired,
240 recipes: PropTypes.instanceOf(RecipesStore).isRequired, 245 recipes: PropTypes.instanceOf(RecipesStore).isRequired,
241 services: PropTypes.instanceOf(ServicesStore).isRequired, 246 services: PropTypes.instanceOf(ServicesStore).isRequired,
247 features: PropTypes.instanceOf(FeaturesStore).isRequired,
242 }).isRequired, 248 }).isRequired,
243 router: PropTypes.shape({ 249 router: PropTypes.shape({
244 params: PropTypes.shape({ 250 params: PropTypes.shape({
diff --git a/src/containers/settings/EditUserScreen.js b/src/containers/settings/EditUserScreen.js
index dda8ce513..a67fa7fb5 100644
--- a/src/containers/settings/EditUserScreen.js
+++ b/src/containers/settings/EditUserScreen.js
@@ -145,6 +145,7 @@ export default class EditUserScreen extends Component {
145 // user={user.data} 145 // user={user.data}
146 status={user.actionStatus} 146 status={user.actionStatus}
147 form={form} 147 form={form}
148 isEnterprise={user.data.isEnterprise}
148 isSaving={user.updateUserInfoRequest.isExecuting} 149 isSaving={user.updateUserInfoRequest.isExecuting}
149 onSubmit={d => this.onSubmit(d)} 150 onSubmit={d => this.onSubmit(d)}
150 /> 151 />
diff --git a/src/models/User.js b/src/models/User.js
index 2e5df4795..6fca78f90 100644
--- a/src/models/User.js
+++ b/src/models/User.js
@@ -1,4 +1,4 @@
1import { observable } from 'mobx'; 1import { observable, computed } from 'mobx';
2 2
3export default class User { 3export default class User {
4 id = null; 4 id = null;
@@ -15,6 +15,14 @@ export default class User {
15 @observable donor = {}; 15 @observable donor = {};
16 @observable isDonor = false; 16 @observable isDonor = false;
17 @observable isMiner = false; 17 @observable isMiner = false;
18 @observable isSSO = false;
19 @observable company = {
20 name: 'Happle Apps',
21 contact: {
22 technical: 'technical@company.com',
23 default: 'default@company.com',
24 },
25 };
18 26
19 constructor(data) { 27 constructor(data) {
20 if (!data.id) { 28 if (!data.id) {
@@ -33,5 +41,12 @@ export default class User {
33 this.isDonor = data.isDonor || this.isDonor; 41 this.isDonor = data.isDonor || this.isDonor;
34 this.isSubscriptionOwner = data.isSubscriptionOwner || this.isSubscriptionOwner; 42 this.isSubscriptionOwner = data.isSubscriptionOwner || this.isSubscriptionOwner;
35 this.isMiner = data.isMiner || this.isMiner; 43 this.isMiner = data.isMiner || this.isMiner;
44 this.isSSO = data.isSSO || this.isSSO;
45 this.company = data.company || this.company;
46 }
47
48 @computed get isEnterprise() {
49 // return false
50 return this.company.name !== undefined;
36 } 51 }
37} 52}
diff --git a/src/styles/badge.scss b/src/styles/badge.scss
index d7dfaf783..18a653118 100644
--- a/src/styles/badge.scss
+++ b/src/styles/badge.scss
@@ -12,4 +12,10 @@
12 background: $theme-brand-primary; 12 background: $theme-brand-primary;
13 color: #FFF; 13 color: #FFF;
14 } 14 }
15
16 &.badge--success {
17 background: $theme-brand-success;
18 color: #FFF;
19 }
20
15} 21}