500 lines
13 KiB
JavaScript
500 lines
13 KiB
JavaScript
import React from 'react';
|
|
import {
|
|
Alert, Col, DatePicker, TimePicker, Form, Input, Row,
|
|
} from 'antd';
|
|
import moment from 'moment';
|
|
import IceUpload from './IceUpload';
|
|
import IceDataGroup from './IceDataGroup';
|
|
import IceSelect from './IceSelect';
|
|
import IceLabel from './IceLabel';
|
|
import IceColorPick from './IceColorPick';
|
|
import IceSignature from './IceSignature';
|
|
|
|
|
|
const ValidationRules = {
|
|
|
|
float(str) {
|
|
const floatstr = /^[-+]?[0-9]+(\.[0-9]+)?$/;
|
|
if (str != null && str.match(floatstr)) {
|
|
return true;
|
|
}
|
|
return false;
|
|
},
|
|
|
|
number(str) {
|
|
const numstr = /^[0-9]+$/;
|
|
if (str != null && str.match(numstr)) {
|
|
return true;
|
|
}
|
|
return false;
|
|
},
|
|
|
|
numberOrEmpty(str) {
|
|
if (str === '') {
|
|
return true;
|
|
}
|
|
const numstr = /^[0-9]+$/;
|
|
if (str != null && str.match(numstr)) {
|
|
return true;
|
|
}
|
|
return false;
|
|
},
|
|
|
|
email(str) {
|
|
const emailPattern = /^\s*[\w\-+_]+(\.[\w\-+_]+)*@[\w\-+_]+\.[\w\-+_]+(\.[\w\-+_]+)*\s*$/;
|
|
return str != null && emailPattern.test(str);
|
|
},
|
|
|
|
emailOrEmpty(str) {
|
|
if (str === '') {
|
|
return true;
|
|
}
|
|
const emailPattern = /^\s*[\w\-+_]+(\.[\w\-+_]+)*@[\w\-+_]+\.[\w\-+_]+(\.[\w\-+_]+)*\s*$/;
|
|
return str != null && emailPattern.test(str);
|
|
},
|
|
|
|
username(str) {
|
|
const username = /^[a-zA-Z0-9.-]+$/;
|
|
return str != null && username.test(str);
|
|
},
|
|
};
|
|
|
|
|
|
class IceForm extends React.Component {
|
|
constructor(props) {
|
|
super(props);
|
|
this.validationRules = {};
|
|
this.state = {
|
|
validations: {},
|
|
errorMsg: false,
|
|
};
|
|
this.formReference = React.createRef();
|
|
}
|
|
|
|
showError(errorMsg) {
|
|
this.setState({ errorMsg });
|
|
}
|
|
|
|
hideError() {
|
|
this.setState({ errorMsg: false });
|
|
}
|
|
|
|
isReady() {
|
|
return this.formReference.current != null;
|
|
}
|
|
|
|
validateFields() {
|
|
return this.formReference.current.validateFields();
|
|
}
|
|
|
|
render() {
|
|
const { fields, twoColumnLayout, adapter } = this.props;
|
|
let formInputs = [];
|
|
const formInputs1 = [];
|
|
const formInputs2 = [];
|
|
const columns = !twoColumnLayout ? 1 : 2;
|
|
for (let i = 0; i < fields.length; i++) {
|
|
formInputs.push(
|
|
adapter.beforeRenderFieldHook(
|
|
fields[i][0],
|
|
this.createFromField(fields[i], this.props.viewOnly),
|
|
fields[i][1]
|
|
)
|
|
);
|
|
}
|
|
formInputs = formInputs.filter(input => !!input);
|
|
|
|
for (let i = 0; i < formInputs.length; i++) {
|
|
|
|
if (formInputs[i] != null) {
|
|
if (columns === 1) {
|
|
formInputs1.push(formInputs[i]);
|
|
} else if (i % 2 === 0) {
|
|
formInputs1.push(formInputs[i]);
|
|
} else {
|
|
formInputs2.push(formInputs[i]);
|
|
}
|
|
}
|
|
}
|
|
|
|
const onFormLayoutChange = () => { };
|
|
|
|
return (
|
|
<Form
|
|
ref={this.formReference}
|
|
labelCol={{ span: 6 }}
|
|
wrapperCol={{ span: 16 }}
|
|
layout={this.props.layout || 'horizontal'}
|
|
initialValues={{ size: 'middle' }}
|
|
onValuesChange={onFormLayoutChange}
|
|
size="middle"
|
|
>
|
|
{this.state.errorMsg
|
|
&& (
|
|
<>
|
|
<Alert message={this.state.errorMsg} type="error" showIcon />
|
|
<br />
|
|
</>
|
|
)}
|
|
{columns === 1 && formInputs1}
|
|
{columns === 2 && (
|
|
<Row gutter={16}>
|
|
<Col className="gutter-row" span={12}>
|
|
{formInputs1}
|
|
</Col>
|
|
<Col className="gutter-row" span={12}>
|
|
{formInputs2}
|
|
</Col>
|
|
</Row>
|
|
)}
|
|
</Form>
|
|
);
|
|
}
|
|
|
|
isValid() {
|
|
return Object.keys(this.validationRules).reduce((acc, fieldName) => acc && (this.state[fieldName] === 'success' || this.state[fieldName] == null), true);
|
|
}
|
|
|
|
validateOnChange(event) {
|
|
const validationRule = this.validationRules[event.target.id];
|
|
const { validations } = this.state;
|
|
|
|
if (validationRule) {
|
|
if (validationRule.rule(event.target.value)) {
|
|
this.state[event.target.id] = 'success';
|
|
this.state[`${event.target.id}_message`] = null;
|
|
} else {
|
|
this.state[event.target.id] = 'error';
|
|
this.state[`${event.target.id}_message`] = validationRule.message;
|
|
}
|
|
}
|
|
this.setState({ validations });
|
|
}
|
|
|
|
createFromField(field, viewOnly = false) {
|
|
let userId = 0;
|
|
const rules = [];
|
|
const requiredRule = { required: true };
|
|
const [name, data] = field;
|
|
const { adapter, layout } = this.props;
|
|
let validationRule = null;
|
|
data.label = adapter.gt(data.label);
|
|
|
|
const labelSpan = layout === 'vertical' ? { span: 24 } : { span: 6 };
|
|
|
|
const tempSelectBoxes = ['select', 'select2', 'select2multi'];
|
|
if (tempSelectBoxes.indexOf(data.type) >= 0 && data['allow-null'] === true) {
|
|
requiredRule.required = false;
|
|
} else if (data.validation === 'none'
|
|
|| data.validation === 'emailOrEmpty'
|
|
|| data.validation === 'numberOrEmpty'
|
|
) {
|
|
requiredRule.required = false;
|
|
} else {
|
|
requiredRule.required = true;
|
|
requiredRule.message = this.generateFieldMessage(data.label);
|
|
}
|
|
|
|
rules.push(requiredRule);
|
|
|
|
if (data.type === 'hidden') {
|
|
requiredRule.required = false;
|
|
return (
|
|
<Form.Item
|
|
labelCol={labelSpan}
|
|
style={{ display: 'none' }}
|
|
label={data.label}
|
|
key={name}
|
|
name={name}
|
|
rules={rules}
|
|
>
|
|
<Input />
|
|
</Form.Item>
|
|
);
|
|
} if (data.type === 'text') {
|
|
if (data.validation) {
|
|
data.validation = data.validation.replace('OrEmpty', '');
|
|
validationRule = this.getValidationRule(data);
|
|
if (validationRule) {
|
|
this.validationRules[name] = {
|
|
rule: validationRule,
|
|
message: `Invalid value for ${data.label}`,
|
|
};
|
|
}
|
|
}
|
|
if (validationRule != null) {
|
|
return (
|
|
<Form.Item
|
|
labelCol={labelSpan}
|
|
label={data.label}
|
|
key={name}
|
|
name={name}
|
|
rules={rules}
|
|
validateStatus={this.state[name]}
|
|
help={this.state[`${name}_message`]}
|
|
>
|
|
{viewOnly
|
|
? <IceLabel />
|
|
: <Input onChange={this.validateOnChange.bind(this)} />}
|
|
</Form.Item>
|
|
);
|
|
}
|
|
return (
|
|
<Form.Item
|
|
labelCol={labelSpan}
|
|
label={data.label}
|
|
key={name}
|
|
name={name}
|
|
rules={rules}
|
|
>
|
|
{viewOnly
|
|
? <IceLabel />
|
|
: <Input />}
|
|
</Form.Item>
|
|
);
|
|
} if (data.type === 'textarea') {
|
|
if (!data.rows) {
|
|
data.rows = 4;
|
|
}
|
|
return (
|
|
<Form.Item
|
|
labelCol={labelSpan}
|
|
label={data.label}
|
|
key={name}
|
|
name={name}
|
|
rules={rules}
|
|
>
|
|
{viewOnly
|
|
? <IceLabel />
|
|
: <Input.TextArea rows={data.rows} />}
|
|
</Form.Item>
|
|
);
|
|
} if (data.type === 'date') {
|
|
return (
|
|
<Form.Item
|
|
labelCol={labelSpan}
|
|
label={data.label}
|
|
key={name}
|
|
name={name}
|
|
rules={rules}
|
|
>
|
|
<DatePicker disabled={viewOnly} />
|
|
</Form.Item>
|
|
);
|
|
} if (data.type === 'datetime') {
|
|
return (
|
|
<Form.Item
|
|
labelCol={labelSpan}
|
|
label={data.label}
|
|
key={name}
|
|
name={name}
|
|
rules={rules}
|
|
>
|
|
<DatePicker format="YYYY-MM-DD HH:mm:ss" disabled={viewOnly} />
|
|
</Form.Item>
|
|
);
|
|
} if (data.type === 'time') {
|
|
return (
|
|
<Form.Item
|
|
labelCol={labelSpan}
|
|
label={data.label}
|
|
key={name}
|
|
name={name}
|
|
rules={rules}
|
|
>
|
|
<TimePicker
|
|
format="HH:mm"
|
|
disabled={viewOnly}
|
|
/>
|
|
</Form.Item>
|
|
);
|
|
} if (data.type === 'fileupload') {
|
|
const currentEmployee = adapter.getCurrentProfile();
|
|
if (currentEmployee != null) {
|
|
userId = currentEmployee.id;
|
|
} else {
|
|
userId = adapter.getUser().id * -1;
|
|
}
|
|
|
|
if (data.filetypes == null) {
|
|
data.filetypes = '.doc,.docx,.xml,'
|
|
+ 'application/msword,application/vnd.openxmlformats-officedocument.wordprocessingml.document,'
|
|
+ 'image/*,'
|
|
+ '.pdf';
|
|
}
|
|
|
|
return (
|
|
<Form.Item
|
|
labelCol={labelSpan}
|
|
name={name}
|
|
key={name}
|
|
label={data.label}
|
|
>
|
|
<IceUpload
|
|
user={userId}
|
|
fileGroup={adapter.tab}
|
|
fileName={name}
|
|
adapter={adapter}
|
|
accept={data.filetypes}
|
|
readOnly={viewOnly}
|
|
/>
|
|
</Form.Item>
|
|
);
|
|
} if (data.type === 'datagroup') {
|
|
return (
|
|
<Form.Item
|
|
labelCol={labelSpan}
|
|
name={name}
|
|
key={name}
|
|
label={data.label}
|
|
>
|
|
<IceDataGroup
|
|
adapter={adapter}
|
|
field={field}
|
|
title={data.label}
|
|
readOnly={viewOnly}
|
|
/>
|
|
</Form.Item>
|
|
);
|
|
} if (data.type === 'select2' || data.type === 'select' || data.type === 'select2multi') {
|
|
return (
|
|
<Form.Item
|
|
labelCol={labelSpan}
|
|
label={data.label}
|
|
key={name}
|
|
name={name}
|
|
rules={rules}
|
|
>
|
|
<IceSelect
|
|
adapter={adapter}
|
|
field={field}
|
|
readOnly={viewOnly}
|
|
/>
|
|
</Form.Item>
|
|
);
|
|
} if (data.type === 'colorpick') {
|
|
return (
|
|
<Form.Item
|
|
labelCol={labelSpan}
|
|
name={name}
|
|
key={name}
|
|
label={data.label}
|
|
>
|
|
<IceColorPick
|
|
adapter={adapter}
|
|
field={field}
|
|
title={data.label}
|
|
readOnly={viewOnly}
|
|
/>
|
|
</Form.Item>
|
|
);
|
|
} if (data.type === 'signature') {
|
|
return (
|
|
<Form.Item
|
|
labelCol={labelSpan}
|
|
label={data.label}
|
|
key={name}
|
|
name={name}
|
|
rules={rules}
|
|
>
|
|
<IceSignature readOnly={viewOnly} />
|
|
</Form.Item>
|
|
);
|
|
}
|
|
return null;
|
|
}
|
|
|
|
generateFieldMessage(label) {
|
|
return `${label}: ${this.props.adapter.gt('is required')}`;
|
|
}
|
|
|
|
getValidationRule(data) {
|
|
if (ValidationRules[data.validation] == null) {
|
|
return null;
|
|
}
|
|
|
|
return ValidationRules[data.validation];
|
|
}
|
|
|
|
dataToFormFields(data, fields) {
|
|
for (let i = 0; i < fields.length; i++) {
|
|
const [key, formInputData] = fields[i];
|
|
if (formInputData.type === 'date') {
|
|
data[key] = data[key] ? moment(data[key], 'YYYY-MM-DD') : null;
|
|
} else if (formInputData.type === 'datetime') {
|
|
data[key] = data[key] ? moment(data[key], 'YYYY-MM-DD HH:mm:ss') : null;
|
|
} else if (formInputData.type === 'time') {
|
|
data[key] = data[key] ? moment(data[key], 'HH:mm') : null;
|
|
}
|
|
}
|
|
|
|
return data;
|
|
}
|
|
|
|
formFieldsToData(params, fields) {
|
|
for (let i = 0; i < fields.length; i++) {
|
|
const [key, formInputData] = fields[i];
|
|
if (formInputData.type === 'date') {
|
|
params[key] = params[key] ? params[key].format('YYYY-MM-DD') : 'NULL';
|
|
} else if (formInputData.type === 'datetime') {
|
|
params[key] = params[key] ? params[key].format('YYYY-MM-DD HH:mm:ss') : 'NULL';
|
|
} else if (formInputData.type === 'time') {
|
|
params[key] = params[key] ? params[key].format('HH:mm') : 'NULL';
|
|
} else if ((formInputData.type === 'select' || formInputData.type === 'select2') && params[key] == null) {
|
|
params[key] = 'NULL';
|
|
}
|
|
}
|
|
|
|
return params;
|
|
}
|
|
|
|
updateFields(data) {
|
|
const { fields } = this.props;
|
|
data = this.dataToFormFields(data, fields);
|
|
this.formReference.current.resetFields();
|
|
if (data == null) {
|
|
return;
|
|
}
|
|
try {
|
|
this.formReference.current.setFieldsValue(data);
|
|
} catch (e) {
|
|
console.log(e);
|
|
}
|
|
}
|
|
|
|
resetFields() {
|
|
this.formReference.current.resetFields();
|
|
}
|
|
|
|
setFieldsValue(data) {
|
|
this.formReference.current.setFieldsValue(data);
|
|
}
|
|
|
|
save(params, success) {
|
|
const { adapter, fields } = this.props;
|
|
let values = params;
|
|
values = adapter.forceInjectValuesBeforeSave(values);
|
|
const msg = adapter.doCustomValidation(values);
|
|
if (msg !== null) {
|
|
this.showError(msg);
|
|
return;
|
|
}
|
|
if (adapter.csrfRequired) {
|
|
values.csrf = $(`#${adapter.getTableName()}Form`).data('csrf');
|
|
}
|
|
|
|
const id = (adapter.currentElement != null) ? adapter.currentElement.id : null;
|
|
if (id != null && id !== '') {
|
|
values.id = id;
|
|
}
|
|
values = this.formFieldsToData(values, fields);
|
|
adapter.add(values, [], () => adapter.get([]), () => {
|
|
this.formReference.current.resetFields();
|
|
this.showError(false);
|
|
success();
|
|
});
|
|
}
|
|
}
|
|
|
|
export default IceForm;
|