aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar Dominik Guzei <dominik.guzei@gmail.com>2019-02-26 15:29:34 +0100
committerLibravatar Dominik Guzei <dominik.guzei@gmail.com>2019-02-26 15:29:34 +0100
commitdca7437b45c8eb67692a1df563fb4e969826b1cc (patch)
tree781bc8f5e99bce0e42b16018517725900bfef86d
parentimprove workspace form setup (diff)
downloadferdium-app-dca7437b45c8eb67692a1df563fb4e969826b1cc.tar.gz
ferdium-app-dca7437b45c8eb67692a1df563fb4e969826b1cc.tar.zst
ferdium-app-dca7437b45c8eb67692a1df563fb4e969826b1cc.zip
finish basic workspace settings
-rw-r--r--src/features/workspaces/actions.js3
-rw-r--r--src/features/workspaces/api.js11
-rw-r--r--src/features/workspaces/components/EditWorkspaceForm.js46
-rw-r--r--src/features/workspaces/components/ServiceListItem.js48
-rw-r--r--src/features/workspaces/containers/EditWorkspaceScreen.js14
-rw-r--r--src/features/workspaces/models/Workspace.js2
-rw-r--r--src/features/workspaces/store.js12
-rw-r--r--src/i18n/locales/de.json1
-rw-r--r--src/i18n/locales/en-US.json1
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 @@
1import { pick } from 'lodash';
1import { sendAuthRequest } from '../../api/utils/auth'; 2import { sendAuthRequest } from '../../api/utils/auth';
2import { API, API_VERSION } from '../../environment'; 3import { 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';
7import injectSheet from 'react-jss'; 7import injectSheet from 'react-jss';
8 8
9import Workspace from '../models/Workspace'; 9import Workspace from '../models/Workspace';
10import Service from '../../../models/Service';
10import Form from '../../../lib/Form'; 11import Form from '../../../lib/Form';
11import { required } from '../../../helpers/validation-helpers'; 12import { required } from '../../../helpers/validation-helpers';
13import ServiceListItem from './ServiceListItem';
12 14
13const messages = defineMessages({ 15const 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
32const styles = () => ({ 38const 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 @@
1import React, { Component } from 'react';
2import PropTypes from 'prop-types';
3import { observer } from 'mobx-react';
4import injectSheet from 'react-jss';
5import { Toggle } from '@meetfranz/forms';
6
7import Service from '../../../models/Service';
8
9const styles = () => ({
10 service: {
11 height: 'auto',
12 display: 'flex',
13 },
14 name: {
15 marginTop: '4px',
16 },
17});
18
19@injectSheet(styles) @observer
20class 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
48export 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';
5import ErrorBoundary from '../../../components/util/ErrorBoundary'; 5import ErrorBoundary from '../../../components/util/ErrorBoundary';
6import EditWorkspaceForm from '../components/EditWorkspaceForm'; 6import EditWorkspaceForm from '../components/EditWorkspaceForm';
7import { state } from '../state'; 7import { state } from '../state';
8import ServicesStore from '../../../stores/ServicesStore';
9import Workspace from '../models/Workspace';
8 10
9@inject('stores', 'actions') @observer 11@inject('stores', 'actions') @observer
10class EditWorkspaceScreen extends Component { 12class 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",