diff options
author | Stefan <stefan@adlk.io> | 2019-06-04 14:26:56 +0200 |
---|---|---|
committer | Stefan <stefan@adlk.io> | 2019-06-04 14:26:56 +0200 |
commit | fd6a1e9ba24c7947af08a30829c860cad4726f67 (patch) | |
tree | 0b6276700ced8d13eaf0a1e3b706a69a5a47b1da /src/features/workspaces | |
parent | fix(Windows): Replace tray icon with high-res version (diff) | |
parent | Merge pull request #1443 from meetfranz/feature/multilingual-announcements (diff) | |
download | ferdium-app-fd6a1e9ba24c7947af08a30829c860cad4726f67.tar.gz ferdium-app-fd6a1e9ba24c7947af08a30829c860cad4726f67.tar.zst ferdium-app-fd6a1e9ba24c7947af08a30829c860cad4726f67.zip |
Merge branch 'develop' of https://github.com/meetfranz/franz into develop
Diffstat (limited to 'src/features/workspaces')
4 files changed, 135 insertions, 37 deletions
diff --git a/src/features/workspaces/components/CreateWorkspaceForm.js b/src/features/workspaces/components/CreateWorkspaceForm.js index 2c00ea63c..cddbb2b04 100644 --- a/src/features/workspaces/components/CreateWorkspaceForm.js +++ b/src/features/workspaces/components/CreateWorkspaceForm.js | |||
@@ -7,7 +7,7 @@ import injectSheet from 'react-jss'; | |||
7 | import Form from '../../../lib/Form'; | 7 | import Form from '../../../lib/Form'; |
8 | import { required } from '../../../helpers/validation-helpers'; | 8 | import { required } from '../../../helpers/validation-helpers'; |
9 | import { gaEvent } from '../../../lib/analytics'; | 9 | import { gaEvent } from '../../../lib/analytics'; |
10 | import { GA_CATEGORY_WORKSPACES } from '../index'; | 10 | import { GA_CATEGORY_WORKSPACES, workspaceStore } from '../index'; |
11 | 11 | ||
12 | const messages = defineMessages({ | 12 | const messages = defineMessages({ |
13 | submitButton: { | 13 | submitButton: { |
@@ -82,7 +82,7 @@ class CreateWorkspaceForm extends Component { | |||
82 | {...form.$('name').bind()} | 82 | {...form.$('name').bind()} |
83 | showLabel={false} | 83 | showLabel={false} |
84 | onEnterKey={this.submitForm.bind(this, form)} | 84 | onEnterKey={this.submitForm.bind(this, form)} |
85 | focus | 85 | focus={workspaceStore.isUserAllowedToUseFeature} |
86 | /> | 86 | /> |
87 | <Button | 87 | <Button |
88 | className={classes.submitButton} | 88 | className={classes.submitButton} |
diff --git a/src/features/workspaces/components/EditWorkspaceForm.js b/src/features/workspaces/components/EditWorkspaceForm.js index bba4485ff..e602ebd5a 100644 --- a/src/features/workspaces/components/EditWorkspaceForm.js +++ b/src/features/workspaces/components/EditWorkspaceForm.js | |||
@@ -1,4 +1,4 @@ | |||
1 | import React, { Component } from 'react'; | 1 | import React, { Component, Fragment } from 'react'; |
2 | import PropTypes from 'prop-types'; | 2 | import PropTypes from 'prop-types'; |
3 | import { observer } from 'mobx-react'; | 3 | import { observer } from 'mobx-react'; |
4 | import { defineMessages, intlShape } from 'react-intl'; | 4 | import { defineMessages, intlShape } from 'react-intl'; |
@@ -36,6 +36,14 @@ const messages = defineMessages({ | |||
36 | id: 'settings.workspace.form.servicesInWorkspaceHeadline', | 36 | id: 'settings.workspace.form.servicesInWorkspaceHeadline', |
37 | defaultMessage: '!!!Services in this Workspace', | 37 | defaultMessage: '!!!Services in this Workspace', |
38 | }, | 38 | }, |
39 | noServicesAdded: { | ||
40 | id: 'settings.services.noServicesAdded', | ||
41 | defaultMessage: '!!!You haven\'t added any services yet.', | ||
42 | }, | ||
43 | discoverServices: { | ||
44 | id: 'settings.services.discoverServices', | ||
45 | defaultMessage: '!!!Discover services', | ||
46 | }, | ||
39 | }); | 47 | }); |
40 | 48 | ||
41 | const styles = () => ({ | 49 | const styles = () => ({ |
@@ -150,14 +158,29 @@ class EditWorkspaceForm extends Component { | |||
150 | </div> | 158 | </div> |
151 | <h2>{intl.formatMessage(messages.servicesInWorkspaceHeadline)}</h2> | 159 | <h2>{intl.formatMessage(messages.servicesInWorkspaceHeadline)}</h2> |
152 | <div className={classes.serviceList}> | 160 | <div className={classes.serviceList}> |
153 | {services.map(s => ( | 161 | {services.length === 0 ? ( |
154 | <WorkspaceServiceListItem | 162 | <div className="align-middle settings__empty-state"> |
155 | key={s.id} | 163 | {/* ===== Empty state ===== */} |
156 | service={s} | 164 | <p className="settings__empty-text"> |
157 | isInWorkspace={workspaceServices.includes(s.id)} | 165 | <span className="emoji"> |
158 | onToggle={() => this.toggleService(s)} | 166 | <img src="./assets/images/emoji/sad.png" alt="" /> |
159 | /> | 167 | </span> |
160 | ))} | 168 | {intl.formatMessage(messages.noServicesAdded)} |
169 | </p> | ||
170 | <Link to="/settings/recipes" className="button">{intl.formatMessage(messages.discoverServices)}</Link> | ||
171 | </div> | ||
172 | ) : ( | ||
173 | <Fragment> | ||
174 | {services.map(s => ( | ||
175 | <WorkspaceServiceListItem | ||
176 | key={s.id} | ||
177 | service={s} | ||
178 | isInWorkspace={workspaceServices.includes(s.id)} | ||
179 | onToggle={() => this.toggleService(s)} | ||
180 | /> | ||
181 | ))} | ||
182 | </Fragment> | ||
183 | )} | ||
161 | </div> | 184 | </div> |
162 | </div> | 185 | </div> |
163 | <div className="settings__controls"> | 186 | <div className="settings__controls"> |
diff --git a/src/features/workspaces/components/WorkspacesDashboard.js b/src/features/workspaces/components/WorkspacesDashboard.js index dd4381a15..09c98ab8c 100644 --- a/src/features/workspaces/components/WorkspacesDashboard.js +++ b/src/features/workspaces/components/WorkspacesDashboard.js | |||
@@ -170,18 +170,32 @@ class WorkspacesDashboard extends Component { | |||
170 | {intl.formatMessage(messages.workspacesRequestFailed)} | 170 | {intl.formatMessage(messages.workspacesRequestFailed)} |
171 | </Infobox> | 171 | </Infobox> |
172 | ) : ( | 172 | ) : ( |
173 | <table className={classes.table}> | 173 | <Fragment> |
174 | {/* ===== Workspaces list ===== */} | 174 | {workspaces.length === 0 ? ( |
175 | <tbody> | 175 | <div className="align-middle settings__empty-state"> |
176 | {workspaces.map(workspace => ( | 176 | {/* ===== Workspaces empty state ===== */} |
177 | <WorkspaceItem | 177 | <p className="settings__empty-text"> |
178 | key={workspace.id} | 178 | <span className="emoji"> |
179 | workspace={workspace} | 179 | <img src="./assets/images/emoji/sad.png" alt="" /> |
180 | onItemClick={w => onWorkspaceClick(w)} | 180 | </span> |
181 | /> | 181 | {intl.formatMessage(messages.noServicesAdded)} |
182 | ))} | 182 | </p> |
183 | </tbody> | 183 | </div> |
184 | </table> | 184 | ) : ( |
185 | <table className={classes.table}> | ||
186 | {/* ===== Workspaces list ===== */} | ||
187 | <tbody> | ||
188 | {workspaces.map(workspace => ( | ||
189 | <WorkspaceItem | ||
190 | key={workspace.id} | ||
191 | workspace={workspace} | ||
192 | onItemClick={w => onWorkspaceClick(w)} | ||
193 | /> | ||
194 | ))} | ||
195 | </tbody> | ||
196 | </table> | ||
197 | )} | ||
198 | </Fragment> | ||
185 | )} | 199 | )} |
186 | </Fragment> | 200 | </Fragment> |
187 | )} | 201 | )} |
diff --git a/src/features/workspaces/store.js b/src/features/workspaces/store.js index ea601700e..51a7f3651 100644 --- a/src/features/workspaces/store.js +++ b/src/features/workspaces/store.js | |||
@@ -14,6 +14,8 @@ import { | |||
14 | updateWorkspaceRequest, | 14 | updateWorkspaceRequest, |
15 | } from './api'; | 15 | } from './api'; |
16 | import { WORKSPACES_ROUTES } from './index'; | 16 | import { WORKSPACES_ROUTES } from './index'; |
17 | import { createReactions } from '../../stores/lib/Reaction'; | ||
18 | import { createActionBindings } from '../utils/ActionBinding'; | ||
17 | 19 | ||
18 | const debug = require('debug')('Franz:feature:workspaces:store'); | 20 | const debug = require('debug')('Franz:feature:workspaces:store'); |
19 | 21 | ||
@@ -51,37 +53,78 @@ export default class WorkspacesStore extends FeatureStore { | |||
51 | return getUserWorkspacesRequest.wasExecuted && this.workspaces.length > 0; | 53 | return getUserWorkspacesRequest.wasExecuted && this.workspaces.length > 0; |
52 | } | 54 | } |
53 | 55 | ||
56 | @computed get isUserAllowedToUseFeature() { | ||
57 | return !this.isPremiumUpgradeRequired; | ||
58 | } | ||
59 | |||
60 | @computed get isAnyWorkspaceActive() { | ||
61 | return !!this.activeWorkspace; | ||
62 | } | ||
63 | |||
64 | // ========== PRIVATE PROPERTIES ========= // | ||
65 | |||
66 | _wasDrawerOpenBeforeSettingsRoute = null; | ||
67 | |||
68 | _freeUserActions = []; | ||
69 | |||
70 | _premiumUserActions = []; | ||
71 | |||
72 | _allActions = []; | ||
73 | |||
74 | _freeUserReactions = []; | ||
75 | |||
76 | _premiumUserReactions = []; | ||
77 | |||
78 | _allReactions = []; | ||
79 | |||
80 | // ========== PUBLIC API ========= // | ||
81 | |||
54 | start(stores, actions) { | 82 | start(stores, actions) { |
55 | debug('WorkspacesStore::start'); | 83 | debug('WorkspacesStore::start'); |
56 | this.stores = stores; | 84 | this.stores = stores; |
57 | this.actions = actions; | 85 | this.actions = actions; |
58 | 86 | ||
59 | this._listenToActions([ | 87 | // ACTIONS |
88 | |||
89 | this._freeUserActions = createActionBindings([ | ||
90 | [workspaceActions.toggleWorkspaceDrawer, this._toggleWorkspaceDrawer], | ||
91 | [workspaceActions.openWorkspaceSettings, this._openWorkspaceSettings], | ||
92 | ]); | ||
93 | this._premiumUserActions = createActionBindings([ | ||
60 | [workspaceActions.edit, this._edit], | 94 | [workspaceActions.edit, this._edit], |
61 | [workspaceActions.create, this._create], | 95 | [workspaceActions.create, this._create], |
62 | [workspaceActions.delete, this._delete], | 96 | [workspaceActions.delete, this._delete], |
63 | [workspaceActions.update, this._update], | 97 | [workspaceActions.update, this._update], |
64 | [workspaceActions.activate, this._setActiveWorkspace], | 98 | [workspaceActions.activate, this._setActiveWorkspace], |
65 | [workspaceActions.deactivate, this._deactivateActiveWorkspace], | 99 | [workspaceActions.deactivate, this._deactivateActiveWorkspace], |
66 | [workspaceActions.toggleWorkspaceDrawer, this._toggleWorkspaceDrawer], | ||
67 | [workspaceActions.openWorkspaceSettings, this._openWorkspaceSettings], | ||
68 | ]); | 100 | ]); |
101 | this._allActions = this._freeUserActions.concat(this._premiumUserActions); | ||
102 | this._registerActions(this._allActions); | ||
69 | 103 | ||
70 | this._startReactions([ | 104 | // REACTIONS |
71 | this._setWorkspaceBeingEditedReaction, | 105 | |
72 | this._setActiveServiceOnWorkspaceSwitchReaction, | 106 | this._freeUserReactions = createReactions([ |
107 | this._stopPremiumActionsAndReactions, | ||
108 | this._openDrawerWithSettingsReaction, | ||
73 | this._setFeatureEnabledReaction, | 109 | this._setFeatureEnabledReaction, |
74 | this._setIsPremiumFeatureReaction, | 110 | this._setIsPremiumFeatureReaction, |
75 | this._activateLastUsedWorkspaceReaction, | ||
76 | this._openDrawerWithSettingsReaction, | ||
77 | this._cleanupInvalidServiceReferences, | 111 | this._cleanupInvalidServiceReferences, |
78 | ]); | 112 | ]); |
113 | this._premiumUserReactions = createReactions([ | ||
114 | this._setActiveServiceOnWorkspaceSwitchReaction, | ||
115 | this._activateLastUsedWorkspaceReaction, | ||
116 | this._setWorkspaceBeingEditedReaction, | ||
117 | ]); | ||
118 | this._allReactions = this._freeUserReactions.concat(this._premiumUserReactions); | ||
119 | |||
120 | this._registerReactions(this._allReactions); | ||
79 | 121 | ||
80 | getUserWorkspacesRequest.execute(); | 122 | getUserWorkspacesRequest.execute(); |
81 | this.isFeatureActive = true; | 123 | this.isFeatureActive = true; |
82 | } | 124 | } |
83 | 125 | ||
84 | stop() { | 126 | stop() { |
127 | super.stop(); | ||
85 | debug('WorkspacesStore::stop'); | 128 | debug('WorkspacesStore::stop'); |
86 | this.isFeatureActive = false; | 129 | this.isFeatureActive = false; |
87 | this.activeWorkspace = null; | 130 | this.activeWorkspace = null; |
@@ -104,9 +147,7 @@ export default class WorkspacesStore extends FeatureStore { | |||
104 | return workspace.services.map(id => services.one(id)).filter(s => !!s); | 147 | return workspace.services.map(id => services.one(id)).filter(s => !!s); |
105 | } | 148 | } |
106 | 149 | ||
107 | // ========== PRIVATE ========= // | 150 | // ========== PRIVATE METHODS ========= // |
108 | |||
109 | _wasDrawerOpenBeforeSettingsRoute = null; | ||
110 | 151 | ||
111 | _getWorkspaceById = id => this.workspaces.find(w => w.id === id); | 152 | _getWorkspaceById = id => this.workspaces.find(w => w.id === id); |
112 | 153 | ||
@@ -192,6 +233,14 @@ export default class WorkspacesStore extends FeatureStore { | |||
192 | this.actions.ui.openSettings({ path: 'workspaces' }); | 233 | this.actions.ui.openSettings({ path: 'workspaces' }); |
193 | }; | 234 | }; |
194 | 235 | ||
236 | @action reorderServicesOfActiveWorkspace = async ({ oldIndex, newIndex }) => { | ||
237 | const { activeWorkspace } = this; | ||
238 | const { services } = activeWorkspace; | ||
239 | // Move services from the old to the new position | ||
240 | services.splice(newIndex, 0, services.splice(oldIndex, 1)[0]); | ||
241 | await updateWorkspaceRequest.execute(activeWorkspace); | ||
242 | }; | ||
243 | |||
195 | // Reactions | 244 | // Reactions |
196 | 245 | ||
197 | _setFeatureEnabledReaction = () => { | 246 | _setFeatureEnabledReaction = () => { |
@@ -218,13 +267,15 @@ export default class WorkspacesStore extends FeatureStore { | |||
218 | _setActiveServiceOnWorkspaceSwitchReaction = () => { | 267 | _setActiveServiceOnWorkspaceSwitchReaction = () => { |
219 | if (!this.isFeatureActive) return; | 268 | if (!this.isFeatureActive) return; |
220 | if (this.activeWorkspace) { | 269 | if (this.activeWorkspace) { |
221 | const services = this.stores.services.allDisplayed; | 270 | const activeService = this.stores.services.active; |
222 | const activeService = services.find(s => s.isActive); | ||
223 | const workspaceServices = this.getWorkspaceServices(this.activeWorkspace); | 271 | const workspaceServices = this.getWorkspaceServices(this.activeWorkspace); |
224 | if (workspaceServices.length <= 0) return; | 272 | if (workspaceServices.length <= 0) return; |
225 | const isActiveServiceInWorkspace = workspaceServices.includes(activeService); | 273 | const isActiveServiceInWorkspace = workspaceServices.includes(activeService); |
226 | if (!isActiveServiceInWorkspace) { | 274 | if (!isActiveServiceInWorkspace) { |
227 | this.actions.service.setActive({ serviceId: workspaceServices[0].id }); | 275 | this.actions.service.setActive({ |
276 | serviceId: workspaceServices[0].id, | ||
277 | keepActiveRoute: true, | ||
278 | }); | ||
228 | } | 279 | } |
229 | } | 280 | } |
230 | }; | 281 | }; |
@@ -273,4 +324,14 @@ export default class WorkspacesStore extends FeatureStore { | |||
273 | getUserWorkspacesRequest.execute(); | 324 | getUserWorkspacesRequest.execute(); |
274 | } | 325 | } |
275 | }; | 326 | }; |
327 | |||
328 | _stopPremiumActionsAndReactions = () => { | ||
329 | if (!this.isUserAllowedToUseFeature) { | ||
330 | this._stopActions(this._premiumUserActions); | ||
331 | this._stopReactions(this._premiumUserReactions); | ||
332 | } else { | ||
333 | this._startActions(this._premiumUserActions); | ||
334 | this._startReactions(this._premiumUserReactions); | ||
335 | } | ||
336 | } | ||
276 | } | 337 | } |