aboutsummaryrefslogtreecommitdiffstats
path: root/src/features/workspaces/store.js
diff options
context:
space:
mode:
Diffstat (limited to 'src/features/workspaces/store.js')
-rw-r--r--src/features/workspaces/store.js258
1 files changed, 258 insertions, 0 deletions
diff --git a/src/features/workspaces/store.js b/src/features/workspaces/store.js
new file mode 100644
index 000000000..ba48022c2
--- /dev/null
+++ b/src/features/workspaces/store.js
@@ -0,0 +1,258 @@
1import {
2 computed,
3 observable,
4 action,
5} from 'mobx';
6import localStorage from 'mobx-localstorage';
7import { matchRoute } from '../../helpers/routing-helpers';
8import { workspaceActions } from './actions';
9import { FeatureStore } from '../utils/FeatureStore';
10import {
11 createWorkspaceRequest,
12 deleteWorkspaceRequest,
13 getUserWorkspacesRequest,
14 updateWorkspaceRequest,
15} from './api';
16import { WORKSPACES_ROUTES } from './index';
17
18const debug = require('debug')('Franz:feature:workspaces:store');
19
20export default class WorkspacesStore extends FeatureStore {
21 @observable isFeatureEnabled = false;
22
23 @observable isFeatureActive = false;
24
25 @observable isPremiumFeature = true;
26
27 @observable isPremiumUpgradeRequired = true;
28
29 @observable activeWorkspace = null;
30
31 @observable nextWorkspace = null;
32
33 @observable workspaceBeingEdited = null;
34
35 @observable isSwitchingWorkspace = false;
36
37 @observable isWorkspaceDrawerOpen = false;
38
39 @observable isSettingsRouteActive = null;
40
41 @computed get workspaces() {
42 if (!this.isFeatureActive) return [];
43 return getUserWorkspacesRequest.result || [];
44 }
45
46 @computed get settings() {
47 return localStorage.getItem('workspaces') || {};
48 }
49
50 @computed get userHasWorkspaces() {
51 return getUserWorkspacesRequest.wasExecuted && this.workspaces.length > 0;
52 }
53
54 start(stores, actions) {
55 debug('WorkspacesStore::start');
56 this.stores = stores;
57 this.actions = actions;
58
59 this._listenToActions([
60 [workspaceActions.edit, this._edit],
61 [workspaceActions.create, this._create],
62 [workspaceActions.delete, this._delete],
63 [workspaceActions.update, this._update],
64 [workspaceActions.activate, this._setActiveWorkspace],
65 [workspaceActions.deactivate, this._deactivateActiveWorkspace],
66 [workspaceActions.toggleWorkspaceDrawer, this._toggleWorkspaceDrawer],
67 [workspaceActions.openWorkspaceSettings, this._openWorkspaceSettings],
68 ]);
69
70 this._startReactions([
71 this._setWorkspaceBeingEditedReaction,
72 this._setActiveServiceOnWorkspaceSwitchReaction,
73 this._setFeatureEnabledReaction,
74 this._setIsPremiumFeatureReaction,
75 this._activateLastUsedWorkspaceReaction,
76 this._openDrawerWithSettingsReaction,
77 ]);
78
79 getUserWorkspacesRequest.execute();
80 this.isFeatureActive = true;
81 }
82
83 stop() {
84 debug('WorkspacesStore::stop');
85 this.isFeatureActive = false;
86 this.activeWorkspace = null;
87 this.nextWorkspace = null;
88 this.workspaceBeingEdited = null;
89 this.isSwitchingWorkspace = false;
90 this.isWorkspaceDrawerOpen = false;
91 }
92
93 filterServicesByActiveWorkspace = (services) => {
94 const { activeWorkspace, isFeatureActive } = this;
95
96 if (!isFeatureActive) return services;
97 if (activeWorkspace) {
98 return services.filter(s => (
99 activeWorkspace.services.includes(s.id)
100 ));
101 }
102 return services;
103 };
104
105 // ========== PRIVATE ========= //
106
107 _wasDrawerOpenBeforeSettingsRoute = null;
108
109 _getWorkspaceById = id => this.workspaces.find(w => w.id === id);
110
111 _updateSettings = (changes) => {
112 localStorage.setItem('workspaces', {
113 ...this.settings,
114 ...changes,
115 });
116 };
117
118 // Actions
119
120 @action _edit = ({ workspace }) => {
121 this.stores.router.push(`/settings/workspaces/edit/${workspace.id}`);
122 };
123
124 @action _create = async ({ name }) => {
125 try {
126 const workspace = await createWorkspaceRequest.execute(name);
127 await getUserWorkspacesRequest.result.push(workspace);
128 this._edit({ workspace });
129 } catch (error) {
130 throw error;
131 }
132 };
133
134 @action _delete = async ({ workspace }) => {
135 try {
136 await deleteWorkspaceRequest.execute(workspace);
137 await getUserWorkspacesRequest.result.remove(workspace);
138 this.stores.router.push('/settings/workspaces');
139 } catch (error) {
140 throw error;
141 }
142 };
143
144 @action _update = async ({ workspace }) => {
145 try {
146 await updateWorkspaceRequest.execute(workspace);
147 // Path local result optimistically
148 const localWorkspace = this._getWorkspaceById(workspace.id);
149 Object.assign(localWorkspace, workspace);
150 this.stores.router.push('/settings/workspaces');
151 } catch (error) {
152 throw error;
153 }
154 };
155
156 @action _setActiveWorkspace = ({ workspace }) => {
157 // Indicate that we are switching to another workspace
158 this.isSwitchingWorkspace = true;
159 this.nextWorkspace = workspace;
160 // Delay switching to next workspace so that the services loading does not drag down UI
161 setTimeout(() => {
162 this.activeWorkspace = workspace;
163 this._updateSettings({ lastActiveWorkspace: workspace.id });
164 }, 100);
165 // Indicate that we are done switching to the next workspace
166 setTimeout(() => {
167 this.isSwitchingWorkspace = false;
168 this.nextWorkspace = null;
169 }, 1000);
170 };
171
172 @action _deactivateActiveWorkspace = () => {
173 // Indicate that we are switching to default workspace
174 this.isSwitchingWorkspace = true;
175 this.nextWorkspace = null;
176 this._updateSettings({ lastActiveWorkspace: null });
177 // Delay switching to next workspace so that the services loading does not drag down UI
178 setTimeout(() => {
179 this.activeWorkspace = null;
180 }, 100);
181 // Indicate that we are done switching to the default workspace
182 setTimeout(() => { this.isSwitchingWorkspace = false; }, 1000);
183 };
184
185 @action _toggleWorkspaceDrawer = () => {
186 this.isWorkspaceDrawerOpen = !this.isWorkspaceDrawerOpen;
187 };
188
189 @action _openWorkspaceSettings = () => {
190 this.actions.ui.openSettings({ path: 'workspaces' });
191 };
192
193 // Reactions
194
195 _setFeatureEnabledReaction = () => {
196 const { isWorkspaceEnabled } = this.stores.features.features;
197 this.isFeatureEnabled = isWorkspaceEnabled;
198 };
199
200 _setIsPremiumFeatureReaction = () => {
201 const { features, user } = this.stores;
202 const { isPremium } = user.data;
203 const { isWorkspacePremiumFeature } = features.features;
204 this.isPremiumFeature = isWorkspacePremiumFeature;
205 this.isPremiumUpgradeRequired = isWorkspacePremiumFeature && !isPremium;
206 };
207
208 _setWorkspaceBeingEditedReaction = () => {
209 const { pathname } = this.stores.router.location;
210 const match = matchRoute('/settings/workspaces/edit/:id', pathname);
211 if (match) {
212 this.workspaceBeingEdited = this._getWorkspaceById(match.id);
213 }
214 };
215
216 _setActiveServiceOnWorkspaceSwitchReaction = () => {
217 if (!this.isFeatureActive) return;
218 if (this.activeWorkspace) {
219 const services = this.stores.services.allDisplayed;
220 const activeService = services.find(s => s.isActive);
221 const workspaceServices = this.filterServicesByActiveWorkspace(services);
222 const isActiveServiceInWorkspace = workspaceServices.includes(activeService);
223 if (!isActiveServiceInWorkspace) {
224 this.actions.service.setActive({ serviceId: workspaceServices[0].id });
225 }
226 }
227 };
228
229 _activateLastUsedWorkspaceReaction = () => {
230 if (!this.activeWorkspace && this.userHasWorkspaces) {
231 const { lastActiveWorkspace } = this.settings;
232 if (lastActiveWorkspace) {
233 const workspace = this._getWorkspaceById(lastActiveWorkspace);
234 if (workspace) this._setActiveWorkspace({ workspace });
235 }
236 }
237 };
238
239 _openDrawerWithSettingsReaction = () => {
240 const { router } = this.stores;
241 const isWorkspaceSettingsRoute = router.location.pathname.includes(WORKSPACES_ROUTES.ROOT);
242 const isSwitchingToSettingsRoute = !this.isSettingsRouteActive && isWorkspaceSettingsRoute;
243 const isLeavingSettingsRoute = !isWorkspaceSettingsRoute && this.isSettingsRouteActive;
244
245 if (isSwitchingToSettingsRoute) {
246 this.isSettingsRouteActive = true;
247 this._wasDrawerOpenBeforeSettingsRoute = this.isWorkspaceDrawerOpen;
248 if (!this._wasDrawerOpenBeforeSettingsRoute) {
249 workspaceActions.toggleWorkspaceDrawer();
250 }
251 } else if (isLeavingSettingsRoute) {
252 this.isSettingsRouteActive = false;
253 if (!this._wasDrawerOpenBeforeSettingsRoute && this.isWorkspaceDrawerOpen) {
254 workspaceActions.toggleWorkspaceDrawer();
255 }
256 }
257 };
258}