diff --git a/admin/javascript/src/components/form-action/README.md b/admin/javascript/src/components/form-action/README.md
index 9022c5f0b..0db385d6d 100644
--- a/admin/javascript/src/components/form-action/README.md
+++ b/admin/javascript/src/components/form-action/README.md
@@ -24,7 +24,7 @@ The html id attribute.
Used for the button's `type` attribute. Defaults to `button`
-### style (string)
+### bootstrapButtonStyle (string)
The style of button to be shown, adds a class `btn-{style}` to the button. Defaults to `secondary`.
diff --git a/admin/javascript/src/components/form-action/index.js b/admin/javascript/src/components/form-action/index.js
index be3439a00..c3dd2c7bd 100644
--- a/admin/javascript/src/components/form-action/index.js
+++ b/admin/javascript/src/components/form-action/index.js
@@ -37,7 +37,7 @@ class FormActionComponent extends SilverStripeComponent {
const buttonClasses = ['btn'];
// Add 'type' class
- buttonClasses.push(`btn-${this.props.style}`);
+ buttonClasses.push(`btn-${this.props.bootstrapButtonStyle}`);
// If there is no text
if (typeof this.props.label === 'undefined') {
@@ -91,9 +91,13 @@ class FormActionComponent extends SilverStripeComponent {
* Event handler triggered when a user clicks the button.
*
* @param object event
- * @returns null
+ * @return undefined
*/
handleClick(event) {
+ if (typeof this.props.handleClick === 'undefined') {
+ return;
+ }
+
this.props.handleClick(event);
}
@@ -107,13 +111,13 @@ FormActionComponent.propTypes = {
loading: React.PropTypes.bool,
icon: React.PropTypes.string,
disabled: React.PropTypes.bool,
- style: React.PropTypes.string,
+ bootstrapButtonStyle: React.PropTypes.string,
extraClass: React.PropTypes.string,
};
FormActionComponent.defaultProps = {
type: 'button',
- style: 'secondary',
+ bootstrapButtonStyle: 'secondary',
disabled: false,
};
diff --git a/admin/javascript/src/sections/campaign-admin/list.js b/admin/javascript/src/sections/campaign-admin/list.js
index a618a626b..2aece7150 100644
--- a/admin/javascript/src/sections/campaign-admin/list.js
+++ b/admin/javascript/src/sections/campaign-admin/list.js
@@ -99,56 +99,53 @@ class CampaignListContainer extends SilverStripeComponent {
}
renderButtonToolbar() {
- const items = this.getItems(this.props.campaignId);
+ const items = this.getItems();
- let itemSummaryLabel;
- if (items) {
- itemSummaryLabel = i18n.sprintf(
- (items.length === 1) ?
- i18n._t('Campaigns.ITEM_SUMMARY_SINGULAR')
- : i18n._t('Campaigns.ITEM_SUMMARY_PLURAL'),
- items.length
- );
-
- let button;
- if (this.props.record.State === 'open') {
- button = (
-
- );
- } else if (this.props.record.State === 'published') {
- // TODO Implement "revert" feature
- button = (
-
- );
- }
-
- // TODO Fix indicator positioning
- // const itemCountIndicator = (
- //
- //
- // {itemSummaryLabel}
- //
- // );
-
- return (
-
- {button}
-
- );
+ // let itemSummaryLabel;
+ if (!items) {
+ return ;
}
- return ;
+ // let itemSummaryLabel = i18n.sprintf(
+ // items.length === 1
+ // ? i18n._t('Campaigns.ITEM_SUMMARY_SINGULAR')
+ // : i18n._t('Campaigns.ITEM_SUMMARY_PLURAL'),
+ // items.length
+ // );
+
+ let actionProps = {};
+
+ if (this.props.record.State === 'open') {
+ actionProps = Object.assign(actionProps, {
+ label: i18n._t('Campaigns.PUBLISHCAMPAIGN'),
+ bootstrapButtonStyle: 'success',
+ loading: this.props.campaign.isPublishing,
+ handleClick: this.handlePublish,
+ icon: 'rocket',
+ });
+ } else if (this.props.record.State === 'published') {
+ // TODO Implement "revert" feature
+ actionProps = Object.assign(actionProps, {
+ label: i18n._t('Campaigns.REVERTCAMPAIGN'),
+ bootstrapButtonStyle: 'default',
+ icon: 'back-in-time',
+ disabled: true,
+ });
+ }
+
+ // TODO Fix indicator positioning
+ // const itemCountIndicator = (
+ //
+ //
+ // {itemSummaryLabel}
+ //
+ // );
+
+ return (
+
+
+
+ );
}
/**
@@ -219,8 +216,13 @@ class CampaignListContainer extends SilverStripeComponent {
}
CampaignListContainer.propTypes = {
+ campaign: React.PropTypes.shape({
+ isPublishing: React.PropTypes.bool.isRequired,
+ }),
+ campaignActions: React.PropTypes.object.isRequired,
publishApi: React.PropTypes.func.isRequired,
- isPublishing: React.PropTypes.bool,
+ record: React.PropTypes.object.isRequired,
+ recordActions: React.PropTypes.object.isRequired,
};
function mapStateToProps(state, ownProps) {
@@ -230,7 +232,7 @@ function mapStateToProps(state, ownProps) {
record = state.records.ChangeSet[parseInt(ownProps.campaignId, 10)];
}
return {
- record: record || [],
+ record: record || {},
campaign: state.campaign,
};
}
diff --git a/admin/javascript/src/silverstripe-backend.js b/admin/javascript/src/silverstripe-backend.js
index 27bae9d10..d11093b37 100644
--- a/admin/javascript/src/silverstripe-backend.js
+++ b/admin/javascript/src/silverstripe-backend.js
@@ -285,7 +285,7 @@ class SilverStripeBackend {
// Always add full payload data to GET requests.
// GET requests with a HTTP body are technically legal,
// but throw an error in the WHATWG fetch() implementation.
- { setFromData: (refinedSpec.method === 'get') }
+ { setFromData: (refinedSpec.method.toLowerCase() === 'get') }
);
const encodedData = encode(
@@ -295,7 +295,7 @@ class SilverStripeBackend {
applySchemaToData(refinedSpec.payloadSchema, data)
);
- const args = refinedSpec.method === 'get'
+ const args = refinedSpec.method.toLowerCase() === 'get'
? [url, headers]
: [url, encodedData, headers];
diff --git a/admin/javascript/src/state/campaign/reducer.js b/admin/javascript/src/state/campaign/reducer.js
index 51d8f1013..05635ba91 100644
--- a/admin/javascript/src/state/campaign/reducer.js
+++ b/admin/javascript/src/state/campaign/reducer.js
@@ -3,6 +3,7 @@ import ACTION_TYPES from './action-types';
const initialState = {
campaignId: null,
+ isPublishing: false,
view: null,
};
diff --git a/admin/javascript/src/state/records/reducer.js b/admin/javascript/src/state/records/reducer.js
index 3c2e06fdd..3ffe882ef 100644
--- a/admin/javascript/src/state/records/reducer.js
+++ b/admin/javascript/src/state/records/reducer.js
@@ -28,7 +28,7 @@ function recordsReducer(state = initialState, action) {
case ACTION_TYPES.FETCH_RECORDS_SUCCESS:
recordType = action.payload.recordType;
// TODO Automatic pluralisation from recordType
- records = action.payload.data._embedded[`${recordType}s`] || [];
+ records = action.payload.data._embedded[`${recordType}s`] || {};
records = records.reduce((prev, val) => Object.assign({}, prev, { [val.id]: val }), {});
return deepFreeze(Object.assign({}, state, {
[recordType]: records,