aboutsummaryrefslogtreecommitdiffstats
path: root/src/features
diff options
context:
space:
mode:
authorLibravatar Dominik Guzei <dominik.guzei@gmail.com>2019-03-28 16:23:17 +0100
committerLibravatar Dominik Guzei <dominik.guzei@gmail.com>2019-03-28 16:23:17 +0100
commit7941831bf773b49944001c095a1949a1bdec2cf2 (patch)
tree5dbcbf097e340c381617410e032c2db6b811096e /src/features
parentimprove styling of workspace switch indicator (diff)
downloadferdium-app-7941831bf773b49944001c095a1949a1bdec2cf2.tar.gz
ferdium-app-7941831bf773b49944001c095a1949a1bdec2cf2.tar.zst
ferdium-app-7941831bf773b49944001c095a1949a1bdec2cf2.zip
add workspace premium notice to dashboard
Diffstat (limited to 'src/features')
-rw-r--r--src/features/delayApp/index.js2
-rw-r--r--src/features/utils/FeatureStore.js21
-rw-r--r--src/features/workspaces/components/CreateWorkspaceForm.js1
-rw-r--r--src/features/workspaces/components/WorkspacesDashboard.js42
-rw-r--r--src/features/workspaces/index.js3
-rw-r--r--src/features/workspaces/store.js69
6 files changed, 98 insertions, 40 deletions
diff --git a/src/features/delayApp/index.js b/src/features/delayApp/index.js
index abc8274cf..67f0fc5e6 100644
--- a/src/features/delayApp/index.js
+++ b/src/features/delayApp/index.js
@@ -55,7 +55,7 @@ export default function init(stores) {
55 55
56 setVisibility(true); 56 setVisibility(true);
57 gaPage('/delayApp'); 57 gaPage('/delayApp');
58 gaEvent('delayApp', 'show', 'Delay App Feature'); 58 gaEvent('DelayApp', 'show', 'Delay App Feature');
59 59
60 timeLastDelay = moment(); 60 timeLastDelay = moment();
61 shownAfterLaunch = true; 61 shownAfterLaunch = true;
diff --git a/src/features/utils/FeatureStore.js b/src/features/utils/FeatureStore.js
new file mode 100644
index 000000000..66b66a104
--- /dev/null
+++ b/src/features/utils/FeatureStore.js
@@ -0,0 +1,21 @@
1import Reaction from '../../stores/lib/Reaction';
2
3export class FeatureStore {
4 _actions = null;
5
6 _reactions = null;
7
8 _listenToActions(actions) {
9 if (this._actions) this._actions.forEach(a => a[0].off(a[1]));
10 this._actions = [];
11 actions.forEach(a => this._actions.push(a));
12 this._actions.forEach(a => a[0].listen(a[1]));
13 }
14
15 _startReactions(reactions) {
16 if (this._reactions) this._reactions.forEach(r => r.stop());
17 this._reactions = [];
18 reactions.forEach(r => this._reactions.push(new Reaction(r)));
19 this._reactions.forEach(r => r.start());
20 }
21}
diff --git a/src/features/workspaces/components/CreateWorkspaceForm.js b/src/features/workspaces/components/CreateWorkspaceForm.js
index a8f07d0d5..0be2d528f 100644
--- a/src/features/workspaces/components/CreateWorkspaceForm.js
+++ b/src/features/workspaces/components/CreateWorkspaceForm.js
@@ -30,7 +30,6 @@ const styles = () => ({
30 }, 30 },
31 submitButton: { 31 submitButton: {
32 height: 'inherit', 32 height: 'inherit',
33 marginTop: '3px',
34 }, 33 },
35}); 34});
36 35
diff --git a/src/features/workspaces/components/WorkspacesDashboard.js b/src/features/workspaces/components/WorkspacesDashboard.js
index 52c3afdcf..1fad1f71d 100644
--- a/src/features/workspaces/components/WorkspacesDashboard.js
+++ b/src/features/workspaces/components/WorkspacesDashboard.js
@@ -10,6 +10,8 @@ import WorkspaceItem from './WorkspaceItem';
10import CreateWorkspaceForm from './CreateWorkspaceForm'; 10import CreateWorkspaceForm from './CreateWorkspaceForm';
11import Request from '../../../stores/lib/Request'; 11import Request from '../../../stores/lib/Request';
12import Appear from '../../../components/ui/effects/Appear'; 12import Appear from '../../../components/ui/effects/Appear';
13import { workspaceStore } from '../index';
14import PremiumFeatureContainer from '../../../components/ui/PremiumFeatureContainer';
13 15
14const messages = defineMessages({ 16const messages = defineMessages({
15 headline: { 17 headline: {
@@ -36,6 +38,14 @@ const messages = defineMessages({
36 id: 'settings.workspaces.deletedInfo', 38 id: 'settings.workspaces.deletedInfo',
37 defaultMessage: '!!!Workspace has been deleted', 39 defaultMessage: '!!!Workspace has been deleted',
38 }, 40 },
41 workspaceFeatureInfo: {
42 id: 'settings.workspaces.workspaceFeatureInfo',
43 defaultMessage: '!!!Info about workspace feature',
44 },
45 workspaceFeatureHeadline: {
46 id: 'settings.workspaces.workspaceFeatureHeadline',
47 defaultMessage: '!!!Less is More: Introducing Franz Workspaces',
48 },
39}); 49});
40 50
41const styles = () => ({ 51const styles = () => ({
@@ -46,6 +56,12 @@ const styles = () => ({
46 appear: { 56 appear: {
47 height: 'auto', 57 height: 'auto',
48 }, 58 },
59 premiumAnnouncement: {
60 padding: '20px',
61 backgroundColor: '#3498db',
62 marginLeft: '-20px',
63 height: 'auto',
64 },
49}); 65});
50 66
51@injectSheet(styles) @observer 67@injectSheet(styles) @observer
@@ -112,14 +128,24 @@ class WorkspacesDashboard extends Component {
112 </Appear> 128 </Appear>
113 )} 129 )}
114 130
115 {/* ===== Create workspace form ===== */} 131 <PremiumFeatureContainer
116 <div className={classes.createForm}> 132 condition={workspaceStore.isPremiumFeature}
117 <CreateWorkspaceForm 133 gaEventInfo={{ category: 'User', event: 'upgrade', label: 'workspaces' }}
118 isSubmitting={createWorkspaceRequest.isExecuting} 134 >
119 onSubmit={onCreateWorkspaceSubmit} 135 {/* ===== Create workspace form ===== */}
120 /> 136 <div className={classes.createForm}>
121 </div> 137 <CreateWorkspaceForm
122 138 isSubmitting={createWorkspaceRequest.isExecuting}
139 onSubmit={onCreateWorkspaceSubmit}
140 />
141 </div>
142 </PremiumFeatureContainer>
143 {workspaceStore.isUpgradeToPremiumRequired && (
144 <div className={classes.premiumAnnouncement}>
145 <h2>{intl.formatMessage(messages.workspaceFeatureHeadline)}</h2>
146 <p>{intl.formatMessage(messages.workspaceFeatureInfo)}</p>
147 </div>
148 )}
123 {getUserWorkspacesRequest.isExecuting ? ( 149 {getUserWorkspacesRequest.isExecuting ? (
124 <Loader /> 150 <Loader />
125 ) : ( 151 ) : (
diff --git a/src/features/workspaces/index.js b/src/features/workspaces/index.js
index 89999ab0f..524a83e3c 100644
--- a/src/features/workspaces/index.js
+++ b/src/features/workspaces/index.js
@@ -4,11 +4,12 @@ import { resetApiRequests } from './api';
4 4
5const debug = require('debug')('Franz:feature:workspaces'); 5const debug = require('debug')('Franz:feature:workspaces');
6 6
7export const GA_CATEGORY_WORKSPACES = 'workspaces'; 7export const GA_CATEGORY_WORKSPACES = 'Workspaces';
8 8
9export const workspaceStore = new WorkspacesStore(); 9export const workspaceStore = new WorkspacesStore();
10 10
11export default function initWorkspaces(stores, actions) { 11export default function initWorkspaces(stores, actions) {
12 stores.workspaces = workspaceStore;
12 const { features, user } = stores; 13 const { features, user } = stores;
13 14
14 // Toggle workspace feature 15 // Toggle workspace feature
diff --git a/src/features/workspaces/store.js b/src/features/workspaces/store.js
index f7df7b29c..62bf3efb4 100644
--- a/src/features/workspaces/store.js
+++ b/src/features/workspaces/store.js
@@ -3,9 +3,9 @@ import {
3 observable, 3 observable,
4 action, 4 action,
5} from 'mobx'; 5} from 'mobx';
6import Reaction from '../../stores/lib/Reaction';
7import { matchRoute } from '../../helpers/routing-helpers'; 6import { matchRoute } from '../../helpers/routing-helpers';
8import { workspaceActions } from './actions'; 7import { workspaceActions } from './actions';
8import { FeatureStore } from '../utils/FeatureStore';
9import { 9import {
10 createWorkspaceRequest, 10 createWorkspaceRequest,
11 deleteWorkspaceRequest, 11 deleteWorkspaceRequest,
@@ -15,7 +15,11 @@ import {
15 15
16const debug = require('debug')('Franz:feature:workspaces:store'); 16const debug = require('debug')('Franz:feature:workspaces:store');
17 17
18export default class WorkspacesStore { 18export default class WorkspacesStore extends FeatureStore {
19 @observable isFeatureEnabled = false;
20
21 @observable isPremiumFeature = true;
22
19 @observable isFeatureActive = false; 23 @observable isFeatureActive = false;
20 24
21 @observable activeWorkspace = null; 25 @observable activeWorkspace = null;
@@ -33,36 +37,39 @@ export default class WorkspacesStore {
33 return getUserWorkspacesRequest.result || []; 37 return getUserWorkspacesRequest.result || [];
34 } 38 }
35 39
36 constructor() { 40 @computed get isUpgradeToPremiumRequired() {
37 // Wire-up action handlers 41 return this.isFeatureEnabled && !this.isFeatureActive;
38 workspaceActions.edit.listen(this._edit);
39 workspaceActions.create.listen(this._create);
40 workspaceActions.delete.listen(this._delete);
41 workspaceActions.update.listen(this._update);
42 workspaceActions.activate.listen(this._setActiveWorkspace);
43 workspaceActions.deactivate.listen(this._deactivateActiveWorkspace);
44 workspaceActions.toggleWorkspaceDrawer.listen(this._toggleWorkspaceDrawer);
45 workspaceActions.openWorkspaceSettings.listen(this._openWorkspaceSettings);
46
47 // Register and start reactions
48 this._registerReactions([
49 this._updateWorkspaceBeingEdited,
50 this._updateActiveServiceOnWorkspaceSwitch,
51 ]);
52 } 42 }
53 43
54 start(stores, actions) { 44 start(stores, actions) {
55 debug('WorkspacesStore::start'); 45 debug('WorkspacesStore::start');
56 this.stores = stores; 46 this.stores = stores;
57 this.actions = actions; 47 this.actions = actions;
58 this._reactions.forEach(r => r.start()); 48
59 this.isFeatureActive = true; 49 this._listenToActions([
50 [workspaceActions.edit, this._edit],
51 [workspaceActions.create, this._create],
52 [workspaceActions.delete, this._delete],
53 [workspaceActions.update, this._update],
54 [workspaceActions.activate, this._setActiveWorkspace],
55 [workspaceActions.deactivate, this._deactivateActiveWorkspace],
56 [workspaceActions.toggleWorkspaceDrawer, this._toggleWorkspaceDrawer],
57 [workspaceActions.openWorkspaceSettings, this._openWorkspaceSettings],
58 ]);
59
60 this._startReactions([
61 this._setWorkspaceBeingEditedReaction,
62 this._setActiveServiceOnWorkspaceSwitchReaction,
63 this._setFeatureEnabledReaction,
64 this._setIsPremiumFeatureReaction,
65 ]);
66
60 getUserWorkspacesRequest.execute(); 67 getUserWorkspacesRequest.execute();
68 this.isFeatureActive = true;
61 } 69 }
62 70
63 stop() { 71 stop() {
64 debug('WorkspacesStore::stop'); 72 debug('WorkspacesStore::stop');
65 this._reactions.forEach(r => r.stop());
66 this.isFeatureActive = false; 73 this.isFeatureActive = false;
67 this.activeWorkspace = null; 74 this.activeWorkspace = null;
68 this.nextWorkspace = null; 75 this.nextWorkspace = null;
@@ -85,12 +92,6 @@ export default class WorkspacesStore {
85 92
86 // ========== PRIVATE ========= // 93 // ========== PRIVATE ========= //
87 94
88 _reactions = [];
89
90 _registerReactions(reactions) {
91 reactions.forEach(r => this._reactions.push(new Reaction(r)));
92 }
93
94 _getWorkspaceById = id => this.workspaces.find(w => w.id === id); 95 _getWorkspaceById = id => this.workspaces.find(w => w.id === id);
95 96
96 // Actions 97 // Actions
@@ -164,7 +165,17 @@ export default class WorkspacesStore {
164 165
165 // Reactions 166 // Reactions
166 167
167 _updateWorkspaceBeingEdited = () => { 168 _setFeatureEnabledReaction = () => {
169 const { isWorkspaceEnabled } = this.stores.features.features;
170 this.isFeatureEnabled = isWorkspaceEnabled;
171 };
172
173 _setIsPremiumFeatureReaction = () => {
174 const { isWorkspacePremiumFeature } = this.stores.features.features;
175 this.isPremiumFeature = isWorkspacePremiumFeature;
176 };
177
178 _setWorkspaceBeingEditedReaction = () => {
168 const { pathname } = this.stores.router.location; 179 const { pathname } = this.stores.router.location;
169 const match = matchRoute('/settings/workspaces/edit/:id', pathname); 180 const match = matchRoute('/settings/workspaces/edit/:id', pathname);
170 if (match) { 181 if (match) {
@@ -172,7 +183,7 @@ export default class WorkspacesStore {
172 } 183 }
173 }; 184 };
174 185
175 _updateActiveServiceOnWorkspaceSwitch = () => { 186 _setActiveServiceOnWorkspaceSwitchReaction = () => {
176 if (!this.isFeatureActive) return; 187 if (!this.isFeatureActive) return;
177 if (this.activeWorkspace) { 188 if (this.activeWorkspace) {
178 const services = this.stores.services.allDisplayed; 189 const services = this.stores.services.allDisplayed;