diff options
Diffstat (limited to 'src/features/workspaces/store.js')
-rw-r--r-- | src/features/workspaces/store.js | 258 |
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 @@ | |||
1 | import { | ||
2 | computed, | ||
3 | observable, | ||
4 | action, | ||
5 | } from 'mobx'; | ||
6 | import localStorage from 'mobx-localstorage'; | ||
7 | import { matchRoute } from '../../helpers/routing-helpers'; | ||
8 | import { workspaceActions } from './actions'; | ||
9 | import { FeatureStore } from '../utils/FeatureStore'; | ||
10 | import { | ||
11 | createWorkspaceRequest, | ||
12 | deleteWorkspaceRequest, | ||
13 | getUserWorkspacesRequest, | ||
14 | updateWorkspaceRequest, | ||
15 | } from './api'; | ||
16 | import { WORKSPACES_ROUTES } from './index'; | ||
17 | |||
18 | const debug = require('debug')('Franz:feature:workspaces:store'); | ||
19 | |||
20 | export 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 | } | ||