@plusscommunities/pluss-maintenance-web-forms 1.2.4-beta.0 → 1.2.4-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{index.esm.js → index.js} +3161 -2629
- package/dist/index.js.map +1 -0
- package/package.json +13 -20
- package/.babelrc +0 -3
- package/dist/index.cjs.js +0 -6232
- package/dist/index.umd.js +0 -6225
- package/rollup.config.js +0 -59
- package/src/actions/JobsActions.js +0 -150
- package/src/actions/index.js +0 -1
- package/src/actions/types.js +0 -8
- package/src/apis/index.js +0 -10
- package/src/apis/maintenanceActions.js +0 -203
- package/src/apis/reactionActions.js +0 -46
- package/src/components/ActivityText.js +0 -57
- package/src/components/AnalyticsHub.js +0 -167
- package/src/components/Configuration.js +0 -392
- package/src/components/JobList.js +0 -1108
- package/src/components/JobTypes.js +0 -198
- package/src/components/PreviewFull.js +0 -33
- package/src/components/PreviewGrid.js +0 -29
- package/src/components/PreviewWidget.js +0 -35
- package/src/components/ViewFull.js +0 -25
- package/src/components/ViewWidget.js +0 -23
- package/src/feature.config.js +0 -127
- package/src/helper/index.js +0 -26
- package/src/images/forms/full.png +0 -0
- package/src/images/forms/fullNoTitle.png +0 -0
- package/src/images/forms/previewWidget.png +0 -0
- package/src/images/forms/widget.png +0 -0
- package/src/images/full.png +0 -0
- package/src/images/fullNoTitle.png +0 -0
- package/src/images/previewWidget.png +0 -0
- package/src/images/widget.png +0 -0
- package/src/index.js +0 -29
- package/src/maintenancePriority.json +0 -5
- package/src/maintenanceStatus.json +0 -20
- package/src/reducers/MaintenanceReducer.js +0 -49
- package/src/screens/AddJob.js +0 -1138
- package/src/screens/AddJobType.js +0 -865
- package/src/screens/Job.js +0 -1531
- package/src/screens/RequestsHub.js +0 -237
- package/src/values.config.a.js +0 -63
- package/src/values.config.default.js +0 -75
- package/src/values.config.enquiry.js +0 -76
- package/src/values.config.feedback.js +0 -74
- package/src/values.config.food.js +0 -74
- package/src/values.config.forms.js +0 -74
- package/src/values.config.js +0 -74
|
@@ -1,865 +0,0 @@
|
|
|
1
|
-
import React, { Component } from 'react';
|
|
2
|
-
import { Table } from 'react-bootstrap';
|
|
3
|
-
import { withRouter } from 'react-router';
|
|
4
|
-
import _ from 'lodash';
|
|
5
|
-
import { connect } from 'react-redux';
|
|
6
|
-
import FontAwesome from 'react-fontawesome';
|
|
7
|
-
import { PlussCore } from '../feature.config';
|
|
8
|
-
import { jobTypesUpdate } from '../actions';
|
|
9
|
-
import { maintenanceActions } from '../apis';
|
|
10
|
-
import { values } from '../values.config';
|
|
11
|
-
import { Colours } from '@plusscommunities/pluss-core-web';
|
|
12
|
-
|
|
13
|
-
const { Components, Session, Helper } = PlussCore;
|
|
14
|
-
const DEFAULT_FIELD = { type: 'text', label: '', mandatory: false, isTitle: false, values: [''] };
|
|
15
|
-
|
|
16
|
-
class AddJobType extends Component {
|
|
17
|
-
constructor(props) {
|
|
18
|
-
super(props);
|
|
19
|
-
|
|
20
|
-
this.fieldTypes = [
|
|
21
|
-
{
|
|
22
|
-
Title: 'Text Input',
|
|
23
|
-
Key: 'text',
|
|
24
|
-
},
|
|
25
|
-
{
|
|
26
|
-
Title: 'Email Input',
|
|
27
|
-
Key: 'email',
|
|
28
|
-
},
|
|
29
|
-
{
|
|
30
|
-
Title: 'Phone Input',
|
|
31
|
-
Key: 'phone',
|
|
32
|
-
},
|
|
33
|
-
{
|
|
34
|
-
Title: 'Date Input',
|
|
35
|
-
Key: 'date',
|
|
36
|
-
},
|
|
37
|
-
{
|
|
38
|
-
Title: 'Time Input',
|
|
39
|
-
Key: 'time',
|
|
40
|
-
},
|
|
41
|
-
{
|
|
42
|
-
Title: 'Image Input',
|
|
43
|
-
Key: 'image',
|
|
44
|
-
},
|
|
45
|
-
// {
|
|
46
|
-
// Title: 'Document Input',
|
|
47
|
-
// Key: 'document',
|
|
48
|
-
// },
|
|
49
|
-
{
|
|
50
|
-
Title: 'Yes/No Question',
|
|
51
|
-
Key: 'yn',
|
|
52
|
-
},
|
|
53
|
-
{
|
|
54
|
-
Title: 'Multiple Choice',
|
|
55
|
-
Key: 'multichoice',
|
|
56
|
-
},
|
|
57
|
-
{
|
|
58
|
-
Title: 'Checkboxes',
|
|
59
|
-
Key: 'checkbox',
|
|
60
|
-
},
|
|
61
|
-
{
|
|
62
|
-
Title: 'Title Text',
|
|
63
|
-
Key: 'staticTitle',
|
|
64
|
-
},
|
|
65
|
-
{
|
|
66
|
-
Title: 'Paragraph Text',
|
|
67
|
-
Key: 'staticText',
|
|
68
|
-
},
|
|
69
|
-
];
|
|
70
|
-
|
|
71
|
-
this.state = {
|
|
72
|
-
loading: false,
|
|
73
|
-
jobTypeId: Helper.safeReadParams(this.props, 'jobTypeId') ? this.props.match.params.jobTypeId : null,
|
|
74
|
-
jobTypeName: '',
|
|
75
|
-
jobTypeEmail: '',
|
|
76
|
-
jobTypeDescription: '',
|
|
77
|
-
hasCustomFields: values.forceCustomFields ? true : false,
|
|
78
|
-
customFields: [_.cloneDeep(DEFAULT_FIELD)],
|
|
79
|
-
jobTypeLevel: 1,
|
|
80
|
-
warnings: [],
|
|
81
|
-
showWarnings: false,
|
|
82
|
-
submitting: false,
|
|
83
|
-
success: false,
|
|
84
|
-
};
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
UNSAFE_componentWillMount() {
|
|
88
|
-
Session.checkLoggedIn(this, this.props.auth);
|
|
89
|
-
if (this.state.jobTypeId) this.getJobType();
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
getJobType = async () => {
|
|
93
|
-
try {
|
|
94
|
-
const res = await maintenanceActions.getJobType(this.props.auth.site, this.state.jobTypeId);
|
|
95
|
-
|
|
96
|
-
const { typeName, email, description, level, hasCustomFields, customFields } = res.data;
|
|
97
|
-
this.setState({
|
|
98
|
-
jobTypeName: typeName,
|
|
99
|
-
jobTypeEmail: email,
|
|
100
|
-
jobTypeDescription: description,
|
|
101
|
-
jobTypeLevel: level,
|
|
102
|
-
hasCustomFields: !!hasCustomFields,
|
|
103
|
-
customFields: customFields || [_.cloneDeep(DEFAULT_FIELD)],
|
|
104
|
-
});
|
|
105
|
-
} catch (error) {
|
|
106
|
-
console.error('getJobType', error);
|
|
107
|
-
}
|
|
108
|
-
};
|
|
109
|
-
|
|
110
|
-
getFieldTypeTitle = (type) => {
|
|
111
|
-
const fieldType = this.fieldTypes.find((f) => f.Key === type);
|
|
112
|
-
return fieldType ? fieldType.Title : '';
|
|
113
|
-
};
|
|
114
|
-
|
|
115
|
-
validateEmail = () => {
|
|
116
|
-
const { jobTypeEmail } = this.state;
|
|
117
|
-
return !_.isEmpty(jobTypeEmail) && Helper.isEmail(jobTypeEmail);
|
|
118
|
-
};
|
|
119
|
-
|
|
120
|
-
isJobTypeValid = () => {
|
|
121
|
-
const { jobTypeName, jobTypeDescription } = this.state;
|
|
122
|
-
|
|
123
|
-
if (_.isEmpty(jobTypeName)) return false;
|
|
124
|
-
if (!this.validateEmail()) return false;
|
|
125
|
-
if (_.isEmpty(jobTypeDescription)) return false;
|
|
126
|
-
if (!this.validateCustomFields()) return false;
|
|
127
|
-
|
|
128
|
-
return true;
|
|
129
|
-
};
|
|
130
|
-
|
|
131
|
-
validateCustomFields() {
|
|
132
|
-
const { submitting, hasCustomFields, customFields } = this.state;
|
|
133
|
-
if (submitting) return false;
|
|
134
|
-
|
|
135
|
-
// Validate custom fields
|
|
136
|
-
const warnings = [];
|
|
137
|
-
if (hasCustomFields) {
|
|
138
|
-
let missingLabel = false;
|
|
139
|
-
let hasMandatoryField = false;
|
|
140
|
-
let titleFieldCount = 0;
|
|
141
|
-
customFields.forEach((field) => {
|
|
142
|
-
const { type, label, values, mandatory, isTitle } = field;
|
|
143
|
-
if (['staticTitle', 'staticText'].includes(type)) return;
|
|
144
|
-
|
|
145
|
-
if (_.isEmpty(label)) {
|
|
146
|
-
missingLabel = true;
|
|
147
|
-
} else if (
|
|
148
|
-
_.isEmpty(type) ||
|
|
149
|
-
((type === 'multichoice' || type === 'checkbox') && (!values || values.length < 2 || !values.every((value) => !_.isEmpty(value))))
|
|
150
|
-
) {
|
|
151
|
-
warnings.push(`'${label}' is incomplete`);
|
|
152
|
-
}
|
|
153
|
-
if (mandatory) hasMandatoryField = true;
|
|
154
|
-
if (isTitle) titleFieldCount += 1;
|
|
155
|
-
});
|
|
156
|
-
if (missingLabel) {
|
|
157
|
-
warnings.push('All inputs must have a label');
|
|
158
|
-
}
|
|
159
|
-
if (!hasMandatoryField) {
|
|
160
|
-
warnings.push('There must be at least one required input');
|
|
161
|
-
}
|
|
162
|
-
if (titleFieldCount > 1) {
|
|
163
|
-
warnings.push('Only one required input can be selected as title for the request');
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
this.setState({ warnings });
|
|
168
|
-
return warnings.length === 0;
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
onHandleChange = (event) => {
|
|
172
|
-
var stateChange = {};
|
|
173
|
-
stateChange[event.target.getAttribute('id')] = event.target.value;
|
|
174
|
-
this.setState(stateChange);
|
|
175
|
-
};
|
|
176
|
-
|
|
177
|
-
onFieldTypeChanged = (fieldIndex, key) => {
|
|
178
|
-
const customFields = [...this.state.customFields];
|
|
179
|
-
if (customFields[fieldIndex].type === key) return;
|
|
180
|
-
|
|
181
|
-
customFields[fieldIndex] = _.cloneDeep(DEFAULT_FIELD);
|
|
182
|
-
customFields[fieldIndex].type = key;
|
|
183
|
-
|
|
184
|
-
this.setState({ customFields });
|
|
185
|
-
};
|
|
186
|
-
|
|
187
|
-
onFieldLabelChanged = (fieldIndex, event) => {
|
|
188
|
-
const customFields = [...this.state.customFields];
|
|
189
|
-
customFields[fieldIndex].label = event.target.value;
|
|
190
|
-
|
|
191
|
-
this.setState({ customFields });
|
|
192
|
-
};
|
|
193
|
-
|
|
194
|
-
onFieldPlaceHolderChanged = (fieldIndex, event) => {
|
|
195
|
-
const customFields = [...this.state.customFields];
|
|
196
|
-
customFields[fieldIndex].placeHolder = event.target.value;
|
|
197
|
-
|
|
198
|
-
this.setState({ customFields });
|
|
199
|
-
};
|
|
200
|
-
|
|
201
|
-
onFieldMandatoryChanged = (fieldIndex) => {
|
|
202
|
-
const customFields = [...this.state.customFields];
|
|
203
|
-
customFields[fieldIndex].mandatory = !customFields[fieldIndex].mandatory;
|
|
204
|
-
if (!customFields[fieldIndex].mandatory) {
|
|
205
|
-
// If a field is not mandatory, it cannot be a title field
|
|
206
|
-
customFields[fieldIndex].isTitle = false;
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
this.setState({ customFields });
|
|
210
|
-
};
|
|
211
|
-
|
|
212
|
-
onFieldIsTitleChanged = (fieldIndex) => {
|
|
213
|
-
const customFields = [...this.state.customFields];
|
|
214
|
-
customFields[fieldIndex].isTitle = !customFields[fieldIndex].isTitle;
|
|
215
|
-
if (customFields[fieldIndex].isTitle) {
|
|
216
|
-
// If a field is title field, force mandatory
|
|
217
|
-
customFields[fieldIndex].mandatory = true;
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
this.setState({ customFields });
|
|
221
|
-
};
|
|
222
|
-
|
|
223
|
-
onFieldOptionChanged = (fieldIndex, optionIndex, event) => {
|
|
224
|
-
const customFields = [...this.state.customFields];
|
|
225
|
-
const prevValue = customFields[fieldIndex].values[optionIndex];
|
|
226
|
-
customFields[fieldIndex].values[optionIndex] = event.target.value;
|
|
227
|
-
// Change corresponding validation if exists
|
|
228
|
-
const validations = customFields[fieldIndex].validation;
|
|
229
|
-
let validation = validations ? validations.find((val) => val.value === prevValue) : null;
|
|
230
|
-
if (validation) validation.value = event.target.value;
|
|
231
|
-
|
|
232
|
-
this.setState({ customFields });
|
|
233
|
-
};
|
|
234
|
-
|
|
235
|
-
onAddNewOption = (fieldIndex) => {
|
|
236
|
-
const customFields = [...this.state.customFields];
|
|
237
|
-
customFields[fieldIndex].values.push('');
|
|
238
|
-
this.setState({ customFields });
|
|
239
|
-
};
|
|
240
|
-
|
|
241
|
-
onRemoveOption = (fieldIndex, optionIndex) => {
|
|
242
|
-
const customFields = [...this.state.customFields];
|
|
243
|
-
customFields[fieldIndex].values.splice(optionIndex, 1);
|
|
244
|
-
this.setState({ customFields });
|
|
245
|
-
};
|
|
246
|
-
|
|
247
|
-
onRemoveField(fieldIndex) {
|
|
248
|
-
const customFields = [...this.state.customFields];
|
|
249
|
-
if (customFields.length < 2) return;
|
|
250
|
-
|
|
251
|
-
customFields.splice(fieldIndex, 1);
|
|
252
|
-
this.setState({ customFields });
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
onAddNewField = () => {
|
|
256
|
-
const customFields = [...this.state.customFields];
|
|
257
|
-
customFields.push(_.cloneDeep(DEFAULT_FIELD));
|
|
258
|
-
this.setState({ customFields });
|
|
259
|
-
};
|
|
260
|
-
|
|
261
|
-
onMoveFieldPrev = (fieldIndex) => {
|
|
262
|
-
if (fieldIndex === 0) return;
|
|
263
|
-
const customFields = [...this.state.customFields];
|
|
264
|
-
const item = customFields.splice(fieldIndex, 1)[0];
|
|
265
|
-
customFields.splice(fieldIndex - 1, 0, item);
|
|
266
|
-
|
|
267
|
-
this.setState({ customFields });
|
|
268
|
-
};
|
|
269
|
-
|
|
270
|
-
onMoveFieldNext = (fieldIndex) => {
|
|
271
|
-
const customFields = [...this.state.customFields];
|
|
272
|
-
if (fieldIndex > customFields.length - 1) return;
|
|
273
|
-
const item = customFields.splice(fieldIndex, 1)[0];
|
|
274
|
-
customFields.splice(fieldIndex + 1, 0, item);
|
|
275
|
-
|
|
276
|
-
this.setState({ customFields });
|
|
277
|
-
};
|
|
278
|
-
|
|
279
|
-
onBack = () => {
|
|
280
|
-
window.history.back();
|
|
281
|
-
};
|
|
282
|
-
|
|
283
|
-
onSave = () => {
|
|
284
|
-
const { site } = this.props.auth;
|
|
285
|
-
const { submitting, jobTypeId, jobTypeName, jobTypeEmail, jobTypeDescription, jobTypeLevel, hasCustomFields, customFields } =
|
|
286
|
-
this.state;
|
|
287
|
-
|
|
288
|
-
if (submitting) return;
|
|
289
|
-
if (!this.isJobTypeValid()) {
|
|
290
|
-
this.setState({ showWarnings: true });
|
|
291
|
-
return;
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
this.setState({ submitting: true }, async () => {
|
|
295
|
-
try {
|
|
296
|
-
if (jobTypeId) {
|
|
297
|
-
await maintenanceActions.editJobType(
|
|
298
|
-
site,
|
|
299
|
-
jobTypeId,
|
|
300
|
-
jobTypeName,
|
|
301
|
-
jobTypeEmail,
|
|
302
|
-
jobTypeDescription,
|
|
303
|
-
jobTypeLevel,
|
|
304
|
-
hasCustomFields,
|
|
305
|
-
customFields,
|
|
306
|
-
);
|
|
307
|
-
} else {
|
|
308
|
-
await maintenanceActions.addJobType(
|
|
309
|
-
site,
|
|
310
|
-
jobTypeName,
|
|
311
|
-
jobTypeEmail,
|
|
312
|
-
jobTypeDescription,
|
|
313
|
-
jobTypeLevel,
|
|
314
|
-
hasCustomFields,
|
|
315
|
-
customFields,
|
|
316
|
-
);
|
|
317
|
-
}
|
|
318
|
-
this.props.jobTypesUpdate(site);
|
|
319
|
-
this.setState({ submitting: false, success: true });
|
|
320
|
-
} catch (error) {
|
|
321
|
-
console.error('onSave', error);
|
|
322
|
-
this.setState({ submitting: false });
|
|
323
|
-
alert('Something went wrong with the request. Please try again.');
|
|
324
|
-
}
|
|
325
|
-
});
|
|
326
|
-
};
|
|
327
|
-
|
|
328
|
-
renderBaseForm() {
|
|
329
|
-
const { success, jobTypeId, showWarnings, jobTypeName, jobTypeEmail, jobTypeDescription, hasCustomFields } = this.state;
|
|
330
|
-
if (success) return null;
|
|
331
|
-
|
|
332
|
-
// TODO: Request Type should be configurable
|
|
333
|
-
return (
|
|
334
|
-
<div className="padding-60 paddingVertical-40 bottomDivideBorder">
|
|
335
|
-
<Components.Text type="formTitleLarge" className="marginBottom-24">
|
|
336
|
-
{!jobTypeId ? 'New' : 'Edit'} {values.textJobType}
|
|
337
|
-
</Components.Text>
|
|
338
|
-
<Components.GenericInput
|
|
339
|
-
id="jobTypeName"
|
|
340
|
-
type="text"
|
|
341
|
-
label={`${values.textJobType} title`}
|
|
342
|
-
placeholder={`${values.textJobType} title`}
|
|
343
|
-
value={jobTypeName}
|
|
344
|
-
onChange={this.onHandleChange}
|
|
345
|
-
isRequired
|
|
346
|
-
isValid={() => !_.isEmpty(jobTypeName)}
|
|
347
|
-
showError={() => showWarnings && _.isEmpty(jobTypeName)}
|
|
348
|
-
alwaysShowLabel
|
|
349
|
-
/>
|
|
350
|
-
<Components.GenericInput
|
|
351
|
-
id="jobTypeEmail"
|
|
352
|
-
type="text"
|
|
353
|
-
label="Email"
|
|
354
|
-
placeholder="Email"
|
|
355
|
-
help={`This is the email address that'll be notified of new submissions for this ${`${values.textJobType}`}.`}
|
|
356
|
-
value={jobTypeEmail}
|
|
357
|
-
onChange={this.onHandleChange}
|
|
358
|
-
isRequired
|
|
359
|
-
isValid={this.validateEmail}
|
|
360
|
-
showError={() => showWarnings && !this.validateEmail()}
|
|
361
|
-
alwaysShowLabel
|
|
362
|
-
/>
|
|
363
|
-
<Components.GenericInput
|
|
364
|
-
id="jobTypeDescription"
|
|
365
|
-
type="text"
|
|
366
|
-
label="Description"
|
|
367
|
-
placeholder="Add a description. "
|
|
368
|
-
help={`This description will be visible to the people to help them select the correct ${`${values.textJobType}`}.`}
|
|
369
|
-
value={jobTypeDescription}
|
|
370
|
-
onChange={this.onHandleChange}
|
|
371
|
-
isRequired
|
|
372
|
-
isValid={() => !_.isEmpty(jobTypeDescription)}
|
|
373
|
-
showError={() => showWarnings && _.isEmpty(jobTypeDescription)}
|
|
374
|
-
alwaysShowLabel
|
|
375
|
-
/>
|
|
376
|
-
{values.forceCustomFields ? null : (
|
|
377
|
-
<Components.RadioButton
|
|
378
|
-
label={`Do you want to create a custom form for this ${`${values.textJobType}`}?`}
|
|
379
|
-
isActive={hasCustomFields}
|
|
380
|
-
options={[
|
|
381
|
-
{
|
|
382
|
-
Label: 'Yes',
|
|
383
|
-
Value: true,
|
|
384
|
-
onChange: () => this.setState({ hasCustomFields: true }),
|
|
385
|
-
},
|
|
386
|
-
{
|
|
387
|
-
Label: 'No',
|
|
388
|
-
Value: false,
|
|
389
|
-
onChange: () => this.setState({ hasCustomFields: false }),
|
|
390
|
-
},
|
|
391
|
-
]}
|
|
392
|
-
/>
|
|
393
|
-
)}
|
|
394
|
-
</div>
|
|
395
|
-
);
|
|
396
|
-
}
|
|
397
|
-
|
|
398
|
-
renderOptionalCheckBox(field, fieldIndex) {
|
|
399
|
-
return (
|
|
400
|
-
<Components.CheckBox
|
|
401
|
-
id={`fieldOptional${fieldIndex}`}
|
|
402
|
-
label="Set this field as optional"
|
|
403
|
-
isActive={!field.mandatory}
|
|
404
|
-
onChange={(e) => this.onFieldMandatoryChanged(fieldIndex, e)}
|
|
405
|
-
/>
|
|
406
|
-
);
|
|
407
|
-
}
|
|
408
|
-
|
|
409
|
-
renderTitleCheckBox(field, fieldIndex) {
|
|
410
|
-
return (
|
|
411
|
-
<Components.CheckBox
|
|
412
|
-
id={`fieldTitle${fieldIndex}`}
|
|
413
|
-
label={`Use this field as the ${values.textSingularName} title`}
|
|
414
|
-
isActive={field.isTitle}
|
|
415
|
-
onChange={(e) => this.onFieldIsTitleChanged(fieldIndex, e)}
|
|
416
|
-
/>
|
|
417
|
-
);
|
|
418
|
-
}
|
|
419
|
-
|
|
420
|
-
renderFieldText(field, fieldIndex) {
|
|
421
|
-
return (
|
|
422
|
-
<div className="fieldInner">
|
|
423
|
-
<Components.GenericInput
|
|
424
|
-
id={`fieldLabel${fieldIndex}`}
|
|
425
|
-
className={'textInput'}
|
|
426
|
-
placeholder={'Type your label here (required)'}
|
|
427
|
-
value={field.label}
|
|
428
|
-
onChange={(e) => this.onFieldLabelChanged(fieldIndex, e)}
|
|
429
|
-
/>
|
|
430
|
-
<Components.GenericInput
|
|
431
|
-
id={`fieldPlaceHolder${fieldIndex}`}
|
|
432
|
-
className={'placeHolderInput'}
|
|
433
|
-
placeholder={'Insert placeholder (optional)'}
|
|
434
|
-
value={field.placeHolder}
|
|
435
|
-
onChange={(e) => this.onFieldPlaceHolderChanged(fieldIndex, e)}
|
|
436
|
-
/>
|
|
437
|
-
{this.renderOptionalCheckBox(field, fieldIndex)}
|
|
438
|
-
{this.renderTitleCheckBox(field, fieldIndex)}
|
|
439
|
-
</div>
|
|
440
|
-
);
|
|
441
|
-
}
|
|
442
|
-
|
|
443
|
-
renderFieldDate(field, fieldIndex) {
|
|
444
|
-
return (
|
|
445
|
-
<div className="fieldInner">
|
|
446
|
-
<Components.GenericInput
|
|
447
|
-
id={`fieldLabel${fieldIndex}`}
|
|
448
|
-
className={'textInput'}
|
|
449
|
-
placeholder={'Type your label here (required)'}
|
|
450
|
-
value={field.label}
|
|
451
|
-
onChange={(e) => this.onFieldLabelChanged(fieldIndex, e)}
|
|
452
|
-
/>
|
|
453
|
-
{this.renderOptionalCheckBox(field, fieldIndex)}
|
|
454
|
-
{this.renderTitleCheckBox(field, fieldIndex)}
|
|
455
|
-
</div>
|
|
456
|
-
);
|
|
457
|
-
}
|
|
458
|
-
|
|
459
|
-
renderFieldTime(field, fieldIndex) {
|
|
460
|
-
return (
|
|
461
|
-
<div className="fieldInner">
|
|
462
|
-
<Components.GenericInput
|
|
463
|
-
id={`fieldLabel${fieldIndex}`}
|
|
464
|
-
className={'textInput'}
|
|
465
|
-
placeholder={'Type your label here (required)'}
|
|
466
|
-
value={field.label}
|
|
467
|
-
onChange={(e) => this.onFieldLabelChanged(fieldIndex, e)}
|
|
468
|
-
/>
|
|
469
|
-
{this.renderOptionalCheckBox(field, fieldIndex)}
|
|
470
|
-
{this.renderTitleCheckBox(field, fieldIndex)}
|
|
471
|
-
</div>
|
|
472
|
-
);
|
|
473
|
-
}
|
|
474
|
-
|
|
475
|
-
renderFieldImage(field, fieldIndex) {
|
|
476
|
-
return (
|
|
477
|
-
<div className="fieldInner">
|
|
478
|
-
<Components.GenericInput
|
|
479
|
-
id={`fieldLabel${fieldIndex}`}
|
|
480
|
-
className={'textInput'}
|
|
481
|
-
placeholder={'Type your label here (required)'}
|
|
482
|
-
value={field.label}
|
|
483
|
-
onChange={(e) => this.onFieldLabelChanged(fieldIndex, e)}
|
|
484
|
-
/>
|
|
485
|
-
{this.renderOptionalCheckBox(field, fieldIndex)}
|
|
486
|
-
</div>
|
|
487
|
-
);
|
|
488
|
-
}
|
|
489
|
-
|
|
490
|
-
renderFieldDocument(field, fieldIndex) {
|
|
491
|
-
return (
|
|
492
|
-
<div className="fieldInner">
|
|
493
|
-
<Components.GenericInput
|
|
494
|
-
id={`fieldLabel${fieldIndex}`}
|
|
495
|
-
className={'textInput'}
|
|
496
|
-
placeholder={'Type your label here (required)'}
|
|
497
|
-
value={field.label}
|
|
498
|
-
onChange={(e) => this.onFieldLabelChanged(fieldIndex, e)}
|
|
499
|
-
/>
|
|
500
|
-
{this.renderOptionalCheckBox(field, fieldIndex)}
|
|
501
|
-
</div>
|
|
502
|
-
);
|
|
503
|
-
}
|
|
504
|
-
|
|
505
|
-
renderFieldYesNo(field, fieldIndex) {
|
|
506
|
-
return (
|
|
507
|
-
<div className="fieldInner">
|
|
508
|
-
<Components.GenericInput
|
|
509
|
-
id={`fieldLabel${fieldIndex}`}
|
|
510
|
-
className={'textInput'}
|
|
511
|
-
placeholder={'Type your label here (required)'}
|
|
512
|
-
value={field.label}
|
|
513
|
-
onChange={(e) => this.onFieldLabelChanged(fieldIndex, e)}
|
|
514
|
-
/>
|
|
515
|
-
<Table className="optionsContainer">
|
|
516
|
-
<thead className="headings">
|
|
517
|
-
<tr>
|
|
518
|
-
<th className="icon" />
|
|
519
|
-
<th className="options">Options</th>
|
|
520
|
-
</tr>
|
|
521
|
-
</thead>
|
|
522
|
-
<tbody>
|
|
523
|
-
{['Yes', 'No'].map((value, optionIndex) => {
|
|
524
|
-
return (
|
|
525
|
-
<tr key={optionIndex} className="option">
|
|
526
|
-
<td>
|
|
527
|
-
<Components.RadioButton single disabled isActive={false} />
|
|
528
|
-
</td>
|
|
529
|
-
<td>
|
|
530
|
-
<Components.GenericInput id={`fieldOption${optionIndex}`} value={value} disabled />
|
|
531
|
-
</td>
|
|
532
|
-
</tr>
|
|
533
|
-
);
|
|
534
|
-
})}
|
|
535
|
-
</tbody>
|
|
536
|
-
</Table>
|
|
537
|
-
{this.renderOptionalCheckBox(field, fieldIndex)}
|
|
538
|
-
</div>
|
|
539
|
-
);
|
|
540
|
-
}
|
|
541
|
-
|
|
542
|
-
renderFieldMultiple(field, fieldIndex) {
|
|
543
|
-
const { customFields } = this.state;
|
|
544
|
-
return (
|
|
545
|
-
<div className="fieldInner">
|
|
546
|
-
<Components.GenericInput
|
|
547
|
-
id={`fieldLabel${fieldIndex}`}
|
|
548
|
-
className={'textInput'}
|
|
549
|
-
placeholder={'Type your label here (required)'}
|
|
550
|
-
value={field.label}
|
|
551
|
-
onChange={(e) => this.onFieldLabelChanged(fieldIndex, e)}
|
|
552
|
-
/>
|
|
553
|
-
<Table className="optionsContainer">
|
|
554
|
-
<thead className="headings">
|
|
555
|
-
<tr>
|
|
556
|
-
<th className="icon" />
|
|
557
|
-
<th className="options-wide">Options</th>
|
|
558
|
-
<th className="remove" />
|
|
559
|
-
</tr>
|
|
560
|
-
</thead>
|
|
561
|
-
<tbody>
|
|
562
|
-
{field.values &&
|
|
563
|
-
field.values.map((value, optionIndex) => {
|
|
564
|
-
return (
|
|
565
|
-
<tr key={optionIndex} className="option">
|
|
566
|
-
<td>
|
|
567
|
-
<Components.RadioButton single disabled isActive={false} />
|
|
568
|
-
</td>
|
|
569
|
-
<td>
|
|
570
|
-
<Components.GenericInput
|
|
571
|
-
id={`fieldOption${optionIndex}`}
|
|
572
|
-
placeholder={'Enter option'}
|
|
573
|
-
value={value}
|
|
574
|
-
onChange={(e) => this.onFieldOptionChanged(fieldIndex, optionIndex, e)}
|
|
575
|
-
/>
|
|
576
|
-
</td>
|
|
577
|
-
<td>
|
|
578
|
-
{customFields[fieldIndex].values.length > 1 ? (
|
|
579
|
-
<div onClick={() => this.onRemoveOption(fieldIndex, optionIndex)}>
|
|
580
|
-
<FontAwesome name="minus-circle" className="cornerCancelButton_icon" />
|
|
581
|
-
</div>
|
|
582
|
-
) : null}
|
|
583
|
-
</td>
|
|
584
|
-
</tr>
|
|
585
|
-
);
|
|
586
|
-
})}
|
|
587
|
-
</tbody>
|
|
588
|
-
</Table>
|
|
589
|
-
<div className="clearfix addoption optionAdd marginBottom-10" onClick={() => this.onAddNewOption(fieldIndex)}>
|
|
590
|
-
<Components.P60Icon className="addoption_plus" icon="add-circle" />
|
|
591
|
-
<div className="fillSpace">
|
|
592
|
-
<p className="addoption_text">Add Another Option</p>
|
|
593
|
-
</div>
|
|
594
|
-
</div>
|
|
595
|
-
{this.renderOptionalCheckBox(field, fieldIndex)}
|
|
596
|
-
{this.renderTitleCheckBox(field, fieldIndex)}
|
|
597
|
-
</div>
|
|
598
|
-
);
|
|
599
|
-
}
|
|
600
|
-
|
|
601
|
-
renderFieldCheckbox(field, fieldIndex) {
|
|
602
|
-
const { customFields } = this.state;
|
|
603
|
-
return (
|
|
604
|
-
<div className="fieldInner">
|
|
605
|
-
<Components.GenericInput
|
|
606
|
-
id={`fieldLabel${fieldIndex}`}
|
|
607
|
-
className={'textInput'}
|
|
608
|
-
placeholder={'Type your label here (required)'}
|
|
609
|
-
value={field.label}
|
|
610
|
-
onChange={(e) => this.onFieldLabelChanged(fieldIndex, e)}
|
|
611
|
-
/>
|
|
612
|
-
<Table className="optionsContainer">
|
|
613
|
-
<thead className="headings">
|
|
614
|
-
<tr>
|
|
615
|
-
<th className="icon" />
|
|
616
|
-
<th>Options</th>
|
|
617
|
-
<th className="remove" />
|
|
618
|
-
</tr>
|
|
619
|
-
</thead>
|
|
620
|
-
<tbody>
|
|
621
|
-
{field.values &&
|
|
622
|
-
field.values.map((value, optionIndex) => {
|
|
623
|
-
return (
|
|
624
|
-
<tr key={optionIndex} className="option">
|
|
625
|
-
<td>
|
|
626
|
-
<Components.RadioButton single disabled isActive={false} isSquare />
|
|
627
|
-
</td>
|
|
628
|
-
<td>
|
|
629
|
-
<Components.GenericInput
|
|
630
|
-
id={`fieldOption${optionIndex}`}
|
|
631
|
-
placeholder={'Enter option'}
|
|
632
|
-
value={value}
|
|
633
|
-
onChange={(e) => this.onFieldOptionChanged(fieldIndex, optionIndex, e)}
|
|
634
|
-
/>
|
|
635
|
-
</td>
|
|
636
|
-
<td>
|
|
637
|
-
{customFields[fieldIndex].values.length > 1 ? (
|
|
638
|
-
<div onClick={() => this.onRemoveOption(fieldIndex, optionIndex)}>
|
|
639
|
-
<FontAwesome name="minus-circle" className="cornerCancelButton_icon" />
|
|
640
|
-
</div>
|
|
641
|
-
) : null}
|
|
642
|
-
</td>
|
|
643
|
-
</tr>
|
|
644
|
-
);
|
|
645
|
-
})}
|
|
646
|
-
</tbody>
|
|
647
|
-
</Table>
|
|
648
|
-
<div className="clearfix addoption optionAdd marginBottom-10" onClick={() => this.onAddNewOption(fieldIndex)}>
|
|
649
|
-
<Components.P60Icon className="addoption_plus" icon="add-circle" />
|
|
650
|
-
<div className="fillSpace">
|
|
651
|
-
<p className="addoption_text">Add Another Option</p>
|
|
652
|
-
</div>
|
|
653
|
-
</div>
|
|
654
|
-
{this.renderOptionalCheckBox(field, fieldIndex)}
|
|
655
|
-
{this.renderTitleCheckBox(field, fieldIndex)}
|
|
656
|
-
</div>
|
|
657
|
-
);
|
|
658
|
-
}
|
|
659
|
-
|
|
660
|
-
renderFieldStaticTitle(field, fieldIndex) {
|
|
661
|
-
return (
|
|
662
|
-
<div className="fieldInner">
|
|
663
|
-
<Components.GenericInput
|
|
664
|
-
id={`fieldStatic${fieldIndex}`}
|
|
665
|
-
placeholder="Insert title here (required)"
|
|
666
|
-
value={field.label}
|
|
667
|
-
onChange={(e) => this.onFieldLabelChanged(fieldIndex, e)}
|
|
668
|
-
large
|
|
669
|
-
/>
|
|
670
|
-
</div>
|
|
671
|
-
);
|
|
672
|
-
}
|
|
673
|
-
|
|
674
|
-
renderFieldStaticText(field, fieldIndex) {
|
|
675
|
-
return (
|
|
676
|
-
<div className="fieldInner">
|
|
677
|
-
<Components.GenericInput
|
|
678
|
-
id={`fieldStatic${fieldIndex}`}
|
|
679
|
-
placeholder="Insert your paragraph text here (required)"
|
|
680
|
-
value={field.label}
|
|
681
|
-
onChange={(e) => this.onFieldLabelChanged(fieldIndex, e)}
|
|
682
|
-
type="textarea"
|
|
683
|
-
/>
|
|
684
|
-
</div>
|
|
685
|
-
);
|
|
686
|
-
}
|
|
687
|
-
|
|
688
|
-
renderField(field, fieldIndex) {
|
|
689
|
-
const { customFields } = this.state;
|
|
690
|
-
|
|
691
|
-
const renderFieldContent = () => {
|
|
692
|
-
switch (field.type) {
|
|
693
|
-
case 'text':
|
|
694
|
-
case 'email':
|
|
695
|
-
case 'phone':
|
|
696
|
-
return this.renderFieldText(field, fieldIndex);
|
|
697
|
-
case 'date':
|
|
698
|
-
return this.renderFieldDate(field, fieldIndex);
|
|
699
|
-
case 'time':
|
|
700
|
-
return this.renderFieldTime(field, fieldIndex);
|
|
701
|
-
case 'image':
|
|
702
|
-
return this.renderFieldImage(field, fieldIndex);
|
|
703
|
-
case 'document':
|
|
704
|
-
return this.renderFieldDocument(field, fieldIndex);
|
|
705
|
-
case 'yn':
|
|
706
|
-
return this.renderFieldYesNo(field, fieldIndex);
|
|
707
|
-
case 'multichoice':
|
|
708
|
-
return this.renderFieldMultiple(field, fieldIndex);
|
|
709
|
-
case 'checkbox':
|
|
710
|
-
return this.renderFieldCheckbox(field, fieldIndex);
|
|
711
|
-
case 'staticTitle':
|
|
712
|
-
return this.renderFieldStaticTitle(field, fieldIndex);
|
|
713
|
-
case 'staticText':
|
|
714
|
-
return this.renderFieldStaticText(field, fieldIndex);
|
|
715
|
-
default:
|
|
716
|
-
return null;
|
|
717
|
-
}
|
|
718
|
-
};
|
|
719
|
-
|
|
720
|
-
return (
|
|
721
|
-
<div className="fieldContainer" key={fieldIndex}>
|
|
722
|
-
<div className="fieldNumberContainer">
|
|
723
|
-
<p className="fieldNumber">{fieldIndex + 1}</p>
|
|
724
|
-
</div>
|
|
725
|
-
<div className="field">
|
|
726
|
-
<div className="fieldHeader">
|
|
727
|
-
<div className="group">
|
|
728
|
-
<div className="line" />
|
|
729
|
-
<div className="fieldType">{this.getFieldTypeTitle(field.type)}</div>
|
|
730
|
-
</div>
|
|
731
|
-
<div className="group">
|
|
732
|
-
<Components.DropdownInput
|
|
733
|
-
id={`fieldType${fieldIndex}`}
|
|
734
|
-
placeholder="Type"
|
|
735
|
-
value="Change Field Type"
|
|
736
|
-
options={this.fieldTypes}
|
|
737
|
-
onSelect={(key) => this.onFieldTypeChanged(fieldIndex, key)}
|
|
738
|
-
/>
|
|
739
|
-
{customFields.length > 1 && (
|
|
740
|
-
<div className="delete" onClick={() => this.onRemoveField(fieldIndex)}>
|
|
741
|
-
Delete
|
|
742
|
-
</div>
|
|
743
|
-
)}
|
|
744
|
-
</div>
|
|
745
|
-
</div>
|
|
746
|
-
{renderFieldContent()}
|
|
747
|
-
</div>
|
|
748
|
-
{customFields.length > 1 && (
|
|
749
|
-
<div className="switchField">
|
|
750
|
-
{fieldIndex > 0 ? (
|
|
751
|
-
<div className="circle" onClick={() => this.onMoveFieldPrev(fieldIndex)}>
|
|
752
|
-
<FontAwesome name="angle-up" className="icon" />
|
|
753
|
-
</div>
|
|
754
|
-
) : null}
|
|
755
|
-
{fieldIndex < customFields.length - 1 ? (
|
|
756
|
-
<div className="circle" onClick={() => this.onMoveFieldNext(fieldIndex)}>
|
|
757
|
-
<FontAwesome name="angle-down" className="icon" />
|
|
758
|
-
</div>
|
|
759
|
-
) : null}
|
|
760
|
-
</div>
|
|
761
|
-
)}
|
|
762
|
-
</div>
|
|
763
|
-
);
|
|
764
|
-
}
|
|
765
|
-
|
|
766
|
-
renderCustomForm() {
|
|
767
|
-
const { success, hasCustomFields, customFields } = this.state;
|
|
768
|
-
if (success || !hasCustomFields) return null;
|
|
769
|
-
|
|
770
|
-
return (
|
|
771
|
-
<div className="padding-60 paddingTop-8 paddingLeft-20">
|
|
772
|
-
<Components.Text type="bodyLarge" className="marginBottom-24 paddingLeft-40" style={{ color: Colours.COLOUR_LIGHTGREY }}>
|
|
773
|
-
By default, the form submission title will be the name of the person submitting the form. You can choose to select a different
|
|
774
|
-
field to use as the title for the form submission.
|
|
775
|
-
</Components.Text>
|
|
776
|
-
<div className="fields">
|
|
777
|
-
{customFields.map((field, fieldIndex) => this.renderField(field, fieldIndex))}
|
|
778
|
-
<div className="clearfix addoption addField" onClick={() => this.onAddNewField()}>
|
|
779
|
-
<Components.P60Icon className="addoption_plus" icon="add-circle" />
|
|
780
|
-
<div className="fillSpace">
|
|
781
|
-
<p className="addoption_text">Add New Field</p>
|
|
782
|
-
</div>
|
|
783
|
-
</div>
|
|
784
|
-
</div>
|
|
785
|
-
</div>
|
|
786
|
-
);
|
|
787
|
-
}
|
|
788
|
-
|
|
789
|
-
renderWarnings() {
|
|
790
|
-
const { showWarnings, warnings } = this.state;
|
|
791
|
-
if (!showWarnings || !warnings || warnings.length === 0) return null;
|
|
792
|
-
|
|
793
|
-
return (
|
|
794
|
-
<div className="padding-60 paddingVertical-8 text-bodyLarge" style={{ color: Colours.COLOUR_RED }}>
|
|
795
|
-
To save the form
|
|
796
|
-
<ul style={{ padding: 0, paddingLeft: 16 }}>
|
|
797
|
-
{warnings.map((warn, index) => (
|
|
798
|
-
<li key={index}>{warn}</li>
|
|
799
|
-
))}
|
|
800
|
-
</ul>
|
|
801
|
-
</div>
|
|
802
|
-
);
|
|
803
|
-
}
|
|
804
|
-
|
|
805
|
-
renderSuccess() {
|
|
806
|
-
const { success, jobTypeId } = this.state;
|
|
807
|
-
if (!success) return null;
|
|
808
|
-
|
|
809
|
-
return (
|
|
810
|
-
<Components.SuccessPopup
|
|
811
|
-
text={`${`${values.textJobType}`} has been ${!jobTypeId ? 'added' : 'edited'}`}
|
|
812
|
-
buttons={[
|
|
813
|
-
{
|
|
814
|
-
type: 'outlined',
|
|
815
|
-
onClick: this.onBack,
|
|
816
|
-
text: 'Go to home',
|
|
817
|
-
},
|
|
818
|
-
]}
|
|
819
|
-
/>
|
|
820
|
-
);
|
|
821
|
-
}
|
|
822
|
-
|
|
823
|
-
renderSubmit() {
|
|
824
|
-
if (this.state.submitting) {
|
|
825
|
-
return <Components.Button buttonType="secondary">Saving...</Components.Button>;
|
|
826
|
-
}
|
|
827
|
-
return (
|
|
828
|
-
<div>
|
|
829
|
-
<Components.Button inline buttonType="tertiary" onClick={this.onBack} isActive style={{ marginRight: 8 }}>
|
|
830
|
-
Cancel
|
|
831
|
-
</Components.Button>
|
|
832
|
-
<Components.Button inline buttonType="primary" onClick={this.onSave} isActive>
|
|
833
|
-
Save
|
|
834
|
-
</Components.Button>
|
|
835
|
-
</div>
|
|
836
|
-
);
|
|
837
|
-
}
|
|
838
|
-
|
|
839
|
-
render() {
|
|
840
|
-
const { success } = this.state;
|
|
841
|
-
|
|
842
|
-
return (
|
|
843
|
-
<Components.OverlayPage>
|
|
844
|
-
<Components.OverlayPageContents noBottomButtons={success}>
|
|
845
|
-
<Components.OverlayPageSection className="pageSectionWrapper--newPopup pageSectionWrapper--newPopup950">
|
|
846
|
-
<div className="addForm">
|
|
847
|
-
{this.renderBaseForm()}
|
|
848
|
-
{this.renderWarnings()}
|
|
849
|
-
{this.renderCustomForm()}
|
|
850
|
-
</div>
|
|
851
|
-
{this.renderSuccess()}
|
|
852
|
-
</Components.OverlayPageSection>
|
|
853
|
-
</Components.OverlayPageContents>
|
|
854
|
-
<Components.OverlayPageBottomButtons>{this.renderSubmit()}</Components.OverlayPageBottomButtons>
|
|
855
|
-
</Components.OverlayPage>
|
|
856
|
-
);
|
|
857
|
-
}
|
|
858
|
-
}
|
|
859
|
-
|
|
860
|
-
const mapStateToProps = (state) => {
|
|
861
|
-
const { auth } = state;
|
|
862
|
-
return { auth, strings: (state.strings && state.strings.config) || {} };
|
|
863
|
-
};
|
|
864
|
-
|
|
865
|
-
export default connect(mapStateToProps, { jobTypesUpdate })(withRouter(AddJobType));
|