mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 14:05:37 +02:00
AddToCampaign save message, Submitting indicator on FormAction button
This commit is contained in:
parent
d7663e850e
commit
b9624994ac
2
admin/client/dist/js/AddToCampaignForm.js
vendored
2
admin/client/dist/js/AddToCampaignForm.js
vendored
@ -22,7 +22,7 @@
|
||||
}
|
||||
|
||||
_jQuery2.default.entwine('ss', function ($) {
|
||||
$('.add-to-campaign-action, #add-to-campaign__action').entwine({
|
||||
$('#add-to-campaign__dialog .add-to-campaign-action,' + '.cms-content-actions .add-to-campaign-action,' + '#add-to-campaign__action').entwine({
|
||||
onclick: function onclick() {
|
||||
var dialog = $('#add-to-campaign__dialog');
|
||||
|
||||
|
@ -2,24 +2,47 @@ import React from 'react';
|
||||
import { Modal } from 'react-bootstrap-4';
|
||||
import SilverStripeComponent from 'lib/SilverStripeComponent';
|
||||
import FormBuilder from 'components/FormBuilder/FormBuilder';
|
||||
import Config from 'lib/Config';
|
||||
|
||||
class AddToCampaignModal extends SilverStripeComponent {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.handleSubmit = this.handleSubmit.bind(this);
|
||||
|
||||
this.state = {
|
||||
response: null,
|
||||
error: false,
|
||||
};
|
||||
}
|
||||
|
||||
handleSubmit(event, fieldValues, submitFn) {
|
||||
|
||||
let promise = null;
|
||||
if (typeof this.props.handleSubmit === 'function') {
|
||||
this.props.handleSubmit(event, fieldValues, submitFn);
|
||||
return;
|
||||
promise = this.props.handleSubmit(event, fieldValues, submitFn);
|
||||
} else {
|
||||
event.preventDefault();
|
||||
promise = submitFn();
|
||||
}
|
||||
|
||||
event.preventDefault();
|
||||
submitFn();
|
||||
if (promise) {
|
||||
promise
|
||||
.then((response) => {
|
||||
// show response
|
||||
if (typeof response === 'string' || response.response.ok) {
|
||||
this.setState({
|
||||
response,
|
||||
error: false,
|
||||
});
|
||||
} else {
|
||||
this.setState({
|
||||
response: `${response.name}: ${response.message}`,
|
||||
error: true,
|
||||
});
|
||||
}
|
||||
return response;
|
||||
});
|
||||
}
|
||||
return promise;
|
||||
}
|
||||
|
||||
getBody() {
|
||||
@ -28,25 +51,60 @@ class AddToCampaignModal extends SilverStripeComponent {
|
||||
return <FormBuilder schemaUrl={schemaUrl} handleSubmit={this.handleSubmit} />;
|
||||
}
|
||||
|
||||
getResponse() {
|
||||
if (!this.state.response) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let className = 'add-to-campaign__response';
|
||||
|
||||
if (this.state.error) {
|
||||
className += ' add-to-campaign__response--error';
|
||||
} else {
|
||||
className += ' add-to-campaign__response--good';
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={className}>
|
||||
<span>{this.state.response}</span>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
clearResponse() {
|
||||
// TODO to be used with "Try again" and other options later
|
||||
this.setState({
|
||||
response: null,
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
const body = this.getBody();
|
||||
const response = this.getResponse();
|
||||
|
||||
return <Modal show={this.props.show} onHide={this.props.handleHide} container={document.getElementsByClassName('cms-container')[0]}>
|
||||
<Modal.Header closeButton>
|
||||
<Modal.Title>{this.props.title + ' - Test'}</Modal.Title>
|
||||
</Modal.Header>
|
||||
<Modal.Body>
|
||||
{body}
|
||||
</Modal.Body>
|
||||
</Modal>;
|
||||
return (
|
||||
<Modal
|
||||
show={this.props.show}
|
||||
onHide={this.props.handleHide}
|
||||
container={document.getElementsByClassName('cms-container')[0]}
|
||||
>
|
||||
<Modal.Header closeButton>
|
||||
<Modal.Title>{this.props.title}</Modal.Title>
|
||||
</Modal.Header>
|
||||
<Modal.Body>
|
||||
{body}
|
||||
{response}
|
||||
</Modal.Body>
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
AddToCampaignModal.propTypes = {
|
||||
show: React.PropTypes.bool.isRequired,
|
||||
title: React.PropTypes.string,
|
||||
show: React.PropTypes.bool.isRequired,
|
||||
title: React.PropTypes.string,
|
||||
handleHide: React.PropTypes.func,
|
||||
schemaUrl: React.PropTypes.string,
|
||||
schemaUrl: React.PropTypes.string,
|
||||
handleSubmit: React.PropTypes.func,
|
||||
};
|
||||
|
||||
|
@ -0,0 +1,63 @@
|
||||
/* global jest, describe, beforeEach, it, expect */
|
||||
|
||||
jest.unmock('react');
|
||||
jest.unmock('react-addons-test-utils');
|
||||
jest.unmock('../AddToCampaignModal');
|
||||
|
||||
import React from 'react';
|
||||
import ReactTestUtils from 'react-addons-test-utils';
|
||||
import AddToCampaignModal from '../AddToCampaignModal';
|
||||
|
||||
describe('AddToCampaignModal', () => {
|
||||
let props;
|
||||
|
||||
beforeEach(() => {
|
||||
props = {
|
||||
title: '',
|
||||
show: false,
|
||||
handleHide: jest.genMockFunction(),
|
||||
};
|
||||
});
|
||||
|
||||
describe('getResponse()', () => {
|
||||
let addToCampaignModal;
|
||||
let response;
|
||||
let message;
|
||||
|
||||
beforeEach(() => {
|
||||
addToCampaignModal = ReactTestUtils.renderIntoDocument(
|
||||
<AddToCampaignModal {...props} />
|
||||
);
|
||||
response = addToCampaignModal.getResponse();
|
||||
message = 'My message';
|
||||
});
|
||||
|
||||
it('should show no response initially', () => {
|
||||
expect(response).toBeNull();
|
||||
});
|
||||
|
||||
it('should show error message', () => {
|
||||
message = 'This is an error';
|
||||
|
||||
addToCampaignModal.state = {
|
||||
response: message,
|
||||
error: true,
|
||||
};
|
||||
const responseDom = ReactTestUtils.renderIntoDocument(addToCampaignModal.getResponse());
|
||||
expect(responseDom.classList.contains('add-to-campaign__response--error')).toBe(true);
|
||||
expect(responseDom.textContent).toBe(message);
|
||||
});
|
||||
|
||||
it('should show success message', () => {
|
||||
message = 'This is a success';
|
||||
|
||||
addToCampaignModal.state = {
|
||||
response: message,
|
||||
error: false,
|
||||
};
|
||||
const responseDom = ReactTestUtils.renderIntoDocument(addToCampaignModal.getResponse());
|
||||
expect(responseDom.classList.contains('add-to-campaign__response--good')).toBe(true);
|
||||
expect(responseDom.textContent).toBe(message);
|
||||
});
|
||||
});
|
||||
});
|
@ -44,9 +44,9 @@ class FormAction extends SilverStripeComponent {
|
||||
const buttonClasses = ['btn'];
|
||||
|
||||
// Add 'type' class
|
||||
const bootstrapStyle = this.getBootstrapButtonStyle();
|
||||
if (bootstrapStyle) {
|
||||
buttonClasses.push(`btn-${bootstrapStyle}`);
|
||||
const style = this.getButtonStyle();
|
||||
if (style) {
|
||||
buttonClasses.push(`btn-${style}`);
|
||||
}
|
||||
|
||||
// If there is no text
|
||||
@ -82,13 +82,22 @@ class FormAction extends SilverStripeComponent {
|
||||
*
|
||||
* @return {String}
|
||||
*/
|
||||
getBootstrapButtonStyle() {
|
||||
getButtonStyle() {
|
||||
// Add 'type' class
|
||||
if (typeof this.props.bootstrapButtonStyle !== 'undefined') {
|
||||
return this.props.bootstrapButtonStyle;
|
||||
if (typeof this.props.data.buttonStyle !== 'undefined') {
|
||||
return this.props.data.buttonStyle;
|
||||
}
|
||||
|
||||
if (this.props.name === 'action_save') {
|
||||
const extraClasses = this.props.extraClass.split(' ');
|
||||
|
||||
// defined their own `btn-${something}` class
|
||||
if (extraClasses.find((className) => className.indexOf('btn-') > -1)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (this.props.name === 'action_save' ||
|
||||
extraClasses.find((className) => className === 'ss-ui-action-constructive')
|
||||
) {
|
||||
return 'primary';
|
||||
}
|
||||
|
||||
@ -134,9 +143,7 @@ class FormAction extends SilverStripeComponent {
|
||||
if (typeof this.props.handleClick === 'function') {
|
||||
this.props.handleClick(event, this.props.name || this.props.id);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
FormAction.propTypes = {
|
||||
@ -148,7 +155,12 @@ FormAction.propTypes = {
|
||||
loading: React.PropTypes.bool,
|
||||
icon: React.PropTypes.string,
|
||||
disabled: React.PropTypes.bool,
|
||||
bootstrapButtonStyle: React.PropTypes.string,
|
||||
data: React.PropTypes.oneOfType([
|
||||
React.PropTypes.array,
|
||||
React.PropTypes.shape({
|
||||
buttonStyle: React.PropTypes.string,
|
||||
}),
|
||||
]),
|
||||
extraClass: React.PropTypes.string,
|
||||
attributes: React.PropTypes.object,
|
||||
};
|
||||
@ -156,6 +168,7 @@ FormAction.propTypes = {
|
||||
FormAction.defaultProps = {
|
||||
title: '',
|
||||
icon: '',
|
||||
extraClass: '',
|
||||
attributes: {},
|
||||
data: {},
|
||||
disabled: false,
|
||||
|
@ -172,9 +172,10 @@ export class FormBuilderComponent extends SilverStripeComponent {
|
||||
}
|
||||
}
|
||||
|
||||
handleAction(event, name) {
|
||||
handleAction(event, submitAction) {
|
||||
this.props.formActions.setSubmitAction(this.getFormId(), submitAction);
|
||||
if (typeof this.props.handleAction === 'function') {
|
||||
this.props.handleAction(event, name);
|
||||
this.props.handleAction(event, submitAction);
|
||||
}
|
||||
}
|
||||
|
||||
@ -227,12 +228,11 @@ export class FormBuilderComponent extends SilverStripeComponent {
|
||||
);
|
||||
|
||||
if (typeof this.props.handleSubmit !== 'undefined') {
|
||||
this.props.handleSubmit(event, fieldValues, submitFn);
|
||||
return;
|
||||
return this.props.handleSubmit(event, fieldValues, submitFn);
|
||||
}
|
||||
|
||||
event.preventDefault();
|
||||
submitFn();
|
||||
return submitFn();
|
||||
}
|
||||
|
||||
buildComponent(field, extraProps = {}) {
|
||||
@ -288,9 +288,16 @@ export class FormBuilderComponent extends SilverStripeComponent {
|
||||
* @return {Array}
|
||||
*/
|
||||
mapActionsToComponents(actions) {
|
||||
const form = this.props.form[this.getFormId()];
|
||||
|
||||
return actions.map((action) => {
|
||||
const loading = (form && form.submitting && form.submitAction === action.name);
|
||||
// Events
|
||||
const extraProps = { handleClick: this.handleAction };
|
||||
const extraProps = {
|
||||
handleClick: this.handleAction,
|
||||
loading,
|
||||
disabled: loading || action.disabled,
|
||||
};
|
||||
|
||||
// Build child nodes
|
||||
if (action.children) {
|
||||
|
@ -4,10 +4,6 @@ Generates a `<select><option></option></select>`
|
||||
|
||||
## Props
|
||||
|
||||
### leftTitle
|
||||
|
||||
The label text to display with the field.
|
||||
|
||||
### extraClass
|
||||
|
||||
Addition CSS classes to apply to the `<select>` element.
|
||||
@ -22,20 +18,32 @@ Handler function called when the field's value changes.
|
||||
|
||||
### value
|
||||
|
||||
The field's value.
|
||||
The field's selected value.
|
||||
|
||||
### source (required)
|
||||
|
||||
The list of possible values that could be selected
|
||||
|
||||
### disabled
|
||||
#### value
|
||||
|
||||
A list of values within `source` that can be seen but not selected
|
||||
The value for this option.
|
||||
|
||||
### hasEmptyDefault
|
||||
#### title
|
||||
|
||||
The title or label displayed for users.
|
||||
|
||||
#### disabled
|
||||
|
||||
This option is shown but disabled from being selected.
|
||||
|
||||
### data
|
||||
|
||||
Additional field specific data
|
||||
|
||||
#### hasEmptyDefault
|
||||
|
||||
If true, create an empty value option first
|
||||
|
||||
### emptyString
|
||||
#### emptyString
|
||||
|
||||
When `hasEmptyDefault` is true, this sets the label for the option
|
||||
|
@ -1,5 +1,7 @@
|
||||
import React from 'react';
|
||||
import SilverStripeComponent from 'lib/SilverStripeComponent';
|
||||
//import fieldHolder from 'components/FieldHolder/FieldHolder';
|
||||
import i18n from 'i18n';
|
||||
|
||||
class SingleSelectField extends SilverStripeComponent {
|
||||
|
||||
@ -10,10 +12,6 @@ class SingleSelectField extends SilverStripeComponent {
|
||||
}
|
||||
|
||||
render() {
|
||||
const labelText = this.props.leftTitle !== null
|
||||
? this.props.leftTitle
|
||||
: this.props.title;
|
||||
|
||||
let field = null;
|
||||
if (this.props.readOnly) {
|
||||
field = this.getReadonlyField;
|
||||
@ -21,22 +19,7 @@ class SingleSelectField extends SilverStripeComponent {
|
||||
field = this.getSelectField();
|
||||
}
|
||||
|
||||
// The extraClass property is defined on both the holder and element
|
||||
// for legacy reasons (same behaviour as PHP rendering)
|
||||
const classNames = ['form-group', this.props.extraClass].join(' ');
|
||||
|
||||
return (
|
||||
<div className={classNames}>
|
||||
{labelText &&
|
||||
<label className="form__field-label" htmlFor={`gallery_${this.props.name}`}>
|
||||
{labelText}
|
||||
</label>
|
||||
}
|
||||
<div className="form__field-holder">
|
||||
{field}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
return field;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -45,9 +28,9 @@ class SingleSelectField extends SilverStripeComponent {
|
||||
* @returns ReactComponent
|
||||
*/
|
||||
getReadonlyField() {
|
||||
let label = this.props.source[this.props.value];
|
||||
let label = this.props.source.find((item) => item.value === this.props.value);
|
||||
|
||||
label = label !== null
|
||||
label = label !== undefined
|
||||
? label
|
||||
: this.props.value;
|
||||
|
||||
@ -65,16 +48,23 @@ class SingleSelectField extends SilverStripeComponent {
|
||||
if (this.props.hasEmptyDefault) {
|
||||
options.unshift({
|
||||
value: '',
|
||||
title: this.props.emptyString
|
||||
title: this.props.emptyString,
|
||||
disabled: false,
|
||||
});
|
||||
}
|
||||
return <select {...this.getInputProps()}>
|
||||
{ options.map((item) => {
|
||||
const key = `${this.props.name}-${item.value || 'null'}`;
|
||||
return (
|
||||
<select {...this.getInputProps()}>
|
||||
{ options.map((item) => {
|
||||
const key = `${this.props.name}-${item.value || 'null'}`;
|
||||
|
||||
return <option key={key} value={item.value} disabled={item.disabled}>{item.title}</option>;
|
||||
}) }
|
||||
</select>;
|
||||
return (
|
||||
<option key={key} value={item.value} disabled={item.disabled}>
|
||||
{item.title}
|
||||
</option>
|
||||
);
|
||||
}) }
|
||||
</select>
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -87,10 +77,10 @@ class SingleSelectField extends SilverStripeComponent {
|
||||
// The extraClass property is defined on both the holder and element
|
||||
// for legacy reasons (same behaviour as PHP rendering)
|
||||
className: ['form-control', this.props.extraClass].join(' '),
|
||||
id: this.props.id,
|
||||
name: this.props.name,
|
||||
onChange: this.handleChange,
|
||||
value: this.props.value,
|
||||
id: this.props.id,
|
||||
name: this.props.name,
|
||||
onChange: this.handleChange,
|
||||
value: this.props.value,
|
||||
};
|
||||
}
|
||||
|
||||
@ -104,25 +94,23 @@ class SingleSelectField extends SilverStripeComponent {
|
||||
return;
|
||||
}
|
||||
|
||||
this.props.onChange(event, {id: this.props.id, value: event.target.value});
|
||||
this.props.onChange(event, { id: this.props.id, value: event.target.value });
|
||||
}
|
||||
}
|
||||
|
||||
SingleSelectField.propTypes = {
|
||||
leftTitle: React.PropTypes.string,
|
||||
extraClass: React.PropTypes.string,
|
||||
id: React.PropTypes.string,
|
||||
name: React.PropTypes.string.isRequired,
|
||||
onChange: React.PropTypes.func,
|
||||
value: React.PropTypes.oneOfType([React.PropTypes.string, React.PropTypes.number]),
|
||||
readOnly: React.PropTypes.bool,
|
||||
source: React.PropTypes.arrayOf(React.PropTypes.shape({
|
||||
id: React.PropTypes.string,
|
||||
name: React.PropTypes.string.isRequired,
|
||||
onChange: React.PropTypes.func,
|
||||
value: React.PropTypes.oneOfType([React.PropTypes.string, React.PropTypes.number]),
|
||||
readOnly: React.PropTypes.bool,
|
||||
source: React.PropTypes.arrayOf(React.PropTypes.shape({
|
||||
value: React.PropTypes.oneOfType([React.PropTypes.string, React.PropTypes.number]),
|
||||
title: React.PropTypes.string,
|
||||
disabled: React.PropTypes.bool,
|
||||
})),
|
||||
hasEmptyDefault: React.PropTypes.bool,
|
||||
emptyString: React.PropTypes.string,
|
||||
emptyString: React.PropTypes.string,
|
||||
};
|
||||
|
||||
SingleSelectField.defaultProps = {
|
||||
|
@ -28,7 +28,7 @@ class TextField extends SilverStripeComponent {
|
||||
* @returns Object properties
|
||||
*/
|
||||
getInputProps() {
|
||||
// @todo Merge with 'attributes' from formfield schema
|
||||
// TODO Merge with 'attributes' from formfield schema
|
||||
return {
|
||||
// The extraClass property is defined on both the holder and element
|
||||
// for legacy reasons (same behaviour as PHP rendering)
|
||||
@ -56,8 +56,6 @@ class TextField extends SilverStripeComponent {
|
||||
}
|
||||
|
||||
TextField.propTypes = {
|
||||
leftTitle: React.PropTypes.string,
|
||||
title: React.PropTypes.string,
|
||||
extraClass: React.PropTypes.string,
|
||||
id: React.PropTypes.string,
|
||||
name: React.PropTypes.string.isRequired,
|
||||
|
@ -1,63 +1,65 @@
|
||||
import jQuery from 'jQuery';
|
||||
|
||||
jQuery.entwine('ss', ($) => {
|
||||
$('#add-to-campaign__dialog .add-to-campaign-action, .cms-content-actions .add-to-campaign-action, #add-to-campaign__action').entwine({
|
||||
onclick() {
|
||||
let dialog = $('#add-to-campaign__dialog');
|
||||
$('#add-to-campaign__dialog .add-to-campaign-action,' +
|
||||
'.cms-content-actions .add-to-campaign-action,' +
|
||||
'#add-to-campaign__action').entwine({
|
||||
onclick() {
|
||||
let dialog = $('#add-to-campaign__dialog');
|
||||
|
||||
if (dialog.length) {
|
||||
dialog.open();
|
||||
} else {
|
||||
dialog = $('<div id="add-to-campaign__dialog" class="add-to-campaign__dialog" />');
|
||||
$('body').append(dialog);
|
||||
}
|
||||
if (dialog.length) {
|
||||
dialog.open();
|
||||
} else {
|
||||
dialog = $('<div id="add-to-campaign__dialog" class="add-to-campaign__dialog" />');
|
||||
$('body').append(dialog);
|
||||
}
|
||||
|
||||
if (dialog.children().length === 0) dialog.addClass('loading');
|
||||
if (dialog.children().length === 0) dialog.addClass('loading');
|
||||
|
||||
const form = this.closest('form');
|
||||
const button = this;
|
||||
const form = this.closest('form');
|
||||
const button = this;
|
||||
|
||||
const formData = form.serializeArray();
|
||||
formData.push({
|
||||
name: button.attr('name'),
|
||||
value: '1',
|
||||
});
|
||||
const formData = form.serializeArray();
|
||||
formData.push({
|
||||
name: button.attr('name'),
|
||||
value: '1',
|
||||
});
|
||||
|
||||
$.ajax({
|
||||
url: form.attr('action'),
|
||||
data: formData,
|
||||
type: 'POST',
|
||||
global: false,
|
||||
complete() {
|
||||
dialog.removeClass('loading');
|
||||
},
|
||||
success(data, status, xhr) {
|
||||
if (xhr.getResponseHeader('Content-Type').indexOf('text/plain') === 0) {
|
||||
$.ajax({
|
||||
url: form.attr('action'),
|
||||
data: formData,
|
||||
type: 'POST',
|
||||
global: false,
|
||||
complete() {
|
||||
dialog.removeClass('loading');
|
||||
},
|
||||
success(data, status, xhr) {
|
||||
if (xhr.getResponseHeader('Content-Type').indexOf('text/plain') === 0) {
|
||||
const container = $(
|
||||
'<div class="add-to-campaign__response add-to-campaign__response--good">' +
|
||||
'<span></span></div>'
|
||||
);
|
||||
container.find('span').text(data);
|
||||
dialog.append(container);
|
||||
} else {
|
||||
dialog.html(data);
|
||||
}
|
||||
},
|
||||
error(xhr) {
|
||||
const error = xhr.responseText
|
||||
|| 'Something went wrong. Please try again in a few minutes.';
|
||||
const container = $(
|
||||
'<div class="add-to-campaign__response add-to-campaign__response--good">' +
|
||||
'<div class="add-to-campaign__response add-to-campaign__response--error">' +
|
||||
'<span></span></div>'
|
||||
);
|
||||
container.find('span').text(data);
|
||||
container.find('span').text(error);
|
||||
dialog.append(container);
|
||||
} else {
|
||||
dialog.html(data);
|
||||
}
|
||||
},
|
||||
error(xhr) {
|
||||
const error = xhr.responseText
|
||||
|| 'Something went wrong. Please try again in a few minutes.';
|
||||
const container = $(
|
||||
'<div class="add-to-campaign__response add-to-campaign__response--error">' +
|
||||
'<span></span></div>'
|
||||
);
|
||||
container.find('span').text(error);
|
||||
dialog.append(container);
|
||||
},
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
return false;
|
||||
},
|
||||
});
|
||||
return false;
|
||||
},
|
||||
});
|
||||
|
||||
$('#add-to-campaign__dialog').entwine({
|
||||
onadd() {
|
||||
|
@ -5,4 +5,5 @@ export const ACTION_TYPES = {
|
||||
SUBMIT_FORM_REQUEST: 'SUBMIT_FORM_REQUEST',
|
||||
SUBMIT_FORM_SUCCESS: 'SUBMIT_FORM_SUCCESS',
|
||||
UPDATE_FIELD: 'UPDATE_FIELD',
|
||||
SET_SUBMIT_ACTION: 'SET_SUBMIT_ACTION',
|
||||
};
|
||||
|
@ -83,3 +83,12 @@ export function submitForm(submitApi, formId, fieldValues) {
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
export function setSubmitAction(formId, submitAction) {
|
||||
return (dispatch) => {
|
||||
dispatch({
|
||||
type: ACTION_TYPES.SET_SUBMIT_ACTION,
|
||||
payload: { formId, submitAction },
|
||||
});
|
||||
};
|
||||
}
|
||||
|
@ -64,6 +64,11 @@ function formReducer(state = initialState, action) {
|
||||
submitting: false,
|
||||
}));
|
||||
|
||||
case ACTION_TYPES.SET_SUBMIT_ACTION:
|
||||
return deepFreeze(updateForm(action.payload.formId, {
|
||||
submitAction: action.payload.submitAction,
|
||||
}));
|
||||
|
||||
default:
|
||||
return state;
|
||||
|
||||
|
@ -21,7 +21,9 @@ class AddToCampaignHandler_FormAction extends FormAction
|
||||
function __construct()
|
||||
{
|
||||
parent::__construct('addtocampaign', _t('CAMPAIGNS.ADDTOCAMPAIGN', 'Add to campaign'));
|
||||
$this->setUseButtonTag(false);
|
||||
$this->addExtraClass('add-to-campaign-action');
|
||||
$this->setValidationExempt(true);
|
||||
$this->addExtraClass('btn-primary');
|
||||
}
|
||||
}
|
||||
|
@ -45,7 +45,7 @@ class FormAction extends FormField {
|
||||
|
||||
/**
|
||||
* Enables the use of <button> instead of <input>
|
||||
* in {@link Field()} - for more customizeable styling.
|
||||
* in {@link Field()} - for more customisable styling.
|
||||
*
|
||||
* @var boolean
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user