aboutsummaryrefslogtreecommitdiffstats
path: root/src/stores
diff options
context:
space:
mode:
Diffstat (limited to 'src/stores')
-rw-r--r--src/stores/AppStore.js2
-rw-r--r--src/stores/FeaturesStore.js4
-rw-r--r--src/stores/ServicesStore.js39
-rw-r--r--src/stores/UserStore.js47
-rw-r--r--src/stores/index.js4
5 files changed, 93 insertions, 3 deletions
diff --git a/src/stores/AppStore.js b/src/stores/AppStore.js
index 2ac306a2a..6054e6721 100644
--- a/src/stores/AppStore.js
+++ b/src/stores/AppStore.js
@@ -357,6 +357,8 @@ export default class AppStore extends Store {
357 this.locale = this._getDefaultLocale(); 357 this.locale = this._getDefaultLocale();
358 } 358 }
359 359
360 moment.locale(this.locale);
361
360 debug(`Set locale to "${this.locale}"`); 362 debug(`Set locale to "${this.locale}"`);
361 } 363 }
362 364
diff --git a/src/stores/FeaturesStore.js b/src/stores/FeaturesStore.js
index 35a050c67..cf28b6bec 100644
--- a/src/stores/FeaturesStore.js
+++ b/src/stores/FeaturesStore.js
@@ -16,6 +16,8 @@ import workspaces from '../features/workspaces';
16import shareFranz from '../features/shareFranz'; 16import shareFranz from '../features/shareFranz';
17import announcements from '../features/announcements'; 17import announcements from '../features/announcements';
18import settingsWS from '../features/settingsWS'; 18import settingsWS from '../features/settingsWS';
19import serviceLimit from '../features/serviceLimit';
20import communityRecipes from '../features/communityRecipes';
19import todos from '../features/todos'; 21import todos from '../features/todos';
20 22
21import { DEFAULT_FEATURES_CONFIG } from '../config'; 23import { DEFAULT_FEATURES_CONFIG } from '../config';
@@ -76,6 +78,8 @@ export default class FeaturesStore extends Store {
76 shareFranz(this.stores, this.actions); 78 shareFranz(this.stores, this.actions);
77 announcements(this.stores, this.actions); 79 announcements(this.stores, this.actions);
78 settingsWS(this.stores, this.actions); 80 settingsWS(this.stores, this.actions);
81 serviceLimit(this.stores, this.actions);
82 communityRecipes(this.stores, this.actions);
79 todos(this.stores, this.actions); 83 todos(this.stores, this.actions);
80 } 84 }
81} 85}
diff --git a/src/stores/ServicesStore.js b/src/stores/ServicesStore.js
index b13425249..2fc543192 100644
--- a/src/stores/ServicesStore.js
+++ b/src/stores/ServicesStore.js
@@ -13,6 +13,8 @@ import CachedRequest from './lib/CachedRequest';
13import { matchRoute } from '../helpers/routing-helpers'; 13import { matchRoute } from '../helpers/routing-helpers';
14import { gaEvent, statsEvent } from '../lib/analytics'; 14import { gaEvent, statsEvent } from '../lib/analytics';
15import { workspaceStore } from '../features/workspaces'; 15import { workspaceStore } from '../features/workspaces';
16import { serviceLimitStore } from '../features/serviceLimit';
17import { RESTRICTION_TYPES } from '../models/Service';
16 18
17const debug = require('debug')('Franz:ServiceStore'); 19const debug = require('debug')('Franz:ServiceStore');
18 20
@@ -75,6 +77,7 @@ export default class ServicesStore extends Store {
75 this._saveActiveService.bind(this), 77 this._saveActiveService.bind(this),
76 this._logoutReaction.bind(this), 78 this._logoutReaction.bind(this),
77 this._handleMuteSettings.bind(this), 79 this._handleMuteSettings.bind(this),
80 this._restrictServiceAccess.bind(this),
78 ]); 81 ]);
79 82
80 // Just bind this 83 // Just bind this
@@ -98,7 +101,10 @@ export default class ServicesStore extends Store {
98 if (this.stores.user.isLoggedIn) { 101 if (this.stores.user.isLoggedIn) {
99 const services = this.allServicesRequest.execute().result; 102 const services = this.allServicesRequest.execute().result;
100 if (services) { 103 if (services) {
101 return observable(services.slice().slice().sort((a, b) => a.order - b.order)); 104 return observable(services.slice().slice().sort((a, b) => a.order - b.order).map((s, index) => {
105 s.index = index;
106 return s;
107 }));
102 } 108 }
103 } 109 }
104 return []; 110 return [];
@@ -153,6 +159,8 @@ export default class ServicesStore extends Store {
153 159
154 // Actions 160 // Actions
155 @action async _createService({ recipeId, serviceData, redirect = true }) { 161 @action async _createService({ recipeId, serviceData, redirect = true }) {
162 if (serviceLimitStore.userHasReachedServiceLimit) return;
163
156 const data = this._cleanUpTeamIdAndCustomUrl(recipeId, serviceData); 164 const data = this._cleanUpTeamIdAndCustomUrl(recipeId, serviceData);
157 165
158 const response = await this.createServiceRequest.execute(recipeId, data)._promise; 166 const response = await this.createServiceRequest.execute(recipeId, data)._promise;
@@ -681,6 +689,35 @@ export default class ServicesStore extends Store {
681 return serviceData; 689 return serviceData;
682 } 690 }
683 691
692 _restrictServiceAccess() {
693 const { features } = this.stores.features;
694 const { userHasReachedServiceLimit, serviceLimit } = this.stores.serviceLimit;
695
696 this.all.map((service, index) => {
697 if (userHasReachedServiceLimit) {
698 service.isServiceAccessRestricted = index >= serviceLimit;
699
700 if (service.isServiceAccessRestricted) {
701 service.restrictionType = RESTRICTION_TYPES.SERVICE_LIMIT;
702
703 debug('Restricting access to server due to service limit');
704 }
705 }
706
707 if (service.isUsingCustomUrl) {
708 service.isServiceAccessRestricted = !features.isCustomUrlIncludedInCurrentPlan;
709
710 if (service.isServiceAccessRestricted) {
711 service.restrictionType = RESTRICTION_TYPES.CUSTOM_URL;
712
713 debug('Restricting access to server due to custom url');
714 }
715 }
716
717 return service;
718 });
719 }
720
684 // Helper 721 // Helper
685 _initializeServiceRecipeInWebview(serviceId) { 722 _initializeServiceRecipeInWebview(serviceId) {
686 const service = this.one(serviceId); 723 const service = this.one(serviceId);
diff --git a/src/stores/UserStore.js b/src/stores/UserStore.js
index b5423af3b..e23106462 100644
--- a/src/stores/UserStore.js
+++ b/src/stores/UserStore.js
@@ -2,12 +2,14 @@ import { observable, computed, action } from 'mobx';
2import moment from 'moment'; 2import moment from 'moment';
3import jwt from 'jsonwebtoken'; 3import jwt from 'jsonwebtoken';
4import localStorage from 'mobx-localstorage'; 4import localStorage from 'mobx-localstorage';
5import ms from 'ms';
5 6
6import { isDevMode } from '../environment'; 7import { isDevMode, WEBSITE } from '../environment';
7import Store from './lib/Store'; 8import Store from './lib/Store';
8import Request from './lib/Request'; 9import Request from './lib/Request';
9import CachedRequest from './lib/CachedRequest'; 10import CachedRequest from './lib/CachedRequest';
10import { gaEvent } from '../lib/analytics'; 11import { gaEvent } from '../lib/analytics';
12import { sleep } from '../helpers/async-helpers';
11 13
12const debug = require('debug')('Franz:UserStore'); 14const debug = require('debug')('Franz:UserStore');
13 15
@@ -37,6 +39,8 @@ export default class UserStore extends Store {
37 39
38 @observable passwordRequest = new Request(this.api.user, 'password'); 40 @observable passwordRequest = new Request(this.api.user, 'password');
39 41
42 @observable activateTrialRequest = new Request(this.api.user, 'activateTrial');
43
40 @observable inviteRequest = new Request(this.api.user, 'invite'); 44 @observable inviteRequest = new Request(this.api.user, 'invite');
41 45
42 @observable getUserInfoRequest = new CachedRequest(this.api.user, 'getInfo'); 46 @observable getUserInfoRequest = new CachedRequest(this.api.user, 'getInfo');
@@ -57,7 +61,9 @@ export default class UserStore extends Store {
57 61
58 @observable accountType; 62 @observable accountType;
59 63
60 @observable hasCompletedSignup = null; 64 @observable hasCompletedSignup = false;
65
66 @observable hasActivatedTrial = false;
61 67
62 @observable userData = {}; 68 @observable userData = {};
63 69
@@ -77,6 +83,7 @@ export default class UserStore extends Store {
77 this.actions.user.retrievePassword.listen(this._retrievePassword.bind(this)); 83 this.actions.user.retrievePassword.listen(this._retrievePassword.bind(this));
78 this.actions.user.logout.listen(this._logout.bind(this)); 84 this.actions.user.logout.listen(this._logout.bind(this));
79 this.actions.user.signup.listen(this._signup.bind(this)); 85 this.actions.user.signup.listen(this._signup.bind(this));
86 this.actions.user.activateTrial.listen(this._activateTrial.bind(this));
80 this.actions.user.invite.listen(this._invite.bind(this)); 87 this.actions.user.invite.listen(this._invite.bind(this));
81 this.actions.user.update.listen(this._update.bind(this)); 88 this.actions.user.update.listen(this._update.bind(this));
82 this.actions.user.resetStatus.listen(this._resetStatus.bind(this)); 89 this.actions.user.resetStatus.listen(this._resetStatus.bind(this));
@@ -87,6 +94,7 @@ export default class UserStore extends Store {
87 this.registerReactions([ 94 this.registerReactions([
88 this._requireAuthenticatedUser, 95 this._requireAuthenticatedUser,
89 this._getUserData.bind(this), 96 this._getUserData.bind(this),
97 this._resetTrialActivationState.bind(this),
90 ]); 98 ]);
91 } 99 }
92 100
@@ -199,6 +207,24 @@ export default class UserStore extends Store {
199 gaEvent('User', 'retrievePassword'); 207 gaEvent('User', 'retrievePassword');
200 } 208 }
201 209
210 @action async _activateTrial({ planId }) {
211 debug('activate trial', planId);
212
213 this.activateTrialRequest.execute({
214 plan: planId,
215 });
216
217 await this.activateTrialRequest._promise;
218
219 this.hasActivatedTrial = true;
220
221 this.stores.features.featuresRequest.invalidate({ immediately: true });
222 this.stores.user.getUserInfoRequest.invalidate({ immediately: true });
223
224
225 gaEvent('User', 'activateTrial');
226 }
227
202 @action async _invite({ invites }) { 228 @action async _invite({ invites }) {
203 const data = invites.filter(invite => invite.email !== ''); 229 const data = invites.filter(invite => invite.email !== '');
204 230
@@ -318,6 +344,14 @@ export default class UserStore extends Store {
318 } 344 }
319 } 345 }
320 346
347 async _resetTrialActivationState() {
348 if (this.hasActivatedTrial) {
349 await sleep(ms('12s'));
350
351 this.hasActivatedTrial = false;
352 }
353 }
354
321 // Helpers 355 // Helpers
322 _parseToken(authToken) { 356 _parseToken(authToken) {
323 try { 357 try {
@@ -347,6 +381,15 @@ export default class UserStore extends Store {
347 } 381 }
348 } 382 }
349 383
384 getAuthURL(url) {
385 const parsedUrl = new URL(url);
386 const params = new URLSearchParams(parsedUrl.search.slice(1));
387
388 params.append('authToken', this.authToken);
389
390 return `${parsedUrl.origin}${parsedUrl.pathname}?${params.toString()}`;
391 }
392
350 async _migrateUserLocale() { 393 async _migrateUserLocale() {
351 await this.getUserInfoRequest._promise; 394 await this.getUserInfoRequest._promise;
352 395
diff --git a/src/stores/index.js b/src/stores/index.js
index e9ef523f8..10dd56665 100644
--- a/src/stores/index.js
+++ b/src/stores/index.js
@@ -12,6 +12,8 @@ import RequestStore from './RequestStore';
12import GlobalErrorStore from './GlobalErrorStore'; 12import GlobalErrorStore from './GlobalErrorStore';
13import { workspaceStore } from '../features/workspaces'; 13import { workspaceStore } from '../features/workspaces';
14import { announcementsStore } from '../features/announcements'; 14import { announcementsStore } from '../features/announcements';
15import { serviceLimitStore } from '../features/serviceLimit';
16import { communityRecipesStore } from '../features/communityRecipes';
15import { todosStore } from '../features/todos'; 17import { todosStore } from '../features/todos';
16 18
17export default (api, actions, router) => { 19export default (api, actions, router) => {
@@ -32,6 +34,8 @@ export default (api, actions, router) => {
32 globalError: new GlobalErrorStore(stores, api, actions), 34 globalError: new GlobalErrorStore(stores, api, actions),
33 workspaces: workspaceStore, 35 workspaces: workspaceStore,
34 announcements: announcementsStore, 36 announcements: announcementsStore,
37 serviceLimit: serviceLimitStore,
38 communityRecipes: communityRecipesStore,
35 todos: todosStore, 39 todos: todosStore,
36 }); 40 });
37 // Initialize all stores 41 // Initialize all stores