diff options
-rw-r--r-- | src/features/workspaces/actions.js | 3 | ||||
-rw-r--r-- | src/features/workspaces/api.js | 11 | ||||
-rw-r--r-- | src/features/workspaces/components/EditWorkspaceForm.js | 46 | ||||
-rw-r--r-- | src/features/workspaces/components/ServiceListItem.js | 48 | ||||
-rw-r--r-- | src/features/workspaces/containers/EditWorkspaceScreen.js | 14 | ||||
-rw-r--r-- | src/features/workspaces/models/Workspace.js | 2 | ||||
-rw-r--r-- | src/features/workspaces/store.js | 12 | ||||
-rw-r--r-- | src/i18n/locales/de.json | 1 | ||||
-rw-r--r-- | src/i18n/locales/en-US.json | 1 |
9 files changed, 132 insertions, 6 deletions
diff --git a/src/features/workspaces/actions.js b/src/features/workspaces/actions.js index 83d3447c3..84de2b011 100644 --- a/src/features/workspaces/actions.js +++ b/src/features/workspaces/actions.js | |||
@@ -11,4 +11,7 @@ export default { | |||
11 | delete: { | 11 | delete: { |
12 | workspace: PropTypes.instanceOf(Workspace).isRequired, | 12 | workspace: PropTypes.instanceOf(Workspace).isRequired, |
13 | }, | 13 | }, |
14 | update: { | ||
15 | workspace: PropTypes.instanceOf(Workspace).isRequired, | ||
16 | }, | ||
14 | }; | 17 | }; |
diff --git a/src/features/workspaces/api.js b/src/features/workspaces/api.js index fabc12455..733cb5593 100644 --- a/src/features/workspaces/api.js +++ b/src/features/workspaces/api.js | |||
@@ -1,3 +1,4 @@ | |||
1 | import { pick } from 'lodash'; | ||
1 | import { sendAuthRequest } from '../../api/utils/auth'; | 2 | import { sendAuthRequest } from '../../api/utils/auth'; |
2 | import { API, API_VERSION } from '../../environment'; | 3 | import { API, API_VERSION } from '../../environment'; |
3 | 4 | ||
@@ -25,4 +26,14 @@ export default { | |||
25 | if (!request.ok) throw request; | 26 | if (!request.ok) throw request; |
26 | return request.json(); | 27 | return request.json(); |
27 | }, | 28 | }, |
29 | |||
30 | updateWorkspace: async (workspace) => { | ||
31 | const url = `${API}/${API_VERSION}/workspace/${workspace.id}`; | ||
32 | const request = await sendAuthRequest(url, { | ||
33 | method: 'PUT', | ||
34 | body: JSON.stringify(pick(workspace, ['name', 'services'])), | ||
35 | }); | ||
36 | if (!request.ok) throw request; | ||
37 | return request.json(); | ||
38 | }, | ||
28 | }; | 39 | }; |
diff --git a/src/features/workspaces/components/EditWorkspaceForm.js b/src/features/workspaces/components/EditWorkspaceForm.js index 05ca65403..48090f608 100644 --- a/src/features/workspaces/components/EditWorkspaceForm.js +++ b/src/features/workspaces/components/EditWorkspaceForm.js | |||
@@ -7,8 +7,10 @@ import { Input, Button } from '@meetfranz/forms'; | |||
7 | import injectSheet from 'react-jss'; | 7 | import injectSheet from 'react-jss'; |
8 | 8 | ||
9 | import Workspace from '../models/Workspace'; | 9 | import Workspace from '../models/Workspace'; |
10 | import Service from '../../../models/Service'; | ||
10 | import Form from '../../../lib/Form'; | 11 | import Form from '../../../lib/Form'; |
11 | import { required } from '../../../helpers/validation-helpers'; | 12 | import { required } from '../../../helpers/validation-helpers'; |
13 | import ServiceListItem from './ServiceListItem'; | ||
12 | 14 | ||
13 | const messages = defineMessages({ | 15 | const messages = defineMessages({ |
14 | buttonDelete: { | 16 | buttonDelete: { |
@@ -27,12 +29,19 @@ const messages = defineMessages({ | |||
27 | id: 'settings.workspace.form.yourWorkspaces', | 29 | id: 'settings.workspace.form.yourWorkspaces', |
28 | defaultMessage: '!!!Your workspaces', | 30 | defaultMessage: '!!!Your workspaces', |
29 | }, | 31 | }, |
32 | servicesInWorkspaceHeadline: { | ||
33 | id: 'settings.workspace.form.servicesInWorkspaceHeadline', | ||
34 | defaultMessage: '!!!Services in this Workspace', | ||
35 | }, | ||
30 | }); | 36 | }); |
31 | 37 | ||
32 | const styles = () => ({ | 38 | const styles = () => ({ |
33 | nameInput: { | 39 | nameInput: { |
34 | height: 'auto', | 40 | height: 'auto', |
35 | }, | 41 | }, |
42 | serviceList: { | ||
43 | height: 'auto', | ||
44 | }, | ||
36 | }); | 45 | }); |
37 | 46 | ||
38 | @injectSheet(styles) @observer | 47 | @injectSheet(styles) @observer |
@@ -42,11 +51,13 @@ class EditWorkspaceForm extends Component { | |||
42 | }; | 51 | }; |
43 | 52 | ||
44 | static propTypes = { | 53 | static propTypes = { |
45 | workspace: PropTypes.instanceOf(Workspace).isRequired, | 54 | classes: PropTypes.object.isRequired, |
46 | onSave: PropTypes.func.isRequired, | ||
47 | onDelete: PropTypes.func.isRequired, | ||
48 | isSaving: PropTypes.bool.isRequired, | ||
49 | isDeleting: PropTypes.bool.isRequired, | 55 | isDeleting: PropTypes.bool.isRequired, |
56 | isSaving: PropTypes.bool.isRequired, | ||
57 | onDelete: PropTypes.func.isRequired, | ||
58 | onSave: PropTypes.func.isRequired, | ||
59 | services: PropTypes.arrayOf(PropTypes.instanceOf(Service)).isRequired, | ||
60 | workspace: PropTypes.instanceOf(Workspace).isRequired, | ||
50 | }; | 61 | }; |
51 | 62 | ||
52 | form = this.prepareWorkspaceForm(this.props.workspace); | 63 | form = this.prepareWorkspaceForm(this.props.workspace); |
@@ -68,6 +79,9 @@ class EditWorkspaceForm extends Component { | |||
68 | value: workspace.name, | 79 | value: workspace.name, |
69 | validators: [required], | 80 | validators: [required], |
70 | }, | 81 | }, |
82 | services: { | ||
83 | value: workspace.services.slice(), | ||
84 | }, | ||
71 | }, | 85 | }, |
72 | }); | 86 | }); |
73 | } | 87 | } |
@@ -83,6 +97,17 @@ class EditWorkspaceForm extends Component { | |||
83 | }); | 97 | }); |
84 | } | 98 | } |
85 | 99 | ||
100 | toggleService(service) { | ||
101 | const servicesField = this.form.$('services'); | ||
102 | const serviceIds = servicesField.value; | ||
103 | if (serviceIds.includes(service.id)) { | ||
104 | serviceIds.splice(serviceIds.indexOf(service.id), 1); | ||
105 | } else { | ||
106 | serviceIds.push(service.id); | ||
107 | } | ||
108 | servicesField.set(serviceIds); | ||
109 | } | ||
110 | |||
86 | render() { | 111 | render() { |
87 | const { intl } = this.context; | 112 | const { intl } = this.context; |
88 | const { | 113 | const { |
@@ -91,8 +116,10 @@ class EditWorkspaceForm extends Component { | |||
91 | isSaving, | 116 | isSaving, |
92 | onDelete, | 117 | onDelete, |
93 | workspace, | 118 | workspace, |
119 | services, | ||
94 | } = this.props; | 120 | } = this.props; |
95 | const { form } = this; | 121 | const { form } = this; |
122 | const workspaceServices = form.$('services').value; | ||
96 | return ( | 123 | return ( |
97 | <div className="settings__main"> | 124 | <div className="settings__main"> |
98 | <div className="settings__header"> | 125 | <div className="settings__header"> |
@@ -110,6 +137,17 @@ class EditWorkspaceForm extends Component { | |||
110 | <div className={classes.nameInput}> | 137 | <div className={classes.nameInput}> |
111 | <Input {...form.$('name').bind()} /> | 138 | <Input {...form.$('name').bind()} /> |
112 | </div> | 139 | </div> |
140 | <h2>{intl.formatMessage(messages.servicesInWorkspaceHeadline)}</h2> | ||
141 | <div className={classes.serviceList}> | ||
142 | {services.map(s => ( | ||
143 | <ServiceListItem | ||
144 | key={s.id} | ||
145 | service={s} | ||
146 | isInWorkspace={workspaceServices.includes(s.id)} | ||
147 | onToggle={() => this.toggleService(s)} | ||
148 | /> | ||
149 | ))} | ||
150 | </div> | ||
113 | </div> | 151 | </div> |
114 | <div className="settings__controls"> | 152 | <div className="settings__controls"> |
115 | {/* ===== Delete Button ===== */} | 153 | {/* ===== Delete Button ===== */} |
diff --git a/src/features/workspaces/components/ServiceListItem.js b/src/features/workspaces/components/ServiceListItem.js new file mode 100644 index 000000000..146cc5a36 --- /dev/null +++ b/src/features/workspaces/components/ServiceListItem.js | |||
@@ -0,0 +1,48 @@ | |||
1 | import React, { Component } from 'react'; | ||
2 | import PropTypes from 'prop-types'; | ||
3 | import { observer } from 'mobx-react'; | ||
4 | import injectSheet from 'react-jss'; | ||
5 | import { Toggle } from '@meetfranz/forms'; | ||
6 | |||
7 | import Service from '../../../models/Service'; | ||
8 | |||
9 | const styles = () => ({ | ||
10 | service: { | ||
11 | height: 'auto', | ||
12 | display: 'flex', | ||
13 | }, | ||
14 | name: { | ||
15 | marginTop: '4px', | ||
16 | }, | ||
17 | }); | ||
18 | |||
19 | @injectSheet(styles) @observer | ||
20 | class ServiceListItem extends Component { | ||
21 | static propTypes = { | ||
22 | classes: PropTypes.object.isRequired, | ||
23 | isInWorkspace: PropTypes.bool.isRequired, | ||
24 | onToggle: PropTypes.func.isRequired, | ||
25 | service: PropTypes.instanceOf(Service).isRequired, | ||
26 | }; | ||
27 | |||
28 | render() { | ||
29 | const { | ||
30 | classes, | ||
31 | isInWorkspace, | ||
32 | onToggle, | ||
33 | service, | ||
34 | } = this.props; | ||
35 | |||
36 | return ( | ||
37 | <div className={classes.service}> | ||
38 | <Toggle | ||
39 | checked={isInWorkspace} | ||
40 | onChange={onToggle} | ||
41 | label={service.name} | ||
42 | /> | ||
43 | </div> | ||
44 | ); | ||
45 | } | ||
46 | } | ||
47 | |||
48 | export default ServiceListItem; | ||
diff --git a/src/features/workspaces/containers/EditWorkspaceScreen.js b/src/features/workspaces/containers/EditWorkspaceScreen.js index 17b723303..790b8a0fe 100644 --- a/src/features/workspaces/containers/EditWorkspaceScreen.js +++ b/src/features/workspaces/containers/EditWorkspaceScreen.js | |||
@@ -5,6 +5,8 @@ import PropTypes from 'prop-types'; | |||
5 | import ErrorBoundary from '../../../components/util/ErrorBoundary'; | 5 | import ErrorBoundary from '../../../components/util/ErrorBoundary'; |
6 | import EditWorkspaceForm from '../components/EditWorkspaceForm'; | 6 | import EditWorkspaceForm from '../components/EditWorkspaceForm'; |
7 | import { state } from '../state'; | 7 | import { state } from '../state'; |
8 | import ServicesStore from '../../../stores/ServicesStore'; | ||
9 | import Workspace from '../models/Workspace'; | ||
8 | 10 | ||
9 | @inject('stores', 'actions') @observer | 11 | @inject('stores', 'actions') @observer |
10 | class EditWorkspaceScreen extends Component { | 12 | class EditWorkspaceScreen extends Component { |
@@ -14,6 +16,9 @@ class EditWorkspaceScreen extends Component { | |||
14 | delete: PropTypes.func.isRequired, | 16 | delete: PropTypes.func.isRequired, |
15 | }), | 17 | }), |
16 | }).isRequired, | 18 | }).isRequired, |
19 | stores: PropTypes.shape({ | ||
20 | services: PropTypes.instanceOf(ServicesStore).isRequired, | ||
21 | }).isRequired, | ||
17 | }; | 22 | }; |
18 | 23 | ||
19 | onDelete = () => { | 24 | onDelete = () => { |
@@ -24,16 +29,23 @@ class EditWorkspaceScreen extends Component { | |||
24 | }; | 29 | }; |
25 | 30 | ||
26 | onSave = (values) => { | 31 | onSave = (values) => { |
27 | console.log('save workspace', values); | 32 | const { workspaceBeingEdited } = state; |
33 | const { actions } = this.props; | ||
34 | const workspace = new Workspace( | ||
35 | Object.assign({}, workspaceBeingEdited, values), | ||
36 | ); | ||
37 | actions.workspace.update({ workspace }); | ||
28 | }; | 38 | }; |
29 | 39 | ||
30 | render() { | 40 | render() { |
31 | const { workspaceBeingEdited } = state; | 41 | const { workspaceBeingEdited } = state; |
42 | const { stores } = this.props; | ||
32 | if (!workspaceBeingEdited) return null; | 43 | if (!workspaceBeingEdited) return null; |
33 | return ( | 44 | return ( |
34 | <ErrorBoundary> | 45 | <ErrorBoundary> |
35 | <EditWorkspaceForm | 46 | <EditWorkspaceForm |
36 | workspace={workspaceBeingEdited} | 47 | workspace={workspaceBeingEdited} |
48 | services={stores.services.all} | ||
37 | onDelete={this.onDelete} | 49 | onDelete={this.onDelete} |
38 | onSave={this.onSave} | 50 | onSave={this.onSave} |
39 | isDeleting={false} | 51 | isDeleting={false} |
diff --git a/src/features/workspaces/models/Workspace.js b/src/features/workspaces/models/Workspace.js index ede2710dc..6c73d7095 100644 --- a/src/features/workspaces/models/Workspace.js +++ b/src/features/workspaces/models/Workspace.js | |||
@@ -19,7 +19,7 @@ export default class Workspace { | |||
19 | this.id = data.id; | 19 | this.id = data.id; |
20 | this.name = data.name; | 20 | this.name = data.name; |
21 | this.order = data.order; | 21 | this.order = data.order; |
22 | this.services = data.services; | 22 | this.services.replace(data.services); |
23 | this.userId = data.userId; | 23 | this.userId = data.userId; |
24 | } | 24 | } |
25 | } | 25 | } |
diff --git a/src/features/workspaces/store.js b/src/features/workspaces/store.js index a9b93f904..5cccb2ab7 100644 --- a/src/features/workspaces/store.js +++ b/src/features/workspaces/store.js | |||
@@ -51,6 +51,7 @@ export default class WorkspacesStore extends Store { | |||
51 | this.actions.workspace.edit.listen(this._edit); | 51 | this.actions.workspace.edit.listen(this._edit); |
52 | this.actions.workspace.create.listen(this._create); | 52 | this.actions.workspace.create.listen(this._create); |
53 | this.actions.workspace.delete.listen(this._delete); | 53 | this.actions.workspace.delete.listen(this._delete); |
54 | this.actions.workspace.update.listen(this._update); | ||
54 | } | 55 | } |
55 | 56 | ||
56 | _setWorkspaces = (workspaces) => { | 57 | _setWorkspaces = (workspaces) => { |
@@ -88,4 +89,15 @@ export default class WorkspacesStore extends Store { | |||
88 | throw error; | 89 | throw error; |
89 | } | 90 | } |
90 | }; | 91 | }; |
92 | |||
93 | _update = async ({ workspace }) => { | ||
94 | try { | ||
95 | await this.api.updateWorkspace(workspace); | ||
96 | const localWorkspace = this.state.workspaces.find(ws => ws.id === workspace.id); | ||
97 | Object.assign(localWorkspace, workspace); | ||
98 | this.stores.router.push('/settings/workspaces'); | ||
99 | } catch (error) { | ||
100 | throw error; | ||
101 | } | ||
102 | }; | ||
91 | } | 103 | } |
diff --git a/src/i18n/locales/de.json b/src/i18n/locales/de.json index e1a955176..4906070a3 100644 --- a/src/i18n/locales/de.json +++ b/src/i18n/locales/de.json | |||
@@ -224,6 +224,7 @@ | |||
224 | "settings.workspace.form.name": "Name", | 224 | "settings.workspace.form.name": "Name", |
225 | "settings.workspace.form.buttonDelete": "Workspace löschen", | 225 | "settings.workspace.form.buttonDelete": "Workspace löschen", |
226 | "settings.workspace.form.buttonSave": "Workspace speichern", | 226 | "settings.workspace.form.buttonSave": "Workspace speichern", |
227 | "settings.workspace.form.servicesInWorkspaceHeadline": "Services in diesem Workspace", | ||
227 | "settings.user.form.accountType.company" : "Firma", | 228 | "settings.user.form.accountType.company" : "Firma", |
228 | "settings.user.form.accountType.individual" : "Einzelperson", | 229 | "settings.user.form.accountType.individual" : "Einzelperson", |
229 | "settings.user.form.accountType.label" : "Konto-Typ", | 230 | "settings.user.form.accountType.label" : "Konto-Typ", |
diff --git a/src/i18n/locales/en-US.json b/src/i18n/locales/en-US.json index fe16e916f..cd5c417e3 100644 --- a/src/i18n/locales/en-US.json +++ b/src/i18n/locales/en-US.json | |||
@@ -207,6 +207,7 @@ | |||
207 | "settings.workspace.form.name": "Name", | 207 | "settings.workspace.form.name": "Name", |
208 | "settings.workspace.form.buttonDelete": "Delete Workspace", | 208 | "settings.workspace.form.buttonDelete": "Delete Workspace", |
209 | "settings.workspace.form.buttonSave": "Save Workspace", | 209 | "settings.workspace.form.buttonSave": "Save Workspace", |
210 | "settings.workspace.form.servicesInWorkspaceHeadline": "Services in this Workspace", | ||
210 | "subscription.type.free": "free", | 211 | "subscription.type.free": "free", |
211 | "subscription.type.month": "month", | 212 | "subscription.type.month": "month", |
212 | "subscription.type.year": "year", | 213 | "subscription.type.year": "year", |