diff options
Diffstat (limited to 'src/stores')
-rw-r--r-- | src/stores/AppStore.js | 2 | ||||
-rw-r--r-- | src/stores/FeaturesStore.js | 4 | ||||
-rw-r--r-- | src/stores/ServicesStore.js | 39 | ||||
-rw-r--r-- | src/stores/UserStore.js | 40 | ||||
-rw-r--r-- | src/stores/index.js | 4 |
5 files changed, 87 insertions, 2 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 e7832088b..27334c9a2 100644 --- a/src/stores/FeaturesStore.js +++ b/src/stores/FeaturesStore.js | |||
@@ -16,6 +16,8 @@ import workspaces from '../features/workspaces'; | |||
16 | import shareFranz from '../features/shareFranz'; | 16 | import shareFranz from '../features/shareFranz'; |
17 | import announcements from '../features/announcements'; | 17 | import announcements from '../features/announcements'; |
18 | import settingsWS from '../features/settingsWS'; | 18 | import settingsWS from '../features/settingsWS'; |
19 | import serviceLimit from '../features/serviceLimit'; | ||
20 | import communityRecipes from '../features/communityRecipes'; | ||
19 | 21 | ||
20 | import { DEFAULT_FEATURES_CONFIG } from '../config'; | 22 | import { DEFAULT_FEATURES_CONFIG } from '../config'; |
21 | 23 | ||
@@ -75,5 +77,7 @@ export default class FeaturesStore extends Store { | |||
75 | shareFranz(this.stores, this.actions); | 77 | shareFranz(this.stores, this.actions); |
76 | announcements(this.stores, this.actions); | 78 | announcements(this.stores, this.actions); |
77 | settingsWS(this.stores, this.actions); | 79 | settingsWS(this.stores, this.actions); |
80 | serviceLimit(this.stores, this.actions); | ||
81 | communityRecipes(this.stores, this.actions); | ||
78 | } | 82 | } |
79 | } | 83 | } |
diff --git a/src/stores/ServicesStore.js b/src/stores/ServicesStore.js index 109ac5cd7..e3b3fcf21 100644 --- a/src/stores/ServicesStore.js +++ b/src/stores/ServicesStore.js | |||
@@ -13,6 +13,8 @@ import CachedRequest from './lib/CachedRequest'; | |||
13 | import { matchRoute } from '../helpers/routing-helpers'; | 13 | import { matchRoute } from '../helpers/routing-helpers'; |
14 | import { gaEvent, statsEvent } from '../lib/analytics'; | 14 | import { gaEvent, statsEvent } from '../lib/analytics'; |
15 | import { workspaceStore } from '../features/workspaces'; | 15 | import { workspaceStore } from '../features/workspaces'; |
16 | import { serviceLimitStore } from '../features/serviceLimit'; | ||
17 | import { RESTRICTION_TYPES } from '../models/Service'; | ||
16 | 18 | ||
17 | const debug = require('debug')('Franz:ServiceStore'); | 19 | const 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; |
@@ -678,6 +686,35 @@ export default class ServicesStore extends Store { | |||
678 | return serviceData; | 686 | return serviceData; |
679 | } | 687 | } |
680 | 688 | ||
689 | _restrictServiceAccess() { | ||
690 | const { features } = this.stores.features; | ||
691 | const { userHasReachedServiceLimit, serviceLimit } = this.stores.serviceLimit; | ||
692 | |||
693 | this.all.map((service, index) => { | ||
694 | if (userHasReachedServiceLimit) { | ||
695 | service.isServiceAccessRestricted = index >= serviceLimit; | ||
696 | |||
697 | if (service.isServiceAccessRestricted) { | ||
698 | service.restrictionType = RESTRICTION_TYPES.SERVICE_LIMIT; | ||
699 | |||
700 | debug('Restricting access to server due to service limit'); | ||
701 | } | ||
702 | } | ||
703 | |||
704 | if (service.isUsingCustomUrl) { | ||
705 | service.isServiceAccessRestricted = !features.isCustomUrlIncludedInCurrentPlan; | ||
706 | |||
707 | if (service.isServiceAccessRestricted) { | ||
708 | service.restrictionType = RESTRICTION_TYPES.CUSTOM_URL; | ||
709 | |||
710 | debug('Restricting access to server due to custom url'); | ||
711 | } | ||
712 | } | ||
713 | |||
714 | return service; | ||
715 | }); | ||
716 | } | ||
717 | |||
681 | // Helper | 718 | // Helper |
682 | _initializeServiceRecipeInWebview(serviceId) { | 719 | _initializeServiceRecipeInWebview(serviceId) { |
683 | const service = this.one(serviceId); | 720 | const service = this.one(serviceId); |
diff --git a/src/stores/UserStore.js b/src/stores/UserStore.js index b5423af3b..e7516e6e6 100644 --- a/src/stores/UserStore.js +++ b/src/stores/UserStore.js | |||
@@ -2,12 +2,14 @@ import { observable, computed, action } from 'mobx'; | |||
2 | import moment from 'moment'; | 2 | import moment from 'moment'; |
3 | import jwt from 'jsonwebtoken'; | 3 | import jwt from 'jsonwebtoken'; |
4 | import localStorage from 'mobx-localstorage'; | 4 | import localStorage from 'mobx-localstorage'; |
5 | import ms from 'ms'; | ||
5 | 6 | ||
6 | import { isDevMode } from '../environment'; | 7 | import { isDevMode } from '../environment'; |
7 | import Store from './lib/Store'; | 8 | import Store from './lib/Store'; |
8 | import Request from './lib/Request'; | 9 | import Request from './lib/Request'; |
9 | import CachedRequest from './lib/CachedRequest'; | 10 | import CachedRequest from './lib/CachedRequest'; |
10 | import { gaEvent } from '../lib/analytics'; | 11 | import { gaEvent } from '../lib/analytics'; |
12 | import { sleep } from '../helpers/async-helpers'; | ||
11 | 13 | ||
12 | const debug = require('debug')('Franz:UserStore'); | 14 | const 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,26 @@ 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 | console.log('hasActivatedTrial', this.hasActivatedTrial); | ||
222 | |||
223 | this.stores.features.featuresRequest.invalidate({ immediately: true }); | ||
224 | this.stores.user.getUserInfoRequest.invalidate({ immediately: true }); | ||
225 | |||
226 | |||
227 | gaEvent('User', 'activateTrial'); | ||
228 | } | ||
229 | |||
202 | @action async _invite({ invites }) { | 230 | @action async _invite({ invites }) { |
203 | const data = invites.filter(invite => invite.email !== ''); | 231 | const data = invites.filter(invite => invite.email !== ''); |
204 | 232 | ||
@@ -318,6 +346,16 @@ export default class UserStore extends Store { | |||
318 | } | 346 | } |
319 | } | 347 | } |
320 | 348 | ||
349 | async _resetTrialActivationState() { | ||
350 | if (this.hasActivatedTrial) { | ||
351 | await sleep(ms('12s')); | ||
352 | |||
353 | console.log('resetting this.hasActivatedTrial', this.hasActivatedTrial); | ||
354 | |||
355 | this.hasActivatedTrial = false; | ||
356 | } | ||
357 | } | ||
358 | |||
321 | // Helpers | 359 | // Helpers |
322 | _parseToken(authToken) { | 360 | _parseToken(authToken) { |
323 | try { | 361 | try { |
diff --git a/src/stores/index.js b/src/stores/index.js index 1912418a2..c9ec77612 100644 --- a/src/stores/index.js +++ b/src/stores/index.js | |||
@@ -12,6 +12,8 @@ import RequestStore from './RequestStore'; | |||
12 | import GlobalErrorStore from './GlobalErrorStore'; | 12 | import GlobalErrorStore from './GlobalErrorStore'; |
13 | import { workspaceStore } from '../features/workspaces'; | 13 | import { workspaceStore } from '../features/workspaces'; |
14 | import { announcementsStore } from '../features/announcements'; | 14 | import { announcementsStore } from '../features/announcements'; |
15 | import { serviceLimitStore } from '../features/serviceLimit'; | ||
16 | import { communityRecipesStore } from '../features/communityRecipes'; | ||
15 | 17 | ||
16 | export default (api, actions, router) => { | 18 | export default (api, actions, router) => { |
17 | const stores = {}; | 19 | const stores = {}; |
@@ -31,6 +33,8 @@ export default (api, actions, router) => { | |||
31 | globalError: new GlobalErrorStore(stores, api, actions), | 33 | globalError: new GlobalErrorStore(stores, api, actions), |
32 | workspaces: workspaceStore, | 34 | workspaces: workspaceStore, |
33 | announcements: announcementsStore, | 35 | announcements: announcementsStore, |
36 | serviceLimit: serviceLimitStore, | ||
37 | communityRecipes: communityRecipesStore, | ||
34 | }); | 38 | }); |
35 | // Initialize all stores | 39 | // Initialize all stores |
36 | Object.keys(stores).forEach((name) => { | 40 | Object.keys(stores).forEach((name) => { |