aboutsummaryrefslogtreecommitdiffstats
path: root/src/features/workspaces/components/EditWorkspaceForm.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'src/features/workspaces/components/EditWorkspaceForm.tsx')
-rw-r--r--src/features/workspaces/components/EditWorkspaceForm.tsx247
1 files changed, 247 insertions, 0 deletions
diff --git a/src/features/workspaces/components/EditWorkspaceForm.tsx b/src/features/workspaces/components/EditWorkspaceForm.tsx
new file mode 100644
index 000000000..a860ac2e8
--- /dev/null
+++ b/src/features/workspaces/components/EditWorkspaceForm.tsx
@@ -0,0 +1,247 @@
1import { Component, ReactElement } from 'react';
2import { observer } from 'mobx-react';
3import { defineMessages, injectIntl, WrappedComponentProps } from 'react-intl';
4import { Link } from 'react-router-dom';
5import withStyles, { WithStylesProps } from 'react-jss';
6import Infobox from '../../../components/ui/infobox/index';
7import Input from '../../../components/ui/input';
8import Button from '../../../components/ui/button';
9import Workspace from '../models/Workspace';
10import Service from '../../../models/Service';
11import Form from '../../../lib/Form';
12import { required } from '../../../helpers/validation-helpers';
13import WorkspaceServiceListItem from './WorkspaceServiceListItem';
14import Request from '../../../stores/lib/Request';
15import { KEEP_WS_LOADED_USID } from '../../../config';
16import Toggle from '../../../components/ui/toggle';
17import { H2 } from '../../../components/ui/headline';
18
19const messages = defineMessages({
20 buttonDelete: {
21 id: 'settings.workspace.form.buttonDelete',
22 defaultMessage: 'Delete workspace',
23 },
24 buttonSave: {
25 id: 'settings.workspace.form.buttonSave',
26 defaultMessage: 'Save workspace',
27 },
28 name: {
29 id: 'settings.workspace.form.name',
30 defaultMessage: 'Name',
31 },
32 yourWorkspaces: {
33 id: 'settings.workspace.form.yourWorkspaces',
34 defaultMessage: 'Your workspaces',
35 },
36 keepLoaded: {
37 id: 'settings.workspace.form.keepLoaded',
38 defaultMessage: 'Keep this workspace loaded*',
39 },
40 keepLoadedInfo: {
41 id: 'settings.workspace.form.keepLoadedInfo',
42 defaultMessage:
43 '*This option will be overwritten by the global "Keep all workspaces loaded" option.',
44 },
45 servicesInWorkspaceHeadline: {
46 id: 'settings.workspace.form.servicesInWorkspaceHeadline',
47 defaultMessage: 'Services in this Workspace',
48 },
49 noServicesAdded: {
50 id: 'settings.services.noServicesAdded',
51 defaultMessage: 'Start by adding a service.',
52 },
53 discoverServices: {
54 id: 'settings.services.discoverServices',
55 defaultMessage: 'Discover services',
56 },
57});
58
59const styles = {
60 nameInput: {
61 height: 'auto',
62 },
63 serviceList: {
64 height: 'auto',
65 },
66 keepLoadedInfo: {
67 marginBottom: '2rem !important',
68 },
69};
70
71interface IProps extends WithStylesProps<typeof styles>, WrappedComponentProps {
72 onDelete: () => void;
73 onSave: (...args: any[]) => void;
74 services: Service[];
75 workspace: Workspace;
76 updateWorkspaceRequest: Request;
77 deleteWorkspaceRequest: Request;
78}
79
80@observer
81class EditWorkspaceForm extends Component<IProps> {
82 form: Form;
83
84 constructor(props: IProps) {
85 super(props);
86
87 this.form = this.prepareWorkspaceForm(this.props.workspace);
88 }
89
90 UNSAFE_componentWillReceiveProps(nextProps): void {
91 const { workspace } = this.props;
92 if (workspace.id !== nextProps.workspace.id) {
93 this.form = this.prepareWorkspaceForm(nextProps.workspace);
94 }
95 }
96
97 prepareWorkspaceForm(workspace: Workspace): Form {
98 const { intl, updateWorkspaceRequest } = this.props;
99 updateWorkspaceRequest.reset();
100
101 return new Form({
102 fields: {
103 name: {
104 label: intl.formatMessage(messages.name),
105 placeholder: intl.formatMessage(messages.name),
106 value: workspace.name,
107 validators: [required],
108 },
109 keepLoaded: {
110 label: intl.formatMessage(messages.keepLoaded),
111 value: workspace.services.includes(KEEP_WS_LOADED_USID),
112 default: false,
113 type: 'checkbox',
114 },
115 services: {
116 value: [...workspace.services],
117 },
118 },
119 });
120 }
121
122 save(form): void {
123 this.props.updateWorkspaceRequest.reset();
124 form.submit({
125 onSuccess: async f => {
126 const { onSave } = this.props;
127 const values = f.values();
128 onSave(values);
129 },
130 onError: async () => {},
131 });
132 }
133
134 delete(): void {
135 const { onDelete } = this.props;
136 onDelete();
137 }
138
139 toggleService(service: Service): void {
140 const servicesField = this.form.$('services');
141 const serviceIds = servicesField.value;
142 if (serviceIds.includes(service.id)) {
143 serviceIds.splice(serviceIds.indexOf(service.id), 1);
144 } else {
145 serviceIds.push(service.id);
146 }
147 servicesField.set(serviceIds);
148 }
149
150 render(): ReactElement {
151 const {
152 classes,
153 workspace,
154 services,
155 deleteWorkspaceRequest,
156 updateWorkspaceRequest,
157 intl,
158 } = this.props;
159 const { form } = this;
160 const workspaceServices = form.$('services').value;
161 const isDeleting = deleteWorkspaceRequest.isExecuting;
162 const isSaving = updateWorkspaceRequest.isExecuting;
163
164 return (
165 <div className="settings__main">
166 <div className="settings__header">
167 <span className="settings__header-item">
168 <Link to="/settings/workspaces">
169 {intl.formatMessage(messages.yourWorkspaces)}
170 </Link>
171 </span>
172 <span className="separator" />
173 <span className="settings__header-item">{workspace.name}</span>
174 </div>
175 <div className="settings__body">
176 {updateWorkspaceRequest.error && (
177 <Infobox icon="alert" type="danger">
178 Error while saving workspace
179 </Infobox>
180 )}
181 <div className={classes.nameInput}>
182 <Input {...form.$('name').bind()} />
183 <Toggle {...form.$('keepLoaded').bind()} />
184 <p className={`${classes.keepLoadedInfo} franz-form__label`}>
185 {intl.formatMessage(messages.keepLoadedInfo)}
186 </p>
187 </div>
188 <H2>{intl.formatMessage(messages.servicesInWorkspaceHeadline)}</H2>
189 <div className={classes.serviceList}>
190 {services.length === 0 ? (
191 <div className="align-middle settings__empty-state">
192 {/* ===== Empty state ===== */}
193 <p className="settings__empty-text">
194 <span className="emoji">
195 <img src="./assets/images/emoji/sad.png" alt="" />
196 </span>
197 {intl.formatMessage(messages.noServicesAdded)}
198 </p>
199 <Link to="/settings/recipes" className="button">
200 {intl.formatMessage(messages.discoverServices)}
201 </Link>
202 </div>
203 ) : (
204 <>
205 {services.map(service => (
206 <WorkspaceServiceListItem
207 key={service.id}
208 service={service}
209 isInWorkspace={workspaceServices.includes(service.id)}
210 onToggle={() => this.toggleService(service)}
211 />
212 ))}
213 </>
214 )}
215 </div>
216 </div>
217 <div className="settings__controls">
218 {/* ===== Delete Button ===== */}
219 <Button
220 label={intl.formatMessage(messages.buttonDelete)}
221 loaded={false}
222 busy={isDeleting}
223 buttonType={isDeleting ? 'secondary' : 'danger'}
224 className="settings__delete-button"
225 disabled={isDeleting}
226 onClick={this.delete.bind(this)}
227 />
228 {/* ===== Save Button ===== */}
229 <Button
230 type="submit"
231 label={intl.formatMessage(messages.buttonSave)}
232 busy={isSaving}
233 className="franz-form__button"
234 buttonType={isSaving ? 'secondary' : 'primary'}
235 onClick={this.save.bind(this, form)}
236 // TODO: Need to disable if no services have been added to this workspace
237 disabled={isSaving}
238 />
239 </div>
240 </div>
241 );
242 }
243}
244
245export default injectIntl(
246 withStyles(styles, { injectTheme: true })(EditWorkspaceForm),
247);