Files
piratepoet/assets/js/src/form/form.jsx

249 lines
6.4 KiB
JavaScript

define(
[
'react',
'mailpoet',
'classnames',
'react-router',
'form/fields/field.jsx',
'jquery',
],
(
React,
MailPoet,
classNames,
Router,
FormField,
jQuery
) => {
const Form = React.createClass({
contextTypes: {
router: React.PropTypes.object.isRequired,
},
getDefaultProps: function () {
return {
params: {},
};
},
getInitialState: function () {
return {
loading: false,
errors: [],
item: {},
};
},
getValues: function () {
return this.props.item ? this.props.item : this.state.item;
},
getErrors: function () {
return this.props.errors ? this.props.errors : this.state.errors;
},
componentDidMount: function () {
if (this.isMounted()) {
if (this.props.params.id !== undefined) {
this.loadItem(this.props.params.id);
} else {
this.setState({
item: jQuery('.mailpoet_form').serializeObject(),
});
}
}
},
componentWillReceiveProps: function (props) {
if (props.params.id === undefined) {
this.setState({
loading: false,
item: {},
});
if (props.item === undefined) {
this.refs.form.reset();
}
} else {
this.loadItem(props.params.id);
}
},
loadItem: function (id) {
this.setState({ loading: true });
MailPoet.Ajax.post({
api_version: window.mailpoet_api_version,
endpoint: this.props.endpoint,
action: 'get',
data: {
id: id,
},
}).done((response) => {
this.setState({
loading: false,
item: response.data,
});
}).fail(() => {
this.setState({
loading: false,
item: {},
}, function () {
this.context.router.push('/new');
});
});
},
handleSubmit: function (e) {
e.preventDefault();
// handle validation
if (this.props.isValid !== undefined) {
if (this.props.isValid() === false) {
return;
}
}
this.setState({ loading: true });
// only get values from displayed fields
const item = {};
this.props.fields.map((field) => {
if (field['fields'] !== undefined) {
field.fields.map((subfield) => {
item[subfield.name] = this.state.item[subfield.name];
});
} else {
item[field.name] = this.state.item[field.name];
}
});
// set id if specified
if (this.props.params.id !== undefined) {
item.id = this.props.params.id;
}
MailPoet.Ajax.post({
api_version: window.mailpoet_api_version,
endpoint: this.props.endpoint,
action: 'save',
data: item,
}).always(() => {
this.setState({ loading: false });
}).done(() => {
if (this.props.onSuccess !== undefined) {
this.props.onSuccess();
} else {
this.context.router.push('/');
}
if (this.props.params.id !== undefined) {
this.props.messages.onUpdate();
} else {
this.props.messages.onCreate();
}
}).fail((response) => {
if (response.errors.length > 0) {
this.setState({ errors: response.errors });
}
});
},
handleValueChange: function (e) {
if (this.props.onChange) {
return this.props.onChange(e);
} else {
const item = this.state.item;
const field = e.target.name;
item[field] = e.target.value;
this.setState({
item: item,
});
return true;
}
},
render: function () {
let errors;
if (this.getErrors() !== undefined) {
errors = this.getErrors().map((error, index) => {
return (
<p key={'error-' + index} className="mailpoet_error">
{ error.message }
</p>
);
});
}
const formClasses = classNames(
'mailpoet_form',
{ mailpoet_form_loading: this.state.loading || this.props.loading }
);
let beforeFormContent = false;
let afterFormContent = false;
if (this.props.beforeFormContent !== undefined) {
beforeFormContent = this.props.beforeFormContent(this.getValues());
}
if (this.props.afterFormContent !== undefined) {
afterFormContent = this.props.afterFormContent(this.getValues());
}
const fields = this.props.fields.map((field, i) => {
// Compose an onChange handler from the default and custom one
let onValueChange = this.handleValueChange;
if (field.onBeforeChange) {
onValueChange = (e) => {
field.onBeforeChange(e);
return this.handleValueChange(e);
};
}
return (
<FormField
field={field}
item={this.getValues()}
onValueChange={onValueChange}
key={'field-' + i} />
);
});
let actions = false;
if (this.props.children) {
actions = this.props.children;
} else {
actions = (
<input
className="button button-primary"
type="submit"
value={MailPoet.I18n.t('save')}
disabled={this.state.loading} />
);
}
return (
<div>
{ beforeFormContent }
<form
id={this.props.id}
ref="form"
className={formClasses}
onSubmit={
(this.props.onSubmit !== undefined)
? this.props.onSubmit
: this.handleSubmit
}
>
{ errors }
<table className="form-table">
<tbody>
{fields}
</tbody>
</table>
{ actions }
</form>
{ afterFormContent }
</div>
);
},
});
return Form;
}
);